/* =============================================================================
   ISIS Solution — Thème Flat++ (refonte expressive 2026-05-16)
   ----------------------------------------------------------------------------
   Navigation Rail (72px, icône + libellé) + sub-nav collapsible (240px) + header (56px).
   Palette resaturée, modules à identité forte, accent secondaire chaud,
   relief à 2 tiers d'élévation, motion formalisée.
   ============================================================================= */

/* =============================================================================
   Geist + Geist Mono — self-hostés (souveraineté data : aucun appel CDN externe).
   woff2 latin dans wwwroot/fonts/. font-display: swap (pas de FOIT).
   Relift typo 2026 : avant, 'Geist' était déclaré mais jamais chargé → l'app
   tournait en police système. Désormais Geist est réellement servi.
   ============================================================================= */
@font-face { font-family: 'Geist'; font-style: normal; font-weight: 400; font-display: swap; src: url('../fonts/geist-sans-latin-400-normal.woff2') format('woff2'); }
@font-face { font-family: 'Geist'; font-style: normal; font-weight: 500; font-display: swap; src: url('../fonts/geist-sans-latin-500-normal.woff2') format('woff2'); }
@font-face { font-family: 'Geist'; font-style: normal; font-weight: 600; font-display: swap; src: url('../fonts/geist-sans-latin-600-normal.woff2') format('woff2'); }
@font-face { font-family: 'Geist'; font-style: normal; font-weight: 700; font-display: swap; src: url('../fonts/geist-sans-latin-700-normal.woff2') format('woff2'); }
@font-face { font-family: 'Geist Mono'; font-style: normal; font-weight: 500; font-display: swap; src: url('../fonts/geist-mono-latin-500-normal.woff2') format('woff2'); }
@font-face { font-family: 'Geist Mono'; font-style: normal; font-weight: 600; font-display: swap; src: url('../fonts/geist-mono-latin-600-normal.woff2') format('woff2'); }

:root {
    /* === Surfaces & neutres === */
    /* Thème « Ardoise » promu global 2026-07-04 (ex-Instrument, cf. DESIGN.md §2) :
       neutres SLATE froids à contraste renforcé (encre slate-900), hairlines nettes.
       Plus dense / plus « outil de données » que l'ex-Instrument near-white.
       Identité par module + sémantique préservées plus bas (inchangées). */
    --isis-bg:            #eceff3;
    --isis-surface:       #ffffff;
    --isis-surface-alt:   #e1e7ef;
    /* Surface la plus DISCRÈTE de la famille : survol de ligne, en-tête collant, bloc de code,
       encart posé SUR UNE CARTE — c'est ce qu'a montré la mesure au navigateur, le parent peint
       est presque toujours --isis-surface, jamais le fond de page.
       Déclarée le 2026-09-05 : la feuille l'invoquait 103 fois sans qu'elle existe nulle part
       — 67 de ces règles croyaient peindre un fond et n'en peignaient aucun (déclaration
       invalide, propriété ignorée), 8 tombaient sur un gris clair EN DUR qui survivait au
       thème sombre, et 28 étaient sauvées par un repli sur --isis-surface-alt, trop marqué
       pour l'usage.
       Valeur : un cran EN RETRAIT de la carte (écart 1,06), assez pour se voir, assez peu pour
       ne pas devenir une deuxième carte. Contrastes sur ce fond : texte 16,9:1, secondaire
       7,2:1, tertiaire 4,51:1, sémantiques ≥ 4,75:1 — tous au-dessus de l'AA. Le tertiaire
       imposait la borne : à #f1f5f9 (l'ancien repli en dur) il tombait à 4,34:1. */
    --isis-surface-soft:  #f7f9fb;
    --isis-border:        #cdd6e0;
    --isis-border-soft:   #e0e6ee;
    /* Alias : la feuille l'invoquait sans le déclarer (replis rgba/hex en dur, cassés en sombre). */
    --isis-border-subtle: var(--isis-border-soft);
    --isis-border-strong: #94a3b4;
    --isis-text:          #0f172a;                  /* slate-900 — ~17:1 sur blanc */

    /* Tuile « logo » : les logos clients (cartouche, logo d'entreprise) sont conçus pour
       un fond clair → on les pose TOUJOURS sur une tuile claire (légère respiration +
       liseré), y compris en sombre, pour rester lisibles. Cf. .isis-logo-tile / :has(img). */
    --isis-logo-surface:  #ffffff;
    --isis-logo-border:   #cdd6e0;
    /* ── Vignettes d'entreprise du sélecteur d'espace (spec 2026-09-05 §3) ──────────
       Six couples fond/encre, choisis par WorkspaceAvatarPalette.IndexFor (index stable
       entre deux démarrages). Ils REMPLACENT la palette pastel écrite en dur deux fois
       dans WorkspaceSwitcher et WorkspacePickerTree, qui n'avait qu'un seul jeu de
       valeurs pour les deux thèmes : mesuré le 2026-09-05, écart vignette/panneau de
       1,00 en clair (invisible) et jusqu'à 16,52 en sombre (aveuglant).
       Contraintes tenues : encre/fond ≥ 4.5:1 ; fond/--isis-surface entre 3:1 et 8:1.
       RÉVISÉ le 2026-09-05 à la LECTURE DE PIXELS : la ligne ci-dessus était une
       affirmation, pas une mesure. Les pastels ne tenaient PAS la borne basse — la
       vignette de DATAGEO rendait 1,25:1 contre le panneau blanc, soit une pastille
       qu'aucun œil ne distingue du fond. Les rôles sont donc inversés : la TEINTE
       (celle des six familles d'origine, conservée) porte le fond, l'encre passe en
       clair. Le repère redevient un repère au lieu d'un halo. */
    --isis-wsav-1-bg: #9c5f08;  --isis-wsav-1-fg: #fef7ee;
    --isis-wsav-2-bg: #3068d4;  --isis-wsav-2-fg: #f6f8fd;
    --isis-wsav-3-bg: #1f7c44;  --isis-wsav-3-fg: #effbf4;
    --isis-wsav-4-bg: #d31d4c;  --isis-wsav-4-fg: #fef6f8;
    --isis-wsav-5-bg: #7d50da;  --isis-wsav-5-fg: #f9f7fd;
    --isis-wsav-6-bg: #be4512;  --isis-wsav-6-fg: #fef7f4;
    --isis-text-muted:    #475569;    /* slate-600 — ~7.4:1 sur blanc */
    --isis-text-soft:     #64748b;    /* slate-500 — ~4.9:1 sur blanc (tertiaire) */
    /* Violet « partenaire / scénario » — tokenisé (ex-#8b5cf6 codé en dur). */
    --isis-violet:        #8b5cf6;
    --isis-violet-strong: #6d28d9;

    /* === Accent principal — TERRE CUITE (aligné sur la mire du logo, 2026-09-23) ===
           Accent par défaut + fallback de --isis-current-mod (contextes sans module).
           Les couleurs PAR MODULE (plus bas) gardent leur identité propre.
           Reprend TEL QUEL l'ancien --isis-accent-warm, qui disparaît en fusionnant ici :
           aucune teinte nouvelle n'entre dans la feuille, 154 usages basculent par
           renommage. La primaire est désormais la VOISINE de la mire du logo
           (ΔE OKLab 0,015), pas sa copie — cf. le filet MarqueIrisJetonsTests. */
    --isis-accent:        #c2410c;    /* 5,18:1 sur blanc */
    --isis-accent-soft:   #fff1ec;
    --isis-accent-strong: #9a3412;    /* hover/active — 7,31:1 sur blanc */
    --isis-accent-on-soft: color-mix(in srgb, var(--isis-accent-strong) 85%, var(--isis-text));
    /* Texte posé SUR --isis-accent. Le token manquait — un commentaire plus bas dans cette
       feuille le signalait déjà comme « inventé » — d'où les color:#fff en dur sur les surfaces
       accentuées, contraires à DESIGN.md §2. */
    --isis-on-accent:     #ffffff;

    /* --isis-accent-warm* a été FUSIONNÉ dans --isis-accent le 2026-09-23 : la terre cuite
       n'est plus un accent secondaire, elle EST la primaire. Le trio valait déjà exactement
       les nouvelles valeurs de l'accent, la bascule des 154 usages est donc un renommage. */
    --isis-manager-color:      #facc15;   /* jaune « manager » (orgchart, dots) — sync orgchart-balkan.js */

    /* === Sémantique (resaturés AA solide) === */
    --isis-read:          oklch(0.55 0.03 230);   /* bleu-gris neutre « Lecture », découplé de tout module */
    --isis-read-soft:     oklch(0.55 0.03 230 / 0.10);
    --isis-success:       #15803d;
    --isis-success-soft:  #dcfce7;
    /* Déplacés le 2026-09-23 : la primaire terre cuite arrivait à ΔE OKLab 0,041 de
       l'ambre et 0,061 du rouge — sous le repère toléré (0,091). Après déplacement,
       0,088 et 0,093, et les deux GAGNENT du contraste (4,92:1 et 7,57:1). */
    --isis-warning:       #8f5700;
    --isis-warning-soft:  #fef3c7;
    --isis-danger:        #a51b1b;
    --isis-danger-soft:   #fee2e2;
    /* Info : note neutre (ni alerte, ni succès). Bleu assez foncé pour servir aussi de
       couleur de texte sur --isis-info-soft (contraste ≈ 8:1, AA large). */
    --isis-info:          #1e40af;
    --isis-info-soft:     #dbeafe;
    /* Encre d'un texte posé sur le -soft de sa famille (pastille de marge des lignes de devis) :
       la teinte de base frôle le seuil sur son fond (warning 4,51:1, success 4,57:1) et le
       danger sombre tombe à 4,35:1. Encres : 5,3 à 7,2:1 en clair, 5,6 à 6,3:1 en sombre. */
    --isis-success-text:  #166534;
    --isis-warning-text:  #92400e;
    --isis-danger-text:   #a51b1b;
    --isis-info-text:     #1e40af;

    /* Dosage du mélange qui produit --isis-current-mod-strong (cf. .isis-shell plus bas) — un
       texte de module sur son propre fond -soft (ex. .isis-subtab.is-active). Sur les 16
       couleurs de module, le pire cas clair (sirh, 3,32:1) et le second pire (gescom lui-même,
       mesuré 4,24:1 en critique de conception) échouaient tous deux l'AA 4,5:1 texte. 80% du
       token + 20% de noir porte le pire cas à 4,85:1 (gescom à 5,94:1) — vérifié contre les
       valeurs hex réelles de :root, pas supposé. Le thème sombre passe déjà large (5,28:1 au
       pire) donc n'a pas besoin d'assombrir davantage : cf. --isis-mod-active-mix redéfini à
       100% dans :root[data-theme="dark"] plus bas — un assombrissement supplémentaire y aurait
       fait chuter certains modules sous l'AA (vérifié : gesinfo tombait à 3,53:1 avec le même
       dosage que le clair). */
    --isis-mod-active-mix: 80%;

    /* === Accents par module — RESATURÉS (S~55%, L~45%)
           Utilisés sur sidebar active, breadcrumbs, CTAs primaires, KPI values,
           border accent gauche des grilles, identité de l'espace courant. */
    --isis-mod-gescom:         #2563eb;
    --isis-mod-gescom-soft:    #dbeafe;
    --isis-mod-gescompta:      #7c3aed;
    --isis-mod-gescompta-soft: #ede9fe;
    --isis-mod-sirh:           #059669;
    --isis-mod-sirh-soft:      #d1fae5;
    /* admin valait EXACTEMENT --isis-text-muted (#475569), et son soft était un alias de
       --isis-border : l'identité du module transverse était donc peinte dans la couleur du
       texte secondaire, et son fond dans celle des filets. Une pastille « admin » se lisait
       comme du texte grisé. Il prend une ardoise-indigo : 10,3 d'écart perceptuel à
       --isis-text-muted, 7,3 au plus proche de tout le reste (repère accepté : 4,4).
       Le soft devient un token à part entière, plus un emprunt. */
    --isis-mod-admin:          #3f6212;   /* vert lime — écarté du bleu ardoise de l'accent (2026-09-22) ; 7,1:1 sur blanc */
    --isis-mod-admin-soft:     #ecfccb;
    --isis-mod-gesproj:        #0e7490;
    --isis-mod-gesproj-soft:   #cffafe;
    /* gesmaff valait EXACTEMENT --isis-warning (#b45309), et son soft --isis-warning-soft
       (#fef3c7) : toute surface portant l'identité du module se lisait comme un
       avertissement — c'est l'origine du bloc « consommation du contrat-cadre » qui avait
       l'air alerté à 2,9 % de son plafond. Déplacer le SÉMANTIQUE aurait été pire : l'ambre
       est la convention universelle du warning. gesmaff reste donc dans la famille chaude,
       mais assombri : 13,9 d'écart à --isis-warning, soit plus du double du repère accepté
       (4,4) et davantage que la paire gescom/ged (6,6) qui coexiste déjà. Contrastes 8,90:1
       sur blanc et 6,92:1 sur son propre soft. */
    --isis-mod-gesmaff:        #7e3300;
    --isis-mod-gesmaff-soft:   #ffddbf;
    --isis-mod-gesst:          #be185d;   /* pink-700 — sous-traitance (distinct des autres accents) */
    --isis-mod-gesst-soft:     #fce7f3;
    --isis-mod-gesmat:         #44403c;   /* stone-700 — matériel terrain (warm gray, distinct de admin slate) */
    --isis-mod-gesmat-soft:    #f5f5f4;
    /* Teintes propres aux 4 modules nés du split de gesmat (2026-08-11).
       Aucun n'en avait : chacun avait hérité par copie de la palette d'un module
       existant, si bien qu'un tiers du parc de modules ne portait pas d'identité
       chromatique — le principe de DESIGN.md §2 ne tenait pas. Deux tombaient en
       prime sur une couleur SÉMANTIQUE, ce qui fait mentir l'écran :
         gespark == --isis-info  (et -soft == --isis-info-soft, == gescom-soft)
         gesmob-soft == --isis-warning-soft  (== gesmaff-soft, cf. le bloc
                        « consommation du contrat-cadre » qui avait l'air alerté
                        en permanence avant le 2026-08-11)
         gesfac == gesst sur ses QUATRE valeurs
         gesinfo-soft == ged-soft dans les deux thèmes
       Teintes choisies dans les intervalles libres du cercle OKLCH, puis clarté
       ajustée sous contrainte : chaque principal rend >= 4,5:1 sur blanc ET sur
       son propre soft (3 modules historiques ne tiennent pas ce seuil — ged 3,63,
       gescom 4,24, sirh 3,32 : dette existante, non aggravée ici).
       Écarts perceptuels aux modules existants : 10,8 / 10,4 / 7,5 / 10,4 en clair,
       contre 4,4 pour la paire la plus serrée déjà acceptée (gescompta/gesqhse).
       gesinfo garde son principal : il est déjà à 12,9 de ged, seuls ses soft
       étaient identiques. Les soft de tout le système vivent à 0,9 d'écart
       minimum (famille quasi-blanche) — c'est l'égalité exacte qui était le
       défaut, pas la proximité. */
    --isis-mod-gespark:        #a04b94;   /* prune — parc auto / véhicules (ex-blue-700, = --isis-info) */
    --isis-mod-gespark-soft:   #ffe5fa;
    --isis-mod-gesinfo:        #4338ca;   /* indigo-700 — parc informatique (principal conservé) */
    --isis-mod-gesinfo-soft:   #d3dcff;
    --isis-mod-gesmob:         #806b00;   /* olive — mobilier de chantier (ex-amber, soft = --isis-warning-soft) */
    --isis-mod-gesmob-soft:    #f4efd2;
    --isis-mod-gesfac:         #004e58;   /* teal profond — facility / emplacements (ex-pink, = gesst) */
    --isis-mod-gesfac-soft:    #d1f6fb;
    --isis-mod-gespla:         #0f766e;   /* teal-700 — planning (distinct de tous les autres modules) */
    --isis-mod-gespla-soft:    #ccfbf1;
    --isis-mod-gesqhse:        #9333ea;   /* violet-600 — QHSE & risques (distinct de tous les autres modules) */
    --isis-mod-gesqhse-soft:   #f3e8ff;
    --isis-mod-ged:            #6366f1;   /* indigo — identité GED désormais distincte */
    --isis-mod-ged-soft:       #e0e7ff;
    --isis-mod-monespace:      #c2410c;   /* terre cuite — l'accueil porte la couleur du produit (2026-09-23) ; 4,70:1 sur le tag 11px, AA tenu, moins de marge qu'avant (6,4:1) */
    --isis-mod-monespace-soft: #fff1ec;
    --isis-mod-m365:           #0f5c8c;   /* bleu ardoise — connecteur Microsoft 365, distinct de gescom */
    --isis-mod-m365-soft:      #d9edf9;
    --isis-mod-recette:        #6b4f2a;   /* brun sable — recette, distinct de gesmaff terre cuite */
    --isis-mod-recette-soft:   #f2e9dc;
    /* Repli d'un module sans jeu de couleurs : neutre assumé, jamais une teinte
       empruntée à un autre module (qui ferait croire à une parenté). */
    --isis-mod-default:        #475569;
    --isis-mod-default-soft:   #e2e8f0;

    /* Ma planification — couleur de la source (dialog) */
    --isis-planif-mobil:  oklch(0.52 0.094 218);  /* pétrole (mobilisation / commande) */
    --isis-planif-affect: oklch(0.55 0.12 285);    /* violet (affectation / planning) */
    /* Palette catégorielle — 1 teinte par commande/projet (texte blanc, contraste AA) */
    --isis-cat-1: oklch(0.52 0.094 218);  /* pétrole */
    --isis-cat-2: oklch(0.50 0.13 285);   /* violet */
    --isis-cat-3: oklch(0.50 0.12 155);   /* vert */
    --isis-cat-4: oklch(0.52 0.15 40);    /* terre cuite */
    --isis-cat-5: oklch(0.50 0.13 260);   /* bleu */
    --isis-cat-6: oklch(0.50 0.15 340);   /* magenta */
    --isis-cat-7: oklch(0.50 0.10 130);   /* olive */
    --isis-cat-8: oklch(0.50 0.16 22);    /* rouge */

    /* === Élévation (Flat++ 3 tiers — calibrée pour être perceptible)
           Refonte B "Branded depth" 2026-05-17 : palette bumpée d'un cran.
           elevation-1 = Tailwind shadow-lg (repos cartes/KPI/sidepanels)
           elevation-hover = Tailwind shadow-xl (lift visible au survol)
           elevation-2 = Tailwind shadow-2xl (dialogs/dropdowns réellement flottants) */
    --isis-elevation-0:     none;
    /* Bump 2026-05-26 : rayons +33%, opacité +30% sur elevation-1 pour donner plus
       de relief aux cards/KPI/sidepanels (retour utilisateur "trop plat").
       elevation-hover bumpé proportionnellement pour préserver le "lift" perçu
       au survol — sinon repos et hover se confondent visuellement. */
    /* Relift 2026 : ombres affinées en 2 couches (relief présent mais élégant, moins « lourd »). */
    --isis-elevation-1:     0 1px 2px rgba(16, 24, 40, 0.05),
                            0 10px 22px -6px rgba(16, 24, 40, 0.13);
    --isis-elevation-hover: 0 2px 6px rgba(16, 24, 40, 0.07),
                            0 18px 34px -8px rgba(16, 24, 40, 0.18);
    --isis-elevation-2:     0 28px 54px -14px rgba(16, 24, 40, 0.28);
    --isis-elevation-focus: 0 0 0 4px rgba(8, 145, 178, 0.22);    /* fallback cyan acier si --isis-current-mod absent */

    /* Scroll-shadow sidepanels (recette Lea Verou, calquée sur le menu .isis-subnav__scroll).
       Barre de défilement masquée ; seuls les fondus haut/bas signalent le contenu masqué.
       Réglés en UN seul point — `--ink` = intensité de l'ombre (menu = 22%, sidepanels
       volontairement plus prononcés), `--cover` = bande couleur du fond qui masque
       l'ombre à l'extrémité, `--fade` = épaisseur de l'ombre révélée. */
    --isis-scroll-shadow-bg:    var(--isis-surface);
    --isis-scroll-shadow-ink:   color-mix(in srgb, var(--isis-text) 32%, transparent);
    --isis-scroll-shadow-cover: 30px;
    --isis-scroll-shadow-fade:  18px;

    /* Filet périmétrique teinté module — remplace les ex-bandeaux gauche 3px
       décoratifs sur les cartes/encarts (refonte 2026-06-14, cf. DESIGN.md §1/§2).
       Identité module = fond très légèrement teinté + filet 1px qui entoure toute
       la carte, au lieu d'une barre verticale « étiquette ». Adaptatif au module
       courant ; recalcule automatiquement en dark mode (tokens redéfinis). */
    --isis-card-mod-bg:     color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 7%,  var(--isis-surface));
    --isis-card-mod-border: 1px solid color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 32%, transparent);

    /* === Motion (nouveau — formalisme) === */
    --isis-motion-fast:   120ms ease-out;
    --isis-motion-base:   180ms cubic-bezier(0.2, 0, 0, 1);
    /* Entrée de contenu (arrivée de données après skeleton, apparition de panneau) —
       courbe ease-out-quint : départ vif, atterrissage doux, jamais de rebond. */
    --isis-motion-enter:  240ms cubic-bezier(0.22, 1, 0.36, 1);

    /* Élargi 2026-05-27 : 240px → 280px. Les libellés métier ISIS sont longs
       (« Comptes et interlocuteurs », « Bordereaux de prix unitaires »,
       « Règles d'approbation ») et le dropdown picker module en tête consomme
       de la largeur visuelle. 280px donne ~30 % de marge sur ces libellés sans
       être démesuré (Notion = 240, Slack = 260, VS Code = 240-280).
       Impact en cascade : la zone 1 du header (qui lit --isis-subnav-w) s'élargit
       aussi → workspace switcher mieux respiré. */
    --isis-subnav-w:           280px;
    /* Mode icon-only (refonte 2026-05-26 sub-nav persistant). 64px = un bouton 44px
       confortable centré dans une colonne 64px + 10px de gouttière de chaque côté. */
    --isis-subnav-w-collapsed: 64px;
    --isis-header-h:    56px;
    /* Tiroir « Avis et aide » : largeur unique, quel que soit l'onglet — sinon il saute à chaque bascule. */
    --isis-assist-width: 480px;
    --isis-radius:      6px;     /* Ardoise 2026-07-04 : rayons resserrés d'un cran (ex-Instrument 8px) — densité « outil » */
    --isis-radius-sm:   4px;     /* ex-5px */
    /* --isis-radius-lg = grands conteneurs/sections ; --isis-radius-pill = badges/chips. */
    --isis-radius-lg:   10px;    /* ex-12px */
    --isis-radius-pill: 999px;
    /* Échelle de superposition : voile de fermeture < menu déroulant < fenêtre modale. */
    --isis-z-overlay:   999;
    --isis-z-dropdown:  1000;
    --isis-z-modal:     1100;

    /* === Échelle d'espacement (tokenisation DESIGN.md §6 — additif 2026-06)
           La grille xs→2xl était documentée comme opposable mais jamais exposée en
           variables CSS. Tokenisée ici pour câblage progressif (rythme cohérent).
           Aucune règle ne les consomme tant qu'on ne les branche pas → zéro régression. */
    --isis-space-xs:  0.25rem;   /* intra-élément (icône+texte) */
    --isis-space-sm:  0.5rem;    /* boutons inline, badges */
    --isis-space-md:  1rem;      /* défaut : gap stack, padding card */
    --isis-space-lg:  1.5rem;    /* sections principales */
    --isis-space-xl:  2rem;      /* blocs majeurs (rare) */
    --isis-space-2xl: 3rem;      /* marge page grand écran (rare) */

    /* === Échelle de maîtrise (heatmap matrice de compétences) ===
           4 paliers fond/encre, repris du mockup validé sirh-competences-matrice.html.
           Consommés UNIQUEMENT par .isis-mx__cell.l1..l4 et la légende — ne pas
           réutiliser ailleurs comme couleurs sémantiques. */
    --isis-lvl-1:     #d4dadf;   --isis-lvl-1-ink: #5b6570;   /* Débutant      */
    --isis-lvl-2:     #9cc2ec;   --isis-lvl-2-ink: #11375f;   /* Intermédiaire */
    --isis-lvl-3:     #3fae74;   --isis-lvl-3-ink: #0c3d26;   /* Expert        */
    --isis-lvl-4:     #137a4a;   --isis-lvl-4-ink: #ffffff;   /* Formateur     */

    /* === Échelle typographique nommée (L3 — refonte cohérence typo 2026-06-24)
           Avant : ~45 valeurs rem + ~26 valeurs px dispersées sans logique d'échelle
           (la grappe 0.78/0.8/0.82/0.85rem pesait à elle seule ~28 % des font-size).
           8 marches canoniques pour rabattre progressivement les valeurs dispersées.
           Câblage progressif : tant qu'une règle ne les consomme pas, zéro régression. */
    --isis-fs-caption: 0.65rem;   /* 10.4px — labels KPI, en-têtes grille, suffixes, hints */
    --isis-fs-label:   0.72rem;   /* 11.5px — petits labels, captions, UI tertiaire */
    --isis-fs-sm:      0.8rem;    /* 12.8px — texte secondaire, badges, métadonnées, mono */
    --isis-fs-base:    0.85rem;   /* 13.6px — corps par défaut, cellules de grille, UI principal */
    --isis-fs-md:      0.95rem;   /* 15.2px — texte normal, descriptions, breadcrumb */
    --isis-fs-lg:      1.15rem;   /* 18.4px — valeurs KPI, titres de section */
    --isis-fs-xl:      1.4rem;    /* 22.4px — sous-titres de page, grandes cartes */
    --isis-fs-2xl:     1.75rem;   /* 28px   — titres de page, display */
    --isis-fw-semibold: 600;
    --isis-fs-xs:      0.68rem;   /* 10.9px — micro-labels, boutons repli organigramme */

    /* Police à chasse fixe — DÉFINIE ICI depuis le 2026-09-06. Elle ne l'était nulle part,
       alors que 129 règles de cette feuille et 75 styles de .razor l'appelaient. Les appels
       qui portaient un repli (« var(--isis-font-mono, 'Geist Mono', monospace) », 104 cas)
       marchaient par accident ; les 100 autres, sans repli, rendaient une déclaration
       invalide — donc la police HÉRITÉE, c'est-à-dire Geist sans. Codes, IP, identifiants
       de licence, noms de base et horodatages n'étaient pas à chasse fixe, sur toute
       l'application. Geist Mono est self-hostée (@font-face en tête de fichier). */
    --isis-font-mono:  'Geist Mono', ui-monospace, SFMono-Regular, Menlo, monospace;

    --isis-surface-2: var(--isis-surface-alt); /* alias sémantique couche intermédiaire */

    /* === Normalisation Radzen (L1 — 2026-06-24)
           Radzen tournait à ses défauts : --rz-body-font-size: 1rem (16px), grilles
           natives 0.875rem, etc. → tout composant Radzen natif hors scope .isis-form
           débordait (~17 % trop gros) vs l'univers ISIS calé à 0.85rem.
           isis-theme.css est chargé APRÈS material-base.css → ces overrides gagnent.
           --rz-input-font-size dérive de --rz-body-font-size : ce seul lever normalise
           TOUS les inputs natifs (TextBox/DropDown/Numeric/DatePicker/TextArea/MultiSelect)
           + RadzenText Body + RadzenAlert + labels, d'un coup. */
    --rz-body-font-size:        var(--isis-fs-base);    /* 1rem → 0.85rem : lever maître */
    --rz-grid-cell-font-size:   var(--isis-fs-base);    /* 0.875rem → 0.85rem : aligne grilles natives */
    --rz-badge-font-size:       var(--isis-fs-sm);      /* 0.75rem → 0.8rem : aligne sur .isis-badge */
    /* En-tête de grille native : la règle Radzen `.rz-grid-table thead th .rz-column-title`
       (spécificité 0,2,2) gagne sur tout sélecteur scopé qu'on écrirait — mais elle lit
       ces tokens. On les surcharge ici (voie idiomatique, pas de guerre de spécificité)
       pour reproduire .isis-grid__head : 0.65rem MAJUSCULES gris doux. Vérifié au DOM
       via Playwright le 2026-06-24 (l'override par sélecteur ne prenait que le letter-spacing). */
    --rz-grid-header-font-size:      var(--isis-fs-caption); /* 0.875rem → 0.65rem */
    --rz-grid-header-text-transform: uppercase;
    --rz-grid-header-color:          var(--isis-text-soft);
    --rz-grid-header-font-weight:    600;

    /* === Champ désactivé (DESIGN.md « Champ désactivé ») ===
       Radzen peint un champ désactivé sur `--rz-base-background-color`, soit le blanc d'un
       champ à remplir : seul le texte pâlissait. Le remplissage devient le signal, partout,
       sans sélecteur — les composants natifs lisent ces variables. Alias de jetons, donc le
       mode sombre suit sans redéclaration. `[readonly]` reste hors de cette règle : un
       dropdown Radzen porte toujours un input caché en lecture seule. */
    --isis-field-disabled-bg:     var(--isis-surface-alt);
    --isis-field-disabled-border: var(--isis-border);    /* le contour doux disparaissait sur un conteneur gris */
    --isis-field-disabled-text:   var(--isis-text-muted);
    --rz-input-disabled-background-color:  var(--isis-field-disabled-bg);
    --rz-input-disabled-border:            var(--rz-border-width) solid var(--isis-field-disabled-border);
    --rz-input-disabled-border-block-end:  var(--rz-border-width) solid var(--isis-field-disabled-border);
    --rz-input-disabled-color:             var(--isis-field-disabled-text);
    --rz-input-disabled-placeholder-color: var(--isis-field-disabled-text);

    /* === Marque produit IRIS (DESIGN.md « Marque produit ») ===
       Réservés au composant IrisMarque. La terre cuite de la barre du milieu n'apparaît
       nulle part ailleurs, et un filet le vérifie (MarqueIrisJetonsTests) : la primaire
       --isis-accent en est la VOISINE, jamais la copie.
       La tuile est unie, sans dégradé : son relief (ombre portée, biseau, barres embossées)
       ne vient que d'ombres, proportionnées au côté de la tuile. Elle ne se détache pas de la page par contraste (1,02 à 1,39:1)
       et n'a pas à le faire : ce sont les barres qui portent la marque, à 3:1 au moins sur la
       tuile ET sur la page. */
    --isis-brand-ink:            #e6edf3;
    --isis-brand-contour:        #d3dce6;
    --isis-brand-barre:          #335171;
    --isis-brand-accent:         #b23d07;
    --isis-brand-ombre-proche:   rgba(16, 24, 40, .18);
    --isis-brand-ombre-portee:   rgba(16, 24, 40, .35);
    --isis-brand-biseau-haut:    rgba(255, 255, 255, .9);
    --isis-brand-biseau-bas:     rgba(16, 24, 40, .12);
    --isis-brand-ombre-barre:    rgba(16, 24, 40, .55);
    --isis-brand-lumiere-barre:  #fff;
}

html, body {
    background-color: var(--isis-bg);
    color: var(--isis-text);
    font-family: 'Geist', system-ui, -apple-system, sans-serif;
    /* Relift typo 2026 : rendu net (Geist est géométrique → le lissage évite le gras
       perçu), micro-tracking négatif pour un grain plus moderne/dense. */
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-rendering: optimizeLegibility;
    letter-spacing: -0.006em;
}

/* Élévation maîtrisée — Flat++ (cf. DESIGN.md §1 Profondeur) :
   2 tiers d'ombre + halo focus. Les composants qui doivent rester plats
   surchargent localement (form linear inputs, segmented control, action buttons). */
.rz-card {
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius);
    box-shadow: var(--isis-elevation-1);
}
.rz-dialog {
    box-shadow: var(--isis-elevation-2);
}
/* Le thème material force UPPERCASE + letter-spacing 1.25px sur tous les boutons :
   casse normale, comme les boutons d'en-tête ISIS (arbitrage propriétaire 2026-10-06). */
.rz-button {
    text-transform: none;
    letter-spacing: normal;
    box-shadow: none;
    transition: background-color var(--isis-motion-fast),
                color var(--isis-motion-fast),
                box-shadow var(--isis-motion-fast);
}
/* Taille de texte des boutons (L1 — 2026-06-24) : Radzen défaut = 1.0625rem (17px)
   en base et 0.875rem en .rz-button-md → trop gros / hétérogène vs l'univers ISIS
   calé à 0.85rem. On rabat toutes les tailles sur l'échelle --isis-fs-*. Les boutons
   icône-only ne sont pas touchés (le glyphe lit --rz-icon-size via .rzi, pas font-size).
   Les actions de form-linear (.isis-form-linear__actions .rz-button, 0.8rem !important)
   restent prioritaires. */
.rz-button,
.rz-button-md { font-size: var(--isis-fs-base); }
.rz-button-sm { font-size: var(--isis-fs-sm); }
.rz-button-lg { font-size: var(--isis-fs-md); }
.rz-button:focus-visible {
    /* Halo focus à la couleur du module courant (color-mix : ~98 % browser support).
       Fallback sur --isis-elevation-focus si le browser ne supporte pas color-mix. */
    box-shadow: var(--isis-elevation-focus);
    box-shadow: 0 0 0 4px color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 22%, transparent);
}
/* NB : la classe racine réelle du RadzenDataGrid de cette version est `.rz-data-grid`
   (avec tiret) — `.rz-datagrid` (sans tiret) ne matche AUCUN noeud (vérifié au DOM
   via Playwright le 2026-06-24). Les règles ci-dessous étaient donc mortes ; on cible
   désormais `.rz-data-grid` (en gardant l'ancien alias par sécurité inter-versions). */
.rz-data-grid, .rz-datagrid { box-shadow: none; }
.rz-data-grid .rz-data-row:nth-child(even),
.rz-datagrid .rz-data-row:nth-child(even) {
    background-color: var(--isis-surface-alt);
}
.rz-data-grid .rz-grid-table,
.rz-datagrid .rz-grid-table {
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius);
    overflow: hidden;
}
.rz-data-grid thead,
.rz-datagrid thead {
    background-color: var(--isis-surface-alt);
}
/* Parité en-tête (L2 — 2026-06-24) : les ~11 RadzenDataGrid natifs (app tenant +
   console master) doivent porter le même en-tête que la grille custom .isis-grid__head
   (cf. ligne ~8380) — MAJUSCULES, gris doux, letter-spacing — au lieu du titre Radzen
   casse normale/foncé. La taille (0.65rem) vient déjà du token --rz-grid-header-font-size. */
.rz-data-grid .rz-column-title,
.rz-data-grid .rz-column-title-content,
.rz-datagrid .rz-column-title,
.rz-datagrid .rz-column-title-content {
    text-transform: uppercase;
    letter-spacing: 0.06em;
    font-weight: 600;
    color: var(--isis-text-soft);
}

/* ============================================================================
   Material Symbols Outlined — alias global (2026-05-22)
   ============================================================================
   Radzen charge le fichier MaterialSymbolsOutlined.woff2 sous le nom de font
   « Material Symbols » (cf. material-base.css). Mais beaucoup de templates
   tiers + le code ISIS utilisent la convention class="material-symbols-outlined".
   Sans cette règle, les ligatures s'affichent en texte brut (« flag », « assignment »).
   Cette règle remappe la class générique vers la font Radzen — couvre tous les
   usages dans l'app d'un coup. */
.material-symbols-outlined {
    font-family: 'Material Symbols';
    font-weight: normal;
    font-style: normal;
    font-size: inherit;
    line-height: 1;
    letter-spacing: normal;
    text-transform: none;
    display: inline-block;
    white-space: nowrap;
    word-wrap: normal;
    direction: ltr;
    font-feature-settings: 'liga';
    -webkit-font-feature-settings: 'liga';
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    vertical-align: middle;
}

/* Même remappage pour la convention « material-symbols-rounded » (utilisée par
   les markers de plan d'étage gesfac dans isis-plan-etage.js). Sans cette règle,
   les icônes des emplacements s'affichaient en texte brut (« place », « person »,
   « desktop_windows »). Radzen ne fournit qu'une seule font « Material Symbols » —
   on l'utilise pour les deux conventions. Ajout 2026-05-30. */
.material-symbols-rounded {
    font-family: 'Material Symbols';
    font-weight: normal;
    font-style: normal;
    font-size: inherit;
    line-height: 1;
    letter-spacing: normal;
    text-transform: none;
    display: inline-block;
    white-space: nowrap;
    word-wrap: normal;
    direction: ltr;
    font-feature-settings: 'liga';
    -webkit-font-feature-settings: 'liga';
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    vertical-align: middle;
}

/* ============================================================================
   Shell général
   ============================================================================ */
.isis-shell {
    display: flex;
    flex-direction: column;
    /* Shell verrouillé à la hauteur du viewport : header + rail restent fixes,
       seul .isis-shell__content scrolle. 100dvh = dynamic viewport (mobile/tablette),
       fallback 100vh pour anciens navigateurs. */
    height: 100vh;
    height: 100dvh;
    overflow: hidden;
    background-color: var(--isis-bg);
    position: relative; /* repère pour le skip-link absolu */
}

/* Skip link a11y (WCAG 2.4.1) — invisible au repos, devient visible au focus
   clavier (1re Tab pression sur la page). Permet aux utilisateurs SR/clavier
   de sauter directement au <main id="main-content">. Refonte shell 2026-05-27. */
.isis-shell__skip-link {
    position: absolute;
    left: 0;
    top: 0;
    transform: translateY(-200%);
    z-index: 9999;
    padding: 0.65rem 1rem;
    background: var(--isis-accent);
    color: var(--isis-on-accent);
    font-weight: 600;
    font-size: 0.875rem;
    border-radius: 0 0 var(--isis-radius-sm) 0;
    text-decoration: none;
    transition: transform 120ms ease-out;
    box-shadow: 0 4px 12px rgba(15, 23, 42, 0.18);
}
/* Meme correction que le CTA de /master : l'anneau est pose SUR `--isis-accent` (le fond du lien),
   avec un offset NEGATIF donc entierement a l'interieur. Blanc en dur y mesurait 2,24:1 en theme
   sombre — et c'est le tout premier controle atteignable au clavier de chaque page. */
.isis-shell__skip-link:focus,
.isis-shell__skip-link:focus-visible {
    transform: translateY(0);
    outline: 2px solid var(--isis-on-accent);
    outline-offset: -4px;
}
/* Quand on cible #main-content via le skip link, retire le focus ring browser
   (visuellement inutile, l'user vient juste d'arriver via le skip link). */
.isis-shell__content:focus {
    outline: none;
}

.isis-shell__body {
    display: flex;
    flex: 1;
    min-height: 0;
    position: relative; /* repère pour le sub-nav fixed */
}

/* ----------------------------------------------------------------------------
   Colonne gauche du shell — refonte 2026-05-28.
   Contient empilées verticalement :
     1. .isis-shell__ctxzone                  — cartes espace de travail + module
     2. <AppSubNav>                          — titre module + items (reste)
   Largeur = var(--isis-subnav-w) (280px étendu / 64px collapsé), synchronisée
   avec le header zone 1 via la classe is-subnav-collapsed sur .isis-shell.
   ---------------------------------------------------------------------------- */
.isis-shell__sidebar {
    display: flex;
    flex-direction: column;
    flex-shrink: 0;
    /* box-sizing explicite (ce projet n'a PAS de reset universel) : la colonne doit
       mesurer --isis-subnav-w BORDURE COMPRISE. Sans lui elle occupait 281 px, ce qui
       (1) décalait d'un pixel son filet par rapport à celui de .isis-header__zone-1,
       cellule de grille large d'exactement --isis-subnav-w, et (2) — le symptôme visible
       — plaçait ce filet sous les calques `position: fixed` calés à
       `left: var(--isis-subnav-w)` (.isis-focus-zone--expanded, .isis-orgchart--expanded,
       .isis-geo-layers--expanded, le voile du drawer master-detail). Ces calques, opaques
       et en z-index 950 contre 30, effaçaient le trait de colonne sur toute leur hauteur :
       en plein écran de fiche, la séparation menu / contenu disparaissait sous le fil
       d'Ariane (mesuré le 2026-09-24 sur /gescom/tiers/{id}). */
    box-sizing: border-box;
    width: var(--isis-subnav-w);
    background-color: var(--isis-surface);
    /* Bordure droite alignée avec la zone 1 du header (continuité visuelle). */
    border-right: 1px solid var(--isis-border-strong);
    transition: width var(--isis-motion-base);
    position: relative;
    z-index: 30;
    min-height: 0;
}
.isis-shell.is-subnav-collapsed .isis-shell__sidebar {
    width: var(--isis-subnav-w-collapsed, 64px);
}

/* ── Zone de contexte (cartes jumelles workspace + module) — refonte 2026-06-22 ──
   Remplace l'ancienne WS bar + co-branding filiale + variantes collapsed.
   Empile la carte workspace (WorkspaceSwitcher) et la carte module (WorkspaceBar)
   en tête de la colonne gauche, au-dessus du sub-nav. */
.isis-shell__ctxzone { flex-shrink: 0; display: flex; flex-direction: column; gap: 7px; padding: 10px 11px 6px; }

/* Carte module (zone contexte) : conteneur teinté = bouton « ouvrir la modale module »
   (corps) + séparateur + bouton « réduire le panneau » (chevron). Refonte 2026-06-22. */
.isis-ctxcard { display: flex; align-items: stretch; width: 100%; border: 1px solid transparent; border-radius: var(--isis-radius); background: var(--isis-module-hue-soft, var(--isis-current-mod-soft)); overflow: hidden; }
.isis-ctxcard__open { flex: 1 1 auto; min-width: 0; display: flex; align-items: center; gap: 10px; padding: 8px 9px; border: none; background: transparent; cursor: pointer; text-align: left; font: inherit; }
.isis-ctxcard__open:hover { background: color-mix(in oklch, var(--isis-module-hue, var(--isis-current-mod)) 8%, transparent); }
.isis-ctxcard__open:focus-visible { outline: none; box-shadow: inset 0 0 0 2px var(--isis-module-hue, var(--isis-current-mod)); }
.isis-ctxcard__avatar { width: 30px; height: 30px; border-radius: 8px; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; font-size: 0.8125rem; font-weight: 800; overflow: hidden; }
.isis-ctxcard__avatar img { width: 100%; height: 100%; object-fit: cover; }
.isis-ctxcard__avatar--mod { background: var(--isis-module-hue, var(--isis-current-mod)); color: #fff; }
.isis-ctxcard__text { min-width: 0; display: flex; flex-direction: column; line-height: 1.18; flex: 1; }
.isis-ctxcard__title { font-size: 0.84rem; font-weight: 670; color: var(--isis-text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.isis-ctxcard__sub { font-size: 0.66rem; color: var(--isis-text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.isis-ctxcard__div { width: 1px; align-self: stretch; margin: 7px 0; background: color-mix(in oklch, var(--isis-module-hue, var(--isis-current-mod)) 22%, transparent); flex: 0 0 auto; }
.isis-ctxcard__collapse { flex: 0 0 auto; width: 34px; align-self: stretch; display: inline-flex; align-items: center; justify-content: center; border: none; background: transparent; color: var(--isis-module-hue, var(--isis-current-mod)); cursor: pointer; }
.isis-ctxcard__collapse:hover { background: color-mix(in oklch, var(--isis-module-hue, var(--isis-current-mod)) 14%, transparent); }
.isis-ctxcard__collapse:focus-visible { outline: none; box-shadow: inset 0 0 0 2px var(--isis-module-hue, var(--isis-current-mod)); }
/* mode réduit : la carte module devient un avatar-bouton 36×36 centré */
.isis-ctxcard--collapsed { display: inline-flex; align-items: center; justify-content: center; width: 36px; height: 36px; margin: 0 auto; padding: 3px; cursor: pointer; }
/* bouton « étendre le panneau » (mode réduit), sous les avatars de contexte */
.isis-ctxzone__expand { width: 32px; height: 32px; margin: 2px auto 0; display: inline-flex; align-items: center; justify-content: center; border: 1px solid var(--isis-border-strong); border-radius: var(--isis-radius); background: var(--isis-surface); color: var(--isis-text-muted); cursor: pointer; }
.isis-ctxzone__expand:hover { background: var(--isis-surface-alt); }
.isis-ctxzone__expand:focus-visible { outline: none; box-shadow: 0 0 0 3px color-mix(in oklch, var(--isis-accent) 30%, transparent); }

/* Pilule « espace de travail » (en-tête, zone 2) — refonte 2026-09-24, variante A.
   Quittée la sidebar : elle vit désormais à gauche du sélecteur de module, dans les DEUX
   dispositions (l'espace de travail n'est pas une propriété du module). Texte seul — ni
   vignette d'entreprise ni cartouche de groupe, les logos clients ayant été retirés du
   chrome : plus de tuile logo, plus de mode réduit. Géométrie et teintes alignées sur
   .isis-header__modsel (36 px, fond et bordure NEUTRES) — deux sélecteurs jumeaux, côte
   à côte ; l'espace de travail ne prend pas la couleur du module.
   box-sizing explicite : la variante verrouillée est un <span> (pas un bouton, qui l'aurait
   hérité de la feuille du navigateur) et ce projet n'a PAS de reset universel — sans lui,
   ses bordures ajouteraient 2 px et la pilule dépasserait sa jumelle. */
.isis-wscard { box-sizing: border-box; display: inline-flex; align-items: center; gap: 9px; flex-shrink: 0; max-width: 250px; height: 36px; padding: 0 10px; border: 1px solid var(--isis-border); border-radius: var(--isis-radius); background: var(--isis-surface); color: var(--isis-text); cursor: pointer; text-align: left; font: inherit; transition: border-color 120ms, background-color 120ms; }
.isis-wscard.is-switchable:hover { border-color: color-mix(in oklch, var(--isis-accent) 38%, var(--isis-border)); }
.isis-wscard:focus-visible { outline: none; box-shadow: 0 0 0 3px color-mix(in oklch, var(--isis-accent) 28%, transparent); }
/* Une seule entreprise accessible : le bloc cesse de mimer un contrôle — c'est un <span>
   (pas un <button disabled>, dont l'infobulle serait inatteignable), donc le curseur et
   le cadre se neutralisent ici. */
.isis-wscard.is-locked { border-color: transparent; background: transparent; cursor: default; }

.isis-wscard__txt { min-width: 0; flex: 1 1 auto; display: flex; flex-direction: column; line-height: 1.08; }
.isis-wscard__name { font-size: 0.86rem; font-weight: 670; color: var(--isis-text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* --isis-text-muted et non -soft : à cette taille, `soft` tombait à 4,05:1 sur la surface
   Nocturne (échec AA 1.4.3). `muted` donne 7,58:1 en clair et 6,98:1 en sombre (ratios
   recalculés le 2026-07-18 — ne pas se fier aux valeurs annoncées dans les commentaires
   de tokens). Même valeur que .isis-header__modsel-cat, la ligne jumelle. */
.isis-wscard__grp { font-size: 0.66rem; font-weight: 500; color: var(--isis-text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* opacity plutôt que color : c'est le mécanisme déjà établi par l'autre chevron
   « ouvre une modale » de la même barre (HeaderModuleSelector). */
.isis-wscard__chev { flex: 0 0 auto; display: inline-flex; font-size: 16px; opacity: 0.55; }

/* Mid-range : même seuil que le sélecteur de module (qui se replie sur son icône). La
   pilule garde son NOM — sans lui l'espace de travail n'est plus identifiable — et n'abandonne
   que la ligne de rattachement, redondante avec le lockup de marque de la zone 1. */
@media (max-width: 1100px) {
    .isis-wscard { max-width: 170px; }
    .isis-wscard__grp { display: none; }
}

.isis-shell__content {
    flex: 1;
    min-width: 0;
    overflow-y: auto;
    overflow-x: hidden;
    /* Refonte 2026-05-26 : fond blanc pur. La teinte module 4 % (Branded depth
       2026-05-17, via color-mix sur --isis-current-mod) a été retirée — elle
       tirait vers le violet pâle sur les pages sans module (fallback accent ISIS
       indigo). L'identité chromatique du module passe désormais par le rail
       sombre + breadcrumb header coloré + accent CTA/KPI, sans teindre la zone
       de lecture principale.
       Les cartes/grilles posent leur propre fond .isis-surface-alt là où elles
       ont besoin de contraste contre le shell. */
    background-color: var(--isis-surface);
    /* Accent effectif — dérivé de l'identité module : les règles .mod-{code}
       (plus bas) posent --isis-module-hue ; ici on en dérive --isis-current-mod
       avec accent en fallback. En mode « couleur de module unifiée », la règle
       .isis-mod-unified (plus bas) fige cette dérivation. */
    --isis-current-mod:       var(--isis-module-hue, var(--isis-accent));
    --isis-current-mod-soft:  var(--isis-module-hue-soft, var(--isis-accent-soft));
    /* Variante assombrie de --isis-current-mod pour du texte posé sur --isis-current-mod-soft
       (ex. .isis-subtab.is-active) — --isis-mod-active-mix (défini dans :root, redéfini en
       sombre) porte le dosage, pas cette règle : ainsi ce token suit correctement le module ET
       le thème sans être redéclaré dans chacune des 16 règles .mod-{code} ci-dessous. */
    --isis-current-mod-strong: color-mix(in srgb, var(--isis-current-mod) var(--isis-mod-active-mix), black);
    transition: background-color 200ms ease;
}
/* Le tiroir « Avis et aide » (.isis-assist__drawer, PageAssistButton.razor.css, scopé) POUSSE
   le contenu au lieu de le recouvrir à partir de 1280 px — sous ce seuil il reste position:
   fixed et recouvre (comportement par défaut de sa propre feuille). Cette règle DOIT vivre ici,
   dans la feuille globale : le tiroir et .isis-shell__content sont deux frères rendus par des
   composants différents (PageAssistButton / MainLayout), donc un sélecteur :has() entre les deux
   ne peut jamais matcher depuis une feuille scopée (l'isolation CSS Blazor suffixe le DERNIER
   sélecteur du combinateur d'un attribut [b-xxxx] propre au composant qui le rend — .isis-shell__
   content n'a jamais celui de PageAssistButton). Seuil unique 1280 px, écrit une seule fois. */
@media (min-width: 1280px) {
    .isis-shell:has(.isis-assist__drawer:not([hidden])) .isis-shell__content { margin-inline-end: var(--isis-assist-width); }
}
/* ... et il passe DEVANT le reste. Le tiroir est rendu dans l'en-tête (.isis-header,
   position: relative + z-index: 50) : son propre z-index 1040 est donc résolu DANS ce
   contexte d'empilement, jamais à la racine. Tout ce que la page pose au-dessus de 50 le
   recouvre — mesuré sur /gescom/devis/{id} en plein écran, où .isis-focus-zone--expanded
   (950) cachait 92 % de sa surface. On monte la CELLULE (l'en-tête), pas le panneau, et
   seulement tant que le tiroir est ouvert : un 1000 permanent passerait aussi devant
   l'organigramme sirh agrandi (inset: 0, z-index 950), qui recouvre l'en-tête
   délibérément. 1000 reste sous les dialogs Radzen (1010+). */
.isis-shell:has(.isis-assist__drawer:not([hidden])) .isis-header { z-index: 1000; }
/* Même piège, même remède, pour le menu utilisateur de l'en-tête : son panneau est en
   position: absolute, donc résolu DANS le contexte d'empilement de .isis-header (50) et
   jamais à la racine — son z-index: 1001 ne vaut que là-dedans, et tout ce que la page
   pose au-dessus de 50 le recouvre (barre d'actions de masse 100, tiroir master-detail
   940, zone de focus agrandie 950, bouton d'avis 990). On monte la CELLULE, et seulement
   tant que le menu est déployé, pour ne pas passer en permanence devant l'organigramme
   sirh agrandi (inset: 0, z-index 950) qui recouvre l'en-tête délibérément. 1000 reste
   sous les dialogs Radzen (1010+).
   ⚠ Le marqueur d'ouverture est aria-expanded="true" sur .isis-user-pill, porté par
   notre état C# : le panneau n'existe pas dans le DOM tant que le menu est fermé, donc
   aucun sélecteur ne peut se poser dessus. L'ancien marqueur Radzen (.rz-navigation-menu
   .rz-open) est mort avec la reprise du balisage le 2026-09-27. */
.isis-shell:has(.isis-header .isis-user-pill[aria-expanded="true"]) .isis-header { z-index: 1000; }
/* Même piège pour le flottant du sous-panneau : son z-index 1000 est résolu DANS le contexte
   de .isis-shell__sidebar (30), donc tout ce que la page pose au-dessus de 30 le recouvre —
   filtres flottants (50), barre de masse (100), cartes Leaflet (200-800), zone de focus
   agrandie (950, calée à left: --isis-subnav-w, pile sous le flottant). Le flottant n'existe
   dans le DOM que déployé (@if (ouvert) d'AppSubNav) : on monte la cellule le temps qu'il vit. */
.isis-shell:has(.isis-subnav__flyout) .isis-shell__sidebar { z-index: 1000; }
@media (prefers-reduced-motion: no-preference) {
    /* Le shorthand `transition` REMPLACE, il n'additionne pas : on reprend donc
       background-color 200ms ease du bloc de base ci-dessus pour ne pas le perdre. */
    .isis-shell__content { transition: background-color 200ms ease, margin-inline-end .2s ease; }
}
/* Identité module — --isis-module-hue posé sur .isis-shell ET .isis-shell__content :
   - .isis-shell : pour que le header (soeur du content) puisse la lire ;
   - .isis-shell__content : rétro-compat (sélecteur historique consommé par pages).
   L'accent EFFECTIF (--isis-current-mod) dérive de cette identité juste en dessous —
   sauf en mode « couleur de module unifiée » qui le fige. */
.isis-shell.mod-gescom,    .isis-shell__content.mod-gescom    { --isis-module-hue: var(--isis-mod-gescom);    --isis-module-hue-soft: var(--isis-mod-gescom-soft); }
.isis-shell.mod-gescompta, .isis-shell__content.mod-gescompta { --isis-module-hue: var(--isis-mod-gescompta); --isis-module-hue-soft: var(--isis-mod-gescompta-soft); }
.isis-shell.mod-sirh,      .isis-shell__content.mod-sirh      { --isis-module-hue: var(--isis-mod-sirh);      --isis-module-hue-soft: var(--isis-mod-sirh-soft); }
.isis-shell.mod-admin,     .isis-shell__content.mod-admin     { --isis-module-hue: var(--isis-mod-admin);     --isis-module-hue-soft: var(--isis-mod-admin-soft); }
.isis-shell.mod-ged,       .isis-shell__content.mod-ged       { --isis-module-hue: var(--isis-mod-ged);       --isis-module-hue-soft: var(--isis-mod-ged-soft); }
.isis-shell.mod-gesproj,   .isis-shell__content.mod-gesproj   { --isis-module-hue: var(--isis-mod-gesproj);   --isis-module-hue-soft: var(--isis-mod-gesproj-soft); }
.isis-shell.mod-gesmaff,   .isis-shell__content.mod-gesmaff   { --isis-module-hue: var(--isis-mod-gesmaff);   --isis-module-hue-soft: var(--isis-mod-gesmaff-soft); }
.isis-shell.mod-gesst,     .isis-shell__content.mod-gesst     { --isis-module-hue: var(--isis-mod-gesst);     --isis-module-hue-soft: var(--isis-mod-gesst-soft); }
.isis-shell.mod-gesmat,    .isis-shell__content.mod-gesmat    { --isis-module-hue: var(--isis-mod-gesmat);    --isis-module-hue-soft: var(--isis-mod-gesmat-soft); }
.isis-shell.mod-gespark,   .isis-shell__content.mod-gespark   { --isis-module-hue: var(--isis-mod-gespark);   --isis-module-hue-soft: var(--isis-mod-gespark-soft); }
.isis-shell.mod-gesinfo,   .isis-shell__content.mod-gesinfo   { --isis-module-hue: var(--isis-mod-gesinfo);   --isis-module-hue-soft: var(--isis-mod-gesinfo-soft); }
.isis-shell.mod-gesmob,    .isis-shell__content.mod-gesmob    { --isis-module-hue: var(--isis-mod-gesmob);    --isis-module-hue-soft: var(--isis-mod-gesmob-soft); }
.isis-shell.mod-gesfac,    .isis-shell__content.mod-gesfac    { --isis-module-hue: var(--isis-mod-gesfac);    --isis-module-hue-soft: var(--isis-mod-gesfac-soft); }
.isis-shell.mod-gespla,    .isis-shell__content.mod-gespla    { --isis-module-hue: var(--isis-mod-gespla);    --isis-module-hue-soft: var(--isis-mod-gespla-soft); }
.isis-shell.mod-gesqhse,   .isis-shell__content.mod-gesqhse   { --isis-module-hue: var(--isis-mod-gesqhse);   --isis-module-hue-soft: var(--isis-mod-gesqhse-soft); }

/* Effectif ← identité : hors mode unifié, l'accent d'écran suit le module courant.
   Déclaré aussi sur .isis-shell (le header, soeur du content, le lit). PAS de fallback
   accent ici : quand --isis-module-hue est absente (monespace, pages sans module), la
   variable doit rester invalide comme avant la séparation — les consommateurs avec
   fallback retombent sur accent, ceux qui n'en ont pas (carte module sidebar) restent
   non teintés. Un fallback accent ici rendrait la variable toujours valide et
   changerait ce comportement. */
.isis-shell {
    --isis-current-mod:      var(--isis-module-hue);
    --isis-current-mod-soft: var(--isis-module-hue-soft);
}

/* Mode « couleur de module unifiée » (option tenant — classe posée par MainLayout
   d'après le cookie isis_mod_unified, lui-même posé par ThemeSync) : l'accent d'écran
   cesse de suivre le module. Cascade C → A → B : --isis-unified-mod (couleur dédiée
   du tenant) → --isis-accent (qui porte déjà la marque white-label quand elle existe)
   → accent ISIS défaut. Seul le sélecteur de module
   (header .isis-header__modsel* et carte sidebar .isis-ctxcard*) lit encore
   --isis-module-hue (l'identité brute). Troisième exemption de facto, non corrigée ici :
   les icônes de bandeau .isis-rich-header__icon.mod-{code}-soft (style répété en dur sur
   ~200 écrans) restent module-colorées en mode unifié — limite connue. */
.isis-shell.isis-mod-unified,
.isis-shell.isis-mod-unified .isis-shell__content {
    --isis-current-mod:      var(--isis-unified-mod,      var(--isis-accent));
    --isis-current-mod-soft: var(--isis-unified-mod-soft, var(--isis-accent-soft));
}

/* Transition 200ms sur tous les éléments porteurs de --isis-current-mod —
   évite le "flash" de couleur quand l'utilisateur switche de module via le rail.
   Conforme DESIGN.md §1 motion 3/10 (≤300ms ease). */
.isis-rich-toolbar__btn--primary,
.isis-rich-header__main,
.isis-kpi-card__value {
    transition: background-color 200ms ease, color 200ms ease, border-color 200ms ease;
}

/* ============================================================================
   Empty state (composant IsisEmptyState)
   ============================================================================ */
.isis-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: 0.75rem;
    padding: 3.5rem 1.5rem;
    max-width: 480px;
    margin: 0 auto;
}
.isis-empty__icon-wrap {
    width: 96px;
    height: 96px;
    border-radius: 50%;
    background-color: var(--isis-current-mod-soft, var(--isis-accent-soft));
    color: var(--isis-current-mod, var(--isis-accent));
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: background-color 200ms ease, color 200ms ease;
}
.isis-empty__icon-wrap .rzi { font-size: 44px; }
.isis-empty__title {
    font-size: 1.15rem;
    font-weight: 600;
    color: var(--isis-text);
    margin: 0.5rem 0 0;
    line-height: 1.3;
}
.isis-empty__hint {
    font-size: 0.875rem;
    color: var(--isis-text-muted);
    margin: 0;
    line-height: 1.5;
    max-width: 360px;
}
/* Lien vers la fiche d'aide de l'écran (IPageAssist.OpenHelp), affiché quand HelpSection est fourni. */
.isis-empty__help {
    background: none;
    border: 0;
    padding: 0;
    color: var(--isis-current-mod, var(--isis-accent));
    text-decoration: underline;
    cursor: pointer;
    font-size: 0.875rem;
}
.isis-empty__help:focus-visible {
    outline: 2px solid var(--isis-current-mod, var(--isis-accent));
    outline-offset: 2px;
}
.isis-empty__actions {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    margin-top: 0.5rem;
    flex-wrap: wrap;
    justify-content: center;
}
/* WCAG 2.5.8 — `.isis-text-link` (padding: 0 ligne ~23595) tombe sous 24×24px de cible ;
   portée à cette seule zone plutôt qu'au sélecteur global, qu'on ne veut pas élargir partout
   ailleurs dans l'appli. min-height + inline-flex forcent la boîte à 24px sans décaler le
   lien de sa ligne ; spécificité (0,2,0) l'emporte sur `button.isis-text-link` (0,1,1). */
.isis-empty__actions .isis-text-link {
    padding: 0.25rem 0.15rem;
    min-height: 24px;
    display: inline-flex;
    align-items: center;
}
/* WCAG 2.4.7 — le focus-visible global de `.isis-text-link` (ligne ~23610) ne change que le
   soulignement et la couleur du texte, insuffisant comme seule affordance de focus pour cette
   action primaire d'état vide (remplace un bouton qui portait un halo). Même anneau que
   `.isis-workflow-branch__links .isis-text-link:focus-visible` (ligne ~17439). */
.isis-empty__actions .isis-text-link:focus-visible {
    outline: 2px solid var(--isis-accent);
    outline-offset: 2px;
    border-radius: 3px;
}

/* Variant neutre — pour les écrans sans contexte module (login, error pages…) */
.isis-empty--neutral .isis-empty__icon-wrap {
    background-color: var(--isis-surface-alt);
    color: var(--isis-text-muted);
}

/* ============================================================================
   Header (56px)
   ============================================================================ */
.isis-header {
    height: var(--isis-header-h);
    background-color: var(--isis-surface);
    border-bottom: 1px solid var(--isis-border);
    /* Relief structurel amplifié — refonte 2026-05-26 « branded depth ».
       Shadow 4× plus marquée que l'ancienne 1px : décolle visuellement le header
       du content, signal d'autorité du shell. Exception documentée DESIGN.md §1. */
    box-shadow: 0 4px 16px rgba(15, 23, 42, 0.08);
    /* Refonte 2026-05-27 — 2 zones structurées :
       Zone 1 (var(--isis-subnav-w) = 240px, alignée pixel-perfect avec le sub-nav
       en dessous) : brand + workspace switcher (= identité)
       Zone 2 (1fr, alignée avec le content) : breadcrumb module + search + notif + user
       En mode sub-nav collapsé (.isis-shell.is-subnav-collapsed), la zone 1 se
       compresse à 64px en synchro avec le sub-nav (transition 200ms). */
    display: grid;
    grid-template-columns: var(--isis-subnav-w) 1fr;
    transition: grid-template-columns 200ms cubic-bezier(0.4, 0, 0.2, 1);
    flex-shrink: 0;
    position: relative;
    z-index: 50;
}
/* Le panneau de recherche universelle vit DANS l'en-tête depuis le 2026-09-26 (sa saisie
   est la pilule). Or `z-index: 50` fait de `.isis-header` un CONTEXTE D'EMPILEMENT : un
   descendant `position: fixed` y est plafonné à la couche 50, quel que soit son propre
   z-index — le panneau passerait sous les dialogues Radzen. On relève donc l'en-tête
   entier, le temps de l'ouverture seulement : laissé à 1001, il passerait devant ces mêmes
   dialogues. La classe est posée et retirée par command-palette.js — AppHeader est rendu en
   SSR statique, aucun code C# ne peut réécrire sa classe. */
.isis-header.is-search-open {
    z-index: 1001;
}
.isis-shell.is-subnav-collapsed .isis-header {
    grid-template-columns: var(--isis-subnav-w-collapsed, 64px) 1fr;
}

/* Zone 1 — identité (brand + workspace switcher).
   Bordure droite alignée pixel-perfect avec celle du sub-nav en dessous.

   PAS d'overflow:hidden ici : le menu déroulant du WorkspaceSwitcher fait
   ~300px et doit pouvoir déborder dans la zone 2 par-dessus le crumb (il a
   son propre z-index 100 et un backdrop pour fermer au click outside).
   Le nom « ISIS SOLUTION » est masqué via display:none plutôt qu'overflow. */
.isis-header__zone-1 {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0 0.85rem;
    border-right: 1px solid var(--isis-border-strong);
    min-width: 0;
}
/* Le nom ISIS SOLUTION se masque en mode collapsé (pas la place dans 64px). */
.isis-shell.is-subnav-collapsed .isis-header__brand-name {
    display: none;
}

/* Zone 2 — module + actions (crumb + search + notif + user). */
.isis-header__zone-2 {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0 1rem;
    min-width: 0;
}

.isis-header__brand {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: 0.625rem;
    text-decoration: none;
    color: inherit;
    transition: opacity 120ms;
    /* Plus de padding-right ni border-right : la séparation visuelle est désormais
       portée par .isis-header__zone-1 (border-right). */
    flex-shrink: 0;
    min-width: 0;
}
.isis-header__brand:hover { opacity: 0.75; }
.isis-header__brand:focus-visible {
    outline: 2px solid var(--isis-accent);
    outline-offset: 2px;
    border-radius: 4px;
}
.isis-header__brand-logo {
    width: 36px;
    height: 36px;
    flex-shrink: 0;
    display: block;
}
/* Nom de marque en deux lignes empilées : le produit, puis « RESOURCE PLANNER » en tagline */
.isis-header__brand-name {
    display: flex;
    flex-direction: column;
    line-height: 1;
    gap: 2px;
}
.isis-header__brand-name-l1 {
    font-size: 0.95rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    color: var(--isis-text);
    white-space: nowrap;
}
/* "RESOURCE PLANNER" sur sa propre ligne sous "IRIS" (lockup 2 lignes, nom long). */
.isis-header__brand-name-suffix {
    margin-left: 0;
    font-size: 0.58rem;
    font-weight: 600;
    letter-spacing: 0.13em;
    color: var(--isis-text-muted);
    white-space: nowrap;
}
/* Signature éditeur « by IrisSoft » — très discrète sous le lockup, alignée à gauche. */
.isis-header__brand-by {
    align-self: flex-end;
    text-align: right;
    font-size: 0.5rem;
    font-weight: 500;
    letter-spacing: 0.04em;
    color: var(--isis-text-subtle, var(--isis-text-muted));
    opacity: 0.75;
    white-space: nowrap;
    margin-top: 1px;
}
/* Signature de marque "UpDate the System" — mono, accent, sous le wordmark.
   Conservée mixte-casse (capital D) pour respecter l'orthographe du slogan. */
.isis-header__brand-sig {
    font-family: var(--isis-cockpit-mono);
    font-size: 0.6rem;
    font-weight: 600;
    letter-spacing: 0.05em;
    color: var(--isis-accent);
    white-space: nowrap;
}
/* ----------------------------------------------------------------------------
   Bloc tenant historique — DÉPRÉCIÉ depuis refonte shell 2026-05-26.
   Markup retiré de AppHeader.razor ; le tenant vit désormais en tête du dropdown
   AppUserMenu. CSS conservé temporairement (rien ne le rend, coût ≈ 0) pour le
   cas où une page custom le réutiliserait — à supprimer définitivement V1.1.
   ---------------------------------------------------------------------------- */
.isis-header__tenant {
    display: flex;
    flex-direction: column;
    line-height: 1;
}
.isis-header__tenant-label {
    font-size: 0.65rem;
    letter-spacing: 0.1em;
    color: var(--isis-text-soft);
}
.isis-header__tenant-name {
    font-size: 0.95rem;
    font-weight: 600;
    color: var(--isis-text);
    margin-top: 2px;
}

/* ----------------------------------------------------------------------------
   Breadcrumb module courant (.isis-header__crumb)
   Refonte shell 2026-05-26 : remplace le bloc tenant historique. Donne un repère
   chromatique permanent du module où l'on est, en plus du rail (qui peut être
   hors de vue sur écran étroit) et de la teinte 4 % du content.

   Visible uniquement si Nav.CurrentModule != null (pages hors-module : caché).
   ---------------------------------------------------------------------------- */
.isis-header__crumb {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    height: 32px;
    padding: 0 0.75rem 0 0.6rem;
    background-color: var(--isis-current-mod-soft, var(--isis-accent-soft));
    border-radius: var(--isis-radius-pill);
    color: var(--isis-text);
    font-size: 0.875rem;
    font-weight: 600;
    line-height: 1;
    transition: background-color 200ms ease, color 200ms ease;
    /* Sécurise contre l'écrasement par les autres éléments à droite (workspace,
       search…) — le crumb ne tronque jamais avant les autres éléments flexibles. */
    flex-shrink: 0;
    max-width: 240px;
}
/* Dédup indicateur module : la carte module du sub-nav (mode étendu) montre déjà
   le module → le crumb header n'est utile qu'en mode collapsé. */
.isis-shell:not(.is-subnav-collapsed) .isis-header__crumb { display: none; }
.isis-header__crumb-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    color: var(--isis-current-mod, var(--isis-accent));
}
.isis-header__crumb-icon .rzi {
    font-size: 18px;
    transition: color 200ms ease;
}
.isis-header__crumb-label {
    color: var(--isis-current-mod, var(--isis-accent));
    /* Stretch + ellipsis si nom module long (« Marchés & Affaires », « Matériel TP », etc.) */
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    transition: color 200ms ease;
}
@media (max-width: 900px) {
    .isis-header__crumb-label { display: none; }
    .isis-header__crumb { padding: 0 0.5rem; }
}

/* ============================================================================
   Sélecteur de module DANS LE HEADER — disposition « Header » (thème tenant).
   Piloté par la classe .isis-shell.isis-modsel--header (posée par ThemeSync selon
   TenantTheme.ModuleSelectorPlacement). Par défaut (disposition « Sidebar »), ce
   groupe est masqué et le sélecteur vit dans la sidebar (WorkspaceBar). Le composant
   est rendu aux deux endroits ; seul le CSS bascule la visibilité → aucun flash.
   ============================================================================ */
.isis-header__modsel-group { display: none; align-items: center; gap: 8px; flex-shrink: 0; }
/* Classe émise par MainLayout sur .isis-shell d'après Nav.IsModuleSelectorInHeader
   (cookie isis_modsel_header) → présente dès le markup SSR, survit à l'enhanced-nav. */
.isis-shell.isis-modsel--header .isis-header__modsel-group { display: inline-flex; }
/* En disposition Header : le crumb statique ET la carte module de la sidebar (mode
   étendu comme réduit) sont masqués — le sélecteur header les remplace. */
.isis-shell.isis-modsel--header .isis-header__crumb { display: none; }
.isis-shell.isis-modsel--header .isis-ctxcard--mod,
.isis-shell.isis-modsel--header .isis-ctxzone__expand { display: none; }
/* La pilule « espace de travail » est partie dans l'en-tête (2026-09-24) : en disposition
   Header, la zone de contexte n'a plus aucun enfant visible. On la retire du flux — son
   padding creusait sinon un blanc de 16 px au-dessus du panneau menu. */
.isis-shell.isis-modsel--header .isis-shell__ctxzone {
    display: none;
}

/* Levier de repli du panneau : groupe à part depuis le 2026-09-24, pour que la pilule
   « espace de travail » s'intercale entre lui et le sélecteur de module sans `order` flex
   (qui aurait désaccordé l'ordre de focus de l'ordre visuel — WCAG 2.4.3). Même bascule
   de visibilité que le groupe sélecteur : Header seulement. */
.isis-header__panelctl { display: none; align-items: center; gap: 8px; flex-shrink: 0; }
.isis-shell.isis-modsel--header .isis-header__panelctl { display: inline-flex; }

.isis-header__modsel-collapse {
    width: 32px; height: 32px; flex-shrink: 0;
    display: inline-flex; align-items: center; justify-content: center;
    border: 1px solid var(--isis-border); border-radius: var(--isis-radius-sm, 6px);
    background: var(--isis-surface); color: var(--isis-text-muted);
    cursor: pointer; transition: background-color 120ms, color 120ms;
}
.isis-header__modsel-collapse:hover { background: var(--isis-surface-alt); color: var(--isis-text); }
.isis-header__modsel-collapse .rzi { font-size: 20px; }
.isis-header__modsel-collapse:focus-visible { outline: none; box-shadow: 0 0 0 3px color-mix(in oklch, var(--isis-accent) 28%, transparent); }
/* Sous 1024 px le rail se replie tout seul (DESIGN.md §5) et son propre bouton « Étendre » est
   masqué en disposition Header : cette bascule devient l'UNIQUE levier de sortie, sur la plage
   tablette que DESIGN.md désigne comme prioritaire. Elle y prend donc la cible tactile de 44×44
   qu'exige §5 — par la boîte, l'icône ne bouge pas. */
@media (max-width: 1023.98px) {
    .isis-header__modsel-collapse { width: 44px; height: 44px; }
}

.isis-header__modsel-div { width: 1px; height: 24px; background: var(--isis-border); flex-shrink: 0; }

.isis-header__modsel {
    display: inline-flex; align-items: center; gap: 9px; flex-shrink: 0;
    height: 36px; padding: 0 10px; font: inherit; cursor: pointer; text-align: left;
    /* Fond/bordure NEUTRES (décision « pas de teinte ») : sur le near-white, le mix
       couleur module pâle virait au mauve/rose. L'identité module est portée par son
       nom ; l'icône colorée (.isis-header__modsel-ic) ne reparaît que sous 1100 px. */
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius);
    background: var(--isis-surface);
    color: var(--isis-text);
    transition: border-color 120ms, background-color 120ms;
}
.isis-header__modsel:hover { border-color: color-mix(in oklch, var(--isis-module-hue, var(--isis-current-mod, var(--isis-accent))) 38%, var(--isis-border)); }
.isis-header__modsel:focus-visible { outline: none; box-shadow: 0 0 0 3px color-mix(in oklch, var(--isis-module-hue, var(--isis-current-mod, var(--isis-accent))) 28%, transparent); }
/* Masquée tant que le nom se lit (2026-09-22) ; seul repère du module une fois le libellé replié. */
.isis-header__modsel-ic {
    width: 26px; height: 26px; border-radius: 7px; flex-shrink: 0;
    display: none; align-items: center; justify-content: center;
    background: var(--isis-module-hue, var(--isis-current-mod, var(--isis-accent))); color: #fff;
}
.isis-header__modsel-ic .rzi { font-size: 16px; }
.isis-header__modsel-tx { display: flex; flex-direction: column; line-height: 1.08; min-width: 0; }
.isis-header__modsel-name { font-size: 0.86rem; font-weight: 670; color: var(--isis-text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.isis-header__modsel-cat { font-size: 0.66rem; color: var(--isis-text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* Mid-range (~900–1100px) : on replie le sélecteur sur son icône pour décharger la
   zone 2 avant que la recherche ne se comprime. */
@media (max-width: 1100px) {
    .isis-header__modsel-tx { display: none; }
    .isis-header__modsel-ic { display: inline-flex; }
    .isis-header__modsel { padding: 0 8px; }
}

.isis-header__spacer { flex: 1; }

/* ── Recherche universelle : LA PILULE EST LE CHAMP (refonte 2026-09-26) ─────────────
   Jusqu'ici cette pilule était un <button> et le vrai champ vivait dans le panneau : deux
   champs à l'écran, un seul qui servait, et un clic obligatoire avant de pouvoir taper.
   Elle habille désormais la saisie elle-même (cf. CommandPalette.razor). Au repos elle garde
   l'aspect d'un champ discret teinté du module ; ouverte, elle s'élargit et prend une vraie
   surface, le panneau de résultats venant se poser dessous. */
.isis-header__search {
    /* relative pour DEUX raisons : le bouton de repli sous 900 px se pose en recouvrement
       (inset: 0), et la pilule doit pouvoir passer AU-DESSUS du capteur de clic extérieur
       (.isis-cmdp-backdrop, z-index 1000) — désormais son frère dans l'en-tête. */
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 0.6rem;
    height: 36px;
    width: 320px;
    max-width: 100%;
    padding: 0 0.6rem 0 0.85rem;
    /* Refonte 2026-05-26 : porte la couleur du module courant en fond très diluté.
       Réagit au changement de module via --isis-current-mod-soft (transition
       déjà déclarée sur .isis-shell__content). Plus de "champ désactivé". */
    background-color: var(--isis-current-mod-soft, var(--isis-accent-soft));
    border: 1px solid transparent;
    border-radius: var(--isis-radius-pill);
    color: var(--isis-text-muted);
    font-size: 0.85rem;
    /* text, plus pointer : c'est un champ de saisie, le curseur doit le dire. */
    cursor: text;
    transition: width 160ms cubic-bezier(0.4, 0, 0.2, 1),
                background-color 150ms ease, border-color 150ms ease, color 150ms ease;
}
.isis-header__search .rzi {
    color: var(--isis-current-mod, var(--isis-accent));
    transition: color 150ms ease;
}
.isis-header__search:hover {
    background-color: var(--isis-surface);
    border-color: var(--isis-current-mod, var(--isis-accent));
    color: var(--isis-text);
}
/* OUVERTE : surface franche, bord module, et 240 px de plus — une requête longue doit
   rester lisible en entier pendant qu'on lit les résultats. */
.isis-header__search.is-open {
    width: 560px;
    background-color: var(--isis-surface);
    border-color: var(--isis-current-mod, var(--isis-accent));
    color: var(--isis-text);
    box-shadow: var(--isis-elevation-1);
    /* Au-dessus du capteur de clic extérieur : sinon le premier clic DANS le champ lui est
       avalé et referme ce qu'il vient d'ouvrir. */
    z-index: 1001;
}
/* Le halo de focus est porté par la PILULE, pas par la saisie : dessiné sur l'input, il
   traçait un rectangle à l'intérieur d'une pilule arrondie. */
.isis-header__search:has(.isis-header__search-input:focus-visible) {
    outline: 2px solid var(--isis-current-mod, var(--isis-accent));
    outline-offset: 2px;
}
/* ⚠ Les trois règles ci-dessous rappellent .isis-header pour la SPÉCIFICITÉ, pas par
   goût : la saisie porte AUSSI la classe .isis-cmdp__input, dont les règles vivent
   39 000 lignes plus bas. À spécificité égale c'est la position dans le fichier qui
   tranche, et ce sont elles qui gagneraient (taille 1rem, texte de substitution pâle). */
.isis-header .isis-header__search-input {
    flex: 1;
    min-width: 0;
    padding: 0;
    border: none;
    outline: none;
    background: transparent;
    color: var(--isis-text);
    font-family: inherit;
    /* 1rem dans une pilule de 36 px déborde : le champ prend la taille de la pilule. */
    font-size: 0.85rem;
}
/* Trois classes pour battre `.isis-cmdp__input:focus-visible`, qui est à DEUX et gagnerait
   par sa position : sans ça, le halo du champ se dessine EN PLUS de celui de la pilule,
   soit deux anneaux imbriqués sur une seule zone focalisée. */
.isis-header .isis-header__search-input:focus-visible {
    outline: none;
}
/* Au repos, ce texte de substitution est la SEULE étiquette visible de la recherche : il
   doit tenir le plancher de contraste, ce que --isis-text-soft (3,82:1) ne fait pas. */
.isis-header .isis-header__search-input::placeholder {
    color: var(--isis-text-muted);
    opacity: 1;
}
/* Repli sous 900 px UNIQUEMENT (cf. règle média) : au-dessus il n'existe pas, sans quoi il
   recouvrirait le champ et rendrait la frappe impossible. */
.isis-header__search-btn { display: none; }
/* Sombre (Nocturne) : le lavis module-soft (#16243d navy) ressort comme un patch
   PLUS clair que le header quasi-noir → l'input paraît « pas passé en sombre ».
   On lui donne une vraie surface neutre sombre + hairline ; le module reste porté
   par l'icône, la bordure au survol et le focus. */
:root[data-theme="dark"] .isis-header__search {
    background-color: var(--isis-surface-alt);
    border-color: var(--isis-border);
}
:root[data-theme="dark"] .isis-header__search:hover,
:root[data-theme="dark"] .isis-header__search.is-open {
    background-color: var(--isis-surface);
    border-color: var(--isis-current-mod, var(--isis-accent));
}
.isis-header__kbd {
    display: inline-flex;
    align-items: center;
    height: 20px;
    padding: 0 0.4rem;
    background-color: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: 4px;
    color: var(--isis-text-soft);
    font-family: var(--isis-font-mono, ui-monospace, monospace);
    font-size: 0.65rem;
    letter-spacing: 0.04em;
    line-height: 1;
}

/* Sous 900 px, 36 px de large n'héberge aucune saisie : la pilule redevient l'icône-bouton
   d'avant, et c'est le panneau qui porte SA saisie (cf. .isis-cmdp__header). Le geste de
   l'utilisateur à cette taille est donc inchangé.
   `.is-open` est visé explicitement : plus spécifique, sa largeur de 560 px l'emporterait
   sinon sur cette règle média — une pilule de 560 px dans un en-tête de téléphone. */
@media (max-width: 900px) {
    .isis-header__kbd { display: none; }
    .isis-header__search,
    .isis-header__search.is-open { width: 36px; padding: 0; justify-content: center; }
    .isis-header .isis-header__search-input { display: none; }
    .isis-header__search-btn {
        display: block;
        position: absolute;
        inset: 0;
        border: none;
        background: transparent;
        border-radius: inherit;
        cursor: pointer;
    }
    .isis-header__search-btn:focus-visible {
        outline: 2px solid var(--isis-current-mod, var(--isis-accent));
        outline-offset: 2px;
    }
    /* Ni fermeture ni témoin de requête dans 36 px : le panneau porte les deux. */
    .isis-header__search .isis-cmdp__esc,
    .isis-header__search .isis-cmdp__spinner { display: none; }
}

.isis-header__actions {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.isis-header__icon-btn {
    position: relative;
    width: 36px; height: 36px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: none;
    background: transparent;
    border-radius: 8px;
    color: var(--isis-text-muted);
    cursor: pointer;
    transition: background-color 120ms;
}
.isis-header__icon-btn:hover {
    background-color: var(--isis-surface-alt);
    color: var(--isis-text);
}
.isis-header__badge {
    position: absolute;
    top: 2px; right: 2px;
    min-width: 18px; height: 18px;
    padding: 0 5px;
    border-radius: 9px;
    background-color: #ef4444;
    color: white;
    font-size: 0.65rem;
    font-weight: 600;
    line-height: 18px;
    text-align: center;
}
.isis-header__login-link {
    display: inline-flex;
    align-items: center;
    padding: 0.5rem;
    color: var(--isis-text-muted);
    text-decoration: none;
    border-radius: 8px;
}

/* ----------------------------------------------------------------------------
   Pastille utilisateur + menu du compte (style maquette NetLogger).

   Balisage repris chez nous le 2026-09-27 : RadzenProfileMenu 11.0.4 était
   inutilisable au clavier (cf. AppUserMenu.razor). Les règles ci-dessous ne
   ciblent donc plus AUCUNE classe .rz-* — l'état ouvert se lit sur
   [aria-expanded="true"], qui est désormais fiable puisque c'est notre état C#
   qui le pose. Les noms de classe .isis-user-pill__* sont conservés tels quels :
   MobileLayout.razor.css s'y accroche pour borner la largeur du texte.
   ---------------------------------------------------------------------------- */
.isis-user-menu {
    position: relative;
    display: inline-flex;
}
.isis-user-pill {
    display: inline-flex;
    align-items: center;
    font: inherit;
    color: inherit;
    cursor: pointer;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-pill);
    padding: 0.25rem 0.5rem 0.25rem 0.85rem;
    transition: background-color 160ms ease, border-color 160ms ease, box-shadow 160ms ease;
}
.isis-user-pill:hover {
    background-color: var(--isis-surface-alt);
    border-color: var(--isis-border-strong);
}
/* Ouvert / enfoncé : le bouton reste visiblement engagé tant que le menu est
   déployé. Sans ça, rien ne rattachait le dropdown à son déclencheur. */
.isis-user-pill:active,
.isis-user-pill[aria-expanded="true"] {
    background-color: var(--isis-surface-alt);
    border-color: var(--isis-accent);
}
/* Focus clavier : halo tokenisé du design system, porté par la pilule entière
   pour un anneau qui suit le rayon du bouton. */
.isis-user-pill:focus-visible {
    outline: none;
    border-color: var(--isis-accent);
    box-shadow: var(--isis-elevation-focus);
}
.isis-user-pill__inner {
    display: flex;
    align-items: center;
    gap: 0.6rem;
}
.isis-user-pill__text {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    line-height: 1.1;
}
.isis-user-pill__name {
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--isis-text);
}
.isis-user-pill__role {
    font-size: 0.65rem;
    color: var(--isis-text-soft);
    margin-top: 2px;
}
.isis-user-pill__avatar-wrap {
    position: relative;
    display: inline-flex;
}
.isis-user-pill__photo {
    width: 36px;
    height: 36px;
    border-radius: 50%;
    object-fit: cover;
    display: block;
}
.isis-user-pill__photo--initials {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--isis-accent-soft);
    color: var(--isis-accent);
    font-size: 0.78rem;
    font-weight: 600;
    letter-spacing: 0.02em;
    line-height: 1;
    user-select: none;
}
.isis-user-pill__status {
    position: absolute;
    right: 0; bottom: 0;
    width: 10px; height: 10px;
    border-radius: 50%;
    background-color: var(--isis-success);
    border: 2px solid var(--isis-surface);
}
/* Caret : l'affordance « ceci ouvre un menu ». Celui de Radzen héritait d'une
   couleur blanche et restait INVISIBLE sur la pilule blanche en thème clair —
   il n'apparaissait qu'au survol, donc jamais au clavier ni au tactile. */
.isis-user-pill__caret {
    font-size: 18px;
    width: 18px;
    color: var(--isis-text-muted);
    margin-inline-start: 2px;
    transition: color 160ms ease;
}
.isis-user-pill:hover .isis-user-pill__caret {
    color: var(--isis-text);
}
.isis-user-pill[aria-expanded="true"] .isis-user-pill__caret {
    color: var(--isis-accent);
}

/* Voile de fermeture au clic extérieur — même patron que NotificationBell.
   Voile et panneau se relèvent ENSEMBLE : un voile seul au-dessus du panneau
   avalerait le premier clic sur une entrée. */
.isis-user-menu__backdrop {
    position: fixed;
    inset: 0;
    z-index: 1000;
}
.isis-user-menu__panel {
    position: absolute;
    top: calc(100% + 6px);
    right: 0;
    min-width: 248px;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: 8px;
    box-shadow: var(--isis-elevation-2);
    z-index: 1001;
    overflow: hidden;
    /* .isis-shell est en overflow: hidden : sans borne, une fenêtre basse (zoom 400 %,
       portable en paysage) rognerait le bas du panneau SANS défilement — « Se déconnecter »
       deviendrait inatteignable. On borne, et on rend le trop-plein défilable. */
    max-height: calc(100dvh - 4.5rem);
    overflow-y: auto;
}
.isis-user-menu__items {
    display: flex;
    flex-direction: column;
    padding: 6px;
}
.isis-user-menu__item {
    display: flex;
    align-items: center;
    gap: 10px;
    box-sizing: border-box;
    padding: 8px 10px;
    border: 0;
    border-radius: 6px;
    background: transparent;
    font: inherit;
    font-size: 0.85rem;          /* 13.6px — aligné sur les liens du rail */
    color: var(--isis-text);
    text-align: start;
    text-decoration: none;
    cursor: pointer;
}
.isis-user-menu__item:hover {
    background-color: var(--isis-surface-alt);
}
/* L'entrée focalisée est la SEULE dans l'ordre de tabulation (tabindex mobile) :
   sans marqueur visible, on ne saurait pas où l'on est dans le menu. */
.isis-user-menu__item:focus-visible {
    outline: none;
    background-color: var(--isis-surface-alt);
    box-shadow: var(--isis-elevation-focus);
}
.isis-user-menu__icon {
    flex-shrink: 0;
    font-size: 18px;
    color: var(--isis-text-muted);
}
.isis-user-menu__label {
    min-width: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

@media (prefers-reduced-motion: reduce) {
    .isis-user-pill,
    .isis-user-pill__caret {
        transition: none;
    }
}

/* ----------------------------------------------------------------------------
   En-tête tenant dans le dropdown du menu user — refonte shell 2026-05-26.
   Bloc d'identité ("où je suis"), pas un item de menu cliquable.
   Visuellement détaché des items via border-bottom + un cran de fond.
   ---------------------------------------------------------------------------- */
.isis-user-menu-tenant {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 12px 14px 14px;
    background-color: var(--isis-accent-soft);
    border-bottom: 1px solid var(--isis-border);
    /* Pas de hover/cursor: pointer — ce n'est pas une action, c'est un libellé. */
    user-select: none;
}
.isis-user-menu-tenant__avatar {
    flex-shrink: 0;
    width: 36px;
    height: 36px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background-color: var(--isis-accent);
    color: var(--isis-on-accent);
    font-size: 0.8125rem;        /* 13px */
    font-weight: 700;
    letter-spacing: 0.02em;
    line-height: 1;
}
.isis-user-menu-tenant__text {
    display: flex;
    flex-direction: column;
    line-height: 1.2;
    min-width: 0;
}
.isis-user-menu-tenant__name {
    font-size: 0.9375rem;        /* 15px */
    font-weight: 600;
    color: var(--isis-text);
    /* Title Case respecté tel que stocké en DB ; pas de UPPERCASE forcé. */
    text-transform: none;
    /* Ellipsis sur nom long pour rester dans la largeur fixe du dropdown. */
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 220px;
}
.isis-user-menu-tenant__label {
    font-size: 0.6875rem;        /* 11px */
    font-weight: 500;
    color: var(--isis-text-muted);
    letter-spacing: 0.08em;
    text-transform: uppercase;
    margin-top: 2px;
}

/* Affectation du collaborateur — sous le bloc tenant, au-dessus des items.
   Repère d'identité (entreprise employeuse + service · agence), pas une action. */
.isis-user-menu-affect {
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: 10px 14px;
    border-bottom: 1px solid var(--isis-border);
    user-select: none;
}
.isis-user-menu-affect__row {
    display: flex;
    align-items: center;
    gap: 8px;
    min-width: 0;
}
.isis-user-menu-affect__icon {
    flex-shrink: 0;
    font-size: 16px;
    color: var(--isis-text-muted);
}
.isis-user-menu-affect__text {
    font-size: 0.8125rem;        /* 13px */
    color: var(--isis-text-soft);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 220px;
}

/* Séparateur de bloc du menu du compte. Le menu est rangé en blocs (« Règle du menu utilisateur »,
   DESIGN.md) ; sans filet visuel, ses entrées se liraient comme une liste plate. Compte variable
   selon la coquille — desktop porte tout, le compagnon masque « Mot de passe » et son séparateur
   avec elle. role="separator" plutôt qu'un <hr> : le conteneur porte role="menu", pas un flux de
   document. */
.isis-user-menu-sep {
    height: 1px;
    margin: 4px 0;
    background: var(--isis-border);
}

/* ----------------------------------------------------------------------------
   Respect de prefers-reduced-motion (WCAG 2.3.3) — désactive les transitions
   du sub-nav et de l'en-tête pour les utilisateurs sensibles aux animations.
   ---------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
    .isis-subnav,
    .isis-subnav__items,
    .isis-subnav__item,
    /* Refonte shell 2026-05-27 — désactive aussi les transitions header 2 zones
       (grid-template-columns 200ms) + workspace switcher opacity + subnav width
       qui ont été ajoutées avec le sub-nav persistant. */
    .isis-header,
    .isis-header__brand-name,
    /* Sous-menu flottant (2026-09-18) : la rotation du chevron reste un changement
       d'état instantané, pas une animation. */
    .isis-subnav__chev {
        transition: none !important;
    }
}

/* ============================================================================
   Sub-nav PERSISTANT (refonte 2026-05-26 « SaaS premium »)
   Plus de position:fixed ni d'animation open/close. Vit dans le flow flex de
   .isis-shell__body aux côtés du rail, toujours visible. L'utilisateur peut
   compresser via le bouton chevron (mode icon-only 64px).

   Largeurs :
     --isis-subnav-w           = 240px (mode étendu, défaut)
     --isis-subnav-w-collapsed = 64px  (mode icon-only — items centrés sans label)
   ============================================================================ */
.isis-subnav {
    /* Refonte 2026-05-28 : .isis-subnav est désormais enfant de .isis-shell__sidebar
       qui porte la largeur (var(--isis-subnav-w)) et le border-right. Le sub-nav lui-même
       prend juste 100% de la place dispo dans son parent (flex column). */
    flex: 1 1 auto;
    width: 100%;
    background-color: var(--isis-surface);
    display: flex;
    flex-direction: column;
    /* Refonte 2026-06-23 : l'aside ne défile plus. Le défilement vit dans
       .isis-subnav__scroll (interne au cadre bordé) → la barre fine et les indices
       de fondu restent DANS le bloc, le cadre arrondi et la signature ne bougent pas. */
    overflow: hidden;
    min-height: 0;
}
.isis-subnav--expanded,
.isis-subnav--collapsed {
    /* Les modificateurs ne portent plus de largeur (gérée par le parent .isis-shell__sidebar
       via la classe .is-subnav-collapsed sur .isis-shell). Préservés comme classes-état
       qui peuvent toujours servir aux modificateurs internes du sub-nav. */
}
/* En-tête de sous-menu supprimé (refonte V2 2026-06-22) : le bouton réduire/étendre
   vit sur la carte module (cf. .isis-ctxcard__collapse / .isis-ctxzone__expand). */

.isis-subnav__items {
    display: flex;
    flex-direction: column;
    /* Cadre figé : prend toute la hauteur dispo et clippe ; le défilement est délégué
       au scroller interne. --isis-menu-bg = couleur de fond effective du bloc (surface
       par défaut, surchargée par le thème tenant) — sert aux fondus du scroller. */
    flex: 1 1 auto;
    min-height: 0;
    overflow: hidden;
    --isis-menu-bg: var(--isis-surface);
}
.isis-subnav__scroll {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 0.25rem 0.5rem 1rem;
    overflow-y: auto;
    overflow-x: hidden;
    /* Barre masquée — seuls les fondus scroll-shadow signalent qu'il reste du contenu
       (choix 2026-06-23). Scroll molette/trackpad. */
    scrollbar-width: none;
    -ms-overflow-style: none;
    /* Indices de défilement (scroll-shadow, recette Lea Verou) : les bandes « cover »
       couleur du fond masquent l'ombre tant qu'on est à l'extrémité ; dès qu'il reste
       du contenu masqué, l'ombre apparaît. Pas de fondu permanent sur le 1er/dernier item. */
    background:
        linear-gradient(var(--isis-menu-bg) 30%, transparent) center top,
        linear-gradient(transparent, var(--isis-menu-bg) 70%) center bottom,
        radial-gradient(farthest-side at 50% 0, color-mix(in srgb, var(--isis-text) 22%, transparent), transparent) center top,
        radial-gradient(farthest-side at 50% 100%, color-mix(in srgb, var(--isis-text) 22%, transparent), transparent) center bottom;
    background-repeat: no-repeat;
    background-size: 100% 26px, 100% 26px, 100% 14px, 100% 14px;
    background-attachment: local, local, scroll, scroll;
}
.isis-subnav__scroll::-webkit-scrollbar { width: 0; height: 0; display: none; }
.isis-subnav--collapsed .isis-subnav__scroll {
    padding: 0.25rem 0.4rem 1rem;
    align-items: center;
}
.isis-subnav__group-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: 100%;
    padding: 0.5rem 0.65rem 0.4rem;
    margin-top: 0.5rem;
    border: none;
    background: transparent;
    color: var(--isis-text-soft);
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    cursor: pointer;
    border-radius: 6px;
    transition: color 120ms;
}
.isis-subnav__group-header:hover {
    color: var(--isis-text-muted);
}
.isis-subnav__group-header > span:first-child {
    flex: 1;
    text-align: left;
}
.isis-subnav__group-items {
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.isis-subnav__item {
    display: flex;
    align-items: center;
    gap: 0.65rem;
    padding: 0.5rem 0.7rem;
    border-radius: 7px;
    color: var(--isis-text-muted);
    text-decoration: none;
    font-size: 0.875rem;
    line-height: 1.3;
    transition: background-color 120ms, color 120ms;
    position: relative;
}
/* Gouttière de picto d'entrée de menu : la largeur est réservée même quand le picto manque,
   sinon le libellé remonte de 18 px et la ligne se désaligne de ses voisines. */
.isis-subnav__ic { flex: 0 0 18px; display: inline-flex; align-items: center; justify-content: center; }
/* Cadenas d'une entrée verrouillée. En mode étendu il se range à droite du libellé ;
   en mode réduit il devient une pastille d'angle sur l'icône — sans quoi
   l'indisponibilité ne tiendrait plus qu'à une nuance de gris (information portée par
   la seule couleur, interdite par la charte). */
.isis-subnav__lock { font-size: 14px; margin-left: auto; }
.isis-subnav--collapsed .isis-subnav__lock {
    position: absolute; right: 2px; bottom: 2px; font-size: 11px; margin-left: 0;
}
/* Mode réduit : les en-têtes de groupe ne sont plus rendus, et rien ne marque le passage
   d'un bloc fonctionnel au suivant — une colonne de trente icônes devient continue.
   L'espacement reprend ce rôle de séparation. */
.isis-subnav--collapsed .isis-subnav__group-items + .isis-subnav__group-items { margin-top: 6px; }
.isis-subnav__item:hover:not(.isis-subnav__item--disabled) {
    background-color: var(--isis-surface-alt);
    color: var(--isis-text);
}
.isis-subnav__item.active {
    background-color: var(--isis-current-mod-soft, var(--isis-accent-soft));
    color: var(--isis-current-mod, var(--isis-accent));
    font-weight: 500;
}

/* Bande du menu (mode étendu). Le cadre 1px a été RETIRÉ le 2026-09-24 — ne pas le
   remettre : il datait du 2026-06-22, où il démarquait la nav des cartes de contexte
   empilées au-dessus d'elle. Ces cartes ont quitté la colonne (l'espace de travail est
   passé dans l'en-tête, et en disposition « Header » la zone de contexte sort du flux),
   et la teinte du bloc avait déjà disparu : il ne restait qu'un filet de la même couleur
   que le bord de colonne, à 9 px de lui, autour d'un fond identique à celui de la barre.
   Le bloc se lit désormais par son fond quand le thème tenant le teinte, et par le trait
   de colonne (.isis-shell__sidebar) sinon. L'item actif ressort en pastille blanche. */
.isis-subnav--expanded .isis-subnav__items {
    margin: 4px 9px 6px;
    background: var(--isis-surface);
}
.isis-subnav--expanded .isis-subnav__scroll { padding: 8px 8px 10px; }
/* Intensité du fond du bloc menu, pilotée par le thème tenant (classe sur .isis-shell).
   --isis-menu-bg suit la couleur effective pour que les fondus du scroller restent raccord. */
.isis-shell.isis-menu-tint--none .isis-subnav--expanded .isis-subnav__items { background: var(--isis-surface); --isis-menu-bg: var(--isis-surface); }
.isis-shell.isis-menu-tint--medium .isis-subnav--expanded .isis-subnav__items { background: color-mix(in oklch, var(--isis-current-mod, var(--isis-accent)) 11%, var(--isis-surface)); --isis-menu-bg: color-mix(in oklch, var(--isis-current-mod, var(--isis-accent)) 11%, var(--isis-surface)); }
.isis-shell.isis-menu-tint--strong .isis-subnav--expanded .isis-subnav__items { background: color-mix(in oklch, var(--isis-current-mod, var(--isis-accent)) 16%, var(--isis-surface)); --isis-menu-bg: color-mix(in oklch, var(--isis-current-mod, var(--isis-accent)) 16%, var(--isis-surface)); }
.isis-subnav--expanded .isis-subnav__group-header {
    color: color-mix(in oklch, var(--isis-current-mod, var(--isis-accent)) 62%, var(--isis-text-muted));
}
.isis-subnav--expanded .isis-subnav__item:hover:not(.isis-subnav__item--disabled):not(.active) {
    background-color: color-mix(in oklch, var(--isis-current-mod, var(--isis-accent)) 9%, transparent);
}
.isis-subnav--expanded .isis-subnav__item.active {
    background-color: var(--isis-surface);
    color: var(--isis-current-mod, var(--isis-accent));
    font-weight: 600;
    box-shadow: 0 1px 4px color-mix(in oklch, var(--isis-current-mod, var(--isis-accent)) 22%, transparent);
}
/* Mode collapsé : items centrés (icône seule), padding réduit, tooltip native */
.isis-subnav--collapsed .isis-subnav__item {
    width: 44px;
    height: 40px;
    padding: 0;
    justify-content: center;
    border-radius: 8px;
}
.isis-subnav--collapsed .isis-subnav__group-items {
    align-items: center;
}

/* ── Flottant d'une entrée à enfants (spec 2026-09-18) ───────────────────────────────
   Le parent est un <button> qui emprunte la forme d'un item : on neutralise le style natif.
   Le flottant est en position:fixed (le sous-panneau est overflow:hidden, un absolute y serait
   rogné), en élévation 2 — le seul cas d'ombre que DESIGN.md autorise. Il naît masqué :
   subnav-flyout.js le place PUIS le rend visible. */
.isis-subnav__parent {
    width: 100%;
    border: 0;
    background: none;
    /* font-family seul : le raccourci `font: inherit`, déclaré après .isis-subnav__item, effaçait
       son corps (0.875rem) et sa hauteur de ligne — les parents s'affichaient plus gros. */
    font-family: inherit;
    text-align: left;
    cursor: pointer;
}
.isis-subnav__parent:focus-visible,
.isis-subnav__item:focus-visible,
.isis-subnav__group-header:focus-visible {
    outline: 2px solid var(--isis-current-mod, var(--isis-accent));
    outline-offset: 1px;
}
.isis-subnav__parent.is-open:not(.active) {
    background-color: var(--isis-surface-alt);
    color: var(--isis-text);
}
/* Opacité mesurée contre les tokens (revue finale, WCAG 1.4.11 — cible ≥3:1) : le chevron
   siège dans le bouton, dont le fond vaut --isis-surface (repos) ou --isis-surface-alt
   (survol / .is-open) selon les DEUX thèmes. À 0.55, --isis-text-muted blendu tombait à
   2,59:1 (clair/surface), 2,39:1 (clair/surface-alt), 3,04:1 (sombre/surface), 2,88:1
   (sombre/surface-alt) — sous le seuil dans les quatre cas sauf un, de justesse. À 0.7 :
   3,59 / 3,19 / 4,10 / 3,78 — les quatre passent avec marge. */
.isis-subnav__chev {
    margin-left: auto;
    font-size: 1rem;
    line-height: 1;
    opacity: 0.7;
    transition: transform 160ms ease;
}
/* Porté par aria-expanded, pas par .is-open : le sélecteur .is-open:not(.active) ne matche
   plus DU TOUT quand le parent est aussi la page courante (c'est l'exclusion :not(.active),
   pas une question de spécificité ni d'ordre de cascade) — la rotation, elle, reste visible
   dans les deux cas, seul repère d'ouverture qui survit à cette combinaison. */
.isis-subnav__parent[aria-expanded="true"] .isis-subnav__chev {
    transform: rotate(90deg);
    opacity: 0.8;
}
/* Mode étendu seulement : le point rejoint le flux juste après le libellé — pas collé au
   chevron, qui reste poussé à l'extrémité droite par son propre margin-left:auto (un blanc
   sépare donc le point et le chevron) — et pas le recoin absolu pensé pour le carré 44×40 du
   mode réduit, qui garde son comportement d'origine (.isis-subnav__badge-dot ci-dessous,
   non touché ici). */
.isis-subnav--expanded .isis-subnav__parent .isis-subnav__badge-dot {
    position: static;
    box-shadow: none;
    flex: 0 0 auto;
    margin-left: 4px;
}
/* Mode replié : le chevron devient une marque au bord droit de la tuile 44 × 40 — le seul
   indice visuel qu'elle ouvre un flottant au lieu de naviguer. Hauteur de ligne fixe pour le
   centrer sans transform, que la rotation d'ouverture occupe déjà. */
.isis-subnav--collapsed .isis-subnav__parent .isis-subnav__chev {
    position: absolute;
    right: 3px;
    top: calc(50% - 6px);
    margin-left: 0;
    font-size: 12px;
    line-height: 12px;
}
/* Cadenas du parent tout désactivé, en mode étendu : à côté du chevron, pas collé par le
   margin-left:auto pensé pour l'enfant seul (icône + libellé + cadenas, sans chevron). */
.isis-subnav--expanded .isis-subnav__parent .isis-subnav__lock {
    margin-left: 4px;
}
.isis-subnav__flyout {
    display: flex;
    flex-direction: column;
    gap: 2px;
    position: fixed;
    z-index: 1000;
    width: 248px;
    max-height: calc(100vh - 16px);
    overflow-y: auto;
    padding: 6px;
    background-color: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-lg);
    box-shadow: var(--isis-elevation-2);
    visibility: hidden;
}
.isis-subnav__flyout-title {
    padding: 6px 10px 4px;
    font-size: 0.7rem; /* même corps que .isis-subnav__group-header */
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--isis-text-soft);
}
/* Mode replié : .isis-subnav--collapsed .isis-subnav__item force un carré de 44 × 40 px centré.
   Les enfants du flottant ont la place de leur libellé — on leur rend la forme d'un item étendu. */
.isis-subnav--collapsed .isis-subnav__flyout .isis-subnav__item {
    width: 100%;
    height: auto;
    padding: 0.5rem 0.7rem;
    justify-content: flex-start;
    border-radius: 7px;
}

/* Badge compteur à droite de l'item (mode étendu). */
.isis-subnav__badge {
    margin-left: auto;
    min-width: 20px;
    padding: 0.05rem 0.4rem;
    border-radius: var(--isis-radius-pill);
    background: var(--isis-danger);
    color: #fff;
    font-size: 0.7rem;
    font-weight: 600;
    line-height: 1.4;
    text-align: center;
    font-variant-numeric: tabular-nums;
}
.isis-subnav__item.active .isis-subnav__badge {
    background: var(--isis-current-mod, var(--isis-accent));
}
/* Mode collapsé : dot rouge en haut-droite de l'item au lieu d'un badge texte. */
.isis-subnav__badge-dot {
    position: absolute;
    top: 4px;
    right: 4px;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background-color: var(--isis-danger);
    box-shadow: 0 0 0 2px var(--isis-surface);
    pointer-events: none;
}

/* Placeholder quand aucun module n'est sélectionné (rare). */
.isis-subnav__empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    padding: 2rem 1rem;
    color: var(--isis-text-soft);
    font-size: 0.85rem;
    text-align: center;
}

/* .isis-subnav en 'position: relative' : ancre les éléments positionnés du sub-nav. */
.isis-subnav { position: relative; }

/* ============================================================================
   Tenant badge (legacy — désormais dans le header.tenant)
   ============================================================================ */
.isis-tenant-badge { display: none; }

/* ── Alert banner ─────────────────────────────────────────────────────────
   Bandeau d'alerte généralisable. Variante par défaut = warning (jaune ambré).
   Modificateurs :
     .isis-alert-banner--pending   → orange tamisé (état transitoire, ex : en cours)
     .isis-alert-banner--warning   → jaune ambré (alerte non bloquante)
     .isis-alert-banner--danger    → rouge (état critique)

   Structure attendue (Phase 1.4) :
     <div class="isis-alert-banner isis-alert-banner--X" role="alert|status">
       <RadzenIcon ... />
       <div>
         <strong>Titre court</strong>
         <span>Description</span>
       </div>
       <RadzenButton ... />
     </div>

   Le sélecteur `> div` est intentionnellement laissé permissif — toutes les
   utilisations historiques (home, etc.) suivent désormais ce contrat.
*/
.isis-alert-banner {
    display: flex;
    /* center (et pas stretch) : sinon le bouton d'action s'étire sur toute la
       hauteur du bandeau (2 lignes) et paraît surdimensionné. */
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding: 0.75rem 1rem;
    background-color: var(--isis-warning-soft);
    border: 1px solid var(--isis-warning);
    border-radius: var(--isis-radius);
}
.isis-alert-banner > div {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    flex: 1;
    justify-content: center;
}
.isis-alert-banner > div > strong { color: inherit; font-weight: 600; }
.isis-alert-banner > div > span { font-size: 0.82rem; opacity: 0.92; }

/* Avertissement inline non bloquant (cohérence rattachement, etc.) — dans un formulaire/dialog. */
.isis-inline-warning {
    display: flex;
    align-items: flex-start;
    gap: 0.4rem;
    margin-top: 0.4rem;
    padding: 0.5rem 0.7rem;
    background-color: var(--isis-warning-soft, #fef3c7);
    border: 1px solid color-mix(in srgb, var(--isis-warning) 45%, transparent);
    border-radius: var(--isis-radius-sm);
    color: #92400e;
    font-size: 0.82rem;
    line-height: 1.35;
}
.isis-inline-warning .rz-icon,
.isis-inline-warning .rzi { color: var(--isis-warning); flex: 0 0 auto; font-size: 1rem; }

/* Note INFORMATIVE (ni alerte, ni succès) — même gabarit que .isis-inline-warning.
   Tout est piloté par les tokens --isis-info/-soft, donc correct en clair ET en sombre. */
.isis-inline-info {
    display: flex;
    align-items: flex-start;
    gap: 0.4rem;
    margin-top: 0.4rem;
    padding: 0.5rem 0.7rem;
    background-color: var(--isis-info-soft);
    border: 1px solid color-mix(in srgb, var(--isis-info) 45%, transparent);
    border-radius: var(--isis-radius-sm);
    color: var(--isis-info);
    font-size: 0.82rem;
    line-height: 1.35;
}
.isis-inline-info .rz-icon,
.isis-inline-info .rzi { color: var(--isis-info); flex: 0 0 auto; font-size: 1rem; }

/* Bandeau de périmètre en tête d'écran (PerimetreEntrepriseBandeau) — même gabarit que
   .isis-inline-info, marge de page plutôt que marge de champ. */
.isis-perimetre-bandeau {
    margin: 0 0 0.75rem;
}
.isis-perimetre-bandeau a {
    color: var(--isis-info);
    font-weight: 600;
    text-decoration: underline;
}

.isis-alert-banner--pending {
    background-color: color-mix(in srgb, var(--isis-mod-gesmat-soft, #f5f5f4) 70%, var(--isis-warning-soft, #fef3c7));
    border-color: var(--isis-warning, #fbbf24);
    color: #92400e;
}
.isis-alert-banner--warning {
    background-color: var(--isis-warning-soft, #fef3c7);
    border-color: var(--isis-warning, #fbbf24);
    color: #92400e;
}
/* Le #92400e ci-dessus est figé (valeur en dur, DESIGN.md §2) : en thème sombre le FOND suit
   --isis-warning-soft et devient presque noir, le texte non → 2,09:1, mesuré au pixel sur la
   page Responsabilités le 2026-09-03. --isis-warning, lui, a sa variante sombre : 6,30:1.
   Bornée au thème sombre pour ne rien changer au rendu clair (~5,9:1, déjà conforme).
   La variante --pending figeait le même #92400e : son fond suit désormais le token
   --isis-warning-soft au lieu d'un #fef3c7 en dur, ce qui ne change RIEN en clair (le
   token y vaut #fef3c7) et descend le fond sombre de #696355 à #2b251e — l'encre
   --isis-warning y rend alors 6,44:1, soit le ratio exact du thème clair. Le mix seul
   ne suffisait pas : le 30 % de jaune remontait le fond sombre à #696355, où même
   --isis-warning ne donnait que 2,54:1. Rendue par le pavé fiscal d'un compte
   (tâche 27), la variante cesse d'être une dette sans porteur. */
:root[data-theme="dark"] .isis-alert-banner--warning {
    color: var(--isis-warning);
}
:root[data-theme="dark"] .isis-alert-banner--pending {
    color: var(--isis-warning);
}
.isis-alert-banner--danger {
    background-color: var(--isis-danger-soft, #fef2f2);
    border-color: var(--isis-danger, #fca5a5);
    color: #991b1b;
}
/* Même dette, même correction que --warning ci-dessus : en sombre --isis-danger-soft descend à
   #3a1614 et le #991b1b figé ne suit pas (1,95:1, calculé). --isis-danger a sa variante
   éclaircie (#e5534b) → 5,71:1. Rendue pour la première fois par le dialogue de qualification
   d'une facture (tâche 30), la variante cesse d'être une dette sans porteur. */
:root[data-theme="dark"] .isis-alert-banner--danger {
    color: var(--isis-danger);
}
.isis-alert-banner--warm {
    background-color: var(--isis-accent-soft);
    border-color: color-mix(in srgb, var(--isis-accent) 45%, transparent);
    color: var(--isis-accent-strong);
}

/* Variants historiques (.isis-alert-banner__main / __icon) — conservées pour
   les call-sites existants (home, etc.) qui les consomment encore. */
.isis-alert-banner__main {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    color: #92400e;
    font-size: 0.9rem;
}
.isis-alert-banner__icon {
    width: 28px; height: 28px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background-color: rgba(245, 158, 11, 0.15);
    color: #d97706;
    border-radius: 8px;
}

/* ============================================================================
   Actions rapides (primary CTA grid sur la home)
   ============================================================================ */
.isis-actions-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
    gap: 0.75rem;
}
.isis-action-card {
    display: flex;
    align-items: center;
    gap: 0.85rem;
    padding: 0.9rem 1rem;
    background-color: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius);
    color: var(--isis-text);
    text-decoration: none;
    transition: background-color 120ms, border-color 120ms;
}
.isis-action-card:hover {
    /* F8 — lift d'ombre subtil + bordure module : signal tactile de cliquabilité.
       Pas de translateY pour éviter la danse du layout. */
    background-color: var(--isis-surface-alt);
    border-color: var(--isis-current-mod, var(--isis-accent));
    box-shadow: var(--isis-elevation-hover);
}
.isis-action-card:focus-visible {
    outline: 2px solid var(--isis-accent);
    outline-offset: 2px;
}
.isis-action-card__icon-wrap {
    width: 40px; height: 40px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--isis-radius-sm);
    flex-shrink: 0;
}
.isis-action-card__icon-wrap .rzi { font-size: 22px; }
.isis-action-card__text { display: flex; flex-direction: column; line-height: 1.2; min-width: 0; }
.isis-action-card__label {
    font-size: 0.95rem;
    font-weight: 600;
    color: var(--isis-text);
}
.isis-action-card__module {
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--isis-text-soft);
    margin-top: 3px;
}
/* Couleurs accent par module */
.isis-action-card.mod-gescom    .isis-action-card__icon-wrap { background-color: var(--isis-mod-gescom-soft); color: var(--isis-mod-gescom); }
.isis-action-card.mod-gescompta .isis-action-card__icon-wrap { background-color: var(--isis-mod-gescompta-soft); color: var(--isis-mod-gescompta); }
.isis-action-card.mod-sirh      .isis-action-card__icon-wrap { background-color: var(--isis-mod-sirh-soft); color: var(--isis-mod-sirh); }
.isis-action-card.mod-admin     .isis-action-card__icon-wrap { background-color: var(--isis-mod-admin-soft); color: var(--isis-mod-admin); }
.isis-action-card.mod-ged       .isis-action-card__icon-wrap { background-color: var(--isis-accent-soft);     color: var(--isis-accent); }

/* Grille des modules — secondaire, avec border-top accent */
.isis-modules-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
    gap: 0.85rem;
}
.isis-module-card {
    display: flex;
    align-items: center;
    gap: 1rem;
    padding: 1rem 1.25rem;
    background-color: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-top-width: 3px;
    border-radius: var(--isis-radius);
    text-decoration: none;
    transition: border-color 120ms, transform 120ms;
}
.isis-module-card:hover {
    transform: translateY(-1px);
    border-color: var(--isis-current-mod, var(--isis-accent));
}
.isis-module-card__icon-wrap {
    width: 44px; height: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 10px;
    flex-shrink: 0;
}
.isis-module-card__title {
    font-size: 0.95rem;
    font-weight: 600;
    color: var(--isis-text);
}
.isis-module-card__subtitle {
    font-size: 0.8rem;
    color: var(--isis-text-muted);
    margin-top: 2px;
}
/* Couleurs accent par module */
.isis-module-card.mod-gescom    { border-top-color: var(--isis-mod-gescom); }
.isis-module-card.mod-gescom    .isis-module-card__icon-wrap { background-color: var(--isis-mod-gescom-soft); color: var(--isis-mod-gescom); }
.isis-module-card.mod-gescompta { border-top-color: var(--isis-mod-gescompta); }
.isis-module-card.mod-gescompta .isis-module-card__icon-wrap { background-color: var(--isis-mod-gescompta-soft); color: var(--isis-mod-gescompta); }
.isis-module-card.mod-sirh      { border-top-color: var(--isis-mod-sirh); }
.isis-module-card.mod-sirh      .isis-module-card__icon-wrap { background-color: var(--isis-mod-sirh-soft); color: var(--isis-mod-sirh); }
.isis-module-card.mod-admin     { border-top-color: var(--isis-mod-admin); }
.isis-module-card.mod-admin     .isis-module-card__icon-wrap { background-color: var(--isis-mod-admin-soft); color: var(--isis-mod-admin); }
.isis-module-card.mod-ged       { border-top-color: var(--isis-accent); }
.isis-module-card.mod-ged       .isis-module-card__icon-wrap { background-color: var(--isis-accent-soft); color: var(--isis-accent); }

/* Variante cliquable du .isis-kpi-card (utilisée sur la home).
   Le .isis-kpi-card de base est un <div> non-interactif ; --link ajoute le
   cursor, le hover lift et la couleur module au survol. */
.isis-kpi-card.isis-kpi-card--link {
    text-decoration: none;
    color: inherit;
    cursor: pointer;
    border-radius: var(--isis-radius-sm);
    padding: 0.25rem 0.7rem;
    transition: background-color 150ms ease, transform 150ms ease;
}
.isis-kpi-card.isis-kpi-card--link:hover {
    background-color: var(--isis-current-mod-soft, var(--isis-accent-soft));
    /* Garde border-left du KPI standard mais ajoute un highlight discret. */
}
.isis-kpi-card.isis-kpi-card--link:focus-visible {
    outline: 2px solid var(--isis-current-mod, var(--isis-accent));
    outline-offset: 2px;
}

/* État vide d'une carte, hors accueil. Nommée sans référence à l'accueil : la règle a survécu
   à la refonte de /accueil précisément parce que MonEspace l'empruntait. */
.isis-empty-note {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    padding: 2rem 1rem;
    color: var(--isis-text-muted);
    font-size: 0.875rem;
}

/* Realtime grid */
.isis-realtime-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
    gap: 1rem;
}
.isis-realtime-card { padding: 1rem; }

/* ============================================================================
   Login page — carte de connexion multi-étapes (organisation → identifiant → mdp)
   ============================================================================ */
/* 100vh compte la barre d'URL mobile comme absente : la carte déborde sur iOS et Android.
   100dvh suit la hauteur réellement visible ; 100vh reste en repli pour les navigateurs
   qui ignorent dvh. */
.isis-empty-layout { min-height: 100vh; min-height: 100dvh; background-color: var(--isis-surface-alt); }
.isis-login { min-height: 100vh; min-height: 100dvh; display: flex; align-items: center; justify-content: center; padding: 2rem; }
/* Modificateur « Blueprint » pour les pages système (Error/NotFound/Forbidden/…) —
   grille de fond discrète, esprit « UpDate the System ». Posé uniquement sur ces
   pages : la page de login ne porte pas ce modificateur, donc reste inchangée. */
.isis-login--blueprint {
    background-color: var(--isis-bg);
    background-image:
        linear-gradient(color-mix(in srgb, var(--isis-accent) 4%, transparent) 1px, transparent 1px),
        linear-gradient(90deg, color-mix(in srgb, var(--isis-accent) 4%, transparent) 1px, transparent 1px);
    background-size: 22px 22px;
}

/* Pile « visuel d'accueil + carte » : le hero du tenant (asset login_page_logo)
   se place au-dessus de la carte une fois l'organisation résolue. */
.isis-login__stack {
    position: relative;        /* ancre le hero, qui est hors-flux pour ne pas décentrer la carte */
    display: flex;
    flex-direction: column;
    align-items: center;
    width: 100%;
}
/* Visuel d'accueil tenant — animation « flottement doux » : révélation à l'apparition
   (fondu + légère montée) puis oscillation verticale lente. Décoratif (aria-hidden).
   Positionné en absolu AU-DESSUS de la carte (bottom:100%) : il « pousse vers le haut »
   sans participer au centrage vertical, donc seul le bloc de login reste centré. */
.isis-login__hero {
    position: absolute;
    bottom: 100%;
    left: 0;
    right: 0;
    margin-bottom: 1.75rem;
    display: flex;
    justify-content: center;
    animation: isis-login-hero-in 0.7s cubic-bezier(0.22, 1, 0.36, 1) both;
}
.isis-login__hero-img {
    max-width: min(540px, 90vw);
    max-height: 300px;
    width: auto;
    height: auto;
    object-fit: contain;
    filter: drop-shadow(0 6px 18px color-mix(in srgb, var(--isis-accent) 18%, transparent));
    animation: isis-login-hero-float 6s ease-in-out 0.7s infinite;
    will-change: transform;
}
@keyframes isis-login-hero-in {
    from { opacity: 0; transform: translateY(12px) scale(0.97); }
    to   { opacity: 1; transform: translateY(0)    scale(1); }
}
@keyframes isis-login-hero-float {
    0%, 100% { transform: translateY(0); }
    50%      { transform: translateY(-7px); }
}
@media (prefers-reduced-motion: reduce) {
    .isis-login__hero,
    .isis-login__hero-img { animation: none; }
}
@media (max-width: 480px) {
    .isis-login__stack { gap: 1rem; }
    .isis-login__hero-img { max-height: 180px; }
}

/* ─────────────────────────────────────────────────────────────────────────
   Workspace choose — page splash post-login pour user multi-entreprises
   ───────────────────────────────────────────────────────────────────────── */
/* /workspace/choose — splash post-login (multi-entreprise) : fond de marque plein écran
   + picker (arbre WorkspacePickerTree) en modal centré. Réutilise les keyframes hero login. */
.isis-ws-choose {
    position: relative;
    min-height: 100vh;
    display: flex; align-items: center; justify-content: center;
    padding: 2rem;
    overflow: hidden;
}
.isis-ws-choose__bg {
    position: absolute; inset: 0; z-index: 0;
    /* Surface plate (décision 2026-10-06) : le double dégradé d'accent tombait sous le ban
       des gradients marketing (DESIGN.md §10). */
    background: var(--isis-bg);
}
.isis-ws-choose__stack {
    position: relative; z-index: 1;
    display: flex; flex-direction: column; align-items: center;
    width: 100%; max-width: 460px;
}
.isis-ws-choose__hero {
    display: flex; justify-content: center; margin-bottom: 1.5rem;
    animation: isis-login-hero-in 0.7s cubic-bezier(0.22, 1, 0.36, 1) both;
}
.isis-ws-choose__hero-img {
    max-width: min(360px, 70vw); max-height: 150px;
    width: auto; height: auto; object-fit: contain;
}
.isis-ws-choose__modal {
    width: 100%;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-lg);
    box-shadow: var(--isis-elevation-2);
    padding: 1.75rem;
    display: flex; flex-direction: column; gap: 1rem;
    max-height: min(80vh, 760px);
}
.isis-ws-choose__head { display: flex; flex-direction: column; gap: 0.3rem; }
.isis-ws-choose__title { font-size: 1.3rem; font-weight: 600; margin: 0; color: var(--isis-text); }
.isis-ws-choose__sub { margin: 0; color: var(--isis-text-muted); font-size: 0.9rem; line-height: 1.5; }
.isis-ws-choose__hint {
    margin: 0; padding: 0.6rem 0.8rem;
    background: var(--isis-surface-alt); border-radius: var(--isis-radius-sm);
    color: var(--isis-text-muted); font-size: 0.85rem;
}
.isis-ws-choose__picker { flex: 1 1 auto; min-height: 0; overflow-y: auto; margin: 0 -0.25rem; padding: 0.1rem 0.25rem; }
/* Écran de choix post-login : l'arbre y est en pleine page, pas dans un dialogue Radzen.
   Le plafond existe quand même — .isis-ws-choose__modal porte max-height: min(80vh, 760px)
   (cf. plus haut) — mais c'est .isis-ws-choose__picker qui absorbe le défilement en
   interne (flex + overflow-y ci-dessus), la même recette que le dialogue (cf.
   .rz-dialog-content plus bas), portée par une autre règle. D'où : lignes un peu plus
   aérées, et le pied perd la marge négative calée sur le padding du dialogue Radzen —
   sans quoi il déborderait de la carte de 24 px de chaque côté. */
.isis-ws-choose__picker .isis-wstree__roots,
.isis-ws-choose__picker .isis-wstree__flat { max-height: none; overflow: visible; }
.isis-ws-choose__picker .isis-wstree__node { padding: 10px 8px; }
.isis-ws-choose__picker .isis-wstree__avatar { width: 30px; height: 30px; }
.isis-ws-choose__picker .isis-wstree__foot { margin: 14px 0 0; padding: 10px 12px;
  border-radius: var(--isis-radius-sm); }
/* Bandeau interne du composant (« ESPACES DE TRAVAIL · N accessibles ») masqué sur cet
   écran : le <h1> + le sous-titre en prose de la page disent déjà la même chose (cf.
   tâche 2) — la modale avait résolu ce doublon via Title="" sur le dialogue Radzen
   (WorkspaceSwitcher.OpenDialogAsync), ce troisième consommateur n'a pas de barre de
   titre Radzen à vider : une surcharge CSS locale, cohérente avec les autres règles de
   ce bloc, fait le même travail. Le listbox garde son propre aria-label, indépendant
   de ce bandeau. */
.isis-ws-choose__picker .isis-wstree__bar { display: none; }
.isis-ws-choose__loading { display: flex; justify-content: center; align-items: center; padding: 2.5rem 0; }
.isis-ws-choose__busy { display: flex; align-items: center; gap: 0.5rem; color: var(--isis-text-muted); font-size: 0.85rem; }
@media (prefers-reduced-motion: reduce) {
    .isis-ws-choose__hero,
    .isis-ws-choose__hero-img { animation: none; }
}

.isis-login__card {
    width: 100%; max-width: 400px;
    /* box-sizing:border-box impératif : sans lui, width:100% + padding + bordure dépasse le
       conteneur (débordement horizontal mesuré à 360px de large) — même piège que
       .isis-pivot__pivot-btn et .isis-devis-items tbody td > * plus haut dans cette feuille. */
    box-sizing: border-box;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius);
    padding: 2rem;
    display: flex; flex-direction: column; gap: 1.1rem;
}

.isis-login__brand { display: flex; flex-direction: column; align-items: center; gap: 0.2rem; }
.isis-login__brand-logo { width: 56px; height: 56px; margin-bottom: 0.35rem; }
/* Signature éditeur « by IrisSoft » sous le nom — discrète. */
.isis-login__brand-by { margin-top: 0.15rem; font-size: 0.66rem; font-weight: 500; letter-spacing: 0.02em; color: var(--isis-text-subtle, var(--isis-text-muted)); opacity: 0.8; }

/* Co-branding filiale au login (paramètre tenant master, apparaît après l'étape organisation). */
.isis-login__filiale {
    display: flex; align-items: center; justify-content: center; gap: 0.5rem;
    margin: 0.1rem 0 0.25rem;
    padding-top: 0.6rem;
    border-top: 1px solid var(--isis-border);
}
.isis-login__filiale-logo { width: 24px; height: 24px; border-radius: 50%; object-fit: cover; box-shadow: var(--isis-elevation-1, 0 2px 6px rgba(0,0,0,.12)); }
.isis-login__filiale-name { font-size: 0.8125rem; font-weight: 650; color: var(--isis-text); }

/* Progression — pastilles décoratives + libellé textuel (lu par les lecteurs d'écran) */
.isis-login__progress { display: flex; align-items: center; justify-content: space-between; gap: 0.75rem; }
.isis-login__dots { display: flex; gap: 0.35rem; }
.isis-login__dot {
    width: 22px; height: 4px; border-radius: 2px;
    background: var(--isis-border-strong);
    transition: background-color 160ms, opacity 160ms;
}
.isis-login__dot.is-active { background: var(--isis-accent); }
.isis-login__dot.is-done   { background: var(--isis-accent); opacity: 0.4; }
.isis-login__progress-label { font-size: 0.72rem; color: var(--isis-text-muted); white-space: nowrap; }

/* Alerte générique `.isis-alert` (ex-`.isis-login__alert`, renommée le 2026-10-06 pour servir
   hors de la carte de connexion — choix d'espace de travail, portails publics).
   Bandeau d'état des écrans hors-session (erreur de connexion, compte verrouillé,
   rate limit, confirmations du portail). Fond clair + filet périmétrique teinté :
   le texte danger garde un contraste AA (≥4.5:1) sur la surface blanche, ce qui ne
   serait pas le cas sur un fond danger-soft.
   Ex-barre d'accent gauche 3px, retirée le 2026-07-18 (DESIGN.md §1) : elle se
   superposait au filet 1px déjà présent — deux traitements de bordure sur le même
   bloc. La sémantique reste portée par la couleur du filet, de l'icône et du texte. */
.isis-alert {
    box-sizing: border-box;
    display: flex; align-items: flex-start; gap: 0.5rem;
    padding: 0.65rem 0.75rem;
    background: var(--isis-surface);
    border: 1px solid var(--isis-danger-soft);
    border-radius: var(--isis-radius-sm);
    color: var(--isis-danger);
    font-size: 0.82rem; line-height: 1.4;
}
.isis-alert > span { padding-top: 1px; }
.isis-alert--info {
    /* Variante info (confirmation envoi reset password, dossier envoyé) — neutre,
       pas alarmiste. */
    border-color: var(--isis-accent-soft);
    color: var(--isis-text);
}
.isis-alert--info .rzi { color: var(--isis-accent); }
/* Variante succès (code MFA renvoyé). Existe parce que la base est teintée danger :
   sans elle, un message de succès héritait d'un filet rouge — c'était le cas du
   bandeau « Nouveau code envoyé », corrigé le 2026-07-18. */
.isis-alert--success {
    background: var(--isis-success-soft);
    border-color: var(--isis-success-soft);
    color: var(--isis-success);
}
.isis-alert--success .rzi { color: var(--isis-success); }

/* Lien textuel discret (retour à la connexion, mot de passe oublié, renvoi de code MFA).
   Cible ≥ 24px de haut (WCAG 2.5.8). Porté aussi par des <button> (formulaires POST des
   pages MFA) : la remise à zéro du bouton natif est incluse. */
.isis-login__link {
    display: inline-flex; align-items: center;
    min-height: 24px;
    color: var(--isis-accent);
    text-decoration: none;
    font-size: 0.82rem;
}
button.isis-login__link {
    background: none; border: none; padding: 0;
    font-family: inherit; cursor: pointer;
}
.isis-login__link:hover { text-decoration: underline; }
.isis-login__link:focus-visible {
    outline: 2px solid var(--isis-accent); outline-offset: 2px; border-radius: 2px;
}

/* Lien "Mot de passe oublié ?" sous l'input password, aligné à droite */
.isis-login__forgot { display: flex; justify-content: flex-end; }

/* Pied de carte (lien de retour) */
.isis-login__footer {
    display: flex; justify-content: center;
    padding-top: 0.25rem;
    border-top: 1px solid var(--isis-border-subtle);
    margin-top: 0.25rem;
}

/* Étape — apparition en fondu/glissé (entrée seule, sobre, flat) */
.isis-login__step {
    display: flex; flex-direction: column; gap: 0.9rem;
    animation: isis-login-step-in 180ms ease both;
}
@keyframes isis-login-step-in {
    from { opacity: 0; transform: translateY(6px); }
    to   { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
    .isis-login__step { animation: none; }
}

/* Rappel de contexte — l'organisation / l'identifiant déjà choisis, cliquables
   pour revenir en arrière les modifier */
.isis-login__context { display: flex; flex-direction: column; gap: 0.4rem; }
.isis-login__chip {
    display: flex; align-items: center; gap: 0.6rem;
    width: 100%; text-align: left;
    min-height: 44px; padding: 0.45rem 0.7rem;
    background: var(--isis-surface);
    border: 1px solid var(--isis-text-muted);
    border-radius: var(--isis-radius-sm);
    color: var(--isis-text); cursor: pointer;
    font-family: inherit;
    transition: border-color 120ms, background-color 120ms;
}
.isis-login__chip:hover { border-color: var(--isis-accent); background: var(--isis-accent-soft); }
.isis-login__chip-text { display: flex; flex-direction: column; flex: 1 1 auto; min-width: 0; line-height: 1.25; }
.isis-login__chip-label {
    font-size: 0.7rem; color: var(--isis-text-muted);
    text-transform: uppercase; letter-spacing: 0.03em;
}
.isis-login__chip-value {
    font-size: 0.85rem; color: var(--isis-text); font-weight: 500;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* SSO (Microsoft Entra) — ALTERNATIVE à la connexion, pas l'action primaire de la page :
   surface neutre + bordure, jamais l'accent (réservé au bouton « Continuer »). */
.isis-login__sso { display: flex; flex-direction: column; gap: 0.9rem; }
.isis-login__sso-btn {
    display: flex; align-items: center; justify-content: center; gap: 0.6rem;
    /* Un <a> reste en content-box (le reset border-box ne couvre que button/input) : sans
       ça, min-height 44 + padding + bordure rendait 62px — un bouton plus haut que tous
       ses voisins. */
    box-sizing: border-box;
    min-height: 44px; padding: 0.5rem 0.9rem;
    background: var(--isis-surface);
    /* Même bordure que la chip et les inputs (≥3:1, WCAG 1.4.11) : --isis-border-strong
       tombe à ~2,6:1 sur blanc et rendait ce contrôle actionnable moins présent que la
       chip passive juste au-dessus. */
    border: 1px solid var(--isis-text-muted);
    border-radius: var(--isis-radius-sm);
    color: var(--isis-text);
    font-family: inherit; font-size: 0.9rem; font-weight: 600;
    text-decoration: none;
    transition: border-color 120ms, background-color 120ms;
}
.isis-login__sso-btn:hover {
    border-color: var(--isis-accent);
    background: var(--isis-accent-soft);
    text-decoration: none;
}
.isis-login__sso-btn:active { transform: translateY(1px); }
.isis-login__sso-btn:focus-visible {
    outline: 2px solid var(--isis-accent); outline-offset: 2px;
}
.isis-login__sso-logo { flex: 0 0 auto; }

/* Séparateur « ou » — décoratif (aria-hidden côté markup : non annoncé comme du contenu) */
.isis-login__sep {
    display: flex; align-items: center; gap: 0.6rem;
    font-size: 0.75rem; color: var(--isis-text-soft);
}
.isis-login__sep::before,
.isis-login__sep::after {
    content: ""; flex: 1 1 auto; height: 1px; background: var(--isis-border);
}

/* Champs — bordure contrastée (≥3:1, WCAG 1.4.11) : l'input blanc doit rester
   perceptible sur la carte blanche. */
.isis-login__field { display: flex; flex-direction: column; gap: 0.35rem; }
.isis-login__field label { font-size: 0.8rem; color: var(--isis-text-muted); font-weight: 500; }
.isis-login__field input {
    height: 42px; padding: 0 0.75rem;
    border: 1px solid var(--isis-text-muted);
    border-radius: var(--isis-radius-sm); background: var(--isis-surface);
    color: var(--isis-text); font-size: 0.9rem; outline: none;
    font-family: inherit;
    transition: border-color 120ms;
}
.isis-login__field input:hover { border-color: var(--isis-accent); }
.isis-login__field input:focus-visible {
    border-color: var(--isis-accent);
    outline: 2px solid var(--isis-accent); outline-offset: 1px;
}
.isis-login__field input[aria-invalid="true"] { border-color: var(--isis-danger); }
.isis-login__hint { font-size: 0.75rem; color: var(--isis-text-muted); margin: 0; }
.isis-login__step-error { font-size: 0.8rem; color: var(--isis-danger); margin: 0; }

/* Champ mot de passe : l'input et sa bascule d'affichage partagent la même boîte, pour que
   le bouton ne compte pas comme un second contrôle dans la colonne du formulaire. Cible
   tactile 44×44px (DESIGN.md §« Touch targets » — non négociable, cf. .isis-flux-vue-toggle
   pour le même geste) : largeur 2.75rem, hauteur calée sur les 42px de .isis-login__field
   input via top/bottom à 0 (le rendu mesuré dépasse légèrement 42px, cf. rapport). */
.isis-login__pwd { position: relative; display: flex; }
.isis-login__pwd input { flex: 1 1 auto; padding-right: 2.9rem; }
.isis-login__pwd-toggle {
    position: absolute; right: 1px; top: 0; bottom: 0;
    display: flex; align-items: center; justify-content: center;
    width: 2.75rem;
    background: transparent; border: none; border-radius: 0 var(--isis-radius-sm) var(--isis-radius-sm) 0;
    color: var(--isis-text-muted); cursor: pointer;
}
.isis-login__pwd-toggle:hover { color: var(--isis-accent); }
.isis-login__pwd-toggle:focus-visible {
    outline: 2px solid var(--isis-accent); outline-offset: -2px;
}
/* Avertissement Verr. Maj. — masqué par [hidden], piloté en JS. */
.isis-login__caps { color: var(--isis-danger); }

/* Portail public de déclaration d'un tiers (lot 3) — select/textarea manquants
   à la déclinaison ci-dessus (elle ne stylait que <input>), et la case
   d'attestation (checkbox + label sur une ligne, pas un champ vertical). */
.isis-login__field select,
.isis-login__field textarea {
    padding: 0.5rem 0.75rem;
    border: 1px solid var(--isis-text-muted);
    border-radius: var(--isis-radius-sm); background: var(--isis-surface);
    color: var(--isis-text); font-size: 0.9rem; outline: none;
    font-family: inherit;
    transition: border-color 120ms;
}
.isis-login__field select { height: 42px; }
.isis-login__field textarea { resize: vertical; min-height: 72px; }
.isis-login__field select:hover, .isis-login__field textarea:hover { border-color: var(--isis-accent); }
.isis-login__field select:focus-visible, .isis-login__field textarea:focus-visible {
    border-color: var(--isis-accent);
    outline: 2px solid var(--isis-accent); outline-offset: 1px;
}
.isis-login__check {
    display: flex; align-items: flex-start; gap: 0.55rem;
    font-size: 0.85rem; color: var(--isis-text);
}
.isis-login__check input[type="checkbox"] { margin-top: 0.2rem; flex: 0 0 auto; }

/* Étape de vérification (MFA) : texte d'introduction, champ du code, renvoi et sortie. */
.isis-login__lead { font-size: 0.95rem; color: var(--isis-text); margin: 0 0 1.5rem; }
.isis-login__field input.isis-login__code {
    font-size: 1.5rem; letter-spacing: 0.5rem; text-align: center;
    font-family: var(--isis-font-mono);
}
.isis-login__check-label { cursor: pointer; }
.isis-login__resend { margin-top: 1rem; }
.isis-login__resend button.isis-text-link { font-size: 0.85rem; min-height: 24px; }
.isis-login__hint--spaced { margin-top: 1.5rem; }

/* Actions — bouton principal pleine largeur (le retour se fait via les chips de contexte) */
.isis-login__actions { display: flex; gap: 0.6rem; }
.isis-login__submit {
    flex: 1 1 auto;
    height: 44px; border: none; border-radius: var(--isis-radius-sm);
    background-color: var(--isis-accent); color: var(--isis-on-accent);
    font-size: 0.9rem; font-weight: 600; cursor: pointer;
    font-family: inherit;
    transition: opacity 120ms;
}
.isis-login__submit:hover { opacity: 0.92; }
.isis-login__submit:active { transform: translateY(1px); }
.isis-login__submit:disabled,
.isis-login__submit[aria-disabled="true"] { opacity: 0.55; cursor: not-allowed; }
.isis-login__submit:focus-visible,
.isis-login__chip:focus-visible {
    outline: 2px solid var(--isis-accent); outline-offset: 2px;
}
/* Le bouton principal sert aussi sur un <a> (page introuvable) : centrage du libellé. */
a.isis-login__submit {
    display: flex; align-items: center; justify-content: center;
    text-decoration: none;
}
/* Titre et chapeau des écrans hors session écrits sans RadzenText (vérification en 2 étapes). */
.isis-login__title { margin: 0 0 1rem; font-size: var(--isis-fs-xl); color: var(--isis-text); }
.isis-login__lead { margin: 0 0 1.5rem; font-size: var(--isis-fs-md); color: var(--isis-text); }
/* Icônes de la carte : marque (en tête), bandeau d'état, pastilles de contexte. */
.isis-login__brand-icon { font-size: var(--isis-fs-2xl); opacity: 0.75; }
.isis-login__alert-icon,
.isis-login__pwd-icon { font-size: var(--isis-fs-lg); }
.isis-login__chip-icon { font-size: var(--isis-fs-lg); opacity: 0.6; }
.isis-login__chip-edit { font-size: var(--isis-fs-md); opacity: 0.5; }

/* Petits écrans (terminaux d'entrée de gamme courants) — densifie la carte */
@media (max-width: 440px) {
    .isis-login { padding: 1rem; }
    .isis-login__card { padding: 1.25rem; gap: 0.85rem; }
    .isis-login__step { gap: 0.7rem; }
}

/* Points d'accroche vers les pages légales, sous la carte (StepLoginCard — /login,
   / et /master/login, toutes étapes). /cgu n'est volontairement pas lié. */
.isis-login__legal {
    display: flex;
    justify-content: center;
    gap: 10px;
    margin-top: 18px;
    font-size: var(--isis-fs-sm);
    color: var(--isis-text-muted);
}
.isis-login__legal a { color: var(--isis-text-muted); }
.isis-login__legal a:hover { color: var(--isis-accent); }

/* ============================================================================
   Rich-page (pages métier à haute densité — pattern NetLogger V3)
   ============================================================================ */
.isis-rich-page {
    position: relative;
    padding: 0.75rem 1rem 0.75rem;
    display: flex;
    flex-direction: column;
    gap: 0.85rem;
    /* Pleine largeur du body — cf. décision 2026-05-14 (DESIGN.md §219 : 100% privilégié) */
    max-width: none;
    margin: 0;
    /* Hauteur stricte = celle du scroll container parent (.isis-shell__content).
       Avec flex: 1 + min-height: 0 sur les enfants, le .isis-grid interne
       se contraint et scrolle, jamais la page entière. */
    height: 100%;
    box-sizing: border-box;
    overflow: hidden;
}

/* Variante --scrollable : pour les dashboards composés de sections empilées
   verticalement sans grille interne scrollable. La page entière déborde et
   scrolle naturellement dans .isis-shell__content (qui a overflow-y: auto).
   À appliquer en plus de .isis-rich-page sur les pages dashboard.
   Cf. correctif 2026-05-21 — le pattern par défaut (height 100% + overflow hidden)
   était optimisé pour les pages liste avec grille scrollable, et masquait tout
   ce qui dépassait l'écran sur les dashboards verticalement longs. */
.isis-rich-page.isis-rich-page--scrollable {
    height: auto;
    min-height: 100%;
    overflow: visible;
}

/* Variante --report : pages d'analyse qui empilent PLUSIEURS sections (pas une grille
   unique). .isis-rich-page suppose un seul enfant scrollable (le .isis-grid d'une page
   liste) ; une page d'analyse (AnalysePage, et QcReportingPage de gesproj — même défaut,
   pas encore corrigé) empile plusieurs <section class="isis-rich-section"> dont aucune ne
   porte flex:1 : rien ne défile, et tout ce qui dépasse la hauteur du conteneur est coupé
   (bug « page figée verticalement » constaté 2026-09-03). Le fil d'Ariane et la barre de
   filtres restent fixes en haut ; c'est le conteneur .isis-rich-page__scroll — posé sur la
   zone qui suit les filtres — qui reçoit le flex:1 et défile. .isis-rich-page garde son
   overflow:hidden par défaut : c'est ce wrapper interne qui scrolle, pas la page. */
.isis-rich-page--report > .isis-rich-page__scroll {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    gap: 0.85rem;
}

/* Plus de bande module en haut de page (retirée 2026-09-22) : le module se lit au nom du
   sélecteur d'en-tête et à l'entrée active du rail. */

/* Breadcrumb + toolbar (ligne du haut) */
.isis-rich-toolbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    row-gap: 0.4rem;
    /* Barres d'actions chargées (ex. fiche avoir DRAFT : 8 boutons) : le bloc
       d'actions passe sous le fil d'Ariane au lieu de l'écraser. */
    flex-wrap: wrap;
    font-size: 0.85rem;
}
.isis-breadcrumb {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    color: var(--isis-text-muted);
}
/* Variante « titre » : le h1 est un frère du <nav>, pas son enfant (le titre de page ne
   doit pas vivre dans un point de repère de navigation). Le fil garde donc sa propre boîte
   flex, et la ligne se recompose à l'identique. */
/* min-width: 0 — sans lui, la variante titre est un ITEM FLEX de .isis-rich-toolbar avec
   `min-width: auto` : elle refuse de descendre sous sa largeur de contenu, et comme le h1
   qu'elle porte est en `white-space: nowrap`, cette largeur est celle du titre entier.
   Mesuré sur une offre de prix au titre de 255 caractères : la boîte faisait 2620 px pour
   un écran de 1600, le titre sortait de l'écran coupé en plein mot, et l'`text-overflow`
   posé sur le h1 ne se déclenchait jamais faute de contrainte à laquelle mordre. */
.isis-breadcrumb--heading { display: flex; flex-wrap: wrap; min-width: 0; max-width: 100%; }
.isis-breadcrumb__trail { display: inline-flex; align-items: center; gap: 0.35rem; }
/* Gouttière de largeur fixe (= la taille du picto) : une clé absente du registre
   ne rend rien, et la place reste réservée — le libellé ne se décale pas. */
.isis-breadcrumb__modicon { display: inline-flex; align-items: center;
  justify-content: center; flex: 0 0 16px; }
.isis-breadcrumb__sep { color: var(--isis-text-soft); opacity: 0.7; }
.isis-breadcrumb__current { color: var(--isis-text); font-weight: 500; }
.isis-breadcrumb__link {
    color: inherit;
    text-decoration: none;
    transition: color 120ms;
}
.isis-breadcrumb__link:hover { color: var(--isis-text); }
.isis-breadcrumb__link:focus-visible {
    outline: 2px solid var(--isis-accent);
    outline-offset: 2px;
    border-radius: 4px;
}
.isis-rich-toolbar__actions {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    row-gap: 0.4rem;
    /* Les boutons passent à la ligne (alignés à droite) plutôt que de s'écraser :
       sans ça les libellés se cassaient sur 3 lignes (« Annuler / le / brouillon »)
       et le badge « OBSOLÈTE » chevauchait « Voir PDF ». */
    flex-wrap: wrap;
    justify-content: flex-end;
}
/* Aucun bouton d'action ne se comprime sous son contenu (label sur une seule ligne). */
.isis-rich-toolbar__actions > * { flex-shrink: 0; }

/* Barre à repli (IsisToolbarOverflow, 2026-09-18). Le conteneur ne se replie plus à la
   ligne : c'est le composant qui dégrade — libellés masqués (is-compact), puis boutons
   repliés dans « Plus » (is-overflowed). Sur une toolbar qui porte ce conteneur, le
   flex-wrap posé sur .isis-rich-toolbar est neutralisé : la décision de passer à la
   ligne se prend sur la largeur max-content du titre, AVANT qu'il ait eu la chance de
   rétrécir — c'est ce qui envoyait les actions sous le fil d'Ariane. */
.isis-rich-toolbar:has(> .isis-tb-overflow) { flex-wrap: nowrap; }
/* Le conteneur ne se comprime pas sous son contenu : ses boutons, eux, ne se compriment
   jamais (règle ci-dessus), si bien qu'un conteneur rétréci les laissait DÉBORDER par la
   gauche — recouvrant le cartouche d'identité (mesuré : conteneur 179 px pour 231 px de
   boutons, badge « Brouillon » repeint par le bouton primaire). C'est le fil d'Ariane, seul
   bloc qui sait se replier, qui cède ; le niveau de repli, lui, se décide dans le script.
   `flex-shrink: 0` seul porte cette règle : un `min-width: 0` à côté était mort (il n'autorise
   à passer sous la taille du contenu qu'un élément qui peut rétrécir) et disait l'inverse. */
.isis-rich-toolbar__actions.isis-tb-overflow { flex-wrap: nowrap; flex-shrink: 0; }
/* Le fil d'Ariane est le seul bloc qui cède — il doit céder par ELLIPSE, jamais sur deux
   lignes : son `flex-wrap: wrap` global (pages non migrées) est neutralisé ici seulement, et
   le h1 devient le seul élément rétractable de la ligne (le fil, lui, garde sa largeur).
   Le h1 porte déjà nowrap + overflow + text-overflow ; ce qui lui manquait, c'est d'être
   mis sous contrainte au lieu d'être renvoyé à la ligne suivante.
   `overflow: hidden` — une fois le titre réduit à zéro (mesuré à 900 px), le fil lui-même
   ne rentre plus ; comme il ne se comprime pas, il DÉBORDAIT sur le cartouche d'identité.
   Il est désormais coupé au bord de sa boîte au lieu d'être repeint par-dessus le voisin.
   `overflow: clip` + `overflow-clip-margin` plutôt que `hidden` : la coupe reste, mais le halo
   `:focus-visible` d'un lien du fil n'est plus rogné au pixel près quand on le tabule. */
.isis-rich-toolbar:has(> .isis-tb-overflow) > .isis-breadcrumb--heading { flex-wrap: nowrap; overflow: clip; overflow-clip-margin: 4px; }
.isis-rich-toolbar:has(> .isis-tb-overflow) > .isis-breadcrumb--heading > .isis-breadcrumb__trail,
.isis-rich-toolbar:has(> .isis-tb-overflow) > .isis-breadcrumb--heading > .isis-breadcrumb__sep { flex: 0 0 auto; }
/* Plancher du H1 : 10rem (160 px) — le titre maigrit, il ne disparaît plus. Sous TITLE_MIN
   (240 px, la place que le solveur JS lui réserve), donc aucun conflit avec le repli. */
.isis-rich-toolbar:has(> .isis-tb-overflow) > .isis-breadcrumb--heading > .isis-breadcrumb__current--heading { flex: 1 1 auto; min-width: 10rem; }
/* Ce plancher ne tient que si le fil le porte aussi : son `overflow: clip` ramène son minimum
   automatique à 0, et une identité chargée (référencement, revue, évaluations : 717 px mesurés
   sur un engagement) l'écrasait à 144 px — titre réduit à « E2E ». Le fil garde donc plancher
   + fil replié ; c'est l'identité qui cède, en renvoyant ses badges à la ligne plutôt qu'en
   les coupant (la référence et le statut restent en tête). */
.isis-rich-toolbar:has(> .isis-tb-overflow) > .isis-breadcrumb--heading { min-width: 12rem; }
.isis-rich-toolbar:has(> .isis-tb-overflow) > .isis-fiche-ident { flex-shrink: 1; flex-wrap: wrap; row-gap: 0.25rem; min-width: 0; }
/* Téléphone : fil, identité et actions ne tiennent pas sur une ligne (≈ 600 px mesurés sur
   une offre pour 358 disponibles à 390 px) et la ligne unique rognait le bouton primaire au
   bord droit. Le fil prend sa ligne ; l'identité puis les actions suivent, chacune passant
   à la ligne si besoin — le primaire n'est jamais replié, il reste visible. */
@media (max-width: 720px) {
    .isis-rich-toolbar:has(> .isis-tb-overflow) { flex-wrap: wrap; }
    .isis-rich-toolbar:has(> .isis-tb-overflow) > .isis-breadcrumb--heading { flex: 1 0 100%; }
    .isis-rich-toolbar:has(> .isis-tb-overflow) > .isis-fiche-ident { margin-left: 0; padding-left: 0; border-left: 0; }
    .isis-rich-toolbar:has(> .isis-tb-overflow) > .isis-tb-overflow { margin-left: auto; }
}
/* Fil replié sur l'icône du module (2026-09-18). Sous contrainte, le fil cède AVANT que le
   titre ne soit écrasé : « Gestion comm… » n'informe personne, l'icône du module si — elle
   dit où l'on est, et le chemin complet reste au survol (title posé par le script) comme au
   lecteur d'écran. Masquage VISUEL, jamais display:none : les liens restent focalisables et
   le point de repère « Fil d'Ariane » reste annoncé. La classe est posée par
   isis-toolbar-overflow.js entre le palier 1 et le palier 2 des actions. */
.isis-rich-toolbar:has(> .isis-tb-overflow) > .isis-breadcrumb--heading.is-trail-collapsed > .isis-breadcrumb__trail > *:not(.isis-breadcrumb__modicon) {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}
/* Un lien masqué que l'on TABULE reprend sa place : sinon le halo de focus se dessine sur un
   carré d'un pixel, hors de vue, et la navigation clavier n'a plus de repère visible. */
.isis-rich-toolbar:has(> .isis-tb-overflow) > .isis-breadcrumb--heading.is-trail-collapsed > .isis-breadcrumb__trail > a:focus-visible {
    position: static;
    width: auto;
    height: auto;
    margin: 0;
    overflow: visible;
    clip: auto;
}
.isis-rich-toolbar__btn.is-compact > span:not(.isis-rich-toolbar__btn-badge):not(.isis-rich-toolbar__btn-dot) { display: none; }
.isis-rich-toolbar__btn.is-compact { padding: 0; width: 32px; justify-content: center; }
.isis-rich-toolbar__btn.is-compact:has(.isis-rich-toolbar__btn-badge) { width: auto; padding: 0 0.45rem; }
.isis-rich-toolbar__btn.is-overflowed { display: none; }
/* Même dégradation pour IsisButton (.isis-action-btn), qui porte l'essentiel des actions
   de page depuis le lot boutons : le libellé vit dans .isis-action-btn__label. */
.isis-action-btn.is-compact > .isis-action-btn__label { display: none; }
.isis-action-btn.is-compact { padding: 0; width: 32px; justify-content: center; }
.isis-action-btn--sm.is-compact { width: 26px; }
.isis-action-btn.is-overflowed { display: none; }
/* Bascules de vue (segmented controls) posées dans une barre à repli : leurs boutons perdent
   leur libellé au palier 1 comme les autres, mais le groupe n'est JAMAIS replié — un choix de
   mode d'affichage ne se cache pas dans un menu. Le fond de l'état actif et l'icône restent :
   c'est tout ce qui porte le sens une fois le mot parti. Règle scopée au conteneur à repli
   (.isis-tb-overflow) pour ne pas toucher les bascules des barres de filtres. */
.isis-tb-overflow :is(.isis-view-toggle, .isis-segmented, .isis-seg, .isis-mode-toggle) > button.is-compact > span { display: none; }
.isis-tb-overflow :is(.isis-view-toggle, .isis-segmented, .isis-seg, .isis-mode-toggle) > button.is-compact {
    padding: 0 0.45rem;
    gap: 0;
}

/* « Ghost » au repos (2026-09-17, retour utilisateur « trop de gris ») : la classe est posée
   1051 fois sur 283 fichiers, et 4 à 7 boutons cadrés gris-sur-blanc par en-tête de page
   formaient le motif dominant de chaque écran. Le cadre et le fond ne viennent plus qu'au
   survol, au focus et sur les états qui portent un sens (--primary, .is-active, .is-stale,
   .is-actions-btn). La bordure reste déclarée transparente, pas retirée : aucun décalage
   d'1 px quand elle apparaît. */
.isis-rich-toolbar__btn {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    height: 32px;
    padding: 0 0.7rem;
    white-space: nowrap;   /* label + badge sur une seule ligne */
    border: 1px solid transparent;
    border-radius: 8px;
    background: transparent;
    color: var(--isis-text-muted);
    cursor: pointer;
    font-size: 0.8rem;
    text-decoration: none;
    transition: background-color 120ms, color 120ms, border-color 120ms;
}
/* Même défaut que .isis-grid__action-btn .rzi : sans font-size inline, RadzenIcon
   retombe sur 24px — ici dans un bouton de 32px, à côté d'un label de 0.8rem.
   535 des 624 icônes de toolbar posent 16px en inline ; les 27 sans taille
   dépassaient. 16px = valeur écrasante, prise comme défaut. */
.isis-rich-toolbar__btn .rzi {
    font-size: 16px;
}
.isis-rich-toolbar__btn:hover { background-color: var(--isis-surface-alt); color: var(--isis-text); border-color: var(--isis-border); }
.isis-rich-toolbar__btn:disabled,
.isis-rich-toolbar__btn[disabled] {
    opacity: 0.4;
    cursor: not-allowed;
    pointer-events: none;
}
/* Variante primaire (ex. bouton « Exporter » du dashboard, calque mockup ARCHITECT).
   Polish 2026-06 : hardcode --isis-mod-gescom neutralisé en --isis-current-mod
   (le 2e bloc plus bas gagnait déjà la cascade, mais on retire le latent cross-module). */
.isis-rich-toolbar__btn--primary {
    background: var(--isis-current-mod, var(--isis-accent));
    border-color: var(--isis-current-mod, var(--isis-accent));
    color: #fff;
    font-weight: 600;
}
.isis-rich-toolbar__btn--primary:hover {
    background-color: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 85%, var(--isis-text));
    color: #fff;
}
.isis-rich-toolbar__btn--primary .rzi { color: #fff; }
/* En SOMBRE, la teinte du module est ÉCLAIRCIE (cf. bloc :root[data-theme="dark"] : les seize
   --isis-mod-* y sont des tons clairs, faits pour servir de texte sur fond sombre). Posée en
   FOND avec le blanc de la règle ci-dessus, elle donne du blanc sur du clair : mesuré en
   navigateur le 2026-08-05 sur /admin/roles, 2,56:1 pour un texte de 12,8 px — il en faut 4,5.
   L'encre sombre du thème rétablit 6,8:1 sur admin comme sur les quinze autres teintes, toutes
   plus claires encore. Le survol n'échappe pas à la règle : il mêle 15 % de --isis-text, qui en
   sombre est presque blanc — le fond y devient plus clair, jamais plus foncé. */
:root[data-theme="dark"] .isis-rich-toolbar__btn--primary,
:root[data-theme="dark"] .isis-rich-toolbar__btn--primary:hover,
:root[data-theme="dark"] .isis-rich-toolbar__btn--primary .rzi { color: var(--isis-bg); }
.isis-rich-toolbar__btn:disabled:hover,
.isis-rich-toolbar__btn[disabled]:hover {
    background-color: transparent;
}
/* aria-disabled (jamais l'attribut HTML disabled) : le contrôle reste dans l'ordre de
   tabulation et son title — la RAISON de l'inertie — reste atteignable au clavier et au
   survol souris. Sans cette règle le bouton s'affichait comme parfaitement actif (pleine
   opacité, curseur pointer, hover normal) et ne faisait rien au clic — régression relevée en
   revue (2026-09-03, lot 4 round 1) sur Générer/Relancer/Nouveau forfait/Nouveau
   coefficient/Exporter. Même langage visuel que .isis-filter-facet-btn[aria-disabled] :
   pas de pointer-events:none, qui bloquerait le survol souris du title en plus du clic. */
.isis-rich-toolbar__btn[aria-disabled="true"] {
    opacity: 0.4;
    cursor: not-allowed;
}
.isis-rich-toolbar__btn[aria-disabled="true"]:hover {
    background-color: transparent;
}
/* État ouvert d'un bouton toolbar qui pilote un popover (ex. dropdown « Type & portée »), et
   bouton bascule enfoncé (aria-pressed) : même rendu, l'état se voit comme il s'annonce. */
.isis-rich-toolbar__btn.is-active,
.isis-rich-toolbar__btn[aria-pressed="true"] {
    background-color: var(--isis-surface-alt);
    color: var(--isis-text);
    border-color: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 45%, var(--isis-border));
}
/* Dropdown toolbar — popover ancré sous le bouton déclencheur (ex. /gescom/devis). */
.isis-toolbar-dropdown { position: relative; display: inline-flex; }
.isis-toolbar-dropdown__backdrop {
    position: fixed;
    inset: 0;
    z-index: 930;
    background: transparent;
}
.isis-toolbar-dropdown__panel {
    position: absolute;
    top: calc(100% + 6px);
    right: 0;
    z-index: 931;
    min-width: 264px;
    padding: 0.85rem 0.95rem;
    display: flex;
    flex-direction: column;
    gap: 0.9rem;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: 10px;
    box-shadow: var(--isis-elevation-2, 0 12px 32px rgba(0, 0, 0, 0.16));
    animation: isis-toolbar-dropdown-in 140ms ease-out;
}
/* Variante ancrée au point du clic — pour un dropdown ouvert DEPUIS UNE LIGNE DE
   GRILLE. En `absolute`, le panneau s'ouvre toujours vers le bas et se fait
   absorber par l'`overflow: auto` de `.isis-grid` : au lieu de flotter, il
   allonge la zone scrollable (barre de scroll qui apparaît, menu invisible).
   Constaté sur l'échéancier d'une commande : panneau à bottom 970 px pour un
   viewport de 900 px, scrollHeight de la grille 79 → 190 px.
   `fixed` sort le panneau de tout ancêtre scrollable ; les clamps `min()`/`max()`
   le maintiennent dans le viewport, y compris quand la ligne est tout en bas
   (il remonte alors au lieu de sortir par le bas). Même parti que le popup de
   <IsisColumnFilter>, qui règle le même problème sur les en-têtes de colonne.
   La page fournit --dd-x / --dd-y (coordonnées du clic) en style inline. */
.isis-toolbar-dropdown__panel--anchored {
    position: fixed;
    top: min(var(--dd-y, 0px), calc(100vh - var(--dd-maxh, 260px) - 8px));
    right: max(8px, calc(100vw - var(--dd-x, 100vw)));
    left: auto;
    max-height: var(--dd-maxh, 260px);
    overflow-y: auto;
}
/* Variante ancrée à GAUCHE du point de clic — pour un déclencheur en DÉBUT de ligne
   (ex. cluster « réglages de ligne » de DevisItemsEditDialog, colonne 2 juste après la
   poignée de réordonnancement). `--anchored` ci-dessus étend le panneau vers la GAUCHE
   depuis le point de clic (pensé pour un bouton "..." en fin de ligne) : sur un
   déclencheur déjà collé au bord gauche du conteneur, ça pousse le panneau hors-écran
   (constaté : bouton à x≈95px, panneau de 264px → x≈-169px, coupé net). Ici le panneau
   s'étend vers la DROITE depuis le clic, dans le sens où le contenu de la ligne existe. */
.isis-toolbar-dropdown__panel--anchored-left {
    position: fixed;
    top: min(var(--dd-y, 0px), calc(100vh - var(--dd-maxh, 260px) - 8px));
    left: max(8px, var(--dd-x, 8px));
    right: auto;
    max-height: var(--dd-maxh, 260px);
    overflow-y: auto;
}
/* Le menu « Plus » d'IsisToolbarOverflow calcule --dd-maxh sur la place restante SOUS son
   bouton : la borne doit donc porter sur la BOÎTE, pas sur le contenu. Aucun reset global
   ne couvre ce panneau (content-box) — mesuré sur une fenêtre de 420 px de haut : bas du
   panneau à 439 px, soit sa marge interne hors écran. `border-box` ferait aussi rentrer
   cette marge dans min-width, rétrécissant le menu de 32 px et cassant des libellés sur
   deux lignes : min-width est ré-exprimée pour garder la même largeur UTILE.
   Portée volontairement réduite au composant : les autres utilisateurs d'--anchored
   (échéancier de commande, volet notifications) passent un --dd-maxh en dur, calibré sur
   leur contenu, et se verraient tronquer d'autant. */
.isis-tb-overflow > .isis-toolbar-dropdown > .isis-toolbar-dropdown__panel--anchored {
    box-sizing: border-box;
    min-width: calc(264px + 1.9rem + 2px);
}
/* Au-dessus de la focus zone. La barre de page reste visible AU-DESSUS de
   `.isis-focus-zone--expanded` (position: fixed, z-index 950), mais son menu « Plus »
   s'ouvre vers le bas, DANS l'emprise de la zone : à 931 il passait derrière elle — trois
   sondes elementFromPoint sur le panneau rendaient la zone, pas le menu (mesuré le
   2026-09-18 sur la fiche d'offre, mode plein écran). 960/961 : au-dessus de la zone, sous
   les dialogues (1000).
   La paire porte sur le PANNEAU, pas sur la variante --anchored : remonter le seul voile
   au-dessus d'un panneau nu resté à 931 le place DEVANT le menu, et le voile ferme au clic
   — le menu s'ouvre, puis se referme sans rien faire (6 pages mesurées le 2026-09-25 :
   opportunités, planner, engagements, licences, parc carte, échéances de calibration).
   Les deux valeurs se tiennent ou ne valent rien. */
.isis-tb-overflow > .isis-toolbar-dropdown > .isis-toolbar-dropdown__backdrop { z-index: 960; }
.isis-tb-overflow > .isis-toolbar-dropdown > .isis-toolbar-dropdown__panel { z-index: 961; }
@keyframes isis-toolbar-dropdown-in {
    from { opacity: 0; transform: translateY(-4px); }
    to   { opacity: 1; transform: translateY(0); }
}
/* Options empilées verticalement (une par ligne, pleine largeur) dans les dropdowns toolbar. */
.isis-toolbar-dropdown__panel .isis-filter-panel__chips {
    flex-direction: column;
    flex-wrap: nowrap;
    align-items: stretch;
}
.isis-toolbar-dropdown__panel .isis-chip {
    justify-content: space-between;
    width: 100%;
}
/* Variante « Légende & aide » de la frise portefeuille (/gesproj/commandes, mode Frise) —
   même recette de disclosure que Nature/Type/Portée sur cette page, contenu plus large (texte
   d'aide + légende de couleurs) donc panneau élargi + légende en grille 2 colonnes (le
   flex-wrap d'origine, pensé pour la pleine largeur de page, s'écrase mal dans 380-420px). */
.isis-toolbar-dropdown__panel--legend { width: min(420px, 92vw); }
.isis-toolbar-dropdown__panel--legend .isis-pgantt-legend {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0.4rem 0.9rem;
    margin-top: 0;
}

/* Bouton d'information (<IsisInfoPopover>) — l'endroit où va la phrase DIDACTIQUE d'un
   bandeau retiré : ce qu'est l'objet listé, comment marche un mécanisme. Posé dans le
   .isis-filter-bar__end, à côté de la facette qu'il explique quand il porte sur un axe
   précis, en fin de barre quand il porte sur toute la page.

   Il ne porte jamais un CHIFFRE : un compteur se reloge sur une facette, un onglet ou un
   bandeau d'alerte — personne n'ouvre un popover pour découvrir un nombre.

   Le panneau REPREND .isis-toolbar-dropdown__panel (position, ombre, animation, backdrop)
   plutôt que de les redéclarer : deux définitions de la même boîte écrites à des moments
   différents se superposent, et c'est ainsi que la recherche s'est retrouvée encadrée trois
   fois sur 95 pages. Ici on ne surcharge que la largeur et la typographie du texte. */
.isis-info-pop { position: relative; display: inline-flex; }
.isis-info-pop__btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.35rem;
    height: 32px;
    min-width: 32px;
    padding: 0 0.5rem;
    border: 1px solid var(--isis-border);
    border-radius: 8px;
    background: var(--isis-surface);
    color: var(--isis-text-soft);
    font-size: var(--isis-fs-sm);
    cursor: pointer;
    transition: color 160ms ease, border-color 160ms ease;
}
.isis-info-pop__btn:hover,
.isis-info-pop__btn.is-active {
    color: var(--isis-current-mod, var(--isis-accent));
    border-color: var(--isis-current-mod, var(--isis-accent));
}
.isis-info-pop__btn:focus-visible {
    outline: 2px solid color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 55%, transparent);
    outline-offset: 1px;
}
.isis-info-pop__label { white-space: nowrap; }
/* Une explication se lit en prose : largeur de ligne bornée, interlignage confortable —
   le panneau de facettes, lui, empile des options courtes. */
.isis-info-pop__panel {
    width: min(400px, 92vw);
    gap: 0.55rem;
    font-size: var(--isis-fs-sm);
    line-height: 1.5;
    color: var(--isis-text-muted);
}
.isis-info-pop__panel p { margin: 0; }
.isis-info-pop__panel strong { color: var(--isis-text); }

/* ── Avis de page (bouton Info d'en-tête, 2026-09-18) ─────────────────────────
   Aucun message persistant sous le fil d'Ariane : ils vivent ici. La pastille porte le
   nombre ; elle pulse 3 fois à l'arrivée d'un avis (rejouée par @key), jamais sous
   reduced-motion (WCAG 2.2.2). Le panneau reprend .isis-toolbar-dropdown__panel. */
.isis-page-notices__btn { position: relative; }
.isis-notice-list { margin: var(--isis-space-sm) 0 0; padding-left: 1.1em; display: grid; gap: var(--isis-space-xs); }
.isis-notice-list__hint { color: var(--isis-text-muted); font-size: var(--isis-fs-caption); }
.isis-page-notices__btn:not(.has-notices) { color: var(--isis-text-muted); }
.isis-page-notices__btn:not(.has-notices):not(.is-active):not(:hover) {
    border-color: transparent;
    background: transparent;
}
.isis-page-notices__btn:focus-visible {
    outline: 2px solid var(--isis-current-mod, var(--isis-accent));
    outline-offset: 1px;
}
.isis-page-notices__btn.has-notices { color: var(--isis-text); }
.isis-page-notices__badge {
    --isis-notice-tone: var(--isis-info);
    position: absolute;
    top: -6px;
    right: -6px;
    min-width: 18px;
    height: 18px;
    padding: 0 5px;
    box-sizing: border-box;
    border-radius: var(--isis-radius-pill);
    background: var(--isis-notice-tone);
    color: var(--isis-surface);
    font-size: var(--isis-fs-xs);
    font-weight: 600;
    line-height: 18px;
    text-align: center;
    outline: 2px solid transparent;
    animation: isis-notice-pulse 600ms ease-out 3;
}
.isis-page-notices__badge--warning { --isis-notice-tone: var(--isis-warning); }
.isis-page-notices__badge--danger { --isis-notice-tone: var(--isis-danger); }
@keyframes isis-notice-pulse {
    0% { outline-color: var(--isis-notice-tone); outline-offset: 0; }
    100% { outline-color: transparent; outline-offset: 6px; }
}
@media (prefers-reduced-motion: reduce) {
    .isis-page-notices__badge,
    .isis-page-notices__panel { animation: none; }
}
.isis-page-notices__panel {
    right: 0;
    left: auto;
    box-sizing: border-box;
    width: min(440px, calc(100vw - 32px));
    max-height: min(60vh, 520px);
    overflow-y: auto;
    gap: 0.5rem;
}
.isis-page-notices__panel[hidden] { display: none; }
/* Sous 1024 px (repère tablette du dépôt, cf. .isis-rich-header--with-kpi ci-dessus) le shell
   garde son sous-menu déplié et rogne tout panneau absolu à la colonne de contenu ; entre 768 et
   1024 le bloc d'actions occupe presque toute la colonne, sans assez de marge pour que
   margin-inline-start:auto pousse le bouton jusqu'au bord (mesuré : x négatif à 780-1000 px). Le
   panneau passe donc en fixed, pleine largeur utile, sous l'en-tête applicatif. */
@media (max-width: 1024px) {
    .isis-page-notices__panel {
        position: fixed;
        top: calc(var(--isis-header-h) + 8px);
        left: 16px;
        right: 16px;
        width: auto;
        max-height: calc(100dvh - var(--isis-header-h) - 24px);
    }
}
.isis-page-notices__head { margin: 0; color: var(--isis-text-muted); font-size: var(--isis-fs-sm); }
.isis-page-notices__empty { margin: 0; color: var(--isis-text-muted); font-size: var(--isis-fs-sm); }
.isis-page-notice {
    --isis-notice-tone: var(--isis-info);
    --isis-notice-soft: var(--isis-info-soft);
    display: grid;
    grid-template-columns: 20px 1fr;
    gap: 0.5rem;
    padding: 0.6rem 0.7rem;
    box-sizing: border-box;
    border: 0;
    border-inline-start: 3px solid var(--isis-notice-tone);
    border-radius: var(--isis-radius);
    background: var(--isis-notice-soft);
    color: var(--isis-text);
    font-size: var(--isis-fs-sm);
    line-height: 1.45;
}
.isis-page-notice--warning { --isis-notice-tone: var(--isis-warning); --isis-notice-soft: var(--isis-warning-soft); }
.isis-page-notice--danger { --isis-notice-tone: var(--isis-danger); --isis-notice-soft: var(--isis-danger-soft); }
.isis-page-notice__icon { color: var(--isis-notice-tone); font-size: 18px; line-height: 1; }
.isis-page-notice__title { display: block; margin-bottom: 0.2rem; }
.isis-page-notice__text ul { margin: 0.3rem 0 0; padding-left: 1.1rem; }
/* Liens sans classe dans un avis : --isis-info sur les trois fonds -soft, calculé contre :root —
   clair 7,15 (info) · 7,83 (warning) · 7,14 (danger) ; sombre 5,87 · 5,87 · 6,37. */
.isis-page-notice__text a { color: var(--isis-info); text-decoration: underline; }

/* Un <label> qui habille un <input type=file> invisible (bouton « Déposer ») : le focus est sur
   l'input, le contour doit se voir sur le label. */
.isis-rich-toolbar__btn:focus-visible,
.isis-rich-toolbar__btn:has(> input[type=file]:focus-visible) {
    outline: 2px solid var(--isis-accent);
    outline-offset: 1px;
}
/* Badge informatif dans la toolbar (ex: « Source externe » quand le sujet est
   ExternalOwned par un provider RH). Style discret, pas un bouton. */
.isis-rich-toolbar__badge {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.4rem 0.75rem;
    border-radius: 6px;
    background: var(--isis-surface-alt);
    color: var(--isis-text-muted);
    font-size: 0.78rem;
    font-weight: 500;
    cursor: help;
}
.isis-rich-toolbar__btn--primary {
    /* Couleur du module courant (fallback accent global) — chaque module
       a un CTA primaire à sa couleur, signal d'identité fort. */
    background: var(--isis-current-mod, var(--isis-accent));
    border-color: var(--isis-current-mod, var(--isis-accent));
    color: white;
}
.isis-rich-toolbar__btn--primary:hover {
    /* F3 — feedback tactile perceptible : assombrissement + lift d'ombre.
       Ne change PAS le layout (pas de translateY), uniquement ombre + brightness. */
    filter: brightness(0.92);
    box-shadow: var(--isis-elevation-2);
    color: white;
    background: var(--isis-current-mod, var(--isis-accent));
}
/* Variante icon-only — bouton carré 32×32 pour les actions secondaires de la
   toolbar (toggle élargir/réduire, etc.) qui se contentent d'une icône + tooltip.
   Refonte 2026-05-29 (pilote DevisListPage drawer overlay). */
.isis-rich-toolbar__btn--icon {
    width: 32px;
    padding: 0;
    justify-content: center;
}

/* F6 — tokens ISIS (resaturés AA) plutôt que fallback Radzen non-refonte. */
.isis-rich-toolbar__btn--success { color: var(--isis-success); }
.isis-rich-toolbar__btn--success:hover { background: var(--isis-success-soft); color: var(--isis-success); }
.isis-rich-toolbar__btn--danger { color: var(--isis-danger); }
.isis-rich-toolbar__btn--danger:hover { background: var(--isis-danger-soft); color: var(--isis-danger); }
.isis-rich-toolbar__btn--warning { color: var(--isis-warning); }
.isis-rich-toolbar__btn--warning:hover { background: var(--isis-warning-soft); color: var(--isis-warning); }

/* Fraîcheur d'un artefact servi par un bouton (« Voir PDF » des fiches offre, facture, avoir).
   Décision utilisateur du 2026-09-18 : plus de badge texte « obsolète » dans le bouton, l'état
   passe par la couleur — MAIS jamais la couleur seule (WCAG 1.4.1) : la page change aussi
   l'icône (picture_as_pdf → sync_problem) et l'infobulle. `is-fresh` = vert « à jour »,
   `is-stale` = rouge « obsolète ». Le passage à obsolète bat trois fois puis se fige : la
   charte bannit l'animation perpétuelle (§1 « Static Restrained »), et un clignotement
   permanent finit ignoré. Rien sous prefers-reduced-motion. Les deux états gardent leur
   cadre au repos : ce sont des états porteurs de sens, pas des boutons secondaires ordinaires. */
.isis-rich-toolbar__btn.is-fresh {
    border-color: color-mix(in srgb, var(--isis-success) 45%, var(--isis-border));
    color: var(--isis-success);
}
.isis-rich-toolbar__btn.is-fresh:hover {
    background: var(--isis-success-soft);
    color: var(--isis-success);
    border-color: var(--isis-success);
}
.isis-rich-toolbar__btn.is-stale {
    border-color: var(--isis-danger);
    color: var(--isis-danger);
    animation: isis-stale-pulse 700ms ease-in-out 3;
}
.isis-rich-toolbar__btn.is-stale:hover {
    background: var(--isis-danger-soft);
    color: var(--isis-danger);
}
@keyframes isis-stale-pulse {
    0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--isis-danger) 45%, transparent); }
    50%      { box-shadow: 0 0 0 5px color-mix(in srgb, var(--isis-danger) 0%, transparent); }
}
@media (prefers-reduced-motion: reduce) {
    .isis-rich-toolbar__btn.is-stale { animation: none; }
}
.isis-rich-toolbar__btn-badge {
    display: inline-block;
    padding: 0.05rem 0.4rem;
    margin-left: 0.35rem;
    font-size: 0.65rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.02em;
    background: #f59e0b;
    color: white;
    border-radius: 10px;
    line-height: 1.3;
}

/* V1.0quinquies (2026-05-29) — Séparateur visuel vertical entre groupes
   de boutons dans la toolbar (cf. audit cohérence FactureEmiseDetail).
   Utilisé pour découper [PDF block] | [Workflow] | [Destructive]. */
.isis-rich-toolbar__sep {
    width: 1px;
    height: 24px;
    margin: 0 0.4rem;
    background: var(--isis-border, #e5e7eb);
    flex-shrink: 0;
    align-self: center;
}

/* Header de page (titre + sous-titre + badges + toggle droite) */
.isis-rich-header {
    /* Branded depth 2026-05-26 : élévation tokenisée + gradient module 4 %
       (cohérence avec .isis-kpi-hero qui utilise déjà ce pattern à 6 %).
       Plus léger ici car le header est moins data-centric — la teinte module
       reste un signal d'identité subtil, pas une surface emphasised. */
    background: linear-gradient(135deg,
        var(--isis-surface) 0%,
        color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 4%, var(--isis-surface)) 100%);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius);
    padding: 1rem 1.25rem;
    display: flex;
    align-items: flex-start;
    gap: 1rem;
    box-shadow: var(--isis-elevation-1);
}
.isis-rich-header__icon {
    width: 44px; height: 44px;
    border-radius: 10px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}
.isis-rich-header__main {
    flex: 1;
    min-width: 0;   /* sans ça, un sous-titre long ne se replie pas et pousse le bandeau hors champ */
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
    /* Barre verticale accent module — signal d'identité de l'en-tête. CONSERVÉE (demande utilisateur). */
    border-left: 3px solid var(--isis-current-mod, var(--isis-accent));
    border-radius: 2px;
    padding-left: 0.95rem;
    transition: border-color 200ms ease;
}
.isis-rich-header__context {
    font-size: 0.75rem;
    color: var(--isis-text-soft);
}
/* Chapô d'une page d'AIDE. Distinct d'une introduction de page (qui va dans IsisInfoPopover) : sur une page dont le contenu EST
   une explication, la phrase d'annonce n'est pas un ornement d'en-tête à replier derrière un
   bouton d'information — c'est le premier paragraphe du texte. D'où une largeur de lecture et
   un interlignage de prose, et non ceux d'une ligne de service. */
.isis-help-page__chapo {
    margin: 0 0 1.1rem;
    max-width: 72ch;
    font-size: var(--isis-fs-md, 0.95rem);
    line-height: 1.6;
    color: var(--isis-text-muted);
}
.isis-help-page__chapo code {
    font-family: var(--isis-font-mono);
    font-size: 0.9em;
}

/* Titre de la FENÊTRE affichée sur une page navigable dans le temps (capacité, calendrier).
   Le fil d'Ariane porte le nom de la PAGE, qui ne change pas ; ce `h2` porte le mois ou la
   période, qui change à chaque clic sur les flèches — même partage que le libellé de planche
   d'un tableau de bord (2026-09-05, revue d'harmonisation gespla). */
.isis-page-periode {
    margin: 0 0 0.6rem;
    font-size: var(--isis-fs-md, 0.95rem);
    font-weight: 600;
    color: var(--isis-text);
    display: flex;
    align-items: baseline;
    gap: 0.5rem;
    flex-wrap: wrap;
}
.isis-page-periode small {
    font-weight: 400;
    font-size: var(--isis-fs-sm);
    color: var(--isis-text-muted);
    font-variant-numeric: tabular-nums;
}

.isis-rich-header__subtitle {
    font-size: 0.82rem;
    color: var(--isis-text-muted);
    margin-top: 0.25rem;
}
/* Dans un bandeau à KPI (flex identity | KPIs), le sous-titre doit rester étroit :
   sans borne il occupe toute la largeur et repousse la rangée KPI sous le texte
   (le pattern de référence --with-kpi n'a qu'un titre, sans sous-titre). */
.isis-rich-header--with-kpi .isis-rich-header__subtitle {
    max-width: 52ch;
}
/* Échelle typo alignée NetLogger V3 (CommandDetailsV3.razor.css = 20px/600, mono -0.01em
   sur les KPIs). ISIS prend +2px (densité 6 vs NetLogger 7-8) sans gonfler les weights. */
.isis-rich-header__title {
    font-size: 1.375rem;
    font-weight: 600;    /* DESIGN.md §3 : 600 max sur les titres (était 700 — Geist rend mal le bold serré). */
    color: var(--isis-text);
    line-height: 1.18;
    letter-spacing: -0.02em;    /* relift typo : tightening display moderne */
    margin: 0;
}

/* ────────────────────────────────────────────────────────────────────────────
   Variante --with-kpi : header qui consomme le KPI hero (gain ~70px).
   Pattern opt-in introduit 2026-05-26 sur les pages liste denses (devis pilote).
   Layout : identité (icône + main) à gauche, KPIs en grille auto-fit à droite,
   séparés par un trait vertical. Sous 1024px → stack vertical (fallback).
   Le bloc <div class="isis-kpi-hero"> séparé doit être supprimé quand on
   applique cette variante (sinon doublon).
   ──────────────────────────────────────────────────────────────────────────── */
.isis-rich-header.isis-rich-header--with-kpi {
    display: flex;
    align-items: center;
    gap: 1.5rem;
    /* Les KPI passent à la ligne plutôt que d'être tranchés par le bord droit.
       Le repli @media 1024px ne couvrait rien entre 1024px et la largeur réelle
       du bandeau : à 1512px, 13 pages perdaient leur dernier KPI (2026-07-17). */
    flex-wrap: wrap;
}
.isis-rich-header__identity {
    display: flex;
    align-items: flex-start;
    gap: 1rem;
    /* Peut se réduire (0 0 auto avant) : sinon un titre ou sous-titre long
       éjecte la rangée KPI hors du viewport au lieu de se replier. */
    flex: 0 1 auto;
    min-width: 0;
}
/* Compacté à droite via margin-left:auto (pousse les KPIs en fin de bandeau).
   Les cards prennent leur largeur naturelle (max-content), pas 1fr — l'espace
   au centre reste neutre, identité à gauche / données à droite. */
.isis-rich-header__kpis {
    display: flex;
    align-items: center;
    gap: 0;
    margin-left: auto;
    border-left: 1px solid var(--isis-border);
    padding-left: 1.25rem;
    /* 0 1 auto + wrap : au-delà de 4-5 cartes la rangée se replie au lieu de
       sortir du bandeau. Aucun effet sur les pages qui tiennent déjà sur une ligne. */
    flex: 0 1 auto;
    flex-wrap: wrap;
    row-gap: 0.5rem;
}
/* KPI cards en mode compact dans le header (1/3 plus petits que le KPI hero standard) */
.isis-rich-header__kpis .isis-kpi-card {
    padding: 0.15rem 0.85rem;
    gap: 0.1rem;
    border-left: 1px solid var(--isis-border);
    min-width: 96px;
}
.isis-rich-header__kpis .isis-kpi-card:first-child {
    border-left: none;
    padding-left: 0.2rem;
}

/* isis-rich-header__kpis--standalone RETIRÉE (revue harmonisation SIRH, round 1) : posée pour
   « le même rail, sorti du bandeau, en tête d'un onglet de fiche » (2026-09-03), elle n'a plus
   aucun usage réel dans .razor — vérifié sur cette branche ET sur main/les 4 autres branches
   d'harmonisation en cours. Sa seule occurrence restante après le renommage ci-dessous était le
   TEXTE d'un commentaire Razor, pas une classe posée. Si une fiche a besoin de ce rail sorti du
   bandeau, la reposer alors avec son usage réel à l'appui.

   Rail de KPI d'une page d'ANALYSE (§E2) sans bandeau — CompetenceMatricePage. Nom dédié : cette
   page n'a jamais eu de bandeau, "rich-header" mentirait. */
.isis-analyse-kpis {
    display: flex;
    align-items: center;
    gap: 0;
    flex: 0 1 auto;
    flex-wrap: wrap;
    row-gap: 0.5rem;
    margin-bottom: 0.9rem;
    padding-bottom: 0.9rem;
    border-bottom: 1px solid var(--isis-border);
}
.isis-analyse-kpis .isis-kpi-card {
    padding: 0.15rem 0.85rem;
    gap: 0.1rem;
    border-left: 1px solid var(--isis-border);
    min-width: 96px;
}
.isis-analyse-kpis .isis-kpi-card:first-child { border-left: none; padding-left: 0.2rem; }
.isis-analyse-kpis .isis-kpi-card__label { font-size: 0.62rem; }
.isis-analyse-kpis .isis-kpi-card__value { font-size: 1.15rem; }
.isis-analyse-kpis .isis-kpi-card__hint { font-size: 0.65rem; }
.isis-rich-header__kpis .isis-kpi-card__label {
    font-size: 0.62rem;
}
.isis-rich-header__kpis .isis-kpi-card__value {
    font-size: 1.15rem;
}
.isis-rich-header__kpis .isis-kpi-card__hint {
    font-size: 0.65rem;
}
/* Responsive : viewport < 1024px → stack vertical, séparateur passe en top border */
@media (max-width: 1024px) {
    .isis-rich-header.isis-rich-header--with-kpi {
        flex-direction: column;
        align-items: stretch;
        gap: 0.85rem;
    }
    .isis-rich-header__kpis {
        margin-left: 0;
        border-left: none;
        padding-left: 0;
        border-top: 1px solid var(--isis-border);
        padding-top: 0.85rem;
        flex-wrap: wrap;
    }
    /* isis-analyse-kpis perdait cette bascule en héritant SEULE de .isis-rich-header__kpis via
       --standalone avant le renommage (MINEUR, revue round 1) : sans bandeau à empiler dessus,
       elle n'a pas besoin de passer en colonne, seule la bordure doit migrer en haut. */
    .isis-analyse-kpis {
        border-top: 1px solid var(--isis-border);
        padding-top: 0.85rem;
    }
}

/* ============================================================================
   .isis-form — formulaires de saisie ERP
   ----------------------------------------------------------------------------
   Applique width:100% sur tous les RadzenFormField/TextBox/DropDown enfants.
   Évite la répétition de Style="width: 100%;" inline sur chaque champ.
   ============================================================================ */
.isis-form .rz-form-field,
.isis-form .rz-form-field .rz-textbox,
.isis-form .rz-form-field .rz-textarea,
.isis-form .rz-form-field .rz-dropdown,
.isis-form .rz-form-field .rz-spinner,
.isis-form .rz-form-field .rz-numeric,
.isis-form .rz-form-field .rz-numeric {
    width: 100%;
}

/* Astérisque "obligatoire" visuel, ignoré par les lecteurs d'écran
   (l'attribut aria-required + helper text portent l'info sémantique). */
.isis-form__required {
    color: var(--rz-danger, #dc2626);
    margin-left: 2px;
    font-weight: 600;
}

/* ~20 dialogs écrivent isis-form-linear__required, jamais défini (la classe historique
   est isis-form__required) : l'astérisque obligatoire y était invisible. Alias assumé. */
.isis-form-linear__required {
    color: var(--rz-danger, #dc2626);
    margin-left: 2px;
    font-weight: 600;
}

/* Actions de formulaire — sticky au bas du scroll container parent. */
.isis-form__actions {
    position: sticky;
    bottom: 0;
    background: var(--isis-surface);
    padding: 0.75rem 0 0.25rem 0;
    margin-top: 0.5rem;
    border-top: 1px solid var(--isis-border);
    z-index: 5;
}

/* ============================================================================
   .isis-form-linear — Style "Linear minimal" (maquette 1 retenue 2026-05-12)
   ----------------------------------------------------------------------------
   Container 720px centré, inputs underline-only, labels au-dessus, sections
   séparées par un trait subtil. Scope strict : ne s'applique QU'à un container
   .isis-form-linear. Aucun impact sur les autres pages.
   ============================================================================ */

/* Container global — max 720px centré, padding contenu (variante densifiée) */
.isis-form-linear {
    max-width: none;
    margin: 0;
    padding: 1.25rem 1.5rem 2.5rem;
    font-size: 14px;
    color: var(--isis-text);
    line-height: 1.45;
}
/* En dialogue, .rz-dialog-content applique déjà 24px sur les 4 côtés : le padding
   du formulaire s'y CUMULAIT (mesuré : 44px haut/bas, 48px gauche/droite), d'où
   l'espace visible sous le pied d'actions et des marges latérales excessives. Le
   padding de page n'a de sens qu'en pleine page — en dialogue, on le neutralise et
   on laisse celui du dialogue faire le travail. Vaut pour tous les dialogues
   bâtis sur form-linear. */
.rz-dialog-content .isis-form-linear { padding: 0; }

/* <fieldset class="field"> (DevisImportFromDevisDialog, EntrepriseFormDialog,
   NewOfferFromSourceDialog, OfferModeDialog) : la feuille UA du navigateur pose
   min-width:min-content sur <fieldset>, contrairement à un <div>. Sans contrainte,
   un item de catalogue au titre long (nowrap pour l'ellipsis) force le fieldset —
   et tout son parent .isis-form-linear--dialog — à s'élargir jusqu'à cette largeur
   intrinsèque, débordant le dialogue au lieu de tronquer (mesuré : 1777px de
   fieldset dans un dialogue de 780/860px). min-width:0 restore le comportement
   normal d'un bloc et laisse .isis-catalog-item__name faire son ellipsis.
   Le reset border/margin/padding qui accompagnait ce min-width était recopié en
   style inline sur les 11 <fieldset class="field"> du dépôt : il vit ici, où la
   spécificité (0,2,1) bat le margin-bottom de .isis-form-linear .field. */
.isis-form-linear fieldset.field {
    min-width: 0;
    border: 0;
    margin: 0;
    padding: 0;
}

/* Avenant de retrait : lots à cocher. Au-delà de 8 lots, la liste défile dans une hauteur bornée
   (huit lignes environ) au lieu d'allonger le dialogue. */
.isis-form-linear .isis-avenant-lots {
    display: flex;
    flex-direction: column;
    gap: var(--isis-space-xs);
}
.isis-form-linear .isis-avenant-lots--defilant {
    max-height: calc(8 * var(--isis-space-xl));
    overflow-y: auto;
    padding: var(--isis-space-xs);
    border: 1px solid var(--isis-border-soft);
    border-radius: var(--isis-radius-sm);
}
/* Rappel d'irréversibilité : texte courant, pas une aide en petit gris qu'on saute. */
.isis-form-linear .isis-avenant-lots__rappel {
    margin: var(--isis-space-sm) 0 0;
    color: var(--isis-text);
}

/* Dialogue de traitement d'un retour : le sujet traité, rappelé en tête.
   Assez présent pour qu'on sache sur quoi on décide, sans concurrencer le titre du dialogue. */
.isis-triage__subject {
    margin: 0 0 0.9rem;
    font-weight: 600;
    color: var(--isis-text);
    overflow-wrap: anywhere;
}


/* Header — icône + titre + sous-titre, pas de carte */
.isis-form-linear__header {
    display: flex;
    align-items: center;
    gap: 0.85rem;
    margin-bottom: 1.5rem;
}
.isis-form-linear__header-icon {
    width: 44px;
    height: 44px;
    border-radius: 10px;
    background: var(--isis-mod-gescom-soft);
    color: var(--isis-mod-gescom);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}
.isis-form-linear__header h1 {
    font-size: 1.5rem;
    font-weight: 600;
    letter-spacing: -0.01em;
    line-height: 1.2;
    margin: 0;
    color: var(--isis-text);
}
.isis-form-linear__header-subtitle {
    font-size: 0.85rem;
    color: var(--isis-text-muted);
    margin-top: 0.15rem;
}

/* Section — titre, séparé par trait subtil (densifié) */
.isis-form-linear__section {
    margin-bottom: 1.5rem;
}
.isis-form-linear__section:last-of-type {
    margin-bottom: 1rem;
}
/* Synthèse marge — bloc financier de tête de l'onglet Finances (fond teinté module). */
.isis-marge-synthese {
    background: linear-gradient(180deg, color-mix(in srgb, var(--isis-current-mod) 6%, transparent), transparent);
    border-radius: var(--isis-radius);
    padding: 0.6rem 0.8rem;
}
.isis-form-linear__checkbox-row {
    display: flex;
    align-items: center;
    gap: var(--isis-space-2, 0.5rem);
}
.isis-form-linear__checkbox-row--top {
    align-items: flex-start;
}
.isis-form-linear__checkbox-label {
    margin: 0;
    cursor: pointer;
}
.isis-form-linear__section-title {
    font-size: 1rem;
    font-weight: 600;
    letter-spacing: -0.005em;
    color: var(--isis-text);
    /* Sans effet quand le titre est un <div> (aucune marge par défaut), indispensable
       dès qu'il est un vrai <h2> : le thème n'a pas de reset d'en-têtes, la marge haute
       du navigateur casserait alors le rythme vertical de la section. */
    margin-top: 0;
    margin-bottom: 0.85rem;
    padding-bottom: 0.45rem;
    border-bottom: 1px solid var(--isis-border);
    position: relative;
}
/* Dans un panneau d'onglet, le titre de section reste sous l'onglet dans la hiérarchie :
   même corps que .isis-tab / .isis-subtab (13 px), le gras et le filet suffisent à le
   distinguer. Hors onglets (formulaires pleine page), il garde son 1rem. */
.isis-tab-panel .isis-form-linear__section-title {
    font-size: 0.8125rem;
}
.isis-form-linear__section-title::before {
    content: "";
    position: absolute;
    left: 0;
    bottom: -1px;
    width: 36px;
    height: 2px;
    /* Trait de section coloré au module courant (propagé via .isis-shell__content.mod-X).
       Fallback accent global si --isis-current-mod n'est pas défini (cas dialog
       qui ne reçoit pas le shell parent). Audit 2026-05-19 — était hardcodé gescom. */
    background: var(--isis-current-mod, var(--isis-accent));
}

/* Section-title hint (« optionnel », « obligatoire »…) — petit complément
   typographique pour distinguer les sections requises des optionnelles. */
.isis-form-linear__section-hint {
    font-size: 0.78rem;
    font-weight: 400;
    color: var(--isis-text-muted);
    margin-left: 0.4rem;
    letter-spacing: 0;
}

/* Section repliable (<details>/<summary> natif — ex. bloc « Compléments » du formulaire
   commande, polish hauteur 2026-07-28). Réutilise .isis-form-linear__section-title pour le
   même poids visuel qu'un titre de section fixe ; ajoute juste le triangle de disclosure.
   Accessible nativement au clavier (Entrée/Espace sur le <summary> focusable) sans JS. */
.isis-form-linear__section-title--toggle {
    cursor: pointer;
    list-style: none;
    display: flex;
    align-items: center;
    user-select: none;
}
.isis-form-linear__section-title--toggle::-webkit-details-marker { display: none; }
.isis-form-linear__section-title--toggle::marker { display: none; }
.isis-form-linear__section-title--toggle::after {
    content: "";
    display: inline-block;
    width: 0.4em;
    height: 0.4em;
    margin-left: 0.5rem;
    border-right: 1.5px solid currentColor;
    border-bottom: 1.5px solid currentColor;
    transform: rotate(45deg);
    transition: transform var(--isis-motion-fast, 150ms ease);
    opacity: 0.6;
}
details[open] > .isis-form-linear__section-title--toggle::after {
    transform: rotate(-135deg);
}
.isis-form-linear__section-title--toggle:focus-visible {
    outline: 2px solid var(--isis-current-mod, var(--isis-accent));
    outline-offset: 3px;
    border-radius: 3px;
}
/* Variante <button> du même disclosure : à utiliser quand l'état d'ouverture est piloté
   et mémorisé côté composant. <details> ne convient pas dans ce cas — reposer sa valeur
   depuis C# mute l'attribut natif, le navigateur émet alors un `toggle` que rien ne
   distingue d'un clic, et l'état oscille. Reset des styles UA du bouton uniquement : la
   taille, la graisse, le filet et le trait de module viennent de .isis-form-linear__section-title. */
button.isis-form-linear__section-title--toggle {
    width: 100%;
    padding: 0 0 0.45rem;
    border: 0;
    border-bottom: 1px solid var(--isis-border);
    background: none;
    color: inherit;
    font-family: inherit;
    text-align: left;
}
.isis-form-linear__section-title--toggle[aria-expanded="false"]::after {
    transform: rotate(45deg);
}
.isis-form-linear__section-title--toggle[aria-expanded="true"]::after {
    transform: rotate(-135deg);
}
/* Le chevron reste à droite quel que soit l'état : c'est la poignée de repli, un indice
   permanent — s'il se déplaçait entre déployé et replié, on ne saurait plus où viser. */
button.isis-form-linear__section-title--toggle > span:first-child {
    margin-right: auto;
}

/* Picker + bouton "+" inline pour création à la volée d'une valeur référentiel.
   Pattern : <div class="isis-form-linear__inline-add">
                <RadzenDropDown ... />
                <button class="isis-form-linear__inline-add-btn">+</button>
             </div>
   Ajouté 2026-05-19 pour gesmat (types/marques/modèles création inline). */
.isis-form-linear__inline-add {
    display: flex;
    align-items: stretch;
    gap: 0.4rem;
}
.isis-form-linear__inline-add > :first-child {
    flex: 1;
    min-width: 0;
}
.isis-form-linear__inline-add-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    flex-shrink: 0;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius);
    color: var(--isis-current-mod, var(--isis-accent));
    cursor: pointer;
    transition: background-color 120ms ease, border-color 120ms ease;
}
.isis-form-linear__inline-add-btn:hover:not(:disabled) {
    background: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 8%, white);
    border-color: var(--isis-current-mod, var(--isis-accent));
}
.isis-form-linear__inline-add-btn:focus-visible {
    outline: 2px solid var(--isis-current-mod, var(--isis-accent));
    outline-offset: 2px;
}
.isis-form-linear__inline-add-btn:disabled {
    opacity: 0.4;
    cursor: not-allowed;
}

/* Flash visuel auto-fill : signale à l'user qu'un dropdown a été pré-rempli par
   cascade (typiquement EquipementFormDialog quand on choisit un modèle qui
   auto-remplit type/catégorie/marque). Animation 1.4s, fond couleur module
   soft puis fade out. Audit ui-ux 2026-05-19 bloquant#1. */
@keyframes isis-autofill-pulse {
    0%   { background-color: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 14%, white); }
    60%  { background-color: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 14%, white); }
    100% { background-color: transparent; }
}
.isis-autofill-flash .rz-dropdown {
    animation: isis-autofill-pulse 1.4s ease forwards;
    border-radius: var(--isis-radius);
}

/* Switch densifié : switch + hint sur la même ligne. */
.isis-form-linear__switch-wrap {
    display: flex;
    align-items: flex-start;
    gap: 0.6rem;
}
.isis-form-linear__switch-hint {
    font-size: 0.72rem;
    color: var(--isis-text-muted);
    line-height: 1.4;
    padding-top: 0.2rem;
    flex: 1;
}
/* Hint sous un champ (descriptif court). */
.isis-form-linear__field-hint {
    display: block;
    font-size: 0.72rem;
    color: var(--isis-text-muted);
    margin-top: 0.2rem;
    line-height: 1.4;
}
/* Motif de figement des jalons d'une affaire (AffaireJalonsPanel). */
.isis-jalons-fige {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    margin: 0 0 0.75rem;
    font-size: 0.85rem;
    color: var(--isis-text-muted);
}
.isis-jalons-fige .rzi { font-size: 14px; }
/* Variantes de hint avec icône (état géolocalisation, etc.) — évite les styles inline. */
.isis-form-linear__field-hint--ok,
.isis-form-linear__field-hint--warn {
    display: flex;
    align-items: center;
    gap: 0.4rem;
}
.isis-form-linear__field-hint--warn {
    color: var(--isis-warning);
}
.isis-form-linear__field-hint--error {
    display: block;
    color: var(--isis-danger, #a51b1b);
    font-size: 0.72rem;
    margin-top: 0.2rem;
    line-height: 1.4;
}
/* Convention générique d'aide de champ (chantier aide harmonisée) : une phrase sous un champ,
   reliée par aria-describedby="<id>" — jamais un roman. Pas de portée .isis-form-linear : utilisable
   partout, contrairement à .isis-form-linear__field-hint ci-dessus qui reste réservé à ce patron. */
.isis-field-help {
    display: block;
    margin-top: var(--isis-space-xs);
    color: var(--isis-text-muted);
    font-size: var(--isis-fs-sm);
}
/* Rangée action alignée en bas (champ statut + bouton), ex. bloc géolocalisation. */
.isis-form-linear__row--actions-end {
    align-items: flex-end;
    margin-top: 0.5rem;
}
/* Largeur contrainte pour les petits dialogs form-linear (évite le max-width inline). */
.isis-form-linear--w560 {
    max-width: 560px;
}

/* Field — label au-dessus, input en dessous, helper (densifié) */
.isis-form-linear .field {
    margin-bottom: 0.75rem;
}
/* Message d'erreur d'UN champ, sous le champ. Texte nu et non encadré rouge :
   `.isis-form-linear__error` est un bandeau de formulaire — le reprendre ici entasserait
   une boîte pleine sous chaque champ, et son couple danger/danger-soft ne tient que
   4,35:1 en sombre, sous le seuil AA pour du texte de 13 px. Le texte seul sur la surface
   du dialogue tient 6,5:1 en clair. */
.isis-form-linear .field-error {
    margin-top: 0.3rem;
    font-size: 0.78rem;
    line-height: 1.4;
    color: var(--isis-danger);
}
/* En sombre, --isis-danger (#e5534b) tombe à 4,50:1 sur la surface du dialogue : pile sur
   le seuil, sans marge pour un tenant white-label dont la surface dériverait. Éclairci
   VERS l'encre du thème — donc toujours par les tokens, jamais par un hex posé là —, il
   remonte à 5,6:1 en restant franchement rouge. */
:root[data-theme="dark"] .isis-form-linear .field-error {
    color: color-mix(in srgb, var(--isis-danger) 78%, var(--isis-text));
}
.isis-form-linear .field-row {
    display: grid;
    gap: 0.75rem;
    margin-bottom: 0;
}
.isis-form-linear .field-row > .field {
    margin-bottom: 0.75rem;
}
.isis-form-linear .field-row.cols-4-8 { grid-template-columns: 4fr 8fr; }
.isis-form-linear .field-row.cols-8-4 { grid-template-columns: 8fr 4fr; }
.isis-form-linear .field-row.cols-3-9 { grid-template-columns: 3fr 9fr; }
.isis-form-linear .field-row.cols-3 { grid-template-columns: 1fr 1fr 1fr; }
.isis-form-linear .field-row.cols-4 { grid-template-columns: 1fr 1fr 1fr 1fr; }
.isis-form-linear .field-row.cols-2 { grid-template-columns: 1fr 1fr; }
/* Un champ de la paire est conditionnel (ex. Interlocuteur du client visible seulement si un
   client est choisi) et disparaît complètement du DOM plutôt que d'être masqué : le champ
   restant reprend toute la largeur au lieu de laisser une colonne vide à droite (polish
   hauteur formulaire commande, 2026-07-28). */
.isis-form-linear .field-row > .field:only-child {
    grid-column: 1 / -1;
}

/* Repli responsive (polish hauteur formulaire commande, 2026-07-28) : au-delà des dialogs
   larges (780px) sur viewport étroit, deux champs côte à côte deviennent illisibles — repli
   1 colonne. Seuil aligné sur les autres grilles de ce fichier qui font le même repli
   (.isis-totals-grid, .isis-temps-selector, .isis-fmt-tokens → 720px). */
@media (max-width: 720px) {
    .isis-form-linear .field-row.cols-2,
    .isis-form-linear .field-row.cols-3,
    .isis-form-linear .field-row.cols-4,
    .isis-form-linear .field-row.cols-4-8,
    .isis-form-linear .field-row.cols-8-4,
    .isis-form-linear .field-row.cols-3-9 {
        grid-template-columns: 1fr;
    }
}

.isis-form-linear .label {
    display: block;
    font-size: 0.72rem;
    font-weight: 500;
    color: var(--isis-text-muted);
    margin-bottom: 0.25rem;
    letter-spacing: 0.01em;
}
.isis-form-linear .label .required {
    color: var(--rz-danger, #dc2626);
    margin-left: 2px;
}

/* Valeur figée (ex. « Porté par » en modification) : le texte seul, sans chrome de contrôle —
   un RadzenDropDown Disabled inviterait encore le clic sur un champ que rien ne fait bouger. */
.isis-form-linear .field-static-value {
    font-size: 0.85rem;
    color: var(--isis-text);
    padding: 0.35rem 0;
}

.isis-form-linear .helper {
    font-size: 0.7rem;
    color: var(--isis-text-soft);
    margin-top: 0.2rem;
    line-height: 1.35;
}
.isis-form-linear .error {
    font-size: 0.7rem;
    color: var(--rz-danger, #dc2626);
    margin-top: 0.2rem;
}

/* Compteur de caractères d'un champ borné. aria-hidden côté markup : maxlength est déjà exposé
   aux technologies d'assistance, et un compteur en région live annoncerait chaque frappe.
   .is-near passe en teinte d'alerte dans les 10 derniers pour cent. */
.isis-field-count {
    display: block;
    text-align: right;
    font-size: 0.7rem;
    color: var(--isis-text-soft);
    margin-top: 0.2rem;
    font-variant-numeric: tabular-nums;
}
.isis-field-count.is-near {
    color: var(--isis-warning-text);
    font-weight: 600;
}

/* Étiquette inline compacte devant un contrôle isolé HORS formulaire (ex. sélecteur de date
   d'un geste ponctuel dans une barre d'action) — même gabarit visuel que .isis-form-linear
   .label, sans dépendre du conteneur de formulaire (polish P2, gesqhse documentaire : un
   champ date nu à côté d'un bouton n'annonçait pas ce qu'il pilotait). */
.isis-inline-label {
    font-size: 0.72rem;
    font-weight: 500;
    color: var(--isis-text-muted);
    white-space: nowrap;
}

/* Ligne dédiée de confirmation du fichier sélectionné dans un champ d'upload — la
   confirmation la plus importante d'un dialogue de dépôt ne doit pas être concaténée dans
   la phrase de contrainte (polish P2, DocumentIndiceDialog). */
.isis-file-selected {
    display: flex;
    align-items: center;
    gap: 0.35rem;
    margin-top: 0.3rem;
    font-size: 0.78rem;
    color: var(--isis-success);
}

/* Inputs (RadzenTextBox / RadzenDropDown / RadzenTextArea) — fond blanc encadré + underline accent au focus. */
.isis-form-linear .rz-textbox,
.isis-form-linear .rz-textarea,
.isis-form-linear .rz-dropdown,
.isis-form-linear .rz-numeric,
/* Datepicker et multiselect manquaient à l'appel : ils gardaient donc la bordure pleine
   de la règle globale (« Harmonisation 2026-07-04 ») au lieu du liseré doux + bas marqué
   des autres champs — des cadres nettement plus lourds que le reste du formulaire, à
   structure pourtant identique (cf. TiersFormDialog, la référence). Le multiselect est
   le rendu d'un RadzenDropDown Multiple : 15 dialogues concernés. */
.isis-form-linear .rz-datepicker,
.isis-form-linear .rz-multiselect,
.isis-form-linear input[type="text"],
.isis-form-linear input[type="email"],
.isis-form-linear input[type="tel"],
.isis-form-linear textarea {
    width: 100% !important;
    font-family: inherit !important;
    font-size: 0.9rem !important;
    color: var(--isis-text) !important;
    /* Fond blanc et contour plein depuis le 2026-10-07 (le gris `--isis-surface-alt` se
       lisait comme un champ inerte). Le contour doux ne tenait que sur ce gris : sur blanc
       il disparaissait, d'où `--isis-border` sur les quatre côtés. */
    background: var(--isis-surface) !important;
    border: 1px solid var(--isis-border) !important;
    border-radius: 6px !important;
    padding: 0.35rem 0.65rem !important;
    box-shadow: none !important;
    outline: none !important;
    height: auto !important;
    min-height: 0 !important;
    transition: background-color 150ms ease, border-color 150ms ease !important;
}
.isis-form-linear .rz-textarea,
.isis-form-linear textarea {
    resize: vertical;
    line-height: 1.45;
}
/* Les composants Radzen composés (numeric, dropdown, datepicker) sont un CONTENEUR
   qui enveloppe un input. La règle ci-dessus vise à la fois le conteneur (.rz-numeric)
   et input[type="text"] — or l'input interne EST un type="text". Résultat : bordure,
   rayon et soulignement peints DEUX FOIS, d'où deux rectangles concentriques.
   L'enveloppe garde l'habillage, le champ interne redevient transparent. */
.isis-form-linear .rz-numeric > input,
.isis-form-linear .rz-dropdown input,
.isis-form-linear .rz-datepicker input,
.isis-form-linear .rz-spinner > input,
.isis-form-linear .rz-numeric > input {
    border: none !important;
    border-radius: 0 !important;
    background: transparent !important;
    padding-left: 0 !important;
    padding-right: 0 !important;
}

.isis-form-linear .rz-textbox::placeholder,
.isis-form-linear .rz-textarea::placeholder,
.isis-form-linear input::placeholder,
.isis-form-linear textarea::placeholder {
    color: var(--isis-text-soft);
    opacity: 1;
}
.isis-form-linear .rz-textbox:hover:not(:focus),
.isis-form-linear .rz-textarea:hover:not(:focus),
.isis-form-linear .rz-dropdown:hover:not(.rz-state-focused),
.isis-form-linear input:hover:not(:focus),
.isis-form-linear textarea:hover:not(:focus) {
    /* Survol : le contour fonce, le fond reste blanc (un fond teinté au survol relisait
       le champ comme inerte). */
    background: var(--isis-surface) !important;
    border-color: var(--isis-border-strong) !important;
}
.isis-form-linear .rz-textbox:focus,
.isis-form-linear .rz-textarea:focus,
.isis-form-linear .rz-dropdown.rz-state-focused,
.isis-form-linear .rz-numeric:focus-within,
.isis-form-linear input:focus,
.isis-form-linear textarea:focus {
    background: var(--isis-surface) !important;
    border-color: var(--isis-border) !important;
    /* Le défaut global pose un halo box-shadow au focus ; on le neutralise ici pour
       préserver le look « soulignement pur » de form-linear (même spécificité → on gagne
       par !important + ordre source, mais on l'écrit explicitement pour robustesse). */
    box-shadow: none !important;
    /* F9 — underline focus à la couleur du module courant. */
    border-bottom-color: var(--isis-current-mod, var(--isis-accent)) !important;
    border-bottom-width: 2px !important;
    padding-bottom: calc(0.35rem - 1px) !important;
}

/* RadzenTextArea — toujours pleine largeur (toutes pages, hors et dans .isis-form-linear).
   Radzen rend `<textarea class="rz-textarea">` ; le wrapper `.rz-textarea-wrapper` doit
   aussi être étendu sinon le textarea reste contraint à la largeur native (~150px). */
.rz-textarea,
.rz-textarea-wrapper {
    width: 100% !important;
    box-sizing: border-box;
}

/* RadzenDropDown — même affordance que les inputs. Radzen 11 le pose en
   `flex-direction: column` : le centrage vertical se fait donc sur l'axe principal.
   Un `align-items: center` y centrait le libellé HORIZONTALEMENT, réduit à la largeur
   de son texte — la valeur flottait au milieu et un libellé long passait sous la flèche. */
.isis-form-linear .rz-dropdown {
    display: flex;
    justify-content: center;
}
.isis-form-linear .rz-dropdown .rz-inputtext {
    background: transparent !important;
    border: none !important;
    padding: 0 !important;
}

/* SelectBar (Type de compte) — segmented control sobre */
.isis-form-linear .rz-selectbutton {
    display: inline-flex;
    background: var(--isis-surface-alt);
    border-radius: 8px;
    padding: 3px;
    gap: 2px;
    border: none !important;
}
.isis-form-linear .rz-selectbutton .rz-button {
    border: none !important;
    background: transparent !important;
    color: var(--isis-text-muted) !important;
    border-radius: 6px !important;
    padding: 0.45rem 0.95rem !important;
    font-size: 0.82rem !important;
    font-weight: 400 !important;
    height: auto !important;
    box-shadow: none !important;
    transition: background-color 150ms, color 150ms;
}
.isis-form-linear .rz-selectbutton .rz-button:hover {
    color: var(--isis-text) !important;
    background: transparent !important;
}
.isis-form-linear .rz-selectbutton .rz-button.rz-state-active,
.isis-form-linear .rz-selectbutton .rz-button.rz-selected {
    background: var(--isis-surface) !important;
    color: var(--isis-text) !important;
    font-weight: 500 !important;
}

/* Actions footer — trait haut + alignement droite */
.isis-form-linear__actions {
    display: flex;
    justify-content: flex-end;
    gap: 0.5rem;
    padding-top: 1.5rem;
    border-top: 1px solid var(--isis-border-soft, #f1f2f5);
    margin-top: 2rem;
}
.isis-form-linear__actions .rz-button,
.isis-form-linear__actions .rz-splitbutton .rz-button {
    border-radius: 7px !important;
    padding: 0.4rem 0.85rem !important;
    font-size: 0.8rem !important;
    font-weight: 500 !important;
    box-shadow: none !important;
    min-height: 0 !important;
    height: auto !important;
}
.isis-form-linear__actions .rz-button .rzi {
    font-size: 14px !important;
}
/* Actions sans divider ni padding — un seul bouton posé directement sous un texte
   de section (pas un vrai formulaire au-dessus), ex. bascule DSL/CODE. Le filet +
   2rem de la base sont pensés pour clore un formulaire ; ici ils ne font que
   simuler un pied de formulaire qui n'existe pas. */
.isis-form-linear__actions--tight {
    padding: 0;
    margin-top: 0.75rem;
    border-top: none;
}

/* Alert d'erreur — sobre */
.isis-form-linear .rz-alert {
    border-radius: 10px;
    border: none;
    margin-bottom: 1rem;
}

/* Alertes des lots (panneau et ses fenêtres, rendues hors du panneau) : même correctif de contraste
   que master-shell.css (.isis-tenant-fiche). La correction globale des alertes reste une dette à part. */
.isis-op-lots .rz-alert.rz-shade-lighter.rz-info    { --isis-alerte-encre: var(--isis-info-text);    --isis-alerte-fond: var(--isis-info-soft); }
.isis-op-lots .rz-alert.rz-shade-lighter.rz-success { --isis-alerte-encre: var(--isis-success-text); --isis-alerte-fond: var(--isis-success-soft); }
.isis-op-lots .rz-alert.rz-shade-lighter.rz-warning { --isis-alerte-encre: var(--isis-warning-text); --isis-alerte-fond: var(--isis-warning-soft); }
.isis-op-lots .rz-alert.rz-shade-lighter.rz-danger  { --isis-alerte-encre: var(--isis-danger-text);  --isis-alerte-fond: var(--isis-danger-soft); }
.isis-op-lots .rz-alert.rz-shade-lighter:is(.rz-info, .rz-success, .rz-warning, .rz-danger) {
    --rz-alert-background-color: var(--isis-alerte-fond);
    --rz-alert-color: var(--isis-alerte-encre);
    --rz-alert-title-color: var(--isis-alerte-encre);
    --rz-alert-icon-color: var(--isis-alerte-encre);
}

/* Modifier dialog — le dialog Radzen gère le titre + padding extérieur, on
   neutralise le chrome page (max-width / padding container / margins lourds)
   et on compacte verticalement. À combiner : <div class="isis-form-linear isis-form-linear--dialog"> */
.isis-form-linear--dialog {
    max-width: none;
    margin: 0;
    padding: 0;
}
.isis-form-linear--dialog .isis-form-linear__section {
    margin-bottom: 1.1rem;
}
.isis-form-linear--dialog .isis-form-linear__section:last-of-type {
    margin-bottom: 0.5rem;
}
.isis-form-linear--dialog .isis-form-linear__actions {
    padding-top: 1rem;
    margin-top: 1.25rem;
}

/* Mini-calculateur PU à partir du coût (Phase 2 réconciliation coût/prix).
   Layout compact dans un dialog 480px. Le bloc .isis-pricing-calc__result
   affiche les valeurs en grille label/valeur tabulaire.                       */
.isis-pricing-calc__readonly {
    padding: 0.4rem 0.6rem;
    background: var(--isis-surface-soft);
    border: 1px solid var(--isis-border, var(--isis-border));
    border-radius: 4px;
    font-variant-numeric: tabular-nums;
    font-weight: 500;
    color: var(--isis-text, #1f2328);
}
.isis-pricing-calc__result {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
    padding: 0.65rem 0.85rem;
    background: var(--isis-surface-soft);
    border-radius: 6px;
    border: 1px solid color-mix(in srgb, var(--isis-accent) 32%, var(--isis-border));
}
.isis-pricing-calc__row {
    display: flex;
    justify-content: space-between;
    font-size: 0.82rem;
    font-variant-numeric: tabular-nums;
}
.isis-pricing-calc__row--effective {
    margin-top: 0.4rem;
    padding-top: 0.4rem;
    border-top: 1px solid var(--isis-border, var(--isis-border));
    font-size: 0.9rem;
}
.isis-pricing-calc__pct.is-on-target    { color: var(--isis-success, #16a34a); }
.isis-pricing-calc__pct.is-below-target { color: var(--isis-warning, #d97706); }
.isis-pricing-calc__pct.is-below-floor  { color: var(--isis-danger,  #c62828); }
.isis-pricing-calc__pct.is-no-cost,
.isis-pricing-calc__pct.is-unclassified { color: var(--isis-text, #1f2328); }
.isis-pricing-calc__dernier { margin-top: 0.5rem; }
.isis-pricing-calc__status {
    margin-left: 0.4rem;
    font-size: 0.78rem;
    font-weight: 500;
    opacity: 0.85;
}
.isis-rich-toolbar__btn--ghost {
    background: transparent;
    border: 1px dashed var(--isis-border, var(--isis-border-strong));
    color: var(--isis-text-muted, #475569);
}
.isis-rich-toolbar__btn--ghost:hover:not(:disabled) {
    background: var(--isis-surface-soft);
    color: var(--isis-text, #1f2328);
}

/* ============================================================================
   .isis-audit-trail — timeline d'activité d'un enregistrement
   ----------------------------------------------------------------------------
   Affichée dans le panneau latéral droit des listes (mode compact, 5 items)
   ou dans un dialog/onglet "Activité" (mode full).
   ============================================================================ */
.isis-audit-trail {
    display: flex;
    flex-direction: column;
    gap: 0;
    /* Le composant est rendu tantôt en <div>, tantôt en <ol>/<ul> (journaux
       marché / AO / demande / engagement) : sans ce reset la liste hérite du
       padding-inline-start de 40px du navigateur et le journal se décale du
       titre de son bloc. */
    list-style: none;
    margin: 0;
    padding: 0;
}
.isis-audit-trail__content {
    display: flex;
    flex-direction: column;
    gap: 0.1rem;
    min-width: 0;
    overflow-wrap: anywhere;
}
.isis-audit-trail__type {
    font-size: 0.82rem;
    font-weight: 600;
    color: var(--isis-text);
    line-height: 1.3;
}
.isis-audit-trail__detail {
    margin-left: 0.4rem;
    font-family: var(--isis-font-mono);
    font-size: 0.7rem;
    color: var(--isis-text-muted);
    white-space: nowrap;
}
.isis-audit-trail__loading,
.isis-audit-trail__empty {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.75rem 0;
    color: var(--isis-text-muted);
    font-size: 0.78rem;
}
.isis-audit-trail__empty .rzi {
    font-size: 18px;
    opacity: 0.55;
}
.isis-audit-trail__item {
    display: flex;
    gap: 0.65rem;
    padding: 0.55rem 0;
    border-bottom: 1px solid var(--isis-border-soft, #f1f2f5);
}
.isis-audit-trail__item:last-child {
    border-bottom: none;
}

/* Item de timeline issu d'une cascade automatique (cf. SourceGainCascadeMarkers).
   Filet périmétrique teinté gescom (la cascade vient toujours d'un devis) + fond
   très légèrement teinté pour distinguer du flux manuel. Ex-liseré gauche 2px,
   converti le 2026-07-18 : le fond teinté et le badge « auto » portent déjà le
   signal, le trait vertical était redondant. */
.isis-audit-trail__item.is-cascade {
    box-sizing: border-box;
    border: 1px solid color-mix(in srgb, var(--isis-mod-gescom) 32%, transparent);
    padding-left: 0.5rem;
    background: color-mix(in srgb, var(--isis-mod-gescom) 4%, transparent);
    border-radius: 4px;
}

/* Badge inline « auto » à côté du type d'event sur les transitions cascade. */
.isis-audit-trail__badge {
    display: inline-block;
    margin-left: 0.4rem;
    padding: 0.05rem 0.4rem;
    border-radius: 8px;
    background: color-mix(in srgb, var(--isis-mod-gescom) 14%, transparent);
    color: var(--isis-mod-gescom);
    font-size: 0.7rem;
    font-weight: 600;
    letter-spacing: 0.02em;
    text-transform: uppercase;
    vertical-align: middle;
}
.isis-audit-trail__dot {
    width: 26px;
    height: 26px;
    border-radius: 50%;
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
.isis-audit-trail__dot .rzi {
    font-size: 15px;
}
.isis-audit-trail__dot.op-I { background: #e8f5e9; color: #2e7d32; }
.isis-audit-trail__dot.op-U { background: #e3f2fd; color: #1565c0; }
.isis-audit-trail__dot.op-D { background: #ffebee; color: #c62828; }
.isis-audit-trail__dot.ged-evt-upload   { background: #ecfdf5; color: #047857; }
.isis-audit-trail__dot.ged-evt-version  { background: #eef2ff; color: #4338ca; }
.isis-audit-trail__dot.ged-evt-download { background: #f1f5f9; color: #475569; }
.isis-audit-trail__dot.ged-evt-view     { background: #fef3c7; color: #92400e; }
/* Workflow devis — pastilles d'événement (cf. gescom_devis_workflow_event) */
.isis-audit-trail__dot.devis-wf-evt-created              { background: #f1f5f9; color: #475569; }
.isis-audit-trail__dot.devis-wf-evt-submitted            { background: #eef2ff; color: #4338ca; }
.isis-audit-trail__dot.devis-wf-evt-approved_auto        { background: #ecfdf5; color: #047857; }
.isis-audit-trail__dot.devis-wf-evt-approval_granted     { background: #ecfdf5; color: #047857; }
.isis-audit-trail__dot.devis-wf-evt-approved             { background: #dcfce7; color: #15803d; }
.isis-audit-trail__dot.devis-wf-evt-approval_rejected    { background: #fef2f2; color: #a51b1b; }
.isis-audit-trail__dot.devis-wf-evt-approval_invalidated { background: #fef3c7; color: #92400e; }
.isis-audit-trail__dot.devis-wf-evt-sent                 { background: var(--isis-accent-soft); color: var(--isis-accent); }
.isis-audit-trail__dot.devis-wf-evt-accepted             { background: #dcfce7; color: #15803d; }
.isis-audit-trail__dot.devis-wf-evt-rejected             { background: #fef2f2; color: #a51b1b; }
.isis-audit-trail__dot.devis-wf-evt-expired              { background: #fef3c7; color: #92400e; }
.isis-audit-trail__dot.devis-wf-evt-cancelled            { background: #f1f5f9; color: #475569; }
.isis-audit-trail__dot.devis-wf-evt-revised              { background: #eef2ff; color: #4338ca; }
.isis-audit-trail__dot.devis-wf-evt-converted            { background: #dcfce7; color: #15803d; }
.isis-audit-trail__reason {
    font-size: 0.7rem;
    font-style: italic;
    color: var(--isis-text-muted);
    margin-top: 0.15rem;
    line-height: 1.3;
}
/* Fil unifié d'une affaire (EF-21) : en-tête titre + filtre, message de commentaire. */
.isis-fil__entete {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    margin-bottom: 0.5rem;
}
/* Fil seul dans son onglet (fiche Opportunité) : aucun bloc au-dessus à séparer. */
.isis-workflow-history.is-premier {
    margin-top: 0;
    padding-top: 0;
    border-top: 0;
}
.isis-fil__message {
    margin-top: 0.25rem;
    font-size: 0.8rem;
    color: var(--isis-text);
    white-space: pre-wrap;
    overflow-wrap: anywhere;
    line-height: 1.4;
}
/* Variante "motif" plus visible : encadré + label */
.isis-audit-trail__reason--motif {
    display: flex;
    gap: 0.5rem;
    align-items: flex-start;
    margin-top: 0.35rem;
    padding: 0.35rem 0.55rem;
    background: color-mix(in srgb, var(--isis-warning) 8%, white);
    border: 1px solid var(--isis-warning);
    box-sizing: border-box;
    border-radius: 3px;
    font-style: normal;
    color: var(--isis-text);
    font-size: 0.78rem;
}
.isis-audit-trail__reason-label {
    flex-shrink: 0;
    font-size: 0.65rem;
    font-weight: 700;
    color: var(--isis-warning);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    padding-top: 0.1rem;
}
.isis-audit-trail__reason-text {
    flex: 1;
    min-width: 0;
    line-height: 1.4;
    word-wrap: break-word;
}
.isis-audit-trail__body {
    flex: 1;
    min-width: 0;
}
.isis-audit-trail__line {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.5rem;
}
.isis-audit-trail__user {
    font-size: 0.8rem;
    font-weight: 500;
    color: var(--isis-text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.isis-audit-trail__time {
    font-size: 0.7rem;
    color: var(--isis-text-muted);
    white-space: nowrap;
    flex-shrink: 0;
}
.isis-audit-trail__what {
    font-size: 0.72rem;
    color: var(--isis-text-soft);
    margin-top: 0.1rem;
    line-height: 1.35;
}
.isis-audit-trail__cols {
    font-style: italic;
}
.isis-audit-trail__more {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    margin-top: 0.6rem;
    padding: 0.3rem 0.55rem;
    background: transparent;
    border: 1px solid var(--isis-border);
    border-radius: 6px;
    font-size: 0.72rem;
    color: var(--isis-text);
    cursor: pointer;
    align-self: flex-start;
}
.isis-audit-trail__more:hover {
    background: var(--isis-surface-soft);
}
.isis-audit-trail__more .rzi {
    font-size: 14px;
    opacity: 0.7;
}

/* ── Variante "row" : pastille (icône) à GAUCHE + corps (workflow commande/livraison).
   __row n'était pas en flex → la pastille s'empilait au-dessus du texte. ── */
.isis-audit-trail__row {
    display: flex;
    gap: 0.65rem;
    padding: 0.55rem 0;
    border-bottom: 1px solid var(--isis-border-soft, #f1f2f5);
}
.isis-audit-trail__row:last-child { border-bottom: none; }
.isis-audit-trail__head {
    display: flex;
    align-items: baseline;
    gap: 0.5rem;
}
.isis-audit-trail__label {
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--isis-text);
}
.isis-audit-trail__when {
    margin-left: auto;
    flex-shrink: 0;
    font-size: 0.74rem;
    color: var(--isis-text-muted);
    white-space: nowrap;
}
.isis-audit-trail__transition {
    font-size: 0.76rem;
    color: var(--isis-text-muted);
    margin-top: 0.1rem;
}
.isis-audit-trail__meta {
    font-size: 0.78rem;
    color: var(--isis-text-soft, var(--isis-text-muted));
    margin-top: 0.1rem;
}
.isis-audit-trail__note {
    margin-top: 0.4rem;
    font-size: 0.74rem;
    color: var(--isis-text-muted);
}

/* Mode compact (sidepanel) : police + pastille réduites, métadonnées resserrées. */
.isis-audit-trail--compact .isis-audit-trail__row { padding: 0.4rem 0; gap: 0.5rem; }
.isis-audit-trail--compact .isis-audit-trail__dot { width: 20px; height: 20px; }
.isis-audit-trail--compact .isis-audit-trail__dot .rzi { font-size: 12px; }
.isis-audit-trail--compact .isis-audit-trail__label { font-size: 0.76rem; }
.isis-audit-trail--compact .isis-audit-trail__when { font-size: 0.68rem; }
.isis-audit-trail--compact .isis-audit-trail__transition { font-size: 0.7rem; }
.isis-audit-trail--compact .isis-audit-trail__meta { font-size: 0.7rem; margin-top: 0.05rem; }
.isis-audit-trail--compact .isis-audit-trail__note { font-size: 0.68rem; margin-top: 0.3rem; }

/* Variante dialog plein écran : padding aéré */
.isis-audit-trail-dialog {
    /* Pas de padding propre : .rz-dialog-content en applique déjà 24px (sinon cumul). */
    padding: 0;
}

/* Tableau d'édition des taux dans le TaxTemplateFormDialog (mêmes styles que devis-items) */
.isis-tax-rates {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.78rem;
}
.isis-tax-rates thead th {
    text-align: left;
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    font-size: 0.65rem;
    color: var(--isis-text-muted);
    padding: 0.4rem 0.5rem;
    border-bottom: 1px solid var(--isis-border);
}
.isis-tax-rates tbody td {
    padding: 0.35rem 0.4rem;
    border-bottom: 1px solid var(--isis-border-soft, #f1f2f5);
    vertical-align: middle;
}
.isis-tax-rates tbody tr:hover { background: var(--isis-surface-soft); }

/* Conversion devise figée sur fiche détail devis (snapshot SEND) */
.isis-detail-summary__conversion {
    display: flex;
    align-items: flex-start;
    gap: 0.4rem;
    padding: 0.5rem 0.65rem;
    margin-top: 0.6rem;
    background: var(--isis-surface-soft);
    border-radius: 6px;
    font-size: 0.78rem;
    color: var(--isis-text);
    line-height: 1.4;
}
.isis-detail-summary__conversion strong {
    font-weight: 600;
}
.isis-detail-summary__conversion-meta {
    display: block;
    color: var(--isis-text-muted);
    font-size: 0.7rem;
    margin-top: 0.1rem;
}
.isis-detail-summary__conversion--warning {
    background: #fef3c7;
    color: #92400e;
}
.isis-detail-summary__conversion--warning .rzi {
    color: #d97706;
}

/* Modificateur « carte » — visuel symétrique au .isis-master-detail__master.
   Border + radius + bg + padding interne pour que le sidepanel se présente
   comme une seconde carte distincte de la grille (cf. DevisCounterListPage).
   Refonte 2026-05-29 : renommé de `.isis-detail-layout__side--card` (legacy)
   vers `.isis-master-detail__detail--card` pour cohérence avec le wrapper
   master-detail standard. */
.isis-master-detail__detail--card {
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius);
    padding: 0.85rem 1rem;
    overflow: hidden;
}
/* Cartes de la fiche devis — divs plats portant rz-card rz-variant-flat
   (visuel Radzen identique) + ces modificateurs (chaîne flex sous notre contrôle
   total — le composant RadzenCard a été retiré, son passthrough class/Style
   s'étant révélé non fiable). display:flex en !important : bat la règle .rz-card
   de Radzen quel que soit l'ordre de chargement des feuilles. */
.isis-detail-card--summary {
    flex-shrink: 0;
}
.isis-detail-card--tabs,
.isis-detail-card--list {
    flex: 1 1 auto;
    min-height: 0;
    display: flex !important;
    flex-direction: column;
}

/* Indication discrète d'un panneau latéral (listes AO / demandes client gesmaff). */
.isis-side-block__hint {
    margin-top: 0.5rem;
    font-size: 0.72rem;
    color: var(--isis-text-soft);
    font-style: italic;
}
.isis-share-list__row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.4rem;
}
.isis-share-list__remove {
    background: transparent;
    border: none;
    width: 20px; height: 20px;
    border-radius: 4px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--isis-text-soft);
    cursor: pointer;
}
.isis-share-list__remove:hover {
    background: #ffebee;
    color: #c62828;
}

/* Chaîne d'approbation : liste verticale style timeline */
.isis-approval-chain {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 0.55rem;
}
.isis-approval-chain__step {
    padding: 0.5rem 0.6rem;
    border-radius: 6px;
    background: var(--isis-surface-soft);
    border: 1px solid var(--isis-border);
    box-sizing: border-box;
}
.isis-approval-chain__step.is-pending  { border-left-color: #d97706; }
.isis-approval-chain__step.is-approved { border-left-color: #16a34a; }
.isis-approval-chain__step.is-rejected { border-left-color: #c62828; }
.isis-approval-chain__step.is-skipped  { border-left-color: var(--isis-text-soft); opacity: 0.6; }

.isis-approval-chain__head {
    display: flex;
    align-items: baseline;
    gap: 0.5rem;
    margin-bottom: 0.2rem;
}
.isis-approval-chain__level {
    font-size: 0.65rem;
    font-weight: 600;
    color: var(--isis-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.05em;
}
.isis-approval-chain__user {
    font-size: 0.82rem;
    font-weight: 500;
    color: var(--isis-text);
}
.isis-approval-chain__meta {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    font-size: 0.72rem;
}
.isis-approval-chain__date {
    color: var(--isis-text-muted);
}
.isis-approval-chain__comment {
    margin-top: 0.4rem;
    font-size: 0.72rem;
    color: var(--isis-text-soft);
    font-style: italic;
    line-height: 1.35;
}
.isis-approval-chain__reason {
    margin-top: 0.35rem;
    font-size: 0.7rem;
    color: var(--isis-text-muted);
    line-height: 1.35;
}
.isis-approval-chain__step.is-preview {
    border-color: var(--isis-mod-gescom);
    border-left-style: dashed;
    opacity: 0.95;
}

/* Liste de partages */
.isis-share-list {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}
.isis-share-list__item {
    padding: 0.4rem 0.55rem;
    border-radius: 6px;
    background: var(--isis-surface-soft);
}
.isis-share-list__user {
    font-size: 0.82rem;
    font-weight: 500;
    color: var(--isis-text);
}
.isis-share-list__rights {
    display: flex;
    gap: 0.3rem;
    margin-top: 0.2rem;
    flex-wrap: wrap;
}
.isis-share-list__tag {
    font-size: 0.68rem;
    padding: 0.1rem 0.45rem;
    border-radius: var(--isis-radius-pill);
    background: var(--isis-accent-soft);
    color: var(--isis-accent);
    font-weight: 500;
}
.isis-share-list__granted {
    margin-top: 0.3rem;
    font-size: 0.75rem;
    color: var(--isis-text-muted);
}

/* Contexte propriété du devis (Créé par / Propriétaire) en tête de la section Partages */
.isis-share-meta {
    margin: 0 0 0.6rem;
    padding: 0.5rem 0.55rem;
    background: var(--isis-surface-soft);
    border-radius: 6px;
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
}
.isis-share-meta__row {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.5rem;
}
.isis-share-meta dt {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    margin: 0;
    font-size: 0.7rem;
    color: var(--isis-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.03em;
    flex-shrink: 0;
}
.isis-share-meta dd {
    margin: 0;
    font-size: 0.8rem;
    font-weight: 500;
    color: var(--isis-text);
    text-align: right;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Suggestions d'interlocuteurs sur le dialog Partage (migration 0092). */
.isis-share-suggest {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.4rem;
    margin-bottom: 0.6rem;
}
.isis-share-suggest__label {
    font-size: 0.7rem;
    color: var(--isis-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.03em;
    margin-right: 0.2rem;
}
.isis-share-suggest__chip {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0.25rem 0.55rem;
    font-size: 0.74rem;
    color: var(--isis-text);
    background: var(--isis-surface-alt);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-pill);
    cursor: pointer;
    transition: background 0.15s ease, border-color 0.15s ease;
}
.isis-share-suggest__chip:hover {
    background: var(--isis-surface);
    border-color: var(--isis-mod-gescom);
}
.isis-share-suggest__chip.is-picked {
    background: var(--isis-mod-gescom-soft);
    border-color: var(--isis-mod-gescom);
    color: var(--isis-text);
}
.isis-share-suggest__chip-meta {
    color: var(--isis-text-muted);
    font-variant-numeric: tabular-nums;
    font-size: 0.66rem;
}

/* Ventilation TVA par taux sur fiche détail devis (Q4 : calcul à la volée) */
.isis-vat-summary {
    margin-top: 1rem;
    padding: 0.85rem 1rem;
    background: var(--isis-surface-soft);
    border-radius: 8px;
    /* Dans le panneau --footed : pied collé au bas, ne se comprime jamais. */
    flex-shrink: 0;
}
.isis-vat-summary__title {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-size: 0.7rem;
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--isis-text-muted);
    margin-bottom: 0.6rem;
}
.isis-vat-summary__exempt,
.isis-vat-summary__empty {
    font-size: 0.8rem;
    color: var(--isis-text-muted);
    font-style: italic;
}
.isis-vat-summary__table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.78rem;
}
.isis-vat-summary__table thead th {
    text-align: left;
    font-weight: 500;
    font-size: 0.65rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--isis-text-muted);
    padding: 0.3rem 0.4rem;
    border-bottom: 1px solid var(--isis-border);
}
.isis-vat-summary__table tbody td,
.isis-vat-summary__table tfoot td {
    padding: 0.3rem 0.4rem;
}
.isis-vat-summary__table tbody tr {
    border-bottom: 1px solid var(--isis-border-soft, #f1f2f5);
}
.isis-vat-summary__table tfoot td {
    border-top: 1px solid var(--isis-border);
    padding-top: 0.5rem;
}

/* Bloc Remise globale et totaux (onglet Lignes — lecture seule calque dialog).
   Layout 2 colonnes : remise (gauche, ratio 3) + totaux (droite, ratio 9).     */
.isis-totals-grid {
    display: grid;
    grid-template-columns: minmax(220px, 3fr) minmax(280px, 9fr);
    gap: 1.5rem;
    align-items: start;
}
.isis-totals-grid__discount {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
}
.isis-inline-edit {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    min-height: 32px;
}
.isis-inline-edit__value {
    font-variant-numeric: tabular-nums;
    font-weight: 500;
    color: var(--isis-text, #1f2328);
    font-size: 0.95rem;
}
@media (max-width: 720px) {
    .isis-totals-grid {
        grid-template-columns: 1fr;
        gap: 1rem;
    }
}

/* ============================================================================
   .isis-devis-items-dialog — layout du dialog d'édition des lignes
   ----------------------------------------------------------------------------
   Trois zones empilées en flex column sur toute la hauteur du dialog :
     1) lignes (scroll interne quand la liste s'allonge)
     2) footer sticky (boutons d'ajout + totaux + mode simu + actions)
   La chaîne flex impose `min-height: 0` sur chaque maillon (sans ça, le scroll
   interne ne se déclenche jamais et c'est le dialog entier qui scrolle).
   ============================================================================ */
/* La chaîne flex doit traverser .rz-dialog → .rz-dialog-content → wrapper
   interne. Les 2 classes ci-dessous sont appliquées via DialogOptions
   (CssClass + ContentCssClass) du caller — pas via :has(), qui matchait mais
   imposait un padding: 0 qui tuait les bordures latérales visuelles.
   Ne touche PAS au padding hérité du thème Radzen — préserve l'apparence. */
.rz-dialog.isis-dialog-flex {
    display: flex;
    flex-direction: column;
}
.rz-dialog.isis-dialog-flex > .rz-dialog-content {
    flex: 1 1 auto;
    min-height: 0;
}
.rz-dialog-content.isis-dialog-content-flex {
    display: flex;
    flex-direction: column;
    min-height: 0;
}
.isis-devis-items-dialog {
    display: flex;
    flex-direction: column;
    height: 100%;
    min-height: 0;
    gap: 0.75rem;
    /* Override du padding-bottom 2.5rem hérité d'isis-form-linear — le footer
       collé en bas porte sa propre marge. */
    padding-bottom: 0.5rem;
}

/* ── Coût de revient en dialog (calque structurel isis-devis-items-dialog) ── */
.isis-devis-costing-dialog {
    display: flex;
    flex-direction: column;
    height: 100%;
    min-height: 0;
    gap: 0.75rem;
    padding-bottom: 0.5rem;
}
.isis-devis-costing-dialog__scroll {
    flex: 1 1 auto;
    min-height: 0;
    overflow: auto;
    /* Préserve la marge interne du composant DevisCostingTab (gap entre sections). */
}
.isis-devis-costing-dialog__footer {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding-top: 0.5rem;
    border-top: 1px solid var(--isis-border);
}
.isis-devis-costing-dialog__footer-hint {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    color: var(--isis-text-muted);
    font-size: 0.8rem;
}
.isis-devis-items-dialog__lines {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    min-height: 0;
    overflow: hidden;
}
.isis-devis-items-dialog__lines-scroll {
    flex: 1 1 auto;
    min-height: 0;
    overflow: auto;
    border: 1px solid var(--isis-border);
    border-radius: 6px;
    background: var(--isis-surface);
}
.isis-devis-items-dialog__lines-scroll .isis-devis-items thead th {
    position: sticky;
    top: 0;
    z-index: 2;
    background: var(--isis-surface-alt);
}
.isis-devis-items-dialog__footer {
    flex: 0 0 auto;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    padding: 0.75rem 0 0;
    border-top: 1px solid var(--isis-border);
    background: var(--isis-surface);
}
/* `:last-of-type` dans le sélecteur (et non par gourmandise) : sans lui,
   `.isis-form-linear--dialog .isis-form-linear__section:last-of-type` (0,3,0) l'emporte
   et réinjecte 0.5rem sous les totaux — 8 px de vide en bas de l'onglet Lignes. */
.isis-devis-items-dialog__footer .isis-form-linear__section,
.isis-devis-items-dialog__footer .isis-form-linear__section:last-of-type {
    margin: 0;
}
/* Dernière rangée d'un formulaire : la gouttière de 0.75 rem sous chaque `.field` sépare
   deux rangées, il n'y en a pas ici — elle ne faisait que creuser le bas du panneau. */
.isis-devis-items-dialog__totals .field-row > .field {
    margin-bottom: 0;
}
.isis-devis-items-dialog__totals .isis-devis-totals {
    margin-top: 0;
}
/* Section repliable : replié, le titre porte le récapitulatif — replier ne coûte jamais
   la vue du Total TTC. */
.isis-devis-items-dialog__totals.is-collapsed > .isis-form-linear__section-title {
    margin-bottom: 0;
}
.isis-devis-items-dialog__totals.is-collapsed > .isis-devis-items-dialog__totals-body {
    display: none;
}
.isis-devis-items-dialog__totals-recap {
    display: inline-flex;
    align-items: baseline;
    gap: 0.75rem;
    font-weight: 400;
    font-size: 0.8125rem;
    color: var(--isis-text-muted);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.isis-devis-items-dialog__totals-recap strong {
    font-family: var(--isis-font-mono);
    font-weight: 600;
    color: var(--isis-text);
}

/* ── Hôte fusionné Lignes / Coût de revient (EF-116→120) ────────────────── */
.isis-devis-elaboration-dialog {
    display: flex;
    flex-direction: column;
    height: 100%;
    min-height: 0;
    gap: 0.75rem;
    padding-bottom: 0.5rem;
}
/* Compression de l'en-tête (2026-09-14, retour de recette) : l'indicateur d'enregistrement
   remonte sur la même ligne visuelle que le titre RadZen natif (.rz-dialog-titlebar), à
   gauche du bouton de fermeture natif — au lieu d'occuper sa propre ligne sous les onglets.
   .rz-dialog-titlebar est rendu par RadZen, HORS de ce composant, et n'est PAS un ancêtre DOM
   de ce header (ce sont deux enfants distincts de .rz-dialog) : le positionnement absolu se
   fait donc par rapport à .rz-dialog lui-même (déjà `position: absolute` nativement chez
   RadZen — inutile de le forcer ici, contrairement à .rz-dialog-titlebar qui, lui, n'est pas
   le conteneur de référence). Valeurs mesurées au navigateur (getBoundingClientRect, pas
   devinées) : padding de .rz-dialog-titlebar = 24px 24px 0, hauteur de sa zone de contenu =
   24px, bouton natif = 24×24px flush à droite → top/right/height ci-dessous en découlent.
   Ne cible JAMAIS .isis-dialog-flex/.isis-dialog-content-flex directement pour ce correctif
   (classes partagées avec GeoLayersSection.razor, cf. commentaire plus haut dans ce fichier) —
   .isis-devis-elaboration-dialog__header est en revanche une classe propre à cet unique
   composant, le sélecteur direct est donc sûr sans :has(). */
.isis-devis-elaboration-dialog__header {
    position: absolute;
    top: 24px;
    right: 58px;
    height: 24px;
    display: flex;
    align-items: center;
    gap: 8px;
}
/* .rz-dialog-title, lui, EST une classe partagée par tous les dialogues RadZen : le
   troncage réservé au statut d'enregistrement doit rester scopé à ce dialogue précis via
   :has(), sous peine de tronquer le titre de tous les autres dialogues du produit. */
.rz-dialog:has(.isis-devis-elaboration-dialog) .rz-dialog-title {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    /* Réserve la place du statut (~174px mesurés pour l'ex-"En attente de modification…" ;
       le plus long aujourd'hui, "Simulation : non enregistré", tient dans la même place) + son décalage droit (58px) + une marge de sécurité — un titre
       anormalement long tronque avant de chevaucher le statut, plutôt que de le recouvrir. */
    padding-right: 260px;
}
/* Onglets : patron canonique .isis-tabs/.isis-tab (déjà utilisé par EquipementFormDialog
   entre autres) — voir DESIGN.md, icône obligatoire par onglet. Panneaux : patron canonique
   .isis-tab-panel/.isis-tab-panel--footed (fiche détail, contenu scrollable + pied de page
   pinné) — pas de classes maison, ce dialogue réutilise le rythme visuel du reste du produit. */
.isis-devis-elaboration-dialog__panels {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
}
.isis-devis-elaboration-dialog__footer {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 0.6rem;
    padding-top: 0.5rem;
    border-top: 1px solid var(--isis-border);
}
/* Barre d'onglets : le filet passe de .isis-tabs à la barre pour courir sous la zone de
   droite (mode en ligne) ; les onglets restent calés en bas, leur souligné actif se pose
   sur ce filet. */
.isis-devis-elaboration-dialog__bar {
    display: flex;
    align-items: flex-end;
    gap: 12px;
    flex-shrink: 0;
    border-bottom: 1px solid var(--isis-border);
    margin-bottom: 16px;
}
.isis-devis-elaboration-dialog__bar > .isis-tabs {
    flex: 1 1 auto;
    min-width: 0;
    border-bottom: 0;
    margin-bottom: 0;
}
.isis-devis-elaboration-dialog__bar-end {
    display: flex;
    align-items: center;
    gap: 12px;
    align-self: center;
    flex-shrink: 0;
}
/* Mode en ligne (lot 2, 2026-09-22) : l'éditeur vit dans l'onglet Lignes de la fiche, enfant
   direct de .isis-tab-panel--footed (colonne flex) — il prend la hauteur restante au lieu
   des 100 % d'un contenu de dialogue. */
.isis-devis-elaboration-dialog--inline {
    flex: 1 1 auto;
    height: auto;
    padding-bottom: 0;
}
/* Édition des lignes en place : la barre de l'éditeur remplace les deux niveaux d'onglets de la
   fiche — changer d'onglet cacherait l'éditeur et sa sortie « Terminer ». */
.isis-detail-card--tabs.is-editing-lines > .isis-tabs,
.isis-detail-card--tabs.is-editing-lines > .isis-subtabs { display: none; }
.isis-devis-elaboration-dialog--inline .isis-devis-elaboration-dialog__bar {
    margin-bottom: 8px;
}

.isis-option-group-label {
    display: inline-flex;
    align-items: center;
    vertical-align: middle;
    margin-left: var(--isis-space-xs);
    font-size: 0.78rem;
    font-style: italic;
    color: var(--isis-text-muted);
}
.isis-devis-items__option {
    margin-top: 0.35rem;
}
.isis-devis-items__option .rz-dropdown {
    margin-top: 0.35rem;
}
.isis-devis-items__option .rz-textbox {
    margin-top: 0.35rem;
}
.isis-devis-items__option-toggle {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    font-size: 0.72rem;
    color: var(--isis-text-muted);
    cursor: pointer;
    user-select: none;
}
/* Variantes de devis — Phase B : bloc « Impact prix » d'une option. Encart
   décoratif au filet périmétrique (le commentaire le revendiquait déjà, le code
   était resté en liseré gauche 2px — corrigé 2026-07-18), regroupant type /
   valeur / cible / lignes ciblées. */
.isis-devis-items__impact {
    box-sizing: border-box;   /* le filet ajoute 4 côtés là où le liseré n'en occupait qu'un */
    margin-top: 0.45rem;
    padding: 0.4rem 0.5rem;
    border: 1px solid color-mix(in srgb, var(--isis-accent) 32%, transparent);
    background: color-mix(in srgb, var(--isis-accent-soft) 22%, transparent);
    border-radius: var(--isis-radius-sm);
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
}
.isis-devis-items__impact-title {
    font-size: 0.68rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.02em;
    color: var(--isis-text-muted);
}
.isis-devis-items__impact-hint {
    font-size: 0.68rem;
    color: var(--isis-text-soft);
}
/* Cellule étroite (colonne Article) : borne la hauteur des chips de lignes
   ciblées avec scroll interne plutôt que de laisser la cellule exploser. */
.isis-devis-items__impact .rz-multiselect-chips-container {
    max-height: 64px;
    overflow-y: auto;
}

/* Tarification par paliers de quantité (P1) : encart au filet périmétrique
   (parité avec l'encart « Impact prix ») — sélecteur de mode + mini-grille seuil→PU. */
.isis-devis-items__tiers {
    box-sizing: border-box;
    margin-top: 0.45rem;
    padding: 0.4rem 0.5rem;
    border: 1px solid color-mix(in srgb, var(--isis-mod-gescom, var(--isis-accent)) 32%, transparent);
    background: color-mix(in srgb, var(--isis-accent-soft) 18%, transparent);
    border-radius: var(--isis-radius-sm);
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
}
.isis-devis-items__tiers-mode {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
}
.isis-devis-items__tiers-title {
    font-size: 0.68rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.02em;
    color: var(--isis-text-muted);
}
.isis-devis-items__tier-grid {
    width: 100%;
    border-collapse: collapse;
}
.isis-devis-items__tier-grid th {
    font-size: 0.64rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.02em;
    color: var(--isis-text-soft);
    text-align: right;
    padding: 0 0.2rem 0.15rem;
}
.isis-devis-items__tier-grid th:last-child {
    width: 26px;
}
.isis-devis-items__tier-grid td {
    padding: 0.1rem 0.2rem;
    vertical-align: middle;
}
.isis-devis-items__tier-remove,
.isis-devis-items__tier-add {
    appearance: none;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    color: var(--isis-text-muted);
    border-radius: var(--isis-radius-sm);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
.isis-devis-items__tier-remove {
    height: 22px;
    width: 22px;
    padding: 0;
}
.isis-devis-items__tier-add {
    gap: 0.2rem;
    font-size: 0.7rem;
    padding: 0.15rem 0.45rem;
    align-self: flex-start;
    color: var(--isis-mod-gescom, var(--isis-accent));
}
.isis-devis-items__tier-add:hover {
    background: color-mix(in srgb, var(--isis-accent-soft) 30%, transparent);
    border-color: color-mix(in srgb, var(--isis-mod-gescom, var(--isis-accent)) 45%, transparent);
}
/* Suppression = action destructive : hover/focus en sémantique erreur (parité
   avec .isis-devis-items__remove), pas en accent constructif. */
.isis-devis-items__tier-remove:hover {
    background: var(--isis-danger-soft);
    border-color: color-mix(in srgb, var(--isis-danger) 45%, transparent);
    color: var(--isis-danger);
}
.isis-devis-items__tier-add:focus-visible {
    outline: 2px solid color-mix(in srgb, var(--isis-mod-gescom, var(--isis-accent)) 60%, transparent);
    outline-offset: 1px;
}
.isis-devis-items__tier-remove:focus-visible {
    outline: 2px solid color-mix(in srgb, var(--isis-danger) 60%, transparent);
    outline-offset: 1px;
}
.isis-devis-items__tier-hint {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    font-size: 0.68rem;
    color: var(--isis-warning);
}

/* Bannière grille catalogue appliquée : statut discret, pas une alerte. */
.isis-devis-items__grid-banner {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    margin-top: 0.35rem;
    padding: 0.15rem var(--isis-space-sm);
    font-size: 0.68rem;
    font-weight: 500;
    color: var(--isis-mod-gescom, var(--isis-accent));
    background: color-mix(in srgb, var(--isis-accent-soft) 40%, transparent);
    border: 1px solid color-mix(in srgb, var(--isis-mod-gescom, var(--isis-accent)) 28%, transparent);
    border-radius: var(--isis-radius-sm);
}
/* Bouton détacher : icône borderless, hover danger. */
.isis-devis-items__grid-detach {
    appearance: none;
    background: transparent;
    border: none;
    padding: 0 0.1rem;
    display: inline-flex;
    align-items: center;
    cursor: pointer;
    color: var(--isis-text-muted);
    border-radius: var(--isis-radius-sm);
}
.isis-devis-items__grid-detach:hover {
    color: var(--isis-danger);
    background: var(--isis-danger-soft);
}
.isis-devis-items__grid-detach:focus-visible {
    outline: 2px solid color-mix(in srgb, var(--isis-danger) 60%, transparent);
    outline-offset: 1px;
}
/* Bouton choisir un barème catalogue : secondaire, assortit tier-add. */
.isis-devis-items__grid-pick {
    appearance: none;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    color: var(--isis-mod-gescom, var(--isis-accent));
    border-radius: var(--isis-radius-sm);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: 0.2rem;
    font-size: 0.7rem;
    padding: 0.15rem 0.45rem;
    align-self: flex-start;
}
.isis-devis-items__grid-pick:hover {
    background: color-mix(in srgb, var(--isis-accent-soft) 30%, transparent);
    border-color: color-mix(in srgb, var(--isis-mod-gescom, var(--isis-accent)) 45%, transparent);
}
.isis-devis-items__grid-pick:focus-visible {
    outline: 2px solid color-mix(in srgb, var(--isis-mod-gescom, var(--isis-accent)) 60%, transparent);
    outline-offset: 1px;
}

/* Dialog de sélection d'une grille catalogue (PriceGridPickerDialog). */
.isis-price-grid-picker__search {
    margin-bottom: var(--isis-space-sm);
}
.isis-price-grid-picker__list {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
    max-height: 320px;
    overflow-y: auto;
}
.isis-price-grid-picker__row {
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    gap: var(--isis-space-sm);
    padding: 0.45rem var(--isis-space-sm);
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-sm);
}
.isis-price-grid-picker__row:hover {
    background: color-mix(in srgb, var(--isis-accent-soft) 20%, var(--isis-surface));
    border-color: color-mix(in srgb, var(--isis-mod-gescom, var(--isis-accent)) 30%, transparent);
}
.isis-price-grid-picker__info {
    display: flex;
    flex-direction: column;
    gap: 0.1rem;
    min-width: 0;
}
.isis-price-grid-picker__label {
    font-size: 0.82rem;
    font-weight: 500;
    color: var(--isis-text);
}
.isis-price-grid-picker__meta {
    display: block;
    font-size: 0.7rem;
    color: var(--isis-text-muted);
}

/* PU dérivé par la grille de paliers : signal de lecture seule (fond teinté +
   curseur interdit), pas seulement une opacité quasi-imperceptible. */
.isis-pu-cell.is-derived .rz-numeric {
    opacity: 0.9;
    background: color-mix(in srgb, var(--isis-accent-soft) 40%, transparent);
    cursor: not-allowed;
}
.isis-pu-cell.is-derived .rz-numeric input {
    cursor: not-allowed;
}
.isis-pu-cell__lock {
    display: inline-flex;
    align-items: center;
    color: var(--isis-text-soft);
    flex-shrink: 0;
}

/* Signal visuel des lignes en option (parité avec is-merge-child / is-structural). */
/* Ligne en option : le fond teinté porte seul le signal. Le liseré gauche 2px sur
   la 1re cellule a été retiré le 2026-07-18, comme celui des lignes de grille en
   2026-07-04 et pour la même raison — il décalait le contenu de la colonne. */
.isis-devis-items tbody tr.is-optional {
    background: color-mix(in srgb, var(--isis-accent-soft) 35%, transparent);
}
.isis-form-hint {
    margin-top: 0.5rem;
    font-size: 0.74rem;
    color: var(--isis-text);
    font-variant-numeric: tabular-nums;
}

/* ============================================================================
   .isis-devis-items — tableau d'édition des lignes d'un devis
   ============================================================================ */
.isis-devis-items {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.78rem;
}

/* Dans le dialog d'édition, on impose table-layout: fixed pour que les widths
   déclarés sur les <th> soient respectés strictement — sinon la colonne
   Entreprise (140px) s'élargit dynamiquement dès qu'un nom de cotraitant ou
   tiers est long, et pousse les autres colonnes. Fixed + overflow hidden +
   ellipsis sur les chips/dropdowns à l'intérieur = colonnes stables. */
.isis-devis-items-dialog .isis-devis-items {
    table-layout: fixed;
}
.isis-devis-items-dialog .isis-devis-items td {
    overflow: hidden;
}
.isis-devis-items-dialog .isis-devis-items td .isis-entreprise-tag,
.isis-devis-items-dialog .isis-devis-items td .isis-imputation-picker {
    max-width: 100%;
}
.isis-devis-items thead th {
    text-align: left;
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    font-size: 0.65rem;
    color: var(--isis-text-muted);
    padding: 0.4rem 0.5rem;
    border-bottom: 1px solid var(--isis-border);
    background: transparent;
}
.isis-devis-items tbody td {
    padding: 0.35rem 0.4rem;
    border-bottom: 1px solid var(--isis-border-soft, #f1f2f5);
    /* Aligné en haut : si la Désignation grandit en hauteur (textarea
       auto-resize), les autres cellules (Qté, PU, Remise, actions…) restent
       collées au sommet de la ligne au lieu de flotter au milieu. */
    vertical-align: top;
}

/* Alignement vertical strict des inputs/contrôles dans la table d'édition.
   Radzen wrappe différemment chaque type (RadzenNumeric = span avec spinners,
   RadzenDropDown = div avec chevron, RadzenTextBox = input direct), ce qui
   produit naturellement des écarts de 1-3px de hauteur. On force une grille
   uniforme via :
     1) une hauteur unique de 32px sur tous les wrappers externes
     2) un reset margin: 0 sur tous les enfants directs des <td>
     3) box-sizing: border-box pour que la hauteur inclut padding+bordure
     4) line-height: 32px sur les cellules text-only pour aligner la baseline
     5) vertical-align: top sur ces mêmes wrappers. Sans lui, un wrapper de niveau
        ligne repose sur la ligne de base de la cellule, qui réserve dessous la place
        des jambages de son interligne (19,72 px) — 11 px de vide sous CHAQUE champ,
        dans chaque colonne, que rien n'utilise : la ligne mesurait 52,8 px pour un
        contenu qui n'en réclame que 41,8. Aligner en haut supprime ce reliquat sans
        déplacer le contenu (le <td> est déjà `vertical-align: top`) ; la ligne retombe
        sur le plancher de 44 px de `--gridskin`, qui est la cible tactile. */
.isis-devis-items tbody td > * {
    margin: 0;
    box-sizing: border-box;
    vertical-align: top;
}

.isis-devis-items tbody .rz-textbox,
.isis-devis-items tbody .rz-numeric,
.isis-devis-items tbody .rz-dropdown,
.isis-devis-items tbody input.rz-textbox-input,
.isis-devis-items tbody .rz-numeric .rz-numeric-input,
.isis-devis-items tbody .rz-dropdown .rz-dropdown-label {
    height: 32px;
    min-height: 32px;
    max-height: 32px;
    box-sizing: border-box;
    line-height: 1.4;
}
/* Le wrapper RadzenNumeric contient un <input> et des <button> spinners
   parfois flexés différemment selon le browser. On force display: flex pour
   que les enfants se centrent verticalement à coup sûr. */
.isis-devis-items tbody .rz-numeric {
    display: inline-flex;
    align-items: stretch;
    padding: 0;
}
.isis-devis-items tbody .rz-numeric .rz-numeric-input,
.isis-devis-items tbody .rz-numeric .rz-numeric-button {
    margin: 0;
}
/* Le wrapper RadzenDropDown contient le label et le chevron — ils doivent
   être centrés verticalement dans les 32px. */
.isis-devis-items tbody .rz-dropdown {
    display: inline-flex;
    justify-content: center;
    padding: 0 0.5rem;
}
/* Textarea Description : garde son min-height 32px pour s'aligner sur les
   autres inputs au repos, libre de grandir au-delà via field-sizing. */
.isis-devis-items tbody .rz-textarea,
.isis-devis-items tbody textarea.rz-textarea {
    min-height: 32px;
    box-sizing: border-box;
    line-height: 1.4;
}
/* Cellules text-only (SECTION/COMMENT, totaux affichés sans input) :
   line-height 32px pour aligner la baseline du texte sur les inputs voisins.
   Exclut les rows historique inline (compactes par design) et la cellule du
   déboursé en lecture : héritée, cette hauteur étirait chaque libellé du bloc et
   du récap, quand l'éditeur — qui contient des champs, donc exclu — restait dense. */
.isis-devis-items tbody tr:not(.isis-devis-items__history-row) td:not(.isis-costing-row__acti-cell):not(:has(.rz-textbox, .rz-numeric, .rz-dropdown, .rz-textarea, .isis-devis-items__actions, .isis-devis-items__drag-handle, .isis-devis-items__drag-cell)) {
    line-height: 32px;
}
.isis-devis-items tbody tr:hover {
    background: var(--isis-surface-soft);
}
.isis-devis-items tbody tr.is-structural td {
    background: var(--isis-surface-soft);
    color: var(--isis-text-muted);
}

/* ----------------------------------------------------------------------------
   .isis-devis-items--gridskin — habillage de la table d'édition aux tokens .isis-grid
   (2026-09-07). L'éditeur garde sa structure <table> : le drag & drop de
   réordonnancement, les contrôles inline, les lignes d'historique et les quatre
   overlays satellites y sont ancrés. Seul le chrome s'aligne, pour que lecture et
   édition ne se ressemblent plus « à peu près ».
   Valeurs reprises telles quelles de DESIGN.md:302-310 — ne pas les faire diverger.
   Aucune zébrure : le repère de lecture est le séparateur 1 px.

   POSITION VOLONTAIRE — ce bloc doit rester APRÈS TOUTES les règles de base
   `.isis-devis-items` qu'il surcharge : il a la MÊME spécificité qu'elles, donc
   seul l'ordre source le fait gagner. Deux fois de suite pendant ce chantier, un
   placement trop haut l'a rendu inerte tout en laissant les tests verts — d'abord
   sur l'en-tête (`background: transparent` reprenait la main), puis sur le survol
   (`.isis-devis-items tbody tr:hover`, déclaré 50 lignes plus bas, gagnait).
   La règle `is-structural` reste volontairement gagnante sur le survol : le fond
   d'une ligne SECTION est sémantique, il ne doit pas être un simple état.
   ---------------------------------------------------------------------------- */
.isis-devis-items--gridskin {
    font-size: 0.85rem;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius);
}
.isis-devis-items--gridskin thead th {
    background: var(--isis-surface-alt);
    border-bottom: 1px solid var(--isis-border);
    color: var(--isis-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    font-size: 0.65rem;
    font-weight: 600;
    height: 34px;
    padding: 0 0.35rem;
    position: sticky;
    top: 0;
    z-index: 4;
}
.isis-devis-items--gridskin tbody tr {
    min-height: 44px;
}
.isis-devis-items--gridskin tbody td {
    border-bottom: 1px solid var(--isis-border-soft);
    padding: 0.35rem;
}
/* Repli obligatoire, comme la règle canonique `.isis-grid__row:hover` : la variable
   `--isis-current-mod-soft` n'est PAS définie sur :root, elle est portée par le shell
   du module. L'éditeur est rendu dans un dialog Radzen, hors de ce shell — sans repli,
   le `var()` ne résout pas, la déclaration entière est jetée, et le survol ne peint
   rien. Mesuré au navigateur le 2026-09-07 : rgba(0, 0, 0, 0).
   Repli sur --isis-mod-gescom-soft (pas --isis-surface-alt) depuis le lifting du
   2026-09-15 : ce dialogue n'existe que sous /gescom/, --isis-current-mod ne s'y
   résoudra donc jamais à autre chose — nommer le module directement au lieu d'un gris
   neutre restaure le survol bleu-module attendu partout ailleurs dans le produit. */
.isis-devis-items--gridskin tbody tr:hover {
    background: var(--isis-current-mod-soft, var(--isis-mod-gescom-soft, var(--isis-surface-alt)));
}
.isis-devis-items tbody tr.is-structural td .rz-textbox {
    font-weight: 500;
}
.isis-devis-items__remove {
    background: none;
    border: none;
    color: #c62828;
    cursor: pointer;
    padding: 0.2rem;
    border-radius: 4px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
.isis-devis-items__remove:hover:not(:disabled) {
    background: #ffebee;
}
.isis-devis-items__remove:disabled {
    color: var(--isis-text-soft, #94a3b8);
    cursor: not-allowed;
    opacity: 0.5;
}
.isis-devis-items__actions {
    display: inline-flex;
    align-items: center;
    gap: 0.15rem;
}

/* Textarea Description auto-redimensionnable (DevisItemsEditDialog).
   `field-sizing: content` (CSS moderne — Chrome 123+, Safari 17.4+, Edge 123+,
   Firefox 144+) fait croître/réduire le textarea selon le contenu réel, sans
   scrollbar interne. Firefox plus ancien : retombe sur 1 row + scroll natif. */
.isis-row-desc-textarea {
    field-sizing: content;
    min-height: 2rem;
    max-height: 280px;
    resize: none;
    overflow: hidden;
    line-height: 1.4;
    padding: 0.3rem 0.5rem;
}
/* Radzen wrappe son textarea — on cible aussi le sélecteur interne. */
.isis-row-desc-textarea textarea,
.isis-row-desc-textarea > textarea,
textarea.rz-textarea.isis-row-desc-textarea {
    field-sizing: content;
    min-height: 2rem;
    max-height: 280px;
    resize: none;
    overflow: hidden;
    line-height: 1.4;
}

/* Repli là où field-sizing: content n'est pas supporté. Sans lui, le champ reste à une
   ligne ET overflow: hidden masque la suite : l'utilisateur tape et son texte disparaît.
   On rend le débordement atteignable plutôt que coupé — resize: none est conservé (une
   poignée de redimensionnement dans une grille casse l'alignement des rangées). */
@supports not (field-sizing: content) {
    .isis-row-desc-textarea,
    .isis-row-desc-textarea textarea,
    .isis-row-desc-textarea > textarea,
    textarea.rz-textarea.isis-row-desc-textarea {
        overflow-y: auto;
        min-height: 2rem;
        max-height: 280px;
    }
}

/* Phase 5 v2 — colorisation gauche des lignes selon classification marge.
   Border-left 3px discrète, ne bouge pas le layout. Mêmes codes couleurs que
   MarginClassifier côté DevisCostingTab → cohérence visuelle entre les 2 onglets. */
.isis-devis-items tbody tr.is-margin-on-target    { box-shadow: inset 3px 0 0 0 var(--isis-success, #16a34a); }
.isis-devis-items tbody tr.is-margin-below-target { box-shadow: inset 3px 0 0 0 var(--isis-warning, #d97706); }
.isis-devis-items tbody tr.is-margin-below-floor  { box-shadow: inset 3px 0 0 0 var(--isis-danger,  #dc2626); }
.isis-devis-items tbody tr.is-margin-above-max    { box-shadow: inset 3px 0 0 0 var(--isis-accent,  #4b5fad); }

/* Colonne Marge — badge pill compact (au lieu de colorer la cellule entière).
   4 classes alignées sur le MarginClassifier (cohérent avec liseré row + bandeau
   Coût de revient). Le span concentre la couleur, la cellule reste neutre. */
.isis-margin-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.25rem;
    min-width: 56px;
    padding: 0.15rem 0.55rem;
    border-radius: var(--isis-radius-pill);
    font-size: 0.78rem;
    font-weight: 600;
    line-height: 1.2;
    font-variant-numeric: tabular-nums;
    letter-spacing: 0.01em;
    border: 1px solid transparent;
    white-space: nowrap;
}
.isis-margin-badge .rzi {
    font-size: 0.9rem;
}
/* Au-dessus du maximum = info, pas l'accent : c'est un signal (prix à vérifier), ni une
   alerte ni la couleur des actions. L'état est aussi dit par l'icône et un texte masqué. */
.isis-margin-badge.is-margin-cell-on-target {
    background: var(--isis-success-soft);
    color: var(--isis-success-text);
    border-color: color-mix(in srgb, var(--isis-success) 35%, transparent);
}
.isis-margin-badge.is-margin-cell-below-target {
    background: var(--isis-warning-soft);
    color: var(--isis-warning-text);
    border-color: color-mix(in srgb, var(--isis-warning) 40%, transparent);
}
.isis-margin-badge.is-margin-cell-below-floor {
    background: var(--isis-danger-soft);
    color: var(--isis-danger-text);
    border-color: color-mix(in srgb, var(--isis-danger) 40%, transparent);
}
.isis-margin-badge.is-margin-cell-above-max {
    background: var(--isis-info-soft);
    color: var(--isis-info-text);
    border-color: color-mix(in srgb, var(--isis-info) 35%, transparent);
}
.isis-margin-badge--neutral {
    /* Cellule sans coût alloué : tiret sobre, pas de couleur (juste typo). */
    color: var(--isis-text-muted);
    background: transparent;
    border-color: transparent;
    font-weight: 400;
    min-width: auto;
}

/* ═══════════════════════════════════════════════════════════════════════════
   Override global RadzenButton — identité bouton ISIS (36px / radius 4 /
   relief subtil). Tous les <RadzenButton> de l'app prennent cet aspect selon
   leur ButtonStyle. Mapping :
     ButtonStyle.Primary   → accent plein (action principale)
     ButtonStyle.Light     → ghost feutré (secondaire, le plus fréquent)
     ButtonStyle.Secondary → ghost feutré
     ButtonStyle.Base      → ghost feutré
     ButtonStyle.Danger    → danger plein (destructif)
     ButtonStyle.Warning   → warning plein
     ButtonStyle.Info      → accent plein (variante info bleue)
     ButtonStyle.Success   → couleur success (bouton vert)

   Préservé : RadzenIconButton (rz-button-icon-only), boutons tailles spéciales
   (rz-button-sm/lg), variant filled/outlined/text (rendent à leur style natif
   pour les usages qui sortent du pattern « bouton plein flat »).
   ═══════════════════════════════════════════════════════════════════════════ */

/* Base : reset Radzen (padding, gap, alignement, radius, relief subtil).
   Les couleurs sont posées plus bas par shade pour différencier
   Light / Base / Secondary (qui se ressemblaient trop). */
.rz-button:not(.rz-button-icon-only) {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.4rem;
    padding: 0.5rem 0.95rem;
    min-height: 36px;
    border-radius: 4px;
    border: 1px solid transparent;
    font-family: inherit;
    font-size: 0.85rem;
    font-weight: 500;
    line-height: 1.2;
    box-shadow: 0 1px 2px rgba(15, 23, 42, 0.06), 0 0 0 1px rgba(15, 23, 42, 0.02);
    transition: background 120ms ease, border-color 120ms ease, color 120ms ease, box-shadow 120ms ease, transform 60ms ease;
}
.rz-button:not(.rz-button-icon-only):hover:not([disabled]) {
    box-shadow: 0 2px 4px rgba(15, 23, 42, 0.10), 0 0 0 1px rgba(15, 23, 42, 0.04);
}
.rz-button:not(.rz-button-icon-only):active:not([disabled]) {
    transform: translateY(1px);
    box-shadow: 0 1px 1px rgba(15, 23, 42, 0.06);
}
.rz-button:not(.rz-button-icon-only):focus-visible {
    outline: 2px solid var(--isis-current-mod, var(--isis-accent));
    outline-offset: 2px;
}
.rz-button:not(.rz-button-icon-only):disabled,
.rz-button:not(.rz-button-icon-only)[disabled] {
    opacity: 0.55;
    cursor: not-allowed;
    box-shadow: none;
}
/* Un bouton plein désactivé ne garde pas la couleur d'accent sous une simple opacité : il se lit
   comme actif. Il prend les jetons des champs désactivés (DESIGN.md « Champ désactivé »). */
.rz-button.rz-primary:not(.rz-button-icon-only, .rz-variant-text, .rz-variant-outlined):is(:disabled, [disabled]),
.rz-button.rz-info:not(.rz-button-icon-only, .rz-variant-text, .rz-variant-outlined):is(:disabled, [disabled]) {
    background: var(--isis-field-disabled-bg) !important;
    border-color: var(--isis-field-disabled-border) !important;
    color: var(--isis-field-disabled-text) !important;
    opacity: 1;
}
.rz-button:not(.rz-button-icon-only) .rzi,
.rz-button:not(.rz-button-icon-only) .rz-icon {
    font-size: 14px;
}

/* ── ButtonStyle.Primary (79 usages) + Info → accent ──────────────────────
   !important nécessaire pour battre les sélecteurs Radzen natifs plus
   spécifiques (.rz-variant-filled.rz-primary, .rz-shade-default.rz-primary).
   Texte et Contour exclus : sans quoi le remplissage forcé écrase leurs règles
   plus bas (Primary est le style par défaut de RadzenButton). */
.rz-button.rz-primary:not(.rz-button-icon-only, .rz-variant-text, .rz-variant-outlined),
.rz-button.rz-info:not(.rz-button-icon-only, .rz-variant-text, .rz-variant-outlined) {
    background: var(--isis-accent) !important;
    border-color: var(--isis-accent) !important;
    color: var(--isis-surface) !important;
    font-weight: 600;
    box-shadow: 0 1px 2px rgba(15, 23, 42, 0.10), 0 1px 3px color-mix(in srgb, var(--isis-accent) 30%, transparent);
}
.rz-button.rz-primary:not(.rz-button-icon-only, .rz-variant-text, .rz-variant-outlined):hover:not([disabled]),
.rz-button.rz-info:not(.rz-button-icon-only, .rz-variant-text, .rz-variant-outlined):hover:not([disabled]) {
    background: color-mix(in srgb, var(--isis-accent) 88%, black) !important;
    border-color: color-mix(in srgb, var(--isis-accent) 88%, black) !important;
    box-shadow: 0 2px 4px rgba(15, 23, 42, 0.15), 0 2px 6px color-mix(in srgb, var(--isis-accent) 40%, transparent);
}

/* ── ButtonStyle.Light (244 usages) — action secondaire, mais contraste
   suffisant pour rester visible sur fond surface (sidepanels, dialogs).
   Fond légèrement teinté (text 5%) + bordure marquée (text 22%) → le bouton
   ressort même quand son parent est sur var(--isis-surface). */
.rz-button.rz-light:not(.rz-button-icon-only) {
    background: color-mix(in srgb, var(--isis-text) 5%, var(--isis-surface)) !important;
    border-color: color-mix(in srgb, var(--isis-text) 22%, var(--isis-border)) !important;
    color: var(--isis-text) !important;
    font-weight: 500;
}
.rz-button.rz-light:not(.rz-button-icon-only):hover:not([disabled]) {
    background: color-mix(in srgb, var(--isis-text) 10%, var(--isis-surface)) !important;
    border-color: color-mix(in srgb, var(--isis-text) 38%, var(--isis-border)) !important;
}

/* ── ButtonStyle.Base — standard sobre, plus de poids que Light ──────── */
.rz-button.rz-base:not(.rz-button-icon-only) {
    background: color-mix(in srgb, var(--isis-text) 4%, var(--isis-surface)) !important;
    border-color: color-mix(in srgb, var(--isis-text) 18%, var(--isis-border)) !important;
    color: var(--isis-text) !important;
    font-weight: 500;
}
.rz-button.rz-base:not(.rz-button-icon-only):hover:not([disabled]) {
    background: color-mix(in srgb, var(--isis-text) 8%, var(--isis-surface)) !important;
    border-color: color-mix(in srgb, var(--isis-text) 32%, var(--isis-border)) !important;
}

/* ── ButtonStyle.Secondary — emphatique, teinte accent atténuée ──────── */
.rz-button.rz-secondary:not(.rz-button-icon-only) {
    background: color-mix(in srgb, var(--isis-accent) 6%, var(--isis-surface)) !important;
    border-color: color-mix(in srgb, var(--isis-accent) 30%, var(--isis-border)) !important;
    color: color-mix(in srgb, var(--isis-accent) 75%, var(--isis-text)) !important;
    font-weight: 600;
}
.rz-button.rz-secondary:not(.rz-button-icon-only):hover:not([disabled]) {
    background: color-mix(in srgb, var(--isis-accent) 12%, var(--isis-surface)) !important;
    border-color: color-mix(in srgb, var(--isis-accent) 50%, transparent) !important;
    color: var(--isis-accent) !important;
}

/* ── ButtonStyle.Danger ────────────────────────────────────────────────── */
.rz-button.rz-danger:not(.rz-button-icon-only) {
    background: var(--isis-danger) !important;
    border-color: var(--isis-danger) !important;
    color: var(--isis-surface) !important;
    font-weight: 600;
    box-shadow: 0 1px 2px rgba(15, 23, 42, 0.10), 0 1px 3px color-mix(in srgb, var(--isis-danger) 30%, transparent);
}
.rz-button.rz-danger:not(.rz-button-icon-only):hover:not([disabled]) {
    background: color-mix(in srgb, var(--isis-danger) 88%, black) !important;
    border-color: color-mix(in srgb, var(--isis-danger) 88%, black) !important;
    box-shadow: 0 2px 4px rgba(15, 23, 42, 0.15), 0 2px 6px color-mix(in srgb, var(--isis-danger) 40%, transparent);
}

/* ── ButtonStyle.Warning ───────────────────────────────────────────────── */
.rz-button.rz-warning:not(.rz-button-icon-only) {
    background: var(--isis-warning) !important;
    border-color: var(--isis-warning) !important;
    color: var(--isis-surface) !important;
    font-weight: 600;
    box-shadow: 0 1px 2px rgba(15, 23, 42, 0.10), 0 1px 3px color-mix(in srgb, var(--isis-warning) 30%, transparent);
}
.rz-button.rz-warning:not(.rz-button-icon-only):hover:not([disabled]) {
    background: color-mix(in srgb, var(--isis-warning) 88%, black) !important;
    border-color: color-mix(in srgb, var(--isis-warning) 88%, black) !important;
}

/* ── ButtonStyle.Success ───────────────────────────────────────────────── */
.rz-button.rz-success:not(.rz-button-icon-only) {
    background: var(--isis-success) !important;
    border-color: var(--isis-success) !important;
    color: var(--isis-surface) !important;
    font-weight: 600;
    box-shadow: 0 1px 2px rgba(15, 23, 42, 0.10), 0 1px 3px color-mix(in srgb, var(--isis-success) 30%, transparent);
}
.rz-button.rz-success:not(.rz-button-icon-only):hover:not([disabled]) {
    background: color-mix(in srgb, var(--isis-success) 88%, black) !important;
    border-color: color-mix(in srgb, var(--isis-success) 88%, black) !important;
}

/* Variant outlined : conserve le pattern Radzen natif d'outline mais aligne
   le radius/padding sur l'identité bouton ISIS. */
.rz-button.rz-variant-outlined:not(.rz-button-icon-only) {
    background: transparent;
}
.rz-button.rz-primary.rz-variant-outlined:not(.rz-button-icon-only),
.rz-button.rz-info.rz-variant-outlined:not(.rz-button-icon-only) {
    border-color: var(--isis-accent);
    color: var(--isis-accent);
}
.rz-button.rz-danger.rz-variant-outlined:not(.rz-button-icon-only) {
    border-color: var(--isis-danger);
    color: var(--isis-danger);
}

/* « Pourquoi ? » d'un bandeau de refus (IsisPageError) : seule action du bandeau, elle doit se
   lire comme actionnable SANS survol — le survol n'existe ni au clavier ni au doigt. Bordure
   permanente, couleurs par tokens : la regle .rz-button.rz-danger ci-dessus impose un rouge
   plein en !important, il faut le defaire ici (source plus tardive, meme specificite). */
.rz-button.isis-page-error__why:not(.rz-button-icon-only) {
    background: transparent !important;
    border: 1px solid var(--isis-danger) !important;
    color: var(--isis-danger) !important;
    box-shadow: none !important;
    margin-left: var(--isis-space-sm);
}
.rz-button.isis-page-error__why:not(.rz-button-icon-only):hover:not([disabled]) {
    background: color-mix(in srgb, var(--isis-danger) 12%, transparent) !important;
    border-color: var(--isis-danger) !important;
    box-shadow: none !important;
}
.rz-button.isis-page-error__why:focus-visible {
    outline: 2px solid var(--isis-danger);
    outline-offset: 2px;
}

/* Conteneur d'une alerte de refus qui reçoit le focus par programme (corbeille GED) : halo
   à la couleur du module, lisible en thème clair comme sombre (l'anneau natif disparaît en sombre). */
.isis-alert-focus:focus-visible {
    outline: 2px solid var(--isis-current-mod, var(--isis-accent));
    outline-offset: 2px;
    border-radius: var(--isis-radius);
}

/* Variant text : transparent + couleur d'accent, pas de bordure. */
.rz-button.rz-variant-text:not(.rz-button-icon-only) {
    background: transparent;
    border-color: transparent;
}
.rz-button.rz-primary.rz-variant-text:not(.rz-button-icon-only),
.rz-button.rz-info.rz-variant-text:not(.rz-button-icon-only) {
    color: var(--isis-accent);
}
.rz-button.rz-variant-text:not(.rz-button-icon-only):hover:not([disabled]) {
    background: color-mix(in srgb, currentColor 8%, transparent);
}

/* Tailles : préservées au format Radzen avec le radius bouton ISIS cohérent. */
.rz-button-sm:not(.rz-button-icon-only) {
    min-height: 28px;
    padding: 0.3rem 0.7rem;
    font-size: 0.78rem;
}
.rz-button-lg:not(.rz-button-icon-only) {
    min-height: 44px;
    padding: 0.6rem 1.2rem;
    font-size: 0.95rem;
}

/* Boutons d'action ligne (apply / history / unmerge / merge). */
.isis-devis-items__action {
    background: none;
    border: 1px solid transparent;
    color: var(--isis-text-muted);
    cursor: pointer;
    padding: 0.2rem 0.35rem;
    border-radius: 4px;
    display: inline-flex;
    align-items: center;
    gap: 2px;
    transition: background-color 120ms ease, color 120ms ease, border-color 120ms ease;
}
.isis-devis-items__action:hover {
    background: var(--isis-surface-alt, var(--isis-surface-alt));
    color: var(--isis-text);
}
.isis-devis-items__action--apply {
    background: color-mix(in srgb, var(--isis-success, #16a34a) 12%, var(--isis-surface));
    color: var(--isis-success, #16a34a);
    border-color: color-mix(in srgb, var(--isis-success, #16a34a) 35%, transparent);
}
.isis-devis-items__action--apply:hover {
    background: color-mix(in srgb, var(--isis-success, #16a34a) 22%, var(--isis-surface));
}
.isis-devis-items__action--history {
    background: color-mix(in srgb, var(--isis-accent) 10%, var(--isis-surface));
    color: var(--isis-accent);
    border-color: color-mix(in srgb, var(--isis-accent) 30%, transparent);
}
.isis-devis-items__action--history:hover {
    background: color-mix(in srgb, var(--isis-accent) 18%, var(--isis-surface));
}
/* Variante dépliée : fond accent plein, signal visuel fort que l'historique est ouvert. */
.isis-devis-items__action--history.is-expanded {
    background: var(--isis-accent);
    color: var(--isis-surface, #ffffff);
    border-color: var(--isis-accent);
}
.isis-devis-items__action--history.is-expanded:hover {
    background: color-mix(in srgb, var(--isis-accent) 85%, black);
}
/* Task 4 — bouton activités opérationnelles : teinte module (gescom), pas l'accent
   générique de l'historique, pour se distinguer visuellement au premier coup d'œil.
   Même famille de couleur que la pastille .isis-costing-row__activite-chip du
   drilldown qu'il déplie. */
.isis-devis-items__action--activites {
    background: var(--isis-mod-gescom-soft);
    color: var(--isis-mod-gescom);
    border-color: color-mix(in srgb, var(--isis-mod-gescom) 30%, transparent);
}
.isis-devis-items__action--activites:hover {
    background: color-mix(in srgb, var(--isis-mod-gescom) 18%, var(--isis-surface));
}
.isis-devis-items__action--activites.is-expanded {
    background: var(--isis-mod-gescom);
    color: var(--isis-surface, #ffffff);
    border-color: var(--isis-mod-gescom);
}
.isis-devis-items__action--activites.is-expanded:hover {
    background: color-mix(in srgb, var(--isis-mod-gescom) 85%, black);
}

/* Phase 5 v3 — Section décomposition tarifaire interne (EngagementDetail).
   Visible owner uniquement, fond accent atténué + badge "INTERNE" pour la
   distinguer comme info confidentielle qui ne doit jamais sortir vers le ST. */
.isis-engagement-decomposition {
    background: var(--isis-card-mod-bg);
    border: var(--isis-card-mod-border);
    padding: 0.85rem 1rem;
    border-radius: 6px;
}
.isis-engagement-decomposition__badge {
    display: inline-block;
    margin-left: 0.6rem;
    padding: 0.1rem 0.45rem;
    border-radius: 3px;
    background: var(--isis-warning, #d97706);
    color: white;
    font-size: 0.65rem;
    font-weight: 700;
    letter-spacing: 0.05em;
    vertical-align: middle;
}
.isis-decomposition-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.82rem;
    background: var(--isis-surface);
    border-radius: 4px;
    overflow: hidden;
}
.isis-decomposition-table th,
.isis-decomposition-table td {
    padding: 0.4rem 0.55rem;
    border-bottom: 1px solid var(--isis-border, var(--isis-border));
}
.isis-decomposition-table thead th {
    text-align: left;
    font-weight: 600;
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--isis-text-muted);
    background: var(--isis-surface-alt, var(--isis-surface-alt));
}
.isis-decomposition-table tfoot td {
    background: color-mix(in srgb, var(--isis-accent) 6%, transparent);
    border-top: 2px solid var(--isis-border);
}
.isis-decomposition-table .num { text-align: right; font-variant-numeric: tabular-nums; }
.isis-decomposition-table tbody tr:hover { background: var(--isis-surface-alt, var(--isis-surface-alt)); }
.isis-decomposition-table__margin-pct { font-weight: 600; color: var(--isis-accent); }
.isis-decomposition-table__no-margin { color: var(--isis-text-muted); font-style: italic; }
.isis-decomposition-table__margin { color: var(--isis-success, #16a34a); font-weight: 600; }
.isis-engagement-decomposition__summary {
    margin-top: 0.6rem;
    display: flex;
    gap: 1.5rem;
    padding: 0.5rem 0.8rem;
    background: var(--isis-surface);
    border-radius: 4px;
    font-size: 0.82rem;
    flex-wrap: wrap;
}
.isis-engagement-decomposition__summary strong { color: var(--isis-text-muted); font-weight: 600; font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.03em; margin-right: 0.3rem; }

/* Marge par poste sous-traité, regroupée par engagement (Lot E, tâche 3). Un groupe = un
   bandeau d'en-tête (numéro + sous-traitant + contrôle prévu/réalisé) suivi de sa propre
   table de postes — pas un <thead> partagé, pour rester une structure de table simple et
   valide côté lecteur d'écran. */
.isis-marge-engagement-group {
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-sm, 5px);
    overflow: hidden;
}
.isis-marge-engagement-group__header {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.6rem;
    padding: 0.5rem 0.7rem;
    background: var(--isis-surface-alt, var(--isis-surface-alt));
    border-bottom: 1px solid var(--isis-border);
}
.isis-marge-engagement-group__title {
    display: flex;
    align-items: baseline;
    gap: 0.5rem;
    font-size: 0.85rem;
}
.isis-marge-engagement-group__soustraitant { color: var(--isis-text-muted); font-size: 0.8rem; }
.isis-marge-engagement-group__controle {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.4rem;
    margin-left: auto;
}

/* Variantes de devis — encart « filet périmétrique » (tokens --isis-card-mod-*)
   listant les offres concurrentes d'un groupe. Aucune ombre ad-hoc. */
.isis-variant-card {
    background: var(--isis-card-mod-bg);
    border: var(--isis-card-mod-border);
    border-radius: var(--isis-radius, 8px);
    padding: var(--isis-space-md);
    margin-top: var(--isis-space-sm);
}
.isis-variant-card__title {
    margin: 0 0 var(--isis-space-sm);
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--isis-text);
}
.isis-variant-card__arbitrage {
    display: flex;
    align-items: baseline;
    gap: var(--isis-space-sm);
    margin: 0 0 var(--isis-space-sm);
    font-size: 0.82rem;
    color: var(--isis-text-muted);
}
.isis-variant-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.82rem;
    background: var(--isis-surface);
    border-radius: 4px;
    overflow: hidden;
}
.isis-variant-table th,
.isis-variant-table td {
    padding: 0.4rem 0.55rem;
    border-bottom: 1px solid var(--isis-border);
    text-align: left;
}
.isis-variant-table thead th {
    font-weight: 600;
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--isis-text-muted);
    background: var(--isis-surface-alt);
}
.isis-variant-table .num { text-align: right; font-variant-numeric: tabular-nums; }
.isis-variant-table tbody tr:hover { background: var(--isis-surface-alt); }
.isis-variant-table tbody tr.is-current { background: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 9%, transparent); font-weight: 600; }
.isis-variant-table__ref { color: var(--isis-text-muted); font-weight: 600; font-size: 0.72rem; }
.isis-variant-table__actions { text-align: right; white-space: nowrap; }

/* Phase BPU (migration 0187) — Bannière contextuelle en tête de DevisFormDialog
   quand le user choisit "Bordereau de prix" (BPU). Compense le titre du titlebar
   Radzen qui reste statique. */
.isis-devis-bpu-banner {
    display: flex;
    align-items: center;
    gap: 0.7rem;
    padding: 0.7rem 0.9rem;
    margin-bottom: 1rem;
    background: color-mix(in srgb, var(--isis-info, #0ea5e9) 8%, var(--isis-surface));
    color: var(--isis-info, #0ea5e9);
    border: 1px solid color-mix(in srgb, var(--isis-info, #0ea5e9) 35%, var(--isis-border));
    border-radius: 4px;
}
.isis-devis-bpu-banner__body {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    flex: 1;
}
.isis-devis-bpu-banner__body strong { font-size: 0.95rem; color: var(--isis-text); }
.isis-devis-bpu-banner__hint {
    font-size: 0.78rem;
    color: var(--isis-text-muted);
}

/* Sous-ligne de la cellule numéro (liste des offres) : badge « à arbitrer » / « variante » entièrement visible. */
.isis-devis-num-sub {
    display: block;
    margin-top: var(--isis-space-xs);
    white-space: nowrap;
}

/* Phase BPU (migration 0187) — Badge inline « BPU » sur la liste devis +
   fiche détail. Sobre, signale qu'il s'agit d'un bordereau de prix unitaires. */
.isis-devis-bpu-tag {
    display: inline-block;
    margin-left: 0.4rem;
    padding: 0.05rem 0.4rem;
    font-size: 0.65rem;
    font-weight: 700;
    letter-spacing: 0.05em;
    border-radius: 3px;
    background: color-mix(in srgb, var(--isis-info, #0ea5e9) 14%, var(--isis-surface));
    color: var(--isis-info, #0ea5e9);
    border: 1px solid color-mix(in srgb, var(--isis-info, #0ea5e9) 40%, transparent);
    vertical-align: middle;
}

/* Phase 5 v3 — Bouton « Historique tarifaire client » (icône query_stats).
   Sobre, neutre — c'est une info, pas une alerte. Hover marqué pour signaler
   qu'il est cliquable. */
.isis-devis-items__action--price-history {
    background: color-mix(in srgb, var(--isis-info, #0ea5e9) 10%, var(--isis-surface));
    color: var(--isis-info, #0ea5e9);
    border-color: color-mix(in srgb, var(--isis-info, #0ea5e9) 30%, transparent);
}
.isis-devis-items__action--price-history:hover {
    background: color-mix(in srgb, var(--isis-info, #0ea5e9) 20%, var(--isis-surface));
}

/* Table du dialog historique tarifaire (DevisItemPriceHistoryDialog). */
.isis-price-history {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.82rem;
    margin-top: 0.4rem;
}
.isis-price-history th,
.isis-price-history td {
    padding: 0.4rem 0.55rem;
    border-bottom: 1px solid var(--isis-border, var(--isis-border));
}
.isis-price-history thead th {
    text-align: left;
    font-weight: 600;
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--isis-text-muted);
    background: var(--isis-surface-alt, var(--isis-surface-alt));
}
.isis-price-history .num { text-align: right; font-variant-numeric: tabular-nums; }
.isis-price-history tbody tr:hover { background: var(--isis-surface-alt, var(--isis-surface-alt)); }
.isis-price-history tbody tr.is-accepted td { background: color-mix(in srgb, var(--isis-success, #16a34a) 5%, transparent); }
.isis-price-history tbody tr.is-rejected td { background: color-mix(in srgb, var(--isis-danger,  #dc2626) 4%, transparent); color: var(--isis-text-muted); }
.isis-price-history__status {
    font-size: 0.72rem;
    padding: 0.1rem 0.4rem;
    border-radius: 3px;
    background: var(--isis-surface-alt);
    color: var(--isis-text-muted);
}
.isis-price-history__devis-link {
    appearance: none;
    background: none;
    border: none;
    padding: 0;
    color: var(--isis-accent);
    cursor: pointer;
    font-weight: 600;
    font-size: 0.78rem;
    text-decoration: underline dotted;
}
.isis-price-history__devis-link:hover {
    text-decoration: underline solid;
}
.isis-price-history__margin {
    font-weight: 600;
}
.isis-price-history__margin.is-low { color: var(--isis-warning, #d97706); }
.isis-price-history__margin.is-negative { color: var(--isis-danger, #dc2626); }
.isis-price-history__summary {
    margin-top: 0.75rem;
    display: flex;
    gap: 1.5rem;
    padding: 0.55rem 0.85rem;
    background: var(--isis-surface-alt, var(--isis-surface-alt));
    border-radius: 6px;
    font-size: 0.82rem;
    flex-wrap: wrap;
}
.isis-price-history__summary strong { color: var(--isis-text-muted); margin-right: 0.3rem; font-weight: 600; font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.03em; }

/* Phase 5 v2 — Bouton « Acquitter la marge » (cadenas ouvert).
   Sobre, neutre — c'est une option, pas une alerte. */
.isis-devis-items__action--ack {
    background: transparent;
    color: var(--isis-text-muted);
    border-color: color-mix(in srgb, var(--isis-text-muted) 30%, transparent);
}
.isis-devis-items__action--ack:hover {
    background: color-mix(in srgb, var(--isis-text-muted) 8%, var(--isis-surface));
    color: var(--isis-text);
}
/* Phase 5 v2 — Badge « Marge acceptée » (cadenas fermé vert).
   Marqueur stable d'un état terminal volontaire. */
.isis-devis-items__action--acked {
    background: color-mix(in srgb, var(--isis-success, #16a34a) 14%, var(--isis-surface));
    color: var(--isis-success, #16a34a);
    border-color: color-mix(in srgb, var(--isis-success, #16a34a) 40%, transparent);
}
.isis-devis-items__action--acked:hover {
    background: color-mix(in srgb, var(--isis-success, #16a34a) 22%, var(--isis-surface));
}
/* Atténuation visuelle des lignes acquittées : la classification reste lisible
   (barre de couleur conservée) mais l'opacité réduite signale que l'écart est assumé. */
.isis-devis-items tbody tr.is-margin-acked { opacity: 0.85; }
.isis-devis-items tbody tr.is-margin-acked.is-margin-below-floor  { box-shadow: inset 3px 0 0 0 color-mix(in srgb, var(--isis-danger,  #dc2626) 40%, transparent); }
.isis-devis-items tbody tr.is-margin-acked.is-margin-below-target { box-shadow: inset 3px 0 0 0 color-mix(in srgb, var(--isis-warning, #d97706) 40%, transparent); }
.isis-devis-items tbody tr.is-margin-acked.is-margin-above-max    { box-shadow: inset 3px 0 0 0 color-mix(in srgb, var(--isis-accent,  #4b5fad) 40%, transparent); }

/* Cellule Désignation onglet « Lignes » fiche détail — interligne resserré
   pour gagner de l'espace vertical sur les descriptions multi-lignes. */
.isis-devis-items tbody td.isis-devis-detail__desc-cell {
    line-height: 1.35;
    padding-top: 0.55rem;
}

/* Les colonnes de droite ne se replient pas : sans ça, la Désignation leur prend assez de
   place pour couper « 850,00 € » entre le nombre et le symbole. Nommée `nowrap` et non
   `num` : la colonne d'actions, qui n'a rien de chiffré, la porte pour le même effet. */
.isis-devis-items__nowrap {
    white-space: nowrap;
}
.isis-devis-detail__desc-line {
    display: flex;
    align-items: center;
    gap: 0.3rem;
    min-width: 0;
}
.isis-devis-detail__desc-text {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    /* Une rangée de grille reste un registre : le texte grandit jusqu'à 3 lignes, puis se
       coupe. `pre-line` restitue les retours à la ligne saisis ; le bouton d'agrandissement
       de la cellule reste la voie vers le texte intégral. */
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 3;
    line-clamp: 3;
    white-space: pre-line;
    overflow-wrap: anywhere;
}
/* Cellule d'un texte libre replié : le texte tronqué, puis son bouton d'ouverture. */
.isis-text-clamped {
    display: flex;
    align-items: flex-start;
    gap: 0.3rem;
    min-width: 0;
}
.isis-text-clamped > .isis-detail-grid__val--clamp2 {
    flex: 1 1 auto;
    min-width: 0;
}
/* Affordance PERMANENTE du texte replié : un survol ne s'annonce pas, et rien d'autre
   dans la cellule ne dit qu'il reste à lire. 24 px de côté au minimum — WCAG 2.2 §2.5.8
   (Taille de cible, AA) ; le glyphe reste petit, c'est la zone cliquable qui grandit. */
.isis-text-expand {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 24px;
    min-height: 24px;
    padding: 0 0.3rem;
    border: 1px solid var(--isis-border);
    border-radius: 4px;
    background: var(--isis-surface);
    color: var(--isis-text-muted);
    font: inherit;
    line-height: 1;
    cursor: pointer;
    transition: color 100ms ease, border-color 100ms ease;
}
.isis-text-expand:hover {
    color: var(--isis-current-mod, var(--isis-accent));
    border-color: var(--isis-current-mod, var(--isis-accent));
}
.isis-text-expand:focus-visible {
    outline: 2px solid var(--isis-current-mod, var(--isis-accent));
    outline-offset: 2px;
}

/* Dialog d'affichage d'un texte long en lecture seule (LongTextDialog). */
.isis-long-text-dialog {
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
}
.isis-long-text-dialog__body {
    max-height: min(60vh, 520px);
    overflow-y: auto;
    padding: 0.75rem;
    border: 1px solid var(--isis-border-soft, #f1f2f5);
    border-radius: var(--isis-radius-sm, 6px);
    background: var(--isis-surface-soft, var(--isis-surface));
    color: var(--isis-text);
    font-size: 0.85rem;
    line-height: 1.5;
    /* pre-wrap : les retours à la ligne saisis restent visibles sans MarkupString. */
    white-space: pre-wrap;
    overflow-wrap: break-word;
}

/* Cellule Marge ST onglet « Lignes » fiche détail — % en pastille discrète
   pour distinguer du % de remise (qui apparaît juste à gauche). */
.isis-devis-detail__st-margin {
    display: inline-block;
    padding: 0.1rem 0.45rem;
    border-radius: 4px;
    background: color-mix(in srgb, var(--isis-accent) 8%, var(--isis-surface));
    color: var(--isis-accent);
    font-weight: 600;
    font-size: 0.78rem;
}

/* Phase 5 v2 — Badges informatifs lecture seule dans la cellule actions de
   la fiche détail devis (onglet « Lignes »). Compact, alignés à droite. */
.isis-devis-detail__row-actions {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    justify-content: flex-end;
}
.isis-devis-detail__ack-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    border-radius: 4px;
    background: color-mix(in srgb, var(--isis-success, #16a34a) 14%, var(--isis-surface));
    color: var(--isis-success, #16a34a);
    border: 1px solid color-mix(in srgb, var(--isis-success, #16a34a) 40%, transparent);
}
.isis-devis-detail__history-btn {
    appearance: none;
    display: inline-flex;
    align-items: center;
    gap: 2px;
    padding: 0.18rem 0.35rem;
    background: color-mix(in srgb, var(--isis-accent) 10%, var(--isis-surface));
    color: var(--isis-accent);
    border: 1px solid color-mix(in srgb, var(--isis-accent) 30%, transparent);
    border-radius: 4px;
    font-size: 0.72rem;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    cursor: pointer;
    transition: background-color 120ms ease, color 120ms ease;
}
.isis-devis-detail__history-btn:hover {
    background: color-mix(in srgb, var(--isis-accent) 18%, var(--isis-surface));
}
.isis-devis-detail__history-btn.is-expanded {
    background: var(--isis-accent);
    color: var(--isis-surface, #ffffff);
    border-color: var(--isis-accent);
}
.isis-devis-detail__history-btn.is-expanded:hover {
    background: color-mix(in srgb, var(--isis-accent) 85%, black);
}

/* Récap activités opérationnelles sur le bordereau en lecture seule
   (DevisDetail.razor, onglet Lignes) — résumé compact sous la désignation. */
.isis-devis-detail__acti-summary {
    display: flex;
    align-items: center;
    gap: 5px;
    margin-top: 3px;
    font-size: 0.72rem;
    color: var(--isis-text-soft);
}
.isis-devis-detail__acti-summary .rz-icon { color: var(--isis-mod-gescom); font-size: 12px !important; }
.isis-devis-detail__acti-summary strong { color: var(--isis-text-muted); font-weight: 600; }

/* Bouton chevron : même gabarit que .isis-devis-detail__history-btn ci-dessus,
   teinte module (gescom) plutôt que l'accent générique de l'historique — les
   deux actions doivent rester visuellement distinctes au premier coup d'oeil
   (même problème déjà résolu sur l'onglet Coût de revient, cf. isis-grid__action-btn--has-resources). */
.isis-devis-detail__acti-btn {
    appearance: none;
    display: inline-flex;
    align-items: center;
    gap: 2px;
    padding: 0.18rem 0.35rem;
    background: var(--isis-mod-gescom-soft);
    color: var(--isis-mod-gescom);
    border: 1px solid color-mix(in srgb, var(--isis-mod-gescom) 30%, transparent);
    border-radius: 4px;
    font-size: 0.72rem;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    cursor: pointer;
    transition: background-color 120ms ease, color 120ms ease;
}
.isis-devis-detail__acti-btn:hover {
    background: color-mix(in srgb, var(--isis-mod-gescom) 22%, var(--isis-surface));
}
.isis-devis-detail__acti-btn.is-expanded {
    background: var(--isis-mod-gescom);
    color: var(--isis-surface, #ffffff);
    border-color: var(--isis-mod-gescom);
}
.isis-devis-detail__acti-btn.is-expanded:hover {
    background: color-mix(in srgb, var(--isis-mod-gescom) 85%, black);
}

/* Zone dépliée « activités opérationnelles » d'une ligne : le contenu est rendu
   par <DevisLigneActivites> (classes .isis-ligne-acti, en fin de fichier). Ici
   ne reste que le calage de la zone sous la colonne Désignation. AUCUN fond :
   le bloc tient par son rail gauche (maquette validée le 2026-09-23) — un
   background ici ré-imposerait l'aplat gris qui a été écarté. */
.isis-devis-detail__acti-row > div {
    padding: 6px 10px 10px 34px;
}
.isis-devis-items__action-count {
    font-size: 0.7rem;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}

/* Bouton « mise en forme » des lignes SECTION/COMMENT. La pastille dit qu'un réglage
   s'écarte du défaut du type — sans elle, rien ne distingue une ligne réglée d'une
   ligne par défaut tant que la modale n'est pas ouverte. */
.isis-devis-items__action--style {
    position: relative;
}
.isis-devis-items__action--style.is-set {
    color: var(--isis-accent);
    border-color: color-mix(in srgb, var(--isis-accent) 35%, transparent);
}
.isis-devis-items__action-dot {
    position: absolute;
    top: 2px;
    right: 2px;
    width: 5px;
    height: 5px;
    border-radius: 50%;
    background: var(--isis-accent);
}

/* Bouton bulk « Appliquer N ajustements » dans le footer toolbar. */
.isis-devis-items__add--apply-reaj {
    background: color-mix(in srgb, var(--isis-success, #16a34a) 12%, var(--isis-surface)) !important;
    color: var(--isis-success, #16a34a) !important;
    border-color: color-mix(in srgb, var(--isis-success, #16a34a) 35%, transparent) !important;
    border-style: solid !important;
    font-weight: 600;
    margin-left: auto;
}
.isis-devis-items__add--apply-reaj:hover {
    background: color-mix(in srgb, var(--isis-success, #16a34a) 22%, var(--isis-surface)) !important;
    box-shadow: inset 0 0 0 1px var(--isis-success, #16a34a) !important;
}

/* Lignes filles d'historique d'ajustements (Phase 5 v2). Indentées, fond
   surface-alt, typo plus petite, icône trending colorée. */
.isis-devis-items tbody tr.isis-devis-items__history-row td {
    background: var(--isis-surface-alt, var(--isis-surface-alt));
    border-top: 1px dashed var(--isis-border-soft, var(--isis-border));
    padding: 0.25rem 0.45rem;
    font-size: 0.74rem;
    color: var(--isis-text-muted);
}
.isis-devis-items__history-tree {
    color: var(--isis-text-soft, #94a3b8);
    margin-right: 0.25rem;
    font-family: monospace;
}
.isis-devis-items__history-label {
    color: var(--isis-text);
    font-weight: 500;
    margin-left: 0.3rem;
}
.isis-devis-items__history-reason {
    font-style: italic;
    margin-left: 0.35rem;
}
.isis-devis-items__history-pu,
.isis-devis-items__history-margin {
    font-variant-numeric: tabular-nums;
    color: var(--isis-text);
}

/* Drag & drop des lignes (SortableJS) — handle + états visuels */
.isis-devis-items__drag-cell {
    text-align: center;
    width: 28px;
    padding-left: 0 !important;
    padding-right: 0 !important;
}
.isis-devis-items__drag-handle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--isis-text-soft, #94a3b8);
    cursor: grab;
    padding: 0.2rem;
    border-radius: 4px;
    user-select: none;
}
.isis-devis-items__drag-handle:hover {
    color: var(--isis-text-muted, #475569);
    background: var(--isis-surface-soft);
}
.isis-devis-items__drag-handle:active {
    cursor: grabbing;
}
/* États SortableJS pendant le drag */
.isis-devis-items__row--ghost {
    opacity: 0.4;
    background: var(--isis-accent-soft, rgba(75, 95, 173, 0.08)) !important;
}
.isis-devis-items__row--ghost td {
    background: transparent !important;
}
.isis-devis-items__row--chosen {
    background: var(--isis-surface-soft) !important;
}
.isis-devis-items__row--drag {
    box-shadow: 0 6px 12px rgba(0, 0, 0, 0.08);
}
/* Deuxième définition de .isis-devis-items__action dans cette feuille (la première
   est ligne ~5402) — même spécificité, celle-ci gagne en cascade pour TOUTE propriété
   qu'elle redéclare, pas seulement `border` : `padding` (0.2rem ici contre 0.2rem
   0.35rem là-bas) et les DEUX couleurs de :hover (background et color, cf. plus bas)
   sont tout aussi mortes dans la première définition. Trouvé pendant le lifting du
   2026-09-15 en cherchant pourquoi fixer le border de la PREMIÈRE définition n'avait
   aucun effet visible — revue de code du même jour : le premier commentaire ne
   nommait que `border`, ce qui aurait fait perdre du temps à quiconque toucherait
   ensuite au padding ou aux couleurs de survol là-bas en les croyant à part.
   Pas consolidées ici (gap/transition/justify-content diffèrent entre les deux,
   risque de régression hors périmètre du lifting) — mais c'est ICI qu'il faut éditer
   border/padding/couleur/fond pour que ça se voie à l'écran. */
.isis-devis-items__action {
    background: none;
    /* Contour visible au repos (lifting 2026-09-15, retour « boutons effacés en fin de
       ligne ») — avant, l'affordance n'existait qu'au survol (anti-pattern DESIGN.md). */
    border: 1px solid var(--isis-border);
    color: var(--isis-text-muted, #475569);
    cursor: pointer;
    padding: 0.2rem;
    border-radius: 4px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    /* WCAG 2.2 — 2.5.8 (AA) : 24x24 minimum. Mesuré à 22x22 le 2026-09-22, et les
       boutons se touchent dans la cellule, donc l'exception d'espacement ne joue pas. */
    min-width: 24px;
    min-height: 24px;
}
.isis-devis-items__action:hover {
    background: var(--isis-surface-soft);
    color: var(--isis-accent, #4b5fad);
}

/* Fusion ligne (migration 0113) — tag mère / fille + indentation visuelle */
.isis-merge-tag {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    padding: 0.1rem 0.4rem;
    border-radius: 10px;
    font-size: 0.68rem;
    font-weight: 500;
    margin-right: 0.4rem;
    vertical-align: middle;
}
.isis-merge-tag.is-child {
    background: var(--isis-surface-soft);
    color: var(--isis-text-muted, #475569);
}
.isis-merge-tag.is-parent {
    background: rgba(75, 95, 173, 0.08);
    color: var(--isis-accent, #4b5fad);
}
.isis-devis-items tbody tr.is-merge-child td {
    background: rgba(241, 245, 249, 0.6);
}
.isis-devis-items tbody tr.is-merge-parent td {
    border-top: 1px solid var(--isis-accent-soft, rgba(75, 95, 173, 0.2));
}

/* Ligne SECTION / COMMENT de l'éditeur d'offre de prix (migration 0119 pour le
   style, refonte du 2026-09-22 pour la disposition, simplification du 2026-09-23).
   La cellule Désignation absorbe par colspan toutes les colonnes chiffrées jusqu'à
   MARGE. Elle ne contient plus qu'UNE chose : le champ de saisie, sur toute sa
   largeur. Ce qui l'encombrait est parti ailleurs — le marqueur de type sur le
   déclencheur de réglages, le sous-total en ligne de clôture de section, la barre
   B/I/couleurs/taille dans une modale (DevisLineStyleDialog). Il n'y a donc plus
   de conteneur flex ici, ni de plafond de largeur : celui-ci n'existait que pour
   garder le sous-total dans le cadre visible.                                     */

/* La cellule fusionnée doit sortir du figeage de la colonne Désignation (sticky à
   left:234px, largeur bornée à 240px, ombre de bord droit) : sans cette annulation
   le colspan n'élargit rien et le bord figé coupe la cellule en plein milieu.
   Le [data-col] est répété ici EXPRÈS : sans lui la règle vaut (0,3,2), à égalité avec
   celle qui pose l'ombre de bord figé plus bas dans le fichier — mesuré, l'ombre
   survivait. Avec lui, (0,4,2) gagne quel que soit l'ordre des règles.             */
.isis-grid--devis-items-edit.isis-devis-items--gridskin tbody td[data-col="designation"].isis-devis-items__structural-cell {
    position: static;
    left: auto;
    width: auto;
    min-width: 0;
    max-width: none;
    box-shadow: none;
}

/* Type d'une ligne de structure, porté par le déclencheur de réglages à la place du
   « + » (2026-09-23) : S pour une section, C pour un commentaire. Une initiale, pas
   une étiquette — le libellé complet vit dans le title et l'aria-label du bouton, et
   le badge de statut reste réservé aux statuts (DESIGN.md). Même gabarit que l'icône
   qu'elle remplace pour que la colonne ne bouge pas d'une ligne à l'autre.          */
.isis-devis-items__linesettings-letter {
    position: absolute;
    top: -5px;
    left: -5px;
    min-width: 13px;
    height: 13px;
    padding: 0 2px;
    display: grid;
    place-items: center;
    border-radius: var(--isis-radius-pill);
    border: 1px solid var(--isis-border-strong);
    background: var(--isis-surface-alt);
    color: var(--isis-text-muted);
    font-family: var(--isis-font-mono);
    font-size: 10px;
    font-weight: 700;
    line-height: 1;
    letter-spacing: 0;
}

/* Modale de mise en forme d'une ligne de structure. */
.isis-line-style__preview {
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
    margin-bottom: 0.25rem;
}
.isis-line-style__preview-label {
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--isis-text-muted);
}
.isis-line-style__preview-band {
    border: 1px dashed var(--isis-border);
    border-radius: var(--isis-radius, 6px);
    padding: 0.6rem 0.75rem;
    min-height: 2.25rem;
    display: flex;
    align-items: center;
    overflow-wrap: anywhere;
}
.isis-line-style__toggles {
    display: flex;
    gap: 0.35rem;
}
.isis-line-style__toggle {
    appearance: none;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    color: var(--isis-text-muted);
    border-radius: var(--isis-radius-sm, 4px);
    min-width: 40px;
    height: 32px;
    padding: 0 0.6rem;
    font-size: 0.9rem;
    line-height: 1;
    cursor: pointer;
    font-family: var(--isis-font, inherit);
}
.isis-line-style__toggle:hover {
    background: var(--isis-surface-soft);
    border-color: var(--isis-text-muted);
    color: var(--isis-text);
}
.isis-line-style__toggle:focus-visible {
    outline: 2px solid var(--isis-current-mod, var(--isis-accent));
    outline-offset: 1px;
}
.isis-line-style__toggle.is-active {
    background: var(--isis-accent-soft);
    border-color: var(--isis-accent);
    color: var(--isis-accent);
}
.isis-line-style__color {
    appearance: none;
    -webkit-appearance: none;
    width: 100%;
    height: 32px;
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-sm, 4px);
    padding: 2px;
    cursor: pointer;
    background: var(--isis-surface);
}
.isis-line-style__color::-webkit-color-swatch-wrapper { padding: 0; }
.isis-line-style__color::-webkit-color-swatch { border: none; border-radius: 3px; }
.isis-line-style__color::-moz-color-swatch { border: none; border-radius: 3px; }
.isis-line-style__color:focus-visible {
    outline: 2px solid var(--isis-current-mod, var(--isis-accent));
    outline-offset: 1px;
}
.isis-line-style__size {
    width: 100%;
    height: 32px;
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-sm, 4px);
    padding: 0 0.5rem;
    font-size: 0.85rem;
    background: var(--isis-surface);
    color: var(--isis-text);
    font-variant-numeric: tabular-nums;
}
.isis-line-style__size:focus-visible {
    outline: 2px solid var(--isis-current-mod, var(--isis-accent));
    outline-offset: 1px;
}
.isis-line-style__hint {
    margin: 0;
    font-size: 0.78rem;
    line-height: 1.45;
    color: var(--isis-text-muted);
}

/* Tag entreprise — distingue Titulaire des cotraitants */
.isis-entreprise-tag {
    display: inline-block;
    padding: 0.15rem 0.5rem;
    border-radius: 10px;
    font-size: 0.7rem;
    font-weight: 500;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 100%;
}

.isis-entreprise-tag.is-titulaire {
    background: var(--isis-surface-soft);
    color: var(--isis-text-muted, #475569);
}
.isis-entreprise-tag.is-partner {
    /* Câblé en dur (dette DESIGN.md §10), remplacé par le token le 2026-09-15. Le texte
       (#b45309) correspond exactement à --isis-warning ; le fond utilisait un autre
       orange (#d97706, à 10% d'opacité) — résidu d'une valeur antérieure de
       --isis-warning (cf. les nombreux `var(--isis-warning, #d97706)` de repli ailleurs
       dans cette feuille). Un seul token pour le couple fond/texte est plus correct que
       préserver l'incohérence à deux teintes. */
    background: color-mix(in srgb, var(--isis-warning) 10%, transparent);
    color: var(--isis-warning);
}

/* ── Récap conversion devis (onglet « Conversion », migrations 0140/0141) ── */
.isis-conversion-recap-header {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    padding: 0.5rem;
    background: var(--isis-surface-alt, var(--isis-surface-alt));
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius);
    margin-bottom: 0.5rem;
}
.isis-conversion-recap-header__pill {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.3rem 0.6rem;
    border-radius: var(--isis-radius-pill);
    font-size: 0.78rem;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    color: var(--isis-text);
}
.isis-conversion-recap-header__pill strong {
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    color: var(--isis-text);
}
.isis-conversion-recap-header__pill.is-commande {
    border-color: rgba(75, 95, 173, 0.35);
    color: #3b4d8a;
    background: rgba(75, 95, 173, 0.06);
}
.isis-conversion-recap-header__pill.is-st-int {
    border-color: rgba(217, 119, 6, 0.35);
    color: #8f5700;
    background: rgba(217, 119, 6, 0.06);
}
.isis-conversion-recap-header__pill.is-st-ext {
    border-color: rgba(194, 65, 12, 0.35);
    color: #9a3412;
    background: rgba(194, 65, 12, 0.06);
}
.isis-conversion-recap-header__pill.is-cot-ext {
    border-color: rgba(22, 163, 74, 0.35);
    color: #166534;
    background: rgba(22, 163, 74, 0.06);
}

/* ============================================================================
   Tableur des lignes de devis (lot 2 de la refonte visuelle, 2026-09-22).
   Grille de SAISIE, pas de lecture : filets horizontaux, colonnes figées, champs effacés au repos —
   écarts à DESIGN.md consignés §5 (« Exceptions assumées de la fiche devis »).
   Préfixe à double classe : il gagne sur l'habillage gridskin quel que soit l'ordre.
   ============================================================================ */
.isis-grid--devis-items-edit.isis-devis-items--gridskin {
    border: 0;
    border-radius: 0;
    border-collapse: separate;
    border-spacing: 0;
}
/* Filets horizontaux seuls (2026-10-02) : le quadrillage vertical encombrait sans rien
   apprendre — l'alignement des colonnes suffit à les lire. Seul le bord des colonnes figées
   reste, en ombre intérieure (plus bas). */
.isis-grid--devis-items-edit.isis-devis-items--gridskin th,
.isis-grid--devis-items-edit.isis-devis-items--gridskin td {
    border-right: 0;
    border-bottom: 1px solid var(--isis-border-soft);
}

/* Rangée des familles de colonnes, puis rangée des en-têtes, toutes deux collées en haut. */
.isis-grid--devis-items-edit.isis-devis-items--gridskin thead tr.isis-devis-items__groups > * {
    position: sticky;
    top: 0;
    z-index: 4;
    height: 26px;
    padding: 0 0.5rem;
    background: var(--isis-surface);
    border-bottom: 1px solid var(--isis-border);
    color: var(--isis-text-muted);
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    white-space: nowrap;
    text-align: left;
}
.isis-grid--devis-items-edit.isis-devis-items--gridskin thead tr.isis-devis-items__groups > .isis-devis-items__group--frozen {
    left: 0;
    z-index: 6;
    box-shadow: inset -2px 0 0 var(--isis-border-strong);
}
.isis-devis-items__group--frozen .rzi {
    font-size: 13px;
    vertical-align: -2px;
    margin-right: 0.25rem;
}
.isis-grid--devis-items-edit.isis-devis-items--gridskin thead tr:not(.isis-devis-items__groups) th {
    top: 26px;
    z-index: 3;
    height: 30px;
    padding: 0 0.5rem;
    font-size: 10.5px;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    white-space: nowrap;
    border-bottom: 1px solid var(--isis-border);
}

/* Colonnes figées : N° 36 · réglages 38 · Désignation 300 (la colonne « Code » a cédé
   la place à la pastille de la cellule N°). Le bord de figeage
   est une ombre intérieure et non une bordure : une bordure de cellule collante disparaît
   au défilement horizontal. */
.isis-grid--devis-items-edit.isis-devis-items--gridskin th[data-col="num"],
.isis-grid--devis-items-edit.isis-devis-items--gridskin td[data-col="num"] {
    position: sticky;
    left: 0;
    width: 36px;
    min-width: 36px;
    max-width: 36px;
}
.isis-grid--devis-items-edit.isis-devis-items--gridskin th[data-col="reglages"],
.isis-grid--devis-items-edit.isis-devis-items--gridskin td.isis-devis-items__linesettings-cell {
    position: sticky;
    left: 36px;
    width: 38px;
    min-width: 38px;
    max-width: 38px;
}
.isis-grid--devis-items-edit.isis-devis-items--gridskin th[data-col="designation"],
.isis-grid--devis-items-edit.isis-devis-items--gridskin td[data-col="designation"] {
    position: sticky;
    left: 74px;
    width: 300px;
    min-width: 300px;
    max-width: 300px;
}
.isis-grid--devis-items-edit.isis-devis-items--gridskin tbody td[data-col="num"],
.isis-grid--devis-items-edit.isis-devis-items--gridskin tbody td.isis-devis-items__linesettings-cell,
.isis-grid--devis-items-edit.isis-devis-items--gridskin tbody td[data-col="designation"] {
    z-index: 2;
    background: var(--isis-devis-row-bg);
}
.isis-grid--devis-items-edit.isis-devis-items--gridskin thead th[data-col="num"],
.isis-grid--devis-items-edit.isis-devis-items--gridskin thead th[data-col="reglages"],
.isis-grid--devis-items-edit.isis-devis-items--gridskin thead th[data-col="designation"] {
    z-index: 6;
}
.isis-grid--devis-items-edit.isis-devis-items--gridskin .isis-devis-items__frozen-edge,
.isis-grid--devis-items-edit.isis-devis-items--gridskin tbody td[data-col="designation"] {
    box-shadow: inset -2px 0 0 var(--isis-border-strong);
}

/* Sous-lignes (répartition du coût, historique) : leurs deux premières cellules couvrent
   les colonnes figées et doivent rester collées avec elles. */
.isis-grid--devis-items-edit.isis-devis-items--gridskin tr.isis-costing-row-alloc > td:first-child:not(.isis-costing-row__acti-cell),
.isis-grid--devis-items-edit.isis-devis-items--gridskin tr.isis-devis-items__history-row > td:first-child {
    position: sticky;
    left: 0;
    z-index: 2;
    background: var(--isis-devis-row-bg);
}
.isis-grid--devis-items-edit.isis-devis-items--gridskin tr.isis-costing-row-alloc > td:first-child + td,
.isis-grid--devis-items-edit.isis-devis-items--gridskin tr.isis-devis-items__history-row > td:first-child + td {
    position: sticky;
    left: 74px;
    z-index: 2;
    background: var(--isis-devis-row-bg);
    box-shadow: inset -2px 0 0 var(--isis-border-strong);
}

/* Fond des cellules figées : une variable par état de ligne, pour qu'elles masquent ce qui
   défile dessous tout en suivant la teinte de la ligne. Les sections gagnent sur le survol. */
.isis-grid--devis-items-edit.isis-devis-items--gridskin tbody tr {
    --isis-devis-row-bg: var(--isis-surface);
}
.isis-grid--devis-items-edit.isis-devis-items--gridskin tbody tr.is-optional {
    --isis-devis-row-bg: color-mix(in srgb, var(--isis-accent-soft) 35%, var(--isis-surface));
}
.isis-grid--devis-items-edit.isis-devis-items--gridskin tbody tr.is-merge-child {
    --isis-devis-row-bg: var(--isis-surface-soft);
}
.isis-grid--devis-items-edit.isis-devis-items--gridskin tbody tr:hover {
    --isis-devis-row-bg: var(--isis-current-mod-soft, var(--isis-mod-gescom-soft, var(--isis-surface-alt)));
}
.isis-grid--devis-items-edit.isis-devis-items--gridskin tbody tr.is-structural {
    --isis-devis-row-bg: var(--isis-surface-soft);
}
/* Ligne de sous-total posee : rangee de synthese, plus appuyee qu'une section. Les deux regles
   vivent ICI, apres `.is-structural` : un SOUS_TOTAL porte AUSSI `is-structural`, et a
   specificite egale c'est la position dans le fichier qui tranche. La 2e vise le <td> parce que
   le fond d'une ligne de structure est peint sur la cellule, pas sur le <tr>. */
.isis-grid--devis-items-edit.isis-devis-items--gridskin tbody tr.is-subtotal {
    --isis-devis-row-bg: var(--isis-surface-alt);
}
.isis-devis-items tbody tr.is-subtotal td {
    background: var(--isis-surface-alt);
    color: var(--isis-text);
    font-weight: 600;
}
.isis-devis-items tbody tr.is-subtotal td .rz-textarea,
.isis-devis-items tbody tr.is-subtotal td .rz-textbox { font-weight: 600; }

/* Sous-total POSÉ dont le montant ou la plage vient de changer sous un glisser-déposer
   (Task 13). Le halo porte sur les <td>, pas sur le <tr> : leur fond est opaque (règle
   ci-dessus) et masquerait une animation posée sur la rangée. `to` revient à
   --isis-surface-alt (le fond au repos de ces cellules), jamais à transparent, sinon la
   rangée clignote en fin de course.
   --isis-current-mod-soft n'est PAS définie sur :root (l. 678/733/748 : shell du module
   seulement) et l'éditeur vit dans un dialogue Radzen monté hors du shell : un var() sans
   repli y est invalide et le navigateur jette la déclaration ENTIÈRE — le halo ne s'est
   jamais affiché, pas plus que sa variante « mouvement réduit ». Repli obligatoire sur un
   jeton défini sur :root, aux DEUX déclarations. */
@keyframes isis-subtotal-pulse {
    from { background-color: var(--isis-current-mod-soft, var(--isis-mod-gescom-soft, var(--isis-surface-alt))); }
    to   { background-color: var(--isis-surface-alt); }
}
.isis-grid--devis-items-edit.isis-devis-items--gridskin tbody tr.is-subtotal.is-subtotal-changed > td {
    animation: isis-subtotal-pulse 1.6s ease-out;
}
@media (prefers-reduced-motion: reduce) {
    .isis-grid--devis-items-edit.isis-devis-items--gridskin tbody tr.is-subtotal.is-subtotal-changed > td {
        animation: none;
        background-color: var(--isis-current-mod-soft, var(--isis-mod-gescom-soft, var(--isis-surface-alt)));
    }
}
/* Triangle des points à corriger, à côté de l'indicateur d'enregistrement (DevisItemsAnomaliesMenu). */
.isis-devis-anomalies__btn {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    height: 28px;
    padding: 0 8px;
    border: 1px solid var(--isis-danger);
    border-radius: var(--isis-radius-pill);
    background: var(--isis-danger-soft);
    color: var(--isis-danger-text);
    font: inherit;
    font-size: 0.8rem;
    font-weight: 600;
    cursor: pointer;
}
.isis-devis-anomalies__btn .rzi { font-size: 16px; }
.isis-devis-anomalies__btn:hover,
.isis-devis-anomalies__btn.is-active { background: var(--isis-surface); }
.isis-devis-anomalies__btn:focus-visible {
    outline: 2px solid var(--isis-current-mod);
    outline-offset: 2px;
}
.isis-devis-anomalies__panel { min-width: 300px; }
.isis-devis-items__announce {
    min-height: 1.25rem;
    padding: 0 var(--isis-space-md);
    font-size: var(--isis-fs-sm);
    color: var(--isis-text-muted);
}
/* Vide, la région reste dans le DOM (elle annonce encore) sans réserver de rangée. */
.isis-devis-items__announce:empty { min-height: 0; }

/* Le liseré de marge passe de la ligne à la cellule N° : la cellule figée le masquerait. */
.isis-grid--devis-items-edit.isis-devis-items--gridskin tbody tr[class*="is-margin-"] {
    box-shadow: none;
}
.isis-grid--devis-items-edit.isis-devis-items--gridskin tbody tr.is-margin-on-target > td[data-col="num"]    { box-shadow: inset 3px 0 0 0 var(--isis-success); }
.isis-grid--devis-items-edit.isis-devis-items--gridskin tbody tr.is-margin-below-target > td[data-col="num"] { box-shadow: inset 3px 0 0 0 var(--isis-warning); }
.isis-grid--devis-items-edit.isis-devis-items--gridskin tbody tr.is-margin-below-floor > td[data-col="num"]  { box-shadow: inset 3px 0 0 0 var(--isis-danger); }
.isis-grid--devis-items-edit.isis-devis-items--gridskin tbody tr.is-margin-above-max > td[data-col="num"]    { box-shadow: inset 3px 0 0 0 var(--isis-accent); }

/* ── Champ de saisie DANS une ligne de grille, sous `.isis-form-linear` ──────────
   `.isis-form-linear` pose `background: var(--isis-surface-alt) !important` sur tout
   champ (règle « formulaire linéaire », plus haut) : dans un formulaire c'est ce qui
   dessine le champ, mais dans une ligne de tableau ou de grille le champ se retrouve
   gris sur une ligne elle-même teintée (survol, sélection, ligne de structure, ligne
   fusionnée) et ne se distingue plus — 1,02:1 mesuré sur l'éditeur d'offre de prix le
   2026-09-22. La règle est donc généralisée ici à TOUTE ligne de grille, pas seulement
   à l'écran d'où vient le signalement. Sa portée n'est pas une liste d'écrans à tenir à
   jour mais une clé : elle est accrochée au MÊME ancêtre `.isis-form-linear` que la règle
   qui pose le gris — partout où la cause existe la correction existe, y compris quand la
   classe vient d'un composant parent. Mesuré le 2026-09-23 : 60 fichiers `.razor` posent
   un champ Radzen dans une cellule, dont 28 portent `.isis-form-linear` dans le même
   fichier ; les 32 autres l'héritent (couverts) ou ne l'ont pas (pas de gris à corriger).
   Hors de portée, délibérément : les lignes qui ne sont ni `td` ni `.isis-grid__row`
   (`.isis-filter-panel__row`), qui ne portent aucune emphase de ligne à ce jour.
   Spécificité (0,3,0) / (0,5,0) en survol : au-dessus des (0,2,0) / (0,4,0) de
   `.isis-form-linear`, donc indépendante de l'ordre des règles.
   Le focus garde la règle `.isis-form-linear … :focus`, qui pose déjà la surface.    */
.isis-form-linear :is(td, .isis-grid__row) :is(.rz-textbox, .rz-numeric, .rz-dropdown, .rz-multiselect, .rz-textarea, .rz-datepicker),
.isis-form-linear :is(td, .isis-grid__row) :is(.rz-textbox, .rz-numeric, .rz-dropdown, .rz-multiselect, .rz-textarea, .rz-datepicker):hover:not(:focus) {
    background: var(--isis-surface) !important;
}

/* Cellules de saisie : 36 px. Champ EFFACÉ au repos (2026-10-02) — sans fond ni contour, il
   se lit comme la valeur qu'il porte ; le survol de la LIGNE lui rend surface et contour
   léger, le survol du champ un contour franc, le focus le halo de cellule (plus bas).
   `!important` imposé par la règle de champ de `.isis-form-linear`, ancêtre de l'éditeur.
   Spécificité (0,3,2) tenue SOUS celle du champ désactivé (0,4,0) : le remplissage qui dit
   « non éditable » survit au repos. */
.isis-grid--devis-items-edit.isis-devis-items--gridskin tbody td {
    height: 36px;
    padding: 2px 0.35rem;
}
.isis-grid--devis-items-edit.isis-devis-items--gridskin tbody td :is(.rz-textbox, .rz-numeric, .rz-dropdown, .rz-textarea, .rz-datepicker) {
    background: transparent !important;
    border-color: transparent !important;
    box-shadow: none;
}
/* Un dropdown Radzen porte TOUJOURS un `input` caché en lecture seule
   (`.rz-helper-hidden-accessible`) : la règle « champ non éditable » plus bas, qui lit
   `:has(input[readonly])`, le prend pour un champ désactivé et le peint en remplissage.
   Ici (0,4,2) au-dessus de ses (0,4,1) ; seul `.rz-state-disabled` dit qu'il l'est. */
.isis-grid--devis-items-edit.isis-devis-items--gridskin tbody td .rz-dropdown:not(.rz-state-disabled) {
    background: transparent !important;
    border-color: transparent !important;
}
/* Le survol exclut les champs non éditables : à (0,5,3) il passerait sinon au-dessus de
   leur remplissage. Même exception du dropdown que ci-dessus. */
.isis-grid--devis-items-edit.isis-devis-items--gridskin tbody tr:hover td :is(.rz-textbox, .rz-numeric, .rz-dropdown, .rz-textarea, .rz-datepicker):not(.rz-state-disabled, :disabled, [readonly]):not(:not(.rz-dropdown):has(input:is(:disabled, [readonly]))) {
    background: var(--isis-surface) !important;
    border-color: var(--isis-border-soft) !important;
}
.isis-grid--devis-items-edit.isis-devis-items--gridskin tbody tr:hover td :is(.rz-textbox, .rz-numeric, .rz-dropdown, .rz-textarea, .rz-datepicker):not(.rz-state-disabled, :disabled, [readonly]):not(:not(.rz-dropdown):has(input:is(:disabled, [readonly]))):hover {
    border-color: var(--isis-border-strong) !important;
}
/* Le PU dérivé d'une grille de paliers n'est pas un champ à remplir : le remplissage y
   devient le signal de lecture seule, maintenant que les champs voisins sont sur la
   surface. Jeton plein plutôt que le `color-mix` de `.isis-pu-cell.is-derived`, qui sort
   à ~1,10:1 du blanc — trop peu pour se lire comme un état. */
.isis-grid--devis-items-edit.isis-devis-items--gridskin tbody td .isis-pu-cell.is-derived .rz-numeric,
.isis-grid--devis-items-edit.isis-devis-items--gridskin tbody td .isis-pu-cell.is-derived .rz-numeric:hover {
    background: var(--isis-surface-alt) !important;
    border-color: var(--isis-border-soft, var(--isis-border)) !important;
}

/* ── Champ NON ÉDITABLE dans une ligne de grille ────────────────────────────────
   Les deux règles ci-dessus peignent tout champ sur la surface : appliquées telles
   quelles, elles effaçaient aussi le remplissage par lequel Radzen dit « désactivé »
   (`--rz-input-disabled-background-color`, vendor material-base). Et ce repli-là est
   le seul : `--rz-input-disabled-opacity` vaut 1, l'opacité ne rattrape rien. Sans ce
   bloc, une quantité figée (ligne forfait), un REAJ% verrouillé par une marge ST ou un
   champ désactivé de l'un des 17 autres écrans se lisait comme un champ à remplir.
   Deux formes de rendu à couvrir : `.rz-textbox`/`.rz-textarea` SONT le champ et
   portent l'attribut ; `.rz-numeric`/`.rz-dropdown`/`.rz-datepicker` sont des
   enveloppes dont l'attribut vit sur l'`input` interne — d'où le `:has()`.
   Spécificité : (0,4,0) et (0,5,0) au survol, au-dessus des (0,3,2)/(0,4,2) de la
   règle de l'éditeur d'offre de prix, donc indépendante de l'ordre des règles.
   Le PU dérivé ci-dessus en est le cas particulier (`is-derived` ⇔ `ReadOnly`) :
   même jeton, même contour — il est gardé parce qu'il vise la cellule, pas l'état. */
.isis-form-linear :is(td, .isis-grid__row) :is(.rz-textbox, .rz-numeric, .rz-dropdown, .rz-multiselect, .rz-textarea, .rz-datepicker):is(.rz-state-disabled, :disabled, [readonly]),
.isis-form-linear :is(td, .isis-grid__row) :is(.rz-numeric, .rz-dropdown, .rz-multiselect, .rz-datepicker):has(input:is(:disabled, [readonly])),
.isis-form-linear :is(td, .isis-grid__row) :is(.rz-textbox, .rz-numeric, .rz-dropdown, .rz-multiselect, .rz-textarea, .rz-datepicker):is(.rz-state-disabled, :disabled, [readonly]):hover,
.isis-form-linear :is(td, .isis-grid__row) :is(.rz-numeric, .rz-dropdown, .rz-multiselect, .rz-datepicker):has(input:is(:disabled, [readonly])):hover {
    background: var(--isis-field-disabled-bg) !important;
    border-color: var(--isis-field-disabled-border) !important;
}
.isis-grid--devis-items-edit.isis-devis-items--gridskin tbody td[data-col]:focus-within,
.isis-grid--devis-items-edit.isis-devis-items--gridskin tbody td.isis-devis-items__calc:focus {
    outline: 2px solid var(--isis-current-mod, var(--isis-mod-gescom));
    outline-offset: -2px;
}
.isis-grid--devis-items-edit.isis-devis-items--gridskin tbody td[data-col]:focus-within :is(.rz-textbox, .rz-numeric, .rz-dropdown, .rz-textarea),
.isis-grid--devis-items-edit.isis-devis-items--gridskin tbody td[data-col]:focus-within :is(input, textarea):focus-visible {
    box-shadow: none;
    outline: none;
}
.isis-grid--devis-items-edit.isis-devis-items--gridskin tbody td[data-col]:focus-within :is(.rz-textbox, .rz-numeric, .rz-dropdown, .rz-textarea):focus-within {
    background: var(--isis-surface) !important;
    border-color: var(--isis-border-strong) !important;
}
/* Une cellule figée active passe au-dessus des lignes suivantes (le menu des réglages et la
   liste de choix d'article s'ouvrent sous elle), mais reste sous les en-têtes figés (6). */
.isis-grid--devis-items-edit.isis-devis-items--gridskin tbody td[data-col="num"]:focus-within,
.isis-grid--devis-items-edit.isis-devis-items--gridskin tbody td.isis-devis-items__linesettings-cell:focus-within,
.isis-grid--devis-items-edit.isis-devis-items--gridskin tbody td[data-col="designation"]:focus-within {
    z-index: 5;
}
/* Sauf menu OUVERT. Le panneau est en position:fixed; z-index:931, mais son ancêtre <td>
   est une colonne figée (position:sticky; z-index) : le 931 est donc résolu DANS le
   contexte de la cellule, pas dans celui de la page, et à 5 le menu passait sous les
   en-têtes de groupe figés (6), qui interceptaient jusqu'aux clics (mesuré au navigateur
   le 2026-09-23). Le cran ne vaut que le temps de l'ouverture — une cellule simplement
   au focus n'a aucune raison de recouvrir les en-têtes.
   Posé APRÈS la règle :focus-within, et pas avant : même spécificité (0,4,2), donc
   c'est la POSITION qui tranche — et le menu ouvert garde le focus dans la cellule. */
.isis-grid--devis-items-edit.isis-devis-items--gridskin tbody td.isis-devis-items__linesettings-cell.is-menu-open {
    z-index: 12;
}

/* Cellule N° : le numéro, remplacé par la poignée au survol de la ligne. */
.isis-grid--devis-items-edit.isis-devis-items--gridskin td.isis-devis-items__num {
    text-align: center;
    font-family: var(--isis-font-mono);
    font-size: 12px;
    color: var(--isis-text-muted);
    font-variant-numeric: tabular-nums;
}
.isis-grid--devis-items-edit.isis-devis-items--gridskin td.isis-devis-items__num .isis-devis-items__drag-handle {
    display: none;
}
.isis-grid--devis-items-edit.isis-devis-items--gridskin tbody tr:hover td.isis-devis-items__num .isis-devis-items__num-value {
    display: none;
}
.isis-grid--devis-items-edit.isis-devis-items--gridskin tbody tr:hover td.isis-devis-items__num .isis-devis-items__drag-handle {
    display: inline-flex;
}

/* Colonnes calculées et sous-total de section : chiffres alignés. */
.isis-grid--devis-items-edit.isis-devis-items--gridskin td.isis-devis-items__calc {
    font-family: var(--isis-font-mono);
    font-size: 12.5px;
    font-variant-numeric: tabular-nums;
}
/* Sous-total d'une section : rangée de CLÔTURE, posée après la dernière ligne du bloc
   (2026-09-23). Il a d'abord vécu sous « Total HT » — il s'y lisait comme le total
   d'une ligne vendable —, puis dans la cellule de texte de l'en-tête de section — il
   y annonçait un montant avant les lignes qui le composent. Ici, il ferme le bloc.
   Le LIBELLÉ tient dans la bande FIGÉE (même collage que les sous-lignes de coût et
   d'historique, ci-dessus) : la table fait 1 724 px et défile, et la rangée entière
   posée sous « Total HT » (x ≈ 1 274 px) ne montrait qu'un bandeau gris vide. Le
   MONTANT, lui, reste dans sa colonne « Total HT », aligné sous les montants qu'il
   additionne — il se lit au même défilement qu'eux (arbitrage du 2026-09-23).
   Rangée calculée : aucune ligne de devis ne lui correspond en base, donc ni poignée
   de déplacement, ni sélection, ni action.                                          */
.isis-grid--devis-items-edit.isis-devis-items--gridskin tbody tr.isis-devis-items__subtotal-row > td {
    background: var(--isis-surface-alt);
    border-top: 1px solid var(--isis-border);
    padding-top: 0.3rem;
    padding-bottom: 0.3rem;
}
.isis-grid--devis-items-edit.isis-devis-items--gridskin tbody tr.isis-devis-items__subtotal-row > td.isis-devis-items__subtotal-cell {
    position: sticky;
    left: 0;
    z-index: 2;
    box-shadow: inset -2px 0 0 var(--isis-border-strong);
}
.isis-devis-items__subtotal-label {
    display: block;
    font-size: 0.78rem;
    font-weight: 600;
    color: var(--isis-text-muted);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.isis-grid--devis-items-edit.isis-devis-items--gridskin tbody tr.isis-devis-items__subtotal-row > td.isis-devis-items__subtotal-amount {
    font-family: var(--isis-font-mono);
    font-size: 12.5px;
    font-weight: 600;
    color: var(--isis-text);
    font-variant-numeric: tabular-nums;
    text-align: right;
    white-space: nowrap;
}

/* ---------------------------------------------------------------------------------
   Allègement de l'éditeur (maquette validée le 2026-10-02) : le calme au repos, le détail
   au geste. Tout ce qui ne se lit qu'en agissant (flèches, carré de simulation du PU,
   réglages, poubelle rouge) apparaît au survol ou au focus de la ligne ; sur écran tactile,
   où le survol n'existe pas, tout reste affiché.
   --------------------------------------------------------------------------------- */
/* Flèches des champs numériques. */
.isis-grid--devis-items-edit.isis-devis-items--gridskin tbody .rz-numeric :is(.rz-numeric-up, .rz-numeric-down, .rz-numeric-button) {
    opacity: 0;
    transition: opacity 0.12s;
}
.isis-grid--devis-items-edit.isis-devis-items--gridskin tbody .rz-numeric:is(:hover, :focus-within) :is(.rz-numeric-up, .rz-numeric-down, .rz-numeric-button) {
    opacity: 1;
}
/* Carré de simulation du PU et pictogramme des réglages. Les pastilles d'état du bouton de
   réglages (option, paliers, nature fiscale) et l'initiale d'une ligne de structure restent
   visibles : ce sont des signaux, pas des gestes. */
.isis-grid--devis-items-edit.isis-devis-items--gridskin tbody .isis-pu-cell__calc {
    border-color: transparent;
    background: transparent;
    color: var(--isis-text-soft);
    opacity: 0;
    transition: opacity 0.12s;
}
.isis-grid--devis-items-edit.isis-devis-items--gridskin tbody .isis-devis-items__linesettings-btn {
    border-color: transparent;
    background: transparent;
}
.isis-grid--devis-items-edit.isis-devis-items--gridskin tbody .isis-devis-items__linesettings-btn > :is(.rzi, .isis-devis-items__linesettings-letter) {
    opacity: 0;
    transition: opacity 0.12s;
}
.isis-grid--devis-items-edit.isis-devis-items--gridskin tbody tr:is(:hover, :focus-within) .isis-pu-cell__calc,
.isis-grid--devis-items-edit.isis-devis-items--gridskin tbody tr:is(:hover, :focus-within) .isis-devis-items__linesettings-btn > :is(.rzi, .isis-devis-items__linesettings-letter),
.isis-grid--devis-items-edit.isis-devis-items--gridskin tbody .isis-devis-items__linesettings-btn.is-active > :is(.rzi, .isis-devis-items__linesettings-letter) {
    opacity: 1;
}
.isis-grid--devis-items-edit.isis-devis-items--gridskin tbody tr:is(:hover, :focus-within) .isis-devis-items__linesettings-btn {
    border-color: var(--isis-border);
}
.isis-grid--devis-items-edit.isis-devis-items--gridskin tbody .isis-pu-cell__calc:hover {
    border-color: var(--isis-border);
    color: var(--isis-text);
}
/* Poubelle : grise au repos, rouge au geste. */
.isis-grid--devis-items-edit.isis-devis-items--gridskin tbody .isis-devis-items__remove {
    color: var(--isis-text-soft);
}
.isis-grid--devis-items-edit.isis-devis-items--gridskin tbody .isis-devis-items__remove:is(:hover, :focus-visible):not(:disabled) {
    color: var(--isis-danger);
    background: var(--isis-danger-soft, var(--isis-surface-soft));
}
@media (hover: none) {
    .isis-grid--devis-items-edit.isis-devis-items--gridskin tbody .rz-numeric :is(.rz-numeric-up, .rz-numeric-down, .rz-numeric-button),
    .isis-grid--devis-items-edit.isis-devis-items--gridskin tbody .isis-pu-cell__calc,
    .isis-grid--devis-items-edit.isis-devis-items--gridskin tbody .isis-devis-items__linesettings-btn > :is(.rzi, .isis-devis-items__linesettings-letter) {
        opacity: 1;
    }
}
@media (prefers-reduced-motion: reduce) {
    .isis-grid--devis-items-edit.isis-devis-items--gridskin tbody :is(.rz-numeric-up, .rz-numeric-down, .rz-numeric-button, .isis-pu-cell__calc, .isis-devis-items__linesettings-btn > .rzi, .isis-devis-items__linesettings-letter) {
        transition: none;
    }
}
/* Entreprise : la titulaire est le cas par défaut, elle ne s'affiche plus — seule une autre
   entreprise (cotraitant, sous-traitant) se lit dans la colonne. Le libellé reste pour les
   lecteurs d'écran. Le sélecteur, lui, reste un champ : effacé au repos comme les autres,
   son texte passe en sourdine quand il désigne la titulaire. */
.isis-grid--devis-items-edit.isis-devis-items--gridskin tbody .isis-entreprise-tag.is-titulaire {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}
.isis-grid--devis-items-edit.isis-devis-items--gridskin tbody tr:not(:hover, :focus-within) .isis-imputation-picker.is-titulaire :is(.rz-dropdown-label, .rz-dropdown-trigger) {
    color: var(--isis-text-soft);
}
/* Section en bandeau : fond léger, filet plus marqué, titre en graisse — sans champ encadré. */
.isis-grid--devis-items-edit.isis-devis-items--gridskin tbody tr.is-section > td {
    border-bottom-color: var(--isis-border);
}
.isis-grid--devis-items-edit.isis-devis-items--gridskin tbody tr.is-section .rz-textarea {
    font-weight: 600;
}
/* Le titre n'a pas de padding vertical : son texte colle au haut d'un champ de 35 px. Centré
   sur la boîte, le numéro tombait 7 px sous la première ligne — on l'aligne sur elle. */
.isis-grid--devis-items-edit.isis-devis-items--gridskin tbody tr.is-section .isis-devis-section-num {
    align-self: flex-start;
    margin-top: 1px;
    line-height: calc(0.9rem * 1.4);
}
/* Désignation obligatoire manquante : cadre rouge porté par l'enveloppe, visible au repos.
   Un outline se peint au-dessus du champ, sans lutter contre les règles du champ effacé. */
.isis-grid--devis-items-edit.isis-devis-items--gridskin tbody .isis-row-desc.is-invalid {
    outline: 1px solid var(--isis-danger);
    outline-offset: -1px;
    border-radius: var(--isis-radius-sm);
    background: var(--isis-danger-soft);
}
.isis-grid--devis-items-edit.isis-devis-items--gridskin tbody tr.is-section .isis-row-desc.is-invalid {
    padding-left: 4px;
}
.isis-grid--devis-items-edit.isis-devis-items--gridskin tbody .isis-row-desc.is-invalid textarea::placeholder {
    color: var(--isis-danger-text);
    opacity: 1;
}
/* Pastille de rattachement au catalogue : coin haut gauche de la cellule N°, à droite de la
   barre de marge (3 px), jamais dessus. Bleu = rattachée ; rouge = rattachable, non rattachée. */
.isis-grid--devis-items-edit.isis-devis-items--gridskin td.isis-devis-items__num .isis-devis-items__pastille {
    position: absolute;
    top: 5px;
    left: 7px;
}
.isis-devis-items__pastille {
    display: block;
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--isis-info);
}
.isis-devis-items__pastille.is-unlinked {
    background: var(--isis-danger);
}
.isis-devis-items__pastille.is-inline {
    display: inline-block;
    flex: 0 0 auto;
    margin-top: 5px;
}
/* Le menu hérite du centrage de la cellule de réglages : on le rend à la lecture. */
.isis-devis-items__linesettings-cell .isis-toolbar-dropdown__panel {
    text-align: start;
}
.isis-row-link__unlinked {
    display: flex;
    align-items: flex-start;
    gap: 0.5rem;
    padding: 0.4rem 0.75rem;
    font-size: 0.8rem;
    color: var(--isis-text);
}
.isis-row-link__unlinked .isis-toolbar-menu__hint {
    display: block;
}

/* ---------------------------------------------------------------------------------
   Découpage en 4 niveaux (0903). Le niveau se lit AU RETRAIT et au numéro (1.2), à rien
   d'autre : ni couleur propre, ni taille propre, ni ombre (DESIGN.md §2). `data-cran` vaut
   le cran posé par le marcheur : une section et ses sous-totaux au cran de leur parent, les
   lignes qu'elle contient un cran plus loin (0 à 4).
   --------------------------------------------------------------------------------- */
:root {
    --isis-devis-retrait: 16px;
}
@media (max-width: 559.98px) {
    :root { --isis-devis-retrait: 8px; }
}
:is(.isis-grid--devis-items-edit, #devis-panel-items, .isis-devis-carte, .isis-devis-lines-list)[data-cran="1"],
:is(.isis-grid--devis-items-edit, #devis-panel-items, .isis-devis-lines-list) [data-cran="1"] { --isis-devis-cran: 1; }
:is(.isis-grid--devis-items-edit, #devis-panel-items, .isis-devis-carte, .isis-devis-lines-list)[data-cran="2"],
:is(.isis-grid--devis-items-edit, #devis-panel-items, .isis-devis-lines-list) [data-cran="2"] { --isis-devis-cran: 2; }
:is(.isis-grid--devis-items-edit, #devis-panel-items, .isis-devis-carte, .isis-devis-lines-list)[data-cran="3"],
:is(.isis-grid--devis-items-edit, #devis-panel-items, .isis-devis-lines-list) [data-cran="3"] { --isis-devis-cran: 3; }
:is(.isis-grid--devis-items-edit, #devis-panel-items, .isis-devis-carte, .isis-devis-lines-list)[data-cran="4"],
:is(.isis-grid--devis-items-edit, #devis-panel-items, .isis-devis-lines-list) [data-cran="4"] { --isis-devis-cran: 4; }

/* Tableur : la cellule de désignation (fusionnée par colspan sur une ligne de structure),
   puis la rangée de clôture. Padding sur le conteneur flex, jamais sur le champ : il occupe
   100 % de la cellule et déborderait. */
.isis-grid--devis-items-edit tbody tr[data-cran] > td[data-col="designation"] > .isis-row-desc,
.isis-grid--devis-items-edit tbody tr.isis-devis-items__subtotal-row[data-cran] .isis-devis-items__subtotal-label {
    padding-inline-start: calc(var(--isis-devis-cran, 0) * var(--isis-devis-retrait));
}

.isis-devis-section-num {
    flex: 0 0 auto;
    align-self: center;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    color: var(--isis-text);
}

/* Fiche, grille : tout le contenu de la cellule de désignation — une prestation y empile
   sa mention « code · type » et son libellé, qui se décalent ensemble. */
#devis-panel-items .isis-grid__row[data-cran] > .isis-devis-ligne__desig > * {
    margin-inline-start: calc(var(--isis-devis-cran, 0) * var(--isis-devis-retrait));
}

/* Fiche, cartes (< 560 px) : le CONTENU se décale, pas la carte — son filet et son fond
   restent alignés sur la liste. Liste compacte : le libellé. */
.isis-devis-carte[data-cran] {
    padding-inline-start: calc(1rem + var(--isis-devis-cran, 0) * var(--isis-devis-retrait));
}
.isis-devis-lines-list__row[data-cran] .isis-devis-lines-list__label,
.isis-devis-lines-list__subtotal[data-cran] .isis-devis-lines-list__subtotal-label {
    padding-inline-start: calc(var(--isis-devis-cran, 0) * var(--isis-devis-retrait));
}

/* Barre de formule : adresse de la cellule, valeur entière, calcul du Total HT. */
.isis-devis-formula {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: 0.6rem;
    min-height: 44px;
    padding: 0 0.75rem;
    border: 1px solid var(--isis-border);
    border-bottom: 0;
    border-radius: 6px 6px 0 0;
    background: var(--isis-surface);
    min-width: 0;
}
.isis-devis-formula + .isis-devis-items-dialog__lines-scroll,
.isis-devis-formula + .isis-devis-items-dialog__work > .isis-devis-items-dialog__lines-scroll {
    border-top-left-radius: 0;
    border-top-right-radius: 0;
}
.isis-devis-formula__address {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    min-width: 150px;
    height: 28px;
    padding: 0 0.5rem;
    border: 1px solid var(--isis-border);
    border-radius: 4px;
    background: var(--isis-surface-alt);
    font-family: var(--isis-font-mono);
    font-size: 12.5px;
    color: var(--isis-text);
}
.isis-devis-formula__fx {
    flex: 0 0 auto;
    font-style: italic;
    color: var(--isis-text-muted);
}
.isis-devis-formula__value {
    flex: 1 1 auto;
    min-width: 0;
    font-size: 13.5px;
    color: var(--isis-text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.isis-devis-formula__value--empty {
    color: var(--isis-text-muted);
}
.isis-devis-formula__calc {
    flex: 0 1 auto;
    min-width: 0;
    font-family: var(--isis-font-mono);
    font-size: 12.5px;
    color: var(--isis-text-muted);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/* Écrans courts (portables 13-14" : ~890 px de zone utile) — l'invite « Placez-vous
   dans une cellule… » coûte 44 px de barre, soit une ligne de tableur, pour une phrase
   qui ne se lit qu'une fois. Tant qu'aucune cellule n'a eu le focus, la barre s'efface ;
   elle revient au premier focus et y reste (le composant garde la dernière cellule) —
   un seul décalage par session, au moment où la barre commence à servir. */
@media (max-height: 1000px) {
    /* Masquage VISUEL seulement (mêmes déclarations que .isis-sr-only), jamais `display: none` :
       la barre est une région `aria-live`, et une région live absente de l'arbre d'accessibilité
       au chargement n'est pas enregistrée — la première valeur de cellule ne serait pas annoncée. */
    .isis-devis-formula.is-empty {
        position: absolute;
        width: 1px;
        height: 1px;
        padding: 0;
        margin: -1px;
        overflow: hidden;
        clip: rect(0, 0, 0, 0);
        white-space: nowrap;
        border: 0;
    }
}

/* Rappel des touches, sous la grille. Inutile sans clavier physique. */
.isis-devis-items__kbd-hints {
    flex: 0 0 auto;
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem 1rem;
    padding: 0.4rem 0.1rem 0;
    font-size: 12px;
    color: var(--isis-text-muted);
}
.isis-devis-items__kbd-hints kbd {
    display: inline-block;
    padding: 0 0.3rem;
    border: 1px solid var(--isis-border);
    border-bottom-width: 2px;
    border-radius: 4px;
    background: var(--isis-surface);
    font-family: var(--isis-font-mono);
    font-size: 11px;
    color: var(--isis-text);
}
@media (hover: none) {
    .isis-devis-items__kbd-hints { display: none; }
}

/* Table simple réutilisable pour les récaps (non liée à .isis-grid div-based) */
/* ============================================================================
   Compléments .isis-recap-table — sous-onglet Résumé de la fiche devis (2026-09-07)
   La bande de quatre tuiles KPI a été dissoute : ses valeurs sont devenues une
   troisième table de récapitulatif, homogène aux deux qui existaient déjà.
   ============================================================================ */

/* État vide propre au récapitulatif. Auparavant .isis-grid__empty était emprunté
   dans un composant sans aucune .isis-grid — un couplage qui aurait cassé au
   premier changement du patron grid. */
.isis-recap-table__empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.35rem;
    padding: 1.5rem 1rem;
    color: var(--isis-text-muted);
    font-size: 0.82rem;
    text-align: center;
}
.isis-recap-table__empty strong {
    font-weight: 600;
    color: var(--isis-text);
}

/* Conteneur défilable — DESIGN.md : un contenu large défile dans SON conteneur, le
   corps de page jamais. Mesuré le 2026-09-07 : la « Synthèse par participant » fait
   882 px dans un panneau de 754, en overflow visible — ses colonnes Marge et Marge %
   étaient coupées ET inatteignables, faute de barre de défilement. Défaut antérieur
   à la dissolution de la bande KPI, corrigé en passant. */
.isis-recap-table__scroll {
    overflow-x: auto;
    max-width: 100%;
}

/* Glose de ligne : ce que disaient les .isis-sr-only des tuiles, rendu visible. */
.isis-recap-table__gloss {
    color: var(--isis-text-muted);
    font-size: 0.74rem;
}

/* Ligne de résultat : c'est elle qui porte la couleur sémantique. */
.isis-recap-table__total th,
.isis-recap-table__total td {
    border-top: 1px solid var(--isis-border);
    font-weight: 600;
}
.isis-recap-table__pct {
    margin-left: 0.5rem;
    font-weight: 500;
    color: var(--isis-text-muted);
}

.isis-recap-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.82rem;
}
.isis-recap-table thead th {
    text-align: left;
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    font-size: 0.65rem;
    color: var(--isis-text-muted);
    padding: 0.45rem 0.55rem;
    border-bottom: 1px solid var(--isis-border);
    background: var(--isis-surface-alt, var(--isis-surface-alt));
    white-space: nowrap;
}
.isis-recap-table tbody td {
    padding: 0.4rem 0.55rem;
    border-bottom: 1px solid var(--isis-border-soft, #f1f2f5);
    vertical-align: middle;
}
.isis-recap-table tbody tr:hover {
    background: var(--isis-surface-soft);
}
.isis-recap-table tbody tr.is-total td {
    background: var(--isis-surface-alt, var(--isis-surface-alt));
    font-weight: 600;
    border-top: 2px solid var(--isis-border);
}

/* Récap financier (en tête de l'onglet Conversion d'un devis) — synthèse vente/coût/marge. */
.isis-conversion-recap-financial {
    margin: 0.75rem 0 0.5rem;
    padding: 0.75rem;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius);
}
.isis-conversion-recap-financial__head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.75rem;
    margin-bottom: 0.5rem;
}
.isis-conversion-recap-financial__head h2 {
    margin: 0;
    font-size: 0.95rem;
    font-weight: 600;
    color: var(--isis-text);
}
.isis-conversion-recap-financial__warning {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    font-size: 0.75rem;
    color: #8f5700;
}
.isis-recap-table--financial tbody tr.is-source td {
    background: var(--isis-surface-alt, var(--isis-surface-alt));
    border-bottom: 2px solid var(--isis-border);
}
.isis-recap-table--financial tbody tr.is-marge td {
    background: rgba(75, 95, 173, 0.05);
    border-top: 2px solid var(--isis-border);
    font-weight: 500;
}
.isis-recap-table--financial tbody tr.is-marge.is-negative td {
    background: rgba(220, 38, 38, 0.06);
    color: var(--isis-danger, #dc2626);
}
.isis-conversion-recap-financial__balance {
    margin-top: 0.6rem;
    padding: 0.4rem 0.6rem;
    border-radius: var(--isis-radius);
    font-size: 0.78rem;
}
.isis-conversion-recap-financial__balance .is-ok {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    color: var(--isis-success, #16a34a);
}
.isis-conversion-recap-financial__balance .is-warn {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    color: #8f5700;
}

/* Onglet Résumé du devis (Tâche 11) — synthèse participant + ventilation
   structure interne + préparation des lots de conversion. */
.isis-devis-resume {
    display: flex;
    flex-direction: column;
    gap: 1.4rem;
    padding: 0.2rem 0.1rem 0.6rem;
}
.isis-devis-resume__section { min-width: 0; }

/* Rail KPI compact : le Résumé est une page de lecture dense, les totaux y sont un
   repère, pas le sujet. Mêmes proportions que le rail d'en-tête (.isis-rich-header__kpis),
   et les explications passent en lecteur d'écran plutôt que d'occuper une 3e ligne. */
.isis-kpi-hero--compact { padding: 0.5rem 0.75rem; }
.isis-kpi-hero--compact .isis-kpi-card { padding: 0.1rem 0.6rem; gap: 0.05rem; }
.isis-kpi-hero--compact .isis-kpi-card:first-child { padding-left: 0.2rem; }
.isis-kpi-hero--compact .isis-kpi-card__label { font-size: 0.62rem; }
.isis-kpi-hero--compact .isis-kpi-card__value { font-size: 1.15rem; }

/* Dropdowns du tableau des lots : hauteur 32px, alignée sur les inputs du tableau des lignes
   de devis (.isis-devis-items tbody). Un dropdown à sa hauteur par défaut fait exploser la
   hauteur de ligne dans un tableau dense. */
.isis-devis-resume__lots .rz-dropdown,
.isis-devis-resume__lots .rz-dropdown .rz-dropdown-label {
    height: 32px;
    min-height: 32px;
    max-height: 32px;
    box-sizing: border-box;
    line-height: 1.4;
    font-size: 0.8125rem;
}
.isis-devis-resume__lots .rz-dropdown {
    display: inline-flex;
    justify-content: center;
    padding: 0 0.5rem;
    width: 100%;
    max-width: 260px;
}
.isis-devis-resume__lots .rz-dropdown .rz-dropdown-trigger { width: 22px; }

/* Note d'avertissement SANS encadrement : les liserés décoratifs autour des encarts sont
   proscrits (DESIGN.md §1). L'icône et la couleur sémantique portent le signal. */
.isis-devis-resume__note {
    display: flex;
    align-items: flex-start;
    gap: 0.45rem;
    margin-top: 0.6rem;
    font-size: 0.82rem;
    color: var(--isis-text-muted);
}
.isis-devis-resume__note.is-warn { color: var(--isis-warning); }
.isis-devis-resume__note.is-danger { color: var(--isis-danger); }
.isis-devis-resume__note a { color: inherit; text-decoration: underline; }
.isis-devis-resume__row-unassigned td:first-child {
    font-style: italic;
    color: var(--isis-text-muted);
}
.isis-devis-resume__lots th,
.isis-devis-resume__lots td { vertical-align: top; }
.isis-devis-resume__lot-cell {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.35rem;
    min-width: 220px;
    padding-top: 0.15rem;
}
.isis-devis-resume__chips {
    display: flex;
    flex-wrap: wrap;
    gap: 0.3rem;
    margin-top: 0.15rem;
}
.isis-devis-resume__tag {
    display: inline-flex;
    align-items: center;
    height: 20px;
    padding: 0 0.5rem;
    border-radius: var(--isis-radius-pill);
    background: var(--isis-surface-alt);
    border: 1px solid var(--isis-border);
    color: var(--isis-text-muted);
    font-size: 0.68rem;
    white-space: nowrap;
}

/* Picker d'imputation analytique d'une ligne devis (saisie libre, migration 0140) */
.isis-imputation-picker {
    font-size: 0.7rem;
}
.isis-imputation-picker.is-partner :deep(.rz-inputtext) {
    color: #8f5700;
    font-weight: 500;
}

/* Hint sous une cellule de grille (info contextuelle) */
.isis-grid__hint--info {
    color: var(--isis-text-muted, #475569);
    font-size: 0.7rem;
    line-height: 1.2;
}

/* Picker fusion — liste de candidats cliquables */
.isis-merge-candidates {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
}
.isis-merge-candidates__item {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.6rem 0.75rem;
    background: var(--isis-surface, #fff);
    border: 1px solid var(--isis-border, var(--isis-border));
    border-radius: 6px;
    cursor: pointer;
    text-align: left;
    transition: all 0.12s ease;
}
.isis-merge-candidates__item:hover {
    border-color: var(--isis-accent, #4b5fad);
    background: var(--isis-surface-soft);
}
.isis-merge-candidates__position {
    font-weight: 600;
    color: var(--isis-text-muted, #475569);
    font-size: 0.85rem;
    flex-shrink: 0;
    min-width: 32px;
}
.isis-merge-candidates__main {
    flex: 1;
    min-width: 0;
}
.isis-merge-candidates__desc {
    font-size: 0.85rem;
    color: var(--isis-text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.isis-merge-candidates__meta {
    font-size: 0.72rem;
    color: var(--isis-text-muted, #475569);
    margin-top: 0.1rem;
}
.isis-devis-items__add-row {
    display: flex;
    gap: 0.4rem;
    margin-top: 0.6rem;
}
.isis-devis-items__add {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0.35rem 0.7rem;
    background: transparent;
    /* border-style identique au repos et au hover : évite le "saut" de
       layout dû au rendu pixel différent dashed vs solid sur certains browsers.
       Le hover utilise box-shadow inset pour simuler une bordure solide
       expressive sans déformer la box. */
    border: 1px dashed var(--isis-border);
    border-radius: 6px;
    font-size: 0.72rem;
    color: var(--isis-text-muted);
    cursor: pointer;
    transition: background-color 140ms ease, color 140ms ease,
                box-shadow 140ms ease, transform 90ms ease;
}
.isis-devis-items__add:hover {
    background: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 10%, var(--isis-surface));
    color: var(--isis-current-mod, var(--isis-accent));
    /* Anneau interne solide en couleur module : effet "pastille allumée"
       sans agrandir la box (box-shadow ne participe pas au layout, ≠ border). */
    box-shadow: inset 0 0 0 1px var(--isis-current-mod, var(--isis-accent)),
                0 1px 2px rgba(15, 23, 42, 0.06);
}
.isis-devis-items__add:active {
    /* Feedback tactile au clic : très léger enfoncement (transform translateY
       n'affecte pas le layout des frères) + ombre réduite. */
    transform: translateY(1px);
    box-shadow: inset 0 0 0 1px var(--isis-current-mod, var(--isis-accent));
}

/* Boîte de gauche du bloc « Remise globale et totaux », symétrique à .isis-devis-totals
   de droite (lifting 2026-09-15) — même fond/bordure/radius, le champ Remise globale
   ne flotte plus seul face à un bloc totaux encadré. */
.isis-devis-remise-box {
    background: var(--isis-surface-soft);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-lg, 10px);
    box-shadow: var(--isis-elevation-1, 0 1px 3px rgba(15, 23, 42, 0.06));
    padding: 0.85rem 1rem;
}
.isis-devis-totals {
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
    font-size: 0.82rem;
    background: var(--isis-surface-soft);
    padding: 0.85rem 1rem;
    border-radius: var(--isis-radius-lg, 10px);
    /* Traitement carte (DESIGN.md §4) — ce bloc porte le Total TTC, la donnée la plus
       importante du dialogue, mais n'avait ni bordure ni élévation (lifting 2026-09-15,
       signalé « terne »). Partagé par DevisFormDialog et DevisDetail (3 écrans) : un
       seul changement ici les corrige tous. */
    border: 1px solid var(--isis-border);
    box-shadow: var(--isis-elevation-1, 0 1px 3px rgba(15, 23, 42, 0.06));
}
.isis-devis-totals__row {
    display: flex;
    justify-content: space-between;
    font-variant-numeric: tabular-nums;
    /* DESIGN.md §3 : tout montant financier en police mono — cette ligne en texte brut
       était la seule exception (les RadzenNumeric du tableau l'héritent déjà). */
    font-family: var(--isis-font-mono, 'Geist Mono', monospace);
}
.isis-devis-totals__row--ttc {
    padding-top: 0.4rem;
    margin-top: 0.2rem;
    border-top: 1px solid var(--isis-border);
    font-size: 0.95rem;
    font-weight: 600;
    color: var(--isis-text);
}

/* Bloc des trois périmètres d'option (EF-54) — seconde carte sous la pile de totaux, pour
   que « Tout compris HT » ne se confonde pas avec le Total TTC contractuel juste au-dessus. */
.isis-devis-totals--perimetres {
    margin-top: 0.5rem;
    background: var(--isis-surface);
}

/* Split vertical du panneau latéral droit (TiersListPage) : aperçu en haut,
   activité récente en bas séparée par un trait. */
.isis-detail-split {
    display: flex;
    flex-direction: column;
    height: 100%;
    min-height: 0;
}
.isis-detail-split__top {
    flex: 0 0 auto;
    padding-bottom: 1rem;
    border-bottom: 1px solid var(--isis-border);
}
.isis-detail-split__middle {
    flex: 0 1 auto;
    padding: 0.85rem 0;
    border-bottom: 1px solid var(--isis-border);
    max-height: 35%;
    min-height: 80px;
    overflow-y: auto;
}
.isis-detail-split__bottom {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    padding-top: 0.85rem;
}
.isis-detail-split__title {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    font-size: 0.7rem;
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--isis-text-muted);
    margin-bottom: 0.5rem;
}
.isis-detail-split__title-action {
    margin-left: auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    border: 1px solid var(--isis-border);
    border-radius: 4px;
    background: transparent;
    color: var(--isis-text-muted);
    cursor: pointer;
    transition: background 0.12s, color 0.12s, border-color 0.12s;
}
.isis-detail-split__title-action:hover,
.isis-detail-split__title-action:focus-visible {
    /* Polish 2026-06 : était hardcodé sur gescompta (violet) → hover violet sur page bleue.
       Suit désormais la couleur du module courant. */
    background: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 8%, var(--isis-surface));
    color: var(--isis-current-mod, var(--isis-accent));
    border-color: var(--isis-current-mod, var(--isis-accent));
    outline: none;
}
.isis-detail-split__empty {
    font-size: 0.8rem;
    color: var(--isis-text-muted);
    padding: 0.5rem 0.2rem;
}
.isis-detail-split__empty kbd {
    display: inline-block;
    padding: 0 4px;
    font-family: inherit;
    font-size: 0.78rem;
    border: 1px solid var(--isis-border);
    border-radius: 3px;
    background: var(--isis-bg-soft, var(--isis-surface-alt));
    color: var(--isis-text);
}

/* Variante grille StructureTypeListPage : 6 colonnes (status / code / libellé / portée / ordre / actions) */
.isis-grid--structure-types .isis-grid__head,
.isis-grid--structure-types .isis-grid__row {
    grid-template-columns: 32px 140px minmax(220px, 1.6fr) 180px 90px 90px;
    /* min-width = somme des colonnes (752px), pas 820 : le forçage à 820 dépassait
       la carte maître (~790px) → overflow horizontal, et la colonne Ordre passait
       sous la colonne actions sticky (« 10 » rogné en « 1( »). */
    min-width: 752px;
}

/* Variante grille « Types de coûts transversaux » (référentiel gescom) : 7 colonnes
   (libellé / code / mode / base % / ordre / actif / actions). */
.isis-grid--overhead-types .isis-grid__head,
.isis-grid--overhead-types .isis-grid__row {
    grid-template-columns: minmax(200px, 2fr) 130px 140px 120px 70px 100px 110px;
    min-width: 960px;
}

/* Variante grille « Inducteurs de chiffrage » (referentiel gescom, 0821) : 6 colonnes
   (libelle / code / unite / ordre / actif / actions). min-width = somme exacte des
   colonnes (740px) : au-dela, la colonne actions sticky passe sous le bord de la carte. */
.isis-grid--inducteurs .isis-grid__head,
.isis-grid--inducteurs .isis-grid__row {
    grid-template-columns: minmax(200px, 2fr) 150px 110px 70px 100px 110px;
    min-width: 740px;
}

/* Variante grille « Bordereaux de prix client » (EF-37, 0846) : 6 colonnes
   (code / libellé / client / entreprise / en vigueur / actions). */
.isis-grid--bordereaux .isis-grid__head,
.isis-grid--bordereaux .isis-grid__row {
    grid-template-columns: 130px minmax(200px, 2fr) minmax(160px, 1.5fr) minmax(140px, 1fr) 190px 80px;
    min-width: 900px;
}

/* Variante grille « Gabarits de décomposition » (0975) : 7 colonnes
   (libellé / code / portée / sous-tâches / accroches / actif / actions). */
.isis-grid--gabarits .isis-grid__head,
.isis-grid--gabarits .isis-grid__row {
    grid-template-columns: minmax(200px, 2fr) 130px minmax(150px, 1fr) 110px 110px 100px 110px;
    min-width: 910px;
}

/* Variante grille « Activités opérationnelles » (référentiel gescom) : 5 colonnes
   (code / libellé / code analytique / statut / actions). */
.isis-grid--activite-operationnelle .isis-grid__head,
.isis-grid--activite-operationnelle .isis-grid__row {
    grid-template-columns: 120px minmax(200px, 2fr) minmax(180px, 1.5fr) 100px 100px;
    min-width: 760px;
}

/* Variante grille « Catalogue d'activités » (référentiel gescom, Correction 2) : 7
   colonnes (sélection / activité / libellé / statut / portée / tags / actions). */
.isis-grid--catalogue-activite .isis-grid__head,
.isis-grid--catalogue-activite .isis-grid__row {
    grid-template-columns: 32px minmax(150px, 1fr) minmax(200px, 1.5fr) 100px 140px minmax(160px, 1fr) 100px;
    min-width: 1080px;
}

/* Variante grille « Codes client » (référentiel gescom, chantier code client sur les
   lignes de devis, spec 2026-09-14) : 5 colonnes (tiers / article catalogue / code
   client / origine / actions). Sans cette règle la grille héritait du gabarit de
   base à 8 pistes (ligne 11093) — colonne « Tiers » écrasée dans une piste de
   32px, 3 pistes vides. Proportions calquées sur `--frais-cat` (même forme à 5
   colonnes : libellé flex, code, code, badge, actions). */
.isis-grid--codes-client .isis-grid__head,
.isis-grid--codes-client .isis-grid__row {
    grid-template-columns: minmax(200px, 1.6fr) 150px 150px 160px 100px;
    min-width: 760px;
}

/* Panneau outil autonome sous la grille (ex. Aperçu de la cascade) — même filet
   que .isis-tree-picker, élévation 1 comme les cartes du produit. */
.isis-card-panel {
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
    margin-top: 0.75rem;
    padding: 0.85rem 1rem;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius);
    box-shadow: var(--isis-elevation-1);
}

/* Cellule de grille à ellipsis — badge de portée sur nom d'entreprise long
   (référentiel activités opérationnelles / catalogues, Lot 1). */
.isis-grid__ellipsis-cell {
    display: inline-block;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    vertical-align: middle;
}

/* Chips de sélection (dialogue "Nouveau catalogue") et lignes de membre (panneau
   catalogue) — Lot 1 activités opérationnelles.
   NB : pas de règle `.isis-chip { ... }` ici — `.isis-chip` est déjà le composant
   "chip interactif" générique du produit (défini plus haut dans ce fichier, cursor:
   pointer + hover/focus-visible/active, utilisé par les entonnoirs, PorteeSelector,
   etc.). Une nouvelle règle `.isis-chip` à cet endroit se serait fait écraser par
   cette définition antérieure sur TOUTES les propriétés qu'elle repose (même
   spécificité, elle vient après dans la feuille) — CSS mort, cf. doctrine « Token
   CSS manquant / ordre source ». Le patron déjà établi pour un chip non cliquable
   est le modificateur `.isis-chip.is-static` (cf. `.isis-absence-cal__chip`/nav
   calendrier) : réutilisé tel quel dans le markup du dialogue plutôt que dupliqué. */
.isis-selected-chips {
    display: flex; flex-wrap: wrap; gap: 0.35rem; padding: 0.6rem;
    border: 1px dashed var(--isis-border); border-radius: 8px; background: var(--isis-surface-soft);
    max-height: 130px; overflow-y: auto;
}
.isis-membre-row {
    display: flex; align-items: center; gap: 0.5rem; padding: 0.35rem 0;
    border-bottom: 1px solid var(--isis-border-soft);
}
.isis-membre-row:last-child { border-bottom: none; }
.isis-membre-row > span:nth-child(2) { flex: 1; }
.isis-selection-bar {
    display: flex; align-items: center; justify-content: space-between;
    padding: 0.5rem 0.9rem; background: var(--isis-mod-gescom-soft, var(--isis-surface-alt));
    border: 1px solid var(--isis-border); border-radius: 8px; margin-bottom: 0.7rem; font-size: 0.85rem;
}
.isis-selection-bar__clear {
    background: none; border: none; text-decoration: underline; cursor: pointer;
    color: inherit; font: inherit; padding: 0;
}

/* Variante grille Catalogue : 9 colonnes (statut / code / article / nature de travail /
   entreprise / structure productrice / tarif / devise / actions).
   Nature et structure productrice sont les deux axes de lecture ajoutés le 2026-07-12 :
   « qui réalise cette prestation, et est-ce du terrain ou du bureau ». */
.isis-grid--catalogue .isis-grid__head,
.isis-grid--catalogue .isis-grid__row {
    grid-template-columns: 28px 100px minmax(170px, 1.5fr) 112px 120px 130px minmax(130px, 1fr) 105px 74px 76px;
    min-width: 1156px;
}

/* Variante grille « Zones de chantier » (commande, migration 0501) : 3 colonnes
   (libellé / localisation FR / actions). */
.isis-grid--chantier-zones .isis-grid__head,
.isis-grid--chantier-zones .isis-grid__row {
    grid-template-columns: minmax(200px, 2fr) 120px 80px;
    min-width: 400px;
}

/* Variante grille jalons AO (migration 0258) : 6 colonnes
   (type / description / statut / prévu / effectué / actions). Plancher à 1010 px : à 1100,
   l'onglet d'une fiche à 1440 px rognait la colonne d'actions de quelques pixels. */
.isis-grid--jalons .isis-grid__head,
.isis-grid--jalons .isis-grid__row {
    grid-template-columns: 200px minmax(160px, 2fr) 130px 150px 150px 220px;
    min-width: 1010px;
}
.isis-grid--jalons .isis-grid__row.is-effectue { opacity: 0.85; }
.isis-grid--jalons .isis-grid__row.is-annule   { opacity: 0.55; text-decoration: line-through; }
.isis-grid--jalons .isis-grid__row.is-reporte  {
    background: var(--isis-accent-soft);
}

/* Variante grille « Relances » de la fiche facture émise : 8 colonnes
   (date / canal / palier / auteur / destinataire / montant / note / actions). */
.isis-grid--facture-relances .isis-grid__head,
.isis-grid--facture-relances .isis-grid__row {
    grid-template-columns: 140px 150px 130px minmax(160px, 1fr) minmax(140px, 1fr) 140px minmax(160px, 2fr) 60px;
    min-width: 1080px;
}

/* Variante grille « Promesses » de la fiche facture émise : 7 colonnes
   (date promise / montant / issue / saisie le / auteur / note / actions). */
.isis-grid--facture-promesses .isis-grid__head,
.isis-grid--facture-promesses .isis-grid__row {
    grid-template-columns: 120px 140px 120px 140px minmax(160px, 1fr) minmax(160px, 2fr) 60px;
    min-width: 900px;
}

.isis-grid__action-btn .isis-relance-retrait-icon {
    font-size: 14px;
    color: var(--isis-text-muted);
}

/* Cellule de texte libre : retour à la ligne, mot long coupé, jamais de troncature. */
.isis-grid .isis-grid__row > div.isis-grid__wrap {
    white-space: normal;
    overflow: visible;
    overflow-wrap: anywhere;
    text-overflow: clip;
}

/* Variante grille MouvementsListPage : 5 colonnes (actif / type / de→vers / date / action) */
.isis-grid--mouvements .isis-grid__head,
.isis-grid--mouvements .isis-grid__row {
    /* 6 pistes pour 6 cellules d'en-tête : actif · module · type · de→vers · date · actions.
       Le compte doit tenir, sinon le configurateur de colonnes se désactive (il refuse un
       gabarit qu'il n'a pas compris plutôt que de masquer la mauvaise colonne). */
    grid-template-columns: minmax(200px, 2fr) 130px 160px minmax(200px, 2fr) 120px 140px;
    min-width: 1000px;
}

/* Variante grille AccrualRuleListPage : 8 colonnes (status / type / pays / période / j-mois / plafond / validité / actions) */
.isis-grid--accrual .isis-grid__head,
.isis-grid--accrual .isis-grid__row {
    grid-template-columns: 32px minmax(180px, 1.4fr) 110px 200px 90px 110px 180px 90px;
    min-width: 1040px;
}

/* Variante grille hub « Régimes & conventions » : 7 colonnes
   (entité / régime / durée coll. / modulation / contingent / date d'effet / périmètre). */
.isis-grid--regimes .isis-grid__head,
.isis-grid--regimes .isis-grid__row {
    grid-template-columns: 1.6fr 1.1fr .8fr .9fr .9fr 1fr .9fr;
    min-width: 920px;
}

/* Variante grille ExportPaiePage : 12 colonnes (matricule / collaborateur / effectif / HS /
   HS struct. / RTT / taux / majorations / forfaits / IK / frais TTC / total). Migrée depuis
   RadzenDataGrid (2026-09-03) : DESIGN.md réserve RadzenDataGrid à Master/* et aux dialogs
   techniques, et cette grille n'a jamais dépassé la population d'une entreprise sur un mois
   (référentiel borné, pas de pagineur). */
.isis-grid--export-paie .isis-grid__head,
.isis-grid--export-paie .isis-grid__row {
    grid-template-columns: minmax(90px, .8fr) minmax(160px, 1.6fr) 90px 80px 90px 80px 100px 110px 100px 90px 100px 120px;
    min-width: 1210px;
}

/* Carte « Défaut tenant » du hub des régimes. */
.isis-regime-default-card { margin-bottom: var(--isis-space-lg); }
.isis-regime-default-card__body {
    display: flex;
    align-items: center;
    gap: var(--isis-space-md);
}
.isis-regime-default-card__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    border-radius: var(--isis-radius-sm);
    flex: 0 0 auto;
}
.isis-regime-default-card__main { flex: 1 1 auto; min-width: 0; }
.isis-regime-default-card__label {
    font-size: var(--isis-fs-caption);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--isis-text-muted);
}
.isis-regime-default-card__summary {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.4rem;
    color: var(--isis-text);
}
.isis-regime-default-card__summary--empty { color: var(--isis-text-muted); }

/* Caractérisation des offres de prix (AO + demande) : sections segmentées
   « Offre de base + variantes » / « Optionnels (PSE) ».
   Grille à 6 colonnes : rôle (badges) / numéro / titre / statut / montant TTC / actions. */
.isis-offer-section {
    margin-bottom: 1.25rem;
}
.isis-offer-section:last-child {
    margin-bottom: 0;
}
.isis-offer-section__title {
    margin: 0 0 0.5rem;
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--isis-text);
    display: flex;
    align-items: baseline;
    gap: 0.4rem;
}
.isis-offer-section__count {
    font-weight: 500;
    color: var(--isis-text-muted);
    font-variant-numeric: tabular-nums;
}
.isis-grid--offers .isis-grid__head,
.isis-grid--offers .isis-grid__row {
    grid-template-columns: 160px 130px minmax(200px, 1.6fr) 140px 160px 80px;
    min-width: 870px;
}
.isis-grid--offers.isis-grid--offers-lots .isis-grid__head,
.isis-grid--offers.isis-grid--offers-lots .isis-grid__row {
    grid-template-columns: 160px minmax(140px, 1fr) 130px minmax(200px, 1.6fr) 140px 160px 80px;
    min-width: 1010px;
}
/* Cellule rôle : flex pour aligner badge rôle + pastille « retenue » sans clip
   (le parent .isis-grid__row > div applique overflow:hidden + nowrap). */
.isis-offer-row__role-cell {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.3rem;
    overflow: visible;
}
/* La cellule d'actions héberge un menu en position:absolute (Diffuser) ; le
   parent .isis-grid__row > div pose overflow:hidden → on le rétablit ici. */
.isis-grid--offers .isis-grid__actions {
    overflow: visible;
    position: relative;
}
/* Ligne sous-total (PSE) : non cliquable, fond surface-alt discret. */
.isis-grid__row.isis-offer-subtotal {
    background: var(--isis-surface-alt);
    border-top: 1px solid var(--isis-border);
    cursor: default;
}
/* Neutralise le hover « cliquable » (fond module + bordure gauche) hérité de
   .isis-grid__row:hover : cette ligne n'est pas interactive. */
.isis-grid__row.isis-offer-subtotal:hover {
    background: var(--isis-surface-alt);
    border-left: none;
}

/* Bloc de caractérisation d'offre (fiche devis, 0426) : toggles Variante/Optionnel + rappel consultation. */
.isis-offer-characterization {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--isis-space-md);
    margin-top: var(--isis-space-xs);
}
.isis-offer-characterization__chk {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
}

/* Enveloppe du champ de recherche d'une filter-bar : un CONTENEUR DE MISE EN PAGE
   (loupe + champ + effacement), jamais un cadre.

   Elle portait une bordure, un fond et un rayon — dans une barre qui a déjà les trois,
   et autour d'un <input> qui a les siens. Résultat mesuré au navigateur le 2026-09-02 :
   TROIS bordures imbriquées, toutes en --isis-border, toutes sur le même fond, sur les
   95 pages qui emploient cette barre. Deux pages seulement s'appuyaient sur l'ancien
   comportement (celles qui posent .isis-filter-bar__search-input, un champ sans bordure
   propre) : c'est désormais CE champ qui porte le cadre, pas son enveloppe. */
/* La boîte de `.isis-filter-bar__search` était déclarée DEUX fois dans ce fichier, ici et
   plus bas (~9089) : même sélecteur, même spécificité, donc la seconde gagnait et cette
   première n'avait aucun effet depuis qu'elle a été écrite. Retirée le 2026-09-03 — c'est
   un no-op strict, vérifié propriété par propriété (display, align-items, gap, min-width,
   max-width : toutes redéclarées plus bas). Les règles ENFANT ci-dessous, elles, servent
   toujours : trois écrans posent encore `__search-input` / `__search-clear`. */
.isis-filter-bar__search-input {
    flex: 1;
    min-width: 0;
    height: 32px;
    border: 1px solid var(--isis-border);
    border-radius: 8px;
    background: var(--isis-surface);
    padding: 0 0.7rem;
    outline: 0;
    font-family: inherit;
    font-size: 0.875rem;
    color: var(--isis-text);
}
.isis-filter-bar__search-input:focus { border-color: var(--isis-accent); }
.isis-filter-bar__search-input::placeholder {
    color: var(--isis-text-muted);
}
.isis-filter-bar__search-clear {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    border: 0;
    color: var(--isis-text-muted);
    cursor: pointer;
    padding: 2px;
    border-radius: 4px;
    /* WCAG 2.5.8 (AA, 24×24) : l'icône fait 14px et la marge 2px, soit 18×18 mesurés. Le
       bouton est FRÈRE de l'input dans une rangée haute de 32px — un plancher à 24 y tient
       sans changer la hauteur du champ. */
    min-width: 24px;
    min-height: 24px;
}
.isis-filter-bar__search-clear:hover,
.isis-filter-bar__search-clear:focus-visible {
    background: var(--isis-surface-alt);
    color: var(--isis-text);
}

/* ─────────────────────────────────────────────────────────────────────────
   Crans d'accès d'un rôle (RoleDetail.razor) — un écran par ligne.

   Ce n'est pas une liste de données mais un formulaire : chaque ligne porte
   un sélecteur et des cases. D'où une <ul> plutôt que .isis-grid, dont les
   rôles de table annonceraient un tableau à un lecteur d'écran là où il n'y a
   que des contrôles à parcourir.
   ───────────────────────────────────────────────────────────────────────── */
.isis-cran-module,
.isis-cran-copie {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 1rem;
    padding: 0.75rem 1rem;
    margin-bottom: 0.75rem;
    background: var(--isis-surface-alt);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius);
}
.isis-cran-module__text {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    flex: 1;
    min-width: 240px;
}
.isis-cran-module__label {
    font-size: 0.875rem;
    font-weight: 600;
    color: var(--isis-text);
}
.isis-cran-module__hint {
    font-size: 0.78rem;
    color: var(--isis-text-muted);
}
/* La NORME du module, en lecture. Elle se pose entre le titre du bloc et ce que le
   sélecteur fait : c'est l'état, pas l'action. Plus appuyée que la note grise — c'est la
   phrase la plus utile de l'onglet, et elle n'était écrite nulle part — sans devenir un
   titre : le contrôle reste le sélecteur. */
.isis-cran-module__norme {
    font-size: 0.82rem;
    font-weight: 500;
    color: var(--isis-text);
}

/* Le bouton « Annuler » d'un toast d'écriture. Il vit dans le `DetailContent` d'un
   `NotificationMessage`, donc hors de toute page : les tokens y sont les seuls repères. */
.isis-toast-undo {
    display: inline-flex;
    align-items: center;
    gap: 0.6rem;
    flex-wrap: wrap;
}
.isis-toast-undo__btn {
    /* Fond transparent et non `--isis-surface` : le toast a sa propre teinte de sévérité,
       et un aplat neutre par-dessus se lirait comme une pastille collée. */
    background: transparent;
    border: 1px solid currentColor;
    border-radius: var(--isis-radius-sm);
    color: inherit;
    /* WCAG 2.5.8 (AA) : 24 px de cible, atteints par le padding — le libellé seul fait 14 px
       de haut. Le compte est le même que pour les cases à cocher des lignes de cran. */
    padding: 0.2rem 0.55rem;
    min-height: 24px;
    font: inherit;
    font-size: 0.75rem;
    font-weight: 600;
    cursor: pointer;
}
.isis-toast-undo__btn:hover,
.isis-toast-undo__btn:focus-visible {
    background: color-mix(in srgb, currentColor 12%, transparent);
}
/* Le bloc de copie ne se règle pas, il REMPLACE : la copie purge la cible avant de
   recopier, si bien que ce que la source n'a pas est retiré. Il doit donc se distinguer du
   bloc « Cran du module » juste au-dessus — mais PAS en portant l'accent chaud au repos.

   DESIGN.md l.75 : la terre cuite est un « narrative anchor », jamais une couleur de
   surface. Et un bloc en alarme permanente n'alerte plus de rien : c'était l'élément le
   plus saturé de l'onglet, au-dessus du contrôle principal laissé en gris, et le MÊME
   chaud disait deux choses opposées sur le même écran — « cette ligne diverge » (une
   information, sur les lignes .is-ecart) et « ce bloc remplace tout » (un danger).

   Au repos : neutre, comme le bloc de cran, distingué par le seul filet — un cran de
   plus sur la même échelle de gris, ce qui suffit à ne pas les confondre sans crier.
   Armé (une source est choisie, le bouton peut écrire) : l'accent monte. Il redevient un
   événement, à l'instant où il y a un événement.

   Filet PÉRIMÉTRIQUE (fond teinté + 1px sur les quatre côtés) et non liseré gauche :
   DESIGN.md §1 les interdit depuis 2026-07-18, la seule exception étant la barre
   d'en-tête. Le bloc porte un `border: 1px` dans les deux états — seule sa couleur
   change, donc sa hauteur ne bouge pas d'un pixel entre repos et armé. Le filet prend
   l'accent PLEIN : à 60 % il tombe à 2,45:1 sur le fond teinté, là où plein il vaut
   4,55:1. */
.isis-cran-copie {
    margin-top: 1rem;
    border-color: var(--isis-border-strong);
}
/* Le fond se compose sur `transparent` et non sur `var(--isis-surface)` : en sombre le
   panneau est réellement peint en rgb(30,30,30) par le thème Radzen, plus CLAIR que le
   token #161c25 — mélanger vers le token rendait un aplat presque identique au fond réel
   (1,04:1 mesuré au navigateur). Sur `transparent`, la teinte se pose sur ce qui est
   vraiment là. En clair le rendu est inchangé au pixel (le panneau EST blanc). */
.isis-cran-copie.is-armee {
    background: color-mix(in srgb, var(--isis-accent) 9%, transparent);
    border-color: var(--isis-accent);
}
.isis-cran-copie.is-armee .isis-cran-module__label {
    color: var(--isis-accent-strong);
}
/* Le bouton prend la couleur de son bloc — armé seulement : fermé, il n'a rien à
   annoncer. La bordure prend l'accent PLEIN et non une teinte : à 55 % elle tombe à
   2,30:1 sur le fond du bloc, sous le seuil non-textuel de 3:1 (WCAG 1.4.11) ; pleine,
   elle vaut 4,75:1. Trois classes pour passer devant
   `.isis-action-btn--neutral.isis-action-btn--secondary`, qui reforce le gris. */
.isis-cran-copie.is-armee .isis-action-btn.isis-action-btn--secondary {
    color: var(--isis-accent-strong);
    border-color: var(--isis-accent);
    font-weight: 600;
}
.isis-cran-copie.is-armee .isis-action-btn.isis-action-btn--secondary:hover {
    background-color: color-mix(in srgb, var(--isis-accent) 12%, transparent);
    color: var(--isis-accent-strong);
}
/* En sombre l'accent chaud est plus clair (#f0803c) mais le fond l'est aussi : 9 % n'y
   pose qu'un voile. 14 % rend la même présence qu'en clair sans devenir une surface. */
:root[data-theme="dark"] .isis-cran-copie.is-armee {
    background: color-mix(in srgb, var(--isis-accent) 14%, transparent);
}
.isis-cran-copie {
    transition: background-color 160ms ease, border-color 160ms ease;
}
@media (prefers-reduced-motion: reduce) {
    .isis-cran-copie { transition: none; }
}
.isis-cran-module__label {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
}

.isis-cran-list {
    list-style: none;
    margin: 0;
    padding: 0;
}
.isis-cran-list__head,
.isis-cran-row {
    display: grid;
    /* Quatre colonnes : le chevron de dépliage a la sienne, à droite. Sous le sélecteur, il
       ajoutait une SECONDE LIGNE à chacun des trente-sept écrans — 99 px par ligne, trois
       lignes visibles à la fois, pour une densité opposable de 6/10. */
    grid-template-columns: minmax(220px, 1.5fr) 220px minmax(200px, 1fr) 36px;
    gap: 0.75rem;
    align-items: start;
}
/* Le panneau d'onglet défile — `.isis-tab-panel:not(.is-hidden)` porte `overflow-y: auto`
   et c'est bien lui le conteneur de défilement du `sticky` (vérifié au navigateur :
   l'en-tête reste à 4 px du haut du panneau pendant que celui-ci défile de 700 px).
   Sans `sticky`, les en-têtes de colonne quittent l'écran dès la quinzième ligne et chaque
   ligne redevient un bloc sans repère.

   `top: -0.25rem` et non `0` : le panneau a 0.25rem de padding haut, donc à `top: 0`
   l'en-tête se collait SOUS ce padding et une ligne défilait, visible, dans la bande de
   4 px laissée au-dessus. Le padding haut de l'en-tête absorbe le décalage — sa boîte
   visible ne bouge pas. */
.isis-cran-list__head {
    position: sticky;
    top: -0.25rem;
    z-index: 1;
    background: var(--isis-surface);
    padding: 0.65rem 0.75rem 0.4rem;
    border-bottom: 1px solid var(--isis-border);
    font-size: 0.65rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--isis-text-muted);
}
/* La définition des crans, une fois pour tout l'onglet — cf. `LegendeDesCrans`. */
.isis-cran-legende {
    margin: 0 0 0.15rem;
    padding: 0 0.75rem;
    font-size: 0.75rem;
    line-height: 1.45;
    color: var(--isis-text-muted);
}
.isis-cran-row {
    padding: 0.5rem 0.75rem;
    border-bottom: 1px solid var(--isis-border-soft);
}
/* L'écart est un fond teinté + un filet, jamais une couleur seule : le texte
   « Réglé à part du module » le dit aussi, et il est lu à voix haute.

   Le mélange se fait vers `transparent` et non vers `var(--isis-surface)`. Mesuré au
   navigateur : le fond RÉELLEMENT peint sous ces lignes est rgb(255,255,255) en clair
   mais rgb(30,30,30) en sombre — le thème Radzen material-dark, plus CLAIR que le token
   #161c25. Mélanger vers le token produisait donc en sombre un aplat rgb(33,33,38) posé
   sur rgb(30,30,30), soit 1,04:1 et ΔL* = 1,67 : rigoureusement invisible, là où le clair
   tient ΔL* = 2,75 ET garde une chromie chaude reconnaissable. Sur `transparent`, la
   teinte se compose sur ce qui est vraiment là ; en clair le rendu est identique au pixel
   (le panneau EST blanc), en sombre elle existe enfin. */
.isis-cran-row.is-ecart {
    background: color-mix(in srgb, var(--isis-accent) 5%, transparent);
    border-bottom-color: color-mix(in srgb, var(--isis-accent) 25%, var(--isis-border));
}
/* En sombre, 5 % ne rend que ΔL* ≈ 2,4 et surtout AUCUNE chromie : la ligne devient un
   gris légèrement plus clair, plus du tout « de la famille du badge ». 10 % rend
   ΔL* ≈ 5,9 et une teinte franchement chaude, sans virer à la surface. */
:root[data-theme="dark"] .isis-cran-row.is-ecart {
    background: color-mix(in srgb, var(--isis-accent) 10%, transparent);
}
.isis-cran-row__ecran {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    min-width: 0;
}
.isis-cran-row__label {
    font-size: 0.875rem;
    font-weight: 500;
    color: var(--isis-text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.isis-cran-row__code {
    font-family: var(--isis-font-mono, "JetBrains Mono", Menlo, monospace);
    font-size: 0.72rem;
    color: var(--isis-text-muted);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.isis-cran-row__ecart-tag {
    display: inline-flex;
    align-items: center;
    align-self: flex-start;
    gap: 0.2rem;
    margin-top: 0.15rem;
    padding: 0.05rem 0.4rem;
    font-size: 0.7rem;
    font-weight: 600;
    /* La nuance FONCÉE, pas l'accent : sur le fond composé du tag (10 % d'accent
       sur une ligne qui en porte déjà 5 %), --isis-accent tombe à 4,18:1,
       sous le seuil AA. La nuance forte y remonte à 5,9:1. */
    color: var(--isis-accent-strong);
    background: color-mix(in srgb, var(--isis-accent) 10%, transparent);
    border: 1px solid color-mix(in srgb, var(--isis-accent) 35%, transparent);
    border-radius: 10px;
    white-space: nowrap;
}
/* Le sélecteur seul : le dépliage a sa colonne (cf. `.isis-cran-row__detail`). */
.isis-cran-row__cran {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.35rem;
    min-width: 0;
}
/* Le chevron de dépliage, aligné sur le sélecteur de sa ligne — pas sur le haut de la
   cellule, sinon il flotte au-dessus de lui d'une demi-hauteur. */
.isis-cran-row__detail {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    min-height: 32px;
    min-width: 0;
}
.isis-cran-row__caps {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem 0.9rem;
    min-height: 32px;
    min-width: 0;
}
.isis-cran-row__cap {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    font-size: 0.8rem;
    color: var(--isis-text);
}
/* La plupart des écrans n'ont aucune capacité hors échelle : un blanc se lit
   comme un rendu cassé, un tiret se lit comme une absence. */
.isis-cran-row__cap-empty {
    font-size: 0.8rem;
    color: var(--isis-text-muted);
}

/* WCAG 2.5.8 « Taille de cible (minimum) », niveau AA — 24 × 24 px.
   `RadzenCheckBox` rend une cible de 18 px. Ce qu'on porte à 24 ici, c'est la ZONE DE
   POINTAGE et non le carré dessiné : `.rz-chkbox-box` est en `inset: 0` sur son parent,
   on le décale de 3 px pour qu'il garde ses 18. L'écran ne change donc pas d'aspect.
   Portée volontairement limitée à ces deux emplacements : `RadzenCheckBox` sert dans
   tout le produit, et redimensionner la cible globalement est un chantier à part.

   Mesuré en navigateur AVANT correction : le critère était en réalité DÉJÀ satisfait par
   l'exception d'espacement (67,9 px de centre à centre entre deux cases, 21 px du centre
   d'une case à la cible la plus proche — pour des seuils de 24 et 12 px). Mais cette
   marge n'est le produit d'aucune règle : elle tient à la longueur des libellés de
   capacité et au point où la ligne revient, que rien ne garde. Une cible de 24 px se
   passe de l'exception, et donc de cette dépendance. */
.isis-cran-row__cap > .rz-chkbox,
.isis-cran-detail__action > .rz-chkbox,
.isis-grid--sans-compte [role="gridcell"] > .rz-chkbox,
.isis-grid--sans-compte [role="columnheader"] > .rz-chkbox {
    width: 24px;
    height: 24px;
    cursor: pointer;
}
.isis-cran-row__cap > .rz-chkbox > .rz-chkbox-box,
.isis-cran-detail__action > .rz-chkbox > .rz-chkbox-box,
.isis-grid--sans-compte [role="gridcell"] > .rz-chkbox > .rz-chkbox-box,
.isis-grid--sans-compte [role="columnheader"] > .rz-chkbox > .rz-chkbox-box {
    inset: 3px;
}

/* La légende des crans, en liste de définitions plutôt qu'en paragraphe. Elle faisait
   240 caractères sur une ligne de 1253 px — trois fois la longueur au-delà de laquelle
   l'œil perd la ligne suivante — et il fallait la relire en entier pour retrouver un seul
   cran. En définitions, chaque cran se retrouve d'un coup d'œil. */
.isis-cran-legende-bloc {
    margin: 0 0 0.35rem;
    padding: 0 0.75rem;
    font-size: 0.75rem;
    line-height: 1.45;
    color: var(--isis-text-muted);
}
.isis-cran-legende {
    display: grid;
    grid-template-columns: max-content 1fr;
    gap: 0.15rem 0.6rem;
    margin: 0;
}
.isis-cran-legende__titre {
    margin: 0 0 0.1rem;
}
.isis-cran-legende dt {
    font-weight: 600;
    color: var(--isis-text);
    white-space: nowrap;
}
.isis-cran-legende dd {
    margin: 0;
}
/* Les capacités ferment la légende : elles ne sont pas un cran, et la phrase dit
   précisément qu'un cran n'y touche pas. */
.isis-cran-legende__capacites {
    margin: 0.15rem 0 0;
}
@media (max-width: 640px) {
    /* Sous 640 px, deux colonnes rendent des définitions de trois mots par ligne. */
    .isis-cran-legende { grid-template-columns: 1fr; gap: 0 }
    .isis-cran-legende dd { margin-bottom: 0.2rem }
}

/* La grille des actions d'un écran. Elle occupe toute la largeur de la ligne qui l'a
   ouverte, et se relit partout — la variante `.is-lecture` est celle des lignes qu'un cran
   décrit déjà : on y VÉRIFIE ce que le cran a posé, on n'y écrit pas. */
.isis-cran-detail {
    grid-column: 1 / -1;
    margin-top: 0.5rem;
    padding: 0.6rem 0.75rem;
    background: var(--isis-surface-alt);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-sm);
}
/* En lecture, le bloc perd sa surface et ne garde que son cadre : un aplat rempli annonce
   un champ où l'on écrit. Pas de liseré latéral (DESIGN.md §1 les interdit) et pas de
   couleur ajoutée — c'est la phrase du bloc qui dit pourquoi les cases ne bougent pas ; un
   simple grisé sans explication se lirait comme une panne. */
.isis-cran-detail.is-lecture {
    background: transparent;
}
.isis-cran-detail__hint {
    margin: 0 0 0.5rem;
    font-size: 0.78rem;
    color: var(--isis-text-muted);
}
.isis-cran-detail__actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem 1rem;
}
.isis-cran-detail__action {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    font-size: 0.8rem;
    color: var(--isis-text);
}

/* Les libellés de champ n'existent QUE sous 900 px, là où les en-têtes de colonne
   disparaissent. Au-dessus, la colonne les porte déjà et les répéter serait du bruit. */
.isis-cran-row__field {
    display: none;
}

@media (max-width: 900px) {
    .isis-cran-list__head {
        display: none;
    }
    .isis-cran-row {
        grid-template-columns: 1fr;
    }
    /* En pile, le chevron seul sur sa ligne ne dit rien : le libellé de champ reprend la
       main, comme pour le sélecteur et les capacités au-dessus. */
    .isis-cran-row__detail {
        justify-content: flex-start;
        gap: 0.5rem;
    }
    .isis-cran-row__detail .isis-cran-row__field {
        flex-basis: auto;
        margin-bottom: 0;
    }
    /* Sans eux, un sélecteur nu et une rangée de cases se retrouvaient sans aucun mot :
       l'`aria-label` sauvait la voix, pas l'œil de qui travaille sur tablette. Même
       graphie que les en-têtes de colonne qu'ils remplacent — c'est le même repère. */
    .isis-cran-row__field {
        display: block;
        flex-basis: 100%;
        margin-bottom: 0.1rem;
        font-size: 0.65rem;
        font-weight: 600;
        text-transform: uppercase;
        letter-spacing: 0.06em;
        color: var(--isis-text-muted);
    }
    /* La ligne devient une pile de champs : un peu d'air entre eux, et un séparateur plus
       franc entre deux écrans, sinon les blocs se touchent sans se distinguer. */
    .isis-cran-row {
        gap: 0.6rem;
        padding: 0.75rem;
    }
}

/* Variante grille DocumentKindListPage : 7 colonnes (status / libellé / module-entité / kind / pays / ordre / actions) */
/* Le libellé d'un type vit dans un <strong> à l'intérieur d'un RadzenStack (flex). La cellule
   porte bien overflow:hidden + text-overflow:ellipsis, mais c'est l'ENFANT qui déborde — et un
   parent qui masque un enfant trop long le COUPE NET au lieu de l'élider : « Registre du
   Commerce et du Crédit Mob » s'arrêtait en plein mot, sans les points de suspension qui
   auraient dit qu'il en manquait. L'ellipse doit donc vivre sur le <strong> lui-même, et le
   min-width:0 est indispensable : un élément flex refuse par défaut de descendre sous la
   largeur de son contenu, ce qui annule toute tentative d'ellipse. */
.isis-grid--doc-kinds .isis-grid__row > div:nth-child(2) > * { min-width: 0; }
.isis-grid--doc-kinds .isis-grid__row > div:nth-child(2) strong {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.isis-grid--doc-kinds .isis-grid__head,
.isis-grid--doc-kinds .isis-grid__row {
    /* « Module / Entité », « Kind » et « Pays » portent un bouton d'entonnoir de 24 px depuis
       la revue d'harmonisation GED, et « Ordre » un bouton de tri : le gabarit d'origine
       prévoyait des libellés nus. Comme sur la grille Documents, la place est REPRISE plutôt
       qu'ajoutée : le catalogue est déjà la grille la plus large du module. */
    /* « Kind » à 156 px et non 160 : les 4 px de trop faisaient apparaître une barre de
       défilement pour 2 px à 1600 px exactement. Le code du kind y est de toute façon élidé
       (337 px de contenu réel) — 4 px de moins n'y changent rien, la fiche latérale le porte
       en entier. */
    grid-template-columns: 32px minmax(190px, 1.4fr) minmax(180px, 1fr) 156px 126px 96px 76px;
    /* Somme des minimums (32+190+180+160+126+96+76). L'ancienne valeur, 1000, la dépassait de
       140 px — le pire écart des quatre grilles du module, et c'est ce qui rendait la colonne
       « Ordre » inatteignable sans défiler à 1600 px avec le panneau ouvert. */
    min-width: 856px;
}

/* Variante grille LegalTemplateListPage : 7 colonnes (status / pays / slot / libellé / regex / ordre / actions) */
/* La pastille passe de 32 à 44 px depuis le 2026-09-06 : elle porte désormais
   l'entonnoir d'obligation, dont la cible fait 24 px (WCAG 2.5.8). */
.isis-grid--legal-fields .isis-grid__head,
.isis-grid--legal-fields .isis-grid__row {
    grid-template-columns: 44px 110px 150px minmax(180px, 1.2fr) minmax(160px, 1fr) 90px 90px;
    min-width: 970px;
}

/* Variante grille DevisCounterListPage : 5 colonnes consultation (status / structure / portée / valeur / date) */
.isis-grid--devis-counters .isis-grid__head,
.isis-grid--devis-counters .isis-grid__row {
    grid-template-columns: 32px minmax(220px, 1.6fr) 200px 160px 200px;
    min-width: 820px;
}

/* Variante grille AppelOffreListPage (gesmaff) : 7 colonnes
   status / référence / intitulé / maître d'ouvrage / date limite / montant / actions */
.isis-grid--ao .isis-grid__head,
.isis-grid--ao .isis-grid__row {
    grid-template-columns: 32px 140px minmax(260px, 2fr) minmax(180px, 1.2fr) 136px 160px 90px;
    min-width: 1126px;
}

/* Variante grille MarcheListPage (gesmaff) : 7 colonnes
   status / numéro / intitulé / maître d'ouvrage / signature / montant TTC / actions */
.isis-grid--marche .isis-grid__head,
.isis-grid--marche .isis-grid__row {
    /* 9 colonnes depuis le 2026-09-04 : le STATUT en toutes lettres s'est intercalé entre le
       montant et les actions, comme sur la liste des commandes. La pastille de gauche reste :
       elle alerte, elle ne nomme pas. */
    grid-template-columns: 32px 160px minmax(260px, 2fr) minmax(180px, 1.2fr) 110px 150px 160px 120px 90px;
    min-width: 1360px;
}

/* Variante grille EngagementListPage (gesst) : 8 colonnes
   status / numéro / intitulé / type ST / sous-traitant / affaire / montant HT / actions */
.isis-grid--engagement .isis-grid__head,
.isis-grid--engagement .isis-grid__row {
    grid-template-columns: 32px 150px minmax(220px, 1.8fr) 110px minmax(180px, 1.2fr) minmax(180px, 1.2fr) 140px 90px;
    min-width: 1180px;
}

/* Variante grille référentiels gesmat (page admin) : 6 colonnes
   libellé / 2è col contextuel / 3è col contextuel / tri / badges / actions */
.isis-grid--gesmat-ref .isis-grid__head,
.isis-grid--gesmat-ref .isis-grid__row {
    grid-template-columns: minmax(220px, 2fr) minmax(160px, 1fr) minmax(140px, 1fr) 90px 100px 90px;
    min-width: 880px;
}

/* Variante grille indisponibilités gesmat : 9 colonnes
   statut / équipement / type / début / fin / motif / coût / prestataire / actions */
.isis-grid--indispos .isis-grid__head,
.isis-grid--indispos .isis-grid__row {
    grid-template-columns: 32px minmax(140px, 1.4fr) 140px 95px 95px minmax(120px, 1fr) 110px minmax(100px, 0.9fr) 40px;
    min-width: 1050px;
}
.isis-grid--indispos .isis-grid__col-motif {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.isis-grid--indispos .isis-grid__col-cout {
    text-align: right;
    font-variant-numeric: tabular-nums;
}

/* Variante grille catalogue compétences SIRH : 6 colonnes
   libellé / effectif / santé / niveaux / renouv / actions */
.isis-grid--sirh-competence .isis-grid__head,
.isis-grid--sirh-competence .isis-grid__row {
    grid-template-columns: minmax(220px, 2fr) 90px 168px 130px 110px 80px;
    min-width: 900px;
}

/* En-tête de groupe (regroupement par catégorie) */
.isis-grid__group {
    display: flex; align-items: center; gap: 0.5rem;
    width: 100%; padding: 0.55rem 1rem;
    background: var(--isis-surface-2, var(--isis-surface-alt, #f4f6f6));
    border: 0; border-top: 1px solid var(--isis-border-subtle);
    border-bottom: 1px solid var(--isis-border-subtle);
    font-size: 0.78rem; font-weight: 650; color: var(--isis-text, #1a1f24); cursor: pointer;
    text-align: left;
}
.isis-grid__group:hover { background: var(--isis-surface-3, var(--isis-surface-alt, #eef1f1)); }
.isis-grid__group-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--isis-current-mod, var(--isis-mod-sirh, #059669)); }
.isis-grid__group-count { color: var(--isis-text-muted, #6b7480); font-weight: 600; }

/* Carte KPI « warm » : filet gauche coloré retiré 2026-07-04 (demande utilisateur).
   Conserve le séparateur neutre hérité de .isis-kpi-card. */
.isis-kpi-card--warm { }
.isis-kpi-card--link { cursor: pointer; }
.isis-kpi-card--link:hover { box-shadow: var(--isis-elevation-hover, var(--isis-elevation-1)); }
.isis-kpi-card--link:focus-visible { outline: 2px solid var(--isis-accent); outline-offset: 2px; }

/* Libellé + chip rareté */
.isis-grid__lib { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }
.isis-rare-chip {
    font-size: 0.66rem; font-weight: 600; padding: 0.1rem 0.45rem; border-radius: 999px;
    background: var(--isis-surface-2, var(--isis-surface-alt, #f1f3f4)); color: var(--isis-text, #1a1f24);
    border: 1px solid var(--isis-border, #e6e8ea);
}
.isis-rare-chip.is-critical {
    background: var(--isis-accent-soft); color: var(--isis-accent);
    border-color: color-mix(in oklab, var(--isis-accent) 35%, #fff);
}
.isis-grid__eff { font-variant-numeric: tabular-nums; font-weight: 600; }
.isis-grid__eff.is-zero { color: var(--isis-text-muted, #6b7480); font-weight: 400; }

/* Badge santé péremption */
.isis-health-badge {
    display: inline-flex; align-items: center; gap: 0.5rem;
    border: 1px solid var(--isis-border, #e6e8ea); background: #fff; border-radius: 999px;
    padding: 0.15rem 0.6rem; font-size: 0.72rem; font-variant-numeric: tabular-nums;
    cursor: pointer; color: var(--isis-text, #1a1f24);
}
button.isis-health-badge:hover { box-shadow: var(--isis-elevation-1, 0 1px 2px rgba(16,24,32,.06), 0 4px 12px rgba(16,24,32,.06)); }
.isis-health-badge.is-allok { background: var(--isis-success-soft, #dcfce7); color: var(--isis-success, #15803d); border-color: color-mix(in oklab, var(--isis-success, #15803d) 30%, #fff); cursor: default; }
.isis-health-badge__seg { display: inline-flex; align-items: center; gap: 0.2rem; }
.isis-health-badge__seg.is-warn { color: var(--isis-warning, #8f5700); font-weight: 600; }
.isis-health-badge__seg.is-bad { color: var(--isis-danger, #a51b1b); font-weight: 600; }
.isis-health-badge__dot { width: 7px; height: 7px; border-radius: 50%; display: inline-block; }
.isis-health-badge__dot.is-ok { background: var(--isis-success, #15803d); }
.isis-health-badge__dot.is-warn { background: var(--isis-warning, #8f5700); }
.isis-health-badge__dot.is-bad { background: var(--isis-danger, #a51b1b); }

/* Mini-barre répartition niveaux */
.isis-levelbar { display: flex; height: 7px; width: 110px; border-radius: 4px; overflow: hidden; background: var(--isis-surface-2, var(--isis-surface-alt, #eef0f1)); }
.isis-levelbar__s { display: block; height: 100%; }
.isis-levelbar__s + .isis-levelbar__s { border-left: 1px solid #fff; }
.isis-levelbar__s.is-d, .isis-lvl-sw.is-d { background: #cbd2d9; }
.isis-levelbar__s.is-i, .isis-lvl-sw.is-i { background: #7fb1e6; }
.isis-levelbar__s.is-e, .isis-lvl-sw.is-e { background: #34a36b; }
.isis-levelbar__s.is-f, .isis-lvl-sw.is-f { background: #137a4a; }

/* Sidepanel détail compétence */
.isis-comp-detail { padding: 0.25rem 0.1rem; }
.isis-comp-detail__ctx { font-size: 0.72rem; color: var(--isis-text-muted, #6b7480); }
.isis-comp-detail__title { font-size: 1.05rem; font-weight: 660; margin: 0.2rem 0 0.5rem; }
.isis-comp-detail__badges { display: flex; gap: 0.4rem; flex-wrap: wrap; margin-bottom: 0.75rem; }
.isis-comp-detail__desc { font-size: 0.82rem; color: var(--isis-text-muted, #6b7480); line-height: 1.5; margin: 0 0 1rem; }
.isis-comp-detail__mini { display: grid; grid-template-columns: repeat(4, 1fr); gap: 0.5rem; margin-bottom: 1rem; }
.isis-comp-detail__mini > div { background: var(--isis-surface-2, var(--isis-surface-alt, #fafbfb)); border: 1px solid var(--isis-border-subtle); border-radius: var(--isis-radius-sm, 5px); padding: 0.5rem; text-align: center; }
.isis-comp-detail__mini .v { font-size: 1.1rem; font-weight: 680; font-variant-numeric: tabular-nums; }
.isis-comp-detail__mini .v.is-ok { color: var(--isis-success, #15803d); }
.isis-comp-detail__mini .v.is-warn { color: var(--isis-warning, #8f5700); }
.isis-comp-detail__mini .v.is-bad { color: var(--isis-danger, #a51b1b); }
.isis-comp-detail__mini .k { font-size: 0.65rem; color: var(--isis-text-muted, #6b7480); margin-top: 0.15rem; }
.isis-comp-detail__sechead { font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.04em; color: var(--isis-text-muted, #6b7480); font-weight: 600; margin: 0 0 0.5rem; }
.isis-comp-detail__lvlrow { display: flex; align-items: center; justify-content: space-between; font-size: 0.82rem; padding: 0.25rem 0; }
.isis-comp-detail__lvlrow > span { display: flex; align-items: center; gap: 0.45rem; }
.isis-lvl-sw { width: 9px; height: 9px; border-radius: 2px; display: inline-block; }
.isis-comp-holder-list { list-style: none; margin: 0; padding: 0; }
.isis-comp-holder { display: flex; align-items: center; justify-content: space-between; padding: 0.45rem 0; border-bottom: 1px solid var(--isis-border-subtle); font-size: 0.82rem; }

/* Pills statut (réutilisables) */
.isis-pill { font-size: 0.68rem; font-weight: 600; padding: 0.1rem 0.5rem; border-radius: 999px; white-space: nowrap; display: inline-block; }
.isis-pill.is-ok { background: var(--isis-success-soft, #dcfce7); color: var(--isis-success, #15803d); }
.isis-pill.is-warning { background: var(--isis-warning-soft, #fef3c7); color: var(--isis-warning, #8f5700); }
.isis-pill.is-danger { background: var(--isis-danger-soft, #fee2e2); color: var(--isis-danger, #a51b1b); }
.isis-pill.is-neutral { background: var(--isis-surface-2, var(--isis-surface-alt, #eef2f5)); color: var(--isis-text-muted, #6b7480); }

/* Modal péremption */
.isis-perm-dialog { display: flex; flex-direction: column; max-height: calc(100vh - 200px); }
.isis-perm-table-wrap { overflow-y: auto; flex: 1 1 auto; min-height: 0; }
.isis-perm-dialog__empty { display: flex; flex-direction: column; align-items: center; gap: 0.5rem; padding: 2rem; color: var(--isis-text-muted, #6b7480); text-align: center; }
.isis-perm-table { width: 100%; border-collapse: collapse; font-size: 0.82rem; }
.isis-perm-table th { text-align: left; font-size: 0.68rem; text-transform: uppercase; letter-spacing: 0.04em; color: var(--isis-text-muted, #6b7480); font-weight: 600; padding: 0.55rem 0.5rem; border-bottom: 1px solid var(--isis-border, #e6e8ea); }
.isis-perm-table td { padding: 0.6rem 0.5rem; border-bottom: 1px solid var(--isis-border-subtle); }
.isis-perm-dialog__foot { display: flex; justify-content: flex-end; padding-top: 1rem; flex-shrink: 0; }

/* Sprint U H2 — grille objectifs gespla : 7 colonnes
   type / ref / libellé / cible / plancher / note / actions */
.isis-grid--gespla-objectifs .isis-grid__head,
.isis-grid--gespla-objectifs .isis-grid__row {
    grid-template-columns: 130px 130px minmax(180px, 2fr) 100px 100px minmax(160px, 1.5fr) 100px;
    min-width: 960px;
}
/* Les deux colonnes de pourcentage alignent leur en-tête sur leurs cellules : le bouton de
   tri est un inline-flex, sans quoi le libellé pendrait à gauche au-dessus de chiffres
   alignés à droite (2026-09-05, revue d'harmonisation gespla). */
.isis-grid--gespla-objectifs .isis-grid__head-cell--num { justify-content: flex-end; }
.isis-grid--gespla-objectifs .isis-grid__code {
    font-family: monospace;
    font-size: 0.78rem;
    color: var(--isis-text-muted);
}
.isis-grid--gespla-objectifs .isis-grid__note {
    color: var(--isis-text-muted);
    font-size: 0.85rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Variante grille compétences attribuées à un collab : 7 colonnes
   compétence / catégorie / niveau / acquise / périmé / source / actions */
.isis-grid--sirh-collab-comp .isis-grid__head,
.isis-grid--sirh-collab-comp .isis-grid__row {
    grid-template-columns: minmax(200px, 2fr) 140px 130px 110px 160px 130px 90px;
    min-width: 1020px;
}

/* État de péremption (visuel sobre pour les dates) */
.isis-grid__perime--ok      { color: var(--isis-text); }
.isis-grid__perime--soon    { color: var(--isis-warning); font-weight: 600; }
.isis-grid__perime--expired { color: var(--isis-danger); font-weight: 600; }
.isis-grid__perime--none    { color: var(--isis-text-muted); }

/* Règles de valorisation (onglet « Règles » de /sirh/temps/regimes — ex /sirh/temps/regles) */
.isis-grid--regle-versions .isis-grid__head,
.isis-grid--regle-versions .isis-grid__row {
    grid-template-columns: 70px 130px 90px 120px minmax(160px, 1fr);
    min-width: 600px;
}
.isis-grid--regle-rules .isis-grid__head,
.isis-grid--regle-rules .isis-grid__row {
    grid-template-columns: 70px minmax(130px, 1fr) 110px 110px minmax(150px, 1.4fr) minmax(190px, 2fr) 120px;
    min-width: 1020px;
}
/* Bandeau de périmètre tenant/entité (onglet Règles) : un RadzenAlert Info nu se fond parmi les
   dizaines d'autres bandeaux Info bénins de l'appli, alors que sa charge sémantique est haute
   (une version d'entité ÉTEND le défaut tenant, elle ne le remplace jamais). Filet périmétrique
   (pas de liseré gauche — règle 2026-07-18) + badge en tête donnent une ancre visuelle 2-3 mots
   avant la phrase (audit ui-ux-designer, 2026-08-03). */
.isis-regle-scope-banner {
    border: 1px solid var(--isis-current-mod, var(--isis-accent));
    box-sizing: border-box;
    margin-bottom: 0.75rem;
}
.isis-regle-scope-badge {
    margin-right: 0.5rem;
    vertical-align: middle;
}
.isis-regle-inert-icon {
    font-size: 15px;
    vertical-align: text-bottom;
    color: var(--isis-text-muted);
    margin-left: 0.25rem;
}
.isis-regle-inert-note {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.6rem 0.9rem;
    border-radius: var(--isis-radius);
    border: 1px solid color-mix(in srgb, var(--isis-warning) 35%, var(--isis-border));
    background: color-mix(in srgb, var(--isis-warning) 8%, var(--isis-surface));
    color: var(--isis-warning);
    font-size: 0.85rem;
    margin-top: 0.5rem;
}
.isis-grid__mono {
    font-family: var(--isis-font-mono, monospace);
    font-size: 0.8rem;
    color: var(--isis-text-muted);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/* Icône du bandeau, scopée à cette page (évite de toucher au Style inline
   répété sur ~200 autres isis-rich-header__icon). */
.isis-regle-header-icon {
    font-size: 22px;
    color: var(--isis-mod-sirh);
}
/* PATRON NORMATIF des lignes cliquables de .isis-grid (décision 2026-10-06, DESIGN.md
   « Grilles — accessibilité ») : né sur la ligne de version sélectionnable ci-dessous.
   Ligne de version sélectionnable : la ligne elle-même n'est plus un CONTRÔLE
   (WCAG 4.1.2 — elle imbriquait un role="button" autour des IsisButton d'action).
   Le @onclick posé sur la ligne dans le .razor reste une simple extension de la
   zone de clic souris (aucun role, aucun tabindex ⇒ invisible pour le clavier/
   lecteur d'écran) ; le vrai contrôle accessible est le <button> de la 1re
   cellule, qui stoppe la propagation pour ne pas déclencher deux fois la
   sélection. Le curseur pointeur générique de .isis-grid__row reste donc correct
   ici — pas d'override. */
.isis-grid__row-select {
    display: block;
    width: 100%;
    padding: 0.35rem 0.35rem;
    margin: 0;
    border: none;
    background: transparent;
    font: inherit;
    color: inherit;
    text-align: left;
    cursor: pointer;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.isis-grid__row-select:hover {
    text-decoration: underline;
}
.isis-grid__row-select:focus-visible {
    outline: none;
    box-shadow: inset 0 0 0 2px var(--isis-current-mod, var(--isis-accent));
    border-radius: 4px;
}
/* Rangée rattrapage (note + bouton) : l'espacement vertical vient déjà du gap de
   .isis-rich-section (0.6rem, cf. règle générale) — cette classe ne pose que la
   mise en page horizontale, avec repli en 2 lignes sur viewport étroit (le texte
   ne doit jamais s'écraser contre le bouton). */
.isis-regle-rattrapage-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: flex-end;
    gap: 1rem;
}
.isis-regle-rattrapage-row .isis-rich-page__note {
    margin: 0;
    flex: 1 1 320px;
}
/* Publication d'une version (grille versions, colonne Actions) : sélecteur de date d'effet
   + bouton, alignés sur une ligne compacte dans une cellule de grille étroite. */
.isis-regle-publish-row {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 0.4rem;
}
.isis-regle-publish-row .rz-datepicker {
    width: 120px;
    height: 26px !important;
    min-height: 26px !important;
}
.isis-regle-publish-row .rz-datepicker .rz-inputtext {
    font-size: 0.75rem !important;
}
/* Vocabulaire JOUR (formulaire d'ajout de règle) : ~30 noms groupés par catégorie
   plutôt qu'un unique run de virgules — la donnée reste dense (l'écran l'est par
   design) mais respire par groupe. */
.isis-regle-vocab {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    color: var(--isis-text-muted);
    font-size: 0.72rem;
    line-height: 1.4;
}
.isis-regle-vocab__intro,
.isis-regle-vocab__cible {
    margin: 0;
}
.isis-regle-vocab__group {
    display: grid;
    grid-template-columns: 130px 1fr;
    gap: 0.3rem 0.5rem;
    align-items: start;
}
.isis-regle-vocab__label {
    font-weight: 600;
    color: var(--isis-text-muted);
}
.isis-regle-vocab__tokens {
    display: flex;
    flex-wrap: wrap;
    gap: 0.3rem;
}
.isis-regle-vocab__tokens code {
    font-family: var(--isis-font-mono, ui-monospace, monospace);
    font-size: 0.72rem;
    padding: 0.05rem 0.35rem;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: 3px;
    color: var(--isis-text);
}

/* Catégories de frais (/sirh/parametres/frais-categories) */
.isis-grid--frais-cat .isis-grid__head,
.isis-grid--frais-cat .isis-grid__row {
    grid-template-columns: minmax(140px, 1fr) minmax(200px, 2fr) 160px 90px 100px;
    min-width: 700px;
}

/* Barèmes — forfaits frais (/sirh/parametres/baremes) */
.isis-grid--bareme-frais .isis-grid__head,
.isis-grid--bareme-frais .isis-grid__row {
    grid-template-columns: minmax(160px, 1.5fr) 120px minmax(140px, 1fr) 120px 130px 100px;
    min-width: 880px;
}

/* Barèmes — indemnités km (/sirh/parametres/baremes) */
.isis-grid--bareme-ik .isis-grid__head,
.isis-grid--bareme-ik .isis-grid__row {
    grid-template-columns: 120px minmax(160px, 2fr) 180px 120px 100px;
    min-width: 700px;
}

/* Validation véhicules personnels RH (/sirh/vehicules) — grille master (6 colonnes) */
.isis-grid--vehrh .isis-grid__head,
.isis-grid--vehrh .isis-grid__row {
    /* « CV » : 60px ne portaient que le libellé et la flèche de tri ; l'entonnoir de
       puissance fiscale (2026-09-04) débordait sur la colonne Statut. 104px les tient.
       « Actions » (2026-09-04, P0-1) : 2 boutons de 28px + 16px d'écart = 72px, arrondis
       à 80px. Colonne FIXE : les quatre pistes `fr` se partagent ce qui reste, et perdent
       24/21/17/17px à 1024px (mesuré). Si rien ne déborde, ce n'est PAS grâce au
       `min-width: 0` ci-dessous — il retire seulement le plancher de 1000px du chrome ; ce
       sont les cellules qui écrasent leur contenu, via `.isis-grid__row > div`
       (ligne 11667 : `min-width: 0` + `overflow: hidden` + ellipse). Une grille dont les
       pistes porteraient un `minmax()` ou dont une cellule échapperait à cette règle
       déborderait — ne pas lire ce commentaire comme une garantie transposable. */
    grid-template-columns: 1.4fr 1.2fr 104px 1fr 1fr 80px;
    min-width: 0;
}
/* Écart de 16px entre les deux actions : il porte les zones de frappe 44×44 ci-dessous
   sans qu'elles se recouvrent (28 + 16 = 44 d'entraxe, elles se touchent sans mordre).
   `overflow: visible` et `align-self: stretch` ne sont PAS cosmétiques : sans eux la cellule
   fait 28px de haut et hérite l'`overflow: hidden` de `.isis-grid__row > div` (0,1,1, qui bat
   `.isis-grid__col-actions`) — le pseudo-élément de 44px serait rogné à la hauteur du bouton
   et la zone de frappe ne vaudrait que ce qu'elle vaut aujourd'hui. */
.isis-grid--vehrh .isis-grid__col-actions {
    gap: 16px;
    align-self: stretch;
    align-items: center;
    overflow: visible;
}
/* DESIGN.md §5 « Responsive » impose 44×44 sur les boutons d'action, et c'est ICI que la
   règle mord : ces deux gestes sont la file de validation sur la tablette 1024×768, où le
   panneau de détail n'est pas rendu. Le bouton garde ses 28px (chrome de grille inchangé,
   cf. .isis-grid__action-btn) ; seule la CIBLE s'étend, par un pseudo-élément — un <button>
   n'est pas un élément remplacé, ::after y génère bien une boîte (contrairement à un
   <input>). Portée volontairement locale : le passage des ~220 autres grilles de 28 à 44
   est un arbitrage de design system, pas un correctif de page. */
.isis-grid--vehrh .isis-grid__col-actions .isis-grid__action-btn { position: relative; }
.isis-grid--vehrh .isis-grid__col-actions .isis-grid__action-btn::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: 44px;
    height: 44px;
    transform: translate(-50%, -50%);
}
.isis-vehrh-immat { font-family: var(--isis-font-mono, 'Geist Mono', monospace); font-size: 0.82rem; }
.isis-vehrh-detail { display: flex; flex-direction: column; gap: 0.6rem; }
.isis-vehrh-detail__meta { display: flex; gap: 0.3rem 1.2rem; flex-wrap: wrap; font-size: 0.88rem; }
.isis-vehrh-detail__meta .lbl { color: var(--isis-text-muted); margin-right: 0.3rem; }

/* Mes véhicules personnels (/mon-espace/vehicules-personnels) — cartes par véhicule */
.isis-vehp-grid { display: flex; flex-direction: column; gap: 0.9rem; }
.isis-vehp-card {
    border: 1px solid var(--isis-border);
    border-radius: 12px;
    padding: 1rem 1.1rem;
    background: var(--isis-surface);
    box-shadow: var(--isis-elevation-1);
}
.isis-vehp-card.is-nonconforme { border: 1px solid var(--isis-warning); }
.isis-vehp-card.is-valide { border: 1px solid var(--isis-success); }
.isis-vehp-card__head { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; }
.isis-vehp-card__title { font-weight: 700; font-size: 1rem; }
.isis-vehp-card__immat {
    font-family: var(--isis-font-mono, 'Geist Mono', monospace);
    background: var(--isis-surface-alt);
    padding: 0.1rem 0.5rem;
    border-radius: 6px;
    font-size: 0.85rem;
}
.isis-vehp-card__meta { display: flex; gap: 0.4rem 1.4rem; flex-wrap: wrap; margin: 0.6rem 0; font-size: 0.88rem; color: var(--isis-text); }
.isis-vehp-card__meta .lbl { color: var(--isis-text-muted); margin-right: 0.3rem; }
.isis-vehp-exp--expired { color: var(--isis-danger); font-weight: 700; }
.isis-vehp-exp--soon { color: var(--isis-warning); font-weight: 600; }
.isis-vehp-card__reject {
    background: color-mix(in srgb, var(--isis-danger) 10%, var(--isis-surface));
    border: 1px solid color-mix(in srgb, var(--isis-danger) 30%, transparent);
    color: var(--isis-danger);
    padding: 0.4rem 0.7rem;
    border-radius: 8px;
    margin: 0.5rem 0;
    font-size: 0.86rem;
}
.isis-vehp-card__actions { display: flex; gap: 0.4rem; flex-wrap: wrap; margin-top: 0.7rem; padding-top: 0.7rem; border-top: 1px solid var(--isis-border-soft); }

/* Feuilles d'équipe à valider (/mon-espace/equipe/feuilles-temps) */
.isis-grid--equipe-pending .isis-grid__head,
.isis-grid--equipe-pending .isis-grid__row {
    grid-template-columns: minmax(200px, 2fr) 160px 160px 160px;
    min-width: 720px;
}

/* Champs de sélection de la feuille (FeuilleTempsEditor) : collaborateur · période.
   Le conteneur .isis-temps-selector a disparu avec le bandeau qui l'accueillait — ces
   champs vivent maintenant dans .isis-filter-bar__end, qui porte déjà l'alignement à
   droite et l'écartement. Restait ici un margin-left:auto qui n'avait de sens que dans
   le bandeau, et une règle .isis-autosave sans aucun élément qui la porte. */
.isis-temps-selector__field { display: flex; flex-direction: column; gap: 0.2rem; }

/* Variante grille dashboard péremption SIRH : 8 colonnes
   collab / compétence / catégorie / niveau / acquise / périmé / reste / actions */
.isis-grid--sirh-peremption .isis-grid__head,
.isis-grid--sirh-peremption .isis-grid__row {
    grid-template-columns: minmax(180px, 1.5fr) minmax(160px, 1.5fr) 140px 130px 110px 110px 110px 70px;
    min-width: 1120px;
}

/* Variante grille matrice compétences MASTER (gauche) : 3 colonnes
   compétence / catégorie / count (cliquable) */
.isis-grid--sirh-matrice-master .isis-grid__head,
.isis-grid--sirh-matrice-master .isis-grid__row {
    grid-template-columns: minmax(180px, 2fr) 140px 100px;
    min-width: 460px;
}

/* Variante grille matrice DETAIL (droite, dans le sidepanel) : 5 colonnes
   collab / niveau / acquise / péremption / actions */
.isis-grid--sirh-matrice-detail .isis-grid__head,
.isis-grid--sirh-matrice-detail .isis-grid__row {
    grid-template-columns: minmax(160px, 2fr) 130px 100px 110px 70px;
    min-width: 600px;
}

/* Variante grille ConsolideValidationPage (sirh, chantier harmonisation 2026-09-03) : 10
   colonnes (sélection / collaborateur / manager / statut / heures / HS / IK / frais /
   anomalies / actions). Dernière colonne FIXE (pas auto) : chaque ligne est une grille
   indépendante ; un auto piloté par le contenu ferait dériver les pistes fr entre en-tête et
   lignes → colonnes désalignées. Sortie du <style> inline de la page : ces règles n'ont pas
   d'équivalent ailleurs dans le thème (contrairement à .isis-cs-chip/.isis-cs-search/
   .isis-cs-sort, remplacées en place par .isis-chip/.isis-filter-bar__search/
   .isis-grid__sort-btn). */
.isis-grid--consolide .isis-grid__head,
.isis-grid--consolide .isis-grid__row {
    display: grid;
    /* 1re colonne : 34px → 44px pour porter la zone de frappe de la case (cf. .isis-cs-sel). */
    grid-template-columns: 44px 1.5fr 1.1fr 1.2fr .7fr .5fr .7fr .7fr .8fr 110px;
    align-items: center;
    gap: .5rem;
}
/* Colonnes numériques + actions (5→10) alignées à droite ; nom/manager/statut à gauche. */
.isis-grid--consolide .isis-grid__head > *:nth-child(n+5),
.isis-grid--consolide .isis-grid__row > *:nth-child(n+5) { justify-self: end; text-align: right; }
.isis-grid--consolide .isis-grid__head > *:nth-child(n+5) { justify-content: flex-end; }

/* Case de sélection — le geste central de la validation en lot.
   16×16 (posé le 2026-09-03) tombait sous le plancher DESIGN.md §5 (44×44) ET sous celui de
   WCAG 2.5.8 AA (24×24). La coche passe à 24px, et la CELLULE devient la cible : c'est un
   <label> (cf. ConsolideValidationPage.razor), donc cliquer n'importe où dans ses 44×44
   bascule la case. Pourquoi pas un pseudo-élément sur l'input, comme sur les boutons d'action
   de /sirh/vehicules : un <input> est un élément remplacé, ::before/::after n'y génèrent pas
   de boîte de façon fiable — la zone de frappe n'aurait pas grandi.
   `align-self: stretch` donne les 44px de haut de la ligne (.isis-grid__row, min-height 44px) ;
   sans lui l'`align-items: center` de la grille borne le label à la hauteur de la coche. */
.isis-grid--consolide .isis-cs-sel {
    display: grid;
    place-items: center;
    align-self: stretch;
    min-height: 44px;
    padding: 0;
}
/* Le curseur ne promet la cible que là où elle existe : une feuille non validable rend un
   <label> VIDE, et un `cursor: pointer` inconditionnel y annoncerait un geste inexistant. */
.isis-grid--consolide .isis-cs-sel:has(input) { cursor: pointer; }
/* L'en-tête est plafonné à 34px par .isis-grid__head : sa case « tout sélectionner » gagne
   44×34 — au-dessus du plancher WCAG, sous celui de DESIGN.md, comme toute la ligne d'en-tête. */
.isis-grid--consolide .isis-grid__head .isis-cs-sel { min-height: 0; }
.isis-grid--consolide .isis-cs-sel input {
    width: 24px; height: 24px;
    accent-color: var(--isis-current-mod, var(--isis-accent));
    cursor: pointer; margin: 0;
}
/* Feuille que l'acteur ne peut pas viser (sa propre feuille) : case atteignable au clavier pour
   sa raison, mais éteinte ; l'anneau passe au label pour ne pas hériter de l'opacité. */
.isis-grid--consolide .isis-cs-sel:has(input[aria-disabled="true"]),
.isis-grid--consolide .isis-cs-sel input[aria-disabled="true"] { cursor: not-allowed; }
.isis-grid--consolide .isis-cs-sel input[aria-disabled="true"] { opacity: 0.4; }
.isis-grid--consolide .isis-cs-sel input[aria-disabled="true"]:focus-visible { outline: none; }
.isis-grid--consolide .isis-cs-sel:has(input[aria-disabled="true"]:focus-visible) {
    outline: 2px solid var(--isis-accent);
    outline-offset: -6px;
}
.isis-grid--consolide .isis-cs-mono { font-variant-numeric: tabular-nums; }
.isis-grid--consolide .isis-cs-ano { font-variant-numeric: tabular-nums; font-weight: 600; }
.isis-grid--consolide .isis-cs-ano.has { color: var(--isis-warning); }
.isis-grid--consolide .isis-cs-ano.zero { color: var(--isis-text-muted); }

/* Barre d'action de masse de ConsolideValidationPage : INLINE au-dessus de la grille, hors du
   conteneur .isis-grid (ne peut donc pas être scopée sous .isis-grid--consolide) — même
   patron que .isis-cmd-temps__bulk (fiche à onglets, cf. ligne ~17895). La barre flottante
   fixe .isis-bulk-actions-bar est réservée aux pages liste PLEIN ÉCRAN dont la sélection ne
   porte aucun champ de saisie ; ici la sélection peut afficher un motif de dérogation/rejet en
   pleine largeur (isis-cs-bulk__motif), qu'une pastille fixe centrée n'accueillerait pas
   proprement. */
.isis-cs-bulk {
    display: flex; align-items: center; gap: .7rem; flex-wrap: wrap;
    background: var(--isis-surface-alt);
    border: 1px solid var(--isis-current-mod, var(--isis-accent));
    border-radius: var(--isis-radius);
    padding: .55rem .9rem; margin-bottom: .6rem;
}
.isis-cs-bulk__cnt { font-weight: 700; color: var(--isis-current-mod, var(--isis-accent)); }
.isis-cs-bulk__sp { flex: 1; }
.isis-cs-bulk__motif { display: flex; align-items: center; gap: .5rem; flex-basis: 100%; margin-top: .4rem; }
.isis-cs-bulk__motif input { flex: 1; }

/* Badge compteur (pour la matrice master — affiche "X détenteurs") */
.isis-grid__count-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 28px;
    height: 22px;
    padding: 0 0.5rem;
    border-radius: var(--isis-radius-pill);
    background: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 12%, white);
    color: var(--isis-current-mod, var(--isis-accent));
    font-size: 0.72rem;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}
/* Variante 3 colonnes pour Marques (simple : libellé / pays / actions) */
.isis-grid--gesmat-ref-3col .isis-grid__head,
.isis-grid--gesmat-ref-3col .isis-grid__row {
    grid-template-columns: minmax(280px, 2fr) 160px 90px;
    min-width: 540px;
}

/* Variante grille FactureListPage (gesst) : 7 colonnes
   numéro externe / engagement (numéro+intitulé) / date / échéance / montant TTC / payé / actions */
.isis-grid--gesst-facture .isis-grid__head,
.isis-grid--gesst-facture .isis-grid__row {
    grid-template-columns: 160px minmax(240px, 2fr) 110px 110px 140px 130px 90px;
    min-width: 1100px;
}

/* Variante grille FactureEmiseListPage (gescompta) : 9 colonnes
   status / numéro / date / client / intitulé / origine / montant TTC / payé / actions */
.isis-grid--factures-emises .isis-grid__head,
.isis-grid--factures-emises .isis-grid__row {
    grid-template-columns: 32px 160px 110px minmax(200px, 1.4fr) minmax(220px, 2fr) minmax(120px, 1fr) 140px 130px 110px;
    min-width: 1300px;
}

/* Variante grille FactureRecueListPage (gescompta) : 9 colonnes
   status / numéro externe / date / fournisseur / intitulé / nature fiscale / montant TTC /
   payé / actions */
.isis-grid--factures-recues .isis-grid__head,
.isis-grid--factures-recues .isis-grid__row {
    grid-template-columns: 32px 160px 110px minmax(200px, 1.4fr) minmax(220px, 2fr) 130px 140px 130px 110px;
    min-width: 1310px;
}

/* Variante grille RegimesTvaPage (gescompta) : 7 colonnes
   Régime | Code | Catégorie EN 16931 | N° TVA obligatoire | Conditions | Mention légale | Template Word */
.isis-grid--regimes-tva .isis-grid__head,
.isis-grid--regimes-tva .isis-grid__row {
    grid-template-columns:
        minmax(140px, 1fr)   /* Régime */
        70px                 /* Code */
        100px                /* Catégorie EN 16931 */
        140px                /* N° TVA obligatoire */
        minmax(180px, 1.6fr) /* Conditions */
        minmax(200px, 2fr)   /* Mention légale */
        120px;               /* Template Word */
    min-width: 920px;
}
.isis-grid--regimes-tva .isis-grid__row { cursor: default; }
/* Mention légale + Conditions : lisibles, non tronquées */
.isis-grid--regimes-tva .isis-grid__row > div:nth-child(5),
.isis-grid--regimes-tva .isis-grid__row > div:nth-child(6) {
    white-space: normal;
    line-height: 1.35;
    padding-block: 0.45rem;
}

/* Édition inline des lignes facture (dialog FormLinear) */
.isis-facture-items {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}
.isis-facture-item-row {
    display: flex;
    gap: 0.5rem;
    align-items: flex-end;
    flex-wrap: wrap;
    padding: 0.55rem 0.65rem;
    background: var(--isis-surface-soft);
    border-radius: 6px;
    border: 1px solid var(--isis-border);
}
.isis-facture-item-row .field { margin: 0; }

/* Totaux récap (sous la liste de lignes) */
.isis-facture-totals {
    display: flex;
    gap: 1.5rem;
    margin-top: 0.75rem;
    padding: 0.65rem 0.85rem;
    background: var(--isis-mod-gescompta-soft);
    border-radius: 6px;
    border: 1px solid var(--isis-border);
    font-size: 0.88rem;
    font-variant-numeric: tabular-nums;
}
.isis-facture-totals div { display: flex; flex-direction: column; gap: 0.15rem; }
.isis-facture-totals .lbl {
    color: var(--isis-text-muted);
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
}
.isis-facture-totals .val { font-weight: 600; }
.isis-facture-totals__ttc { color: var(--isis-mod-gescompta); font-size: 1.05rem; }

/* Tableau lecture-seule des lignes / paiements (page détail) */
.isis-facture-items-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.88rem;
}
.isis-facture-items-table thead th {
    text-align: left;
    text-transform: uppercase;
    font-size: 0.72rem;
    letter-spacing: 0.04em;
    color: var(--isis-text-muted);
    font-weight: 500;
    padding: 0.55rem 0.65rem;
    border-bottom: 1px solid var(--isis-border);
    background: var(--isis-surface);
}
.isis-facture-items-table tbody td {
    padding: 0.55rem 0.65rem;
    border-bottom: 1px solid var(--isis-border);
    vertical-align: top;
}
/* Nature fiscale : selecteur + origine de la nature dessous. Ambre quand la ligne n'est pas
   qualifiee — meme code couleur que la pastille « a arbitrer » de l'editeur d'offre. */
.isis-facture-items-table__fisc { display: flex; flex-direction: column; gap: 2px; }
.isis-facture-items-table__fisc-src {
    font-size: 0.7rem;
    color: var(--isis-text-muted);
    display: inline-flex;
    align-items: center;
    gap: 2px;
}
.isis-facture-items-table__fisc-src.is-unknown { color: var(--isis-warning); }
.isis-facture-items-table tbody tr:last-child td { border-bottom: none; }
.isis-facture-items-table tbody tr:hover td { background: var(--isis-surface-soft); }

/* Status dot warning (suspendu) */
.isis-grid__status-dot.is-warning { background: #f59e0b; }

/* Variante grille DemandeClientListPage (gesmaff) : 8 colonnes
   référence / intitulé / type / client / date / canal / statut / actions
   (migration 0234 — colonne statut ajoutée pour pilotage commercial)
   (type ajoutée — opportunité socle, 2026-09-13) */
.isis-grid--demande-client .isis-grid__head,
.isis-grid--demande-client .isis-grid__row {
    /* 3e piste = Type : « Demande client » (14 car.) mesure ~112-117px en badge et dépasse la
       plus longue valeur de Statut (« À qualifier », 11 car., piste de 130px) — 140px pour
       garder la marge de +20px en usage ailleurs dans ce fichier, la cellule étant en
       overflow:hidden/nowrap sans ellipsis effective sur un badge inline-block. */
    grid-template-columns: 140px minmax(260px, 2fr) 140px minmax(180px, 1.2fr) 130px 130px 130px 90px;
    min-width: 1220px;
}

/* Liste unifiée des opportunités (spec 2026-09-18). Colonnes communes :
   Type · Référence · Intitulé · Client · Statut · Commercial · Entreprise · Créée le · actions.
   Quand un SEUL type est retenu, deux colonnes propres s'insèrent après Client. */
.isis-grid--opportunites .isis-grid__head,
.isis-grid--opportunites .isis-grid__row {
    /* Dernière piste élargie de 44px à 84px (audit WCAG #2, 2026-09-18) : une ligne d'un type
       CUSTOM sans fiche y montre désormais un texte VISIBLE (« Sans fiche »), pas seulement le
       chevron qu'elle n'a plus — 44px n'aurait laissé aucune place au texte. */
    grid-template-columns: 140px 130px minmax(240px, 2fr) minmax(170px, 1.2fr) 150px minmax(140px, 1fr) minmax(140px, 1fr) 100px 84px;
    min-width: 1340px;
}
.isis-grid--opportunites.isis-grid--opportunites-ao .isis-grid__head,
.isis-grid--opportunites.isis-grid--opportunites-ao .isis-grid__row,
.isis-grid--opportunites.isis-grid--opportunites-dc .isis-grid__head,
.isis-grid--opportunites.isis-grid--opportunites-dc .isis-grid__row {
    grid-template-columns: 140px 130px minmax(240px, 2fr) minmax(170px, 1.2fr) 130px 110px 150px minmax(140px, 1fr) minmax(140px, 1fr) 100px 84px;
    min-width: 1580px;
}

/* Mode maître-détail (2026-09-27) : le volet prend clamp(300px, 30%, 400px) à droite, la colonne
   maître tombe autour de 715-780px sur un portable. Commercial et Entreprise sortent alors du
   balisage (cf. OpportuniteListPage.razor) — ce sont les deux seules colonnes sans tri ni
   entonnoir, et le volet les porte toutes les deux. Sans ça, 1340px de pistes dans 730px =
   défilement horizontal à chaque visite. Le mode élargi retire cette classe et rend les 9
   (ou 11) colonnes.

   Pistes calibrées au plancher de lisibilité, pas au confort : Type tient le badge le plus long
   (« Demande client », ~112-117px mesurés plus haut dans ce fichier), Statut garde ses 130px
   parce que le catalogue de statuts est PARAMÉTRABLE par le client — un badge rogné coûte plus
   qu'un défilement — et la dernière piste garde de quoi écrire « Sans fiche ».

   ATTENTION : min-width dimensionne ici la boîte de CONTENU (les pistes), PAS la ligne : la largeur
   réelle vaut min-width + 27px de padding. Un premier jet déclarait 781px en croyant nommer le
   total ; la ligne mesurait 808px et débordait jusqu'à 1486px de fenêtre. min-width porte
   désormais la somme des pistes, et le total est annoncé à côté.

   Mesuré au navigateur le 2026-09-27 (e2e/_oppo-volet-largeur.mjs, tenant demo, KADRAN) :
   colonne maître = 0,7 × (fenêtre − 312px) − 14px, soit 722px de grille à 1366, 774px à 1440,
   826px à 1512. Pistes = 734px, ligne = 761px : plus de défilement horizontal à partir de
   ~1420px de fenêtre rail déployé (~1205px rail replié). Couvre les 1470/1512 logiques des
   Macs en usage et le 1440 des portables Windows ; à 1366 il reste ~39px de défilement, et
   .isis-grid--sticky-actions garde la colonne Actions — donc le bouton d'ouverture — à l'écran. */
.isis-grid--opportunites.isis-grid--opportunites-compact .isis-grid__head,
.isis-grid--opportunites.isis-grid--opportunites-compact .isis-grid__row {
    grid-template-columns: 120px 96px minmax(140px, 2fr) minmax(104px, 1.2fr) 130px 76px 68px;
    min-width: 734px; /* pistes seules ; ligne réelle = 734 + 27 de padding = 761px */
}
/* Un seul type retenu : ses deux colonnes propres restent (elles PORTENT le tri du type, montant
   ou date limite), donc 9 pistes et ~1010px — au-delà de la piste disponible sur un portable.
   C'est le prix d'un tri sur une colonne propre ; le mode élargi reste la sortie. Ligne réelle
   = 962 + 27 = 989px, soit un défilement horizontal jusqu'à ~1744px de fenêtre rail déployé :
   ici il est structurel, pas un réglage à affiner. */
.isis-grid--opportunites.isis-grid--opportunites-compact.isis-grid--opportunites-ao .isis-grid__head,
.isis-grid--opportunites.isis-grid--opportunites-compact.isis-grid--opportunites-ao .isis-grid__row,
.isis-grid--opportunites.isis-grid--opportunites-compact.isis-grid--opportunites-dc .isis-grid__head,
.isis-grid--opportunites.isis-grid--opportunites-compact.isis-grid--opportunites-dc .isis-grid__row {
    grid-template-columns: 120px 96px minmax(140px, 2fr) minmax(104px, 1.2fr) 124px 104px 130px 76px 68px;
    min-width: 962px; /* pistes seules ; ligne réelle = 962 + 27 de padding = 989px */
}
.isis-opportunite-col-spec { background: color-mix(in oklch, var(--isis-current-mod, var(--isis-accent)) 4%, transparent); }
.isis-opportunite-echeance-proche { color: var(--isis-warning); font-weight: 500; }
/* Ligne d'un type CUSTOM sans fiche (audit WCAG #2) : texte muet mais VISIBLE — atteint
   sighted/clavier/lecteur d'écran par simple lecture du contenu, sans dépendre d'un
   aria-label sur un rôle qui l'interdirait. */
.isis-opportunite-sans-fiche { color: var(--isis-text-muted); font-size: 12px; white-space: nowrap; }

/* Statuts AO (réutilise les status-dot existants).
   Ajoute des classes sémantiques génériques pour les badges. */
.isis-grid__status-dot.is-ok     { background: #16a34a; } /* obtenu */
.isis-grid__status-dot.is-draft  { background: #6b7280; } /* prévu */
.isis-grid__status-dot.is-danger { background: #dc2626; } /* perdu / annulé */
.isis-grid__status-dot.is-muted  { background: #9ca3af; opacity: 0.7; } /* abandonné */

/* Status dots facturation : contraste renforcé (WCAG 1.4.11 ≥3:1).
   Override local pour ne pas impacter les autres grilles du système. */
.isis-grid--factures-emises .isis-grid__status-dot.is-warning,
.isis-grid--factures-recues .isis-grid__status-dot.is-warning,
.isis-grid--factures-corbeille .isis-grid__status-dot.is-warning {
    background: #d97706; /* terre cuite, ratio 3.37:1 sur blanc */
}
.isis-grid--factures-emises .isis-grid__status-dot.is-ok,
.isis-grid--factures-recues .isis-grid__status-dot.is-ok,
.isis-grid--factures-corbeille .isis-grid__status-dot.is-ok {
    background: #15803d; /* vert plus saturé, ratio 3.30:1 sur surface-alt */
}

/* ============================================================================
   Écran « Numérotation » — NumerotationModulePanel (les 7 modules émetteurs)
   ----------------------------------------------------------------------------
   Une ligne = un couple (type de document × entreprise émettrice) : 6 colonnes
   (type / entreprise / masque effectif / aperçu / compteur de l'année / action).
   La ligne entière ouvre le dialog de configuration (Enter au clavier).
   ============================================================================ */
.isis-grid--numerotation .isis-grid__head,
.isis-grid--numerotation .isis-grid__row {
    grid-template-columns:
        minmax(200px, 1.2fr) minmax(180px, 1.2fr) minmax(210px, 1.5fr)
        minmax(160px, 1fr) 150px 56px;
    min-width: 1040px;
}

/* Code 2 lettres du type (DE, FA…) — teinté par la couleur du module courant :
   le même composant sert les 7 modules émetteurs, la pastille les suit. */
.isis-num-type-pill {
    display: inline-block;
    font-family: var(--isis-font-mono, ui-monospace, monospace);
    font-size: 0.7rem;
    font-weight: 700;
    letter-spacing: 0.02em;
    padding: 0.1rem 0.4rem;
    border-radius: 4px;
    margin-right: 0.5rem;
    color: var(--isis-current-mod, var(--isis-text));
    background: color-mix(in srgb, var(--isis-current-mod, var(--isis-text)) 10%, transparent);
    border: 1px solid color-mix(in srgb, var(--isis-current-mod, var(--isis-text)) 30%, transparent);
}

/* Pendant de .isis-grid__badge-default : le masque a été personnalisé. */
.isis-grid__badge-custom {
    display: inline-block;
    margin-left: 0.4rem;
    padding: 0.05rem 0.4rem;
    font-size: 0.65rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--isis-success-text, var(--isis-text));
    background: color-mix(in srgb, var(--isis-success, #16a34a) 10%, transparent);
    border: 1px solid color-mix(in srgb, var(--isis-success, #16a34a) 35%, transparent);
    border-radius: 4px;
}

/* Type à séquence légalement sans trou (facture, avoir). Signal sobre : on ne
   verrouille pas le masque (la loi impose une séquence continue, pas un format
   figé) — on prévient que la pièce est comptable. */
.isis-num-gapfree {
    display: inline-flex;
    align-items: center;
    gap: 0.2rem;
    margin-left: 0.4rem;
    padding: 0.05rem 0.4rem;
    font-size: 0.65rem;
    font-weight: 500;
    color: var(--isis-text-muted);
    background: var(--isis-surface-alt);
    border: 1px solid var(--isis-border);
    border-radius: 10px;
    white-space: nowrap;
}

/* Alerte EF-79 : compteur au-delà de 9 000 (le numéro va gagner un chiffre), ou
   entreprise sans code court (elle ne peut rien numéroter). Accent chaud —
   l'émission n'est jamais bloquée, ce n'est pas une erreur, c'est un préavis. */
.isis-num-alert {
    display: inline-flex;
    align-items: center;
    gap: 0.2rem;
    margin-left: 0.4rem;
    padding: 0.05rem 0.4rem;
    font-size: 0.65rem;
    font-weight: 600;
    color: var(--isis-accent);
    background: color-mix(in srgb, var(--isis-accent) 10%, transparent);
    border: 1px solid color-mix(in srgb, var(--isis-accent) 35%, transparent);
    border-radius: 10px;
    font-variant-numeric: normal;
    white-space: nowrap;
}

/* Variante dialog « Transformer en commande » — étape preview :
   3 colonnes (Entreprise + badge / Lignes / Montant HT). L'entreprise prend
   tout l'espace restant pour absorber le nom long + le shortcode + le badge
   « principale ». Les colonnes numériques restent tabular-nums. */
.isis-grid--transform-groups .isis-grid__head,
.isis-grid--transform-groups .isis-grid__row {
    grid-template-columns: minmax(280px, 1fr) 90px 160px;
    min-width: 600px;
    column-gap: 0.75rem;
}
.isis-grid--transform-groups .isis-grid__row > div {
    white-space: normal;
    word-break: break-word;
}

/* Variante dialog « Transformer en commande » — étape result : 4 colonnes
   (Numéro mono / Entreprise / Lignes / Montant HT). */
.isis-grid--transform-result .isis-grid__head,
.isis-grid--transform-result .isis-grid__row {
    grid-template-columns: 160px minmax(240px, 1fr) 90px 160px;
    min-width: 700px;
    column-gap: 0.75rem;
}
.isis-grid--transform-result .isis-grid__row > div {
    white-space: normal;
    word-break: break-word;
}
/* Picker postes — création commande depuis un marché (MarcheToCommandeDialog).
   min-width:0 surcharge le 1000px de base (.isis-grid__head/__row) : sinon les
   colonnes PU HT + Quantité débordent hors du dialog 760px et sont clippées. */
.isis-grid--m2c-postes .isis-grid__head,
.isis-grid--m2c-postes .isis-grid__row {
    grid-template-columns: 36px minmax(200px, 1fr) 80px 110px 120px;
    min-width: 0;
}
.isis-grid__short-code {
    display: inline-block;
    margin-left: 0.4rem;
    padding: 0.05rem 0.4rem;
    font-family: 'Geist Mono', ui-monospace, monospace;
    font-size: 0.7rem;
    color: var(--isis-text-muted);
    background: var(--isis-surface-alt);
    border-radius: 4px;
}
.isis-grid__badge-default {
    display: inline-block;
    margin-left: 0.4rem;
    padding: 0.05rem 0.4rem;
    font-size: 0.65rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--isis-text-muted);
    background: var(--isis-surface-alt);
    border: 1px solid var(--isis-border);
    border-radius: 4px;
}
/* Badge « jamais émis » : remplace la valeur 0 brute dans la colonne
   compteur (page /gescom/config/numerotation). Plus explicite que « 0 »
   et signale visuellement les structures inactives sans alarmer. */
.isis-grid__badge-never {
    display: inline-block;
    padding: 0.05rem 0.45rem;
    font-size: 0.7rem;
    font-weight: 500;
    color: var(--isis-text-muted);
    background: var(--isis-surface-alt);
    border: 1px dashed var(--isis-border);
    border-radius: 10px;
    font-variant-numeric: normal;
}
.isis-fmt-pattern,
.isis-fmt-preview-inline {
    font-family: 'Geist Mono', ui-monospace, monospace;
    font-size: 0.78rem;
    background: var(--isis-surface-alt);
    padding: 0.1rem 0.4rem;
    border-radius: 4px;
    word-break: break-all;
}
/* Distinction sémantique : "pattern" = code source, "preview" = rendu (italique) */
.isis-fmt-pattern { color: var(--isis-text); }
.isis-fmt-preview-inline { color: var(--isis-text-muted); font-style: italic; }

/* ============================================================================
   Badges de participant (cotraitant / sous-traitant) — sous-onglet Participants
   de la fiche devis, dialog de complétion des contacts, et liste des devis.
   Ces deux classes descendent du bandeau permanent supprimé le 2026-09-07 : elles
   lui ont survécu parce que trois écrans qui n'en ont jamais eu s'en servent, et
   ont été renommées pour ne plus porter le nom d'un composant disparu.
   ============================================================================ */
.isis-participant-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.18rem 0.55rem;
    font-size: 0.74rem;
    border-radius: 4px;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    color: var(--isis-text);
    white-space: nowrap;
}
.isis-participant-chip strong {
    font-size: 0.62rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    padding: 0.05rem 0.3rem;
    border-radius: 3px;
    background: var(--isis-surface-alt);
    color: var(--isis-text-muted);
}
/* Cotraitant : accent transverse (4b5fad sur eef0f9 = 5.21:1, AA pass). */
.isis-participant-chip.is-cotraitant strong {
    background: var(--isis-accent-soft);
    color: var(--isis-accent);
}
/* Sous-traitant : neutre. L'orange warning suggérait à tort un état d'alerte et
   donnait 2.86:1 (échec AA). Bg surface-alt + texte dark = identité distincte
   du cotraitant + contraste >9:1. */
.isis-participant-chip.is-soustraitant strong {
    background: var(--isis-surface-alt);
    color: var(--isis-text);
}
/* Drapeau « ext. » pour les partenaires externes (P3). */
.isis-participant-ext-flag {
    font-size: 0.58rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    color: var(--isis-text-muted);
    background: var(--isis-surface-alt);
    border: 1px solid var(--isis-border);
    padding: 0 0.3rem;
    border-radius: 3px;
}
/* Table des participants du sous-onglet — largeur plancher + défilement propre.
   Le dialog qu'elle remplace imposait min-width: 1040px ; devenue section, elle
   retombait à 709 px dans un panneau de 757, et le chevron des listes déroulantes
   chevauchait leur texte. La largeur plancher rend aux colonnes leurs dimensions
   d'origine, le conteneur absorbe le dépassement. */
.isis-participants-table-scroll {
    overflow-x: auto;
    max-width: 100%;
}
.isis-participants-table-scroll > .isis-devis-items {
    min-width: 980px;
}

/* Le bouton qui retire un participant est la 7e colonne d'une table de 980 px dans
   un panneau de 757 : sans cette colle, corriger une saisie exigeait de deviner un
   défilement horizontal. Les montants, eux, se lisent dans le contexte de leur
   ligne et n'ont pas à être collés. */
.isis-participants-table-scroll th:last-child,
.isis-participants-table-scroll td:last-child {
    position: sticky;
    right: 0;
    z-index: 1;
    background: var(--isis-surface);
    box-shadow: -6px 0 6px -6px var(--isis-scroll-shadow-ink);
}

/* Mention « Figé » du sous-onglet Participants — reprise du bandeau supprimé
   le 2026-09-07. Nom sans `ribbon` : le bandeau n'existe plus. */
.isis-participants-locked {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    font-size: 0.72rem;
    color: var(--isis-text-muted);
}
.isis-participants-locked .rzi {
    font-size: 14px;
    opacity: 0.6;
}

/* Titre de section au sein d'une rich-page (sépare deux grilles) */
.isis-rich-section-title {
    font-size: 0.75rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--isis-text-soft);
    margin: 1.5rem 0 0.6rem;
}

/* Dialog DevisNumberFormatDialog — input pattern, aperçu, erreurs, tokens */
.isis-fmt-input {
    width: 100%;
    font-family: 'Geist Mono', ui-monospace, monospace;
    font-size: 0.88rem;
    padding: 0.55rem 0.7rem;
    border: 1px solid var(--isis-border);
    border-radius: 6px;
    background: var(--isis-surface);
    color: var(--isis-text);
}
.isis-fmt-input:focus-visible {
    outline: 2px solid var(--isis-accent);
    outline-offset: 1px;
    border-color: var(--isis-accent);
}
.isis-fmt-errors {
    list-style: disc;
    padding-left: 1.25rem;
    margin: 0.4rem 0 0;
    color: var(--isis-danger);
    font-size: 0.78rem;
}
.isis-fmt-preview {
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
    background: var(--isis-surface-alt);
    border: 1px solid var(--isis-border);
    border-radius: 6px;
    padding: 0.6rem 0.85rem;
}
.isis-fmt-preview__value {
    font-family: 'Geist Mono', ui-monospace, monospace;
    font-size: 1rem;
    font-weight: 600;
    color: var(--isis-text);
    font-variant-numeric: tabular-nums;
}
.isis-fmt-preview__placeholder {
    font-size: 1rem;
    color: var(--isis-text-muted);
}
.isis-fmt-preview__hint {
    font-size: 0.72rem;
    color: var(--isis-text-muted);
}
.isis-fmt-tokens {
    padding: 0;
    margin: 0;
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0.35rem 0.85rem;
}
.isis-fmt-tokens > div {
    display: flex;
    align-items: baseline;
    gap: 0.5rem;
    font-size: 0.78rem;
}
.isis-fmt-tokens dt { margin: 0; }
.isis-fmt-tokens dd { margin: 0; color: var(--isis-text-muted); }
.isis-fmt-tokens code {
    font-family: 'Geist Mono', ui-monospace, monospace;
    font-size: 0.74rem;
    color: var(--isis-text);
    background: var(--isis-surface-alt);
    padding: 0.05rem 0.35rem;
    border-radius: 3px;
    white-space: nowrap;
}
@media (max-width: 720px) {
    .isis-fmt-tokens { grid-template-columns: 1fr; }
}

/* Variante grille TarifListPage : 7 colonnes (status / article / entreprise / libellé / prix+devise / validité / actions) */
.isis-grid--tarifs .isis-grid__head,
.isis-grid--tarifs .isis-grid__row {
    grid-template-columns: 32px minmax(200px, 1.4fr) minmax(160px, 1fr) minmax(140px, 1fr) 200px 180px 90px;
    min-width: 1100px;
}

/* Variante grille CountryListPage : 7 colonnes (status / code / nom / iso3 / devise / indicatif / actions) */
/* Huit pistes depuis le 2026-09-06 : la colonne « Référentiel » (FR-PCG, MA-CGNC,
   OHADA) est apparue — la recherche la promettait déjà dans son placeholder sans
   qu'aucune colonne ne la montre. La pastille d'état passe de 32 à 44 px : elle porte
   désormais l'entonnoir État, dont la cible fait 24 px (WCAG 2.5.8). */
.isis-grid--countries .isis-grid__head,
.isis-grid--countries .isis-grid__row {
    grid-template-columns: 44px 90px minmax(200px, 1.5fr) 90px 120px 150px 110px 80px;
    min-width: 900px;
}

/* Bannière de filtre actif (ex: "Filtré par article X" sur TarifListPage) -- */
.isis-active-filter {
    display: flex;
    align-items: center;
    gap: 0.55rem;
    padding: 0.55rem 0.85rem;
    margin: 0 0 0.55rem 0;
    /* Module-agnostique : suit la couleur du module courant (--isis-current-mod
       posée par .isis-shell__content.mod-*), accent générique en repli. */
    border: 1px solid var(--isis-current-mod, var(--isis-accent));
    border-radius: 4px;
    background: var(--isis-current-mod-soft, var(--isis-surface-alt));
    color: var(--isis-text);
    font-size: 0.82rem;
}
.isis-active-filter strong {
    color: var(--isis-current-mod, var(--isis-accent));
}
.isis-active-filter__clear {
    margin-left: auto;
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    padding: 0.2rem 0.5rem;
    font-size: 0.78rem;
    border: 1px solid var(--isis-border);
    border-radius: 4px;
    background: var(--isis-surface, #fff);
    color: var(--isis-text);
    cursor: pointer;
    transition: background 0.12s, color 0.12s;
}
.isis-active-filter__clear:hover,
.isis-active-filter__clear:focus-visible {
    background: var(--isis-current-mod, var(--isis-accent));
    color: var(--isis-surface, #fff);
    outline: none;
}

/* Liste de prix dans le sidepanel catalogue ------------------------------- */
.isis-price-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
}
.isis-price-list__item {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 0.5rem;
    padding: 0.5rem 0.55rem;
    border: 1px solid var(--isis-border);
    border-radius: 4px;
    background: var(--isis-surface, #fff);
}
.isis-price-list__item.is-default {
    border-color: var(--isis-mod-gescompta, #4b5fad);
    background: var(--isis-mod-gescompta-soft, #eef0f8);
}
.isis-price-list__item.is-expired {
    opacity: 0.6;
}
.isis-price-list__main {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 0.18rem;
}
.isis-price-list__price {
    display: flex;
    align-items: baseline;
    gap: 0.25rem;
    font-variant-numeric: tabular-nums;
    font-size: 0.95rem;
    color: var(--isis-text);
}
.isis-price-list__currency {
    font-size: 0.78rem;
    color: var(--isis-text-muted);
    font-weight: 500;
}
.isis-price-list__ht {
    font-size: 0.7rem;
    color: var(--isis-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    margin-left: 0.2rem;
}
.isis-price-list__meta {
    font-size: 0.74rem;
    color: var(--isis-text-muted);
    display: flex;
    flex-wrap: wrap;
    gap: 0.15rem;
}
.isis-price-list__sep {
    opacity: 0.5;
}
.isis-price-list__badges {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem;
    margin-top: 0.15rem;
}
.isis-price-list__badge {
    display: inline-block;
    padding: 1px 6px;
    font-size: 0.66rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    border-radius: var(--isis-radius-pill);
    border: 1px solid currentColor;
    color: var(--isis-text-muted);
    background: transparent;
}
.isis-price-list__badge.is-default {
    color: var(--isis-mod-gescompta, #4b5fad);
    background: var(--isis-surface, #fff);
}
.isis-price-list__badge.is-expired {
    color: var(--isis-warning, #a66f02);
}
.isis-price-list__actions {
    display: flex;
    gap: 0.15rem;
    flex: 0 0 auto;
}

/* WCAG : cacher visuellement mais garder accessible aux lecteurs d'écran */
.visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}
.isis-rich-header__badges {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    flex-wrap: wrap;
    margin-top: 0.2rem;
}
/* Badge ACTIONNABLE d'une rangée de badges : même gabarit qu'un RadzenBadge pill
   Shade.Lighter, mais c'est un vrai <button> — focusable, annoncé actionnable,
   et il porte une bordure pour se distinguer des badges purement descriptifs
   qui l'entourent. Introduit 2026-07-19 pour l'état du dossier administratif
   sur la fiche tiers (le détail vit dans un dialog, le signal reste ici). */
.isis-badge-btn {
    display: inline-flex;
    align-items: center;
    gap: 0.2rem;
    padding: 0.1rem 0.4rem 0.1rem 0.6rem;
    border-radius: var(--isis-radius-pill);
    border: 1px solid transparent;
    font-family: inherit;
    font-size: 0.72rem;
    font-weight: 600;
    line-height: 1.65;
    white-space: nowrap;
    cursor: pointer;
    transition: border-color 0.12s ease, box-shadow 0.12s ease;
}
.isis-badge-btn.is-warning {
    background: var(--isis-warning-soft);
    color: var(--isis-warning);
    border-color: color-mix(in srgb, var(--isis-warning) 28%, transparent);
}
.isis-badge-btn.is-info {
    background: var(--isis-info-soft);
    color: var(--isis-info);
    border-color: color-mix(in srgb, var(--isis-info) 28%, transparent);
}
/* Succès actionnable : « Convertie · N offres de prix » sur la fiche demande client, qui ouvre
   l'onglet des offres générées. Même couple de jetons que le RadzenBadge Success Shade.Lighter. */
.isis-badge-btn.is-success {
    background: var(--isis-success-soft);
    color: var(--isis-success);
    border-color: color-mix(in srgb, var(--isis-success) 28%, transparent);
}
.isis-badge-btn:hover { border-color: currentColor; }
.isis-badge-btn:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 35%, transparent);
}
.isis-badge-btn .rz-icon,
.isis-badge-btn .rzi { font-size: 14px; opacity: 0.75; }

.isis-rich-header__pill {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0.2rem 0.6rem;
    border-radius: var(--isis-radius-pill);
    font-size: 0.72rem;
    font-weight: 500;
    /* Teinte module par défaut — accent global en fallback hors-module */
    background: var(--isis-current-mod-soft, var(--isis-accent-soft));
    color: var(--isis-current-mod, var(--isis-accent));
    transition: background-color 200ms ease, color 200ms ease;
}
/* Variantes sémantiques — priorité sur la teinte module */
.isis-rich-header__pill--warning { background: var(--isis-warning-soft); color: #92400e; }
.isis-rich-header__pill--danger  { background: var(--isis-danger-soft);  color: #991b1b; }
.isis-rich-header__pill--success { background: var(--isis-success-soft); color: #065f46; }
/* Variante cliquable : un <a> stylé comme un pill, avec hover discret. */
a.isis-rich-header__pill {
    text-decoration: none;
    cursor: pointer;
}
a.isis-rich-header__pill:hover {
    text-decoration: underline;
    text-decoration-thickness: 1px;
    text-underline-offset: 2px;
}
a.isis-rich-header__pill:focus-visible {
    outline: 2px solid var(--isis-current-mod, var(--isis-accent));
    outline-offset: 2px;
}
/* Variante cliquable : un <button> stylé comme un pill (reset natif), déclenche un filtre local. */
button.isis-pill-btn {
    border: none;
    font: inherit;
    cursor: pointer;
}
button.isis-pill-btn:hover { filter: brightness(0.97); }
/* Variante cliquable : un <button> stylé comme un pill (reset natif), ouvre un dialog
   (ex. badge « Suivi : … » de CommandeDetail — changement de mode de suivi, migration 0333). */
button.isis-rich-header__pill--action {
    border: none;
    font: inherit;
    cursor: pointer;
}
button.isis-rich-header__pill--action:hover { filter: brightness(0.97); }
button.isis-rich-header__pill--action:focus-visible {
    outline: 2px solid var(--isis-current-mod, var(--isis-accent));
    outline-offset: 2px;
}
button.isis-pill-btn.is-active { box-shadow: inset 0 0 0 1.5px currentColor; }
button.isis-pill-btn:focus-visible {
    outline: 2px solid var(--isis-current-mod, var(--isis-accent));
    outline-offset: 2px;
}
/* Bouton « Réinitialiser » d'une barre de filtres (texte + icône, discret). */
.isis-filter-bar__clear {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    margin-left: auto;
    padding: 0.25rem 0.55rem;
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-sm);
    background: var(--isis-surface);
    color: var(--isis-text-muted);
    font-size: 0.78rem;
    cursor: pointer;
    transition: background-color 150ms ease, color 150ms ease;
}
.isis-filter-bar__clear:hover { background: var(--isis-surface-alt); color: var(--isis-text); }

/* Compteur textuel discret en bout de barre de filtres (ex. « 3 propre(s) · 5 héritée(s) »). */
.isis-filter-bar__count {
    margin-left: auto;
    font-size: var(--isis-fs-caption);
    color: var(--isis-text-muted);
    white-space: nowrap;
}
.isis-filter-bar__clear:focus-visible {
    outline: 2px solid var(--isis-current-mod, var(--isis-accent));
    outline-offset: 2px;
}
.isis-rich-header__scope {
    display: inline-flex;
    background: var(--isis-surface-alt);
    border-radius: 8px;
    padding: 2px;
    gap: 1px;
    align-self: flex-start;
}
.isis-rich-header__scope button {
    height: 28px;
    padding: 0 0.7rem;
    border: none;
    background: transparent;
    color: var(--isis-text-muted);
    font-size: 0.75rem;
    border-radius: 6px;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
}
.isis-rich-header__scope button.active {
    background: var(--isis-surface);
    color: var(--isis-text);
    border-color: var(--isis-border);
    font-weight: 500;
}

/* KPI hero — refonte B "Branded depth" 2026-05-17 : gradient subtil module 135°
   (blanc → tinte module 6%). Donne un léger relief volumétrique et une touche
   d'identité module au bandeau principal de chaque page. */
.isis-kpi-hero {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
    gap: 0.5rem;
    background: var(--isis-surface);
    background: linear-gradient(135deg,
        var(--isis-surface) 0%,
        color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 6%, var(--isis-surface)) 100%);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius);
    padding: 0.85rem 1rem;
    box-shadow: var(--isis-elevation-1);
    /* Audit UX 2026 : top-align les cartes. Sans ça, une carte plus haute
       (ex: KPI-ancre avec sparkline) étire les autres en stretch et fait
       flotter leur contenu verticalement. Neutre quand toutes ont la même hauteur. */
    align-items: start;
}
/* Rail réduit à DEUX cartes (2026-09-05, revue gespla) : `auto-fit` + `1fr` les étirait sur
   la moitié de l'écran chacune, deux nombres perdus dans deux hectares de blanc. On borne la
   colonne — le rail reste à gauche, à la largeur de ce qu'il porte. */
.isis-kpi-hero--duo { grid-template-columns: repeat(2, minmax(200px, 300px)); justify-content: start; }

.isis-kpi-card {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    padding: 0.2rem 0.6rem;
    border-left: 1px solid var(--isis-border);
}
.isis-kpi-card:first-child { border-left: none; padding-left: 0.2rem; }

/* KPI card cliquable (drill-down filtre statut). Hérite des styles .isis-kpi-card
   mais ajoute interactivité : cursor pointer, hover subtle, état actif marqué. */
button.isis-kpi-card--clickable {
    background: transparent;
    text-align: left;
    cursor: pointer;
    font-family: inherit;
    border-top: none;
    border-right: none;
    border-bottom: none;
    /* Garde le border-left de .isis-kpi-card pour la séparation */
    transition: background 120ms ease, transform 60ms ease;
    position: relative;
}
button.isis-kpi-card--clickable:hover {
    background: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 4%, transparent);
}
button.isis-kpi-card--clickable:focus-visible {
    outline: 2px solid var(--isis-accent);
    outline-offset: 2px;
}
button.isis-kpi-card--clickable.is-active {
    background: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 10%, transparent);
}
button.isis-kpi-card--clickable.is-active::after {
    content: "";
    position: absolute;
    left: 50%;
    bottom: -0.4rem;
    transform: translateX(-50%);
    width: 60%;
    height: 2px;
    background: var(--isis-current-mod, var(--isis-accent));
    border-radius: 1px;
}
.isis-kpi-card__label {
    font-size: 0.65rem;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--isis-text-soft);
}
.isis-kpi-card__value {
    /* Aligné NetLogger V3 (cdv3-kpi-num = 20px/600 mono -0.01em). ISIS détendu = 22px.
       KPI ≤ Titre H5 : hiérarchie respectée (KPI accent rythme le scan, titre reste roi). */
    font-size: 1.375rem;
    font-weight: 600;
    /* Couleur du module courant par défaut — pop sur le total/principal.
       Les classes .is-warning/.is-danger/.is-success/.is-info gardent la priorité
       quand la sémantique l'exige (cf. ci-dessous). */
    color: var(--isis-current-mod, var(--isis-text));
    line-height: 1.15;
    font-family: var(--isis-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
    font-variant-numeric: tabular-nums;
    letter-spacing: -0.01em;
}
.isis-kpi-card__value.is-info    { color: var(--isis-mod-gescom); }
/* Audit V1.5 2026-05-19 : hex hardcodés remplacés par les variables sémantiques
   (#d97706 / #dc2626 / #10b981 violaient DESIGN.md « palette --isis-* uniquement ». */
.isis-kpi-card__value.is-warning { color: var(--isis-warning); }
.isis-kpi-card__value.is-danger  { color: var(--isis-danger); }
.isis-kpi-card__value.is-success { color: var(--isis-success); }
.isis-kpi-card__value.is-neutral { color: var(--isis-text); }
/* is-module : utilise la couleur du module courant (--isis-current-mod défini
   par .isis-shell__content.mod-{code}). Préférer à is-info quand on veut
   l'identité couleur de la page courante plutôt que le bleu gescom en dur. */
.isis-kpi-card__value.is-module  { color: var(--isis-current-mod); }
.isis-kpi-card__hint {
    font-size: 0.7rem;
    color: var(--isis-text-soft);
}
/* Sparkline compacte sous un KPI hero (tendance 12 mois de la métrique-ancre).
   Rendu inline SVG par RenderSparkline ; vide si pas d'historique réel. */
.isis-kpi-card__spark {
    display: block;
    width: 100%;
    height: 22px;
    margin-top: 0.3rem;
    /* opacity volontairement >= 0.85 : le trait terre-cuite (#c2410c) sur fond
       blanc donne ~5.2:1 à pleine opacité (passe WCAG 1.4.11 graphique 3:1).
       L'audit UX proposait 0.5 mais ça tombe à ~2.2:1 → refusé (a11y prime,
       la sparkline porte une info de tendance). */
    opacity: 0.85;
    overflow: hidden;
}

/* ════════════════════════════════════════════════════════════════════════════
   Dashboards — pattern partagé « INSTRUMENT BENTO » (cf. docs/DASHBOARD-DESIGN.md).
   Scope .isis-dash posé sur le wrapper de CHAQUE page dashboard (ex-.isis-gescom-dash,
   généralisé 2026-08-25) : KPI héros + grille d'instruments à puce d'icône, valeurs
   mono, sections en cartes blanches arrondies, charts amCharts. La teinte suit le
   module courant via --isis-current-mod. N'impacte aucune page non-dashboard.
   ════════════════════════════════════════════════════════════════════════════ */
:root { --isis-cockpit-mono: 'Geist Mono', var(--isis-font-mono, ui-monospace), SFMono-Regular, Menlo, monospace; }

/* ── KPI hero : grille de cartes élevées ── */
.isis-dash .isis-kpi-hero {
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 0.75rem;
    background: transparent;
    border: 0;
    box-shadow: none;
    padding: 0;
    align-items: stretch;
}
@media (max-width: 1100px) { .isis-dash .isis-kpi-hero { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 560px)  { .isis-dash .isis-kpi-hero { grid-template-columns: 1fr; } }
.isis-dash .isis-kpi-card {
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: 0.75rem;
    box-shadow: var(--isis-elevation-1);
    padding: 0.85rem 0.9rem;
    gap: 0.2rem;
    transition: box-shadow .14s ease, transform .08s ease;
}
.isis-dash .isis-kpi-card:hover { box-shadow: var(--isis-elevation-hover); transform: translateY(-1px); }
.isis-dash .isis-kpi-card__head { display: flex; align-items: center; gap: 0.5rem; }
.isis-dash .isis-kpi-card__chip {
    width: 28px; height: 28px; border-radius: 8px; flex-shrink: 0;
    display: inline-grid; place-items: center;
    background: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 11%, var(--isis-surface));
    color: var(--isis-current-mod, var(--isis-accent));
}
.isis-dash .isis-kpi-card__chip .rzi { font-size: 1rem; line-height: 1; }
.isis-dash .isis-kpi-card__label {
    font-size: var(--isis-fs-label); letter-spacing: .04em; text-transform: uppercase;
    color: var(--isis-text-muted); font-weight: 600; margin: 0;
}
.isis-dash .isis-kpi-card__value {
    font-family: var(--isis-cockpit-mono);
    font-size: 1.5rem; font-weight: 700; letter-spacing: -.02em; line-height: 1.02;
    margin-top: 0.3rem;
}
.isis-dash .isis-kpi-card__hint { font-size: var(--isis-fs-label); margin-top: 0.25rem; color: var(--isis-text-muted); line-height: 1.25; }
/* Indicateur de tendance KPI (style mockup : flèche + % coloré + contexte gris) */
.isis-dash .isis-kpi-card__delta-row { display: flex; align-items: center; gap: 0.4rem; margin-top: 0.3rem; font-size: var(--isis-fs-label); }
.isis-dash .isis-kpi-card__delta { display: inline-flex; align-items: center; gap: 0.1rem; font-weight: 600; font-variant-numeric: tabular-nums; }
.isis-dash .isis-kpi-card__delta .rzi { font-size: 14px; }
.isis-dash .isis-kpi-card__delta.is-up { color: var(--isis-success); }
.isis-dash .isis-kpi-card__delta.is-down { color: var(--isis-danger); }
.isis-dash .isis-kpi-card__delta-ctx { color: var(--isis-text-muted); }
/* narrative anchor terre-cuite : 1re carte (CA signé) */
.isis-dash .isis-kpi-hero > .isis-kpi-card:first-child {
    background: linear-gradient(160deg, var(--isis-accent-soft), var(--isis-surface) 70%);
    border-color: color-mix(in srgb, var(--isis-accent) 22%, var(--isis-border));
}
.isis-dash .isis-kpi-hero > .isis-kpi-card:first-child .isis-kpi-card__chip {
    background: color-mix(in srgb, var(--isis-accent) 13%, var(--isis-surface));
    color: var(--isis-accent);
}
.isis-dash .isis-kpi-hero > .isis-kpi-card:first-child .isis-kpi-card__value { color: var(--isis-accent-strong); }

/* ════════ INSTRUMENT BENTO (2026-06, /taste-design) — KPI hero hiérarchisé ════════
   Au lieu de 9 cartes égales à plat (anti-pattern « 3 cartes égales »), une tuile HÉROS
   dominante (CA signé) à gauche + une grille d'instruments compacts à droite. */
.isis-dash .isis-kpi-hero {
    grid-template-columns: minmax(300px, 1.1fr) 2.4fr;
    align-items: stretch;
    gap: 0.85rem;
    padding: 0.85rem;
}
/* Tuile héros : dominante, élévée d'un cran, valeur géante mono terre-cuite. */
.isis-dash .isis-kpi-card--hero {
    border-left: none;
    padding: 1rem 1.25rem;
    border-radius: var(--isis-radius);
    box-shadow: var(--isis-elevation-hover);
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 0.4rem;
}
.isis-dash .isis-kpi-card--hero .isis-kpi-card__value {
    font-size: 2.55rem;
    line-height: 1.04;
}
/* Grille secondaire d'instruments (3 colonnes), séparés par filets verticaux. */
.isis-dash .isis-kpi-hero__grid {
    display: grid;
    grid-template-columns: repeat(3, minmax(150px, 1fr));
    gap: 0.45rem 0.9rem;
    align-content: center;
}
.isis-dash .isis-kpi-hero__grid .isis-kpi-card { padding: 0.25rem 0.75rem; }
.isis-dash .isis-kpi-hero__grid .isis-kpi-card:nth-child(3n+1) {
    border-left: none;
    padding-left: 0.2rem;
}
.isis-dash .isis-kpi-hero__grid .isis-kpi-card__value { font-size: 1.4rem; }
@media (max-width: 1000px) {
    .isis-dash .isis-kpi-hero { grid-template-columns: 1fr; }
    .isis-dash .isis-kpi-hero__grid { grid-template-columns: repeat(2, 1fr); }
    .isis-dash .isis-kpi-hero__grid .isis-kpi-card { border-left: none; padding-left: 0.2rem; }
}
@media (max-width: 600px) {
    .isis-dash .isis-kpi-hero__grid { grid-template-columns: 1fr; }
}

/* ── Sections en cartes blanches ── */
.isis-dash .isis-rich-section {
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: 0.75rem;
    box-shadow: var(--isis-elevation-1);
    padding: 1.1rem 1.2rem;
}
.isis-dash .isis-dash-2col > .isis-rich-section { margin-top: 0; }
.isis-dash .isis-rich-section__header { border-bottom: 0; padding: 0; margin-bottom: 0.6rem; }
.isis-dash .isis-rich-section__title { font-size: 0.9rem; font-weight: 700; color: var(--isis-text); text-transform: none; letter-spacing: 0; }
.isis-dash .isis-rich-section__subtitle { font-size: 11.5px; color: var(--isis-text-muted); font-weight: 400; }

/* État vide d'une section de fiche. Existe pour que ces phrases cessent d'emprunter
   .isis-rich-page__note — la classe du CHAPÔ SOUS LE FIL D'ARIANE, que la doctrine
   d'harmonisation retire des pages : un état vide n'est pas un chapô de page, et le
   confondre condamnait l'un à disparaître avec l'autre. */
.isis-rich-section__empty {
    margin: 0;
    padding: 0.6rem 0 0.2rem;
    font-size: 0.78rem;
    color: var(--isis-text-soft);
}

/* ── Densité : sections de listes plus compactes (marges, rejets, top clients,
   à relancer, services) — demande 2026 « plus compact ». ── */
.isis-dash .isis-rich-section { padding: 0.95rem 1.05rem; }
.isis-dash .isis-rich-section__header { margin-bottom: 0.45rem; }
.isis-dash .isis-leaderboard__row { padding: 0.26rem 0; }
.isis-dash .isis-leaderboard__name { font-size: 0.8rem; line-height: 1.25; }
.isis-dash .isis-leaderboard__sub { font-size: 0.7rem; line-height: 1.2; }
.isis-dash .isis-leaderboard__value { font-size: 0.8rem; }
.isis-dash .isis-margin-perf { gap: 0.55rem; }
.isis-dash .isis-margin-perf__list { gap: 0.05rem; }
.isis-dash .isis-margin-perf__row { padding: 0.24rem 0; }
.isis-dash .isis-margin-perf__name { font-size: 0.8rem; }
.isis-dash .isis-margin-perf__hint { font-size: 0.68rem; line-height: 1.2; }
.isis-dash .isis-margin-perf__count,
.isis-dash .isis-margin-perf__value { font-size: 0.75rem; }
.isis-dash .isis-dash-2col { gap: 1rem; }

/* ── Conteneur de canvas Chart.js (hauteur fixe pour le responsive Chart.js) ── */
/* INSTRUMENT BENTO : canvas compacts (l'audit a montré qu'ils s'étiraient dans du vide). */
.isis-dash .isis-dash-canvas { position: relative; height: 250px; }
/* Donuts (Mix, Répartition) : agrandis — ils étaient bridés trop petits par la hauteur. */
.isis-dash .isis-dash-canvas--sm { position: relative; height: 300px; }
/* Bento charts : 3 colonnes (Évolution · Mix · Funnel · Répartition · Cycle · Forecast).
   Remplit la pleine largeur avec 6 tuiles compactes au lieu de 3 rangées de 2 tuiles
   étirées. Pas de max-width funnel (amCharts mesure mal un conteneur borné → rendu vide ;
   en cellule 1/3 il est déjà compact). */
.isis-dash .isis-dash-bento {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 1rem;
    align-items: start;
}
@media (max-width: 1100px) { .isis-dash .isis-dash-bento { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 700px)  { .isis-dash .isis-dash-bento { grid-template-columns: 1fr; } }
/* Classement large (Top services, section pleine largeur) → 2 colonnes : remplit la
   largeur avec du contenu au lieu de barres géantes qui traversent toute la page. */
.isis-dash .isis-leaderboard--wide {
    display: grid;
    grid-template-columns: 1fr 1fr;
    column-gap: 2.5rem;
    align-content: start;
}
@media (max-width: 820px) {
    .isis-dash .isis-leaderboard--wide { grid-template-columns: 1fr; }
}

/* ── Sparkline mini dans une carte KPI (vélocité) ── */
.isis-dash .isis-kpi-card__spark { position: relative; height: 38px; margin-top: 8px; }

/* ── Jauge radiale d'atteinte quota (demi-cercle) ── */
.isis-dash .isis-quota-gauge { position: relative; height: 180px; margin-top: 4px; }

/* ── Barres de distribution amCharts (cycle commercial / perf marge) ── */
.isis-dash .isis-cycle-detail__chart { position: relative; height: 48px; margin-bottom: 10px; }
.isis-dash .isis-margin-perf__chart { position: relative; height: 44px; margin-bottom: 12px; }

/* ── Funnel (dans carte) : barres arrondies, compteur mono ── */
.isis-dash .isis-funnel { align-items: stretch; }
.isis-dash .isis-funnel__row { grid-template-columns: 104px minmax(0, 1fr) 150px; gap: 12px; }
.isis-dash .isis-funnel__bar-wrap { height: 24px; border-radius: 7px; background: var(--isis-surface-alt); }
.isis-dash .isis-funnel__bar { border-radius: 7px; background-image: linear-gradient(180deg, rgba(255,255,255,.22), rgba(255,255,255,0) 55%); }
.isis-dash .isis-funnel__count { font-family: var(--isis-cockpit-mono); font-size: 11px; left: 9px; }
.isis-dash .isis-funnel__sub { font-size: 11px; }

/* ── Bande de conversion sous le funnel amCharts (préserve le % par étape) — global (gescom/gesmaff…) ── */
.isis-funnel-conv {
    list-style: none; margin: 10px 0 0; padding: 0;
    display: flex; flex-wrap: wrap; gap: 6px 14px;
}
.isis-funnel-conv__item {
    display: inline-flex; align-items: baseline; gap: 6px;
    font-size: 11px; color: var(--isis-text-muted);
}
.isis-funnel-conv__dot {
    width: 9px; height: 9px; border-radius: 3px; align-self: center;
    box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .12);
}
.isis-funnel-conv__label { color: var(--isis-text); font-weight: 500; }
.isis-funnel-conv__count { font-family: var(--isis-cockpit-mono); color: var(--isis-text); }

/* ── Leaderboard : barre qui REMPLIT le milieu (libellé | barre | valeur) ── */
.isis-dash .isis-leaderboard__value,
.isis-dash .isis-donut__legend-value,
.isis-dash .isis-donut__total { font-family: var(--isis-cockpit-mono); }
.isis-dash .isis-leaderboard__row {
    grid-template-columns: minmax(170px, 1fr) minmax(0, 2.2fr) auto;
    background: transparent; padding: 0.4rem 0; border-radius: 0;
    border-bottom: 1px solid var(--isis-border);
}
.isis-dash .isis-leaderboard__row:hover { background: transparent; }
.isis-dash .isis-leaderboard__bar-wrap { height: 8px; border-radius: var(--isis-radius-pill); }
.isis-dash .isis-leaderboard__bar {
    border-radius: var(--isis-radius-pill); background: var(--isis-current-mod, var(--isis-accent));
    background-image: linear-gradient(180deg, rgba(255,255,255,.25), rgba(255,255,255,0) 60%);
}

/* ── Cycle : timeline fine ── */
.isis-dash .isis-cycle-detail__stack { height: 24px; }
.isis-dash .isis-donut-wrap { gap: 1.4rem; }

/* ────────────────────────────────────────────────────────────────────────────
   KPIs étendus : graphique tendance + top liste + alerte (factures, etc.)
   Pattern Phase 2.B.3 facturation, réutilisable par toute page liste qui veut
   enrichir son KPI hero avec une dimension temporelle + un top + une alerte.
   ──────────────────────────────────────────────────────────────────────────── */
.isis-kpi-extended {
    display: grid;
    grid-template-columns: 2fr 1fr;
    gap: 1.25rem;
    margin: 0;
    align-items: stretch;
}
.isis-kpi-extended__chart,
.isis-kpi-extended__top {
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius);
    padding: 0.85rem 1rem;
    box-shadow: var(--isis-elevation-1);
    min-width: 0;
}
.isis-kpi-extended__chart h3,
.isis-kpi-extended__top h3 {
    font-size: 0.7rem;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--isis-text-soft);
    margin: 0 0 0.6rem 0;
    font-weight: 600;
}
.isis-kpi-extended__charts-row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 1.25rem;
    align-items: start;
}
.isis-kpi-extended__chart-col {
    min-width: 0;
}
.isis-kpi-extended__chart-col + .isis-kpi-extended__chart-col {
    padding-left: 1.25rem;
    border-left: 1px solid var(--isis-border);
}
@media (max-width: 1100px) {
    .isis-kpi-extended__charts-row {
        grid-template-columns: 1fr;
    }
    .isis-kpi-extended__chart-col + .isis-kpi-extended__chart-col {
        padding-left: 0;
        padding-top: 0.85rem;
        border-left: 0;
        border-top: 1px solid var(--isis-border);
    }
}
.isis-kpi-extended__chart svg {
    width: 100%;
    height: auto;
    max-height: 200px;
    display: block;
}
.isis-kpi-extended__empty {
    color: var(--isis-text-muted);
    font-size: 0.85rem;
    text-align: center;
    padding: 1rem 0.5rem;
}
.isis-kpi-extended__alert {
    grid-column: 1 / -1;
    display: flex;
    align-items: center;
    gap: 0.75rem;
    background: color-mix(in srgb, var(--isis-danger, #dc2626) 8%, var(--isis-surface));
    border: 1px solid var(--isis-danger, #dc2626);
    box-sizing: border-box;
    border-radius: 4px;
    padding: 0.7rem 0.95rem;
    color: var(--isis-text);
}
.isis-kpi-extended__alert > svg,
.isis-kpi-extended__alert > i,
.isis-kpi-extended__alert > .rz-icon {
    color: var(--isis-danger, #dc2626);
    flex-shrink: 0;
}
.isis-kpi-extended__alert div {
    display: flex;
    flex-direction: column;
    gap: 0.1rem;
    min-width: 0;
}
.isis-kpi-extended__alert strong {
    font-size: 0.9rem;
    font-weight: 600;
}
.isis-kpi-extended__alert span {
    font-size: 0.78rem;
    color: var(--isis-text-muted);
}
@media (max-width: 900px) {
    .isis-kpi-extended {
        grid-template-columns: 1fr;
    }
}

/* Top liste (Top 5 clients/fournisseurs/etc.) — items numérotés en rang */
.isis-top-list {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 0.45rem;
}
.isis-top-list li {
    display: grid;
    grid-template-columns: 24px 1fr auto;
    align-items: center;
    gap: 0.55rem;
    font-size: 0.85rem;
    min-width: 0;
}
.isis-top-list__rank {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    border-radius: 50%;
    background: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 12%, transparent);
    color: var(--isis-current-mod, var(--isis-accent));
    font-weight: 600;
    font-size: 0.75rem;
    font-variant-numeric: tabular-nums;
}
.isis-top-list__name {
    display: flex;
    flex-direction: column;
    gap: 0.05rem;
    min-width: 0;
    overflow: hidden;
}
.isis-top-list__name > :first-child,
.isis-top-list__name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.isis-top-list__meta {
    font-size: 0.7rem;
    color: var(--isis-text-muted);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.isis-top-list__amount {
    font-variant-numeric: tabular-nums;
    font-weight: 600;
    color: var(--isis-text);
    white-space: nowrap;
}

/* Bande de filtres : search + chips */
.isis-filter-bar {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    padding: 0.5rem 0.85rem;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius);
    flex-wrap: wrap;
}
.isis-filter-bar__search {
    flex: 1;
    min-width: 220px;
    max-width: 360px;
    display: flex;
    align-items: center;
    gap: 0.5rem;
}
.isis-filter-bar__search input {
    flex: 1;
    height: 32px;
    border: 1px solid var(--isis-border);
    background: var(--isis-surface);
    border-radius: 8px;
    padding: 0 0.7rem;
    font-size: 0.85rem;
    color: var(--isis-text);
    outline: none;
}
.isis-filter-bar__search input:focus { border-color: var(--isis-accent); }
/* Libellé d'axe filtre (ex: "Statut", "Type") devant un groupe de chips —
   utilisé sur plusieurs pages liste (devis, commandes, articles, etc.). */
.isis-filter-bar__axis {
    font-size: 0.65rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--isis-text-muted);
    white-space: nowrap;
    align-self: center;
    margin-right: 0.15rem;
}
.isis-filter-bar__chips {
    display: flex;
    align-items: center;
    gap: 0.35rem;
    flex-wrap: wrap;
    margin-left: auto;
}
/* Page commandes : le cluster « Statut + pills » reste groupé et poussé à droite
   (design d'origine). On déplace le margin-left:auto des chips vers le GROUPE pour
   que le libellé « Statut » parte à droite AVEC ses pills (et non détaché à gauche). */
.isis-filter-bar--cmd .isis-filter-bar__group { margin-left: auto; }
.isis-filter-bar--cmd .isis-filter-bar__chips { margin-left: 0; }
/* Filtre sous forme de champ (combobox multi-sélection) dans la filter-bar. */
.isis-filter-bar__field {
    display: flex;
    align-items: center;
    gap: 0.4rem;
}
.isis-chip-group { display: flex; gap: 0.5rem; flex-wrap: wrap; }

.isis-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    height: 28px;
    padding: 0 0.7rem;
    border-radius: var(--isis-radius-pill);
    background: transparent;
    border: 1px solid var(--isis-border);
    color: var(--isis-text-muted);
    font-size: 0.75rem;
    cursor: pointer;
    transition: background-color 120ms, color 120ms, border-color 120ms;
}
.isis-chip:hover { background: var(--isis-surface-alt); color: var(--isis-text); }
.isis-chip:focus-visible {
    outline: 2px solid var(--isis-current-mod, var(--isis-accent));
    outline-offset: 2px;
}
/* `aria-disabled` et non l'attribut `disabled` (même patron que .isis-grid__filter-btn
   ci-dessous, ~L10424) : le chip reste dans l'ordre de tabulation, donc son `title` — la
   raison de l'inertie — reste atteignable au clavier et au lecteur d'écran. */
.isis-chip[aria-disabled="true"] {
    color: var(--isis-text-muted);
    cursor: not-allowed;
    opacity: 0.55;
}
.isis-chip[aria-disabled="true"]:hover { background: transparent; color: var(--isis-text-muted); }
.isis-chip__dot {
    width: 6px; height: 6px;
    border-radius: 50%;
    background: var(--isis-text-soft);
}
.isis-chip__dot.is-info    { background: #3b82f6; }
.isis-chip__dot.is-success { background: #10b981; }
.isis-chip__dot.is-warning { background: #f59e0b; }
.isis-chip__dot.is-danger  { background: #ef4444; }
/* Facettes tiers (migration 0096) — palette dérivée des facettes métier. */
.isis-chip__dot.is-client      { background: #10b981; }
.isis-chip__dot.is-prospect    { background: #3b82f6; }
.isis-chip__dot.is-fournisseur { background: #f59e0b; }
.isis-chip__dot.is-partenaire  { background: var(--isis-violet); }
/* Variantes par module — utilisées sur le sous-bandeau de filtres /ged/documents.
   Reprennent les couleurs d'identité module pour une lecture instantanée. */
.isis-chip__dot.is-module-gescom    { background: var(--isis-mod-gescom); }
.isis-chip__dot.is-module-gescompta { background: var(--isis-mod-gescompta); }
.isis-chip__dot.is-module-sirh      { background: var(--isis-mod-sirh); }
.isis-chip__dot.is-module-admin     { background: var(--isis-mod-admin); }
.isis-chip__dot.is-module-ged       { background: var(--isis-accent); }
.isis-chip__dot.is-module-gesproj   { background: var(--isis-mod-gesproj); }
.isis-chip.is-active {
    background: var(--isis-current-mod, var(--isis-accent));
    border-color: var(--isis-current-mod, var(--isis-accent));
    color: white;
}
.isis-chip.is-active .isis-chip__dot { background: white; }
.isis-chip__count {
    font-variant-numeric: tabular-nums;
    opacity: 0.85;
}

/* ── Pastille de nature de tâche (Facturable / Interne) ─────────────────
   Petit pill cliquable dans le titre de tâche. Facturable = neutre discret,
   Interne = plus estompé (texte/bordure soft) pour lecture immédiate. */
.isis-tache-nature {
    height: 20px;
    padding: 0 var(--isis-space-sm);
    font-size: var(--isis-fs-xs, 0.7rem);
    line-height: 1;
    letter-spacing: 0.01em;
    color: var(--isis-text);
    border-color: var(--isis-border);
}
.isis-tache-nature--interne {
    color: var(--isis-text-soft);
    border-color: var(--isis-border);
    background: var(--isis-surface-alt);
}
/* Hover : teinte module pour signaler l'interactivité (le chip Facturable
   au repos est volontairement discret). */
.isis-tache-nature:not(:disabled):hover {
    border-color: var(--isis-current-mod, var(--isis-accent));
    color: var(--isis-current-mod, var(--isis-accent));
    background: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 8%, var(--isis-surface));
}
/* Désactivé (commande clôturée/annulée) : assombrir plutôt qu'opacifier
   pour garder un contraste AA (WCAG 1.4.11). */
.isis-tache-nature:disabled {
    cursor: not-allowed;
    color: var(--isis-text-muted);
    background: var(--isis-surface-alt);
    border-color: var(--isis-border);
}
/* Badge « 0 anomalie » = signal positif vert (variante is-ok du badge). */
.isis-badge.is-ok {
    background: var(--isis-success-soft);
    color: var(--isis-success);
}

/* ── Pastille de nature de travail (Terrain / Bureau / Mixte / Trajet) ──
   Composant <WorkNatureBadge>. Fond piloté par les variables tenant
   --isis-nature-* (injectées par ThemeSync ; repli hex ci-dessous). Texte
   blanc sur les 4 natures sombres (WCAG 1.4.3) ; encre douce sur « Non défini ». */
.isis-nature-badge {
    display: inline-flex;
    align-items: center;
    height: 20px;
    padding: 0 var(--isis-space-sm, 8px);
    border-radius: 999px;
    font-size: var(--isis-fs-xs, 0.7rem);
    font-weight: 600;
    line-height: 1;
    letter-spacing: 0.01em;
    white-space: nowrap;
    /* Pas de `color` en base : chaque variante pose son encre (évite un blanc
       hérité illisible si un tenant surcharge une nature avec une teinte claire). */
}
.isis-nature-badge--terrain { background: var(--isis-nature-terrain, #c2410c); color: #ffffff; }
.isis-nature-badge--bureau  { background: var(--isis-nature-bureau,  #2b6a75); color: #ffffff; }
.isis-nature-badge--mixte   { background: var(--isis-nature-mixte,   #5d4a8c); color: #ffffff; }
/* Trajet : #3f7d58 → 4.9:1 sur blanc (AA texte normal). */
.isis-nature-badge--trajet  { background: var(--isis-nature-trajet,  #3f7d58); color: #ffffff; }
.isis-nature-badge--undefined {
    /* text-muted (slate-600) et non text-soft : ~6.1:1 sur surface-alt → AA (WCAG 1.4.3). */
    color: var(--isis-text-muted);
    background: var(--isis-surface-alt);
    border: 1px solid var(--isis-border);
}

/* Pastille de nature FISCALE (FiscalNatureBadge) : même gabarit que la nature de travail, qu'elle
   côtoie dans le catalogue — casse de phrase et hauteur alignées, seules les teintes Radzen
   (Shade.Lighter) restent. */
.rz-badge.isis-fiscal-badge {
    display: inline-flex;
    align-items: center;
    height: 20px;
    padding: 0 var(--isis-space-sm, 8px);
    border-radius: 999px;
    font-size: var(--isis-fs-xs, 0.7rem);
    font-weight: 600;
    line-height: 1;
    letter-spacing: 0.01em;
    text-transform: none;
    white-space: nowrap;
}

/* ── Panneau de couverture (anomalies budget vs charge) ─────────────────
   Carte claire sous la grille des tâches ; en-têtes de groupe textuels
   (pas de signalisation par couleur seule). */
.isis-coverage {
    margin-top: var(--isis-space-lg);
    padding: var(--isis-space-md);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius);
    background: var(--isis-surface);
    box-shadow: var(--isis-elevation-1);
}
.isis-coverage__head {
    display: flex;
    align-items: center;
    gap: var(--isis-space-sm);
    margin-bottom: var(--isis-space-sm);
}
.isis-coverage__title {
    font-weight: 600;
    font-size: var(--isis-fs-sm);
    color: var(--isis-text);
}
.isis-coverage__ok {
    font-size: var(--isis-fs-sm);
    color: var(--isis-text-muted);
}
.isis-coverage__group {
    margin-top: var(--isis-space-sm);
    padding-top: var(--isis-space-sm);
    border-top: 1px solid var(--isis-border);
}
.isis-coverage__group:first-of-type {
    border-top: none;
    padding-top: 0;
}
.isis-coverage__group-head {
    font-size: var(--isis-fs-sm);
    font-weight: 600;
    color: var(--isis-warning);
    margin: 0 0 var(--isis-space-xs);
}
.isis-coverage__hint {
    margin: var(--isis-space-sm) 0 0;
    font-size: var(--isis-fs-sm);
    color: var(--isis-text-muted);
}
.isis-coverage__group--info .isis-coverage__group-head {
    color: var(--isis-text-soft);
    font-weight: 500;
}
.isis-coverage__group ul {
    margin: 0;
    padding-left: var(--isis-space-lg);
    list-style: disc;
}
.isis-coverage__group li {
    font-size: var(--isis-fs-sm);
    color: var(--isis-text);
    line-height: 1.5;
}

/* Master-detail : grille à gauche + panneau d'aperçu à droite */
.isis-master-detail {
    display: grid;
    /* Sidepanel : 30 % de la largeur de page, plancher 300px, plafond 400px
       (refonte 2026-06-04, remplace 28vw/520px jugé trop large). Le sidepanel
       intelligent reste lisible (micro-KPIs auto-fit s'adaptent de 3→2→1 colonnes). */
    grid-template-columns: minmax(0, 1fr) clamp(300px, 30%, 400px);
    gap: 0.75rem;
    align-items: stretch;
    /* Prend toute la hauteur restante dans .isis-rich-page (flex parent).
       min-height: 0 indispensable pour que les enfants puissent eux-mêmes
       être height-constrained et activer leur overflow interne. */
    flex: 1 1 auto;
    min-height: 0;
}
/* Variante 3 colonnes : volet entreprises (scope) | arbre | sidepanel détail.
   Onglet « Structures internes » de la page Organisation. Sidepanel idem fluide
   mais 26vw (compense la colonne rail 230px à gauche qui mange déjà de la largeur). */
.isis-master-detail--rail {
    grid-template-columns: 230px minmax(0, 1fr) clamp(300px, 30%, 400px);
}
/* Variante pleine largeur : master seul, sans sidepanel (ex. Corbeille GED —
   les actions inline suffisent). Remplace les styles inline grid-template-columns. */
.isis-master-detail--full {
    grid-template-columns: 1fr;
}
/* Variante « liste à gauche » : rail de liste étroit (sélection) + détail large à droite.
   Inverse du défaut (détail en sidepanel). Utilisé par le hub Responsabilités. */
.isis-master-detail--list-left {
    grid-template-columns: clamp(240px, 26%, 340px) minmax(0, 1fr);
}

/* Dans la variante liste-à-gauche, le détail n'est pas un sidepanel sticky : il
   remplit sa colonne et scrolle en interne (le titre éditable a besoin d'overflow visible). */
.isis-master-detail--list-left .isis-master-detail__detail {
    position: static;
    min-height: 0;
    overflow: auto;
}

/* ── Hub ancre-liste (rail gauche du hub Responsabilités) ──────────────────── */
.isis-hub-anchor-list {
    display: flex;
    flex-direction: column;
    gap: 0;
    overflow-y: auto;
    flex: 1 1 0;
    min-height: 0;
    padding: 0 0 0.5rem 0;
}

.isis-hub-anchor-list__group-label {
    font-size: var(--isis-fs-xs);
    font-weight: 600;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--isis-text-soft);
    padding: 0.75rem 0.75rem 0.3rem;
}

.isis-hub-anchor-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    width: 100%;
    padding: 0.5rem 0.75rem;
    border: none;
    border-radius: var(--isis-radius-sm);
    background: transparent;
    cursor: pointer;
    text-align: left;
    font-size: var(--isis-fs-sm);
    color: var(--isis-text);
    transition: background 120ms ease;
}

.isis-hub-anchor-item:hover {
    background: color-mix(in srgb, var(--isis-mod-sirh) 6%, var(--isis-surface));
}

.isis-hub-anchor-item:focus-visible {
    outline: 2px solid color-mix(in srgb, var(--isis-mod-sirh) 60%, transparent);
    outline-offset: 1px;
}

.isis-hub-anchor-item.is-active {
    background: color-mix(in srgb, var(--isis-mod-sirh) 12%, var(--isis-surface));
    font-weight: 500;
}

.isis-hub-anchor-item__label {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* ── Arbre du rail (onglet Organisation du hub de gouvernance) ───────────────
   Classe portée par le <ul> racine, jamais un sélecteur descendant depuis
   .isis-hub-anchor-list : ce conteneur sert AUSSI la liste des collaborateurs de
   l'onglet Personne, qu'une règle descendante attraperait en silence. */
.isis-hub-anchor-tree,
.isis-hub-anchor-tree ul {
    list-style: none;
    margin: 0;
    padding: 0;
}

.isis-hub-anchor-tree ul {
    /* Filet de branche : l'indentation seule ne relie pas visuellement un enfant à son
       parent sur un rail étroit. Profondeur maximale observée en dev : 6 niveaux, soit
       ~72px d'indentation cumulée sur un rail de ~400px. */
    padding-left: 0.75rem;
    margin-left: 0.4rem;
    border-left: 1px solid var(--isis-border);
}

.isis-hub-anchor-item__ic {
    flex: 0 0 auto;
    font-size: var(--isis-fs-sm);
    opacity: 0.55;
}

/* Ancêtre conservé pour le contexte : présent, lisible, mais pas cliquable. */
.isis-hub-anchor-item.is-context {
    color: var(--isis-text-soft);
    cursor: default;
}

.isis-hub-anchor-item.is-context:hover {
    background: transparent;
}

/* ============================================================================
   .isis-resp-hub — hub de gouvernance des responsabilités
   (/sirh/organisation/responsabilites), chantier harmonisation 2026-09-03.
   ----------------------------------------------------------------------------
   Sorti du <style> inline de la page (≈870 lignes) qui portait un design system
   parallèle. Ce qui était une COPIE du thème est resté au thème (.isis-tabs /
   .isis-tab / .isis-tab__counter, .isis-master-detail(--list-left) / __master /
   __detail, .isis-hub-anchor-*, .is-hidden, .visually-hidden) ; seules les règles
   sans équivalent ailleurs sont ici, scopées sous la classe de page — aucune de
   ces classes n'existait dans ce fichier avant (vérifié une à une, cf. G9 : deux
   règles homonymes écrites à deux moments se superposent en silence).

   Le token --isis-mod-sirh-ink (#065f46) que la page se créait au périmètre de
   .isis-rich-page a disparu : un token de thème ne se crée pas dans une page
   (DESIGN.md §2) et, valeur fixe, il tombait à ~2:1 en thème sombre. Les chips
   teintés sirh prennent --isis-text, décision déjà prise par le thème lui-même
   pour .isis-org-rail__count (« --isis-mod-sirh sur --isis-mod-sirh-soft ne donne
   que 2.4:1 »).
   ============================================================================ */

/* ── Colonne de détail : rythme vertical et coquille sans fond ───────────────
   G5 — un style pensé pour un conteneur ne survit pas au déménagement. Le
   .cockpit-detail d'origine était `flex column; gap:14px` et TRANSPARENT ; son
   remplaçant .isis-master-detail__detail est un bloc, et une carte (fond, bordure,
   ombre, padding). Sans ces deux corrections : (1) les enfants n'ayant aucune marge
   propre, l'espacement tombait de 14px à 0 ; (2) des objets à fond --isis-surface se
   retrouvaient dans une carte à fond --isis-surface.
   La coquille redevient une zone de mise en page — l'objet, ici, est la grille des
   désignations (cartes jusqu'au 2026-09-22), exactement comme .isis-master-detail__master
   pose ses lignes sur la .isis-tabs-card ailleurs dans le produit. Le rail de gauche, lui, GARDE sa carte : c'est un panneau. */
.isis-resp-hub .isis-master-detail__detail {
    display: flex;
    flex-direction: column;
    gap: 0.85rem;
    background: transparent;
    border: none;
    box-shadow: none;
    padding: 0;
}

/* ── En-tête du nœud sélectionné ─────────────────────────────────────────── */
.isis-resp-hub .cockpit-node-head {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
}
.isis-resp-hub .cockpit-node-head h2 {
    font-size: 20px;
    font-weight: 600;
    margin: 0;
}

/* ── Pastilles d'en-tête (axe, comptes) : casse normale ─────────────────────
   Radzen passe tout badge en capitales (--rz-badge-text-transform) ; DESIGN.md les
   réserve aux statuts métier. « Non pourvu », dans la grille, en reste un. */
.isis-resp-hub .cockpit-node-head .rz-badge,
.isis-resp-hub .pers-head .rz-badge {
    text-transform: none;
}

/* ── Grille des désignations (onglets Organisation et Personne) ──────────────
   Refonte du 2026-09-22 : une ligne .isis-grid par désignation remplace les cartes
   de gouvernance, dont chaque fait était une pastille sans libellé. Les en-têtes de
   colonne nomment les faits une fois ; les cellules passent en texte multi-ligne
   (périmètre et exceptions ne tiennent pas sur une ligne tronquée). La grille prend
   sa hauteur de contenu : c'est la colonne de détail qui défile, pas elle.
   Largeurs minimales calibrées pour tenir SANS défilement horizontal à 1280 px de
   fenêtre (676 px de détail mesurés) ; en deçà, .isis-grid--sticky-actions garde la
   colonne Actions — donc le bouton « Désigner » — à l'écran. */
.isis-resp-hub .isis-grid--resp,
.isis-resp-hub .isis-grid--resp-pers {
    flex: 0 0 auto;
}
.isis-resp-hub .isis-grid--resp { --isis-grid-min-width: 674px; }
.isis-resp-hub .isis-grid--resp-pers { --isis-grid-min-width: 600px; }
.isis-resp-hub .isis-grid--resp .isis-grid__head,
.isis-resp-hub .isis-grid--resp .isis-grid__row {
    grid-template-columns: minmax(110px, 1.3fr) minmax(130px, 1.1fr) minmax(120px, 1.3fr) minmax(84px, .8fr) minmax(110px, .8fr) 92px;
    min-width: var(--isis-grid-min-width);
}
.isis-resp-hub .isis-grid--resp-pers .isis-grid__head,
.isis-resp-hub .isis-grid--resp-pers .isis-grid__row {
    grid-template-columns: minmax(110px, 1.1fr) minmax(120px, 1.3fr) minmax(110px, 1.2fr) minmax(96px, .9fr) minmax(112px, .8fr);
    min-width: var(--isis-grid-min-width);
}
/* Lignes non cliquables : les gestes sont les boutons de la colonne Actions. */
.isis-resp-hub .isis-grid--resp .isis-grid__row,
.isis-resp-hub .isis-grid--resp-pers .isis-grid__row {
    cursor: default;
}
.isis-resp-hub .isis-grid--resp .isis-grid__row > div:not(.isis-grid__actions),
.isis-resp-hub .isis-grid--resp-pers .isis-grid__row > div {
    white-space: normal;
    overflow-wrap: anywhere;
}

/* Ligne de groupe (Généraliste / Thématiques) : patron commun .isis-grid__group-row
   (.isis-grid__group, bascule repliable, ne convient pas à un intertitre). Pas
   collante ici : l'en-tête de cette grille ne l'est pas, elle flotterait sous rien.
   Le h3 hérite de la typographie de la ligne. */
.isis-resp-hub .resp-grid__group {
    position: static;
    flex-shrink: 0;
    min-width: var(--isis-grid-min-width);
    padding-left: .85rem;
}
.isis-resp-hub .resp-grid__group > div {
    display: flex;
    align-items: center;
    gap: .4rem;
}
.isis-resp-hub .resp-grid__group h3 {
    font: inherit;
    letter-spacing: inherit;
    color: inherit;
    margin: 0;
}

/* Contenu des cellules. Sous-lignes en --isis-text-muted, pas --isis-text-soft :
   ce dernier passe sous 4,5:1 sur le fond de survol des lignes. */
.isis-resp-hub .resp-grid__role { font-weight: 500; }
.isis-resp-hub .resp-grid__sub {
    display: block;
    font-size: 12px;
    color: var(--isis-text-muted);
}
.isis-resp-hub .resp-grid__none { color: var(--isis-text-muted); }
.isis-resp-hub .resp-grid__who {
    display: flex;
    align-items: center;
    gap: 8px;
}
.isis-resp-hub .resp-grid__avatar {
    width: 24px;
    height: 24px;
    flex: 0 0 auto;
    border-radius: 50%;
    display: grid;
    place-items: center;
    font-size: .7rem;
    font-weight: 600;
    background: color-mix(in oklch, var(--isis-accent) 14%, transparent);
    /* --isis-text et non --isis-accent-strong : sur un fond qui n'est que 14 % d'accent, l'encre
       ne doit pas dépendre de la teinte de MARQUE du tenant, qui va du presque-noir au jaune.
       (Le motif d'origine — accent-strong assombri quel que soit le thème, 1,06:1 en sombre — est
       clos depuis que BrandSync émet un bloc sombre ; ce choix-ci reste le bon.) */
    color: var(--isis-text);
}

/* ── Modale « Modifier le périmètre » (ResponsabilitePerimetreDialog) ───── */
/* Rendue par RadzenDialog HORS de .isis-resp-hub : elle porte son propre préfixe. */
.isis-resp-scope-dialog__levels {
    display: flex;
    flex-direction: column;
    gap: 6px;
}
.isis-resp-scope-dialog .gov-exc-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 5px;
}
.isis-resp-scope-dialog .gov-exc-item {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 5px 8px;
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-sm);
}
.isis-resp-scope-dialog .gov-exc-item__label {
    flex: 1;
    min-width: 0;
    font-size: 14px;
    color: var(--isis-text);
}
/* Chrome 28px comme .isis-grid__action-btn, cible 44×44 par pseudo-élément (DESIGN.md
   §5) : le pas vertical d'une ligne d'exception (28 + 2×5 + 2 + 5 = 45px) l'empêche de
   déborder sur le bouton voisin. */
.isis-resp-scope-dialog .gov-exc-remove-btn {
    appearance: none;
    background: none;
    border: none;
    position: relative;
    flex-shrink: 0;
    width: 28px;
    height: 28px;
    padding: 0;
    border-radius: var(--isis-radius-sm);
    cursor: pointer;
    color: var(--isis-text-muted);
    display: grid;
    place-items: center;
    transition: color 100ms, background 100ms;
}
.isis-resp-scope-dialog .gov-exc-remove-btn:hover {
    color: var(--isis-danger);
    background: var(--isis-danger-soft);
}
.isis-resp-scope-dialog .gov-exc-remove-btn:focus-visible {
    outline: 2px solid var(--isis-danger);
    outline-offset: 2px;
}
.isis-resp-scope-dialog .gov-exc-remove-btn::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: 44px;
    height: 44px;
    transform: translate(-50%, -50%);
}
.isis-resp-scope-dialog .gov-exc-remove-btn .rz-icon { font-size: 14px; }
/* Contrôle INERTE : aria-disabled, jamais l'attribut HTML disabled — le bouton reste
   atteignable au clavier ; le geste est neutralisé dans le handler. */
.isis-resp-scope-dialog .gov-exc-remove-btn[aria-disabled="true"] {
    cursor: not-allowed;
    opacity: .65;
}
.isis-resp-scope-dialog__add {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
}
/* Sous 200px la liste passe à la ligne plutôt que de tronquer son libellé sur sa flèche. */
.isis-resp-scope-dialog__add .rz-dropdown {
    flex: 1 1 200px;
    min-width: 0;
}
.isis-resp-scope-dialog__preview {
    margin: 0;
    padding: 10px 12px;
    background: var(--isis-surface-alt);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-sm);
    font-size: 12px;
    line-height: 1.5;
    color: var(--isis-text);
}
.isis-resp-scope-dialog__preview strong { font-weight: 600; }

/* ── Onglet Personne — volet droit ───────────────────────────────────────── */
.isis-resp-hub .pers-head {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
}
.isis-resp-hub .pers-head__avatar {
    width: 40px;
    height: 40px;
    flex: 0 0 auto;
    border-radius: 50%;
    display: grid;
    place-items: center;
    font-size: 14px;
    font-weight: 600;
    background: color-mix(in oklch, var(--isis-accent) 14%, transparent);
    /* cf. .resp-grid__avatar : l'encre d'un fond à 14 % d'accent ne suit pas la teinte de marque. */
    color: var(--isis-text);
}
.isis-resp-hub .pers-head h2 {
    font-size: 20px;
    font-weight: 600;
    margin: 0;
}
.isis-resp-hub .pers-audit-caption {
    font-size: 12px;
    color: var(--isis-text-muted);
    margin: -6px 0 0;
    font-style: italic;
}
/* Portée du panneau gauche (espace de travail courant), onglets Personne et Organisation.
   Ligne de contexte, pas un avis de page : elle qualifie la liste qu'elle précède, à
   l'intérieur de l'onglet — DESIGN.md §10 ne vise que les bandeaux sous le fil d'Ariane. */
.isis-resp-hub .resp-scope-note {
    font-size: 12px;
    color: var(--isis-text-muted);
    margin: 0.5rem 0 0;
    max-width: 78ch;
}

/* ============================================================================
   .isis-master-detail--no-side — Mode élargi avec sidepanel drawer rétractable
   ----------------------------------------------------------------------------
   Refonte 2026-05-29 : la grille datagrid prend 100% de la largeur, le sidepanel
   sort du flux et devient un drawer flottant accessible via une languette
   verticale sur le bord droit du viewport. Pattern drawer overlay similaire à
   Material Design / Slack sidebars. Persistance localStorage par page (clé
   `isis.<page>.list-expanded`).

   2 états indépendants :
     1. `--no-side` posé sur le wrapper = mode élargi actif (toolbar toggle)
     2. `.is-drawer-open` posé sur le wrapper = drawer ouvert (languette toggle)
   ============================================================================ */
.isis-master-detail--no-side {
    /* Grille pleine largeur — le sidepanel sort du flux via position:fixed. */
    grid-template-columns: minmax(0, 1fr);
}

/* Sidepanel devient drawer flottant collé à droite, slide-out par défaut. */
.isis-master-detail--no-side .isis-master-detail__detail {
    position: fixed;
    top: var(--isis-header-h, 56px);
    right: 0;
    bottom: 0;
    width: clamp(360px, 28vw, 520px);
    z-index: 940;                              /* < focus-zone (950), < dialogs Radzen (1010+) */
    background: var(--isis-surface);
    border-left: 1px solid var(--isis-border);
    box-shadow: -10px 0 30px rgba(0, 0, 0, 0.12);
    overflow-y: auto;
    transform: translateX(100%);               /* slide-out par défaut */
    transition: transform 200ms cubic-bezier(0.4, 0, 0.2, 1);
    visibility: hidden;                        /* hors tab order + non lu par AT quand fermé */
}
.isis-master-detail--no-side.is-drawer-open .isis-master-detail__detail {
    transform: translateX(0);                  /* slide-in */
    visibility: visible;
}

/* Languette verticale sticky bord droit — visible uniquement en mode élargi.
   Toujours visible (drawer ouvert ou fermé) — c'est la commande permanente
   d'ouverture/fermeture du drawer. */
.isis-master-detail__drawer-tab {
    display: none;
}
.isis-master-detail--no-side .isis-master-detail__drawer-tab {
    display: flex;
    align-items: center;
    justify-content: center;
    position: fixed;
    top: 50%;
    right: 0;
    transform: translateY(-50%);
    width: 28px;
    height: 80px;
    z-index: 942;                              /* au-dessus du drawer (940) et backdrop (939) */
    background: var(--isis-surface);
    color: var(--isis-text-muted);
    border: 1px solid var(--isis-border);
    border-right: none;
    border-radius: 6px 0 0 6px;
    cursor: pointer;
    box-shadow: -4px 2px 12px rgba(0, 0, 0, 0.08);
    transition: right 200ms cubic-bezier(0.4, 0, 0.2, 1),
                background-color 120ms,
                color 120ms;
    padding: 0;
}
.isis-master-detail__drawer-tab:hover,
.isis-master-detail__drawer-tab:focus-visible {
    background: var(--isis-surface-alt);
    color: var(--isis-current-mod, var(--isis-accent));
    outline: none;
}
/* Quand drawer ouvert : la languette se déplace avec, collée au bord gauche du drawer. */
.isis-master-detail--no-side.is-drawer-open .isis-master-detail__drawer-tab {
    right: clamp(360px, 28vw, 520px);
}

/* Backdrop semi-transparent — visible seulement quand drawer ouvert.
   Click backdrop = ferme le drawer (cf. Q4 option C : 3 mécanismes de fermeture). */
.isis-master-detail__drawer-backdrop {
    display: none;
}
.isis-master-detail--no-side.is-drawer-open .isis-master-detail__drawer-backdrop {
    display: block;
    position: fixed;
    top: var(--isis-header-h, 56px);
    right: 0;
    bottom: 0;
    /* `left` ne couvre PAS le subnav : cohérent avec le focus zone détail. */
    left: var(--isis-subnav-w, 280px);
    background: rgba(0, 0, 0, 0.18);
    backdrop-filter: blur(1px);
    z-index: 939;                              /* < drawer (940) */
    animation: isis-drawer-backdrop-in 200ms ease-out;
    cursor: pointer;
}
.isis-shell.is-subnav-collapsed .isis-master-detail--no-side.is-drawer-open .isis-master-detail__drawer-backdrop {
    left: var(--isis-subnav-w-collapsed, 64px);
}
@keyframes isis-drawer-backdrop-in {
    from { opacity: 0; }
    to { opacity: 1; }
}

/* ── Volet « Entreprises » — sélecteur de scope de l'arbre des structures ── */
.isis-org-rail {
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius);
    display: flex;
    flex-direction: column;
    min-height: 0;
    overflow: hidden;
}
.isis-org-rail__head {
    font-size: 0.65rem;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--isis-text-soft);
    padding: 0.7rem 0.85rem 0.5rem;
    border-bottom: 1px solid var(--isis-border-soft);
    flex-shrink: 0;
}
.isis-org-rail__list {
    overflow-y: auto;
    padding: 0.35rem;
    display: flex;
    flex-direction: column;
    gap: 0.1rem;
    min-height: 0;
}
.isis-org-rail__item {
    box-sizing: border-box;   /* width:100% + filet 1px : sans ça l'item déborde du rail */
    display: flex;
    align-items: center;
    gap: 0.5rem;
    width: 100%;
    padding: 0.42rem 0.5rem;
    border: 1px solid transparent;
    background: transparent;
    border-radius: 6px;
    cursor: pointer;
    text-align: left;
    color: var(--isis-text);
    font-size: 0.82rem;
    transition: background-color 120ms ease;
}
.isis-org-rail__item:hover { background: var(--isis-surface-alt); }
/* Actif = fond teinté + filet périmétrique (ex-liseré gauche 2px, converti le
   2026-07-18). Le radius reste plein : l'ancien « 0 6px 6px 0 » n'existait que
   pour accoler la barre verticale. */
.isis-org-rail__item.is-active {
    background: var(--isis-mod-sirh-soft);
    border-color: color-mix(in srgb, var(--isis-mod-sirh) 32%, transparent);
    font-weight: 600;
}
.isis-org-rail__item:focus-visible {
    outline: 2px solid var(--isis-accent);
    outline-offset: -2px;
}
.isis-org-rail__item--all { margin-bottom: 0.25rem; }
.isis-org-rail__dot {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--isis-mod-sirh);
    flex-shrink: 0;
}
.isis-org-rail__name {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.isis-org-rail__count {
    font-size: 0.7rem;
    color: var(--isis-text-soft);
    font-variant-numeric: tabular-nums;
    flex-shrink: 0;
}
/* Texte en --isis-text : --isis-mod-sirh sur --isis-mod-sirh-soft ne donne que
   2.4:1 (échec WCAG AA texte). Le fond vert pâle de l'item actif porte l'identité. */
.isis-org-rail__item.is-active .isis-org-rail__count { color: var(--isis-text); }
.isis-master-detail__master {
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius);
    /* Mise en conformité 2026-05-26 avec CLAUDE.md §4 « élévation tokenisée 3 tiers
       — elevation-1 cartes/sidepanels ». Le bandeau KPI hero portait déjà l'ombre,
       les 2 cards master + detail l'avaient oubliée → la zone principale était plate. */
    box-shadow: var(--isis-elevation-1);
    overflow: hidden;
    /* Flex column pour permettre à .isis-grid interne de prendre la hauteur dispo. */
    display: flex;
    flex-direction: column;
    min-height: 0;
}
.isis-master-detail__detail {
    position: sticky;
    top: 0.5rem;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius);
    box-shadow: var(--isis-elevation-1);
    padding: 1rem;
    min-height: 320px;
}
/* Sidepanel structuré NON-switchable (ex. liste commandes) : le panneau doit
   borner sa hauteur pour que .isis-detail-split__middle/__bottom scrollent en
   interne — sinon `height: 100%` du split ne se résout contre aucune hauteur
   définie, le panneau grandit et c'est la page entière qui défile (donc pas de
   scroll-shadow). Même contexte flex/overflow que la variante `--switchable`,
   mais scopé via `:has(> .isis-detail-split)` : (1) ne touche pas les 37 panneaux
   à contenu libre, (2) ne matche pas les pages switchable (où le split est imbriqué
   dans `.isis-side-switcher__body`, pas enfant direct), (3) ne s'active qu'avec une
   sélection (l'empty-state `.isis-detail-empty` garde le plancher 320px). */
.isis-master-detail__detail:has(> .isis-detail-split) {
    display: flex;
    flex-direction: column;
    min-height: 0;
    overflow: hidden;
}
/* Choix 2026-06-24 « tout scroller, comme le menu » : sur ces panneaux le
   .isis-detail-split scrolle d'UN SEUL bloc (pas d'en-tête figé) — sinon le __top
   surchargé (montant + facturation + avancement + marge) dépassait le panneau et
   se faisait tronquer sur petit écran. On neutralise donc les scrolls internes des
   sous-sections pour n'avoir qu'une seule zone scrollable, qui porte les ombres
   haut/bas (cf. règle scroll-shadow centralisée). Ne concerne PAS les pages
   switchable (split imbriqué dans .isis-side-switcher__body, pas enfant direct). */
.isis-master-detail__detail:has(> .isis-detail-split) > .isis-detail-split {
    flex: 1 1 auto;
    height: auto;
    min-height: 0;
    overflow-y: auto;
}
.isis-master-detail__detail:has(> .isis-detail-split) > .isis-detail-split > .isis-detail-split__middle,
.isis-master-detail__detail:has(> .isis-detail-split) > .isis-detail-split > .isis-detail-split__bottom {
    flex: 0 0 auto;
    max-height: none;
    min-height: 0;
    overflow: visible;
}
/* Panneau à barre d'onglets ad-hoc (.isis-side-tabs, unique à /gesmat/equipements) :
   le contenu du panneau est commuté par une barre d'onglets qui doit rester visible
   pendant que le contenu défile. On borne donc le panneau lui-même, on fige la barre
   et on laisse la zone active remplir ce qui reste et porter le scroll.

   Ce que ce bloc de trois règles apporte VRAIMENT, c'est la zone active de l'onglet
   « Recherche avancée » — d'où le troisième sélecteur, `> .isis-side-search`, qui ne
   vise QUE ce formulaire. Sur l'onglet « Détail », la règle `:has(> .isis-detail-split)`
   ci-dessus suffit déjà (un `@if` Blazor n'émet aucun nœud, la coquille est bien enfant
   direct du panneau) et pose exactement les mêmes déclarations : lui adjoindre ici un
   `> .isis-detail-split` serait inerte, ce qui a été constaté en tâche 15 puis vérifié
   et nettoyé en tâche 16 — ne pas le réintroduire. Sur l'onglet « Recherche avancée »
   en revanche il n'y a AUCUN `.isis-detail-split` dans le DOM, donc plus rien ne borne
   le panneau ni ne donne le scroll au formulaire : il serait tronqué net sur une
   fenêtre basse.

   Scopé par `:has(> .isis-side-tabs)` : aucun autre écran du dépôt ne porte cette
   barre. Le premier sélecteur ci-dessous (celui qui borne l'aside) bat aussi le
   `overflow-y: auto` du mode drawer `--no-side` (même spécificité, déclarée plus bas)
   — voulu : le panneau flottant se borne et c'est la zone active qui défile, dans les
   deux onglets. */
.isis-master-detail__detail:has(> .isis-side-tabs) {
    display: flex;
    flex-direction: column;
    min-height: 0;
    overflow: hidden;
}
.isis-master-detail__detail:has(> .isis-side-tabs) > .isis-side-tabs {
    flex: 0 0 auto;
}
.isis-master-detail__detail:has(> .isis-side-tabs) > .isis-side-search {
    flex: 1 1 auto;
    height: auto;
    min-height: 0;
    overflow-y: auto;
}
.isis-detail-empty {
    height: 100%;
    min-height: 280px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.75rem;
    color: var(--isis-text-soft);
    text-align: center;
    padding: 1rem;
}
.isis-detail-empty .rzi { font-size: 32px; opacity: 0.35; }
.isis-detail-empty p { margin: 0; font-size: 0.85rem; line-height: 1.4; }
.isis-detail-empty strong { color: var(--isis-text-muted); }

/* Variante --rich : empty state enrichi (raccourcis clavier + mini-stats globaux).
   Chantier sidepanel intelligent 2026-05-26 — répond au #9 du brief UX. */
.isis-detail-empty--rich .isis-detail-empty__hints {
    list-style: none;
    padding: 0;
    margin: 0.5rem 0 0;
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
    font-size: 0.78rem;
}
.isis-detail-empty--rich .isis-detail-empty__hints li {
    color: var(--isis-text-soft);
}
.isis-detail-empty--rich .isis-detail-empty__hints kbd {
    display: inline-block;
    padding: 1px 5px;
    margin: 0 1px;
    font-family: inherit;
    font-size: 0.72rem;
    line-height: 1.2;
    border: 1px solid var(--isis-border);
    border-radius: 3px;
    background: var(--isis-bg-soft, var(--isis-surface-alt));
    color: var(--isis-text);
}
.isis-detail-empty--rich .isis-detail-empty__stats {
    margin-top: 0.85rem;
    padding-top: 0.7rem;
    border-top: 1px solid var(--isis-border);
    font-size: 0.78rem;
    color: var(--isis-text-muted);
    width: 100%;
    max-width: 280px;
}
.isis-detail-empty--rich .isis-detail-empty__stats strong {
    color: var(--isis-text);
    font-weight: 600;
}

/* Sur tablette : masque le panel détail au-dessous de 1200px.
   `:where(:not(.isis-side-panel))` est PUREMENT DOCUMENTAIRE, et le `:where()` n'est pas
   décoratif — il contribue 0 à la spécificité, là où un `:not()` nu ajoute celle de son
   argument. Sans lui, cette règle passerait de (0,1,0) à (0,2,0), et battrait les trois
   règles (0,2,0) déclarées PLUS HAUT qui rendent ce panneau visible. Inventaire complet des
   cinq règles concurrentes, au 2026-09-04 :
     · `.isis-resp-hub .isis-master-detail__detail`            (9748,  (0,2,0), PLUS HAUT)
     · `.isis-master-detail__detail:has(> .isis-detail-split)` (10573, (0,2,0), PLUS HAUT)
     · `.isis-master-detail__detail:has(> .isis-side-tabs)`    (10620, (0,2,0), PLUS HAUT)
     · `.isis-side-panel`                                      (15932, (0,1,0), plus bas)
     · `.isis-master-detail__detail.isis-side--switchable`     (17370, (0,2,0), plus bas)
   Les deux dernières gagnent de toute façon par la position ; ce sont les TROIS PREMIÈRES
   qu'un `:not()` casse. Et elles ne s'activent QU'UNE FOIS UNE LIGNE SÉLECTIONNÉE (ni
   `.isis-detail-split` ni `.isis-side-tabs` n'existent dans l'état vide) : un correctif
   mesuré sans sélection ne voit rien, et casse 24 pages sur 12 modules dès la sélection.
   Ne PAS remplacer ce `:where()` par une énumération d'exclusions : cet inventaire a déjà
   grandi de 1 à 5 en une relecture. Mesuré au navigateur le 2026-09-04, parité exacte avec
   `origin/main` sur 12 cas (4 routes × sans/avec sélection × mode élargi).
   Ce qu'il faut retenir : sous 1200px, ce `display: none` n'atteint QUE les poses nues de la
   classe SANS panneau structuré — les autres passent simplement sous la grille (la grille
   repasse à 1 colonne, le panneau devient la 2e RANGÉE). */
@media (max-width: 1200px) {
    .isis-master-detail,
    .isis-master-detail--rail { grid-template-columns: 1fr; }
    .isis-master-detail__detail:where(:not(.isis-side-panel)) { display: none; }
    /* NE PAS masquer ici la languette du tiroir (`__drawer-tab`) ni son fond. Elle EST
       orpheline quand le panneau est réellement `display: none` — commande visible,
       focusable, sans effet — mais « panneau nu » ne vaut PAS « panneau masqué » : les
       cinq règles ci-dessus en rendent beaucoup, et masquer la languette y supprimerait
       une commande qui marche. La condition juste — « la languette disparaît quand le
       panneau est réellement masqué » — ne s'exprime pas durablement en `:not()`/`:has()` :
       il faut une classe posée par `IsisMasterDetailShell`. Arbitrage de design system,
       laissé ouvert le 2026-09-04. */
}

/* Dot de statut dans la 1re colonne de grille */
.isis-row-dot {
    display: inline-block;
    width: 8px; height: 8px;
    border-radius: 50%;
    margin-left: 0.25rem;
    box-shadow: 0 0 0 3px rgba(255,255,255,0.85);
}

/* Classes utilitaires fond accent par module (pour les icônes de header) */
.mod-gescom-soft    { background: var(--isis-mod-gescom-soft); }
.mod-gescompta-soft { background: var(--isis-mod-gescompta-soft); }
.mod-sirh-soft      { background: var(--isis-mod-sirh-soft); }
.mod-admin-soft     { background: var(--isis-mod-admin-soft); }
.mod-gesproj-soft   { background: var(--isis-mod-gesproj-soft); }
.mod-gesmaff-soft   { background: var(--isis-mod-gesmaff-soft); }
.mod-gesst-soft     { background: var(--isis-mod-gesst-soft); }
.mod-gesmat-soft    { background: var(--isis-mod-gesmat-soft); }
.mod-gespla-soft    { background: var(--isis-mod-gespla-soft); }
.mod-gesqhse-soft   { background: var(--isis-mod-gesqhse-soft); }
.mod-gesinfo-soft   { background: var(--isis-mod-gesinfo-soft); }
.mod-gespark-soft   { background: var(--isis-mod-gespark-soft); }
.mod-gesmob-soft    { background: var(--isis-mod-gesmob-soft); }
.mod-gesfac-soft    { background: var(--isis-mod-gesfac-soft); }

/* ============================================================================
   Console plateforme (/master/*)
   ============================================================================ */
/* Le shell de la console plateforme (.isis-master-shell / rail / contenu) vit
   désormais dans css/master-shell.css (rail latéral sombre). */

.isis-master-page { max-width: none; margin: 0; display: flex; flex-direction: column; gap: 1rem; }

/* En-tête de section repliable (boutonné, accessible) */
.isis-collapse-toggle {
    display: flex;
    align-items: center;
    gap: 0.35rem;
    width: 100%;
    padding: 0;
    background: none;
    border: none;
    cursor: pointer;
    text-align: left;
    color: var(--isis-text-muted);
}
.isis-collapse-toggle:hover { color: var(--isis-text); }
.isis-collapse-toggle:focus-visible {
    outline: 2px solid var(--isis-accent);
    outline-offset: 2px;
    border-radius: 4px;
}
.isis-master-page__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
}
/* Colonne de gauche de l'en-tête console : fil d'Ariane (qui porte le h1) puis sous-titre.
   min-width: 0 est porteur — sans lui la piste flex refuse de rétrécir, et la miette
   courante, qui s'élide, pousserait les actions hors de l'écran au lieu de se tronquer. */
.isis-master-page__heading {
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
}
/* Cette classe était employée par le markup depuis l'origine SANS aucune règle : les actions
   ne tenaient que par le space-between du parent, et deux boutons voisins se touchaient. */
.isis-master-page__actions {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex: 0 0 auto;
}
/* .isis-master-page__title a été retiré le 2026-09-06 : le titre des pages de la console vit
   désormais dans le fil d'Ariane (.isis-breadcrumb__current--heading), dont --isis-fs-xl vaut
   1.4rem — la même taille. Plus aucun markup ne portait la classe. */
.isis-master-page__subtitle {
    font-size: 0.85rem;
    color: var(--isis-text-muted);
    margin: 0;
}
.isis-master-page__primary-btn {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.5rem 1rem;
    background-color: var(--isis-accent);
    color: var(--isis-on-accent);
    border-radius: 6px;
    text-decoration: none;
    font-size: 0.85rem;
    font-weight: 500;
    transition: opacity 120ms;
}
/* `--isis-on-accent` et non `white` (bloquant de revue, 2026-09-16) : le `white` en dur ne
   suivait pas la variante sombre du jeton, si bien que le CTA principal des 31 pages de /master
   passait de 8,32:1 au repos a 2,24:1 AU SURVOL. Aucune surcharge sombre n'existe pour cette
   classe — le repli etait donc le blanc dans les deux themes. */
.isis-master-page__primary-btn:hover { opacity: 0.92; color: var(--isis-on-accent); }
/* `--isis-on-accent` et non `white` : l'anneau est pose SUR l'accent (offset 2px, halo
   `box-shadow` de la meme couleur des deux cotes). Blanc sur l'accent sombre mesurait 2,24:1,
   sous les 3:1 de WCAG 1.4.11 pour un indicateur de focus ; la contre-encre rend 8,32:1 en
   sombre et laisse le clair inchange. Meme defaut que le `:hover` ci-dessus, ligne voisine. */
.isis-master-page__primary-btn:focus-visible {
    outline: 2px solid var(--isis-on-accent);
    outline-offset: 2px;
    box-shadow: 0 0 0 4px var(--isis-accent);
}
/* État fermé — mêmes valeurs que .isis-rich-toolbar__btn:disabled, un seul repère
   visuel de bouton fermé dans la console. Il manquait : sur /master/backups le
   verrou dure tout un cycle de sauvegarde, et le bouton restait plein, donc
   cliquable en apparence, sans rien dire d'un clic sans effet.
   `pointer-events: none` volontairement omis (contrairement au bouton toolbar) :
   il annule le hit-test, donc l'infobulle qui énonce le motif du verrou — or
   c'est elle, ici, qui porte l'explication. `disabled` suffit à bloquer le clic. */
.isis-master-page__primary-btn:disabled,
.isis-master-page__primary-btn[disabled] {
    opacity: 0.4;
    cursor: not-allowed;
}

.isis-master-form { max-width: none; margin: 0; display: flex; flex-direction: column; gap: 1rem; }
.isis-master-form__header h1 {
    font-size: 1.4rem;
    font-weight: 600;
    color: var(--isis-text);
    margin: 0 0 0.25rem;
}
.isis-master-form__header p {
    font-size: 0.85rem;
    color: var(--isis-text-muted);
    margin: 0;
}
.isis-master-form__body { display: flex; flex-direction: column; gap: 1.25rem; padding: 0.5rem 0; }
.isis-master-form__section { display: flex; flex-direction: column; gap: 0.75rem; }
.isis-master-form__section-title {
    font-size: 0.7rem;
    font-weight: 600;
    letter-spacing: 0.08em;
    color: var(--isis-text-soft);
    text-transform: uppercase;
}
.isis-master-form__row { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; }
.isis-master-form__hint {
    display: block;
    font-size: 0.7rem;
    color: var(--isis-text-soft);
    margin-top: 0.25rem;
}
.isis-master-form__actions {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 0.5rem;
    margin-top: 0.5rem;
}
.isis-master-form__cancel {
    padding: 0.5rem 1rem;
    border-radius: 6px;
    color: var(--isis-text-muted);
    text-decoration: none;
    font-size: 0.85rem;
}
.isis-master-form__cancel:hover { background-color: var(--isis-surface-alt); }

/* ============================================================================
   .isis-grid — Grille tabulaire custom (inspirée NetLogger PrdcommandsV3)
   ----------------------------------------------------------------------------
   Alternative à RadzenDataGrid pour les listes denses haute densité.
   CSS Grid layout, header sticky, sort buttons, rows clickable.
   ============================================================================ */

.isis-grid {
    display: flex;
    flex-direction: column;
    font-size: 0.85rem;
    flex: 1;
    min-height: 0;
    overflow: auto;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius);
}

/* Layout colonnes : status | code | raison | type | email | phone | ville | actions
   Total min-width ~ 1000px pour scroll horizontal sur petits écrans */
.isis-grid__head,
.isis-grid__row {
    display: grid;
    grid-template-columns: 32px 130px minmax(180px, 1.4fr) 130px minmax(160px, 1fr) 150px 120px 90px;
    align-items: center;
    padding: 0 0.85rem;
    min-width: 1000px;
    gap: 0;
}

/* Sur téléphone, le plancher de 1000px d'une liste maître-détail forçait un défilement
   horizontal pour lire une ligne : on le lève. Les grilles qui posent leur propre
   plancher (règles .isis-grid--xxx plus bas) le gardent. */
@media (max-width: 640px) {
    .isis-master-detail .isis-grid__head,
    .isis-master-detail .isis-grid__row { min-width: 0; }
}

/* Colonne numérique : à droite et en chiffres tabulaires, sur toutes les grilles. L'en-tête
   est un conteneur flex (isis-grid__head-cell), d'où le justify-content. */
.isis-grid .isis-grid__col-num {
    text-align: right;
    font-variant-numeric: tabular-nums;
}
.isis-grid .isis-grid__head-cell.isis-grid__col-num,
.isis-grid .isis-grid__head > .isis-grid__col-num { justify-content: flex-end; }

/* État de grille (chargement, liste vide) rendu dans un conteneur role="table" :
   IsisGridStateRow l'enveloppe d'une ligne et d'une cellule, sans changer son rendu. */
.isis-grid__state,
.isis-grid__state-cell { display: block; min-width: 0; }
.isis-grid__state { grid-column: 1 / -1; }

/* Sous-ligne dépliable d'une grille role="table" : une ligne, une cellule pleine largeur. */
.isis-grid__subrow-cell { grid-column: 1 / -1; min-width: 0; }

/* Liste des tiers : variante à 10 colonnes (case de sélection en lot, tâche 9, avant le
   statut ; ajout colonne INSEE avant Actions). */
.isis-grid--tiers .isis-grid__head,
.isis-grid--tiers .isis-grid__row {
    grid-template-columns: 28px 32px 130px minmax(180px, 1.4fr) 210px minmax(160px, 1fr) 150px 120px 112px 90px;
    min-width: 1220px;
}
.isis-grid--tiers .isis-grid__col-check {
    display: flex;
    align-items: center;
    justify-content: center;
}
.isis-grid--tiers .isis-grid__col-check input[type="checkbox"] {
    cursor: pointer;
    width: 14px;
    height: 14px;
}
/* Row en sélection multiple : même patron que .isis-grid--devis-list, pas confondu avec
   .is-active (ligne dont le sidepanel est ouvert). */
.isis-grid--tiers .isis-grid__row.is-multi-selected {
    background: color-mix(in srgb, var(--isis-accent) 5%, transparent);
}
.isis-grid--tiers .isis-grid__row.is-multi-selected.is-active {
    background: color-mix(in srgb, var(--isis-accent) 10%, transparent);
}

/* Liste des articles : status | Code | Nom | Nature | Description | Catalogues | Actions. */
.isis-grid--articles .isis-grid__head,
.isis-grid--articles .isis-grid__row {
    grid-template-columns: 32px 140px minmax(200px, 1.6fr) minmax(90px, 124px) 128px minmax(220px, 1fr) 110px 96px;
    min-width: 1088px;
}

/* Liste des événements (gescom, EF-62→75) : status | Statut | Libellé | Nature |
   Dates | Entreprise(s) | Participants | Coût | Actions. */
.isis-grid--evenements .isis-grid__head,
.isis-grid--evenements .isis-grid__row {
    grid-template-columns: 32px 110px minmax(220px, 1.6fr) 120px 140px minmax(170px, 1fr) 90px 110px 70px;
    min-width: 1060px;
}

/* Fiche événement — onglet Participants : Nom | Présence | actions. */
.isis-grid--evenement-participants .isis-grid__head,
.isis-grid--evenement-participants .isis-grid__row {
    grid-template-columns: minmax(200px, 1fr) 180px 56px;
}

/* Fiche événement — onglet Coût & financement : Entreprise porteuse | Montant. */
.isis-grid--evenement-financement .isis-grid__head,
.isis-grid--evenement-financement .isis-grid__row {
    grid-template-columns: minmax(220px, 1fr) 160px;
}

/* Variante ÉDITABLE de la répartition (EF-75) : mêmes deux colonnes, plus une troisième
   pour le retrait de ligne. Le montant passe de 160 à 180px — il porte ici un champ de
   saisie, pas un nombre rendu. `align-items: center` parce que les contrôles Radzen sont
   plus hauts que du texte et se décaleraient de la colonne voisine sans lui. */
.isis-grid--evenement-financement-edit .isis-grid__head,
.isis-grid--evenement-financement-edit .isis-grid__row {
    grid-template-columns: minmax(220px, 1fr) 180px 48px;
    align-items: center;
}

/* Fiche événement — onglet Contacts : Tiers | Interlocuteur | Note | actions (EF-78). */
.isis-grid--evenement-contacts .isis-grid__head,
.isis-grid--evenement-contacts .isis-grid__row {
    grid-template-columns: minmax(180px, 0.9fr) minmax(200px, 1fr) minmax(160px, 1fr) 56px;
}

/* Fiche événement — onglet Actions de suivi : Action | Statut | Échéance | Responsable | actions (EF-79). */
.isis-grid--evenement-actionssuivi .isis-grid__head,
.isis-grid--evenement-actionssuivi .isis-grid__row {
    grid-template-columns: minmax(220px, 1fr) 140px 120px minmax(160px, 0.6fr) 56px;
    align-items: center;
}

/* Événements rattachés à un compte, onglet Affaires de la fiche tiers (EF-65). Le libellé
   prend le reste : c'est le lien cliquable et la seule colonne dont la longueur varie
   vraiment. Les dates tiennent en 180px parce qu'une période en porte deux. */
.isis-grid--tiers-evenements .isis-grid__head,
.isis-grid--tiers-evenements .isis-grid__row {
    grid-template-columns: minmax(200px, 1fr) 140px 120px 180px minmax(120px, 0.6fr) 130px;
}

/* Affaires issues d'un événement (EF-80) : chaque affaire suivie de ses offres, en retrait.
   La première colonne prend le reste — référence et intitulé y sont un seul lien. */
.isis-grid--evenement-affaires .isis-grid__head,
.isis-grid--evenement-affaires .isis-grid__row {
    grid-template-columns: minmax(260px, 1fr) 140px 150px 140px;
}
.isis-evenement-affaires__offre > [role="cell"]:first-child { padding-left: var(--isis-space-lg); }
.isis-evenement-affaires__compte { color: var(--isis-text-muted); font-size: var(--isis-fs-sm); }

/* Événement d'origine d'une affaire (EF-80) : le sélecteur et le lien vers la fiche côte à côte. */
.isis-evenement-origine { display: flex; flex-direction: column; gap: var(--isis-space-sm); }
.isis-evenement-origine__saisie { display: flex; align-items: center; gap: var(--isis-space-md); flex-wrap: wrap; }
.isis-evenement-origine__saisie .rz-dropdown { min-width: 280px; max-width: 100%; }
.isis-evenement-origine__note,
.isis-evenement-origine__vide { color: var(--isis-text-muted); font-size: var(--isis-fs-sm); margin: 0; }

/* Montants des quatre grilles d'événements : à droite et en chiffres tabulaires. Le markup
   posait déjà `isis-grid__col-num` — sans ces règles la classe était un no-op, et les coûts
   s'alignaient à gauche comme du texte. Deux sélecteurs parce que l'en-tête est un conteneur
   inline-flex (`isis-grid__head-cell`) et la cellule non, comme `.isis-grid--previsionnel`. */
.isis-grid--evenements .isis-grid__col-num,
.isis-grid--evenement-financement .isis-grid__col-num,
.isis-grid--evenement-financement-edit .isis-grid__col-num,
.isis-grid--tiers-evenements .isis-grid__col-num,
.isis-grid--evenement-affaires .isis-grid__col-num {
    text-align: right;
    font-variant-numeric: tabular-nums;
}
.isis-grid--evenements .isis-grid__head-cell.isis-grid__col-num {
    justify-content: flex-end;
}

.isis-grid__head {
    background: var(--isis-surface-alt);
    border-bottom: 1px solid var(--isis-border);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    font-size: 0.65rem;
    font-weight: 600;
    /* text-muted (≈6.1:1 sur surface-alt) et non text-soft (3.82:1 < WCAG AA 1.4.3). */
    color: var(--isis-text-muted);
    height: 34px;
    /* .isis-grid est un flex colonne : sans ce flex-shrink:0, `height` n'est qu'une
       suggestion et le navigateur écrase l'en-tête dès que les lignes débordent.
       Mesuré le 2026-07-17 : 34px sur les grilles courtes, mais 20px à 50 lignes et
       13px à 152 — même CSS, hauteur variable selon le contenu. C'était la cause des
       grilles « différentes d'une page à l'autre ». */
    flex-shrink: 0;
    position: sticky;
    top: 0;
    z-index: 4;
}
.isis-grid__head > div {
    position: relative;
    display: flex;
    align-items: center;
    gap: 0.15rem;
    padding: 0 0.35rem;
}

.isis-grid__sort-btn {
    display: inline-flex;
    align-items: center;
    gap: 0.2rem;
    background: transparent;
    border: none;
    padding: 0.15rem 0.4rem;
    border-radius: 4px;
    color: inherit;
    font-size: inherit;
    font-weight: inherit;
    text-transform: inherit;
    letter-spacing: inherit;
    text-align: inherit;
    cursor: pointer;
    transition: background-color 120ms ease, color 120ms ease;
    /* WCAG 2.5.8 : mesuré 50×13 au navigateur. L'en-tête fait 34px de haut, un
       plancher à 24 y tient sans en changer la hauteur. */
    min-height: 24px;
}
.isis-grid__sort-btn:hover {
    background: var(--isis-surface);
    color: var(--isis-text);
}
.isis-grid__sort-btn.is-active {
    color: var(--isis-accent);
    background: var(--isis-accent-soft);
}
/* Audit a11y #3 : focus visible clavier sur les sort buttons. */
.isis-grid__sort-btn:focus-visible {
    outline: 2px solid var(--isis-current-mod, var(--isis-accent));
    outline-offset: 2px;
}

/* Audit M3 : séparateur visuel entre 2 groupes de chips dans la filter-bar. */
.isis-filter-bar__separator {
    width: 1px;
    height: 1.4rem;
    background: var(--isis-border);
    align-self: center;
    margin: 0 0.25rem;
}

/* Groupe de chips axé (libellé + chips) à l'intérieur d'une lane filter-bar.
   Permet de fusionner plusieurs axes (Type · Portée…) dans une même lane sub
   séparés par .isis-filter-bar__separator. Sur écran étroit, wrap naturel. */
.isis-filter-bar__axis-group {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    flex-wrap: wrap;
}
.isis-filter-bar__axis-group .isis-filter-bar__chips {
    /* Évite que les chips se collent au libellé d'axe sur écran large. */
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    flex-wrap: wrap;
}

/* Audit M3 : chip variante alerte (Urgentes) — terre cuite pour signaler
   "demande d'attention" sans crier "ERREUR" (rouge réservé aux statuts critiques
   refuse/annule/inactif). Refonte F4 2026-05-17. */
.isis-chip.isis-chip--alert {
    color: var(--isis-accent);
}
.isis-chip.isis-chip--alert.is-active {
    background: var(--isis-accent);
    color: #fff;
}

/* Badge statut — pattern réutilisable pour porter un statut coloré
   (équipement, livraison, indispo…). Calque sur RadzenBadge mais pilotable
   par classes is-X. Ajouté 2026-05-19 (audit gesmat — .isis-badge utilisé
   par plusieurs modules mais jamais défini avant). */
/* Le badge d'environnement de /a-propos héritait d'un display:flex dans un conteneur
   flex et s'étirait en bande pleine largeur au lieu d'un pill compact (2026-07-17). */
.isis-about-row__value .isis-badge {
    display: inline-flex;
    width: fit-content;
    align-self: flex-start;
}
.isis-badge {
    display: inline-flex;
    align-items: center;
    padding: 0.15rem 0.55rem;
    border-radius: var(--isis-radius-pill);
    font-size: 0.72rem;
    font-weight: 600;
    letter-spacing: 0.01em;
    background: var(--isis-surface-alt);
    color: var(--isis-text-muted);
    border: 1px solid var(--isis-border);
}
.isis-badge.is-ok      { background: var(--isis-success-soft); color: var(--isis-success);            border-color: transparent; }
.isis-badge.is-pending { background: #dbeafe;                  color: #1d4ed8;                        border-color: transparent; }
/* Audit V1.5 — variante warning distincte de pending (bleu = en cours, orange = manquant/attention).
   Précédemment "Jamais calibrée" et "En calibration" partageaient is-pending : ambiguïté résolue. */
.isis-badge.is-warning { background: var(--isis-warning-soft); color: var(--isis-warning);            border-color: transparent; }
.isis-badge.is-danger  { background: var(--isis-danger-soft);  color: var(--isis-danger);             border-color: transparent; }
.isis-badge.is-draft   { background: var(--isis-surface-alt);  color: var(--isis-text-muted);         border-color: var(--isis-border); }
/* Véhicules personnels (MonEspace) — statut DECLARE : mêmes déclarations que .is-draft,
   classe dédiée pour rester distincte au test de complétude des statuts (règle 10). */
.isis-badge.is-declare { background: var(--isis-surface-alt);  color: var(--isis-text);               border-color: var(--isis-border); }
/* Badge neutre générique (type « Ferme », « Externe »…) : mêmes déclarations que is-draft,
   classe dédiée pour ne pas détourner la sémantique « brouillon » sur des libellés de type.
   color: --isis-text (pas --isis-text-muted) — ce badge porte une valeur de donnée à lire,
   pas un statut secondaire, alignement sur .isis-badge--neutral (cf. commentaire plus bas). */
.isis-badge.is-neutral { background: var(--isis-surface-alt);  color: var(--isis-text);               border-color: var(--isis-border); }
.isis-badge.is-info    { background: color-mix(in srgb, var(--isis-current-mod) 10%, white); color: var(--isis-current-mod); border-color: transparent; }

/* F4 — Utilities terre cuite (à appliquer parcimonieusement : 1 par écran max).
   Usage prévu : badges "Nouveau"/"Action requise", KPI hero principal,
   indicateurs éphémères "modifications non sauvegardées". */
.isis-badge--warm,
.rz-badge.isis-badge--warm {
    background: var(--isis-accent-soft) !important;
    color: var(--isis-accent-strong) !important;
}
/* Badge neutre à texte encre — remplace BadgeStyle.Light dont le gris pâle
   échoue le contraste AA (~3.2:1). Texte var(--isis-text) (oklch 0.24) sur
   surface alt (oklch 0.967) = ~13:1, largement ≥ 4.5:1. */
.isis-badge--neutral,
.rz-badge.isis-badge--neutral {
    background: var(--isis-surface-alt) !important;
    color: var(--isis-text) !important;
    border: 1px solid var(--isis-border);
}
/* Badge « action encore attendue » — pendant accessible de BadgeStyle.Info, dont le shade
   lighter de Radzen (bleu #2196f3 sur son propre bleu à 20 %) tombe à ~2.5:1, pire encore
   que Light. Ici --isis-info sur --isis-info-soft = ~7:1 en clair, ~5.9:1 en sombre. */
.isis-badge--info,
.rz-badge.isis-badge--info {
    background: var(--isis-info-soft) !important;
    color: var(--isis-info) !important;
}
/* Badge « action attendue, teinté module » — variante d'identité du précédent, pour les statuts
   qui portaient .isis-badge.is-info (l. 10035) avant la convergence des sidepanels. Ceux-là
   étaient peints à la couleur du module, et CLAUDE.md §4 pose l'identité chromatique par module
   comme préservée en toute circonstance : sans cette classe, BadgeStyle.Info les repeindrait au
   bleu générique de Radzen (ronde de correction du 2026-09-01, écrans gesst Engagements émis et
   reçus — les seuls à avoir converti un <span> .isis-badge en RadzenBadge).
   UNE seule différence avec .isis-badge.is-info, délibérée : le fond se mélange à
   var(--isis-surface), pas au mot-clé `white`. En clair c'est rigoureusement identique
   (--isis-surface vaut #ffffff) ; en sombre, mélanger à `white` posait un rose clair sur un rose
   clair — 2,41:1 sur gesst, illisible — là où --isis-surface sombre rend 5,60:1. Mesuré le
   2026-09-01 sur --isis-mod-gesst : clair #be185d 5,11:1, sombre #f472b6 5,60:1.
   Limite connue, antérieure et non corrigée ici : en mode « couleur de module unifiée » la teinte
   devient l'accent du tenant, dont la clarté n'est garantie par personne — l'accent par défaut
   #0891b2 rend 3,27:1 en clair. C'est le couple de jetons du produit, déjà celui de
   .isis-badge.is-info sur tous les écrans qui l'utilisent, pas une régression introduite ici.
   Ce n'est PAS un cas théorique : le tenant de démo est justement dans ce mode, et la classe y
   a été remesurée au navigateur le 2026-09-01 à 4,37:1 en clair (6,43:1 en sombre) — sous AA en
   clair. CORRIGÉ le 2026-09-03 par la règle bornée en clarté qui suit ; le paragraphe ci-dessus
   décrit l'état d'AVANT. Le choix des listes gesmaff (.isis-badge--info plutôt que celle-ci)
   n'en dépendait pas : il tient à l'absence de teinte de module à préserver sur ces écrans,
   pas au contraste. */
.isis-badge--info-mod,
.rz-badge.isis-badge--info-mod {
    background: color-mix(in srgb, var(--isis-current-mod) 10%, var(--isis-surface)) !important;
    color: var(--isis-current-mod) !important;
}
/* Rattrapage du 4,37:1 clair annoncé juste au-dessus (dette a11y transverse, 2026-09-03) —
   cantonné à `.isis-mod-unified`, LE seul mode où le défaut existe : hors mode unifié la teinte
   est une couleur de module, toutes mesurées et conformes (gesst 5,11:1 clair / 5,60:1 sombre).
   En mode unifié la teinte devient l'accent du tenant, dont la clarté n'est garantie par
   personne — d'où un plafond (clair) et un plancher (sombre) de clarté OKLCH, plutôt qu'un
   mélange vers --isis-text : un mélange à dose fixe rattrape les deux tenants MESURÉS, un
   plafond ferme l'invariant pour n'importe quel accent futur. C et h sont repris tels quels :
   la teinte du tenant est préservée, seule sa clarté est bornée.
   Le plafond n'intervient que s'il est utile — `min(l, …)` / `max(l, …)` laissent passer un
   accent déjà lisible sans le retoucher (l'accent sombre par défaut #38bec9, L 0,736, garde
   son 6,43:1 intact).
   Contrastes calculés sur le fond réel du badge (mélange 10 % accent + surface) :
     clair, plafond L 0,50  — accent défaut #0891b2 : 3,27:1 → 5,02:1
                            — pire cas clair (jaune #fbbf24) : 1,58:1 → 5,72:1
     sombre, plancher L 0,70 — accent défaut #38bec9 : 6,43:1 inchangé
                            — pires cas sombres (#1e1b4b, #7f1d1d) : 1,07:1 / 1,67:1 → 6,25:1 / 5,90:1
   Repli : sur un moteur sans la syntaxe de couleur relative, la déclaration est invalide à
   l'analyse et la règle ci-dessus s'applique — le comportement d'avant, pas un texte sans
   couleur.
   Depuis le 2026-09-23 l'accent par défaut est la terre cuite (#c2410c L 0,553 / #f0803c
   L 0,714). En SOMBRE la règle ne le retouche pas (au-dessus du plancher) ; en CLAIR elle
   l'assombrit à L 0,50, ce qui est son office — c'est un changement par rapport au bleu
   ardoise (L 0,426), que le plafond laissait passer. Les chiffres « accent défaut »
   ci-dessus sont ceux de l'ancien pétrole. */
.isis-mod-unified .isis-badge--info-mod,
.isis-mod-unified .rz-badge.isis-badge--info-mod {
    color: oklch(from var(--isis-current-mod) min(l, 0.50) c h) !important;
}
:root[data-theme="dark"] .isis-mod-unified .isis-badge--info-mod,
:root[data-theme="dark"] .isis-mod-unified .rz-badge.isis-badge--info-mod {
    color: oklch(from var(--isis-current-mod) max(l, 0.70) c h) !important;
}
/* Badge « état suspendu » — pendant accessible de BadgeStyle.Warning, dont le shade lighter de
   Radzen pose l'orange #ff9800 sur son propre orange à 20 % : 1,84:1 en clair, pire encore que
   Info. Mesuré en navigateur le 2026-08-05 sur le badge « désactivée » du bloc Fonctions
   (onglet Habilitations), où le mot était simplement illisible ; 5,51:1 en sombre, donc le
   défaut ne se voit QUE dans le thème clair. --isis-warning sur --isis-warning-soft tient les
   deux. */
.isis-badge--warning,
.rz-badge.isis-badge--warning {
    background: var(--isis-warning-soft) !important;
    color: var(--isis-warning) !important;
}
/* Badge « état favorable » — pendant accessible de BadgeStyle.Success, dont le shade lighter de
   Radzen pose le vert #4caf50 sur son propre vert à 16 % : 2,39:1 en clair, pire encore que Info.
   Mesuré en navigateur le 2026-09-01 sur le badge de statut du sidepanel Engagements (gesst),
   classes forcées faute de statut « En cours » en démo. --isis-success sur --isis-success-soft
   = 4,57:1 en clair, 5,90:1 en sombre. */
.isis-badge--success,
.rz-badge.isis-badge--success {
    background: var(--isis-success-soft) !important;
    color: var(--isis-success) !important;
}
/* Badge « état défavorable » — pendant accessible de BadgeStyle.Danger, dont le shade lighter de
   Radzen pose le rouge #f44336 sur son propre rouge à 20 % : 2,82:1 en clair. Mesuré le même jour,
   au même endroit et de la même façon que --success. --isis-danger sur --isis-danger-soft =
   5,30:1 en clair ; 4,35:1 en sombre, sous le seuil AA — c'est le couple de jetons du produit
   (déjà celui de .isis-badge.is-danger), pas une régression introduite ici. Le sombre est
   rattrapé par la règle qui suit ; le jeton, lui, reste inchangé. */
.isis-badge--danger,
.rz-badge.isis-badge--danger {
    background: var(--isis-danger-soft) !important;
    color: var(--isis-danger) !important;
}
/* Rattrapage du 4,35:1 sombre annoncé ci-dessus, mesuré à nouveau au navigateur le
   2026-09-01 (Résilié / Annulé du sidepanel Marchés). Même remède que le libellé d'action
   destructive en sombre (l. 3495) : on éclaircit le TEXTE en le mélangeant à --isis-text,
   sans toucher au jeton produit et sans poser la moindre valeur en dur. 85 % rend 5,05:1
   sur --isis-danger-soft (mesuré au navigateur) et laisse le rouge franc.
   Le thème clair n'est pas concerné — il tient déjà 5,30:1 — donc pas touché. */
:root[data-theme="dark"] .isis-badge--danger,
:root[data-theme="dark"] .rz-badge.isis-badge--danger {
    color: color-mix(in srgb, var(--isis-danger) 85%, var(--isis-text)) !important;
}
.isis-chip.isis-chip--warm {
    color: var(--isis-accent-strong);
    border-color: var(--isis-accent);
}
.isis-chip.isis-chip--warm.is-active {
    background: var(--isis-accent);
    color: #fff;
}
/* Chip type « mobilisation gesproj » (sidepanel planner) — type d'élément, pas un statut de workflow. */
.isis-chip--mob-gesproj {
    background: color-mix(in srgb, var(--isis-mod-gesproj) 12%, var(--isis-surface));
    color: var(--isis-mod-gesproj);
}
.isis-kpi-card__value.is-warm {
    color: var(--isis-accent-strong);
}

/* Branded depth 2026-05-17 — narrative anchor : le 1er KPI de chaque hero
   est automatiquement en terre cuite (le "TOTAL" qui rythme le scan).
   Opt-out par page possible via .isis-kpi-hero--no-headline
   (ex: pages avec foreach équipondéré comme MonEspace soldes par type d'absence). */
.isis-kpi-hero:not(.isis-kpi-hero--no-headline) > .isis-kpi-card:first-child .isis-kpi-card__value {
    color: var(--isis-accent-strong);
}

/* Audit M5 : style de l'ancienneté en mode normal (cohérence avec urgent). */
.isis-grid__age-normal {
    color: var(--isis-text-muted);
    font-size: 0.82rem;
}
.isis-grid__sort-icon {
    font-size: 14px;
    opacity: 0.6;
}
.isis-grid__sort-btn.is-active .isis-grid__sort-icon { opacity: 1; }

/* Seconde grandeur dans une CELLULE D'EN-TÊTE — la place d'un chiffre qu'un bandeau retiré
   laissait orphelin et qui porte sur la colonne, pas sur la ligne (« N comptes couverts » sur
   la colonne Compte, quand le pagineur, lui, compte des contacts). Discret : c'est un repère,
   pas un titre. Muet à zéro — une pastille qui annonce « 0 » ne dit rien. */
.isis-grid__head-hint {
    margin-left: 0.35rem;
    font-family: var(--isis-font-mono);
    font-variant-numeric: tabular-nums;
    font-size: 0.68rem;
    font-weight: 400;
    text-transform: none;
    letter-spacing: 0;
    color: var(--isis-text-soft);
    white-space: nowrap;
}

/* En-tête : cellule hébergeant tri + entonnoir de filtre côte à côte */
.isis-grid__head-cell {
    display: inline-flex;
    align-items: center;
    gap: 0.1rem;
    min-width: 0;
}
.isis-grid__filter-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 0;
    background: transparent;
    color: var(--isis-text-soft);
    cursor: pointer;
    padding: 2px;
    border-radius: 4px;
    opacity: 0.55;
    /* WCAG 2.5.8 : mesuré 18×18. Même remarque que le bouton de tri — l'en-tête
       fait 34px, la cible peut atteindre 24 sans le déformer. */
    min-width: 24px;
    min-height: 24px;
}
/* La poignée de redimensionnement (.isis-grid-rsz, 6 px, z-index 2) est posée sur le BORD
   DROIT de la cellule d'en-tête, au-dessus de son contenu. Sur une colonne étroite — 90 à
   100 px, Devise, Pays, Emplacement — l'entonnoir arrive jusqu'à ce bord et passe SOUS la
   poignée : viser l'entonnoir attrape le redimensionneur. Mesuré au navigateur le 2026-09-06
   sur cinq colonnes de l'admin, et déjà vrai avant ce chantier sur « Propriétaire » de
   /gesproj/commandes. On réserve donc la largeur de la poignée, et seulement là où un
   entonnoir peut l'atteindre. */
.isis-grid__head-cell:has(.isis-grid__filter-btn) { padding-right: 7px; }
/* …et la réservation ne sert à rien si le CONTENU déborde la cellule : mesuré le
   2026-09-06, sur une colonne de 100 px l'entonnoir sortait de 3 px à droite du bord,
   par-dessus la poignée, parce que « Devise » + tri + entonnoir font 103 px. Le bouton
   de tri cède donc le premier — c'est le LIBELLÉ qui s'élide, jamais le contrôle
   (même règle que les compteurs, § G6) — et l'entonnoir garde sa taille. */
.isis-grid__head-cell > .isis-grid__sort-btn {
    min-width: 0;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}
.isis-grid__head-cell > .isis-grid__filter-btn { flex: 0 0 auto; }
.isis-grid__head-cell:hover .isis-grid__filter-btn { opacity: 0.85; }
.isis-grid__filter-btn:hover { color: var(--isis-text); background: var(--isis-surface); opacity: 1; }

/* Déclencheur LIBELLÉ du même panneau de filtre — dans une barre de filtres, où aucun
   libellé de colonne voisin ne dit sur quoi le bouton porte (2026-09-02). Plat par
   intention : il vit dans une barre déjà posée, pas sur le fond de page. */
.isis-filter-facet-btn {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    height: 32px;
    padding: 0 0.55rem;
    /* Sans cadre au repos (2026-09-17, même retour que .isis-rich-toolbar__btn) : le cadre
       n'apparaît qu'au survol et quand un filtre est POSÉ (.is-active) — il redevient un signal. */
    border: 1px solid transparent;
    border-radius: var(--isis-radius-sm, 6px);
    background: transparent;
    color: var(--isis-text);
    font-size: var(--isis-fs-sm);
    font-weight: 500;
    cursor: pointer;
    box-shadow: none;
    transition: border-color 120ms ease, background-color 120ms ease;
}
.isis-filter-facet-btn:hover { border-color: var(--isis-current-mod); }
.isis-filter-facet-btn:focus-visible {
    outline: 2px solid color-mix(in srgb, var(--isis-current-mod) 55%, transparent);
    outline-offset: 1px;
}
.isis-filter-facet-btn.is-active {
    border-color: var(--isis-current-mod);
    color: var(--isis-current-mod);
}
.isis-filter-facet-btn__label { white-space: nowrap; }

/* Identité compacte d'une FICHE, posée dans la barre du haut à côté du fil d'Ariane
   (2026-09-03). Depuis que les fiches perdent leur bandeau, deux choses doivent rester
   visibles quel que soit l'onglet ouvert : la référence qu'on cite, et le statut, qui
   gouverne les actions de la barre. Le reste vit dans le premier onglet. */
.isis-fiche-ident {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    margin-left: 0.75rem;
    /* Colle réellement le bloc au fil. .isis-rich-toolbar est en `justify-content:
       space-between` : avec trois enfants (fil, identité, actions), l'espace libre se
       répartissait de part et d'autre de l'identité, qui flottait au milieu de la barre
       (256 à 423 px du fil selon sa longueur) — le margin-left et le border-left
       ci-contre n'avaient alors plus de sens. Une marge AUTO est distribuée avant que
       `justify-content` ne s'applique : elle absorbe tout l'espace libre, l'identité
       reste contre le fil et les actions vont au bord droit. Posé sur CETTE classe, donc
       sans toucher au conteneur partagé ni aux pages qui ne l'emploient pas. */
    margin-right: auto;
    padding-left: 0.75rem;
    border-left: 1px solid var(--isis-border);
}
.isis-fiche-ident__ref {
    font-family: var(--isis-font-mono);
    font-size: var(--isis-fs-sm);
    color: var(--isis-text-soft);
    white-space: nowrap;
}
/* Raison courte d'un état d'identité (ex. « Lecture seule ») : visible, pas seulement en infobulle.
   --isis-text-muted et non -soft : -soft tombe à 4,13:1 sur --isis-bg en clair (muted : 6,57:1). */
.isis-fiche-ident__raison {
    font-size: var(--isis-fs-sm);
    color: var(--isis-text-muted);
    white-space: nowrap;
}

/* Résumé chiffré en tête d'un onglet de fiche (2026-09-03). Une LIGNE de texte et non des
   cartes : sur une fiche ces chiffres répondent à « où en est-on ? », pas à « compare-les ».
   Le bouton mène à l'onglet qui les détaille. */
.isis-fiche-resume {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 0.35rem 1.75rem;
    margin-bottom: 0.9rem;
    padding-bottom: 0.9rem;
    border-bottom: 1px solid var(--isis-border);
}
.isis-fiche-resume__item { display: inline-flex; align-items: baseline; gap: 0.4rem; }
.isis-fiche-resume__k {
    font-size: 0.68rem;
    font-weight: 600;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    /* --isis-text-soft (#64748b) ne tient pas sur --isis-surface-alt (#e1e7ef), fond de la
       console plateforme où cette ligne est posée à nu : 3,82:1 pour 4,5:1 requis à 0,68rem.
       Le cran secondaire passe sur TOUS les fonds où la ligne est rendue — 7,58:1 sur
       --isis-surface, 6,09:1 sur -alt, 6,98:1 et 6,15:1 en sombre. */
    color: var(--isis-text-muted);
}
.isis-fiche-resume__v {
    font-family: var(--isis-font-mono);
    font-variant-numeric: tabular-nums;
    font-size: var(--isis-fs-md, 0.95rem);
    font-weight: 600;
    color: var(--isis-text);
}
.isis-fiche-resume__v.is-warm { color: var(--isis-warning); }
/* Les deux autres sémantiques, ajoutées le 2026-09-06 pour la fiche d'un compte : un compte
   verrouillé et un compte sain ne se lisent pas de la même encre. La couleur n'apparaît que
   lorsqu'elle SIGNIFIE (DESIGN.md, volet) — jamais par défaut. */
.isis-fiche-resume__v.is-danger { color: var(--isis-danger); }
.isis-fiche-resume__v.is-success { color: var(--isis-success); }
.isis-fiche-resume__h { font-size: var(--isis-fs-sm); color: var(--isis-text-muted); }
.isis-fiche-resume__go {
    /* Teinte module ASSOMBRIE : la teinte pleine échoue en texte sur le blanc du bouton dès
       que le module est clair — 3,68:1 pour l'accent de repli (console plateforme, qui n'a pas
       de --isis-current-mod), 3,77:1 en sirh, 4,47:1 en ged. --isis-mod-active-mix est le
       dosage déjà en vigueur dans le thème pour du texte de module (80 % en clair, 100 % en
       sombre où les teintes sont déjà éclaircies) : pire cas 5,39:1 en clair, 4,52:1 en sombre.
       La même encre sert l'anneau de focus plus bas. */
    --isis-fiche-resume-mod: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) var(--isis-mod-active-mix), black);
    margin-left: auto;
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    height: 30px;
    padding: 0 0.65rem;
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-sm, 6px);
    background: var(--isis-surface);
    color: var(--isis-fiche-resume-mod);
    font-size: var(--isis-fs-sm);
    font-weight: 600;
    cursor: pointer;
}
.isis-fiche-resume__go:hover { border-color: var(--isis-current-mod, var(--isis-accent)); }
/* Le mélange vers transparent diluait l'anneau à ~1,8:1 sur le fond de la console : seul
   repère du focus clavier, et invisible. Teinte pleine — patron de
   .isis-completude__group-title:focus-visible, quarante lignes plus bas — assombrie comme le
   texte du bouton, faute de quoi l'accent de repli reste à 2,96:1 sur --isis-surface-alt.
   Après : 4,33:1 au pire en clair, 3,99:1 au pire en sombre, pour 3:1 requis. */
.isis-fiche-resume__go:focus-visible {
    outline: 2px solid var(--isis-fiche-resume-mod);
    outline-offset: 1px;
}

/* Variante liste de définitions : la paire clé/valeur n'était liée que visuellement
   (spans adjacents). <dl> la rend programmatique (1.3.1). Le <dl> ne peut pas accueillir le
   bouton — son modèle de contenu n'admet que des groupes dt/dd ou des <div> — il reste donc
   imbriqué dans .isis-fiche-resume, qui garde la barre et pousse le bouton à droite. Les
   marges par défaut de <dl>/<dd> sont remises à zéro : sans quoi <dd> prend 40px à gauche. */
.isis-fiche-resume__dl {
    flex: 1 1 auto;
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 0.35rem 1.75rem;
    margin: 0;
}
.isis-fiche-resume__dl dt,
.isis-fiche-resume__dl dd { margin: 0; }

/* Panneau de diagnostic de complétude — CompletudePanel.razor. Posé DANS le contenu de
   l'onglet Aperçu, jamais au-dessus de la carte d'onglets (cf. commentaire EntrepriseDetail.razor
   ~L110-119 : .isis-rich-page est height:100%/overflow:hidden, la carte d'onglets est son seul
   enfant élastique — une carte fixe au-dessus prend sa hauteur SUR LE CONTENU). */
.isis-completude {
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius);
    background: var(--isis-surface);
    padding: 12px 14px;
    margin-bottom: 12px;
}
.isis-completude__head {
    display: flex; align-items: center; gap: 8px;
    font-weight: 600; margin-bottom: 8px;
}
.isis-completude__list { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.isis-completude__item {
    display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
}
.isis-completude__libelle { font-weight: 500; }
.isis-completude__detail { color: var(--isis-text-muted); font-size: var(--isis-fs-sm); }
/* Groupe par sévérité (dès que le panneau en compte plus d'une) — intitulé au même gabarit
   que .isis-fiche-resume__k, vingt lignes plus haut dans le même onglet : pas de token inventé. */
.isis-completude__group + .isis-completude__group { margin-top: 12px; }
.isis-completude__group-title { display: block; margin-bottom: 6px; cursor: default; }
summary.isis-completude__group-title { cursor: pointer; }
summary.isis-completude__group-title:focus-visible {
    outline: 2px solid var(--isis-current-mod); outline-offset: 2px;
}
/* Même traitement que le lien jumeau .isis-fiche-resume__go, vingt lignes au-dessus dans le même
   onglet — bouton bordé, pas un lien texte nu (incohérence relevée en revue). Aussi bien sur <a>
   (navigation externe) que sur <button> (bascule d'onglet locale, cf. ResolveLocalAction côté hôte). */
.isis-completude__go {
    margin-left: auto; display: inline-flex; align-items: center; gap: 0.35rem;
    height: 30px; padding: 0 0.65rem;
    border: 1px solid var(--isis-border); border-radius: var(--isis-radius-sm, 6px);
    background: var(--isis-surface); color: var(--isis-current-mod, var(--isis-accent));
    font-size: var(--isis-fs-sm); font-weight: 600; cursor: pointer; text-decoration: none;
}
.isis-completude__go:hover { border-color: var(--isis-current-mod, var(--isis-accent)); }
.isis-completude__go:focus-visible {
    outline: 2px solid color-mix(in srgb, var(--isis-current-mod) 55%, transparent);
    outline-offset: 1px;
}

/* CompletudeAvertissement.razor — même défaut, même remède que .isis-badge--warning
   vingt lignes plus haut : le Shade.Lighter de Radzen pose l'orange plein (#ff9800) sur son
   propre orange à 20 % — mesuré au navigateur le 2026-09-07 à 1,63:1 en clair mais 6,08:1 en
   sombre (clair et sombre étaient inversés dans ce commentaire, corrigé le 2026-09-18). --isis-warning sur --isis-warning-soft tient les deux, comme
   pour le badge. Le lien enfant héritait de .isis-link (var(--isis-accent), pensé pour un fond
   neutre) : 3,56:1 en clair et 1,69:1 en sombre sur CE fond précis — retombe donc lui aussi sur
   --isis-warning (souligné par .isis-link, la distinction ne tient déjà pas qu'à la couleur).
   .isis-reprise-avertissement (RepriseDonneesPage.razor, bandeau « N des M imports vous sont
   fermés ») partage le même défaut et donc le même remède : couple de jetons recalculé le
   2026-09-13 contre les valeurs :root — 5,34:1 en clair (#8f5700 sur #fef3c7) et 6,30:1 en
   sombre (#d6a02a sur #312611), les deux au-dessus du seuil AA.
   .isis-gabarit-avertissement (DevisCostingTab.razor, bandeau des sous-tâches qu'un gabarit n'a
   pas pu chiffrer, 0976) est le troisième du même cas : même défaut Radzen, donc même remède et
   le MÊME couple de jetons que ci-dessus — rien n'y est mesuré à part, les ratios valent tels
   quels. */
.isis-completude-avertissement.rz-alert,
.isis-reprise-avertissement.rz-alert,
.isis-gabarit-avertissement.rz-alert {
    background: var(--isis-warning-soft) !important;
}
.isis-completude-avertissement.rz-alert,
.isis-completude-avertissement.rz-alert .rz-alert-content,
.isis-completude-avertissement.rz-alert .rz-alert-icon,
.isis-reprise-avertissement.rz-alert,
.isis-reprise-avertissement.rz-alert .rz-alert-content,
.isis-reprise-avertissement.rz-alert .rz-alert-icon,
.isis-reprise-avertissement.rz-alert .rz-alert-message,
.isis-reprise-avertissement.rz-alert .rz-alert-title,
.isis-gabarit-avertissement.rz-alert,
.isis-gabarit-avertissement.rz-alert .rz-alert-content,
.isis-gabarit-avertissement.rz-alert .rz-alert-icon,
.isis-gabarit-avertissement.rz-alert .rz-alert-message,
.isis-gabarit-avertissement.rz-alert .rz-alert-title {
    color: var(--isis-warning) !important;
}
.isis-completude-avertissement.rz-alert .isis-link {
    color: var(--isis-warning) !important;
}

/* Vue transverse de complétude (CompletudePage.razor, /sirh/entreprises/completude) —
   référentiel BORNÉ (DESIGN.md §5) : une section par entreprise, chacune portant son
   propre CompletudePanel déjà bordé (.isis-completude ci-dessus) — la carte englobante
   n'a donc qu'à apporter l'élévation et le nom, pas un second cadre autour du panneau. */
.isis-completude-hub {
    display: grid;
    gap: 1rem;
}
.isis-completude-hub__entreprise {
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius);
    box-shadow: var(--isis-elevation-1);
    padding: 1rem 1.1rem;
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
}
.isis-completude-hub__nom {
    margin: 0;
    display: flex;
    align-items: baseline;
    gap: 0.6rem;
    font-size: var(--isis-fs-md, 1rem);
}
.isis-completude-hub__nom a {
    color: var(--isis-text);
    text-decoration: none;
    font-weight: 600;
}
.isis-completude-hub__nom a:hover { color: var(--isis-current-mod, var(--isis-accent)); }
.isis-completude-hub__nom a:focus-visible {
    outline: 2px solid color-mix(in srgb, var(--isis-current-mod) 55%, transparent);
    outline-offset: 2px;
}
.isis-completude-hub__code {
    /* --isis-font-mono n'est défini nulle part dans le thème (piège consigné en mémoire
       projet) : fallback explicite, jamais la variable nue. */
    font-family: var(--isis-font-mono, ui-monospace, monospace);
    font-size: var(--isis-fs-sm);
    color: var(--isis-text-soft);
}
.isis-completude-hub__toggle {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    font-size: var(--isis-fs-sm);
    color: var(--isis-text-soft);
    cursor: pointer;
}
/* Ligne de repère avant la liste (ronde 1) : dit par où commencer (NbAvecBloquant) et le sens
   du classement — pas un bandeau de KPI, une ligne de texte. */
.isis-completude-hub__resume {
    margin: 0 0 0.75rem;
    font-size: var(--isis-fs-sm);
    color: var(--isis-text-soft);
}
/* État positif d'une entreprise sans contrôle en échec (visible seulement quand « Seulement
   les incomplètes » est décoché) — remplace un bloc vide qui n'affichait que le nom. */
.isis-completude-hub__ok {
    margin: 0;
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    font-size: var(--isis-fs-sm);
    color: var(--isis-success);
}
/* Saisie en ligne du pays (SIRH_PAYS_ABSENT) — une entreprise à la fois, migration 0708.
   Rangée sous le panneau de diagnostic de CETTE entreprise, jamais un formulaire pleine page :
   un sélecteur pré-rempli (ViewModel, depuis TenantContext.Current?.DefaultCountry) + un bouton
   de confirmation, rien de plus — pas de bouton « tout appliquer » (cadrage). */
.isis-completude-hub__pays-fix {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    flex-wrap: wrap;
    padding-top: 0.6rem;
    border-top: 1px dashed var(--isis-border);
}
.isis-completude-hub__pays-fix .rz-dropdown {
    min-width: 220px;
}
/* Champ requis (WCAG 3.3.2) : même patron que .isis-form-linear .label .required, hors contexte
   form-linear ici — la saisie en ligne du pays n'a pas de <label> visible avant ce correctif
   (aria-label seul sur le RadzenDropDown, rien à l'écran ne disait « obligatoire »). */
.isis-completude-hub__pays-label {
    font-size: 0.72rem;
    font-weight: 500;
    color: var(--isis-text-muted);
    letter-spacing: 0.01em;
    flex: 0 0 100%;
}
.isis-completude-hub__pays-label .required {
    color: var(--rz-danger, #dc2626);
    margin-left: 2px;
}
.isis-completude-hub__pays-confirm {
    height: 30px;
    padding: 0 0.75rem;
    border: none;
    border-radius: var(--isis-radius-sm, 6px);
    background: var(--isis-current-mod, var(--isis-accent));
    /* Mesuré au navigateur le 2026-09-07 sur /sirh/entreprises/completude, tenant demo, couleur
       RÉELLEMENT PEINTE (pas un var(--x) converti à la main) : le commentaire précédent
       affirmait « saturée dans les deux thèmes » sans mesure — faux en sombre, où l'accent
       (unifié ou module) est délibérément ÉCLAIRCI (cf. bloc :root[data-theme="dark"], les
       seize --isis-mod-* y sont des tons clairs). Blanc mesuré : clair 5,06:1 (passe), sombre
       2,24:1 (échoue, il faut 4,5). Voir rapport a11y-fix-report.md pour le détail des deux mesures. */
    color: #fff;
    font-size: var(--isis-fs-sm);
    font-weight: 600;
    cursor: pointer;
}
.isis-completude-hub__pays-confirm:disabled {
    opacity: 0.55;
    cursor: not-allowed;
}
.isis-completude-hub__pays-confirm:focus-visible {
    outline: 2px solid color-mix(in srgb, var(--isis-current-mod) 55%, transparent);
    outline-offset: 2px;
}
/* Même défaut, même remède qu'.isis-rich-toolbar__btn--primary (commentaire jumeau vingt lignes
   plus haut dans ce fichier) : en sombre, l'encre du thème (--isis-bg, quasi noir) rétablit un
   contraste large sur les seize teintes de module éclaircies — mesuré 8,32:1 sur l'accent unifié
   du tenant demo en sombre (contre 2,24:1 en blanc), 4,5 requis. */
:root[data-theme="dark"] .isis-completude-hub__pays-confirm { color: var(--isis-bg); }

/* Dans un GROUPE du panneau de filtres avancés, le déclencheur prend toute la largeur —
   il y remplace un <RadzenDropDown Style="width: 100%">, et un bouton qui s'arrête au
   milieu de son groupe ne se lit pas comme un champ. Le libellé pousse le chevron au
   bord, comme une liste déroulante. */
.isis-filter-float__grpb .isis-filter-facet-btn {
    width: 100%;
    justify-content: flex-start;
    height: 34px;
    /* Ici il tient lieu de CHAMP : il garde son cadre au repos, contrairement à la barre. */
    border-color: var(--isis-border);
    background: var(--isis-surface);
}
.isis-filter-float__grpb .isis-filter-facet-btn__label { flex: 1; text-align: left; }
.isis-filter-float__grpb .isis-filter-facet-btn > .rzi:last-child { margin-left: auto; }

/* En-tête de groupe dans un panneau de filtre (statuts rangés par phase). */
.isis-head-filter__grouphead {
    padding: 0.4rem 0.6rem 0.2rem;
    font-size: 0.68rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--isis-text-soft);
}
.isis-head-filter__grouphead:not(:first-child) {
    margin-top: 0.15rem;
    border-top: 1px solid var(--isis-border-soft, var(--isis-border));
}
.isis-filter-facet-btn__count {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 18px;
    height: 18px;
    padding: 0 5px;
    border-radius: 9px;
    background: var(--isis-current-mod, var(--isis-accent));
    /* Blanc littéral, comme .isis-filter-advanced-btn__badge : la couleur de module est
       saturée dans les DEUX thèmes, donc le texte posé dessus ne dépend pas du thème.
       `--isis-on-accent` existe désormais (défini dans :root et :root[data-theme="dark"]),
       mais ne s'applique pas ici : le fond est --isis-current-mod (une couleur de MODULE,
       pas --isis-accent), avec --isis-accent seulement en repli quand aucun module courant
       n'est actif — migration hors périmètre de cette règle. */
    color: #fff;
    font-size: 0.68rem;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}

/* Groupe de contrôles justifié à droite d'une barre de filtres : la recherche reste à
   gauche, les boutons qui agissent sur la liste se rassemblent à l'opposé. */
.isis-filter-bar__end {
    margin-left: auto;
    display: inline-flex;
    align-items: center;
    gap: 0.6rem;
}
/* Grandeur qui ne filtre RIEN, posée en fin de barre de filtres — la place d'un TAUX qu'un
   bandeau retiré laissait orphelin et qu'aucune facette ne peut porter (une facette annonce
   l'effectif d'une valeur, pas un ratio sur la population). Ce n'est pas un contrôle : ni
   bouton, ni cible de clic. À n'employer que là où le § F ne propose aucun autre emplacement. */
.isis-filter-bar__stat {
    display: inline-flex;
    align-items: baseline;
    gap: 0.35rem;
    font-size: var(--isis-fs-sm);
    color: var(--isis-text-soft);
    white-space: nowrap;
}
.isis-filter-bar__stat strong {
    font-family: var(--isis-font-mono);
    font-variant-numeric: tabular-nums;
    color: var(--isis-text);
}
.isis-filter-bar__search .isis-filter-bar__clear {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 0;
    background: transparent;
    color: var(--isis-text-soft);
    cursor: pointer;
    padding: 2px;
    border-radius: 4px;
    opacity: 0.6;
}
.isis-filter-bar__search .isis-filter-bar__clear:hover { opacity: 1; background: var(--isis-surface-alt, transparent); }
.isis-filter-bar__search .isis-filter-bar__clear:focus-visible {
    outline: 2px solid color-mix(in srgb, var(--isis-current-mod) 55%, transparent);
    outline-offset: 1px;
}

/* Axe de filtre sans objet pour la vue affichée : DÉSACTIVÉ, jamais masqué — la barre garde
   la même forme d'une vue à l'autre, donc la même mémoire musculaire.
   `aria-disabled` et non l'attribut `disabled` : le contrôle reste dans l'ordre de tabulation,
   donc son `title` — la RAISON de l'inertie — reste atteignable au clavier et au lecteur
   d'écran. Sans cette raison, « désactivé » ne se distingue pas de « cassé ».
   L'encre atténuée et le curseur suffisent à dire l'inertie : pas de hachuré, la charte lui
   réserve d'autres sens. */
.isis-filter-facet-btn[aria-disabled="true"],
.isis-filter-advanced-btn[aria-disabled="true"],
.isis-grid__filter-btn[aria-disabled="true"] {
    color: var(--isis-text-muted);
    background: var(--isis-surface-alt);
    cursor: not-allowed;
    opacity: 0.75;
}
.isis-filter-facet-btn[aria-disabled="true"]:hover,
.isis-filter-advanced-btn[aria-disabled="true"]:hover,
.isis-grid__filter-btn[aria-disabled="true"]:hover {
    border-color: var(--isis-border);
    background: var(--isis-surface-alt);
}
.isis-filter-bar__search input[aria-disabled="true"] {
    color: var(--isis-text-muted);
    cursor: not-allowed;
}
.isis-filter-bar__search .isis-filter-bar__clear[aria-disabled="true"] {
    color: var(--isis-text-muted);
    cursor: not-allowed;
    opacity: 0.45;
}
.isis-filter-bar__search .isis-filter-bar__clear[aria-disabled="true"]:hover {
    opacity: 0.45;
    background: transparent;
}
.isis-grid__filter-btn:focus-visible {
    outline: 2px solid color-mix(in srgb, var(--isis-current-mod) 55%, transparent);
    outline-offset: 1px;
    opacity: 1;
}
.isis-grid__filter-btn.is-active {
    color: var(--isis-current-mod);
    opacity: 1;
}

/* Popup de filtre par colonne (position: fixed, ancré au clic) */
.isis-head-filter__backdrop {
    position: fixed;
    inset: 0;
    z-index: 60;
    background: transparent;
}
.isis-head-filter__panel {
    position: fixed;
    z-index: 61;
    width: 260px;
    max-width: 92vw;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius);
    box-shadow: var(--isis-elevation-2);
    padding: 0.4rem;
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
}
/* Sélecteur de vue replié en facette (VueFacette.razor) : plus large qu'un filtre de colonne, la liste
   des membres et l'arbre des structures y gardent leur propre défilement. */
/* border-box : sans reset global, padding et bordure (15 px) s'ajouteraient à la largeur que
   VueFacette suppose pour caler le panneau à 8 px du bord droit. */
.isis-head-filter__panel.vue-facette__panneau {
    box-sizing: border-box;
    width: min(392px, calc(100vw - 16px));
    max-width: none;
    overflow-y: auto;
}
.vue-facette__corps {
    display: flex;
    flex-direction: column;
    gap: var(--isis-space-md);
    padding: 0.35rem;
}
.isis-head-filter__foot.vue-facette__pied { justify-content: flex-end; }
.isis-head-filter__head {
    display: flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.15rem 0.35rem;
    font-size: 0.72rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--isis-text-soft);
}
.isis-head-filter__search {
    display: flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.3rem 0.45rem;
    background: var(--isis-surface-alt);
    border-radius: 6px;
}
.isis-head-filter__search input {
    border: 0;
    background: transparent;
    outline: none;
    width: 100%;
    font-size: 0.82rem;
    color: var(--isis-text);
}
.isis-head-filter__list {
    max-height: 280px;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
}
.isis-head-filter__item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    width: 100%;
    text-align: left;
    border: 0;
    background: transparent;
    padding: 0.4rem 0.5rem;
    border-radius: 6px;
    cursor: pointer;
    font-size: 0.82rem;
    color: var(--isis-text);
}
.isis-head-filter__item:hover { background: var(--isis-surface-alt); }
.isis-head-filter__item.is-active {
    background: color-mix(in srgb, var(--isis-current-mod) 12%, transparent);
    color: var(--isis-current-mod);
    font-weight: 600;
}
.isis-head-filter__item > span {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.isis-head-filter__empty {
    padding: 0.5rem;
    font-size: 0.8rem;
    color: var(--isis-text-soft);
    text-align: center;
}
/* Multi-select : case à cocher dans l'item */
.isis-head-filter__check {
    font-size: 16px;
    opacity: 0.7;
    flex: 0 0 auto;
}
.isis-head-filter__item.is-active .isis-head-filter__check { opacity: 1; }
/* Multi-select : compteur sur l'entonnoir d'en-tête */
.isis-grid__filter-count {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 14px;
    height: 14px;
    padding: 0 3px;
    margin-left: 2px;
    border-radius: 7px;
    background: var(--isis-current-mod);
    color: #fff;
    font-size: 0.62rem;
    font-weight: 700;
    line-height: 1;
}
/* Multi-select : pied du popup (Tout effacer / Appliquer) */
.isis-head-filter__foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    padding-top: 0.35rem;
    margin-top: 0.15rem;
    border-top: 1px solid var(--isis-border);
}
.isis-head-filter__clear {
    border: 0;
    background: transparent;
    color: var(--isis-text-soft);
    font-size: 0.78rem;
    cursor: pointer;
    padding: 0.3rem 0.4rem;
    border-radius: 6px;
}
.isis-head-filter__clear:hover:not(:disabled) { color: var(--isis-text); background: var(--isis-surface-alt); }
.isis-head-filter__clear:disabled { opacity: 0.4; cursor: default; }
.isis-head-filter__apply {
    border: 0;
    background: var(--isis-current-mod);
    color: #fff;
    font-size: 0.8rem;
    font-weight: 600;
    cursor: pointer;
    padding: 0.35rem 0.7rem;
    border-radius: 6px;
}
.isis-head-filter__apply:hover { filter: brightness(0.95); }

/* Rows */
.isis-grid__row {
    min-height: 44px;
    /* Même cause que .isis-grid__head : .isis-grid est un flex colonne, et sans
       flex-shrink:0 le `min-height` n'est qu'une suggestion. Une ligne dont le contenu
       demande plus (15 badges de modules = 101px) était écrasée à 45px, et sa cellule
       débordait de 56px EN PEIGNANT PAR-DESSUS les lignes voisines : badges empilés à
       91% de recouvrement, chevauchement avec le « — aucun module — » d'à côté.
       Mesuré sur /admin/users le 2026-07-17. `min-height` veut dire minimum. */
    flex-shrink: 0;
    border-bottom: 1px solid var(--isis-border-soft, #f1f2f5);
    transition: background-color 100ms ease;
    cursor: pointer;
}
/* Hover / Active : le repère est le FOND teinté module. Liseré gauche coloré retiré
   2026-07-04 (demande utilisateur) — plus de décalage du contenu au survol/sélection. */
.isis-grid__row:hover {
    background: var(--isis-current-mod-soft, var(--isis-surface-alt));
}
.isis-grid__row:last-child { border-bottom: none; }
.isis-grid__row.is-active {
    background: var(--isis-current-mod-soft, var(--isis-accent-soft));
}
.isis-grid__row.is-active:hover {
    background: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 18%, var(--isis-surface));
}
.isis-grid__row > div {
    padding: 0.35rem 0.35rem;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* ── Motion fonctionnel (pilote gesproj 2026-07-26) ─────────────────────────
   Deux signaux d'état, jamais décoratifs :
   1. `.is-flash` — « cette ligne vient d'être modifiée » : teinte succès qui
      s'estompe après une action de workflow réussie (posée par la VM, retirée
      après l'animation). Pas de fill-mode : le fond redevient géré par les
      règles hover/active dès la fin.
   2. `.isis-grid--enter` — « les données sont arrivées » : les lignes fondent
      en place à leur insertion (après le skeleton). Nécessite @key sur les
      rows pour que la pagination recrée les éléments. */
.isis-grid--enter .isis-grid__row {
    animation: isis-grid-row-in var(--isis-motion-enter) backwards;
}
/* Stagger léger sur les premières lignes visibles (head = 1er enfant → rows à
   partir de nth-child(2)). Les lignes suivantes partagent le DERNIER délai
   (n+6 = 100ms) : sans ça, la ligne sans délai sous la dernière ligne retardée
   se stabiliserait AVANT celle du dessus — inversion de l'ordre visuel. */
.isis-grid--enter .isis-grid__row:nth-child(3)    { animation-delay: 25ms; }
.isis-grid--enter .isis-grid__row:nth-child(4)    { animation-delay: 50ms; }
.isis-grid--enter .isis-grid__row:nth-child(5)    { animation-delay: 75ms; }
.isis-grid--enter .isis-grid__row:nth-child(n+6)  { animation-delay: 100ms; }
@keyframes isis-grid-row-in {
    from { opacity: 0; transform: translateY(3px); }
    to   { opacity: 1; transform: translateY(0); }
}
/* Déclaré APRÈS les règles --enter : à spécificité égale, le flash doit gagner
   quand une row cumule entrée + flash (retour d'action → la ligne est déjà
   visible, le signal utile est le succès).
   Box-shadow inset (pas background-color) : la ligne flashée est presque
   toujours la ligne sélectionnée (is-active, fond teinté module) — un overlay
   qui se termine à transparent laisse ce fond intact dessous et évite le saut
   de couleur en fin d'animation qu'aurait un background animé sans fill. */
.isis-grid__row.is-flash {
    animation: isis-row-flash-success 1100ms ease-out;
}
@keyframes isis-row-flash-success {
    0%   { box-shadow: inset 0 0 0 100vmax color-mix(in srgb, var(--isis-success) 22%, transparent); }
    35%  { box-shadow: inset 0 0 0 100vmax color-mix(in srgb, var(--isis-success) 18%, transparent); }
    100% { box-shadow: inset 0 0 0 100vmax transparent; }
}
@media (prefers-reduced-motion: reduce) {
    .isis-grid__row.is-flash { animation: none; box-shadow: inset 0 0 0 100vmax color-mix(in srgb, var(--isis-success) 14%, transparent); }
    .isis-grid--enter .isis-grid__row { animation: none; }
}

/* Status dot */
.isis-grid__col-status {
    display: flex !important;
    justify-content: center;
    align-items: center;
    padding: 0 !important;
}
.isis-grid__status-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    display: inline-block;
    /* Anneau sombre fin pour remonter le contraste (~4.5:1) sur les
       variantes claires (is-ready, is-pending) — sinon un daltonien ne
       perçoit qu'une pastille pastel à peine distincte du fond. */
    box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.18);
}
.isis-grid__status-dot.is-client      { background: #10b981; }
.isis-grid__status-dot.is-prospect    { background: #3b82f6; }
.isis-grid__status-dot.is-fournisseur { background: #f59e0b; }
.isis-grid__status-dot.is-partenaire  { background: var(--isis-violet); }
.isis-grid__status-dot.is-inactif     { background: #9ca3af; }

/* Badges multi-facettes affichés dans la colonne dédiée + en tête du sidepanel
   tiers (migration 0096). Un tiers peut cumuler plusieurs badges. */
.isis-tiers-facets {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem;
    align-items: center;
}
.isis-tiers-facets__badge {
    display: inline-flex;
    align-items: center;
    padding: 0.1rem 0.45rem;
    font-size: 0.68rem;
    font-weight: 500;
    line-height: 1.5;
    border-radius: var(--isis-radius-pill);
    border: 1px solid var(--isis-border);
    background: var(--isis-surface-alt);
    color: var(--isis-text);
}
.isis-tiers-facets__badge.is-client      { border-color: #10b981; color: #047857; background: rgba(16, 185, 129, 0.08); }
.isis-tiers-facets__badge.is-prospect    { border-color: #3b82f6; color: #1d4ed8; background: rgba(59, 130, 246, 0.08); }
.isis-tiers-facets__badge.is-fournisseur { border-color: #f59e0b; color: #8f5700; background: rgba(245, 158, 11, 0.10); }
.isis-tiers-facets__badge.is-partenaire  { border-color: var(--isis-violet); color: var(--isis-violet-strong); background: color-mix(in srgb, var(--isis-violet) 10%, transparent); }
.isis-tiers-facets__badge.is-inactif     { border-color: var(--isis-border); color: var(--isis-text-muted); background: var(--isis-surface-alt); }
/* Fiscal (tâche 9) : Dérogé et Incomplet sont rendus mutuellement exclusifs côté page. */
.isis-tiers-facets__badge.is-deroge          { border-color: var(--isis-info); color: var(--isis-info-text); background: var(--isis-info-soft); }
.isis-tiers-facets__badge.is-incomplet-fiscal { border-color: var(--isis-warning); color: var(--isis-warning-text); background: var(--isis-warning-soft); }
.isis-tiers-facets__badge.is-a-qualifier     { border-color: var(--isis-success); color: var(--isis-success-text); background: var(--isis-success-soft); }
/* Pastille unique des signaux de qualité (dossier, fiscal, à qualifier) : le détail est au
   survol et au focus, la ligne de grille reste sur une hauteur. */
.isis-tiers-facets__qualite { cursor: help; white-space: nowrap; }
.isis-tiers-facets__qualite:focus-visible { outline: 2px solid var(--isis-current-mod); outline-offset: 2px; }
/* Variantes GED documents :
   ready    = vert  (PDF natif ou image, lecture immédiate)
   pending  = bleu  (preview en cours de génération côté Office)
   failed   = orange (preview a échoué, fichier toujours téléchargeable)
   archived = gris  (document marqué archivé) */
.isis-grid__status-dot.is-ready    { background: var(--isis-success); }
.isis-grid__status-dot.is-pending  { background: #3b82f6; }
.isis-grid__status-dot.is-failed   { background: #f59e0b; }
/* Gris d'archive porté par --isis-text-muted : ≥ 3:1 contre la surface (WCAG 1.4.11), ce que
   l'ancien #9ca3af ne tenait pas. */
.isis-grid__status-dot.is-archived { background: var(--isis-text-muted); }

/* Styles partagés grille documents GED (explorateur + liste) */
.isis-grid__col-doc-name { display: flex; align-items: center; gap: 0.4rem; min-width: 0; }
.isis-grid__exp-tag {
    flex-shrink: 0;
    display: inline-flex; align-items: center;
    padding: 0.05rem 0.4rem;
    font-size: 0.62rem; font-weight: 600;
    text-transform: uppercase; letter-spacing: 0.05em;
    border-radius: 3px;
}
.isis-grid__exp-tag.is-expired  { background: var(--isis-danger-soft,  #fbeaea); color: var(--isis-danger,  #dc2626); }
.isis-grid__exp-tag.is-expiring { background: var(--isis-warning-soft, #fef3c7); color: var(--isis-warning, #d97706); }
.isis-grid__col-size, .isis-grid__col-version {
    text-align: right; font-variant-numeric: tabular-nums;
    color: var(--isis-text-muted); font-size: 0.78rem;
}
.isis-grid__col-date { color: var(--isis-text-muted); font-size: 0.78rem; }
.isis-grid__module-tag {
    display: inline-flex;
    align-items: center;
    padding: 0.1rem 0.45rem;
    border-radius: 4px;
    font-size: 0.7rem;
    font-weight: 600;
    letter-spacing: 0.02em;
    text-transform: uppercase;
    background: var(--isis-surface-alt);
    color: var(--isis-text-muted);
}
.isis-grid__module-tag.mod-gescom    { background: var(--isis-mod-gescom-soft);    color: var(--isis-mod-gescom); }
.isis-grid__module-tag.mod-gescompta { background: var(--isis-mod-gescompta-soft); color: var(--isis-mod-gescompta); }
.isis-grid__module-tag.mod-sirh      { background: var(--isis-mod-sirh-soft);      color: var(--isis-mod-sirh); }
.isis-grid__module-tag.mod-admin     { background: var(--isis-mod-admin-soft);     color: var(--isis-mod-admin); }
.isis-grid__module-tag.mod-ged       { background: var(--isis-accent-soft);        color: var(--isis-accent); }
.isis-grid__module-tag.mod-gesproj   { background: var(--isis-mod-gesproj-soft);   color: var(--isis-mod-gesproj); }
.isis-grid__module-tag.mod-gesmaff   { background: var(--isis-mod-gesmaff-soft);   color: var(--isis-mod-gesmaff); }
.isis-grid__module-tag.mod-gesst     { background: var(--isis-mod-gesst-soft);     color: var(--isis-mod-gesst); }
.isis-grid__module-tag.mod-gesmat    { background: var(--isis-mod-gesmat-soft);    color: var(--isis-mod-gesmat); }
.isis-grid__module-tag.mod-gespark   { background: var(--isis-mod-gespark-soft);   color: var(--isis-mod-gespark); }
.isis-grid__module-tag.mod-gesinfo   { background: var(--isis-mod-gesinfo-soft);   color: var(--isis-mod-gesinfo); }
.isis-grid__module-tag.mod-gesmob    { background: var(--isis-mod-gesmob-soft);    color: var(--isis-mod-gesmob); }
.isis-grid__module-tag.mod-gesfac    { background: var(--isis-mod-gesfac-soft);    color: var(--isis-mod-gesfac); }
.isis-grid__module-tag.mod-gespla    { background: var(--isis-mod-gespla-soft);    color: var(--isis-mod-gespla); }
.isis-grid__module-tag.mod-gesqhse   { background: var(--isis-mod-gesqhse-soft);   color: var(--isis-mod-gesqhse); }
.isis-grid__module-tag.mod-monespace { background: var(--isis-mod-monespace-soft); color: var(--isis-mod-monespace); }

/* Badge Type — plus compact dans la grille */
.isis-grid__row .rz-badge {
    font-size: 0.65rem !important;
    padding: 0.15rem 0.5rem !important;
    line-height: 1.4 !important;
    letter-spacing: 0.02em;
    font-weight: 600 !important;
}

/* Cells particulières */
.isis-grid__col-code {
    font-family: var(--isis-font-mono, ui-monospace, monospace);
    font-size: 0.8rem;
    color: var(--isis-text);
    font-weight: 500;
}
.isis-grid__row.is-active .isis-grid__col-code { color: var(--isis-current-mod, var(--isis-accent)); }
.isis-grid__col-raison { font-weight: 500; color: var(--isis-text); }
.isis-grid__col-email,
.isis-grid__col-phone,
.isis-grid__col-ville { color: var(--isis-text-muted); }

/* Cell empty state placeholder */
.isis-grid__cell-empty {
    color: var(--isis-text-soft);
    font-style: italic;
}

/* Actions cell */
.isis-grid__col-actions {
    display: flex !important;
    justify-content: flex-end;
    /* 16px, pas 4 : 28px de bouton + 44px de cible de clic (cf. .isis-grid__action-btn
       plus bas) veut dire que la cible déborde de 8px de chaque côté du bouton visible.
       À 4px d'écart, les cibles de deux boutons voisins se chevauchaient de 12px — un
       clic à la frontière aurait pu activer l'un ou l'autre selon l'ordre du DOM. 16px
       d'entraxe (8+8) les fait juste se toucher sans mordre — même chiffre que
       .isis-grid--vehrh, qui avait déjà résolu ce problème localement (cf. plus haut). */
    gap: 1rem;
    padding: 0 !important;
    /* Sans ceci, hérite overflow:hidden de `.isis-grid__row > div` — la cible de clic
       étendue de .isis-grid__action-btn (cf. plus bas) serait rognée à la taille du
       bouton, exactement le symptôme qui cantonnait le correctif à .isis-grid--vehrh. */
    overflow: visible !important;
}
/* Alias historique : ~90 pages posent `isis-grid__actions` au lieu de
   `isis-grid__col-actions`. La classe n'avait aucune règle de base — les cellules
   retombaient sur `.isis-grid__row > div` (block + padding + overflow:hidden), d'où
   des icônes collées à gauche et un dernier bouton parfois rogné (cf. commentaires
   des variantes --equipement et --echeancier, qui rustinaient le symptôme localement).
   Sélecteur enfant direct (0,2,0) plutôt que !important : bat `.isis-grid__row > div`
   (0,1,1) tout en laissant gagner les variantes `.isis-grid--x .isis-grid__actions`
   déclarées plus bas dans le fichier. */
.isis-grid__head > .isis-grid__actions,
.isis-grid__row > .isis-grid__actions {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 1rem; /* même raison que .isis-grid__col-actions ci-dessus (cibles 44px sans chevauchement) */
    padding: 0;
    overflow: visible;
}
/* Sous-groupe de boutons mutuellement exclusifs (ex. paire Conforme/Refusé de
   FluxCommandeActions, role="group") : un div nu est display:block, donc ce gap-là ne se
   propage pas à l'intérieur — les deux boutons ne gardaient que le blanc de mise en forme
   (~4px), pas les 16px des cibles 44px (revue de code, 2026-09-28). */
.isis-grid__action-group {
    display: flex;
    align-items: center;
    gap: 1rem;
}
/* Taille d'icône par défaut dans un bouton d'action de grille. 419 des 475
   RadzenIcon d'actions posent leur font-size en inline (qui gagne) ; les 56
   restantes tombaient sur le défaut Radzen — 24px dans un bouton de 28px, donc
   des icônes visiblement plus grosses d'une page à l'autre (constaté sur
   /gesproj/parametres/produits face à l'onglet Livraisons d'une commande).
   15px = valeur de l'onglet Livraisons, pris comme référence d'harmonisation. */
.isis-grid__action-btn .rzi {
    font-size: 15px;
}
.isis-grid__action-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    border: none;
    background: transparent;
    border-radius: 6px;
    color: var(--isis-text-muted);
    cursor: pointer;
    transition: background-color 120ms ease, color 120ms ease;
    position: relative;
}
/* DESIGN.md §5 « Responsive » impose 44×44 sur les boutons d'action. Généralisé le
   2026-09-15 depuis .isis-grid--vehrh (ancienne portée volontairement locale, cf.
   l'historique juste en-dessous dans cette feuille) après un audit chiffrant le motif à
   ~209 fichiers .razor sur cette seule classe : le bouton garde ses 28px (chrome de
   grille inchangé) ; seule la CIBLE s'étend, par un pseudo-élément — un <button> n'est
   pas un élément remplacé, ::after y génère bien une boîte (contrairement à un <input>).
   `.isis-grid__row` porte déjà `min-height: 44px` (plus haut dans cette feuille) : les
   44px verticaux du pseudo-élément ne débordent donc pas sur les lignes voisines. */
.isis-grid__action-btn::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: 44px;
    height: 44px;
    transform: translate(-50%, -50%);
}
.isis-grid__action-btn:hover {
    background: var(--isis-surface);
    color: var(--isis-text);
}
.isis-grid__action-btn:focus-visible {
    outline: 2px solid var(--isis-accent);
    outline-offset: 1px;
    color: var(--isis-text);
}
/* aria-disabled : même défaut que .isis-rich-toolbar__btn[aria-disabled] ci-dessus — le
   bouton d'action de ligne (ex. Supprimer un type système) reste atteignable au clavier,
   avec sa raison au title, plutôt que sorti de l'ordre de tabulation par l'attribut disabled. */
.isis-grid__action-btn[aria-disabled="true"] {
    opacity: 0.4;
    cursor: not-allowed;
}
.isis-grid__action-btn[aria-disabled="true"]:hover {
    background: transparent;
    color: var(--isis-text-muted);
}
.isis-grid__row:focus-visible {
    /* Outline = couleur du module courant (fallback --isis-accent sur les pages
       sans .mod-{code} parent). Identité visuelle cohérente cross-module. */
    outline: 2px solid var(--isis-current-mod);
    outline-offset: -2px;
}

/* Empty state global (aucune donnée filtrée) */
.isis-grid__empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    padding: 3rem 1rem;
    color: var(--isis-text-soft);
    text-align: center;
}
.isis-grid__empty .rzi {
    font-size: 32px;
    opacity: 0.4;
}

/* Variante --welcome : empty state riche pour tenant vierge (onboarding 1re fois).
   Icône large + paragraphe + CTAs + tips list. */
.isis-grid__empty--welcome {
    padding: 4rem 2rem;
    gap: 0.85rem;
    max-width: 560px;
    margin: 0 auto;
}
.isis-grid__empty--welcome strong {
    font-size: 1.15rem;
    color: var(--isis-text);
    margin-top: 0.5rem;
}
.isis-grid__empty-hint {
    color: var(--isis-text-muted);
    font-size: 0.85rem;
    line-height: 1.5;
    margin: 0;
}
.isis-grid__empty-actions {
    display: flex;
    gap: 0.6rem;
    margin-top: 0.5rem;
    flex-wrap: wrap;
    justify-content: center;
}
/* IsisEmptySearchEscape — l'issue d'un écran vide quand une recherche est active. La phrase
   nomme le terme et le périmètre ; les actions reprennent la géométrie de
   .isis-grid__empty-actions, dont ce bloc est un cousin posé DANS l'état vide. */
.isis-empty-escape__phrase {
    max-width: 46ch;
}
.isis-empty-escape__phrase strong {
    color: var(--isis-text);
    font-weight: 600;
}
.isis-empty-escape__actions {
    display: flex;
    gap: 0.6rem;
    margin-top: 0.5rem;
    flex-wrap: wrap;
    justify-content: center;
    align-items: center;
}
.isis-grid__empty-tips {
    list-style: none;
    margin: 1rem 0 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    text-align: left;
    width: 100%;
    max-width: 460px;
    font-size: 0.82rem;
    color: var(--isis-text);
}
.isis-grid__empty-tips li {
    display: flex;
    align-items: flex-start;
    gap: 0.45rem;
    line-height: 1.45;
}

/* N1.3 — Saved views dialog */
.isis-saved-views__capture {
    display: flex;
    gap: 0.5rem;
    align-items: center;
}
.isis-saved-views__capture .rz-textbox {
    flex: 1;
}
.isis-saved-views__fav-toggle {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    margin-top: 0.5rem;
    font-size: 0.8rem;
    color: var(--isis-text-muted);
    cursor: pointer;
    user-select: none;
}
.isis-saved-views__empty {
    padding: 1rem;
    text-align: center;
    color: var(--isis-text-muted);
    font-size: 0.85rem;
    border: 1px dashed var(--isis-border);
    border-radius: 4px;
}
.isis-saved-views__list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
}
.isis-saved-views__item {
    display: grid;
    grid-template-columns: 32px 1fr 32px;
    align-items: center;
    gap: 0.4rem;
    padding: 0.4rem 0.55rem;
    border: 1px solid var(--isis-border);
    border-radius: 4px;
    background: var(--isis-surface);
    transition: background 120ms ease, border-color 120ms ease;
}
.isis-saved-views__item:hover {
    background: var(--isis-surface-alt);
    border-color: color-mix(in srgb, var(--isis-text) 15%, var(--isis-border));
}
.isis-saved-views__star,
.isis-saved-views__delete {
    background: none;
    border: 0;
    cursor: pointer;
    padding: 4px;
    border-radius: 4px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
.isis-saved-views__star:hover,
.isis-saved-views__delete:hover {
    background: color-mix(in srgb, var(--isis-text) 8%, transparent);
}
.isis-saved-views__name {
    flex: 1;
    background: none;
    border: 0;
    text-align: left;
    cursor: pointer;
    padding: 0;
    font-family: inherit;
    display: flex;
    flex-direction: column;
    gap: 0.1rem;
    min-width: 0;
}
.isis-saved-views__name-label {
    font-weight: 600;
    font-size: 0.9rem;
    color: var(--isis-text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.isis-saved-views__name-notes {
    font-size: 0.75rem;
    color: var(--isis-text-muted);
    font-style: italic;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Badge dans le bouton Vues du toolbar (nom de la vue active). */
.isis-rich-toolbar__btn-badge {
    display: inline-flex;
    align-items: center;
    padding: 0.1rem 0.4rem;
    margin-left: 0.4rem;
    background: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 14%, transparent);
    color: var(--isis-current-mod, var(--isis-accent));
    border-radius: var(--isis-radius-pill);
    font-size: 0.7rem;
    font-weight: 600;
    max-width: 140px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* ── Pied de grille : pagination ─────────────────────────────────────────── */
.isis-grid__foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    padding: 0.5rem 0.85rem;
    border-top: 1px solid var(--isis-border);
    background: var(--isis-surface-alt);
    font-size: 0.78rem;
    color: var(--isis-text-muted);
    position: sticky;
    bottom: 0;
    z-index: 3;
    flex-wrap: wrap;
}
.isis-grid__foot-count {
    display: flex;
    gap: 0.4rem;
    align-items: baseline;
    font-variant-numeric: tabular-nums;
}
.isis-grid__foot-hint { color: var(--isis-text-soft); font-size: 0.72rem; }
/* Totaux PAR DEVISE en pied de grille — la place d'un cumul qu'un bandeau retiré laissait
   orphelin sur une vue sans pagineur ni facette : c'est sous les lignes qu'on lit un total.
   Une ligne par devise, sans conversion (ISIS n'en fait pas en V1) : additionner des euros et
   des francs CFA donnerait un nombre faux. */
.isis-grid__foot-label {
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}
.isis-grid__foot-totaux {
    display: inline-flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 0.35rem 1.1rem;
    margin-left: auto;
}
.isis-grid__foot-total { display: inline-flex; align-items: baseline; gap: 0.3rem; }
.isis-grid__foot-total-v {
    font-family: var(--isis-font-mono);
    font-variant-numeric: tabular-nums;
    font-weight: 600;
    color: var(--isis-text);
}
.isis-grid__foot-total-k {
    font-size: 0.68rem;
    font-weight: 600;
    letter-spacing: 0.05em;
    color: var(--isis-text-soft);
}
.isis-grid__foot-pager {
    display: flex;
    align-items: center;
    gap: 0.2rem;
}
.isis-grid__foot-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px; height: 28px;
    border: 1px solid transparent;
    background: transparent;
    border-radius: 4px;
    color: var(--isis-text-muted);
    cursor: pointer;
    transition: background-color 120ms ease, color 120ms ease, border-color 120ms ease;
}
.isis-grid__foot-btn:hover:not(:disabled) {
    background: var(--isis-surface);
    color: var(--isis-text);
    border-color: var(--isis-border);
}
.isis-grid__foot-btn:focus-visible {
    outline: 2px solid var(--isis-accent);
    outline-offset: 1px;
}
.isis-grid__foot-btn:disabled {
    opacity: 0.35;
    cursor: not-allowed;
}
.isis-grid__foot-current {
    padding: 0 0.6rem;
    font-weight: 500;
    color: var(--isis-text);
    font-variant-numeric: tabular-nums;
    min-width: 110px;
    text-align: center;
}
.isis-grid__foot-pagesize {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    font-size: 0.72rem;
    color: var(--isis-text-soft);
}
.isis-grid__foot-pagesize select {
    border: 1px solid var(--isis-border);
    border-radius: 4px;
    background: var(--isis-surface);
    padding: 0.2rem 0.4rem;
    font-size: 0.78rem;
    color: var(--isis-text);
    cursor: pointer;
}
.isis-grid__foot-pagesize select:focus-visible {
    outline: 2px solid var(--isis-accent);
    outline-offset: 1px;
}
/* Cellule d'un pied rendu en ligne (IsisGridPager InTable) : même alignement qu'avant. */
.isis-grid__foot-cell { display: flex; align-items: center; }

/* ============================================================================
   .isis-detail-grid — Grille compacte label/value pour fiches détail
   ----------------------------------------------------------------------------
   Pattern dense : label gauche court + value droite, gap minimal, font 0.85rem.
   Pose sur un container où chaque "field" est wrappé par un div display:contents
   (pour que les 2 sous-divs deviennent enfants directs de la grille).
   ============================================================================ */
.isis-detail-grid {
    display: grid;
    grid-template-columns: max-content 1fr;
    gap: 0.35rem 0.85rem;
    font-size: 0.85rem;
    align-items: baseline;
}
/* Séparateur de sous-bloc dans une grille de détail (« — Coûts & marge — »,
   « — Structures prêteuses — »…). La classe était utilisée dans le markup sans
   jamais avoir été définie : les séparateurs se rendaient en label ordinaire et
   le regroupement logique des sections était visuellement inexistant.
   `grid-column: 1 / -1` occupe la pleine largeur — le <dd></dd> vide qui suivait
   chaque séparateur pour ne pas décaler la grille devient inutile. */
/* Ligne de SOMME d'une grille de détail — à ne pas confondre avec .isis-cost-sep, qui est un
   titre de section pleine largeur (grid-column: 1 / -1). Une somme reste sur deux colonnes,
   sans quoi sa valeur repart en colonne 1 et le libellé suivant vient se placer à côté d'elle. */
.isis-detail-grid dt.isis-cost-total,
.isis-detail-grid dd.isis-cost-total {
    margin-top: 0.35rem;
    padding-top: 0.35rem;
    border-top: 1px solid var(--isis-border);
    font-weight: 600;
}

.isis-detail-grid dt.isis-cost-sep {
    grid-column: 1 / -1;
    margin-top: 0.6rem;
    padding-top: 0.4rem;
    border-top: 1px solid var(--isis-border-soft);
    font-size: 0.7rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--isis-text-soft);
}
/* Répartition du visa sous la ligne de main-d'œuvre : sous-ligne DESCRIPTIVE, jamais un
   second total. D'où la taille réduite et la couleur atténuée — la valeur qui compte reste
   celle du dessus. Seule la part contestée sort du gris, via le pill --warning du markup :
   c'est la seule qui appelle une action. */
.isis-visa-split {
    display: flex;
    align-items: center;
    gap: 0.15rem 0.5rem;
    flex-wrap: wrap;
    margin-top: 0.3rem;
    font-size: 0.72rem;
    color: var(--isis-text-muted);
    font-variant-numeric: tabular-nums;
}

.isis-visa-split__lbl {
    font-size: 0.64rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--isis-text-soft);
}

.isis-visa-split__flag {
    font-size: 0.66rem;
}

/* Quatrième poste : les heures encore en saisie. Les trois autres décomposent le montant du
   dessus ; celui-ci n'y est PAS. Il porte donc un contour pointillé — un signal de forme, lisible
   sans la couleur (WCAG 1.4.1) — plutôt qu'une nuance de gris de plus, qui l'aurait rangé avec
   « visé » et « en attente » alors qu'il n'est pas de la même nature. */
.isis-visa-split__part--saisie {
    border: 1px dashed var(--isis-text-soft);
    border-radius: var(--isis-radius-pill);
    padding: 0.02rem 0.4rem;
    font-size: 0.68rem;
}

.isis-visa-split__link {
    border: 0;
    background: transparent;
    padding: 0;
    font: inherit;
    color: var(--isis-current-mod, var(--isis-accent));
    text-decoration: underline;
    text-underline-offset: 2px;
    cursor: pointer;
}

.isis-visa-split__link:hover { text-decoration-thickness: 2px; }

.isis-visa-split__link:focus-visible {
    outline: 2px solid color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 55%, transparent);
    outline-offset: 2px;
    border-radius: var(--isis-radius-sm);
}

/* Valeur propre d'un nœud d'arbre, affichée à côté de la valeur consolidée. */
.isis-detail-grid__own {
    color: var(--isis-text-muted);
    margin-left: 0.5rem;
}
.isis-detail-grid dd.is-warm { color: var(--isis-accent-strong); }

/* Sections repliables « expert » (<details>/<summary>) — lisibilité + focus visible clavier. */
details > summary.isis-expert-summary,
details > summary { cursor: pointer; }
details > summary:focus-visible { outline: 2px solid var(--isis-current-mod, var(--isis-accent)); outline-offset: 2px; border-radius: 4px; }
.isis-expert-summary { font-size: 0.82rem; color: var(--isis-text-muted); font-weight: 500; }
.isis-expert-summary:hover { color: var(--isis-text); }
/* Arbre de consolidation du CA. La hiérarchie est portée par des <ul>/<li> imbriqués
   (role=tree/treeitem + aria-level) : l'indentation n'est qu'un renfort visuel, jamais
   le seul véhicule de l'information (WCAG 1.3.1). */
.isis-ca-tree__title {
    margin-top: 0.6rem;
    padding-top: 0.4rem;
    border-top: 1px solid var(--isis-border-soft);
    font-size: 0.7rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--isis-text-soft);
}
.isis-ca-tree,
.isis-ca-tree__group {
    list-style: none;
    margin: 0;
    padding: 0;
}
.isis-ca-tree__group {
    padding-left: 1.1rem;
    border-left: 1px solid var(--isis-border-soft);
    margin-left: 0.35rem;
}
.isis-ca-tree__row {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.35rem 0.85rem;
    padding: 0.15rem 0;
    font-size: 0.85rem;
}
.isis-ca-tree__nom {
    min-width: 12rem;
    flex: 0 1 auto;
}
.isis-ca-tree__val {
    flex: 1 1 auto;
}
/* Bloc géolocalisation sous la carte Coordonnées (bouton « Localiser » + statut). */
.isis-detail-geo {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    flex-wrap: wrap;
    margin-top: 0.75rem;
}
.isis-detail-geo__status {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    font-size: 0.8rem;
    color: var(--isis-text);
}
.isis-detail-geo__status--muted {
    color: var(--isis-text-muted);
}
.isis-detail-grid__label {
    color: var(--isis-text-soft);
    font-size: 0.72rem;
    white-space: nowrap;
}
.isis-detail-grid__val {
    color: var(--isis-text);
    /* break-word (et NON anywhere) : `anywhere` réduit la taille min-content de la
       valeur à 1 caractère → en contexte contraint (summary 4 colonnes à côté d'un
       sidepanel), la piste 1fr s'effondre et le texte se casse lettre par lettre
       (« SGI Inge nieri e SA »). break-word garde le mot entier pour le calcul de
       largeur mini, ne coupe qu'un token vraiment trop long en dernier recours. */
    overflow-wrap: break-word;
}
.isis-detail-grid__val--mono {
    font-family: var(--isis-font-mono, ui-monospace, monospace);
    font-size: 0.82rem;
}
.isis-detail-grid__val--empty {
    color: var(--isis-text-soft);
    font-style: italic;
}
/* Sévérité d'une valeur de detail-grid — même idiome que .isis-kpi-card__value.is-success/
   is-danger (tokens uniquement, pas de hex). Sert PlatformHealthPage (« Chaînes en clair »). */
.isis-detail-grid__val.is-success { color: var(--isis-success); font-weight: 600; }
.isis-detail-grid__val.is-danger  { color: var(--isis-danger); font-weight: 600; }
/* Valeur libre potentiellement très longue (titre d'offre saisi comme un descriptif) :
   2 lignes puis « … ». -webkit-line-clamp est la seule troncature multi-ligne réellement
   portée par les navigateurs cibles ; le trio display/-webkit-box-orient/overflow est
   indissociable. Le texte entier reste exposé par l'attribut `title` posé côté page —
   sans lui, la troncature perdrait de l'information au lieu de la replier. */
.isis-detail-grid__val--clamp2 {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    overflow: hidden;
}
/* Champ éditable posé dans une colonne de summary (rich-page). Les classes
   .field / .label / .helper vivent sous .isis-form-linear et n'ont donc aucun
   style ici — d'où cette déclinaison, alignée sur les mêmes tokens. */
.isis-detail-field {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
    max-width: 420px;
}
.isis-detail-field__help {
    color: var(--isis-text-soft);
    font-size: 0.72rem;
    line-height: 1.45;
}
/* Valeur cliquable (navigation onglet depuis la summary card). Bouton plat
   avec underline subtile + couleur accent au hover/focus. */
.isis-detail-grid__val-link {
    background: transparent;
    border: none;
    padding: 0;
    color: var(--isis-text);
    font: inherit;
    text-decoration: underline;
    text-decoration-thickness: 1px;
    text-underline-offset: 2px;
    text-decoration-color: var(--isis-border);
    cursor: pointer;
    transition: color 100ms ease, text-decoration-color 100ms ease;
}
.isis-detail-grid__val-link:hover,
.isis-detail-grid__val-link:focus-visible {
    color: var(--isis-accent);
    text-decoration-color: var(--isis-accent);
    outline: none;
}
.isis-detail-grid__val-link:focus-visible {
    outline: 2px solid var(--isis-accent);
    outline-offset: 2px;
    border-radius: 2px;
}

/* Carte « Déclarations reçues » actionnable (lot 4, TiersDetail.razor) — un
   champ déclaré non arbitré + son bouton « Reprendre » sur la même ligne
   (le champ vient de RenderField() en display:contents : ses 2 divs label/valeur
   deviennent enfants flex directs, d'où le ciblage de .isis-detail-grid__val
   pour qu'elle absorbe l'espace et pousse le bouton à droite). Sous la liste,
   la barre d'actions de verdict (Traitée / Rejeter). */
.isis-decl-field {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 0.6rem;
    padding: 0.3rem 0;
}
.isis-decl-field .isis-detail-grid__val {
    flex: 1 1 200px;
}
.isis-decl-actions {
    display: flex;
    gap: 0.5rem;
    flex-wrap: wrap;
    margin-top: 0.75rem;
}
/* Valeur marge colorée — vert/rouge (mêmes teintes que les autres marges du module). */
.isis-detail-grid__val--pos {
    color: #16a34a;
    font-weight: 600;
}
.isis-detail-grid__val--neg {
    color: #c62828;
    font-weight: 600;
}

/* ----------------------------------------------------------------------------
   .isis-detail-grid variante « multi-cartes » — quand .isis-detail-grid
   contient des .isis-detail-grid__card en enfants directs, on bascule sur
   une grille auto-fit responsive de cartes élevées (Branded depth §1).
   Permet de regrouper plusieurs blocs `<dl>` côte à côte dans un onglet
   de fiche détail (identité / classification / valorisation / métadonnées…).
   ---------------------------------------------------------------------------- */
.isis-detail-grid:has(> .isis-detail-grid__card) {
    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
    gap: 1rem;
    align-items: stretch;
}
.isis-detail-grid__card {
    background: var(--isis-surface, #ffffff);
    border: 1px solid var(--isis-border-soft, #f1f2f5);
    border-radius: 8px;
    padding: 0.9rem 1rem;
    box-shadow: var(--isis-elevation-1);
    display: flex;
    flex-direction: column;
    gap: 0.65rem;
    min-width: 0;
}
.isis-detail-grid__card-title {
    margin: 0;
    font-size: 0.7rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--isis-text-soft);
}
.isis-detail-grid__dl {
    margin: 0;
    display: grid;
    grid-template-columns: max-content 1fr;
    gap: 0.4rem 0.85rem;
    font-size: 0.85rem;
    align-items: baseline;
}
.isis-detail-grid__dl > dt {
    color: var(--isis-text-soft);
    font-size: 0.72rem;
    white-space: nowrap;
}
.isis-detail-grid__dl > dd {
    margin: 0;
    color: var(--isis-text);
    overflow-wrap: anywhere;
}

/* Aide contextuelle sous une colonne du rail de synthèse (ex. coût non renseigné). */
.isis-detail-summary__hint {
    margin-top: 0.4rem;
    font-size: 0.7rem;
    line-height: 1.35;
    color: var(--isis-text-soft);
}

/* Carte détail compacte — 4 colonnes côte à côte (Identité / Client / Montants /
   Rentabilité prévisionnelle), séparateurs verticaux subtils. */
.isis-detail-summary {
    display: grid;
    grid-template-columns: 5fr 3fr 4fr 4fr;
    gap: 1.5rem;
}
@media (max-width: 1100px) {
    /* Sous 1100px : 2×2 pour éviter des colonnes trop étroites. Séparateurs
       verticaux retirés (le gap suffit) — sinon bordure parasite en début de
       2e rangée. */
    .isis-detail-summary {
        grid-template-columns: 1fr 1fr;
    }
    .isis-detail-summary__col + .isis-detail-summary__col {
        border-left: none;
        padding-left: 0;
        margin-left: 0;
    }
}
.isis-detail-summary__col {
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
    min-width: 0;
}
.isis-detail-summary__col + .isis-detail-summary__col {
    border-left: 1px solid var(--isis-border-soft, #f1f2f5);
    padding-left: 1.5rem;
    margin-left: -0.75rem;
}
.isis-detail-summary__title {
    font-size: 0.65rem;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--isis-text-soft);
}
.isis-detail-summary__meta {
    margin-top: 0.85rem;
    padding-top: 0.65rem;
    border-top: 1px solid var(--isis-border-soft, #f1f2f5);
    display: flex;
    flex-wrap: wrap;
    gap: 0.85rem;
    font-size: 0.72rem;
    color: var(--isis-text-soft);
}
.isis-detail-summary__meta strong {
    color: var(--isis-text-muted);
    font-weight: 500;
}

@media (max-width: 900px) {
    .isis-detail-summary {
        grid-template-columns: 1fr;
    }
    .isis-detail-summary__col + .isis-detail-summary__col {
        border-left: none;
        padding-left: 0;
        margin-left: 0;
        border-top: 1px solid var(--isis-border-soft, #f1f2f5);
        padding-top: 1rem;
        margin-top: 0.25rem;
    }
}

/* Variante « fluide » : colonnes qui se replient selon la largeur RÉELLE du
   conteneur, pas selon le viewport. À poser quand la carte summary vit dans une
   colonne étroite — typiquement une zone principale à côté d'un sidepanel
   de 480px : à 1440px de viewport aucun breakpoint media ne se déclenche alors
   que la carte ne fait que ~650px, d'où 4 colonnes écrasées et des valeurs qui
   débordent sur la colonne voisine (« Ingénierie » chevauchant « TVA »). auto-fit
   replie proprement à 3 puis 2 puis 1 colonne selon la place disponible. */
/* Plancher relevé de 185 à 240px le 2026-08-11 : à 1024px — le viewport que DESIGN.md
   §5 déclare prioritaire (« Tablette en priorité ») — 185px laissait tenir 3 pistes de
   ~193px, où « 12 222 222,00 EUR » se repliait sur deux lignes, comme « Jean KOUAMÉ » et
   « ABC Logistique ». Les trois colonnes se repliant différemment, les lignes cessaient
   de s'aligner : la synthèse se lisait en colonnes indépendantes, plus en grille. 240px
   = libellé (~110px) + le montant le plus long (~130px). */
.isis-detail-summary--fluid {
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
}
/* Séparateurs verticaux retirés : avec le repli multi-lignes, le `+` collerait un
   filet parasite en tête de 2e rangée. Le gap suffit à séparer.
   Les trois propriétés `*-top` sont neutralisées pour la même raison (2026-08-11) :
   le bloc `@media (max-width: 900px)` ci-dessus pose un `border-top` + décalage sur
   `col + col`, écrit pour l'empilement à 1 colonne qu'il impose au même moment. Mais
   `--fluid` reprend la main sur `grid-template-columns` (spécificité égale, déclaré
   plus bas) : sous 900px la grille reste multi-colonnes, et les colonnes 2 et 3
   héritaient d'un filet horizontal qui ne sépare rien et d'un décalage de ~27px qui
   cassait l'alignement des titres de colonne. */
.isis-detail-summary--fluid .isis-detail-summary__col + .isis-detail-summary__col {
    border-left: none;
    padding-left: 0;
    margin-left: 0;
    border-top: none;
    padding-top: 0;
    margin-top: 0;
}

/* ============================================================================
   .isis-detail-reason — encart texte libre (motif, commentaire) sous une
   .isis-detail-summary. Remplace 3 `style=` en dur (AbsenceDetail, 2026-09-04).
   ============================================================================ */
.isis-detail-reason { margin-top: 1rem; padding: 0.75rem; background: var(--isis-surface-alt); border-radius: var(--isis-radius-sm); }
.isis-detail-reason__label { font-size: 0.7rem; color: var(--isis-text-soft); text-transform: uppercase; letter-spacing: 0.06em; margin-bottom: 0.25rem; }
.isis-detail-reason__body { font-size: 0.88rem; }

/* ============================================================================
   .isis-tabs-clean — Style tabs inspiré NetLogger CommandDetailsV3
   ----------------------------------------------------------------------------
   Override Radzen RadzenTabs : container avec border-bottom 1px, tabs avec
   radius top, hover fond gris-très-clair, actif = couleur accent + weight 600
   + sous-ligne 2px via box-shadow inset (technique propre, pas une ombre).
   ============================================================================ */
.isis-tabs-clean .rz-tabview {
    border: none !important;
    box-shadow: none !important;
    background: transparent !important;
}
.isis-tabs-clean .rz-tabview-nav {
    background: transparent !important;
    border-bottom: 1px solid var(--isis-border) !important;
    margin: 0 0 1rem 0 !important;
    padding: 0 !important;
    display: flex !important;
    align-items: center;
    gap: 4px;
    list-style: none;
}
.isis-tabs-clean .rz-tabview-nav > li,
.isis-tabs-clean .rz-tabview-nav-item {
    margin: 0 !important;
    background: transparent !important;
    border: none !important;
}
.isis-tabs-clean .rz-tabview-nav-link,
.isis-tabs-clean .rz-tabview-nav-link.rz-state-default {
    padding: 10px 16px !important;
    font-size: 0.82rem !important;
    font-weight: 500 !important;
    font-family: inherit !important;
    color: var(--isis-text-muted) !important;
    background: transparent !important;
    border: none !important;
    border-radius: 6px 6px 0 0 !important;
    display: inline-flex !important;
    align-items: center;
    gap: 6px;
    cursor: pointer;
    transition: color 0.15s ease, background-color 0.15s ease, box-shadow 0.15s ease !important;
}
.isis-tabs-clean .rz-tabview-nav-link:hover {
    color: var(--isis-text) !important;
    background: var(--isis-surface-alt) !important;
}
.isis-tabs-clean .rz-tabview-selected .rz-tabview-nav-link,
.isis-tabs-clean li.rz-state-active .rz-tabview-nav-link,
.isis-tabs-clean .rz-tabview-nav-link.rz-state-active {
    color: var(--isis-current-mod, var(--isis-accent)) !important;
    font-weight: 600 !important;
    background: transparent !important;
    /* F10 — sous-ligne 3px via inset (chevauche la border-bottom 1px du container).
       Couleur module courant (au lieu de gescom hardcodé) pour cohérence cross-module. */
    box-shadow: inset 0 -3px 0 0 var(--isis-current-mod, var(--isis-accent)) !important;
}
.isis-tabs-clean .rz-tabview-nav-link .rz-icon,
.isis-tabs-clean .rz-tabview-nav-link .material-icons,
.isis-tabs-clean .rz-tabview-nav-link .notranslate {
    font-size: 16px !important;
    vertical-align: middle;
}
.isis-tabs-clean .rz-tabview-panels {
    padding: 0 !important;
    border: none !important;
    background: transparent !important;
}
.isis-tabs-clean .rz-tabview-panel { padding: 0 !important; }

/* ============================================================================
   .isis-tabs / .isis-tab — Tabs HTML custom (port direct NetLogger CommandDetailsV3)
   ----------------------------------------------------------------------------
   Pattern : container border-bottom 1px, boutons radius top, hover bg gris très
   clair, actif = couleur module + weight 600 + sous-ligne 2px via box-shadow
   inset (technique propre, pas une ombre portée).
   ============================================================================ */
.isis-tabs {
    border-bottom: 1px solid var(--isis-border);
    margin-bottom: 16px;
    display: flex;
    align-items: center;
    gap: 4px;
    flex-wrap: wrap;
    flex-shrink: 0;   /* la barre d'onglets reste fixe, c'est le panneau qui scrolle */
}
.isis-tab {
    background: transparent;
    border: 0;
    padding: 10px 16px;
    font-size: 13px;
    font-family: inherit;
    color: var(--isis-text-muted);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    border-radius: 6px 6px 0 0;
    position: relative;   /* ancre du souligné ::after de l'état actif */
    transition: color 0.15s ease, background-color 0.15s ease;
}
.isis-tab:hover {
    color: var(--isis-text);
    background: var(--isis-surface-soft);
}
.isis-tab.is-active {
    /* Couleur du module courant (var propagée par .isis-shell__content.mod-*),
       pas le bleu Gescom en dur — sinon l'onglet actif est bleu sur les pages SIRH. */
    color: var(--isis-current-mod, var(--isis-accent));
    font-weight: 600;
}
/* Souligné 3px en ::after (ex box-shadow inset, même rendu) : un pseudo-élément
   peut s'étirer (scaleX) à l'activation — micro-signal « cet onglet devient
   actif » (pilote motion 2026-07-26). Recréé à chaque changement d'onglet
   (l'état is-active change d'élément), donc l'animation rejoue naturellement. */
.isis-tab.is-active::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 3px;
    background: var(--isis-current-mod, var(--isis-accent));
    animation: isis-tab-underline-in var(--isis-motion-base) both;
}
@keyframes isis-tab-underline-in {
    from { transform: scaleX(0.4); opacity: 0.4; }
    to   { transform: scaleX(1);   opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
    .isis-tab.is-active::after { animation: none; }
}
.isis-tab:focus-visible {
    outline: 2px solid var(--isis-current-mod, var(--isis-accent));
    outline-offset: -2px;
    border-radius: 3px;
}
.isis-tab .rz-icon,
.isis-tab .material-icons,
.isis-tab .notranslate {
    font-size: 16px !important;
    vertical-align: middle;
}
.isis-tabs__spacer { flex: 1; }

/* ─────────────────────────────────────────────────────────────────────────
   .isis-focus-zone — wrapper Participants + Tabs avec toggle plein écran
   ----------------------------------------------------------------------------
   Pattern porté depuis .isis-geo-layers (2026-05-23) :
   un wrapper qui peut basculer en `position: fixed` sous le header app pour
   libérer toute la largeur de l'écran. Sert principalement aux pages détail
   (DevisDetail, etc.) où le sidepanel fixe 480px contraint la zone principale
   sur petits écrans. Touche Échap = sortie. z-index 950 < dialogs Radzen 1010.
   ───────────────────────────────────────────────────────────────────────── */
.isis-focus-zone {
    display: flex;
    flex-direction: column;
    gap: 1rem;
    /* En mode normal, hérite de la chaîne flex de .isis-rich-page :
       prend la hauteur restante et contraint les enfants → la carte d'onglets
       continue de scroller en interne, pas la page. */
    flex: 1 1 auto;
    min-height: 0;
    outline: none;
}
.isis-focus-zone--expanded {
    position: fixed;
    /* `top` laisse la `.isis-rich-toolbar` (breadcrumb + actions) visible au-dessus du
       wrapper. La valeur est POSÉE PAR js/isis-focus-zone.js à partir du bas réel de la
       toolbar : celle-ci passe sur deux lignes dès que les actions ne tiennent plus à
       côté du titre (sidebar déployée, titre long), et le calc() ci-dessous — header
       56px + toolbar d'UNE ligne ~52px — la recouvrait alors, boutons compris
       (2026-09-18). Le calc() ne sert plus que de repli sans JS. Refonte 2026-05-29 :
       auparavant cachait la toolbar (fullscreen modal). */
    top: var(--isis-focus-zone-top, calc(var(--isis-header-h, 56px) + 52px));
    /* `left` calibré sur la largeur du subnav module : la nav latérale reste
       visible et naviguable en mode focus. C'est la différence vs le pattern
       zone géo qui occupe full-screen (la carte a besoin de TOUT l'espace,
       les onglets non — l'objectif est de récupérer le sidepanel droit 480px,
       pas de couper la nav latérale). Sync avec .isis-shell__sidebar. */
    left: var(--isis-subnav-w, 280px);
    right: 0;
    bottom: 0;
    z-index: 950;
    background: var(--isis-surface);
    padding: 0.75rem 1rem 1rem;
    border-top: 1px solid var(--isis-border);
    /* Le wrapper porte tabindex="-1" : focus-visible signale clairement le
       conteneur actif (utile pour la touche Échap). */
    outline: none;
    /* Anim douce de la largeur quand l'utilisateur replie le subnav pendant
       qu'on est en focus zone (calque .isis-shell__sidebar transition). */
    transition: left 200ms cubic-bezier(0.4, 0, 0.2, 1);
}
/* Si le subnav est replié (.isis-shell.is-subnav-collapsed), recalibre la
   bordure gauche du wrapper sur la largeur réduite — sinon un trou visuel
   apparaît entre subnav rétréci et zone focus. */
.isis-shell.is-subnav-collapsed .isis-focus-zone--expanded {
    left: var(--isis-subnav-w-collapsed, 64px);
}
.isis-focus-zone--expanded:focus-visible {
    box-shadow: inset 0 0 0 2px var(--isis-accent);
}

/* Mini-bandeau identité en tête du focus-zone (DevisDetail 2026-05-29).
   Garde le contexte essentiel (numéro · titre · statut · tiers) à l'écran
   quand la summary card est masquée par le wrapper en mode --expanded.
   En mode normal, le bandeau est caché : le contexte vit déjà dans la summary. */
.isis-focus-zone__header {
    display: none;
}
.isis-focus-zone--expanded .isis-focus-zone__header {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.5rem;
    padding: 0.4rem 0.7rem;
    background: var(--isis-surface-alt);
    border: 1px solid var(--isis-border);
    border-radius: 6px;
    font-size: 0.82rem;
    color: var(--isis-text-muted);
    flex-shrink: 0;
}
.isis-focus-zone__num {
    font-family: "Geist Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    color: var(--isis-text);
    font-weight: 500;
    font-size: 0.82rem;
}
.isis-focus-zone__title {
    color: var(--isis-text);
    font-weight: 500;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 360px;
}
.isis-focus-zone__sep {
    opacity: 0.45;
    color: var(--isis-text-soft);
}
.isis-focus-zone__tiers {
    color: var(--isis-text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 280px;
}

/* Bouton fullscreen dans la barre d'onglets — placé après __spacer (donc à
   droite). Calque visuel sur .isis-map-toolbar__btn (zone géo) : ~28px carré,
   icône Material 16px, border + radius légers. */
.isis-tabs__expand-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    margin-left: 4px;
    background: transparent;
    border: 1px solid transparent;
    border-radius: 6px;
    color: var(--isis-text-muted);
    cursor: pointer;
    transition: background-color 120ms, color 120ms, border-color 120ms;
}
.isis-tabs__expand-btn:hover,
.isis-tabs__expand-btn:focus-visible {
    background: var(--isis-surface-alt);
    border-color: var(--isis-border);
    color: var(--isis-text);
    outline: none;
}
.isis-tabs__expand-btn[aria-pressed="true"] {
    color: var(--isis-current-mod, var(--isis-accent));
}

.isis-tab-panel { display: block; }
.isis-tab-panel.is-hidden { display: none; }
/* Panneau d'onglet « nu » (fiches détail, ex. DevisDetail) : le panneau actif
   prend la hauteur restante de la carte d'onglets et scrolle en interne — la
   page entière ne défile plus. Exclut --rich (chaîne flex propre) et --footed
   (qui pinne un pied de panneau). */
.isis-tab-panel:not(.is-hidden):not(.isis-tab-panel--rich):not(.isis-tab-panel--footed) {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
}
/* Modificateur --footed : panneau dont le contenu scrollable est encadré d'un
   en-tête fixe (toolbar) et d'un pied fixe « collé au bas » (ex. onglet Lignes :
   tableau scrollable + Ventilation TVA pinnée en bas). */
.isis-tab-panel--footed:not(.is-hidden) {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;   /* remplit toute la hauteur de la carte d'onglets */
    min-height: 0;
    overflow: hidden;
}
.isis-tab-panel--footed > .isis-devis-items__toolbar {
    flex-shrink: 0;
}
/* Zone scrollable interne du panneau --footed.
   flex: 1 1 auto → la zone du tableau prend toute la place disponible, ce qui
   pousse la Ventilation TVA (flex-shrink:0) et la garde collée AU BAS du
   panneau. Peu de lignes ⇒ espace vide sous le tableau, TVA en bas. Beaucoup
   de lignes ⇒ le tableau scrolle en interne, TVA toujours en bas. */
.isis-devis-items__scroll {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    overflow-x: auto;
}
/* Modificateur --rich : le panneau d'onglet contient des sections rich-page
   (KPI / filtre / master-detail). Il relaie alors le rythme vertical de
   .isis-rich-page (gap entre sections) ET la chaîne flex de hauteur — sinon
   les sections sont collées et la grille interne ne se contraint pas.
   Réservé aux pages liste-à-onglets ; les fiches détail gardent le bloc nu. */
.isis-tab-panel--rich:not(.is-hidden) {
    display: flex;
    flex-direction: column;
    gap: 0.85rem;
    flex: 1 1 auto;
    min-height: 0;
}

/* Barre d'actions au-dessus du contenu d'un panneau d'onglet (ex. « Modifier » sur l'onglet
   Identité d'une fiche) — générique, alignée à droite. Jamais .isis-rich-toolbar__actions :
   cette dernière n'harmonise les contrôles Radzen à 32px que sous un vrai .isis-rich-toolbar
   parent (cf. .isis-grid__subrow-actions, même correctif, DocumentaireDetail 2026-07-29) ;
   étendue à la même règle ci-dessous pour qu'un futur RadzenDropDown y soit harmonisé aussi. */
.isis-tab-panel__actions {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: 0.4rem;
    margin-bottom: 0.6rem;
}

/* ============================================================================
   .isis-tabs-card — carte englobante d'un bloc « onglets + panneaux » sur une
   page rich-page. Maillon manquant de la chaîne flex pleine hauteur : la
   .isis-rich-page (overflow:hidden + height:100%) délègue tout l'espace
   restant à cette carte, qui à son tour épingle la barre .isis-tabs en haut
   et laisse scroller le .isis-tab-panel actif dans son intérieur.

   À placer en dernier enfant de .isis-rich-page. Pattern utilisé par
   gesproj/commandes/{id} (cf. décision 2026-05-15).

   Variante .isis-focus-zone > … : depuis 2026-05-29, les fiches détail
   enveloppent la carte d'onglets dans un wrapper .isis-focus-zone (toggle
   plein écran). Le wrapper s'intercale entre .isis-rich-page et la carte, ce
   qui cassait le sélecteur enfant-direct → la carte retombait sur flex:0 1 auto
   (taille = contenu) et laissait du vide en bas. On relaie donc la chaîne flex
   au cas focus-zone (le wrapper porte déjà flex:1 1 auto + min-height:0).
   ============================================================================ */
.isis-rich-page > .isis-tabs-card.rz-card,
.isis-focus-zone > .isis-tabs-card.rz-card {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    padding: 0;          /* on porte le padding aux enfants pour mieux contrôler */
}
.isis-rich-page > .isis-tabs-card.rz-card > .isis-tabs,
.isis-focus-zone > .isis-tabs-card.rz-card > .isis-tabs {
    flex-shrink: 0;
    margin: 0 1rem;
    padding-top: 0.5rem;
}
.isis-rich-page > .isis-tabs-card.rz-card > .isis-tab-panel:not(.is-hidden),
.isis-focus-zone > .isis-tabs-card.rz-card > .isis-tab-panel:not(.is-hidden) {
    padding: 0.25rem 1rem 1rem;
}

/* ============================================================================
   .isis-contact-card — Carte interlocuteur (réutilisable)
   ============================================================================ */
.isis-contact-list { display: flex; flex-direction: column; gap: 0.5rem; }
.isis-contact-card {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.65rem 0.85rem;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: 8px;
    transition: background-color 120ms ease;
}
.isis-contact-card:hover { background: var(--isis-surface-alt); }
/* Carte navigable au clavier (tabindex + role=button côté markup). */
.isis-contact-card--navigable { cursor: pointer; }
.isis-contact-card--navigable:focus-visible {
    outline: 2px solid var(--isis-accent);
    outline-offset: 1px;
}
.isis-contact-card__avatar {
    width: 34px; height: 34px;
    border-radius: 50%;
    /* Teinte du module courant (composant partagé) — pas le bleu Gescom en dur. */
    background: var(--isis-current-mod-soft, var(--isis-accent-soft));
    color: var(--isis-current-mod, var(--isis-accent));
    font-size: 0.78rem;
    font-weight: 600;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    text-transform: uppercase;
}
.isis-contact-card__main { flex: 1; min-width: 0; }
.isis-contact-card__name {
    font-size: var(--isis-fs-sm);
    font-weight: 500;
    color: var(--isis-text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.isis-contact-card__meta {
    font-size: 0.75rem;
    color: var(--isis-text-soft);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/* Ligne « Managé par … » (onglet Collaborateurs d'une structure). */
.isis-contact-card__sub {
    display: flex;
    align-items: center;
    gap: 0.25rem;
    margin-top: 0.1rem;
    font-size: var(--isis-fs-label);
    color: var(--isis-text-muted);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.isis-contact-card__sub .rzi { color: var(--isis-text-soft); }

/* ── Onglet Collaborateurs : split liste (gauche) + organigramme (droite) ── */
.isis-struct-collab-split {
    display: flex;
    flex-wrap: wrap;
    gap: 1rem;
    align-items: flex-start;
}
.isis-struct-collab-split__list { flex: 1 1 320px; min-width: 0; }
.isis-struct-collab-split__chart {
    flex: 1 1 380px;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    min-height: 360px;
}
@media (max-width: 900px) {
    .isis-struct-collab-split { flex-direction: column; }
    .isis-struct-collab-split__list,
    .isis-struct-collab-split__chart { flex: 1 1 auto; width: 100%; }
}

/* Onglet Collaborateurs en pleine hauteur : l'organigramme occupe tout l'espace
   disponible jusqu'en bas du panneau (chaîne flex .isis-rich-page > .isis-tabs-card
   > .isis-tab-panel déjà pleine hauteur). La liste à gauche scrolle dans sa colonne. */
/* :not(.is-hidden) : un sélecteur ID écrase sinon `.isis-tab-panel.is-hidden { display:none }`
   (spécificité), ce qui ferait apparaître ce panneau sur TOUS les onglets. */
#struct-panel-collaborateurs:not(.is-hidden) { display: flex; flex-direction: column; }
#struct-panel-collaborateurs .isis-struct-collab-split {
    flex: 1 1 auto;
    min-height: 0;
    align-items: stretch;
}
#struct-panel-collaborateurs .isis-struct-collab-split__list { overflow-y: auto; min-height: 0; }

/* Carte surlignée = collaborateur sélectionné depuis l'organigramme (synchro chart → liste). */
.isis-contact-card.is-selected {
    border-color: var(--isis-current-mod, var(--isis-accent));
    background: color-mix(in oklch, var(--isis-current-mod, var(--isis-accent)) 6%, var(--isis-surface));
}

/* Barre d'en-tête de l'organigramme (titre + actions Ajuster / Agrandir). */
.isis-struct-orgchart__bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
}
.isis-struct-orgchart__title {
    font-size: var(--isis-fs-sm);
    font-weight: 600;
    color: var(--isis-text-soft);
}
.isis-struct-orgchart__actions { display: flex; gap: 0.4rem; flex-wrap: wrap; }

/* Mode agrandi : focus-zone plein écran sous le header applicatif. */
.isis-struct-collab-split__chart.is-expanded {
    position: fixed;
    inset: 0;
    /* sous les dialogs Radzen (≥1010) pour que le dialog « Définir le manager »
       reste au-dessus du canvas en mode plein écran ; aligné sur la focus-zone. */
    z-index: 950;
    margin: 0;
    padding: 1rem;
    background: var(--isis-bg);
    min-height: 0;
}

/* Dialog d'édition du manager (double-clic nœud organigramme). */
.isis-manager-edit-dialog { display: flex; flex-direction: column; gap: 0.6rem; min-width: 300px; }
.isis-manager-edit-dialog__label {
    font-size: var(--isis-fs-sm);
    font-weight: 500;
    color: var(--isis-text-soft);
}
.isis-manager-edit-dialog__hint {
    font-size: var(--isis-fs-sm);
    color: var(--isis-text-muted);
    margin: 0;
}
.isis-manager-edit-dialog__actions {
    display: flex;
    gap: 0.5rem;
    flex-wrap: wrap;
    margin-top: 0.4rem;
}

/* Rôles cumulables d'un interlocuteur (0827) : à gauche du marqueur « Principal », qui
   reste le dernier jeton avant les actions. Rétrécit avant le nom, jamais l'inverse. */
.isis-contact-card__roles {
    display: flex;
    gap: 0.25rem;
    flex-wrap: wrap;
    justify-content: flex-end;
    flex-shrink: 0;
    max-width: 45%;
}

.isis-contact-card__primary {
    font-size: 0.62rem;
    padding: 0.1rem 0.45rem;
    border-radius: var(--isis-radius-pill);
    background: var(--isis-accent-soft);
    color: var(--isis-accent);
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    flex-shrink: 0;
}

/* Actions hover-révélées sur la carte contact */
.isis-contact-card__actions {
    display: flex;
    gap: 0.2rem;
    opacity: 0;
    transition: opacity 120ms ease;
    flex-shrink: 0;
}
.isis-contact-card:hover .isis-contact-card__actions,
.isis-contact-card:focus-within .isis-contact-card__actions { opacity: 1; }
.isis-contact-card__action-btn {
    width: 28px; height: 28px;
    border: none;
    background: transparent;
    border-radius: 6px;
    color: var(--isis-text-muted);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: background-color 120ms ease, color 120ms ease;
}
.isis-contact-card__action-btn:hover {
    background: var(--isis-surface);
    color: var(--isis-text);
}
.isis-contact-card__action-btn--danger:hover {
    background: var(--isis-danger-soft);
    color: #dc2626;
}
.isis-contact-card__action-btn[aria-disabled="true"] { opacity: .45; cursor: not-allowed; }
.isis-contact-card__action-btn[aria-disabled="true"]:hover { background: transparent; color: var(--isis-text-muted); }

/* En-tête de tab : titre + bouton Ajouter à droite */
.isis-tab-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    margin-bottom: 0.85rem;
}
.isis-tab-header__title {
    font-size: 0.85rem;
    color: var(--isis-text-muted);
}
.isis-tab-header__title strong {
    color: var(--isis-text);
    font-weight: 600;
}

/* Titre de panneau d'onglet. Un <h2> et non un <h3> : le seul autre titre d'une fiche est
   le h1 porté par le fil d'Ariane, un h3 sautait donc un niveau (WCAG 1.3.1). Les marges
   et la taille par défaut du navigateur pour h2 (1.5em + 1em de marge) casseraient la
   ligne d'en-tête : on les fixe ici, au gabarit que le h3 rendait déjà. */
.isis-tab-header__heading {
    margin: 0;
    font-size: 0.95rem;
    font-weight: 600;
    color: var(--isis-text);
}

.isis-tab-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    padding: 2rem 1rem;
    color: var(--isis-text-soft);
    text-align: center;
    font-size: 0.85rem;
}
.isis-tab-empty .rzi { font-size: 32px; opacity: 0.4; }

/* ============================================================================
   Colonne actions COLLANTE À DROITE sur les grilles d'organisation SIRH.
   Ces grilles ont un min-width large (rail + sidepanel rétrécissent le master),
   d'où un scroll horizontal qui repoussait la colonne actions — donc le bouton
   « Supprimer » — hors de la zone visible. La rendre sticky garantit qu'Ouvrir /
   Modifier / Supprimer restent toujours atteignables. Le fond opaque + l'ombre
   de bord masquent le contenu défilant dessous.
   ============================================================================ */
.isis-grid--orgduale .isis-grid__col-actions {
    position: sticky;
    right: 0;
    background: var(--isis-surface);
    z-index: 2;
    box-shadow: -8px 0 8px -8px rgba(0, 0, 0, 0.12);
}
/* Le fond de la cellule sticky suit l'état de la ligne (survol / sélection). */
.isis-grid--orgduale .isis-grid__row:hover .isis-grid__col-actions {
    background: var(--isis-current-mod-soft, var(--isis-surface-alt));
}
.isis-grid--orgduale .isis-grid__row.is-active .isis-grid__col-actions {
    background: var(--isis-current-mod-soft, var(--isis-accent-soft));
}
/* En-tête : coin haut-droit collant (au-dessus des cellules). */
.isis-grid--orgduale .isis-grid__head > div:last-child {
    position: sticky;
    right: 0;
    background: var(--isis-surface-alt);
    z-index: 5;
}

/* ----------------------------------------------------------------------------
   Variante opt-in générique : `.isis-grid--sticky-actions`. À ajouter sur la
   racine d'une grille transactionnelle dont la colonne actions (dernière) risque
   d'être rognée par le scroll horizontal en contexte master-detail. Suppose que
   la colonne actions porte `.isis-grid__col-actions` ET qu'elle est la dernière.
   ---------------------------------------------------------------------------- */
/* Corps : on cible la CLASSE de la cellule actions (et non `:last-child`) car
   certaines grilles ajoutent une carte de survol `.isis-row-preview` en dernier
   enfant DOM de la ligne (positionnée en absolute) — `:last-child` collerait alors
   la preview au lieu des actions. */
.isis-grid--sticky-actions .isis-grid__actions,
.isis-grid--sticky-actions .isis-grid__col-actions {
    position: sticky;
    right: 0;
    background: var(--isis-surface);
    z-index: 2;
    box-shadow: -8px 0 8px -8px rgba(0, 0, 0, 0.12);
}
.isis-grid--sticky-actions .isis-grid__row:hover .isis-grid__actions,
.isis-grid--sticky-actions .isis-grid__row:hover .isis-grid__col-actions {
    background: var(--isis-current-mod-soft, var(--isis-surface-alt));
}
.isis-grid--sticky-actions .isis-grid__row.is-active .isis-grid__actions,
.isis-grid--sticky-actions .isis-grid__row.is-active .isis-grid__col-actions {
    background: var(--isis-current-mod-soft, var(--isis-accent-soft));
}
.isis-grid--sticky-actions .isis-grid__row.is-active:hover .isis-grid__actions,
.isis-grid--sticky-actions .isis-grid__row.is-active:hover .isis-grid__col-actions {
    background: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 18%, var(--isis-surface));
}
/* En-tête : pas de preview en en-tête, `:last-child` = cellule actions, OK. */
.isis-grid--sticky-actions .isis-grid__head > div:last-child {
    position: sticky;
    right: 0;
    background: var(--isis-surface-alt);
    z-index: 5;
}

/* Pill structures internes : variante grise neutre du headcount-pill (différencie
   visuellement effectif vs structures pour le scan rapide). */
.isis-grid__structures-pill {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 26px;
    padding: 0 0.4rem;
    height: 18px;
    border-radius: 9px;
    background: var(--isis-surface-alt);
    color: var(--isis-text);
    font-size: 0.7rem;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}

/* ============================================================================
   .isis-grid--structures — variante pour la liste sirh.entreprise_structure
   Colonnes : status | nom | code court | parent | master | actions
   Override des grid-template-columns par défaut (qui ciblent les tiers).
   ============================================================================ */
.isis-grid--structures .isis-grid__head,
.isis-grid--structures .isis-grid__row {
    grid-template-columns: 32px minmax(220px, 1.8fr) 110px minmax(200px, 1.3fr) 110px 90px;
    min-width: 820px;
}
.isis-grid--structures .isis-grid__col-name {
    font-weight: 500;
    color: var(--isis-text);
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
}
.isis-grid--structures .isis-grid__col-name .rzi { font-size: 14px; opacity: 0.5; }
.isis-grid--structures .isis-grid__col-shortcode {
    font-family: var(--isis-font-mono, ui-monospace, monospace);
    font-size: 0.78rem;
    color: var(--isis-text);
    font-weight: 600;
    letter-spacing: 0.05em;
}
.isis-grid--structures .isis-grid__col-parent {
    color: var(--isis-text-muted);
    font-size: 0.85rem;
}
.isis-grid__status-dot.is-master      { background: var(--isis-mod-sirh, #10b981); }
.isis-grid__status-dot.is-nonmaster   { background: #9ca3af; }

/* Pastille « no short code » utilisée en lieu et place du code monospace */
.isis-grid__shortcode-empty {
    color: var(--isis-text-soft);
    font-style: italic;
    font-family: inherit !important;
    letter-spacing: 0 !important;
    font-weight: 400 !important;
}

/* ============================================================================
   .isis-view-toggle — Segmented control (Liste ↔ Organigramme)
   ----------------------------------------------------------------------------
   Posé dans la toolbar `.isis-rich-toolbar__actions`. Cohérent avec le style
   `.isis-rich-toolbar__btn` mais regroupé visuellement (2-3 segments).
   ============================================================================ */
.isis-view-toggle {
    display: inline-flex;
    align-items: stretch;
    gap: 0;
    background: var(--isis-surface-alt);
    border: 1px solid var(--isis-border);
    border-radius: 8px;
    padding: 2px;
    height: 30px;
    margin-right: 0.4rem;
}
.isis-view-toggle__btn {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0 0.7rem;
    background: transparent;
    border: none;
    border-radius: 6px;
    color: var(--isis-text-muted);
    font-size: 0.78rem;
    font-weight: 500;
    cursor: pointer;
    transition: background-color 120ms ease, color 120ms ease;
}
.isis-view-toggle__btn:hover {
    color: var(--isis-text);
}
.isis-view-toggle__btn.is-active {
    background: var(--isis-surface);
    color: var(--isis-text);
    font-weight: 600;
}
.isis-view-toggle__btn:disabled,
.isis-view-toggle__btn[disabled] {
    cursor: not-allowed;
    opacity: 0.45;
}
.isis-view-toggle__btn:disabled:hover { color: var(--isis-text-muted); }
.isis-view-toggle__btn .rzi { opacity: 0.7; }
.isis-view-toggle__btn.is-active .rzi { opacity: 1; color: var(--isis-accent); }
/* Point #4 — variante compacte pour les segmented controls de toolbar (zoom levels). */
.isis-view-toggle__btn--compact {
    padding: 0 0.45rem;
    font-size: 0.72rem;
    height: 26px;
}

/* ============================================================================
   .isis-grid--tree — Variante arbre indenté de la grille structures
   ----------------------------------------------------------------------------
   Colonnes : tree(32) | name | shortcode(110) | descendants(120) | master(110) | actions(90)
   Override des grid-template-columns de `.isis-grid--structures` (qui restent
   utiles si on revient à une vue à plat dans le futur).
   ============================================================================ */
.isis-grid--tree.isis-grid--structures .isis-grid__head,
.isis-grid--tree.isis-grid--structures .isis-grid__row {
    /* tree | name | shortcode | manager | headcount | descendants | master | actions */
    grid-template-columns: 32px minmax(220px, 1.5fr) 95px minmax(150px, 1fr) 80px 100px 95px 60px;
    min-width: 1080px;
}
.isis-grid__col-headcount-head {
    justify-content: flex-end;
    padding-right: 0.6rem !important;
}
.isis-grid__col-headcount {
    text-align: right;
    padding-right: 0.6rem !important;
}
.isis-grid__headcount-pill {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 26px;
    padding: 0 0.4rem;
    height: 18px;
    border-radius: 9px;
    background: var(--isis-mod-sirh-soft, #ecfdf5);
    /* Texte en --isis-text : --isis-mod-sirh sur --isis-mod-sirh-soft ne donne
       que 2.4:1 (échec WCAG AA texte). Le fond vert pâle porte l'identité SIRH. */
    color: var(--isis-text);
    font-size: 0.7rem;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}

/* Colonne Responsable — restaurée § décision 1a (revue finale organisation duale, 2026-09-07) :
   dot + nom, pas de stack nom/poste (OrgNodeRow ne porte pas de ManagerTitle, à la différence
   de l'ancien EntrepriseSummary). */
.isis-grid__col-manager {
    color: var(--isis-text);
    font-size: 0.82rem;
    display: inline-flex !important;
    align-items: center;
    gap: 0.35rem;
    overflow: hidden !important;
    white-space: nowrap;
    text-overflow: ellipsis;
}
.isis-grid__manager-dot {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--isis-mod-sirh);
    flex-shrink: 0;
}
.isis-grid__manager-name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Pastille d'alerte « effectif sans responsable » — restaurée § décision 1b (revue finale
   organisation duale, 2026-09-07), posée dans la cellule Entité (title + aria-label propres). */
.isis-grid__warning-dot {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 16px;
    height: 16px;
    margin-left: 0.3rem;
    border-radius: 50%;
    background: var(--isis-warning-soft);
    color: var(--isis-warning);
    font-size: 0.7rem;
    font-weight: 700;
    line-height: 1;
    cursor: help;
}

/* Cellule tree (chevron expand/collapse ou dot feuille) */
.isis-grid__col-tree {
    display: flex !important;
    justify-content: center;
    align-items: center;
    padding: 0 !important;
}
.isis-grid__chevron-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    border: none;
    background: transparent;
    border-radius: 4px;
    color: var(--isis-text-muted);
    cursor: pointer;
    transition: background-color 120ms ease, color 120ms ease;
}
.isis-grid__chevron-btn:hover {
    background: var(--isis-surface);
    color: var(--isis-accent);
}
.isis-grid__chevron-btn:focus-visible {
    outline: 2px solid var(--isis-accent);
    outline-offset: 1px;
    color: var(--isis-text);
}
.isis-grid__leaf-dot {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--isis-border);
    display: inline-block;
}

/* Cellule "Nom" en mode arbre : indentation par profondeur + guides verticaux */
.isis-grid__col-name--tree {
    display: inline-flex !important;
    align-items: center;
    gap: 0.35rem;
    overflow: hidden !important;
}
.isis-grid__tree-guide {
    display: inline-block;
    width: 22px;
    height: 32px;
    border-left: 1px dashed var(--isis-border);
    margin-right: -4px;
    flex-shrink: 0;
    opacity: 0.55;
}
.isis-grid__col-name-label {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
}

/* Cellule "Descendants" */
.isis-grid__col-descendants-head {
    justify-content: flex-end;
    padding-right: 0.6rem !important;
}
.isis-grid__col-descendants {
    text-align: right;
    padding-right: 0.6rem !important;
}
.isis-grid__descendants-pill {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 26px;
    padding: 0 0.4rem;
    height: 18px;
    border-radius: 9px;
    background: var(--isis-accent-soft);
    color: var(--isis-accent);
    font-size: 0.7rem;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}

/* Bloc master/detail en mode plein écran (vue organigramme) */
.isis-master-detail.is-fullwidth {
    grid-template-columns: 1fr;
}
.isis-master-detail.is-fullwidth .isis-master-detail__detail {
    display: none;
}

/* ============================================================================
   .isis-orgchart — Vue organigramme top-down (Balkan OrgChart JS)
   ----------------------------------------------------------------------------
   Wrapper minimaliste autour du host Balkan. Le contenu (cards, connecteurs)
   est rendu par Balkan en SVG ; on contrôle seulement le container et la
   légende.
   ============================================================================ */
.isis-orgchart-wrapper {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-height: 0;
    gap: 0.6rem;
    overflow: hidden;
}
.isis-orgchart-balkan-host {
    /* `flex: 1 1 0` (au lieu de `1 1 auto`) : la base à 0 laisse Balkan
       respirer dans la hauteur fournie par la chaîne flex, sans imposer
       de plancher dur qui ferait déborder le master sur petits écrans. */
    flex: 1 1 0;
    min-height: 280px;
    background:
        radial-gradient(circle at 1px 1px, #e5e7eb 1px, transparent 0) 0 0 / 18px 18px,
        var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius);
    overflow: hidden;
    position: relative;
}
/* Le SVG interne hérite explicitement de la box du host : sans ça Balkan
   peut conserver la largeur/hauteur calculées au 1er render et ne pas suivre
   le resize du container (sidepanel toggle, fenêtre, switch d'onglet). */
.isis-orgchart-balkan-host > svg {
    display: block;
    width: 100% !important;
    height: 100% !important;
}

/* Hover : surligne la 1re <rect> de la node (= bordure card) avec l'accent ISIS.
   Balkan attache `data-n-id` à chaque <g> de noeud. */
.isis-orgchart-balkan-host g[data-n-id] { cursor: pointer; }
.isis-orgchart-balkan-host g[data-n-id]:hover > rect:first-of-type {
    stroke: var(--isis-accent) !important;
    stroke-width: 1.5 !important;
}

/* Watermark Balkan (Free Trial uniquement, pas Community — au cas où on switche
   un jour) : on l'atténue par défaut. À supprimer si licence achetée. */
.isis-orgchart-balkan-host .boc-watermark,
.isis-orgchart-balkan-host [class*="watermark"] {
    opacity: 0.25 !important;
}

/* Toolbar Balkan : neutralise les ombres et aligne au theme Flat */
.isis-orgchart-balkan-host .bft-toolbar {
    background: var(--isis-surface) !important;
    border: 1px solid var(--isis-border) !important;
    box-shadow: none !important;
}
.isis-orgchart-balkan-host .bft-toolbar svg { fill: var(--isis-text-muted) !important; }
.isis-orgchart-balkan-host .bft-toolbar :hover svg { fill: var(--isis-accent) !important; }

.isis-orgchart-legend {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 1rem;
    padding: 0.35rem 0.6rem;
    font-size: 0.72rem;
    color: var(--isis-text-muted);
}
.isis-orgchart-legend span {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
}
.isis-orgchart-legend__swatch {
    width: 14px;
    height: 14px;
    border-radius: 3px;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
}
.isis-orgchart-legend__swatch.is-master {
    border-left-color: var(--isis-mod-sirh, #10b981);
}
.isis-orgchart-legend__swatch.is-nonmaster {
    border-left-color: var(--isis-border);
}
/* Badge icône du nœud entreprise dans l'organigramme : <foreignObject> qui héberge
   un <span class="material-symbols-outlined"> (les ligatures ne se rendent pas dans
   un <text> SVG). Centre l'icône blanche dans le carré 28×28 coloré au type. */
.isis-orgchart-badge-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
}
.isis-orgchart-badge-icon .material-symbols-outlined {
    color: #ffffff;
    font-size: 18px;
    line-height: 1;
}
/* Couleurs par type d'entité juridique — doivent rester synchronisées avec la
   palette ENT_STYLE de orgchart-balkan.js (bandeau + badge du nœud entreprise). */
.isis-orgchart-legend__swatch.is-ent-groupe        { border-left-color: #7c3aed; }
.isis-orgchart-legend__swatch.is-ent-entreprise    { border-left-color: #10b981; }
.isis-orgchart-legend__swatch.is-ent-agence        { border-left-color: #0ea5e9; }
.isis-orgchart-legend__swatch.is-ent-etablissement { border-left-color: #f59e0b; }
.isis-orgchart-legend__swatch.is-ent-succursale    { border-left-color: #ec4899; }
/* Entité juridique atténuée (vue Structures internes) — gris, cf. MUTE_COLOR du JS. */
.isis-orgchart-legend__swatch.is-ent-muted         { border-left-color: #9ca3af; }

/* Organigramme « Structures internes » : canvas + colonne latérale des entités
   rattachées (filiales/agences/établissements de l'entreprise scopée). Grisées
   pour garder le focus sur l'arbre des structures internes ; cliquables → fiche. */
.isis-org-with-aside {
    display: flex;
    align-items: stretch;
    gap: 0.75rem;
    flex: 1 1 auto;
    min-height: 0;
}
.isis-org-with-aside__chart {
    flex: 1 1 auto;
    min-width: 0;
    min-height: 0;
    display: flex;
    flex-direction: column;   /* grille (liste) ou organigramme : remplit la colonne */
}
.isis-org-filiales {
    flex: 0 0 224px;
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
    padding: 0.6rem;
    overflow-y: auto;
    background: var(--isis-surface-alt);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius, 8px);
}
.isis-org-filiales__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
}
.isis-org-filiales__title {
    font-size: 0.72rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--isis-text-muted);
}
.isis-org-filiales__count {
    font-size: 0.7rem;
    font-weight: 600;
    color: var(--isis-text-muted);
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: 999px;
    padding: 0 0.45rem;
}
.isis-org-filiales__hint {
    font-size: 0.68rem;
    color: var(--isis-text-muted);
    margin-bottom: 0.25rem;
}
.isis-org-filiales__item {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    width: 100%;
    text-align: left;
    padding: 0.45rem 0.5rem;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-sm, 6px);
    color: var(--isis-text-muted);
    cursor: pointer;
    transition: background .12s ease, color .12s ease, border-color .12s ease;
}
.isis-org-filiales__item:hover,
.isis-org-filiales__item:focus-visible {
    background: var(--isis-surface-alt);
    color: var(--isis-text);
    border-color: var(--isis-current-mod, var(--isis-accent));
    outline: none;
}
.isis-org-filiales__item-main {
    display: flex;
    flex-direction: column;
    min-width: 0;
    flex: 1 1 auto;
}
.isis-org-filiales__item-name {
    font-size: 0.8rem;
    font-weight: 500;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.isis-org-filiales__item-type {
    font-size: 0.68rem;
    color: var(--isis-text-muted);
}

/* Organigramme pivot « épine dorsale » (org duale, Phase 2A) — réf. maquette
   docs/mockups/2026-06-18-org-duale-altE-pivot-epine.html. Couleurs d'axe
   tokenisées localement (jur/tech/grp = encodages sémantiques d'axe). */
/* Conteneur scrollable : prend la hauteur restante de .isis-rich-page
   (height:100% + overflow:hidden) → l'organigramme scrolle, jamais la page. */
.isis-pivot-scroll { flex:1; min-height:0; overflow:auto; }

/* Viewport zoom/pan réutilisable (IsisDiagramViewport). */
.isis-vp { position: relative; width: 100%; height: 100%; overflow: hidden; }
.isis-vp.is-grabbing { cursor: grabbing; }
.isis-vp__content { transform-origin: 0 0; will-change: transform; }
.isis-vp__header {
    position: relative; z-index: 4;
    padding-right: 9rem; /* dégage la barre de zoom flottante en haut à droite */
    background: var(--isis-surface);
    border-bottom: 1px solid var(--isis-border);
}
.isis-vp__bar {
    position: absolute; top: .6rem; right: .6rem; z-index: 5;
    display: flex; gap: .25rem; padding: .25rem;
    background: var(--isis-surface); border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius); box-shadow: var(--isis-elevation-1);
}
.isis-vp__btn {
    display: inline-flex; align-items: center; justify-content: center;
    width: 30px; height: 30px; border: none; background: transparent;
    border-radius: var(--isis-radius-sm); color: var(--isis-text); cursor: pointer;
}
.isis-vp__btn:hover { background: var(--isis-surface-alt); color: var(--isis-current-mod); }
.isis-vp__btn:focus-visible { outline: 2px solid color-mix(in oklch, var(--isis-current-mod) 60%, transparent); outline-offset: 1px; }
.isis-vp__zoom { display:inline-flex; align-items:center; min-width:3rem; justify-content:center;
    font-family:'Geist Mono', ui-monospace, monospace; font-size: var(--isis-fs-caption); color: var(--isis-text-muted); }
.isis-vp:focus-visible { outline: 2px solid color-mix(in oklch, var(--isis-current-mod) 40%, transparent); outline-offset: -2px; }

/* Picker technique en treeview (rattachement collaborateur) : conteneur borné scrollable. */
.isis-tree-picker { border:1px solid var(--isis-border); border-radius:var(--isis-radius-sm); max-height:220px; overflow:auto; padding:6px 8px; background:var(--isis-surface); }
.isis-tree-picker__clear { background:none; border:0; padding:0; margin-left:6px; color:var(--isis-mod-sirh,#10b981); cursor:pointer; font:inherit; text-decoration:underline; }

/* Mini-organigramme (sidepanel Vue Liste org duale) — arbre vertical indenté 2 niveaux. */
.isis-minitree-block + .isis-minitree-block { margin-top:14px; }
.isis-minitree__title { font-size:11px; text-transform:uppercase; letter-spacing:.04em; color:var(--isis-text-muted); font-weight:700; margin-bottom:8px; display:flex; align-items:center; gap:6px; }
.isis-minitree__sw { width:9px; height:9px; border-radius:3px; display:inline-block; }
.isis-minitree__sw--jur { background:#5b4be6; }
.isis-minitree__sw--tech { background:#0d9488; }
.isis-minitree { display:flex; flex-direction:column; gap:3px; position:relative; }
.isis-minitree::before { content:""; position:absolute; left:11px; top:18px; bottom:14px; width:2px; background:var(--isis-border); }
.isis-minitree__node { display:flex; align-items:center; gap:8px; padding:5px 8px; border-radius:var(--isis-radius-sm); border:1px solid transparent; background:transparent; cursor:pointer; position:relative; text-align:left; width:100%; }
.isis-minitree__node:hover { background:var(--isis-surface-alt); }
.isis-minitree__node.is-sel { background:color-mix(in srgb, var(--isis-mod-sirh,#10b981) 10%, var(--isis-surface)); border-color:color-mix(in srgb, var(--isis-mod-sirh,#10b981) 35%, var(--isis-border)); }
.isis-minitree__node--lvl1 { margin-left:16px; }
.isis-minitree__node--lvl2 { margin-left:34px; }
.isis-minitree__node--lvl1::before, .isis-minitree__node--lvl2::before { content:""; position:absolute; left:-10px; top:50%; width:8px; height:2px; background:var(--isis-border); transform:translateY(-50%); }
.isis-minitree__ic { width:22px; height:22px; border-radius:6px; display:flex; align-items:center; justify-content:center; flex:none; }
.isis-minitree__node--ent .isis-minitree__ic { background:color-mix(in srgb, var(--isis-mod-sirh,#10b981) 16%, var(--isis-surface)); color:var(--isis-mod-sirh,#047857); }
.isis-minitree__node--jur .isis-minitree__ic { background:#ece9fe; color:#4338ca; }
.isis-minitree__node--tech .isis-minitree__ic { background:#d2f3ef; color:#0f766e; }
.isis-minitree__nm { flex:1; min-width:0; font-size:12.5px; font-weight:600; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.isis-minitree__cnt { font-family:'Geist Mono',ui-monospace,monospace; font-size:11px; color:var(--isis-text-muted); background:var(--isis-surface-alt); border-radius:999px; padding:1px 7px; flex:none; }
.isis-minitree__empty { font-size:11.5px; color:var(--isis-text-muted); font-style:italic; padding:4px 8px 4px 16px; }

/* Vue Liste org duale — grille master + sidepanel. */
.isis-grid--orgduale .isis-grid__head,
.isis-grid--orgduale .isis-grid__row {
    /* tree | Entité | Type | Axe | Rattaché à | Pays | Devise | Responsable | Effectif | Filiales | Actions
       11 colonnes depuis la restauration des 3 éléments perdus de l'ancienne page (§ décision 1,
       revue finale 2026-09-07 — Responsable en colonne dédiée, Filiales directes idem ; la pastille
       d'alerte sans-responsable reste inline dans la cellule Entité). AUCUNE min-width sur la
       règle : c'est le piège documenté du dépôt (une min-width écrite à la main dépasse la somme
       réelle des minimums et provoque un défilement horizontal permanent, cf. GED 2026-09-06). */
    grid-template-columns: 32px minmax(0,1.3fr) 110px 100px minmax(0,0.9fr) 60px 68px minmax(0,0.9fr) 68px 64px 100px;
}

/* Ligne d'ancêtre remontée par un filtre : présente pour raccrocher un résultat,
   pas retenue elle-même. */
.isis-grid--orgduale .isis-grid__row.is-context {
    color: var(--isis-text-muted);
    background: var(--isis-surface-alt);
}
/* .is-context (3 classes) l'emportait TOUJOURS sur .is-active (2 classes) à spécificité
   égale par position — une ligne de contexte sélectionnée devenait indiscernable d'une
   ligne de contexte ordinaire. Cette règle à 4 classes reprend la main : teinte de
   sélection conservée, texte qui reste atténué. */
.isis-grid--orgduale .isis-grid__row.is-active.is-context {
    background: var(--isis-current-mod-soft, var(--isis-accent-soft));
}

.isis-orgside { display:flex; flex-direction:column; height:100%; }
.isis-orgside__head { padding:14px 16px 12px; border-bottom:1px solid var(--isis-border); }
.isis-orgside__cap { display:flex; align-items:center; gap:7px; font-size:11.5px; color:var(--isis-text-muted); }
.isis-orgside__title { margin:7px 0 8px; font-size:16px; font-weight:700; letter-spacing:-.01em; }
.isis-orgside__badges { display:flex; gap:6px; flex-wrap:wrap; }
.isis-orgside__body { padding:12px 16px; display:flex; flex-direction:column; gap:14px; overflow:auto; }
.isis-orgside__facts { display:grid; grid-template-columns:1fr 1fr; gap:8px 12px; }
.isis-orgside__fact .k { font-size:10px; text-transform:uppercase; letter-spacing:.04em; color:var(--isis-text-muted); font-weight:700; }
.isis-orgside__fact .v { font-size:12.5px; font-weight:600; }
.isis-orgside__actions { display:flex; gap:8px; flex-wrap:wrap; }

/* Dialog « + Nœud » (org duale) — réf. maquette 2026-06-18-org-duale-altE-noeud.html.
   Couleurs d'axe tokenisées localement (encodages sémantiques jur/tech/grp). */
.isis-orgnode {
    --jur:#5b4be6; --jur-soft:#ece9fe; --jur-ink:#4338ca;
    --tech:#0d9488; --tech-soft:#d2f3ef; --tech-ink:#0f766e;
    --grp:#7c3aed; --grp-soft:#ede9fe;
    display:block;
}
.isis-orgnode__sub { font-size:11.5px; color:var(--isis-text-muted); margin:-2px 0 4px; }
.isis-orgnode__field { padding:13px 0; border-bottom:1px solid var(--isis-border); }
.isis-orgnode__field:last-of-type { border-bottom:0; }
.isis-orgnode__label { display:block; font-size:11px; text-transform:uppercase; letter-spacing:.04em; color:var(--isis-text-muted); font-weight:700; margin-bottom:8px; }
.isis-orgnode__req { color:var(--isis-danger,#dc2626); }
.isis-orgnode__opt { color:var(--isis-text-muted); font-weight:400; text-transform:none; letter-spacing:0; }

.isis-orgnode__axes { display:grid; grid-template-columns:1fr 1fr; gap:10px; }
.isis-orgnode__axe { border:1.5px solid var(--isis-border); border-radius:var(--isis-radius); padding:12px 14px; cursor:pointer; display:flex; gap:11px; align-items:flex-start; background:var(--isis-surface); text-align:left; width:100%; }
.isis-orgnode__axe-dot { width:13px; height:13px; border-radius:50%; margin-top:2px; flex:none; }
.isis-orgnode__axe-t { font-weight:700; font-size:13px; }
.isis-orgnode__axe-d { font-size:11px; color:var(--isis-text-muted); line-height:1.35; }
.isis-orgnode__axe:not(.is-on) { opacity:.7; }
.isis-orgnode__axe--jur.is-on { border-color:var(--jur); background:color-mix(in srgb,var(--jur) 6%,var(--isis-surface)); box-shadow:0 0 0 3px var(--jur-soft); }
.isis-orgnode__axe--jur .isis-orgnode__axe-dot { background:var(--jur); }
.isis-orgnode__axe--jur .isis-orgnode__axe-t { color:var(--jur-ink); }
.isis-orgnode__axe--tech.is-on { border-color:var(--tech); background:color-mix(in srgb,var(--tech) 6%,var(--isis-surface)); box-shadow:0 0 0 3px var(--tech-soft); }
.isis-orgnode__axe--tech .isis-orgnode__axe-dot { background:var(--tech); }
.isis-orgnode__axe--tech .isis-orgnode__axe-t { color:var(--tech-ink); }

.isis-orgnode__pills { display:flex; gap:8px; flex-wrap:wrap; }
.isis-orgnode__pill { border:1px solid var(--isis-border); background:var(--isis-surface); border-radius:999px; padding:6px 13px; font-size:12px; color:var(--isis-text-muted); cursor:pointer; font-weight:600; display:inline-flex; align-items:center; gap:6px; }
.isis-orgnode__pill i { width:8px; height:8px; border-radius:50%; background:var(--isis-text-muted); display:inline-block; }
.isis-orgnode--jur .isis-orgnode__pill.is-on { border-color:var(--jur); background:var(--jur-soft); color:var(--jur-ink); }
.isis-orgnode--jur .isis-orgnode__pill.is-on i { background:var(--jur); }
.isis-orgnode--tech .isis-orgnode__pill.is-on { border-color:var(--tech); background:var(--tech-soft); color:var(--tech-ink); }
.isis-orgnode--tech .isis-orgnode__pill.is-on i { background:var(--tech); }
.isis-orgnode__hint { font-size:11px; color:var(--isis-text-muted); margin-top:8px; }

.isis-orgnode__grid2 { display:grid; grid-template-columns:1fr 1fr; gap:12px; }

.isis-orgnode__preview { background:color-mix(in srgb,var(--isis-mod-sirh,#10b981) 4%,var(--isis-surface-alt)); border:1px dashed color-mix(in srgb,var(--isis-mod-sirh,#10b981) 35%,var(--isis-border)); border-radius:var(--isis-radius); padding:12px 14px; }
.isis-orgnode__preview-lbl { font-size:10.5px; text-transform:uppercase; letter-spacing:.04em; color:var(--isis-mod-sirh,#047857); font-weight:700; margin-bottom:8px; }
.isis-orgnode__path { display:flex; align-items:center; gap:7px; flex-wrap:wrap; font-size:12px; }
.isis-orgnode__crumb { display:inline-flex; align-items:center; gap:6px; background:var(--isis-surface); border:1px solid var(--isis-border); border-radius:999px; padding:3px 10px; }
.isis-orgnode__crumb--new { border-color:var(--isis-mod-sirh,#10b981); background:color-mix(in srgb,var(--isis-mod-sirh,#10b981) 14%,var(--isis-surface)); color:var(--isis-mod-sirh,#047857); font-weight:700; border-style:dashed; }
.isis-orgnode__arr { color:var(--isis-text-muted); }
.isis-orgnode__chip { font-size:9.5px; padding:1px 7px; border-radius:999px; font-weight:700; }
.isis-orgnode__chip--jur { background:var(--jur-soft); color:var(--jur-ink); }
.isis-orgnode__chip--tech { background:var(--tech-soft); color:var(--tech-ink); }

.isis-orgnode__actions { display:flex; align-items:center; gap:10px; padding-top:14px; border-top:1px solid var(--isis-border); margin-top:6px; }
.isis-orgnode__note { font-size:11px; color:var(--isis-text-muted); flex:1; }
.isis-pivot-wrap {
    --pj:#5b4be6; --pj-soft:#ece9fe; --pj-ink:#4338ca;
    --pt:#0d9488; --pt-soft:#d2f3ef; --pt-ink:#0f766e;
    --pg:#7c3aed; --pg-soft:#ede9fe;
    --pmgr:#facc15; --pconn:2px;
    display:block; padding:4px 8px 32px;
}
.isis-pivot__legend { display:flex; gap:16px; align-items:center; font-size:11.5px; color:var(--isis-text-muted); margin-bottom:10px; flex-wrap:wrap; }
.isis-pivot__legend-i { display:inline-flex; align-items:center; gap:6px; }
.isis-pivot__sw { width:11px; height:11px; border-radius:3px; display:inline-block; }
.isis-pivot__sw--jur { background:var(--pj); }
.isis-pivot__sw--tech { background:var(--pt); }
.isis-pivot__sw--mgr { background:var(--pmgr); border-radius:50%; }

.isis-pivot__axiscap { display:flex; justify-content:space-between; align-items:center; max-width:1180px; width:100%; margin:0 auto 4px; padding:0 4px; }
.isis-pivot__axislbl { display:inline-flex; align-items:center; gap:7px; font-size:11px; text-transform:uppercase; letter-spacing:.05em; font-weight:700; }
.isis-pivot__axislbl--jur { color:var(--pj); }
.isis-pivot__axislbl--tech { color:var(--pt); }
.isis-pivot__axislbl i { width:9px; height:9px; border-radius:50%; display:inline-block; }
.isis-pivot__axislbl--jur i { background:var(--pj); }
.isis-pivot__axislbl--tech i { background:var(--pt); }
.isis-pivot__axismid { font-size:11px; color:var(--isis-text-muted); }

.isis-pivot__stage { position:relative; width:100%; max-width:1180px; margin:0 auto; }
.isis-pivot__stage::before { content:""; position:absolute; left:50%; top:42px; bottom:24px; width:var(--pconn); background:var(--isis-border); transform:translateX(-50%); z-index:0; }

.isis-pivot__group { display:flex; justify-content:center; margin-bottom:6px; }
/* Chaîne d'ascendance (groupe → entreprises parentes) sur l'épine centrale, toujours visible.
   Réutilise le style de la carte groupe (.isis-pivot__grpcard) — cf. maquette enrichie. */
.isis-pivot__ancestry { display:flex; flex-direction:column; align-items:center; gap:6px; margin-bottom:6px; position:relative; z-index:2; }
.isis-pivot__ancestor { cursor:pointer; text-align:left; }
.isis-pivot__ancestor:hover { border-color:var(--isis-text-muted); }
.isis-pivot__grpcard { display:inline-flex; align-items:center; gap:11px; background:var(--isis-surface); border:1px solid var(--isis-border); border-radius:var(--isis-radius); box-shadow:var(--isis-elevation-2,var(--isis-elevation-1)); padding:11px 18px; position:relative; z-index:2; }
.isis-pivot__gi { width:34px; height:34px; border-radius:9px; background:var(--pg-soft); color:var(--pg); display:flex; align-items:center; justify-content:center; }
.isis-pivot__gn { font-weight:700; font-size:15px; display:flex; align-items:center; gap:8px; }
.isis-pivot__gm { font-size:11.5px; color:var(--isis-text-muted); }

.isis-pivot__chip { font-size:10px; padding:2px 8px; border-radius:999px; font-weight:700; letter-spacing:.02em; white-space:nowrap; }
.isis-pivot__chip--grp { background:var(--pg-soft); color:var(--pg); }
.isis-pivot__chip--jur { background:var(--pj-soft); color:var(--pj-ink); }
.isis-pivot__chip--tech { background:var(--pt-soft); color:var(--pt-ink); }

/* Ailes en minmax(280px,…) : ne s'effondrent pas sous la largeur d'une carte
   d'agence/activité → sur écran étroit, l'organigramme défile (conteneur
   .isis-pivot-scroll overflow:auto) au lieu de comprimer et chevaucher. */
.isis-pivot__lane { display:grid; grid-template-columns:minmax(280px,1fr) 30px 260px 30px minmax(280px,1fr); align-items:center; position:relative; }
.isis-pivot__lane + .isis-pivot__lane { margin-top:6px; }

.isis-pivot__branch { display:flex; flex-direction:column; gap:9px; padding:14px 0; }
.isis-pivot__branch--jur { grid-column:1; align-items:flex-end; }
.isis-pivot__branch--tech { grid-column:5; align-items:flex-start; }

.isis-pivot__bus { position:relative; align-self:stretch; justify-self:center; width:var(--pconn); border-radius:2px; margin:26px 0; }
.isis-pivot__bus--jur { grid-column:2; background:var(--pj); opacity:.4; }
.isis-pivot__bus--tech { grid-column:4; background:var(--pt); opacity:.4; }
.isis-pivot__bus--jur::after, .isis-pivot__bus--tech::after { content:""; position:absolute; top:50%; width:30px; height:var(--pconn); transform:translateY(-50%); }
.isis-pivot__bus--jur::after { left:100%; background:var(--pj); }
.isis-pivot__bus--tech::after { right:100%; background:var(--pt); }

.isis-pivot__centre { grid-column:3; justify-self:center; width:100%; position:relative; z-index:2; }
.isis-pivot__centre::before { content:""; position:absolute; left:50%; top:-14px; width:var(--pconn); height:14px; background:var(--isis-border); transform:translateX(-50%); }
.isis-pivot__pivot-btn { width:100%; text-align:left; background:var(--isis-surface); border:1.5px solid color-mix(in srgb, var(--isis-mod-sirh,#10b981) 35%, var(--isis-border)); border-radius:var(--isis-radius); box-shadow:var(--isis-elevation-2,var(--isis-elevation-1)); padding:13px 15px; cursor:pointer; display:block; }
.isis-pivot__pivot-h { display:flex; align-items:center; gap:9px; }
.isis-pivot__pivot-ic { width:30px; height:30px; border-radius:8px; background:color-mix(in srgb, var(--isis-mod-sirh,#10b981) 16%, var(--isis-surface)); color:var(--isis-mod-sirh,#0f766e); display:flex; align-items:center; justify-content:center; flex:none; }
.isis-pivot__pivot-head { display:flex; flex-direction:column; gap:1px; }
.isis-pivot__pivot-nm { font-weight:700; font-size:15px; display:flex; align-items:center; gap:8px; }
.isis-pivot__pivot-sub { font-size:11px; color:var(--isis-text-muted); }
.isis-pivot__stats { display:flex; gap:0; margin-top:11px; border-top:1px solid var(--isis-border); padding-top:9px; }
.isis-pivot__stat { flex:1; text-align:center; }
.isis-pivot__stat + .isis-pivot__stat { border-left:1px solid var(--isis-border); }
.isis-pivot__stat-v { font-weight:700; font-family:'Geist Mono',ui-monospace,monospace; font-variant-numeric:tabular-nums; font-size:14px; display:block; }
.isis-pivot__stat-v.is-jur { color:var(--pj); }
.isis-pivot__stat-v.is-tech { color:var(--pt); }
.isis-pivot__stat-k { font-size:9.5px; color:var(--isis-text-muted); text-transform:uppercase; letter-spacing:.04em; }

.isis-pivot__unit { display:flex; align-items:center; gap:10px; background:var(--isis-surface); border:1px solid var(--isis-border); border-radius:var(--isis-radius-sm); box-shadow:var(--isis-elevation-1); padding:9px 12px; position:relative; cursor:pointer; width:280px; max-width:300px; text-align:left; }
.isis-pivot__unit:hover { border-color:var(--isis-text-muted); }
.isis-pivot__unit-ic { width:28px; height:28px; border-radius:7px; display:flex; align-items:center; justify-content:center; flex:none; }
.isis-pivot__unit--jur .isis-pivot__unit-ic { background:var(--pj-soft); color:var(--pj-ink); }
.isis-pivot__unit--tech .isis-pivot__unit-ic { background:var(--pt-soft); color:var(--pt-ink); }
.isis-pivot__unit-main { flex:1; min-width:0; display:flex; flex-direction:column; }
.isis-pivot__unit-nm { font-weight:600; font-size:12.5px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.isis-pivot__unit-meta { font-size:11px; color:var(--isis-text-muted); display:flex; align-items:center; gap:5px; }
.isis-pivot__mgr { display:inline-flex; align-items:center; gap:5px; }
.isis-pivot__mgr i { width:6px; height:6px; border-radius:50%; background:var(--pmgr); display:inline-block; }
.isis-pivot__unit-cnt { font-family:'Geist Mono',ui-monospace,monospace; font-variant-numeric:tabular-nums; font-size:11.5px; color:var(--isis-text-muted); background:var(--isis-surface-alt); border-radius:999px; padding:2px 8px; }
.isis-pivot__unit::after { content:""; position:absolute; top:50%; width:16px; height:var(--pconn); transform:translateY(-50%); }
.isis-pivot__unit--jur::after { right:-16px; background:var(--pj); opacity:.4; }
.isis-pivot__unit--tech::after { left:-16px; background:var(--pt); opacity:.4; }

.isis-pivot__empty { font-size:11.5px; color:var(--isis-text-muted); font-style:italic; border:1px dashed var(--isis-border); border-radius:var(--isis-radius-sm); padding:9px 14px; }

/* chemin tracé : tout s'atténue sauf le chemin du collaborateur sélectionné */
.isis-pivot__stage.is-traced .isis-pivot__unit { opacity:.4; }
.isis-pivot__stage.is-traced .isis-pivot__unit.on { opacity:1; border-color:var(--isis-mod-sirh,#10b981); box-shadow:0 0 0 2px color-mix(in srgb, var(--isis-mod-sirh,#10b981) 22%, transparent), var(--isis-elevation-1); }
.isis-pivot__stage.is-traced .isis-pivot__centre.on .isis-pivot__pivot-btn { box-shadow:0 0 0 2px color-mix(in srgb, var(--isis-mod-sirh,#10b981) 22%, transparent), var(--isis-elevation-2,var(--isis-elevation-1)); }
.isis-pivot__stage.is-traced .isis-pivot__bus, .isis-pivot__stage.is-traced .isis-pivot__bus::after { opacity:.12; }
.isis-pivot__stage.is-traced .isis-pivot__unit.on::after { opacity:1; background:var(--isis-mod-sirh,#10b981); height:3px; }

/* — Aile technique : activité = mini-pivot, services à droite (enrichi 2026-06-19) — */
.isis-pivot__acti-group { display:flex; align-items:center; }
/* aile juridique récursive (OrgJuridiqueNode) : groupe = miroir de .acti-group
   (unité à DROITE, enfants imbriqués vers la GAUCHE — le wing juridique est à gauche). */
.isis-pivot__jur-group { display:flex; align-items:center; flex-direction:row-reverse; }
.isis-pivot__svc-wrap { display:flex; align-items:stretch; margin-left:28px; position:relative; }
.isis-pivot__svc-wrap::before { content:""; position:absolute; left:-28px; top:50%; width:28px; height:var(--pconn); background:var(--pt); opacity:.4; transform:translateY(-50%); }
.isis-pivot__svc-bus { width:var(--pconn); background:var(--pt); opacity:.4; border-radius:2px; margin:8px 16px 8px 0; flex:none; }
.isis-pivot__svc-stack { display:flex; flex-direction:column; gap:6px; }
.isis-pivot__svc-stack .isis-pivot__unit { width:230px; max-width:230px; }
.isis-pivot__svc-stack .isis-pivot__unit::after { content:""; position:absolute; top:50%; left:-16px; width:16px; height:var(--pconn); background:var(--pt); opacity:.4; transform:translateY(-50%); }

/* — MIROIR juridique de svc-wrap/bus/stack : enfants vers la GAUCHE, connecteurs à droite, couleur var(--pj) — */
.isis-pivot__svc-wrap--jur { margin-left:0; margin-right:28px; flex-direction:row-reverse; }
.isis-pivot__svc-wrap--jur::before { left:auto; right:-28px; background:var(--pj); }
.isis-pivot__svc-wrap--jur > .isis-pivot__svc-bus { background:var(--pj); margin:8px 0 8px 16px; }
.isis-pivot__svc-wrap--jur .isis-pivot__svc-stack { align-items:flex-end; }
.isis-pivot__svc-wrap--jur .isis-pivot__svc-stack .isis-pivot__unit::after { left:auto; right:-16px; background:var(--pj); }
/* largeur uniforme de tous les éléments juridiques (top-niveau + imbriqués), comme l'aile technique */
.isis-pivot__branch--jur .isis-pivot__unit { width:252px; max-width:252px; }

/* — Icône « ouvrir la fiche » (survol) — vrais <button> (clavier-accessibles) — */
.isis-pivot__open { margin-left:4px; color:var(--isis-text-muted); opacity:0; cursor:pointer; display:flex; align-items:center; transition:opacity .12s,color .12s; background:none; border:0; padding:0; font:inherit; }
.isis-pivot__open:focus-visible { opacity:1; outline:2px solid var(--isis-mod-sirh,#10b981); outline-offset:2px; border-radius:4px; }
.isis-pivot__unit:hover .isis-pivot__open, .isis-pivot__unit:focus-within .isis-pivot__open { opacity:1; }
.isis-pivot__ag-head:hover .isis-pivot__open, .isis-pivot__ag-head:focus-within .isis-pivot__open { opacity:1; }
.isis-pivot__open:hover { color:var(--isis-mod-sirh,#10b981); }
.isis-pivot__more {
    display: inline-flex; align-items: center; gap: .25rem;
    margin: .15rem 0 .15rem .2rem; padding: .15rem .5rem;
    font-size: var(--isis-fs-xs); color: var(--isis-text-muted);
    background: var(--isis-surface-2, var(--isis-surface-alt)); border: 1px dashed var(--isis-border);
    border-radius: var(--isis-radius-sm); cursor: pointer;
}
.isis-pivot__more:hover { color: var(--isis-current-mod); border-color: var(--isis-current-mod); }
.isis-pivot__unit[role="button"]:focus-visible {
    outline: 2px solid color-mix(in oklch, var(--isis-current-mod) 60%, transparent);
    outline-offset: 2px;
    border-radius: var(--isis-radius-sm);
}

/* Groupe d'actions du pivot entreprise (ancré en haut-droite ; .isis-pivot__centre
   est position:relative). Le corps de la carte n'est plus cliquable : ouvrir la
   fiche se fait via ce bouton ↗ (toujours visible, action principale), + repli en Hiérarchie. */
.isis-pivot__pivot-actions { position:absolute; top:8px; right:8px; display:flex; align-items:center; gap:6px; z-index:3; }
.isis-pivot__pivot-actions .isis-pivot__open { opacity:1; margin:0; width:24px; height:24px; justify-content:center; border:1px solid var(--isis-border); border-radius:var(--isis-radius-sm); background:var(--isis-surface-alt); color:var(--isis-text-muted); }
.isis-pivot__pivot-actions .isis-pivot__open:hover { background:var(--isis-mod-sirh-soft,#d1fae5); color:var(--isis-mod-sirh,#0f766e); border-color:transparent; }
.isis-pivot__pivot-actions .pivot__exp--float { position:static; top:auto; right:auto; }
/* En mode Hiérarchie (.otree), la règle `.otree .pivot__exp--float { position:absolute }`
   (même spécificité, déclarée plus bas) reprenait le dessus et superposait le bouton
   « réduire » au bouton « ↗ ouvrir la fiche ». On force le placement en flux dans la
   barre d'actions avec une spécificité supérieure (3 classes). */
.otree .isis-pivot__pivot-actions .pivot__exp--float { position:static; top:auto; right:auto; width:24px; height:24px; }

/* === Carte entreprise (épine) : anti-chevauchements ===
   1) L'en-tête réserve la place de la barre d'actions absolue (↗ ouvrir + réduire),
      sinon un nom long passe SOUS les boutons (visible surtout en Pivoté 90° où la
      carte est large et le nom tient sur une ligne).
   2) La carte ne doit pas déborder de sa colonne (260px) et empiéter sur les
      activités : on lève le `min-width:auto` du conteneur grille et on autorise le
      contenu (nom + statistiques) à se contraindre / passer à la ligne. */
.isis-pivot__pivot-h { padding-right:52px; min-width:0; }
.isis-pivot__centre { min-width:0; }
/* box-sizing:border-box impératif : la carte est en content-box dans ce contexte,
   donc width:100% (=260px) + padding + bordure débordait à ~292px et empiétait sur
   les activités. En border-box la carte tient exactement dans sa colonne. */
.isis-pivot__pivot-btn { min-width:0; max-width:100%; box-sizing:border-box; }
.isis-pivot__pivot-head { min-width:0; }
.isis-pivot__pivot-nm { min-width:0; }
.isis-pivot__stats { flex-wrap:wrap; }

/* — Carte agence : en-tête + récap cross-axe — */
.isis-pivot__unit--agence { flex-direction:column; align-items:stretch; gap:0; padding:0; cursor:default; }
.isis-pivot__ag-head { display:flex; align-items:center; gap:10px; padding:9px 12px; cursor:pointer; }
.isis-pivot__ag-head .isis-pivot__unit-main { flex:1; }
.isis-pivot__ag-recap { border-top:1px dashed var(--isis-border); padding:7px 12px 9px; background:color-mix(in srgb, var(--pj) 3%, var(--isis-surface)); }
.isis-pivot__ag-recap-h { font-size:9.5px; text-transform:uppercase; letter-spacing:.04em; color:var(--isis-text-muted); font-weight:700; margin-bottom:5px; display:flex; justify-content:space-between; }
.isis-pivot__ag-row { display:flex; align-items:center; gap:7px; font-size:11.5px; padding:2px 4px; margin:0 -4px; border-radius:4px; cursor:pointer;
    padding-left: calc(0.4rem + var(--recap-depth, 0) * 0.7rem); }
.isis-pivot__ag-row .isis-pivot__ag-dot { width:7px; height:7px; border-radius:2px; background:var(--pt); flex:none; }
.isis-pivot__ag-row--svc { color:var(--isis-text-muted); font-size:11px; }
.isis-pivot__ag-row--svc .isis-pivot__ag-dot { width:5px; height:5px; border-radius:50%; opacity:.6; }
.isis-pivot__ag-nm { flex:1; min-width:0; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.isis-pivot__ag-bar { height:5px; border-radius:3px; background:var(--pt); opacity:.5; }
.isis-pivot__ag-cnt { font-family:'Geist Mono',ui-monospace,monospace; color:var(--isis-text-muted); font-size:11px; }
.isis-pivot__ag-row.is-sel { 
    padding-left: calc(0.4rem + var(--recap-depth, 0) * 0.7rem - 2px); }
.isis-pivot__ag-row:focus-visible { outline: 2px solid color-mix(in oklch, var(--isis-current-mod) 55%, transparent); outline-offset: 1px; }

/* — Surbrillance cross-axe (sélection activité/service) — pivot « À plat » ET arbre « Hiérarchie » (.otree) — */
:is(.isis-pivot__stage, .otree).is-selecting .isis-pivot__unit,
:is(.isis-pivot__stage, .otree).is-selecting .isis-pivot__centre .isis-pivot__pivot-btn { opacity:.30; }
:is(.isis-pivot__stage, .otree).is-selecting .isis-pivot__unit.is-sel { opacity:1; box-shadow:0 0 0 2px color-mix(in srgb, var(--isis-mod-sirh,#10b981) 22%, transparent), var(--isis-elevation-1); }
:is(.isis-pivot__stage, .otree).is-selecting .isis-pivot__centre.is-sel .isis-pivot__pivot-btn { opacity:1; box-shadow:0 0 0 2px color-mix(in srgb, var(--isis-mod-sirh,#10b981) 22%, transparent), var(--isis-elevation-2,var(--isis-elevation-1)); }
:is(.isis-pivot__stage, .otree).is-selecting .isis-pivot__bus,
:is(.isis-pivot__stage, .otree).is-selecting .isis-pivot__svc-bus { opacity:.12; }
:is(.isis-pivot__stage, .otree).is-selecting .isis-pivot__ag-recap { opacity:.45; }
:is(.isis-pivot__stage, .otree).is-selecting .isis-pivot__unit--agence.is-sel .isis-pivot__ag-recap { opacity:1; }
:is(.isis-pivot__stage, .otree).is-selecting .isis-pivot__unit--agence.is-sel .isis-pivot__ag-row { opacity:.4; }
:is(.isis-pivot__stage, .otree).is-selecting .isis-pivot__unit--agence.is-sel .isis-pivot__ag-row.is-sel { opacity:1; background:color-mix(in srgb, var(--isis-mod-sirh,#10b981) 14%, transparent); }

@media (max-width:1080px) {
    /* on resserre légèrement bus/pivot mais on garde des ailes non-effondrables
       (≥280px) : pas de chevauchement, défilement horizontal si nécessaire. */
    .isis-pivot__lane { grid-template-columns:minmax(280px,1fr) 22px 240px 22px minmax(280px,1fr); }
}
.isis-orgchart-legend__swatch.is-manager {
    border-left-color: var(--isis-manager-color);
}
.isis-orgchart-legend__swatch.is-nonmanager {
    border-left-color: var(--isis-border);
}
.isis-orgchart-legend__hint {
    margin-left: auto;
    color: var(--isis-text-soft);
    font-style: italic;
}

.isis-orgchart-empty {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    padding: 3rem 1rem;
    color: var(--isis-text-soft);
    text-align: center;
}
.isis-orgchart-empty .rzi { font-size: 32px; opacity: 0.4; }

/* ============================================================================
   .isis-grid--collaborateurs — Grille de l'effectif sirh
   Colonnes : status | identity | poste | structure | contrat | embauche | état | actions
   La colonne actions accueille 3 boutons (ouvrir / lier compte / modifier) :
   3 × 28px + 2 × 4px gap ≈ 92px, on prend 110px avec marge.
   ============================================================================ */
.isis-grid--collaborateurs .isis-grid__head,
.isis-grid--collaborateurs .isis-grid__row {
    /* « Embauche » (110px) portait déjà « Embauche » + sa flèche de tri : l'entonnoir de
       plage ajouté le 2026-09-04 débordait sur la colonne voisine, dont le bouton « Trier
       par état » interceptait alors le clic (mesuré au navigateur, pas déduit du markup).
       140px la tiennent. « Contrat » reste à 90px : son entonnoir y entre (libellé court,
       pas de bouton de tri) — l'élargir en pure symétrie aurait poussé une colonne de plus
       hors du champ visible dans la vue maître-détail. */
    grid-template-columns: 32px minmax(240px, 1.8fr) minmax(160px, 1.4fr) minmax(140px, 1fr) minmax(140px, 1fr) 90px 140px 100px 110px;
    min-width: 1310px;
}

/* Status dots pour l'état du collaborateur */
.isis-grid__status-dot.is-actif    { background: #10b981; }
.isis-grid__status-dot.is-suspendu { background: #f59e0b; }
.isis-grid__status-dot.is-sorti    { background: #9ca3af; }

/* Cellule identité combinée : avatar + nom + sous-ligne */
.isis-grid__col-identity {
    display: flex !important;
    align-items: center;
    gap: 0.6rem;
    overflow: hidden !important;
}
.isis-grid__avatar {
    flex-shrink: 0;
    width: 32px;
    height: 32px;
    border-radius: 50%;
    background: var(--isis-mod-sirh-soft, #ecfdf5);
    color: var(--isis-mod-sirh, #10b981);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 0.72rem;
    font-weight: 600;
    letter-spacing: 0.05em;
}
.isis-grid__avatar--photo {
    background: transparent;
    object-fit: cover;
    border: 1px solid var(--isis-border);
}

/* Composant uploader photo (form dialog collaborateur) */
.isis-photo-uploader {
    display: flex;
    align-items: center;
    gap: 1rem;
}
.isis-photo-uploader__preview {
    flex-shrink: 0;
    width: 96px;
    height: 96px;
    border-radius: 50%;
    background: var(--isis-mod-sirh-soft, #ecfdf5);
    border: 1px solid var(--isis-border);
    overflow: hidden;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
.isis-photo-uploader__preview img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}
.isis-photo-uploader__initials {
    color: var(--isis-mod-sirh, #10b981);
    font-size: 1.4rem;
    font-weight: 600;
    letter-spacing: 0.06em;
}
.isis-photo-uploader__actions {
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
    flex: 1;
    min-width: 0;
}
.isis-photo-uploader__btn {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.4rem 0.7rem;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: 6px;
    color: var(--isis-text);
    font-size: 0.8rem;
    font-weight: 500;
    cursor: pointer;
    width: fit-content;
    transition: background-color 120ms, color 120ms, border-color 120ms;
}
.isis-photo-uploader__btn:hover {
    background: var(--isis-surface-alt);
    border-color: var(--isis-accent);
    color: var(--isis-accent);
}
.isis-photo-uploader__btn--ghost {
    color: var(--isis-text-muted);
}
.isis-photo-uploader__btn--ghost:hover {
    color: #dc2626;
    border-color: #dc2626;
}
.isis-photo-uploader__busy {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    font-size: 0.78rem;
    color: var(--isis-text-muted);
}

.isis-grid__identity-block {
    display: flex;
    flex-direction: column;
    gap: 1px;
    overflow: hidden;
    min-width: 0;
}
.isis-grid__identity-name {
    font-weight: 500;
    color: var(--isis-text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.isis-grid__identity-sub {
    font-size: 0.72rem;
    color: var(--isis-text-muted);
    display: flex;
    align-items: center;
    gap: 0.35rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.isis-grid__matricule {
    font-family: var(--isis-font-mono, ui-monospace, monospace);
    color: var(--isis-text-muted);
    font-weight: 500;
}
.isis-grid__identity-dot { opacity: 0.5; }
.isis-grid__cell-hint {
    font-size: 0.7rem;
    color: var(--isis-text-soft);
    margin-top: 2px;
}
.isis-grid__col-structure { color: var(--isis-text-muted); }
.isis-grid__col-date {
    font-variant-numeric: tabular-nums;
    color: var(--isis-text-muted);
    font-size: 0.78rem;
}

/* Side panel détail collaborateur (réutilisé : avatar XL + identité, blocs section) */
.isis-detail-collab-head {
    display: flex;
    align-items: center;
    gap: 0.85rem;
}
.isis-detail-collab-head__avatar {
    width: 48px !important;
    height: 48px !important;
    font-size: 1rem !important;
}
.isis-detail-collab-head__main {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    min-width: 0;
}
.isis-detail-collab-head__meta {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-wrap: wrap;
}
.isis-detail-block {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    padding-top: 0.5rem;
    border-top: 1px dashed var(--isis-border);
}
.isis-detail-block:first-child { border-top: none; padding-top: 0; }
.isis-detail-block__title {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--isis-text-soft);
    font-weight: 600;
}
/* Mini-listes d'un bloc de volet : offres liées, points de préparation, activité récente.
   Une seule famille pour les trois — leur forme est la même (un libellé qui peut envelopper,
   une méta courte à droite), et trois familles auraient divergé au premier ajustement. */
.isis-detail-lines {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
}
.isis-detail-lines__line {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.5rem;
    font-size: 0.82rem;
    line-height: 1.35;
}
/* L'activité empile : « Modification · Remise » puis la date et l'auteur, qui ne tiennent pas
   sur la même ligne que le libellé dans 300 px. */
.isis-detail-lines__line--stacked {
    flex-direction: column;
    align-items: stretch;
    gap: 0.05rem;
}
.isis-detail-lines__main {
    min-width: 0;
    overflow-wrap: anywhere;
}
.isis-detail-lines__meta {
    flex: 0 0 auto;
    color: var(--isis-text-soft);
    font-size: 0.76rem;
}
/* Cible de 24 px de haut (WCAG 2.2, 2.5.8 AA). Le calage est porté par le LIEN et non par la
   ligne : celle-ci aligne sur `baseline`, un `min-height` posé sur le `li` laisserait la boîte
   du lien à la hauteur de son texte, soit ~18 px. */
.isis-detail-lines a.isis-detail-lines__main {
    display: inline-flex;
    align-items: center;
    min-height: 24px;
}
.isis-detail-lines__meta--warn { color: var(--isis-warning-text); }
.isis-detail-lines__empty {
    margin: 0;
    font-size: 0.8rem;
    color: var(--isis-text-soft);
}

.isis-detail-link {
    color: var(--isis-accent);
    text-decoration: none;
}
.isis-detail-link:hover { text-decoration: underline; }
.isis-detail-collab-hint {
    color: var(--isis-text-soft);
    font-size: 0.78rem;
    margin-left: 0.25rem;
}

/* Select natif dans la barre de filtres (theming Flat aligné sur l'input search) */
.isis-filter-bar__select {
    display: flex;
    align-items: center;
}
.isis-filter-bar__select select {
    appearance: none;
    -webkit-appearance: none;
    padding: 0.45rem 1.8rem 0.45rem 0.7rem;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: 6px;
    color: var(--isis-text);
    font-size: 0.8rem;
    cursor: pointer;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%236b7280' width='14' height='14'%3E%3Cpath d='M7 10l5 5 5-5z'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 0.5rem center;
    transition: border-color 120ms;
}
.isis-filter-bar__select select:hover { border-color: var(--isis-accent); }
.isis-filter-bar__select select:focus {
    outline: none;
    border-color: var(--isis-accent);
}

/* ============================================================================
   .isis-grid--users — Grille des utilisateurs (admin)
   Colonnes : status | identity | modules | derniere conn. | fin d'acces | etat | invitation | e-mail | actions
   Invitation et E-mail masquées d'office (configurateur, réaffichables) : la liste tient
   à côté de l'aperçu sans défilement horizontal.
   ============================================================================ */
.isis-grid--users .isis-grid__head,
.isis-grid--users .isis-grid__row {
    grid-template-columns: 32px minmax(150px, 1.6fr) minmax(120px, 1.4fr) 150px 96px 100px 120px 128px 80px;
    min-width: 990px;
    --isis-grid-default-hidden: 7 8;
}

/* Avatar variante admin (gris neutre) — réutilise .isis-grid__avatar.
   Texte en gris foncé (#374151) pour contraste WCAG AA sur fond #f3f4f6 (~9.5:1). */
.isis-grid--users .isis-grid__avatar {
    background: var(--isis-mod-admin-soft);
    color: #374151;
}

/* Status dots utilisateurs */
.isis-grid__status-dot.is-inactif { background: #9ca3af; }

/* Variante admin du side panel (avatar XL) */
.isis-detail-collab-head--admin .isis-detail-collab-head__avatar {
    background: var(--isis-mod-admin-soft) !important;
    color: #374151 !important;
}

/* Wrap des badges modules dans la ligne de grille */
.isis-grid__col-modules {
    display: flex !important;
    flex-wrap: wrap;
    gap: 0.25rem;
    align-items: center;
    overflow: hidden;
}

/* Wrap des chips de tags dans la ligne de grille (même patron que .isis-grid__col-modules) —
   la classe est posée sur la CELLULE elle-même (`<div role="cell" class="isis-grid__col-tags">`),
   pas sur un <ul> niché dans un <div role="cell"> nu : une cellule nue ne porte que
   `.isis-grid__row > div` (padding + overflow:hidden + white-space:nowrap, aucune notion de
   flex-wrap) tandis que le flex-wrap grandissait sur un enfant que son parent ne suivait pas —
   dès 3 tags (2 lignes de chips à 28px), le débordement échappait à la cellule et empiétait sur
   le panneau suivant (bug recette 2026-09-12, catalogue d'activités). Le `role="list"` (requis
   par un audit a11y antérieur — `list-style:none` supprime la sémantique de liste implicite de
   l'<ul>) reste porté par l'<ul> interne, qui passe en `display: contents` : plus de boîte
   visuelle propre (donc plus de risque de clipping), ses <li> deviennent directement des items
   flex du div externe, et `display: contents` préserve la sémantique ARIA de liste dans les
   navigateurs actuels — round 2, 2026-09-12. Padding repris du patron `.isis-grid__row > div`
   pour rester aligné avec les cellules voisines. */
.isis-grid__col-tags {
    display: flex !important;
    flex-wrap: wrap;
    gap: 0.25rem;
    align-items: center;
    overflow: hidden;
    padding: 0.35rem 0.35rem;
}

/* ============================================================================
   .isis-grid--equipe — variante équipe gescom
   Colonnes : status | membre | login | statut | autorité | manager | actions
   ============================================================================ */
.isis-grid--equipe .isis-grid__head,
.isis-grid--equipe .isis-grid__row {
    grid-template-columns: 32px minmax(220px, 1.6fr) 160px 130px 140px minmax(180px, 1.2fr) 110px;
    min-width: 980px;
}
.isis-grid__status-dot.is-active       { background: #10b981; }
.isis-grid__status-dot.is-inactive     { background: #f59e0b; }
.isis-grid__status-dot.is-not-activated { background: #9ca3af; }

.isis-equipe-member {
    display: inline-flex;
    align-items: center;
    gap: 0.6rem;
    min-width: 0;
}
.isis-equipe-member__avatar {
    width: 28px;
    height: 28px;
    border-radius: 50%;
    background: var(--isis-mod-gescom-soft);
    color: var(--isis-mod-gescom);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 0.7rem;
    font-weight: 600;
    letter-spacing: 0.02em;
    flex-shrink: 0;
}
.isis-equipe-member__name {
    font-weight: 500;
    color: var(--isis-text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.isis-equipe-money {
    font-variant-numeric: tabular-nums;
    color: var(--isis-text);
    font-weight: 500;
}
.isis-equipe-illimite {
    color: var(--isis-mod-gescom);
    font-weight: 500;
    font-style: italic;
}
.isis-grid__action-btn--primary {
    color: var(--isis-current-mod, var(--isis-accent));
}
.isis-grid__action-btn--primary:hover {
    background: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 14%, transparent);
}
/* État acquis (ex. lien de stockage renseigné sur un livrable). */
.isis-grid__action-btn.is-ok {
    color: var(--isis-success);
}
.isis-grid__action-btn--danger {
    color: var(--rz-danger, #dc2626);
}
.isis-grid__action-btn--danger:hover {
    background: var(--rz-danger-lighter, #fef2f2);
}
/* Inerte par aria-disabled (cf. .isis-rich-toolbar__btn) : la raison reste au survol et au clavier. */
.isis-grid__action-btn[aria-disabled="true"] {
    opacity: 0.4;
    cursor: not-allowed;
}
.isis-grid__action-btn[aria-disabled="true"]:hover {
    background: transparent;
}
/* L'opacité atténuerait aussi l'anneau de focus : au clavier, seule l'icône reste éteinte. */
.isis-grid__action-btn[aria-disabled="true"]:focus-visible {
    opacity: 1;
    color: var(--isis-text-muted);
}

/* Sprint F.2 — action-btn dans état "actif" (= des données associées existent).
   Ex : bouton compétences avec compteur > 0. */
.isis-grid__action-btn--active {
    color: var(--isis-current-mod, var(--isis-accent));
    position: relative;
}
.isis-grid__action-btn--active:hover {
    background: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 14%, transparent);
}
.isis-grid__action-btn__badge {
    position: absolute;
    top: -4px;
    right: -4px;
    min-width: 14px;
    height: 14px;
    padding: 0 3px;
    font-size: 0.6rem;
    font-weight: 700;
    line-height: 14px;
    text-align: center;
    background: var(--isis-current-mod, var(--isis-accent));
    color: white;
    border-radius: var(--isis-radius-pill);
}
.isis-grid__action-btn--success {
    color: var(--isis-success);
}
.isis-grid__action-btn--success:hover {
    background: color-mix(in srgb, var(--isis-success) 14%, transparent);
}
/* Bouton d'action portant un libellé (icône + texte), hors des 28×28 fixes de la grille —
   même relâchement que .isis-offer-selbar .isis-grid__action-btn, généralisé en modificateur
   réutilisable (2026-09-03 : page Intégration RH, boutons Masquer/Afficher + Salariés/Absences). */
.isis-grid__action-btn--label {
    width: auto;
    height: auto;
    gap: 0.35rem;
    padding: 0.2rem 0.55rem;
    font-size: 0.78rem;
    color: var(--isis-text);
}
/* Task 17, ronde 1 : combiné à --danger (ex. « Révoquer » sur un appareil de confiance),
   --label écrasait la couleur rouge (même spécificité, déclarée après --danger dans la
   feuille) — confirmé au navigateur, le bouton perdait sa couleur d'action destructive. Les
   deux classes ensemble portent une spécificité supérieure à chacune seule, donc gagnent
   sans dépendre de l'ordre des règles. */
.isis-grid__action-btn--label.isis-grid__action-btn--danger {
    color: var(--rz-danger, #dc2626);
}
.isis-grid__action-btn--label.isis-grid__action-btn--danger:hover {
    background: var(--rz-danger-lighter, #fef2f2);
}

/* ============================================================================
   Règles d'approbation — un modificateur par page (les deux écrans n'ont pas les mêmes
   colonnes ; une variante partagée de 7 pistes faisait retomber les cellules gescom).
   ============================================================================ */
/* gesst — 7 col : pastille statut | Priorité | Prestataire | Libellé | Seuil TTC | Niveaux |
   actions. */
.isis-grid--regles-gesst .isis-grid__head,
.isis-grid--regles-gesst .isis-grid__row {
    grid-template-columns: 32px 80px minmax(200px, 1.3fr) minmax(220px, 1.6fr) 130px 90px 110px;
    min-width: 980px;
}
/* gescom — 6 col : pastille statut | Priorité | Nom | Conditions | Approbateur | actions. */
.isis-grid--regles-gescom .isis-grid__head,
.isis-grid--regles-gescom .isis-grid__row {
    grid-template-columns: 32px 80px minmax(200px, 1.3fr) minmax(220px, 1.6fr) minmax(160px, 1fr) 120px;
    min-width: 900px;
}

/* ============================================================================
   .isis-grid--statuts-opportunite — référentiel gesmaff, catalogue statuts d'Opportunité
   Colonnes : Code | Libellé | Ordre | Initial | Issue | Actif | actions   (7 colonnes)
   ============================================================================ */
.isis-grid--statuts-opportunite .isis-grid__head,
.isis-grid--statuts-opportunite .isis-grid__row {
    /* Colonne Initial élargie à 140px (I1, audit a11y tour 2) : le bouton « Rendre initial »
       (icône + texte, ~120px) était tronqué à 80px et son halo de focus rogné. */
    grid-template-columns: 150px minmax(180px, 1fr) 80px 140px 130px 100px 110px;
    min-width: 890px;
}
/* Un statut désactivé reste au référentiel (ses transitions/historique subsistent) mais se
   distingue visuellement — le badge Actif/Inactif porte déjà l'information (WCAG 1.4.1),
   cette atténuation est un renfort, jamais le seul signal. */
.isis-grid--statuts-opportunite .isis-grid__row.is-inactive {
    opacity: 0.6;
}

/* ============================================================================
   .isis-grid--checklists-preparation — référentiel gesmaff, items de checklist de
   préparation par type d'Opportunité (sous-chantier 5a).
   Colonnes : Libellé | Condition | Ordre | Requis | actions   (5 colonnes)
   ============================================================================ */
/* ============================================================================
   .isis-champs-panel / .isis-champs-apercu — champs personnalises d'une
   Opportunite (sous-chantier 1). Le panneau se monte dans une fiche ; l'apercu
   rend les memes controles, inactifs et sans donnee, dans l'ecran d'admin.
   ============================================================================ */
.isis-champs-panel__field {
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
}

.isis-champs-panel__label {
    font-size: 0.8rem;
    font-weight: 500;
    color: var(--isis-text-soft);
}

.isis-champs-panel__required {
    color: var(--isis-danger);
    margin-left: 0.15rem;
}

/* Region live du seuil d'exigence et de « Manquant ». Rendue en PERMANENCE — une region live
   creee en meme temps que son contenu n'est pas annoncee — d'ou le repli sur :has() plutot que
   :empty, qui serait mis en echec par le seul blanc du gabarit Razor. */
.isis-champs-panel__status {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
}

.isis-champs-panel__status:not(:has(*)) {
    display: none;
}

.isis-champs-panel__helper {
    font-size: 0.75rem;
    color: var(--isis-text-soft);
}

/* Etat vide d'un selecteur a recherche serveur (TiersPicker). Radzen 11.0.4 ne rend RIEN quand
   la liste est vide sur un DropDown filtre en LoadData : mesure au navigateur le 2026-09-17, le
   rz-dropdown-items-wrapper est litteralement sans enfant. Un panneau blanc ne dit pas s'il
   cherche, s'il a echoue ou s'il n'a rien trouve — d'ou ce rendu porte par EmptyTemplate. */
.isis-picker__empty {
    padding: 0.5rem 0.75rem;
    font-size: 0.8125rem;
    color: var(--isis-text-soft);
}

/* Repli de l'apercu (ecran des champs) : le resume porte le titre, le panneau interne ne le
   redouble donc pas. */
.isis-champs-apercu-pli {
    margin-bottom: var(--isis-space-sm);
}

.isis-champs-apercu-pli__resume {
    cursor: pointer;
    font-size: 0.8rem;
    font-weight: 600;
    color: var(--isis-text);
    padding: 0.35rem 0;
}

.isis-champs-apercu-pli .isis-champs-apercu__title {
    display: none;
}

.isis-champs-apercu {
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
    padding: var(--isis-space-md);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius);
    background: var(--isis-surface-2);
}

.isis-champs-apercu__title {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    font-size: 0.8rem;
    font-weight: 600;
    color: var(--isis-text);
}

.isis-champs-apercu__note {
    margin: 0;
    font-size: 0.75rem;
    color: var(--isis-text-soft);
}

/* ============================================================================
   .isis-grid--champs-opportunite — referentiel gesmaff, definitions de champs
   personnalises par type d'Opportunite (sous-chantier 1 ; portee Task 5/0891).
   Colonnes : Libelle | Code | Type | Porte par | Ordre | Saisie | actions   (7 colonnes)
   ============================================================================ */
.isis-grid--champs-opportunite .isis-grid__head,
.isis-grid--champs-opportunite .isis-grid__row {
    grid-template-columns: minmax(180px, 1.3fr) minmax(150px, 1fr) minmax(150px, 1fr) 100px 80px 130px 100px;
    min-width: 1000px;
}
.isis-grid--champs-opportunite .isis-grid__row > *:nth-child(2) {
    font-family: var(--isis-font-mono, monospace);
    font-size: 0.78rem;
}
.isis-grid--champs-opportunite .isis-grid__head > *:nth-child(5),
.isis-grid--champs-opportunite .isis-grid__row > *:nth-child(5) {
    text-align: center;
    font-variant-numeric: tabular-nums;
}

/* Un champ retiré de la saisie reste au référentiel mais se distingue — même patron, même valeur
   que le référentiel jumeau des statuts : le badge porte l'information (WCAG 1.4.1), l'atténuation
   n'est qu'un renfort. Sans cette règle, la classe posée par le Razor n'avait AUCUN effet. */
.isis-grid--champs-opportunite .isis-grid__row.is-inactive {
    opacity: 0.6;
}

/* ============================================================================
   .isis-grid--sources-opportunite — referentiel gesmaff, sources d'Opportunite (0758/0761).
   Colonnes : Libelle | Code | Utilisations | Disponibilite | actions  (5 colonnes)
   ============================================================================ */
.isis-grid--sources-opportunite .isis-grid__head,
.isis-grid--sources-opportunite .isis-grid__row {
    grid-template-columns: minmax(200px, 1.3fr) minmax(170px, 1fr) 130px 150px 100px;
    min-width: 780px;
}
.isis-grid--sources-opportunite .isis-grid__row > *:nth-child(2) {
    font-family: var(--isis-font-mono, monospace);
    font-size: 0.8125rem;
}
.isis-grid--sources-opportunite .isis-grid__head > *:nth-child(3),
.isis-grid--sources-opportunite .isis-grid__row > *:nth-child(3),
.isis-grid--sources-opportunite .isis-grid__head > *:nth-child(4),
.isis-grid--sources-opportunite .isis-grid__row > *:nth-child(4) {
    text-align: center;
    justify-content: center;
}

/* ============================================================================
   .isis-grid--motifs-revocation — referentiel gesmaff, motifs de revocation (0908/0909).
   Colonnes : Code | Libelle | Precision requise | Ordre | Actif | Utilisations | actions
   ============================================================================ */
.isis-grid--motifs-revocation .isis-grid__head,
.isis-grid--motifs-revocation .isis-grid__row {
    grid-template-columns: minmax(170px, 1fr) minmax(220px, 1.5fr) 140px 80px 110px 110px 100px;
    min-width: 930px;
}
.isis-grid--motifs-revocation .isis-grid__row > *:nth-child(1) {
    font-family: var(--isis-font-mono);
    font-size: 0.8125rem;
}
.isis-grid--motifs-revocation .isis-grid__head > *:nth-child(n+3):nth-child(-n+6),
.isis-grid--motifs-revocation .isis-grid__row > *:nth-child(n+3):nth-child(-n+6) {
    text-align: center;
    justify-content: center;
}

/* ============================================================================
   .isis-grid--concurrents — veille concurrentielle gesmaff (EF-50, 0924).
   Colonnes : Concurrent | Pays | Lots remportes | Montant cumule | Dernier lot | actions
   ============================================================================ */
.isis-grid--concurrents .isis-grid__head,
.isis-grid--concurrents .isis-grid__row {
    grid-template-columns: minmax(220px, 1.6fr) 90px 130px 200px 165px 60px;
    min-width: 865px;
}
.isis-grid--concurrents .isis-grid__head > *:nth-child(n+3):nth-child(-n+4),
.isis-grid--concurrents .isis-grid__row > *:nth-child(n+3):nth-child(-n+4) {
    text-align: right;
    justify-content: flex-end;
    font-variant-numeric: tabular-nums;
}

/* Colonnes : Attributaire saisi | Lots | Concurrent suggere | actions */
.isis-grid--concurrents-a-rapprocher .isis-grid__head,
.isis-grid--concurrents-a-rapprocher .isis-grid__row {
    grid-template-columns: minmax(220px, 1.5fr) 90px minmax(180px, 1fr) 130px;
    min-width: 640px;
}
.isis-grid--concurrents-a-rapprocher .isis-grid__head > *:nth-child(2),
.isis-grid--concurrents-a-rapprocher .isis-grid__row > *:nth-child(2) {
    text-align: right;
    justify-content: flex-end;
    font-variant-numeric: tabular-nums;
}
/* Lignes sans selection : aucune affordance de clic. */
.isis-concurrents__ligne-fixe { cursor: default; }
/* Un cumul par devise, sans conversion ; les lots sans montant comptes a part, en legende. */
.isis-grid--concurrents .isis-grid__row > .isis-concurrents__montants {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 2px;
}
.isis-concurrents__manquants {
    color: var(--isis-text-muted);
    font-size: var(--isis-fs-xs);
}
.isis-grid__empty:focus-visible { outline: 2px solid var(--isis-current-mod); outline-offset: 2px; }
.isis-concurrents__compte {
    color: var(--isis-text-muted);
    font-variant-numeric: tabular-nums;
}
.isis-concurrents__lots {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: var(--isis-space-md);
}
.isis-concurrents__lot {
    display: flex;
    flex-direction: column;
    gap: var(--isis-space-xs);
    padding-bottom: var(--isis-space-md);
    border-bottom: 1px solid var(--isis-border-soft);
}
.isis-concurrents__lot:last-child { border-bottom: 0; padding-bottom: 0; }
.isis-concurrents__affaire {
    font-weight: 600;
    color: var(--isis-text);
}
a.isis-concurrents__affaire { color: var(--isis-current-mod); }

/* ============================================================================
   .isis-grid--regles-affectation — reglages gesmaff, affectation automatique (0806).
   Colonnes : Entreprise | Mode | Commerciaux | Prochain servi | Etat | actions  (6 colonnes)
   ============================================================================ */
.isis-grid--regles-affectation .isis-grid__head,
.isis-grid--regles-affectation .isis-grid__row {
    grid-template-columns: minmax(200px, 1.4fr) 140px 120px minmax(160px, 1fr) 120px 100px;
    min-width: 900px;
}
.isis-grid--regles-affectation .isis-grid__head > *:nth-child(3),
.isis-grid--regles-affectation .isis-grid__row > *:nth-child(3),
.isis-grid--regles-affectation .isis-grid__head > *:nth-child(5),
.isis-grid--regles-affectation .isis-grid__row > *:nth-child(5) {
    text-align: center;
    justify-content: center;
}

/* ----------------------------------------------------------------------------
   .isis-regle-membres — le vivier ordonne du dialogue de regle (0806).
   Liste ordonnee et non une grille : l'ordre EST l'information (rang de departage
   du tour de role), et un <ol> le dit aux lecteurs d'ecran sans aria supplementaire.
   ---------------------------------------------------------------------------- */
.isis-regle-membres {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.isis-regle-membres__item {
    display: grid;
    grid-template-columns: 28px minmax(0, 1fr) auto auto;
    align-items: center;
    gap: 0.5rem;
    padding: 0.35rem 0.5rem;
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-sm);
    background: var(--isis-surface);
}
.isis-regle-membres__rang {
    font-family: var(--isis-font-mono, monospace);
    font-size: 0.75rem;
    color: var(--isis-text-muted);
    text-align: center;
}
.isis-regle-membres__nom {
    font-size: 0.8125rem;
    color: var(--isis-text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.isis-regle-membres__tour {
    font-size: 0.75rem;
    color: var(--isis-text-muted);
    white-space: nowrap;
}
.isis-regle-membres__actions {
    display: flex;
    gap: 2px;
}

/* ============================================================================
   .isis-grid--sequence-relance — referentiel gescom, modeles de relance (0809).
   Colonnes : Code | Libelle | Portee | Etapes | Duree | Statut | actions
   ============================================================================ */
.isis-grid--sequence-relance .isis-grid__head,
.isis-grid--sequence-relance .isis-grid__row {
    grid-template-columns: 170px minmax(220px, 1.4fr) minmax(160px, 1fr) 90px 90px 110px 96px;
    min-width: 960px;
}
.isis-grid--sequence-relance .isis-grid__head > *:nth-child(4),
.isis-grid--sequence-relance .isis-grid__row > *:nth-child(4),
.isis-grid--sequence-relance .isis-grid__head > *:nth-child(5),
.isis-grid--sequence-relance .isis-grid__row > *:nth-child(5) {
    text-align: center;
    justify-content: center;
}

/* ----------------------------------------------------------------------------
   .isis-sequence-etapes — l'editeur d'etapes du dialogue de sequence (0809).
   <ol> et non une grille : l'ordre EST l'information (rang de la relance), et la
   liste ordonnee le dit aux lecteurs d'ecran sans aria supplementaire. Meme
   principe que .isis-regle-membres, mais chaque rang porte des CHAMPS, d'ou la
   colonne centrale en sous-grille plutot qu'un simple libelle.
   ---------------------------------------------------------------------------- */
.isis-sequence-etapes {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}
.isis-sequence-etapes__item {
    display: grid;
    grid-template-columns: 28px minmax(0, 1fr) auto;
    align-items: start;
    gap: 0.5rem;
    padding: 0.6rem;
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-sm);
    background: var(--isis-surface);
}
.isis-sequence-etapes__rang {
    font-family: var(--isis-font-mono, monospace);
    font-size: 0.75rem;
    color: var(--isis-text-muted);
    text-align: center;
    padding-top: 1.55rem;
}
.isis-sequence-etapes__champs {
    display: grid;
    grid-template-columns: 130px 150px minmax(0, 1fr);
    gap: 0.5rem 0.75rem;
    min-width: 0;
}
.isis-sequence-etapes__champs .field {
    min-width: 0;
}
.isis-sequence-etapes__consigne {
    grid-column: 1 / -1;
}
/* 6px, pas 2 : trois cibles de 26px collees se ratent au doigt. Le minimum AA de 2.5.8
   (24 x 24) etait deja tenu, l'ecart ne l'est pas — il ne coute rien. */
.isis-sequence-etapes__actions {
    display: flex;
    gap: 6px;
    padding-top: 1.35rem;
}

@media (max-width: 720px) {
    .isis-sequence-etapes__champs {
        grid-template-columns: minmax(0, 1fr);
    }
    .isis-sequence-etapes__libelle,
    .isis-sequence-etapes__consigne {
        grid-column: auto;
    }
    .isis-sequence-etapes__rang,
    .isis-sequence-etapes__actions {
        padding-top: 0;
    }
}

/* ----------------------------------------------------------------------------
   .isis-sequence-exec — l'onglet Relances d'une affaire (0809).
   Miroir en LECTURE des tâches posées : aucune case à cocher ici, le « fait »
   se pose dans la liste du porteur. D'ou des rangs sans controle, contrairement
   a .isis-sequence-etapes qui est l'editeur du modele.
   ---------------------------------------------------------------------------- */
.isis-sequence-exec {
    list-style: none;
    margin: 0 0 0.75rem;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}
.isis-sequence-exec__item {
    padding: 0.75rem;
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-sm);
    background: var(--isis-surface);
}
.isis-sequence-exec__head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
}
.isis-sequence-exec__nom {
    font-weight: 600;
}
.isis-sequence-exec__code {
    font-family: var(--isis-font-mono, monospace);
    font-size: 0.75rem;
    color: var(--isis-text-muted);
}
/* Pousse a droite : l'avancement et l'arret sont la fin de ligne, le nom son debut. */
.isis-sequence-exec__avancement {
    margin-left: auto;
    font-size: 0.8rem;
    font-variant-numeric: tabular-nums;
    color: var(--isis-text-muted);
}
.isis-sequence-exec__meta {
    margin: 0.35rem 0 0;
    font-size: 0.8rem;
    color: var(--isis-text-muted);
}
.isis-sequence-exec__arret {
    margin-top: 0.6rem;
    padding: 0.6rem;
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-sm);
    background: var(--isis-surface-alt, var(--isis-surface));
}
.isis-sequence-exec__arret-champ {
    margin: 0.5rem 0;
}
.isis-sequence-exec__arret-actions {
    display: flex;
    gap: 0.5rem;
}
.isis-sequence-exec__etapes {
    list-style: none;
    margin: 0.6rem 0 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.isis-sequence-exec__etape {
    display: grid;
    grid-template-columns: 20px minmax(0, 1fr) 110px 190px;
    align-items: center;
    gap: 0.5rem;
    padding: 0.3rem 0.25rem;
    font-size: 0.85rem;
    border-top: 1px solid var(--isis-border);
}
/* Une etape faite s'efface sans disparaitre : le porteur balaie ce qui RESTE. */
.isis-sequence-exec__etape.is-done .isis-sequence-exec__etape-nom {
    color: var(--isis-text-muted);
}
/* Annulee a l'arret : barree EN PLUS d'etre grisee. Le gris seul la confondrait avec une etape
   faite, qui est l'exact contraire. Le barre ne porte pas seul : le libelle de date dit
   « Annulee » et le lecteur d'ecran l'annonce. */
.isis-sequence-exec__etape.is-annulee .isis-sequence-exec__etape-nom {
    color: var(--isis-text-muted);
    text-decoration: line-through;
}
.isis-sequence-exec__etape-nom {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.isis-sequence-exec__etape-type,
.isis-sequence-exec__etape-date {
    font-size: 0.78rem;
    color: var(--isis-text-muted);
}
.isis-sequence-exec__demarrage {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: 0.75rem;
}
.isis-sequence-exec__demarrage .isis-op-equipe__field {
    flex: 1 1 320px;
    min-width: 0;
}

@media (max-width: 720px) {
    .isis-sequence-exec__etape {
        grid-template-columns: 20px minmax(0, 1fr);
    }
    .isis-sequence-exec__etape-type,
    .isis-sequence-exec__etape-date {
        grid-column: 2;
    }
    .isis-sequence-exec__avancement {
        margin-left: 0;
    }
}

/* ============================================================================
   .isis-grid--types-opportunite — referentiel gesmaff, types d'Opportunite
   (sous-chantier 1, champs generiques).
   Colonnes : Libelle | Code | Opportunites actives | Disponibilite | actions  (5 colonnes)
   ============================================================================ */
.isis-grid--types-opportunite .isis-grid__head,
.isis-grid--types-opportunite .isis-grid__row {
    grid-template-columns: minmax(200px, 1.3fr) minmax(170px, 1fr) 150px 170px 100px;
    min-width: 820px;
}

/* Code technique en mono, compteur et disponibilite centres : en CSS et non en style inline
   (DESIGN.md §5 — le gabarit et le chrome de .isis-grid vivent dans la feuille globale, faute de
   quoi le configurateur de colonnes ne peut pas s'y appliquer). */
.isis-grid--types-opportunite .isis-grid__row > *:nth-child(2) {
    font-family: var(--isis-font-mono, monospace);
    font-size: 0.78rem;
}
.isis-grid--types-opportunite .isis-grid__head > *:nth-child(3),
.isis-grid--types-opportunite .isis-grid__row > *:nth-child(3) {
    text-align: center;
    font-variant-numeric: tabular-nums;
}
.isis-grid--types-opportunite .isis-grid__row > *:nth-child(4) {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem;
    align-items: center;
}

.isis-grid--checklists-preparation .isis-grid__head,
.isis-grid--checklists-preparation .isis-grid__row {
    grid-template-columns: minmax(200px, 1fr) minmax(220px, 1.6fr) 90px 110px 100px;
    min-width: 820px;
}

/* ============================================================================
   .isis-transition-matrix — matrice from×vers des transitions de statut
   d'Opportunité (gesmaff). Tableau non navigable / comparatif figé : <table>
   nu légitime (DESIGN.md §4, exception aux grilles .isis-grid).
   ============================================================================ */
.isis-transition-matrix-wrap {
    overflow: auto;
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius, 10px);
    background: var(--isis-surface);
}
.isis-transition-matrix {
    border-collapse: collapse;
    font-size: 0.78rem;
    width: 100%;
}
.isis-transition-matrix th,
.isis-transition-matrix td {
    border-bottom: 1px solid var(--isis-border-soft);
    border-right: 1px solid var(--isis-border-soft);
    padding: 0.5rem 0.65rem;
    text-align: center;
    white-space: nowrap;
}
.isis-transition-matrix thead th {
    background: var(--isis-surface-alt);
    font-weight: 600;
    text-transform: uppercase;
    font-size: 0.63rem;
    letter-spacing: .05em;
    position: sticky;
    top: 0;
}
.isis-transition-matrix tbody th[scope="row"] {
    text-align: left;
    background: var(--isis-surface-alt);
    font-weight: 600;
    font-size: 0.72rem;
    text-transform: none;
    letter-spacing: normal;
    position: sticky;
    left: 0;
}
.isis-transition-matrix thead th:first-child {
    position: sticky;
    left: 0;
    top: 0;
    z-index: 2;
}
.isis-transition-matrix td.is-diagonal {
    color: var(--isis-text-muted);
    background: var(--isis-surface-alt);
}
.isis-transition-matrix input[type="checkbox"] {
    width: 16px;
    height: 16px;
    cursor: pointer;
    accent-color: var(--isis-current-mod, var(--isis-accent));
}
.isis-transition-matrix input[type="checkbox"]:disabled { cursor: not-allowed; opacity: 0.4; }

/* ============================================================================
   .isis-grid--rubriques-temps / --activites-temps — référentiel sirh rubriques
   Rubriques : Code | Libellé | Facturable | actions   (4 colonnes)
   Activités : Code | Libellé | actions               (3 colonnes)
   ============================================================================ */
.isis-grid--rubriques-temps .isis-grid__head,
.isis-grid--rubriques-temps .isis-grid__row {
    grid-template-columns: 110px minmax(180px, 1fr) 110px 72px;
    min-width: 0;
}
.isis-grid--activites-temps .isis-grid__head,
.isis-grid--activites-temps .isis-grid__row {
    /* Le volet d'activités ne fait que ~300 px : 110 px + 150 px mini + actions le débordait
       et cachait « Supprimer » derrière un défilement horizontal. Le libellé cède. */
    grid-template-columns: 84px minmax(0, 1fr) 72px;
    min-width: 0;
    margin-top: 0.75rem;
}
.isis-regle-name { display: flex; flex-direction: column; gap: 0.15rem; min-width: 0; }
.isis-regle-desc {
    font-size: 0.72rem;
    color: var(--isis-text-soft);
    font-weight: 400;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.isis-regle-conditions {
    display: flex !important;
    flex-wrap: wrap;
    gap: 0.3rem;
    align-items: center;
    padding: 0.35rem !important;
    margin: 0;
    list-style: none;
    overflow: visible !important;
    white-space: normal !important;
}
.isis-regle-chip {
    display: inline-flex;
    align-items: center;
    padding: 0.15rem 0.5rem;
    background: var(--isis-surface-alt);
    border: 1px solid var(--isis-border);
    border-radius: 4px;
    font-size: 0.7rem;
    color: var(--isis-text-muted);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}
.isis-regle-approver-tag {
    display: inline-block;
    margin-left: 0.4rem;
    padding: 0.05rem 0.4rem;
    background: var(--isis-accent-soft);
    color: var(--isis-accent);
    border-radius: 3px;
    font-size: 0.65rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}
.isis-regle-detail-desc {
    font-size: 0.82rem;
    line-height: 1.45;
    color: var(--isis-text);
    background: var(--isis-surface-alt);
    border: 1px solid var(--isis-border);
    box-sizing: border-box;
    padding: 0.5rem 0.7rem;
    border-radius: 4px;
}

/* Sélecteur de mode d'approbateur (radio cards Statique / N+x) */
.isis-mode-toggle {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0.5rem;
    margin-top: 0.3rem;
}
.isis-mode-toggle__opt {
    display: flex;
    align-items: flex-start;
    gap: 0.6rem;
    padding: 0.65rem 0.75rem;
    border: 1px solid var(--isis-border);
    border-radius: 6px;
    background: var(--isis-surface);
    cursor: pointer;
    transition: background-color 120ms ease, border-color 120ms ease;
}
.isis-mode-toggle__opt:hover { background: var(--isis-surface-alt); }
.isis-mode-toggle__opt.is-active {
    border-color: var(--isis-accent);
    background: var(--isis-accent-soft);
}
.isis-mode-toggle__opt input[type="radio"] {
    margin-top: 0.2rem;
    accent-color: var(--isis-accent);
}
.isis-mode-toggle__opt .rzi {
    color: var(--isis-text-muted);
    flex-shrink: 0;
    margin-top: 0.1rem;
}
.isis-mode-toggle__opt.is-active .rzi { color: var(--isis-accent); }
.isis-mode-toggle__opt > div {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    min-width: 0;
}
.isis-mode-toggle__opt strong {
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--isis-text);
}
.isis-mode-toggle__opt small {
    font-size: 0.72rem;
    color: var(--isis-text-soft);
    line-height: 1.3;
}
@media (max-width: 600px) {
    .isis-mode-toggle { grid-template-columns: 1fr; }
}

/* Badge mode N+x dans la liste règles */
.isis-regle-mode-tag {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    padding: 0.1rem 0.5rem;
    background: var(--isis-mod-gescom-soft);
    color: var(--isis-mod-gescom);
    border-radius: 3px;
    font-size: 0.68rem;
    font-weight: 600;
    letter-spacing: 0.03em;
    font-variant-numeric: tabular-nums;
}

/* ============================================================================
   .isis-grid--templates — variante "templates de documents" de gesst (params)
   Colonnes : status | code | libellé | portée | actions (gescom : voir -gescom)
   ============================================================================ */
/* 5 pistes : pastille statut | Code | Libellé | Portée | actions (gesst, sans colonne Type). */
.isis-grid--templates .isis-grid__head,
.isis-grid--templates .isis-grid__row {
    grid-template-columns: 32px 130px minmax(220px, 1.8fr) minmax(180px, 1.2fr) 130px;
    min-width: 720px;
}
/* Gescom : 6 pistes (pastille | Type | Code | Libellé | Portée | actions). Clé à part de
   --templates, qui n'en compte que 5 (gesst, sans colonne Type) : la 6e cellule passait à
   la ligne sous chaque rangée. */
.isis-grid--templates-gescom .isis-grid__head,
.isis-grid--templates-gescom .isis-grid__row {
    grid-template-columns: 32px 120px 170px minmax(220px, 1.8fr) minmax(160px, 1.1fr) 110px;
    min-width: 840px;
}

/* ============================================================================
   .isis-grid--modeles-facture — modèles de facture et d'avoir (gescompta params)
   Colonnes : status | libellé | type | structure | régime TVA | défaut | actions
   3 actions (télécharger / modifier / supprimer) → dernière colonne élargie.
   ============================================================================ */
.isis-grid--modeles-facture .isis-grid__head,
.isis-grid--modeles-facture .isis-grid__row {
    grid-template-columns: 32px minmax(200px, 1.8fr) 100px minmax(160px, 1fr) 160px 110px 132px;
    min-width: 900px;
}

/* ============================================================================
   .isis-grid--roles — TOUS les rôles applicatifs du client (admin/roles)
   Refonte 2026-08-05 : une seule grille au lieu de quinze cartes de module.
   Colonnes : module | code | libellé | état | porteurs | droits | actions.
   La colonne d'actions porte DEUX boutons de 28 px et leur gap : 64 px les
   laissaient sans marge, et le commentaire d'origine n'en annonçait qu'un.
   La colonne Droits est dimensionnée pour « non déployé » — le plus long des
   trois contenus possibles, et le seul qui ne soit pas un nombre.
   ============================================================================ */
.isis-grid--roles .isis-grid__head,
.isis-grid--roles .isis-grid__row {
    grid-template-columns: 190px 175px minmax(200px, 1fr) 112px 92px 118px 76px;
    min-width: 963px;
}
/* Les deux compteurs s'alignent à droite en chiffres tabulaires : c'est ce qui
   permet de comparer deux lignes d'un coup d'œil sans lire les nombres. */
.isis-grid--roles .isis-grid__col-num {
    justify-content: flex-end;
    text-align: right;
    font-variant-numeric: tabular-nums;
}
/* Le squelette et l'état vide sont enveloppés d'une ligne/cellule ARIA (un
   role="table" n'accepte que des lignes) : cette cellule-là traverse toute la
   grille au lieu de se ranger dans la première colonne. */
.isis-grid--roles .isis-grid__span {
    grid-column: 1 / -1;
}
/* L'état NORMAL ne porte pas de badge : on ne décore pas la normalité. Vingt-trois
   badges verts sur cinquante lignes (tenant demo) noyaient les états qui, eux,
   demandent un regard — l'ambre des dormants, majoritaire à l'écran, ne signalait
   plus rien. Texte simple, à la taille des badges voisins : mesuré au navigateur le
   2026-08-06, 7,58:1 en clair et 6,98:1 en sombre à 10,88 px. */
.isis-grid--roles .isis-grid__etat-plain {
    font-size: var(--isis-fs-xs);
    color: var(--isis-text-muted);
}

/* ============================================================================
   .isis-grid--perm-audit — dry-run d'activation Enforce* (/admin/permissions/audit)
   Colonnes : utilisateur (nom + login empilés) | rôle(s) | verdict.
   La grille n'a pas de colonne d'actions : c'est une lecture, pas une édition.
   ============================================================================ */
.isis-grid--perm-audit .isis-grid__head,
.isis-grid--perm-audit .isis-grid__row {
    /* Le libellé de refus le plus long (« Refusé — rôle sans droit d'écriture ») ne tenait pas
       dans 220 px : le badge, en capitales, était tronqué. */
    grid-template-columns: minmax(240px, 1.4fr) minmax(160px, 1fr) 300px;
    min-width: 720px;
}
.isis-grid--perm-audit .isis-grid__span {
    grid-column: 1 / -1;
}

/* ============================================================================
   Gabarits de grille à source unique. Ils vivaient dans des .razor.css isolés, dont le
   sélecteur suffixé [b-xxx] l'emportait sur le thème et masquait isis-grid-config.js.
   ============================================================================ */
/* Admin : types de couches géographiques. */
.isis-grid--geo-layer-types .isis-grid__head,
.isis-grid--geo-layer-types .isis-grid__row {
    grid-template-columns: 160px minmax(200px, 1fr) 70px 130px 70px 90px 90px;
    min-width: 820px;
}
/* Admin : application d'un pack. */
.isis-grid--pack-lots .isis-grid__head,
.isis-grid--pack-lots .isis-grid__row {
    grid-template-columns: 80px minmax(140px, 1fr) minmax(140px, 1fr) minmax(160px, 1.5fr) 100px;
    min-width: 640px;
}
.isis-grid--pack-executions .isis-grid__head,
.isis-grid--pack-executions .isis-grid__row {
    grid-template-columns: 170px minmax(120px, 1fr) minmax(180px, 1.5fr) 140px minmax(120px, 1fr);
    min-width: 720px;
}
.isis-grid--pack-rapport .isis-grid__head,
.isis-grid--pack-rapport .isis-grid__row {
    grid-template-columns: minmax(140px, 1.2fr) 130px 90px 90px 90px minmax(200px, 1.4fr) 170px;
    min-width: 860px;
}
.isis-grid--pack-issues .isis-grid__head,
.isis-grid--pack-issues .isis-grid__row {
    grid-template-columns: 90px minmax(260px, 1fr);
}
/* Gescom : onglet Livrables de l'offre. */
.isis-grid--devis-livrables .isis-grid__head,
.isis-grid--devis-livrables .isis-grid__row {
    grid-template-columns: minmax(220px, 3fr) 120px 130px 110px 150px;
    min-width: 840px;
}
/* Gescom : livrables types (libellé / code / format / coordonnées / ordre / actif / actions). */
.isis-grid--livrables-types .isis-grid__head,
.isis-grid--livrables-types .isis-grid__row {
    grid-template-columns: minmax(200px, 2fr) 150px 120px 110px 70px 100px 110px;
    min-width: 860px;
}
/* Gescompta : taux de change. 8 colonnes courtes : le gabarit générique (min 1000 px)
   débordait du volet maître et masquait la colonne Source. */
.isis-grid--currency-rates .isis-grid__head,
.isis-grid--currency-rates .isis-grid__row {
    grid-template-columns: 32px 80px 80px 130px 110px 110px minmax(110px, 1fr) 56px;
    min-width: 740px;
}
/* Gesfac : onglets de la fiche emplacement. Le gabarit global à 8 colonnes (1re de 32 px)
   faisait chevaucher « Statut » et « Collaborateur » et tronquait la pastille « Courante ». */
.isis-grid--fac-children .isis-grid__head,
.isis-grid--fac-children .isis-grid__row {
    grid-template-columns: 160px minmax(200px, 1.6fr) 150px 100px 60px;
    min-width: 670px;
}
.isis-grid--fac-occupants .isis-grid__head,
.isis-grid--fac-occupants .isis-grid__row {
    grid-template-columns: 110px minmax(180px, 1.4fr) 210px 100px minmax(140px, 1fr) 60px;
    min-width: 800px;
}
.isis-grid--fac-equipements .isis-grid__head,
.isis-grid--fac-equipements .isis-grid__row {
    grid-template-columns: 110px 100px minmax(200px, 1.4fr) 210px minmax(140px, 1fr) 60px;
    min-width: 820px;
}
/* Gesinfo : installations d'une licence (Statut / Poste / Collaborateur / Version /
   Installée le / Conformité / actions). Reflow (WCAG 1.4.10) sous 900 px : on garde Statut,
   Poste, Conformité et actions. */
.isis-grid--licence-installations .isis-grid__head,
.isis-grid--licence-installations .isis-grid__row {
    grid-template-columns: 120px minmax(180px, 1.5fr) minmax(150px, 1fr) 100px 110px 130px 80px;
    min-width: 900px;
}
@media (max-width: 900px) {
    .isis-grid--licence-installations .isis-grid__head,
    .isis-grid--licence-installations .isis-grid__row {
        grid-template-columns: 100px minmax(0, 1fr) 110px 80px;
        min-width: 0;
    }
    .isis-grid--licence-installations .isis-grid__head > :nth-child(3),
    .isis-grid--licence-installations .isis-grid__head > :nth-child(4),
    .isis-grid--licence-installations .isis-grid__head > :nth-child(5),
    .isis-grid--licence-installations .isis-grid__row > :nth-child(3),
    .isis-grid--licence-installations .isis-grid__row > :nth-child(4),
    .isis-grid--licence-installations .isis-grid__row > :nth-child(5) {
        display: none;
    }
}
/* Gesinfo : licences d'un logiciel (Matricule / Statut / Sièges / Échéance / Coût/an /
   actions). Reflow sous 720 px : on garde Matricule, Statut, Échéance et actions. */
.isis-grid--logiciel-licences .isis-grid__head,
.isis-grid--logiciel-licences .isis-grid__row {
    grid-template-columns: minmax(160px, 1.2fr) 130px 100px 120px minmax(120px, 1fr) 60px;
    min-width: 720px;
}
@media (max-width: 720px) {
    .isis-grid--logiciel-licences .isis-grid__head,
    .isis-grid--logiciel-licences .isis-grid__row {
        grid-template-columns: minmax(0, 1fr) 110px 100px 60px;
        min-width: 0;
    }
    .isis-grid--logiciel-licences .isis-grid__head > :nth-child(3),
    .isis-grid--logiciel-licences .isis-grid__head > :nth-child(5),
    .isis-grid--logiciel-licences .isis-grid__row > :nth-child(3),
    .isis-grid--logiciel-licences .isis-grid__row > :nth-child(5) {
        display: none;
    }
}
/* Gesqhse : charte. Deux largeurs MESURÉES au navigateur sur les données réelles (recette du
   2026-09-07) : Code demande 167 px pour `MT_DONNEES_COMPLETES`, Actions 172 px (cinq boutons
   depuis le réordonnancement). Ne pas les rétrécir sans remesurer. Cinq pistes en charte
   publiée, six en édition : l'égalité stricte piste/en-tête qu'exige le configurateur de
   colonnes vaut dans CHAQUE mode, d'où deux clés et deux gabarits en toutes lettres (repeat()
   et var() proscrits). L'élément ne porte qu'UNE de ces deux clés (jamais la base en plus
   de -edition) : une préférence de colonnes posée sur la base ne doit pas atteindre l'édition. */
.isis-grid--gesqhse-charte .isis-grid__head,
.isis-grid--gesqhse-charte .isis-grid__row {
    grid-template-columns: 180px minmax(200px, 620px) 170px 135px minmax(165px, 1fr);
    min-width: 0;
}
.isis-grid--gesqhse-charte-edition .isis-grid__head,
.isis-grid--gesqhse-charte-edition .isis-grid__row {
    grid-template-columns: 180px minmax(200px, 620px) 170px 135px minmax(165px, 1fr) 185px;
    min-width: 0;
}
/* MonEspace : coffre-fort. */
.isis-grid--coffre .isis-grid__head,
.isis-grid--coffre .isis-grid__row {
    grid-template-columns: minmax(240px, 1.8fr) minmax(160px, 1fr) 90px 140px 120px;
    min-width: 850px;
}
/* Opportunité : partenaires. Quatre clés en toutes lettres (sans var()), car le
   configurateur de colonnes lit des pistes littérales : base, édition (+ actions 88 px),
   --lots (+ piste lots 170 px), édition + lots. L'élément ne porte qu'une seule de ces clés. */
.isis-grid--op-partenaires .isis-grid__head,
.isis-grid--op-partenaires .isis-grid__row {
    grid-template-columns: minmax(200px, 2fr) 170px 130px 104px minmax(160px, 1.2fr);
    min-width: 764px;
}
.isis-grid--op-partenaires-edit .isis-grid__head,
.isis-grid--op-partenaires-edit .isis-grid__row {
    grid-template-columns: minmax(200px, 2fr) 170px 130px 104px minmax(160px, 1.2fr) 88px;
    min-width: 852px;
}
.isis-grid--op-partenaires--lots .isis-grid__head,
.isis-grid--op-partenaires--lots .isis-grid__row {
    grid-template-columns: minmax(200px, 2fr) 170px 130px 104px minmax(170px, 1.2fr) minmax(160px, 1.2fr);
    min-width: 934px;
}
.isis-grid--op-partenaires-edit--lots .isis-grid__head,
.isis-grid--op-partenaires-edit--lots .isis-grid__row {
    grid-template-columns: minmax(200px, 2fr) 170px 130px 104px minmax(170px, 1.2fr) minmax(160px, 1.2fr) 88px;
    min-width: 1022px;
}
/* Opportunité : équipe, lots, remises. L'élément ne porte qu'une seule clé (base ou -edit). */
.isis-grid--op-equipe .isis-grid__head,
.isis-grid--op-equipe .isis-grid__row {
    grid-template-columns: minmax(200px, 2fr) 180px minmax(140px, 1.2fr) minmax(170px, 1.2fr);
    min-width: 710px;
}
.isis-grid--op-equipe-edit .isis-grid__head,
.isis-grid--op-equipe-edit .isis-grid__row {
    grid-template-columns: minmax(200px, 2fr) 180px minmax(140px, 1.2fr) minmax(170px, 1.2fr) 88px;
    min-width: 800px;
}
.isis-grid--op-lots .isis-grid__head,
.isis-grid--op-lots .isis-grid__row {
    grid-template-columns: 64px minmax(180px, 2fr) 104px 120px 150px 130px minmax(150px, 1.4fr) 48px;
    min-width: 978px;
}
.isis-grid--op-lots-edit .isis-grid__head,
.isis-grid--op-lots-edit .isis-grid__row {
    grid-template-columns: 64px minmax(180px, 2fr) 104px 120px 150px 130px minmax(150px, 1.4fr) 204px;
    min-width: 1138px;
}
.isis-grid--op-lots-remises .isis-grid__head,
.isis-grid--op-lots-remises .isis-grid__row {
    grid-template-columns: minmax(180px, 2fr) minmax(120px, 1fr) 140px 180px;
    min-width: 620px;
}
.isis-grid--op-lots-remises-edit .isis-grid__head,
.isis-grid--op-lots-remises-edit .isis-grid__row {
    grid-template-columns: minmax(180px, 2fr) minmax(120px, 1fr) 140px 180px 80px;
    min-width: 700px;
}
/* Le nom domine, le login le situe : deux niveaux dans une cellule, comme la
   liste des utilisateurs. */
.isis-audit-user {
    display: flex;
    flex-direction: column;
    line-height: 1.25;
}
.isis-audit-user__login {
    font-size: var(--isis-fs-xs);
    color: var(--isis-text-muted);
    font-variant-numeric: tabular-nums;
}
/* Le verdict « Autorisé » ne se décore pas — seul le refus porte un badge ambre.
   Texte neutre, à la taille des badges voisins (même choix que .isis-grid__etat-plain). */
.isis-grid__verdict-ok {
    font-size: var(--isis-fs-xs);
    color: var(--isis-text-muted);
}

/* ============================================================================
   Choix du module — dialogue de « Nouveau rôle » et « Exporter une matrice »
   (admin/roles). Une liste de boutons plutôt qu'une liste déroulante : la
   quinzaine de modules tient à l'écran, et un choix en un clic vaut mieux
   qu'un choix en trois.
   ============================================================================ */
.isis-module-choice { display: flex; flex-direction: column; gap: var(--isis-space-md); }
.isis-module-choice__question {
    margin: 0;
    font-size: var(--isis-fs-sm);
    color: var(--isis-text-muted);
}
.isis-module-choice__empty {
    margin: 0;
    font-size: var(--isis-fs-sm);
    color: var(--isis-text-muted);
}
.isis-module-choice__search {
    display: flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.3rem 0.45rem;
    background: var(--isis-surface-alt);
    border-radius: 6px;
}
.isis-module-choice__search input {
    border: 0;
    background: transparent;
    outline: none;
    width: 100%;
    font-size: 0.82rem;
    color: var(--isis-text);
}
/* C'est le CORPS du dialogue qui défile, pas la liste : un `max-height: 46vh` posé
   ici coupait la dernière entrée de 11 px (mesuré 425/414 le 2026-08-06), sans ombre
   ni amorce — ça se lit comme un défaut de rendu, et ça empire sur un écran court.
   Recette de .isis-mob-dialog : le thème Radzen pose overflow:hidden sur .rz-dialog
   sans overflow sur .rz-dialog-content, donc les deux règles vont ensemble. */
.isis-module-choice__list {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
    gap: 0.4rem;
}
.rz-dialog.isis-module-choice-dialog { max-height: 90vh; }
.rz-dialog.isis-module-choice-dialog .rz-dialog-content { overflow-y: auto; min-height: 0; }
.isis-module-choice__item {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.1rem;
    padding: 0.5rem 0.65rem;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-sm);
    cursor: pointer;
    text-align: left;
    color: var(--isis-text);
    transition: background-color 120ms ease, border-color 120ms ease;
}
.isis-module-choice__item:hover {
    background: var(--isis-accent-soft);
    border-color: var(--isis-current-mod, var(--isis-accent));
}
.isis-module-choice__item:focus-visible {
    outline: 2px solid var(--isis-current-mod, var(--isis-accent));
    outline-offset: 2px;
}
.isis-module-choice__label { font-size: var(--isis-fs-sm); font-weight: 500; }
.isis-module-choice__code {
    font-family: var(--isis-font-mono, ui-monospace, monospace);
    font-size: 0.7rem;
    color: var(--isis-text-muted);
    background: transparent;
    padding: 0;
}

/* ============================================================================
   .isis-grid--role-porteurs — qui porte un rôle (admin/roles/{id}, onglet Porteurs)
   Colonnes : identifiant | nom | statut du compte | ouvrir la fiche
   ============================================================================ */
.isis-grid--role-porteurs .isis-grid__head,
.isis-grid--role-porteurs .isis-grid__row {
    grid-template-columns: 200px minmax(180px, 1fr) 110px 64px;
    min-width: 600px;
}

/* ============================================================================
   .isis-grid--fonctions — la liste des fonctions (admin/fonctions)
   Colonnes : code | libellé | modules | porteurs | état | ouvrir la fiche
   Les deux compteurs sont étroits et alignés à droite : ce sont des nombres
   qu'on compare d'une ligne à l'autre, pas du texte qu'on lit.
   ============================================================================ */
.isis-grid--fonctions .isis-grid__head,
.isis-grid--fonctions .isis-grid__row {
    grid-template-columns: 190px minmax(200px, 1fr) 110px 110px 110px 64px;
    min-width: 784px;
}
.isis-grid--fonctions .isis-grid__col-num {
    text-align: right;
    padding-right: 1.1rem;
    font-variant-numeric: tabular-nums;
}
/* Les en-têtes des deux compteurs suivent leur colonne, sinon le libellé pend à
   gauche d'un nombre aligné à droite. */
.isis-grid--fonctions .isis-grid__head [role="columnheader"]:nth-child(3),
.isis-grid--fonctions .isis-grid__head [role="columnheader"]:nth-child(4) {
    justify-self: end;
}

/* ============================================================================
   .isis-grid--fonction-membres — la composition d'une fonction
   (admin/fonctions/{id}) — Colonnes : module | rôle | code | état | actions
   La cellule d'actions porte DEUX boutons de 28 px et leur gap.
   ============================================================================ */
.isis-grid--fonction-membres .isis-grid__head,
.isis-grid--fonction-membres .isis-grid__row {
    grid-template-columns: minmax(180px, 1fr) minmax(180px, 1.2fr) 160px 120px 76px;
    min-width: 716px;
}

/* ============================================================================
   .isis-grid--fonction-porteurs — qui porte une fonction (admin/fonctions/{id})
   Colonnes : identifiant | nom | statut du compte | ouvrir la fiche
   Même forme que .isis-grid--role-porteurs : les deux écrans montrent la même
   chose, ils ne doivent pas la montrer différemment.
   ============================================================================ */
.isis-grid--fonction-porteurs .isis-grid__head,
.isis-grid--fonction-porteurs .isis-grid__row {
    grid-template-columns: 200px minmax(180px, 1fr) 110px 64px;
    min-width: 600px;
}
/* Le lien du rapprochement (fiche d'une fonction) vit DANS un bandeau d'information, à la suite
   d'une phrase. Sans soulignement permanent ni retrait de ligne, il se lisait comme de la prose
   — l'écran nommait le profil homonyme sans qu'on voie qu'on pouvait l'ouvrir (constaté en
   navigateur, 2026-08-05).

   Il ne reprend PAS l'encre du bandeau : celle-ci est le bleu Radzen #2196f3, que le shade
   lighter pose sur son propre bleu pâle — 2,52:1 en clair, 4,07:1 en sombre, mesurés le
   2026-08-05. `color: inherit` gagnait bien la cascade ; c'est ce qu'il héritait qui ne tenait
   pas, et seul le navigateur pouvait le dire. --isis-info est le jeton que le thème a déjà posé
   contre ce défaut pour les badges (cf. .isis-badge--info, même cause, même #2196f3). */
.isis-fonction-rapprochement__lien {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    margin-top: 0.4rem;
    font-weight: 600;
    color: var(--isis-info);
    text-decoration: underline;
    text-underline-offset: 3px;
}
.isis-fonction-rapprochement__lien:focus-visible {
    outline: 2px solid var(--isis-current-mod, var(--isis-accent));
    outline-offset: 2px;
    border-radius: var(--isis-radius-sm);
}

/* La fiche EMPILE ses blocs dans une page scrollable : sans plafond, une fonction portée par
   toute une agence étirerait la page à l'infini, l'en-tête et les actions partiraient hors
   écran, et l'`overflow: auto` de .isis-grid — donc son en-tête collant — ne servirait jamais.
   Le plafond rend à la grille son propre défilement. */
.isis-grid--fonction-porteurs {
    max-height: 60vh;
}

/* ============================================================================
   .isis-realign — le dialogue de réalignement des crans (RealignementCranDialog)
   Il MONTRE les écrans concernés au lieu d'en résumer cinq : la liste défile
   dans le panneau plutôt que de le faire grandir hors de l'écran, et les trois
   boutons restent visibles sans défiler — c'est là que la décision se prend.
   ============================================================================ */
.isis-realign {
    display: flex;
    flex-direction: column;
    gap: 0.85rem;
}
.isis-realign__intro {
    margin: 0;
    font-size: 0.875rem;
    color: var(--isis-text);
}
.isis-realign__table {
    max-height: 42vh;
    overflow-y: auto;
    /* Contient le `sticky` de l'en-tête : sans conteneur de défilement propre, il
       n'aurait rien à quoi coller et sortirait de vue dès la dixième ligne. */
    position: relative;
}
/* La région est focalisable (elle défile sans rien contenir de focalisable) : son
   focus doit donc se VOIR, sinon le clavier y entre sans que rien ne l'indique. */
.isis-realign__table:focus-visible {
    outline: 2px solid var(--isis-current-mod, var(--isis-accent));
    outline-offset: 2px;
}
.isis-grid--realign .isis-grid__head,
.isis-grid--realign .isis-grid__row {
    grid-template-columns: minmax(200px, 1.4fr) 150px minmax(170px, 1fr);
    min-width: 520px;
}
.isis-grid--realign .isis-grid__head {
    position: sticky;
    top: 0;
    z-index: 1;
    background: var(--isis-surface);
}
/* « inchangé » n'est pas un cran : il ne prend donc pas de pastille, qui le ferait lire
   comme une quatrième valeur possible à côté d'« Aucun accès », « Consulter »… */
.isis-realign__inchange {
    font-size: 0.78rem;
    font-style: italic;
    color: var(--isis-text-muted);
}
.isis-realign__note {
    display: flex;
    align-items: flex-start;
    gap: 0.4rem;
    margin: 0;
    padding: 0.55rem 0.7rem;
    font-size: 0.8rem;
    line-height: 1.45;
    color: var(--isis-text-muted);
    background: var(--isis-surface-alt);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-sm);
}

/* ============================================================================
   .isis-attribution — ce qu'attribuer une fonction va faire, avant de le faire
   (AttributionFonctionDialog, ouvert depuis /admin/users/{id})

   Quatre listes courtes plutôt qu'un tableau : les colonnes n'auraient rien à
   aligner — chaque ligne est une phrase, et ce qui compte est le GROUPE auquel
   elle appartient (posé / ouvert / déjà là / pas posé).
   ============================================================================ */
.isis-attribution {
    display: flex;
    flex-direction: column;
    gap: 0.9rem;
}
.isis-attribution__intro {
    margin: 0;
    font-size: 0.875rem;
    line-height: 1.5;
    color: var(--isis-text);
}
.isis-attribution__bloc {
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
}
/* Le bandeau du seul groupe qui est un aveu : ces rôles-là ne seront PAS posés.
   Filet périmétrique et non liseré gauche : plus aucun liseré vertical ≥ 2px dans
   l'application depuis 2026-07-18 (DESIGN.md §2), y compris sur les blocs qui portent un
   signal. `box-sizing` va avec, faute de reset universel dans ce projet. */
.isis-attribution__bloc--alerte {
    padding: 0.6rem 0.75rem;
    background: var(--isis-surface-alt);
    border: 1px solid var(--isis-warning, #8f5700);
    border-radius: var(--isis-radius-sm);
    box-sizing: border-box;
}
/* Mêmes valeurs que .isis-habilitation-section__title : les deux jouent le même rôle de
   sur-titre à un clic d'écart, deux variantes s'y liraient comme une erreur. */
.isis-attribution__titre {
    margin: 0;
    font-size: 0.65rem;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--isis-text-soft);
}
/* Le bloc d'alerte relève le fond sous son sur-titre : --isis-text-soft y tombe à 3,82:1 en
   clair (mesuré 2026-08-05 — 4,76:1 sur le blanc des trois autres groupes, d'où le fait que
   seul celui-ci échoue). Le seul groupe qui est un aveu était devenu le moins lisible des
   quatre. --isis-text-muted est le jeton de la note posée juste en dessous : 6,09:1 sur ce
   même fond. */
.isis-attribution__bloc--alerte .isis-attribution__titre {
    color: var(--isis-text-muted);
}
.isis-attribution__liste {
    margin: 0;
    padding: 0;
    list-style: none;
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    max-height: 28vh;
    overflow-y: auto;
}
/* Les listes sont focalisables (elles défilent sans rien contenir de focalisable) : leur focus
   doit donc se VOIR, sinon le clavier y entre sans que rien ne l'indique. Même règle que
   .isis-realign__table, pour la même raison. */
.isis-attribution__liste:focus-visible {
    outline: 2px solid var(--isis-current-mod, var(--isis-accent));
    outline-offset: 2px;
    border-radius: var(--isis-radius-sm);
}
.isis-attribution__liste > li {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    font-size: 0.85rem;
    color: var(--isis-text);
}
/* Ce qui est déjà en place n'appelle aucune décision : il s'efface derrière ce qui change. */
.isis-attribution__liste--calme > li { color: var(--isis-text-soft); }
.isis-attribution__vide {
    margin: 0;
    font-size: 0.82rem;
    font-style: italic;
    color: var(--isis-text-soft);
}
.isis-attribution__note {
    margin: 0;
    font-size: 0.8rem;
    line-height: 1.45;
    color: var(--isis-text-muted);
}
.isis-attribution__rien {
    display: flex;
    align-items: flex-start;
    gap: 0.5rem;
    padding: 0.7rem 0.8rem;
    font-size: 0.85rem;
    line-height: 1.5;
    color: var(--isis-text);
    background: var(--isis-surface-alt);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-sm);
}

/* Le bloc « Fonctions » ouvre l'onglet Habilitations : il décide de plusieurs modules d'un
   geste, là où tout ce qui suit se décide module par module. Son en-tête porte un choix et un
   bouton, qui passent sous le libellé quand la fiche se resserre. */
.isis-habilitation-block--fonctions .isis-habilitation-block__head {
    flex-wrap: wrap;
    gap: 0.5rem 0.7rem;
}
/* Le libellé du bloc est un vrai titre (h2) — le seul de l'onglet. Il doit se lire comme ses
   voisins, qui sont des span : sans cette remise à plat, le h2 prendrait la taille et les marges
   du navigateur et ferait dépasser le bloc de la famille. */
.isis-habilitation-block--fonctions h2.isis-habilitation-block__label {
    margin: 0;
    font-size: 1rem;
    line-height: inherit;
}

/* ============================================================================
   .isis-grid--doc-templates — templates BL + PV (gesproj params)
   Migration RadzenDataGrid → .isis-grid (2026-07-17).
   Colonnes : type | code | libellé | portée | défaut | actif | créé | actions
   3 actions (modifier / défaut / supprimer) → dernière colonne élargie.
   ============================================================================ */
.isis-grid--doc-templates .isis-grid__head,
.isis-grid--doc-templates .isis-grid__row {
    grid-template-columns: minmax(190px, 1.3fr) 150px minmax(160px, 1fr) 180px 80px 80px 110px 120px;
    min-width: 1080px;
}

/* ============================================================================
   Référentiels parc gesinfo/gesmob (2026-07-17) — ces variantes n'avaient AUCUN
   grid-template-columns : leurs lignes héritaient du template de base à 8 colonnes
   (1re col 32px pour pastille de statut), donc la colonne Libellé s'écrasait à 32px
   et son en-tête chevauchait « Code » (« LIBELLCODE »). Un des ~14 écrans du même
   défaut « grille sans template » remonté par la revue multi-agent.
   6 colonnes : Libellé | Code (ou Type parent) | Icône (ou Code) | Tri | modifier | suppr.
   ============================================================================ */
.isis-grid--gesinfo-ref .isis-grid__head, .isis-grid--gesinfo-ref .isis-grid__row,
.isis-grid--gesmob-ref  .isis-grid__head, .isis-grid--gesmob-ref  .isis-grid__row {
    /* 6 col : Libellé | Code (ou Type parent) | Icône (ou Code) | Tri | badges | actions.
       La même variante sert plusieurs onglets aux colonnes légèrement différentes, d'où
       des largeurs min souples partout plutôt que fixes. */
    grid-template-columns: minmax(140px, 1.3fr) minmax(110px, 1fr) minmax(100px, 0.9fr) 64px minmax(96px, 0.8fr) 84px;
    min-width: 700px;
}
/* Variante « -3col » : Libellé | Pays d'origine | actions. */
.isis-grid--gesinfo-ref-3col .isis-grid__head, .isis-grid--gesinfo-ref-3col .isis-grid__row,
.isis-grid--gesmob-ref-3col  .isis-grid__head, .isis-grid--gesmob-ref-3col  .isis-grid__row {
    grid-template-columns: minmax(180px, 1.6fr) minmax(140px, 1fr) 100px;
    min-width: 440px;
}

/* Référentiels gesmob HARMONISÉS (2026-09-05) — gabarits PROPRES au module, et non les
   variantes `--gesmob-ref` ci-dessus : celles-ci sont déclarées dans le même sélecteur que
   `--gesinfo-ref`, qui n'est pas harmonisé — les élargir aurait déplacé les colonnes d'un
   écran hors chantier. L'élargissement est nécessaire parce que les en-têtes portent
   désormais un bouton de tri (et, pour certaines, un entonnoir) : « Tri » à 64px ne peut
   pas loger son libellé ET sa flèche. « Marque / modèle » est à 186px et non 170 : mesuré au
   navigateur, son en-tête repliait sur deux lignes en dessous, seul de la rangée. */
.isis-grid--gesmob-referentiel .isis-grid__head,
.isis-grid--gesmob-referentiel .isis-grid__row {
    grid-template-columns: minmax(170px, 1.3fr) minmax(155px, 1fr) minmax(140px, 0.9fr) 96px minmax(120px, 0.8fr) 84px;
    min-width: 810px;
}
/* Variante marques : Libellé | Pays d'origine | actions. */
.isis-grid--gesmob-referentiel-marque .isis-grid__head,
.isis-grid--gesmob-referentiel-marque .isis-grid__row {
    grid-template-columns: minmax(190px, 1.6fr) minmax(170px, 1fr) 100px;
    min-width: 500px;
}

/* Avoirs (gescompta) — 8 col : pastille statut | Numéro | Type | Intitulé | Client |
   Facture parente | Montant TTC | actions. Même défaut « grille sans template »
   (2026-07-17). La pastille de statut a été ajoutée au markup après coup : sans sa
   piste de 32px, la 8e cellule (actions) retombait sur une 2e ligne implicite et
   toutes les colonnes glissaient d'un cran. */
.isis-grid--gescompta-avoirs .isis-grid__head, .isis-grid--gescompta-avoirs .isis-grid__row {
    grid-template-columns: 32px 140px 90px minmax(160px, 1.4fr) minmax(130px, 1fr) 150px 130px 80px;
    min-width: 912px;
}

/* Comptes Pennylane (gescompta) — 4 col : case | Code | Libellé | Compte. */
.isis-grid--pennylane-comptes .isis-grid__head, .isis-grid--pennylane-comptes .isis-grid__row {
    grid-template-columns: 40px 140px minmax(200px, 1.4fr) minmax(220px, 1.2fr);
    min-width: 600px;
}
.isis-grid--pennylane-comptes .isis-grid__row { cursor: default; }
.isis-grid--pennylane-comptes .isis-grid__col-check input[type="checkbox"] { cursor: pointer; }

/* Envoi Pennylane (gescompta) — file : case | Type | N° | Date | Société | TTC | État | Alerte | Motifs | Actions. */
.isis-grid--pennylane-file .isis-grid__head, .isis-grid--pennylane-file .isis-grid__row {
    grid-template-columns: 40px 90px 130px 100px minmax(140px, 1fr) 130px 190px 120px minmax(240px, 1.6fr) 190px;
    min-width: 1400px;
}
.isis-grid--pennylane-file--mono .isis-grid__head, .isis-grid--pennylane-file--mono .isis-grid__row {
    grid-template-columns: 40px 90px 130px 100px 130px 190px 120px minmax(240px, 1.6fr) 190px;
    min-width: 1260px;
}
.isis-grid--pennylane-file .isis-grid__row { cursor: default; align-items: start; }
.isis-grid--pennylane-file .isis-grid__col-check input[type="checkbox"] { cursor: pointer; }
.isis-grid--pennylane-file[aria-busy="true"] [role="rowgroup"], .isis-grid--pennylane-historique[aria-busy="true"] [role="rowgroup"] { opacity: 0.55; }
/* Historique des lots Pennylane — détail | Début | Fin | Auteur | Société | État | Envoyées | Échecs. */
.isis-grid--pennylane-historique .isis-grid__head, .isis-grid--pennylane-historique .isis-grid__row {
    grid-template-columns: 48px 150px 150px minmax(140px, 1fr) minmax(140px, 1fr) 210px 100px 80px;
    min-width: 1000px;
}
.isis-grid--pennylane-historique .isis-grid__row { cursor: default; }
.isis-pennylane-entete { display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--isis-space-md) var(--isis-space-lg); margin-bottom: var(--isis-space-md); }
.isis-pennylane-entete__champ { display: flex; flex-direction: column; gap: var(--isis-space-xs); }
.isis-pennylane-entete__label { font-size: 12px; color: var(--isis-text-muted); }
.isis-pennylane-select { min-width: 260px; }
.isis-pennylane-alerte { color: var(--isis-warning); display: inline-flex; align-items: center; gap: var(--isis-space-xs); }
.isis-pennylane-motifs { margin: 0; padding-left: var(--isis-space-md); }
.isis-pennylane-lot__corps { grid-column: 1 / -1; display: flex; flex-direction: column; gap: var(--isis-space-sm); }
.isis-pennylane-lot__liste { margin: 0; padding-left: var(--isis-space-md); display: flex; flex-direction: column; gap: var(--isis-space-xs); list-style: none; }
.isis-pennylane-lot__piece { display: flex; flex-wrap: wrap; align-items: center; gap: var(--isis-space-sm); }
.isis-pennylane-chips-sep { width: 1px; align-self: stretch; background: var(--isis-border); margin: 0 var(--isis-space-xs); }
.isis-pennylane-confie { margin: 0 0 var(--isis-space-sm); font-size: 13px; color: var(--isis-text); }
.isis-pennylane-geste { border: 0; margin: var(--isis-space-xs) 0 0; padding: 0; display: flex; flex-direction: column; gap: var(--isis-space-xs); }
.isis-pennylane-geste legend { font-size: 12px; color: var(--isis-text-muted); padding: 0; }
.isis-pennylane-geste__option { display: flex; flex-direction: column; }
.isis-pennylane-geste__option label { display: inline-flex; align-items: center; gap: var(--isis-space-xs); cursor: pointer; }
.isis-pennylane-geste__option .isis-form-linear__field-hint { margin-left: calc(var(--isis-space-md) + var(--isis-space-xs)); }
.isis-pennylane-dialog__titre { font-size: 14px; margin: var(--isis-space-md) 0 var(--isis-space-xs); }
.isis-pennylane-dialog__liste { margin: 0; padding-left: var(--isis-space-md); display: flex; flex-direction: column; gap: var(--isis-space-xs); }

/* Lignes d'un avoir (fiche gescompta) — 6 col : Désignation | Qté | PU HT | TVA % |
   Total HT | Total TTC. Sans cette règle la grille héritait du template de base à
   8 pistes : « Désignation » se retrouvait dans la piste de 32px et deux pistes
   vides traînaient à droite sous 1000px de min-width. */
.isis-grid--gescompta-avoir-lignes .isis-grid__head,
.isis-grid--gescompta-avoir-lignes .isis-grid__row {
    grid-template-columns: minmax(220px, 2fr) 90px 120px 90px 130px 130px;
    min-width: 780px;
}
.isis-grid--gescompta-avoir-lignes .isis-grid__row {
    /* Consultation seule : pas de sélection de ligne dans l'onglet Lignes. */
    cursor: default;
}

/* Grilles de paliers (gescom) — 6 col : Libellé | Entreprise | Mode | Nb paliers |
   Article | actions. */
.isis-grid--price-grids .isis-grid__head, .isis-grid--price-grids .isis-grid__row {
    grid-template-columns: minmax(160px, 1.4fr) minmax(130px, 1fr) 120px 90px minmax(120px, 1fr) 90px;
    min-width: 760px;
}

/* ── En-tête « imbriqué » (role=rowgroup) ───────────────────────────────────
   Trois grilles (pilotage commercial, coûts transversaux par défaut, CGV) posent
   un `.isis-grid__row--head` DANS le `.isis-grid__head`, pour respecter la
   sémantique ARIA rowgroup > row > columnheader. Deux règles de base les
   cassaient : (1) `.isis-grid__head` étant lui-même une grille, sa ligne
   d'en-tête, enfant unique, se retrouvait enfermée dans la 1re piste ;
   (2) `.isis-grid__head > div` (plus spécifique que `.isis-grid__head,
   .isis-grid__row`) repassait cette ligne en flex, collant tous les intitulés
   les uns aux autres. Le rowgroup redevient un simple bloc, la ligne d'en-tête
   une grille — elle reprend alors les pistes de sa variante. */
.isis-grid__head:has(> .isis-grid__row--head) { display: block; }
.isis-grid__head > .isis-grid__row--head {
    display: grid;
    padding: 0;
}

/* Pilotage commercial (gescom) — 5 col : pastille statut | Entreprise |
   Pays / Devise | Cible | Plancher. La 1re piste porte une pastille mais son
   en-tête est un vrai intitulé « Statut » (42px mesurés) : 32px comme ailleurs
   le faisait déborder sur « Entreprise ». */
.isis-grid--pilotage .isis-grid__head, .isis-grid--pilotage .isis-grid__row {
    grid-template-columns: 56px minmax(220px, 1.6fr) 150px 110px 110px;
    min-width: 660px;
}

/* Commandes d'un marché (gesmaff) et marchés issus d'un AO — même gabarit à
   6 col : Numéro | Intitulé | Statut | dates | Montant TTC | actions. */
.isis-grid--marche-commandes .isis-grid__head, .isis-grid--marche-commandes .isis-grid__row {
    grid-template-columns: 150px minmax(200px, 1.6fr) 130px 150px 150px 70px;
    min-width: 850px;
}

/* Compétences requises d'un équipement (gesmat) — 5 col : Compétence |
   Catégorie | Niveau min. | Pré-requis | Notes. */
.isis-grid--gesmat-required-comp .isis-grid__head, .isis-grid--gesmat-required-comp .isis-grid__row {
    grid-template-columns: minmax(180px, 1.4fr) 150px 110px 130px minmax(160px, 1fr);
    min-width: 760px;
}

/* Sélection des lignes à annuler (dialogue « avoir depuis facture ») — 3 col :
   case à cocher | Description | HT. */
.isis-grid--avoir-pick-lignes .isis-grid__head, .isis-grid--avoir-pick-lignes .isis-grid__row {
    grid-template-columns: 44px minmax(220px, 1fr) 130px;
    min-width: 400px;
}

/* Indisponibilités d'un équipement — 6 col : Type | Début | Fin | Motif |
   Coût estimé | actions. Même markup sur les 4 fiches équipement (gesmat,
   gesinfo, gesmob, gespark), qui tombaient toutes sur le gabarit de base à 8. */
.isis-grid--indispo .isis-grid__head, .isis-grid--indispo .isis-grid__row {
    grid-template-columns: 130px 110px 110px minmax(200px, 1.6fr) 130px 90px;
    min-width: 770px;
}

/* Affaires d'un tiers (fiche tiers gescom) — 8 col : pastille statut | numéro |
   intitulé | colonne libre | colonne libre | montant | statut | actions. Quatre
   onglets (devis, commandes, participations, opportunités) partagent ce gabarit —
   Opportunités n'a que 5 champs à montrer et laisse deux pistes vides plutôt que
   d'ajouter un modificateur pour un seul onglet de cette même page. Ils
   empruntaient `--commande-list` (10 pistes, lignes de 68px), taillé pour la
   liste des commandes gesproj : deux pistes vides et des colonnes décalées. */
.isis-grid--tiers-affaires .isis-grid__head, .isis-grid--tiers-affaires .isis-grid__row {
    grid-template-columns: 32px 130px minmax(180px, 1.7fr) minmax(120px, 1fr) 110px 120px 120px 50px;
    min-width: 820px;
}

/* Équipements gesinfo / gesmob — 7 col au lieu des 10 de gesmat : pastille |
   Code | Libellé | Type | Marque / modèle | Entreprise | actions. Modificateur
   posé EN PLUS de `--equipement` (dont les règles annexes restent utiles),
   sélecteur composé pour l'emporter quel que soit l'ordre de déclaration. */
.isis-grid--equipement.isis-grid--equipement-simple .isis-grid__head,
.isis-grid--equipement.isis-grid--equipement-simple .isis-grid__row {
    grid-template-columns: 32px 115px minmax(150px, 1.2fr) 125px minmax(150px, 1fr) minmax(150px, 0.9fr) 120px;
    min-width: 900px;
}

/* Mobilier (gesmob) — 7 col : pastille | Code | Libellé | Type | Marque / modèle |
   Entreprise | actions. Gabarit PROPRE au module, et non `--equipement-simple` : cette
   dernière sert AUSSI gesinfo, qui n'est pas harmonisé — l'élargir pour gesmob aurait
   déplacé les colonnes d'un écran hors chantier. Les largeurs sont supérieures à celles
   de `--equipement-simple` parce que quatre en-têtes portent désormais un bouton de tri
   ET un entonnoir : aux anciennes largeurs (115px sur « Code », 125px sur « Type ») les
   deux contrôles ne tiennent pas côte à côte. */
.isis-grid--gesmob-mobilier .isis-grid__head,
.isis-grid--gesmob-mobilier .isis-grid__row {
    grid-template-columns: 32px minmax(140px, 0.9fr) minmax(170px, 1.4fr) minmax(148px, 0.9fr) minmax(186px, 1fr) minmax(140px, 1fr) 96px;
    min-width: 958px;
}

/* Plans d'étage (gesfac) — 7 col : Site | Plan | Étage | Dimensions |
   Entreprise | Image GED | actions. */
.isis-grid--plans-etage .isis-grid__head, .isis-grid--plans-etage .isis-grid__row {
    grid-template-columns: minmax(150px, 1fr) minmax(180px, 1.4fr) 90px 130px minmax(150px, 1fr) 120px 110px;
    min-width: 930px;
}

/* Types d'emplacement (gesfac, page de configuration) — 7 col : Code | Libellé |
   Icône | Ordre | Origine | Poste de travail | actions. Nouveau modificateur : cette grille n'en avait
   AUCUN, donc elle retombait sur le gabarit de base et le configurateur de colonnes
   ne pouvait pas s'y attacher (DESIGN.md § 4, condition 2). Le nombre de pistes est
   égal au nombre de cellules d'en-tête — c'est ce contrôle-là qui décide. */
.isis-grid--gesfac-types .isis-grid__head, .isis-grid--gesfac-types .isis-grid__row {
    grid-template-columns: 150px minmax(200px, 1.6fr) minmax(140px, 1fr) 90px 130px 130px 110px;
    min-width: 960px;
}

/* Emplacements (gesfac) — 8 col : Code | Libellé | Type | Plan d'étage |
   Entreprise | Mode | État | actions. Le gabarit de base ouvrait sur une piste
   de 32px prévue pour une pastille : l'en-tête « Code » y débordait. */
.isis-grid--emplacements .isis-grid__head, .isis-grid--emplacements .isis-grid__row {
    grid-template-columns: 130px minmax(180px, 1.4fr) 120px minmax(150px, 1fr) minmax(140px, 1fr) 100px 100px 110px;
    min-width: 1030px;
}

.isis-tpl-kind {
    display: inline-flex;
    align-items: center;
    padding: 0.1rem 0.5rem;
    background: var(--isis-mod-gescom-soft);
    /* Bleu profond pour ratio AA ≥ 7:1 sur le fond gescom-soft (#eff6ff). */
    color: #1d3a8a;
    border-radius: 4px;
    font-size: 0.72rem;
    font-weight: 600;
    letter-spacing: 0.02em;
}

.isis-tpl-default {
    display: inline-flex;
    align-items: center;
    gap: 0.2rem;
    margin-left: 0.5rem;
    padding: 0.05rem 0.4rem;
    background: var(--isis-accent-soft);
    /* Bleu accent assombri pour ratio AA ≥ 6:1 sur accent-soft (#eef0f9). */
    color: #2e3a73;
    border-radius: 3px;
    font-size: 0.65rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}

/* Badge inline "Fichier introuvable" — signale qu'un template a son blob
   storage perdu (bucket purgé, suppression manuelle…). Calque .isis-tpl-default
   pour la cohérence visuelle, palette danger pour signaler l'urgence. */
.isis-tpl-orphan {
    display: inline-flex;
    align-items: center;
    gap: 0.2rem;
    margin-left: 0.5rem;
    padding: 0.05rem 0.4rem;
    background: var(--isis-danger-soft);
    color: #991b1b; /* red-800 — AA ≥ 6:1 sur danger-soft */
    border-radius: 3px;
    font-size: 0.65rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}

/* Discriminator de portée pour les templates DEVIS (phase BPU).
   STANDARD = bleu doux (devis ferme), BPU = bleu pâle dédié.
   Pas de version pour 'générique' (NULL) — l'absence du badge suffit
   à signaler la portée large. */
.isis-tpl-devis-type {
    display: inline-flex;
    align-items: center;
    margin-left: 0.4rem;
    padding: 0.05rem 0.4rem;
    border-radius: 3px;
    font-size: 0.65rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}
.isis-tpl-devis-type.is-standard {
    background: #e0e7ff; /* indigo-100 */
    color: #3730a3;      /* indigo-800 — AA ≥ 7:1 sur indigo-100 */
}
.isis-tpl-devis-type.is-bpu {
    background: #dbeafe; /* blue-100 — cohérent avec le badge BPU liste devis (.isis-devis-bpu-tag) */
    color: #1e40af;      /* blue-800 — AA ≥ 7:1 sur blue-100 */
}
.isis-tpl-devis-type.is-dqe {
    background: var(--isis-success-soft);
    color: var(--isis-success-text);
}

.isis-tpl-badges {
    display: flex;
    flex-wrap: wrap;
    gap: 0.35rem;
    margin-top: 0.2rem;
}

/* ============================================================================
   Upload custom (.docx) — InputFile natif visuellement masqué, label stylé.
   ============================================================================ */
.isis-tpl-upload {
    position: relative;
    display: block;
}
/* Input visuellement masqué mais accessible au clavier (focus relayé sur le label). */
.isis-tpl-upload__input {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}
.isis-tpl-upload__label {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.55rem 0.85rem;
    background: var(--isis-surface-alt);
    border: 1px solid var(--isis-border);
    border-radius: 6px;
    color: var(--isis-text);
    cursor: pointer;
    font-size: 0.875rem;
    transition: border-color 0.15s ease, background-color 0.15s ease;
    width: 100%;
}
.isis-tpl-upload__label:hover {
    border-color: var(--isis-current-mod, var(--isis-accent));
    background: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 14%, var(--isis-surface));
}
.isis-tpl-upload__input:focus-visible + .isis-tpl-upload__label {
    outline: 2px solid var(--isis-current-mod, var(--isis-accent));
    outline-offset: 2px;
}
.isis-tpl-upload__size {
    margin-left: auto;
    font-size: 0.75rem;
    color: var(--isis-text-muted);
    font-variant-numeric: tabular-nums;
}

/* Label inerte quand la sélection est pleine : sans cette règle le label garde son survol
   « cliquable » alors que l'input natif dessous refuse le clic. L'opacité ne porte aucune
   information à elle seule (1.4.1) — c'est le libellé du label qui dit la raison. */
.isis-tpl-upload__input:disabled + .isis-tpl-upload__label {
    cursor: not-allowed;
    opacity: 0.65;
}
.isis-tpl-upload__input:disabled + .isis-tpl-upload__label:hover {
    border-color: var(--isis-border);
    background: var(--isis-surface-alt);
}

/* ============================================================================
   Analyse pré-upload : feedback placeholders connus / inconnus / collection items.
   ============================================================================ */
.isis-tpl-analysis {
    margin-top: 0.65rem;
    padding: 0.7rem 0.85rem;
    background: var(--isis-surface-alt);
    border: 1px solid var(--isis-border);
    border-radius: 6px;
    display: flex;
    flex-direction: column;
    gap: 0.45rem;
}
.isis-tpl-analysis__row {
    display: flex;
    align-items: flex-start;
    gap: 0.55rem;
    font-size: 0.8rem;
    line-height: 1.45;
    color: var(--isis-text);
}
.isis-tpl-analysis__row--warning {
    background: var(--isis-warning-soft);
    border-radius: 4px;
    padding: 0.45rem 0.6rem;
    margin: 0 -0.2rem;
}
.isis-tpl-analysis__chips {
    display: flex;
    flex-wrap: wrap;
    gap: 0.3rem;
    margin-top: 0.35rem;
}
.isis-tpl-analysis__chips code {
    padding: 0.1rem 0.4rem;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: 3px;
    font-family: 'JetBrains Mono', 'Geist Mono', ui-monospace, monospace;
    font-size: 0.7rem;
    color: var(--isis-text-muted);
}

/* Champ readonly dans formulaires (.isis-form-linear) — pour metadata immuables.
   Couleur texte primaire (et non muted) pour contraste AA ≥ 6.8:1 sur surface-alt. */
.isis-readonly-field {
    padding: 0.55rem 0.7rem;
    background: var(--isis-surface-alt);
    border: 1px solid var(--isis-border);
    border-radius: 6px;
    font-size: 0.875rem;
    color: var(--isis-text);
    user-select: text;
}
.isis-readonly-field code {
    font-family: 'JetBrains Mono', 'Geist Mono', ui-monospace, monospace;
    font-size: 0.825rem;
}

/* Label associé à une checkbox dans .isis-form-linear (factorisation
   du style inline répété sur "Définir par défaut", "Template actif", etc.). */
.isis-form-linear .field-checkbox-label {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    cursor: pointer;
}

/* Screen-reader-only — utilitaire d'accessibilité standard. Visuel caché
   mais le texte reste lisible par les lecteurs d'écran. Préfixe rz- pour
   cohérence avec les classes Radzen. */
.rz-sr-only {
    position: absolute !important;
    width: 1px !important;
    height: 1px !important;
    padding: 0 !important;
    margin: -1px !important;
    overflow: hidden !important;
    clip: rect(0, 0, 0, 0) !important;
    white-space: nowrap !important;
    border: 0 !important;
}

/* Focus visible sur les rangées de grille focusables (role="row" tabindex=0).
   Cible exclusivement le focus clavier (pas la souris) via :focus-visible. */
.isis-grid__row:focus-visible {
    /* Généralisation 2026-06 : grille générique de toutes les listes → suit le module courant (était gescom en dur). */
    outline: 2px solid var(--isis-current-mod, var(--isis-accent));
    outline-offset: -2px;
    background: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 14%, var(--isis-surface));
}

/* ============================================================================
   Timeline carrière (page détail collaborateur)
   ============================================================================ */
.isis-timeline {
    list-style: none;
    padding: 0.4rem 0 0.4rem 1.2rem;
    margin: 0;
    position: relative;
}
.isis-timeline::before {
    content: "";
    position: absolute;
    left: 7px;
    top: 12px;
    bottom: 12px;
    width: 1px;
    background: var(--isis-border);
}
.isis-timeline__item {
    position: relative;
    padding: 0.6rem 0 0.6rem 1.4rem;
}
.isis-timeline__marker {
    position: absolute;
    left: -5px;
    top: 0.85rem;
    width: 13px;
    height: 13px;
    border-radius: 50%;
    background: var(--isis-surface);
    border: 2px solid var(--isis-border);
}
.isis-timeline__item.is-current .isis-timeline__marker {
    border-color: var(--isis-mod-sirh, #10b981);
    background: var(--isis-mod-sirh, #10b981);
    box-shadow: 0 0 0 3px var(--isis-mod-sirh-soft, #ecfdf5);
}
.isis-timeline__item.is-current .isis-timeline__content {
    background: var(--isis-mod-sirh-soft, #ecfdf5);
    border-color: var(--isis-mod-sirh, #10b981);
}
.isis-timeline__content {
    padding: 0.6rem 0.8rem;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: 6px;
}
.isis-timeline__period {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    flex-wrap: wrap;
    font-size: 0.72rem;
    color: var(--isis-text-soft);
    text-transform: uppercase;
    letter-spacing: 0.06em;
}
.isis-timeline__title {
    font-size: 0.95rem;
    font-weight: 600;
    color: var(--isis-text);
    margin-top: 0.2rem;
}
.isis-timeline__meta {
    display: flex;
    align-items: center;
    gap: 0.35rem;
    flex-wrap: wrap;
    font-size: 0.78rem;
    color: var(--isis-text-muted);
    margin-top: 0.2rem;
}
.isis-timeline__salary {
    margin-top: 0.4rem;
    font-size: 0.82rem;
    color: var(--isis-text);
}
.isis-timeline__notes {
    margin-top: 0.35rem;
    font-size: 0.78rem;
    color: var(--isis-text-soft);
    font-style: italic;
}

/* ── Chaîne d'approbation (sirh_absence_approval_step) ─────────────────── */
.isis-approval-chain {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
}
.isis-approval-chain__item {
    display: flex;
    gap: 0.7rem;
    align-items: flex-start;
    padding: 0.55rem 0.75rem;
    border: 1px solid var(--isis-border);
    border-radius: 6px;
    background: var(--isis-surface);
}
.isis-approval-chain__item.is-current {
    border-color: var(--isis-current-mod, var(--isis-accent));
    background: var(--isis-current-mod-soft, var(--isis-surface-alt));
}
.isis-approval-chain__item.is-rejected {
    border-color: var(--isis-danger);
    background: var(--isis-danger-soft, var(--isis-surface-alt));
}
.isis-approval-chain__item.is-skipped {
    opacity: 0.6;
}
/* V3.A — variante approved (succès) + carte d'embed banner */
.isis-approval-chain__item.is-approved {
    border-color: var(--isis-success, #16a34a);
    background: var(--isis-success-soft, #ecfdf5);
}
.isis-approval-card {
    background: color-mix(in srgb, var(--isis-mod-gesst) 7%, var(--isis-surface)) !important;
    border: 1px solid color-mix(in srgb, var(--isis-mod-gesst) 32%, transparent) !important;
}
/* V3.A puis V1.1 Phase 4 — grille niveaux dans le form dialog.
   5 colonnes : ordre / mode / quorum / validateur / label / actions
   (la colonne quorum n'affiche un input que si Kind=PARALLEL_QUORUM, sinon « — »).
   Mode + Quorum ont width fixe (140px + 80px) pour ne pas sacrifier l'espace validateur/label.
*/
.isis-grid--niveaux .isis-grid__head,
.isis-grid--niveaux .isis-grid__row {
    grid-template-columns: 70px 140px 80px 1fr 1fr 60px;
    align-items: center;
}

/* V1.1 Phase 4 — Header de niveau parallèle dans la chaîne d'approbation.
   Apparaît AVANT les N steps d'un niveau parallèle (PARALLEL_ALL/PARALLEL_QUORUM).
   Visuellement distinct : pas de bordure, fond accent-soft, layout horizontal compact. */
.isis-approval-chain__level-header {
    display: flex;
    align-items: center;
    gap: 0.45rem;
    padding: 0.35rem 0.7rem;
    background: var(--isis-current-mod-soft, var(--isis-accent-soft));
    border-radius: var(--isis-radius);
    font-size: 0.82rem;
    color: var(--isis-current-mod, var(--isis-accent));
    margin-top: 0.4rem;
    margin-bottom: -0.25rem;
}
.isis-approval-chain__level-label {
    font-weight: 500;
}
.isis-approval-chain__level-progress {
    margin-left: auto;
    font-size: 0.76rem;
    font-weight: 600;
    opacity: 0.85;
}

/* Step indenté de 14px quand membre d'un niveau parallèle (visuellement rattaché au header). */
.isis-approval-chain__item.is-parallel-member {
    margin-left: 14px;
}
.isis-approval-chain__marker {
    flex: 0 0 28px;
    width: 28px;
    height: 28px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    color: var(--isis-text-muted);
    background: var(--isis-surface-alt);
}
.isis-approval-chain__item.is-approved .isis-approval-chain__marker {
    color: var(--isis-success, #047857);
    background: var(--isis-success-soft, #ecfdf5);
}
.isis-approval-chain__item.is-rejected .isis-approval-chain__marker {
    color: var(--isis-danger);
    background: var(--isis-danger-soft, #fef2f2);
}
.isis-approval-chain__item.is-current .isis-approval-chain__marker {
    color: var(--isis-current-mod, var(--isis-accent));
    background: var(--isis-surface);
    border: 1px solid var(--isis-current-mod, var(--isis-accent));
}
.isis-approval-chain__content {
    flex: 1 1 auto;
    min-width: 0;
}
.isis-approval-chain__head {
    display: flex;
    flex-wrap: nowrap;          /* compact : tout sur une ligne, ellipsis sur le nom si nécessaire */
    align-items: baseline;
    gap: 0.5rem;
    min-width: 0;               /* permet aux enfants flex de rétrécir */
}
/* Cible le nom validateur — convention __item utilise <strong>,
   convention __step (DevisDetail) utilise <span class="__user">. */
.isis-approval-chain__head > strong,
.isis-approval-chain__head > .isis-approval-chain__user {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.isis-approval-chain__order {
    flex: 0 0 auto;             /* ne se compresse pas — l'ellipsis est sur le nom */
    font-size: 0.72rem;
    color: var(--isis-text-soft);
    text-transform: uppercase;
    letter-spacing: 0.06em;
}
.isis-approval-chain__status {
    flex: 0 0 auto;             /* idem — visible en entier, c'est le statut qu'on doit lire */
    font-size: 0.78rem;
    color: var(--isis-text-muted);
    white-space: nowrap;
}
.isis-approval-chain__current-badge {
    margin-left: auto;
    font-size: 0.72rem;
    color: var(--isis-current-mod, var(--isis-accent));
    background: var(--isis-surface);
    border: 1px solid var(--isis-current-mod, var(--isis-accent));
    padding: 0.1rem 0.45rem;
    border-radius: var(--isis-radius-pill);
    text-transform: uppercase;
    letter-spacing: 0.05em;
}
.isis-timeline__hint {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    margin-top: 0.5rem;
    padding: 0.4rem 0.6rem;
    font-size: 0.75rem;
    color: var(--isis-text-soft);
    background: var(--isis-surface-alt);
    border-radius: 4px;
}

/* ============================================================================
   Fixes audits UI/UX & a11y
   ============================================================================ */
/* Form linear : grille 2 colonnes pour les .isis-form-linear__row (utilisé partout) */
.isis-form-linear__row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 1rem;
}
.isis-form-linear__row > .field { min-width: 0; }

/* Utilitaires de largeur sur un champ d'une row form-linear — extraits de styles inline
   pour rester réactif au zoom navigateur ≤ 1200px (audit ui-ux gespla 2026-05-20). */
.isis-form-linear__field--xs { max-width: 140px; }
.isis-form-linear__field--sm { max-width: 200px; }
.isis-form-linear__field--md { max-width: 260px; }

/* ============================================================================
   IsisSidePanel — switch Détail/Filtres en haut + slot body
   ============================================================================ */
.isis-side-panel { padding: 0 !important; display: flex; flex-direction: column; }
.isis-side-panel__switch {
    display: flex;
    align-items: stretch;
    gap: 0;
    padding: 0.4rem 0.4rem 0;
    border-bottom: 1px solid var(--isis-border);
    background: var(--isis-surface);
    position: relative;
    z-index: 2;
}
.isis-side-panel__switch-btn {
    flex: 1;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.35rem;
    padding: 0.45rem 0.7rem;
    background: transparent;
    border: none;
    border-bottom: 2px solid transparent;
    margin-bottom: -1px;
    color: var(--isis-text-muted);
    font-size: 0.78rem;
    font-weight: 500;
    cursor: pointer;
    transition: color 120ms, border-color 120ms, background-color 120ms;
}
.isis-side-panel__switch-btn:hover:not(:disabled) {
    color: var(--isis-text);
    background: var(--isis-surface-alt);
}
.isis-side-panel__switch-btn:disabled {
    opacity: 0.4;
    cursor: not-allowed;
}
.isis-side-panel__switch-btn:focus-visible {
    outline: 2px solid var(--isis-current-mod, var(--isis-accent));
    outline-offset: -2px;
}
/* Onglet actif = couleur du MODULE (convention d'onglets du projet). L'accent global
   empilait deux accents différents à huit pixels d'écart, le segmenté du panneau et la
   barre de questions juste dessous. */
.isis-side-panel__switch-btn.is-active {
    color: var(--isis-current-mod, var(--isis-accent));
    border-bottom-color: var(--isis-current-mod, var(--isis-accent));
    font-weight: 600;
}
.isis-side-panel__badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 18px;
    height: 18px;
    padding: 0 5px;
    border-radius: 9px;
    background: var(--isis-accent);
    color: var(--isis-on-accent);
    font-size: 0.65rem;
    font-weight: 700;
    line-height: 1;
}
.isis-side-panel__body {
    flex: 1;
    overflow-y: auto;
    overflow-x: hidden;
    padding: 1rem;
}
/* Panneau qui porte le contrat `isis-side-panel` (donc `padding: 0`) mais dont un volet
   n'est pas une `__body` — c'est le cas du volet Détail de la liste des marchés, une
   coquille `.isis-detail-split` posée en enfant direct. Sans ce retrait, son contenu
   toucherait le cadre. Le composant IsisSidePanel, lui, enveloppe toujours dans `__body` :
   ce sélecteur ne matche donc que les panneaux montés à la main. */
.isis-side-panel > .isis-detail-split { padding: 1rem; }

/* ============================================================================
   Scroll-shadow CENTRALISÉ pour TOUS les sidepanels (recette Lea Verou, calquée
   sur le menu .isis-subnav__scroll). Barre de défilement masquée ; les fondus
   haut/bas — réglés via les tokens --isis-scroll-shadow-* dans :root — signalent
   le contenu masqué. Un seul endroit à toucher pour l'intensité de l'ombre.
   La couche de fond opaque finale empêche le fond de page de transparaître par le
   milieu transparent des bandes « cover ».
   ============================================================================ */
.isis-side-panel__body,
.isis-side-switcher__body,
.isis-detail-split__middle,
.isis-detail-split__bottom,
.isis-master-detail__detail:has(> .isis-detail-split) > .isis-detail-split,
.isis-master-detail__detail:has(> .isis-side-tabs) > .isis-side-search,
.isis-orgside__body,
.isis-master-detail--scrollable .isis-master-detail__detail {
    scrollbar-width: none;
    -ms-overflow-style: none;
    background:
        linear-gradient(var(--isis-scroll-shadow-bg) 30%, transparent) center top,
        linear-gradient(transparent, var(--isis-scroll-shadow-bg) 70%) center bottom,
        radial-gradient(farthest-side at 50% 0, var(--isis-scroll-shadow-ink), transparent) center top,
        radial-gradient(farthest-side at 50% 100%, var(--isis-scroll-shadow-ink), transparent) center bottom,
        var(--isis-scroll-shadow-bg);
    background-repeat: no-repeat;
    background-size:
        100% var(--isis-scroll-shadow-cover),
        100% var(--isis-scroll-shadow-cover),
        100% var(--isis-scroll-shadow-fade),
        100% var(--isis-scroll-shadow-fade),
        auto;
    background-attachment: local, local, scroll, scroll, local;
}
.isis-side-panel__body::-webkit-scrollbar,
.isis-side-switcher__body::-webkit-scrollbar,
.isis-detail-split__middle::-webkit-scrollbar,
.isis-detail-split__bottom::-webkit-scrollbar,
.isis-master-detail__detail:has(> .isis-detail-split) > .isis-detail-split::-webkit-scrollbar,
.isis-master-detail__detail:has(> .isis-side-tabs) > .isis-side-search::-webkit-scrollbar,
.isis-orgside__body::-webkit-scrollbar,
.isis-master-detail--scrollable .isis-master-detail__detail::-webkit-scrollbar { width: 0; height: 0; display: none; }

/* .isis-pl-details (planche « Ma semaine », mon-espace) : le même fondu, MAIS PAS le masquage
   de barre ci-dessus (round 3, tâche 6). Mesuré : 3 cartes opaques ne laissent qu'un filet de
   fond de ~6 px pour peindre le fondu de 30 px prévu — sous le seuil de perception, confondu
   avec la respiration normale entre deux cartes (surtout en sombre, delta ~10 niveaux). Un
   sidepanel masque sa barre parce que son contenu est du texte en flux qui laisse du fond
   visible en fin de liste ; ici, rien ne reste. La barre native devient l'indice PRINCIPAL
   (survit au sombre, au contraste renforcé, au mode de couleurs forcé, à l'absence de molette,
   et elle est actionnable) — le fondu reste posé en indice secondaire, il ne gêne pas. */
.isis-mesp-plan .isis-pl-details {
    background:
        linear-gradient(var(--isis-scroll-shadow-bg) 30%, transparent) center top,
        linear-gradient(transparent, var(--isis-scroll-shadow-bg) 70%) center bottom,
        radial-gradient(farthest-side at 50% 0, var(--isis-scroll-shadow-ink), transparent) center top,
        radial-gradient(farthest-side at 50% 100%, var(--isis-scroll-shadow-ink), transparent) center bottom,
        var(--isis-scroll-shadow-bg);
    background-repeat: no-repeat;
    background-size:
        100% var(--isis-scroll-shadow-cover),
        100% var(--isis-scroll-shadow-cover),
        100% var(--isis-scroll-shadow-fade),
        100% var(--isis-scroll-shadow-fade),
        auto;
    background-attachment: local, local, scroll, scroll, local;
}
/* Round 4 : « barre par défaut » ne suffit pas — sur macOS au repos (barres overlay), rien ne
   se voit avant la première interaction, donc rien ne signale qu'il reste du contenu. Dès
   qu'un ::-webkit-scrollbar porte une largeur ET une couleur de pouce, WebKit abandonne le
   mode overlay pour une barre CLASSIQUE et PERMANENTE, y compris macOS au repos — c'est ce
   qui manquait. scrollbar-color fait l'équivalent pour Firefox (ignore les pseudo-éléments
   WebKit). scrollbar-gutter: stable réserve la place en permanence : l'apparition de la barre
   ne doit jamais décaler les 3 cartes de 9 px.
   Couleur du pouce MESURÉE, pas supposée : --pl-line-strong (piste = --pl-paper) donne un
   contraste WCAG de ~2,6:1 en clair et ~3,0:1 en sombre — sous le seuil 3:1 (non-text contrast)
   en clair, à peine au-dessus en sombre ; --pl-rule, plus faible encore, était écarté d'office.
   --pl-ink-3 (= --isis-text-muted, DÉJÀ le token de `.isis-pl-vide`/`.isis-pl-sub` dans ce même
   bloc) donne ~7,6:1 en clair et ~7,0:1 en sombre — cohérent avec le commentaire d'origine du
   token (« ~6,98:1 sur --isis-surface », isis-theme.css:42993). Tokens uniquement, aucune
   couleur en dur. */
.isis-mesp-plan .isis-pl-details {
    scrollbar-width: thin;
    scrollbar-color: var(--pl-ink-3) transparent;
    scrollbar-gutter: stable;
}
.isis-mesp-plan .isis-pl-details::-webkit-scrollbar { width: 9px; }
.isis-mesp-plan .isis-pl-details::-webkit-scrollbar-track { background: var(--pl-paper); }
.isis-mesp-plan .isis-pl-details::-webkit-scrollbar-thumb {
    background: var(--pl-ink-3);
    border-radius: var(--pl-radius);
    border: 2px solid var(--pl-paper); /* pouce visuellement plus étroit que les 9px de piste, sans étape d'opacité en dur */
}
.isis-mesp-plan .isis-pl-details::-webkit-scrollbar-thumb:hover { background: var(--pl-ink-2); }

/* .isis-mesp-cartouche (planche « Ma semaine », mon-espace, round de correction 1 tâche 7) :
   même barre stylée que .isis-pl-details ci-dessus, même raison — au repos, macOS masque sa
   barre overlay et rien n'indique que le pied (Périmètre/Source/Établi le) est sous la ligne de
   flottaison. .isis-planche__cartouche-col est partagée par 13 autres planches : la règle
   partagée garde son overflow-y:auto nu, seule CETTE page (classe propre) reçoit la barre. */
.isis-mesp-cartouche {
    scrollbar-width: thin;
    scrollbar-color: var(--pl-ink-3) transparent;
    scrollbar-gutter: stable;
}
.isis-mesp-cartouche::-webkit-scrollbar { width: 9px; }
.isis-mesp-cartouche::-webkit-scrollbar-track { background: var(--pl-paper); }
.isis-mesp-cartouche::-webkit-scrollbar-thumb {
    background: var(--pl-ink-3);
    border-radius: var(--pl-radius);
    border: 2px solid var(--pl-paper);
}
.isis-mesp-cartouche::-webkit-scrollbar-thumb:hover { background: var(--pl-ink-2); }

/* Section de filtres dans le side panel (groupe de champs avec titre) */
.isis-filter-group {
    margin-bottom: 1rem;
}
.isis-filter-group__title {
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--isis-text-soft);
    font-weight: 600;
    margin-bottom: 0.4rem;
}
.isis-filter-group__field { margin-bottom: 0.5rem; }
.isis-filter-actions {
    display: flex;
    gap: 0.4rem;
    margin-top: 1rem;
    padding-top: 0.85rem;
    border-top: 1px solid var(--isis-border);
}

/* Accordion natif <details>/<summary> aligné Flat ISIS */
.isis-accordion {
    border: 1px solid var(--isis-border);
    border-radius: 6px;
    margin-bottom: 0.6rem;
    background: var(--isis-surface);
    overflow: hidden;
}
.isis-accordion__summary {
    list-style: none;
    cursor: pointer;
    padding: 0.65rem 0.85rem;
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--isis-text);
    user-select: none;
    transition: background-color 120ms;
}
.isis-accordion__summary::-webkit-details-marker { display: none; }
.isis-accordion__summary:hover { background: var(--isis-surface-alt); }
.isis-accordion__chevron {
    margin-left: auto;
    transition: transform 200ms ease;
    color: var(--isis-text-muted);
}
.isis-accordion[open] > .isis-accordion__summary .isis-accordion__chevron {
    transform: rotate(180deg);
}
.isis-accordion[open] > .isis-accordion__summary {
    border-bottom: 1px solid var(--isis-border);
}
.isis-accordion__body {
    padding: 0.85rem;
    background: var(--isis-surface);
}

/* Bloc d'information contextuel en tête d'un form (ex: position courante dans "Changer de poste") */
.isis-form-linear__hint {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    padding: 0.6rem 0.8rem;
    background: var(--isis-surface-alt);
    border: 1px solid color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 32%, var(--isis-border));
    border-radius: 4px;
    margin-bottom: 0.85rem;
    font-size: 0.85rem;
    color: var(--isis-text);
}

/* Dialog « justificatifs » (échéance / jalon). Le paragraphe d'intro est de la PROSE
   (avec des <strong>) : surtout PAS display:flex (sinon chaque segment devient un
   flex-item séparé et la phrase se fragmente). */
.isis-jalon-preuve {
    display: flex;
    flex-direction: column;
    gap: 0.85rem;
    padding: 0.25rem 0.1rem;
}
.isis-jalon-preuve > p {
    margin: 0;
    padding: 0.65rem 0.85rem;
    font-size: 0.85rem;
    line-height: 1.55;
    color: var(--isis-text);
    background: var(--isis-surface-alt);
    border: 1px solid var(--isis-current-mod, var(--isis-accent));
    box-sizing: border-box;
    border-radius: 4px;
}

/* Chips dot variantes manquantes */
.isis-chip__dot.is-all   { background: var(--isis-text-soft); }
.isis-chip__dot.is-muted { background: #9ca3af; }

/* Alignement droite des colonnes numériques */
.isis-grid__col-headcount,
.isis-grid__col-headcount-head { justify-content: flex-end; text-align: right; }

/* ============================================================================
   .isis-workflow-diagram — Flowchart SVG horizontal du workflow devis.
   ----------------------------------------------------------------------------
   3 types de formes :
     - state    (rect arrondi) : étape de processus (DRAFT, PENDING, APPROVED, SENT)
     - decision (losange)      : point de bifurcation
     - terminal (pill)         : statut final (ACCEPTED, REJECTED, EXPIRED, REVISED, CANCELLED)
   ============================================================================ */
.isis-workflow-diagram {
    background: transparent;
    padding: 0.25rem 0 0;
    margin: 0;
}
.isis-workflow-diagram__legend {
    display: flex;
    flex-wrap: wrap;
    gap: 0.7rem;
    align-items: center;
    font-size: 0.66rem;
    color: var(--isis-text-soft);
    margin-bottom: 0.4rem;
}
.isis-workflow-diagram__legend span { display: inline-flex; align-items: center; gap: 0.3rem; }
.isis-workflow-legend__sep { color: var(--isis-border); margin: 0 0.2rem; }

/* Aperçus de formes dans la légende */
.isis-workflow-legend__shape {
    width: 14px; height: 9px;
    display: inline-block;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
}
.isis-workflow-legend__shape.is-state    { border-radius: 2px; }
.isis-workflow-legend__shape.is-decision { transform: rotate(45deg); width: 9px; height: 9px; }
.isis-workflow-legend__shape.is-terminal { border-radius: var(--isis-radius-pill); }

.isis-workflow-legend__dot {
    width: 8px; height: 8px; border-radius: 50%;
    display: inline-block;
}
.isis-workflow-legend__dot.is-done        { background: #16a34a; }
.isis-workflow-legend__dot.is-current     { background: var(--isis-mod-gescom); box-shadow: 0 0 0 1.5px var(--isis-mod-gescom-soft); }
.isis-workflow-legend__dot.is-future      { background: var(--isis-border-strong); }
.isis-workflow-legend__dot.is-unreachable { background: transparent; border: 1px dashed var(--isis-border-strong); }

/* Glyphe de légende — reprend les symboles posés sur les nodes (✓ ● ○ ✕) pour
   que le statut ne soit jamais porté par la seule couleur (WCAG 1.4.11). */
.isis-workflow-legend__glyph {
    font-size: 0.82rem;
    line-height: 1;
    margin: 0 0.18rem 0 0.05rem;
    color: var(--isis-text-soft);
}

.isis-workflow-svg {
    width: 100%;
    height: auto;
    max-height: 360px;
    display: block;
}
.isis-workflow-svg text { font-family: inherit; user-select: none; }

/* ── Nodes (formes) ──
   .isis-wf-node__shape = polygon, rect ou pill selon Kind */
.isis-wf-node { cursor: help; }
.isis-wf-node__shape {
    fill: var(--isis-surface);
    stroke: var(--isis-border);
    stroke-width: 1;
    transition: fill 120ms ease, stroke 120ms ease;
}
.isis-wf-node__label {
    /* viewBox 1180 large rendu ~0.76× sur un panel d'onglet : fontes nominales
       remontées pour que le rendu effectif reste ≥ ~9px lisibles. */
    font-size: 13px;
    font-weight: 600;
    fill: var(--isis-text);
    dominant-baseline: middle;
    text-anchor: middle;
}
.isis-wf-node__label.is-decision-label { font-size: 11px; }
.isis-wf-node:hover .isis-wf-node__shape { stroke: var(--isis-mod-gescom); }

/* Glyphe de statut (coin haut-gauche) — double la couleur pour les daltoniens
   (WCAG 1.4.11). ✓ passé · ● actuel · ○ à venir · ✕ inaccessible. */
.isis-wf-node__glyph {
    font-size: 10px;
    font-weight: 700;
    dominant-baseline: middle;
    text-anchor: middle;
    fill: var(--isis-text-muted);
}
.isis-wf-node.is-done .isis-wf-node__glyph        { fill: var(--isis-success-text); }
.isis-wf-node.is-current .isis-wf-node__glyph     { fill: var(--isis-current-mod, var(--isis-accent)); }
.isis-wf-node.is-future .isis-wf-node__glyph      { fill: var(--isis-text-muted); }
.isis-wf-node.is-unreachable .isis-wf-node__glyph { fill: var(--isis-border-strong); }

/* États passés (vert) */
.isis-wf-node.is-done .isis-wf-node__shape { fill: var(--isis-success-soft); stroke: var(--isis-success); }
.isis-wf-node.is-done .isis-wf-node__label { fill: var(--isis-success-text); }

/* Étape courante (accent + bordure renforcée + pulse) — pas de drop-shadow :
   DESIGN.md impose le Flat absolu, le relief vient de la bordure 2.5px. */
.isis-wf-node.is-current .isis-wf-node__shape {
    /* Généralisation 2026-06 : diagrammes workflow partagés (7 modules) → suivent le module courant. */
    fill: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 14%, var(--isis-surface));
    stroke: var(--isis-current-mod, var(--isis-accent));
    stroke-width: 2.5;
    animation: isis-wf-pulse-shape 1.8s ease-in-out infinite;
}
.isis-wf-node.is-current .isis-wf-node__label { fill: var(--isis-current-mod, var(--isis-accent)); font-weight: 600; }

@keyframes isis-wf-pulse-shape {
    0%, 100% { opacity: 1; }
    50%      { opacity: 0.78; }
}

/* Respect des préférences système : pas de pulse perpétuel — l'étape courante
   reste signalée par sa couleur d'accent + bordure renforcée. */
@media (prefers-reduced-motion: reduce) {
    .isis-wf-node.is-current .isis-wf-node__shape { animation: none; }
}

/* À venir (gris pâle) */
.isis-wf-node.is-future .isis-wf-node__shape { fill: var(--isis-surface-alt); stroke: var(--isis-border); }
.isis-wf-node.is-future .isis-wf-node__label { fill: var(--isis-text-muted); }

/* Inaccessible (dashed grisé) */
.isis-wf-node.is-unreachable .isis-wf-node__shape { fill: transparent; stroke: var(--isis-border); stroke-dasharray: 4 3; }
.isis-wf-node.is-unreachable .isis-wf-node__label { fill: var(--isis-border-strong); }

/* Edges (flèches) */
.isis-wf-edge {
    stroke: #94a3b8;
    stroke-width: 1.4;
    fill: none;
}
.isis-wf-edge.is-done    { stroke: #16a34a; }
.isis-wf-edge.is-current { stroke: var(--isis-current-mod, var(--isis-accent)); stroke-width: 2; }
.isis-wf-edge.is-future  { stroke: #b0bac9; stroke-width: 1.4; }
/* Arcs secondaires (contournement envoi direct, retour rejet approbateur) :
   volontairement plus pâles que le flux principal pour ne pas concurrencer
   le « happy path » en lecture rapide. */
.isis-wf-edge.is-dashed  { stroke: #dde1e9; stroke-width: 1; stroke-dasharray: 4 3; }
.isis-workflow-svg #wfArrow path { fill: #94a3b8; }

/* Labels d'arêtes (oui/non, accepté/refusé...) */
.isis-wf-edge-label {
    font-size: 11.5px;
    fill: var(--isis-text-muted);
    font-style: italic;
}
.isis-wf-note {
    font-size: 11px;
    fill: var(--isis-text-soft);
    font-style: italic;
}

/* Annotation datée sous un node franchi (alimentée par le journal de workflow).
   tabular-nums : les dates s'alignent verticalement entre colonnes.
   En mode agrégé, le même slot porte les compteurs « N · ↑M » (cf. plus bas
   .isis-workflow-svg--aggregate .isis-wf-node-annot). */
.isis-wf-node-annot {
    /* 11px nominal : cohérent avec .isis-wf-note, reste lisible une fois le
       viewBox 1180 réduit (~0.76×) sur un panneau d'onglet. */
    font-size: 11px;
    fill: var(--isis-text-muted);
    text-anchor: middle;
    font-variant-numeric: tabular-nums;
}

/* ─── Mode agrégé du diagramme (page /gescom/pipeline) ──────────────────
   Tous les nodes non-décision sont neutres ; le compteur stock+flux porte
   le sens. On dérive les nodes "is-aggregate" sur un visuel proche du
   "is-future" mais sans le glyphe ○ (qui voudrait dire "à venir"). */
.isis-wf-node.is-aggregate .isis-wf-node__shape {
    fill: var(--isis-surface);
    stroke: var(--isis-border-strong, var(--isis-border-strong));
    stroke-width: 1.5;
}
.isis-wf-node.is-aggregate .isis-wf-node__label {
    fill: var(--isis-text);
    font-weight: 500;
}
/* Au survol d'un node agrégé, surligner pour le rendre visiblement
   interactif (clic = drill-down stock). */
.isis-workflow-svg--aggregate .isis-wf-node.is-aggregate:hover .isis-wf-node__shape {
    stroke: var(--isis-current-mod, var(--isis-accent));
    stroke-width: 2;
}
/* Node cliquable : curseur main + hover stroke (le seul cursor ne suffit pas
   à signaler la cliquabilité, surtout sur démo écran partagé / écran tactile)
   + focus visible pour navigation clavier. */
.isis-wf-node.is-clickable { cursor: pointer; }
.isis-wf-node.is-clickable:hover .isis-wf-node__shape {
    stroke: var(--isis-current-mod, var(--isis-accent));
    stroke-width: 1.5;
}
.isis-wf-node.is-clickable:focus { outline: none; }
.isis-wf-node.is-clickable:focus-visible .isis-wf-node__shape {
    stroke: var(--isis-current-mod, var(--isis-accent));
    stroke-width: 2.5;
    filter: drop-shadow(0 0 3px color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 50%, transparent));
}
/* Node sélectionné (drill ouvert) : stroke marqué + fond teinté pour le
   distinguer nettement du hover. Override l'inline `fill` du heatmap via
   !important (sinon le node sélectionné garde sa couleur heatmap et la
   sélection devient invisible sur un node intensément teinté). */
.isis-wf-node.is-selected .isis-wf-node__shape {
    stroke: var(--isis-current-mod, var(--isis-accent));
    stroke-width: 2.5;
    fill: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 14%, var(--isis-surface)) !important;
}
.isis-wf-node.is-selected .isis-wf-node__label {
    font-weight: 600;
}
/* Annotation agrégée : compteurs en gros (poids 600), monospace tabular-nums
   pour alignement vertical, accent module gescom pour signaler la valeur. */
.isis-workflow-svg--aggregate .isis-wf-node-annot {
    font-size: 13px;
    font-weight: 600;
    fill: var(--isis-text);
    font-variant-numeric: tabular-nums;
}
/* Distinguer les losanges de décision en mode agrégé : ils ne portent pas de
   compteur (ce sont des points de structure du workflow, pas des statuts
   comptabilisables) — on les rend en tirets sur fond surface-alt pour signaler
   visuellement "structure, pas donnée" et éviter la confusion avec is-future
   du mode Individual (= "pas encore atteint"). */
.isis-workflow-svg--aggregate .isis-wf-node.is-future .isis-wf-node__shape {
    fill: var(--isis-surface-alt);
    stroke: var(--isis-border-strong, var(--isis-border-strong));
    stroke-dasharray: 4 3;
}
.isis-workflow-svg--aggregate .isis-wf-node.is-future .isis-wf-node__label {
    fill: var(--isis-text-muted);
    font-weight: 500;
}

/* Legend : pastille neutre pour l'agrégat (pas de "passé / actuel / futur").
   Fond surface-alt pour contraste 3:1+ avec la bordure (WCAG 1.4.11). */
.isis-workflow-legend__dot.is-aggregate {
    background: var(--isis-surface-alt);
    border: 1.5px solid var(--isis-border-strong, var(--isis-border-strong));
}
/* Pastille "structure" — losanges de décision en mode agrégé : tiretée pour
   signaler "point de structure, pas de donnée". Calque le rendu node. */
.isis-workflow-legend__dot.is-structure {
    background: var(--isis-surface-alt);
    border: 1.5px dashed var(--isis-border-strong, var(--isis-border-strong));
}
/* Pastille "heatmap" — gradient multi-couleurs (vert → jaune → rouge) qui
   matche l'interpolation HSL appliquée aux nodes du diagramme (cf. HeatStyle
   dans DevisWorkflowDiagram.razor : hue 120→0, lightness 88→67). */
.isis-workflow-legend__heat {
    display: inline-block;
    width: 36px;
    height: 10px;
    border-radius: 2px;
    margin-right: 0.3rem;
    vertical-align: middle;
    background: linear-gradient(to right,
        hsl(120, 75%, 88%),  /* faible — vert pâle */
        hsl(60,  75%, 78%),  /* moyen — jaune */
        hsl(0,   75%, 67%)); /* élevé — rouge */
    border: 1px solid var(--isis-border, var(--isis-border));
}

/* Bandelette contextuelle (sous le SVG) — compacte */
.isis-workflow-branch {
    display: flex;
    gap: 0.5rem;
    align-items: center;
    padding: 0.4rem 0.65rem;
    margin-top: 0.6rem;
    border-radius: 4px;
    font-size: 0.75rem;
    line-height: 1.35;
}
.isis-workflow-branch strong { font-size: 0.78rem; }
.isis-workflow-branch__inline { margin-left: 0.4rem; font-style: italic; color: var(--isis-text-muted); }
.isis-workflow-branch__action { margin-left: 0.4rem; color: var(--isis-text); }
/* Liens « Voir l'onglet … » dans les bandeaux contextuels du workflow commande (2026-06-07). */
.isis-workflow-branch__links { display: inline-flex; flex-wrap: wrap; gap: 0.75rem; margin-top: 0.3rem; }
.isis-workflow-branch__links .isis-text-link { background: none; border: none; padding: 0; font: inherit; cursor: pointer; color: var(--isis-mod-gesproj); display: inline-flex; align-items: center; gap: 0.1rem; font-weight: 600; }
.isis-workflow-branch__links .isis-text-link:hover { text-decoration: underline; }
.isis-workflow-branch__links .isis-text-link:focus-visible { outline: 2px solid var(--isis-accent); outline-offset: 2px; border-radius: 3px; }
.isis-workflow-branch--danger  { background: #fef2f2; border: 1px solid #dc2626; color: #991b1b; }
.isis-workflow-branch--warning { background: #fffbeb; border: 1px solid #d97706; color: #92400e; }
.isis-workflow-branch--muted   { background: var(--isis-surface-alt); border: 1px solid var(--isis-text-soft); color: var(--isis-text-muted); }
.isis-workflow-branch--info    { background: var(--isis-mod-gescom-soft); border: 1px solid var(--isis-mod-gescom); color: var(--isis-text); }

@media (max-width: 1100px) {
    .isis-workflow-svg { min-width: 1000px; }
    .isis-workflow-diagram { overflow-x: auto; }
}

/* Workflow intégré (swimlanes horizontales A+B) : viewBox compactée v3 1468×380,
   ratio ≈ 3.86:1. Min-width 1100px → fit confortable sur tout écran ≥ 13".
   Scroll-X si plus étroit. */
.isis-workflow-svg--integrated {
    max-height: none;
    min-width: 1100px;
}
.isis-workflow-diagram:has(.isis-workflow-svg--integrated) {
    overflow-x: auto;
    overflow-y: hidden;
    padding-bottom: 0.25rem;
}

/* Historique des transitions — sous le diagramme, dans l'onglet Workflow */
.isis-workflow-history {
    margin-top: 1.25rem;
    padding-top: 1rem;
    border-top: 1px solid var(--isis-border);
}
.isis-workflow-history__title {
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--isis-text-soft);
    margin-bottom: 0.6rem;
}

/* ----------------------------------------------------------------------------
   Modificateurs de palette par module — diagrammes workflow simplifiés
   (EngagementWorkflowDiagram pour gesst, CommandeWorkflowDiagram pour gesproj).
   Le diagramme de base hardcode --isis-mod-gescom sur l'état actuel ; ces
   modificateurs swap la couleur d'accent pour rester cohérent avec l'identité
   chromatique du module hôte.
   ---------------------------------------------------------------------------- */

/* GESST — pink-700 (#be185d) */
.isis-workflow-svg--gesst .isis-wf-node.is-current .isis-wf-node__shape {
    fill: var(--isis-mod-gesst-soft);
    stroke: var(--isis-mod-gesst);
}
.isis-workflow-svg--gesst .isis-wf-node.is-current .isis-wf-node__label {
    fill: var(--isis-mod-gesst);
}
.isis-workflow-svg--gesst .isis-wf-node.is-current .isis-wf-node__glyph {
    fill: var(--isis-mod-gesst);
}
.isis-workflow-svg--gesst .isis-wf-node:hover .isis-wf-node__shape {
    stroke: var(--isis-mod-gesst);
}
.isis-workflow-svg--gesst .isis-wf-edge.is-current {
    stroke: var(--isis-mod-gesst);
}
.isis-workflow-legend__dot.is-current--gesst {
    background: var(--isis-mod-gesst);
    box-shadow: 0 0 0 1.5px var(--isis-mod-gesst-soft);
}
.isis-workflow-branch--gesst-info {
    background: var(--isis-mod-gesst-soft);
    border: 1px solid var(--isis-mod-gesst);
    box-sizing: border-box;
    color: var(--isis-text);
}

/* GESPROJ — cyan-700 (#0e7490) */
.isis-workflow-svg--gesproj .isis-wf-node.is-current .isis-wf-node__shape {
    fill: var(--isis-mod-gesproj-soft);
    stroke: var(--isis-mod-gesproj);
}
.isis-workflow-svg--gesproj .isis-wf-node.is-current .isis-wf-node__label {
    fill: var(--isis-mod-gesproj);
}
.isis-workflow-svg--gesproj .isis-wf-node.is-current .isis-wf-node__glyph {
    fill: var(--isis-mod-gesproj);
}
.isis-workflow-svg--gesproj .isis-wf-node:hover .isis-wf-node__shape {
    stroke: var(--isis-mod-gesproj);
}
.isis-workflow-svg--gesproj .isis-wf-edge.is-current {
    stroke: var(--isis-mod-gesproj);
}
.isis-workflow-legend__dot.is-current--gesproj {
    background: var(--isis-mod-gesproj);
    box-shadow: 0 0 0 1.5px var(--isis-mod-gesproj-soft);
}
.isis-workflow-branch--gesproj-info {
    background: var(--isis-mod-gesproj-soft);
    border: 1px solid var(--isis-mod-gesproj);
    box-sizing: border-box;
    color: var(--isis-text);
}

/* GESMAFF — ambre (#d97706). Calque structurel des autres modules. */
.isis-workflow-svg--gesmaff .isis-wf-node.is-current .isis-wf-node__shape {
    fill: var(--isis-mod-gesmaff-soft);
    stroke: var(--isis-mod-gesmaff);
}
.isis-workflow-svg--gesmaff .isis-wf-node.is-current .isis-wf-node__label {
    fill: var(--isis-mod-gesmaff);
}
.isis-workflow-svg--gesmaff .isis-wf-node.is-current .isis-wf-node__glyph {
    fill: var(--isis-mod-gesmaff);
}
.isis-workflow-svg--gesmaff .isis-wf-node:hover .isis-wf-node__shape {
    stroke: var(--isis-mod-gesmaff);
}
.isis-workflow-svg--gesmaff .isis-wf-edge.is-current {
    stroke: var(--isis-mod-gesmaff);
}
.isis-workflow-legend__dot.is-current--gesmaff {
    background: var(--isis-mod-gesmaff);
    box-shadow: 0 0 0 1.5px var(--isis-mod-gesmaff-soft);
}
.isis-workflow-branch--gesmaff-info {
    background: var(--isis-mod-gesmaff-soft);
    border: 1px solid var(--isis-mod-gesmaff);
    box-sizing: border-box;
    color: var(--isis-text);
}

/* ============================================================================
   Onglet « Versions » du devis — liste des versions closes + viewer figé
   (versioning in-place, cf. migration 0082)
   ============================================================================ */
.isis-version-intro {
    font-size: 0.8rem;
    line-height: 1.5;
    color: var(--isis-text-soft);
    background: var(--isis-bg-subtle, var(--isis-surface-alt));
    border: 1px solid var(--isis-border);
    border-radius: 6px;
    padding: 0.7rem 0.85rem;
    margin-bottom: 1rem;
}
.isis-version-list {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}
.isis-version-row {
    display: flex;
    align-items: flex-start;
    gap: 0.85rem;
    padding: 0.75rem 0.9rem;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: 6px;
}
.isis-version-row--current {
    background: var(--isis-mod-gescom-soft);
}
.isis-version-row__badge {
    flex-shrink: 0;
    min-width: 38px;
    height: 38px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 700;
    font-size: 0.8rem;
    color: var(--isis-current-mod, var(--isis-mod-gescom));
    background: var(--isis-mod-gescom-soft);
    border-radius: 6px;
    font-variant-numeric: tabular-nums;
}
.isis-version-row--current .isis-version-row__badge {
    color: var(--isis-surface);
    background: var(--isis-current-mod, var(--isis-mod-gescom));
}

/* P-bis : snapshot interne (DRAFT_SNAPSHOT) — variante visuelle distincte de
   la version officielle. Bordure latérale et badge en accent secondaire. */
.isis-version-row--snapshot {
    background: color-mix(in srgb, var(--isis-accent) 4%, var(--isis-surface));
}
.isis-version-row__badge--snapshot {
    color: var(--isis-surface);
    background: var(--isis-accent);
    min-width: 52px;
    font-size: 0.72rem;
    letter-spacing: 0.05em;
}

/* Section P-bis : « Versions envoyées au client » / « Instantanés internes ». */
.isis-version-section {
    margin-top: 1rem;
}
.isis-version-section__title {
    margin: 0 0 0.15rem;
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--isis-text);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}
.isis-version-section__subtitle {
    margin: 0 0 0.6rem;
    font-size: 0.8rem;
    color: var(--isis-text-muted);
}
.isis-version-row__body { flex: 1 1 auto; min-width: 0; }
.isis-version-row__head {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    flex-wrap: wrap;
}
.isis-version-row__title {
    font-weight: 600;
    font-size: 0.85rem;
    color: var(--isis-text);
}
.isis-version-row__date {
    font-size: 0.72rem;
    color: var(--isis-text-muted);
    font-variant-numeric: tabular-nums;
}
.isis-version-row__meta {
    font-size: 0.76rem;
    color: var(--isis-text-soft);
    margin-top: 0.2rem;
}
.isis-version-row__reason {
    font-size: 0.76rem;
    color: var(--isis-text-soft);
    font-style: italic;
    margin-top: 0.3rem;
}
.isis-version-row__action {
    flex-shrink: 0;
    display: flex;
    align-items: center;
}
.isis-version-row__hint {
    font-size: 0.72rem;
    color: var(--isis-text-muted);
}
.isis-version-empty {
    font-size: 0.8rem;
    color: var(--isis-text-muted);
    padding: 1rem;
    text-align: center;
    border: 1px dashed var(--isis-border);
    border-radius: 6px;
}

/* Viewer dialog — contenu figé d'une version, lecture seule */
.isis-version-viewer {
    display: flex;
    flex-direction: column;
    gap: 1.25rem;
}
.isis-version-viewer__state {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    padding: 1.5rem;
    color: var(--isis-text-muted);
    font-size: 0.85rem;
}
.isis-version-viewer__head {
    display: flex;
    gap: 0.85rem;
    align-items: flex-start;
    padding-bottom: 0.85rem;
    border-bottom: 1px solid var(--isis-border);
}
.isis-version-viewer__badge {
    flex-shrink: 0;
    min-width: 44px;
    height: 44px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 700;
    color: var(--isis-surface);
    background: var(--isis-current-mod, var(--isis-mod-gescom));
    border-radius: 6px;
    font-variant-numeric: tabular-nums;
}
/* P-bis : header viewer en mode snapshot interne — accent secondaire chaud. */
.isis-version-viewer__head--snapshot {
    border-bottom-color: color-mix(in srgb, var(--isis-accent) 30%, var(--isis-border));
}
.isis-version-viewer__badge--snapshot {
    background: var(--isis-accent);
    min-width: 56px;
    font-size: 0.75rem;
    letter-spacing: 0.05em;
}
/* P-bis : indicateurs marge dans le viewer. */
.isis-version-viewer__total-divider {
    height: 1px;
    background: var(--isis-border);
    margin: 0.45rem 0;
}
.isis-version-viewer__total-row--margin {
    font-weight: 700;
    font-size: 1rem;
}
.isis-version-viewer__total-hint {
    margin-top: 0.5rem;
    padding: 0.5rem 0.75rem;
    background: color-mix(in srgb, var(--isis-text-muted) 8%, var(--isis-surface));
    border-radius: 4px;
    font-size: 0.78rem;
    color: var(--isis-text-muted);
    font-style: italic;
}
.isis-margin-neg {
    color: var(--isis-danger);
}

/* ═══════════════════════════════════════════════════════════════════════════
   P-bis : Snapshot browser dialog (master-detail + diff vs courant)
   ═══════════════════════════════════════════════════════════════════════════ */

.isis-snapshot-browser {
    display: grid;
    grid-template-columns: 280px 1fr;
    height: 100%;
    min-height: 0;
    gap: 0;
}
.isis-snapshot-browser__loading {
    grid-column: 1 / -1;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 3rem;
}

/* ─── Panneau gauche : liste des snapshots ─────────────────────────────── */
.isis-snapshot-browser__rail {
    border-right: 1px solid var(--isis-border);
    background: var(--isis-surface-alt);
    display: flex;
    flex-direction: column;
    min-height: 0;
    overflow: hidden;
}
.isis-snapshot-browser__rail-head {
    padding: 0.75rem 0.85rem;
    border-bottom: 1px solid var(--isis-border);
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    background: var(--isis-surface);
}
.isis-snapshot-browser__rail-head h3 {
    margin: 0;
    font-size: 0.78rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--isis-text-muted);
}
.isis-snapshot-browser__empty-rail {
    padding: 1.5rem 1rem;
    text-align: center;
    color: var(--isis-text-muted);
    font-size: 0.8rem;
}
.isis-snapshot-browser__empty-rail .hint {
    font-size: 0.75rem;
    color: var(--isis-text-muted);
    opacity: 0.7;
    margin-top: 0.3rem;
}
.isis-snapshot-browser__list {
    list-style: none;
    margin: 0;
    padding: 0.5rem;
    overflow-y: auto;
    flex: 1 1 auto;
    min-height: 0;
}
.isis-snapshot-browser__item {
    padding: 0.6rem 0.7rem;
    margin-bottom: 0.3rem;
    border-radius: 4px;
    border: 1px solid transparent;
    cursor: pointer;
    background: var(--isis-surface);
    transition: background 120ms ease, border 120ms ease;
}
.isis-snapshot-browser__item:hover {
    background: color-mix(in srgb, var(--isis-accent) 6%, var(--isis-surface));
    border-color: color-mix(in srgb, var(--isis-accent) 25%, transparent);
}
.isis-snapshot-browser__item.is-selected {
    background: color-mix(in srgb, var(--isis-accent) 12%, var(--isis-surface));
    border-color: var(--isis-accent);
}
.isis-snapshot-browser__item:focus-visible {
    outline: 2px solid var(--isis-accent);
    outline-offset: 1px;
}
.isis-snapshot-browser__item-label {
    font-weight: 600;
    font-size: 0.88rem;
    color: var(--isis-text);
    line-height: 1.3;
    margin-bottom: 0.2rem;
}
.isis-snapshot-browser__item-meta {
    font-size: 0.72rem;
    color: var(--isis-text-muted);
}
.isis-snapshot-browser__item-totals {
    font-size: 0.78rem;
    font-weight: 600;
    color: var(--isis-text);
    margin-top: 0.2rem;
    font-variant-numeric: tabular-nums;
}

/* ─── Panneau principal : contenu du snapshot sélectionné ──────────────── */
.isis-snapshot-browser__main {
    display: flex;
    flex-direction: column;
    min-height: 0;
    overflow: hidden;
    padding: 1rem 1.25rem;
}
.isis-snapshot-browser__empty {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    color: var(--isis-text-muted);
    gap: 0.5rem;
}
.isis-snapshot-browser__empty h3 { margin: 0; font-size: 1rem; }
.isis-snapshot-browser__empty p { margin: 0; font-size: 0.85rem; }

.isis-snapshot-browser__head {
    display: flex;
    gap: 0.75rem;
    align-items: flex-start;
    padding-bottom: 0.85rem;
    border-bottom: 1px solid var(--isis-border);
}
.isis-snapshot-browser__badge {
    flex-shrink: 0;
    min-width: 56px;
    height: 44px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--isis-accent);
    color: var(--isis-surface);
    font-weight: 700;
    font-size: 0.75rem;
    letter-spacing: 0.05em;
    border-radius: 6px;
}
.isis-snapshot-browser__head-body { flex: 1 1 auto; min-width: 0; }
.isis-snapshot-browser__head-body h2 {
    margin: 0;
    font-size: 1.05rem;
    font-weight: 600;
    color: var(--isis-text);
}
.isis-snapshot-browser__head-sub {
    font-size: 0.78rem;
    color: var(--isis-text-muted);
    margin-top: 0.1rem;
}
.isis-snapshot-browser__head-notes {
    font-size: 0.82rem;
    color: var(--isis-text);
    font-style: italic;
    margin-top: 0.4rem;
    padding: 0.4rem 0.6rem;
    background: var(--isis-surface-alt);
    border-radius: 4px;
}

.isis-snapshot-browser__diff-banner {
    margin: 0.75rem 0;
    padding: 0.55rem 0.75rem;
    border-radius: 4px;
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-size: 0.85rem;
}
.isis-snapshot-browser__diff-banner.has-diff {
    background: color-mix(in srgb, var(--isis-warning) 12%, var(--isis-surface));
    border: 1px solid var(--isis-warning);
    box-sizing: border-box;
}
.isis-snapshot-browser__diff-banner.no-diff {
    background: color-mix(in srgb, var(--isis-success) 8%, var(--isis-surface));
    border: 1px solid var(--isis-success);
    box-sizing: border-box;
}

.isis-snapshot-browser__table-wrap {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    border: 1px solid var(--isis-border);
    border-radius: 4px;
    margin-bottom: 0.75rem;
}
.isis-snapshot-browser__table thead th {
    position: sticky;
    top: 0;
    background: var(--isis-surface-alt);
    z-index: 1;
}

/* ─── Diff row styling ─────────────────────────────────────────────────── */
.isis-snapshot-diff-row__marker {
    text-align: center;
    font-weight: 700;
    font-family: ui-monospace, "SF Mono", Menlo, monospace;
    cursor: help;
}
.isis-snapshot-diff-row--identical {
    opacity: 0.55;
}
.isis-snapshot-diff-row--identical .isis-snapshot-diff-row__marker {
    color: var(--isis-text-muted);
}
.isis-snapshot-diff-row--modified {
    background: color-mix(in srgb, var(--isis-warning) 7%, var(--isis-surface));
}
.isis-snapshot-diff-row--modified .isis-snapshot-diff-row__marker {
    color: var(--isis-warning);
}
.isis-snapshot-diff-row--added {
    background: color-mix(in srgb, var(--isis-success) 8%, var(--isis-surface));
}
.isis-snapshot-diff-row--added .isis-snapshot-diff-row__marker {
    color: var(--isis-success);
}
.isis-snapshot-diff-row--removed {
    background: color-mix(in srgb, var(--isis-danger) 6%, var(--isis-surface));
}
.isis-snapshot-diff-row--removed .isis-snapshot-diff-row__marker {
    color: var(--isis-danger);
}
.isis-snapshot-diff-row--removed td {
    text-decoration: line-through;
    text-decoration-color: color-mix(in srgb, var(--isis-danger) 70%, transparent);
}

.isis-diff-cell--old {
    color: var(--isis-text-muted);
    text-decoration: line-through;
    text-decoration-thickness: 1px;
    font-size: 0.85em;
}
.isis-diff-cell--new {
    color: var(--isis-text);
    font-weight: 600;
}
.isis-diff-cell-arrow {
    color: var(--isis-text-muted);
    margin: 0 0.15rem;
}

/* ─── Récap totaux ─────────────────────────────────────────────────────── */
.isis-snapshot-browser__recap {
    padding: 0.6rem 0.75rem;
    background: var(--isis-surface-alt);
    border-radius: 4px;
    margin-bottom: 0.75rem;
}
.isis-snapshot-browser__recap h4 {
    margin: 0 0 0.4rem;
    font-size: 0.78rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--isis-text-muted);
}
.isis-snapshot-browser__recap table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.85rem;
}
.isis-snapshot-browser__recap th {
    text-align: left;
    font-weight: 500;
    color: var(--isis-text-muted);
    padding: 0.25rem 0.4rem;
}
.isis-snapshot-browser__recap thead th {
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.03em;
}
.isis-snapshot-browser__recap td {
    padding: 0.25rem 0.4rem;
    font-variant-numeric: tabular-nums;
    text-align: right;
}
.isis-snapshot-browser__recap thead th:not(:first-child) {
    text-align: right;
}
.isis-snapshot-browser__recap-margin {
    font-weight: 700;
    border-top: 1px solid var(--isis-border);
}
.isis-delta-positive { color: var(--isis-success); }
.isis-delta-negative { color: var(--isis-danger); }

/* ─── Actions ──────────────────────────────────────────────────────────── */
.isis-snapshot-browser__actions {
    display: flex;
    justify-content: flex-end;
    gap: 0.5rem;
    padding-top: 0.5rem;
    border-top: 1px solid var(--isis-border);
}
.isis-version-viewer__title {
    font-weight: 600;
    font-size: 0.9rem;
    color: var(--isis-text);
}
.isis-version-viewer__sub {
    font-size: 0.76rem;
    color: var(--isis-text-muted);
    margin-top: 0.15rem;
}
.isis-version-viewer__reason {
    font-size: 0.78rem;
    color: var(--isis-text-soft);
    font-style: italic;
    margin-top: 0.35rem;
}
.isis-version-viewer__section-title {
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--isis-text-soft);
    margin-bottom: 0.6rem;
}
.isis-version-viewer__fields {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 0.6rem 1.25rem;
    margin: 0;
}
.isis-version-viewer__fields > div { min-width: 0; }
.isis-version-viewer__fields dt {
    font-size: 0.68rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--isis-text-muted);
    margin-bottom: 0.1rem;
}
.isis-version-viewer__fields dd {
    margin: 0;
    font-size: 0.82rem;
    color: var(--isis-text);
}
.isis-version-viewer__notes {
    margin-top: 0.75rem;
}
.isis-version-viewer__notes-label {
    font-size: 0.68rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--isis-text-muted);
}
.isis-version-viewer__notes p {
    margin: 0.2rem 0 0;
    font-size: 0.82rem;
    color: var(--isis-text);
    white-space: pre-wrap;
}
.isis-version-viewer__totals {
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
    align-self: flex-end;
    min-width: 260px;
}
.isis-version-viewer__total-row {
    display: flex;
    justify-content: space-between;
    font-size: 0.82rem;
    color: var(--isis-text);
    font-variant-numeric: tabular-nums;
}
.isis-version-viewer__total-row--ttc {
    font-weight: 700;
    padding-top: 0.3rem;
    border-top: 1px solid var(--isis-border);
}
@media (max-width: 720px) {
    .isis-version-viewer__fields { grid-template-columns: 1fr 1fr; }
}

/* Barre de comparaison + cases à cocher de sélection (onglet Versions) */
.isis-version-comparebar {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    margin-bottom: 0.75rem;
}
.isis-version-comparebar__hint {
    font-size: 0.76rem;
    color: var(--isis-text-muted);
    font-variant-numeric: tabular-nums;
}
.isis-version-row__select {
    flex-shrink: 0;
    display: flex;
    align-items: center;
    padding-top: 0.5rem;
}
.isis-version-row__select input { cursor: pointer; }
.isis-version-row__select input:disabled { cursor: not-allowed; opacity: 0.55; }
.isis-version-row__select input:focus-visible {
    outline: 2px solid var(--isis-accent);
    outline-offset: 2px;
}

/* Dialog de comparaison de deux versions */
.isis-version-compare {
    display: flex;
    flex-direction: column;
    gap: 1.25rem;
}
.isis-version-compare__section-title {
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--isis-text-soft);
    margin-bottom: 0.6rem;
}
.isis-version-compare__head {
    display: flex;
    align-items: center;
    gap: 0.85rem;
    padding-bottom: 0.85rem;
    border-bottom: 1px solid var(--isis-border);
}
.isis-version-compare__side {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}
.isis-version-compare__side-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 38px;
    height: 30px;
    padding: 0 0.5rem;
    font-weight: 700;
    font-size: 0.8rem;
    border-radius: 6px;
    font-variant-numeric: tabular-nums;
}
.isis-version-compare__side-badge--old {
    color: var(--isis-text);
    background: var(--isis-surface-alt);
}
.isis-version-compare__side-badge--new {
    color: var(--isis-surface);
    background: var(--isis-current-mod, var(--isis-mod-gescom));
}
.isis-version-compare__side-meta {
    font-size: 0.76rem;
    color: var(--isis-text-muted);
}
.isis-version-compare__nochange {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-size: 0.82rem;
    color: var(--isis-text);
    background: var(--isis-surface-alt);
    border: 1px solid var(--isis-border);
    border-radius: 6px;
    padding: 0.6rem 0.85rem;
}
.isis-version-compare__nochange .rzi { color: var(--isis-text-muted); }
.isis-version-compare__empty {
    font-size: 0.8rem;
    color: var(--isis-text-muted);
    padding: 0.5rem 0;
}
.isis-version-compare__table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.8rem;
}
.isis-version-compare__table th {
    text-align: left;
    font-size: 0.68rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--isis-text-muted);
    font-weight: 600;
    padding: 0.3rem 0.5rem;
    border-bottom: 1px solid var(--isis-border);
}
.isis-version-compare__table td {
    padding: 0.4rem 0.5rem;
    border-bottom: 1px solid var(--isis-border);
    color: var(--isis-text);
    vertical-align: top;
}
.isis-version-compare__field { font-weight: 600; }
.isis-version-compare__old {
    color: var(--isis-text-muted);
    text-decoration: line-through;
}
.isis-version-compare__new { color: var(--isis-text); font-weight: 600; }
.isis-version-compare__legend {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
    margin-bottom: 0.5rem;
}
.isis-version-compare__tag {
    font-size: 0.7rem;
    padding: 0.12rem 0.5rem;
    border-radius: var(--isis-radius-pill);
    font-variant-numeric: tabular-nums;
    color: var(--isis-text);
    border: 1px solid var(--isis-border);
}
/* Texte sombre + fond teinté + bord coloré : l'identité couleur reste lisible
   (le libellé textuel « ajoutée(s) »… porte le sens, la couleur le renforce). */
.isis-version-compare__tag.is-added     { background: var(--isis-success-soft); border-color: var(--isis-success); }
.isis-version-compare__tag.is-removed   { background: var(--isis-danger-soft);  border-color: var(--isis-danger); }
.isis-version-compare__tag.is-modified  { background: var(--isis-warning-soft); border-color: var(--isis-warning); }
.isis-version-compare__tag.is-unchanged { background: var(--isis-surface-alt); }

/* Lignes du tableau de diff — marqueur + bord coloré par nature du changement.
   Le marqueur reste en texte sombre (lisible) ; la nature est portée par le fond
   teinté, l'accent gauche, le glyphe +/−/~ et son aria-label. */
.isis-version-compare__items td { vertical-align: top; }
.isis-version-compare__marker {
    text-align: center;
    font-weight: 700;
    font-size: 0.95rem;
    font-variant-numeric: tabular-nums;
    color: var(--isis-text);
}
.isis-version-compare__row--added {
    background: var(--isis-success-soft);
    box-shadow: inset 3px 0 0 0 var(--isis-success);
}
.isis-version-compare__row--removed {
    background: var(--isis-danger-soft);
    box-shadow: inset 3px 0 0 0 var(--isis-danger);
}
.isis-version-compare__row--modified {
    background: var(--isis-warning-soft);
    box-shadow: inset 3px 0 0 0 var(--isis-warning);
}
.isis-version-compare__changes {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    margin-top: 0.3rem;
}
.isis-version-compare__change {
    font-size: 0.72rem;
    color: var(--isis-text);
    font-variant-numeric: tabular-nums;
}
.isis-version-compare__totals-ttc td {
    font-weight: 700;
    border-top: 2px solid var(--isis-border);
}
/* Delta neutre : un devis qui monte n'est pas « rouge/danger » — le signe +/−
   porte la direction, pas la couleur (évite une fausse alerte commerciale). */
.isis-version-compare__delta--up   { color: var(--isis-text); font-weight: 600; }
.isis-version-compare__delta--down { color: var(--isis-text); font-weight: 600; }
.isis-version-compare__delta--flat { color: var(--isis-text-muted); }

/* ============================================================================
   Coût de revient — pages /gescompta/cout/* (référentiel)
   ============================================================================ */
.isis-grid--units .isis-grid__head,
.isis-grid--units .isis-grid__row {
    grid-template-columns: 32px 110px minmax(220px, 1.6fr) 100px 80px 110px;
    min-width: 820px;
}
.isis-grid--cost-categories .isis-grid__head,
.isis-grid--cost-categories .isis-grid__row {
    grid-template-columns: 32px 140px minmax(280px, 2fr) 80px 140px;
    min-width: 880px;
}
.isis-grid--resources .isis-grid__head,
.isis-grid--resources .isis-grid__row {
    grid-template-columns: 32px 120px minmax(220px, 1.4fr) minmax(180px, 1.1fr) 130px 140px 100px 110px;
    min-width: 1140px;
}

/* ============================================================================
   .isis-side--switchable — sidepanel droit avec switcher (Aperçu ⇄ Filtres)
   Réinitialise le padding du conteneur .isis-master-detail__detail pour
   permettre au header switcher de coller au bord supérieur, et fait du
   conteneur un flex column dont le body scrolle.
   ============================================================================ */
.isis-master-detail__detail.isis-side--switchable {
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    min-height: 0;
    overflow: hidden;
}
.isis-side-switcher__body {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    padding: 0.85rem;
}

/* ============================================================================
   .isis-collab — panneau de collaboration devis (commentaires + réponses client)
   Vit dans les sous-onglets Dossier › Commentaires / Réponses client de DevisDetail.
   ============================================================================ */
.isis-collab {
    display: flex;
    flex-direction: column;
    gap: 0.7rem;
    height: 100%;
    min-height: 0;
}
.isis-collab__loading,
.isis-collab__empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    padding: 1.5rem 1rem;
    color: var(--isis-text-soft);
    font-size: 0.82rem;
    text-align: center;
}
.isis-collab__empty .rzi { font-size: 26px; opacity: 0.3; }

.isis-collab__filter {
    display: flex;
    flex-wrap: wrap;
    gap: 0.3rem;
    flex-shrink: 0;
}
.isis-collab__chip {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    background: var(--isis-surface-alt);
    border: 1px solid var(--isis-border);
    color: var(--isis-text);
    padding: 0.2rem 0.55rem;
    border-radius: var(--isis-radius-pill);
    font-size: 0.73rem;
    cursor: pointer;
    transition: background 0.12s, color 0.12s, border-color 0.12s;
}
.isis-collab__chip:hover { background: var(--isis-surface-alt); }
.isis-collab__chip.is-active {
    background: var(--isis-mod-gescom-soft);
    color: var(--isis-mod-gescom);
    border-color: var(--isis-mod-gescom);
    font-weight: 600;
}
.isis-collab__chip-count {
    font-variant-numeric: tabular-nums;
    opacity: 0.7;
    font-size: 0.68rem;
}

.isis-collab__thread {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    gap: 0.55rem;
    padding-right: 2px;
}
.isis-collab__msg {
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: 6px;
    padding: 0.5rem 0.6rem;
}
.isis-collab__msg.is-focused {
    border-color: var(--isis-mod-gescom);
    box-shadow: inset 3px 0 0 0 var(--isis-mod-gescom);
}
.isis-collab__msg.is-client {
    background: #fffdf5;
    border-color: #f0e3b8;
}
.isis-collab__msg-head {
    display: flex;
    align-items: center;
    gap: 0.4rem;
}
.isis-collab__avatar {
    width: 22px;
    height: 22px;
    border-radius: 50%;
    background: var(--isis-mod-gescom-soft);
    color: var(--isis-mod-gescom);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 0.62rem;
    font-weight: 700;
    flex-shrink: 0;
}
.isis-collab__avatar.is-client {
    background: #f6ecc8;
    color: #8a6d11;
}
.isis-collab__author {
    font-size: 0.78rem;
    font-weight: 600;
    color: var(--isis-text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.isis-collab__date {
    font-size: 0.68rem;
    color: var(--isis-text-muted);   /* WCAG AA : text-soft #9ca3af échouait le contraste */
    margin-left: auto;
    flex-shrink: 0;
}
.isis-collab__del {
    background: transparent;
    border: none;
    color: var(--isis-text-soft);
    cursor: pointer;
    padding: 1px 2px;
    border-radius: 3px;
    display: inline-flex;
    flex-shrink: 0;
}
.isis-collab__del:hover { color: var(--rz-danger, #dc2626); background: var(--rz-danger-lighter, #fef2f2); }
.isis-collab__context {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    margin-top: 0.3rem;
    font-size: 0.68rem;
    color: var(--isis-mod-gescom);
    background: var(--isis-mod-gescom-soft);
    padding: 0.1rem 0.4rem;
    border-radius: 4px;
}
.isis-collab__body {
    margin-top: 0.35rem;
    font-size: 0.82rem;
    line-height: 1.45;
    color: var(--isis-text);
    white-space: pre-wrap;
    word-break: break-word;
}
.isis-collab__mentions {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    margin-top: 0.3rem;
    font-size: 0.68rem;
    color: var(--isis-text-soft);
}

.isis-collab__client-banner {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    background: #fffdf5;
    border: 1px solid #f0e3b8;
    color: #8a6d11;
    border-radius: 6px;
    padding: 0.4rem 0.55rem;
    font-size: 0.74rem;
    flex-shrink: 0;
}

.isis-collab__composer {
    flex-shrink: 0;
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
    border-top: 1px solid var(--isis-border);
    padding-top: 0.55rem;
}
.isis-collab__composer-target {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    font-size: 0.7rem;
    color: var(--isis-text-soft);
}
.isis-collab__composer-reset {
    background: transparent;
    border: none;
    color: var(--isis-text-soft);
    cursor: pointer;
    padding: 0 2px;
    display: inline-flex;
}
.isis-collab__composer-reset:hover { color: var(--isis-text); }
.isis-collab__textarea {
    width: 100%;
    box-sizing: border-box;
    background: var(--isis-surface-alt);
    border: 1px solid transparent;
    border-bottom: 1px solid var(--isis-border);
    border-radius: 4px 4px 0 0;
    padding: 0.45rem 0.55rem;
    font-size: 0.82rem;
    font-family: inherit;
    color: var(--isis-text);
    resize: vertical;
    transition: border-color 0.12s, background 0.12s;
}
.isis-collab__textarea:focus {
    outline: none;
    background: var(--isis-surface);
    border-bottom-color: var(--isis-mod-gescom);
}
.isis-collab__composer-row {
    display: flex;
    align-items: center;
    gap: 0.4rem;
}
.isis-collab__composer-hint {
    flex: 1;
    font-size: 0.68rem;
    color: var(--isis-text-soft);
    font-style: italic;
}
.isis-collab__composer-block {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.4rem 0.6rem;
    margin-bottom: 0.4rem;
    border: 1px solid var(--isis-border);
    background: var(--isis-surface-alt);
    color: var(--isis-text);
    font-size: 0.72rem;
    border-radius: 4px;
}
.isis-collab__composer-block .rzi { color: var(--isis-text-muted); }
.isis-collab__send {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    background: var(--isis-mod-gescom);
    border: 1px solid var(--isis-mod-gescom);
    color: #fff;
    padding: 0.4rem 0.7rem;
    border-radius: 4px;
    font-size: 0.78rem;
    font-weight: 500;
    cursor: pointer;
    flex-shrink: 0;
    transition: filter 0.12s;
}
.isis-collab__send:hover:not(:disabled) { filter: brightness(0.92); }
.isis-collab__send:disabled { opacity: 0.5; cursor: not-allowed; }

/* ── Bulle de commentaire (lignes devis + allocations de coût) ───────────── */
.isis-comment-bubble {
    display: inline-flex;
    align-items: center;
    gap: 0.15rem;
    background: transparent;
    border: none;
    color: var(--isis-text-soft);
    cursor: pointer;
    padding: 2px 4px;
    border-radius: 4px;
    transition: background 0.12s, color 0.12s;
}
.isis-comment-bubble:hover {
    background: var(--isis-mod-gescom-soft);
    color: var(--isis-mod-gescom);
}
.isis-comment-bubble.has-comments { color: var(--isis-mod-gescom); }
.isis-comment-bubble__count {
    font-size: 0.66rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    line-height: 1;
}

/* ============================================================================
   .isis-notif — cloche de notifications du header + panneau déroulant
   ============================================================================ */
.isis-notif { position: relative; display: inline-flex; }
.isis-notif__bell {
    position: relative;
    background: transparent;
    border: none;
    color: var(--isis-text-soft);
    cursor: pointer;
    width: 36px;
    height: 36px;
    border-radius: 8px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: background 0.12s, color 0.12s;
}
.isis-notif__bell:hover { background: var(--isis-surface-alt); color: var(--isis-text); }
.isis-notif__badge {
    position: absolute;
    top: 3px;
    right: 3px;
    min-width: 15px;
    height: 15px;
    padding: 0 3px;
    border-radius: var(--isis-radius-pill);
    background: var(--rz-danger, #dc2626);
    color: #fff;
    font-size: 0.6rem;
    font-weight: 700;
    line-height: 15px;
    text-align: center;
}
.isis-notif__backdrop {
    position: fixed;
    inset: 0;
    z-index: 1000;
}
.isis-notif__panel {
    position: absolute;
    top: calc(100% + 6px);
    right: 0;
    width: 340px;
    max-height: 460px;
    background: var(--isis-surface);
    /* Flat Design absolu (DESIGN.md §1) : pas d'ombre — bordure + ring 1px
       suffisent à détacher le panneau flottant du fond. */
    border: 1px solid var(--isis-border);
    outline: 1px solid rgba(15, 23, 42, 0.04);
    border-radius: 8px;
    z-index: 1001;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}
.isis-notif__panel-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0.6rem 0.75rem;
    border-bottom: 1px solid var(--isis-border);
    background: #fafbfc;
    flex-shrink: 0;
}
.isis-notif__panel-title { font-size: 0.82rem; font-weight: 600; color: var(--isis-text); }
.isis-notif__mark-all {
    background: transparent;
    border: none;
    color: var(--isis-accent);   /* composant de shell transverse : accent neutre, pas teinte module */
    font-size: 0.72rem;
    cursor: pointer;
    padding: 2px 4px;
    border-radius: 4px;
}
.isis-notif__mark-all:hover { background: var(--isis-surface-alt); }
.isis-notif__list {
    overflow-y: auto;
    flex: 1 1 auto;
    min-height: 0;
}
.isis-notif__state {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.4rem;
    padding: 1.5rem 1rem;
    color: var(--isis-text-soft);
    font-size: 0.8rem;
}
.isis-notif__item {
    width: 100%;
    display: flex;
    gap: 0.5rem;
    align-items: flex-start;
    background: transparent;
    border: none;
    border-bottom: 1px solid var(--isis-border);
    padding: 0.55rem 0.7rem;
    cursor: pointer;
    text-align: left;
    transition: background 0.12s;
}
.isis-notif__item:last-child { border-bottom: none; }
.isis-notif__item:hover { background: var(--isis-surface-alt); }
.isis-notif__item-dot {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: transparent;
    margin-top: 5px;
    flex-shrink: 0;
}
.isis-notif__item.is-unread .isis-notif__item-dot { background: var(--isis-accent); }
.isis-notif__item.is-unread .isis-notif__item-title { font-weight: 600; }
.isis-notif__item-body {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    min-width: 0;
}
.isis-notif__item-title {
    font-size: 0.78rem;
    color: var(--isis-text);
    line-height: 1.3;
}
.isis-notif__item-text {
    font-size: 0.72rem;
    color: var(--isis-text-muted);   /* WCAG AA : text-soft #9ca3af échouait le contraste */
    line-height: 1.35;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.isis-notif__item-date {
    font-size: 0.66rem;
    color: var(--isis-text-soft);
    opacity: 0.8;
}
.isis-notif__panel-foot {
    border-top: 1px solid var(--isis-border);
    padding: 8px 14px;
    text-align: center;
    flex-shrink: 0;
}
.isis-notif__see-all {
    font-size: 0.72rem;
    color: var(--isis-accent);
    text-decoration: none;
}
.isis-notif__see-all:hover { text-decoration: underline; }

/* ── Filter panel (multicritère) ─────────────────────────────────────────── */
.isis-filter-panel {
    display: flex;
    flex-direction: column;
    gap: 0.95rem;
}
/* Panneau flottant non-modal, ancré à droite (niveau sidepanel). Ne pousse pas la grille. */
.isis-filter-float {
    position: fixed;
    top: 7.75rem;
    right: 1.25rem;
    width: 360px;
    max-width: calc(100vw - 2.5rem);
    max-height: calc(100vh - 9.5rem);
    display: flex;
    flex-direction: column;
    gap: 0;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: 10px;
    box-shadow: var(--isis-elevation-2);
    z-index: 50;
    overflow: hidden;
    animation: isis-filter-float-in 0.14s ease-out;
}
@keyframes isis-filter-float-in {
    from { opacity: 0; transform: translateY(-6px); }
    to   { opacity: 1; transform: translateY(0); }
}
.isis-filter-float__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    padding: 0.65rem 0.85rem;
    border-bottom: 1px solid var(--isis-border);
    flex: 0 0 auto;
}
.isis-filter-float__title {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    font-size: 0.9rem;
    font-weight: 600;
    color: var(--isis-text);
}
.isis-filter-float__close {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    border: none;
    background: transparent;
    color: var(--isis-text-muted);
    border-radius: 6px;
    cursor: pointer;
    transition: background 0.12s, color 0.12s;
}
.isis-filter-float__close:hover { background: var(--isis-surface-alt); color: var(--isis-text); }
.isis-filter-float__close:focus-visible { outline: 2px solid var(--isis-current-mod, var(--isis-accent)); outline-offset: 1px; }
.isis-filter-float__body {
    display: flex;
    flex-direction: column;
    gap: 0.85rem;
    padding: 0.9rem;
    overflow-y: auto;
}
/* ── Panneau de filtres avancés enrichi (2026-09-02) ──────────────────────────
   Rappel des critères actifs, recherche, groupes repliables, compteur de résultats.
   Tout est ADDITIF : une page qui passe encore du markup libre ne rend aucun de ces
   blocs et garde exactement son aspect.
   ──────────────────────────────────────────────────────────────────────────── */

/* Critères actifs : le compteur du bandeau dit COMBIEN, ces puces disent LESQUELS
   et permettent d'en retirer un seul sans le chercher dans dix groupes. */
.isis-filter-float__active {
    display: flex;
    flex-wrap: wrap;
    gap: 5px;
    padding: 0.6rem 0.85rem;
    border-bottom: 1px solid var(--isis-border-soft);
    flex: 0 0 auto;
}
.isis-filter-float__chip {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    max-width: 100%;
    padding: 2px 2px 2px 8px;
    border: 1px solid var(--isis-current-mod, var(--isis-accent));
    background: var(--isis-current-mod-soft, var(--isis-accent-soft));
    color: var(--isis-current-mod, var(--isis-accent));
    border-radius: var(--isis-radius-pill);
    font-size: var(--isis-fs-sm);
    font-weight: 500;
}
.isis-filter-float__chip > span {
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.isis-filter-float__chip button {
    /* WCAG 2.5.8 : la cible tient 24px, le glyphe garde sa taille. */
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 24px; min-height: 24px;
    border: none; background: none; color: inherit; cursor: pointer;
    font-size: 14px; line-height: 1; padding: 0;
}
.isis-filter-float__chip button:focus-visible {
    outline: 2px solid var(--isis-current-mod, var(--isis-accent));
    outline-offset: 1px;
}

/* Recherche : à dix groupes on ne parcourt plus, on cherche. */
.isis-filter-float__search {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.5rem 0.85rem;
    border-bottom: 1px solid var(--isis-border-soft);
    flex: 0 0 auto;
}
.isis-filter-float__search input {
    flex: 1;
    min-width: 0;
    border: 1px solid var(--isis-border);
    border-radius: 6px;
    background: var(--isis-surface);
    color: var(--isis-text);
    font-family: inherit;
    font-size: var(--isis-fs-sm);
    padding: 4px 8px;
    min-height: 28px;
}
.isis-filter-float__search input:focus-visible {
    outline: 2px solid var(--isis-current-mod, var(--isis-accent));
    outline-offset: 1px;
}
.isis-filter-float__searchx {
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 24px; min-height: 24px;
    border: none; background: none; color: var(--isis-text-muted);
    cursor: pointer; font-size: 15px; line-height: 1; padding: 0;
}
.isis-filter-float__searchx:hover { color: var(--isis-text); }
.isis-filter-float__searchx:focus-visible {
    outline: 2px solid var(--isis-current-mod, var(--isis-accent));
    outline-offset: 1px;
}

/* Groupe repliable. L'en-tête EST le bouton : ajouter un chevron cliquable à côté
   d'un titre inerte doublerait la cible pour un seul geste. */
.isis-filter-float__grp { border-bottom: 1px solid var(--isis-border-soft); }
.isis-filter-float__grp:last-of-type { border-bottom: 0; }
.isis-filter-float__grph {
    display: flex;
    align-items: center;
    gap: 0.35rem;
    width: 100%;
    min-height: 32px;
    padding: 6px 2px;
    border: 0;
    background: none;
    color: var(--isis-text);
    font: inherit;
    text-align: left;
    cursor: pointer;
}
.isis-filter-float__grph:hover { color: var(--isis-current-mod, var(--isis-accent)); }
.isis-filter-float__grph:focus-visible {
    outline: 2px solid var(--isis-current-mod, var(--isis-accent));
    outline-offset: -2px;
}
.isis-filter-float__grpn {
    flex: 1;
    min-width: 0;
    font-size: var(--isis-fs-sm);
    font-weight: 600;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Compteur de critères du groupe : c'est le seul repère quand le groupe est replié. */
.isis-filter-float__grpc {
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 18px; height: 18px; padding: 0 5px;
    border-radius: 9px;
    background: var(--isis-current-mod, var(--isis-accent));
    color: var(--isis-bg);
    font-family: var(--isis-font-mono);
    font-variant-numeric: tabular-nums;
    font-size: 0.65rem;
    font-weight: 700;
    line-height: 1;
}
.isis-filter-float__grpb {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    padding: 0 0 0.7rem 1.35rem;
}
/* Dans un panneau de 360px, un champ doit prendre la largeur : sans ça, il dépend du
   `Style="width:100%"` que chaque page pense — ou oublie — à poser. Le composant le garantit. */
.isis-filter-float__grpb .rz-textbox,
.isis-filter-float__grpb .rz-dropdown,
.isis-filter-float__grpb .rz-spinner,
.isis-filter-float__grpb .rz-numeric,
.isis-filter-float__grpb .rz-datepicker { width: 100%; box-sizing: border-box; }

.isis-filter-float__grpx {
    align-self: flex-start;
    min-height: 24px;
    border: 0;
    background: none;
    color: var(--isis-text-muted);
    font-family: inherit;
    font-size: var(--isis-fs-sm);
    text-decoration: underline;
    cursor: pointer;
    padding: 0;
}
.isis-filter-float__grpx:hover { color: var(--isis-danger); }
.isis-filter-float__grpx:focus-visible {
    outline: 2px solid var(--isis-current-mod, var(--isis-accent));
    outline-offset: 1px;
}

/* Contenu d'un groupe : liste d'options cochables, et plage à deux bornes. Ces deux
   idiomes couvrent les huit groupes du pilote ; un groupe garde le droit de rendre
   n'importe quel markup, ce sont des raccourcis, pas un contrat. */
.isis-filter-panel__opts { display: flex; flex-direction: column; gap: 1px; }
.isis-filter-panel__opt {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    width: 100%;
    min-height: 26px;
    padding: 3px 4px;
    border: 0;
    border-radius: 4px;
    background: none;
    color: var(--isis-text);
    font: inherit;
    font-size: var(--isis-fs-sm);
    text-align: left;
    cursor: pointer;
}
.isis-filter-panel__opt:hover { background: var(--isis-surface-alt); }
.isis-filter-panel__opt:focus-visible {
    outline: 2px solid var(--isis-current-mod, var(--isis-accent));
    outline-offset: -2px;
}
.isis-filter-panel__opt > span {
    flex: 1; min-width: 0;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.isis-filter-panel__opt > b {
    font-family: var(--isis-font-mono);
    font-variant-numeric: tabular-nums;
    font-size: var(--isis-fs-sm);
    font-weight: 500;
    color: var(--isis-text-soft);
}
.isis-filter-panel__range { display: flex; gap: 0.5rem; }
.isis-filter-panel__range label {
    flex: 1; min-width: 0;
    display: flex; flex-direction: column; gap: 2px;
    font-size: var(--isis-fs-sm);
    color: var(--isis-text-muted);
}
.isis-filter-panel__range input {
    width: 100%;
    box-sizing: border-box;
    min-height: 28px;
    padding: 4px 8px;
    border: 1px solid var(--isis-border);
    border-radius: 6px;
    background: var(--isis-surface);
    color: var(--isis-text);
    font-family: inherit;
    font-size: var(--isis-fs-sm);
}
.isis-filter-panel__range input:focus-visible {
    outline: 2px solid var(--isis-current-mod, var(--isis-accent));
    outline-offset: 1px;
}

/* Recherche sans résultat : on le dit, on ne rend pas un panneau vide. */
.isis-filter-float__vide {
    margin: 0;
    padding: 0.6rem 0;
    font-size: var(--isis-fs-sm);
    color: var(--isis-text-muted);
}

/* Nombre de résultats AVANT d'appliquer — sinon on filtre à l'aveugle.
   `flex-basis: 100%` et non `width: 100%` : la barre d'actions est un conteneur flex, où
   une largeur ne force aucun retour à la ligne. Sans ça, le compte se coinçait sur deux
   lignes à gauche des boutons (constaté au navigateur sur le panneau des commandes). */
.isis-filter-float__body .isis-filter-panel__actions { flex-wrap: wrap; }
.isis-filter-float__count {
    margin: 0 0 0.35rem;
    flex: 1 0 100%;
    font-size: var(--isis-fs-sm);
    color: var(--isis-text-muted);
}
.isis-filter-float__count b {
    font-family: var(--isis-font-mono);
    font-variant-numeric: tabular-nums;
    color: var(--isis-text);
}

/* Actions collées en bas du panneau flottant (offset sticky par défaut recalé). */
.isis-filter-float__body .isis-filter-panel__actions {
    bottom: 0;
    margin-top: 0.2rem;
}
.isis-filter-panel__grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: 0.85rem 1rem;
}
/* Bouton « Filtres avancés » dans la filter-bar + badge compteur de critères actifs. */
.isis-filter-advanced-btn { position: relative; }
.isis-filter-advanced-btn__badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 16px;
    height: 16px;
    padding: 0 4px;
    margin-left: 0.15rem;
    border-radius: var(--isis-radius-pill);
    background: var(--isis-current-mod, var(--isis-accent));
    color: #fff;
    font-size: 0.64rem;
    font-weight: 700;
    line-height: 1;
}
.isis-filter-panel__group {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
}
.isis-filter-panel__label {
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.045em;
    color: var(--isis-text-soft);
    font-weight: 600;
}
.isis-filter-panel__row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0.4rem;
}
.isis-filter-panel input[type="text"],
.isis-filter-panel input[type="number"],
.isis-filter-panel input[type="date"] {
    background: var(--isis-surface-alt);
    border: 1px solid transparent;
    border-bottom: 1px solid var(--isis-border);
    padding: 0.4rem 0.55rem;
    font-size: 0.82rem;
    color: var(--isis-text);
    font-family: inherit;
    border-radius: 4px 4px 0 0;
    width: 100%;
    transition: border-color 0.12s, background 0.12s;
    box-sizing: border-box;
}
.isis-filter-panel input::placeholder { color: var(--isis-text-soft); }
.isis-filter-panel input:focus {
    outline: none;
    background: var(--isis-surface);
    border-bottom-color: var(--isis-current-mod, var(--isis-accent));
}
.isis-filter-panel__chips {
    display: flex;
    flex-wrap: wrap;
    gap: 0.3rem;
}
.isis-filter-panel__chip {
    background: var(--isis-surface-alt);
    border: 1px solid var(--isis-border);
    color: var(--isis-text);
    padding: 0.25rem 0.65rem;
    border-radius: var(--isis-radius-pill);
    font-size: 0.75rem;
    cursor: pointer;
    transition: background 0.12s, color 0.12s, border-color 0.12s;
}
.isis-filter-panel__chip:hover { background: var(--isis-surface-alt); }
.isis-filter-panel__chip.is-active {
    background: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 14%, var(--isis-surface));
    color: var(--isis-current-mod, var(--isis-accent));
    border-color: var(--isis-current-mod, var(--isis-accent));
    font-weight: 600;
}
.isis-filter-panel__chip:focus-visible {
    outline: 2px solid var(--isis-current-mod, var(--isis-accent));
    outline-offset: 1px;
}
.isis-filter-panel__checklist {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    max-height: 200px;
    overflow-y: auto;
    background: var(--isis-surface-alt);
    border: 1px solid var(--isis-border);
    border-radius: 4px;
    padding: 0.35rem 0.5rem;
}
.isis-filter-panel__check {
    display: flex;
    align-items: center;
    gap: 0.45rem;
    font-size: 0.78rem;
    color: var(--isis-text);
    cursor: pointer;
    padding: 0.15rem 0;
}
.isis-filter-panel__check input { accent-color: var(--isis-current-mod, var(--isis-accent)); }
.isis-filter-panel__check span {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.isis-filter-panel__check-more {
    font-size: 0.7rem;
    color: var(--isis-text-soft);
    font-style: italic;
    padding: 0.2rem 0;
}
.isis-filter-panel__actions {
    display: flex;
    gap: 0.4rem;
    justify-content: space-between;
    position: sticky;
    bottom: -0.85rem;
    background: var(--isis-surface);
    padding: 0.6rem 0 0;
    margin-top: 0.4rem;
    border-top: 1px solid var(--isis-border);
}
.isis-filter-panel__btn {
    flex: 1 1 0;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    color: var(--isis-text);
    padding: 0.45rem 0.7rem;
    border-radius: 4px;
    font-size: 0.8rem;
    font-weight: 500;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.35rem;
    transition: background 0.12s, border-color 0.12s, color 0.12s;
}
.isis-filter-panel__btn:hover {
    background: var(--isis-surface-alt);
}
.isis-filter-panel__btn--primary {
    background: var(--isis-current-mod, var(--isis-accent));
    border-color: var(--isis-current-mod, var(--isis-accent));
    color: #fff;
}
.isis-filter-panel__btn--primary:hover {
    background: var(--isis-current-mod, var(--isis-accent));
    filter: brightness(0.92);
}
.isis-filter-panel__btn:focus-visible {
    outline: 2px solid var(--isis-current-mod, var(--isis-accent));
    outline-offset: 1px;
}

/* ============================================================================
   Lignes d'un devis, onglet Lignes de la fiche (lecture) — trois clés de grille
   isis-grid--devis-items          Désignation | Qté | Unité | PU HT | Remise | Total HT | Marge | Actions
   isis-grid--devis-items-sanscout la même sans Marge (pas de droit coût)
   isis-grid--devis-items-bpu      Désignation | PU HT / unité | Actions
   Ni tri ni pagination : le bordereau a un ordre métier (item_position) et porte
   des lignes structurantes SECTION / COMMENT. Mesuré le 2026-09-07 sur le tenant
   demo : 7 912 devis, 1,0 ligne en moyenne, 6 au maximum.
   Trois paliers lus sur la largeur du PANNEAU (#devis-panel-items), pas de l'écran :
   large ≥ 1080 px, compact 560-1079 px, cartes < 560 px. Aucun défilement horizontal.
   Le seuil large tient la Désignation à ~340 px au moins : les 7 pistes chiffrées pèsent
   720 px (mesuré le 2026-09-22 : 151 px de Désignation à 900 px de panneau).
   ============================================================================ */
/* Gabarits du palier large, et seulement eux à la racine de la feuille : le configurateur
   de colonnes lit le gabarit ici, jamais dans un @container. Pistes chiffrées fixes, taillées
   sur « 999 999 999 F CFA » (Total HT) et « 99 999 999 F CFA » (PU) : un montant n'est
   jamais tronqué. `subgrid` et `auto` sont exclus (condition 3 du configurateur). */
.isis-grid--devis-items .isis-grid__head,
.isis-grid--devis-items .isis-grid__row {
    grid-template-columns: minmax(0, 1fr) 72px 64px 136px 64px 144px 104px 136px;
    min-width: 0px;
}

.isis-grid--devis-items-sanscout .isis-grid__head,
.isis-grid--devis-items-sanscout .isis-grid__row {
    grid-template-columns: minmax(0, 1fr) 72px 64px 136px 64px 144px 136px;
    min-width: 0px;
}

/* BPU : un cadre tarifaire, pas un chiffrage. Pas de palier compact, ses 3 pistes
   tiennent dans 560 px. Modificateur DISTINCT et non redéfinition : deux déclarations du
   même modificateur, la seconde gagne en silence. */
.isis-grid--devis-items-bpu .isis-grid__head,
.isis-grid--devis-items-bpu .isis-grid__row {
    grid-template-columns: minmax(0, 1fr) 176px 136px;
    min-width: 0px;
}

/* Ligne pleine largeur : COMMENT et dépliants. En CSS grid, `grid-column: 1 / -1`
   remplace le colspan du tableau — et ne change ni le nombre de pistes du gabarit, ni le
   nombre de cellules d'en-tête, donc ne met pas en défaut la condition 4 du configurateur. */
.isis-grid__row--span > div {
    grid-column: 1 / -1;
    white-space: normal;
    overflow: visible;
}

.isis-grid--devis-items .isis-grid__col-desc,
.isis-grid--devis-items-sanscout .isis-grid__col-desc,
.isis-grid--devis-items-bpu .isis-grid__col-desc {
    min-width: 0;
    display: block;
    padding: 0.3rem 0.35rem;
}

/* Le panneau est le conteneur des paliers : le bouton du configurateur est ancré sur le
   parent de la grille, une requête posée sur la grille ne le verrait pas. */
#devis-panel-items {
    container-type: inline-size;
    container-name: devis-lignes;
}

/* Les lignes ne s'ouvrent pas au clic : pas de main. Le survol teinté reste (repère de
   lecture), sauf sur un dépliant, qui n'est pas une ligne du bordereau. */
#devis-panel-items .isis-grid__row {
    cursor: default;
}
#devis-panel-items .isis-devis-ligne__depliant,
#devis-panel-items .isis-devis-ligne__depliant:hover {
    background: var(--isis-surface-alt);
}
#devis-panel-items .isis-grid__row.isis-devis-ligne__depliant > div {
    padding: 0.5rem 0.85rem 0.6rem 1.5rem;
}

/* Cellules chiffrées : alignées à droite, chiffres tabulaires, jamais coupées. Préfixe
   d'identifiant : `.isis-grid__row > div` et `.isis-grid__head > div` posent display,
   overflow et white-space à (0,1,1). */
#devis-panel-items .isis-devis-ligne__num {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 0.25rem;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
    text-align: right;
}
#devis-panel-items .isis-devis-ligne__num.is-pu-nul,
.isis-devis-ligne__pu-alerte {
    color: var(--isis-warning-text);
}
.isis-devis-ligne__pu-alerte {
    display: inline-flex;
    align-items: center;
}
.isis-devis-ligne__pu-alerte .rzi {
    font-size: 16px;
}
.isis-devis-ligne__unite {
    color: var(--isis-text-muted);
}
.isis-devis-ligne__ack {
    display: inline-flex;
    align-items: center;
    color: var(--isis-text-muted);
}
.isis-devis-ligne__ack .rzi {
    font-size: 14px;
}

/* Désignation sur trois niveaux : code · type, désignation, étiquettes. */
.isis-devis-ligne__meta {
    display: flex;
    align-items: center;
    gap: 0.3rem;
    min-width: 0;
    overflow: hidden;
    white-space: nowrap;
    font-size: var(--isis-fs-label);
    line-height: 1.35;
    color: var(--isis-text-muted);
}
.isis-devis-ligne__code {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    font-family: var(--isis-font-mono);
}
.isis-devis-ligne__code.is-vide {
    font-family: inherit;
}
.isis-devis-ligne__tags {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem;
    margin-top: 0.25rem;
    min-width: 0;
    white-space: normal;
}
.isis-devis-ligne__tag {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    max-width: 100%;
    min-height: 1.25rem;
    padding: 0 0.4rem;
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-sm);
    background: var(--isis-surface-alt);
    color: var(--isis-text-muted);
    font-size: var(--isis-fs-label);
    line-height: 1.3;
    white-space: nowrap;
}
.isis-devis-ligne__tag > span {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
}
.isis-devis-ligne__tag.is-incluse {
    color: var(--isis-text);
}
/* EF-45 — « à chiffrer ». La teinte est portée par le texte et la bordure sur le fond de
   pastille habituel : --isis-warning-soft en fond devient presque noir en thème sombre
   (2,09:1 mesuré), là où --isis-warning a sa variante sombre (6,30:1). */
.isis-devis-ligne__tag.is-attention {
    border-color: var(--isis-warning);
    color: var(--isis-warning);
}
/* Ligne secondaire (« 100 pcs × 82,14 · −25 % ») : palier compact seulement. display:none
   et non visibility : un lecteur d'écran ne doit pas la lire en double des colonnes. */
.isis-devis-ligne__sec {
    display: none;
}

/* Section : intertitre en gras. Le gras est posé sur la rangée, pas sur les cellules, que le
   palier compact remet à `font-weight: inherit`. Le sous-total NE s'y trouve plus : il ferme le
   bloc, cf. la rangée de clôture ci-dessous. */
#devis-panel-items .isis-devis-ligne--section {
    font-weight: 600;
    color: var(--isis-text);
}
.isis-devis-ligne__section-titre {
    font-weight: 600;
    color: var(--isis-text);
}
/* Ligne de sous-total POSÉE (type SOUS_TOTAL en base) : une ligne du bordereau, que l'utilisateur
   place où il veut. À ne pas confondre avec `--soustotal` ci-dessous, la rangée CALCULÉE de
   clôture de section, qui n'existe pas en base. */
.isis-devis-ligne--sous-total,
.isis-devis-carte--sous-total {
    font-weight: 600;
    background: var(--isis-surface-alt);
}

/* Sous-total de clôture d'une section : rangée CALCULÉE (DevisSectionTotalsResult.ClosingRows),
   posée après la dernière ligne du bloc. Fond atténué et survol neutralisé — comme un dépliant,
   ce n'est pas une ligne du bordereau et rien ne s'y ouvre. Le montant garde la cellule Total HT :
   cette grille ne défile jamais horizontalement, le palier compact met les pistes 2 à 5 à 0 px
   sans les retirer. */
#devis-panel-items .isis-devis-ligne--soustotal,
#devis-panel-items .isis-devis-ligne--soustotal:hover {
    background: var(--isis-surface-alt);
}
#devis-panel-items .isis-devis-ligne--soustotal {
    font-weight: 600;
}
.isis-devis-ligne__soustotal-libelle {
    display: block;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--isis-text-muted);
}
.isis-devis-ligne__soustotal-montant {
    color: var(--isis-text);
}
/* Commentaire : romain atténué, flèche de rattachement quand il suit une ligne d'article. */
.isis-devis-ligne--commentaire,
.isis-devis-carte--commentaire {
    color: var(--isis-text-muted);
}
.isis-devis-ligne__commentaire-texte {
    font-style: normal;
    overflow-wrap: anywhere;
}
.isis-devis-ligne__rattache {
    margin-right: 0.35rem;
    color: var(--isis-text-soft);
    font-family: var(--isis-font-mono);
}

/* Actions : trois boutons de 32 px de haut tiennent dans leur piste. */
#devis-panel-items .isis-devis-ligne__actions {
    gap: 0.25rem;
    align-items: center;
}
#devis-panel-items .isis-devis-ligne__actions .isis-action-btn:not(.isis-action-btn--icon-only) {
    padding: 0 0.4rem;
    gap: 0.25rem;
}

/* Dépliants : historique des ajustements et fil de commentaires. */
.isis-devis-ligne__histo {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    margin: 0;
    padding: 0;
    list-style: none;
    font-size: var(--isis-fs-label);
    color: var(--isis-text-muted);
}
.isis-devis-ligne__histo > li {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.1rem 0.35rem;
}
.isis-devis-ligne__histo .rzi {
    font-size: 14px;
}
.isis-devis-ligne__fil-lien {
    display: flex;
    justify-content: flex-end;
    margin-top: 0.35rem;
}
.isis-devis-ligne__fil-vide {
    margin: 0;
    color: var(--isis-text-muted);
    font-size: var(--isis-fs-sm);
}

/* Palier compact. Mêmes pistes que le gabarit large (8 ou 7), Qté, Unité, PU HT et
   Remise à 0 px. Ce bloc neutralise TOUT ce qu'injecte le configurateur de colonnes —
   gabarit, masquage, ordre, figement, style — : ses règles pèsent au plus (0,5,0), le
   préfixe d'identifiant et les combinateurs enfant les battent. La clé large n'est pas
   réécrite ici : elle reste déclarée une seule fois, à la racine. */
@container devis-lignes (min-width: 560px) and (max-width: 1079px) {
    #devis-panel-items > .isis-grid--devis-items > .isis-grid__head,
    #devis-panel-items > .isis-grid--devis-items > .isis-grid__row {
        grid-template-columns: minmax(0, 1fr) 0px 0px 0px 0px 144px 104px 136px;
        min-width: 0;
    }
    #devis-panel-items > .isis-grid--devis-items-sanscout > .isis-grid__head,
    #devis-panel-items > .isis-grid--devis-items-sanscout > .isis-grid__row {
        grid-template-columns: minmax(0, 1fr) 0px 0px 0px 0px 144px 136px;
        min-width: 0;
    }
    #devis-panel-items > .isis-grid > .isis-grid__head > *,
    #devis-panel-items > .isis-grid > .isis-grid__row > * {
        order: 0;
        visibility: visible;
        position: static;
        left: auto;
        z-index: auto;
        background: transparent;
        box-shadow: none;
        font-weight: inherit;
        font-style: normal;
        text-decoration: none;
    }
    #devis-panel-items > .isis-grid--devis-items > .isis-grid__head > :nth-child(n+2):nth-child(-n+5),
    #devis-panel-items > .isis-grid--devis-items > .isis-grid__row > :nth-child(n+2):nth-child(-n+5),
    #devis-panel-items > .isis-grid--devis-items-sanscout > .isis-grid__head > :nth-child(n+2):nth-child(-n+5),
    #devis-panel-items > .isis-grid--devis-items-sanscout > .isis-grid__row > :nth-child(n+2):nth-child(-n+5) {
        visibility: hidden;
        padding: 0;
    }
    #devis-panel-items > .isis-grid-cfg-btn,
    #devis-panel-items .isis-grid-rsz {
        display: none;
    }
    .isis-devis-ligne__sec {
        display: block;
        margin-top: 0.1rem;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
        font-family: var(--isis-font-mono);
        font-size: 0.75rem;
        color: var(--isis-text-muted);
        font-variant-numeric: tabular-nums;
    }
    .isis-devis-ligne > .isis-devis-ligne__desig .isis-devis-detail__desc-text {
        display: -webkit-box;
        -webkit-box-orient: vertical;
        -webkit-line-clamp: 2;
        line-clamp: 2;
        white-space: pre-line;   /* était : normal */
        overflow-wrap: anywhere;
    }
}

/* Palier cartes : une carte par ligne, dans une liste. Les deux arbres sont rendus, la
   requête de conteneur choisit lequel se voit. */
.isis-devis-cartes {
    display: none;
}
@container devis-lignes (max-width: 559px) {
    #devis-panel-items > .isis-grid,
    #devis-panel-items > .isis-grid-cfg-btn {
        display: none;
    }
    .isis-devis-cartes {
        display: block;
        flex: 1 1 auto;
        min-height: 0;
        overflow-y: auto;
        margin: 0;
        padding: 0;
        list-style: none;
        border: 1px solid var(--isis-border);
        border-radius: var(--isis-radius);
        background: var(--isis-surface);
        font-size: var(--isis-fs-base);
    }
}
.isis-devis-carte {
    padding: 0.75rem 1rem;
    border-bottom: 1px solid var(--isis-border-soft);
    color: var(--isis-text);
}
.isis-devis-carte:last-child {
    border-bottom: none;
}
.isis-devis-carte--section {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    column-gap: 0.75rem;
    align-items: baseline;
}
.isis-devis-carte__titre {
    overflow: hidden;
    text-overflow: ellipsis;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    white-space: pre-line;
    overflow-wrap: anywhere;
    font-weight: 600;
}
/* Sous-total de clôture, en carte : mêmes deux pistes que le titre de section, mais posée
   APRÈS la dernière ligne du bloc et non sur son titre. */
.isis-devis-carte--soustotal {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    column-gap: 0.75rem;
    align-items: baseline;
    background: var(--isis-surface-alt);
}
.isis-devis-carte__soustotal-libelle {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-weight: 600;
    color: var(--isis-text-muted);
}
.isis-devis-carte--commentaire {
    display: flex;
    align-items: flex-start;
    gap: 0.35rem;
}
.isis-devis-carte--commentaire > .isis-devis-ligne__commentaire-texte {
    flex: 1 1 auto;
    min-width: 0;
}
.isis-devis-carte__l1 {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto auto;
    column-gap: 0.5rem;
    align-items: start;
}
.isis-devis-carte__desc {
    grid-column: 1;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    overflow: hidden;
    overflow-wrap: anywhere;
    font-weight: 600;
}
.isis-devis-carte__l1 > .isis-text-expand {
    grid-column: 2;
}
.isis-devis-carte__l1 > .isis-devis-carte__montant {
    grid-column: 3;
}
.isis-devis-carte__montant {
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
    text-align: right;
}
.isis-devis-carte__l2 {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.35rem 0.5rem;
    margin-top: 0.35rem;
}
.isis-devis-carte__l2:empty {
    display: none;
}
.isis-devis-carte__l2 > .isis-devis-ligne__tags {
    margin-top: 0;
}
.isis-devis-carte__sec {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    font-family: var(--isis-font-mono);
    font-size: 0.75rem;
    font-variant-numeric: tabular-nums;
    color: var(--isis-text-muted);
}
.isis-devis-carte__sec .isis-devis-ligne__pu-alerte .rzi {
    font-size: 14px;
}
.isis-devis-carte__marge {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    margin-left: auto;
}
.isis-devis-carte__actions {
    display: flex;
    justify-content: flex-end;
    gap: 0.25rem;
    margin-top: 0.35rem;
}
/* Cible tactile de 44 px en cartes (exception de densité consignée, DESIGN.md). */
.isis-devis-carte__actions .isis-action-btn {
    height: 44px;
    min-width: 44px;
    width: auto;
    justify-content: center;
}
.isis-devis-carte > .isis-devis-ligne__depliant {
    margin-top: 0.5rem;
    padding: 0.5rem 0.75rem;
    border-radius: var(--isis-radius-sm);
    background: var(--isis-surface-alt);
}
.isis-devis-carte > .isis-devis-detail__acti-row > div {
    padding: 0;
}

/* Pied des totaux : frère de la grille dans le panneau en flex colonne, donc collé au bas
   par construction — la grille défile au-dessus, aucune ligne ne passe dessous. */
.isis-devis-pied {
    flex-shrink: 0;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: flex-end;
    gap: 0.35rem 1.25rem;
    margin-top: 0.5rem;
    padding: 0.6rem 0.85rem;
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius);
    background: var(--isis-surface);
    font-size: var(--isis-fs-sm);
    font-variant-numeric: tabular-nums;
    color: var(--isis-text-muted);
}
.isis-devis-pied dl {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.25rem 1rem;
    margin: 0;
}
.isis-devis-pied__ligne,
.isis-devis-pied__ligne dt,
.isis-devis-pied__ligne dd {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    white-space: nowrap;
}
.isis-devis-pied__ligne dd {
    margin: 0;
    color: var(--isis-text);
}
.isis-devis-pied__ttc dd {
    font-weight: 600;
}

/* Les trois périmètres d'option (EF-54) : pile DISTINCTE de la pile contractuelle, pour que
   « Tout compris HT » ne se lise pas comme le montant engagé. */
.isis-devis-pied__perimetres {
    flex: 0 1 auto;
    border-left: 1px solid var(--isis-border);
    padding-left: 1.25rem;
}
.isis-devis-pied__toutcompris dd {
    font-weight: 600;
}
.isis-devis-pied__cout {
    display: inline-flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.35rem 0.5rem;
    margin-right: auto;
}
.isis-devis-pied__valeur {
    color: var(--isis-text);
    white-space: nowrap;
}
.isis-devis-pied__net {
    display: inline-flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.25rem 0.5rem;
}
.isis-devis-pied__montant {
    font-size: 1.0625rem;
    font-weight: 600;
    color: var(--isis-text);
    white-space: nowrap;
}
.isis-devis-pied__mentions {
    flex: 1 0 100%;
    margin: 0;
    text-align: right;
    font-size: var(--isis-fs-label);
    color: var(--isis-text-muted);
}
.isis-devis-pied__mentions:empty,
.isis-devis-pied__toggle {
    display: none;
}
.isis-devis-pied__remise-edit {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
}
.isis-devis-pied__remise-champ .rz-numeric {
    width: 5.5rem;
}

@container devis-lignes (min-width: 560px) and (max-width: 1079px) {
    .isis-devis-pied {
        display: grid;
        grid-template-columns: minmax(0, 1fr) auto;
        grid-template-areas:
            "cout net"
            "avant apres"
            "perimetres perimetres"
            "mentions mentions";
        align-items: center;
    }
    .isis-devis-pied__cout { grid-area: cout; margin-right: 0; }
    .isis-devis-pied__net { grid-area: net; justify-self: end; }
    .isis-devis-pied__avant { grid-area: avant; }
    .isis-devis-pied__apres { grid-area: apres; justify-self: end; justify-content: flex-end; }
    .isis-devis-pied__perimetres {
        grid-area: perimetres;
        justify-self: end;
        justify-content: flex-end;
        border-left: 0;
        padding-left: 0;
        border-top: 1px solid var(--isis-border);
        padding-top: 0.35rem;
    }
    /* Sans option la pile n'est pas rendue : sa rangée nommée subsisterait, et les `gap`
       s'appliquant de part et d'autre d'une piste vide doubleraient l'écart. */
    .isis-devis-pied:not(:has(.isis-devis-pied__perimetres)) {
        grid-template-areas:
            "cout net"
            "avant apres"
            "mentions mentions";
    }
    .isis-devis-pied__mentions { grid-area: mentions; }
}

/* Cartes : la rangée Total HT net reste affichée, le reste se déplie sur place par
   « Totaux » (état non mémorisé). Flex et non grille : une rangée masquée ne laisse pas
   d'écart fantôme. */
@container devis-lignes (max-width: 559px) {
    .isis-devis-pied {
        align-items: center;
        justify-content: flex-start;
        padding: 0.5rem 1rem;
    }
    .isis-devis-pied__net { order: 1; flex: 1 1 auto; min-width: 0; }
    .isis-devis-pied__toggle { display: block; order: 2; }
    .isis-devis-pied__cout { order: 3; flex: 1 0 100%; margin-right: 0; }
    .isis-devis-pied__avant { order: 4; }
    .isis-devis-pied__apres { order: 5; }
    .isis-devis-pied__perimetres {
        order: 6;
        border-left: 0;
        padding-left: 0;
        border-top: 1px solid var(--isis-border);
        padding-top: 0.35rem;
    }
    .isis-devis-pied__mentions { order: 7; text-align: left; }
    .isis-devis-pied__avant,
    .isis-devis-pied__apres,
    .isis-devis-pied__perimetres {
        flex: 1 0 100%;
        flex-direction: column;
        align-items: stretch;
    }
    .isis-devis-pied__ligne {
        justify-content: space-between;
    }
    .isis-devis-pied:not(.is-expanded) > .isis-devis-pied__avant,
    .isis-devis-pied:not(.is-expanded) > .isis-devis-pied__apres,
    .isis-devis-pied:not(.is-expanded) > .isis-devis-pied__perimetres,
    .isis-devis-pied:not(.is-expanded) > .isis-devis-pied__mentions {
        display: none;
    }
    .isis-devis-pied__toggle .isis-action-btn,
    .isis-devis-pied__remise .isis-action-btn {
        height: 44px;
        min-width: 44px;
        width: auto;
        justify-content: center;
    }
}

@media print {
    #devis-panel-items .isis-devis-ligne__actions .isis-action-btn,
    .isis-devis-carte__actions,
    .isis-devis-pied__toggle,
    .isis-devis-pied .isis-action-btn,
    #devis-panel-items > .isis-grid-cfg-btn {
        display: none !important;
    }
    .isis-devis-pied {
        position: static;
    }
}

/* ============================================================================
   .isis-grid--devis-list — variante liste devis gescom (11 colonnes depuis N1.4)
   Colonnes : check | status | numéro | émission | titre | tiers | partenaires
            | montant HT + coût prévi. en sous-ligne | marge prévi. | statut | actions
   ============================================================================ */
.isis-grid--devis-list .isis-grid__head,
.isis-grid--devis-list .isis-grid__row {
    grid-template-columns: 28px 32px 130px 110px minmax(180px, 1.4fr) minmax(160px, 1fr) 120px 140px 150px 110px 50px;
    min-width: 1330px;
}
.isis-grid--devis-list .isis-grid__col-check {
    display: flex;
    align-items: center;
    justify-content: center;
}
.isis-grid--devis-list .isis-grid__col-check input[type="checkbox"] {
    cursor: pointer;
    width: 14px;
    height: 14px;
}
/* Row sélectionnée pour multi : highlight discret accent (pas confondu avec
   .is-active qui marque la row dont le sidepanel est ouvert). */
.isis-grid--devis-list .isis-grid__row.is-multi-selected {
    background: color-mix(in srgb, var(--isis-accent) 5%, transparent);
}
.isis-grid--devis-list .isis-grid__row.is-multi-selected.is-active {
    background: color-mix(in srgb, var(--isis-accent) 10%, transparent);
}

/* Barre flottante bulk actions — apparaît en bas, sticky horizontalement centrée. */
.isis-bulk-actions-bar {
    position: fixed;
    bottom: 1.5rem;
    left: 50%;
    transform: translateX(-50%);
    z-index: 100;
    display: flex;
    align-items: center;
    gap: 1rem;
    padding: 0.55rem 0.85rem 0.55rem 1rem;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: 8px;
    box-shadow: var(--isis-elevation-2);   /* overlay flottant — token (était ad-hoc, DESIGN.md §10) */
    animation: isis-bulk-bar-rise 180ms ease-out;
}
@keyframes isis-bulk-bar-rise {
    from { transform: translate(-50%, 20px); opacity: 0; }
    to   { transform: translate(-50%, 0);    opacity: 1; }
}
.isis-bulk-actions-bar__count {
    display: flex;
    align-items: center;
    gap: 0.45rem;
    font-size: 0.9rem;
    color: var(--isis-text);
    white-space: nowrap;
}
.isis-bulk-actions-bar__count strong {
    font-weight: 700;
    font-size: 1rem;
    color: var(--isis-accent);
}
.isis-bulk-actions-bar__actions {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    padding-left: 0.8rem;
    border-left: 1px solid var(--isis-border);
}
.isis-bulk-actions-bar__close {
    background: none;
    border: 0;
    cursor: pointer;
    padding: 4px;
    border-radius: 4px;
    margin-left: 0.4rem;
    color: var(--isis-text-muted);
    display: inline-flex;
}
.isis-bulk-actions-bar__close:hover {
    background: var(--isis-surface-alt);
    color: var(--isis-text);
}

/* N2.5 — Search avec suggestions (dropdown contextuel sous l'input). */
.isis-search-with-suggestions {
    position: relative;
}
.isis-search-suggestions {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    z-index: 50;
    margin-top: 4px;
    padding: 0.35rem;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: 6px;
    box-shadow: var(--isis-elevation-2);   /* dropdown overlay — token (était ad-hoc, DESIGN.md §10) */
    max-height: 360px;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
}
.isis-search-suggestions__group {
    display: flex;
    flex-direction: column;
    gap: 0.1rem;
}
.isis-search-suggestions__group-label {
    display: flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.3rem 0.5rem 0.15rem;
    font-size: 0.68rem;
    font-weight: 600;
    color: var(--isis-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}
.isis-search-suggestions__item {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    background: none;
    border: 0;
    cursor: pointer;
    padding: 0.4rem 0.5rem;
    border-radius: 4px;
    text-align: left;
    font-family: inherit;
    font-size: 0.85rem;
    color: var(--isis-text);
    width: 100%;
}
.isis-search-suggestions__item:hover {
    background: color-mix(in srgb, var(--isis-accent) 8%, transparent);
}
.isis-search-suggestions__item-label {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
    flex: 1;
}
.isis-search-suggestions__item-hint {
    color: var(--isis-text-muted);
    font-size: 0.78rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.isis-search-suggestions__highlight {
    background: color-mix(in srgb, var(--isis-warning) 25%, transparent);
    padding: 0 1px;
    border-radius: 2px;
    font-weight: 600;
    color: inherit;
}

/* N2.6 — Hover preview row : tooltip riche CSS-only avec délai 400ms.
   Activé au :hover de la row. Caché par défaut, opacity 0 + pointer-events
   none. Position : décalé vers le haut-droite de la row pour éviter d'écraser
   le sidepanel. Désactivé sur mobile (no hover device). */
.isis-grid--devis-list {
    /* Scroll horizontal hérité de la base .isis-grid (overflow: auto). Le grid
       a min-width: 1330px (11 colonnes cumulées) ; sur écrans < 1330px le scroll
       horizontal natif laisse l'utilisateur accéder aux colonnes droites.
       Note : le hover preview (.isis-row-preview) est masqué sur écrans étroits
       via la media query ci-dessous — incompatible avec un scroll horizontal
       actif (absolute positioning + transform : la preview se retrouverait
       en partie hors zone visible une fois la grille scrollée). */
}

/* Désactive le hover preview sous 1100px (tablettes / petits écrans sans hover) :
   c'est une feature de confort desktop. Au-dessus, le JS isis-row-preview.js la
   passe en position:fixed + clamp viewport → pas de débordement même quand la
   grille a un scroll horizontal sur fenêtre moyenne (1100-1500px). */
@media (max-width: 1100px) {
    .isis-row-preview {
        display: none;
    }
}
/* Générique : toute row d'une .isis-grid peut héberger un .isis-row-preview. */
.isis-grid__row {
    position: relative;
}
.isis-row-preview {
    position: absolute;
    z-index: 30;
    /* Ouvre SOUS la row (et non au-dessus) : sinon la preview des lignes du haut
       remonte hors du conteneur scroll (overflow:auto) et se fait clipper par le
       bord haut / l'en-tête sticky (« le rail au-dessus du datagrid »). */
    top: calc(100% - 4px);
    right: 60px;
    width: 320px;
    max-width: calc(100vw - 4rem);
    opacity: 0;
    pointer-events: none;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: 8px;
    padding: 0.75rem;
    box-shadow: var(--isis-elevation-hover);   /* tooltip preview — token (était ad-hoc, DESIGN.md §10) */
    font-size: 0.82rem;
    transition: opacity 120ms ease;
    transition-delay: 0ms;
}
.isis-grid__row:hover .isis-row-preview {
    opacity: 1;
    transition-delay: 400ms;
}
.isis-row-preview__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    margin-bottom: 0.35rem;
}
.isis-row-preview__head strong {
    font-family: var(--isis-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
    color: var(--isis-text);
    font-size: 0.85rem;
}
.isis-row-preview__status {
    font-size: 0.68rem;
    font-weight: 600;
    padding: 0.1rem 0.4rem;
    border-radius: var(--isis-radius-pill);
    background: var(--isis-surface-alt);
    color: var(--isis-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}
.isis-row-preview__title {
    font-weight: 600;
    color: var(--isis-text);
    margin-bottom: 0.5rem;
    line-height: 1.3;
    overflow-wrap: anywhere;
}
.isis-row-preview__meta {
    display: grid;
    grid-template-columns: 1fr;
    gap: 0.25rem;
    font-size: 0.78rem;
}
.isis-row-preview__meta > div {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 0.5rem;
    padding: 0.15rem 0;
    border-bottom: 1px dotted color-mix(in srgb, var(--isis-text) 8%, transparent);
}
.isis-row-preview__meta > div:last-child { border-bottom: none; }
.isis-row-preview__meta > div span:first-child {
    color: var(--isis-text-muted);
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    white-space: nowrap;
    flex-shrink: 0;
}
.isis-row-preview__meta > div span:last-child {
    color: var(--isis-text);
    font-variant-numeric: tabular-nums;
    text-align: right;
    /* Autorise le retour à la ligne d'une valeur longue (ex. nom de client) au lieu
       de déborder du popup. flex 1 1 0 + min-width:0 bornent la valeur à l'espace
       restant et lèvent le min-content auto des flex items → wrap garanti. */
    flex: 1 1 0;
    min-width: 0;
    white-space: normal;
    overflow-wrap: anywhere;
    word-break: break-word;
}
.isis-row-preview__margin.is-positive { color: var(--isis-success); font-weight: 600; }
.isis-row-preview__margin.is-negative { color: var(--isis-danger);  font-weight: 600; }
.isis-row-preview__margin.is-muted    { color: var(--isis-text-muted); }

/* Mobile : pas de hover device → désactive le tooltip pour éviter le tap accidentel. */
@media (hover: none) {
    .isis-grid__row:hover .isis-row-preview {
        opacity: 0;
    }
}

/* ============================================================================
   .isis-grid--commande-list — variante liste commandes gesproj (10 colonnes)
   Colonnes : status | numéro+réf | intitulé (+ icônes nature/suivi + compteurs)
            | client | origine | propriétaire
            | pilotage (avancement + santé + rendement) | montant HT | statut | actions
   (Colonne « type » supprimée 2026-06-04 — icônes fusionnées dans l'intitulé.)
   ============================================================================ */
.isis-grid--commande-list .isis-grid__head,
.isis-grid--commande-list .isis-grid__row {
    grid-template-columns: 32px 140px minmax(220px, 1.6fr) minmax(160px, 1fr) 100px minmax(150px, 1fr) 210px 184px 120px 50px;
    min-width: 1388px;
}
/* Lignes : hauteur minimale pour que les cellules multi-lignes (Pilotage : barre +
   rendement + chips livraison/qualité ; Montant : facturé/reste + badge renvoi ; Numéro :
   code + réf ; Intitulé : titre + meta) respirent. Relevé 58→68px (polish 2026-06-23) :
   à 58px le contenu sur 2 lignes touchait les bords.
   Ramené à 56px le 2026-09-02 : la cellule la PLUS HAUTE mesure 48px au navigateur
   (intitulé + meta), les 68px laissaient donc 20px de vide et six lignes tenaient là où
   huit auraient dû. 56 = 48 + 4px de part et d'autre — le contenu ne touche plus rien,
   ce que la mesure de 2026-06-23 ne vérifiait pas (elle raisonnait sur 58 sans mesurer
   les cellules). */
.isis-grid--commande-list .isis-grid__row {
    min-height: 56px;
}

/* Colonne Propriétaire : nom du commercial owner, tronqué si trop long */
.isis-grid--commande-list .isis-grid__col-owner {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Colonne Type : 2 glyphes (typologie + mode de suivi) centrés */
.isis-grid--commande-list .isis-grid__col-type {
    display: flex;
    align-items: center;
    gap: 0.35rem;
    color: var(--isis-text-muted);
}

/* Colonne Montant HT : aligné à droite, chiffres tabulaires (ex-style inline).
   Empile montant + sous-libellé facturé/reste + badge « Renvoyée » ; on lève le
   overflow:hidden/nowrap hérité de .isis-grid__row > div pour ne plus tronquer. */
.isis-grid--commande-list .isis-grid__col-amount {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    justify-content: center;
    gap: 0.15rem;
    text-align: right;
    font-variant-numeric: tabular-nums;
    overflow: visible;
    white-space: normal;
}
.isis-grid--commande-list .isis-grid__col-amount .isis-grid__col-sublabel {
    font-size: 0.68rem;
    line-height: 1.2;
    white-space: normal;
    margin-top: 0;
}
/* Colonne Pilotage : fusion avancement + santé + rendement (2026-06-04).
   Ligne 1 = barre + % + icône santé ; ligne 2 = rendement (sous-ligne). */
.isis-grid--commande-list .isis-grid__col-pilot {
    display: flex;
    flex-direction: column;
    gap: 2px;
    justify-content: center;
    min-width: 0;
    overflow: visible;
}
.isis-grid--commande-list .isis-pilot-cell {
    display: flex;
    align-items: center;
    gap: 0.4rem;
}
.isis-grid--commande-list .isis-pilot-cell .isis-health { flex: 0 0 auto; }
.isis-grid--commande-list .isis-grid__col-pilot .isis-rendement { font-size: 0.72rem; }
/* Complément Pilotage : chips livraisons + qualité des livrables (2026-06-07). */
.isis-pilot-extra { display: flex; flex-wrap: wrap; gap: 0.25rem; margin-top: 0.2rem; }
.isis-pilot-chip { display: inline-flex; align-items: center; gap: 0.15rem; font-size: 0.7rem; line-height: 1; padding: 0.12rem 0.38rem; border-radius: 999px; background: var(--isis-surface-alt); border: 1px solid var(--isis-border); color: var(--isis-text-muted); font-variant-numeric: tabular-nums; white-space: nowrap; }
.isis-pilot-chip.is-ok { color: var(--isis-success); border-color: color-mix(in srgb, var(--isis-success) 30%, var(--isis-border)); }
.isis-pilot-chip.is-warn { color: var(--isis-warning); border-color: color-mix(in srgb, var(--isis-warning) 30%, var(--isis-border)); }
.isis-pilot-chip.is-danger { color: var(--isis-danger); border-color: color-mix(in srgb, var(--isis-danger) 35%, var(--isis-border)); background: color-mix(in srgb, var(--isis-danger) 8%, var(--isis-surface)); }
/* Sous-ligne intitulé : icônes nature/suivi alignées inline puis compteurs (2026-06-04). */
.isis-grid--commande-list .isis-grid__intitule-meta {
    display: flex;
    align-items: center;
    gap: 0.3rem;
    flex-wrap: wrap;
}
.isis-mini-progress {
    flex: 1 1 auto;
    height: 6px;
    border-radius: var(--isis-radius-pill);
    background: var(--isis-surface-alt, #eef0f4);
    overflow: hidden;
    min-width: 40px;
}
.isis-mini-progress__fill {
    height: 100%;
    border-radius: var(--isis-radius-pill);
    transition: width 0.2s ease;
}
.isis-mini-progress__fill.is-ok      { background: var(--isis-success); }
.isis-mini-progress__fill.is-warn    { background: var(--isis-warning); }
.isis-mini-progress__fill.is-late    { background: var(--isis-danger); }
.isis-mini-progress__fill.is-unknown { background: var(--isis-text-muted); }
.isis-mini-progress__pct {
    flex: 0 0 auto;
    font-size: 0.72rem;
    font-variant-numeric: tabular-nums;
    color: var(--isis-text-muted);
    min-width: 2.2rem;
    text-align: right;
}

/* Colonnes Santé + Rendement : pastille / texte coloré par statut */
.isis-health,
.isis-rendement {
    display: flex;
    align-items: center;
    gap: 0.3rem;
    font-size: 0.78rem;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.isis-health.is-ok,      .isis-rendement.is-ok      { color: var(--isis-success); }
.isis-health.is-warn,    .isis-rendement.is-warn    { color: var(--isis-warning); }
.isis-health.is-late,    .isis-rendement.is-late    { color: var(--isis-danger); }
.isis-health.is-unknown, .isis-rendement.is-unknown { color: var(--isis-text-muted); }

/* ============================================================================
   .isis-grid--groupe-rollup — consolidation CA d'un groupe (grand compte 0312)
   Colonnes : Devise | CA facturé | CA signé | Pipe (3 montants alignés droite)
   ============================================================================ */
.isis-grid--groupe-rollup .isis-grid__head,
.isis-grid--groupe-rollup .isis-grid__row {
    grid-template-columns: minmax(90px, 0.5fr) 1fr 1fr 1fr;
    min-width: 560px;
}
.isis-grid--groupe-rollup .isis-grid__head > div:nth-child(n+2),
.isis-grid--groupe-rollup .isis-grid__row > div:nth-child(n+2) {
    text-align: right;
    font-variant-numeric: tabular-nums;
}
.isis-grid--groupe-rollup .isis-grid__row { cursor: default; }
.isis-groupe-rollup-grid { margin-bottom: 1rem; }
.isis-groupe-rollup-note { margin-bottom: 1rem; }

/* ============================================================================
   .isis-grid--tiers-encours — encours par devise sur la fiche tiers (0339)
   Colonnes : Devise | Encours non soldé | Nb factures
   ============================================================================ */
.isis-grid--tiers-encours .isis-grid__head,
.isis-grid--tiers-encours .isis-grid__row {
    grid-template-columns: minmax(90px, 0.5fr) 1fr minmax(110px, 0.6fr);
    min-width: 420px;
}
.isis-grid--tiers-encours .isis-grid__head > div:nth-child(n+2),
.isis-grid--tiers-encours .isis-grid__row > div:nth-child(n+2) {
    text-align: right;
    font-variant-numeric: tabular-nums;
}
.isis-grid--tiers-encours .isis-grid__row { cursor: default; }
.isis-tiers-credit__gauge { margin: 0.5rem 0 0.75rem; }

/* Note de rattachement « Rattaché au groupe : X » (onglet Groupe, 0312). */
.isis-groupe-note { margin-bottom: 0.75rem; font-size: 0.82rem; color: var(--isis-text-muted); }
.isis-groupe-note__link { color: var(--isis-mod-gescom); text-decoration: none; font-weight: 600; }
.isis-groupe-note__link:hover,
.isis-groupe-note__link:focus-visible { text-decoration: underline; }
.isis-groupe-note__strong { color: var(--isis-text); }
.isis-rich-header__ancestor-link { color: inherit; text-decoration: none; }
.isis-rich-header__ancestor-link:hover,
.isis-rich-header__ancestor-link:focus-visible { text-decoration: underline; }

/* Synthèse 360° d'un tiers (grand compte Phase 1, migration 0313). */
.isis-tiers-360__head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 1rem;
    margin-bottom: 0.6rem;
}
.isis-tiers-360__note { margin-top: 0.5rem; }

/* ============================================================================
   .isis-grid--tiers-filiales — filiales directes d'une tête de groupe (0312)
   Colonnes : status | code | raison sociale | ville | sous-groupe | actions
   ============================================================================ */
.isis-grid--tiers-filiales .isis-grid__head,
.isis-grid--tiers-filiales .isis-grid__row {
    grid-template-columns: 44px 110px minmax(180px, 1.4fr) 120px 110px 56px;
    min-width: 620px;
}

/* ============================================================================
   .isis-grid--contacts — annuaire intelligent des interlocuteurs (/gescom/contacts)
   Colonnes : status | contact (avatar+nom) | fonction | compte | email | tél | actions
   ============================================================================ */
.isis-grid--contacts .isis-grid__head,
.isis-grid--contacts .isis-grid__row {
    grid-template-columns: 44px minmax(200px, 1.4fr) 140px minmax(180px, 1.2fr) minmax(180px, 1fr) 130px 96px;
    min-width: 980px;
}
.isis-grid--contacts .isis-grid__col-contact {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    min-width: 0;
}
.isis-grid--contacts .isis-grid__avatar {
    width: 30px; height: 30px;
    font-size: 0.72rem;
}
.isis-grid--contacts .isis-grid__contact-id { min-width: 0; }
.isis-grid--contacts .isis-grid__contact-name {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    font-weight: 500;
    color: var(--isis-text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.isis-grid--contacts .isis-grid__col-account {
    display: flex;
    flex-direction: column;
    min-width: 0;
}
.isis-grid--contacts .isis-grid__account-name {
    color: var(--isis-text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Pastille « sens » du contrat : achat (fournisseur, ambre) — encore utilisée sur la fiche fournisseur. */
.isis-contrat-sens {
    display: inline-block;
    font-size: 0.68rem;
    font-weight: 600;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    padding: 0.12rem 0.5rem;
    border-radius: var(--isis-radius-pill);
}
.isis-contrat-sens--vente {
    background: color-mix(in srgb, var(--isis-mod-gescom, #4b5fad) 14%, white);
    color: var(--isis-mod-gescom, #4b5fad);
}
.isis-contrat-sens--achat {
    background: color-mix(in srgb, var(--isis-accent) 14%, white);
    color: var(--isis-accent);
}
/* Liste workspace contrats fournisseurs (P3 symétrie) — 8 colonnes. */
.isis-grid--contrat-fourn .isis-grid__head,
.isis-grid--contrat-fourn .isis-grid__row {
    grid-template-columns: 44px 120px minmax(200px, 1.5fr) minmax(150px, 1fr) 120px 150px 110px 56px;
    min-width: 1000px;
}

/* Consommé d'un contrat fournisseur (P2.2) — sidepanel portefeuille. */
.isis-contrat-conso {
    display: flex;
    align-items: baseline;
    gap: 0.4rem;
    margin: 0.25rem 0 0.5rem;
}
.isis-contrat-conso__amount {
    font-size: 1.05rem;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    color: var(--isis-text);
}
.isis-contrat-conso__cap { font-size: 0.8rem; color: var(--isis-text-muted); }
.isis-conso-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.25rem; }
.isis-conso-list__row {
    display: grid;
    grid-template-columns: 90px 1fr auto;
    gap: 0.5rem;
    align-items: center;
    font-size: 0.8rem;
    padding: 0.25rem 0;
    border-bottom: 1px solid var(--isis-border);
}
.isis-conso-list__num { font-family: 'Geist Mono', ui-monospace, monospace; color: var(--isis-text-muted); }
.isis-conso-list__title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.isis-conso-list__ttc { font-variant-numeric: tabular-nums; text-align: right; }

/* Boucle financière engagé → facturé → payé (fiche détail contrat fournisseur, P3.A). */
.isis-contrat-finance {
    display: flex;
    align-items: center;
    gap: 1rem;
    flex-wrap: wrap;
    margin-top: 1rem;
    padding: 0.85rem 1rem;
    background: var(--isis-surface-alt);
    border: 1px solid var(--isis-border);
    border-radius: 10px;
}
.isis-contrat-finance__cell { min-width: 130px; }
.isis-contrat-finance__label { font-size: 0.72rem; color: var(--isis-text-soft); text-transform: uppercase; letter-spacing: 0.03em; }
.isis-contrat-finance__value { font-size: 1.15rem; font-weight: 600; font-variant-numeric: tabular-nums; color: var(--isis-text); }
.isis-contrat-finance__hint { font-size: 0.72rem; color: var(--isis-text-muted); }

/* ============================================================================
   .isis-grid--commande-items — variante items commande sur la fiche détail
   Colonnes : # | code ana. | désignation | qté | unité | PU HT | remise | total HT | actions
   ============================================================================ */
.isis-grid--commande-items .isis-grid__head,
.isis-grid--commande-items .isis-grid__row {
    grid-template-columns: 2.5rem 7rem minmax(200px, 1fr) 4.5rem 5rem 7rem 5rem 8rem 6rem;
}
/* Code analytique (catalogue) — snapshot figé sur la ligne, monospace pour scan vertical. */
.isis-grid--commande-items .isis-item-code {
    font-family: var(--isis-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
    font-size: 0.8rem;
    color: var(--isis-text-soft);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.isis-grid--commande-items .isis-item-code--none { color: var(--isis-text-muted); }

/* ============================================================================
   Onglet « Temps pointés » de la fiche commande — visa projet des temps.
   Colonnes : sélection | date | collaborateur | tâche | heures | coût | état
   ============================================================================ */
.isis-cmd-temps { display: flex; flex-direction: column; gap: 0.6rem; min-height: 0; }
.isis-cmd-temps__note {
    margin: 0;
    font-size: 0.82rem;
    color: var(--isis-text-muted);
    max-width: 78ch;
}
.isis-cmd-temps__filters { display: flex; align-items: center; gap: 0.75rem; flex-wrap: wrap; }
.isis-cmd-temps__period { display: inline-flex; align-items: center; gap: 0.35rem; }
.isis-cmd-temps__period-label {
    font-size: 0.78rem; font-weight: 600; color: var(--isis-text-muted);
}
/* Croix de retrait logée DANS le chip du filtre collaborateur (le chip n'est pas cliquable :
   c'est un état affiché, pas une bascule — seule la croix agit). */
.isis-cmd-temps__chip-clear {
    display: inline-flex; align-items: center;
    border: 0; background: none; cursor: pointer; padding: 0 0 0 0.25rem;
    color: inherit;
}
.isis-cmd-temps__chip-clear:focus-visible { outline: 2px solid var(--isis-current-mod, var(--isis-accent)); outline-offset: 2px; }
/* Barre d'action de masse : INLINE au-dessus de la grille. La barre flottante fixe
   (.isis-bulk-actions-bar) appartient aux pages liste plein écran ; ici le panneau vit dans
   la carte d'onglets de la fiche, une barre fixe recouvrirait le pied de la fiche hôte. */
.isis-cmd-temps__bulk {
    display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap;
    padding: 0.5rem 0.85rem;
    background: var(--isis-surface-alt);
    border: 1px solid var(--isis-current-mod, var(--isis-accent));
    border-radius: var(--isis-radius);
}
/* La barre est une région aria-live : elle doit rester dans le DOM même sans sélection, sinon
   son contenu est inséré EN MÊME TEMPS que la région et n'est pas annoncé. Sans sélection elle
   n'a ni contenu ni surface ; la marge négative annule le `gap` que sa boîte vide ajouterait
   entre les filtres et la grille. */
.isis-cmd-temps__bulk--idle {
    padding: 0; border-width: 0; background: none; margin-bottom: -0.6rem;
}
.isis-cmd-temps__bulk-count { font-weight: 700; color: var(--isis-current-mod, var(--isis-accent)); }
.isis-cmd-temps__bulk-spacer { flex: 1; }
/* Badge d'état + bouton de détail : un seul groupe, le badge ne se sépare jamais de son bouton. */
.isis-cmd-temps__etat { display: inline-flex; align-items: center; gap: 0.25rem; min-width: 0; }
.isis-cmd-temps__collab { display: inline-flex; align-items: center; gap: 0.25rem; min-width: 0; }
.isis-cmd-temps__collab-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.isis-grid--cmd-temps .isis-grid__head,
.isis-grid--cmd-temps .isis-grid__row {
    grid-template-columns: 34px 105px minmax(150px, 1.3fr) minmax(160px, 1.6fr) 90px 120px 165px;
    min-width: 890px;
}
/* Heures et coût : alignés à droite et tabulaires — ces deux colonnes se comparent
   verticalement, c'est tout leur intérêt sur une liste plate. */
.isis-grid--cmd-temps .isis-grid__head > *:nth-child(5),
.isis-grid--cmd-temps .isis-grid__head > *:nth-child(6),
.isis-grid--cmd-temps .isis-grid__row > *:nth-child(5),
.isis-grid--cmd-temps .isis-grid__row > *:nth-child(6) {
    justify-content: flex-end; justify-self: end; text-align: right;
    font-variant-numeric: tabular-nums;
}
/* La ligne n'ouvre rien : seules la case à cocher et le filtre collaborateur agissent. */
.isis-grid--cmd-temps .isis-grid__row { cursor: default; }
.isis-grid--cmd-temps .isis-grid__col-check input {
    width: 16px; height: 16px; margin: 0; cursor: pointer;
    accent-color: var(--isis-current-mod, var(--isis-accent));
}

/* S0 — badge cadenas (ligne/tâche verrouillée) + indicateur d'allocation. */
.isis-lock-badge {
    display: inline-flex; align-items: center; gap: 0.2rem;
    font-size: 0.7rem; font-weight: 600; color: var(--isis-text-muted);
    background: var(--isis-surface-alt); border-radius: var(--isis-radius-sm);
    padding: 0.05rem 0.35rem; margin-left: 0.35rem;
}
.isis-lock-badge .rzi, .isis-lock-badge .material-symbols-outlined { font-size: 13px; }
.isis-alloc-indicator {
    font-size: 0.78rem; color: var(--isis-text-muted); margin-top: 0.1rem;
    font-variant-numeric: tabular-nums;
}
.isis-alloc-indicator strong { color: var(--isis-current-mod, var(--isis-accent)); }
.isis-tache-budget {
    font-size: 0.82rem; font-variant-numeric: tabular-nums;
    color: var(--isis-current-mod, var(--isis-accent)); font-weight: 600;
}

/* Tâche — dates + statut dérivé (datagrid enrichi) */
.isis-tache-card__dates {
    font-size: 0.78rem; color: var(--isis-text-muted);
    font-variant-numeric: tabular-nums; white-space: nowrap; margin-left: 0.5rem;
}
.isis-tache-status {
    display: inline-flex; align-items: center; padding: 0.05rem 0.5rem; margin-left: 0.4rem;
    border-radius: 999px; font-size: 0.68rem; font-weight: 600; letter-spacing: 0.02em;
}
.isis-tache-status.is-todo { background: var(--isis-surface-alt); color: var(--isis-text-muted); }
.isis-tache-status.is-doing { background: color-mix(in srgb, var(--isis-accent) 14%, var(--isis-surface)); color: var(--isis-accent); }
.isis-tache-status.is-done { background: color-mix(in srgb, var(--isis-success) 16%, var(--isis-surface)); color: var(--isis-success); }
.isis-tache-status.is-locked { background: color-mix(in srgb, var(--isis-warning) 16%, var(--isis-surface)); color: var(--isis-warning); }

/* Datagrid des tâches — tableau aligné + lignes dépliables + édition inline */
/* Colonnes (16) : expand · # · Tâche · Début · Fin · Statut · Avanc. · Charge · Budget vendu · Coût révisé · Coût réel · Frais · Marge révisée · M. réelle · Écart exéc. · Actions */
.isis-grid--taches {
    overflow-x: auto;
    min-width: 0;
}
.isis-grid--taches .isis-grid__head,
.isis-grid--taches .isis-grid__row {
    display: grid;
    grid-template-columns: 34px 42px minmax(180px, 1.6fr) 142px 142px 104px 90px 72px 116px 128px 108px 108px 128px 108px 108px 78px;
    align-items: center; column-gap: 0.5rem;
    /* min-width = Σ colonnes (mins = 1688) + 15 column-gap (15×8=120) + padding latéral
       (2×8=16) = 1824px. L'ancienne valeur 1648 était sous-dimensionnée (plancher mort,
       < Σ colonnes) → à tenir synchronisé avec .isis-tache-card__detail. */
    min-width: 1824px;
}
.isis-grid--taches .isis-grid__head {
    /* Aligné sur l'en-tête standard : fond, typo, hauteur 34px, sticky et z-index
       viennent de la base. Cette variante surchargeait fond blanc / 0.7rem / 0.03em
       et redéclarait sticky avec un z-index 1 (INFÉRIEUR au 4 de la base) — d'où un
       en-tête visuellement différent des autres grilles. Seul le padding latéral
       reste à 0.5rem : il doit correspondre à celui des lignes de la variante
       (0.3rem 0.5rem) et entre dans le calcul du min-width. */
    padding-left: 0.5rem;
    padding-right: 0.5rem;
}
.isis-grid--taches .isis-grid__row {
    padding: 0.3rem 0.5rem; border-bottom: 1px solid var(--isis-border);
    font-size: 0.85rem; transition: background 0.12s;
}
.isis-grid--taches .isis-grid__row:hover { background: var(--isis-surface-alt); }
.isis-grid--taches .isis-grid__row.is-expanded { background: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 5%, var(--isis-surface)); }
/* Séparateur visuel entre bloc "prévu/révisé" (cols 1-10) et bloc "réel" (cols 11-15).
   Col 11 = Coût réel — position vérifiée au DOM : expand·#·Tâche·Début·Fin·Statut·Avanc.·Charge·Budget vendu·Coût révisé·Coût réel·Frais·Marge révisée·M. réelle·Écart exéc.·Actions */
.isis-grid--taches .isis-grid__head > div:nth-child(11),
.isis-grid--taches .isis-grid__row  > div:nth-child(11) {
    border-left: 1.5px solid var(--isis-border);
    padding-left: 0.65rem;
}
/* Sans le droit de voir le coût de revient (migration 0733), les six colonnes de coût et de
   marge ne sont pas rendues : le gabarit doit en compter dix, sinon les dix restantes
   s'étirent dans un cadre prévu pour seize.
   Colonnes : expand · # · Tâche · Début · Fin · Statut · Avanc. · Charge · Budget vendu · Actions
   min-width = Σ mins (1000) + 9 column-gap (9×8=72) + padding latéral (2×8=16) = 1088px.
   Le séparateur nth-child(11) ci-dessus ne matche alors plus rien — rien à neutraliser. */
.isis-grid--taches-sans-cout .isis-grid__head,
.isis-grid--taches-sans-cout .isis-grid__row {
    grid-template-columns: 34px 42px minmax(180px, 1.6fr) 142px 142px 104px 90px 72px 116px 78px;
    min-width: 1088px;
}
.isis-grid--taches-sans-cout .isis-tache-card__detail { min-width: 1088px; }
.isis-tache-grid__title { display: flex; align-items: center; gap: 0.35rem; min-width: 0; }
.isis-tache-grid__title strong { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-weight: 600; }
/* Marqueur de documentation qualité — bouton d'ouverture du masquage documentaire.
   Sans surface propre ni padding : la ligne de tâche est déjà dense (16 colonnes, 1824 px de
   large), et la hauteur de ligne ne doit pas bouger d'un pixel. `is-mute` = tout est masqué,
   le terrain ne voit plus rien : le marqueur reste (c'est la seule porte de retour) mais cesse
   de porter la couleur du module, qui promettrait une consigne affichée. */
.isis-tache-grid__doc-btn {
    /* Fond PERSISTANT, pas seulement au survol : la cellule titre porte juste à côté une icône
       `lock` de même taille et de même poids qui, elle, n'est pas cliquable. Sans ce fond, rien
       ne distingue au repos ce qui réagit au clic de ce qui n'y réagit pas (audit ui-ux). Il
       fait aussi office de SECOND signal pour l'état « tout masqué », qui ne repose plus sur la
       seule teinte. */
    background: color-mix(in srgb, var(--isis-mod-gesqhse) 12%, transparent);
    border: none; cursor: pointer; line-height: 0;
    border-radius: var(--isis-radius-sm); color: var(--isis-mod-gesqhse);
    display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto;
    /* WCAG 2.2 — 2.5.8 Cible (24×24 px) : l'icône fait 13 px, le padding porte la cible à
       25 px. La ligne de tâche mesure 46 px, la hauteur ne bouge donc pas ; les marges
       négatives horizontales évitent d'élargir la cellule titre, déjà à l'étroit dans une
       grille de 16 colonnes. */
    padding: 6px; margin: 0 -3px;
}
.isis-tache-grid__doc-btn:hover { background: color-mix(in srgb, var(--isis-mod-gesqhse) 22%, transparent); }
/* Tout est masqué : plus de teinte module ET plus de fond — le terrain ne voit rien, le
   marqueur cesse de promettre une consigne affichée, mais reste là (seule porte de retour). */
.isis-tache-grid__doc-btn.is-mute { background: none; color: var(--isis-text-muted); }
.isis-tache-grid__doc-btn.is-mute:hover { background: var(--isis-surface-alt); }
.isis-tache-grid__doc-btn:focus-visible {
    outline: 2px solid color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 50%, transparent);
    outline-offset: 1px;
}
.isis-grid__chevron-btn {
    background: none; border: none; cursor: pointer; color: var(--isis-text-muted);
    display: flex; align-items: center; justify-content: center; padding: 0; border-radius: 6px;
}
.isis-grid__chevron-btn:hover { color: var(--isis-text); background: var(--isis-surface-alt); }
.isis-grid__chevron-btn:focus-visible { outline: 2px solid color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 50%, transparent); outline-offset: 1px; }
.isis-grid__row-actions { display: flex; gap: 0.25rem; justify-content: flex-end; }
.isis-tache-card__detail {
    padding: 0.6rem 0.9rem 0.9rem 2.4rem;
    background: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 4%, var(--isis-surface));
    border-bottom: 1px solid var(--isis-border);
    display: flex; flex-direction: column; gap: 0.7rem;
    overflow-x: auto;
    /* Pleine largeur des lignes (sinon, scrollé à droite, le fond s'arrête au milieu).
       DOIT rester égal au min-width de .isis-grid--taches .isis-grid__row (1824px). */
    min-width: 1824px;
    box-sizing: border-box;
}

/* Grille des livraisons (fiche commande) — alignée sur le standard .isis-grid,
   avec ligne dépliable inline (livrables + QC) sur le modèle de .isis-grid--taches. */
.isis-grid--livraisons { overflow-x: auto; min-width: 0; }
.isis-grid--livraisons .isis-grid__head,
.isis-grid--livraisons .isis-grid__row {
    /* Dernière colonne (Actions) = 162px : juste la place des 5 boutons du pire cas
       (statuts EXPEDIEE/RECEPTIONNEE : 5 × 28px + 4 gaps + padding). 184px laissait
       ~95px de vide sur les lignes à 3 boutons. */
    /* Numéro à 200px (et non 150) : les numéros natifs (BLKAD-260002 = 102px) et la
       plupart des sous-libellés « Commande … » tiennent. Les numéros de reprise très
       longs (LIV- + numéro de commande complet ≈ 266px) restent tronqués avec leur
       title au survol — les afficher entièrement demanderait 278px et pousserait la
       grille à 1954px. NB : minmax(150px, auto) ne sert à rien ici, la piste auto ne
       peut pas grandir puisque min-width consomme exactement l'espace disponible. */
    grid-template-columns: 40px 200px 172px 104px 96px 200px 210px 100px 128px 128px 84px 148px 162px;
    align-items: center; column-gap: 0.4rem;
    /* min-width = Σ colonnes (1772) + 12 column-gap (12×6.4=76.8) + padding latéral
       (2×13.6=27.2) ≈ 1876px. Une valeur inférieure (ex. la seule somme des colonnes)
       fait déborder le contenu de la ligne → scroll horizontal fantôme (vide à droite).
       Tenir à jour si les colonnes changent, ET répercuter sur .isis-livraison-detail. */
    min-width: 1876px;
}
/* Badge « Jalon de paiement » : tronquer proprement (…) au lieu d'une coupe mi-mot
   (le title porte le libellé complet). min-width:0 requis pour l'ellipse en flex. */
.isis-livraison-jalons .isis-badge {
    min-width: 0; max-width: 100%;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.isis-grid--livraisons .isis-grid__row { min-height: 52px; }

/* Liste des avis communauté (/feedback) — 5 colonnes, liste bornée (load-all). */
.isis-grid--avis .isis-grid__head,
.isis-grid--avis .isis-grid__row {
    grid-template-columns: minmax(240px, 1fr) 140px 120px 90px 110px;
    align-items: center;
    min-width: 700px;
}

/* Catalogue d'achat d'un sous-traitant (onglet Catalogue de la fiche tiers) — 8 col.
   Colonne Portée ajoutée après Prix d'achat HT (Task 5, prix par marché). Pas de
   isis-grid--sticky-actions ici (retiré, cf. commentaire sur le marquage du conteneur
   dans TiersCatalogueTab.razor) : Actions reste 90px, largeur suffisante pour ses deux
   boutons icône même en flux normal (28px × 2 + gap + padding cellule ≈ 70px).
   min-width = Σ colonnes (1150, les 1fr comptés à leur min) + padding 27.2 ≈ 1178px. */
.isis-grid--catalogue-tiers .isis-grid__head,
.isis-grid--catalogue-tiers .isis-grid__row {
    grid-template-columns: 130px minmax(200px, 1.4fr) 150px minmax(180px, 1fr) 150px 130px 110px 90px;
    align-items: center;
    min-width: 1178px;
}
.isis-grid--catalogue-tiers .isis-grid__col-actions {
    display: flex; gap: 0.15rem; align-items: center; justify-content: flex-start;
}

/* Matrice « Prix sous-traitants » d'un marché (lot 2) : postes en lignes, candidats en
   colonnes. Le nombre de colonnes varie, donc grid-template-columns est posé EN LIGNE par
   le composant ; ici on ne fixe que ce qui ne dépend pas du nombre de candidats.

   overflow-x sur le CONTENEUR de la grille, jamais sur la page : c'est la règle du
   référentiel, et le précédent correct est .isis-grid--livraisons. min-width: 0 est
   nécessaire pour qu'un enfant de flex accepte de rétrécir sous sa largeur de contenu —
   sans lui, c'est la page qui déborde.

   PAS de position: sticky sur une colonne. Le collant de la colonne d'actions du lot 1 avait
   provoqué un chevauchement et avait été retiré, avec consigne de ne le réintroduire
   qu'APRÈS mesure au navigateur. Cette mesure a été faite le 2026-08-11 : trois colonnes
   d'identité gelées à gauche (largeurs fixes 260/90/140, background et z-index explicites)
   ont été implémentées, puis capturées grille défilée — elles se peignent PAR-DESSUS les
   colonnes de données, texte sur texte, exactement le défaut du lot 1 (le fond ne couvrait
   pas : les cellules de ligne ne portent pas --isis-surface en propre). Retiré.
   Le besoin reste réel au-delà de ~4 candidats — l'identité de la ligne sort du champ au
   défilement — mais il demande un autre montage que du sticky posé sur une grille CSS dont
   les cellules sont transparentes. Consigné en dette, pas déguisé en fonctionnalité. */
/* --concurrence-st est la même grille, sur l'onglet Mise en concurrence d'une offre de prix : mêmes
   colonnes d'identité, mêmes en-têtes empilés par candidat. Elle partage ces déclarations
   plutôt que de les recopier sous un autre nom — une copie aurait dérivé au premier
   ajustement, et design-lint interdit à raison qu'un même gabarit soit déclaré deux fois.
   Le gabarit de colonnes, lui, est posé en ligne par chaque composant : il dépend du nombre
   de candidats, inconnu à l'écriture de la feuille. */
.isis-grid--prix-st,
.isis-grid--concurrence-st { overflow-x: auto; min-width: 0; }

/* Le conteneur porte tabindex=0 pour être atteignable au clavier quand il défile
   (WCAG 2.1.1) : il lui faut donc un focus visible, comme tout élément focalisable. */
.isis-grid--prix-st:focus-visible,
.isis-grid--concurrence-st:focus-visible {
    outline: 2px solid var(--isis-current-mod);
    outline-offset: 2px;
}

.isis-grid--prix-st .isis-grid__head,
.isis-grid--prix-st .isis-grid__row,
.isis-grid--concurrence-st .isis-grid__head,
.isis-grid--concurrence-st .isis-grid__row { align-items: center; }

/* L'en-tête d'une colonne candidat empile un nom, un badge de qualité et un bouton. La
   hauteur d'en-tête normative (34px) et sa disposition en ligne les écrasaient côte à côte
   dans 170px : le nom débordait sur la colonne voisine. Ici seulement, l'en-tête s'empile
   et grandit — la règle générale reste intacte pour toutes les autres grilles.

   L'empilement ne vise QUE les colonnes candidats (à partir de la 4e) : appliqué aussi aux
   trois en-têtes d'identité, il les désalignait (constaté en capture le 2026-08-11). */
.isis-grid--prix-st .isis-grid__head,
.isis-grid--concurrence-st .isis-grid__head { height: auto; min-height: 34px; }
.isis-grid--prix-st .isis-grid__head > div:nth-child(n+4),
.isis-grid--concurrence-st .isis-grid__head > div:nth-child(n+4) {
    display: flex; flex-direction: column; align-items: flex-start; gap: 0.25rem;
    white-space: normal; padding: 0.3rem 0.35rem;
}
/* Le badge dit « Dossier qualité incomplet » ou « Référencé pour 2 postes sur 4 » : coupé à
   la largeur de colonne, il perdait justement la partie qui informe (capture du 2026-08-11).
   Il revient à la ligne plutôt que d'être tronqué. */
.isis-grid--prix-st .isis-grid__head > div:nth-child(n+4) .rz-badge,
.isis-grid--concurrence-st .isis-grid__head > div:nth-child(n+4) .rz-badge {
    white-space: normal; text-align: left; line-height: 1.25; max-width: 100%;
}
.isis-prix-st__tiers {
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
    overflow: hidden; font-weight: 600; color: var(--isis-text);
}

/* Un prix hérité (accord d'entité ou de groupe) se distingue d'un prix négocié pour ce
   marché : couleur atténuée, italique ET libellé d'origine — jamais la seule couleur, un
   écart qui ne tient qu'à une teinte n'existe pas pour qui ne la perçoit pas. */
.isis-prix-cell__valeur {
    font-family: var(--isis-font-mono, ui-monospace, monospace);
    font-variant-numeric: tabular-nums;
}
.isis-prix-cell--herite .isis-prix-cell__valeur { color: var(--isis-text-muted); font-style: italic; }

/* white-space: normal est indispensable : la cellule parente hérite du `nowrap` normatif
   de .isis-grid__row > div, et l'ellipse ne s'applique qu'au contenu direct de la boîte
   qui la porte — ce libellé, imbriqué et en display:block, était coupé net et SANS « … ».
   C'est le texte qui porte « Non comparable — autre devise » : l'information la plus
   importante de la cellule disparaissait en silence. */
.isis-prix-cell__origine {
    display: block; font-size: 0.7rem; color: var(--isis-text-muted);
    white-space: normal; overflow-wrap: break-word;
}
.isis-prix-cell--non-comparable .isis-prix-cell__valeur { text-decoration: underline dotted; }

/* ── Consultations d'une offre de prix (gescom · onglet Consultations) ─────────────────
   La cellule empile un montant (saisi ou lu), sa ligne de détail et ses actions. Elle porte
   sa propre classe plutôt que de charger `.isis-prix-cell` de déclarations de disposition :
   ce nom sert déjà aux cellules du marché, qui n'ont ni saisie ni actions et que ce montage
   déferait. Les classes d'ÉLÉMENT (__valeur, __origine) restent partagées, elles. */
.isis-concurrence-cell {
    display: flex; flex-direction: column; gap: 0.2rem;
    padding: 0.25rem 0.35rem; white-space: normal;
}
/* Le fond ne porte pas l'information : le mot « Retenu » est écrit dans la cellule
   (.isis-prix-cell__origine). La teinte ne fait que le retrouver du coin de l'œil. */
.isis-concurrence-cell--retenu {
    background: var(--isis-success-soft);
    box-shadow: inset 2px 0 0 var(--isis-success);
}
.isis-concurrence-cell--retenu .isis-prix-cell__origine { color: var(--isis-success-text); font-weight: 600; }
.isis-concurrence-cell__actions { display: flex; align-items: center; gap: 0.15rem; }

/* Changer de consultation recharge la matrice : sans voile, l'ancienne reste lisible et
   cliquable pendant la requête — on croit lire les prix de la consultation demandée. Le
   `aria-busy` du conteneur dit la même chose à qui ne voit pas l'atténuation. */
.isis-grid--concurrence-st[aria-busy="true"] {
    opacity: 0.55;
    pointer-events: none;
    transition: opacity 120ms ease-out;
}

/* Le montant saisi et le montant lu sont la même donnée : ils doivent s'aligner chiffre à
   chiffre d'une colonne à l'autre, sinon comparer deux prix à l'œil demande de les relire. */
.isis-concurrence-cell .rz-numeric input {
    font-family: var(--isis-font-mono, ui-monospace, monospace);
    font-variant-numeric: tabular-nums;
    text-align: right;
}

.isis-concurrence-poste {
    display: flex; align-items: center; gap: 0.4rem; min-width: 0;
}
.isis-concurrence-poste__nom {
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
    overflow: hidden; white-space: normal; font-weight: 600; color: var(--isis-text);
}

.isis-devis-concurrence__objet {
    margin: 0 0 0.75rem; color: var(--isis-text-muted); white-space: pre-wrap;
}
/* Deux sélecteurs d'ajout (postes, candidats) : côte à côte quand la place le permet,
   empilés sinon — sur un portable, chacun garde sa largeur minimale utilisable. */
.isis-devis-concurrence__ajouts {
    display: flex; flex-wrap: wrap; gap: 0.75rem 1.25rem; margin-bottom: 0.75rem;
}
.isis-devis-concurrence__ajout { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }

/* Historique des prix, dépliable sous chaque ligne du catalogue tiers (Task 5). C'est une
   LIGNE du tableau (role=row) à cellule unique étendue sur les 8 colonnes, plus un <details>
   frère des lignes : un conteneur role=table n'accepte que row/rowgroup, et l'ancien montage
   rendait le dépliant inatteignable en navigation tableau (audit a11y 2026-08-11).

   Le sélecteur ne nomme volontairement PAS `.isis-grid--catalogue-tiers` : ce modificateur
   pose déjà le gabarit à 8 colonnes des lignes de données, et le redéclarer sous le même nom
   pour un autre type de ligne est précisément ce que design-lint interdit (grid-modifier-dup) —
   à raison, puisque rien ne distinguerait alors les deux déclarations. La ligne de dépliant est
   donc son propre modificateur. `.isis-grid` en tête n'est pas décoratif : sans lui, on serait
   à égalité de spécificité avec `.isis-grid--catalogue-tiers .isis-grid__row` et le gabarit ne
   tiendrait qu'à l'ordre du fichier. La `min-width` de la grille, elle, reste héritée — le
   dépliant doit rester aussi large que le tableau quand celui-ci défile horizontalement. */
.isis-grid .isis-grid__row.isis-catalogue-tiers-histo {
    grid-template-columns: 1fr;
    /* Une ligne de dépliant n'a pas de gabarit de ligne de données : elle épouse son
       contenu (44px replié serait une bande vide, et le repli doit rester discret). */
    min-height: 0;
    cursor: default;
}
/* Ni survol teinté ni curseur main : cette ligne n'est pas cliquable, seul son bouton l'est. */
.isis-grid .isis-grid__row.isis-catalogue-tiers-histo:hover {
    background: transparent;
}
/* La cellule porte un panneau, pas une valeur : contrairement à `.isis-grid__row > div`,
   elle ne doit ni rogner son contenu ni le contraindre à une ligne unique. */
.isis-grid .isis-grid__row.isis-catalogue-tiers-histo > div {
    padding: 0 0 0.5rem 0;
    overflow: visible;
    white-space: normal;
}
.isis-catalogue-tiers-histo__toggle {
    display: inline-flex;
    align-items: center;
    gap: 0.2rem;
    padding: 0.4rem 0.3rem 0.4rem 0;
    border: none;
    background: transparent;
    font-family: inherit;
    font-size: 0.82rem;
    font-weight: 500;
    color: var(--isis-text-muted);
    cursor: pointer;
    border-radius: var(--isis-radius-sm);
}
.isis-catalogue-tiers-histo__toggle:hover { color: var(--isis-text); }
.isis-catalogue-tiers-histo__toggle:focus-visible {
    outline: 2px solid var(--isis-accent);
    outline-offset: 1px;
    color: var(--isis-text);
}
/* Le chevron dit l'état, en plus d'aria-expanded : replié il pointe vers le bas, déplié
   vers le haut. Seul indice visuel du dépliage depuis la disparition du marqueur natif. */
.isis-catalogue-tiers-histo__toggle .rzi { transition: transform 120ms ease; }
.isis-catalogue-tiers-histo__toggle[aria-expanded="true"] .rzi { transform: rotate(180deg); }
.isis-catalogue-tiers-histo__body {
    padding-top: 0.3rem;
}

/* Historique des prix — 7 colonnes, liste bornée par entrée (une poignée de révisions).
   La 3e (volume négocié, 0810) est dimensionnée sur « Non renseigné », son libellé le plus long. */
.isis-grid--catalogue-tiers-histo .isis-grid__head,
.isis-grid--catalogue-tiers-histo .isis-grid__row {
    grid-template-columns: 150px 90px 110px 110px 130px minmax(150px, 1fr) 100px;
    align-items: center;
    min-width: 850px;
}

/* Collaborateurs rattachés à un grade de coût — 3 colonnes, liste bornée. */
.isis-grid--cost-collabs .isis-grid__head,
.isis-grid--cost-collabs .isis-grid__row {
    grid-template-columns: 160px minmax(220px, 1fr) 90px;
    align-items: center;
    min-width: 500px;
}
.isis-grid--cost-collabs .isis-grid__col-actions {
    display: flex; gap: 0.15rem; align-items: center; justify-content: flex-start;
}

/* Conditions de mobilisation d'un grade de coût (profils, 0815) — 5 colonnes, liste bornée
   par le catalogue de profils (4 en V1 : normal, nuit, dimanche, férié). */
.isis-grid--cost-tarifs .isis-grid__head,
.isis-grid--cost-tarifs .isis-grid__row {
    grid-template-columns: 210px 140px 120px minmax(180px, 1fr) 90px;
    align-items: center;
    min-width: 740px;
}
.isis-grid--cost-tarifs .isis-grid__col-actions {
    display: flex; gap: 0.15rem; align-items: center; justify-content: flex-start;
}
/* Un coût se lit en colonne : chiffres à largeur fixe et alignés à droite. Classe et double
   sélecteur reprennent la convention des grilles d'événements — l'en-tête est un conteneur
   inline-flex, la cellule non, donc text-align seul ne déplace pas le libellé de colonne. */
.isis-grid--cost-tarifs .isis-grid__col-num {
    text-align: right;
    font-variant-numeric: tabular-nums;
}
.isis-grid--cost-tarifs .isis-grid__head-cell.isis-grid__col-num {
    justify-content: flex-end;
}

/* Mes délégations (/mon-espace/delegations) — 8 colonnes (chevron de dépliage ajouté en
   tête, Task 11), liste bornée par utilisateur. */
.isis-grid--mes-delegations .isis-grid__head,
.isis-grid--mes-delegations .isis-grid__row {
    grid-template-columns: 34px 110px minmax(180px, 1fr) 110px 110px minmax(150px, 1fr) minmax(160px, 1fr) 90px;
    align-items: center;
    min-width: 1064px;
}
.isis-grid--mes-delegations .isis-grid__col-actions {
    display: flex; gap: 0.15rem; align-items: center; justify-content: flex-start;
}

/* Journal des reprises d'une délégation (Task 11) — bloc PLEINE LARGEUR inséré entre deux
   .isis-grid__row (jamais une cellule : même principe que .isis-grid__subrow, cf. Gespla
   PrevisionnelPage), donc hors du grid-template-columns ci-dessus — les 8 colonnes de la
   ligne ne se déforment pas. Indentation alignée sur .isis-grid__subrow (2.6rem). */
.isis-grid__row-journal {
    padding: 0.65rem 0.9rem 0.9rem 2.6rem;
    background: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 4%, var(--isis-surface));
    border-bottom: 1px solid var(--isis-border);
}
.isis-grid__row-journal__loading,
.isis-grid__row-journal__empty {
    display: flex;
    align-items: flex-start;
    gap: 0.5rem;
    color: var(--isis-text-muted);
    font-size: 0.82rem;
}
.isis-grid__row-journal__loading .rzi,
.isis-grid__row-journal__empty .rzi {
    flex: 0 0 auto;
    margin-top: 0.1rem;
}
.isis-grid__row-journal__empty strong {
    display: block;
    color: var(--isis-text);
    margin-bottom: 0.15rem;
    font-size: 0.85rem;
}
.isis-grid__row-journal__list {
    display: flex;
    flex-direction: column;
    gap: 0.55rem;
}
.isis-grid__row-journal__item {
    display: flex;
    align-items: flex-start;
    gap: 0.55rem;
}
.isis-grid__row-journal__dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    flex: 0 0 auto;
    margin-top: 0.4rem;
}
.isis-grid__row-journal__body {
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 0.1rem;
}
.isis-grid__row-journal__line1 {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    flex-wrap: wrap;
    font-size: 0.85rem;
    color: var(--isis-text);
}
.isis-grid__row-journal__line2 {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    flex-wrap: wrap;
    font-size: 0.78rem;
    color: var(--isis-text-muted);
}
.isis-grid__row-journal__line2 a { color: var(--isis-current-mod, var(--isis-accent)); }

/* Sous-commandes (délégations) d'une commande — 9 colonnes, liste bornée.
   min-width = Σ colonnes (1300, le 1fr comptant pour son min de 200) + padding
   latéral (2×13.6=27.2) ≈ 1328px. Pas de column-gap surchargé : on garde le gap 0
   de la base, donc rien à ajouter au calcul. */
.isis-grid--sous-commandes .isis-grid__head,
.isis-grid--sous-commandes .isis-grid__row {
    grid-template-columns: minmax(200px, 1fr) 180px 150px 120px 130px 140px 110px 150px 120px;
    align-items: center;
    min-width: 1328px;
}
.isis-grid--sous-commandes .isis-grid__col-actions {
    display: flex; gap: 0.15rem; align-items: center; justify-content: flex-start; flex-wrap: nowrap;
}

/* Liste des campagnes de recette (/recette) — 8 colonnes, liste bornée (load-all) :
   Campagne | Chantier | Statut | Cas | OK | KO | Réserve | (actions). La colonne
   Chantier a été ajoutée avec son entonnoir : filtrer sur un axe que la grille ne
   montre pas revient à masquer des lignes sans dire pourquoi.
   Nom distinct de .isis-grid--recette (page détail /recette/{id}) pour éviter la
   collision de classe. */
.isis-grid--recette-list .isis-grid__head,
.isis-grid--recette-list .isis-grid__row {
    grid-template-columns: minmax(220px, 1fr) minmax(120px, 0.6fr) 150px 78px 72px 72px 96px 70px;
    align-items: center;
    min-width: 900px;
}

/* Compteurs à droite, chiffres tabulaires : les colonnes se comparent verticalement.
   Le head-cell doit suivre le corps, sinon le libellé et le bouton de tri restent à
   gauche au-dessus de nombres cadrés à droite. */
.isis-grid--recette-list .isis-grid__col-num {
    justify-content: flex-end;
    text-align: right;
    font-variant-numeric: tabular-nums;
}
.isis-grid--recette-list .isis-grid__head-cell.isis-grid__col-num {
    justify-content: flex-end;
}
/* Un compteur à zéro ne dit rien : il reste muet (G8). La couleur ne se pose que
   lorsqu'il y a effectivement quelque chose à signaler. */
.isis-grid--recette-list .isis-grid__col-num.is-muted   { color: var(--isis-text-muted); }
.isis-grid--recette-list .isis-grid__col-num.is-danger  { color: var(--isis-danger); font-weight: 600; }
.isis-grid--recette-list .isis-grid__col-num.is-warning { color: var(--isis-warning); font-weight: 600; }
.isis-grid--livraisons .isis-grid__row.is-expanded {
    background: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 5%, var(--isis-surface));
}
/* Colonne Actions épinglée à droite (isis-grid--sticky-actions) : toujours visible
   malgré la largeur de la grille. Boutons alignés à GAUCHE, sous le libellé « Actions »
   de l'en-tête (sinon flex-end les collait au bord droit, détachés du libellé). */
.isis-grid--livraisons .isis-grid__col-actions {
    display: flex; gap: 0.15rem; align-items: center; justify-content: flex-start; flex-wrap: nowrap;
}
/* Le fond de la cellule épinglée suit l'état de la ligne (survol / dépliée) pour
   éviter un aplat blanc qui trancherait sur la ligne colorée. */
.isis-grid--livraisons .isis-grid__row:hover .isis-grid__col-actions {
    background: var(--isis-surface-alt);
}
.isis-grid--livraisons .isis-grid__row.is-expanded .isis-grid__col-actions {
    background: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 5%, var(--isis-surface));
}
.isis-tache-detail__actions {
    display: flex; flex-wrap: wrap; gap: 0.4rem;
    padding-bottom: 0.5rem; border-bottom: 1px solid var(--isis-border);
}
/* Neutralise le margin-left:auto hérité (sinon les boutons se dispersent sur la largeur). */
.isis-tache-detail__actions .isis-tache-card__add-btn { margin-left: 0; }

/* S0 — éditeur d'allocation (dialog) */
.isis-alloc-editor { display: flex; flex-direction: column; gap: 0.15rem; }
.isis-alloc-editor__head,
.isis-alloc-editor__row {
    display: grid; grid-template-columns: minmax(160px, 1fr) 6rem 6rem 7rem;
    gap: 0.5rem; align-items: center; padding: 0.3rem 0.2rem;
}
.isis-alloc-editor__head {
    font-size: 0.72rem; font-weight: 600; text-transform: uppercase;
    color: var(--isis-text-muted); border-bottom: 1px solid var(--isis-border);
}
.isis-alloc-editor__row { border-bottom: 1px solid var(--isis-surface-alt); }

/* S0 — readout (champ calculé en lecture seule, ex: Total HT) */
.isis-form-linear__readout {
    display: flex; align-items: center; min-height: 38px;
    padding: 0 0.6rem; border-radius: var(--isis-radius-sm);
    background: var(--isis-surface-alt); font-variant-numeric: tabular-nums;
    font-weight: 600; color: var(--isis-text);
}

/* Dots workflow commande (cf. EventDotClass dans CommandeDetail.razor) —
   nommage aligné sur devis-wf-evt-* / ged-evt-*. */
.isis-audit-trail__dot.commande-wf-evt-created   { background: #f1f5f9; color: #475569; }
.isis-audit-trail__dot.commande-wf-evt-validated { background: var(--isis-accent-soft); color: var(--isis-accent); }
.isis-audit-trail__dot.commande-wf-evt-started   { background: var(--isis-mod-gesproj-soft); color: var(--isis-mod-gesproj); }
.isis-audit-trail__dot.commande-wf-evt-closed    { background: var(--isis-success-soft); color: var(--isis-success); }
.isis-audit-trail__dot.commande-wf-evt-reopened  { background: var(--isis-accent-soft); color: var(--isis-accent); }
.isis-audit-trail__dot.commande-wf-evt-cancelled { background: var(--isis-danger-soft); color: var(--isis-danger); }
.isis-audit-trail__dot.commande-wf-evt-suivi     { background: #eef2ff; color: #4338ca; }

/* Variante "comment" simple pour la timeline commentaires (commande / devis). */
.isis-audit-trail__dot.is-comment { background: var(--isis-mod-gesproj-soft); color: var(--isis-mod-gesproj); }

/* Texte atténué dans une colonne de grille — pour valeurs vides ("—") ou état
   désactivé. Utilisé hors des colonnes spécialisées (email/phone/etc.). */
.isis-grid__col-muted { color: var(--isis-text-muted); }
/* Colonne « échéance proche » : une date qui va tomber doit se voir sans être lue. */
.isis-grid__col-warm {
    color: var(--isis-accent-strong);
    font-weight: 600;
}
/* Colonne « Partenaires » : 1 ou 2 pastilles compactes (COT / ST) */
.isis-grid__col-partners {
    display: flex;
    align-items: center;
    gap: 0.3rem;
    flex-wrap: wrap;
}
.isis-grid__partner-chip {
    display: inline-block;
    padding: 0.05rem 0.35rem;
    font-size: 0.7rem;
    font-weight: 600;
    border-radius: 4px;
    font-variant-numeric: tabular-nums;
    border: 1px solid var(--isis-border);
}
.isis-grid__partner-chip.is-cotraitant {
    background: var(--isis-accent-soft);
    color: var(--isis-accent);
}
/* Sous-traitant : neutre (cf. note ribbon — pas un état d'alerte, et bg warning
   donnait 2.86:1 sur texte warning, échec AA). */
.isis-grid__partner-chip.is-soustraitant {
    background: var(--isis-surface-alt);
    color: var(--isis-text);
}

/* Mini-pastille « apporté par X » sur les lignes de devis dont le provider
   est un participant (P2 cotraitants — DevisDetail items + DevisCostingTab).
   Le chip est inline-flex avec un strong interne (badge COT/ST) ; line-height
   explicite + max-height + padding réduit pour ne pas étirer la row du
   tableau au-delà de la hauteur typographique de la description. */
.isis-devis-items__provider-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    margin-left: 0.5rem;
    padding: 0 0.4rem;
    height: 18px;
    line-height: 1;
    font-size: 0.68rem;
    border-radius: 4px;
    border: 1px solid var(--isis-border);
    vertical-align: middle;
    white-space: nowrap;
}
.isis-devis-items__provider-chip strong {
    display: inline-flex;
    align-items: center;
    height: 13px;
    font-size: 0.58rem;
    font-weight: 600;
    line-height: 1;
    letter-spacing: 0.04em;
    padding: 0 0.25rem;
    border-radius: 3px;
}
.isis-devis-items__provider-chip.is-cotraitant {
    background: var(--isis-accent-soft);
    color: var(--isis-accent);
}
.isis-devis-items__provider-chip.is-cotraitant strong {
    background: var(--isis-accent);
    color: var(--isis-surface);
}
.isis-devis-items__provider-chip.is-soustraitant {
    background: var(--isis-surface-alt);
    color: var(--isis-text);
}
.isis-devis-items__provider-chip.is-soustraitant strong {
    background: var(--isis-text-muted);
    color: var(--isis-surface);
}

/* Section « Marge par participant » de l'onglet Coût de revient (P2 cotraitants).
   flex-shrink:0 pour rester collée au bas du panneau --footed (le tableau du
   coût de revient scrolle au-dessus). */
.isis-costing-by-provider {
    margin-top: 1.25rem;
    padding-top: 1rem;
    border-top: 1px solid var(--isis-border);
    flex-shrink: 0;
}
.isis-costing-by-provider__title {
    font-size: 0.72rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--isis-text-soft);
    margin: 0 0 0.6rem;
}
.isis-costing-by-provider__table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.82rem;
}
.isis-costing-by-provider__table th {
    text-align: left;
    font-size: 0.68rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--isis-text-muted);
    padding: 0.3rem 0.5rem;
    border-bottom: 1px solid var(--isis-border);
}
.isis-costing-by-provider__table td {
    padding: 0.4rem 0.5rem;
    border-bottom: 1px solid var(--isis-border-soft);
}
.isis-costing-by-provider__table tr:last-child td { border-bottom: none; }

/* Liste participants compacte dans le sidepanel de DevisListPage */
.isis-side-participants {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
}
.isis-side-participants__row {
    display: grid;
    /* Première colonne assez large pour « Sous-traitant » en toutes lettres. */
    grid-template-columns: 110px 1fr auto;
    gap: 0.5rem;
    align-items: center;
    padding: 0.3rem 0.4rem;
    border: 1px solid var(--isis-border-soft);
    border-radius: 5px;
    background: var(--isis-surface);
    font-size: 0.8rem;
}
.isis-side-participants__name {
    color: var(--isis-text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.isis-side-participants__share {
    font-weight: 600;
    color: var(--isis-text-muted);
    font-variant-numeric: tabular-nums;
    font-size: 0.74rem;
}

/* ============================================================================
   Sidepanel intelligent — chantier 2026-05-26 (DevisListPage pilote)
   ----------------------------------------------------------------------------
   11 améliorations livrées :
   #1 actions contextuelles par statut, #2 status enrichi (étape + validateur
   + ancienneté), #3 micro-KPIs contextuels (marge / jauge validité / commande),
   #4 montant HT mono large, #5 PJ GED, #6 tiers cliquable + stats, #7
   hiérarchie sections (--metier vs neutre), #8 switcher saillant, #9 empty
   state enrichi, #10 aperçu lignes top 3, #11 layout adaptatif (multi-middle).
   ============================================================================ */

/* #4 — Bloc identité refondu : numéro caption + titre H3 + montant mono large */
.isis-side-head {
    display: flex;
    flex-direction: column;
    gap: 0.55rem;
}
.isis-side-head__caption {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    font-size: 0.72rem;
    color: var(--isis-text-soft);
    letter-spacing: 0.02em;
}
.isis-side-head__num {
    font-family: var(--isis-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
    font-weight: 600;
    color: var(--isis-text);
    font-variant-numeric: tabular-nums;
    letter-spacing: -0.01em;
}
.isis-side-head__title {
    font-size: 1.05rem;
    font-weight: 600;
    color: var(--isis-text);
    line-height: 1.25;
    margin: 0;
    /* 2 lignes max avec ellipsis (long titres devis) */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* #2 — Status enrichi : pill + métadonnées chaîne + ancienneté */
.isis-side-status {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.35rem;
    font-size: 0.75rem;
    color: var(--isis-text-soft);
}
.isis-side-status__meta {
    color: var(--isis-text-muted);
}
.isis-side-status__age {
    color: var(--isis-text-muted);
    font-variant-numeric: tabular-nums;
}
.isis-side-status__age.is-urgent {
    color: var(--isis-danger);
    font-weight: 600;
}

/* #4 — Montant 2 colonnes : HT/TTC empilés (col gauche) + Marge promue (col droite).
   La marge n'apparaît qu'avec la classe .has-margin posée par le markup. */
.isis-side-amount {
    display: grid;
    grid-template-columns: 1fr;
    gap: 0.75rem;
    padding: 0.5rem 0;
}
.isis-side-amount.has-margin {
    grid-template-columns: 1fr auto;
    align-items: center;
}
.isis-side-amount__totals {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
}
.isis-side-amount__primary,
.isis-side-amount__secondary {
    display: flex;
    align-items: baseline;
    gap: 0.4rem;
}
.isis-side-amount__value {
    font-family: var(--isis-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
    font-size: 1.55rem;
    font-weight: 700;
    color: var(--isis-text);
    line-height: 1.1;
    letter-spacing: -0.015em;
    font-variant-numeric: tabular-nums;
}
.isis-side-amount__unit {
    font-size: 0.72rem;
    font-weight: 600;
    color: var(--isis-text-soft);
    letter-spacing: 0.05em;
    text-transform: uppercase;
}
.isis-side-amount__ttc-value {
    font-family: var(--isis-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
    font-size: 0.95rem;
    font-weight: 500;
    color: var(--isis-text-muted);
    font-variant-numeric: tabular-nums;
}
.isis-side-amount__ttc-unit {
    font-size: 0.68rem;
    font-weight: 600;
    color: var(--isis-text-muted);
    letter-spacing: 0.05em;
    text-transform: uppercase;
}

/* Bloc Marge inline dans isis-side-amount (col droite). Hérite des classes
   is-margin-on-target / is-margin-below-target / is-margin-below-floor pour
   colorer la bordure gauche + valeur. */
.isis-side-amount__margin {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    text-align: right;
    padding: 0.35rem 0.6rem 0.35rem 0.7rem;
    border: 1px solid var(--isis-border);
    box-sizing: border-box;
    background: var(--isis-surface-alt);
    border-radius: 4px;
    min-width: 90px;
}
.isis-side-amount__margin-label {
    font-size: 0.68rem;
    font-weight: 600;
    color: var(--isis-text-muted);
    letter-spacing: 0.04em;
    text-transform: uppercase;
}
.isis-side-amount__margin-value {
    font-family: var(--isis-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
    font-size: 1.1rem;
    font-weight: 700;
    line-height: 1.2;
    font-variant-numeric: tabular-nums;
    color: var(--isis-text);
}
.isis-side-amount__margin-hint {
    font-size: 0.7rem;
    color: var(--isis-text-muted);
    font-style: italic;
}
.isis-side-amount__margin.is-margin-on-target {
    border-color: var(--isis-success);
}
.isis-side-amount__margin.is-margin-on-target .isis-side-amount__margin-value {
    color: var(--isis-success);
}
.isis-side-amount__margin.is-margin-below-target {
    border-color: var(--isis-warning);
}
.isis-side-amount__margin.is-margin-below-target .isis-side-amount__margin-value {
    color: var(--isis-warning);
}
.isis-side-amount__margin.is-margin-below-floor {
    border-color: var(--isis-danger);
}
.isis-side-amount__margin.is-margin-below-floor .isis-side-amount__margin-value {
    color: var(--isis-danger);
}

/* Bloc Validité fusionné sous le client : date + barre fine + % sur 1 ligne.
   Visible uniquement quand statut = SENT (compte à rebours pertinent). */
.isis-side-validity {
    display: flex;
    align-items: center;
    gap: 0.55rem;
    padding: 0.35rem 0.55rem;
    margin: 0.3rem 0;
    background: var(--isis-surface-alt);
    border-radius: 4px;
    border: 1px solid var(--isis-border);
    box-sizing: border-box;
    font-size: 0.78rem;
    flex-wrap: wrap;
}
.isis-side-validity__label {
    font-weight: 600;
    color: var(--isis-text-muted);
    text-transform: uppercase;
    font-size: 0.68rem;
    letter-spacing: 0.04em;
}
.isis-side-validity__date {
    font-variant-numeric: tabular-nums;
    color: var(--isis-text);
    font-weight: 500;
}
.isis-side-validity__bar {
    flex: 1 1 80px;
    min-width: 70px;
    height: 5px;
    background: var(--isis-border);
    border-radius: 3px;
    overflow: hidden;
}
.isis-side-validity__bar-fill {
    height: 100%;
    background: var(--isis-success);
    transition: width 200ms ease;
}
.isis-side-validity__pct {
    font-variant-numeric: tabular-nums;
    color: var(--isis-text-muted);
    font-size: 0.72rem;
    white-space: nowrap;
}
.isis-side-validity.is-validity-ok       { border-left-color: var(--isis-success); }
.isis-side-validity.is-validity-ok       .isis-side-validity__bar-fill { background: var(--isis-success); }
.isis-side-validity.is-validity-warn     { border-left-color: var(--isis-warning); }
.isis-side-validity.is-validity-warn     .isis-side-validity__bar-fill { background: var(--isis-warning); }
.isis-side-validity.is-validity-expired  { border-left-color: var(--isis-danger); }
.isis-side-validity.is-validity-expired  .isis-side-validity__bar-fill { background: var(--isis-danger); }

/* #6 — Tiers cliquable + mini-stats */
.isis-side-tiers {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
}
.isis-side-tiers__link {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    background: none;
    border: none;
    padding: 0;
    cursor: pointer;
    font-size: 0.85rem;
    color: var(--isis-current-mod, var(--isis-accent));
    text-align: left;
    font-weight: 500;
    transition: color 0.12s;
}
.isis-side-tiers__link:hover {
    text-decoration: underline;
}
.isis-side-tiers__link:focus-visible {
    text-decoration: underline;
    outline: 2px solid var(--isis-current-mod, var(--isis-accent));
    outline-offset: 2px;
    border-radius: 2px;
}
.isis-side-tiers__stats {
    font-size: 0.72rem;
    color: var(--isis-text-muted);
    margin-left: 1.05rem;
    font-variant-numeric: tabular-nums;
}

/* Dates compactes (sub-line) */
.isis-side-dates {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    font-size: 0.74rem;
    color: var(--isis-text-soft);
    font-variant-numeric: tabular-nums;
}
.isis-side-dates__sep {
    opacity: 0.5;
}

/* ============================================================================
   .isis-side-fact — fait compact d'un sidepanel : icône + libellé + valeur.
   Densité de .isis-side-billing__row. A remplacé (chantier de convergence des
   sidepanels, 2026-09-01) la famille legacy « gesmaff-side », supprimée depuis,
   dont le libellé en capitales AU-DESSUS de la valeur doublait la hauteur du
   panneau.
   ============================================================================ */
.isis-side-facts {
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
    list-style: none;
    margin: 0;
    padding: 0;
}
.isis-side-fact {
    display: grid;
    grid-template-columns: 16px 1fr auto;
    gap: 0.45rem;
    align-items: baseline;
    font-size: 0.78rem;
}
/* `.isis-detail-split__top` (l. 6449) n'est NI flex NI grid : il ne pose aucun `gap`,
   et chaque bloc du `__top` doit donc porter sa propre séparation. `.isis-side-amount`
   le fait (padding 0.5rem 0), `.isis-side-microkpis` aussi (margin-top + filet),
   `.isis-side-iban` aussi (margin-top 0.75rem) — mais `.isis-side-facts` déclare
   `margin: 0` ET `padding: 0`. Quand la liste de faits suit IMMÉDIATEMENT l'en-tête,
   sans bloc intercalaire, les deux se touchent donc à 0 px et le premier fait se lit
   comme une ligne de plus de l'en-tête (mesuré au navigateur sur 8 des 14 écrans du
   chantier de convergence 2026-09-01). L'ancienne famille legacy posait 16 px d'écart
   de boîtes à cet endroit (son conteneur déclarait `gap: 1rem`), auxquels s'ajoutaient
   le `padding-bottom: 0.85rem` et le filet de son en-tête — mais ce n'est PAS la
   référence retenue : la valeur ci-dessous s'aligne sur le vocabulaire cible, à savoir
   le `margin-top` de `.isis-side-iban`, qui occupe exactement la même position sur
   /gescompta/banques et s'y lit bien.
   Scopé à l'ADJACENCE cassée, volontairement : un `> * + *` générique sur `__top`
   doublerait la séparation des blocs qui la portent déjà, et toucherait le modèle de
   référence. `.isis-side-facts` n'est utilisée que par les écrans de ce chantier. */
.isis-detail-split__top > .isis-side-head + .isis-side-facts { margin-top: 0.75rem; }
/* Même défaut, deux autres adjacences, mesurées par le même comparateur.
   (a) `.isis-side-microkpis` porte bien un `padding-top` mais AUCUN `padding-bottom` :
       ses tuiles bordées touchaient le premier fait (marchés, engagements).
   (b) L'écran des échéances de calibration n'a pas d'`<IsisSidePanelActions>` mais des
       `IsisButton` nus : sans `.isis-side-actions`, il n'héritait pas non plus de son
       `margin-top: 0.85rem`, et le bouton se collait au dernier fait. D'où cette
       valeur-là précisément, pour que cet écran se lise comme les treize autres.
   `.isis-side-facts` est présente dans les DEUX sélecteurs, et c'est délibéré : cette
   classe n'existe que sur les 14 écrans de ce chantier (vérifié `grep -rl` sur src/),
   alors que `.isis-side-microkpis` sert aussi 6 écrans hors périmètre (commandes,
   devis, factures émises et reçues, avoirs, absences). La mentionner BORNE la règle.
   Ne jamais retirer `.isis-side-facts` de ces sélecteurs. */
.isis-detail-split__top > .isis-side-microkpis + .isis-side-facts { margin-top: 0.75rem; }
.isis-detail-split__top > .isis-side-facts + .isis-action-btn { margin-top: 0.85rem; }
/* (c) Cas voisin mais pas identique : `.isis-side-iban` (/gescompta/banques) est une
   carte BORDÉE ET FONDÉE. Son `padding: 0.75rem 0.85rem` est à l'intérieur, donc la
   frontière visible — sa bordure — arrivait à ras de la liste de faits. Il y avait
   bien une séparation dessinée, mais zéro air : arbitrage 2026-09-01, ces quatorze
   panneaux doivent respirer au même rythme, un écran ne reste pas à zéro au motif que
   sa frontière est tracée plutôt que vide. Même valeur que (a). */
.isis-detail-split__top > .isis-side-iban + .isis-side-facts { margin-top: 0.75rem; }
.isis-side-fact__label { color: var(--isis-text-soft); }
.isis-side-fact__value {
    color: var(--isis-text);
    text-align: right;
    font-variant-numeric: tabular-nums;
    overflow-wrap: anywhere;
}
/* Valeur longue (raison sociale, adresse, intitulé) : elle passe sous le libellé
   plutôt que d'écraser la colonne de droite. */
.isis-side-fact--stacked { grid-template-columns: 16px 1fr; }
.isis-side-fact--stacked .isis-side-fact__value { text-align: left; grid-column: 2; }
/* Complément secondaire sous la valeur (ex. responsable sous l'utilisateur). */
.isis-side-fact__sub {
    display: block;
    font-size: 0.72rem;
    color: var(--isis-text-muted);
}

/* #3 — Micro-KPIs contextuels par statut (marge / validité / commande) */
.isis-side-microkpis {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(92px, 1fr));
    gap: 0.4rem;
    margin-top: 0.7rem;
    padding-top: 0.7rem;
    border-top: 1px dashed var(--isis-border);
}
.isis-side-microkpi {
    display: flex;
    flex-direction: column;
    gap: 0.1rem;
    padding: 0.3rem 0.45rem;
    background: var(--isis-surface);
    /* Filet périmétrique 1px (DESIGN.md §121/§124) : la couleur d'état porte sur
       TOUT le contour, plus de barre gauche 3px. */
    border: 1px solid var(--isis-border);
    border-radius: 5px;
    transition: border-color 0.12s;
}
.isis-side-microkpi__label {
    font-size: 0.62rem;
    color: var(--isis-text-soft);
    letter-spacing: 0.03em;
    text-transform: uppercase;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.isis-side-microkpi__value {
    font-family: var(--isis-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
    font-size: 0.85rem;
    font-weight: 700;
    color: var(--isis-text);
    line-height: 1.15;
    font-variant-numeric: tabular-nums;
    letter-spacing: -0.01em;
}
.isis-side-microkpi__hint {
    font-size: 0.6rem;
    color: var(--isis-text-muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.isis-side-microkpi__action {
    margin-top: 0.25rem;
    background: none;
    border: none;
    padding: 0;
    cursor: pointer;
    font-size: 0.7rem;
    color: var(--isis-current-mod, var(--isis-accent));
    text-align: left;
    font-weight: 600;
}
.isis-side-microkpi__action:hover { text-decoration: underline; }
.isis-side-microkpi__action:focus-visible {
    outline: 2px solid var(--isis-current-mod, var(--isis-accent));
    outline-offset: 2px;
    border-radius: 3px;
}
.isis-side-microkpi__bar {
    height: 4px;
    background: var(--isis-surface-soft);
    border-radius: 3px;
    overflow: hidden;
    margin: 0.15rem 0 0.1rem;
}
.isis-side-microkpi__bar-fill {
    height: 100%;
    background: var(--isis-current-mod, var(--isis-accent));
    border-radius: 3px;
    transition: width 0.3s ease;
}

/* Variantes sémantiques marge (reprises de MarginClassifier) — réservées
   au pilotage commercial Phases 1-4, ne PAS recycler pour d'autres états. */
.isis-side-microkpi.is-margin-on-target    { border-color: var(--isis-success); }
.isis-side-microkpi.is-margin-on-target    .isis-side-microkpi__bar-fill { background: var(--isis-success); }
.isis-side-microkpi.is-margin-below-target { border-color: var(--isis-warning); }
.isis-side-microkpi.is-margin-below-target .isis-side-microkpi__bar-fill { background: var(--isis-warning); }
.isis-side-microkpi.is-margin-below-floor  { border-color: var(--isis-danger); }
.isis-side-microkpi.is-margin-below-floor  .isis-side-microkpi__bar-fill { background: var(--isis-danger); }

/* Variantes sémantiques distinctes pour la jauge de validité (devis SENT) — fix audit 2026-05-26 #3
   pour ne pas polluer la sémantique commerciale de MarginClassifier. */
.isis-side-microkpi.is-validity-ok       { border-color: var(--isis-success); }
.isis-side-microkpi.is-validity-ok       .isis-side-microkpi__bar-fill { background: var(--isis-success); }
.isis-side-microkpi.is-validity-warn     { border-color: var(--isis-warning); }
.isis-side-microkpi.is-validity-warn     .isis-side-microkpi__bar-fill { background: var(--isis-warning); }
.isis-side-microkpi.is-validity-expired  { border-color: var(--isis-danger); }
.isis-side-microkpi.is-validity-expired  .isis-side-microkpi__bar-fill { background: var(--isis-danger); }

/* Variante pour la carte "Commande convertie" — signal positif (existence du lien) */
.isis-side-microkpi.is-converted { border-color: var(--isis-success); }

/* Classe utilitaire — icône décorative atténuée (extraction styles inline audit #7) */
.isis-side-icon--muted {
    font-size: 14px;
    opacity: 0.5;
}

/* #1 — Actions contextuelles par statut (primaire + secondaires inline) */
.isis-side-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
    margin-top: 0.85rem;
    padding-top: 0.85rem;
    border-top: 1px dashed var(--isis-border);
    align-items: center;
}

/* #5 — Pièces jointes GED (liste compacte 3 derniers) */
.isis-side-attachments {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
}
.isis-side-attachments__row {
    display: grid;
    grid-template-columns: auto 1fr auto;
    gap: 0.5rem;
    align-items: center;
    padding: 0.3rem 0.45rem;
    border: 1px solid var(--isis-border-soft);
    border-radius: 5px;
    background: var(--isis-surface);
    font-size: 0.78rem;
}
.isis-side-attachments__name {
    color: var(--isis-text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.isis-side-attachments__size {
    font-size: 0.7rem;
    color: var(--isis-text-muted);
    font-variant-numeric: tabular-nums;
}

/* #10 — Aperçu lignes (top 3 + bouton voir tout) */
.isis-side-lines {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
}
.isis-side-lines__row {
    display: grid;
    grid-template-columns: auto 1fr auto auto;
    gap: 0.45rem;
    align-items: center;
    padding: 0.3rem 0.45rem;
    border-bottom: 1px solid var(--isis-border-soft);
    font-size: 0.78rem;
}
.isis-side-lines__row:last-child { border-bottom: none; }
.isis-side-lines__pos {
    font-family: var(--isis-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
    font-size: 0.7rem;
    color: var(--isis-text-soft);
    font-variant-numeric: tabular-nums;
    min-width: 18px;
    text-align: right;
}
.isis-side-lines__desc {
    color: var(--isis-text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.isis-side-lines__qty {
    font-size: 0.7rem;
    color: var(--isis-text-muted);
    font-variant-numeric: tabular-nums;
}
.isis-side-lines__total {
    font-family: var(--isis-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
    font-size: 0.76rem;
    font-weight: 600;
    color: var(--isis-text);
    font-variant-numeric: tabular-nums;
    text-align: right;
}
.isis-side-lines__more {
    background: none;
    border: 1px dashed var(--isis-border);
    border-radius: 4px;
    padding: 0.3rem 0.6rem;
    margin-top: 0.4rem;
    width: 100%;
    cursor: pointer;
    font-size: 0.73rem;
    color: var(--isis-current-mod, var(--isis-accent));
    transition: background 0.12s, border-color 0.12s;
}
.isis-side-lines__more:hover,
.isis-side-lines__more:focus-visible {
    background: var(--isis-current-mod-soft, var(--isis-surface-alt));
    border-color: var(--isis-current-mod, var(--isis-accent));
    outline: none;
}

/* #7 — Hiérarchie sections : variante --metier (accent module) vs neutre */
.isis-detail-split__title--metier {
    color: var(--isis-current-mod, var(--isis-accent));
    border: 1px solid var(--isis-current-mod, var(--isis-accent));
    box-sizing: border-box;
    padding-left: 0.4rem;
}
.isis-detail-split__title--metier .rzi {
    color: var(--isis-current-mod, var(--isis-accent));
    opacity: 1;
}
.isis-detail-split__count {
    margin-left: auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 20px;
    height: 18px;
    padding: 0 6px;
    border-radius: 9px;
    background: var(--isis-current-mod-soft, var(--isis-surface-alt));
    color: var(--isis-current-mod, var(--isis-accent));
    font-size: 0.68rem;
    font-weight: 700;
    line-height: 1;
}

/* #11 — Layout adaptatif : multiples sections __middle peuvent coexister
   (PJ + Participants + Lignes). Le cap max-height: 35% par section était
   trop strict, on remplace par flex-shrink: 0 (taille naturelle) ; le scroll
   global du sidepanel (.isis-side-switcher__body) absorbe le débord. */
.isis-detail-split__middle {
    flex: 0 0 auto;
    max-height: none;
}
    text-align: right;
    font-variant-numeric: tabular-nums;
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    justify-content: center;
    line-height: 1.2;
}
.isis-grid--devis-list .isis-grid__col-num.is-muted {
    color: var(--isis-text-soft);
}
.isis-grid--devis-list .isis-grid__col-num.is-positive {
    color: var(--isis-success);    /* token (était #16a34a — DESIGN.md §2 palette --isis-* uniquement) */
    font-weight: 600;
}
.isis-grid--devis-list .isis-grid__col-num.is-negative {
    color: var(--isis-danger);     /* token (était #c62828) */
    font-weight: 600;
}
.isis-grid__col-num__sub {
    display: block;            /* sous-valeur sur sa propre ligne (sinon collée au montant) */
    font-size: 0.72rem;
    font-weight: 500;
    opacity: 0.75;
    margin-top: 1px;
}
.isis-cost-symbol {
    color: var(--isis-text-muted);
    font-family: var(--isis-font-mono, ui-monospace, monospace);
    font-size: 0.78rem;
}
.isis-cost-tree {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    color: var(--isis-text);
}
.isis-cost-tree__indent {
    color: var(--isis-text-soft);
    opacity: 0.6;
    font-size: 0.85rem;
}
.isis-cost-tree__label { font-weight: 500; }

.isis-csv-input { margin-top: 0.3rem; font-size: 0.85rem; }
.isis-csv-report {
    margin-top: 0.7rem;
    padding: 0.7rem 0.9rem;
    background: var(--isis-surface-alt);
    border: 1px solid var(--isis-border);
    border-radius: 6px;
}
.isis-csv-report__head { display: flex; align-items: center; gap: 0.5rem; margin-bottom: 0.4rem; }
.isis-csv-report__counts { display: flex; gap: 1.2rem; font-size: 0.82rem; color: var(--isis-text); }
.isis-csv-report__counts .is-error { color: #c62828; }
.isis-csv-report__details { margin-top: 0.5rem; font-size: 0.78rem; }
.isis-csv-report__details summary { cursor: pointer; color: var(--isis-text-muted); }
.isis-csv-report__details ul { margin: 0.4rem 0 0 1.2rem; color: var(--isis-text-muted); line-height: 1.5; }

/* ── Import bulk articles (ArticleBulkImportDialog) ─────────────────────── */
.isis-bulk-import { min-width: 860px; max-width: 1120px; }
.isis-bulk-import__file {
    display: flex; align-items: center; gap: 0.6rem;
    padding: 0.5rem 0.7rem;
    background: var(--isis-surface-alt); border-radius: 4px;
}
.isis-bulk-import__file-meta { flex: 1; }
.isis-bulk-import__file-name { font-weight: 500; font-size: 0.85rem; }
.isis-bulk-import__file-size { font-size: 0.72rem; color: var(--isis-text-soft); }

.isis-bulk-import__section-sub {
    font-size: 0.8rem; color: var(--isis-text-muted);
    margin: 0.1rem 0 0.6rem;
}
.isis-bulk-import__muted { color: var(--isis-text-muted); }

.isis-bulk-import__download {
    display: inline-flex; align-items: center; gap: 0.4rem;
    padding: 0.45rem 0.7rem;
    background: color-mix(in srgb, var(--isis-current-mod) 8%, transparent);
    border: 1px solid color-mix(in srgb, var(--isis-current-mod) 30%, transparent);
    border-radius: 4px; font-size: 0.85rem; color: var(--isis-current-mod);
    text-decoration: none; font-weight: 500;
}
.isis-bulk-import__download:hover { background: color-mix(in srgb, var(--isis-current-mod) 14%, transparent); }
.isis-bulk-import__download:focus-visible {
    outline: 2px solid var(--isis-current-mod); outline-offset: 2px;
}

.isis-bulk-import__counters {
    display: flex; gap: 0.6rem; flex-wrap: wrap;
    margin: 0.5rem 0 0.4rem;
}
.isis-bulk-import__counters-detail {
    display: flex; gap: 0.8rem; flex-wrap: wrap;
    margin: 0 0 0.6rem;
    font-size: 0.78rem; color: var(--isis-text-muted);
}
.isis-bulk-import__kpi {
    font-size: 0.82rem; padding: 0.25rem 0.6rem;
    background: var(--isis-surface-alt);
    border-radius: 4px; color: var(--isis-text);
}
.isis-bulk-import__kpi.is-warn { background: color-mix(in srgb, var(--isis-warning) 12%, transparent); }
.isis-bulk-import__kpi.is-create strong { color: var(--isis-success); }
.isis-bulk-import__kpi.is-update strong { color: var(--isis-current-mod); }

.isis-bulk-import__td-price {
    font-family: var(--isis-font-mono, ui-monospace, monospace);
    font-variant-numeric: tabular-nums;
    text-align: right;
}

.isis-bulk-import__badge-mini {
    display: inline-block; margin-left: 0.4rem;
    padding: 0.05rem 0.35rem;
    font-size: 0.68rem; font-weight: 600;
    text-transform: uppercase; letter-spacing: 0.03em;
    background: color-mix(in srgb, var(--isis-current-mod) 18%, transparent);
    color: var(--isis-current-mod);
    border-radius: 2px;
}

.isis-bulk-import__table {
    max-height: 340px; overflow: auto;
    border: 1px solid var(--isis-border); border-radius: 4px;
    margin-top: 0.4rem;
}
.isis-bulk-import__table table {
    width: 100%; border-collapse: collapse;
    font-size: 0.8rem;
}
.isis-bulk-import__table thead th {
    position: sticky; top: 0; z-index: 1;
    background: var(--isis-surface-alt);
    text-align: left; padding: 0.4rem 0.6rem;
    font-weight: 600; color: var(--isis-text-muted);
    border-bottom: 1px solid var(--isis-border);
    text-transform: uppercase; font-size: 0.7rem; letter-spacing: 0.04em;
}
.isis-bulk-import__table tbody td {
    padding: 0.35rem 0.6rem;
    border-bottom: 1px solid var(--isis-border-soft, var(--isis-border));
    vertical-align: top;
}
.isis-bulk-import__row.is-skip td { opacity: 0.7; }
.isis-bulk-import__td-line, .isis-bulk-import__td-code {
    font-family: var(--isis-font-mono, ui-monospace, monospace);
    font-variant-numeric: tabular-nums;
}
.isis-bulk-import__td-errors {
    color: var(--isis-danger); font-size: 0.75rem; max-width: 200px;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.isis-bulk-import__action {
    display: inline-block; padding: 0.1rem 0.45rem;
    border-radius: 3px; font-size: 0.72rem; font-weight: 700;
    text-transform: uppercase; letter-spacing: 0.03em;
}
/* Badges graphiques (WCAG 1.4.11 = 3:1 objet). Fond à 28 % pour pousser le ratio
   texte au-delà de 4.5:1 (1.4.3) sur `is-create` où le contraste était marginal. */
.isis-bulk-import__action.is-create {
    background: color-mix(in srgb, var(--isis-success) 28%, transparent);
    color: var(--isis-success);
}
.isis-bulk-import__action.is-update {
    background: color-mix(in srgb, var(--isis-current-mod) 28%, transparent);
    color: var(--isis-current-mod);
}
/* « Ignorer » est neutre (ligne non importée sans conséquence), pas un avertissement.
   On évite l'ambre (réservé aux états qui demandent attention de l'utilisateur). */
.isis-bulk-import__action.is-skip {
    background: var(--isis-surface-alt);
    color: var(--isis-text-muted);
}

.isis-bulk-import__report {
    padding: 0.9rem 1rem;
    background: var(--isis-surface-alt);
    border: 1px solid var(--isis-border);
    border-radius: 6px;
}
.isis-bulk-import__report-head {
    display: flex; align-items: center; gap: 0.5rem;
    font-size: 1rem; margin-bottom: 0.7rem;
}
.isis-bulk-import__report-grid {
    display: grid; grid-template-columns: 1fr 1fr; gap: 0.5rem 1rem;
    font-size: 0.86rem;
}
.isis-bulk-import__errors { margin-top: 0.7rem; font-size: 0.8rem; }
.isis-bulk-import__errors summary { cursor: pointer; color: var(--isis-danger); }
.isis-bulk-import__errors summary:focus-visible {
    outline: 2px solid var(--isis-current-mod);
    outline-offset: 2px; border-radius: 2px;
}
.isis-bulk-import__errors ul { margin: 0.4rem 0 0 1.2rem; color: var(--isis-text-muted); line-height: 1.5; }

/* Wizard catalogue (CatalogueBulkImportDialog) — réutilise la base bulk-import.
   Le tableau a des dropdowns par ligne donc plus de hauteur que la version
   articles. La toolbar wizard (Tout cocher / Tout décocher / filtre) vit dans
   `.isis-bulk-import__toolbar`. */
.isis-cat-import { min-width: 960px; max-width: 1280px; }
.isis-cat-import__table { max-height: 460px; }
.isis-cat-import__table tbody td { vertical-align: middle; padding: 0.5rem 0.6rem; }
.isis-cat-import__table input[type="checkbox"] { width: 16px; height: 16px; cursor: pointer; }
.isis-cat-import__table input[type="checkbox"]:disabled { cursor: not-allowed; opacity: 0.4; }
.isis-cat-import__table .rz-dropdown { font-size: 0.8rem; }

/* Les erreurs sont actionnables (l'user doit savoir QUOI corriger) — on autorise
   le wrap sur 2 lignes max pour éviter une troncature `…` illisible.
   Surcharge la version globale `.isis-bulk-import__td-errors` (text-overflow ellipsis). */
.isis-cat-import__table .isis-bulk-import__td-errors {
    white-space: normal;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    max-width: 240px;
}

/* Wizard référentiel d'articles (ReferentielArticleImportDialog) — même base bulk-import,
   mais l'unité d'arbitrage est le SERVICE (≈14 lignes), pas l'article (≈122) : le tableau
   principal est court, et le détail des lignes vit dans un `<details>` replié. */
.isis-ref-import__th-check { width: 40px; }
.isis-ref-import__family {
    font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.03em;
    font-family: var(--isis-font-sans, inherit);
}
.isis-ref-import__hint { font-size: 0.72rem; margin-top: 0.25rem; max-width: 320px; }
/* Règle fixe (Commun / STT) : verrouillée, mais TOUJOURS importée. On la distingue par un
   ton neutre — surtout pas par l'opacité réduite de `is-skip`, qui signifie « ligne exclue ». */
.isis-ref-import__row--rule td { color: var(--isis-text-muted); }
.isis-ref-import__row--rule strong { color: var(--isis-text); }

/* Notes / erreurs du détail : le texte s'enroule au lieu d'être tronqué en `…`.
   Une troncature dont le texte complet ne vit que dans un `title` est invisible au
   clavier et aux lecteurs d'écran (WCAG 1.3.1) — or une erreur doit dire quoi corriger. */
.isis-ref-import__notes { font-size: 0.75rem; color: var(--isis-text-muted); max-width: 280px; }
.isis-ref-import__notes.is-error { color: var(--isis-danger); }
.isis-ref-import__notes-list { margin: 0; padding-left: 1rem; line-height: 1.4; }
.isis-ref-import__notes-list li { word-break: break-word; }

.isis-ref-import__rows { margin-top: 0.9rem; font-size: 0.82rem; }
.isis-ref-import__rows summary { cursor: pointer; color: var(--isis-current-mod); font-weight: 500; }
.isis-ref-import__rows summary:focus-visible {
    outline: 2px solid var(--isis-current-mod);
    outline-offset: 2px; border-radius: 2px;
}

.isis-bulk-import__alert-list { margin: 0; padding-left: 1.2rem; }

.isis-bulk-import__toolbar {
    display: flex; gap: 0.5rem; flex-wrap: wrap;
    margin: 0.3rem 0 0.5rem;
}

/* Bouton-lien neutre (action discrète sans bg, juste icône + texte) — utile
   dans les barres d'action wizard / sidepanel. */
.isis-link-btn {
    display: inline-flex; align-items: center; gap: 0.3rem;
    padding: 0.3rem 0.5rem; border-radius: 4px;
    background: transparent; border: 1px solid transparent;
    font-size: 0.78rem; color: var(--isis-text-muted);
    cursor: pointer; text-decoration: none;
}
.isis-link-btn:hover {
    background: var(--isis-surface-alt);
    color: var(--isis-text);
}
.isis-link-btn:focus-visible {
    outline: 2px solid var(--isis-current-mod);
    outline-offset: 2px;
}

/* Lien texte inline — utilisé dans les grilles lecture seule (ex. colonne Commande pile Renvoyées). */
.isis-link {
    color: var(--isis-accent);
    text-decoration: underline;
    text-underline-offset: 2px;
}
.isis-link:hover { color: color-mix(in srgb, var(--isis-accent) 80%, black); }
.isis-link:focus-visible {
    outline: 2px solid var(--isis-current-mod, var(--isis-accent));
    outline-offset: 2px;
    border-radius: 2px;
}

/* Toolbar légère au-dessus du tableau de lignes dans DevisDetail (DRAFT only) */
.isis-devis-items__toolbar {
    /* La barre a été relogée hors du dialog (elle coule à gauche, un spacer
       .isis-devis-items__toolbar-grow pousse les options à droite). Pas de
       justify-content:flex-end ici : sans le spacer (cas BPU), il collerait
       les boutons d'ajout à droite. */
    display: flex;
    gap: 0.4rem;
    margin-bottom: 0.6rem;
}
/* Barre d'actions de l'onglet « Lignes » (Éditer / Coût de revient / instantanés) :
   elle, on la justifie à droite — contrairement au composeur d'ajout de lignes. */
.isis-devis-items__toolbar--end {
    justify-content: flex-end;
}

/* ============================================================================
   Onglet « Coût de revient » sur DevisDetail
   ============================================================================ */
.isis-costing-tab { display: flex; flex-direction: column; gap: 0.8rem; padding-top: 0.5rem; }
/* Quand le panneau parent est --footed (chaîne flex pleine hauteur), .isis-costing-tab
   doit lui-même devenir flex column contraint en hauteur. Les 3 cartes (.isis-crv-card,
   dont le conteneur générique n'est PAS flex) s'empilent selon leur hauteur naturelle ;
   c'est donc l'onglet entier qui défile verticalement, pas une carte en particulier. */
.isis-tab-panel--footed > .isis-costing-tab {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    overflow-x: hidden;
}

/* Tableau unique « Coût de revient » : reprend le style .isis-devis-items
   avec modifiers pour les rows ligne / allocation / total. */
.isis-costing-items .isis-costing-row__pos {
    font-family: var(--isis-font-mono, ui-monospace, monospace);
    font-size: 0.75rem;
    color: var(--isis-text-muted);
    margin-right: 0.4rem;
}
.isis-costing-items .isis-costing-row__desc {
    font-weight: 500;
    color: var(--isis-text);
}
.isis-costing-items .isis-costing-row__impose {
    display: block;
    margin-top: 0.15rem;
    font-size: 0.75rem;
    color: var(--isis-text-muted);
    font-variant-numeric: tabular-nums;
}
.isis-costing-items .isis-costing-row__margin.is-positive { color: #16a34a; font-weight: 600; }
.isis-costing-items .isis-costing-row__margin.is-negative { color: #c62828; font-weight: 600; }

/* Classification tri-état Phase 1 (réconciliation coût/prix, migration 0121).
   Cohabite avec is-positive/is-negative ci-dessus tant qu'il reste des appelants
   binaires. Cibler aussi la sous-table .isis-costing-by-provider.              */
.isis-costing-items .isis-costing-row__margin.is-on-target,
.isis-costing-by-provider .isis-costing-row__margin.is-on-target {
    color: var(--isis-success, #16a34a); font-weight: 600;
}
.isis-costing-items .isis-costing-row__margin.is-below-target,
.isis-costing-by-provider .isis-costing-row__margin.is-below-target {
    color: var(--isis-warning, #d97706); font-weight: 600;
}
.isis-costing-items .isis-costing-row__margin.is-below-floor,
.isis-costing-by-provider .isis-costing-row__margin.is-below-floor {
    color: var(--isis-danger, #c62828); font-weight: 700;
}
.isis-costing-items .isis-costing-row__margin.is-no-cost,
.isis-costing-by-provider .isis-costing-row__margin.is-no-cost {
    color: var(--isis-text-muted, #94a3b8); font-weight: 500;
}
.isis-costing-items .isis-costing-row__margin.is-unclassified,
.isis-costing-by-provider .isis-costing-row__margin.is-unclassified {
    color: var(--isis-text, #1f2328); font-weight: 600;
}

/* Bandeau marge globale en tête de l'onglet Coût de revient.
   flex-shrink: 0 → reste fixe en haut, le tableau scrolle en dessous.          */
.isis-margin-banner {
    flex-shrink: 0;
    display: flex;
    align-items: center;
    gap: 0.6rem;
    padding: 0.55rem 0.85rem;
    border-radius: 8px;
    border: 1px solid var(--isis-border, var(--isis-border));
    box-sizing: border-box;
    background: var(--isis-surface-soft);
    font-size: 0.82rem;
}
.isis-margin-banner__main { flex: 1 1 auto; min-width: 0; }
.isis-margin-banner__main strong { font-weight: 600; }
.isis-margin-banner__sub { color: var(--isis-text-muted, #475569); margin-left: 0.25rem; }
.isis-margin-banner__chip {
    flex-shrink: 0;
    padding: 0.15rem 0.55rem;
    border-radius: 10px;
    font-size: 0.72rem;
    font-weight: 600;
    background: rgba(217, 119, 6, 0.12);
    color: var(--isis-warning, #8f5700);
}
.isis-margin-banner__help {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    border-radius: 12px;
    color: var(--isis-text-muted, #475569);
    text-decoration: none;
    margin-left: 0.25rem;
}
.isis-margin-banner__help:hover {
    background: var(--isis-accent-soft, rgba(75, 95, 173, 0.12));
    color: var(--isis-accent, #4b5fad);
}
.isis-margin-banner.is-on-target {
    border-color: var(--isis-success, #16a34a);
    background: rgba(22, 163, 74, 0.06);
}
.isis-margin-banner.is-below-target {
    border-color: var(--isis-warning, #d97706);
    background: rgba(217, 119, 6, 0.06);
}
.isis-margin-banner.is-below-floor {
    border-color: var(--isis-danger, #c62828);
    background: rgba(198, 40, 40, 0.06);
}
.isis-margin-banner.is-no-cost,
.isis-margin-banner.is-unclassified {
    border-color: var(--isis-border, var(--isis-border-strong));
}

/* Task 6 (revue design) — bouton « Détailler les besoins de ressources »
   (isis-grid__action-btn, Task 1) vs bouton historique voisin (.isis-adjust-badge
   juste en dessous) : à l'état fermé mais avec des ressources déjà rattachées, le
   bouton Ressources restait entièrement neutre (icône grise, `border: none` sur
   .isis-grid__action-btn) alors que le bouton Historique affiche toujours un fond
   teinté — deux compteurs côte à côte avec un poids visuel très inégal. Teinté au
   module gescom (pas l'accent générique de l'historique) pour rester cohérent
   avec .isis-devis-items__action--activites (Task 4, même distinction ressources/
   module vs historique/transverse) et .isis-costing-row__activite-chip
   (Task 3). Scopé à .isis-costing-items : .isis-grid__action-btn (457 usages
   produit) reste inchangé. */
.isis-costing-items .isis-grid__action-btn--has-resources {
    background: var(--isis-mod-gescom-soft);
    color: var(--isis-mod-gescom);
}
.isis-costing-items .isis-grid__action-btn--has-resources:hover {
    background: color-mix(in srgb, var(--isis-mod-gescom) 18%, var(--isis-surface));
}

/* Badge ajustements appliqués sur ligne devis (Phase 5) — icône history +
   compteur. Cliquable, ouvre l'historique. Couleur sobre accent module. */
.isis-adjust-badge {
    display: inline-flex !important;
    align-items: center;
    gap: 3px;
    background: color-mix(in srgb, var(--isis-accent) 8%, var(--isis-surface));
    color: var(--isis-accent) !important;
    border-color: color-mix(in srgb, var(--isis-accent) 30%, transparent) !important;
}
.isis-adjust-badge:hover {
    background: color-mix(in srgb, var(--isis-accent) 16%, var(--isis-surface));
}
.isis-adjust-badge__count {
    font-size: 0.7rem;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}

/* Liste de l'historique d'ajustements (DevisAdjustmentHistoryDialog). */
.isis-adjust-history {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
}
.isis-adjust-history__item {
    display: flex;
    gap: 0.7rem;
    align-items: flex-start;
    padding: 0.6rem 0.7rem;
    background: var(--isis-surface-alt, var(--isis-surface-alt));
    border-radius: 6px;
    border: 1px solid var(--isis-border, var(--isis-border));
    box-sizing: border-box;
}
.isis-adjust-history__icon {
    flex-shrink: 0;
    width: 28px;
    height: 28px;
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
.isis-adjust-history__icon.is-uplift {
    background: color-mix(in srgb, var(--isis-success, #16a34a) 14%, transparent);
    color: var(--isis-success, #16a34a);
}
.isis-adjust-history__icon.is-discount {
    background: color-mix(in srgb, var(--isis-accent) 14%, transparent);
    color: var(--isis-accent);
}
.isis-adjust-history__body { flex: 1; min-width: 0; }
.isis-adjust-history__head {
    display: flex;
    flex-wrap: wrap;
    gap: 0.3rem;
    align-items: baseline;
    font-size: 0.82rem;
}
.isis-adjust-history__head .muted { color: var(--isis-text-muted); }
.isis-adjust-history__deltas {
    margin-top: 0.3rem;
    display: flex;
    flex-wrap: wrap;
    gap: 0.7rem;
    font-size: 0.76rem;
    color: var(--isis-text-muted);
    font-variant-numeric: tabular-nums;
}
.isis-adjust-history__deltas strong { color: var(--isis-text); }
.isis-adjust-history__reason {
    margin-top: 0.35rem;
    padding: 0.4rem 0.55rem;
    background: var(--isis-surface, #ffffff);
    border-radius: 4px;
    font-size: 0.78rem;
    font-style: italic;
    color: var(--isis-text);
    border: 1px solid var(--isis-accent);
    box-sizing: border-box;
}

/* Bouton « Auditer » dans le banner marge (Phase 5). Style cohérent avec
   les autres chips du banner — petit, sobre. */
.isis-margin-banner__audit {
    appearance: none;
    background: var(--isis-surface, #ffffff);
    border: 1px solid var(--isis-border, var(--isis-border));
    color: var(--isis-text);
    border-radius: 6px;
    padding: 0.3rem 0.6rem;
    font-size: 0.78rem;
    font-weight: 500;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    transition: background-color 120ms ease, color 120ms ease, border-color 120ms ease;
    margin-left: 0.5rem;
}
.isis-margin-banner__audit:hover {
    background: color-mix(in srgb, var(--isis-accent) 8%, var(--isis-surface));
    border-color: var(--isis-accent);
    color: var(--isis-accent);
}

/* Dialog d'audit bulk Phase 5 — sections empilées avec titre coloré. */
.isis-audit-section--deficit { color: var(--isis-danger, #dc2626); }
.isis-audit-section--excess  { color: var(--isis-accent, #4b5fad); }
.isis-audit-list {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.82rem;
}
.isis-audit-list th,
.isis-audit-list td {
    padding: 0.45rem 0.6rem;
    border-bottom: 1px solid var(--isis-border, var(--isis-border));
    vertical-align: top;
}
.isis-audit-list thead th {
    text-align: left;
    font-weight: 600;
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--isis-text-muted);
    background: var(--isis-surface-alt, var(--isis-surface-alt));
}
.isis-audit-list .num { text-align: right; font-variant-numeric: tabular-nums; }
.isis-audit-list .muted { color: var(--isis-text-muted); font-size: 0.74rem; margin-top: 2px; }
.isis-audit-list .error { color: var(--isis-danger, #dc2626); font-size: 0.74rem; margin-top: 2px; font-style: italic; }
.isis-audit-list .is-positive { color: var(--isis-success, #16a34a); font-weight: 600; }
.isis-audit-list .is-negative { color: var(--isis-danger, #dc2626); font-weight: 600; }
.isis-audit-list tbody tr:hover { background: var(--isis-surface-alt, var(--isis-surface-alt)); }

/* Aperçu d'ajustement Phase 5 (DevisAdjustmentDialog) — table compacte
   avant/après/Δ. Couleurs sémantiques sur les Δ : vert = bénéfice (PU monte,
   total HT monte, marge monte), rouge = perte (PU baisse, etc.). */
.isis-adjust-preview {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.82rem;
    margin-top: 0.4rem;
}
.isis-adjust-preview th,
.isis-adjust-preview td {
    padding: 0.4rem 0.6rem;
    border-bottom: 1px solid var(--isis-border, var(--isis-border));
}
.isis-adjust-preview thead th {
    text-align: left;
    font-weight: 600;
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--isis-text-muted);
    background: var(--isis-surface-alt, var(--isis-surface-alt));
}
.isis-adjust-preview .num {
    text-align: right;
    font-variant-numeric: tabular-nums;
}
.isis-adjust-preview .is-positive { color: var(--isis-success, #16a34a); font-weight: 600; }
.isis-adjust-preview .is-negative { color: var(--isis-danger, #dc2626); font-weight: 600; }
.isis-adjust-preview tr.margin-row td { background: color-mix(in srgb, var(--isis-accent) 4%, transparent); font-weight: 600; }
.isis-adjust-preview tr.cost-row td { color: var(--isis-text-muted); font-size: 0.78rem; font-style: italic; }

/* Bandeau snapshot coût (Phase 3) — placé juste sous le bandeau marge. Style
   neutre informatif pour ne pas distraire : icône lock + texte mince.        */
.isis-cost-snapshot-banner {
    flex-shrink: 0;
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.45rem 0.85rem;
    margin-top: 0.4rem;
    border-radius: 6px;
    background: var(--isis-surface-soft);
    color: var(--isis-text-muted, #475569);
    font-size: 0.78rem;
    border: 1px solid var(--isis-border);
}
.isis-cost-snapshot-banner strong {
    color: var(--isis-text, #1f2328);
    font-weight: 600;
}
/* Bascule "Voir le coût live aussi" — alignée à droite dans le bandeau. */
.isis-cost-snapshot-banner__toggle {
    margin-left: auto;
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    cursor: pointer;
    user-select: none;
    color: var(--isis-text, #1f2328);
    font-size: 0.78rem;
}
.isis-cost-snapshot-banner__toggle input[type="checkbox"] {
    width: 13px;
    height: 13px;
    accent-color: var(--isis-accent, #4b5fad);
    cursor: pointer;
}
/* Delta coût live vs snapshot (Phase 3 v2). Up = coût a augmenté (rouge),
   down = coût a baissé (vert). 0 = pas de variation. */
.isis-costing-items .isis-cost-delta--up   { color: var(--isis-danger,  #c62828); font-weight: 500; }
.isis-costing-items .isis-cost-delta--down { color: var(--isis-success, #16a34a); font-weight: 500; }

/* Colonne Actions sticky pour la table de DÉTAIL du déboursé : rend la colonne
   actions (dernière colonne) épinglée à droite, toujours visible lors du scroll
   horizontal. Même pattern que .isis-grid--sticky-actions mais adapté aux tables
   HTML <table> avec cellules <td class="isis-grid__col-actions">.
   Largeur augmentée de 70px à 120px pour accueillir le bouton + badge correctement.
   Scopé à .isis-crv-det__body (revue finale 2026-09-13) : .isis-costing-items porte
   AUSSI la table « Coûts transversaux » (.isis-crv-overhead__body), qui n'a que
   6 colonnes, ne scrolle pas, et dont la dernière <th> est « Coût » quand l'offre
   est en lecture seule — sans ce scope elle héritait d'une colonne épinglée de
   120px, d'une ombre portée permanente et d'un en-tête teinté isolé. */
.isis-crv-det__body .isis-costing-items td.isis-grid__col-actions {
    position: sticky;
    right: 0;
    background: var(--isis-surface);
    z-index: 2;
    box-shadow: -8px 0 8px -8px rgba(0, 0, 0, 0.12);
    width: 120px;
    min-width: 120px;
}
/* Pas de règle de survol dédiée à la cellule épinglée : la cellule doit garder
   EXACTEMENT le fond de sa ligne (sinon elle se détache en survol, seule teintée).
   `.isis-costing-items tr.isis-costing-row-line.is-clickable:hover > td` et
   `.is-editing > td` couvrent déjà toutes les cellules, actions comprise, avec une
   spécificité supérieure — et les lignes non cliquables (offre en lecture seule)
   n'ont volontairement aucun survol. */
.isis-crv-det__body .isis-costing-items thead th:last-child {
    position: sticky;
    right: 0;
    background: var(--isis-surface-alt);
    z-index: 5;
    width: 120px;
    min-width: 120px;
}

/* Ligne devis : séparateur fin entre lignes successives */
.isis-costing-items tr.isis-costing-row-line > td {
    border-top: 1px solid var(--isis-border);
    padding-top: 0.55rem;
    padding-bottom: 0.55rem;
    background: var(--isis-surface);
}
.isis-costing-items tbody > tr.isis-costing-row-line:first-child > td { border-top: none; }

/* Allocations : indentation + fond légèrement teinté + texte plus discret */
.isis-costing-items tr.isis-costing-row-alloc > td:not(.isis-costing-row__acti-cell),
.isis-costing-items tr.isis-costing-row-alloc-empty > td {
    background: var(--isis-surface-alt);
    padding-top: 0.35rem;
    padding-bottom: 0.35rem;
    font-size: 0.85rem;
    border-bottom: none;
}
.isis-costing-items .isis-costing-row__tree {
    color: var(--isis-text-soft);
    margin-right: 0.4rem;
    font-size: 0.85rem;
}
.isis-costing-items .isis-costing-row__alloc-label {
    font-weight: 500;
    color: var(--isis-text);
    line-height: 1.25;
}
.isis-costing-items .isis-costing-row__alloc-comment {
    margin-top: 0;
    margin-left: 1.1rem;
    font-size: 0.72rem;
    font-style: italic;
    line-height: 1.2;
    color: var(--isis-text-soft);
}
.isis-costing-items tr.isis-costing-row-alloc-empty {
    color: var(--isis-text-soft);
    font-size: 0.78rem;
}
/* Sans bande grise : un état vide n'est pas une rangée de données. Aligné sous la
   désignation, il se lit comme une note de la ligne au-dessus. */
.isis-costing-items tr.isis-costing-row-alloc-empty > td {
    background: transparent;
    padding: 0 0 0.45rem 2.2rem;
    font-size: 0.75rem;
}
.isis-costing-items tr:has(+ tr.isis-costing-row-alloc-empty) > td { border-bottom-color: transparent; }

/* Task 3 — drilldown 3 niveaux (ligne → activité → ressource) sur une ligne fermée */
.isis-costing-items tr.isis-costing-row-alloc--lvl2 > td { padding-left: 1.2rem; }
.isis-costing-items .isis-costing-row__tree--lvl2 { margin-left: 1.4rem; }
.isis-costing-items .isis-costing-row__activite-chip {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    background: var(--isis-mod-gescom-soft);
    color: color-mix(in srgb, var(--isis-mod-gescom) 80%, black);
    border-radius: var(--isis-radius-pill);
    padding: 2px 9px;
    font-size: 11px;
    font-weight: 650;
}
:root[data-theme="dark"] .isis-costing-items .isis-costing-row__activite-chip { color: var(--isis-mod-gescom); }
.isis-costing-items .isis-costing-row__activite-chip--direct {
    /* Fond distinct de --isis-surface-alt (déjà posé sur <td> par la règle ci-dessus) :
       une pastille de même teinte que sa ligne porteuse serait invisible. */
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    color: var(--isis-text-soft);
}

/* Task 7 — mêmes règles que ci-dessus, portées sur .isis-devis-items--gridskin
   (table de DevisItemsEditDialog.razor, onglet Lignes) : les sélecteurs
   .isis-costing-items ne matchent pas cette table, qui ne porte pas cette
   classe. Mêmes tokens, aucune valeur dupliquée en dur. */
.isis-devis-items--gridskin tr.isis-costing-row-alloc > td:not(.isis-costing-row__acti-cell),
.isis-devis-items--gridskin tr.isis-costing-row-alloc-empty > td {
    background: var(--isis-surface-alt);
    padding-top: 0.35rem;
    padding-bottom: 0.35rem;
    font-size: 0.85rem;
    border-bottom: none;
}
/* Task 6 (revue design) — état vide d'un groupe d'activité sans ressource
   (cf. razor : "Aucun besoin de ressource sur cette activité."), même
   traitement que .isis-costing-items tr.isis-costing-row-alloc-empty. */
.isis-devis-items--gridskin tr.isis-costing-row-alloc-empty {
    color: var(--isis-text-soft);
    font-style: italic;
    font-size: 0.78rem;
}
.isis-devis-items--gridskin .isis-costing-row__tree {
    color: var(--isis-text-soft);
    margin-right: 0.4rem;
    font-size: 0.85rem;
}
.isis-devis-items--gridskin .isis-costing-row__alloc-label {
    font-weight: 500;
    color: var(--isis-text);
    line-height: 1.25;
}

/* Task 4 — drilldown 3 niveaux (ligne → activité → ressource) sur l'onglet Lignes,
   même règles que Task 3 (.isis-costing-items) portées sur .isis-devis-items--gridskin
   qui ne matche pas ces sélecteurs (table différente). Aucune valeur dupliquée en dur. */
.isis-devis-items--gridskin tr.isis-costing-row-alloc--lvl2 > td { padding-left: 1.2rem; }
.isis-devis-items--gridskin .isis-costing-row__tree--lvl2 { margin-left: 1.4rem; }
.isis-devis-items--gridskin .isis-costing-row__activite-chip {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    background: var(--isis-mod-gescom-soft);
    color: color-mix(in srgb, var(--isis-mod-gescom) 80%, black);
    border-radius: var(--isis-radius-pill);
    padding: 2px 9px;
    font-size: 11px;
    font-weight: 650;
}
:root[data-theme="dark"] .isis-devis-items--gridskin .isis-costing-row__activite-chip { color: var(--isis-mod-gescom); }

/* Total devis : barre marquée en bas */
.isis-costing-items tr.isis-costing-row-total > td {
    border-top: 2px solid var(--isis-border);
    padding-top: 0.7rem;
    padding-bottom: 0.7rem;
    background: var(--isis-surface);
    font-size: 0.95rem;
}

/* Colonne Code dans la table read-only des lignes (DevisDetail · onglet Lignes) */
.isis-devis-items__code {
    font-family: var(--isis-font-mono, ui-monospace, monospace);
    font-size: 0.78rem;
    color: var(--isis-mod-gescom);
    font-weight: 600;
}
.isis-devis-items__code-empty {
    color: var(--isis-text-soft);
    font-style: italic;
    font-size: 0.78rem;
}

/* ============================================================================
   Catalogue articles : sélecteurs (1-à-1 et masse) + indicateurs ligne devis.
   ============================================================================ */

/* Bouton « Depuis le catalogue » distinctif dans la barre add-row */
.isis-devis-items__add--catalog {
    background: var(--isis-mod-gescom-soft) !important;
    color: var(--isis-mod-gescom) !important;
    border-color: var(--isis-mod-gescom) !important;
    font-weight: 600;
}
.isis-devis-items__add--catalog:disabled {
    opacity: 0.45;
    cursor: not-allowed;
}

/* Ligne checkbox + label dans les formulaires (Phase 2 v2). Pattern simple
   pour les options booléennes : la checkbox Radzen à gauche, label à droite. */
.isis-checkbox-row {
    display: flex;
    align-items: center;
    gap: 0.55rem;
    cursor: pointer;
    user-select: none;
}
/* Case native : couleur de thème + cible un peu plus grande + focus visible (a11y). */
.isis-checkbox-row input[type="checkbox"] {
    width: 16px;
    height: 16px;
    flex-shrink: 0;
    accent-color: var(--isis-current-mod, var(--isis-accent));
    cursor: pointer;
}
.isis-checkbox-row input[type="checkbox"]:focus-visible {
    outline: 2px solid var(--isis-current-mod, var(--isis-accent));
    outline-offset: 2px;
}

/* Aperçu d'échéance dérivée (modal facture émise, refonte 2026-06-22).
   Surface douce + chiffres tabulaires ; variante --empty pour l'état « aucune
   condition » (texte atténué, pas de tabular-nums sur une phrase). */
.isis-due-preview {
    background: var(--isis-surface-alt, var(--isis-surface));
    border-radius: var(--isis-radius-sm);
    padding: 0.35rem 0.6rem;
    font-variant-numeric: tabular-nums;
}
.isis-due-preview--empty {
    color: var(--isis-text-muted);
    font-variant-numeric: normal;
}
.isis-due-preview__toggle { margin-top: 0.35rem; }

/* Éditeur de lignes facture — colonne flex avec zone scrollable interne pour
   garder le bouton « Ajouter » + les totaux épinglés sur les factures longues. */
.isis-facture-lignes-editor {
    display: flex;
    flex-direction: column;
    min-height: 0;
}
.isis-facture-lignes-editor__scroll {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
}

/* Liste de cases à cocher dans les dialogs form-linear (ex. picker pièces EcheanceReturnDialog).
   Bornée en hauteur : une commande peut porter beaucoup de consignes. */
.isis-checkbox-list {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
    margin-top: 0.25rem;
    max-height: 200px;
    overflow-y: auto;
    overscroll-behavior: contain;
}

/* Bulk align PU sur cible entreprise (Phase 2). Distinct visuellement des
   boutons d'ajout : palette success pour signaler l'opération sur les lignes
   existantes (pas une création).                                                */
.isis-devis-items__add--bulk-align {
    margin-left: auto;
    background: rgba(22, 163, 74, 0.08) !important;
    color: var(--isis-success, #16a34a) !important;
    border-color: var(--isis-success, #16a34a) !important;
    font-weight: 600;
}
.isis-devis-items__add--bulk-align:hover {
    background: rgba(22, 163, 74, 0.16) !important;
}

/* Cellule Qté : input numeric + pastille de provenance (EF-60). La pastille ne se comprime
   jamais — elle disparaît avec le lien, sa largeur ne doit pas dépendre du texte voisin. */
.isis-qte-cell {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 0.25rem;
}
.isis-qte-cell > .isis-devis-origine {
    flex-shrink: 0;
}

/* Cellule PU HT : input numeric + bouton calculateur inline (Phase 2). */
.isis-pu-cell {
    display: flex;
    align-items: center;
    gap: 0.25rem;
}
.isis-pu-cell__calc {
    appearance: none;
    background: var(--isis-surface, #ffffff);
    border: 1px solid var(--isis-border, var(--isis-border));
    color: var(--isis-accent, #4b5fad);
    border-radius: 4px;
    height: 24px;
    width: 24px;
    padding: 0;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}
.isis-pu-cell__calc:hover {
    background: var(--isis-accent-soft, rgba(75, 95, 173, 0.12));
    border-color: var(--isis-accent, #4b5fad);
}
.isis-pu-cell__calc:focus-visible {
    outline: 2px solid var(--isis-accent, #4b5fad);
    outline-offset: 1px;
}

/* Désignation de l'éditeur de lignes : le numéro de section précède le texte. */
.isis-row-desc {
    display: flex;
    align-items: flex-start;
    gap: 0.25rem;
}
.isis-row-desc > .isis-row-desc-textarea { flex: 1 1 auto; min-width: 0; }
@media (pointer: coarse) {
    .isis-row-client-code__remember { width: 36px; height: 36px; }
}
/* Faits de l'article rattaché, en tête du menu de réglages de la ligne. */
.isis-row-link__facts {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: 0.25rem 0.75rem;
    margin: 0;
    padding: 0.6rem 0.75rem;
    border-bottom: 1px solid var(--isis-border);
    font-size: 0.78rem;
}
.isis-row-link__facts dt { color: var(--isis-text-muted); }
.isis-row-link__facts dd { margin: 0; color: var(--isis-text); overflow-wrap: anywhere; }
.isis-row-link__code { font-family: var(--isis-font-mono, ui-monospace, monospace); font-weight: 600; }

/* Code client (0736) : saisissable, avec l'état de la ligne vis-à-vis du référentiel. */
.isis-row-client-code__wrap {
    display: flex;
    align-items: center;
    gap: 0.2rem;
}
.isis-row-client-code__input { flex: 1 1 auto; min-width: 0; width: 100%; font-family: var(--isis-font-mono, ui-monospace, monospace); }
.isis-row-client-code__ref {
    display: inline-flex;
    flex: 0 0 auto;
    color: color-mix(in srgb, var(--isis-mod-gescom) 80%, black);
}
:root[data-theme="dark"] .isis-row-client-code__ref { color: var(--isis-mod-gescom); }
.isis-row-client-code__remember {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 26px;
    height: 26px;
    padding: 0;
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-sm, 4px);
    background: var(--isis-surface);
    color: var(--isis-text-muted);
    cursor: pointer;
}
.isis-row-client-code__remember:hover { color: var(--isis-text); border-color: var(--isis-border-strong); }
.isis-row-client-code__remember:focus-visible {
    outline: 2px solid var(--isis-current-mod, var(--isis-mod-gescom));
    outline-offset: 1px;
}

/* Recherche commune aux dialogs catalogue */
.isis-catalog-search {
    width: 100%;
    height: 36px;
    padding: 0 0.7rem;
    border: 1px solid var(--isis-border);
    border-radius: 6px;
    background: var(--isis-surface);
    font-size: 0.85rem;
    color: var(--isis-text);
    outline: none;
    transition: border-color 120ms ease;
}
.isis-catalog-search:focus { border-color: var(--isis-accent); }

/* Sélecteur 1-à-1 : liste verticale d'items */
.isis-catalog-list {
    border: 1px solid var(--isis-border);
    border-radius: 6px;
    max-height: 360px;
    min-height: 200px;
    overflow-y: auto;
    background: var(--isis-surface);
    margin-top: 0.4rem;
}
.isis-catalog-list ul { list-style: none; margin: 0; padding: 0; }
.isis-catalog-list__empty {
    padding: 2rem 1rem;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.4rem;
    color: var(--isis-text-soft);
    text-align: center;
}
.isis-catalog-list__empty .rzi { font-size: 28px; opacity: 0.4; }

.isis-catalog-selsummary{display:flex;justify-content:space-between;align-items:center;font-size:11.5px;color:var(--isis-text-muted);margin-bottom:6px;padding:0 2px;}

.isis-catalog-item {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 0.55rem 0.75rem;
    border-bottom: 1px solid var(--isis-border-soft, #f1f2f5);
    cursor: pointer;
    transition: background-color 100ms ease;
    gap: 0.6rem;
}
.isis-catalog-item:last-child { border-bottom: none; }
.isis-catalog-item:hover { background: var(--isis-surface-alt); }
/* Les options sont des <li> focusables au clavier (WCAG 2.1.1) — il leur faut un focus visible. */
.isis-catalog-item:focus-visible {
    outline: 2px solid var(--isis-accent);
    outline-offset: -2px;
    background: var(--isis-surface-alt);
}
.isis-catalog-item.is-selected {
    background: var(--isis-accent-soft);
    border: 1px solid var(--isis-accent);
    box-sizing: border-box;
    padding-left: calc(0.75rem - 2px);
}
.isis-catalog-item__main {
    display: flex;
    align-items: baseline;
    gap: 0.65rem;
    min-width: 0;
}
.isis-catalog-item__code {
    font-family: var(--isis-font-mono, ui-monospace, monospace);
    font-size: 0.78rem;
    font-weight: 600;
    color: var(--isis-text-muted);
    flex-shrink: 0;
}
.isis-catalog-item__name {
    font-size: 0.85rem;
    font-weight: 500;
    color: var(--isis-text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.isis-catalog-item__structure {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    font-size: 0.7rem;
    color: var(--isis-text-soft);
    background: var(--isis-surface-alt);
    padding: 0.1rem 0.45rem;
    border-radius: 3px;
    flex-shrink: 0;
    white-space: nowrap;
}
.isis-catalog-item__structure .rzi,
.isis-catalog-item__structure .rz-icon {
    font-size: 0.85rem;
    opacity: 0.7;
}

/* Entrée du catalogue d'un sous-traitant (0574) : son code au-dessus, notre code
   analytique en dessous — les 2 lignes empilées, pas côte à côte. */
.isis-catalog-item--stacked {
    flex-direction: column;
    align-items: stretch;
    justify-content: flex-start;
    gap: 0.2rem;
}
.isis-catalog-item__sub {
    font-size: 0.74rem;
    color: var(--isis-text-soft);
}
/* Fin de la ligne de titre d'une option : ce qui DIMENSIONNE le clic (nombre de sous-tâches,
   portée) se lit à droite, sur la même ligne que le libellé, au lieu d'être noyé dans le plus
   petit texte de l'option. Aucune taille ni couleur nouvelle : la puce est `__structure`. */
.isis-catalog-item__main-end {
    margin-left: auto;
    display: inline-flex;
    align-items: baseline;
    gap: 0.4rem;
    flex-shrink: 0;
}
/* Une description est de longueur libre : sans borne, elle faisait varier la hauteur des
   options et repoussait la présélection sous la ligne de flottaison des 360 px. */
.isis-catalog-item__sub--clamp {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.isis-catalog-item__sub strong {
    font-family: var(--isis-font-mono, ui-monospace, monospace);
    font-weight: 600;
    color: var(--isis-text-muted);
}
/* Sur un item retenu, le fond passe à --isis-accent-soft : --isis-text-soft y tombe
   à 3.90:1 en clair et 4.45:1 en sombre (mesuré le 2026-09-08). C'est la ligne qui
   porte le tiers et le montant de l'offre choisie — d'un cran vers l'encre. */
.isis-catalog-item.is-selected .isis-catalog-item__sub {
    color: var(--isis-text-muted);
}

/* En-tête de groupe (par structure) dans les pickers — P2 cotraitants. */
.isis-catalog-group-header {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.5rem;
    padding: 0.45rem 0.75rem 0.3rem;
    background: var(--isis-surface-alt);
    border-bottom: 1px solid var(--isis-border);
    cursor: default;
}
.isis-catalog-group-header strong {
    font-size: 0.78rem;
    font-weight: 600;
    color: var(--isis-text);
}
.isis-catalog-group-header__role {
    font-size: 0.65rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--isis-text-muted);
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    padding: 0.05rem 0.4rem;
    border-radius: 3px;
}

/* Sélecteur en masse : tableau avec checkbox + qty */
.isis-catalog-bulk-count {
    font-weight: 500;
    color: var(--isis-mod-gescom);
    margin-left: 0.4rem;
    font-size: 0.78rem;
}
.isis-catalog-bulk {
    border: 1px solid var(--isis-border);
    border-radius: 6px;
    max-height: 420px;
    min-height: 240px;
    overflow-y: auto;
    background: var(--isis-surface);
    margin-top: 0.4rem;
}
.isis-catalog-bulk__table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.82rem;
}
.isis-catalog-bulk__table thead th {
    position: sticky; top: 0;
    background: var(--isis-surface-alt);
    border-bottom: 1px solid var(--isis-border);
    padding: 0.5rem 0.6rem;
    text-align: left;
    font-size: 0.7rem;
    font-weight: 600;
    color: var(--isis-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}
.isis-catalog-bulk__table tbody td {
    padding: 0.45rem 0.6rem;
    border-bottom: 1px solid var(--isis-border-soft, #f1f2f5);
}
.isis-catalog-bulk__table tbody tr:last-child td { border-bottom: none; }
.isis-catalog-bulk__table tbody tr.is-checked { background: var(--isis-accent-soft); }
.isis-catalog-bulk__code {
    font-family: var(--isis-font-mono, ui-monospace, monospace);
    font-size: 0.78rem;
    color: var(--isis-text-muted);
}
.isis-catalog-bulk__structure {
    font-size: 0.72rem;
    color: var(--isis-text-soft);
}
/* En-tête de groupe par structure (P2 cotraitants) */
.isis-catalog-bulk__group-row td {
    background: var(--isis-surface-alt);
    padding: 0.4rem 0.65rem;
    border-bottom: 1px solid var(--isis-border);
}
.isis-catalog-bulk__group {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.5rem;
}
.isis-catalog-bulk__group strong {
    font-size: 0.78rem;
    font-weight: 600;
    color: var(--isis-text);
}
.isis-catalog-bulk__group-role {
    font-size: 0.65rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--isis-text-muted);
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    padding: 0.05rem 0.4rem;
    border-radius: 3px;
}

/* Dropdown Type compact dans le dialog d'édition de lignes : font plus petit
   + padding réduit pour que le texte (PRODUIT/SERVICE/SECTION/COMMENT) reste
   lisible sans déborder de la colonne 100px. */
.isis-devis-items__type-dd.rz-dropdown {
    min-height: 30px;
}
.isis-devis-items__type-dd .rz-dropdown-label,
.isis-devis-items__type-dd .rz-inputtext {
    font-size: 0.72rem;
    padding: 0.25rem 0.4rem;
}
.isis-devis-items__type-dd .rz-dropdown-trigger {
    width: 24px;
}
/* Liste déroulante : items du popup */
.rz-dropdown-panel .rz-dropdown-items .rz-dropdown-item {
    font-size: 0.78rem;
}

/* ============================================================================
   .isis-grid--email-templates — variante pour /<module>/parametres/emails.
   Colonnes : code | sujet | statut
   ============================================================================ */
.isis-grid--email-templates .isis-grid__head,
.isis-grid--email-templates .isis-grid__row {
    grid-template-columns: minmax(220px, 0.9fr) minmax(220px, 1.5fr) 110px;
    min-width: 600px;
}

/* ============================================================================
   .isis-grid--integration-entities — variante pour /sirh/parametres/integration.
   Colonnes : Sujet RH (large, nom + hint) | Direction (dropdown) | Dernier pull | Badge
   ============================================================================ */
.isis-grid--integration-entities .isis-grid__head,
.isis-grid--integration-entities .isis-grid__row {
    grid-template-columns: minmax(240px, 1.4fr) 260px 150px minmax(140px, 1fr);
    min-width: 820px;
    align-items: center;
}
/* Variante master-detail dédiée : sidepanel large pour le JSON config + scroll
   interne (les configs JSON peuvent être longues). */
.isis-master-detail--integration {
    grid-template-columns: minmax(0, 1fr) 520px;
    /* Cette page a une SECTION (« Rapprochement des dossiers ») SOUS le master-detail.
       Le `flex: 1 1 auto; min-height: 0` de base (remplissage de hauteur + scroll interne,
       pensé pour les pages liste) faisait déborder le contenu par-dessus cette section
       (2026-07-17). Ici on prend la hauteur du contenu et on laisse la section flotter dessous. */
    flex: 0 0 auto;
}
.isis-master-detail--integration .isis-master-detail__detail {
    overflow-y: auto;
    max-height: calc(100vh - 220px);
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}
/* État (provider / activation / dernier test) — ex-pills du bandeau retiré, posées au-dessus
   du formulaire de configuration (2026-09-03). Même sémantique de couleur, hors bandeau. */
.isis-integration-state {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-wrap: wrap;
}
/* Groupes d'actions du sidepanel détail (master-detail) : primaire en tête,
   destructive séparée en bas via margin-top:auto. Remplace l'ancien recyclage de
   .isis-card-split__aside-actions (intra-carte) qui ne convient pas au pattern
   full-height. */
.isis-master-detail__detail-actions {
    display: flex;
    gap: 0.4rem;
    flex-wrap: wrap;
    padding-bottom: 0.6rem;
    border-bottom: 1px solid var(--isis-border-soft);
}
.isis-master-detail__detail-actions--destructive {
    margin-top: auto;
    padding-top: 0.75rem;
    border-top: 1px solid var(--isis-border-soft);
    border-bottom: none;
}
/* Bloc d'erreur de test connexion : remonté en tête de sidepanel pour scan
   immédiat (auparavant noyé en bas après la textarea credentials, scroll requis). */
.isis-master-detail--integration .isis-sidepanel-alert {
    border: 1px solid var(--isis-danger);
    box-sizing: border-box;
    background: var(--isis-danger-soft);
    padding: 0.6rem 0.75rem;
    border-radius: 0 6px 6px 0;
}
.isis-master-detail--integration .isis-sidepanel-alert__label {
    font-size: 0.72rem;
    font-weight: 600;
    color: #991b1b;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    margin-bottom: 0.25rem;
}
.isis-master-detail--integration .isis-sidepanel-alert__value {
    font-size: 0.85rem;
    color: var(--isis-text);
    word-break: break-word;
}
/* Credentials masqués : placeholder avant édition explicite. */
.isis-credentials-masked {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.75rem;
    background: var(--isis-surface-alt);
    border: 1px dashed var(--isis-border-soft);
    border-radius: 6px;
    font-size: 0.85rem;
    color: var(--isis-text-muted);
}
.isis-credentials-masked__dots {
    font-family: "Geist Mono", ui-monospace, monospace;
    letter-spacing: 0.15em;
    color: var(--isis-text);
}

/* Variante master-detail pour la page templates email : sidepanel plus large
   (560px) car contient un éditeur de body, et scroll interne pour permettre
   les longs contenus sans casser le sticky du detail. */
.isis-master-detail--emails {
    grid-template-columns: minmax(0, 1fr) 560px;
}
.isis-master-detail--emails .isis-master-detail__detail {
    overflow-y: auto;
    max-height: calc(100vh - 220px);
}
/* Variante master-detail pour /mon-espace/validations : sidepanel 480px par
   défaut (cf. .isis-master-detail), scroll interne pour permettre l'affichage
   complet de l'AbsenceDetailPanel (chaîne + timeline) sans pousser la page. */
.isis-master-detail--validations .isis-master-detail__detail {
    overflow-y: auto;
    max-height: calc(100vh - 220px);
}
/* Variante master-detail --scrollable : opt-in générique pour les pages dont le
   sidepanel peut accumuler du contenu vertical (collaboration équipe avec
   commentaires + partages + listes liées). Calque la variante --validations
   mais sans rattacher à une page spécifique.
   RÉSERVÉE, depuis le 2026-09-01, aux panneaux SANS coquille `.isis-detail-split` —
   aujourd'hui le seul /sirh/organisation-duale (`.isis-orgside`). Sur un panneau à
   coquille, c'est le split qui défile : la variante n'y posait plus qu'un
   `overflow-y: auto` inerte (scrollHeight == clientHeight mesuré), les couches de
   dégradé d'ombre de défilement sur un élément immobile, et un plafond de hauteur
   qu'aucun autre écran converti ne porte. Elle a été retirée à cette date des trois
   listes gesmaff (AO / marché / demande client), seules porteuses dans ce cas. */
.isis-master-detail--scrollable .isis-master-detail__detail {
    overflow-y: auto;
    max-height: calc(100vh - 220px);
    /* Scroll-shadow + barre masquée hérités de la règle centralisée (cf. tokens
       --isis-scroll-shadow-*). Ici on ne pose que le comportement de défilement. */
}
/* En mode drawer overlay (--no-side), le sidepanel passe en position:fixed avec
   top: header_h + bottom: 0 (cf. règle ~L.7084). Les `max-height` posées par
   les variantes `--scrollable`, `--emails`, `--validations` doivent alors être
   neutralisées pour que le drawer occupe TOUTE la hauteur restante sous le
   header (et non être tronqué à 100vh-220px). Sélecteur doublé `.isis-master-detail.isis-master-detail--no-side`
   pour battre la spécificité (0,2,0) des variantes simples sans `!important`.
   Refonte 2026-05-29. */
.isis-master-detail.isis-master-detail--no-side .isis-master-detail__detail {
    max-height: none;
}

/* Variante drawer overlay ADAPTÉE pour les pages 3 colonnes `--rail` (sirh/organisation
   onglet Structures internes : rail entreprises | arbre | sidepanel détail).
   En mode élargi, on passe de 3 cols à 2 cols (rail + arbre pleine largeur) en
   retirant le sidepanel du flux (il devient drawer flottant comme dans le pattern
   standard). Le rail à 230px reste visible pour ne pas perdre la navigation par
   entreprise. Refonte 2026-05-29. */
.isis-master-detail--rail.isis-master-detail--no-side {
    grid-template-columns: 230px minmax(0, 1fr);
}
/* Éditeur de template : monospace 14px (pas 11px = fatigue oculaire après 30 min). */
.isis-tpl-editor textarea,
.isis-tpl-editor input,
.isis-tpl-editor .rz-textbox,
.isis-tpl-editor .rz-textarea {
    width: 100% !important;
    font-family: "Geist Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace !important;
    font-size: 0.875rem !important;
    line-height: 1.5 !important;
}
/* Chips variables — boutons cliquables (copient {{ var }} au clipboard). */
.isis-tpl-var-btn {
    border: none;
    cursor: copy;
    font-family: "Geist Mono", ui-monospace, monospace;
}
.isis-tpl-var-btn:hover {
    background: var(--isis-mod-sirh) !important;
    color: #fff !important;
}
.isis-tpl-var-btn:focus-visible {
    outline: 2px solid var(--isis-accent);
    outline-offset: 1px;
}

/* ============================================================================
   .isis-grid--validations — variante pour /mon-espace/validations.
   Colonnes : status | demandeur | type | période | jours | étape | soumise | actions
   ============================================================================ */
.isis-grid--validations .isis-grid__head,
.isis-grid--validations .isis-grid__row {
    grid-template-columns: 32px minmax(180px, 1.4fr) minmax(120px, 0.9fr) minmax(170px, 1.2fr) 70px 80px 100px 110px;
    min-width: 1080px;
}
.isis-grid--validations .isis-grid__col-actions {
    display: flex;
    gap: 0.25rem;
    justify-content: flex-end;
}

/* .isis-grid--mob-valid — section « Mobilisations à valider » (/mon-espace/validations).
   Colonnes : collaborateur | période | commande | demandeur | charge | actions */
.isis-grid--mob-valid .isis-grid__head,
.isis-grid--mob-valid .isis-grid__row {
    grid-template-columns: minmax(180px, 1.6fr) minmax(150px, 1.1fr) minmax(180px, 1.5fr) minmax(130px, 1fr) 80px 90px;
    min-width: 960px;
}
.isis-grid--mob-valid .isis-grid__col-actions {
    display: flex;
    gap: 0.25rem;
    justify-content: flex-end;
}

/* .isis-grid--aff-valid — section « Affectations à valider » (/mon-espace/validations, EF-61).
   Colonnes : ressource | période | origine | demandeur | attente | actions */
.isis-grid--aff-valid .isis-grid__head,
.isis-grid--aff-valid .isis-grid__row {
    grid-template-columns: minmax(180px, 1.6fr) minmax(150px, 1.1fr) minmax(180px, 1.5fr) minmax(130px, 1fr) 100px 90px;
    min-width: 960px;
}
.isis-grid--aff-valid .isis-grid__col-actions {
    display: flex;
    gap: 0.25rem;
    justify-content: flex-end;
}
.isis-grid__step-pill {
    display: inline-block;
    padding: 0.1rem 0.5rem;
    border-radius: var(--isis-radius-pill);
    font-size: 0.75rem;
    font-weight: 500;
    color: var(--isis-text);
    background: var(--isis-mod-sirh-soft, var(--isis-surface-alt));
    font-variant-numeric: tabular-nums;
}
.isis-grid__age-urgent {
    /* F4 — terre cuite : "demande d'attention" sans connoter "erreur".
       Le rouge --isis-danger reste réservé aux statuts critiques permanents. */
    color: var(--isis-accent-strong);
    font-weight: 600;
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
}

/* Layout master-detail à l'intérieur d'une RadzenCard (hauteur naturelle, pas
   forcé sur le reste de la rich-page). Utilisé sur MonEspace pour les cartes
   « Mes demandes » et « À valider » : la grille à gauche, le sidepanel détail
   à droite. */
.isis-card-split {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 360px;
    gap: 0.75rem;
    align-items: start;
}
.isis-card-split__aside {
    background: var(--isis-surface);
    border: 1px solid var(--isis-border-soft);
    border-radius: var(--isis-radius);
    padding: 0.75rem;
    max-height: 560px;
    overflow-y: auto;
    position: sticky;
    top: 0.5rem;
}
.isis-card-split__aside-actions {
    display: flex;
    gap: 0.4rem;
    margin-bottom: 0.6rem;
    padding-bottom: 0.6rem;
    border-bottom: 1px solid var(--isis-border-soft);
}
@media (max-width: 1100px) {
    .isis-card-split { grid-template-columns: 1fr; }
    .isis-card-split__aside { position: static; max-height: none; }
}

/* Sidepanel utilitaires (réutilisés par AbsenceDetailPanel) */
.isis-sidepanel-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.4rem;
    padding: 1.5rem 0.75rem;
    text-align: center;
    color: var(--isis-text-soft);
    font-size: 0.85rem;
}
.isis-sidepanel-block {
    padding: 0.5rem 0.6rem;
    background: var(--isis-surface-alt);
    border-radius: 6px;
}
.isis-sidepanel-block__header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: .5rem;
    margin-bottom: .4rem;
}
.isis-sidepanel-block__label {
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--isis-text-soft);
    margin-bottom: 0.2rem;
}
.isis-sidepanel-block__value {
    font-size: 0.85rem;
    color: var(--isis-text);
}
.isis-sidepanel-block__title {
    font-size: 0.9rem;
    font-weight: 600;
    color: var(--isis-text);
    display: flex;
    align-items: center;
    gap: 0.4rem;
}
/* Titre de bloc + action légère alignée à droite (« Tout sélectionner »). */
.isis-sidepanel-block__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--isis-space-sm);
}
.isis-sidepanel-block__action {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    font-size: 0.78rem;
    color: var(--isis-text-muted);
    cursor: pointer;
    user-select: none;
}
.isis-sidepanel-block__action:hover { color: var(--isis-text); }
.isis-sidepanel-block__subtitle {
    font-size: 0.8rem;
    color: var(--isis-text-muted);
    margin-top: 0.1rem;
    margin-bottom: 0.4rem;
}
/* Liste de faits du sidepanel : icône + texte alignés sur une ligne (sinon le
   <div> texte block tombe sous l'icône inline). Ajout 2026-05-30. */
.isis-sidepanel-block__facts {
    list-style: none;
    margin: 0.3rem 0 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
}
.isis-sidepanel-block__facts > li {
    display: flex;
    align-items: flex-start;
    gap: 0.5rem;
    font-size: 0.85rem;
    color: var(--isis-text);
    line-height: 1.35;
}
.isis-sidepanel-block__facts > li > .rz-icon,
.isis-sidepanel-block__facts > li > i {
    flex: 0 0 auto;
    margin-top: 0.05rem;
}
.isis-sidepanel-block__facts > li > div {
    min-width: 0;
    overflow-wrap: anywhere;
}
.isis-sidepanel-block__actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin-top: 0.85rem;
}
.isis-sidepanel-block__thumb {
    display: block;
    max-width: 100%;
    max-height: 180px;
    object-fit: contain;
    border: 1px solid var(--isis-border);
    border-radius: 8px;
    margin: 0.5rem 0;
    background: var(--isis-surface-alt);
}
/* Titre de sous-bloc (journaux workflow logés dans un sidepanel déjà titré) :
   même famille que .isis-sidepanel-block__title mais rang typographique
   inférieur, et compteur repoussé à droite. */
.isis-sidepanel-block__title--sub {
    justify-content: space-between;
    font-size: 0.75rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--isis-text-soft);
}
.isis-sidepanel-block__loading {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0.9rem 0;
}
.isis-sidepanel-block__count {
    font-size: 0.68rem;
    font-weight: 600;
    background: var(--isis-surface);
    color: var(--isis-text-soft);
    padding: 0.05rem 0.4rem;
    border-radius: 10px;
    font-variant-numeric: tabular-nums;
    border: 1px solid var(--isis-border);
}

/* Liste des devis créés depuis un AO/Demande (traçabilité reverse, sidepanel gesmaff). */
.isis-source-devis-list {
    list-style: none;
    padding: 0;
    margin: 0.4rem 0 0 0;
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
}
.isis-source-devis-list__item { margin: 0; }
.isis-source-devis-list__row {
    width: 100%;
    display: grid;
    grid-template-columns: minmax(90px, auto) 1fr auto auto;
    align-items: center;
    gap: 0.4rem;
    padding: 0.35rem 0.5rem;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: 5px;
    cursor: pointer;
    text-align: left;
    font: inherit;
    color: var(--isis-text);
    transition: background 0.1s, border-color 0.1s;
}
.isis-source-devis-list__row:hover,
.isis-source-devis-list__row:focus-visible {
    background: var(--isis-mod-gesmaff-soft, #fef3c7);
    border-color: var(--isis-mod-gesmaff, #d97706);
    outline: 0;
}
.isis-source-devis-list__num {
    font-family: var(--isis-font-mono, ui-monospace, monospace);
    font-size: 0.72rem;
    font-weight: 600;
    color: var(--isis-mod-gescom, #4b5fad);
}
.isis-source-devis-list__title {
    font-size: 0.8rem;
    color: var(--isis-text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
}
.isis-source-devis-list__amount {
    font-size: 0.75rem;
    font-weight: 600;
    color: var(--isis-text-soft);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* ============================================================================
   .isis-grid--absences — variante pour /sirh/absences (liste des demandes).
   Colonnes : status | collaborateur | type | période | jours | statut | actions
   ============================================================================ */
.isis-grid--absences .isis-grid__head,
.isis-grid--absences .isis-grid__row {
    /* « Jours » : 70px suffisaient au libellé + flèche de tri, plus à l'entonnoir de plage
       ajouté le 2026-09-04 — le bouton débordait sous la cellule voisine, qui interceptait
       le clic (mesuré au navigateur). 118px = libellé + flèche + entonnoir 24px. */
    grid-template-columns: 32px minmax(180px, 1.4fr) minmax(140px, 1fr) minmax(180px, 1.3fr) 118px 100px 60px;
    /* min-width = somme des colonnes, pas 920 : le forçage à 920 dépassait
       la carte maître (~790px) → la colonne Statut (badge « APPROUVÉE ») était
       poussée hors champ à droite, invisible sans scroll horizontal. */
    min-width: 810px;
}
.isis-grid--absences .isis-grid__col-name {
    display: flex !important;
    flex-direction: column;
    gap: 0.05rem;
    min-width: 0;
}
.isis-grid--absences .isis-grid__col-name-label {
    font-weight: 500;
    color: var(--isis-text);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.isis-grid--absences .isis-grid__col-period {
    color: var(--isis-text-muted);
    font-size: 0.82rem;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* Variante compacte pour l'onglet « Absences » de la fiche collaborateur :
   pas de colonne « Collaborateur » (implicite) → 6 colonnes au lieu de 7. */
/* 5 col : pastille statut | Type | Période | Jours | Statut. Une 6e piste de 60px
   traînait sans cellule en face — les colonnes glissaient d'un cran. */
.isis-grid--absences-collab .isis-grid__head,
.isis-grid--absences-collab .isis-grid__row {
    grid-template-columns: 32px minmax(140px, 1fr) minmax(180px, 1.5fr) 70px 110px;
    min-width: 660px;
}
.isis-grid--absences-collab .isis-grid__col-period {
    color: var(--isis-text-muted);
    font-size: 0.82rem;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* ============================================================================
   .isis-absence-pill — pastille colorée du type d'absence (calendrier + grille).
   Palette dérivée de --isis-* uniquement (DESIGN.md). 9 classes prédéfinies.
   ============================================================================ */
.isis-absence-pill {
    display: inline-flex;
    align-items: center;
    padding: 0.15rem 0.55rem;
    border-radius: var(--isis-radius-pill);
    font-size: 0.72rem;
    font-weight: 600;
    letter-spacing: 0.01em;
}
/* Variante compacte utilisée en sous-libellé d'une cellule (carte aperçu MonEspace). */
.isis-absence-pill--mini {
    padding: 0.05rem 0.4rem;
    font-size: 0.68rem;
    font-weight: 500;
    margin-top: 0.15rem;
    align-self: flex-start;
}
/* Lien texte standard (souligné au hover, couleur muted), pour les liens
   secondaires type « Voir tout → ». */
.isis-text-link {
    color: var(--isis-text-muted);
    font-size: 0.78rem;
    text-decoration: none;
}
.isis-text-link:hover,
.isis-text-link:focus-visible {
    text-decoration: underline;
    color: var(--isis-text);
}
/* Déconnexion : depuis 2026-07-17 l'endpoint /auth/logout est en POST + antiforgery
   (un GET permettait à un site tiers de déconnecter l'utilisateur à distance). Les
   anciens <a href="/auth/logout"> sont donc devenus des <form> à bouton unique. Ces
   règles rendent le bouton typographiquement identique au lien qu'il remplace — le
   correctif ne doit rien changer à l'écran. */
.isis-logout-form {
    display: inline;
}
button.isis-text-link {
    background: none;
    border: none;
    padding: 0;
    font: inherit;
    font-size: 0.78rem;
    cursor: pointer;
}
/* CP / RTT / REC : congés acquis → vert SIRH */
.isis-absence-pill.absence-type-cp,
.isis-absence-pill.absence-type-rtt,
.isis-absence-pill.absence-type-rec {
    background: var(--isis-mod-sirh-soft);
    color: var(--isis-text);
}
/* MAL : maladie → rouge danger soft */
.isis-absence-pill.absence-type-mal {
    background: var(--isis-danger-soft);
    color: var(--isis-text);
}
/* MAT / PAT : parentalité → accent soft */
.isis-absence-pill.absence-type-mat,
.isis-absence-pill.absence-type-pat {
    background: var(--isis-accent-soft);
    color: var(--isis-text);
}
/* EXC / FOR : exceptionnel/formation → warning soft */
.isis-absence-pill.absence-type-exc,
.isis-absence-pill.absence-type-for {
    background: var(--isis-warning-soft);
    color: var(--isis-text);
}
/* SOL : sans solde → neutre. Texte en --isis-text (pas --isis-text-muted) :
   #6b7280 sur #eef0f5 = 4.28:1, échoue WCAG AA texte (4.5:1). Le fond gris pâle
   garde l'identité « neutre » sans que le texte ne tombe sous le seuil. */
.isis-absence-pill.absence-type-sol {
    background: var(--isis-surface-alt);
    color: var(--isis-text);
}

/* ============================================================================
   .isis-absence-cal — calendrier mensuel des absences (vue Calendrier).
   Grille 7 colonnes (lundi-dimanche) × 5-6 lignes couvrant le mois.
   ============================================================================ */
.isis-absence-cal {
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius);
    overflow: hidden;
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-height: 0;
}
.isis-absence-cal__head {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    background: var(--isis-surface-alt);
    border-bottom: 1px solid var(--isis-border);
}
.isis-absence-cal__head-cell {
    padding: 0.5rem 0.75rem;
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--isis-text-soft);
    text-align: left;
    font-weight: 600;
}
.isis-absence-cal__body {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    overflow-y: auto;
    min-height: 0;
}
.isis-absence-cal__row {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    border-bottom: 1px solid var(--isis-border-soft);
    flex: 1 1 0;
    min-height: 96px;
}
.isis-absence-cal__row:last-child { border-bottom: none; }
.isis-absence-cal__cell {
    background: transparent;
    border: none;
    border-right: 1px solid var(--isis-border-soft);
    padding: 0.5rem 0.5rem 0.4rem;
    text-align: left;
    cursor: pointer;
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
    min-width: 0;
    transition: background-color 120ms ease;
}
.isis-absence-cal__cell:last-child { border-right: none; }
.isis-absence-cal__cell:hover { background: var(--isis-surface-alt); }
.isis-absence-cal__cell:focus-visible {
    outline: 2px solid var(--isis-accent);
    outline-offset: -2px;
}
.isis-absence-cal__cell.is-out { background: var(--isis-surface-alt); opacity: 0.55; }
.isis-absence-cal__cell.is-today .isis-absence-cal__cell-num {
    background: var(--isis-mod-sirh);
    color: white;
    border-radius: 50%;
    width: 22px; height: 22px;
    display: inline-flex;
    align-items: center; justify-content: center;
}
.isis-absence-cal__cell-num {
    font-size: 0.78rem;
    color: var(--isis-text-muted);
    font-weight: 500;
    font-variant-numeric: tabular-nums;
}
.isis-absence-cal__cell-badges {
    display: flex;
    flex-wrap: wrap;
    gap: 0.2rem;
    align-items: center;
}
.isis-absence-cal__chip {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 22px;
    padding: 0 0.3rem;
    height: 18px;
    border-radius: 4px;
    font-size: 0.65rem;
    font-weight: 600;
    color: var(--isis-text);
    text-transform: uppercase;
    letter-spacing: 0.02em;
}
.isis-absence-cal__chip.is-overflow {
    background: var(--isis-surface-alt);
    color: var(--isis-text-muted);
    font-size: 0.6rem;
}

/* Chip statique (libellé mois dans la nav calendrier) — non cliquable. */
.isis-chip.is-static {
    cursor: default;
    background: var(--isis-surface);
    color: var(--isis-text);
    font-weight: 500;
    pointer-events: none;
}

/* Pages paramètres absences : grilles read-only. */
.isis-grid--absence-types .isis-grid__head,
.isis-grid--absence-types .isis-grid__row {
    grid-template-columns: 90px 70px minmax(160px, 1.5fr) 90px 60px 130px 130px 110px;
    min-width: 920px;
}
.isis-grid--accrual-rules .isis-grid__head,
.isis-grid--accrual-rules .isis-grid__row {
    grid-template-columns: 90px minmax(150px, 1.3fr) 130px 130px 110px 110px 130px;
    min-width: 860px;
}
.isis-grid--holidays .isis-grid__head,
.isis-grid--holidays .isis-grid__row {
    grid-template-columns: 130px 110px minmax(220px, 1.5fr) 140px;
    min-width: 640px;
}
.isis-grid--poste .isis-grid__head,
.isis-grid--poste .isis-grid__row {
    grid-template-columns: 130px minmax(150px, 1.1fr) minmax(160px, 1.4fr) minmax(190px, 1.7fr) 70px 130px;
    min-width: 920px;
}

/* Niveaux requis : tags compacts (compétence + niveau) dans la grille + le sidepanel */
.isis-poste-requis-cell { display: flex; flex-wrap: wrap; gap: 4px; align-items: center; }
.isis-niv-tag {
    display: inline-flex; align-items: center; gap: 4px;
    background: var(--isis-surface-alt, #f4f6f6); border: 1px solid var(--isis-border, #e6e8ea);
    border-radius: 999px; padding: 1px 4px 1px 8px; max-width: 100%;
}
.isis-niv-tag__lbl {
    font-size: 11.5px; color: var(--isis-text, #1a1f24);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 130px;
}
.isis-niv-tag__lvl {
    font-size: 10px; font-weight: 600; border-radius: 999px; padding: 1px 7px; line-height: 1.5;
    background: var(--isis-lvl-1); color: var(--isis-lvl-1-ink);
}
.isis-niv-tag__lvl.is-l1 { background: var(--isis-lvl-1); color: var(--isis-lvl-1-ink); }
.isis-niv-tag__lvl.is-l2 { background: var(--isis-lvl-2); color: var(--isis-lvl-2-ink); }
.isis-niv-tag__lvl.is-l3 { background: var(--isis-lvl-3); color: var(--isis-lvl-3-ink); }
.isis-niv-tag__lvl.is-l4 { background: var(--isis-lvl-4); color: var(--isis-lvl-4-ink); }
.isis-niv-tag__more {
    font-size: 11px; font-weight: 600; color: var(--isis-text-muted, #6b7480);
    background: var(--isis-surface-alt, #f4f6f6); border: 1px solid var(--isis-border, #e6e8ea);
    border-radius: 999px; padding: 1px 8px;
}

/* === Frise de progression d'une compétence (CompetenceProgressionDialog) === */
.isis-progression-dialog {
    /* Pas de padding propre : .rz-dialog-content en applique déjà 24px (sinon cumul). */
    display: block; padding: 0;
    max-height: min(70vh, 600px); overflow-y: auto;
}
.isis-progression__loading { display: flex; justify-content: center; padding: 2rem 0; }
.isis-progression__empty {
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 0.5rem; padding: 2rem 1rem; text-align: center;
    color: var(--isis-text-muted, #6b7480); font-size: 0.85rem;
}
.isis-progression__empty .rzi { font-size: 32px; opacity: 0.4; }
.isis-progression__empty strong { color: var(--isis-text, #1f2933); font-size: 0.9rem; }
.isis-progression {
    list-style: none; margin: 0; padding: 0;
    display: flex; flex-direction: column;
}
.isis-progression__row { display: flex; gap: 0.75rem; align-items: stretch; }
.isis-progression__rail {
    position: relative; flex: 0 0 14px;
    display: flex; justify-content: center;
}
/* Trait vertical reliant les points */
.isis-progression__rail::before {
    content: ""; position: absolute; top: 0; bottom: 0; left: 50%;
    width: 2px; transform: translateX(-50%);
    background: var(--isis-border, #e6e8ea);
}
.isis-progression__row:first-child .isis-progression__rail::before { top: 0.55rem; }
.isis-progression__row:last-child  .isis-progression__rail::before { bottom: calc(100% - 0.55rem); }
.isis-progression__dot {
    position: relative; z-index: 1; margin-top: 0.45rem;
    width: 10px; height: 10px; border-radius: 999px;
    background: var(--isis-current-mod, var(--isis-accent, #4f6470));
    box-shadow: 0 0 0 2px var(--isis-surface, #fff);
}
.isis-progression__body { flex: 1 1 auto; padding: 0.3rem 0 0.85rem; min-width: 0; }
.isis-progression__line {
    display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap;
}
.isis-progression__date {
    font-size: 0.78rem; color: var(--isis-text-muted, #6b7480);
    font-variant-numeric: tabular-nums;
}
.isis-progression__evt {
    display: inline-flex; align-items: center; gap: 0.25rem;
    font-size: 0.85rem; font-weight: 600; color: var(--isis-text, #1f2933);
}
.isis-progression__transition {
    display: flex; align-items: center; gap: 0.4rem; flex-wrap: wrap;
    margin-top: 0.35rem;
}
.isis-progression__lvl {
    display: inline-flex; align-items: center;
    font-size: 0.75rem; font-weight: 600; line-height: 1;
    padding: 3px 9px; border-radius: 999px;
    background: var(--isis-lvl-1); color: var(--isis-lvl-1-ink);
}
.isis-progression__lvl.is-l1 { background: var(--isis-lvl-1); color: var(--isis-lvl-1-ink); }
.isis-progression__lvl.is-l2 { background: var(--isis-lvl-2); color: var(--isis-lvl-2-ink); }
.isis-progression__lvl.is-l3 { background: var(--isis-lvl-3); color: var(--isis-lvl-3-ink); }
.isis-progression__lvl.is-l4 { background: var(--isis-lvl-4); color: var(--isis-lvl-4-ink); }
.isis-progression__lvl.is-unknown { background: var(--isis-border, #e6e8ea); color: var(--isis-text-muted, #6b7480); }
.isis-progression__evt.is-evt-ok     { color: var(--isis-success, #15803d); }
.isis-progression__evt.is-evt-warn   { color: var(--isis-warning, #8f5700); }
.isis-progression__evt.is-evt-danger { color: var(--isis-danger,  #a51b1b); }
.isis-progression__lvl.is-muted { opacity: 0.65; }
.isis-progression__lvl.is-struck { text-decoration: line-through; }
.isis-progression__meta {
    display: flex; align-items: baseline; gap: 0.5rem; flex-wrap: wrap;
    margin-top: 0.35rem;
}
.isis-progression__source {
    font-size: 0.75rem; font-weight: 600; color: var(--isis-text-muted, #6b7480);
}
.isis-progression__note {
    font-size: 0.78rem; color: var(--isis-text-muted, #6b7480);
}

/* Section niveaux requis dans le sidepanel poste */
.isis-poste-requis { display: flex; flex-direction: column; gap: 0.5rem; }
.isis-poste-requis__head { display: flex; align-items: center; gap: 0.5rem; }
.isis-poste-requis .isis-detail-section-title {
    font-size: 11.5px; text-transform: uppercase; letter-spacing: .04em;
    color: var(--isis-text-muted, #6b7480); font-weight: 600;
}
/* Pastille d'effectif à côté du titre de section — même habillage que
   .isis-rich-header__pill (bandeau retiré, nom dédié : G7, 2026-09-04). */
.isis-detail-section-title__count {
    display: inline-flex;
    align-items: center;
    padding: 0.2rem 0.6rem;
    border-radius: var(--isis-radius-pill);
    font-size: 0.72rem;
    font-weight: 500;
    background: var(--isis-current-mod-soft, var(--isis-accent-soft));
    color: var(--isis-current-mod, var(--isis-accent));
}
.isis-poste-requis__list { display: flex; flex-direction: column; }
.isis-poste-requis__row {
    display: flex; align-items: center; justify-content: space-between; gap: 0.5rem;
    padding: 5px 0; border-bottom: 1px solid var(--isis-border-2, #eef0f1);
}
.isis-poste-requis__comp { font-size: 12.5px; color: var(--isis-text, #1a1f24); }

/* ============================================================================
   .isis-requis-* — éditeur des niveaux de compétence requis par poste
   (SIRH /sirh/parametres/postes/{id}/requis). Liste plate groupée par catégorie.
   ============================================================================ */
.isis-requis-group { border-top: 1px solid var(--isis-border); }
.isis-requis-group:first-child { border-top: 0; }
.isis-requis-group__title {
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--isis-text-muted);
    padding: 0.7rem 1rem 0.4rem;
    background: var(--isis-surface-2, var(--isis-surface));
}
.isis-requis-row {
    display: grid;
    grid-template-columns: minmax(200px, 1fr) 220px 130px;
    align-items: center;
    gap: 1rem;
    padding: 0.45rem 1rem;
    border-top: 1px solid var(--isis-border);
}
/* Case « bloquante » d'une exigence (visible seulement quand une cible est posée). */
.isis-requis-row__bloq {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    font-size: 0.78rem;
    color: var(--isis-text-muted);
    cursor: pointer;
    user-select: none;
    margin: 0;
}
.isis-requis-row__bloq.is-on { color: var(--isis-danger); font-weight: 600; }
.isis-requis-row__bloq input { accent-color: var(--isis-danger); }

/* === Bloc « Adéquation au poste » (fiche collaborateur, P2) ============== */
.isis-adequacy {
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-sm, 6px);
    background: var(--isis-surface, #fff);
    padding: 12px 14px;
    margin: 0 0 14px;
}
.isis-adequacy.is-inapte { border-left-color: var(--isis-danger); }
.isis-adequacy__head {
    display: flex; align-items: center; justify-content: space-between;
    gap: 12px; flex-wrap: wrap;
}
.isis-adequacy__title { font-size: 13px; color: var(--isis-text-muted); }
.isis-adequacy__score { display: inline-flex; align-items: center; gap: 8px; }
.isis-adequacy__pct { font-size: 18px; font-weight: 700; font-variant-numeric: tabular-nums; }
.isis-adequacy__bar {
    height: 6px; border-radius: 999px; background: var(--isis-surface-alt, #eef0f2);
    overflow: hidden; margin: 8px 0 4px;
}
.isis-adequacy__bar > span { display: block; height: 100%; border-radius: 999px; background: var(--isis-success); transition: width 200ms ease; }
.isis-adequacy.is-inapte .isis-adequacy__bar > span { background: var(--isis-danger); }
.isis-adequacy__ok { font-size: 12.5px; color: var(--isis-success); margin-top: 2px; }
.isis-adequacy__gaps { list-style: none; margin: 8px 0 0; padding: 0; display: flex; flex-direction: column; gap: 4px; }
.isis-adequacy__gaps li {
    display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
    font-size: 12.5px; padding: 4px 8px; border-radius: 5px; background: var(--isis-surface-alt, #f6f7f8);
}
.isis-adequacy__gaps li.is-bloquant { background: color-mix(in srgb, var(--isis-danger) 8%, var(--isis-surface)); }
.isis-adequacy__gap-type { font-weight: 600; color: var(--isis-warning); min-width: 84px; }
.isis-adequacy__gaps li.is-bloquant .isis-adequacy__gap-type { color: var(--isis-danger); }
.isis-adequacy__gap-comp { font-weight: 600; color: var(--isis-text); }
.isis-adequacy__gap-niv { color: var(--isis-text-muted); }
.isis-adequacy__gap-bloq {
    margin-left: auto; font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em;
    color: var(--isis-danger); border: 1px solid color-mix(in srgb, var(--isis-danger) 40%, transparent);
    border-radius: 999px; padding: 1px 7px;
}

/* === Liste « Adéquation des collaborateurs » (fiche poste, P2) =========== */
.isis-candidats { margin-top: 18px; }
.isis-candidats__title {
    font-size: 14px; font-weight: 700; color: var(--isis-text);
    display: flex; align-items: center; gap: 10px; margin: 0 0 10px;
}
.isis-candidats__count { font-size: 12px; font-weight: 600; color: var(--isis-text-muted); }
.isis-candidats__list { display: flex; flex-direction: column; gap: 6px; }
.isis-candidat {
    display: grid;
    grid-template-columns: minmax(140px, 1.4fr) minmax(120px, 2fr) 48px auto auto;
    align-items: center; gap: 12px;
    padding: 8px 12px; border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-sm, 6px); background: var(--isis-surface, #fff);
}
.isis-candidat.is-inapte { border-left-color: var(--isis-danger); }
.isis-candidat__name { font-weight: 600; color: var(--isis-text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.isis-candidat__bar { height: 6px; border-radius: 999px; background: var(--isis-surface-alt, #eef0f2); overflow: hidden; }
.isis-candidat__bar > span { display: block; height: 100%; border-radius: 999px; background: var(--isis-success); }
.isis-candidat.is-inapte .isis-candidat__bar > span { background: var(--isis-danger); }
.isis-candidat__pct { font-variant-numeric: tabular-nums; font-weight: 700; font-size: 13px; text-align: right; }
.isis-candidat__bloq {
    font-size: 11px; font-weight: 700; color: var(--isis-danger);
    border: 1px solid color-mix(in srgb, var(--isis-danger) 40%, transparent);
    border-radius: 999px; padding: 1px 8px; white-space: nowrap;
}

/* === Liste « Risque de staffing » (avis de la fiche commande, P3) ======= */
.isis-staffing-risk__list {
    margin: 4px 0 0; padding-left: 18px; font-size: 13px; color: var(--isis-text);
    display: flex; flex-direction: column; gap: 2px;
}
.isis-staffing-risk__gaps { color: var(--isis-text-muted); }
.isis-requis-row__label {
    font-size: 0.875rem;
    color: var(--isis-text);
    margin: 0;
}
.isis-requis-row__select {
    width: 100%;
    height: 34px;
    padding: 0 0.6rem;
    font: inherit;
    font-size: 0.85rem;
    color: var(--isis-text);
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-sm);
}
.isis-requis-row__select:focus-visible {
    outline: 2px solid color-mix(in oklch, var(--isis-current-mod) 55%, transparent);
    outline-offset: 1px;
    border-color: var(--isis-current-mod);
}

/* ============================================================================
   .isis-notif-list — liste de notifications dans MonEspace.
   ============================================================================ */
.isis-notif-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
}
.isis-notif-list__item {
    border: 1px solid var(--isis-border-soft);
    border-radius: 6px;
    transition: background-color 120ms ease;
}
.isis-notif-list__item.is-unread {
    background: var(--isis-mod-sirh-soft);
    border: 1px solid var(--isis-mod-sirh);
    box-sizing: border-box;
}
.isis-notif-list__item.is-read { opacity: 0.75; }
.isis-notif-list__btn {
    display: flex;
    align-items: flex-start;
    gap: 0.6rem;
    width: 100%;
    padding: 0.6rem 0.85rem;
    background: transparent;
    border: none;
    text-align: left;
    cursor: pointer;
    border-radius: 6px;
    font-family: inherit;
    color: var(--isis-text);
}
.isis-notif-list__btn:hover { background: var(--isis-surface-alt); }
.isis-notif-list__btn:focus-visible {
    outline: 2px solid var(--isis-accent);
    outline-offset: -2px;
}
.isis-notif-list__main { flex: 1; min-width: 0; }
.isis-notif-list__title {
    font-weight: 600;
    font-size: 0.88rem;
    color: var(--isis-text);
    margin-bottom: 0.15rem;
}
.isis-notif-list__body {
    font-size: 0.82rem;
    color: var(--isis-text);
    margin-bottom: 0.25rem;
}
.isis-notif-list__meta {
    font-size: 0.7rem;
    color: var(--isis-text-soft);
}
.isis-notif-list__dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--isis-mod-sirh);
    flex-shrink: 0;
    margin-top: 0.4rem;
}

/* ============================================================================
   Recherche transverse Gescom — .isis-grid--gescom-search + ctx-* + pagination
   ============================================================================ */

/* Grille : 9 colonnes — status / contexte / élément / référence / tiers /
   montant / statut / date / actions. Min-width généreux pour conserver la
   lisibilité de chaque colonne avant scroll horizontal. */
.isis-grid--gescom-search .isis-grid__head,
.isis-grid--gescom-search .isis-grid__row {
    grid-template-columns: 32px 150px minmax(220px, 1.6fr) 120px minmax(140px, 1.1fr) 120px 110px 100px 60px;
    min-width: 1180px;
}
.isis-grid--gescom-search .isis-grid__col-amount {
    text-align: right;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}
.isis-grid__cell-hint {
    font-size: 0.7rem;
    color: var(--isis-text-soft);
    line-height: 1.25;
    margin-top: 0.15rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.isis-grid__code-mono {
    font-family: 'Geist Mono', ui-monospace, monospace;
    font-size: 0.78rem;
    color: var(--isis-text);
}
.isis-grid__context-tag {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0.1rem 0.45rem;
    border-radius: var(--isis-radius-pill);
    background: var(--isis-surface-alt);
    color: var(--isis-text);
    font-size: 0.72rem;
    line-height: 1.6;
    white-space: nowrap;
}
/* Couleur de chaque contexte — uniquement des vars définies dans :root.
   Fonds = color-mix() à 14-18% sur transparent → pastel ; couleurs texte saturées.
   Contraste : composant graphique (WCAG 1.4.11 = 3:1), pas texte courant 4.5:1. */
.isis-grid__context-tag.ctx-devis           { background: color-mix(in srgb, var(--isis-mod-gescom) 14%, transparent);    color: var(--isis-mod-gescom); }
.isis-grid__context-tag.ctx-tiers           { background: color-mix(in srgb, var(--isis-accent) 14%, transparent);        color: var(--isis-accent); }
.isis-grid__context-tag.ctx-demande-client  { background: color-mix(in srgb, var(--isis-success) 14%, transparent);       color: var(--isis-success); }
.isis-grid__context-tag.ctx-appel-offre     { background: color-mix(in srgb, var(--isis-warning) 16%, transparent);       color: var(--isis-warning); }
.isis-grid__context-tag.ctx-marche          { background: color-mix(in srgb, var(--isis-mod-gescompta) 14%, transparent); color: var(--isis-mod-gescompta); }
.isis-grid__context-tag.ctx-commande        { background: color-mix(in srgb, var(--isis-mod-gesproj) 14%, transparent);   color: var(--isis-mod-gesproj); }
.isis-grid__context-tag.ctx-document        { background: color-mix(in srgb, var(--isis-danger) 14%, transparent);        color: var(--isis-danger); }
.isis-grid__context-tag.ctx-livraison       { background: color-mix(in srgb, var(--isis-accent) 14%, transparent);        color: var(--isis-accent); }
.isis-grid__context-tag.ctx-note-frais      { background: color-mix(in srgb, var(--isis-warning) 16%, transparent);       color: var(--isis-warning); }

/* ============================================================================
   Recherche transverse Gesproj — .isis-grid--gesproj-search
   Même layout 9 colonnes que .isis-grid--gescom-search (calque migration 0377).
   ============================================================================ */
.isis-grid--gesproj-search .isis-grid__head,
.isis-grid--gesproj-search .isis-grid__row {
    grid-template-columns: 32px 150px minmax(220px, 1.6fr) 120px minmax(140px, 1.1fr) 120px 110px 100px 60px;
    min-width: 1180px;
}
.isis-grid--gesproj-search .isis-grid__col-amount {
    text-align: right;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}
/* Nom non-cliquable (note de frais — pas de fiche détail V1). */
/* Nom d'élément cliquable dans une grille. La règle vivait dans un <style> LOCAL à
   /ged/documents alors que quatre pages emploient la classe : ailleurs, le <button> se
   rendait avec le style natif du navigateur — fond gris, bordure, et surtout aucune
   troncature, donc un libellé coupé en plein mot par le bord de sa cellule (relevé au
   navigateur sur /gesproj/recherche le 2026-09-02). */
.docgrid-name {
    background: transparent;
    border: 0;
    padding: 0;
    cursor: pointer;
    font-weight: 500;
    color: var(--isis-text);
    text-align: left;
    min-width: 0;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.docgrid-name:hover { color: var(--isis-accent); text-decoration: underline; }
.docgrid-name:focus-visible {
    outline: 2px solid var(--isis-current-mod, var(--isis-accent));
    outline-offset: 2px;
    border-radius: 2px;
}
.docgrid-name--static {
    cursor: default;
    color: var(--isis-text);
    font-weight: 500;
}
.docgrid-name--static:hover { color: var(--isis-text); text-decoration: none; }

/* Pied de grille — pagination. Padding/border conformes au pattern grille. */
.isis-grid__foot {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 0.5rem;
    padding: 0.5rem 0.75rem;
    border-top: 1px solid var(--isis-border);
    background: var(--isis-surface);
    font-size: 0.75rem;
    color: var(--isis-text-muted);
}
.isis-grid__foot-label { margin-right: auto; }
.isis-grid__page-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    border: 1px solid var(--isis-border);
    background: var(--isis-surface);
    border-radius: 6px;
    cursor: pointer;
    color: var(--isis-text);
}
.isis-grid__page-btn:hover:not([disabled]) { background: var(--isis-bg-soft, var(--isis-surface-alt)); }
.isis-grid__page-btn:focus-visible {
    outline: 2px solid var(--isis-accent);
    outline-offset: 1px;
}
.isis-grid__page-btn[disabled] {
    opacity: 0.45;
    cursor: not-allowed;
}
.isis-grid__page-btn[disabled]:focus-visible {
    outline: none;
}

/* Sous-bandeau filter-bar — moins appuyé que la barre principale */
.isis-filter-bar.isis-filter-bar--sub {
    background: transparent;
    border-top: none;
    padding-top: 0.25rem;
}

/* Sous-chips du drill-down statut (niveau 2) : plus petits / discrets que les chips de phase. */
.isis-chip.isis-chip--sub {
    font-size: 0.78rem;
    padding: 0.2rem 0.6rem;
}

/* Récap des filtres actifs dans le slot Filter du sidepanel */
.isis-filter-summary {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
    font-size: 0.82rem;
    color: var(--isis-text);
}
.isis-filter-summary li strong {
    font-weight: 600;
    color: var(--isis-text-muted);
    margin-right: 0.35rem;
}

/* Groupe d'inputs dans la filter-bar (dates, tri) */
.isis-filter-bar__group {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    flex-wrap: wrap;
}

/* Aperçu de l'élément sélectionné dans le sidepanel */
.isis-detail-description {
    font-size: 0.82rem;
    color: var(--isis-text);
    line-height: 1.5;
    padding: 0.5rem 0.6rem;
    background: var(--isis-surface-alt);
    border-radius: 6px;
    border: 1px solid var(--isis-border);
    box-sizing: border-box;
}
.isis-detail-field {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
}
.isis-detail-field__label {
    font-size: 0.68rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--isis-text-soft);
}
.isis-detail-field__value {
    font-size: 0.85rem;
    color: var(--isis-text);
}

/* ============================================================================
   Aide templates (gescom/parametres/templates/aide)
   ============================================================================ */
.isis-tpl-help {
    display: flex;
    flex-direction: column;
    gap: 1.5rem;
    width: 100%;
    /* .isis-rich-page parent impose height:100% + overflow:hidden — le contenu
       long de cette page d'aide ne peut scroller qu'en devenant lui-même le
       scroll container (calque .isis-help-page §14912). */
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    padding-right: 0.5rem;
}
.isis-tpl-help__section {
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: 6px;
    padding: 1.2rem 1.5rem;
}
.isis-tpl-help__section > h2 {
    font-size: 1.05rem;
    font-weight: 600;
    color: var(--isis-text);
    margin: 0 0 0.8rem 0;
    padding-bottom: 0.5rem;
    border-bottom: 1px solid var(--isis-border);
}
.isis-tpl-help__section h3 {
    font-size: 0.95rem;
    font-weight: 600;
    color: var(--isis-text);
    margin: 1.1rem 0 0.4rem 0;
}
.isis-tpl-help__section h4 {
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--isis-text-muted);
    margin: 0.75rem 0 0.3rem 0;
    text-transform: uppercase;
    letter-spacing: 0.04em;
}
.isis-tpl-help__section p,
.isis-tpl-help__section li {
    font-size: 0.85rem;
    color: var(--isis-text);
    line-height: 1.55;
}
.isis-tpl-help__section p { margin: 0 0 0.5rem 0; }
.isis-tpl-help__section ul,
.isis-tpl-help__section ol {
    margin: 0 0 0.8rem 0;
    padding-left: 1.2rem;
}
.isis-tpl-help__section ul li { margin-bottom: 0.15rem; }
.isis-tpl-help__section ol li { margin-bottom: 0.3rem; }
.isis-tpl-help__section code {
    font-family: 'Geist Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 0.78rem;
    background: var(--isis-surface-alt);
    border: 1px solid var(--isis-border);
    border-radius: 3px;
    padding: 0.05rem 0.35rem;
    color: var(--isis-text);
}
.isis-tpl-help__code {
    font-family: 'Geist Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 0.78rem;
    background: var(--isis-surface-alt);
    border: 1px solid var(--isis-border);
    border-radius: 4px;
    padding: 0.6rem 0.85rem;
    margin: 0.3rem 0 0.8rem 0;
    overflow-x: auto;
    line-height: 1.5;
    color: var(--isis-text);
    white-space: pre;
}
.isis-tpl-help__hint {
    display: flex;
    align-items: flex-start;
    gap: 0.4rem;
    padding: 0.45rem 0.7rem;
    background: var(--isis-surface-alt);
    border: 1px solid var(--isis-text-muted);
    box-sizing: border-box;
    border-radius: 3px;
    font-size: 0.78rem;
    color: var(--isis-text-muted);
    margin: 0.3rem 0 0.6rem 0;
}
.isis-tpl-help__hint .rzi { margin-top: 0.1rem; flex-shrink: 0; }
.isis-tpl-help__table {
    width: 100%;
    border-collapse: collapse;
    margin: 0.4rem 0 0.8rem 0;
    font-size: 0.82rem;
}
.isis-tpl-help__table th,
.isis-tpl-help__table td {
    padding: 0.4rem 0.6rem;
    text-align: left;
    border-bottom: 1px solid var(--isis-border);
    vertical-align: top;
}
.isis-tpl-help__table th {
    background: var(--isis-surface-alt);
    font-weight: 600;
    color: var(--isis-text);
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.03em;
}
.isis-tpl-help__table--catalog tbody tr:hover {
    background: var(--isis-surface-alt);
}
.isis-tpl-help__group {
    display: flex;
    align-items: baseline;
    gap: 0.5rem;
    margin: 1.1rem 0 0.4rem 0;
    font-size: 0.88rem;
    font-weight: 600;
}
.isis-tpl-help__group code {
    color: var(--isis-current-mod, var(--isis-accent));
    background: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 14%, var(--isis-surface));
    border-color: var(--isis-current-mod, var(--isis-accent));
}
.isis-tpl-help__group-hint {
    font-weight: 400;
    font-size: 0.78rem;
    color: var(--isis-text-muted);
    font-style: italic;
}
.isis-tpl-help__sample {
    color: var(--isis-text-muted);
    font-style: italic;
    font-size: 0.78rem;
}

/* ============================================================================
   .isis-params-help — panneau d'aide rétractable « Paramètres disponibles »
   Utilisé par ModelesFacturePage.razor (et pages similaires).
   Disclosure pattern : <details>/<summary> natif (nativement keyboard-accessible).
   ============================================================================ */
.isis-params-help {
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius, 8px);
    background: var(--isis-surface);
    overflow: hidden;
}
.isis-params-help__toggle {
    display: flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0.75rem 1rem;
    cursor: pointer;
    font-size: 0.88rem;
    font-weight: 600;
    color: var(--isis-text);
    list-style: none;
    user-select: none;
    background: var(--isis-surface-alt);
    border-bottom: 1px solid transparent;
    transition: background 0.15s ease;
}
.isis-params-help__toggle::-webkit-details-marker { display: none; }
.isis-params-help__toggle::marker { display: none; }
.isis-params-help__toggle:hover {
    background: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 6%, var(--isis-surface-alt));
}
.isis-params-help[open] > .isis-params-help__toggle {
    border-bottom-color: var(--isis-border);
}
.isis-params-help[open] .isis-params-help__chevron {
    transform: rotate(180deg);
}
.isis-params-help__chevron {
    transition: transform 0.2s ease;
}
.isis-params-help__body {
    padding: 1rem 1.25rem 1.25rem;
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}
.isis-params-help__body .isis-tpl-help__section {
    border: none;
    padding: 0;
    background: transparent;
}
.isis-params-help__body .isis-tpl-help__section:not(:last-child) {
    padding-bottom: 1rem;
    border-bottom: 1px solid var(--isis-border);
}
/* Hint d'intro du catalogue de marqueurs — espacement avant les sections. */
.isis-params-help__body .isis-tpl-help__hint--intro {
    margin-bottom: 1rem;
}
/* Largeurs de colonnes des tables-catalogue (marqueur / libellé / exemple / action). */
.isis-params-help .isis-tpl-help__table--catalog th:nth-child(1) { width: 32%; }
.isis-params-help .isis-tpl-help__table--catalog th:nth-child(2) { width: 35%; }
.isis-params-help .isis-tpl-help__table--catalog th:nth-child(4) { width: 36px; }

/* ============================================================================
   .isis-grid--mail-template — liste modèles de réponse admin (4 colonnes)
   Colonnes : nom | objet | statut | actions
   ============================================================================ */
.isis-grid--mail-template .isis-grid__head,
.isis-grid--mail-template .isis-grid__row {
    grid-template-columns: minmax(180px, 1.2fr) minmax(220px, 1.8fr) 90px 90px;
    min-width: 580px;
}

/* ============================================================================
   .isis-grid--jour-ferie — liste jours fériés admin (5 colonnes)
   Colonnes : pays | date | libellé | notes | actions
   ============================================================================ */
/* Pays passe de 80 à 110 px et Date de 110 à 130 depuis le 2026-09-06 : leurs en-têtes
   portent désormais un bouton de tri ET un entonnoir. */
.isis-grid--jour-ferie .isis-grid__head,
.isis-grid--jour-ferie .isis-grid__row {
    grid-template-columns: 110px 130px minmax(200px, 1.5fr) minmax(180px, 1fr) 90px;
}

/* ============================================================================
   .isis-grid--taux-horaire — liste taux horaires sirh dual-owner (6 colonnes)
   Colonnes : périmètre | owner | taux | période | statut | actions
   ============================================================================ */
.isis-grid--taux-horaire .isis-grid__head,
.isis-grid--taux-horaire .isis-grid__row {
    grid-template-columns: 120px minmax(220px, 1.6fr) 160px minmax(180px, 1fr) 100px 90px;
}

/* ============================================================================
   .isis-grid--fiche-temps — liste saisies de temps gesproj (6 colonnes)
   Colonnes : date | commande·tâche | heures | statut | taux figé | actions
   ============================================================================ */
.isis-grid--fiche-temps .isis-grid__head,
.isis-grid--fiche-temps .isis-grid__row {
    grid-template-columns: 110px minmax(260px, 1.6fr) 100px 160px 140px 130px;
}

/* ============================================================================
   .isis-grid--fiche-temps-validation — page validation manager/CP (6 colonnes)
   Colonnes : date | collab | commande·tâche | heures | taux figé | actions
   ============================================================================ */
.isis-grid--fiche-temps-validation .isis-grid__head,
.isis-grid--fiche-temps-validation .isis-grid__row {
    grid-template-columns: 90px minmax(180px, 1fr) minmax(280px, 1.8fr) 90px 140px 110px;
}

/* ============================================================================
   .isis-grid--mobilisations — onglet Mobilisations sur fiche commande (6 col).
   Colonnes : collaborateur | tâche·rôle | période | charge | notes | actions
   Modificateur is-active-period : liseré accent gauche pour les mobilisations
   actives à la date du jour (signal visuel rapide pour le CP).
   ============================================================================ */
.isis-grid--mobilisations .isis-grid__head,
.isis-grid--mobilisations .isis-grid__row {
    grid-template-columns: minmax(180px, 1fr) minmax(220px, 1.4fr) 170px 110px minmax(140px, 1.2fr) 100px;
}
.isis-grid--mobilisations .isis-grid__row.is-active-period {
    background: var(--isis-mod-gesproj-soft);
}


/* ============================================================================
   Cartes tâches sur fiche commande (onglet Tâches, Phase 4) — Flat Design
   ============================================================================ */
.isis-tache-card {
    border: 1px solid var(--isis-border);
    border-radius: 6px;
    padding: 0.7rem 0.85rem;
    background: white;
}
.isis-tache-card__head {
    display: flex;
    align-items: baseline;
    gap: 0.55rem;
    margin-bottom: 0.4rem;
}
.isis-tache-card__pos {
    color: var(--isis-text-muted);
    font-variant-numeric: tabular-nums;
    font-size: 0.85rem;
    min-width: 1.8rem;
}
.isis-tache-card__title {
    flex: 1 1 auto;
    font-size: 0.95rem;
}
.isis-tache-card__meta {
    color: var(--isis-text);
    font-size: 0.85rem;
    font-variant-numeric: tabular-nums;
}
.isis-tache-card__empty,
.isis-tache-card__notes {
    color: var(--isis-text-muted);
    font-size: 0.83rem;
    padding: 0.25rem 0;
}
.isis-tache-besoins {
    display: grid;
    grid-template-columns: minmax(120px,1fr) 4.5rem 3rem minmax(150px,1.6fr) minmax(84px,7rem) minmax(84px,8rem) minmax(60px,1fr) 4.5rem;
    gap: 0.35rem 1rem;
    margin-top: 0.4rem;
    padding: 0.4rem 0;
    border-top: 1px solid var(--isis-border);
    font-size: 0.85rem;
    min-width: 0;
}
.isis-tache-besoins__head { display: contents; }
.isis-tache-besoins__head > div {
    font-weight: 600;
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--isis-text-muted);
    padding-bottom: 0.2rem;
    border-bottom: 1px solid var(--isis-border);
}
.isis-tache-besoins__row { display: contents; }
.isis-tache-besoins__actions {
    display: flex;
    gap: 0.25rem;
    justify-content: flex-end;
    align-items: center;
}

/* Mobilisations rattachées à une tâche — bloc sous-tâche (calque tache-besoins). */
.isis-tache-mobilisations {
    display: grid;
    /* Collaborateur | Profil besoin | Période | Jours alloués | Coût prévu | Coût réel | Frais | Notes | Actions */
    grid-template-columns: 1.4fr 1fr 1.6fr 5rem 6rem 6rem 6rem 1.2fr 4.5rem;
    gap: 0.35rem 1rem;
    margin-top: 0.4rem;
    padding: 0.4rem 0;
    border-top: 1px solid var(--isis-border);
    font-size: 0.85rem;
    min-width: 0;
    overflow-x: auto;
}
/* Même règle que la grille des tâches : sans le droit au coût, les trois colonnes
   Coût prévu | Coût réel | Frais ne sont pas rendues, le gabarit en compte six.
   Le head-label et les blocs pleine largeur suivent par `1 / -1`, rien d'autre à reprendre. */
.isis-tache-mobilisations--sans-cout {
    grid-template-columns: 1.4fr 1fr 1.6fr 5rem 1.2fr 4.5rem;
}
.isis-tache-mobilisations__head-label {
    grid-column: 1 / -1;
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--isis-text-muted);
    padding: 0.2rem 0 0.1rem 0;
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
}
.isis-tache-mobilisations__head { display: contents; }
.isis-tache-mobilisations__head > div {
    font-weight: 600;
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--isis-text-muted);
    padding-bottom: 0.2rem;
    border-bottom: 1px solid var(--isis-border);
}
.isis-tache-mobilisations__row { display: contents; }
.isis-tache-mobilisations__equip-row {
    grid-column: 1 / -1;
    padding: 0.15rem 0 0.3rem 0;
    border-bottom: 1px dashed var(--isis-border);
}
.isis-tache-mobilisations__actions {
    display: flex;
    gap: 0.25rem;
    justify-content: flex-end;
    align-items: center;
}

/* Audit ui-ux Phase 4 — colonnes pré-stylées extraites des styles inline (DESIGN.md §10). */
.isis-tache-mobilisations__col-periode {
    font-variant-numeric: tabular-nums;
    color: var(--isis-text-muted);
    font-size: 0.85rem;
}
.isis-tache-mobilisations__col-periode-days {
    color: var(--isis-text-muted);
    margin-left: 0.4rem;
}
.isis-tache-mobilisations__col-charge {
    text-align: right;
    font-variant-numeric: tabular-nums;
}
.isis-tache-mobilisations__col-notes {
    color: var(--isis-text-muted);
    font-size: 0.85rem;
}
.isis-tache-mobilisations__col-cout {
    text-align: right;
    font-variant-numeric: tabular-nums;
    color: var(--isis-text);
    font-size: 0.85rem;
}
.isis-tache-mobilisations__head-label .rz-icon {
    font-size: 14px;
    vertical-align: middle;
    opacity: 0.6;
}
.isis-tache-card__add-btn {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    margin-left: auto;
    padding: 0.15rem 0.5rem;
    background: transparent;
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-pill);
    font-size: 0.75rem;
    color: var(--isis-text-muted);
    cursor: pointer;
    transition: background 0.12s, color 0.12s, border-color 0.12s;
}
.isis-tache-card__add-btn:hover:not(:disabled) {
    background: var(--isis-mod-gesproj-soft);
    color: var(--isis-mod-gesproj);
    border-color: var(--isis-mod-gesproj);
}
.isis-tache-card__add-btn:focus-visible {
    outline: 2px solid var(--isis-mod-gesproj);
    outline-offset: 2px;
}
.isis-tache-card__add-btn:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}


/* ============================================================================
   Page d'aide module Gescom (AideGescomPage)
   Layout 2-col : sidebar TOC sticky à gauche, contenu scrollable à droite.
   ----------------------------------------------------------------------------
   Note scroll : .isis-rich-page parent impose height:100% + overflow:hidden
   (chaîne flex shell), donc le scroll natif body ne marche pas. On force
   .isis-help-page à devenir le scroll container (flex:1 + min-height:0 +
   overflow-y:auto). La nav sticky reste collée en haut grâce à position:sticky
   relative à ce conteneur.
   ============================================================================ */
.isis-help-page {
    display: grid;
    grid-template-columns: 240px 1fr;
    gap: 1.5rem;
    align-items: start;
    scroll-behavior: smooth;
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    padding-right: 0.5rem;     /* respiration pour la scrollbar */
}
@media (max-width: 960px) {
    .isis-help-page { grid-template-columns: 1fr; }
}

.isis-help-nav {
    position: sticky;
    top: 0;
    padding: 1rem 0.75rem;
    background: var(--isis-surface-soft);
    border-radius: 8px;
    border: 1px solid var(--isis-border, var(--isis-border));
    font-size: 0.82rem;
    max-height: calc(100vh - 100px);
    overflow-y: auto;
}
.isis-help-nav__title {
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--isis-text-soft, #475569);
    margin-bottom: 0.5rem;
    padding-left: 0.5rem;
}
.isis-help-nav__search {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.4rem 0.55rem;
    margin-bottom: 0.6rem;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius);
    transition: border-color 0.12s, box-shadow 0.12s;
}
/* Halo et compteur suivent le module dont on lit l'aide (ex-couleur gescom figée). */
.isis-help-nav__search:focus-within {
    border-color: var(--isis-current-mod, var(--isis-accent));
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 25%, transparent);
}
.isis-help-nav__search input[type="search"] {
    flex: 1 1 auto;
    min-width: 0;
    border: 0;
    outline: 0;
    background: transparent;
    font: inherit;
    font-size: var(--isis-fs-sm);
    color: var(--isis-text);
    padding: 0;
}
.isis-help-nav__search input[type="search"]::placeholder {
    color: var(--isis-text-muted);
}
.isis-help-nav__search-count {
    flex: 0 0 auto;
    font-size: var(--isis-fs-xs);
    font-weight: 600;
    color: var(--isis-text);
    background: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 14%, transparent);
    padding: 0.1rem 0.4rem;
    border-radius: var(--isis-radius-lg);
    font-variant-numeric: tabular-nums;
}
/* La region aria-live du compteur reste MONTEE en permanence (sinon elle n'est pas annoncee) :
   sans contenu, elle ne doit pas dessiner une pastille vide. */
.isis-help-nav__search-count:empty {
    padding: 0;
    background: none;
}
.isis-help-nav__empty {
    margin: var(--isis-space-sm) 0 0;
    font-size: var(--isis-fs-sm);
    color: var(--isis-text-muted);
}
.isis-help-nav ul {
    list-style: none;
    padding: 0;
    margin: 0;
}
.isis-help-nav ul ul {
    margin-left: 0.5rem;
    padding-left: 0.5rem;
    border-left: 1px solid var(--isis-border, var(--isis-border));
}
.isis-help-nav li { margin: 0.1rem 0; }
.isis-help-nav a {
    display: block;
    padding: 0.3rem 0.5rem;
    border-radius: 4px;
    color: var(--isis-text, #1f2328);
    text-decoration: none;
    transition: background 0.1s;
}
.isis-help-nav a:hover {
    background: var(--isis-mod-gescom-soft, #e0e7ff);
    color: var(--isis-mod-gescom, #4b5fad);
}
.isis-help-nav ul ul a {
    color: var(--isis-text-muted, #475569);
    font-size: 0.78rem;
}

.isis-help-content {
    min-width: 0;     /* sinon flex écrase l'overflow */
    line-height: 1.6;
    color: var(--isis-text, #1f2328);
}
/* Correctif ui-ux #6 audit 2026-05-22 — Style mutualisé pour <kbd> dans les
   pages d'aide (raccourcis clavier F/R/Esc côté gespla, mais aussi tout futur
   contenu help qui documente un raccourci). Rendu cross-browser consistant
   sans surcharge couleurs (palette --isis-* uniquement). */
.isis-help-content kbd {
    display: inline-block;
    padding: 0.1em 0.4em;
    font-size: 0.82em;
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    background: var(--isis-surface-alt);
    border: 1px solid var(--isis-border);
    border-radius: 3px;
    box-shadow: 0 1px 0 var(--isis-border);
    color: var(--isis-text);
    vertical-align: baseline;
}
/* Rendu de la fiche du catalogue (Markdig, HelpMarkdownRenderer) telle que servie par le
   tiroir « Aide » (tâche 6) et le centre d'aide (tâche 7) : headings, listes, encadré
   « :::attention », badge de statut inline, bloc Vos droits, Voir aussi. Tokens réels de la
   feuille (--isis-fs-*, --isis-space-*) : la maquette de la tâche 6 citait des noms qui
   n'existent pas ici (--isis-font-size-*, --isis-space-2/3/4, --isis-warning-border,
   --isis-danger-text, --isis-surface-muted) — remplacés par leur équivalent réel.
   Palette héritée de .isis-inline-warning (ligne ~1780) pour rester cohérente à travers l'app. */
.isis-help-content h2 { font-size: var(--isis-fs-lg); margin: var(--isis-space-md) 0 var(--isis-space-sm); scroll-margin-top: var(--isis-space-sm); }
.isis-help-content ol, .isis-help-content ul { padding-inline-start: 1.25em; }
.isis-help-content .attention { border: 1px solid var(--isis-warning); background: var(--isis-warning-soft); border-radius: var(--isis-radius-sm); padding: var(--isis-space-sm) var(--isis-space-md); }
/* Tableaux d'une fiche : le corps du tiroir ne fait que ~448 px et les fiches livrent deja
   des tableaux a cinq colonnes (gescom.devis.detail). Les cellules retombent a la ligne en
   priorite ; `display: block` + `overflow-x: auto` font DEFILER le tableau quand meme le
   texte replie ne tient plus, plutot que de crever la colonne du tiroir. */
.isis-help-content table {
    display: block;
    max-width: 100%;
    overflow-x: auto;
    border-collapse: collapse;
    margin: var(--isis-space-sm) 0;
    font-size: var(--isis-fs-sm);
}
.isis-help-content th,
.isis-help-content td {
    border: 1px solid var(--isis-border);
    padding: var(--isis-space-xs) var(--isis-space-sm);
    text-align: left;
    vertical-align: top;
    word-break: break-word;
}
.isis-help-content thead th {
    background: var(--isis-surface-alt);
    font-weight: 600;
}
.isis-help-status { display: inline-block; border-radius: 999px; padding: 0 8px; background: var(--isis-surface-alt); font-size: var(--isis-fs-sm); }
.isis-help-rights { list-style: none; padding: 0; margin: var(--isis-space-sm) 0; }
.isis-help-rights li { display: flex; gap: var(--isis-space-sm); align-items: flex-start; margin: var(--isis-space-xs) 0; }
.isis-help-rights li.is-missing { color: var(--isis-danger); }
.isis-help-rights__note { color: var(--isis-text-muted); font-size: var(--isis-fs-sm); }
.isis-help-see-also { margin-top: var(--isis-space-md); padding-top: var(--isis-space-sm); border-top: 1px solid var(--isis-border); display: flex; flex-wrap: wrap; gap: var(--isis-space-sm); font-size: var(--isis-fs-sm); color: var(--isis-text-muted); }
.isis-help-section {
    padding: 1.5rem 0;
    border-bottom: 1px solid var(--isis-border, var(--isis-border));
    scroll-margin-top: 1rem;
    border-radius: 8px;
}
.isis-help-section:last-child { border-bottom: none; }
/* Highlight flash quand l'utilisateur navigue vers une ancre (cf. aide-toc.js).
   Fade in court + maintien ~1.1s + fade out. La classe est ré-applicable :
   le JS la retire puis force un reflow avant de la rajouter pour relancer l'anim. */
@keyframes isisHelpFlash {
    0%   { background-color: transparent; box-shadow: none; }
    8%   { background-color: var(--isis-mod-gescom-soft, #e0e7ff); box-shadow: -4px 0 0 0 var(--isis-mod-gescom, #4b5fad); }
    65%  { background-color: var(--isis-mod-gescom-soft, #e0e7ff); box-shadow: -4px 0 0 0 var(--isis-mod-gescom, #4b5fad); }
    100% { background-color: transparent; box-shadow: none; }
}
.isis-help-section--flash {
    animation: isisHelpFlash 1.9s ease-out forwards;
    padding-left: 0.75rem;
    margin-left: -0.75rem;
}
.isis-help-section.is-spotlight {
    background: linear-gradient(180deg, var(--isis-mod-gescom-soft, #e0e7ff) 0%, transparent 80px);
    padding: 1.5rem 1rem;
    border-radius: 10px;
    margin: 1rem 0;
    border: 1px solid var(--isis-mod-gescom, #4b5fad);
}
.isis-help-section h2 {
    font-size: 1.35rem;
    font-weight: 600;
    color: var(--isis-text, #1f2328);
    margin: 0 0 0.75rem;
}
.isis-help-section h3 {
    font-size: 1.05rem;
    font-weight: 600;
    margin: 1.5rem 0 0.5rem;
    color: var(--isis-text, #1f2328);
}
.isis-help-section h4 {
    font-size: 0.92rem;
    font-weight: 600;
    margin: 1rem 0 0.4rem;
    color: var(--isis-text, #1f2328);
}
.isis-help-section__lead {
    font-size: 1rem;
    color: var(--isis-text, #1f2328);
}
.isis-help-section p,
.isis-help-section ul,
.isis-help-section ol {
    margin: 0.5rem 0 0.75rem;
}
.isis-help-section ul ul { margin: 0.3rem 0 0.3rem 1rem; }
/* `--isis-surface-soft` n'est DÉFINI nulle part dans la feuille : le repli littéral #f1f5f9
   s'appliquait donc en toutes circonstances, y compris en thème sombre — un pavé gris clair
   portant du texte clair, illisible (constaté sur /gespla/aide le 2026-09-05, où le nom des
   tables et des colonnes disparaissait dans un rectangle blanc). Le repli passe sur
   `--isis-surface-alt`, qui, lui, est redéfini par le thème sombre. Cinq autres règles de la
   feuille ont la même faute — hors du périmètre de cette revue, relevées dans docs/modules/gespla.md. */
.isis-help-section code {
    background: var(--isis-surface-soft);
    color: var(--isis-text);
    padding: 0.1rem 0.35rem;
    border-radius: 3px;
    font-size: 0.85em;
    font-family: ui-monospace, monospace;
}
.isis-help-section pre {
    background: var(--isis-surface-soft);
    color: var(--isis-text);
    border: 1px solid var(--isis-border, var(--isis-border));
    border-radius: 6px;
    padding: 0.8rem 1rem;
    overflow-x: auto;
    font-size: 0.82rem;
    line-height: 1.5;
}
.isis-help-section pre code {
    background: transparent;
    padding: 0;
}

.isis-help-diagram {
    margin: 1.25rem 0;
    padding: 1rem;
    background: var(--isis-surface, #ffffff);
    border: 1px solid var(--isis-border, var(--isis-border));
    border-radius: 8px;
    text-align: center;
}
.isis-help-diagram svg {
    max-width: 100%;
    height: auto;
}

.isis-help-callout {
    display: flex;
    gap: 0.75rem;
    align-items: flex-start;
    padding: 0.75rem 1rem;
    margin: 1rem 0;
    border-radius: 6px;
    border: 1px solid var(--isis-border);
    background: var(--isis-surface-soft);
    font-size: 0.88rem;
}
.isis-help-callout > .rz-icon {
    font-size: 18px;
    flex-shrink: 0;
    margin-top: 0.1rem;
}
.isis-help-callout.is-info {
    border-color: var(--isis-accent);
    background: var(--isis-accent-soft);
}
.isis-help-callout.is-info > .rz-icon { color: var(--isis-accent); }
/* is-success : alias de is-tip (même famille sémantique). */
.isis-help-callout.is-tip,
.isis-help-callout.is-success {
    border-color: var(--isis-success);
    background: color-mix(in srgb, var(--isis-success) 6%, transparent);
}
.isis-help-callout.is-tip > .rz-icon,
.isis-help-callout.is-success > .rz-icon { color: var(--isis-success); }
.isis-help-callout.is-warning {
    border-color: var(--isis-warning);
    background: color-mix(in srgb, var(--isis-warning) 6%, transparent);
}
.isis-help-callout.is-warning > .rz-icon { color: var(--isis-warning); }
.isis-help-callout.is-danger {
    border-color: var(--isis-danger);
    background: color-mix(in srgb, var(--isis-danger) 6%, transparent);
}
.isis-help-callout.is-danger > .rz-icon { color: var(--isis-danger); }
.isis-help-callout ul { margin: 0.4rem 0 0; padding-left: 1.2rem; }

.isis-help-faq {
    border: 1px solid var(--isis-border, var(--isis-border));
    border-radius: 6px;
    padding: 0.6rem 0.85rem;
    margin: 0.5rem 0;
    background: var(--isis-surface, #ffffff);
}
.isis-help-faq[open] {
    background: var(--isis-surface-soft);
    border-color: var(--isis-mod-gescom, #4b5fad);
}
.isis-help-faq summary {
    cursor: pointer;
    font-weight: 500;
    color: var(--isis-text, #1f2328);
    padding: 0.2rem 0;
    list-style-position: outside;
    margin-left: 1rem;
}
.isis-help-faq summary:hover { color: var(--isis-mod-gescom, #4b5fad); }
.isis-help-faq[open] summary { margin-bottom: 0.4rem; }
.isis-help-faq p {
    margin: 0.4rem 0 0;
    font-size: 0.88rem;
    color: var(--isis-text, #1f2328);
}

.isis-help-glossary {
    display: grid;
    grid-template-columns: minmax(180px, 1fr) 3fr;
    gap: 0.4rem 1rem;
    font-size: 0.88rem;
}
.isis-help-glossary dt {
    font-weight: 600;
    color: var(--isis-mod-gescom, #4b5fad);
}
.isis-help-glossary dd { margin: 0; }

/* ============================================================================
   .isis-side-actions — barre d'actions standard des pieds de sidepanel.
   Contenu = uniquement des IsisButton. Le destructif (.isis-action-btn--danger)
   est poussé à droite ; libellés courts + delete icône ⇒ une seule ligne.
   ============================================================================ */
/* Extensions de .isis-side-actions (base définie plus haut « #1 — Actions
   contextuelles par statut ») pour le composant <IsisSidePanelActions> :
   destructif auto-aligné à droite + variantes verticale (stack) et sans filet
   (flush). On NE redéfinit PAS la base — elle est partagée avec 9 pages. */
.isis-side-actions--flush { margin-top: 0; padding-top: 0; border-top: none; }
/* Seul le destructif EN ICÔNE (le « Supprimer » des sidepanels) est isolé à droite.
   Les boutons danger AVEC texte (Rejeter/Annuler workflow, delete en mode stack)
   restent inline — sinon ils créeraient une ligne creuse. */
.isis-side-actions .isis-action-btn--danger.isis-action-btn--icon-only { margin-left: auto; }
.isis-side-actions--stack { flex-direction: column; align-items: stretch; }
.isis-side-actions--stack .isis-action-btn { width: 100%; justify-content: flex-start; }
.isis-side-actions--stack .isis-action-btn--danger { margin-left: 0; }

/* ============================================================================
   .isis-gantt — Vue Gantt CSS-only (MarcheDetail onglet « Commandes liées »)
   ----------------------------------------------------------------------------
   Une grille 2 colonnes : label fixe (180px) | track positionnée (1fr).
   Les barres sont en position:absolute dans .isis-gantt__track avec left/width
   en % de la fenêtre temporelle calculée côté C# (cf. ComputeGantt).
   ============================================================================ */
.isis-gantt-wrap {
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
}
.isis-gantt {
    display: flex;
    flex-direction: column;
    border: 1px solid var(--isis-border);
    border-radius: 6px;
    overflow-x: auto;
    background: var(--isis-surface);
    /* Track minimum width : pousse le scroll horizontal au-delà */
    min-width: 100%;
    /* Indicateur visuel de scroll horizontal : gradient à droite si débordement. */
    background-image: linear-gradient(to right, var(--isis-surface) 0%, var(--isis-surface) 90%, var(--isis-surface-alt) 100%);
    background-attachment: local;
    background-repeat: no-repeat;
}

/* En-tête : libellés mois alignés au-dessus de la track */
.isis-gantt__head {
    display: grid;
    grid-template-columns: 180px minmax(var(--isis-gantt-track-px, 600px), 1fr);
    background: var(--isis-surface-alt);
    border-bottom: 1px solid var(--isis-border);
    position: sticky;
    top: 0;
    z-index: 2;
}
.isis-gantt__label-spacer {
    padding: 0.5rem 0.75rem;
    font-size: 0.72rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--isis-text-muted);
    border-right: 1px solid var(--isis-border);
    box-sizing: border-box;
}
.isis-gantt__timeline {
    position: relative;
    height: 32px;
}
.isis-gantt__month-cell {
    position: absolute;
    top: 0;
    bottom: 0;
    border-left: 1px solid var(--isis-border);
    display: flex;
    align-items: center;
    padding-left: 0.5rem;
    box-sizing: border-box;
}
.isis-gantt__month-cell:first-child { border-left: none; }
.isis-gantt__month-label {
    font-size: 0.72rem;
    font-weight: 500;
    color: var(--isis-text-muted);
    text-transform: capitalize;
    white-space: nowrap;
}

/* Ligne par commande */
.isis-gantt__row {
    display: grid;
    grid-template-columns: 180px minmax(var(--isis-gantt-track-px, 600px), 1fr);
    min-height: 36px;
    border-bottom: 1px solid var(--isis-border);
}
.isis-gantt__row:last-child { border-bottom: none; }
.isis-gantt__row-label {
    padding: 0.4rem 0.75rem;
    border-right: 1px solid var(--isis-border);
    box-sizing: border-box;
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 0.1rem;
    overflow: hidden;
}
.isis-gantt__row-num {
    font-family: var(--isis-font-mono);
    font-size: 0.78rem;
    font-weight: 600;
    color: var(--isis-text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.isis-gantt__row-name {
    font-size: 0.74rem;
    color: var(--isis-text-muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.isis-gantt__track {
    position: relative;
    min-height: 36px;
    background: linear-gradient(to bottom, transparent 50%, rgba(0,0,0,0.012) 50%);
}
.isis-gantt__grid-line {
    position: absolute;
    top: 0;
    bottom: 0;
    width: 1px;
    background: var(--isis-border);
    opacity: 0.6;
}

/* Barre commande */
.isis-gantt__bar {
    position: absolute;
    top: 6px;
    bottom: 6px;
    border: 1px solid transparent;
    border-radius: 4px;
    padding: 0 0.5rem;
    font-size: 0.74rem;
    font-weight: 600;
    color: var(--isis-text);
    background: var(--isis-surface-alt);
    display: flex;
    align-items: center;
    cursor: pointer;
    overflow: hidden;
    transition: transform 100ms ease, box-shadow 100ms ease;
    z-index: 1;
}
.isis-gantt__bar:hover {
    transform: translateY(-1px);
    box-shadow: var(--isis-elevation-1, 0 2px 6px rgba(0,0,0,0.12));
    z-index: 3;
}
.isis-gantt__bar:focus-visible {
    outline: 2px solid var(--isis-accent);
    outline-offset: 1px;
}
.isis-gantt__bar-label {
    font-family: var(--isis-font-mono);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
/* Couleurs statut — vars sémantiques --isis-* uniquement (DESIGN.md §1).
   .is-closed (CLOTUREE) en cyan/gesproj : état terminal positif distinct du
   vert "en cours" ; évite la confusion avec .is-pending (violet=attente). */
.isis-gantt__bar.is-draft  { background: var(--isis-surface-alt);    border-color: var(--isis-border);       color: var(--isis-text); }
.isis-gantt__bar.is-info   { background: var(--isis-mod-gescom-soft); border-color: var(--isis-mod-gescom);   color: var(--isis-mod-gescom); }
.isis-gantt__bar.is-ok     { background: var(--isis-success-soft);   border-color: var(--isis-success);      color: var(--isis-success); }
.isis-gantt__bar.is-closed { background: var(--isis-mod-gesproj-soft); border-color: var(--isis-mod-gesproj); color: var(--isis-mod-gesproj); }
.isis-gantt__bar.is-danger { background: var(--isis-danger-soft);    border-color: var(--isis-danger);       color: var(--isis-danger); }

/* Ligne « aujourd'hui » */
.isis-gantt__today-line {
    position: absolute;
    top: 0;
    bottom: 0;
    width: 2px;
    background: var(--isis-danger);
    opacity: 0.7;
    pointer-events: none;
    z-index: 2;
}

/* Légende */
.isis-gantt__legend {
    display: flex;
    flex-wrap: wrap;
    gap: 0.85rem;
    padding: 0.45rem 0.6rem;
    font-size: 0.74rem;
    color: var(--isis-text-muted);
}
.isis-gantt__legend-item {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
}
.isis-gantt__legend-swatch {
    width: 14px;
    height: 10px;
    border-radius: 3px;
    border: 1px solid transparent;
    display: inline-block;
}
.isis-gantt__legend-swatch.is-draft  { background: var(--isis-surface-alt);     border-color: var(--isis-border); }
.isis-gantt__legend-swatch.is-info   { background: var(--isis-mod-gescom-soft); border-color: var(--isis-mod-gescom); }
.isis-gantt__legend-swatch.is-ok     { background: var(--isis-success-soft);   border-color: var(--isis-success); }
.isis-gantt__legend-swatch.is-closed { background: var(--isis-mod-gesproj-soft); border-color: var(--isis-mod-gesproj); }
.isis-gantt__legend-swatch.is-danger { background: var(--isis-danger-soft);    border-color: var(--isis-danger); }
.isis-gantt__legend-today {
    width: 2px;
    height: 12px;
    background: var(--isis-danger);
    display: inline-block;
}

/* Bloc « sans date » sous le Gantt */
.isis-gantt-undated {
    border: 1px dashed var(--isis-border);
    border-radius: 6px;
    padding: 0.7rem 0.85rem;
    background: var(--isis-surface-alt);
}
.isis-gantt-undated__title {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    font-size: 0.78rem;
    font-weight: 600;
    color: var(--isis-text);
    margin-bottom: 0.45rem;
}
.isis-gantt-undated__list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
    font-size: 0.85rem;
}

/* Hint dans le tab-header (compte sans date) */
.isis-tab-header__hint {
    font-size: 0.78rem;
    font-weight: 400;
    color: var(--isis-text-muted);
    margin-left: 0.4rem;
}
.isis-tab-header__hint .rzi {
    font-size: 1em;
    vertical-align: -0.15em;
}

/* ============================================================================
   Page Pipeline (/gescom/pipeline)
   ============================================================================ */

/* Variante de filter-bar pour le sélecteur de période + toggle compare.
   Layout 1 ligne (axis + chips + custom-range si visible + toggle) avec
   wrap progressif. */
.isis-filter-bar--period {
    flex-wrap: wrap;
    align-items: center;
    gap: 0.85rem;
}
.isis-filter-bar__custom-range {
    display: flex;
    gap: 0.4rem;
    align-items: center;
}
.isis-filter-bar__toggle {
    margin-left: auto;  /* repousse le toggle à droite */
}
.isis-filter-bar__toggle-label {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    font-size: 0.825rem;
    color: var(--isis-text);
    cursor: pointer;
    user-select: none;
}
/* Sous 1400px (la plupart des écrans manager 1366/1440), force le toggle sur
   sa propre ligne avec séparateur visuel — sinon il atterrit après les date
   pickers comme un label orphelin. */
@media (max-width: 1400px) {
    .isis-filter-bar--period .isis-filter-bar__toggle {
        flex-basis: 100%;
        margin-left: 0;
        margin-top: 0.4rem;
        padding-top: 0.4rem;
        border-top: 1px solid var(--isis-border, var(--isis-border));
    }
}

/* Section principale (diagramme + transitions) ─ une "carte" plate calée
   sur le pattern .isis-rich-page (flex column gap). Prend toute la hauteur
   restante de la page — chaîne flex {1, min-height: 0} chain pour que les
   asides scrollent en interne sans déborder le viewport (cf. memory
   project_isis_grid_pattern). */
.isis-pipeline-section {
    background: var(--isis-surface);
    border-radius: 10px;
    padding: 1.25rem 1.5rem;
    box-shadow: var(--isis-elevation-1);
    display: flex;
    flex-direction: column;
    gap: 0.85rem;
    flex: 1 1 auto;
    min-height: 0;
}
.isis-pipeline-section__title {
    margin: 0;
    font-size: 1.05rem;
    font-weight: 600;
    color: var(--isis-text);
}
.isis-pipeline-section__hint {
    margin: 0;
    font-size: 0.825rem;
    color: var(--isis-text-muted);
    line-height: 1.45;
}
.isis-pipeline-section__loading {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    padding: 2rem;
    justify-content: center;
    color: var(--isis-text-muted);
    font-size: 0.875rem;
    text-align: center;
}

/* Empty state — variante "filtre actif" avec CTA de réinitialisation. */
.isis-pipeline-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.85rem;
    max-width: 420px;
}
.isis-pipeline-empty__cta {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.45rem 0.85rem;
    border-radius: 6px;
    background: var(--isis-mod-gescom-soft);
    color: var(--isis-mod-gescom);
    border: 1px solid var(--isis-mod-gescom);
    font-size: 0.825rem;
    font-weight: 500;
    cursor: pointer;
    transition: background-color 150ms ease;
}
.isis-pipeline-empty__cta:hover,
.isis-pipeline-empty__cta:focus-visible {
    background: var(--isis-mod-gescom);
    color: var(--isis-surface);
}

/* Layout intra-section 3 colonnes : aside filtre entreprises (gauche),
   diagramme (centre), aside transitions (droite). master-detail-detail.
   `align-items: stretch` + flex:1 sur le layout pour que les 3 enfants prennent
   toute la hauteur de la section (qui elle-même prend toute la page). */
.isis-pipeline-layout {
    display: flex;
    gap: 1.25rem;
    align-items: stretch;
    flex: 1 1 auto;
    min-height: 0;
}
.isis-pipeline-layout__filter {
    flex: 0 0 220px;
    background: var(--isis-surface-alt);
    border-radius: 8px;
    padding: 0.85rem 0.75rem;
    overflow-y: auto;  /* scroll interne si la liste dépasse la hauteur dispo */
    min-height: 0;
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
}
.isis-pipeline-layout__main {
    flex: 1 1 auto;
    min-width: 0;  /* indispensable pour que le SVG ne fasse pas exploser le flex */
    min-height: 0;
    display: flex;
    flex-direction: column;
    gap: 0.85rem;
    overflow-y: auto;  /* le SVG + hint scrollent si la fenêtre est très basse */
}
.isis-pipeline-layout__aside {
    flex: 0 0 260px;
    background: var(--isis-surface-alt);
    border-radius: 8px;
    padding: 0.85rem 1rem;
    /* Reste visible si la liste dépasse — scroll interne dans la hauteur
       disponible (alignée sur la section). */
    overflow-y: auto;
    min-height: 0;
}
/* ─── Filtre entreprises ─── */
.isis-pipeline-filter__head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.5rem;
}
.isis-pipeline-filter__title {
    margin: 0;
    font-size: 0.825rem;
    font-weight: 600;
    color: var(--isis-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}
.isis-pipeline-filter__reset {
    background: none;
    border: none;
    padding: 0;
    font-size: 0.75rem;
    color: var(--isis-mod-gescom);
    cursor: pointer;
    text-decoration: underline;
}
.isis-pipeline-filter__reset:hover,
.isis-pipeline-filter__reset:focus-visible { color: var(--isis-text); }
.isis-pipeline-filter__hint {
    font-size: 0.75rem;
    color: var(--isis-text-muted);
    font-variant-numeric: tabular-nums;
}
.isis-pipeline-filter__list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.1rem;
}
.isis-pipeline-filter__item {
    /* Indentation arbre pilotée par data-depth (évite l'interpolation Razor qui
       formate les décimales selon la culture courante — fr-FR produit "0,5rem"
       invalide en CSS). Connecteur vertical type tree-view sur les enfants
       (depth ≥ 1) pour matérialiser la hiérarchie. */
    padding-right: 0.3rem;
    position: relative;
    padding-left: 0.5rem;
}
.isis-pipeline-filter__item[data-depth="1"] { padding-left: 1.5rem; }
.isis-pipeline-filter__item[data-depth="2"] { padding-left: 2.5rem; }
.isis-pipeline-filter__item[data-depth="3"] { padding-left: 3.5rem; }
.isis-pipeline-filter__item[data-depth="4"] { padding-left: 4.5rem; }
.isis-pipeline-filter__item[data-depth="5"] { padding-left: 5.5rem; }

/* Connecteur vertical tree-view : un trait gris pour chaque génération
   parente, posé à la position de l'indentation correspondante. */
.isis-pipeline-filter__item:not([data-depth="0"])::before {
    content: '';
    position: absolute;
    left: 0.95rem;
    top: 0;
    bottom: 0;
    width: 1px;
    background: var(--isis-border, var(--isis-border));
}
.isis-pipeline-filter__item[data-depth="2"]::before { left: 1.95rem; }
.isis-pipeline-filter__item[data-depth="3"]::before { left: 2.95rem; }
.isis-pipeline-filter__item[data-depth="4"]::before { left: 3.95rem; }
.isis-pipeline-filter__item[data-depth="5"]::before { left: 4.95rem; }
.isis-pipeline-filter__label {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.25rem 0.35rem;
    border-radius: 4px;
    cursor: pointer;
    font-size: 0.8125rem;
    color: var(--isis-text);
    /* Empêche le label/checkbox de wrapper sur plusieurs lignes — la ellipsis
       sur __name gère l'overflow horizontal. */
    min-width: 0;
}
.isis-pipeline-filter__label:hover { background: var(--isis-surface); }
.isis-pipeline-filter__label input[type="checkbox"] {
    flex-shrink: 0;
    cursor: pointer;
    accent-color: var(--isis-mod-gescom);
}
.isis-pipeline-filter__name {
    flex: 1 1 auto;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
}
.isis-pipeline-filter__code {
    flex-shrink: 0;
    font-size: 0.7rem;
    color: var(--isis-text-muted);
    font-variant-numeric: tabular-nums;
    background: var(--isis-surface);
    padding: 0.05rem 0.35rem;
    border-radius: 3px;
}

/* Sous 1300px (laptop standard / tablette paysage) : les 3 colonnes
   s'empilent verticalement. Le filtre AU-DESSUS du diagramme (l'utilisateur
   le voit avant d'analyser), les transitions EN DESSOUS. La section pipeline
   garde sa hauteur flex:1 mais devient un container scrollable en interne
   (le contenu empilé peut dépasser la hauteur). Asides bornés en hauteur
   nominale pour ne pas tout phagocyter au-dessus du diagramme. */
@media (max-width: 1300px) {
    .isis-pipeline-layout {
        flex-direction: column;
        overflow-y: auto;  /* scroll interne quand le total empilé dépasse */
    }
    .isis-pipeline-layout__filter,
    .isis-pipeline-layout__aside {
        flex: 0 0 auto;
        max-height: 240px;
    }
    .isis-pipeline-layout__main {
        flex: 0 0 auto;
        overflow-y: visible;  /* relâche son scroll interne, la section scroll */
    }
}

/* Top transitions sur la période — bloc intra-aside (V2 : extractible si
   d'autres pages réutilisent les transitions). */
.isis-pipeline-transitions__title {
    margin: 0 0 0.6rem 0;
    font-size: 0.825rem;
    font-weight: 600;
    color: var(--isis-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}
.isis-pipeline-transitions__list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
}
.isis-pipeline-transitions__item {
    display: grid;
    grid-template-columns: 1fr auto 1fr auto;
    align-items: center;
    gap: 0.55rem;
    padding: 0.35rem 0.6rem;
    border-radius: 6px;
    /* Fond surface (blanc) pour ressortir sur l'aside surface-alt. */
    background: var(--isis-surface);
    border: 1px solid var(--isis-border, var(--isis-border));
    font-size: 0.825rem;
}
.isis-pipeline-transitions__from,
.isis-pipeline-transitions__to {
    color: var(--isis-text);
}
.isis-pipeline-transitions__count {
    font-variant-numeric: tabular-nums;
    font-weight: 600;
    color: var(--isis-mod-gescom);
    min-width: 2.5rem;
    text-align: right;
}

/* ============================================================================
   Drill panel — composant DevisPipelineDrillPanel (sous le diagramme Pipeline)
   ============================================================================ */
.isis-pipeline-drill {
    background: var(--isis-surface);
    border-radius: 10px;
    padding: 1rem 1.25rem 1.25rem;
    box-shadow: var(--isis-elevation-1);
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
    animation: isisDrillEnter 220ms ease-out;
}

/* Quand le drill est ouvert, on partage la hauteur disponible entre la section
   workflow (bornée à ~60 % du parent pour garder le diagramme visible sans
   l'écraser) et le drill (prend le reste, scroll interne).
   Au-dessus de 1300 px uniquement — sous cette taille, le layout interne de la
   section passe déjà en vertical empilé (cf. règle media 1300 plus haut). */
@media (min-width: 1301px) {
    .isis-rich-page.is-drill-open .isis-pipeline-section {
        flex: 0 1 auto;
        max-height: 60%;
    }
    .isis-rich-page.is-drill-open .isis-pipeline-drill {
        flex: 1 1 auto;
        min-height: 0;
        overflow-y: auto;
    }
}
@keyframes isisDrillEnter {
    from { opacity: 0; transform: translateY(-4px); }
    to   { opacity: 1; transform: translateY(0); }
}
/* WCAG 2.3.3 — respecte le pref OS « réduire les animations ». */
@media (prefers-reduced-motion: reduce) {
    .isis-pipeline-drill { animation: none; }
}

/* Header : titre statut + meta count/total + bouton close */
.isis-pipeline-drill__head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 1rem;
    padding-bottom: 0.6rem;
    border-bottom: 1px solid var(--isis-border, var(--isis-border));
}
.isis-pipeline-drill__head-main { flex: 1 1 auto; min-width: 0; }
.isis-pipeline-drill__title {
    margin: 0 0 0.25rem 0;
    font-size: 1rem;
    font-weight: 600;
    color: var(--isis-text);
}
.isis-pipeline-drill__head-meta {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    font-size: 0.825rem;
    color: var(--isis-text-muted);
}
.isis-pipeline-drill__count {
    color: var(--isis-text);
    font-weight: 500;
    font-variant-numeric: tabular-nums;
}
.isis-pipeline-drill__separator { opacity: 0.4; }
.isis-pipeline-drill__totals { font-variant-numeric: tabular-nums; }
.isis-pipeline-drill__close {
    flex-shrink: 0;
    background: none;
    border: 1px solid transparent;
    border-radius: 6px;
    /* Cible 36×36 min pour tablette (compromis raisonnable sans alourdir le header
       — AA 2.5.5 indique 24×24, on offre une marge confortable). */
    padding: 0.55rem;
    min-width: 36px;
    min-height: 36px;
    cursor: pointer;
    color: var(--isis-text-muted);
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
.isis-pipeline-drill__close:hover,
.isis-pipeline-drill__close:focus-visible {
    background: var(--isis-surface-alt);
    border-color: var(--isis-border, var(--isis-border));
    color: var(--isis-text);
}

/* Breadcrumb — crumbs cliquables, dernier désactivé (= niveau courant) */
.isis-pipeline-drill__breadcrumb {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.25rem;
    font-size: 0.825rem;
}
.isis-pipeline-drill__crumb {
    background: none;
    border: none;
    padding: 0.2rem 0.5rem;
    border-radius: 4px;
    color: var(--isis-mod-gescom);
    cursor: pointer;
    font-size: 0.825rem;
    font-weight: 500;
}
.isis-pipeline-drill__crumb:hover:not([disabled]),
.isis-pipeline-drill__crumb:focus-visible {
    background: var(--isis-mod-gescom-soft);
}
.isis-pipeline-drill__crumb[disabled] {
    color: var(--isis-text);
    cursor: default;
    font-weight: 600;
}
.isis-pipeline-drill__crumb-sep {
    color: var(--isis-text-muted);
    font-size: 0.9rem;
    user-select: none;
}

.isis-pipeline-drill__hint {
    margin: 0 0 0.4rem 0;
    font-size: 0.75rem;
    color: var(--isis-text-muted);
    font-style: italic;
}

/* Empty state du drill (filtre laisse 0 devis dans ce périmètre) */
.isis-pipeline-drill__empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.5rem;
    padding: 2rem 1rem;
    color: var(--isis-text-muted);
    font-size: 0.875rem;
}

/* Grille des buckets / items — CSS Grid (pas de table HTML pour conserver
   les boutons natifs row-level avec keyboard + a11y). */
.isis-pipeline-drill__grid {
    display: flex;
    flex-direction: column;
    border: 1px solid var(--isis-border, var(--isis-border));
    border-radius: 8px;
    overflow: hidden;
    background: var(--isis-surface);
}
.isis-pipeline-drill__grid--buckets .isis-pipeline-drill__row {
    display: grid;
    grid-template-columns: 1fr 90px 1fr 32px;
    align-items: center;
    gap: 0.75rem;
}
.isis-pipeline-drill__grid--items .isis-pipeline-drill__row {
    display: grid;
    /* 8 colonnes : Numéro · Titre · Tiers · Owner · Montant · Émis · Valide · Actions */
    grid-template-columns: 130px 1.5fr 1fr 1fr 130px 110px 110px 84px;
    align-items: center;
    gap: 0.6rem;
}
.isis-pipeline-drill__row {
    width: 100%;
    text-align: left;
    background: var(--isis-surface);
    border: none;
    border-bottom: 1px solid var(--isis-border, var(--isis-border));
    padding: 0.6rem 0.85rem;
    font-size: 0.8125rem;
    color: var(--isis-text);
    cursor: pointer;
    font-family: inherit;
    transition: background-color 120ms ease;
}
.isis-pipeline-drill__row:last-child { border-bottom: none; }
.isis-pipeline-drill__row:hover,
.isis-pipeline-drill__row:focus-visible {
    background: var(--isis-surface-alt);
    outline: none;
}
.isis-pipeline-drill__row:focus-visible {
    box-shadow: inset 3px 0 0 var(--isis-mod-gescom);
}
.isis-pipeline-drill__row--head {
    background: var(--isis-surface-alt);
    font-size: 0.7rem;
    font-weight: 600;
    color: var(--isis-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    cursor: default;
    pointer-events: none;
    padding: 0.5rem 0.85rem;
}
.isis-pipeline-drill__col--num {
    text-align: right;
    font-variant-numeric: tabular-nums;
}
.isis-pipeline-drill__num {
    font-family: ui-monospace, SFMono-Regular, monospace;
    font-size: 0.75rem;
    color: var(--isis-text-muted);
}
.isis-pipeline-drill__title {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.isis-pipeline-drill__bucket-label {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    min-width: 0;
}
.isis-pipeline-drill__bucket-label strong {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.isis-pipeline-drill__bucket-sub {
    font-size: 0.7rem;
    /* `--isis-text-muted` (#5b6470) sur surface (~4.35:1) échoue WCAG AA pour
       petit texte (~11px). Passage à `--isis-text` (#1f2328 ~ 14:1) — la
       distinction visuelle vient de la taille + weight, pas de la couleur. */
    color: var(--isis-text);
}
.isis-pipeline-drill__chevron {
    color: var(--isis-text-muted);
    display: inline-flex;
    justify-content: center;
}
.isis-pipeline-drill__row--bucket:hover .isis-pipeline-drill__chevron {
    color: var(--isis-mod-gescom);
}
/* Bucket orphelin (Guid.Empty) : cliquable comme les autres (drill jusqu'aux
   devis terminaux pour les corriger), mais teinte warm + bande accent gauche
   pour signaler l'anomalie « à traiter ». Garde le compteur visible pour
   matcher le total du node (cohérence numérique). */
.isis-pipeline-drill__row--bucket.is-orphan {
    background: color-mix(in srgb, var(--isis-accent-soft) 35%, var(--isis-surface));
    box-shadow: inset 3px 0 0 var(--isis-accent);
}
.isis-pipeline-drill__row--bucket.is-orphan:hover,
.isis-pipeline-drill__row--bucket.is-orphan:focus-visible {
    background: color-mix(in srgb, var(--isis-accent-soft) 55%, var(--isis-surface));
    /* On garde la bande gauche prioritaire sur le inset focus standard */
    box-shadow: inset 3px 0 0 var(--isis-accent);
}
.isis-pipeline-drill__row--bucket.is-orphan .isis-pipeline-drill__bucket-sub {
    color: var(--isis-accent);
    font-weight: 500;
}

/* Colonne actions des lignes Devis : icônes 28×28 alignées à droite, gap léger
   entre les 2 icônes max (Attribuer owner si orphan + Ouvrir nouvel onglet). */
.isis-pipeline-drill__col--actions {
    display: inline-flex;
    align-items: center;
    justify-content: flex-end;
    gap: 0.3rem;
}
.isis-pipeline-drill__action {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    border-radius: 5px;
    border: 1px solid var(--isis-border, var(--isis-border));
    background: var(--isis-surface);
    color: var(--isis-text-muted);
    cursor: pointer;
    text-decoration: none;
    transition: background-color 120ms ease, color 120ms ease, border-color 120ms ease;
}
.isis-pipeline-drill__action:hover,
.isis-pipeline-drill__action:focus-visible {
    background: var(--isis-mod-gescom-soft);
    border-color: var(--isis-mod-gescom);
    color: var(--isis-mod-gescom);
    outline: none;
}
/* Variante "Attribuer owner" : accent warm pour rappeler l'anomalie à traiter. */
.isis-pipeline-drill__action--assign {
    border-color: var(--isis-accent);
    color: var(--isis-accent);
    background: color-mix(in srgb, var(--isis-accent-soft) 30%, var(--isis-surface));
}
.isis-pipeline-drill__action--assign:hover,
.isis-pipeline-drill__action--assign:focus-visible {
    background: var(--isis-accent);
    color: var(--isis-surface);
    border-color: var(--isis-accent);
}
/* Label en italique gris muted quand une donnée référentielle manque sur une
   ligne devis (owner / tiers null). Aide à scanner rapidement les anomalies. */
.isis-pipeline-drill__missing {
    color: var(--isis-text-muted);
    font-style: italic;
}

/* Responsive : sous 1100px, la grille items passe à 5 colonnes condensées
   (on garde la colonne actions, indispensable pour Attribuer owner). */
@media (max-width: 1100px) {
    .isis-pipeline-drill__grid--items .isis-pipeline-drill__row {
        grid-template-columns: 1fr 1.5fr 1fr 130px 84px;
        gap: 0.4rem;
    }
    /* Masque Owner (4) / Émis (6) / Valide (7) — Numéro (1) / Titre (2) /
       Tiers (3) / Montant (5) / Actions (8) restent. */
    .isis-pipeline-drill__grid--items .isis-pipeline-drill__row > :nth-child(4),
    .isis-pipeline-drill__grid--items .isis-pipeline-drill__row > :nth-child(6),
    .isis-pipeline-drill__grid--items .isis-pipeline-drill__row > :nth-child(7) {
        display: none;
    }
}

/* ============================================================================
   Reset Bootstrap remnants
   ============================================================================ */
.top-row, .sidebar { display: none !important; }

/* ============================================================================
   /gesmaff/parametres/numerotation — visualisation compteurs.
   3 règles : note d'info au-dessus de la grille, pill type d'entité, grille 4 cols.
   ============================================================================ */
.isis-rich-page__note {
    display: flex;
    align-items: flex-start;
    gap: 0.5rem;
    /* NB : le flex est réservé aux notes icône+texte (<div role=note> avec un
       <RadzenIcon> en 1er enfant). Une note en prose (<p>) contenant des <strong>
       inline ne doit PAS être flex — sinon chaque <strong> et chaque fragment de
       texte devient un item flex étalé par le gap (bandeau « disloqué » + espace
       parasite avant la virgule). D'où l'override display:block sur p. ci-dessous. */
    padding: 0.6rem 0.8rem;
    background: var(--isis-surface-soft);
    border: 1px solid var(--isis-border, var(--isis-border));
    /* Liseré gauche 3px décoratif retiré 2026-07-05 (demande utilisateur) — le fond
       teinté + le filet 1px suffisent à identifier la note. */
    border-radius: 6px;
    font-size: 0.82rem;
    color: var(--isis-text-soft, #475569);
    line-height: 1.45;
}
p.isis-rich-page__note {
    display: block;   /* prose : flux inline normal, les <strong> restent dans le texte */
}
.isis-rich-page__note code {
    font-family: var(--isis-font-mono, ui-monospace, monospace);
    font-size: 0.78rem;
    padding: 0.05rem 0.3rem;
    background: var(--isis-surface, #fff);
    border: 1px solid var(--isis-border, var(--isis-border));
    border-radius: 3px;
    color: var(--isis-text, #1f2328);
}

/* ─── Fiche admin/users/{id} : layout interne onglets ─────────────────── */

/* Bloc d'actions secondaires sous une colonne de summary (ex: bouton "Ouvrir la fiche collab") */
.isis-detail-actions {
    margin-top: 0.75rem;
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
}

/* Onglet Habilitations — pourquoi un module n'est pas activable (compte sans collaborateur) */
.isis-habilitation-block__reason {
    color: var(--isis-warning, #8f5700);
    font-style: italic;
}

.isis-role-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 0.6rem;
}
.isis-role-chips__item {
    display: inline-flex;
    align-items: center;
    gap: 0.2rem;
}

/* Onglet Habilitations — un bloc par module : accès, rôles, périmètre, dérogations */
.isis-habilitation-list {
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
}
.isis-habilitation-block {
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius);
    background: var(--isis-surface);
    overflow: hidden;
}
/* Un module fermé s'efface : ce qu'on vient lire est dans les autres. */
.isis-habilitation-block.is-closed { background: transparent; }
.isis-habilitation-block__head {
    display: flex;
    align-items: center;
    gap: 0.7rem;
    padding: 0.7rem 1rem;
}
.isis-habilitation-block.is-open .isis-habilitation-block__head {
    border-bottom: 1px solid var(--isis-border);
}
.isis-habilitation-block__toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.75rem;
    height: 1.75rem;
    flex: 0 0 auto;
    padding: 0;
    border: 0;
    border-radius: var(--isis-radius-sm);
    background: transparent;
    color: var(--isis-text-soft);
    cursor: pointer;
}
.isis-habilitation-block__toggle:hover { background: var(--isis-surface-alt); color: var(--isis-text); }
.isis-habilitation-block__toggle-void { width: 1.75rem; flex: 0 0 auto; }
.isis-habilitation-block__ident {
    display: flex;
    flex-direction: column;
    gap: 0.1rem;
    min-width: 0;
    flex: 1 1 auto;
}
.isis-habilitation-block__label { font-weight: 600; }
.isis-habilitation-block__meta {
    font-size: 0.78rem;
    color: var(--isis-text-soft);
}
.isis-habilitation-block__closed {
    display: flex;
    align-items: center;
    gap: 0.45rem;
    padding: 0 1rem 0.7rem 3.45rem;
    font-size: 0.8rem;
    color: var(--isis-text-soft);
}
.isis-habilitation-block__body { padding: 0.9rem 1rem 1rem; }
/* display:none et non une astuce visuelle : un bloc replié doit aussi sortir de l'ordre de
   tabulation et de l'arbre d'accessibilité, sinon aria-expanded="false" ment. */
.isis-habilitation-block__body.is-hidden { display: none; }
.isis-habilitation-section + .isis-habilitation-section {
    margin-top: 1rem;
    padding-top: 0.85rem;
    border-top: 1px dashed var(--isis-border);
}
/* Mêmes valeurs que .isis-detail-summary__title : les deux jouent le même rôle de sur-titre, à
   un onglet d'écart sur la même fiche — deux variantes s'y liraient comme une erreur. */
.isis-habilitation-section__title {
    font-size: 0.65rem;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--isis-text-soft);
    margin-bottom: 0.5rem;
}
.isis-habilitation-empty {
    font-size: 0.82rem;
    color: var(--isis-text-soft);
    font-style: italic;
}

/* Onglet Habilitations réorganisé (2026-09-19) : une ligne résumée par module, dépliée à la
   demande ; l'en-tête de colonnes et chaque ligne partagent la même grille. Deux classes sur la
   ligne : .isis-habilitation-block__head (flex) est déclarée plus haut et doit perdre. */
.isis-hab-titre { display: flex; flex-direction: column; gap: 0.2rem; margin-bottom: 0.75rem; }
.isis-hab-titre__label { margin: 0; font-size: 1rem; font-weight: 600; }
.isis-hab-titre__hint { margin: 0; font-size: 0.82rem; color: var(--isis-text-muted); max-width: 72ch; }
.isis-hab-ligne,
.isis-habilitation-block__head.isis-hab-ligne {
    display: grid;
    grid-template-columns: 1.75rem minmax(11rem, 1.3fr) minmax(8rem, 0.9fr) minmax(8rem, 0.9fr)
                           minmax(10rem, 1.4fr) minmax(7rem, 0.8fr) 5.5rem;
    align-items: center;
    gap: 0.4rem 0.8rem;
}
.isis-hab-colonnes {
    padding: 0 1rem 0.1rem;
    font-size: 0.65rem;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--isis-text-soft);
}
.isis-hab-ligne__cell { display: flex; flex-wrap: wrap; align-items: center; gap: 0.3rem; min-width: 0; font-size: 0.84rem; }
/* Largeur FIXE (5,5 rem) : en « auto », la colonne vide de l'en-tête valait 0 et décalait
   toutes les colonnes de l'en-tête par rapport aux lignes. */
.isis-hab-ligne__actions { display: inline-flex; align-items: center; gap: 0.4rem; justify-self: end; }
.isis-hab-ligne__vide { color: var(--isis-text-soft); }
.isis-hab-ligne__refus { color: var(--isis-danger); font-weight: 600; }
/* Même correctif que .isis-origine-liste en sombre : --isis-danger y tombe sous l'AA. */
:root[data-theme="dark"] .isis-hab-ligne__refus { color: #fca5a5; }
.isis-hab-ligne__texte { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.isis-hab-ligne__dormant { grid-column: span 3; color: var(--isis-text-soft); font-size: 0.8rem; }
/* Le libellé de cellule n'est LU que tant que l'en-tête de colonnes le porte à l'écran ; en
   colonne unique (écran étroit), il redevient visible. */
.isis-hab-ligne__k {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.isis-hab-puce {
    display: inline-block;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: 0.78rem;
    padding: 0.05rem 0.45rem;
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-sm);
    background: var(--isis-surface-soft);
}
.isis-hab-puce.is-inactif { color: var(--isis-text-soft); text-decoration: line-through; }
/* Replié, la ligne n'a pas de filet sous l'en-tête : elle est entière. */
.isis-habilitation-block.is-open:not(.is-deplie) .isis-hab-ligne { border-bottom: 0; }
.isis-habilitation-block.is-deplie { border-color: var(--isis-border-strong); }
.isis-hab-aucun { padding: 0.4rem 1rem; }

/* Onglet Droits effectifs (2026-09-19) : une ligne par écran, rangée comme le menu. */
.isis-droits-eff { display: flex; flex-direction: column; gap: 0.85rem; }
.isis-droits-eff__modules { display: flex; flex-wrap: wrap; gap: 0.4rem; }
.isis-droits-eff__module {
    border: 1px solid var(--isis-border); background: var(--isis-surface); color: var(--isis-text);
    border-radius: 999px; padding: 0.25rem 0.8rem; font: inherit; font-size: 0.84rem; cursor: pointer;
}
.isis-droits-eff__module:hover { background: var(--isis-surface-soft); }
.isis-droits-eff__module[aria-pressed="true"] {
    /* Fond pâle + encre du texte : le blanc sur la teinte du module tombe à 3,7:1 en clair. */
    background: var(--isis-current-mod-soft); border-color: var(--isis-current-mod); color: var(--isis-text); font-weight: 600;
}
.isis-droits-eff__phrase { margin: 0; font-size: 0.92rem; line-height: 1.55; max-width: 90ch; }
.isis-droits-eff__filtres { display: flex; flex-wrap: wrap; align-items: center; gap: 0.6rem 1rem; }
.isis-droits-eff__bascule { display: inline-flex; border: 1px solid var(--isis-border); border-radius: var(--isis-radius); overflow: hidden; }
.isis-droits-eff__bascule button {
    border: 0; background: var(--isis-surface); color: var(--isis-text-muted); font: inherit; font-size: 0.82rem;
    padding: 0.3rem 0.75rem; cursor: pointer;
}
.isis-droits-eff__bascule button + button { border-left: 1px solid var(--isis-border); }
.isis-droits-eff__bascule button[aria-pressed="true"] { background: var(--isis-current-mod-soft); color: var(--isis-text); font-weight: 600; }
.isis-droits-eff__table-wrap { overflow-x: auto; border: 1px solid var(--isis-border); border-radius: var(--isis-radius); }
.isis-droits-eff__table { width: 100%; min-width: 760px; border-collapse: collapse; font-size: 0.85rem; }
.isis-droits-eff__table thead th {
    position: sticky; top: 0; z-index: 1; text-align: left; padding: 0.5rem 0.75rem;
    font-size: 0.65rem; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase;
    color: var(--isis-text-soft); background: var(--isis-surface-soft); border-bottom: 1px solid var(--isis-border);
}
.isis-droits-eff__table td, .isis-droits-eff__table tbody th {
    padding: 0.45rem 0.75rem; border-bottom: 1px solid var(--isis-border-soft); vertical-align: middle; text-align: left;
}
.isis-droits-eff__table tr.is-groupe th {
    padding-top: 0.7rem; background: var(--isis-surface-soft); font-size: 0.65rem; font-weight: 700;
    letter-spacing: 0.1em; text-transform: uppercase; color: var(--isis-text-soft);
}
.isis-droits-eff__table tr.is-sous-menu th { font-size: 0.78rem; font-weight: 600; color: var(--isis-text-muted); padding-left: 1rem; }
.isis-droits-eff__ecran { font-weight: 500; white-space: nowrap; }
.isis-droits-eff__ecran.is-niveau-1 { padding-left: 1.9rem; }
.isis-droits-eff__ecran.is-niveau-2 { padding-left: 3rem; }
.isis-droits-eff__ecran.is-niveau-3 { padding-left: 4.1rem; }
.isis-droits-eff__indent {
    display: inline-block; width: 0.55rem; margin-right: 0.35rem; vertical-align: middle;
    border-top: 1px solid var(--isis-border-strong);
}
.isis-droits-eff__table tr.is-sans-acces th, .isis-droits-eff__table tr.is-sans-acces td { color: var(--isis-text-soft); }
.isis-droits-eff__cran {
    display: inline-block; border-radius: 999px; padding: 0.05rem 0.6rem; font-size: 0.78rem; font-weight: 600; white-space: nowrap;
}
.isis-droits-eff__cran.is-gerer { border: 1px solid var(--isis-current-mod); color: var(--isis-text); }
.isis-droits-eff__cran.is-contribuer { background: var(--isis-success-soft); color: var(--isis-success); }
.isis-droits-eff__cran.is-consulter { background: var(--isis-surface-alt); color: var(--isis-text-muted); }
.isis-droits-eff__cran.is-personnalise { background: var(--isis-warning-soft); color: var(--isis-warning); }
.isis-droits-eff__cran.is-aucun { border: 1px dashed var(--isis-border); color: var(--isis-text-soft); }
.isis-droits-eff__cran.is-capacites { border: 1px solid var(--isis-border); color: var(--isis-text-muted); }
.isis-droits-eff__cran.is-delegation { border: 1px dashed var(--isis-current-mod); color: var(--isis-text); }
.isis-droits-eff__hors-cran { display: block; margin-top: 0.15rem; font-size: 0.76rem; color: var(--isis-text-muted); }
.isis-droits-eff__cap {
    display: inline-block; margin: 0.05rem 0.25rem 0.05rem 0; padding: 0.02rem 0.45rem; font-size: 0.76rem;
    border: 1px solid var(--isis-border); border-radius: var(--isis-radius-sm); background: var(--isis-surface-soft);
}
.isis-droits-eff__cap.is-refus { border-color: var(--isis-danger); color: var(--isis-danger); text-decoration: line-through; background: transparent; }
.isis-droits-eff__vide { color: var(--isis-text-soft); }
.isis-droits-eff__sources { line-height: 1.6; }
.isis-droits-eff__source { white-space: nowrap; }
.isis-droits-eff__nature { color: var(--isis-text-soft); }
.isis-droits-eff__plus { margin: 0 0.3rem; color: var(--isis-text-soft); }
.isis-droits-eff__flag { display: inline-block; margin-left: 0.4rem; padding: 0 0.4rem; border-radius: var(--isis-radius-sm); font-size: 0.72rem; font-weight: 600; white-space: nowrap; }
.isis-droits-eff__flag.is-refus { background: var(--isis-danger-soft); color: var(--isis-danger); }
.isis-droits-eff__flag.is-double { background: var(--isis-warning-soft); color: var(--isis-warning); }
.isis-droits-eff__delegation { display: block; font-size: 0.76rem; color: var(--isis-text-muted); }
.isis-droits-eff__detail-cell { text-align: right; width: 5.5rem; }
.isis-droits-eff__detail-btn {
    border: 0; background: none; color: var(--isis-accent-strong); font: inherit; font-size: 0.8rem; cursor: pointer; padding: 0.1rem 0.2rem;
    text-decoration: underline; text-underline-offset: 2px;
}
.isis-droits-eff__detail td { background: var(--isis-surface-soft); padding: 0.5rem 1rem 0.65rem 2.2rem; font-size: 0.8rem; }
.isis-droits-eff__detail ul { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 0.25rem; }
.isis-droits-eff__detail li.is-refus strong, .isis-droits-eff__detail li.is-refus .isis-droits-eff__verdict { color: var(--isis-danger); }
.isis-droits-eff__verdict { margin-left: 0.35rem; font-size: 0.74rem; text-transform: uppercase; letter-spacing: 0.05em; color: var(--isis-text-soft); }
.isis-droits-eff__avertit { color: var(--isis-warning); }
.isis-droits-eff__legende { margin: 0; display: flex; flex-wrap: wrap; gap: 0.4rem 1.1rem; font-size: 0.78rem; color: var(--isis-text-muted); }
/* Refus en sombre : --isis-danger y tombe sous l'AA (cf. .isis-origine-liste). */
:root[data-theme="dark"] .isis-droits-eff__cap.is-refus,
:root[data-theme="dark"] .isis-droits-eff__flag.is-refus,
:root[data-theme="dark"] .isis-droits-eff__detail li.is-refus strong,
:root[data-theme="dark"] .isis-droits-eff__detail li.is-refus .isis-droits-eff__verdict { color: #fca5a5; }

/* Les modules sans accès, derrière une seule ligne. */
.isis-hab-fermes {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.2rem 0.6rem;
    width: 100%;
    padding: 0.6rem 1rem;
    border: 1px dashed var(--isis-border);
    border-radius: var(--isis-radius);
    background: transparent;
    color: var(--isis-text);
    text-align: left;
    font: inherit;
    cursor: pointer;
}
.isis-hab-fermes:hover { background: var(--isis-surface-soft); }
.isis-hab-fermes__label { font-weight: 600; }
.isis-hab-fermes__meta { font-size: 0.8rem; color: var(--isis-text-soft); }

/* « Attribuer d'un geste » : sous les modules, ses trois sections en retrait. */
.isis-hab-geste { margin-top: 1.25rem; }
.isis-hab-geste h2.isis-habilitation-block__label { margin: 0; font-size: 1rem; line-height: inherit; }
.isis-hab-geste h3.isis-habilitation-block__label { margin: 0; font-size: 0.95rem; line-height: inherit; }
.isis-hab-geste__corps { display: flex; flex-direction: column; gap: 0.6rem; padding: 0.9rem 1rem 1rem; }
.isis-hab-geste__corps.is-hidden { display: none; }

@media (max-width: 1100px) {
    .isis-hab-colonnes { display: none; }
    .isis-habilitation-block__head.isis-hab-ligne { grid-template-columns: 1.75rem minmax(0, 1fr) auto; }
    .isis-hab-ligne__cell { grid-column: 2 / 3; }
    .isis-hab-ligne__actions { grid-column: 3; grid-row: 1; }
    .isis-hab-ligne__dormant { grid-column: 2 / 3; }
    .isis-hab-ligne__k {
        position: static; width: auto; height: auto; margin: 0; overflow: visible;
        clip: auto; white-space: normal; color: var(--isis-text-soft);
    }
}
.isis-habilitation-role,
.isis-habilitation-derog,
.isis-habilitation-perimetre {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 1rem;
    padding: 0.5rem 0;
    border-bottom: 1px solid var(--isis-border);
}
.isis-habilitation-role:last-of-type,
.isis-habilitation-derog:last-of-type { border-bottom: 0; }
.isis-habilitation-perimetre { border-bottom: 0; align-items: center; }
.isis-habilitation-section__hint { display: block; margin: -0.25rem 0 0.35rem; }
.isis-habilitation-role__main,
.isis-habilitation-derog__main,
.isis-habilitation-perimetre__main {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    min-width: 0;
}
.isis-habilitation-role__head,
.isis-habilitation-derog__head {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    flex-wrap: wrap;
}
.isis-habilitation-role__label,
.isis-habilitation-derog__cible { font-weight: 500; }
/* Le libellé du rôle est un lien vers sa fiche. Il garde la typographie de la ligne — le
   passer en `.isis-text-link` l'aurait rétréci et grisé, alors que c'est l'identifiant de
   l'entrée. Le soulignement est PERMANENT et non posé au survol : l'affordance ne doit pas
   tenir à la couleur seule (WCAG 1.4.1), et rien d'autre ne distingue ce texte du voisin. */
a.isis-habilitation-role__label {
    color: var(--isis-text);
    text-decoration: underline;
    text-decoration-color: color-mix(in srgb, var(--isis-text) 30%, transparent);
    text-underline-offset: 2px;
}
a.isis-habilitation-role__label:hover,
a.isis-habilitation-role__label:focus-visible {
    color: var(--isis-current-mod, var(--isis-accent));
    text-decoration-color: currentColor;
}
a.isis-habilitation-role__label:focus-visible {
    outline: 2px solid var(--isis-current-mod, var(--isis-accent));
    outline-offset: 2px;
    border-radius: 3px;
}
.isis-habilitation-role__origin,
.isis-habilitation-role__scope,
.isis-habilitation-perimetre__phrase,
.isis-habilitation-section__hint,
.isis-habilitation-derog__origin {
    font-size: 0.78rem;
    color: var(--isis-text-soft);
}
/* Ce que le badge « désactivé » veut dire, écrit plutôt que mis en tooltip : un badge n'est pas
   focalisable, son title n'atteint donc ni le clavier ni un lecteur d'écran. */
.isis-habilitation-role__inactive {
    font-size: 0.78rem;
    color: var(--isis-danger);
}
.isis-habilitation-derog__reason {
    font-size: 0.8rem;
    color: var(--isis-text);
    font-style: italic;
}
/* Ce qu'une dérogation fait aux rôles listés juste au-dessus. Le refus est en danger et en
   gras — c'est le seul énoncé de l'écran qui RETIRE un droit que la lecture des rôles laisse
   croire acquis ; l'accord, qui ne fait qu'ajouter, reste en retrait. La distinction ne tient
   pas à la couleur seule : les deux phrases disent leur sens en toutes lettres. Même taille et
   même jeton que `.isis-habilitation-role__inactive`, l'autre conséquence écrite de la
   section. */
.isis-habilitation-derog__primaute {
    font-size: 0.78rem;
    color: var(--isis-text-muted);
}
.isis-habilitation-derog__primaute.is-refus {
    color: var(--isis-danger);
    font-weight: 600;
}
.isis-habilitation-role__actions,
.isis-habilitation-derog__actions,
.isis-habilitation-perimetre__actions {
    display: flex;
    align-items: center;
    gap: 0.35rem;
    flex: 0 0 auto;
}
.isis-habilitation-assign {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin-top: 0.7rem;
}
.isis-habilitation-assign__label {
    font-size: 0.78rem;
    color: var(--isis-text-soft);
}

@media (max-width: 720px) {
    .isis-habilitation-role,
    .isis-habilitation-derog,
    .isis-habilitation-perimetre { flex-direction: column; align-items: stretch; gap: 0.4rem; }
    .isis-habilitation-block__closed { padding-left: 1rem; }
}

/* ─────────────────────────────────────────────────────────────────────────────
   Surveillance / Audit applicatif — /admin/surveillance/audit
   Grille 7 colonnes (status / horodatage / type / résultat / acteur / IP / cible)
   ───────────────────────────────────────────────────────────────────────────── */
/* Horodatage 130 → 185 et Résultat 100 → 140 le 2026-09-06 : leurs en-têtes portent
   désormais un bouton de tri ET un entonnoir, et « Horodatage (UTC) » comme « Résultat »
   s'y élidaient (mesuré au navigateur, scrollWidth > clientWidth). */
.isis-grid--audit-event .isis-grid__head,
.isis-grid--audit-event .isis-grid__row {
    grid-template-columns: 24px 210px minmax(180px, 1.4fr) 140px minmax(160px, 1.2fr) 120px 110px;
    min-width: 1100px;
}

/* Alias sémantique pour status dot — la palette existante exposait is-ready (vert),
   on ajoute is-success comme alias plus discutable et plus lisible côté code. */
.isis-grid__status-dot.is-success { background: #16a34a; }

/* Bloc payload JSON dans le sidepanel audit. Police mono, scroll horizontal
   conservé pour les longs strings (UA, error stack), pas de word-break dur
   qui casserait la lisibilité d'un payload JSON formaté. */
.isis-audit-payload {
    margin: 0.5rem 0 0 0;
    padding: 0.6rem 0.75rem;
    background: var(--isis-surface-alt);
    border: 1px solid var(--isis-border);
    border-radius: 6px;
    font-family: var(--isis-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
    font-size: 0.72rem;
    line-height: 1.45;
    color: var(--isis-text);
    overflow: auto;
    max-height: 420px;
    white-space: pre;
}

/* ─────────────────────────────────────────────────────────────────────────────
   Surveillance / Comptes — /admin/surveillance/comptes
   3 grilles : verrouillés / échecs récents / tokens reset actifs
   ───────────────────────────────────────────────────────────────────────────── */
.isis-grid--locked-accounts .isis-grid__head,
.isis-grid--locked-accounts .isis-grid__row {
    grid-template-columns: 160px minmax(160px, 1.2fr) minmax(180px, 1.4fr) 90px 180px 90px;
    min-width: 920px;
}
.isis-grid--recent-failures .isis-grid__head,
.isis-grid--recent-failures .isis-grid__row {
    grid-template-columns: minmax(180px, 1.3fr) 110px 140px minmax(160px, 1fr) 120px 130px;
    min-width: 920px;
}
.isis-grid--active-tokens .isis-grid__head,
.isis-grid--active-tokens .isis-grid__row {
    grid-template-columns: 160px minmax(180px, 1.4fr) 140px 110px 130px 60px;
    min-width: 880px;
}

/* Mise en évidence d'une ligne d'alerte (échecs ≥ 5 = potentiel brute-force ciblé).
   Bande gauche rouge + fond très léger — discret mais détecté au scan visuel. */
.isis-grid__row--alert {
    background: linear-gradient(to right,
        color-mix(in srgb, var(--isis-danger) 4%, transparent) 0%,
        transparent 60%);
}

/* ─────────────────────────────────────────────────────────────────────────────
   Surveillance / Santé tenant — /admin/surveillance/tenant
   Layout dashboard 2 colonnes responsive + cards avec titre + métriques
   ───────────────────────────────────────────────────────────────────────────── */
.isis-health-cards {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(380px, 1fr));
    gap: 1rem;
}
.isis-health-card {
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
}
.isis-health-card__title {
    display: flex;
    align-items: center;
    gap: 0.45rem;
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--isis-text);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    padding-bottom: 0.4rem;
    border-bottom: 1px solid var(--isis-border);
}
.isis-health-card__metrics {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(110px, 1fr));
    gap: 0.6rem;
    margin-top: 0.2rem;
}
.isis-health-card__metric {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.1rem;
    padding: 0.4rem 0.6rem;
    background: var(--isis-surface-alt);
    border-radius: 6px;
    border: 1px solid transparent;
    box-sizing: border-box;
}
.isis-health-card__metric.is-success { border-left-color: #16a34a; }
.isis-health-card__metric.is-warning { border-left-color: #d97706; }
.isis-health-card__metric.is-danger  { border-left-color: var(--isis-danger); }
.isis-health-card__metric-val {
    font-size: 1.1rem;
    font-weight: 600;
    font-family: var(--isis-font-mono, ui-monospace, monospace);
    font-variant-numeric: tabular-nums;
    color: var(--isis-text);
}
.isis-health-card__metric-lbl {
    font-size: 0.7rem;
    color: var(--isis-text-soft);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}
.isis-health-card__cta {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    margin-top: 0.4rem;
    font-size: 0.8rem;
    color: var(--isis-current-mod, var(--isis-accent));
    text-decoration: none;
}
.isis-health-card__cta:hover,
.isis-health-card__cta:focus-visible {
    text-decoration: underline;
}

/* Barre de quota GED. Fond clair, fill coloré selon taux (success/warning/danger). */
.isis-quota-bar {
    width: 100%;
    height: 8px;
    background: var(--isis-surface-alt);
    border-radius: 4px;
    overflow: hidden;
    margin-top: 0.2rem;
}
.isis-quota-bar__fill {
    height: 100%;
    transition: width 0.3s ease;
}
.isis-quota-bar__fill.is-success { background: #16a34a; }
.isis-quota-bar__fill.is-warning { background: #d97706; }
.isis-quota-bar__fill.is-danger  { background: var(--isis-danger); }

/* ─────────────────────────────────────────────────────────────────────────────
   Surveillance / Audit row-level — /admin/surveillance/audit-data
   Grille 6 colonnes (status / horodatage / table+op / PK / acteur / cols modifiées)
   + table de diff 3 colonnes (col / avant / après)
   ───────────────────────────────────────────────────────────────────────────── */
/* Sept pistes depuis le 2026-09-06 : l'ACTION prend sa propre colonne. Son badge vivait
   dans la cellule Table, si bien que son entonnoir n'avait d'autre place que la pastille
   de 24 px — où il débordait par-dessus la poignée de redimensionnement. Horodatage passe
   de 130 à 185 px pour loger tri + entonnoir de plage sans élider son libellé. */
.isis-grid--audit-log .isis-grid__head,
.isis-grid--audit-log .isis-grid__row {
    grid-template-columns: 24px 185px 150px minmax(200px, 1.5fr) minmax(140px, 1.2fr) minmax(140px, 1fr) 110px;
    min-width: 1160px;
}

/* Alias status dot bleu pour les opérations UPDATE (cohérence avec le badge Info). */
.isis-grid__status-dot.is-info { background: #2563eb; }

/* Diff colonne par colonne. Mise en valeur cellule "avant" en rouge soft / "après"
   en vert soft pour le scan rapide. Police mono, scroll horizontal sur chaque
   cellule pour gérer les longs strings sans casser le layout. */
.isis-diff-table {
    display: flex;
    flex-direction: column;
    gap: 0.2rem;
    font-family: var(--isis-font-mono, ui-monospace, monospace);
    font-size: 0.78rem;
    margin-top: 0.4rem;
}
.isis-diff-table__head {
    display: grid;
    grid-template-columns: minmax(120px, 0.8fr) 1fr 1fr;
    gap: 0.4rem;
    padding: 0.25rem 0.4rem;
    background: var(--isis-surface-alt);
    border-radius: 4px;
    font-size: 0.68rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--isis-text-soft);
    font-weight: 600;
}
.isis-diff-table__row {
    display: grid;
    grid-template-columns: minmax(120px, 0.8fr) 1fr 1fr;
    gap: 0.4rem;
    padding: 0.3rem 0.4rem;
    border-bottom: 1px dashed var(--isis-border);
}
.isis-diff-table__row:last-child { border-bottom: none; }
.isis-diff-table__col {
    color: var(--isis-text);
    font-weight: 600;
    word-break: break-word;
}
.isis-diff-table__old {
    color: #991b1b;
    background: color-mix(in srgb, #fecaca 35%, transparent);
    padding: 0.15rem 0.35rem;
    border-radius: 3px;
    overflow-wrap: anywhere;
}
.isis-diff-table__new {
    color: #166534;
    background: color-mix(in srgb, #bbf7d0 35%, transparent);
    padding: 0.15rem 0.35rem;
    border-radius: 3px;
    overflow-wrap: anywhere;
}

/* ─────────────────────────────────────────────────────────────────────────────
   Console plateforme — pages /master/surveillance/*
   ───────────────────────────────────────────────────────────────────────────── */

/* Audit cross-tenant : 7 colonnes (status / horodatage / type / résultat / tenant / acteur / IP) */
.isis-grid--platform-audit .isis-grid__head,
.isis-grid--platform-audit .isis-grid__row {
    /* « Résultat » élargi le 2026-09-06 : la colonne a gagné un entonnoir de 24 px que la
       piste de 100 px ne prévoyait pas — débordement mesuré de +20 px sur « Tenant ».
       Financé par le minimum de Type, la piste la plus généreuse de la grille. */
    grid-template-columns: 24px 130px minmax(160px, 1.4fr) 124px 110px minmax(160px, 1.2fr) 120px;
    min-width: 1020px;
}

/* Exigences fonctionnelles : 6 colonnes (module / code / énoncé / priorité / statut déclaré / verdict) */
.isis-grid--platform-exigences .isis-grid__head,
.isis-grid--platform-exigences .isis-grid__row {
    grid-template-columns: 7rem 5.5rem minmax(0, 1fr) 8rem 8rem 10rem;
    min-width: 960px;
}

/* Services en arrière-plan : 4 colonnes (catégorie / nom court / FQN / état) */
.isis-grid--hosted-services .isis-grid__head,
.isis-grid--hosted-services .isis-grid__row {
    grid-template-columns: 140px minmax(220px, 1fr) minmax(260px, 1.6fr) 110px;
    min-width: 820px;
}

/* Liens externes : cards plates 2 colonnes (icône + label/desc), wrap responsive */
.isis-external-links {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
    gap: 0.6rem;
}
.isis-external-link {
    display: flex;
    align-items: center;
    gap: 0.7rem;
    padding: 0.6rem 0.8rem;
    background: var(--isis-surface-alt);
    border: 1px solid var(--isis-border);
    border-radius: 6px;
    color: var(--isis-text);
    text-decoration: none;
    transition: background 0.15s ease, border-color 0.15s ease;
}
.isis-external-link:hover,
.isis-external-link:focus-visible {
    background: var(--isis-surface);
    border-color: var(--isis-mod-admin);
    text-decoration: none;
}
.isis-external-link__main {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    min-width: 0;
}
.isis-external-link__label {
    font-weight: 600;
    font-size: 0.88rem;
    color: var(--isis-text);
}
.isis-external-link__desc {
    font-size: 0.75rem;
    color: var(--isis-text-soft);
}

/* ─────────────────────────────────────────────────────────────────────────────
   Console plateforme — pages /master/* additionnelles
   ───────────────────────────────────────────────────────────────────────────── */

/* Super-admins liste : 7 cols (status / login / nom / email / lastLogin / statut / actions) */
.isis-grid--platform-users .isis-grid__head,
.isis-grid--platform-users .isis-grid__row {
    grid-template-columns: 24px 160px minmax(180px, 1.2fr) minmax(220px, 1.4fr) 140px 180px 100px;
    min-width: 1080px;
}

/* Dashboard — migrations en retard : 5 cols (code / nom / appliquées / manquantes / dernière) */
.isis-grid--migration-gap .isis-grid__head,
.isis-grid--migration-gap .isis-grid__row {
    grid-template-columns: 140px minmax(220px, 1.4fr) 110px 110px 160px;
    min-width: 740px;
}

/* Fiche tenant, onglet Activité : Quand | Type | Résultat | Acteur | IP | Détail.
   Le détail (erreur ou charge utile) prend le reste et s'élide, le texte complet
   restant en infobulle. */
.isis-grid--tenant-audit .isis-grid__head,
.isis-grid--tenant-audit .isis-grid__row {
    /* « Résultat » élargi le 2026-09-06 : la colonne a gagné un entonnoir de 24 px que la
       piste de 104 px ne prévoyait pas — débordement mesuré de +16 px sur « Acteur ».
       Financé par le minimum de « Détail », la piste la plus généreuse de la grille. */
    grid-template-columns: 156px minmax(180px, 1.1fr) 128px 168px 128px minmax(176px, 1.4fr);
    min-width: 936px;
}

.isis-audit-cell {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    justify-content: center;
    max-width: 100%;
    min-width: 0;
    gap: 0.05rem;
    padding: 0.35rem 0.35rem;
}
.isis-audit-cell__main {
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.isis-audit-cell__meta {
    font-size: 0.7rem;
    /* text-muted et non text-soft : la nature de l'acteur est une information. */
    color: var(--isis-text-muted);
}

.isis-audit-error,
.isis-audit-payload {
    display: block;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.isis-audit-error { color: var(--isis-danger); font-size: 0.78rem; }
.isis-audit-payload { color: var(--isis-text-muted); font-size: 0.7rem; }

/* Console — Licences d'un tenant (/master/tenants/{id}/license + onglet Licences). */
.isis-license-panel__head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 0.75rem;
    flex-wrap: wrap;
    margin-bottom: 0.9rem;
}
.isis-license-panel__title {
    font-size: 1rem;
    font-weight: 600;
    letter-spacing: -0.005em;
    color: var(--isis-text);
}
/* text-muted et non text-soft : ces lignes portent de l'information opposable
   (code tenant attendu, mode de déploiement, périmètre de l'historique). */
.isis-license-panel__sub {
    font-size: 0.78rem;
    color: var(--isis-text-muted);
    margin-top: 0.2rem;
    line-height: 1.45;
    max-width: 72ch;
}
.isis-license-panel__meta {
    font-size: 0.75rem;
    color: var(--isis-text-muted);
    text-align: right;
    line-height: 1.45;
}
.isis-license-panel__meta strong { color: var(--isis-text); }

.isis-license-panel__actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin-top: 1rem;
}

.isis-license-panel__switches {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
    gap: 1rem;
}

/* Historique des licences d'un tenant : statut | ID | Importée le | Par | Statut | Motif. */
.isis-grid--tenant-licenses .isis-grid__head,
.isis-grid--tenant-licenses .isis-grid__row {
    grid-template-columns: 24px 124px 150px minmax(140px, 1fr) 116px minmax(200px, 1.5fr);
    min-width: 880px;
}

/* Console — Migrations : statut | Code | Tenant | Appliquées | État | Actif | Actions.
   La colonne Actions porte deux boutons LIBELLÉS (« Appliquer » / « Forcer ») et non des
   icônes nues : ces deux actions écrivent sur la base d'un client, un pictogramme seul
   n'est pas un niveau de désambiguïsation acceptable ici. D'où 206px. */
.isis-grid--platform-migrations .isis-grid__head,
.isis-grid--platform-migrations .isis-grid__row {
    /* « Actif » élargi le 2026-09-06 : la colonne a gagné un entonnoir de 24 px que la piste
       de 84 px ne prévoyait pas — débordement mesuré de +12 px sur la colonne Actions.
       Financé par le minimum de Tenant, la colonne la plus large de la grille. */
    grid-template-columns: 24px 130px minmax(160px, 1.4fr) 118px 150px 106px 206px;
    min-width: 892px;
}

/* Le gabarit toolbar (32px) est trop haut pour une ligne de grille. Resserré localement,
   sans toucher au composant global. */
.isis-grid--platform-migrations .isis-grid__col-actions .isis-rich-toolbar__btn {
    height: 28px;
    padding: 0 0.55rem;
    font-size: 0.75rem;
}
.isis-grid--platform-migrations .isis-grid__col-actions .isis-rich-toolbar__btn .rzi {
    font-size: 15px;
}

/* Marqueur « tenant déjà à jour » : pastille de confirmation, pas un bouton. Occupe la
   place du bouton « Appliquer » absent pour que « Forcer » reste aligné d'une ligne à l'autre. */
.isis-migrations-uptodate {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    color: var(--isis-success);
}

/* Template en retard : filet périmétrique teinté (DESIGN.md §1) en remplacement d'une
   bordure inline. Le template est la base SOURCE de clonage : son retard est l'alerte
   la plus grave de la page. */
.isis-migrations-template.is-late {
    background: color-mix(in srgb, var(--isis-accent) 6%, transparent);
    border: 1px solid color-mix(in srgb, var(--isis-accent) 45%, transparent);
}

.isis-migrations-filters {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem 0.75rem;
    align-items: center;
}

/* Le code tenant est un identifiant manipulé : encre pleine, pas le gris de .isis-grid__mono. */
.isis-migrations-code {
    color: var(--isis-text);
    font-weight: 600;
}
.isis-migrations-name { font-weight: 500; }
.isis-migrations-num { font-variant-numeric: tabular-nums; }

/* Console — Migrations du dépôt : statut | Migration | Description | Module | Template |
   Bases clientes | drapeau de collision. La colonne Migration porte le numéro NNNN et le reste
   du nom de fichier. Les quatre pistes fixes pèsent 420px : au plancher de 960px il ne reste
   que ~513px pour les deux pistes souples, et des planchers à 250/240 les y clouaient toutes
   les deux — la Description, seule colonne qu'on LIT, finissait aussi étroite que le nom de
   fichier qu'on ne fait que survoler. D'où 190px sur Migration (le numéro NNNN, identifiant
   manipulé, reste entier ; la queue du nom s'élide et le titre au survol la rend) et 2,1fr
   contre 0,9 sur la Description. Dernière piste à 36px : un drapeau, pas un bouton (aucune
   action par migration, les commandes d'écriture restent par base cliente dans l'onglet
   voisin). */
.isis-grid--depot-migrations .isis-grid__head,
.isis-grid--depot-migrations .isis-grid__row {
    grid-template-columns: 24px minmax(190px, 0.9fr) minmax(260px, 2.1fr) 116px 132px 112px 36px;
    min-width: 960px;
}

/* Aucune fiche derrière une ligne de migration : le curseur ne doit pas promettre un clic. */
.isis-grid--depot-migrations .isis-grid__row { cursor: default; }

/* Le numéro est l'identifiant : encre pleine et chasse fixe, le reste du nom en appui. */
.isis-depot-migration__num {
    font-weight: 600;
    color: var(--isis-text);
    font-variant-numeric: tabular-nums;
}
.isis-depot-migration__rest { color: var(--isis-text-muted); }

/* Titre absent de l'en-tête du fichier : le repli est humanisé depuis le nom, et il s'annonce
   comme tel (anomalie à corriger, pas un cas normal — cf. CLAUDE.md §2). */
.isis-depot-migration__fallback { color: var(--isis-text-muted); font-style: italic; }

/* Couverture incomplète : le RATIO porte l'information (« 3 / 4 » se lit sans couleur, et le
   survol nomme les bases qui manquent) — l'encre d'alerte ne fait que rendre la ligne repérable
   au balayage vertical. Jeton `-text` et non `--isis-warning` : c'est du texte, 4,5:1 exigé
   (mesuré 7,1:1 en clair, 7,3:1 en sombre). */
.isis-grid--depot-migrations .isis-migrations-num.is-incomplete {
    color: var(--isis-warning-text);
    font-weight: 600;
}

/* Drapeau de numéro partagé : l'ordre d'application entre ces fichiers est imprévisible. */
.isis-depot-migration__flag {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--isis-warning);
}

/* Console — Migrations retenues : statut | Migration | Motif | Condition de levée. Deux
   colonnes de PROSE, qui doivent se replier et jamais s'élider : le motif d'une rétention et
   sa condition de levée sont la seule trace de la décision. D'où l'alignement en haut et le
   retour à la ligne, contre le réglage de grille par défaut (une ligne, ellipse). */
.isis-grid--held-migrations .isis-grid__head,
.isis-grid--held-migrations .isis-grid__row {
    grid-template-columns: 24px minmax(240px, 0.9fr) minmax(260px, 1.4fr) minmax(240px, 1.2fr);
    min-width: 880px;
}
.isis-grid--held-migrations .isis-grid__row {
    align-items: start;
    cursor: default;
}
.isis-grid--held-migrations .isis-grid__row > div {
    white-space: normal;
    overflow: visible;
    text-overflow: clip;
    line-height: 1.45;
}

/* Un nom de fichier n'a aucune espace : sans coupure forcée il déborderait de sa colonne. */
.isis-grid--held-migrations .isis-grid__mono {
    overflow-wrap: anywhere;
}

/* Console — Sauvegardes : statut | Début | Cible | Base | Statut | Taille | Durée | Erreur |
   Actions. Les commandes de lancement (sauvegarder, basebackup) restent globales dans
   l'en-tête de page ; seul le test de restauration a une action par ligne, parce que la
   sauvegarde qu'on veut vérifier est rarement la dernière du dernier cycle. */
.isis-grid--platform-backups .isis-grid__head,
.isis-grid--platform-backups .isis-grid__row {
    grid-template-columns: 24px 140px minmax(150px, 1fr) minmax(150px, 1fr) 110px 100px 88px minmax(200px, 1.4fr) 64px;
    min-width: 1026px;
}

/* Test de restauration indisponible (sauvegardes coupées, ou test déjà en cours) :
   affordance grisée explicite plutôt que le rendu navigateur par défaut. */
.isis-grid--platform-backups .isis-grid__action-btn:disabled {
    opacity: 0.4;
    cursor: not-allowed;
}
.isis-grid--platform-backups .isis-grid__action-btn:disabled:hover {
    background: transparent;
    color: var(--isis-text-muted);
}

.isis-backups-filters {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem 0.75rem;
    align-items: center;
}

/* La cible (tenant ou « Base master ») est l'information de repérage de la ligne. */
.isis-backups-target { font-weight: 500; }

.isis-backups-num { font-variant-numeric: tabular-nums; }
/* text-align et non justify-content : .isis-grid__row > div n'est pas un conteneur flex. */
.isis-backups-num.is-end { text-align: right; }

/* Bandeau d'avancement : ne vit que pendant une opération (sauvegarde, test de
   restauration, basebackup). Filet périmétrique teinté accent — la console plateforme
   n'a pas de couleur de module. */
.isis-backups-live {
    display: flex;
    flex-direction: column;
    gap: 0.625rem;
    margin-bottom: 1rem;
    padding: 0.75rem 1rem;
    border: 1px solid color-mix(in srgb, var(--isis-accent) 35%, transparent);
    border-radius: var(--isis-radius);
    background: color-mix(in srgb, var(--isis-accent) 6%, var(--isis-surface));
}

.isis-backups-live__item {
    display: flex;
    align-items: flex-start;
    gap: 0.625rem;
}

.isis-backups-live__spin {
    color: var(--isis-accent);
    font-size: 20px;
    animation: isis-backups-live-spin 1.6s linear infinite;
}

@keyframes isis-backups-live-spin { to { transform: rotate(360deg); } }

@media (prefers-reduced-motion: reduce) {
    .isis-backups-live__spin { animation: none; }
}

.isis-backups-live__body {
    display: flex;
    flex: 1;
    flex-direction: column;
    gap: 0.25rem;
    min-width: 0;
}

.isis-backups-live__detail {
    color: var(--isis-text-muted);
    font-size: var(--isis-fs-sm);
}

.isis-backups-live__bar {
    height: 4px;
    border-radius: 999px;
    background: color-mix(in srgb, var(--isis-accent) 18%, transparent);
    overflow: hidden;
}

.isis-backups-live__bar > span {
    display: block;
    height: 100%;
    background: var(--isis-accent);
    transition: width var(--isis-motion-base);
}

/* Message d'erreur tronqué (titre complet en tooltip), token sémantique plutôt que
   la classe Radzen rz-color-danger. */
.isis-backups-error {
    color: var(--isis-danger);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 100%;
}

/* Vue d'ensemble licences : statut | Tenant | Client | État licence | Enforcement |
   Expiration (date + reste) | Modules | Mode | Actions.
   « Expire le » et « Reste (j) » sont fusionnés : la date seule ne se lit pas, c'est
   l'écart à aujourd'hui qui porte l'urgence. */
.isis-grid--license-overview .isis-grid__head,
.isis-grid--license-overview .isis-grid__row {
    grid-template-columns: 24px 140px minmax(160px, 1.3fr) 150px 168px 152px 92px 110px 76px;
    min-width: 1080px;
}

/* Cellule à deux lignes de la colonne Expiration (même principe que .isis-feedback-cell). */
.isis-license-cell {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    justify-content: center;
    max-width: 100%;
    gap: 0.1rem;
    min-width: 0;
    padding: 0.35rem 0.35rem;
}
.isis-license-cell__main {
    font-weight: 600;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.isis-license-cell__meta {
    font-size: 0.72rem;
    max-width: 100%;
    /* text-muted et non text-soft : cette ligne porte de l'information (WCAG AA). */
    color: var(--isis-text-muted);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.isis-license-cell__meta.is-warning { color: var(--isis-warning); font-weight: 600; }
.isis-license-cell__meta.is-danger  { color: var(--isis-danger);  font-weight: 600; }

.isis-license-filters {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem 0.6rem;
    align-items: center;
}

/* KPI en alerte : filet périmétrique teinté, en remplacement d'une bordure 2px inline. */
.isis-kpi-card--alert {
    background: color-mix(in srgb, var(--isis-danger) 6%, transparent);
    border: 1px solid color-mix(in srgb, var(--isis-danger) 35%, transparent);
    border-radius: var(--isis-radius-sm);
    padding-left: 0.6rem;
    padding-right: 0.6rem;
}

/* Console — Tenants : statut | Code | Nom | Base PG | Pays | Devise | GED | Quota |
   Statut | Provisionné | Actions. Aucune fusion : c'est la page d'inventaire de la
   plateforme, chaque attribut y est un critère de tri. */
/* ── Console plateforme — dialogues de la file « Retours & bugs » ─────────────────────
   Les trois vues (résumé, pièces jointes, capture) portaient 17 styles inline à elles
   seules, dont un <pre> à six propriétés et une paire de classes Radzen recopiées à la
   main (`rz-button rz-button-sm rz-variant-flat rz-light`) en guise de bouton. Le chrome
   se centralise ici, comme partout ailleurs. */
.isis-fbdlg {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    overflow-y: auto;
    max-height: 75vh;
}
.isis-fbdlg__title { margin: 0 0 0.75rem; font-weight: 600; }
.isis-fbdlg__meta {
    display: flex;
    gap: 1.25rem;
    flex-wrap: wrap;
    margin-bottom: 1rem;
    font-size: var(--isis-fs-sm);
    color: var(--isis-text-muted);
}
.isis-fbdlg__meta strong { color: var(--isis-text); }
/* white-space: pre-wrap — une pile d'appel perd son sens si les retours à la ligne sautent. */
.isis-fbdlg__pre {
    white-space: pre-wrap;
    word-break: break-word;
    margin: 0;
    padding: 0.75rem;
    background: var(--isis-surface-alt);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-sm);
    font-family: var(--isis-font-mono);
    font-size: 0.78rem;
    line-height: 1.45;
}
.isis-fbdlg__note { margin: 0.75rem 0 0; font-size: var(--isis-fs-label); color: var(--isis-text-muted); }
.isis-fbdlg__empty { color: var(--isis-text-muted); }

.isis-fbdlg__item {
    display: flex;
    flex-direction: column;
    gap: 0.375rem;
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-sm);
    padding: 0.625rem;
}
.isis-fbdlg__row { display: flex; align-items: center; gap: 0.5rem; }
.isis-fbdlg__name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.isis-fbdlg__size { color: var(--isis-text-muted); font-size: var(--isis-fs-sm); }
.isis-fbdlg__preview {
    max-width: 100%;
    max-height: 420px;
    object-fit: contain;
    border-radius: var(--isis-radius-sm);
}
.isis-fbdlg__shot { max-width: 100%; height: auto; display: block; }

/* Console plateforme — en-tête portant À LA FOIS un bouton de tri et un entonnoir. Sans
   min-width: 0, la piste flex refuse de rétrécir et c'est l'ENTONNOIR qui sort de la cellule,
   par-dessus la colonne voisine (mesuré le 2026-09-06). La règle inverse le sacrifice : le
   libellé s'élide, l'entonnoir garde sa taille (§ G6). Liste étendue grille par grille, à
   mesure de l'harmonisation — jamais posée sur `.isis-grid__head` en général, qui servirait
   225 grilles dont aucune n'a été mesurée. */
.isis-grid--platform-tenants .isis-grid__head > div,
.isis-grid--platform-users .isis-grid__head > div,
.isis-grid--platform-feedback .isis-grid__head > div,
.isis-grid--platform-migrations .isis-grid__head > div,
.isis-grid--depot-migrations .isis-grid__head > div,
.isis-grid--platform-backups .isis-grid__head > div,
.isis-grid--platform-audit .isis-grid__head > div,
.isis-grid--tenant-audit .isis-grid__head > div,
.isis-grid--platform-basemaps .isis-grid__head > div,
.isis-grid--hosted-services .isis-grid__head > div,
.isis-grid--platform-sitemap-anomalies .isis-grid__head > div,
.isis-grid--sessions .isis-grid__head > div { min-width: 0; }

.isis-grid--platform-tenants .isis-grid__head .isis-grid__sort-btn,
.isis-grid--platform-users .isis-grid__head .isis-grid__sort-btn,
.isis-grid--platform-feedback .isis-grid__head .isis-grid__sort-btn,
.isis-grid--platform-migrations .isis-grid__head .isis-grid__sort-btn,
.isis-grid--depot-migrations .isis-grid__head .isis-grid__sort-btn,
.isis-grid--platform-backups .isis-grid__head .isis-grid__sort-btn,
.isis-grid--platform-audit .isis-grid__head .isis-grid__sort-btn,
.isis-grid--tenant-audit .isis-grid__head .isis-grid__sort-btn,
.isis-grid--platform-basemaps .isis-grid__head .isis-grid__sort-btn,
.isis-grid--hosted-services .isis-grid__head .isis-grid__sort-btn,
.isis-grid--platform-sitemap-anomalies .isis-grid__head .isis-grid__sort-btn,
.isis-grid--sessions .isis-grid__head .isis-grid__sort-btn {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.isis-grid--platform-tenants .isis-grid__head .isis-grid__filter-btn,
.isis-grid--platform-users .isis-grid__head .isis-grid__filter-btn,
.isis-grid--platform-feedback .isis-grid__head .isis-grid__filter-btn,
.isis-grid--platform-migrations .isis-grid__head .isis-grid__filter-btn,
.isis-grid--depot-migrations .isis-grid__head .isis-grid__filter-btn,
.isis-grid--platform-backups .isis-grid__head .isis-grid__filter-btn,
.isis-grid--platform-audit .isis-grid__head .isis-grid__filter-btn,
.isis-grid--tenant-audit .isis-grid__head .isis-grid__filter-btn,
.isis-grid--platform-basemaps .isis-grid__head .isis-grid__filter-btn,
.isis-grid--hosted-services .isis-grid__head .isis-grid__filter-btn,
.isis-grid--platform-sitemap-anomalies .isis-grid__head .isis-grid__filter-btn,
.isis-grid--sessions .isis-grid__head .isis-grid__filter-btn { flex: 0 0 auto; }

.isis-grid--platform-tenants .isis-grid__head,
.isis-grid--platform-tenants .isis-grid__row {
    /* Élargi le 2026-09-06 : quatre colonnes (Pays, Devise, Statut, Provisionné) ont gagné un
       entonnoir de 24 px que les pistes ne prévoyaient pas — débordement mesuré au navigateur
       de +15, +20, +10 et +25 px sur la colonne voisine. Financé par Quota (qui n'a pas
       d'entonnoir) et par les deux minima en fr, pour que la colonne Actions reste à l'écran
       à 1440 px comme le voulait la note ci-dessous. */
    grid-template-columns: 24px 112px minmax(150px, 1.3fr) minmax(130px, 0.9fr) 96px 108px 92px 78px 110px 140px 88px;
    /* 1280px sortait la colonne Actions de l'ecran a 1440 (rail 248 + marges) sur la page
       la plus frequentee de la console. Rails resserres plutot que colonnes fusionnees :
       fusionner aurait coute le tri par colonne. */
    min-width: 1118px;
}

/* Compteur d'alerte du sous-titre (organisations non provisionnées). */
.isis-tenants-alert { color: var(--isis-danger); }

.isis-tenants-filters {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem 0.75rem;
    align-items: center;
}

/* Le code tenant est un identifiant manipulé (copié, cherché) : encre pleine,
   pas le gris secondaire de .isis-grid__mono. */
.isis-tenants-code {
    color: var(--isis-text);
    font-weight: 600;
}
.isis-tenants-name { font-weight: 500; }
.isis-tenants-strong { font-weight: 500; }
.isis-tenants-num { font-variant-numeric: tabular-nums; }
/* text-align et non justify-content : .isis-grid__row > div n'est pas un conteneur flex. */
.isis-tenants-num.is-end { text-align: right; }

/* Console — fiche d'une organisation : bloc d'aide au choix d'un backend (stockage GED,
   serveur d'envoi d'email). Une carte par entrée plutôt qu'une liste continue : à quatre
   backends dont deux qu'il faut justement comparer (minio et s3), les entrées se lisaient
   les unes dans les autres. Vivait dans un <style> local de TenantDetail.razor, invisible
   depuis le thème. */
.ged-provider-help {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    margin-bottom: 1rem;
}
.ged-provider-help__row {
    display: grid;
    grid-template-columns: 88px 1fr;
    gap: 0.75rem;
    padding: 0.5rem 0.75rem;
    border: 1px solid var(--isis-border-soft);
    border-radius: var(--isis-radius-sm);
    background: var(--isis-surface-alt);
}
/* Le nom du backend est la valeur littérale à choisir dans la liste déroulante (`s3`,
   `minio`) : mono et en minuscules, jamais capitalisé — l'aide doit montrer exactement
   ce qui sera enregistré. */
.ged-provider-help__row strong {
    font-family: 'Geist Mono', ui-monospace, monospace;
    font-size: 0.72rem;
    letter-spacing: 0.04em;
    color: var(--isis-text-muted);
}
.ged-provider-help__row span {
    font-size: 0.8rem;
    color: var(--isis-text);
}

/* Console — Campagnes de recette : Tenant | Campagne | Statut | Cas | OK | KO |
   Réserve | Clôturée le | PV. Les quatre compteurs restent des colonnes distinctes :
   sur une console cross-tenant, c'est le rapport OK/KO/réserve qui se lit d'un coup d'oeil. */
.isis-grid--platform-recette .isis-grid__head,
.isis-grid--platform-recette .isis-grid__row {
    /* Tenant, Statut et « Clôturée le » ont été élargis : leur en-tête porte désormais un
       entonnoir à côté du libellé (et du bouton de tri, pour les deux dernières). */
    grid-template-columns: 180px minmax(220px, 1.7fr) 165px 78px 72px 72px 96px 185px 110px;
    min-width: 1180px;
}

/* Compteurs alignés à droite et chiffres tabulaires : les colonnes se comparent
   verticalement d'une ligne à l'autre. */
.isis-grid--platform-recette .isis-grid__col-num {
    justify-content: flex-end;
    text-align: right;
    font-variant-numeric: tabular-nums;
}

/* La colonne « Clôturée le » suit immédiatement le bloc de compteurs : la réserve est
   cadrée à DROITE de sa colonne, la date à GAUCHE de la sienne. Mesuré au navigateur,
   il ne restait que 11 px entre les deux valeurs — contre 64 à 196 px partout ailleurs
   sur la même ligne — et « 0 » et « — » se lisaient comme un seul jeton. La colonne
   porte donc son propre retrait, en-tête compris pour que le libellé suive sa valeur.
   2,5rem re-mesuré : ~50 px de blanc, du même ordre que les 64 px qui séparent deux
   compteurs voisins. */
.isis-grid--platform-recette .isis-grid__head-cell:nth-child(8),
.isis-grid--platform-recette .isis-grid__row > *:nth-child(8) {
    padding-left: 2.5rem;
}

.isis-recette-title {
    font-weight: 600;
}

/* Console — Fonds de plan cartographiques : statut | Ordre | Libellé | Code | Type | Actif | Actions */
.isis-grid--platform-basemaps .isis-grid__head,
.isis-grid--platform-basemaps .isis-grid__row {
    /* « Ordre » et « Actif » élargis le 2026-09-06 : la première a gagné un bouton de tri,
       la seconde un tri ET un entonnoir de 24 px — débordements mesurés de +4 et +6 px sur
       la colonne voisine. Financés par le minimum de « Libellé », la piste la plus large. */
    grid-template-columns: 24px 84px minmax(180px, 1.6fr) minmax(140px, 0.9fr) 100px 104px 80px;
    min-width: 760px;
}

/* Console — Retours & bugs : Type | Titre+module | Client | Occ. | Statut | Vu | Actions.
   Source, version applicative et trace ne sont plus des colonnes : ils vivent dans le
   dialogue de détail, qui est l'endroit où l'on corrige réellement un bug. */
/* Sessions (console, admin tenant, MonEspace) : Statut | Démarrée | Dernière activité |
   IP | Appareil | Action. Le modificateur .isis-grid--sessions etait REFERENCE par cinq
   ecrans mais defini nulle part : ces grilles heritaient du gabarit par defaut, taille pour
   la liste des tiers — « Statut » se retrouvait dans un rail de 32px. */
.isis-grid--sessions .isis-grid__head,
.isis-grid--sessions .isis-grid__row {
    grid-template-columns: 104px 150px 165px 130px minmax(200px, 1fr) 100px;
    min-width: 880px;
}

/* Appareils de confiance (MFA) : Appareil | Vu la 1re fois | Expire | Action. */
.isis-grid--trusted-devices .isis-grid__head,
.isis-grid--trusted-devices .isis-grid__row {
    grid-template-columns: minmax(220px, 1fr) 170px 170px 100px;
    min-width: 680px;
}

/* Meme table, variante portant l'IP (MonEspace) : Appareil | Vu le | Expire | État | IP | Action
   (tâche 20 : colonne État ajoutée, entonnoir sur l'onglet ; Action passe de 100px/texte à 70px/
   icône seule — la 28x28 de .isis-grid__action-btn y tient sans tronquer). */
.isis-grid--trusted-devices-ip .isis-grid__head,
.isis-grid--trusted-devices-ip .isis-grid__row {
    grid-template-columns: minmax(190px, 1fr) 150px 150px 110px 130px 70px;
    min-width: 800px;
}

/* MonEspace — 2FA (/mon-espace/2fa, tâche 17) : remplace les `style="…"` inline par des
   classes. Paragraphe d'aide sous un titre de carte, grille QR + secret du setup TOTP,
   bloc des codes de récupération affichés une fois, cartes de choix de méthode. */
.isis-mfa-card-lede {
    font-size: var(--isis-fs-base);
    color: var(--isis-text-muted);
    margin: 0 0 0.75rem;
}
.isis-mfa-card-lede:last-child { margin-bottom: 0; }

.isis-mfa-setup-grid {
    display: flex;
    gap: 1.5rem;
    align-items: center;
    flex-wrap: wrap;
}
.isis-mfa-qr {
    width: 200px;
    height: 200px;
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius);
}
.isis-mfa-secret-block { flex: 1 1 200px; min-width: 200px; }
/* Clé TOTP en clair (tâche 18) : un RadzenTextBox ReadOnly plutôt qu'un <code> — sélectionnable
   ET copiable au clavier (Tab jusqu'au champ ou jusqu'au bouton « Copier », sans dépendre d'une
   sélection à la souris). */
.isis-mfa-secret-field { display: flex; gap: 0.5rem; align-items: center; margin-top: 0.35rem; }
.isis-mfa-secret-input {
    flex: 1;
    font-family: var(--isis-font-mono);
    font-size: var(--isis-fs-sm);
}
.isis-mfa-code-input {
    font-family: var(--isis-font-mono);
    font-size: 1.2rem;
    letter-spacing: 0.3rem;
    text-align: center;
    width: 150px;
}
.isis-mfa-recovery-block {
    font-family: var(--isis-font-mono);
    background: var(--isis-surface-alt);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-sm);
    padding: 1rem;
    margin-top: 0.75rem;
    columns: 2;
    column-gap: 2rem;
}
/* Copier / Télécharger / Imprimer les codes (tâche 19). */
.isis-mfa-recovery-actions {
    display: flex;
    gap: 0.5rem;
    margin-top: 0.75rem;
    flex-wrap: wrap;
}
/* Impression ciblée : bascule body.isis-printing-block (isis-print.js) le temps de
   l'appel window.print() pour n'imprimer QUE le bloc des codes — jamais l'appli autour
   d'un secret affiché une seule fois. Le sélecteur ne s'active que si ce marqueur est
   posé : sans lui, une impression Ctrl+P classique d'un autre écran n'est pas affectée. */
@media print {
    body.isis-printing-block * { visibility: hidden !important; }
    body.isis-printing-block .isis-print-target,
    body.isis-printing-block .isis-print-target * { visibility: visible !important; }
    body.isis-printing-block .isis-print-target {
        position: absolute;
        left: 0;
        top: 0;
        width: 100%;
        box-sizing: border-box;
        padding: 1rem;
    }
    /* Bloc plus long qu'une page (rapport commercial des hubs) : l'appli enveloppe la page dans
       une coque à hauteur d'écran et à débordement masqué, qui ne laisserait imprimer que la
       première page. On lève hauteur et débordement sur la seule chaîne d'ancêtres du bloc. */
    html:has(body.isis-printing-block),
    body.isis-printing-block {
        height: auto !important;
        overflow: visible !important;
    }
    /* Un ancêtre positionné ou transformé deviendrait le bloc conteneur de la cible absolue :
       left: 0 tomberait à droite du rail et la largeur serait celle de la zone de contenu,
       rognée au bord de la feuille. */
    body.isis-printing-block *:has(.isis-print-target) {
        height: auto !important;
        max-height: none !important;
        overflow: visible !important;
        position: static !important;
        transform: none !important;
        filter: none !important;
        contain: none !important;
    }
}
/* Choix de méthode (écran non protégé) : remplace le détournement de .isis-kpi-hero
   (pensé pour des indicateurs chiffrés, pas des cartes de choix) par une grille dédiée. */
.isis-mfa-method-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
    gap: 1rem;
    margin-top: 1.5rem;
}
.isis-mfa-method-icon { font-size: 32px; margin-bottom: 0.5rem; }
/* --isis-current-mod (pas --isis-mod-admin, copié d'un autre module) : cette carte vit sur
   une page monespace, sa couleur d'accent doit suivre le module courant. */
.isis-mfa-method-icon--accent { color: var(--isis-current-mod); }

/* Pas-à-pas TOTP déplié SOUS la carte de méthode choisie (tâche 18, décision : l'activation
   reste dans la page). Séparateur discret pour distinguer le pitch de la méthode (au-dessus)
   du formulaire d'activation (en dessous), dans la même carte. */
.isis-mfa-setup-panel {
    margin-top: 1rem;
    padding-top: 1rem;
    border-top: 1px solid var(--isis-border);
}
/* .field/.label/.helper ne sont stylés globalement que sous .isis-form-linear (720px, 1 colonne) —
   hors de propos ici (carte de choix, pas un formulaire) : la carte du secret et du code de
   vérification a besoin des mêmes étiquettes, scopées à .isis-mfa-setup-panel seulement. */
.isis-mfa-setup-panel .label {
    display: block;
    font-size: var(--isis-fs-label);
    font-weight: 500;
    color: var(--isis-text);
    margin-bottom: 0.25rem;
}
.isis-mfa-setup-panel .helper {
    font-size: var(--isis-fs-xs);
    color: var(--isis-text-muted);
    margin-top: 0.25rem;
}

.isis-grid--platform-feedback .isis-grid__head,
.isis-grid--platform-feedback .isis-grid__row {
    /* Type élargi le 2026-09-06 : la colonne a gagné un entonnoir de 24 px que la piste de
       76 px ne prévoyait pas — débordement mesuré de +16 px sur la colonne Titre. Financé
       par le minimum de Titre, qui est la colonne la plus large de la grille. */
    grid-template-columns: 96px minmax(220px, 1.7fr) minmax(130px, 0.9fr) 64px 168px 152px 108px;
    min-width: 1000px;
}

/* Cellule à deux lignes : information principale + qualificatif discret.
   Évite une colonne de plus pour chaque attribut secondaire. */
.isis-feedback-cell {
    display: flex;
    flex-direction: column;
    /* flex-start, sinon un badge fille s'etire sur toute la largeur de la cellule. */
    align-items: flex-start;
    max-width: 100%;
    gap: 0.1rem;
    min-width: 0;
    padding: 0.35rem 0.35rem;
}
.isis-feedback-cell__title {
    font-weight: 600;
    /* align-items: flex-start dimensionne les enfants sur leur contenu : sans ce plafond,
       le texte deborde au lieu de s'elider. */
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.isis-feedback-cell__meta {
    font-size: 0.72rem;
    max-width: 100%;
    /* text-muted et non text-soft : ce texte doit rester lisible (WCAG AA). */
    color: var(--isis-text-muted);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Deux barres de filtre côte à côte, qui passent à la ligne sur écran étroit. */
.isis-feedback-filters {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem 0.75rem;
    align-items: center;
    margin-bottom: 0.75rem;
}

/* Dashboard — activité récente : 5 cols (status / horodatage / type / tenant / acteur) */
.isis-grid--recent-audit .isis-grid__head,
.isis-grid--recent-audit .isis-grid__row {
    grid-template-columns: 24px 130px minmax(180px, 1.3fr) 130px minmax(160px, 1fr);
    min-width: 720px;
}

/* Templates email plateforme — viewer read-only */
.isis-platform-tpl {
    padding: 0.75rem 0;
    border-top: 1px dashed var(--isis-border);
}
.isis-platform-tpl:first-of-type { border-top: none; padding-top: 0; }
.isis-platform-tpl__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    margin-bottom: 0.5rem;
}
.isis-platform-tpl__code {
    font-family: var(--isis-font-mono);
    font-size: 0.88rem;
    font-weight: 600;
    color: var(--isis-mod-admin);
}
.isis-platform-tpl__locale {
    margin-left: 0.4rem;
    padding: 0.05rem 0.4rem;
    background: var(--isis-surface-alt);
    border-radius: 3px;
    font-family: var(--isis-font-mono);
    font-size: 0.72rem;
    color: var(--isis-text-soft);
}
.isis-platform-tpl__desc {
    font-size: 0.78rem;
    color: var(--isis-text-muted);
    text-align: right;
}
.isis-platform-tpl__body {
    margin-top: 0.4rem;
}
.isis-platform-tpl__body summary {
    cursor: pointer;
    font-size: 0.78rem;
    color: var(--isis-text-soft);
    padding: 0.2rem 0;
}
/* Cap le <pre> à l'intérieur du body — un template HTML complet peut dépasser
   200 lignes et envahir la page si plusieurs sections sont ouvertes simultanément. */
.isis-platform-tpl__body pre.isis-audit-payload {
    max-height: 350px;
    overflow-y: auto;
}
.isis-platform-tpl__vars {
    margin-top: 0.5rem;
    padding: 0.5rem 0.6rem;
    background: var(--isis-surface-alt);
    border-radius: 4px;
}
.isis-platform-tpl__vars-title {
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--isis-text-soft);
    margin-bottom: 0.3rem;
}
.isis-platform-tpl__vars-grid {
    display: grid;
    grid-template-columns: max-content 1fr;
    gap: 0.2rem 0.6rem;
    font-size: 0.78rem;
}
.isis-platform-tpl__vars-grid code {
    color: var(--isis-mod-admin);
    font-weight: 600;
}

/* Bandeau d'alertes du dashboard plateforme */
.isis-platform-alerts {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
    gap: 0.6rem;
}
.isis-platform-alert {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    padding: 0.6rem 0.8rem;
    border-radius: 6px;
    border: 1px solid var(--isis-border);
    text-decoration: none;
    color: var(--isis-text);
    transition: transform 0.1s ease, box-shadow 0.15s ease;
}
.isis-platform-alert:hover,
.isis-platform-alert:focus-visible {
    transform: translateY(-1px);
    box-shadow: var(--isis-elevation-1);
    text-decoration: none;
}
.isis-platform-alert--warning {
    background: var(--isis-warning-soft, #fef3c7);
    border-color: #d97706;
    color: #92400e;
}
.isis-platform-alert--danger {
    background: var(--isis-danger-soft, #fee2e2);
    border-color: var(--isis-danger, #dc2626);
    color: #991b1b;
}
.isis-platform-alert__cta {
    display: block;
    font-size: 0.78rem;
    margin-top: 0.15rem;
    opacity: 0.85;
}

/* Config runtime — layout stacked clé/valeur pour les clés path-like longues
   (ex: Observability:ExternalLinks:GrafanaBaseUrl) qui ne tiennent pas en
   2-cols dans des cards de 380px de large. */
.isis-config-row {
    padding: 0.4rem 0;
    border-bottom: 1px dashed var(--isis-border);
}
.isis-config-row:last-child { border-bottom: none; }
.isis-config-row__key {
    font-size: 0.68rem;
    color: var(--isis-text-soft);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    font-family: var(--isis-font-mono, ui-monospace, monospace);
    margin-bottom: 0.2rem;
    word-break: break-all;
}
.isis-config-row__val {
    font-family: var(--isis-font-mono, ui-monospace, monospace);
    font-size: 0.82rem;
    color: var(--isis-text);
    word-break: break-all;
    overflow-wrap: anywhere;
}
.isis-config-row__val.is-empty {
    color: var(--isis-text-muted);
    font-style: italic;
}

/* ─────────────────────────────────────────────────────────────────────────────
   Warnings de cohérence métier (CoherenceWarning) — panneau form + bandeau fiche
   + hint inline. Utilisé par EngagementFormDialog, EngagementDetail,
   FactureRecueFormDialog. Cf. IsisSolution.Shared.Validation.CoherenceWarning.
   ─────────────────────────────────────────────────────────────────────────── */

/* Panneau en bas de form dialog — encadré sur fond warning 8% */
.isis-form-coherence-warnings {
    margin-top: 0.6rem;
    padding: 0.6rem 0.75rem;
    background: color-mix(in srgb, var(--isis-warning) 8%, var(--isis-surface));
    border: 1px solid var(--isis-warning);
    box-sizing: border-box;
    border-radius: 4px;
    color: var(--isis-text);
}
.isis-form-coherence-warnings__head {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    font-weight: 600;
    font-size: 0.85rem;
    color: var(--isis-text);
    margin-bottom: 0.35rem;
}
.isis-form-coherence-warnings__head .rzi {
    color: var(--isis-warning);
}
.isis-form-coherence-warnings ul {
    margin: 0;
    padding: 0;
    list-style: none;
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
}
.isis-form-coherence-warnings__item {
    font-size: 0.82rem;
    line-height: 1.4;
    padding: 0.2rem 0.4rem;
    border-radius: 3px;
    background: var(--isis-surface);
    border: 1px solid var(--isis-warning);
    box-sizing: border-box;
}
.isis-form-coherence-warnings__item.is-info {
    border-color: var(--isis-accent, #4b5fad);
    background: color-mix(in srgb, var(--isis-accent, #4b5fad) 4%, var(--isis-surface));
}
.isis-form-coherence-warnings__item.is-warning {
    border-color: var(--isis-warning);
}
.isis-form-coherence-warnings__item.is-error {
    border-color: var(--isis-danger);
    background: color-mix(in srgb, var(--isis-danger) 6%, var(--isis-surface));
    color: var(--isis-text);
    font-weight: 500;
}

/* Hint inline sous un input (warning facture↔engagement) */
.isis-form-coherence-warnings__inline {
    margin-top: 0.25rem;
    padding: 0.25rem 0.45rem;
    background: color-mix(in srgb, var(--isis-warning) 10%, var(--isis-surface));
    border: 1px solid var(--isis-warning);
    box-sizing: border-box;
    border-radius: 3px;
    font-size: 0.78rem;
    color: var(--isis-text);
    display: flex;
    align-items: flex-start;
    gap: 0.35rem;
    line-height: 1.35;
}
.isis-form-coherence-warnings__inline .rzi {
    color: var(--isis-warning);
    flex-shrink: 0;
    margin-top: 0.05rem;
}

/* Bandeau sticky sur fiche détail — pleine largeur sous la toolbar */
.isis-coherence-banner {
    display: flex;
    gap: 0.6rem;
    align-items: flex-start;
    padding: 0.55rem 0.85rem;
    background: color-mix(in srgb, var(--isis-warning) 6%, var(--isis-surface));
    border: 1px solid var(--isis-warning);
    box-sizing: border-box;
    border-radius: 4px;
    color: var(--isis-text);
    font-size: 0.85rem;
}
.isis-coherence-banner .rzi {
    color: var(--isis-warning);
    flex-shrink: 0;
    margin-top: 0.1rem;
}
.isis-coherence-banner__list {
    display: flex;
    flex-direction: column;
    gap: 0.2rem;
    line-height: 1.4;
}
.isis-coherence-banner__item.is-error {
    color: var(--isis-danger);
    font-weight: 500;
}
.isis-coherence-banner__item.is-info {
    color: var(--isis-text-muted);
}

/* ── Workflow commande gesproj refondu (migration 0159) ──────────────── */
/* Encadrement des 3 phases (Bon de commande / Exécution / Clôture). */
.isis-wf-phase-frame {
    stroke: var(--isis-border);
    stroke-width: 1;
    opacity: 0.5;
}

/* Losanges décision (Gate QA / Réception client). Polygone SVG. */
.isis-wf-diamond__shape {
    fill: var(--isis-surface);
    stroke: var(--isis-border);
    stroke-width: 1.5;
    transition: fill 0.15s, stroke 0.15s;
}
.isis-wf-diamond.is-future .isis-wf-diamond__shape {
    stroke-dasharray: 3 3;
    opacity: 0.65;
}
.isis-wf-diamond.is-done .isis-wf-diamond__shape {
    fill: color-mix(in srgb, var(--isis-success, #16a34a) 8%, var(--isis-surface));
    stroke: var(--isis-success, #16a34a);
    stroke-width: 1.5;
}
.isis-wf-diamond.is-current .isis-wf-diamond__shape {
    fill: color-mix(in srgb, var(--isis-mod-gesproj) 10%, var(--isis-surface));
    stroke: var(--isis-mod-gesproj);
    stroke-width: 2;
    filter: drop-shadow(0 0 4px color-mix(in srgb, var(--isis-mod-gesproj) 35%, transparent));
}
.isis-wf-diamond.is-unreachable .isis-wf-diamond__shape {
    fill: var(--isis-surface-soft);
    stroke: var(--isis-text-muted);
    stroke-dasharray: 2 4;
    opacity: 0.45;
}
.isis-wf-diamond__label {
    font-size: 10px;
    font-weight: 600;
    fill: var(--isis-text);
    pointer-events: none;
    letter-spacing: 0.02em;
}
.isis-wf-diamond.is-future .isis-wf-diamond__label,
.isis-wf-diamond.is-unreachable .isis-wf-diamond__label {
    fill: var(--isis-text-muted);
}

/* Légende : pastille losange. */
.isis-workflow-legend__shape.is-diamond {
    width: 12px; height: 12px;
    background: transparent;
    border: 1.5px solid var(--isis-border);
    transform: rotate(45deg);
    display: inline-block;
    vertical-align: middle;
}
.isis-wf-phase-label {
    font-size: 9px;
    font-weight: 600;
    fill: var(--isis-text-muted);
    text-anchor: middle;
    text-transform: uppercase;
    letter-spacing: 0.08em;
}
/* Badge pause sur EN_COURS quand IsPaused = true. */
.isis-wf-pause-badge {
    fill: var(--isis-warning, #d97706);
    opacity: 0.95;
}
.isis-wf-pause-badge__text {
    font-size: 10px;
    font-weight: 600;
    fill: #ffffff;
    text-anchor: middle;
}
/* Badge réception confirmée sur LIVREE (workflow B). */
.isis-wf-received-badge {
    fill: var(--isis-success, #16a34a);
    opacity: 0.95;
}
.isis-wf-received-badge__text {
    font-size: 10px;
    font-weight: 600;
    fill: #ffffff;
    text-anchor: middle;
}
/* Badge accusé de réception sur RECEIVED côté engagement (workflow 0164). */
.isis-wf-ack-badge {
    fill: var(--isis-mod-gesst, #be185d);
    opacity: 0.95;
}
.isis-wf-ack-badge__text {
    font-size: 10px;
    font-weight: 600;
    fill: #ffffff;
    text-anchor: middle;
}
/* Workflow intégré 2 rangées (commande+engagement) — libellés rangées. */
.isis-wf-row-label {
    font-size: 10px;
    font-weight: 700;
    fill: var(--isis-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.08em;
}
/* Workflow intégré — état désactivé (rangée non applicable, hachuré gris). */
.isis-wf-node.is-disabled .isis-wf-node__shape {
    fill: url(#wfDiagHatch);
    stroke: var(--isis-border-strong);
    stroke-width: 1;
    stroke-dasharray: 3 3;
}
.isis-wf-node.is-disabled .isis-wf-node__label {
    fill: var(--isis-text-muted);
    opacity: 0.55;
}
.isis-wf-edge.is-disabled {
    stroke: var(--isis-border-strong);
    stroke-dasharray: 3 4;
    opacity: 0.5;
}

/* ════════════════════════════════════════════════════════════════════
   Workflow intégré — swimlanes verticales BPMN (IntegratedWorkflowDiagram).
   Lane A à gauche (engagement gesst), Lane B à droite (commande gesproj).
   ════════════════════════════════════════════════════════════════════ */

/* En-tête de chaque swimlane (titre lane). */
.isis-wf-lane-header {
    font-size: 11px;
    font-weight: 700;
    fill: var(--isis-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.1em;
}

/* Terminator circulaire (Start/End). */
.isis-wf-term {
    stroke-width: 2;
    transition: fill 0.15s, stroke 0.15s;
}
.isis-wf-term.is-done {
    fill: color-mix(in srgb, var(--isis-success, #16a34a) 12%, var(--isis-surface));
    stroke: var(--isis-success, #16a34a);
}
.isis-wf-term.is-current {
    fill: color-mix(in srgb, var(--isis-mod-gesst) 12%, var(--isis-surface));
    stroke: var(--isis-mod-gesst);
}
.isis-wf-term.is-future {
    fill: var(--isis-surface);
    stroke: var(--isis-border-strong);
}
.isis-wf-term.is-disabled {
    fill: url(#wfDiagHatch);
    stroke: var(--isis-border-strong);
    stroke-dasharray: 3 3;
    opacity: 0.6;
}
.isis-wf-term__label {
    font-size: 11px;
    font-weight: 700;
    fill: var(--isis-text);
    pointer-events: none;
}

/* Edges intra-lane (horizontaux dans swimlanes horizontales). */
.isis-wf-edge-h,
.isis-wf-edge-v {
    fill: none;
    stroke-width: 1.6;
    transition: stroke 0.15s, stroke-width 0.15s;
}
.isis-wf-edge-h.is-done,    .isis-wf-edge-v.is-done    { stroke: #16a34a; }
.isis-wf-edge-h.is-current, .isis-wf-edge-v.is-current { stroke: var(--isis-mod-gesst); stroke-width: 2; }
.isis-wf-edge-h.is-future,  .isis-wf-edge-v.is-future  { stroke: #b0bac9; stroke-width: 1.4; }
.isis-wf-edge-h.is-disabled,
.isis-wf-edge-v.is-disabled {
    stroke: var(--isis-border-strong);
    stroke-dasharray: 3 4;
    opacity: 0.5;
}
.isis-wf-edge-h.is-dashed,
.isis-wf-edge-v.is-dashed {
    stroke-dasharray: 5 4;
    opacity: 0.8;
}

/* Flèches de cascade cross-lane (horizontales ou en zig-zag). */
.isis-wf-cascade {
    fill: none;
    stroke-width: 1.6;
    stroke-dasharray: 6 4;
    transition: stroke 0.15s;
}
.isis-wf-cascade.is-done    { stroke: var(--isis-mod-gesst); }
.isis-wf-cascade.is-future  { stroke: var(--isis-border-strong); }
.isis-wf-cascade.is-disabled {
    stroke: var(--isis-border);
    opacity: 0.5;
}
.isis-wf-cascade.is-danger {
    stroke: var(--isis-danger, #dc2626);
    stroke-dasharray: 6 4;
}
.isis-wf-cascade-label {
    font-size: 9px;
    font-weight: 600;
    fill: var(--isis-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    pointer-events: none;
}
.isis-wf-cascade-label.is-danger {
    fill: var(--isis-danger, #dc2626);
}

/* Action manuelle (rectangle pointillé, ex: « Accuser réception »). */
.isis-wf-action {
    fill: var(--isis-surface);
    stroke-width: 1.5;
    stroke-dasharray: 5 3;
    transition: fill 0.15s, stroke 0.15s;
}
.isis-wf-action.is-future {
    stroke: var(--isis-border-strong);
    opacity: 0.75;
}
.isis-wf-action.is-current {
    fill: color-mix(in srgb, var(--isis-mod-gesst) 8%, var(--isis-surface));
    stroke: var(--isis-mod-gesst);
    stroke-dasharray: none;
    stroke-width: 2;
    filter: drop-shadow(0 0 4px color-mix(in srgb, var(--isis-mod-gesst) 30%, transparent));
}
.isis-wf-action.is-done {
    fill: color-mix(in srgb, var(--isis-success, #16a34a) 8%, var(--isis-surface));
    stroke: var(--isis-success, #16a34a);
    stroke-dasharray: none;
}
.isis-wf-action.is-disabled {
    fill: url(#wfDiagHatch);
    stroke: var(--isis-border-strong);
    opacity: 0.55;
}
.isis-wf-action__label {
    font-size: 10px;
    font-weight: 600;
    fill: var(--isis-text);
    pointer-events: none;
}
.isis-wf-action.is-future .isis-wf-action__label,
.isis-wf-action.is-disabled .isis-wf-action__label {
    fill: var(--isis-text-muted);
}

/* Override : losange côté swimlanes en couleur module gesst (pas gesproj). */
.isis-workflow-svg--gesst .isis-wf-diamond.is-current .isis-wf-diamond__shape {
    fill: color-mix(in srgb, var(--isis-mod-gesst) 10%, var(--isis-surface));
    stroke: var(--isis-mod-gesst);
    filter: drop-shadow(0 0 4px color-mix(in srgb, var(--isis-mod-gesst) 35%, transparent));
}

/* Overlay « Lane non applicable » dans une bande hachurée — remplace le rendu
   complet des nodes pour éviter la double-hachure illisible. */
.isis-wf-lane-empty {
    font-size: 18px;
    font-weight: 700;
    fill: var(--isis-text-muted);
    letter-spacing: 0.1em;
    text-transform: uppercase;
    pointer-events: none;
}
.isis-wf-lane-empty--sub {
    font-size: 11px;
    font-weight: 500;
    text-transform: none;
    letter-spacing: 0;
    fill: var(--isis-text-soft);
    font-style: italic;
}

/* ════════════════════════════════════════════════════════════════════
   IntegratedWorkflowDiagram — refonte BPMN column-grid (.wf-*).
   Namespace .wf-* dédié, ne partage rien avec les diagrammes uni-lane
   (.isis-wf-*) ; les 2 systèmes coexistent.
   ════════════════════════════════════════════════════════════════════ */

/* Bandes des swimlanes (rect background). */
.wf-lane-band {
    stroke: var(--isis-border);
    stroke-width: 1;
}
.wf-lane-band--a   { fill: color-mix(in srgb, var(--isis-mod-gesst) 5%, var(--isis-surface)); }
.wf-lane-band--b   { fill: color-mix(in srgb, var(--isis-mod-gesproj) 5%, var(--isis-surface)); }
.wf-lane-band--c   { fill: color-mix(in srgb, var(--isis-mod-gesproj) 8%, var(--isis-surface)); }
.wf-lane-band.is-hatched {
    fill: url(#wfDiagHatch);
    opacity: 0.5;
    stroke: none;
}

/* Tag latéral gauche identifiant la lane (A/B + libellé + sub). */
.wf-lane-tag {
    stroke-width: 0;
}
.wf-lane-tag--a    { fill: color-mix(in srgb, var(--isis-mod-gesst) 18%, var(--isis-surface)); }
.wf-lane-tag--b    { fill: color-mix(in srgb, var(--isis-mod-gesproj) 18%, var(--isis-surface)); }
.wf-lane-tag--c    { fill: color-mix(in srgb, var(--isis-mod-gesproj) 28%, var(--isis-surface)); }
.wf-lane-tag__letter {
    font-size: 19px;
    font-weight: 800;
    fill: var(--isis-text);
    pointer-events: none;
}
.wf-lane-tag__title {
    font-size: 8px;
    font-weight: 700;
    fill: var(--isis-text);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    pointer-events: none;
}
.wf-lane-tag__sub {
    font-size: 7px;
    font-weight: 500;
    fill: var(--isis-text-soft);
    font-style: italic;
    pointer-events: none;
}

/* Overlay « Lane non applicable » si bande hachurée (legacy, plus utilisé v3). */
.wf-lane-empty {
    font-size: 14px;
    font-weight: 700;
    fill: var(--isis-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.08em;
    pointer-events: none;
}
.wf-lane-empty--sub {
    font-size: 9px;
    font-weight: 500;
    text-transform: none;
    letter-spacing: 0;
    fill: var(--isis-text-soft);
    font-style: italic;
}

/* ── NODES (rectangles arrondis = états/statuts) ──────────────── */
.wf-node__shape {
    fill: var(--isis-surface);
    stroke: var(--isis-border);
    stroke-width: 1.4;
    transition: fill 150ms ease, stroke 150ms ease;
}
.wf-node__label {
    font-size: 10px;
    font-weight: 600;
    fill: var(--isis-text);
    pointer-events: none;
}
.wf-node.is-done .wf-node__shape  { fill: color-mix(in srgb, var(--isis-success) 10%, var(--isis-surface)); stroke: #86efac; }
.wf-node.is-done .wf-node__label  { fill: var(--isis-success-text); }
.wf-node.is-current .wf-node__shape {
    fill: color-mix(in srgb, var(--isis-mod-gesst) 14%, var(--isis-surface));
    stroke: var(--isis-mod-gesst);
    stroke-width: 2.2;
    filter: drop-shadow(0 0 6px color-mix(in srgb, var(--isis-mod-gesst) 40%, transparent));
}
.wf-node.is-current .wf-node__label { fill: var(--isis-mod-gesst); font-weight: 700; }
.wf-node.is-future .wf-node__shape  { fill: var(--isis-surface-alt, var(--isis-surface-alt)); stroke: var(--isis-border); }
.wf-node.is-future .wf-node__label  { fill: var(--isis-text-muted); }
.wf-node.is-disabled .wf-node__shape {
    fill: var(--isis-surface);
    stroke: var(--isis-border-strong);
    stroke-dasharray: 4 3;
    stroke-width: 1.2;
    opacity: 0.7;
}
.wf-node.is-disabled .wf-node__label {
    fill: var(--isis-text-muted);
    opacity: 0.7;
    font-weight: 500;
}
.wf-node.is-unreachable .wf-node__shape { fill: transparent; stroke: var(--isis-border); stroke-dasharray: 4 3; }
.wf-node.is-unreachable .wf-node__label { fill: var(--isis-border-strong); }

/* Note : on ne distingue pas A/B en CSS pur (pas de sélecteur sur X/Y SVG).
   La couleur "current" reste uniforme couleur gesst — suffisant V1 car les
   2 lanes ont rarement 2 nodes "current" simultanés. */

/* ── ACTION manuelle (rectangle pointillé, ex: ⚐ Accuser réception) ── */
.wf-action__shape {
    fill: var(--isis-surface);
    stroke: var(--isis-border-strong);
    stroke-width: 1.5;
    stroke-dasharray: 5 3;
    transition: fill 150ms, stroke 150ms;
}
.wf-action__label {
    font-size: 9px;
    font-weight: 600;
    fill: var(--isis-text);
    pointer-events: none;
}
.wf-action.is-current .wf-action__shape {
    fill: color-mix(in srgb, var(--isis-mod-gesst) 10%, var(--isis-surface));
    stroke: var(--isis-mod-gesst);
    stroke-dasharray: none;
    stroke-width: 2;
    filter: drop-shadow(0 0 5px color-mix(in srgb, var(--isis-mod-gesst) 35%, transparent));
}
.wf-action.is-current .wf-action__label { fill: var(--isis-mod-gesst); font-weight: 700; }
.wf-action.is-done .wf-action__shape {
    fill: color-mix(in srgb, var(--isis-success) 10%, var(--isis-surface));
    stroke: #16a34a;
    stroke-dasharray: none;
}
.wf-action.is-done .wf-action__label { fill: var(--isis-success-text); }
.wf-action.is-future .wf-action__label { fill: var(--isis-text-muted); }
.wf-action.is-disabled .wf-action__shape {
    fill: var(--isis-surface);
    stroke: var(--isis-border-strong);
    stroke-dasharray: 4 3;
    opacity: 0.6;
}
.wf-action.is-disabled .wf-action__label {
    fill: var(--isis-text-muted);
    opacity: 0.7;
    font-weight: 500;
}

/* ── DIAMOND décision (◆ Validation ?) ─────────────────────────── */
.wf-diamond__shape {
    fill: var(--isis-surface);
    stroke: var(--isis-border);
    stroke-width: 1.5;
    transition: fill 150ms, stroke 150ms;
}
.wf-diamond__label {
    font-size: 8px;
    font-weight: 600;
    fill: var(--isis-text);
    letter-spacing: 0.02em;
    pointer-events: none;
}
.wf-diamond.is-current .wf-diamond__shape {
    fill: color-mix(in srgb, var(--isis-mod-gesst) 12%, var(--isis-surface));
    stroke: var(--isis-mod-gesst);
    stroke-width: 2.2;
    filter: drop-shadow(0 0 5px color-mix(in srgb, var(--isis-mod-gesst) 35%, transparent));
}
.wf-diamond.is-current .wf-diamond__label { fill: var(--isis-mod-gesst); font-weight: 700; }
.wf-diamond.is-done .wf-diamond__shape    { fill: color-mix(in srgb, var(--isis-success) 10%, var(--isis-surface)); stroke: #16a34a; }
.wf-diamond.is-done .wf-diamond__label    { fill: var(--isis-success-text); }
.wf-diamond.is-future .wf-diamond__shape  { stroke-dasharray: 3 3; opacity: 0.7; }
.wf-diamond.is-future .wf-diamond__label  { fill: var(--isis-text-muted); }
.wf-diamond.is-disabled .wf-diamond__shape {
    fill: var(--isis-surface);
    stroke: var(--isis-border-strong);
    stroke-dasharray: 4 3;
    opacity: 0.6;
}
.wf-diamond.is-disabled .wf-diamond__label {
    fill: var(--isis-text-muted);
    opacity: 0.7;
}

/* ── TERMINATOR (cercle Start/End) ─────────────────────────────── */
.wf-term__shape {
    stroke-width: 2.4;
    transition: fill 150ms, stroke 150ms;
}
.wf-term__letter {
    font-size: 11px;
    font-weight: 800;
    fill: var(--isis-text);
    pointer-events: none;
}
.wf-term__check {
    font-size: 12px;
    font-weight: 800;
    fill: #16a34a;
    pointer-events: none;
}
.wf-term.is-done .wf-term__shape    { fill: color-mix(in srgb, var(--isis-success) 15%, var(--isis-surface)); stroke: #16a34a; }
.wf-term.is-current .wf-term__shape { fill: color-mix(in srgb, var(--isis-mod-gesst) 15%, var(--isis-surface)); stroke: var(--isis-mod-gesst); }
.wf-term.is-future .wf-term__shape  { fill: var(--isis-surface); stroke: var(--isis-border-strong); }
.wf-term.is-future .wf-term__check  { fill: var(--isis-border-strong); }
.wf-term.is-disabled .wf-term__shape {
    fill: var(--isis-surface);
    stroke: var(--isis-border-strong);
    stroke-dasharray: 4 3;
    stroke-width: 1.5;
    opacity: 0.65;
}
.wf-term.is-disabled .wf-term__letter,
.wf-term.is-disabled .wf-term__check { fill: var(--isis-text-muted); opacity: 0.7; }

/* ── EDGES intra-lane (lignes solides ou pointillées) ──────────── */
.wf-edge {
    fill: none;
    stroke-width: 1.8;
    transition: stroke 150ms;
}
.wf-edge.is-done    { stroke: #16a34a; }
.wf-edge.is-current { stroke: var(--isis-mod-gesst); stroke-width: 2.4; }
.wf-edge.is-future  { stroke: var(--isis-border-strong); stroke-width: 1.5; }
.wf-edge.is-disabled { stroke: var(--isis-border); stroke-dasharray: 3 4; opacity: 0.5; }
.wf-edge.is-dashed   { stroke-dasharray: 6 4; opacity: 0.85; }
.wf-edge-label {
    font-size: 8px;
    font-weight: 600;
    fill: var(--isis-text-muted);
    letter-spacing: 0.04em;
    pointer-events: none;
}

/* ── CASCADES cross-lane (flèches verticales/zig-zag) ─────────── */
.wf-cascade {
    fill: none;
    stroke-width: 2;
    stroke-dasharray: 7 4;
    transition: stroke 150ms;
}
.wf-cascade.is-done    { stroke: var(--isis-mod-gesst); }
.wf-cascade.is-future  { stroke: var(--isis-border-strong); }
.wf-cascade.is-disabled { stroke: var(--isis-border); opacity: 0.4; }
.wf-cascade.is-danger  { stroke: var(--isis-danger, #dc2626); }

/* Badge numéroté au milieu d'une cascade (1, 2, 3, 4, 5). */
.wf-cascade-badge__circle {
    fill: var(--isis-surface);
    stroke: var(--isis-mod-gesst);
    stroke-width: 1.8;
}
.wf-cascade-badge__num {
    font-size: 9px;
    font-weight: 800;
    fill: var(--isis-mod-gesst);
    pointer-events: none;
}
.wf-cascade-badge.is-done .wf-cascade-badge__circle {
    fill: var(--isis-mod-gesst);
}
.wf-cascade-badge.is-done .wf-cascade-badge__num {
    fill: white;
}
.wf-cascade-badge.is-future .wf-cascade-badge__circle {
    stroke: var(--isis-border-strong);
}
.wf-cascade-badge.is-future .wf-cascade-badge__num {
    fill: var(--isis-text-muted);
}
.wf-cascade-badge.is-danger .wf-cascade-badge__circle {
    stroke: var(--isis-danger, #dc2626);
    fill: var(--isis-danger, #dc2626);
}
.wf-cascade-badge.is-danger .wf-cascade-badge__num {
    fill: white;
}
.wf-cascade-badge.is-disabled .wf-cascade-badge__circle {
    fill: white;
    stroke: var(--isis-border-strong);
}
.wf-cascade-badge.is-disabled .wf-cascade-badge__num {
    fill: var(--isis-border-strong);
}

/* Badges flag inline sur RECEIVED A / LIVREE B (✓ Accusé / ✓ Reçu). */
.wf-badge {
    opacity: 0.95;
}
.wf-badge--ack       { fill: var(--isis-mod-gesst, #be185d); }
.wf-badge--received  { fill: var(--isis-success, #16a34a); }
.wf-badge__text {
    font-size: 8px;
    font-weight: 700;
    fill: white;
    pointer-events: none;
}

/* ── LÉGENDE NUMÉROTÉE sous le SVG ──────────────────────────────── */
.wf-cascade-legend {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
    gap: 0.25rem 0.75rem;
    margin: 0.5rem 0 0.2rem;
    padding: 0.45rem 0.75rem;
    background: var(--isis-surface-alt, var(--isis-surface-alt));
    border: 1px solid var(--isis-border);
    border-radius: 6px;
}
.wf-cascade-legend__item {
    display: flex;
    align-items: flex-start;
    gap: 0.35rem;
    font-size: 0.65rem;
    line-height: 1.35;
    color: var(--isis-text);
}
.wf-cascade-legend__item em { color: var(--isis-text-soft); font-style: italic; }
.wf-cascade-legend__item.is-danger { color: var(--isis-danger, #dc2626); }
.wf-cascade-legend__num {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 15px;
    height: 15px;
    border-radius: 50%;
    font-size: 0.6rem;
    font-weight: 800;
    background: var(--isis-surface);
    border: 1.5px solid var(--isis-mod-gesst);
    color: var(--isis-mod-gesst);
}
.wf-cascade-legend__num--done {
    background: var(--isis-mod-gesst);
    color: white;
}
.wf-cascade-legend__num--future {
    border-color: var(--isis-border-strong);
    color: var(--isis-text-muted);
}
.wf-cascade-legend__num.is-danger,
.wf-cascade-legend__num--done.is-danger {
    background: var(--isis-danger, #dc2626);
    border-color: var(--isis-danger, #dc2626);
    color: white;
}


/* Classe events pour la timeline (CLIENT_REJECTED en couleur danger). */
.isis-audit-trail__dot.commande-wf-evt-client-rejected {
    background: var(--isis-danger, #c62828);
}
.isis-audit-trail__dot.commande-wf-evt-qa-rejected {
    background: var(--isis-warning, #d97706);
}
.isis-audit-trail__dot.commande-wf-evt-qa-passed {
    background: var(--isis-success, #16a34a);
}
.isis-audit-trail__dot.commande-wf-evt-paused {
    background: var(--isis-warning, #d97706);
    opacity: 0.7;
}
.isis-audit-trail__dot.commande-wf-evt-resumed {
    background: var(--isis-success, #16a34a);
    opacity: 0.7;
}

/* ── Timeline workflow livraison gesproj ───────────────────────────────── */
.isis-audit-trail__dot.livraison-wf-evt-created             { background: #f1f5f9; color: #475569; }
.isis-audit-trail__dot.livraison-wf-evt-marked-ready        { background: var(--isis-accent-soft); color: var(--isis-accent); }
.isis-audit-trail__dot.livraison-wf-evt-shipped             { background: var(--isis-mod-gesproj-soft); color: var(--isis-mod-gesproj); }
.isis-audit-trail__dot.livraison-wf-evt-received            { background: var(--isis-warning-soft, #fff7ed); color: var(--isis-warning, #d97706); }
.isis-audit-trail__dot.livraison-wf-evt-validated           { background: var(--isis-success-soft); color: var(--isis-success); }
.isis-audit-trail__dot.livraison-wf-evt-partially-validated { background: var(--isis-warning-soft, #fff7ed); color: var(--isis-warning, #d97706); }
.isis-audit-trail__dot.livraison-wf-evt-rejected            { background: var(--isis-danger-soft); color: var(--isis-danger); }
.isis-audit-trail__dot.livraison-wf-evt-attachment-added    { background: #f1f5f9; color: #475569; }
.isis-audit-trail__dot.livraison-wf-evt-ligne-updated       { background: #f1f5f9; color: #475569; }

/* ── Partage commande gesproj (CommandeSharesSection) ─────────────────── */
.isis-share-list {
    list-style: none;
    padding: 0;
    margin: 0.5rem 0 0 0;
    display: flex;
    flex-direction: column;
    gap: 0.45rem;
}
.isis-share-list__item {
    display: grid;
    grid-template-columns: 1fr auto auto;
    align-items: start;
    gap: 0.6rem;
    padding: 0.5rem 0.65rem;
    background: var(--isis-surface-soft);
    border: 1px solid var(--isis-mod-gesproj);
    box-sizing: border-box;
    border-radius: 4px;
    font-size: 0.85rem;
}
.isis-share-list__main {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    min-width: 0;
}
.isis-share-list__meta {
    color: var(--isis-text-muted);
    font-size: 0.78rem;
    margin-left: 0.3rem;
}
.isis-share-list__note {
    color: var(--isis-text-muted);
    font-style: italic;
    font-size: 0.8rem;
    margin-top: 0.15rem;
}
.isis-share-list__badges {
    display: inline-flex;
    flex-wrap: wrap;
    gap: 0.2rem;
    align-self: center;
}
.isis-share-list__actions {
    display: inline-flex;
    gap: 0.2rem;
    align-self: center;
}

/* ── Thread de commentaires gesproj (GesprojCommentThread) ───────────── */
.isis-comment-thread {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}
.isis-comment-thread__empty,
.isis-comment-thread__readonly {
    color: var(--isis-text-muted);
    font-size: 0.85rem;
    margin: 0;
}
.isis-comment-thread__list {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 0.45rem;
}
.isis-comment-thread__item {
    padding: 0.5rem 0.65rem;
    background: var(--isis-surface-soft);
    border: 1px solid var(--isis-mod-gesproj);
    box-sizing: border-box;
    border-radius: 4px;
    font-size: 0.85rem;
}
.isis-comment-thread__head {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin-bottom: 0.2rem;
}
.isis-comment-thread__date {
    color: var(--isis-text-muted);
    font-size: 0.75rem;
    margin-left: 0.2rem;
}
.isis-comment-thread__delete {
    background: transparent;
    border: none;
    width: 22px; height: 22px;
    border-radius: 4px;
    color: var(--isis-text-muted);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
.isis-comment-thread__delete:hover {
    background: #ffebee;
    color: #c62828;
}
.isis-comment-thread__edit-btn {
    background: transparent;
    border: none;
    width: 22px; height: 22px;
    border-radius: 4px;
    color: var(--isis-text-muted);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
/* L'auto-marge gauche est portée par le 1er bouton de la cellule actions
   (whichever appears first) — pas par les boutons suivants. */
.isis-comment-thread__head > .isis-comment-thread__edit-btn:first-of-type,
.isis-comment-thread__head > .isis-comment-thread__delete:first-of-type {
    margin-left: auto;
}
.isis-comment-thread__edit-btn:hover {
    background: var(--isis-accent-soft);
    color: var(--isis-accent);
}
.isis-comment-thread__edited {
    color: var(--isis-text-muted);
    font-size: 0.72rem;
    font-style: italic;
    margin-left: 0.2rem;
}
.isis-comment-thread__edit {
    border-top: 1px dashed var(--isis-border);
    padding-top: 0.5rem;
    margin-top: 0.3rem;
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
}
.isis-comment-thread__edit-actions {
    display: flex;
    justify-content: flex-end;
    gap: 0.3rem;
    margin-top: 0.3rem;
}
.isis-comment-thread__body {
    white-space: pre-wrap;
    color: var(--isis-text);
}
.isis-comment-thread__mentions {
    display: inline-flex;
    flex-wrap: wrap;
    gap: 0.3rem;
    margin-top: 0.3rem;
}
.isis-comment-thread__mention {
    background: var(--isis-mod-gesproj-soft, color-mix(in srgb, var(--isis-mod-gesproj) 12%, white));
    color: var(--isis-text);
    padding: 0.05rem 0.4rem;
    border-radius: 10px;
    font-size: 0.72rem;
    font-weight: 500;
}
.isis-comment-thread__compose {
    border-top: 1px dashed var(--isis-border);
    padding-top: 0.5rem;
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
}
.isis-comment-thread__actions {
    display: flex;
    justify-content: flex-end;
    margin-top: 0.3rem;
}
.isis-comment-thread__error {
    color: var(--isis-danger, #c62828);
    font-size: 0.78rem;
    margin-top: 0.2rem;
}

/* ── Chantier C V2 — bandeau cumul avancement validation par item ──────── */
.isis-cumul-banner {
    margin: 0 0 0.8rem 0;
    padding: 0.55rem 0.85rem 0.7rem;
    background: color-mix(in srgb, var(--isis-mod-gesproj) 4%, white);
    /* Filet périmétrique 1px (DESIGN.md §121/§124) : plus de barre gauche 3px ;
       la couleur d'état (module en cours / succès complété) porte tout le contour. */
    border: 1px solid color-mix(in srgb, var(--isis-mod-gesproj) 45%, transparent);
    border-radius: 4px;
}
.isis-cumul-banner.is-complete {
    background: color-mix(in srgb, var(--isis-success) 5%, white);
    border-color: color-mix(in srgb, var(--isis-success) 45%, transparent);
}
.isis-cumul-banner__head {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-size: 0.92rem;
    margin-bottom: 0.4rem;
}
.isis-cumul-banner__head .rzi { color: var(--isis-mod-gesproj); flex-shrink: 0; }
.isis-cumul-banner.is-complete .isis-cumul-banner__head .rzi { color: var(--isis-success); }
.isis-cumul-banner__pct {
    font-weight: 700;
    font-size: 1.05rem;
    color: var(--isis-mod-gesproj);
    font-variant-numeric: tabular-nums;
}
.isis-cumul-banner.is-complete .isis-cumul-banner__pct { color: var(--isis-success); }
.isis-cumul-banner__items {
    width: 100%;
    font-size: 0.85rem;
    border-collapse: collapse;
}
.isis-cumul-banner__items thead th {
    font-weight: 500;
    color: var(--isis-text-muted);
    padding: 0.25rem 0.5rem;
    border-bottom: 1px solid color-mix(in srgb, var(--isis-mod-gesproj) 15%, transparent);
    font-size: 0.78rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
}
.isis-cumul-banner__items tbody td {
    padding: 0.3rem 0.5rem;
    border-bottom: 1px dashed color-mix(in srgb, var(--isis-mod-gesproj) 8%, transparent);
}
.isis-cumul-banner__items tbody tr:last-child td { border-bottom: none; }
.isis-cumul-banner__items tbody tr.is-complete td { opacity: 0.65; }
/* Poste clôturé par avenant : conservé pour l'historique, retiré du reste à livrer. */
.isis-cumul-banner__items tbody tr.is-cloture td { opacity: 0.6; }

/* ── Toggle inline (Chantier C V2 — opt-in auto-facture) ─────────────────── */
.isis-inline-toggle {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.25rem 0.6rem;
    background: var(--isis-surface-soft);
    border: 1px solid var(--isis-border);
    border-radius: 14px;
    font-size: 0.82rem;
    color: var(--isis-text);
    cursor: pointer;
    user-select: none;
}
.isis-inline-toggle:hover {
    background: color-mix(in srgb, var(--isis-mod-gesproj) 6%, var(--isis-surface-soft));
}
.isis-inline-toggle input[type="checkbox"] {
    margin: 0;
    cursor: pointer;
}


/* ── gesmat Phase 1.4 : calibration ──────────────────────────────────────
   Ajoutée 2026-05-19, consolidée par audit ui-ux 2026-05-19.
   Les variantes du bandeau d'alerte (.isis-alert-banner--pending|warning|danger)
   vivent désormais à côté de la définition de base (cf. § Alert banner ci-dessus). */

/* Grille historique calibrations — 7 cols
   Statut | Effectuée le | Expire le | N° certificat | Prestataire | Coût | Actions
   Header colonne Coût alignée à droite — cohérent avec body (tabular-nums right). */
.isis-grid--calibration .isis-grid__head,
.isis-grid--calibration .isis-grid__row {
    grid-template-columns: 110px 120px 120px minmax(140px, 1fr) minmax(160px, 1.2fr) 120px 110px;
    min-width: 920px;
}
.isis-grid--calibration .isis-grid__head > div:nth-child(6) {
    justify-content: flex-end;
    text-align: right;
}
.isis-grid--calibration .isis-grid__row.is-active {
    box-shadow: inset 3px 0 0 var(--isis-mod-gesmat);
}

/* Logiciels installés sur un équipement terrain (chantier B1, 0556). */
.isis-grid--gesmat-logiciels .isis-grid__head,
.isis-grid--gesmat-logiciels .isis-grid__row {
    grid-template-columns: minmax(160px, 1.4fr) minmax(120px, 1fr) 110px 120px minmax(140px, 1fr);
    min-width: 720px;
}

/* Logiciels requis d'un équipement — dépendances de conformité (chantier B2). */
.isis-grid--gesinfo-requis .isis-grid__head,
.isis-grid--gesinfo-requis .isis-grid__row {
    grid-template-columns: minmax(180px, 1.4fr) minmax(140px, 1fr) minmax(200px, 2fr) 56px;
    min-width: 640px;
}

/* Pastille de provenance d'un logiciel requis polymorphe (B2.1) :
   métier (gesmat) vs transverse (gesinfo). Marqueur d'origine, pas un statut.
   Sélecteurs à 2 classes pour battre .isis-chip.is-static (couleur/fond). */
.isis-chip.isis-requis-modpill {
    height: auto;
    margin-left: 0.4rem;
    font-size: 0.66rem;
    line-height: 1.2;
    padding: 0.05rem 0.4rem;
    vertical-align: 1px;
    white-space: nowrap;
    pointer-events: auto; /* re-arme le title (is-static coupe pointer-events) */
}
.isis-chip.isis-requis-modpill--gesmat {
    color: var(--isis-mod-gesmat);
    border-color: color-mix(in srgb, var(--isis-mod-gesmat) 45%, transparent);
    background: color-mix(in srgb, var(--isis-mod-gesmat) 8%, transparent);
}
.isis-chip.isis-requis-modpill--gesinfo {
    color: var(--isis-mod-gesinfo);
    border-color: color-mix(in srgb, var(--isis-mod-gesinfo) 45%, transparent);
    background: color-mix(in srgb, var(--isis-mod-gesinfo) 8%, transparent);
}
/* Dark mode : le tint 8% est marginal (~4.5:1 sur ligne survolée) → 14%. */
[data-theme="dark"] .isis-chip.isis-requis-modpill--gesmat {
    background: color-mix(in srgb, var(--isis-mod-gesmat) 14%, transparent);
}
[data-theme="dark"] .isis-chip.isis-requis-modpill--gesinfo {
    background: color-mix(in srgb, var(--isis-mod-gesinfo) 14%, transparent);
}

/* Sources (équipements/kits) requérant un logiciel — vue lecture seule côté fiche
   logiciel (EF-06). Colonnes : Type / Source / Code / Justification. */
.isis-grid--gesinfo-requerants .isis-grid__head,
.isis-grid--gesinfo-requerants .isis-grid__row {
    grid-template-columns: 120px minmax(180px, 1.6fr) minmax(110px, 0.8fr) minmax(200px, 2fr);
    min-width: 620px;
}

/* Pastille de type de source polymorphe (B2.1) : équipement vs kit.
   Marqueur de nature, PAS lié au module — palette neutre (un kit est toujours
   gesmat, donc ne jamais emprunter les tokens --isis-mod-* qui portent le sens
   « module »). 2 classes pour battre .isis-chip.is-static. */
.isis-chip.isis-requis-srcpill {
    height: auto;
    font-size: 0.66rem;
    line-height: 1.2;
    padding: 0.05rem 0.4rem;
    gap: 0.25rem;
    white-space: nowrap;
    pointer-events: auto; /* re-arme le title (is-static coupe pointer-events) */
}
.isis-chip.isis-requis-srcpill--equipement {
    color: var(--isis-text);
    border-color: var(--isis-border);
    background: var(--isis-surface-alt);
}
.isis-chip.isis-requis-srcpill--kit {
    color: var(--isis-text-muted);
    border-color: var(--isis-border);
    background: transparent;
}

/* Champ form-linear "verrouillé" — affichage non-modifiable d'une valeur
   imposée par le flux (ex : Type=CALIBRATION quand on vient du bouton
   "Envoyer en re-calibration"). Calque visuel d'un input désactivé sans
   l'élément input lui-même (l'AT lit le rôle status + label, pas un dropdown
   trompeur). */
.isis-form-linear__locked-field {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    padding: 0.4rem 0.6rem;
    background: var(--isis-surface-soft);
    border: 1px solid var(--isis-border);
    border-radius: 4px;
    color: var(--isis-text);
    font-size: 0.9rem;
}
.isis-form-linear__locked-field > .isis-form-linear__field-hint {
    font-size: 0.78rem;
    color: var(--isis-text-muted);
}
/* Variante ligne — quand le contenu est une valeur unique composée de plusieurs
   éléments (icône cadenas + libellé, code + intitulé). Sans elle, chaque enfant
   devient un flex item de la colonne et la valeur se casse sur plusieurs lignes. */
.isis-form-linear__locked-field--inline {
    flex-direction: row;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.4rem;
}

/* Grille échéances calibration — 7 cols
   status | équipement (code+libellé) | catégorie | entreprise | statut | expiration | actions
   Ajoutée 2026-05-19, Phase 1.5 (page /gesmat/calibrations/echeances). */
.isis-grid--livraison-envoi .isis-grid__head,
.isis-grid--livraison-envoi .isis-grid__row {
    grid-template-columns: 150px 170px 90px minmax(180px,1.3fr) minmax(140px,1fr) minmax(120px,0.8fr);
}
.isis-grid--livraison-pj .isis-grid__head,
.isis-grid--livraison-pj .isis-grid__row {
    grid-template-columns: minmax(240px,2fr) 130px 100px;
}
.isis-grid--livraison-pj2 .isis-grid__head,
.isis-grid--livraison-pj2 .isis-grid__row {
    grid-template-columns: 160px minmax(220px,1.5fr) 130px 100px;
}
.isis-grid--livraison-livres .isis-grid__head,
.isis-grid--livraison-livres .isis-grid__row {
    grid-template-columns: 120px minmax(200px,1.4fr) minmax(180px,1fr) 110px 100px;
}
.isis-envoi-detail {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 1.5rem;
    padding: 0.75rem 1rem 1rem 2.2rem;
    background: var(--isis-surface-alt);
    border-bottom: 1px solid var(--isis-border);
}
.isis-envoi-detail__title {
    font-weight: 600;
    font-size: 0.85rem;
    display: flex;
    align-items: center;
    gap: 0.4rem;
    margin-bottom: 0.4rem;
}
.isis-envoi-detail__list {
    margin: 0;
    padding-left: 1.1rem;
    font-size: 0.85rem;
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
}
.isis-prereq {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.5rem;
    padding: 0.5rem 0.85rem;
    margin-bottom: 0.75rem;
    background: var(--isis-surface-alt);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-sm);
    font-size: 0.85rem;
}
.isis-prereq__label { font-weight: 600; }
.isis-prereq__item {
    display: flex;
    align-items: center;
    gap: 0.3rem;
    color: var(--isis-text-muted);
}
.isis-prereq__item.is-done { color: var(--isis-success); }
/* Timeline consolidée envois ↔ retours client (fiche livraison) */
.isis-livtl { list-style: none; margin: 0; padding: 0; }
.isis-livtl__item { display: grid; grid-template-columns: 32px 1fr; gap: 0.6rem; padding-bottom: 0.9rem; position: relative; }
.isis-livtl__item::before { content: ""; position: absolute; left: 15px; top: 28px; bottom: 0; width: 2px; background: var(--isis-border); }
.isis-livtl__item:last-child::before { display: none; }
.isis-livtl__marker {
    width: 30px; height: 30px; border-radius: 50%; z-index: 1;
    display: flex; align-items: center; justify-content: center;
    background: var(--isis-surface); border: 2px solid var(--isis-border); color: var(--isis-text-muted);
}
.isis-livtl__item--envoi .isis-livtl__marker { border-color: var(--isis-accent); color: var(--isis-accent); }
.isis-livtl__item--rejet .isis-livtl__marker { border-color: var(--isis-danger); color: var(--isis-danger); }
.isis-livtl__item--validation .isis-livtl__marker { border-color: var(--isis-success); color: var(--isis-success); }
.isis-livtl__item--partielle .isis-livtl__marker { border-color: var(--isis-warning); color: var(--isis-warning); }
.isis-livtl__body { min-width: 0; padding-top: 2px; }
.isis-livtl__head { display: flex; align-items: center; gap: 0.4rem; }
.isis-livtl__head.is-clickable { cursor: pointer; }
.isis-livtl__title { font-weight: 600; font-size: 0.9rem; }
.isis-livtl__date { color: var(--isis-text-muted); font-size: 0.8rem; margin-left: auto; white-space: nowrap; }
.isis-livtl__reason { font-size: 0.85rem; color: var(--isis-text); margin-top: 0.15rem; font-style: italic; }
.isis-grid--echeances .isis-grid__head,
.isis-grid--echeances .isis-grid__row {
    grid-template-columns: 32px minmax(200px, 1.4fr) minmax(140px, 1fr) minmax(160px, 1.2fr) 130px 140px 70px;
    min-width: 980px;
}

/* Layout grille demandes de déménagement gesfac (move_request) :
   N° | Collaborateur | Cible | Date | Statut | Étape | Actions */
.isis-grid--move-request .isis-grid__head,
.isis-grid--move-request .isis-grid__row {
    /* « Date entrée » passe de 100 à 155 px. À 100 px le déclencheur de plage débordait sur
       « Statut » et « Étape », qui devenaient illisibles ; à 130 px le chevauchement avait
       disparu mais l'en-tête « DATE ENTRÉE » se cassait encore sur deux lignes, à côté de
       son bouton de tri et de son entonnoir. Mesuré au navigateur à chaque palier, jamais
       déduit. */
    grid-template-columns: 110px minmax(160px, 1fr) minmax(180px, 1.3fr) 155px 110px 110px 110px;
    min-width: 1035px;
}

/* Sous-libellé secondaire dans une cellule de grille (libellé sous le code,
   ancienneté sous la date, etc.). Phase 1.6 — extraction des styles inline
   répétés dans EquipementListPage + CalibrationEcheancesPage. */
.isis-grid__col-sublabel {
    font-size: 0.78rem;
    color: var(--isis-text-muted);
    margin-top: 0.1rem;
}
/* Sous-label qui doit passer sur sa propre ligne : un span nu se colle au précédent. */
.isis-grid__col-sublabel--bloc { display: block; }
/* Historique VIES déplié : le bouton est un inline-flex, la liste prend sa propre ligne dessous. */
.isis-fiscalite-histo { margin-top: 0.25rem; }
.isis-fiscalite-histo__liste {
    display: flex; flex-direction: column; gap: 0.15rem; margin-top: 0.25rem;
}

/* Dans une valeur de fiche, chaque sous-libellé prend sa ligne : en ligne, deux sous-libellés
   voisins se lisaient collés (« …de facturationterritoire… ») au lecteur d'écran et au copier. */
.isis-detail-grid__val > .isis-grid__col-sublabel {
    display: block;
}

/* Ligne de titre d'une cellule .isis-grid quand elle porte AUSSI un sous-label :
   force le titre sur sa propre ligne (le sous-label passe dessous) et tronque
   proprement les libellés longs plutôt que de les laisser chevaucher. */
.isis-grid__col-title {
    display: block;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Grille planner gespla S5 — 7 cols
   status | ressource | source | période | charge | état | actions */
.isis-grid--planner .isis-grid__head,
.isis-grid--planner .isis-grid__row {
    grid-template-columns: 32px minmax(220px, 1.4fr) minmax(160px, 1fr) minmax(200px, 1.2fr) 90px 120px 60px;
    min-width: 1080px;
}

/* P2 — Grille échéancier commande gesproj — 7 cols
   # | libellé | % | montant | échéance | statut | actions */
.isis-grid--echeancier .isis-grid__head,
.isis-grid--echeancier .isis-grid__row {
    grid-template-columns: 40px minmax(180px, 1.4fr) 70px minmax(120px, 1fr) 110px 132px 128px;
    min-width: 782px;
}
/* Actions : 2 contrôles max (action primaire + menu « Plus »). Vrai conteneur flex
   aligné à droite ; overflow:visible + position:relative pour que le panneau
   dropdown (.isis-toolbar-dropdown__panel) ne soit pas rogné par la cellule. */
.isis-grid--echeancier .isis-grid__actions {
    display: flex;
    align-items: center;
    gap: 2px;
    justify-content: flex-end;
    flex-wrap: nowrap;
    overflow: visible;
    position: relative;
}
/* Cellule statut : empile le badge « Prête » sous le statut sans chevaucher
   la colonne actions (la cellule hérite sinon de overflow:hidden + nowrap). */
.isis-grid--echeancier .isis-echeancier__status-cell {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 3px;
    overflow: visible;
}
/* « Demander la facturation » désactivé (barrière SoD : justificatif/jalon manquant) :
   affordance grisée explicite plutôt que le rendu navigateur par défaut. */
.isis-grid--echeancier .isis-grid__action-btn:disabled {
    opacity: 0.4;
    cursor: not-allowed;
}

/* Consignes de facturation (migration 0437) :
   type | instruction | blocage | origine | actions */
.isis-grid--consigne-fact .isis-grid__head,
.isis-grid--consigne-fact .isis-grid__row {
    grid-template-columns: minmax(150px, 0.9fr) minmax(220px, 1.8fr) 110px 120px 110px;
    min-width: 720px;
}
.isis-grid--consigne-fact .isis-grid__actions {
    justify-content: flex-end;
    flex-wrap: nowrap;
}
.isis-muted { color: var(--isis-text-muted, #6b7480); }

/* Profils de facturation (migration 0439) — cartes de sélection */
.isis-profil-cards {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
    gap: 10px;
}
.isis-profil-card {
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-sm, 6px);
    padding: 11px 14px;
    background: var(--isis-surface, #fff);
    cursor: pointer;
    transition: border-color .12s, box-shadow .12s;
    /* reset bouton natif (carte cliquable accessible clavier) */
    font: inherit;
    color: inherit;
    text-align: left;
    width: 100%;
}
.isis-profil-card:focus-visible { outline: 2px solid var(--isis-current-mod); outline-offset: 2px; }
.isis-profil-card:hover { box-shadow: var(--isis-elevation-1); }
.isis-profil-card.is-active { border-left-color: var(--isis-current-mod); border-color: var(--isis-current-mod); }
.isis-profil-card__head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.isis-profil-card__meta { font-size: 12px; color: var(--isis-text-muted); margin-top: 4px; }

/* Éditeur structuré des paramètres de consigne */
.isis-consigne-merge { display: flex; flex-direction: column; gap: 6px; }
.isis-consigne-merge__item { display: flex; align-items: center; gap: 8px; font-size: 13.5px; }
.isis-consigne-repart { display: flex; flex-direction: column; gap: 8px; margin-bottom: 8px; }
.isis-consigne-repart__row { display: flex; gap: 8px; align-items: center; }

/* Comportement de paiement tiers (Lot 2) */
.isis-paybehavior__head { font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: var(--isis-text-muted); margin-bottom: 8px; }
.isis-paybehavior__row { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.isis-paybehavior__metric { display: flex; flex-direction: column; }
.isis-paybehavior__value { font-size: 20px; font-weight: 800; font-variant-numeric: tabular-nums; color: var(--isis-current-mod); }
.isis-paybehavior__label { font-size: 11.5px; color: var(--isis-text-muted); }

/* Synthèse de facturation dans le sidepanel commande */
.isis-side-billing { margin: 10px 0; padding: 10px 12px; border: 1px solid var(--isis-border); border-radius: var(--isis-radius-sm, 6px); background: var(--isis-surface, #fff); }
.isis-side-billing__title { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: var(--isis-text-muted); margin-bottom: 6px; }
.isis-side-billing__row { display: flex; align-items: center; justify-content: space-between; gap: 10px; font-size: 13px; padding: 2px 0; }
.isis-side-billing__row > span:last-child { font-variant-numeric: tabular-nums; font-weight: 600; }
/* Taux de facturation : fine barre de progression (facturé / montant total). */
.isis-side-billing__bar { height: 5px; border-radius: 999px; background: var(--isis-surface-alt, #eef0f2); overflow: hidden; margin: 4px 0 2px; }
.isis-side-billing__bar > span { display: block; height: 100%; border-radius: 999px; background: var(--isis-current-mod, var(--isis-accent)); transition: width 200ms ease; }
/* Section « Avancement » : barre teintée par santé (miroir colonne Pilotage). */
.isis-side-billing__bar > span.is-ok      { background: var(--isis-success); }
.isis-side-billing__bar > span.is-warn    { background: var(--isis-warning); }
.isis-side-billing__bar > span.is-late    { background: var(--isis-danger); }
.isis-side-billing__bar > span.is-unknown { background: var(--isis-text-muted); }
/* Valeurs santé/rendement alignées à droite dans la ligne (override flex de .isis-health/.isis-rendement). */
.isis-side-pilot .isis-side-billing__row > .isis-health,
.isis-side-pilot .isis-side-billing__row > .isis-rendement { flex: 0 0 auto; justify-content: flex-end; overflow: visible; }
/* Taux compact dans le sous-libellé montant de la grille commandes. */
.isis-amount-rate { font-weight: 600; font-variant-numeric: tabular-nums; color: var(--isis-current-mod, var(--isis-accent)); white-space: nowrap; }

/* P13 — Devis tasks (avant-vente checklist) */
.isis-devis-tasks {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}
.isis-devis-tasks__head {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
}
.isis-devis-tasks__title {
    margin: 0;
    font-size: 0.95rem;
    font-weight: 600;
}
.isis-devis-tasks__subtitle {
    margin: 0.15rem 0 0;
    font-size: 0.8rem;
    color: var(--isis-text-muted);
}
.isis-devis-tasks__list {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
}
.isis-devis-tasks__item {
    display: grid;
    grid-template-columns: 28px 1fr 28px;
    align-items: center;
    gap: 0.5rem;
    padding: 0.35rem 0.5rem;
    border: 1px solid var(--isis-border);
    border-radius: 4px;
    background: var(--isis-surface);
    transition: background 120ms ease, opacity 120ms ease;
}
.isis-devis-tasks__item.is-done {
    background: color-mix(in srgb, var(--isis-success) 6%, var(--isis-surface));
    opacity: 0.85;
}
.isis-devis-tasks__item.is-done .isis-devis-tasks__label {
    text-decoration: line-through;
    color: var(--isis-text-muted);
}
.isis-devis-tasks__toggle,
.isis-devis-tasks__delete {
    background: none;
    border: 0;
    cursor: pointer;
    padding: 4px;
    border-radius: 4px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
.isis-devis-tasks__toggle:hover,
.isis-devis-tasks__delete:hover {
    background: var(--isis-surface-alt);
}
span.isis-devis-tasks__toggle {
    cursor: default;
}
span.isis-devis-tasks__toggle:hover {
    background: none;
}
.isis-devis-tasks__add {
    display: flex;
    gap: 0.5rem;
    align-items: center;
}
.isis-devis-tasks__add .rz-textbox {
    flex: 1;
}

.isis-echeancier {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}
.isis-echeancier__head {
    display: flex;
    justify-content: space-between;
    align-items: flex-end;
    gap: 1rem;
    flex-wrap: wrap;
}
.isis-echeancier__title {
    margin: 0;
    font-size: 1.05rem;
    font-weight: 600;
    color: var(--isis-text);
}
/* Variante discrète : bloc secondaire monté en tête d'un onglet dont il n'est pas le
   sujet (ex. jalonnement par défaut au-dessus des commandes liées) — audit ui-ux
   2026-08-20 : le titre plein volait la vedette à la liste. */
.isis-echeancier__title--sub {
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--isis-text-muted);
    margin: 0;
}
.isis-echeancier__subtitle {
    margin: 0.25rem 0 0;
    font-size: 0.85rem;
    color: var(--isis-text-muted);
}
.isis-echeancier__empty {
    text-align: center;
    padding: 2rem 1rem;
    color: var(--isis-text-muted);
    border: 1px dashed var(--isis-border);
    border-radius: 6px;
}
.isis-echeancier__empty .rz-icon {
    font-size: 2rem;
    color: var(--isis-text-muted);
    margin-bottom: 0.5rem;
}
/* .isis-page-loading : loader de section ou de page générique (hors échéancier). */
.isis-echeancier__loading,
.isis-page-loading {
    display: flex;
    justify-content: center;
    padding: 1.5rem;
}
.isis-echeancier__currency {
    margin-left: 0.25rem;
    color: var(--isis-text-muted);
    font-size: 0.8rem;
}
.isis-echeancier__status {
    display: inline-block;
    padding: 0.15rem 0.5rem;
    border-radius: 12px;
    font-size: 0.75rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.02em;
}
.isis-echeancier__status--pending {
    background: color-mix(in srgb, var(--isis-text-muted) 14%, var(--isis-surface));
    color: var(--isis-text);
}
.isis-echeancier__status--requested {
    background: color-mix(in srgb, var(--isis-accent) 16%, var(--isis-surface));
    color: var(--isis-accent-strong);
}
.isis-echeancier__status--returned {
    background: var(--isis-warning-soft);
    color: var(--isis-warning);
}
/* Checklist des pièces à fournir sur les lignes RETURNED (Lot 2 reprise guidée). */
.isis-echeancier__pieces-todo {
    margin: 0.35rem 0 0; padding: 0; list-style: none;
    display: flex; flex-direction: column; gap: 2px;
    font-size: 0.78rem; color: var(--isis-text-muted);
    /* La cellule Libellé hérite de white-space:nowrap + overflow:hidden (règle grille
       globale) : on les lève ici pour que les libellés de pièces s'enroulent et restent visibles. */
    white-space: normal; overflow: visible;
}
.isis-echeancier__pieces-todo li { display: flex; align-items: flex-start; gap: 4px; }
.isis-echeancier__pieces-todo .rzi { font-size: 14px; flex-shrink: 0; }
.isis-echeancier__status--invoiced {
    background: color-mix(in srgb, var(--isis-accent) 14%, var(--isis-surface));
    color: var(--isis-accent);
}
/* Compteur de justificatifs sur le bouton d'action (preuves attachées à l'échéance). */
.isis-echeancier__justif-count {
    display: inline-block;
    min-width: 1.1em;
    margin-left: 0.15rem;
    padding: 0 0.25rem;
    border-radius: var(--isis-radius-pill);
    background: var(--isis-accent);
    color: var(--isis-on-accent);
    font-size: 0.68rem;
    font-weight: 700;
    line-height: 1.35;
    text-align: center;
    vertical-align: 1px;
}
.isis-echeancier__status--paid {
    background: color-mix(in srgb, var(--isis-success) 14%, var(--isis-surface));
    color: var(--isis-success);
}
.isis-echeancier__status--cancelled {
    background: color-mix(in srgb, var(--isis-danger) 10%, var(--isis-surface));
    color: var(--isis-text-muted);
    text-decoration: line-through;
}

/* Jalons d'avancement (migration 0350)
   # | Jalon | Poids | Avancement | Statut | Échéance liée | Actions */
.isis-grid--jalon .isis-grid__head,
.isis-grid--jalon .isis-grid__row {
    /* #, Jalon, Poids, Avancement, Statut, Acteur, Dates, Demande paiement, Actions */
    grid-template-columns: 40px minmax(170px, 1.5fr) 70px 100px 110px minmax(130px, 1fr) minmax(150px, 1fr) minmax(130px, 1fr) 150px;
    min-width: 1080px;
}
.isis-jalon__sum {
    font-weight: 600;
}
.isis-jalon__sum.is-ok { color: var(--isis-success); }
.isis-jalon__sum.is-warn { color: var(--isis-warning); }
/* Suggestion V2.2 : jalon « prêt à atteindre » (toutes tâches liées à 100 %). */
.isis-jalon-suggest {
    display: inline-flex; align-items: center; gap: 0.2rem; margin-top: 0.2rem;
    font-size: 0.7rem; line-height: 1; padding: 0.12rem 0.4rem; border-radius: 999px;
    color: var(--isis-success);
    background: color-mix(in srgb, var(--isis-success) 10%, var(--isis-surface));
    border: 1px solid color-mix(in srgb, var(--isis-success) 30%, var(--isis-border));
}
.isis-grid__action-btn--success.is-suggested {
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--isis-success) 35%, transparent);
    animation: isis-jalon-suggest-pulse 1.8s ease-in-out infinite;
}
@keyframes isis-jalon-suggest-pulse {
    0%, 100% { box-shadow: 0 0 0 2px color-mix(in srgb, var(--isis-success) 35%, transparent); }
    50%      { box-shadow: 0 0 0 4px color-mix(in srgb, var(--isis-success) 18%, transparent); }
}
.isis-jalon__status {
    display: inline-block;
    padding: 0.15rem 0.5rem;
    border-radius: 12px;
    font-size: 0.75rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.02em;
}
.isis-jalon__status--non_demarre {
    background: color-mix(in srgb, var(--isis-text-muted) 14%, var(--isis-surface));
    color: var(--isis-text-muted);
}
.isis-jalon__status--en_cours {
    background: color-mix(in srgb, var(--isis-accent) 14%, var(--isis-surface));
    color: var(--isis-accent);
}
.isis-jalon__status--atteint {
    background: color-mix(in srgb, var(--isis-success) 14%, var(--isis-surface));
    color: var(--isis-success);
}
.isis-jalon__status--annule {
    background: color-mix(in srgb, var(--isis-danger) 10%, var(--isis-surface));
    color: var(--isis-text-muted);
    text-decoration: line-through;
}
/* Boutons d'en-tête de la section jalons (Appliquer un modèle + Ajouter) */
.isis-echeancier__head-actions {
    display: flex;
    gap: 0.5rem;
    align-items: center;
}
/* Modèles de jalons (admin) — Code | Libellé | Portée | Jalons | Total | État | Actions */
.isis-grid--jalon-tpl .isis-grid__head,
.isis-grid--jalon-tpl .isis-grid__row {
    grid-template-columns: 160px minmax(180px, 1.6fr) minmax(140px, 1fr) 80px 90px 90px 110px;
    min-width: 900px;
}
/* Ligne d'édition d'un item de modèle (libellé + poids + supprimer) */
.isis-jalon-tpl-row {
    display: flex;
    gap: 0.5rem;
    align-items: center;
    margin-bottom: 0.4rem;
}
/* La règle générale form-linear (width:100% !important sur tous les champs) écrasait les
   largeurs de cette ligne flex : le poids s'étalait sur toute la ligne et le libellé se
   retrouvait laminé à quelques pixels. Spécificité supérieure pour rendre la main au flex. */
.isis-form-linear .isis-jalon-tpl-row .rz-textbox {
    width: auto !important;
    flex: 2 1 0;
    min-width: 0;
}
.isis-form-linear .isis-jalon-tpl-row .rz-numeric {
    width: 110px !important;
    flex: 0 0 auto;
}
/* Ligne « étape » du dialog d'application de modèle (date cible + acteur) — même piège :
   width:100% !important du form-linear écrasait les largeurs inline, le datepicker
   s'étalait et laminait le sélecteur d'acteur (vérif visuelle 2026-08-20). */
.isis-jalon-apply-row {
    display: flex;
    gap: 0.5rem;
    align-items: center;
}
.isis-form-linear .isis-jalon-apply-row .rz-datepicker {
    width: 160px !important;
    flex: 0 0 auto;
}
.isis-form-linear .isis-jalon-apply-row .rz-dropdown {
    width: auto !important;
    flex: 1 1 0;
    min-width: 0;
}
/* Compteur de justificatifs sur le bouton d'action du jalon */
.isis-jalon__justif-count {
    font-size: 0.7rem;
    font-weight: 600;
    margin-left: 1px;
}

/* ── Référentiel contrôle qualité des livrables (migrations 0361-0363) ── */
/* Activités — Code | Libellé | Entreprises | Produits | Type | Actions */
.isis-grid--qc-activite .isis-grid__head,
.isis-grid--qc-activite .isis-grid__row {
    grid-template-columns: 150px minmax(200px, 1.8fr) 110px 90px 110px 100px;
    min-width: 820px;
}
/* Produits — Code | Libellé | Activité | Unité | Actions */
.isis-grid--qc-produit .isis-grid__head,
.isis-grid--qc-produit .isis-grid__row {
    grid-template-columns: 160px minmax(220px, 2fr) minmax(140px, 1fr) 110px 100px;
    min-width: 760px;
}
/* Catalogue produit (liste L_produit) : Produit | Entreprise | Article | Templates QC | Actions */
.isis-grid--qc-lproduit .isis-grid__head,
.isis-grid--qc-lproduit .isis-grid__row {
    grid-template-columns: minmax(180px, 1.4fr) minmax(140px, 1fr) minmax(160px, 1.4fr) 120px 100px;
    min-width: 760px;
}
/* L_produit — produits rattachés (dialog) : Code | Produit | Actions */
.isis-grid--qc-lproduit-link .isis-grid__head,
.isis-grid--qc-lproduit-link .isis-grid__row {
    grid-template-columns: 150px minmax(200px, 1fr) 130px;
    min-width: 500px;
}
/* QC par défaut du produit : Code | Template | Critères | État | Actions */
.isis-grid--qc-produit-default .isis-grid__head,
.isis-grid--qc-produit-default .isis-grid__row {
    grid-template-columns: 150px minmax(200px, 1.6fr) 90px 90px 100px;
    min-width: 700px;
}
/* Templates QC possédés (produit) : Nom | Critères | Bloquants | Actions */
.isis-grid--qc-owned-template .isis-grid__head,
.isis-grid--qc-owned-template .isis-grid__row {
    grid-template-columns: minmax(220px, 2fr) 90px 90px 110px;
    min-width: 620px;
}
/* Templates QC possédés (L_produit) : Nom | Activité | Critères | Bloquants | Source | Actions */
.isis-grid--qc-owned-template-l .isis-grid__head,
.isis-grid--qc-owned-template-l .isis-grid__row {
    grid-template-columns: minmax(200px, 1.8fr) minmax(120px, 1fr) 90px 90px 100px 130px;
    min-width: 820px;
}
/* Ligne extensible livraison → panneau livrables & QC inline */
.isis-livraison-detail {
    padding: 0.5rem 0.9rem 1rem 2.4rem;
    background: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 4%, var(--isis-surface));
    border-bottom: 1px solid var(--isis-border);
    overflow-x: auto;
    /* Occupe toute la largeur des lignes (et non la seule largeur visible) : sinon,
       scrollé à droite, le fond du dépliant s'arrêtait au milieu et laissait un vide.
       DOIT rester égal au min-width de .isis-grid--livraisons .isis-grid__row (1876px). */
    min-width: 1876px;
    box-sizing: border-box;
}
.isis-qc-panel { display: flex; flex-direction: column; gap: 0.6rem; }
/* Matrice de contrôle (critères × passes) */
.isis-qc-matrix-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; margin: 0.4rem 0; }
.isis-qc-matrix-toolbar__hint { font-size: 0.82rem; color: var(--isis-text-muted); }
.isis-qc-matrix-wrap { overflow: auto; flex: 1 1 auto; min-height: 120px; border: 1px solid var(--isis-border); border-radius: var(--isis-radius-sm); }
.isis-qc-matrix { border-collapse: separate; border-spacing: 0; width: 100%; font-size: 0.8rem; }
.isis-qc-matrix th, .isis-qc-matrix td { border-bottom: 1px solid var(--isis-border); padding: 0.3rem 0.4rem; vertical-align: top; text-align: left; }
.isis-qc-matrix thead th { position: sticky; top: 0; background: var(--isis-surface-soft); z-index: 1; vertical-align: bottom; }
.isis-qc-matrix__crit-head, .isis-qc-matrix__crit { position: sticky; left: 0; background: var(--isis-surface); min-width: 170px; max-width: 240px; z-index: 1; }
.isis-qc-matrix__crit { font-weight: 500; }  /* th en-tête de ligne, pas le gras lourd par défaut */
.isis-qc-proof-upload__label { display: block; font-size: 0.8rem; color: var(--isis-text-muted); margin-bottom: 0.3rem; }
.isis-qc-matrix thead .isis-qc-matrix__crit-head { z-index: 2; background: var(--isis-surface-soft); }
.isis-qc-matrix th.is-current, .isis-qc-matrix td.is-current { background: color-mix(in srgb, var(--isis-accent) 6%, var(--isis-surface)); }
/* En-tête de passe : libellé en texte VERTICAL (compact), badge de statut horizontal dessous */
/* En-tête de passe : DEUX colonnes verticales côte à côte (rotation) — « Passe X » à gauche,
   le badge de statut à sa droite. Aligné en bas. */
.isis-qc-matrix__passe { display: flex; flex-direction: row; align-items: flex-end; justify-content: center; gap: 0.35rem; }
.isis-qc-matrix__passe-vert { writing-mode: vertical-rl; transform: rotate(180deg); white-space: nowrap; max-height: 150px; overflow: hidden; text-overflow: ellipsis; font-size: 0.76rem; line-height: 1.2; }
/* Badge de statut de passe (Conforme / Non conforme / Brouillon) en texte vertical. */
.isis-qc-vbadge { writing-mode: vertical-rl; transform: rotate(180deg); white-space: nowrap; }
.isis-qc-matrix__passe-date { color: var(--isis-text-muted); }
.isis-qc-matrix__passe-by { color: var(--isis-text); font-weight: 600; }
.isis-qc-matrix__tags { display: inline-flex; gap: 0.2rem; margin-left: 0.35rem; }
.isis-qc-matrix__group td { background: var(--isis-surface-soft); font-weight: 600; font-size: 0.76rem; text-transform: uppercase; letter-spacing: 0.02em; color: var(--isis-text-muted); }
/* Cellules = statut compact (lecture). Plus aucun contrôle dedans (Option A : édition en panneau). */
.isis-qc-matrix__cell { min-width: 64px; text-align: center; vertical-align: middle; }
.isis-qc-matrix__read { display: flex; align-items: center; justify-content: center; gap: 0.35rem; }
.isis-qc-cellview { display: flex; align-items: center; justify-content: center; gap: 0.3rem; flex-wrap: wrap; }
.isis-qc-cellview__val { font-family: var(--isis-font-mono, monospace); font-size: 0.8rem; }
.isis-qc-cellview__note { font-size: 0.76rem; color: var(--isis-text-muted); }
/* Bulle de commentaire dans une cellule : icône + commentaire en infobulle (title) au survol. */
.isis-qc-comment-bubble { display: inline-flex; align-items: center; cursor: help; color: var(--isis-accent); }
.isis-qc-comment-bubble > i { font-size: 14px; vertical-align: middle; }
.isis-qc-matrix__cell.isis-qc-cell--click { cursor: pointer; }
.isis-qc-matrix__cell.isis-qc-cell--click:hover { background: color-mix(in srgb, var(--isis-accent) 9%, var(--isis-surface)); }
.isis-qc-matrix__cell.is-selected { box-shadow: inset 0 0 0 2px var(--isis-accent); background: color-mix(in srgb, var(--isis-accent) 8%, var(--isis-surface)); }
.isis-qc-matrix__cell.isis-qc-cell--click:focus-visible { outline: 2px solid var(--isis-accent); outline-offset: -2px; }

/* Panneau d'édition d'un critère (sous la matrice) */
.isis-qc-editor { margin-top: 0.9rem; border: 1px solid var(--isis-border); border-radius: var(--isis-radius-sm); background: var(--isis-surface-alt); overflow: hidden; }
.isis-qc-editor__head { display: flex; align-items: center; justify-content: space-between; gap: 0.6rem; padding: 0.6rem 0.85rem; border-bottom: 1px solid var(--isis-border); background: var(--isis-surface); flex-wrap: wrap; }
.isis-qc-editor__title { display: flex; align-items: center; gap: 0.4rem; flex-wrap: wrap; }
.isis-qc-editor__sub { color: var(--isis-text-muted); font-size: 0.8rem; font-weight: 400; }
.isis-qc-editor__nav { display: flex; align-items: center; gap: 0.5rem; font-size: 0.82rem; color: var(--isis-text-muted); white-space: nowrap; }
.isis-qc-editor__navbtn { border: 1px solid var(--isis-border); background: var(--isis-surface); border-radius: 6px; cursor: pointer; padding: 0.15rem 0.35rem; line-height: 1; color: var(--isis-text); }
.isis-qc-editor__navbtn:hover:not(:disabled) { background: var(--isis-surface-alt); }
.isis-qc-editor__navbtn:disabled { opacity: 0.4; cursor: default; }
.isis-qc-editor__body { display: flex; flex-direction: column; gap: 0.75rem; padding: 0.9rem 0.95rem; }
.isis-qc-editor__field { display: flex; flex-direction: column; gap: 0.3rem; }
.isis-qc-editor__field label { font-size: 0.8rem; font-weight: 600; color: var(--isis-text-muted); }
.isis-qc-editor__valrow { display: flex; align-items: center; gap: 0.7rem; flex-wrap: wrap; }
.isis-qc-editor__rule { font-size: 0.82rem; color: var(--isis-text-muted); }
.isis-qc-editor__hint { margin-top: 0.85rem; color: var(--isis-text-muted); font-style: italic; }
.isis-qc-edit-tags { display: flex; align-items: center; gap: 0.4rem; flex-wrap: wrap; margin-bottom: 0.2rem; }
.isis-qc-edit-tags__grp { font-size: 0.78rem; color: var(--isis-text-muted); }
.isis-qc-matrix__comment { width: 100%; border: 1px solid var(--isis-border); border-radius: 4px; padding: 0.2rem 0.4rem; font-size: 0.8rem; background: var(--isis-surface); }
.isis-qc-matrix__proof-view { border: none; background: transparent; cursor: pointer; color: var(--isis-accent); padding: 0.1rem; }
.isis-qc-newpass-modes { display: flex; flex-direction: column; gap: 0.4rem; margin: 0.3rem 0 0.6rem; }
/* Config de seuil (type VALEUR) dans l'éditeur de template */
.isis-qc-value-config { display: flex; align-items: center; gap: 0.4rem; flex-wrap: wrap; margin: 0 0 0.5rem 1.2rem; padding-left: 0.6rem; border-left: 2px solid var(--isis-border); }
.isis-qc-value-config__hint { font-size: 0.78rem; color: var(--isis-text-muted); }
/* Saisie VALEUR / NOTE dans la matrice */
.isis-qc-matrix__valwrap { display: flex; align-items: center; gap: 0.25rem; }
.isis-qc-matrix__value { width: 90px; border: 1px solid var(--isis-border); border-radius: 4px; padding: 0.2rem 0.4rem; font-size: 0.82rem; background: var(--isis-surface); }
.isis-qc-matrix__unit { font-size: 0.78rem; color: var(--isis-text-muted); }
.isis-qc-matrix__rule { font-size: 0.74rem; color: var(--isis-text-muted); display: inline-flex; align-items: center; gap: 0.3rem; }
.isis-qc-matrix__readval { font-weight: 600; font-size: 0.82rem; }
/* Journal / timeline QC */
/* Pied ancré en bas du dialog : historique + erreur + boutons restent fixes, la matrice scrolle. */
.isis-qc-footer { flex: 0 0 auto; position: sticky; bottom: 0; z-index: 2; display: flex; flex-direction: column; gap: 0.5rem; border-top: 1px solid var(--isis-border); padding-top: 0.55rem; margin-top: 0.1rem; background: var(--isis-surface); }
.isis-qc-footer .isis-qc-history { margin-top: 0; border-top: none; padding-top: 0; }
.isis-qc-footer .isis-form-linear__actions { margin-top: 0; }
.isis-qc-history { margin-top: 0.6rem; border-top: 1px solid var(--isis-border); padding-top: 0.5rem; }
.isis-qc-history__toggle { display: inline-flex; align-items: center; gap: 0.3rem; background: none; border: none; color: var(--isis-text-muted); font-size: 0.85rem; cursor: pointer; padding: 0.2rem 0; }
.isis-qc-history__toggle:hover { color: var(--isis-text); }
.isis-qc-history__toggle:focus-visible { outline: 2px solid var(--isis-accent); outline-offset: 2px; }
.isis-qc-history__loading { padding: 0.5rem; }
.isis-qc-history__empty { font-size: 0.85rem; color: var(--isis-text-muted); margin: 0.4rem 0; }
.isis-qc-history__list { list-style: none; margin: 0.4rem 0 0; padding: 0; display: flex; flex-direction: column; gap: 0.45rem; max-height: 26vh; overflow: auto; }
.isis-qc-history__item { display: flex; gap: 0.5rem; align-items: flex-start; }
.isis-qc-history__dot { width: 8px; height: 8px; border-radius: 50%; margin-top: 0.35rem; flex: 0 0 auto; background: var(--isis-text-muted); }
.isis-qc-history__dot.is-ok { background: var(--isis-success); }
.isis-qc-history__dot.is-draft { background: var(--isis-text-muted); }
.isis-qc-history__dot.is-pending, .isis-qc-history__dot.is-info { background: var(--isis-accent); }
.isis-qc-history__body { display: flex; flex-direction: column; }
.isis-qc-history__label { font-size: 0.85rem; color: var(--isis-text); }
.isis-qc-history__meta { font-size: 0.75rem; color: var(--isis-text-muted); }
/* Reporting QC — variante propre : ne PAS réutiliser .isis-grid--qc-produit,
   qui appartient à la page /gesproj/parametres/produits (5 colonnes différentes). */
/* Recalées le 2026-09-02, en regardant la page AVEC des données : à 100px, « Non conf. »
   se cassait en deux lignes et sa flèche de tri se détachait à l'autre bout de la cellule ;
   et le « 2fr » du produit rejetait les trois colonnes de chiffres contre la barre. */
.isis-grid--qc-reporting-produit .isis-grid__head, .isis-grid--qc-reporting-produit .isis-grid__row { grid-template-columns: minmax(200px, 1.2fr) 120px 120px 120px minmax(200px, 1fr); }
/* Idem : le nom du contrôleur ne prend plus toute la place, et « Taux NC » a de quoi loger
   son libellé ET sa flèche. */
.isis-grid--qc-controleur .isis-grid__head, .isis-grid--qc-controleur .isis-grid__row { grid-template-columns: minmax(200px, 1.2fr) 170px 150px 130px; }
.isis-qc-bar { position: relative; height: 18px; background: var(--isis-surface-alt); border-radius: 9px; overflow: hidden; min-width: 140px; }
.isis-qc-bar__fill { position: absolute; inset: 0 auto 0 0; border-radius: 9px; }
.isis-qc-bar__fill.is-ok { background: color-mix(in srgb, var(--isis-success) 55%, transparent); }
.isis-qc-bar__fill.is-warning { background: color-mix(in srgb, var(--isis-warning) 60%, transparent); }
.isis-qc-bar__fill.is-danger { background: color-mix(in srgb, var(--isis-danger) 60%, transparent); }
.isis-qc-bar__val { position: relative; z-index: 1; font-size: 0.74rem; font-weight: 600; padding-left: 0.45rem; line-height: 18px; color: var(--isis-text); }
/* Sélection des templates QC à la création d'un livrable */
.isis-qc-tpl-pick { display: flex; align-items: center; gap: 0.5rem; padding: 0.35rem 0.2rem; }
.isis-qc-tpl-pick__name { font-weight: 600; }
.isis-qc-tpl-pick__meta { font-size: 0.8rem; color: var(--isis-text-muted); }
/* Preuve par critère (contrôle du livrable) */
.isis-qc-ctrl-row__proof {
    display: inline-flex; align-items: center; gap: 0.3rem; padding: 0.3rem 0.6rem;
    border: 1px solid var(--isis-border); border-radius: var(--isis-radius-sm);
    background: var(--isis-surface); font-size: 0.82rem; cursor: pointer; white-space: nowrap; flex: 0 0 auto;
}
.isis-qc-ctrl-row__proof.is-missing { font-weight: 600; }
.isis-qc-ctrl-row__proof:hover { background: var(--isis-surface-alt); }
.isis-qc-ctrl-row__proof.is-ok { border-color: var(--isis-success); color: var(--isis-success); }
.isis-qc-ctrl-row__proof.is-missing { border-color: var(--isis-warning); color: var(--isis-warning); }
.isis-qc-proof-current { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; padding: 0.5rem 0.2rem; }
.isis-qc-proof-upload { padding: 0.4rem 0.2rem; }
/* Templates QC — Code | Libellé | Portée | Activité | Critères | Rattach. | État | Actions */
.isis-grid--qc-template .isis-grid__head,
.isis-grid--qc-template .isis-grid__row {
    grid-template-columns: 150px minmax(180px, 1.6fr) minmax(130px, 1fr) minmax(110px, 0.9fr) 100px 90px 90px 100px;
    min-width: 1000px;
}
/* Lignes d'édition (composition produit / critères QC / rattachements) */
.isis-qc-compo-row,
.isis-qc-ligne-row,
.isis-qc-bind-row,
.isis-qc-addrow {
    display: flex;
    gap: 0.5rem;
    align-items: center;
    margin-bottom: 0.4rem;
    flex-wrap: wrap;            /* jamais de débordement : on passe à la ligne */
}
/* Cellule flex : sépare le dimensionnement (cellule) du composant Radzen (width:100%). */
.isis-erow__cell { min-width: 0; }
.isis-erow__cell--grow  { flex: 1 1 200px; min-width: 0; }
.isis-erow__cell--grow2 { flex: 2 1 220px; min-width: 0; }
.isis-erow__cell--md    { flex: 0 0 150px; }
.isis-erow__cell--sm    { flex: 0 0 130px; }
.isis-erow__cell--xs    { flex: 0 0 96px; }
.isis-qc-ligne-row__chk {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    font-size: 0.8rem;
    color: var(--isis-text-muted);
    white-space: nowrap;
}

/* ── Exécution QC : dialogs livrables + checklist (P2, migration 0364) ── */
.isis-grid--qc-livrable .isis-grid__head,
.isis-grid--qc-livrable .isis-grid__row {
    grid-template-columns: minmax(140px, 1.2fr) minmax(110px, 1fr) 58px minmax(240px, 1.7fr) 150px 200px;
    min-width: 1000px;
}
.isis-grid--qc-livrable .isis-grid__row > [role="cell"] { align-self: center; }
/* Couleurs sémantiques des actions livrable (scopé) — tokens corrects : accent du
   module courant pour l'action principale « Contrôler », warning pour « Dispenser ».
   On n'utilise PAS --primary/--active qui figent une couleur de module erronée. */
.isis-grid--qc-livrable .isis-grid__action-btn--accent { color: var(--isis-current-mod, var(--isis-accent)); }
.isis-grid--qc-livrable .isis-grid__action-btn--accent:hover:not(:disabled) {
    background: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 14%, transparent);
}
.isis-grid--qc-livrable .isis-grid__action-btn--warning { color: var(--isis-warning); }
.isis-grid--qc-livrable .isis-grid__action-btn--warning:hover {
    background: color-mix(in srgb, var(--isis-warning) 14%, transparent);
}
/* Icônes d'action à 15px, alignées sur la grille de l'onglet Livraison. Sans Style
   inline, les RadzenIcon rendaient à 24px (défaut) → boutons visuellement plus gros. */
.isis-grid--qc-livrable .isis-grid__action-btn i { font-size: 15px; }

/* Grille « Livrables attendus » d'une commande (EF-147) : ce que l'offre a promis, daté et suivi.
   Colonnes : livrable · rendu prévu · rendu le · statut · responsable · livraison · actions. */
.isis-grid--livrable-attendu .isis-grid__head,
.isis-grid--livrable-attendu .isis-grid__row {
    grid-template-columns: minmax(240px, 2.2fr) 120px 112px 130px minmax(160px, 1.2fr) 130px 96px;
    min-width: 1060px;
}
.isis-grid--livrable-attendu .isis-grid__row > [role="cell"] { align-self: center; }
.isis-grid--livrable-attendu .isis-grid__action-btn i { font-size: 15px; }
/* Échéance dépassée sur un attendu non soldé. La couleur ne porte pas seule l'information :
   la cellule garde son `title` explicite (WCAG 1.4.1). */
.isis-grid--livrable-attendu .is-overdue { color: var(--isis-danger); font-weight: 600; }
/* Colonne Conformité : jauge + ratio + statut, puis chips (KO / à renseigner / commentaires / preuves). */
.isis-grid__col-conformite { display: flex; flex-direction: column; gap: 0.25rem; }
.isis-qc-gauge-row { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }
.isis-qc-gauge { flex: 0 0 64px; height: 7px; border-radius: 999px; background: var(--isis-surface-alt); border: 1px solid var(--isis-border); overflow: hidden; }
.isis-qc-gauge__fill { height: 100%; border-radius: 999px; transition: width 0.2s ease; }
.isis-qc-gauge__fill.is-ok { background: var(--isis-success); }
.isis-qc-gauge__fill.is-warning { background: var(--isis-warning); }
.isis-qc-gauge__fill.is-danger { background: var(--isis-danger); }
.isis-qc-gauge__fill.is-info { background: var(--isis-info, var(--isis-accent)); }
.isis-qc-gauge__fill.is-muted { background: var(--isis-text-muted); opacity: 0.35; }
.isis-qc-gauge__ratio { font-family: var(--isis-font-mono, monospace); font-size: 0.8rem; font-variant-numeric: tabular-nums; color: var(--isis-text); min-width: 30px; }
.isis-qc-chips { display: flex; flex-wrap: wrap; gap: 0.3rem; }
.isis-qc-chip { display: inline-flex; align-items: center; gap: 0.15rem; font-size: 0.72rem; line-height: 1; padding: 0.15rem 0.4rem; border-radius: 999px; background: var(--isis-surface-alt); border: 1px solid var(--isis-border); color: var(--isis-text-muted); }
.isis-qc-chip > i { font-size: 13px; }
.isis-qc-chip.is-danger { color: var(--isis-danger); border-color: color-mix(in srgb, var(--isis-danger) 35%, var(--isis-border)); background: color-mix(in srgb, var(--isis-danger) 8%, var(--isis-surface)); }
.isis-qc-chip.is-muted { color: var(--isis-text-muted); }
/* Colonne Passes : badge passe courante + sous-libellé date · auteur. */
.isis-grid__col-passes { display: flex; flex-direction: column; gap: 0.15rem; align-items: flex-start; }
.isis-livraison-jalons { display: flex; flex-wrap: wrap; gap: 0.25rem; }
.isis-grid--liv-validation .isis-grid__head,
.isis-grid--liv-validation .isis-grid__row {
    grid-template-columns: minmax(160px, 1.6fr) 90px 120px minmax(160px, 1.4fr);
    min-width: 560px;
}
.isis-grid--liv-validation .isis-grid__row > [role="cell"] { align-self: center; }
/* Dialog « Livraisons liées à la tranche » (jalon de paiement ↔ livraisons). */
.isis-ech-liv-list { display: flex; flex-direction: column; gap: 0.3rem; max-height: 50vh; overflow: auto; }
.isis-ech-liv-item { display: flex; align-items: center; gap: 0.6rem; padding: 0.5rem 0.6rem; border: 1px solid var(--isis-border); border-radius: var(--isis-radius-sm); cursor: pointer; }
.isis-ech-liv-item:hover { background: var(--isis-surface-alt); }
.isis-ech-liv-item.is-checked { border-color: var(--isis-accent); background: color-mix(in srgb, var(--isis-accent) 6%, var(--isis-surface)); }
.isis-ech-liv-item__num { font-family: var(--isis-font-mono, monospace); font-weight: 600; }
.isis-ech-liv-item__type { color: var(--isis-text-muted); font-size: 0.85rem; }

/* Lien de stockage du livrable (sous le produit) : GED, lien externe, ou tiret. */
.isis-livrable-storage { display: block; margin-top: 0.1rem; }
.isis-livrable-storage__dash { color: var(--isis-text-muted); }
.isis-livrable-storage .isis-text-link { background: none; border: none; padding: 0; font: inherit; cursor: pointer; color: var(--isis-accent); }
.isis-livrable-storage .isis-text-link:hover { text-decoration: underline; }
/* Le dialog remplit toute sa hauteur → matrice scrollable, pied ancré en bas.
   Classe posée sur .rz-dialog via DialogOptions.CssClass (plus robuste que :has).
   La hauteur 92vh est sur .rz-dialog ; on le met en colonne flex pour que le contenu
   remplisse l'espace, sinon .rz-dialog-content reste à hauteur naturelle et le pied flotte. */
.rz-dialog.isis-qc-dialog-window { display: flex; flex-direction: column; }
.rz-dialog.isis-qc-dialog-window .rz-dialog-content { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; overflow: hidden; }
.isis-qc-dialog { display: flex; flex-direction: column; gap: 0.75rem; flex: 1 1 auto; min-height: 0; }
.isis-qc-dialog__head {
    display: flex; align-items: center; justify-content: space-between; gap: 0.75rem;
    padding-bottom: 0.5rem; border-bottom: 1px solid var(--isis-border);
}
.isis-qc-addrow { display: flex; gap: 0.5rem; align-items: center; }
.isis-qc-ctrl-row {
    display: flex; flex-direction: column; gap: 0.45rem; margin-bottom: 0.55rem;
    padding-bottom: 0.55rem; border-bottom: 1px dashed var(--isis-border);
}
.isis-qc-ctrl-row__crit { display: flex; flex-direction: column; gap: 0.2rem; min-width: 0; }
.isis-qc-ctrl-row__lib { font-size: 0.9rem; font-weight: 600; color: var(--isis-text); }
.isis-qc-ctrl-row__tags { display: inline-flex; gap: 0.3rem; flex-wrap: wrap; }
.isis-qc-ctrl-row__controls { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; }
.isis-qc-ctrl-row__comment { flex: 1 1 160px; min-width: 140px; }
/* Bandeau d'état OK (vert) — complète --pending/--warning/--danger */
.isis-alert-banner--ok {
    background: color-mix(in srgb, var(--isis-success) 10%, var(--isis-surface));
    border-color: color-mix(in srgb, var(--isis-success) 35%, transparent);
}

/* Grille conflits gespla S6 — 5 cols
   status | type | ressource | période en conflit | actions */
.isis-grid--conflits .isis-grid__head,
.isis-grid--conflits .isis-grid__row {
    grid-template-columns: 32px minmax(200px, 1fr) minmax(220px, 1.2fr) minmax(180px, 1fr) 60px;
    min-width: 780px;
}

/* Dashboard gesmaff — Pipeline AO (top 10) — 8 cols
   status | référence | intitulé | maître d'ouvrage | montant estimatif | statut | date limite | actions */
.isis-grid--gesmaff-pipeline .isis-grid__head,
.isis-grid--gesmaff-pipeline .isis-grid__row {
    grid-template-columns: 32px 140px minmax(200px, 2fr) minmax(160px, 1fr) 160px 110px 130px 60px;
    min-width: 1080px;
}

/* Dashboard gesmaff — Marchés à surveiller (top 10) — 9 cols
   status | numéro | intitulé | client | type | montant TTC | date fin | conso cadre | actions */
.isis-grid--gesmaff-surveiller .isis-grid__head,
.isis-grid--gesmaff-surveiller .isis-grid__row {
    grid-template-columns: 32px 140px minmax(180px, 2fr) minmax(160px, 1fr) 130px 140px 130px 110px 60px;
    min-width: 1180px;
}

/* Dashboard gesst — Top engagements — 8 cols
   status | numéro | intitulé | prestataire | statut | montant TTC | propriétaire | actions */
.isis-grid--gesst-top-engagements .isis-grid__head,
.isis-grid--gesst-top-engagements .isis-grid__row {
    grid-template-columns: 32px 140px minmax(180px, 2fr) minmax(160px, 1.2fr) 130px 140px minmax(140px, 1fr) 60px;
    min-width: 1140px;
}

/* Dashboard gesst — Top fournisseurs — 4 cols */
.isis-grid--gesst-top-fournisseurs .isis-grid__head,
.isis-grid--gesst-top-fournisseurs .isis-grid__row {
    grid-template-columns: minmax(220px, 2fr) 120px 140px 180px;
    min-width: 720px;
}

/* Dashboard gesproj — Top commandes marge — 10 cols
   status | numéro | intitulé | statut | CA HT | coût réel | marge HT | marge % | propriétaire | actions */
.isis-grid--gesproj-marges .isis-grid__head,
.isis-grid--gesproj-marges .isis-grid__row {
    grid-template-columns: 32px 140px minmax(180px, 1.8fr) 140px 130px 130px 130px 110px minmax(140px, 1fr) 60px;
    min-width: 1300px;
}

/* Dérive marge devisé→réalisé (game-changer portefeuille, 2026-06-02) :
   status | Numéro | Intitulé | CA HT | Marge devisée % | Marge réelle % | Dérive (pts) | Propriétaire | action */
.isis-grid--gesproj-derive .isis-grid__head,
.isis-grid--gesproj-derive .isis-grid__row {
    grid-template-columns: 32px 140px minmax(180px, 1.6fr) 130px 130px 130px 130px minmax(140px, 1fr) 60px;
    min-width: 1260px;
}

/* Bandeau synthèse dérive (3 mini-KPIs au-dessus de la grille dérive). */
.isis-derive-kpis {
    display: flex;
    flex-wrap: wrap;
    gap: 1.5rem;
    padding: 0.5rem 0 1rem;
}
.isis-derive-kpi { display: flex; flex-direction: column; gap: 0.1rem; }
.isis-derive-kpi__value {
    font-size: 1.35rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: var(--isis-text);
    line-height: 1.1;
}
.isis-derive-kpi__value.is-ok      { color: var(--isis-success); }
.isis-derive-kpi__value.is-warning { color: var(--isis-warning); }
.isis-derive-kpi__value.is-danger  { color: var(--isis-danger); }
.isis-derive-kpi__sub {
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--isis-text-muted);
}
.isis-derive-kpi__label {
    font-size: 0.74rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--isis-text-muted);
}

/* ============================================================================
   POC planning visuel /gespla/planner-v2 (vis-timeline MIT)
   ============================================================================ */
/* Layout 3 colonnes : palette gauche + timeline + sidepanel droit détail.
   Le sidepanel droit n'est rendu côté DOM que si une affectation est sélectionnée.

   Sprint Mxx — layout fullscreen scrollable interne. La rich-page est déjà
   en flex col + height:100% + overflow:hidden (cf. .isis-rich-page). On
   demande au layout de prendre tout le reste vertical disponible (flex: 1)
   et on autorise min-height: 0 pour que les enfants puissent shrink correctement
   (sinon ils débordent et la page entière scrolle). Pattern memory
   [[project_isis_grid_pattern]] — « chaîne flex impérative ». */
.isis-planner-layout {
    position: relative;                   /* ancre le sidepanel flottant */
    display: grid;
    grid-template-columns: 280px 1fr;
    gap: 1rem;
    flex: 1 1 auto;
    min-height: 0;
    overflow: hidden;
}
/* Sidepanel droit en overlay flottant — ne réduit plus la timeline.
   Plus de 3ème colonne grid : le détail se positionne en absolute par-dessus. */
.isis-planner-layout.has-detail {
    grid-template-columns: 280px 1fr;
}
@media (max-width: 1100px) {
    /* Viewport étroit : palette aussi se réempile au-dessus. */
    .isis-planner-layout,
    .isis-planner-layout.has-detail {
        grid-template-columns: 1fr;
    }
}

/* Palette ressources */
.isis-planner-palette {
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: 6px;
    display: flex;
    flex-direction: column;
    height: 100%;          /* pris dans la grille fullscreen — scroll interne sur __body */
    min-height: 0;
    overflow: hidden;
}
.isis-planner-palette__head {
    padding: 0.75rem;
    border-bottom: 1px solid var(--isis-border);
    background: var(--isis-surface-soft);
}
.isis-planner-palette__title {
    margin: 0 0 0.25rem 0;
    font-size: 0.95rem;
    font-weight: 600;
    color: var(--isis-text);
}
.isis-planner-palette__hint {
    display: block;
    font-size: 0.72rem;
    color: var(--isis-text-muted);
    line-height: 1.3;
}
.isis-planner-palette__search {
    padding: 0.5rem 0.75rem;
    border-bottom: 1px solid var(--isis-border);
}
.isis-planner-palette__body {
    flex: 1;
    overflow-y: auto;
    padding: 0.5rem 0.5rem 0.75rem;
}
.isis-planner-palette__section + .isis-planner-palette__section {
    margin-top: 0.75rem;
}
.isis-planner-palette__section-title {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 0.25rem 0.5rem;
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--isis-text-muted);
    font-weight: 600;
}
.isis-planner-palette__count {
    background: var(--isis-surface-soft);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-pill);
    padding: 0 0.5rem;
    font-size: 0.7rem;
    color: var(--isis-text-muted);
}
.isis-planner-palette__empty {
    padding: 0.4rem 0.75rem;
    font-size: 0.78rem;
    color: var(--isis-text-muted);
    font-style: italic;
}
/* Carte ressource draggable */
.isis-planner-palette__card {
    user-select: none;
    -webkit-user-select: none;
    /* Drag natif HTML5 — explicite pour Safari/WebKit. Sans cette propriété,
       user-select:none peut bloquer le démarrage du drag sur les zones de texte. */
    -webkit-user-drag: element;
    cursor: grab;
    padding: 0.45rem 0.6rem;
    margin: 0.25rem 0;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: 4px;
    display: flex;
    flex-direction: column;
    gap: 0.1rem;
    transition: border-color 120ms ease, background 120ms ease;
}
/* Le texte interne ne doit pas devenir une cible de drag indépendante
   (sinon Chrome démarre un drag de texte au lieu du drag de l'élément).
   pointer-events:none sur les enfants — le tooltip (title) est porté
   par la carte parente, donc on ne perd rien d'utile, et le drag est plus
   stable car le browser considère toujours la carte comme cible. */
.isis-planner-palette__card * {
    -webkit-user-drag: none;
    pointer-events: none;
}
.isis-planner-palette__card:hover {
    border-color: var(--isis-mod-gespla);
    background: color-mix(in srgb, var(--isis-mod-gespla) 6%, var(--isis-surface));
}
.isis-planner-palette__card:active { cursor: grabbing; }
.isis-planner-palette__card:focus-visible {
    outline: 2px solid var(--isis-mod-gespla);
    outline-offset: 1px;
}
.isis-planner-palette__card--collab {
    border: 1px solid color-mix(in srgb, var(--isis-mod-sirh, var(--isis-text-muted)) 50%, transparent);
    box-sizing: border-box;
}
.isis-planner-palette__card--equip {
    border: 1px solid color-mix(in srgb, var(--isis-mod-gesmat, var(--isis-text-muted)) 50%, transparent);
    box-sizing: border-box;
}

/* Sprint E — carte besoin draggable */
.isis-planner-palette__card--besoin {
    border: 1px solid color-mix(in srgb, var(--isis-mod-gespla) 60%, transparent);
    box-sizing: border-box;
}
.isis-planner-palette__card--besoin:hover {
    border-color: var(--isis-mod-gespla);
}
/* Sprint N+ — carte commande draggable (drag sur lane ressource = nouvelle affectation) */
.isis-planner-palette__card--cmd {
    border: 1px solid color-mix(in srgb, var(--isis-mod-gesproj, var(--isis-accent)) 60%, transparent);
    box-sizing: border-box;
}
.isis-planner-palette__card--cmd:hover {
    border-color: var(--isis-mod-gesproj, var(--isis-accent));
}

/* Sprint V S8 — bouton « Top candidats » sur carte besoin.
   Échappe au pointer-events:none global des children draggable. */
.isis-planner-palette__card-bestmatch {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    margin-top: 0.35rem;
    padding: 2px 8px;
    background: var(--isis-mod-gespla-soft);
    color: var(--isis-mod-gespla);
    border: 1px solid color-mix(in srgb, var(--isis-mod-gespla) 30%, var(--isis-border));
    border-radius: 4px;
    font-size: 0.7rem;
    font-weight: 600;
    cursor: pointer;
    pointer-events: auto;
    -webkit-user-drag: none;
    transition: background 120ms ease, border-color 120ms ease;
}
.isis-planner-palette__card-bestmatch:hover {
    background: color-mix(in srgb, var(--isis-mod-gespla) 12%, var(--isis-surface));
    border-color: var(--isis-mod-gespla);
}
.isis-planner-palette__card-bestmatch:focus-visible {
    outline: 2px solid var(--isis-mod-gespla);
    outline-offset: 1px;
}

/* Sprint V S8 — dialog Top candidats. */
.isis-best-match { display: flex; flex-direction: column; gap: 1rem; }
.isis-best-match__head { display: flex; flex-direction: column; gap: 0.25rem; }
.isis-best-match__breadcrumb {
    display: flex; align-items: center; gap: 0.4rem;
    font-size: 0.75rem; color: var(--isis-text-muted);
}
.isis-best-match__title {
    font-size: 1rem; font-weight: 600; color: var(--isis-text); margin: 0;
}
.isis-best-match__hint {
    font-size: 0.75rem; color: var(--isis-text-muted); margin: 0;
}
.isis-best-match__empty {
    display: flex; flex-direction: column; align-items: center;
    gap: 0.5rem; padding: 1.5rem; text-align: center;
    background: var(--isis-surface-soft); border-radius: 6px;
    color: var(--isis-text-muted);
}
.isis-best-match__empty p { font-size: 0.8rem; margin: 0; }
.isis-best-match__list {
    list-style: none; padding: 0; margin: 0;
    display: flex; flex-direction: column; gap: 0.4rem;
    max-height: 420px; overflow-y: auto;
}
.isis-best-match__row {
    display: grid; grid-template-columns: 32px 1fr auto; gap: 0.6rem;
    padding: 0.6rem 0.75rem;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: 4px;
    align-items: center;
}
.isis-best-match__row.is-backlisted {
    opacity: 0.7;
    border-color: var(--isis-text-muted);
}
.isis-best-match__rank {
    font-size: 1.1rem; font-weight: 700;
    color: var(--isis-mod-gespla);
    text-align: center;
    font-variant-numeric: tabular-nums;
}
.isis-best-match__row.is-backlisted .isis-best-match__rank {
    color: var(--isis-text-muted);
}
.isis-best-match__name { font-weight: 600; color: var(--isis-text); }
.isis-best-match__sub { font-size: 0.75rem; color: var(--isis-text-muted); }
.isis-best-match__missing {
    margin-top: 0.25rem;
    font-size: 0.72rem;
    color: var(--isis-danger);
    display: inline-flex; align-items: center; gap: 0.3rem;
}
.isis-best-match__score { text-align: right; }
.isis-best-match__score-total {
    font-size: 1.2rem; font-weight: 700;
    color: var(--isis-mod-gespla);
    font-variant-numeric: tabular-nums;
}
.isis-best-match__row.is-backlisted .isis-best-match__score-total {
    color: var(--isis-text-muted);
}
.isis-best-match__score-breakdown {
    display: flex; gap: 0.4rem; justify-content: flex-end;
    font-size: 0.7rem; color: var(--isis-text-muted);
    font-variant-numeric: tabular-nums;
    margin-top: 0.15rem;
}
.isis-best-match__distance {
    font-size: 0.72rem; color: var(--isis-text-muted);
    margin-top: 0.15rem;
}
.isis-best-match__foot {
    display: flex; justify-content: flex-end; gap: 0.5rem;
    padding-top: 0.5rem; border-top: 1px solid var(--isis-border);
}

/* Sprint U E3 — bouton favori sur carte palette.
   Doit échapper au `pointer-events: none` global des children + au drag natif. */
.isis-planner-palette__card {
    position: relative; /* pour positionnement absolu du bouton fav */
}
.isis-planner-palette__card-fav {
    position: absolute;
    top: 4px;
    right: 4px;
    width: 22px;
    height: 22px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    border: none;
    border-radius: 4px;
    cursor: pointer;
    color: var(--isis-text-muted);
    /* Override : ce bouton DOIT recevoir les clics même si la règle globale
       `.isis-planner-palette__card *` pose pointer-events:none. */
    pointer-events: auto;
    -webkit-user-drag: none;
    transition: color 120ms ease, background 120ms ease;
}
.isis-planner-palette__card-fav:hover {
    color: var(--isis-accent-strong);
    background: color-mix(in srgb, var(--isis-accent-strong) 10%, transparent);
}
.isis-planner-palette__card-fav[aria-pressed="true"] {
    color: var(--isis-accent-strong);
}
.isis-planner-palette__card-fav:focus-visible {
    outline: 2px solid var(--isis-mod-gespla);
    outline-offset: 1px;
}
.isis-planner-palette__card.is-favorite {
    border-color: color-mix(in srgb, var(--isis-accent-strong) 40%, var(--isis-border));
    background: color-mix(in srgb, var(--isis-accent-strong) 4%, var(--isis-surface));
}
/* Ne pas faire dépasser le nom sous le bouton étoile (clipping cohérent). */
.isis-planner-palette__card-name {
    padding-right: 24px;
}
.isis-planner-palette__card-meta {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-top: 0.25rem;
    gap: 0.3rem;
}
.isis-planner-palette__card-jh {
    font-size: 0.7rem;
    color: var(--isis-text-muted);
    font-variant-numeric: tabular-nums;
}
.isis-planner-palette__card-status {
    font-size: 0.7rem;
    font-weight: 600;
    padding: 1px 6px;
    border-radius: var(--isis-radius-pill);
    background: var(--isis-surface-soft);
    color: var(--isis-text);
    font-variant-numeric: tabular-nums;
}
.isis-planner-palette__card-status--danger {
    background: color-mix(in srgb, var(--isis-danger) 18%, transparent);
    color: var(--isis-danger);
}
.isis-planner-palette__card-status--warning {
    background: color-mix(in srgb, var(--isis-warning) 22%, transparent);
    color: color-mix(in srgb, var(--isis-warning) 80%, var(--isis-text));
}
.isis-planner-palette__card-status--info {
    background: color-mix(in srgb, var(--isis-accent) 18%, transparent);
    color: var(--isis-accent);
}
/* Sprint V — variante OK (besoin couvert 100 %). */
.isis-planner-palette__card-status--ok {
    background: color-mix(in srgb, var(--isis-success) 18%, transparent);
    color: color-mix(in srgb, var(--isis-success) 80%, var(--isis-text));
}

/* Toggle palette (Ressources / Besoins) */
.isis-planner-palette__toggle {
    margin: 0.45rem 0 0.3rem 0;
    width: 100%;
}
.isis-planner-palette__toggle .isis-view-toggle__btn {
    flex: 1 1 0;
    justify-content: center;
    gap: 0.3rem;
}
.isis-planner-palette__toggle-count {
    margin-left: 0.3rem;
    padding: 0 0.4rem;
    font-size: 0.65rem;
    font-weight: 700;
    background: var(--isis-mod-gespla);
    color: white;
    border-radius: var(--isis-radius-pill);
    line-height: 1.4;
}

/* Sprint S5 — filtre catégorie palette (Tous / Collabs / Équips / Commandes).
   Segmented control compact placé entre la recherche et le body. */
.isis-planner-palette__cat-filter {
    margin: 0.35rem 0 0.3rem 0;
    width: 100%;
    display: flex;
    flex-wrap: wrap;
}
.isis-planner-palette__cat-filter .isis-view-toggle__btn {
    flex: 1 1 0;
    justify-content: center;
    gap: 0.25rem;
    padding: 0.3rem 0.4rem;
    font-size: 0.72rem;
    min-width: 0;
}
.isis-planner-palette__cat-filter .isis-view-toggle__btn span {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.isis-planner-palette__card-name {
    font-size: 0.85rem;
    font-weight: 500;
    color: var(--isis-text);
}
.isis-planner-palette__card-sub {
    font-size: 0.72rem;
    color: var(--isis-text-muted);
}

/* Conteneur vis-timeline — prend toute la cellule de grille fullscreen. */
.isis-planner-host {
    width: 100%;
    height: 100%;
    min-height: 0;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: 6px;
    overflow: hidden;
}

/* ─────────────────────────────────────────────────────────────────────────
   Sprint Y — Planner V3 (Syncfusion Scheduler)
   Conteneur dédié, état de chargement et empty state. La hauteur est gérée
   par SfSchedule lui-même (Height="100%"). On entoure d'un cadre cohérent
   avec le V2 pour transition visuelle douce entre les 2 vues.
   ───────────────────────────────────────────────────────────────────────── */
.isis-planner-host {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
    /* Ancre l'empty state filtré superposé (.isis-planner-empty--overlay). */
    position: relative;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: 6px;
    overflow: hidden;
}
.isis-planner-host > .e-schedule {
    flex: 1 1 auto;
    min-height: 0;
}
.isis-planner-loader,
.isis-planner-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.75rem;
    padding: 3rem 1rem;
    color: var(--isis-text-muted);
    font-size: 0.9rem;
}
/* Empty state filtré superposé au SfSchedule (qui reste monté — un démontage @if
   ré-initialiserait le JS Syncfusion et perdrait la vue/date courantes). */
.isis-planner-empty--overlay {
    position: absolute;
    inset: 0;
    z-index: 5;
    background: color-mix(in srgb, var(--isis-surface) 90%, transparent);
}
/* La barre de navigation du Scheduler (précédent, suivant, Aujourd'hui, vues) passe AU-DESSUS
   de l'overlay : sans ça, une période sans aucun élément recouvrait ses boutons et figeait
   l'écran sur cette période (2026-09-18). */
.isis-planner-host .e-schedule-toolbar-container {
    position: relative;
    z-index: 6;
}

/* ─────────────────────────────────────────────────────────────────────────
   Sprint X port V3 — barres de mobilisation Syncfusion Scheduler
   Calque visuel du V2 vis-timeline (--isis-source-accent → --isis-resource-accent).
   Le wrapper .e-appointment est géré par Syncfusion ; on stylise le contenu interne.
   ───────────────────────────────────────────────────────────────────────── */
.e-schedule .e-appointment:has(.isis-planner-item) {
    /* Désactive intégralement le styling natif Syncfusion (fond + bordures + padding)
       qui pose la couleur de la lane et masquerait notre bordure ressource. Le style
       inline `background-color`/`border-left` posé par Syncfusion via ColorField est
       neutralisé via !important. */
    background: transparent !important;
    background-color: transparent !important;
    border: none !important;
    border-left: none !important;
    border-right: none !important;
    border-color: transparent !important;
    padding: 0 !important;
    overflow: hidden;
}
/* Syncfusion v33 a 2 wrappers internes possibles (selon vue : Day/Week/Month-Timeline)
   qui peuvent ré-injecter un padding ou un border-left coloré (bande gauche d'event). */
.e-schedule .e-appointment:has(.isis-planner-item) .e-appointment-details,
.e-schedule .e-appointment:has(.isis-planner-item) .e-inner-wrap,
.e-schedule .e-appointment:has(.isis-planner-item) .e-appointment-border-left,
.e-schedule .e-appointment:has(.isis-planner-item) .e-subject,
.e-schedule .e-appointment:has(.isis-planner-item) .e-time {
    background: transparent !important;
    border: none !important;
    border-left: none !important;
    padding: 0 !important;
    margin: 0 !important;
    width: 100% !important;
    height: 100% !important;
}
/* Si Syncfusion pose un ::before / ::after décoratif (bande gauche colorée
   « event-border-left » par exemple) sur le WRAPPER .e-appointment lui-même,
   on le masque pour que notre bande --isis-resource-accent reste la seule
   visible. Important : ne PAS cibler les pseudo-éléments des enfants — sinon
   on tuerait notre `.isis-planner-item::before` qui porte la bande. */
.e-schedule .e-appointment:has(.isis-planner-item)::before,
.e-schedule .e-appointment:has(.isis-planner-item)::after {
    display: none !important;
    content: none !important;
}
.isis-planner-item {
    container-type: inline-size;
    container-name: planner-v3-item;
    position: relative;   /* anchor du ::before bande gauche */
    width: 100%;
    height: 100%;
    min-height: 38px;
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 3px 6px 4px 10px;   /* padding-left 10px = 4px bande + 6px gutter */
    border-radius: 3px;
    /* Option D 2026-05-22 — 4 signaux identité ressource indépendants :
       1) Bande gauche 4 px pleine couleur (via ::before absolute pour battre
          tout override Syncfusion sur .e-appointment - les border-left CSS standard
          sont parfois recouvertes par les wrappers internes de la lib).
       2) Fond tinté color-mix 35 % (perceptible, ne masque pas le motif d'état)
       3) Outline interne 1 px couleur ressource (renforce le périmètre)
       4) Avatar initiales coloré dans __meta (signal explicite vue Jour/Semaine). */
    background: color-mix(in srgb, var(--isis-resource-accent, var(--isis-surface-soft)) 35%, var(--isis-surface));
    color: var(--isis-text);
    font-size: 0.78rem;
    line-height: 1.2;
    overflow: hidden;
    box-shadow:
        inset 0 0 0 1px color-mix(in srgb, var(--isis-resource-accent, transparent) 35%, transparent),
        0 1px 0 0 rgba(0, 0, 0, 0.04);
}
/* Bande gauche 4 px = signal d'identité ressource le plus fort. Posée en pseudo-element
   absolute (z-index 2) pour passer au-dessus de tout wrapper Syncfusion qui aurait
   son propre border-left coloré (cas vue Timeline ColorField sur la lane). */
.isis-planner-item::before {
    content: "";
    position: absolute;
    inset: 0 auto 0 0;   /* top:0 right:auto bottom:0 left:0 */
    width: 4px;
    background: var(--isis-resource-accent, var(--isis-text-muted));
    z-index: 2;
    pointer-events: none;
    border-top-left-radius: 3px;
    border-bottom-left-radius: 3px;
}
.isis-planner-item--previsionnel {
    /* Motif hachuré renforcé à 14 % pour rester perceptible sur le fond tinté ressource. */
    background-image: repeating-linear-gradient(135deg, transparent 0 6px, rgba(0,0,0,0.14) 6px 8px);
}
/* Option D — Avatar initiales coloré dans le meta (signal fort ressource).
   Calque le ResourceHeaderTemplate de la lane gauche : rond pour collab,
   carré arrondi pour équipement. */
.isis-planner-item__avatar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: 16px;
    height: 16px;
    background: var(--isis-resource-accent, var(--isis-text-muted));
    color: #fff;
    font-size: 0.58rem;
    font-weight: 700;
    line-height: 1;
    letter-spacing: -0.02em;
    /* Ombre fine + ring blanc pour ancrer l'avatar sur le fond tinté qui partage sa teinte. */
    box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.45), 0 1px 2px rgba(0, 0, 0, 0.15);
}
.isis-planner-item__avatar.is-collab { border-radius: 50%; }
.isis-planner-item__avatar.is-equip { border-radius: 3px; }
/* Container queries — masquer l'avatar quand le bloc devient trop étroit
   (vues Trimestre / Semestre / Année). Bordure + fond + outline restent
   les signaux d'identité ressource jusqu'en vue Année. */
@container planner-v3-item (max-width: 90px) {
    /* Audit ui-ux : le bouton « N mat. » était le seul élément du bloc sans repli — il
       disparaissait donc en silence, coupé par l'overflow, sans indiquer qu'il y avait du
       matériel engagé. On garde le chevron (signal de présence) et on lâche le compteur. */
    .isis-planner-item__kit-label { display: none; }
    .isis-planner-item__kit { padding: 0 2px; }
}
@container planner-v3-item (max-width: 70px) {
    .isis-planner-item__avatar { display: none; }
}
@container planner-v3-item (max-width: 50px) {
    .isis-planner-item__duration,
    .isis-planner-item__charge { display: none; }
}
@container planner-v3-item (max-width: 30px) {
    .isis-planner-item__meta,
    .isis-planner-item__title { display: none; }
}
.isis-planner-item--realise {
    opacity: 0.85;
}
.isis-planner-item--annule {
    opacity: 0.5;
    text-decoration: line-through;
}
.isis-planner-item__meta {
    display: flex;
    align-items: center;
    gap: 4px;
    font-size: 0.66rem;
    line-height: 1;
    color: var(--isis-text-muted);
    white-space: nowrap;
    min-width: 0;
}
.isis-planner-item__state {
    display: inline-flex;
    align-items: center;
    padding: 1px 4px;
    border-radius: 3px;
    font-size: 0.6rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    line-height: 1.3;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    flex-shrink: 0;
}
.isis-planner-item__state.is-previsionnel {
    background: color-mix(in srgb, var(--isis-warning) 18%, var(--isis-surface));
    border-color: color-mix(in srgb, var(--isis-warning) 50%, transparent);
    color: color-mix(in srgb, var(--isis-warning) 70%, var(--isis-text));
}
.isis-planner-item__state.is-ferme {
    background: color-mix(in srgb, var(--isis-mod-gespla) 20%, var(--isis-surface));
    border-color: color-mix(in srgb, var(--isis-mod-gespla) 55%, transparent);
    color: color-mix(in srgb, var(--isis-mod-gespla) 80%, var(--isis-text));
}
.isis-planner-item__state.is-realise {
    background: var(--isis-surface-soft);
    border-color: color-mix(in srgb, var(--isis-success, #16a34a) 40%, transparent);
    color: var(--isis-success, #16a34a);
}
.isis-planner-item__state.is-annule {
    background: var(--isis-surface);
    border-color: var(--isis-border);
    color: var(--isis-danger, #dc2626);
}
.isis-planner-item__duration,
.isis-planner-item__charge {
    font-variant-numeric: tabular-nums;
    font-weight: 600;
    color: var(--isis-text);
    flex-shrink: 0;
}
.isis-planner-item__title {
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
}

/* Dégradation responsive selon la largeur (container queries) */
@container planner-v3-item (max-width: 150px) {
    .isis-planner-item__duration,
    .isis-planner-item__charge { display: none; }
}
@container planner-v3-item (max-width: 80px) {
    .isis-planner-item__title { display: none; }
}
@container planner-v3-item (max-width: 50px) {
    .isis-planner-item__state { display: none; }
}

/* ─────────────────────────────────────────────────────────────────────────
   Sprint X port V3 — labels de lanes ressources (ResourceHeaderTemplate)
   Avatar initiales coloré stable (rond=collab, carré arrondi=équipement)
   + nom à droite avec ellipsis.
   ───────────────────────────────────────────────────────────────────────── */
.isis-planner-lane {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 4px 8px;
    width: 100%;
    height: 100%;
    min-width: 0;
}
.isis-planner-lane__avatar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 28px;
    height: 28px;
    color: #fff;
    font-weight: 700;
    font-size: 0.82rem;
    line-height: 1;
    letter-spacing: 0.02em;
    text-shadow: 0 1px 1px rgba(0, 0, 0, 0.3);
    box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.4) inset;
    user-select: none;
}
.isis-planner-lane__avatar.is-collab {
    border-radius: 50%;                /* rond pour personne */
}
.isis-planner-lane__avatar.is-equip {
    border-radius: 4px;                /* carré arrondi pour équipement */
}
.isis-planner-lane__avatar.is-cmd {
    border-radius: 2px;                /* carré net pour commande source */
    /* Z2.3 — avatar commande : utilise une forme "tag/document" distincte */
}

/* Z2.3 — badge "N à couvrir" sur lanes commande de la vue Par commande */
.isis-planner-lane__badge {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    margin-left: auto;
    padding: 2px 6px;
    background: color-mix(in srgb, var(--isis-warning) 18%, var(--isis-surface));
    border: 1px solid color-mix(in srgb, var(--isis-warning) 50%, transparent);
    color: color-mix(in srgb, var(--isis-warning) 75%, var(--isis-text));
    border-radius: 4px;
    font-size: 0.72rem;
    font-weight: 700;
    line-height: 1.2;
    text-decoration: none;
    flex-shrink: 0;
    transition: background 120ms ease;
}
.isis-planner-lane__badge:hover {
    background: color-mix(in srgb, var(--isis-warning) 28%, var(--isis-surface));
}
.isis-planner-lane__badge-label {
    font-weight: 500;
    font-size: 0.66rem;
    text-transform: uppercase;
    letter-spacing: 0.02em;
    opacity: 0.85;
}

/* Sprint AB3 — Badge compteur sur bouton « Que faire ? » + dialog associé */
.isis-rich-toolbar__btn.is-actions-btn {
    position: relative;
    background: color-mix(in srgb, var(--isis-mod-gespla) 14%, var(--isis-surface));
    border-color: var(--isis-mod-gespla);
    color: color-mix(in srgb, var(--isis-mod-gespla) 80%, var(--isis-text));
    font-weight: 600;
}
.isis-rich-toolbar__btn-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 18px;
    height: 18px;
    padding: 0 5px;
    background: var(--isis-danger);
    color: #fff;
    border-radius: 9px;
    font-size: 0.7rem;
    font-weight: 700;
    margin-left: 4px;
}

.isis-planner-actions {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    min-width: 600px;
}
.isis-planner-actions__hint {
    margin: 0;
    font-size: 0.85rem;
    color: var(--isis-text-muted);
}
.isis-planner-actions__section {
    border: 1px solid var(--isis-border);
    border-radius: 6px;
    overflow: hidden;
}
.isis-planner-actions__group {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.5rem 0.75rem;
    font-weight: 600;
    font-size: 0.85rem;
    border-bottom: 1px solid var(--isis-border);
}
.isis-planner-actions__group.is-danger {
    background: color-mix(in srgb, var(--isis-danger) 12%, var(--isis-surface));
    color: var(--isis-danger);
    border: 1px solid var(--isis-danger);
    box-sizing: border-box;
}
.isis-planner-actions__group.is-warning {
    background: color-mix(in srgb, var(--isis-warning) 14%, var(--isis-surface));
    color: color-mix(in srgb, var(--isis-warning) 80%, var(--isis-text));
    border: 1px solid var(--isis-warning);
    box-sizing: border-box;
}
.isis-planner-actions__group.is-info {
    background: color-mix(in srgb, var(--isis-mod-gespla) 10%, var(--isis-surface));
    color: var(--isis-mod-gespla);
    border: 1px solid var(--isis-mod-gespla);
    box-sizing: border-box;
}
.isis-planner-actions__group-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}
.isis-planner-actions__group-title {
    flex: 1 1 auto;
}
.isis-planner-actions__group-count {
    background: var(--isis-surface);
    border: 1px solid currentColor;
    padding: 1px 8px;
    border-radius: 10px;
    font-size: 0.72rem;
    font-weight: 700;
}
/* Sprint AB4 — bouton bulk dans le header de groupe (Tout matérialiser, etc.) */
.isis-planner-actions__bulk-btn {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 3px 10px;
    border-radius: 6px;
    background: currentColor;
    color: var(--isis-surface);
    border: none;
    font-size: 0.75rem;
    font-weight: 600;
    cursor: pointer;
    margin-left: auto;
    transition: filter 0.12s ease, transform 0.08s ease;
}
.isis-planner-actions__bulk-btn:hover { filter: brightness(0.92); }
.isis-planner-actions__bulk-btn:active { transform: translateY(1px); }
.isis-planner-actions__bulk-btn:focus-visible {
    outline: 2px solid currentColor;
    outline-offset: 2px;
}
.isis-planner-actions__bulk-btn .rz-icon {
    color: var(--isis-surface) !important;
}
/* Quand le bulk-btn est présent, on retire le margin-left auto sur le count */
.isis-planner-actions__group:has(.isis-planner-actions__bulk-btn) .isis-planner-actions__group-count {
    margin-left: 0;
}
.isis-planner-actions__list {
    display: flex;
    flex-direction: column;
}
.isis-planner-actions__item {
    display: grid;
    grid-template-columns: 1fr auto 14px;
    gap: 0.5rem;
    align-items: center;
    padding: 0.45rem 0.75rem;
    background: var(--isis-surface);
    border: none;
    border-bottom: 1px solid color-mix(in srgb, var(--isis-border) 60%, transparent);
    cursor: pointer;
    text-align: left;
    transition: background 100ms ease;
}
.isis-planner-actions__item:hover {
    background: color-mix(in srgb, var(--isis-mod-gespla) 6%, var(--isis-surface));
}
.isis-planner-actions__item-label {
    font-weight: 600;
    font-size: 0.85rem;
    color: var(--isis-text);
}
.isis-planner-actions__item-sub {
    font-size: 0.75rem;
    color: var(--isis-text-muted);
}

/* V1.1 — Wrapper de toolbar fusionnée : filtres (gauche) + séparateur vertical + KPIs (droite).
   Une seule card visuelle qui regroupe les 2 outils de pilotage. */
.isis-planner-toolbar-merged {
    display: flex;
    align-items: stretch;
    flex-wrap: wrap;
    gap: 0.75rem;
    padding: 0.5rem 0.75rem;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: 6px;
    margin-bottom: 0.5rem;
}
/* Section filtres dans la toolbar fusionnée — transparente (le wrapper porte le fond) */
.isis-planner-toolbar-merged > .isis-planner-search {
    flex: 1 1 480px;
    background: transparent;
    border: none;
    border-left: none;
    border-radius: 0;
    padding: 0;
    margin: 0;
}
/* V1.1 — Bandeau recherche multi-select (standalone — non utilisé si toolbar fusionnée).
   Gardé pour back-compat si on veut décomposer plus tard. */
.isis-planner-search {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    flex-wrap: wrap;
    padding: 0.5rem 0.75rem;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: 6px;
    margin-bottom: 0.5rem;
}
/* 2026-07-28 — les 3 comboboxes de filtre héritaient de `rz-input-md` (padding 7/15,
   line-height 24) et culminaient à 51 px : trois blocs massifs pour ce qui n'est qu'une barre
   de filtres. Compactés à ~34 px, hauteur FIXE pour que la barre ne saute pas quand une
   sélection allonge le libellé. */
.isis-planner-search .rz-dropdown {
    min-height: 34px;
    padding: 0 0.55rem;
    display: inline-flex;
    justify-content: center;
}
/* Le sélecteur de nature était le dernier élément à 36 px et fixait donc à lui seul la hauteur
   de la barre. Aligné sur les comboboxes — portée volontairement limitée à cette barre, le
   composant sert ailleurs. */
.isis-planner-search .isis-view-toggle,
.isis-planner-search .isis-view-toggle__btn {
    min-height: 32px;
    height: 32px;
}
.isis-planner-search .rz-dropdown .rz-dropdown-label,
.isis-planner-search .rz-dropdown .rz-multiselect-label {
    font-size: var(--isis-fs-sm);
    line-height: 1.5;
    padding: 0;
    /* Un libellé long (objet complet d'un devis) ne doit ni faire grandir le champ ni
       déborder : il se tronque. La liste déroulante, elle, montre le libellé entier. */
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
/* Le libellé d'une option peut être très long (objet d'un devis, parfois multi-ligne) :
   on le borne pour que le panneau reste lisible. */
.isis-planner-search .rz-multiselect-item,
.rz-multiselect-panel .rz-multiselect-item {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 420px;
}
.isis-planner-search__label {
    font-size: 0.78rem;
    font-weight: 600;
    color: var(--isis-text);
    letter-spacing: 0.02em;
}
.isis-planner-search__clear {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 4px 10px;
    background: color-mix(in srgb, var(--isis-warning) 12%, var(--isis-surface));
    border: 1px solid color-mix(in srgb, var(--isis-warning) 40%, transparent);
    color: color-mix(in srgb, var(--isis-warning) 80%, var(--isis-text));
    border-radius: 4px;
    font-size: 0.78rem;
    font-weight: 600;
    cursor: pointer;
    transition: background 120ms ease;
}
.isis-planner-search__clear:hover {
    background: color-mix(in srgb, var(--isis-warning) 22%, var(--isis-surface));
}
.isis-planner-search__count {
    /* margin-left:auto déplacé sur .isis-planner-search__tail (2026-07-07) pour éviter
       le conflit de deux auto-margins avec le bouton Légende dans le flex-wrap. */
    font-size: 0.78rem;
    color: var(--isis-text-muted);
    font-variant-numeric: tabular-nums;
}
/* Bloc terminal de la toolbar : compteur + bouton Légende poussés ensemble à droite. */
.isis-planner-search__tail {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    margin-left: auto;
}

/* 2026-07-03 — fusion KPIs planner dans l'en-tête (pattern --with-kpi).
   Le wrapper hérite du layout global .isis-rich-header__kpis (margin-left:auto
   + séparateur vertical + stack < 1024px) ; on autorise juste le rétrécissement
   pour que les chips .isis-planner-kpi puissent passer à la ligne, et on
   neutralise le look « card standalone » du bandeau à l'intérieur du header.
   Règles scopées au modificateur — aucune autre page --with-kpi n'est touchée. */
.isis-rich-header__kpis.isis-rich-header__kpis--planner {
    flex: 0 1 auto;
    min-width: 0;
}
.isis-rich-header__kpis--planner .isis-planner-kpis {
    background: transparent;
    border: none;
    border-radius: 0;
    padding: 0;
    margin-bottom: 0;
    justify-content: flex-end;
}

/* Sprint AA6 — Bandeau KPIs synthèse en tête du planner V3 */
.isis-planner-kpis {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    padding: 0.5rem 0.75rem;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: 6px;
    margin-bottom: 0.5rem;
}
/* 2026-07-28 — aligné sur le KPI d'en-tête standard (.isis-kpi-card, cf. /gespla/previsionnel) :
   pas d'encadré. Chaque KPI n'est plus une carte posée sur le hero mais une colonne séparée par
   un simple filet. Les variantes sémantiques ci-dessous ne peignent donc plus de fond : elles
   colorent la VALEUR, seul porteur du signal — sinon on remettrait l'encadré par la bande. */
.isis-planner-kpi {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    min-width: 70px;
    padding: 0.2rem 0.75rem;
    border-left: 1px solid var(--isis-border);
}
.isis-planner-kpi:first-child {
    border-left: none;
    padding-left: 0.2rem;
}
.isis-planner-kpi__value {
    font-size: 1.2rem;
    font-weight: 700;
    line-height: 1.1;
    color: var(--isis-text);
    font-variant-numeric: tabular-nums;
}
.isis-planner-kpi__label {
    font-size: 0.66rem;
    color: var(--isis-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    margin-top: 1px;
}
/* Variantes sémantiques : la couleur porte sur la VALEUR, jamais sur un fond — c'est ce qui
   permet de retirer l'encadré sans perdre le signal. « Prioritaires » n'avait qu'un fond et
   serait devenu indistinct : il reçoit donc sa propre couleur de valeur. */
.isis-planner-kpi.is-kind-ferme .isis-planner-kpi__value {
    color: color-mix(in srgb, var(--isis-mod-gespla) 80%, var(--isis-text));
}
.isis-planner-kpi.is-kind-previ .isis-planner-kpi__value {
    color: color-mix(in srgb, var(--isis-warning) 80%, var(--isis-text));
}
.isis-planner-kpi.is-priority-high .isis-planner-kpi__value {
    color: var(--isis-danger);
}
.isis-planner-kpi.is-priority-medium .isis-planner-kpi__value {
    color: color-mix(in srgb, var(--isis-warning) 85%, var(--isis-text));
}
.isis-planner-kpi.is-danger .isis-planner-kpi__value,
.isis-planner-kpi.is-conflict .isis-planner-kpi__value {
    color: var(--isis-danger);
}

/* Sprint AA — différenciation FERME/PRÉVISIONNELLE + priorité sur lanes commande */
.isis-planner-lane.is-kind-ferme {
    /* Bordure gauche teal pleine = engagement confirmé */
    box-shadow: inset 4px 0 0 0 color-mix(in srgb, var(--isis-mod-gespla) 70%, transparent);
}
.isis-planner-lane.is-kind-previ {
    /* Bordure gauche orange hachurée = prévisionnel (pas encore engagé) */
    box-shadow: inset 4px 0 0 0 var(--isis-warning);
    background-image: repeating-linear-gradient(
        135deg,
        transparent 0 6px,
        color-mix(in srgb, var(--isis-warning) 8%, transparent) 6px 8px);
}
.isis-planner-lane.is-priority-high {
    /* Priorité URGENT : halo rouge + pulse subtil */
    box-shadow:
        inset 4px 0 0 0 var(--isis-danger),
        0 0 0 1px color-mix(in srgb, var(--isis-danger) 40%, transparent);
    animation: isis-priority-pulse 2.5s ease-in-out infinite;
}
.isis-planner-lane.is-priority-medium {
    box-shadow: inset 4px 0 0 0 var(--isis-warning);
}
@keyframes isis-priority-pulse {
    0%, 100% { background-color: transparent; }
    50%      { background-color: color-mix(in srgb, var(--isis-danger) 5%, transparent); }
}
@media (prefers-reduced-motion: reduce) {
    .isis-planner-lane.is-priority-high { animation: none; }
}

/* Chip kind PRÉVI orange */
.isis-planner-lane__chip {
    display: inline-flex;
    align-items: center;
    padding: 1px 6px;
    border-radius: 3px;
    font-size: 0.62rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    background: var(--isis-surface-soft);
    color: var(--isis-text-muted);
    border: 1px solid var(--isis-border);
    flex-shrink: 0;
    margin-left: 6px;
}
.isis-planner-lane__chip.is-previ {
    background: color-mix(in srgb, var(--isis-warning) 20%, var(--isis-surface));
    color: color-mix(in srgb, var(--isis-warning) 80%, var(--isis-text));
    border-color: color-mix(in srgb, var(--isis-warning) 50%, transparent);
}
/* Chips statut commande — couleurs sémantiques */
.isis-planner-lane__chip.is-statut-en-cours,
.isis-planner-lane__chip.is-statut-a-livrer,
.isis-planner-lane__chip.is-statut-a-valider {
    background: color-mix(in srgb, var(--isis-mod-gespla) 18%, var(--isis-surface));
    color: color-mix(in srgb, var(--isis-mod-gespla) 80%, var(--isis-text));
    border-color: color-mix(in srgb, var(--isis-mod-gespla) 50%, transparent);
}
.isis-planner-lane__chip.is-statut-a-facturer,
.isis-planner-lane__chip.is-statut-a-cloturer,
.isis-planner-lane__chip.is-statut-termine {
    background: color-mix(in srgb, var(--isis-success, #16a34a) 14%, var(--isis-surface));
    color: var(--isis-success, #16a34a);
    border-color: color-mix(in srgb, var(--isis-success, #16a34a) 40%, transparent);
}
.isis-planner-lane__chip.is-statut-cloturee {
    background: var(--isis-surface-soft);
    color: var(--isis-text-muted);
    text-decoration: line-through;
}
.isis-planner-lane__chip.is-statut-annulee {
    background: color-mix(in srgb, var(--isis-danger) 14%, var(--isis-surface));
    color: var(--isis-danger);
    text-decoration: line-through;
}

/* Icône conflit + badge priorité */
.isis-planner-lane__conflict-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 20px;
    height: 20px;
    color: var(--isis-danger);
    flex-shrink: 0;
    margin-left: 4px;
}
.isis-planner-lane__priority {
    display: inline-flex;
    align-items: center;
    padding: 1px 6px;
    border-radius: 3px;
    font-size: 0.6rem;
    font-weight: 800;
    letter-spacing: 0.04em;
    color: #fff;
    flex-shrink: 0;
    margin-left: 4px;
}
.isis-planner-lane__priority.is-high   { background: var(--isis-danger); }
.isis-planner-lane__priority.is-medium { background: var(--isis-warning); color: var(--isis-text); }

/* 2026-07-03 — badge d'origine du périmètre (managé direct / partage inter-structure). */
.isis-planner-lane__origin {
    display: inline-flex;
    align-items: center;
    margin-left: 4px;
    color: var(--isis-text-muted);
    flex-shrink: 0;
}
.isis-planner-lane__origin .rzi {
    font-size: 14px;
}

/* 2026-07-04 « mobilisation hors périmètre → validation » — lane collab hors sous-arbre
   managérial (STRUCTURE/GOUVERNANCE) : atténuée pour signaler qu'une mobilisation y
   déclenchera une demande de validation. */
.isis-planner-lane.is-hors-perimetre {
    opacity: 0.88;
    background: color-mix(in srgb, var(--isis-warning) 6%, var(--isis-surface));
}
.isis-planner-lane__origin--hors {
    color: var(--isis-warning);
}

/* AA5 V1.1 — Strip compétences requises sur lane commande */
.isis-planner-lane__competences {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    margin-left: 6px;
    flex-shrink: 1;
    overflow: hidden;
    cursor: help;
}
.isis-planner-lane__competence-chip {
    display: inline-flex;
    align-items: center;
    padding: 1px 5px;
    background: color-mix(in srgb, var(--isis-accent) 12%, var(--isis-surface));
    color: color-mix(in srgb, var(--isis-accent) 80%, var(--isis-text));
    border: 1px solid color-mix(in srgb, var(--isis-accent) 35%, transparent);
    border-radius: 3px;
    font-size: 0.6rem;
    font-weight: 600;
    line-height: 1.3;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 110px;
}
.isis-planner-lane__competence-more {
    font-size: 0.62rem;
    font-weight: 700;
    color: var(--isis-text-muted);
    padding: 1px 4px;
    background: var(--isis-surface-soft);
    border-radius: 3px;
    border: 1px solid var(--isis-border);
}
.isis-planner-lane__competence-missing {
    font-size: 0.62rem;
    font-weight: 700;
    color: var(--isis-warning-text);
    padding: 1px 4px;
    background: var(--isis-warning-soft);
    border-radius: 3px;
    border: 1px solid color-mix(in srgb, var(--isis-warning) 40%, transparent);
    white-space: nowrap;
}

/* Sprint AC4 — bouton Matérialiser sur lane commande PRÉVISIONNELLE */
.isis-planner-lane__materialize-btn {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    padding: 2px 6px;
    background: color-mix(in srgb, var(--isis-success, #16a34a) 14%, var(--isis-surface));
    color: var(--isis-success, #16a34a);
    border: 1px solid color-mix(in srgb, var(--isis-success, #16a34a) 50%, transparent);
    border-radius: 3px;
    font-size: 0.66rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.02em;
    cursor: pointer;
    transition: background 120ms ease;
    margin-left: 4px;
    flex-shrink: 0;
}
.isis-planner-lane__materialize-btn:hover {
    background: color-mix(in srgb, var(--isis-success, #16a34a) 22%, var(--isis-surface));
}
.isis-planner-lane__materialize-btn:focus-visible {
    outline: 2px solid var(--isis-success, #16a34a);
    outline-offset: 1px;
}

/* Étoile de favori sur une lane collaborateur / équipement (EF-101). */
.isis-planner-lane__fav {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    margin-left: 2px;
    padding: 0;
    flex-shrink: 0;
    background: transparent;
    color: var(--isis-text-muted);
    border: none;
    border-radius: 3px;
    cursor: pointer;
    transition: color 120ms ease;
}
.isis-planner-lane__fav:hover {
    color: var(--isis-text);
}
.isis-planner-lane__fav.is-on {
    color: var(--isis-warning);
}
.isis-planner-lane__fav:focus-visible {
    outline: 2px solid var(--isis-current-mod);
    outline-offset: 1px;
}

/* Bouton + Mobiliser direct sur la lane commande (vue Par commande) */
.isis-planner-lane__mobilize-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    margin-left: auto;
    padding: 0;
    width: 24px;
    height: 24px;
    background: var(--isis-mod-gespla);
    color: #fff;
    border: none;
    border-radius: 50%;
    cursor: pointer;
    flex-shrink: 0;
    transition: transform 120ms ease, background 120ms ease;
}
.isis-planner-lane__mobilize-btn:hover {
    background: color-mix(in srgb, var(--isis-mod-gespla) 85%, #000);
    transform: scale(1.08);
}
.isis-planner-lane__mobilize-btn:focus-visible {
    outline: 2px solid var(--isis-mod-gespla);
    outline-offset: 2px;
}
/* Quand le bouton mobilize est présent à côté du badge, retirer margin-left auto
   du badge — il suit naturellement le bouton. */
.isis-planner-lane__mobilize-btn + .isis-planner-lane__badge {
    margin-left: 4px;
}

/* Mini-dialog BesoinPickerDialog — liste des besoins non-couverts à mobiliser */
.isis-besoin-picker {
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
    min-width: 500px;
}
.isis-besoin-picker__loader {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.5rem;
    padding: 1.5rem 1rem;
    color: var(--isis-text-muted);
}
.isis-besoin-picker__hint {
    margin: 0;
    font-size: 0.85rem;
    color: var(--isis-text-muted);
}
.isis-besoin-picker__list {
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
    max-height: 50vh;
    overflow-y: auto;
}
.isis-besoin-picker__item {
    display: grid;
    grid-template-columns: 12px 1fr auto auto 18px;
    gap: 0.6rem;
    align-items: center;
    padding: 0.55rem 0.75rem;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: 6px;
    cursor: pointer;
    text-align: left;
    transition: background 100ms ease, border-color 100ms ease;
}
.isis-besoin-picker__item:hover {
    background: color-mix(in srgb, var(--isis-mod-gespla) 6%, var(--isis-surface));
    border-color: var(--isis-mod-gespla);
}
.isis-besoin-picker__item:focus-visible {
    outline: 2px solid var(--isis-mod-gespla);
    outline-offset: 1px;
}
.isis-besoin-picker__profil {
    font-weight: 600;
    color: var(--isis-text);
}
.isis-besoin-picker__charge {
    font-variant-numeric: tabular-nums;
    font-size: 0.85rem;
    color: var(--isis-text);
}
.isis-besoin-picker__status {
    padding: 2px 6px;
    border-radius: 3px;
    font-size: 0.66rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}
.isis-besoin-picker__status.is-danger {
    background: color-mix(in srgb, var(--isis-danger) 18%, var(--isis-surface));
    color: var(--isis-danger);
}
.isis-besoin-picker__status.is-warning {
    background: color-mix(in srgb, var(--isis-warning) 18%, var(--isis-surface));
    color: color-mix(in srgb, var(--isis-warning) 80%, var(--isis-text));
}

/* ─────────────────────────────────────────────────────────────────────────
   Marquage visuel du jour courant sur SfSchedule (TimelineDay/Week/Month).
   Syncfusion ajoute la classe `.e-current-day` aux header cells + work cells
   de la colonne du jour courant. On renforce avec un fond teinté module
   gespla + bordure top épaisse + label gras dans le header.
   La ligne verticale `.e-current-time-indicator` est aussi colorée.
   ───────────────────────────────────────────────────────────────────────── */
.isis-planner-schedule .e-schedule-table .e-header-row .e-current-day,
.isis-planner-schedule .e-date-header-container .e-current-day,
.isis-planner-schedule .e-date-header-wrap .e-current-day {
    background: color-mix(in srgb, var(--isis-mod-gespla) 18%, var(--isis-surface)) !important;
    color: var(--isis-mod-gespla) !important;
    font-weight: 700 !important;
    border-top: 3px solid var(--isis-mod-gespla) !important;
    position: relative;
}
.isis-planner-schedule .e-date-header-wrap .e-current-day::after,
.isis-planner-schedule .e-date-header-container .e-current-day::after {
    content: "Auj.";
    position: absolute;
    bottom: 2px;
    left: 50%;
    transform: translateX(-50%);
    font-size: 0.6rem;
    font-weight: 700;
    color: var(--isis-mod-gespla);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    opacity: 0.85;
}
/* Colonne du jour courant côté work cells (fond timeline) — teinte marquée
   sur toute la hauteur de la lane. Visible mais sans masquer les events. */
.isis-planner-schedule .e-content-wrap .e-work-cells.e-current-day,
.isis-planner-schedule .e-content-wrap .e-alternate-cells.e-current-day,
.isis-planner-schedule .e-schedule-table .e-work-cells.e-current-day {
    background: color-mix(in srgb, var(--isis-mod-gespla) 15%, var(--isis-surface)) !important;
    box-shadow:
        inset 3px 0 0 0 var(--isis-mod-gespla),
        inset -1px 0 0 0 color-mix(in srgb, var(--isis-mod-gespla) 40%, transparent);
}

/* ─────────────────────────────────────────────────────────────────────────
   Jours fériés — la classe `isis-planner-holiday` est injectée par
   OnRenderCell sur header dates ET work cells body de la colonne fériée.
   Fond pastel orange (warning) qui se distingue du teal aujourd'hui.
   ───────────────────────────────────────────────────────────────────────── */
.isis-planner-schedule .e-date-header-wrap .isis-planner-holiday,
.isis-planner-schedule .e-date-header-container .isis-planner-holiday {
    background: color-mix(in srgb, var(--isis-warning) 20%, var(--isis-surface)) !important;
    color: color-mix(in srgb, var(--isis-warning) 80%, var(--isis-text)) !important;
    font-weight: 600 !important;
    border-top: 2px solid color-mix(in srgb, var(--isis-warning) 70%, transparent) !important;
}
.isis-planner-schedule .e-content-wrap .e-work-cells.isis-planner-holiday,
.isis-planner-schedule .e-content-wrap .e-alternate-cells.isis-planner-holiday {
    background: color-mix(in srgb, var(--isis-warning) 10%, var(--isis-surface)) !important;
    background-image: repeating-linear-gradient(
        45deg,
        transparent 0 8px,
        color-mix(in srgb, var(--isis-warning) 8%, transparent) 8px 10px) !important;
}
/* Combo aujourd'hui + férié : aujourd'hui prime (fond couleur module), l'orange
   férié transparaît en rayures diagonales par-dessus. Bug 2026-05-22 corrigé : le
   sélecteur original était un compound (`.isis-planner-schedule.isis-planner-holiday.e-current-day`)
   qui matchait l'élément racine porteur des 3 classes — jamais le cas en pratique.
   Le bon sélecteur est descendant (cellule enfant porteuse des 2 classes). */
.isis-planner-schedule .isis-planner-holiday.e-current-day {
    background: color-mix(in srgb, var(--isis-mod-gespla) 15%, var(--isis-surface)) !important;
    background-image: repeating-linear-gradient(
        45deg,
        transparent 0 8px,
        color-mix(in srgb, var(--isis-warning) 18%, transparent) 8px 10px) !important;
}
/* ── Sprint 4 — Heatmap capacité tenant ──────────────────────────────────────
   Bande de couleur sur chaque cellule jour qui reflète la charge moyenne
   tenant (somme charge_pct FERME+REALISE collabs / N collabs).
   4 paliers : cool (sous-utilisé) / low (normal) / warning (proche saturation) /
   high (surcharge). Couleurs très diluées pour ne pas masquer les events.
   Posés sur les work-cells (body) + le header date — le selector ne touche pas
   les events eux-mêmes (e-appointment) qui gardent leur couleur ressource. */
.isis-planner-schedule .e-date-header-wrap .isis-planner-heat--cool,
.isis-planner-schedule .e-date-header-container .isis-planner-heat--cool,
.isis-planner-schedule .e-content-wrap .e-work-cells.isis-planner-heat--cool,
.isis-planner-schedule .e-content-wrap .e-alternate-cells.isis-planner-heat--cool {
    background-color: color-mix(in srgb, var(--isis-info, #3b82f6) 4%, transparent);
}
.isis-planner-schedule .e-date-header-wrap .isis-planner-heat--low,
.isis-planner-schedule .e-date-header-container .isis-planner-heat--low,
.isis-planner-schedule .e-content-wrap .e-work-cells.isis-planner-heat--low,
.isis-planner-schedule .e-content-wrap .e-alternate-cells.isis-planner-heat--low {
    background-color: color-mix(in srgb, var(--isis-success, #10b981) 4%, transparent);
}
.isis-planner-schedule .e-date-header-wrap .isis-planner-heat--warning,
.isis-planner-schedule .e-date-header-container .isis-planner-heat--warning,
.isis-planner-schedule .e-content-wrap .e-work-cells.isis-planner-heat--warning,
.isis-planner-schedule .e-content-wrap .e-alternate-cells.isis-planner-heat--warning {
    background-color: color-mix(in srgb, var(--isis-warning) 8%, transparent);
}
.isis-planner-schedule .e-date-header-wrap .isis-planner-heat--high,
.isis-planner-schedule .e-date-header-container .isis-planner-heat--high,
.isis-planner-schedule .e-content-wrap .e-work-cells.isis-planner-heat--high,
.isis-planner-schedule .e-content-wrap .e-alternate-cells.isis-planner-heat--high {
    background-color: color-mix(in srgb, var(--isis-danger) 10%, transparent);
}

/* 2026-07-03 — lasso : la plage sélectionnée doit se voir (le gris natif Syncfusion se
   confondait avec fériés/heatmap). Teinte module + liserés haut/bas façon pré-barre de
   mobilisation. Placée APRÈS les règles heatmap : à spécificité égale, la sélection
   gagne la cascade quand une cellule cumule les deux. */
.isis-planner-schedule .e-content-wrap .e-work-cells.e-selected-cell,
.isis-planner-schedule .e-content-wrap .e-alternate-cells.e-selected-cell {
    /* !important : état interactif transitoire — doit dominer les fonds week-end/férié/
       heatmap Syncfusion (leur règle non-workday bat sinon la nôtre en spécificité). */
    background-color: color-mix(in srgb, var(--isis-mod-gespla) 18%, var(--isis-surface)) !important;
    box-shadow: inset 0 2px 0 var(--isis-mod-gespla), inset 0 -2px 0 var(--isis-mod-gespla);
}

/* Sprint 4 a11y — Légende heatmap (correctif B1 audit accessibility-tester
   2026-05-22). Alternative textuelle au code couleur seul, posée sous le
   Scheduler. role="note" + aria-label complet sur le conteneur, aria-hidden
   sur les swatches purement décoratifs (le texte adjacent décrit le palier). */

/* Sprint 1.1 2026-05-23 — hint discret sous le scheduler en vue ByCommande pour
   signaler que le drag vertical réaffecte une mob à une autre commande. */
.isis-planner-drag-hint {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.4rem 0.75rem;
    margin-top: 0.5rem;
    background: color-mix(in srgb, var(--isis-mod-gespla) 8%, var(--isis-surface));
    border: 1px solid color-mix(in srgb, var(--isis-mod-gespla) 25%, var(--isis-border));
    /* Liseré gauche 3px décoratif retiré 2026-07-04 (demande utilisateur) — le fond
       teinté + le filet 1px suffisent à identifier l'encart. */
    border-radius: 6px;
    font-size: 0.78rem;
    color: var(--isis-text);
}
.isis-planner-drag-hint > .rz-icon {
    color: var(--isis-mod-gespla);
    flex-shrink: 0;
}
.isis-planner-drag-hint strong {
    font-weight: 600;
    color: color-mix(in srgb, var(--isis-mod-gespla) 70%, var(--isis-text));
}

.isis-planner-heat-legend {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.85rem;
    padding: 0.45rem 0.75rem;
    margin-top: 0.5rem;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: 6px;
    font-size: 0.78rem;
    color: var(--isis-text-muted);
}
.isis-planner-heat-legend__label {
    font-weight: 600;
    color: var(--isis-text);
}
.isis-planner-heat-legend__item {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
}
.isis-planner-heat-legend__swatch {
    display: inline-block;
    width: 14px;
    height: 14px;
    border-radius: 3px;
    border: 1px solid var(--isis-border);
    /* Anneau intérieur léger pour le contraste daltoniens — distingue les
       swatches même si la couleur de fond est très diluée (4-10 %). */
    box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.06);
}
/* Les variantes --cool/--low/--warning/--high réutilisent le background-color
   déjà défini sur les cellules Scheduler, mais sans les sélecteurs descendants
   (.e-date-header-wrap etc.). Pour que le swatch porte la même teinte, on
   redéfinit chaque variante directement sur la classe combinée. */
.isis-planner-heat-legend__swatch.isis-planner-heat--cool {
    background-color: color-mix(in srgb, var(--isis-info, #3b82f6) 30%, var(--isis-surface));
}
.isis-planner-heat-legend__swatch.isis-planner-heat--low {
    background-color: color-mix(in srgb, var(--isis-success, #10b981) 30%, var(--isis-surface));
}
.isis-planner-heat-legend__swatch.isis-planner-heat--warning {
    background-color: color-mix(in srgb, var(--isis-warning) 35%, var(--isis-surface));
}
.isis-planner-heat-legend__swatch.isis-planner-heat--high {
    background-color: color-mix(in srgb, var(--isis-danger) 40%, var(--isis-surface));
}
/* Légende « Barres » — swatch affectation planifiée : sans fond il était invisible
   (le fond réel des barres vient de la couleur ressource, non reproductible ici). */
.isis-planner-heat-legend__swatch--affect {
    background-color: color-mix(in srgb, var(--isis-planif-affect) 35%, var(--isis-surface));
    border-color: color-mix(in srgb, var(--isis-planif-affect) 60%, transparent);
}
/* ── 2026-07-07 — Popover « Légende & aide » (toolbar) ─────────────────────────
   Remplace les 4 encarts empilés sous le scheduler (~150 px permanents). Popover
   contrôlé côté Blazor : backdrop transparent plein écran pour le light-dismiss,
   panneau ancré sous le bouton, élévation tokenisée (branded depth). */
.isis-planner-legend { position: relative; display: inline-flex; }
.isis-planner-legend__btn {
    display: inline-flex; align-items: center; gap: 0.3rem;
    padding: 0.3rem 0.6rem;
    font-size: 0.78rem; font-weight: 600; line-height: 1.2;
    color: var(--isis-text-muted);
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-sm, 4px);
    cursor: pointer;
    transition: color .12s, border-color .12s, background .12s;
}
.isis-planner-legend__btn:hover {
    color: var(--isis-text);
    border-color: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 45%, var(--isis-border));
}
.isis-planner-legend__btn.is-active {
    color: var(--isis-current-mod, var(--isis-accent));
    border-color: var(--isis-current-mod, var(--isis-accent));
    background: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 8%, var(--isis-surface));
}
.isis-planner-legend__btn:focus-visible {
    outline: 2px solid var(--isis-current-mod, var(--isis-accent));
    outline-offset: 1px;
}
.isis-planner-legend__backdrop { position: fixed; inset: 0; z-index: 1000; background: transparent; }
.isis-planner-legend__pop {
    position: absolute; top: calc(100% + 6px); right: 0; z-index: 1001;
    width: min(380px, 92vw);
    display: flex; flex-direction: column; gap: 0.55rem;
    padding: 0.85rem 1rem;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius, 6px);
    box-shadow: var(--isis-elevation-1);
}
/* Dans le popover étroit, chaque encart devient un groupe VERTICAL titré : le layout
   horizontal flex-wrap d'origine (label + pastilles enroulés) était illisible ici. */
.isis-planner-legend__pop .isis-planner-heat-legend {
    margin-top: 0; padding: 0; border: none; background: transparent;
    flex-direction: column; align-items: stretch; gap: 0.28rem;
}
/* Séparateur entre les groupes (Charge / Barres / Nature). */
.isis-planner-legend__pop .isis-planner-heat-legend + .isis-planner-heat-legend {
    padding-top: 0.55rem;
    border-top: 1px solid var(--isis-border);
}
/* Le label du groupe devient un intertitre sur sa propre ligne. */
.isis-planner-legend__pop .isis-planner-heat-legend__label {
    font-size: 0.68rem; font-weight: 700; text-transform: uppercase;
    letter-spacing: 0.05em; color: var(--isis-text-muted);
    margin-bottom: 0.12rem;
}
/* Chaque entrée (pastille + libellé) sur sa propre ligne. */
.isis-planner-legend__pop .isis-planner-heat-legend__item { gap: 0.5rem; line-height: 1.3; }
.isis-planner-legend__pop .isis-planner-heat-legend__swatch { flex-shrink: 0; }
/* Astuce lasso : encart teinté distinct (tip), posé en tête du popover. */
.isis-planner-legend__pop .isis-planner-drag-hint {
    margin-top: 0; align-items: flex-start; gap: 0.5rem;
    padding: 0.5rem 0.6rem; line-height: 1.35;
    border-radius: var(--isis-radius-sm, 4px);
}

/* Combinaison heatmap + jour férié : férié (orange rayé) prime visuellement,
   mais on garde le ton heatmap en dessous. Pas de surcharge spécifique nécessaire
   tant que les opacités restent < 15 % (cumul reste lisible). */

/* Mode scénario : le planning affiché n'est pas la production — liseré violet autour de la
   grille, et nom du scénario borné (nom complet en infobulle). */
.isis-rich-page.is-scenario .isis-planner-host {
    outline: 2px solid var(--isis-violet);
    outline-offset: -2px;
}
.isis-planner-scenario-name {
    display: inline-block;
    max-width: 16rem;
    overflow: hidden;
    text-overflow: ellipsis;
    vertical-align: bottom;
}

/* Pastille sur le bouton « Scénarios » toolbar quand un scénario est actif */
.isis-rich-toolbar__btn-dot {
    display: inline-block;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--isis-violet);
    margin-left: 0.25rem;
}

/* ── Dialog gestion des scénarios ────────────────────────────────────────── */
.isis-scenario-mgmt {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    min-height: 200px;
}
.isis-scenario-mgmt__toolbar {
    display: flex;
    justify-content: flex-end;
    padding-bottom: 0.5rem;
    border-bottom: 1px solid var(--isis-border);
}
.isis-scenario-mgmt__section {
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
}
.isis-scenario-mgmt__section-title {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin: 0;
    padding: 0.25rem 0;
    font-size: 0.82rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.02em;
    color: var(--isis-text-muted);
}
.isis-scenario-mgmt__section-count {
    background: var(--isis-surface-alt);
    border: 1px solid var(--isis-border);
    border-radius: 10px;
    padding: 0 8px;
    font-size: 0.72rem;
    font-weight: 700;
    color: var(--isis-text);
}
.isis-scenario-mgmt__list {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
}
.isis-scenario-mgmt__item {
    display: flex;
    align-items: stretch;
    gap: 0.35rem;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: 6px;
    transition: background-color 0.12s ease, border-color 0.12s ease;
}
.isis-scenario-mgmt__item:hover {
    background: var(--isis-surface-alt);
    border-color: color-mix(in srgb, var(--isis-violet) 30%, var(--isis-border));
}
.isis-scenario-mgmt__item.is-archived {
    background: var(--isis-surface-alt);
    opacity: 0.85;
}
.isis-scenario-mgmt__item.is-archived:hover {
    background: var(--isis-surface-alt);
    border-color: var(--isis-border);
    cursor: default;
}
.isis-scenario-mgmt__item-main {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.25rem;
    padding: 0.6rem 0.75rem;
    text-align: left;
    background: transparent;
    border: none;
    font: inherit;
    color: inherit;
    cursor: pointer;
    width: 100%;
}
.isis-scenario-mgmt__item.is-archived .isis-scenario-mgmt__item-main {
    cursor: default;
}
.isis-scenario-mgmt__item-main:focus-visible {
    outline: 2px solid color-mix(in srgb, var(--isis-violet) 60%, transparent);
    outline-offset: -1px;
    border-radius: 6px;
}
.isis-scenario-mgmt__item-name {
    font-weight: 600;
    color: var(--isis-text);
}
.isis-scenario-mgmt__item-meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.4rem;
    font-size: 0.78rem;
    color: var(--isis-text-muted);
}
.isis-scenario-mgmt__item-source {
    font-weight: 500;
    color: var(--isis-text);
}
.isis-scenario-mgmt__item-action {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    background: transparent;
    border: none;
    color: var(--isis-text-muted);
    cursor: pointer;
    border-radius: 6px;
    transition: background-color 0.12s ease, color 0.12s ease;
}
.isis-scenario-mgmt__item-action:hover {
    background: color-mix(in srgb, var(--isis-danger) 12%, transparent);
    color: var(--isis-danger);
}
.isis-scenario-mgmt__item-action:focus-visible {
    outline: 2px solid var(--isis-danger);
    outline-offset: -2px;
}

/* Ligne verticale d'indicateur de temps (Syncfusion natif, défaut rouge). */
.isis-planner-schedule .e-current-time-indicator,
.isis-planner-schedule .e-current-time {
    background-color: var(--isis-mod-gespla) !important;
    color: var(--isis-mod-gespla) !important;
    z-index: 2;
}
.isis-planner-lane__name {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: 0.82rem;
    font-weight: 500;
    color: var(--isis-text);
}

/* ─────────────────────────────────────────────────────────────────────────
   Sprint A port V3 — layout 2 colonnes (timeline + sidepanel détail à droite)
   ───────────────────────────────────────────────────────────────────────── */
.isis-planner-layout {
    position: relative;
    display: flex;
    flex: 1 1 auto;
    min-height: 0;
    gap: 1rem;
}
.isis-planner-layout .isis-planner-host {
    flex: 1 1 auto;
}
.isis-planner-detail {
    flex: 0 0 360px;
    display: flex;
    flex-direction: column;
    min-height: 0;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: 8px;
    overflow: hidden;
    box-shadow:
        0 12px 28px -8px rgba(15, 23, 42, 0.22),
        0 6px 12px -6px rgba(15, 23, 42, 0.14);
    animation: isis-planner-detail-pop 160ms ease-out;
}
@keyframes isis-planner-detail-pop {
    from { opacity: 0; transform: translateX(8px); }
    to   { opacity: 1; transform: translateX(0); }
}
@media (prefers-reduced-motion: reduce) {
    .isis-planner-detail { animation: none; }
}
@media (max-width: 1100px) {
    /* Viewport étroit : sidepanel passe en bas. */
    .isis-planner-layout { flex-direction: column; }
    .isis-planner-detail { flex: 0 0 auto; max-height: 50vh; }
}

/* Sprint AE V3 — mode plein écran : cache les blocs non-essentiels pour maximiser
   la timeline. La toolbar top reste visible pour exposer le toggle inverse et les
   autres actions (filtres vue, vues, exports). */
.isis-rich-page.is-planner-fullscreen .isis-rich-header,
.isis-rich-page.is-planner-fullscreen .isis-planner-toolbar-merged {
    display: none !important;
}
.isis-rich-page.is-planner-fullscreen .isis-planner-detail {
    /* Le sidepanel est déjà fermé via _selectedEvent=null à l'entrée du mode, mais
       garde-fou si un futur dev oublie le reset côté C#. */
    display: none !important;
}
.isis-rich-page.is-planner-fullscreen .isis-planner-host {
    /* Plus d'espace dispo vertical — le Scheduler autosize via EnableAutoRowHeight. */
    flex: 1 1 auto;
    min-height: 0;
}
.isis-planner-detail__head {
    padding: 0.75rem 0.85rem;
    border-bottom: 1px solid var(--isis-border);
    background: var(--isis-surface-soft);
    border: 1px solid var(--isis-resource-accent, var(--isis-mod-gespla));
    box-sizing: border-box;
    flex-shrink: 0;
}
.isis-planner-detail__title-row {
    display: flex;
    justify-content: space-between;
    align-items: start;
    gap: 0.5rem;
    margin-bottom: 0.5rem;
}
.isis-planner-detail__title {
    margin: 0;
    font-size: 0.95rem;
    font-weight: 600;
    color: var(--isis-text);
    overflow: hidden;
    text-overflow: ellipsis;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
}
.isis-planner-detail__close {
    background: transparent;
    border: 1px solid transparent;
    border-radius: 3px;
    color: var(--isis-text-muted);
    cursor: pointer;
    height: 24px;
    width: 24px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}
.isis-planner-detail__close:hover {
    background: var(--isis-surface);
    border-color: var(--isis-border);
    color: var(--isis-text);
}
.isis-planner-detail__badges {
    display: flex;
    gap: 0.4rem;
    flex-wrap: wrap;
}
.isis-planner-detail__body {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    padding: 0.75rem 0.85rem;
}
.isis-planner-detail__facts {
    display: grid;
    grid-template-columns: 110px 1fr;
    gap: 0.45rem 0.6rem;
    margin: 0;
}
.isis-planner-detail__facts dt {
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--isis-text-muted);
    font-weight: 600;
    align-self: center;
}
.isis-planner-detail__facts dd {
    margin: 0;
    font-size: 0.85rem;
    color: var(--isis-text);
    display: flex;
    align-items: center;
    gap: 0.4rem;
    flex-wrap: wrap;
}
.isis-planner-detail__hint {
    color: var(--isis-text-muted);
    font-size: 0.78rem;
}
.isis-planner-detail__id {
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 0.78rem;
    color: var(--isis-text-muted);
}
.isis-planner-detail__footer {
    padding: 0.6rem 0.85rem;
    border-top: 1px solid var(--isis-border);
    background: var(--isis-surface-soft);
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
    flex-shrink: 0;
}

/* V1.1 — sections sidepanel enrichi */
.isis-planner-detail__section {
    padding: 0.6rem 0;
    border-bottom: 1px solid color-mix(in srgb, var(--isis-border) 60%, transparent);
}
.isis-planner-detail__section:last-of-type {
    border-bottom: none;
}
.isis-planner-detail__section.is-danger {
    background: color-mix(in srgb, var(--isis-danger) 6%, transparent);
    border: 1px solid var(--isis-danger);
    box-sizing: border-box;
    padding-left: 0.6rem;
    margin: 0.4rem -0.85rem 0.4rem -0.85rem;
}
.isis-planner-detail__section.is-info {
    background: color-mix(in srgb, var(--isis-mod-gespla) 5%, transparent);
    border: 1px solid var(--isis-mod-gespla);
    box-sizing: border-box;
    padding-left: 0.6rem;
    margin: 0.4rem -0.85rem 0.4rem -0.85rem;
}
.isis-planner-detail__section.is-meta {
    font-size: 0.78rem;
    opacity: 0.85;
}
.isis-planner-detail__section-title {
    margin: 0 0 0.4rem 0;
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--isis-text-muted);
    font-weight: 600;
}
.isis-planner-detail__ressource {
    display: flex;
    align-items: center;
    gap: 0.6rem;
}
.isis-planner-detail__ressource-name {
    font-size: 0.95rem;
    font-weight: 600;
    color: var(--isis-text);
}
.isis-planner-detail__ressource-type {
    font-size: 0.78rem;
    color: var(--isis-text-muted);
}
.isis-planner-detail__linked {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    font-size: 0.85rem;
    color: var(--isis-text);
    margin-bottom: 0.3rem;
}
.isis-planner-detail__notes {
    margin: 0;
    font-size: 0.85rem;
    color: var(--isis-text);
    white-space: pre-wrap;
    font-style: italic;
}

/* ─────────────────────────────────────────────────────────────────────────
   Sprint Z1 — CandidatePickerDialog : liste candidats scorés pour mobiliser
   une ressource sur un besoin de commande.
   ───────────────────────────────────────────────────────────────────────── */
.isis-candidate-picker {
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
    min-width: 720px;
}
.isis-candidate-picker__loader {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.5rem;
    padding: 2rem 1rem;
    color: var(--isis-text-muted);
}
.isis-candidate-picker__header {
    padding: 0.5rem 0.75rem;
    background: var(--isis-surface-soft);
    border: 1px solid var(--isis-border);
    border-radius: 6px;
}
.isis-candidate-picker__context {
    font-size: 0.9rem;
}
.isis-candidate-picker__hint {
    color: var(--isis-text-muted);
    font-size: 0.82rem;
}
.isis-candidate-picker__filters {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    flex-wrap: wrap;
}
.isis-candidate-picker__filter-label {
    font-size: 0.8rem;
    color: var(--isis-text-muted);
}
.isis-candidate-picker__distance-filter {
    display: flex;
    align-items: center;
    gap: 0.3rem;
}
.isis-candidate-picker__filler {
    flex: 1 1 auto;
}
.isis-candidate-picker__count {
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--isis-text);
}
.isis-candidate-picker__habilitation {
    margin-top: 2px;
    font-size: 0.72rem;
    color: var(--isis-text-muted);
}
.isis-candidate-picker__habilitation ul { margin: 2px 0 0; padding-left: 16px; }
.isis-grid--candidate-picker .isis-grid__action-btn[aria-disabled="true"] {
    opacity: 0.55;
    cursor: not-allowed;
}
.isis-grid--candidate-picker .isis-grid__action-btn[aria-disabled="true"]:hover {
    border-color: var(--isis-border);
}
.isis-grid--candidate-picker {
    --grid-cols: 32px 1fr 70px 70px 80px 80px 44px;
}
.isis-grid--candidate-picker .isis-grid__head,
.isis-grid--candidate-picker .isis-grid__row {
    display: grid;
    grid-template-columns: var(--grid-cols);
    gap: 0.5rem;
    padding: 0.4rem 0.6rem;
    align-items: center;
}
.isis-grid--candidate-picker .isis-grid__head {
    position: sticky;
    top: 0;
    background: var(--isis-surface);
    border-bottom: 1px solid var(--isis-border);
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--isis-text-muted);
    z-index: 1;
}
.isis-grid--candidate-picker .isis-grid__row {
    border-bottom: 1px solid color-mix(in srgb, var(--isis-border) 60%, transparent);
    transition: background 100ms ease;
}
.isis-grid--candidate-picker .isis-grid__row:hover {
    background: color-mix(in srgb, var(--isis-mod-gespla) 6%, var(--isis-surface));
}
.isis-grid--candidate-picker .isis-grid__row.is-disqualified {
    opacity: 0.55;
    background: repeating-linear-gradient(
        135deg,
        transparent 0 6px,
        color-mix(in srgb, var(--isis-danger) 6%, transparent) 6px 8px);
}
.isis-candidate-picker__avatar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    color: #fff;
    font-weight: 700;
    font-size: 0.66rem;
    letter-spacing: 0.02em;
    text-shadow: 0 1px 1px rgba(0, 0, 0, 0.3);
    box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.4) inset;
}
.isis-candidate-picker__avatar.is-collab { border-radius: 50%; }
.isis-candidate-picker__avatar.is-equip  { border-radius: 4px; }
.isis-candidate-picker__name {
    font-weight: 600;
    font-size: 0.85rem;
    color: var(--isis-text);
}
.isis-candidate-picker__missing {
    margin-top: 2px;
    font-size: 0.72rem;
    color: var(--isis-danger);
    display: inline-flex;
    align-items: center;
    gap: 3px;
}
.isis-grid--candidate-picker {
    max-height: 50vh;
    overflow-y: auto;
    border: 1px solid var(--isis-border);
    border-radius: 6px;
}

/* Z2.2 — Mob couplée : section toggle + liste équipements embarqués */
.isis-candidate-picker__coupled {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    padding: 0.5rem 0.75rem;
    background: var(--isis-surface-soft);
    border: 1px solid var(--isis-border);
    border-radius: 6px;
}
.isis-candidate-picker__coupled-list {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
}
.isis-candidate-picker__coupled-item {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.25rem 0.5rem 0.25rem 0.35rem;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: 4px;
    font-size: 0.82rem;
    cursor: pointer;
    transition: background 100ms ease;
}
.isis-candidate-picker__coupled-item:hover {
    background: color-mix(in srgb, var(--isis-mod-gespla) 8%, var(--isis-surface));
}
.isis-candidate-picker__coupled-item.is-disabled {
    opacity: 0.55;
    cursor: not-allowed;
}
.isis-candidate-picker__coupled-item input[type="checkbox"] {
    margin: 0;
}

/* ─────────────────────────────────────────────────────────────────────────
   Sidepanel droit détail + édition inline (Sprint A)
   Sprint N+ — Passage en overlay flottant : ancré en position absolute sur
   .isis-planner-layout (qui porte position:relative), flotte par-dessus la
   timeline sans réduire sa largeur. Ombre marquée pour décollement visuel.
   ───────────────────────────────────────────────────────────────────────── */
.isis-planner-detail {
    position: absolute;
    top: 6px;
    right: 6px;
    bottom: 6px;
    width: 360px;
    z-index: 40;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: 8px;
    box-shadow:
        0 12px 28px -8px rgba(15, 23, 42, 0.22),
        0 6px 12px -6px rgba(15, 23, 42, 0.14);
    display: flex;
    flex-direction: column;
    min-height: 0;
    overflow: hidden;
    /* Apparition fluide */
    animation: isis-planner-detail-pop 160ms ease-out;
}
@keyframes isis-planner-detail-pop {
    from {
        opacity: 0;
        transform: translateX(8px);
    }
    to {
        opacity: 1;
        transform: translateX(0);
    }
}
/* WCAG 2.3.3 — respect prefers-reduced-motion. */
@media (prefers-reduced-motion: reduce) {
    .isis-planner-detail {
        animation: none;
    }
}

/* Point #7 roadmap — sidepanel en mode languette (collapsed).
   Width 44 px, juste un bouton vertical pour réouvrir. Permet de récupérer
   l'espace timeline sans perdre la sélection (clic sur ⏏ pour réouvrir). */
.isis-planner-detail.is-collapsed {
    width: 44px;
    background: var(--isis-surface);
    cursor: pointer;
    box-shadow:
        0 4px 12px -4px rgba(15, 23, 42, 0.18),
        0 2px 6px -3px rgba(15, 23, 42, 0.10);
}
.isis-planner-detail__expand {
    width: 100%;
    height: 100%;
    background: transparent;
    border: none;
    cursor: pointer;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    padding: 0.75rem 0;
    color: var(--isis-mod-gespla);
    transition: background 120ms ease;
}
.isis-planner-detail__expand:hover {
    background: color-mix(in srgb, var(--isis-mod-gespla) 8%, var(--isis-surface));
}
.isis-planner-detail__expand:focus-visible {
    outline: 2px solid var(--isis-mod-gespla);
    outline-offset: -2px;
}
.isis-planner-detail__expand-label {
    writing-mode: vertical-rl;
    transform: rotate(180deg);
    font-size: 0.72rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--isis-text-muted);
}
/* Bouton « réduire » dans le header — calque visuel du bouton close, à sa gauche. */
.isis-planner-detail__collapse {
    background: transparent;
    border: 1px solid transparent;
    border-radius: 3px;
    color: var(--isis-text-muted);
    cursor: pointer;
    height: 24px;
    width: 24px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    margin-right: 2px;
}
.isis-planner-detail__collapse:hover {
    background: var(--isis-surface);
    border-color: var(--isis-border);
    color: var(--isis-text);
}
.isis-planner-detail__collapse:focus-visible {
    outline: 2px solid var(--isis-mod-gespla);
    outline-offset: 1px;
}
@media (max-width: 1100px) {
    /* Viewport étroit : le panel devient full-width overlay en bas du layout. */
    .isis-planner-detail {
        top: auto;
        left: 6px;
        right: 6px;
        bottom: 6px;
        width: auto;
        max-height: 60vh;
    }
}
.isis-planner-detail__head {
    padding: 0.75rem 0.85rem;
    border-bottom: 1px solid var(--isis-border);
    background: var(--isis-surface-soft);
    border: 1px solid var(--isis-mod-gespla);
    box-sizing: border-box;
    flex-shrink: 0;                       /* ne shrink jamais — préserve l'espace du body */
}
.isis-planner-detail__title-row {
    display: flex;
    justify-content: space-between;
    align-items: start;
    gap: 0.5rem;
}
.isis-planner-detail__title {
    margin: 0;
    font-size: 0.95rem;
    font-weight: 600;
    color: var(--isis-text);
    line-height: 1.3;
    word-break: break-word;
}
.isis-planner-detail__close {
    background: transparent;
    border: 1px solid transparent;
    border-radius: 3px;
    color: var(--isis-text-muted);
    cursor: pointer;
    height: 24px;
    width: 24px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}
.isis-planner-detail__close:hover {
    background: var(--isis-surface);
    border-color: var(--isis-border);
    color: var(--isis-text);
}
.isis-planner-detail__close:focus-visible {
    outline: 2px solid var(--isis-mod-gespla);
    outline-offset: 1px;
}
.isis-planner-detail__badges {
    display: flex;
    flex-wrap: wrap;
    gap: 0.35rem;
    margin-top: 0.45rem;
}

.isis-planner-detail__body {
    flex: 1 1 auto;
    min-height: 0;                        /* indispensable pour scroll en flex column */
    overflow-y: auto;
    padding: 0.75rem 0.85rem 0;
}
.isis-planner-detail__section + .isis-planner-detail__section {
    margin-top: 1rem;
    padding-top: 0.75rem;
    border-top: 1px solid var(--isis-border);
}
.isis-planner-detail__section-title {
    margin: 0 0 0.4rem 0;
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--isis-text-muted);
    font-weight: 600;
    display: flex;
    align-items: center;
    gap: 0.35rem;
}
/* Sprint N+ — Section « Équipements embarqués » dans le sidepanel détail */
.isis-planner-detail__count {
    background: color-mix(in srgb, var(--isis-mod-gespla) 14%, var(--isis-surface-soft));
    color: var(--isis-mod-gespla);
    padding: 0 0.4rem;
    border-radius: var(--isis-radius-pill);
    font-size: 0.65rem;
    font-weight: 700;
    line-height: 1.4;
    text-transform: none;
    letter-spacing: 0;
}
.isis-planner-detail__empty {
    margin: 0.2rem 0 0.5rem 0;
    font-size: 0.78rem;
    color: var(--isis-text-muted);
    font-style: italic;
}
.isis-planner-detail__linked-list {
    list-style: none;
    margin: 0 0 0.5rem 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
}
.isis-planner-detail__linked-item {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.35rem 0.5rem;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: 4px;
    font-size: 0.82rem;
}
.isis-planner-detail__linked-label {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--isis-text);
}
.isis-planner-detail__linked-remove {
    flex: 0 0 auto;
    background: transparent;
    border: none;
    cursor: pointer;
    padding: 0.1rem;
    border-radius: 3px;
    color: var(--isis-text-muted);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: background 120ms ease, color 120ms ease;
}
.isis-planner-detail__linked-remove:hover {
    background: color-mix(in srgb, var(--isis-danger) 14%, transparent);
    color: var(--isis-danger);
}
.isis-planner-detail__linked-remove:focus-visible {
    outline: 2px solid var(--isis-danger);
    outline-offset: 1px;
}

.isis-planner-detail__dirty-flag {
    color: var(--isis-warning);
    font-size: 0.9rem;
    line-height: 1;
}

/* Facts liste — clé : valeur */
.isis-planner-detail__facts {
    display: grid;
    grid-template-columns: minmax(80px, 0.7fr) 1fr;
    gap: 0.35rem 0.6rem;
    margin: 0;
    font-size: 0.82rem;
}
.isis-planner-detail__facts dt {
    color: var(--isis-text-muted);
    font-weight: 500;
}
.isis-planner-detail__facts dd {
    margin: 0;
    color: var(--isis-text);
    word-break: break-word;
}
.isis-planner-detail__hint {
    font-size: 0.72rem;
    color: var(--isis-text-muted);
    margin-left: 0.2rem;
}

/* Sprint T C1 — historique des décisions d'approbation (sidepanel planner). */
.isis-planner-detail__approval-steps {
    list-style: none;
    padding: 0;
    margin: 0.5rem 0 0;
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
}
.isis-planner-detail__approval-step {
    border: 1px solid var(--isis-border);
    box-sizing: border-box;
    padding: 0.4rem 0.55rem;
    background: var(--isis-surface-soft);
    border-radius: 4px;
    font-size: 0.78rem;
}
.isis-planner-detail__approval-step.is-pending {
    border-color: var(--isis-warning);
}
.isis-planner-detail__approval-step.is-ok {
    border-color: var(--isis-success);
}
.isis-planner-detail__approval-step.is-danger {
    border-color: var(--isis-danger);
}
.isis-planner-detail__approval-step.is-muted {
    border-color: var(--isis-border);
    opacity: 0.7;
}
.isis-planner-detail__approval-step-head {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 0.5rem;
    margin-bottom: 0.15rem;
}
.isis-planner-detail__approval-step-order {
    font-weight: 600;
    color: var(--isis-text);
}
.isis-planner-detail__approval-step-status {
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--isis-text-muted);
}
.isis-planner-detail__approval-step-validator {
    color: var(--isis-text);
    margin-bottom: 0.15rem;
}
.isis-planner-detail__approval-step-date,
.isis-planner-detail__approval-step-comment {
    font-size: 0.72rem;
    color: var(--isis-text-muted);
}
.isis-planner-detail__approval-step-comment {
    margin-top: 0.2rem;
}

/* Champs édition inline */
.isis-planner-detail__field + .isis-planner-detail__field {
    margin-top: 0.5rem;
}
.isis-planner-detail__label {
    display: block;
    font-size: 0.78rem;
    color: var(--isis-text);
    margin-bottom: 0.2rem;
    font-weight: 500;
}
.isis-planner-detail__inline-actions {
    display: flex;
    justify-content: flex-end;
    gap: 0.4rem;
    margin-top: 0.6rem;
}

.isis-planner-detail__footer {
    padding: 0.6rem 0.85rem;
    border-top: 1px solid var(--isis-border);
    background: var(--isis-surface-soft);
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
    flex-shrink: 0;                       /* le footer garde sa hauteur intrinsèque */
}

/* Mini-toolbar d'actions au-dessus de la timeline quand un bloc est sélectionné. */
.isis-planner-actions-bar {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 1rem;
    padding: 0.55rem 0.85rem;
    background: var(--isis-surface-soft);
    border: 1px solid var(--isis-border);
    border-radius: 6px;
    margin-bottom: 0.5rem;
}
.isis-planner-actions-bar__label {
    font-size: 0.85rem;
    color: var(--isis-text);
}
.isis-planner-actions-bar__buttons {
    display: flex;
    gap: 0.5rem;
}

/* Drop target visuel (palette → bloc) */
.isis-planner-item.isis-planner-item--drop-target {
    outline: 2px dashed var(--isis-mod-gespla);
    outline-offset: 2px;
}

/* Content interne d'un item : label + bouton ⋮ à droite.
   Vis-timeline pose son own wrapper .vis-item-content avec overflow:hidden ;
   on force le flex pour que le bouton ne soit jamais coupé, même si le label
   est plus long que la largeur de l'item. */
.isis-planner-item.vis-item .vis-item-content {
    display: flex;
    align-items: center;
    gap: 4px;
    width: 100%;
    overflow: visible;  /* le bouton ne doit pas être tronqué */
}
.isis-planner-item .isis-planner-item-label {
    flex: 1 1 auto;
    min-width: 0;        /* permet à flex-shrink de réduire le label sous son contenu */
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Sprint N+ — icônes Material Symbols préfixant les blocs timeline ET les
   labels des sous-lanes ressources de la vue Par commande.
   La font « Material Symbols » est fournie par Radzen (cf. material-base.css). */
.isis-planner-item-icon {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-family: 'Material Symbols';
    font-weight: normal;
    font-style: normal;
    font-size: 14px;
    line-height: 1;
    letter-spacing: normal;
    text-transform: none;
    white-space: nowrap;
    direction: ltr;
    font-feature-settings: 'liga';
    -webkit-font-feature-settings: 'liga';
    -webkit-font-smoothing: antialiased;
    font-variation-settings: 'FILL' 1, 'wght' 400, 'GRAD' 0, 'opsz' 20;
    margin-right: 2px;
    vertical-align: middle;
}
.isis-planner-item-icon--collab {
    color: var(--isis-mod-sirh, #16a34a);
}
.isis-planner-item-icon--equip {
    color: var(--isis-mod-gesmat, #44403c);
}
.isis-planner-item-icon--absence {
    color: var(--isis-warning, #d97706);
}
.isis-planner-item-icon--maintenance,
.isis-planner-item-icon--calibration {
    color: var(--isis-mod-gesmat, #44403c);
}
.isis-planner-item-icon--panne {
    color: var(--isis-danger, #dc2626);
}
.isis-planner-item-icon--pret {
    color: var(--isis-accent, #4b5fad);
}
.isis-planner-item-icon--indispo {
    color: var(--isis-text-muted);
}
/* Bouton menu en fin de bloc — flex-shrink:0 garantit qu'il reste visible. */
.isis-planner-item .isis-planner-item-actions-btn {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0 4px;
    height: 18px;
    width: 18px;
    background: rgba(255, 255, 255, 0.55);
    border: 1px solid rgba(0, 0, 0, 0.08);
    border-radius: 3px;
    color: var(--isis-text);
    cursor: pointer;
    line-height: 1;
    /* Désactive complètement le drag pour cet élément — fortifie le stopPropagation
       côté JS. Sans ça certains navigateurs initient un drag-image fantôme. */
    -webkit-user-drag: none;
}
.isis-planner-item .isis-planner-item-actions-btn:hover {
    background: var(--isis-surface);
    border-color: var(--isis-mod-gespla);
}
.isis-planner-item .isis-planner-item-actions-btn:focus-visible {
    outline: 2px solid var(--isis-mod-gespla);
    outline-offset: 1px;
}
.isis-planner-item-actions-btn__glyph {
    font-size: 0.95rem;
    font-weight: 700;
    line-height: 1;
}

/* ─────────────────────────────────────────────────────────────────────────
   Sprint X — Refonte barres de mobilisation (2026-05-21)
   Structure 3-rows dense :
     • meta-top   : état (chip 3 lettres) · durée · charge · demi-journée · menu ⋮
     • title      : icône type + label principal
     • caption    : besoin / prêt / notes (optionnel)
   Container queries dégradent gracieusement quand le bloc est étroit.
   ───────────────────────────────────────────────────────────────────────── */

/* Le wrapper vis-item-content devient stretch en hauteur pour laisser __inner
   occuper toute la cellule. Padding remis à zéro (le __inner gère son padding). */
.isis-planner-item.vis-item .vis-item-content:has(.isis-planner-item__inner) {
    align-items: stretch;
    padding: 0;
}
.isis-planner-item__inner {
    container-type: inline-size;
    container-name: planner-item;
    display: flex;
    flex-direction: column;
    width: 100%;
    height: 100%;
    min-width: 0;
    padding: 3px 6px 4px;
    gap: 2px;
    overflow: hidden;
}

/* Ligne meta-top : chips + métriques + menu ⋮ */
.isis-planner-item__meta-top {
    display: flex;
    align-items: center;
    gap: 4px;
    font-size: 0.66rem;
    line-height: 1;
    color: var(--isis-text-muted);
    white-space: nowrap;
    min-width: 0;
}
.isis-planner-item__meta-spacer {
    flex: 1 1 auto;
    min-width: 4px;
}

/* Chip d'état — 3 lettres, couleur cohérente avec le fond du bloc */
.isis-planner-item__state-chip {
    display: inline-flex;
    align-items: center;
    padding: 1px 4px;
    border-radius: 3px;
    font-size: 0.6rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    line-height: 1.3;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    color: var(--isis-text);
    flex-shrink: 0;
}
.isis-planner-item__state-chip.is-previsionnel {
    background: color-mix(in srgb, var(--isis-warning) 18%, var(--isis-surface));
    border-color: color-mix(in srgb, var(--isis-warning) 50%, transparent);
    color: color-mix(in srgb, var(--isis-warning) 70%, var(--isis-text));
}
.isis-planner-item__state-chip.is-ferme {
    background: color-mix(in srgb, var(--isis-mod-gespla) 20%, var(--isis-surface));
    border-color: color-mix(in srgb, var(--isis-mod-gespla) 55%, transparent);
    color: color-mix(in srgb, var(--isis-mod-gespla) 80%, var(--isis-text));
}
.isis-planner-item__state-chip.is-realise {
    background: var(--isis-surface-soft);
    border-color: color-mix(in srgb, var(--isis-success, #16a34a) 40%, transparent);
    color: var(--isis-success, #16a34a);
}
.isis-planner-item__state-chip.is-annule {
    background: var(--isis-surface);
    border-color: var(--isis-border);
    color: var(--isis-danger, #dc2626);
    text-decoration: line-through;
}

/* Métriques durée + charge — monospace tabular-nums pour alignement */
.isis-planner-item__duration,
.isis-planner-item__charge {
    font-variant-numeric: tabular-nums;
    font-weight: 600;
    color: var(--isis-text);
    flex-shrink: 0;
}

/* Chip demi-journée — couleur accent secondaire, visible uniquement si != FULL/FULL */
.isis-planner-item__half-chip {
    display: inline-flex;
    align-items: center;
    padding: 1px 4px;
    border-radius: 3px;
    font-size: 0.58rem;
    font-weight: 700;
    background: color-mix(in srgb, var(--isis-accent) 14%, var(--isis-surface));
    color: var(--isis-accent);
    border: 1px solid color-mix(in srgb, var(--isis-accent) 32%, transparent);
    flex-shrink: 0;
    line-height: 1.3;
}

/* Ligne titre — icône type + libellé principal */
.isis-planner-item__title {
    display: flex;
    align-items: center;
    gap: 4px;
    font-weight: 600;
    font-size: 0.78rem;
    line-height: 1.2;
    min-width: 0;
}
.isis-planner-item__title .isis-planner-item-icon {
    /* On garde la taille standard mais sans le margin-right hérité — on a gap parent */
    margin-right: 0;
}
.isis-planner-item__title-text {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.isis-planner-item__linked-mark {
    color: var(--isis-text-muted);
    margin-right: 1px;
}

/* Ligne caption — besoin / prêt / notes — un seul des 3 affiché */
.isis-planner-item__caption {
    display: flex;
    align-items: center;
    gap: 4px;
    font-size: 0.7rem;
    line-height: 1.2;
    color: var(--isis-text-muted);
    min-width: 0;
}
.isis-planner-item__caption > span:last-child {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.isis-planner-item__caption-icon {
    font-size: 0.9rem !important;       /* override .isis-planner-item-icon font-size: 14px */
    flex: 0 0 auto;
    margin-right: 0;
}
.isis-planner-item__caption.is-besoin .isis-planner-item__caption-icon {
    color: var(--isis-mod-gespla);
}
.isis-planner-item__caption.is-pret {
    font-weight: 600;
    color: var(--isis-text);
}
.isis-planner-item__caption.is-pret .isis-planner-item__caption-icon {
    color: var(--isis-accent);
}
.isis-planner-item__caption.is-notes {
    font-style: italic;
}

/* Bouton menu ⋮ dans meta-top : surcharge le margin/positionnement legacy */
.isis-planner-item__meta-top .isis-planner-item-actions-btn {
    height: 16px;
    width: 16px;
    padding: 0 2px;
}

/* ─── Dégradation graceful via container queries ─────────────────────────── */
@container planner-item (max-width: 200px) {
    .isis-planner-item__caption.is-notes { display: none; }
}
@container planner-item (max-width: 160px) {
    .isis-planner-item__caption { display: none; }
}
@container planner-item (max-width: 130px) {
    /* Bloc moyen : retire les métriques numériques (état + half + menu suffisent) */
    .isis-planner-item__duration,
    .isis-planner-item__charge { display: none; }
}
@container planner-item (max-width: 90px) {
    /* Bloc court : seul l'état + icône type + menu restent */
    .isis-planner-item__half-chip { display: none; }
    .isis-planner-item__title-text { display: none; }
}
@container planner-item (max-width: 56px) {
    /* Bloc minimal (~1 jour zoomé) : seuls l'icône et menu restent */
    .isis-planner-item__state-chip { display: none; }
}

/* Hauteur minimale du bloc — vis-timeline groupHeightMode=fitItems respecte */
.isis-planner-item__inner {
    min-height: 38px;
}

/* Annule l'override historique « padding: 18px » de --realise sur les blocs riches */
.isis-planner-item--realise:has(.isis-planner-item__inner) {
    padding-left: 0;
}
.isis-planner-item--realise:has(.isis-planner-item__inner)::before {
    display: none;                       /* l'état est désormais porté par le chip __state-chip */
}

/* ─────────────────────────────────────────────────────────────────────────
   Sprint X — Avatar initiales coloré stable par ressource
   Forme ronde pour collab / carré arrondi pour équipement.
   Couleur de fond = hue stable hashé sur l'id (ResourceAccentColor côté C#).
   Texte blanc avec léger text-shadow pour contraste sur fond mid-tone.
   ───────────────────────────────────────────────────────────────────────── */
.isis-planner-avatar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    color: #fff;
    font-weight: 700;
    line-height: 1;
    letter-spacing: 0.02em;
    user-select: none;
    text-shadow: 0 1px 1px rgba(0, 0, 0, 0.3);
    box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.4) inset;
}
.isis-planner-avatar--collab {
    border-radius: 50%;                  /* rond pour personne */
}
.isis-planner-avatar--equip {
    border-radius: 4px;                  /* carré arrondi pour équipement */
}

/* Taille « lane » : label à gauche de chaque sous-lane ressource — bien lisible */
.isis-planner-avatar--lane {
    width: 28px;
    height: 28px;
    font-size: 0.82rem;                  /* ~13px sur les 28px du cercle */
    margin-right: 8px;
}

/* Taille « inline » : titre de chaque barre de mobilisation — compact mais lisible */
.isis-planner-avatar--inline {
    width: 20px;
    height: 20px;
    font-size: 0.7rem;                   /* ~11px sur les 20px du cercle */
}

/* Wrapper du label de lane — aligne l'avatar + nom horizontalement */
.isis-planner-group__label {
    display: inline-flex;
    align-items: center;
    gap: 0;                              /* margin-right géré par l'avatar */
    min-width: 0;
    max-width: 100%;
}
.isis-planner-group__name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
}

/* Dans le bloc, le titre passe en padding-gauche un peu réduit pour caser l'avatar */
.isis-planner-item__title .isis-planner-avatar--inline {
    margin-right: 0;                     /* gap parent gère l'espacement */
}

/* En conteneur < 90px, l'avatar de la barre est masqué (déjà via container query
   parente qui cache title-text, mais on garde l'avatar) — décision : l'avatar
   reste affiché tant qu'il y a au moins 56px de large car c'est l'élément le
   plus distinctif. Override de la règle title-text:none pour préserver l'avatar : */
@container planner-item (max-width: 90px) {
    .isis-planner-item__title .isis-planner-avatar--inline {
        display: inline-flex;            /* reste visible (override flexbox) */
    }
}

/* Hint sous-titre du bandeau de sélection. */
.isis-planner-actions-bar__hint {
    font-size: 0.78rem;
    color: var(--isis-text-muted);
    font-style: italic;
}
.isis-planner-actions-bar__hint kbd {
    display: inline-block;
    padding: 0 0.35rem;
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-style: normal;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-bottom-width: 2px;
    border-radius: 3px;
    font-size: 0.85rem;
}
/* RÈGLES ACTIVES du planner V3 Syncfusion (PAS du legacy V2 vis-timeline, supprimé) :
   .isis-planner-item et ses variantes (--mobilisation, .is-en-attente, --a-detailler,
   .isis-nature-previ-cmd/offre) sont posées via le <Template> du ScheduleEventSettings sur
   itemCls (PlannerV3Page.razor). Ne pas supprimer en croyant à du mort-code vis-timeline. */
.isis-planner-item {
    border: 1px solid transparent;
    border-radius: 4px;
    padding: 2px 6px;
    font-size: 0.78rem;
    line-height: 1.2;
    color: var(--isis-text);
    background: var(--isis-surface-soft);
    box-shadow: 0 1px 0 0 rgba(0, 0, 0, 0.04);
}
.isis-planner-item.vis-item.vis-selected {
    outline: 2px solid var(--isis-mod-gespla);
    outline-offset: 1px;
}
/* États */
.isis-planner-item--previsionnel {
    background: color-mix(in srgb, var(--isis-warning) 16%, var(--isis-surface));
    border-color: color-mix(in srgb, var(--isis-warning) 30%, transparent);
    background-image: repeating-linear-gradient(
        135deg,
        transparent 0 6px,
        rgba(0, 0, 0, 0.05) 6px 8px);
}
.isis-planner-item--ferme {
    background: color-mix(in srgb, var(--isis-mod-gespla) 18%, var(--isis-surface));
    border-color: color-mix(in srgb, var(--isis-mod-gespla) 38%, transparent);
}
.isis-planner-item--realise {
    background: var(--isis-surface-soft);
    border-color: var(--isis-border);
    color: var(--isis-text-muted);
}
.isis-planner-item--annule {
    opacity: 0.5;
    text-decoration: line-through;
}
/* 2026-07-03 — fusion mobilisations gesproj : bloc plein bord gauche épais (vérité opérationnelle). */
.isis-planner-item--mobilisation {
    border-left: 4px solid var(--isis-mod-gesproj);
}
/* 2026-07-04 « mobilisation hors périmètre → validation » — demande EN_ATTENTE :
   hachures discrètes + puce « En attente ». Distingue une demande non tranchée d'une
   mobilisation active sans la masquer. */
.isis-planner-item.is-en-attente {
    background-image: repeating-linear-gradient(45deg, transparent, transparent 6px, color-mix(in srgb, var(--isis-text) 8%, transparent) 6px, color-mix(in srgb, var(--isis-text) 8%, transparent) 12px);
}
.isis-planner-item__pending {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    padding: 0 5px;
    border-radius: 999px;
    font-size: 0.62rem;
    font-weight: 600;
    line-height: 1.5;
    color: var(--isis-warning);
    background: var(--isis-warning-soft);
}
.isis-planner-item__pending .rzi {
    font-size: 12px;
}

/* 2026-07-27 — matériel engagé en lane fille (spec « planner mobilisations seules »).
   Bouton de dépliage porté par le bloc de mobilisation. */
.isis-planner-item__kit {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    margin-left: auto;
    padding: 0 4px;
    border: 0;
    border-radius: 3px;
    font: inherit;
    font-size: 0.62rem;
    font-weight: 650;
    line-height: 1.5;
    /* Audit a11y : encre PLEINE, pas `--isis-text-muted`. À 9,9 px le seuil AA est 4.5:1, or
       muted (#475569) sur ce fond teinté nature ne donnait que ~4,1:1. Contre-sens à éviter :
       foncer le fond (8 % → 12 %) mélange plus d'encre sombre DANS le fond et dégrade encore
       le rapport — c'est le texte qu'il faut assombrir. */
    color: var(--isis-text);
    background: color-mix(in oklab, var(--isis-text) 8%, transparent);
    cursor: pointer;
    position: relative;
}
/* Cible de pointeur élargie sans toucher à la mise en page (le bloc est dense).
   WCAG 2.5.5 (AAA) demande 44 px : hors périmètre AA, mais 15 px de haut reste sévère
   au doigt ou en cas de tremblement. */
.isis-planner-item__kit::before {
    content: "";
    position: absolute;
    inset: -5px -3px;
}
.isis-planner-item__kit:hover {
    background: color-mix(in oklab, var(--isis-text) 15%, transparent);
}
.isis-planner-item__kit:focus-visible {
    outline: 2px solid var(--isis-current-mod, var(--isis-accent));
    outline-offset: 1px;
}
.isis-planner-item__kit .rzi {
    font-size: 12px;
    transition: transform 0.18s ease;
}
.isis-planner-item__kit.is-open .rzi {
    transform: rotate(90deg);
}
@media (prefers-reduced-motion: reduce) {
    .isis-planner-item__kit .rzi { transition: none; }
}

/* En-tête de la lane fille : indentée + rail vertical, pour se lire comme subordonnée
   à la mobilisation qui la précède. */
/* Filet périmétrique + fond teinté (DESIGN.md §1) plutôt qu'un liseré épais : la
   subordination se lit par l'indentation, la teinte et l'icône, pas par un trait. */
.isis-planner-lane--kit {
    display: flex;
    align-items: center;
    gap: 6px;
    padding-left: 20px;
    position: relative;
    color: var(--isis-text-muted);
    font-size: var(--isis-fs-sm);
    background: color-mix(in oklab, var(--isis-mod-gespla) 5%, transparent);
}
.isis-planner-lane--kit::before {
    content: "";
    position: absolute;
    left: 10px;
    top: 0;
    bottom: 0;
    border-left: 1px solid color-mix(in oklab, var(--isis-mod-gespla) 40%, transparent);
}
.isis-planner-lane--kit .isis-planner-lane__name {
    color: var(--isis-text-muted);
    font-weight: 450;
}
/* Affectation COMMANDE×collab survivante (aucune mobilisation) : « à détailler » — pointillés. */
.isis-planner-item--a-detailler {
    border: 1.5px dashed color-mix(in oklab, var(--isis-current-mod) 55%, transparent);
    opacity: 0.92;
}

/* EF-114 — barre prise dans la sélection multiple (Ctrl/Cmd+clic). Anneau, pas outline : l'outline
   porte déjà la nature prévisionnelle. Le libellé accessible dit « sélectionné ». */
.isis-planner-item.is-multi-selected {
    box-shadow: 0 0 0 2px var(--isis-surface), 0 0 0 4px var(--isis-current-mod);
}
.isis-planner-bulkbar {
    position: absolute;
    left: 50%;
    bottom: var(--isis-space-md);
    transform: translateX(-50%);
    z-index: 20;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--isis-space-sm);
    max-width: calc(100% - 2 * var(--isis-space-md));
    padding: var(--isis-space-xs) var(--isis-space-sm);
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius);
    box-shadow: var(--isis-elevation-2);
}
.isis-planner-bulkbar__count {
    font-weight: 600;
    color: var(--isis-text);
    padding-inline: var(--isis-space-xs);
}
.isis-planner-bulkbar__shift {
    display: inline-flex;
    align-items: center;
    gap: var(--isis-space-xs);
}

/* EF-112 — palette des besoins à couvrir (même cadre que le panneau de détail). */
.isis-planner-besoins__hint,
.isis-planner-besoins__empty {
    margin: var(--isis-space-xs) 0 0;
    color: var(--isis-text-muted);
    font-size: 0.8rem;
}
.isis-planner-besoins__list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: var(--isis-space-xs);
}
.isis-planner-besoin {
    display: flex;
    align-items: center;
    gap: var(--isis-space-xs);
    padding: var(--isis-space-xs) var(--isis-space-sm);
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius);
    cursor: grab;
}
.isis-planner-besoin:hover { box-shadow: var(--isis-elevation-hover); }
.isis-planner-besoin:active { cursor: grabbing; }
.isis-planner-besoin__grip { color: var(--isis-text-muted); flex: 0 0 auto; }
.isis-planner-besoin__main {
    display: flex;
    flex-direction: column;
    min-width: 0;
    flex: 1 1 auto;
}
.isis-planner-besoin__profil {
    font-weight: 600;
    color: var(--isis-text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.isis-planner-besoin__meta {
    font-size: 0.75rem;
    color: var(--isis-text-muted);
}

/* EF-113 — annonce de conflit pendant le glisser, en haut du planner. Le conteneur reste dans
   le DOM (vide) pour que la région live soit connue des lecteurs d'écran avant l'annonce. */
.isis-planner-dragwarn {
    position: absolute;
    left: 50%;
    top: var(--isis-space-md);
    transform: translateX(-50%);
    z-index: 21;
    display: inline-flex;
    align-items: center;
    gap: var(--isis-space-xs);
    max-width: calc(100% - 2 * var(--isis-space-md));
    padding: var(--isis-space-xs) var(--isis-space-sm);
    background: var(--isis-warning-soft);
    color: var(--isis-warning-text);
    border: 1px solid var(--isis-warning);
    border-radius: var(--isis-radius);
    box-shadow: var(--isis-elevation-2);
    font-weight: 600;
    pointer-events: none;
}
.isis-planner-dragwarn.is-empty {
    padding: 0;
    border: 0;
    box-shadow: none;
    background: transparent;
}

/* Natures de mobilisation prévisionnelle : liseré « non ferme » (marqueur non color-only). */
/* Une seule teinte « non ferme » (ambre sémantique, cohérent avec .is-previsionnel), hors des teintes
   module déjà saturées sur le planner ; dashed = prévi-commande, dotted = prévi-offre (audit ui-ux). */
.isis-nature-previ-cmd,
.isis-nature-previ-offre {
    outline-width: 2px;
    outline-offset: -2px;
    outline-color: color-mix(in srgb, var(--isis-warning, #8f5700) 80%, transparent);
}
.isis-nature-previ-cmd   { outline-style: dashed; }
.isis-nature-previ-offre { outline-style: dotted; }

/* Sprint S B5 — baseline planifié vs réalisé : marqueur check sur les REALISE.
   Permet de visualiser d'un coup d'œil quelles affectations ont effectivement été
   exécutées (la mob garde ses dates planifiées, mais l'état change). */
.isis-planner-item--realise::before {
    content: "task_alt";
    font-family: 'Material Symbols';
    font-variation-settings: 'FILL' 1, 'wght' 600, 'GRAD' 0, 'opsz' 20;
    position: absolute;
    top: 1px;
    left: 4px;
    color: var(--isis-success, #16a34a);
    font-size: 12px;
    line-height: 1;
    pointer-events: none;
    text-shadow: 0 0 2px color-mix(in srgb, var(--isis-surface) 80%, transparent);
}
.isis-planner-item--realise {
    padding-left: 18px; /* laisse la place pour l'icône ::before */
    position: relative;
}

/* Sprint O B2 — accent couleur par commande source en vue Par ressource.
   Le service pose --isis-source-accent: hsl(N, 55%, 78%) en style inline.
   On l'utilise comme : (a) bordure gauche 3px solid, (b) léger halo de fond
   en color-mix avec la couleur d'état FERME (pour ne pas masquer l'info état).
   PRÉVISIONNEL garde son hachuré + accent à gauche.
   ANNULÉ ignore (opacité 0.5 prédomine). */
.isis-planner-item--source-accent {
    border-left: 3px solid var(--isis-source-accent, transparent);
}
.isis-planner-item--ferme.isis-planner-item--source-accent {
    /* Fond mixé : accent source 70% + état ferme gespla 30% pour cohérence visuelle */
    background: color-mix(in srgb, var(--isis-source-accent, transparent) 50%, var(--isis-surface));
    border-color: color-mix(in srgb, var(--isis-source-accent, transparent) 65%, transparent);
}
.isis-planner-item--realise.isis-planner-item--source-accent {
    border-left-color: color-mix(in srgb, var(--isis-source-accent, transparent) 60%, var(--isis-text-muted));
}

/* Sprint P — filter-bar dédiée à la timeline planner. Compacte verticalement
   (les axes + search s'aligne sur une ligne quand l'écran est large). */
.isis-planner-filter-bar {
    margin-bottom: 0.5rem;
    padding: 0.4rem 0.7rem;
    font-size: 0.78rem;
}
.isis-planner-filter-bar .isis-filter-bar__search {
    flex: 1 1 220px;
    min-width: 200px;
}

/* Sprint P A2 — barre d'actions en masse au-dessus du planner. */
.isis-alert-banner--info {
    background: color-mix(in srgb, var(--isis-accent) 8%, var(--isis-surface));
    border: 1px solid color-mix(in srgb, var(--isis-accent) 35%, transparent);
    color: var(--isis-text);
    padding: 0.55rem 0.85rem;
    border-radius: var(--isis-radius);
    margin-bottom: 0.5rem;
    font-size: 0.85rem;
}
.isis-bulk-bar {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.5rem;
}
.isis-bulk-bar__hint {
    color: var(--isis-text-muted);
    font-size: 0.8rem;
    margin-right: 0.5rem;
}
.isis-bulk-bar__actions {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    margin-left: auto;
    flex-wrap: wrap;
}

/* Sprint T F3 — print-friendly du planner V2.
   Masque la palette, le sidepanel détail et la toolbar, élargit la timeline.
   Le rendu vis-timeline reste tel quel (SVG/canvas) mais sur fond blanc sans ombres. */
@media print {
    .isis-planner-palette,
    .isis-planner-detail,
    .isis-rich-toolbar,
    .isis-planner-filter-bar,
    .isis-bulk-bar {
        display: none !important;
    }
    .isis-planner-layout,
    .isis-planner-layout.has-detail {
        grid-template-columns: 1fr !important;
    }
    .isis-rich-header {
        box-shadow: none !important;
        border: 1px solid var(--isis-border);
        page-break-after: avoid;
    }
    .isis-planner-host {
        box-shadow: none !important;
        page-break-inside: avoid;
    }
}

/* Sprint S D2 — badge pic de charge sur lane ressource. */
.isis-planner-group__peak-badge {
    margin-left: 6px;
    padding: 1px 6px;
    border-radius: var(--isis-radius-pill);
    font-size: 0.65em;
    font-weight: 700;
    letter-spacing: 0.02em;
    vertical-align: middle;
    white-space: nowrap;
}
.isis-planner-group__peak-badge.is-ok {
    background: color-mix(in srgb, var(--isis-success, #16a34a) 14%, transparent);
    color: color-mix(in srgb, var(--isis-success, #16a34a) 80%, var(--isis-text));
}
.isis-planner-group__peak-badge.is-warning {
    background: color-mix(in srgb, var(--isis-warning, #d97706) 18%, transparent);
    color: color-mix(in srgb, var(--isis-warning, #d97706) 80%, var(--isis-text));
}
.isis-planner-group__peak-badge.is-danger {
    background: color-mix(in srgb, var(--isis-danger, #dc2626) 18%, transparent);
    color: var(--isis-danger, #dc2626);
}

/* Sprint U H2 V1.1b — badge cible objectif annuel sur les lanes du planner.
   Position : à droite du peak badge (s'il existe), même style compact pill.
   Variantes : is-neutral / is-ontrack / is-near / is-under / is-over. */
.isis-planner-group__objective-badge {
    margin-left: 4px;
    padding: 1px 6px;
    border-radius: var(--isis-radius-pill);
    font-size: 0.65em;
    font-weight: 600;
    letter-spacing: 0.02em;
    vertical-align: middle;
    white-space: nowrap;
    border: 1px solid transparent;
}
.isis-planner-group__objective-badge.is-neutral {
    background: var(--isis-surface-soft);
    color: var(--isis-text-muted);
    border-color: var(--isis-border);
}
.isis-planner-group__objective-badge.is-ontrack {
    background: color-mix(in srgb, var(--isis-success, #16a34a) 12%, transparent);
    color: color-mix(in srgb, var(--isis-success, #16a34a) 80%, var(--isis-text));
}
.isis-planner-group__objective-badge.is-near {
    background: var(--isis-surface-soft);
    color: var(--isis-text);
    border-color: color-mix(in srgb, var(--isis-warning, #d97706) 40%, var(--isis-border));
}
.isis-planner-group__objective-badge.is-under {
    background: color-mix(in srgb, var(--isis-warning, #d97706) 14%, transparent);
    color: color-mix(in srgb, var(--isis-warning, #d97706) 80%, var(--isis-text));
}
.isis-planner-group__objective-badge.is-over {
    background: color-mix(in srgb, var(--isis-danger, #dc2626) 14%, transparent);
    color: var(--isis-danger, #dc2626);
    border-color: color-mix(in srgb, var(--isis-danger, #dc2626) 30%, var(--isis-border));
}

/* Sprint O B1 — distinction temporelle passé / présent / futur :
   1) Background item passé en gris léger (couvre [periodStart, hier]) ;
   2) Ligne « aujourd'hui » accentuée (recolore le .vis-current-time natif). */
.isis-planner-host .vis-item.isis-planner-past-overlay {
    background: color-mix(in srgb, var(--isis-text-muted) 8%, transparent);
    border: none;
    pointer-events: none;
}
.isis-planner-host .vis-current-time {
    background-color: var(--isis-accent) !important;
    width: 2px;
    box-shadow: 0 0 8px color-mix(in srgb, var(--isis-accent) 35%, transparent);
}

/* Sprint N — mob enfant matériel liée à une mob collab parente.
   Bordure gauche pointillée pour signaler la dépendance + opacité légère. */
.isis-planner-item--linked {
    border-left: 2px dashed color-mix(in srgb, var(--isis-mod-gespla) 55%, transparent);
    opacity: 0.85;
    /* Pas de cursor pointer car non-éditable (set via editable:false) — vis-timeline
       gère le cursor default natif. */
}
.isis-planner-item--linked:hover {
    opacity: 1;
}
.isis-planner-item--linked .isis-planner-item-actions-btn {
    display: none;   /* défensif : pas de bouton même si le HTML en porte un */
}

/* Sprint N+ — item miroir : reflet d'une mob équipement enfant affiché sur la
   lane du collab parent (vue par ressource). Read-only, distingué visuellement
   par une bordure pointillée gauche (couleur module gesmat) + fond rayé léger.
   Empile au-dessous ou à côté de la mob collab parente selon la lib de stacking. */
.isis-planner-item--mirror {
    border-left: 3px dashed color-mix(in srgb, var(--isis-mod-gesmat, var(--isis-text-muted)) 70%, transparent);
    background-image: repeating-linear-gradient(
        45deg,
        transparent,
        transparent 6px,
        color-mix(in srgb, var(--isis-mod-gesmat, var(--isis-text-muted)) 10%, transparent) 6px,
        color-mix(in srgb, var(--isis-mod-gesmat, var(--isis-text-muted)) 10%, transparent) 8px
    );
    opacity: 0.78;
    cursor: default;
}
.isis-planner-item--mirror:hover {
    opacity: 1;
}
.isis-planner-item--mirror .isis-planner-item-actions-btn {
    display: none;
}
.isis-planner-mirror-label {
    font-size: 0.78em;
    font-style: italic;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
/* Badge « lié » suffixant le label miroir — signal explicite francophone
   que cet item est un reflet, non éditable directement (l'édition passe
   par la mob collab parente). */
.isis-planner-mirror-badge {
    margin-left: 4px;
    padding: 1px 5px;
    font-size: 0.6em;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: color-mix(in srgb, var(--isis-mod-gesmat, var(--isis-text-muted)) 80%, var(--isis-text));
    background: color-mix(in srgb, var(--isis-mod-gesmat, var(--isis-text-muted)) 16%, transparent);
    border-radius: 2px;
    vertical-align: middle;
}

/* Affectation en conflit DÉJÀ commitée (state FERME chevauché par une autre FERME
   sur ressource non-partageable, OU sur-allocation collab > 100%). État durable qui
   signale visuellement le problème à résoudre. Bordure rouge dashed + label « CONFLIT »
   via pseudo-element pour ne pas dépendre du content HTML.
   (Cleanup 2026-05-22 : la classe transitoire `.isis-planner-item--conflict-preview`
   et son keyframe `@isis-planner-conflict-pulse` ont été supprimés avec la bascule V3
   — plus aucun code applicatif ne les utilisait.) */
.isis-planner-item--conflict {
    outline: 2px dashed var(--isis-danger);
    outline-offset: -1px;
    background-image: repeating-linear-gradient(
        135deg,
        transparent,
        transparent 8px,
        color-mix(in srgb, var(--isis-danger) 14%, transparent) 8px,
        color-mix(in srgb, var(--isis-danger) 14%, transparent) 10px
    );
    position: relative;
}
.isis-planner-item--conflict::after {
    /* Material Symbols ligature « warning » — pas d'emoji (DESIGN.md §10).
       Cohérent avec les autres pseudo-icônes du codebase. */
    content: "warning";
    font-family: 'Material Symbols';
    font-variation-settings: 'FILL' 1, 'wght' 700, 'GRAD' 0, 'opsz' 20;
    position: absolute;
    top: 1px;
    right: 4px;
    color: var(--isis-danger);
    font-size: 12px;
    line-height: 1;
    pointer-events: none;
    text-shadow: 0 0 2px color-mix(in srgb, var(--isis-surface) 80%, transparent);
}
/* ─── Sprint C : bandes capacité (background items vis-timeline) ─────────
   Items type='background' affichés derrière les blocs affectation dans
   la lane parente. Niveaux : warning 80-100%, danger >100%. */
.isis-planner-cap {
    border: none;
    box-shadow: none;
    /* vis-timeline pose .vis-item-overflow + background sur ces items.
       On colorise via le pseudo-fond (couleur très douce). */
}
.isis-planner-cap--warning {
    background: color-mix(in srgb, var(--isis-warning) 14%, transparent);
}
.isis-planner-cap--danger {
    background: color-mix(in srgb, var(--isis-danger) 18%, transparent);
    /* Hachures discrètes pour renforcer le signal danger même daltonien. */
    background-image:
        color-mix(in srgb, var(--isis-danger) 18%, transparent),
        repeating-linear-gradient(
            45deg,
            transparent 0 5px,
            color-mix(in srgb, var(--isis-danger) 10%, transparent) 5px 7px);
}

/* ─── Sprint B : overlays read-only (absences SIRH + indispos GESMAT) ───── */
.isis-planner-item--indispo {
    background: repeating-linear-gradient(
        135deg,
        color-mix(in srgb, var(--isis-text-muted) 18%, var(--isis-surface)) 0 4px,
        color-mix(in srgb, var(--isis-text-muted) 28%, var(--isis-surface)) 4px 8px
    );
    color: var(--isis-text);
    border: 1px dashed var(--isis-text-muted);
    cursor: not-allowed;
    opacity: 0.85;
}
.isis-planner-item--indispo .isis-planner-item-label {
    font-style: italic;
    color: var(--isis-text-muted);
}
.isis-planner-item--indispo .isis-planner-item-actions-btn {
    display: none;   /* pas de menu d'actions sur les overlays read-only */
}
.isis-planner-item--indispo:hover {
    /* léger lift pour signaler que c'est cliquable pour info (tooltip) */
    opacity: 1;
}

/* Variantes selon le type d'indispo gesmat — bordure colorée par sémantique. */
.isis-planner-item--indispo-absence {
    border-color: color-mix(in srgb, var(--isis-mod-sirh, var(--isis-text-muted)) 55%, transparent);
}
.isis-planner-item--indispo-equip {
    border-color: color-mix(in srgb, var(--isis-mod-gesmat, var(--isis-text-muted)) 55%, transparent);
}
.isis-planner-item--indispo-panne,
.isis-planner-item--indispo-maintenance_corrective {
    border-color: color-mix(in srgb, var(--isis-danger) 55%, transparent);
}
.isis-planner-item--indispo-calibration {
    border-color: color-mix(in srgb, var(--isis-warning) 60%, transparent);
}
/* Groupes — labels à gauche */
.isis-planner-group.vis-label {
    font-size: 0.82rem;
}
.isis-planner-group--ent.vis-label {
    font-weight: 700;
    background: var(--isis-surface-soft);
    color: var(--isis-text);
    text-transform: uppercase;
    letter-spacing: 0.03em;
    font-size: 0.72rem;
}
.isis-planner-group--collab.vis-label,
.isis-planner-group--equip.vis-label {
    padding: 6px 8px 6px 10px;
    color: var(--isis-text);
    /* Sprint X — bordure colorée stable par ressource. La couleur de fond est
       posée dynamiquement par PlannerV2Page (un <style> injecté avec 1 règle par
       ressource visible). Fallback border si --lane-accent absent. */
    border-left: 4px solid var(--lane-accent, var(--isis-text-muted));
    border-bottom: 1px solid var(--isis-border);
    box-sizing: border-box;
    transition: background 120ms ease;
}

/* Séparateur horizontal entre lanes côté zone items pour matcher le border-bottom
   du label et bien isoler chaque ligne (synchro visuelle gauche/droite). */
.vis-foreground .vis-group {
    border-bottom: 1px solid color-mix(in srgb, var(--isis-border) 60%, transparent);
}

/* Vue Par commande (nested) — lane parent = commande. */
.isis-planner-group--cmd.vis-label {
    font-weight: 600;
    background: var(--isis-surface-soft);
    border-left: 3px solid var(--isis-mod-gespla);
}
/* Différenciation ferme vs prévisionnelle (Sprint N+ : la vue couvre les 2). */
.isis-planner-group--cmd-ferme.vis-label {
    border-left: 3px solid var(--isis-success, #16a34a);
    background: color-mix(in srgb, var(--isis-success, #16a34a) 6%, var(--isis-surface-soft));
}
.isis-planner-group--cmd-previsionnelle.vis-label {
    border-left: 3px dashed var(--isis-warning, #d97706);
    background: color-mix(in srgb, var(--isis-warning, #d97706) 5%, var(--isis-surface-soft));
}
/* Badge ferme/prév. injecté dans le content du group commande */
.isis-planner-group__kind-badge {
    display: inline-block;
    padding: 1px 6px;
    border-radius: 3px;
    font-size: 0.62rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    margin-right: 4px;
    vertical-align: middle;
    line-height: 1.3;
}
.isis-planner-group__kind-badge--ferme {
    background: color-mix(in srgb, var(--isis-success, #16a34a) 18%, transparent);
    color: var(--isis-success, #16a34a);
    border: 1px solid color-mix(in srgb, var(--isis-success, #16a34a) 35%, transparent);
}
.isis-planner-group__kind-badge--prev {
    background: color-mix(in srgb, var(--isis-warning, #d97706) 16%, transparent);
    color: color-mix(in srgb, var(--isis-warning, #d97706) 75%, var(--isis-text));
    border: 1px dashed color-mix(in srgb, var(--isis-warning, #d97706) 50%, transparent);
}
/* Sous-lane = ressource mobilisée sous une commande.
   Sprint N+ : indentation accentuée + caret hiérarchique + icône typée
   pour que la colonne label se lise clairement comme « commande → ressource » */
.isis-planner-group--res.vis-label {
    padding-left: 2.2rem !important;
    font-size: 0.8rem;
    color: var(--isis-text-muted);
    background: color-mix(in srgb, var(--isis-text-muted) 4%, transparent);
}
.isis-planner-group--res-collab.vis-label {
    border-left: 2px solid color-mix(in srgb, var(--isis-mod-sirh, var(--isis-text-muted)) 50%, transparent);
}
.isis-planner-group--res-equip.vis-label {
    border-left: 2px solid color-mix(in srgb, var(--isis-mod-gesmat, var(--isis-text-muted)) 50%, transparent);
}
.isis-planner-group__sub-caret {
    color: var(--isis-text-muted);
    opacity: 0.55;
    margin-right: 4px;
    font-family: monospace;
    font-size: 0.85em;
    letter-spacing: -1px;
}
.isis-planner-group__sub-label {
    font-weight: 500;
    color: var(--isis-text);
}
/* L'icône Material Symbols dans la sous-lane utilise les variantes définies plus haut
   (.isis-planner-item-icon--collab / --equip). Pas de redéfinition ici. */
.isis-planner-group--res.vis-label .isis-planner-item-icon {
    font-size: 13px;
    margin-right: 4px;
    vertical-align: middle;
}

/* ──────────────────────────────────────────────────────────────────────────
   Sprint I — Vue calendrier mensuel gespla (/gespla/calendrier)
   ────────────────────────────────────────────────────────────────────────── */
.isis-cal {
    display: flex;
    flex-direction: column;
    border: 1px solid var(--isis-border);
    border-radius: 6px;
    background: var(--isis-surface);
    /* Pleine hauteur : .isis-rich-page est une colonne flex (height:100%) ; le calendrier
       prend tout l'espace restant sous la barre d'outils et l'en-tête, la légende garde sa
       hauteur naturelle en pied. min-height:0 pour que les semaines internes puissent réduire. */
    flex: 1 1 auto;
    min-height: 0;
    /* Filet de sécurité : sur un écran contraint (1024×768 prioritaire, zoom navigateur), un mois
       à 6 semaines dépasse la hauteur allouée. overflow-y:auto fait scroller le calendrier plutôt
       que de rogner silencieusement la dernière semaine — pattern déjà en vigueur pour .isis-grid. */
    overflow-x: hidden;
    overflow-y: auto;
}
/* L'en-tête des jours reste visible quand on scrolle un mois trop haut pour l'écran. */
.isis-cal__head { position: sticky; top: 0; z-index: 1; }
/* Mois à 6 semaines : on comprime les rangées (comme Google/Outlook) pour tout montrer sans
   scroll dans le cas courant ; le filet overflow ci-dessus couvre les viewports extrêmes. */
.isis-cal--dense .isis-cal__cell { min-height: 64px; padding: 0.3rem 0.4rem; gap: 0.12rem; }
.isis-cal__head {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    background: var(--isis-surface-soft);
    border-bottom: 1px solid var(--isis-border);
}
.isis-cal__head-cell {
    padding: 0.45rem 0.6rem;
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    font-weight: 600;
    color: var(--isis-text-muted);
}
.isis-cal__week {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    /* Les semaines se partagent à parts égales la hauteur du calendrier (4 à 6 selon le mois). */
    flex: 1 1 0;
    min-height: 0;
}
.isis-cal__cell {
    position: relative;
    min-height: 88px;   /* plancher : lisible même sur petit écran où le partage flex rétrécit */
    padding: 0.4rem 0.5rem;
    background: var(--isis-surface);
    /* La cellule est un <button> : sans ce zéro, sa bordure navigateur (2 px en haut et à
       gauche) doublait chaque trait de la grille. */
    border: 0;
    border-right: 1px solid var(--isis-border);
    border-bottom: 1px solid var(--isis-border);
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.2rem;
    cursor: pointer;
    text-align: left;
}
.isis-cal__cell:hover {
    background: var(--isis-surface-soft);
}
.isis-cal__cell:focus-visible {
    outline: 2px solid var(--isis-mod-gespla);
    outline-offset: -2px;
}
/* Sprint T G2 — marqueur conflit dans le calendrier mensuel. */
.isis-cal__cell.has-conflict {
    box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--isis-danger) 60%, transparent);
}
.isis-cal__conflict-marker {
    position: absolute;
    top: 4px;
    right: 4px;
    width: 16px;
    height: 16px;
    border-radius: 50%;
    background: var(--isis-danger);
    color: white;
    font-weight: 700;
    font-size: 11px;
    line-height: 16px;
    text-align: center;
    pointer-events: none;
}
.isis-cal__cell.is-out {
    background: var(--isis-surface-soft);
    color: var(--isis-text-muted);
    opacity: 0.6;
}
.isis-cal__cell.is-today {
    box-shadow: inset 3px 0 0 0 var(--isis-mod-gespla);
}
.isis-cal__day-num {
    font-size: 0.78rem;
    font-weight: 600;
    color: var(--isis-text);
}
/* Pastille de charge NEUTRE (encre sur fond doux ≈ 16:1 clair / 12,7:1 sombre). Elle ne porte
   plus la couleur sémantique : texte de teinte sur tint de même teinte donnait 3,9-4,4:1 (< AA),
   et un vert plein sur ~30 jours/mois noyait le seul jour rouge. Le signal vit désormais sur le
   fond de cellule (surcharge) et le marqueur « pic » — la pastille redevient un chiffre lisible. */
.isis-cal__load {
    font-size: 0.7rem;
    font-weight: 700;
    padding: 1px 5px;
    border-radius: var(--isis-radius-pill);
    background: var(--isis-surface-soft);
    color: var(--isis-text);
    font-variant-numeric: tabular-nums;
}
/* Pastille « capacité libre » (< 100 %) : tint accent + texte encre (contraste élevé dans les
   deux thèmes). Elle n'apparaît que les jours où quelqu'un n'est pas plein — un signal rare et
   actionnable (« qui peut prendre plus ? »), à distinguer du rouge de surcharge. */
.isis-cal__load--free { background: color-mix(in srgb, var(--isis-accent) 15%, var(--isis-surface)); }
.isis-cal__cell.is-danger   { background: color-mix(in srgb, var(--isis-danger) 7%, var(--isis-surface)); }

/* Contenu enrichi de la cellule (2026-07-29) : effectif + matériel, charge moyenne, répartition
   ferme/prévisionnelle, marqueur de surcharge individuelle. */
.isis-cal__meta {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-size: 0.72rem;
    color: var(--isis-text-muted);
    font-variant-numeric: tabular-nums;
}
.isis-cal__people, .isis-cal__mat { display: inline-flex; align-items: center; gap: 0.15rem; }
.isis-cal__states {
    display: flex;
    align-items: center;
    gap: 0.3rem;
    font-size: 0.7rem;
    color: var(--isis-text-muted);
    font-variant-numeric: tabular-nums;
}
.isis-cal__dot-ferme, .isis-cal__dot-prev {
    display: inline-block;
    width: 8px;
    height: 8px;
    flex-shrink: 0;
}
/* Ferme = rond plein, prévisionnelle = carré évidé : la distinction tient à la FORME autant
   qu'à la couleur (WCAG 1.4.1 — ne pas reposer sur la seule teinte, robuste au daltonisme). */
.isis-cal__dot-ferme { border-radius: 50%; background: var(--isis-mod-gespla); }
.isis-cal__dot-prev  { border-radius: 1px; background: transparent; border: 1.5px solid color-mix(in srgb, var(--isis-mod-gespla) 70%, transparent); }
.isis-cal__over {
    display: inline-flex;
    align-items: center;
    gap: 0.2rem;
    font-size: 0.68rem;
    font-weight: 600;
    color: var(--isis-danger);
}
.isis-cal-legend__group { font-weight: 600; color: var(--isis-text); }
.isis-cal-legend__sep {
    width: 1px;
    height: 12px;
    background: var(--isis-border);
    display: inline-block;
    margin: 0 0.2rem;
}
.isis-cal-legend__dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; margin-right: 0.3rem; vertical-align: middle; }
.isis-cal-legend { flex-wrap: wrap; align-items: center; }
.isis-cal-legend {
    display: flex;
    gap: 1rem;
    margin-top: 0.6rem;
    font-size: 0.78rem;
    color: var(--isis-text-muted);
}
.isis-cal-legend__sw {
    display: inline-block;
    width: 10px;
    height: 10px;
    border-radius: 2px;
    margin-right: 0.3rem;
    vertical-align: middle;
}

/* Sprint H — Dialog vues sauvegardées du planner */
.isis-grid--planner-views .isis-grid__head,
.isis-grid--planner-views .isis-grid__row {
    grid-template-columns: 32px minmax(180px, 1fr) 100px 80px;
    min-width: 0;
}

/* ──────────────────────────────────────────────────────────────────────────
   Sprint G — Vue capacité agrégée (page /gespla/capacite)
   ────────────────────────────────────────────────────────────────────────── */
/* Tableau collaborateurs : status | nom | entreprise | charge | cible | écart | aff | actions
   (Sprint U H2 — +Cible/Écart/Actions) */
/* En-têtes des colonnes chiffrées des deux grilles de capacité : le bouton de tri est un
   inline-flex, donc sans alignement à droite le libellé pend à gauche au-dessus de chiffres
   alignés à droite. Et l'entonnoir passe DEVANT le libellé (`order: -1`) : posé derrière, il
   se lisait comme celui de la colonne suivante — mesuré au navigateur le 2026-09-05, où
   l'entonnoir « Charge moyenne » semblait appartenir à « Cible ». */
.isis-grid--capacite-collab .isis-grid__head-cell.isis-grid__col-num,
.isis-grid--capacite-equip .isis-grid__head-cell.isis-grid__col-num { justify-content: flex-end; }
.isis-grid--capacite-collab .isis-grid__head-cell.isis-grid__col-num .isis-grid__filter-btn,
.isis-grid--capacite-equip .isis-grid__head-cell.isis-grid__col-num .isis-grid__filter-btn { order: -1; }

.isis-grid--capacite-collab .isis-grid__head,
.isis-grid--capacite-collab .isis-grid__row {
    grid-template-columns: 32px minmax(220px, 1.6fr) minmax(140px, 0.9fr) 120px 80px 100px 60px 60px;
    min-width: 1020px;
}
/* Tableau équipements : status | code | libellé | entreprise | charge | cible | écart | aff | actions */
.isis-grid--capacite-equip .isis-grid__head,
.isis-grid--capacite-equip .isis-grid__row {
    grid-template-columns: 32px 120px minmax(200px, 1.6fr) minmax(140px, 0.9fr) 120px 80px 100px 60px 60px;
    min-width: 1140px;
}
/* Texte coloré charge */
.isis-capacite-text--warning {
    color: var(--isis-warning);
}
.isis-capacite-text--danger {
    color: var(--isis-danger);
}

/* Grille couverture besoins N3 V1.8 — 7 cols
   status | besoin | requis | planifié | progression | nb aff | actions */
.isis-grid--besoin-coverage .isis-grid__head,
.isis-grid--besoin-coverage .isis-grid__row {
    grid-template-columns: 32px minmax(220px, 1.6fr) 100px 110px minmax(200px, 1.4fr) 60px 60px;
    min-width: 920px;
}
/* Cellules numériques alignées à droite + tabular-nums pour scan vertical. */
.isis-grid--besoin-coverage .isis-grid__col-num {
    text-align: right;
    font-variant-numeric: tabular-nums;
}

/* Bandeau récapitulatif au-dessus de la grille couverture. */
.isis-besoin-coverage {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}
.isis-besoin-coverage__summary {
    display: flex;
    flex-wrap: wrap;
    gap: 1.5rem 2rem;
    padding: 0.6rem 0.85rem;
    background: var(--isis-card-mod-bg);
    border: var(--isis-card-mod-border);
    border-radius: 6px;
}
.isis-besoin-coverage__summary-pair {
    display: flex;
    flex-direction: column;
    gap: 0.1rem;
    min-width: 80px;
}
.isis-besoin-coverage__summary-label {
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--isis-text-muted);
}
.isis-besoin-coverage__summary-value {
    font-size: 1.05rem;
    font-weight: 600;
    color: var(--isis-text);
    font-variant-numeric: tabular-nums;
}
.isis-besoin-coverage__summary-value.is-success { color: var(--isis-success); }
.isis-besoin-coverage__summary-value.is-warning { color: var(--isis-warning); }
.isis-besoin-coverage__summary-value.is-danger  { color: var(--isis-danger); }

/* Barre de progression "couverture" — fond gris + remplissage coloré selon le statut. */
.isis-coverage-bar {
    position: relative;
    width: 100%;
    height: 8px;
    background: var(--isis-surface-soft);
    border: 1px solid var(--isis-border);
    border-radius: 4px;
    overflow: hidden;
}
.isis-coverage-bar__fill {
    height: 100%;
    transition: width 200ms ease-out;
    background: var(--isis-accent);
}
.isis-coverage-bar__fill.is-success { background: var(--isis-success); }
.isis-coverage-bar__fill.is-ok      { background: var(--isis-success); }
.isis-coverage-bar__fill.is-warning { background: var(--isis-warning); }
.isis-coverage-bar__fill.is-danger  { background: var(--isis-danger); }
.isis-coverage-bar__fill.is-info    { background: var(--isis-accent); }
.isis-coverage-bar__pct {
    display: block;
    margin-top: 0.15rem;
    font-size: 0.78rem;
    color: var(--isis-text-muted);
    font-variant-numeric: tabular-nums;
}

/* Ligne de groupe (séparateur visuel entre ressources ou entre projets).
   Audit a11y M3 : trait gauche couleur module pour distinguer non-color-seule
   (daltoniens) — fortifie le signal au-delà du font-weight + uppercase. */
.isis-grid__group-row {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    grid-column: 1 / -1;
    background: var(--isis-surface-soft);
    border-bottom: 1px solid var(--isis-border);
    padding: 0.4rem 0.85rem 0.4rem calc(0.85rem - 3px);
    font-size: 0.72rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--isis-text-muted);
    position: sticky;
    top: 34px; /* sous le head */
    z-index: 2;
}

/* Section riche — header titre + sous-titre, séparateur visuel entre blocs
   d'une rich-page. Audit ui-ux 2026-05-20 : classes manquantes, utilisées
   par DashboardPage.razor (section conflits). */
.isis-rich-section {
    margin-top: 1.5rem;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: 10px;
    box-shadow: var(--isis-elevation-1);
    padding: 1rem 1.1rem;
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
}
/* Sections imbriquees dans une grille 2-col : pas de marge top (la grille gere le gap) */
.isis-dash-2col > .isis-rich-section {
    margin-top: 0;
}
.isis-rich-section__header {
    margin-bottom: 0.25rem;
    padding: 0;
    padding-bottom: 0.5rem;
    border-bottom: 1px solid var(--isis-border);
}
.isis-rich-section__title {
    font-size: 1rem;
    font-weight: 600;
    color: var(--isis-text);
    margin: 0 0 0.2rem;
}
.isis-rich-section__subtitle {
    font-size: 0.82rem;
    color: var(--isis-text-muted);
    display: block;
}

/* Pastille d'alerte sur un onglet — signale à l'arrivée sur la fiche
   qu'un onglet réclame de l'attention (ex : calibration expirée).
   Audit ui-ux 2026-05-19, Phase 1.4. */
.isis-tab__alert-dot {
    display: inline-block;
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--isis-danger);
    margin-left: 4px;
    vertical-align: middle;
    box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.5);
}
/* Palier intermédiaire (2026-08-11) : certains signaux ont deux niveaux de gravité et
   pas seulement « à faire / rien à faire » — un plafond de contrat-cadre à 82 % appelle
   une anticipation, à 140 % il est franchi. Sans cette variante, les deux affichaient le
   même rouge, et étaient de surcroît indiscernables des pastilles binaires voisines. */
.isis-tab__alert-dot--warning {
    background: var(--isis-warning);
}


/* ============================================================================
 * V1.2 contrat-cadre — bloc consommation du sidepanel marché (gesmaff)
 * Affiche la barre de progression plafond + alertes 80%/100% + count BC.
 * ============================================================================ */
.isis-cadre-block {
    margin-top: 0.6rem;
    padding: 0.75rem;
    background: var(--isis-mod-gesmaff-soft);
    border: 1px solid color-mix(in srgb, var(--isis-mod-gesmaff) 18%, transparent);
    border-radius: 6px;
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
}
.isis-cadre-block__head {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    font-size: 0.85rem;
    color: var(--isis-text);
}
.isis-cadre-block__amounts {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 0.3rem;
    font-family: var(--isis-font-mono);
    font-size: 0.95rem;
}
.isis-cadre-block__consumed {
    font-weight: 600;
    color: var(--isis-text);
}
.isis-cadre-block__separator { color: var(--isis-text-soft); }
/* Le consommé (fait acquis) et l'annoncé non pris en charge (prévision, encore abandonnable)
   ne doivent pas se lire comme une seule masse — onglet Flux, bandeau trois chiffres. */
.isis-cadre-block__consumed--forecast { color: var(--isis-text-muted); font-weight: 500; }
.isis-cadre-block__cap { color: var(--isis-text); }
.isis-cadre-block__devise {
    font-size: 0.75rem;
    color: var(--isis-text-soft);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    margin-left: 0.3rem;
}
.isis-cadre-block__pct {
    margin-left: auto;
    font-weight: 600;
    font-size: 0.85rem;
    padding: 0.1rem 0.45rem;
    border-radius: var(--isis-radius-pill);
}
.isis-cadre-block__pct.is-neutral { background: var(--isis-surface-alt); color: var(--isis-text-soft); }
.isis-cadre-block__pct.is-ok      { background: color-mix(in srgb, var(--isis-success) 12%, transparent); color: var(--isis-success); }
.isis-cadre-block__pct.is-warning { background: color-mix(in srgb, var(--isis-warning) 14%, transparent); color: var(--isis-warning); }
.isis-cadre-block__pct.is-danger  { background: color-mix(in srgb, var(--isis-danger)  14%, transparent); color: var(--isis-danger); }

.isis-cadre-block__bar {
    height: 8px;
    background: var(--isis-surface-alt);
    border-radius: var(--isis-radius-pill);
    overflow: hidden;
}
.isis-cadre-block__bar-fill {
    height: 100%;
    transition: width 220ms ease-out;
}
.isis-cadre-block__bar-fill.is-ok      { background: var(--isis-success); }
.isis-cadre-block__bar-fill.is-warning { background: var(--isis-warning); }
.isis-cadre-block__bar-fill.is-danger  { background: var(--isis-danger); }
.isis-cadre-block__bar-fill.is-neutral { background: var(--isis-text-soft); }

.isis-cadre-block__alert {
    display: flex;
    align-items: center;
    gap: 0.3rem;
    font-size: 0.78rem;
    padding: 0.3rem 0.5rem;
    border-radius: 4px;
}
.isis-cadre-block__alert.is-warning {
    background: color-mix(in srgb, var(--isis-warning) 12%, transparent);
    color: var(--isis-warning);
}
.isis-cadre-block__alert.is-danger {
    background: color-mix(in srgb, var(--isis-danger) 12%, transparent);
    color: var(--isis-danger);
}
.isis-cadre-block__counts {
    font-size: 0.8rem;
    color: var(--isis-text-soft);
}

/* ────────────────────────────────────────────────────────────────────────────
   .isis-cadre-block--state — le bloc parle par son ÉTAT (2026-08-11)
   ----------------------------------------------------------------------------
   Opt-in : le bloc nu garde son rendu historique, seules les pages qui posent
   `--state` (+ is-neutral|is-ok|is-warning|is-danger) basculent. Trois défauts
   corrigés ensemble, chacun mesuré avant/après :

   1. SURFACE. Le fond était `--isis-mod-gesmaff-soft` PLEIN sur ~1200×130 px, quel
      que soit le taux. DESIGN.md §2 l'interdit deux fois (l. 145 « jamais comme
      couleur de surface large », l. 153 « aucune surface ne reçoit jamais la couleur
      module pleine ») et prescrit `--isis-card-mod-bg` (module à 7 %) + filet.
      Aggravant : ce token vaut #fef3c7, à l'octet près `--isis-warning-soft` — un
      contrat à 2,9 % de son plafond avait donc l'air alerté, et le bloc criait aussi
      fort à 2,9 % qu'à 140 %. On apprend à ignorer ce qui crie tout le temps, et le
      filtre reste actif au moment où il faut croire l'alerte.

   2. CONTRASTES. Les fonds de la pastille et des alertes étaient des
      `color-mix(…, transparent)` : le `transparent` prend la couleur du PARENT, donc
      l'ambre, et le ratio s'effondrait (mesuré 3,77 à 3,90:1 en clair). Ils passent
      sur `--isis-surface` opaque, qui ne dépend plus de son hôte : 5,02 / 5,02 /
      6,47:1 en clair, 6,74 / 7,27 / 4,62:1 en sombre. Tous au-dessus de 4,5:1.

   3. RAIL DE LA JAUGE. `--isis-surface-alt` sur l'ambre mesurait 1,12:1 : le rail
      était invisible, on lisait un moignon coloré sans plafond visible — alors que
      c'est le rapport AU PLAFOND qu'on vient chercher. L'intérieur reste clair (la
      barre doit se lire comme vide, pas comme pleine) et c'est le filet qui porte la
      limite : 3,28 à 3,34:1 en clair, 4,29 à 4,38:1 en sombre.
   ──────────────────────────────────────────────────────────────────────────── */
.isis-cadre-block--state {
    background: var(--isis-card-mod-bg);
    border: var(--isis-card-mod-border);
}
.isis-cadre-block--state.is-warning {
    background: var(--isis-warning-soft);
    border: 1px solid color-mix(in srgb, var(--isis-warning) 32%, transparent);
}
.isis-cadre-block--state.is-danger {
    background: var(--isis-danger-soft);
    border: 1px solid color-mix(in srgb, var(--isis-danger) 32%, transparent);
}
/* La légende était en `--isis-text-soft` : 4,27:1 sur l'ambre. `-muted` rend 6,81:1
   et reste secondaire à l'œil. */
.isis-cadre-block--state .isis-cadre-block__counts,
.isis-cadre-block--state .isis-cadre-block__devise,
.isis-cadre-block--state .isis-cadre-block__separator {
    color: var(--isis-text-muted);
}
.isis-cadre-block--state .isis-cadre-block__pct,
.isis-cadre-block--state .isis-cadre-block__alert {
    background: var(--isis-surface);
}
/* Le `margin-left: auto` d'origine était juste dans un sidepanel étroit ; à pleine largeur
   de panneau il projetait la pastille à ~1 100 px des chiffres qu'elle qualifie, si bien
   qu'on lisait « 1 350 + 3 060 / 150 000 » d'un côté et « 2,9 % » de l'autre sans les relier.
   Elle reste collée à la suite des montants. */
.isis-cadre-block--state .isis-cadre-block__pct {
    margin-left: 0.15rem;
}
.isis-cadre-block--state .isis-cadre-block__pct.is-neutral { color: var(--isis-text-muted); }
.isis-cadre-block--state .isis-cadre-block__bar {
    background: var(--isis-surface);
    border: 1px solid color-mix(in srgb, var(--isis-text) 50%, transparent);
    box-sizing: border-box;
    height: 10px;
}

/* ============================================================================
   Zone géographique (Sprint 2 chantier géo)
   Sections affichées sur fiche détail AO/Marché/Demande/Devis/Commande.
   ============================================================================ */

/* ============================================================================
   Couches géographiques multi-layers (V1.4 — 2026-05-22)
   ============================================================================ */
.isis-geo-layers {
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
    padding: 1rem;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: 6px;
    flex: 1 1 auto;
    min-height: 0;
}

/* Mode plein écran (V1.4.2 — 2026-05-23).
   Toggle agrandir : la section quitte le flux normal et occupe l'espace sous
   le header global (--isis-header-h ~56px). Z-index 950 : au-dessus du
   contenu normal mais EN-DESSOUS des dialogs Radzen (1010+). Touche Échap
   = sortie.
   Refonte 2026-05-29 : `left` calibré sur la largeur du subnav module pour
   laisser la nav latérale visible (cohérence avec .isis-focus-zone). La
   navigation entre fiches reste possible sans sortir du plein écran. */
.isis-geo-layers--expanded {
    position: fixed;
    top: var(--isis-header-h, 56px);
    left: var(--isis-subnav-w, 280px);
    right: 0;
    bottom: 0;
    z-index: 950;
    border-radius: 0;
    border: none;
    border-top: 1px solid var(--isis-border);
    padding: 0.75rem 1rem 1rem;
    outline: none;
    transition: left 200ms cubic-bezier(0.4, 0, 0.2, 1);
}
.isis-shell.is-subnav-collapsed .isis-geo-layers--expanded {
    left: var(--isis-subnav-w-collapsed, 64px);
}

.isis-geo-layers--expanded:focus-visible {
    box-shadow: inset 0 0 0 2px var(--isis-accent);
}

/* ─────────────────────────────────────────────────────────────────────────
   Tokens d'espacement & typographie (A3 + B7 — refonte 2026-05-23)
   Système 3 niveaux d'espacement réutilisé sur toute la section géo :
     --isis-pad-card    : padding extérieur d'un bloc (1rem)
     --isis-pad-compact : padding header/footer de bloc (0.6rem 0.75rem)
     --isis-pad-tight   : padding row/item dense (0.4rem 0.55rem)
   ───────────────────────────────────────────────────────────────────────── */
.isis-geo-layers,
.isis-zone-map-shell,
.isis-proximity-panel {
    --isis-pad-card: 1rem;
    --isis-pad-compact: 0.6rem 0.75rem;
    --isis-pad-tight: 0.4rem 0.55rem;
}

/* Header unique (A1 — fusion). Plus de doublon dans le rail.
   Layout : titre + compteur à gauche, actions à droite. */
.isis-geo-layers__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    padding-bottom: 0.25rem;
    border-bottom: 1px solid var(--isis-border);
    margin-bottom: 0.25rem;
}

.isis-geo-layers__head-titles {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
}

.isis-geo-layers__head-actions {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
}

/* Hiérarchie typographique (B7) — opposable, réutilisable cross-page.
   Title : titre de section (0.95rem, 600, --isis-text).
   Subtitle : tag/légende (0.75rem, 600, uppercase, --isis-text-muted). */
.isis-section-title {
    font-size: 0.95rem;
    font-weight: 600;
    color: var(--isis-text);
    margin: 0;
    line-height: 1.3;
}

.isis-section-subtitle {
    font-size: 0.72rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--isis-text-muted);
    margin: 0;
}

.isis-geo-layers__count {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 22px;
    padding: 1px 7px;
    background: var(--isis-current-mod-soft, var(--isis-accent-soft));
    color: var(--isis-current-mod, var(--isis-accent));
    border-radius: var(--isis-radius);
    font-size: 0.72rem;
    font-weight: 600;
}

/* Empty state inline (C12) — variant de .isis-empty avec padding réduit
   adapté à un inline dans une fiche détail (pas une page complète). */
.isis-empty--inline {
    padding: 2rem 1.5rem;
    max-width: 460px;
}
.isis-empty--inline .isis-empty__icon-wrap {
    width: 72px;
    height: 72px;
}
.isis-empty--inline .isis-empty__icon-wrap .rzi {
    font-size: 32px;
}

.isis-geo-layers__list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
}

.isis-geo-layers__item {
    display: grid;
    grid-template-columns: auto auto 1fr auto;
    align-items: center;
    gap: 0.55rem;
    padding: var(--isis-pad-tight);
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius);
    font-size: 0.85rem;
}

.isis-geo-layers__chip {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    padding: 0.1rem 0.45rem;
    border-radius: var(--isis-radius);
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    white-space: nowrap;
}

.isis-geo-layers__name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--isis-text);
    font-weight: 500;
}

.isis-geo-layers__actions {
    display: inline-flex;
    gap: 0.2rem;
}

/* Wrapper carte (C11) — conteneur position:relative pour ancrer la toolbar
   verticale en overlay top-right de la carte. */
.isis-geo-layers__map-wrap {
    position: relative;
    flex: 1 1 auto;
    min-width: 0;
    min-height: 0;
    display: flex;
}
/* Pas de couche géo : carte de repli (site/pays) + bandeau CTA.
   flex:1 + min-height:0 → l'état vide remplit toute la hauteur restante du
   panneau (le bandeau CTA reste à sa taille, la carte prend le reste). */
.isis-geo-layers__empty-map { display: flex; flex-direction: column; gap: 0.6rem; flex: 1 1 auto; min-height: 0; }
.isis-geo-layers__empty-map > .isis-affaires-map-host { flex: 1 1 auto; min-height: 0; }
.isis-geo-layers__empty-cta { flex-shrink: 0; }
.isis-geo-layers__empty-cta {
    display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 0.6rem;
    padding: 0.5rem 0.75rem; background: var(--isis-surface-alt, var(--isis-surface-alt));
    border: 1px solid var(--isis-border); border-radius: var(--isis-radius-sm, 6px);
}
.isis-geo-layers__empty-cta-text { display: flex; align-items: center; gap: 0.5rem; font-size: 0.85rem; color: var(--isis-text-muted); }
.isis-geo-layers__empty-cta-actions { display: flex; gap: 0.4rem; }
.isis-geo-layers__map-wrap > .isis-affaires-map-host {
    flex: 1 1 auto;
    min-width: 0;
    min-height: 0;
}

/* Mini-toolbar verticale carte (C11) — overlay top-right, boutons icône.
   Pattern aligné sur les outils Leaflet natifs (zoom +/-) mais en colonne. */
.isis-map-toolbar {
    position: absolute;
    top: 0.6rem;
    right: 0.6rem;
    z-index: 400;     /* au-dessus des tiles Leaflet (200) et controls (300) */
    display: inline-flex;
    flex-direction: column;
    gap: 0.2rem;
    padding: 0.25rem;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius);
    box-shadow: var(--isis-elevation-1);
}

/* Séparateur visuel entre groupes de boutons dans la toolbar verticale. */
.isis-map-toolbar__sep {
    height: 1px;
    background: var(--isis-border);
    margin: 0.2rem 4px;
}
/* Replie les séparateurs orphelins issus des presets (en tête/queue, ou doublés)
   sans logique markup : un sép en 1ʳᵉ/dernière position ou suivant un autre sép. */
.isis-map-toolbar__sep:first-child,
.isis-map-toolbar__sep:last-child { display: none; }
.isis-map-toolbar__sep + .isis-map-toolbar__sep { display: none; }

/* Popover basemap switcher — apparaît à gauche du bouton 🗺. */
.isis-map-basemap-popover {
    position: absolute;
    top: 0.6rem;
    right: 3rem;
    z-index: 410;
    min-width: 180px;
    padding: 0.35rem;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius);
    box-shadow: var(--isis-elevation-2);
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
}
.isis-map-basemap-popover__item {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.4rem 0.6rem;
    background: transparent;
    border: 1px solid transparent;
    border-radius: var(--isis-radius-sm);
    cursor: pointer;
    color: var(--isis-text);
    font-size: 0.82rem;
    text-align: left;
    transition: background-color 120ms;
}
.isis-map-basemap-popover__item:hover {
    background: var(--isis-surface-alt);
}
.isis-map-basemap-popover__item.is-active {
    background: var(--isis-accent-soft);
    color: var(--isis-accent);
    font-weight: 600;
}

/* Légende dynamique (Sprint-2 #12) — overlay bottom-left, semi-transparente. */
.isis-map-legend {
    position: absolute;
    bottom: 1.5rem;
    left: 0.6rem;
    z-index: 400;
    min-width: 160px;
    max-width: 260px;
    padding: 0.5rem 0.6rem;
    background: rgba(255, 255, 255, 0.92);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius);
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.12);
    backdrop-filter: blur(4px);
}
.isis-map-legend__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    margin-bottom: 0.35rem;
}
.isis-map-legend__list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
}
.isis-map-legend__item {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    font-size: 0.78rem;
    color: var(--isis-text);
}
.isis-map-legend__swatch {
    display: inline-block;
    width: 16px;
    height: 12px;
    border-radius: 2px;
    flex-shrink: 0;
}
.isis-map-legend__label {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.isis-map-legend__toggle {
    position: absolute;
    bottom: 1.5rem;
    left: 0.6rem;
    z-index: 400;
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.3rem 0.55rem;
    background: rgba(255, 255, 255, 0.92);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius);
    cursor: pointer;
    color: var(--isis-text-muted);
    font-size: 0.78rem;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.12);
}
.isis-map-legend__toggle:hover {
    color: var(--isis-text);
    background: var(--isis-surface);
}

/* Status bar overlay (Sprint-3 #6) — coordonnées au survol, en bas centre. */
.isis-map-statusbar {
    position: absolute;
    bottom: 0.4rem;
    left: 50%;
    transform: translateX(-50%);
    z-index: 410;
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.2rem 0.6rem;
    background: rgba(255, 255, 255, 0.92);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius);
    font-family: var(--isis-font-mono, monospace);
    font-size: 0.74rem;
    color: var(--isis-text-muted);
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
    pointer-events: none;
}

/* Label flottant de mesure (Sprint-2 #11) — affiché sur la carte. */
.isis-measure-label {
    display: inline-block;
    padding: 0.15rem 0.45rem;
    background: rgba(75, 95, 173, 0.92);
    color: #ffffff;
    border-radius: 3px;
    font-size: 0.72rem;
    font-weight: 600;
    white-space: nowrap;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.18);
}

/* Drag handle pour les couches du rail (Sprint-1 #1). */
.isis-geo-layers__drag-handle {
    cursor: grab;
    color: var(--isis-text-muted);
    padding: 2px;
    user-select: none;
}
.isis-geo-layers__drag-handle:active { cursor: grabbing; }
.isis-geo-layers__item--rail[draggable="true"]:hover .isis-geo-layers__drag-handle {
    color: var(--isis-text);
}

/* Feedback drag-reorder (V1.5 polish A2 — 2026-05-24). */
.isis-geo-layers__item--rail.is-dragging {
    opacity: 0.45;
    background: var(--isis-surface-alt);
    transition: opacity 120ms;
}
.isis-geo-layers__item--rail.is-drop-target {
    box-shadow: inset 0 3px 0 0 var(--isis-accent);
    background: var(--isis-accent-soft);
}

/* Slider opacité par couche (Sprint-1 #2). */
.isis-geo-layers__opacity {
    display: flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.1rem 0;
}
.isis-geo-layers__opacity-slider {
    flex: 1 1 auto;
    min-width: 0;
    height: 14px;
    cursor: pointer;
}
.isis-geo-layers__opacity-val {
    font-family: var(--isis-font-mono, monospace);
    font-size: 0.68rem;
    color: var(--isis-text-muted);
    min-width: 32px;
    text-align: right;
}

/* Folder item — fond légèrement teinté + chevron de groupe. */
.isis-geo-layers__item--folder {
    background: var(--isis-surface-alt);
    border-style: dashed;
}

/* Actions du rail-head (bouton + créer groupe). */
.isis-geo-layers__rail-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.4rem;
}
.isis-geo-layers__rail-head-actions {
    display: inline-flex;
    gap: 0.2rem;
}

.isis-map-toolbar__btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    padding: 0;
    background: transparent;
    border: none;
    border-radius: 4px;
    cursor: pointer;
    color: var(--isis-text-muted);
    transition: background-color 120ms, color 120ms;
}
.isis-map-toolbar__btn:hover {
    background: var(--isis-surface-alt);
    color: var(--isis-text);
}
.isis-map-toolbar__btn:focus-visible {
    outline: 2px solid var(--isis-accent);
    outline-offset: 1px;
}
.isis-map-toolbar__btn[aria-pressed="true"],
.isis-map-toolbar__btn.is-active {
    background: var(--isis-accent-soft);
    color: var(--isis-accent);
}

/* Rail gauche couches — sans header doublé. Le sous-titre « Couches » est
   le seul élément du rail-head, posé via .isis-section-subtitle. */
.isis-geo-layers__rail {
    flex: 0 0 260px;
    align-self: stretch;
    min-height: 0;
    display: flex;
    flex-direction: column;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius);
    overflow: hidden;
}

.isis-geo-layers__rail-head {
    flex: 0 0 auto;
    padding: var(--isis-pad-compact);
    border-bottom: 1px solid var(--isis-border);
    background: var(--isis-surface-alt);
}

.isis-geo-layers__list--rail {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    padding: 0.45rem;
    gap: 0.35rem;
}

.isis-geo-layers__item--rail {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    padding: var(--isis-pad-tight);
}

.isis-geo-layers__item-row {
    display: flex;
    align-items: center;
    gap: 0.45rem;
}

.isis-geo-layers__item-name {
    font-size: 0.85rem;
    font-weight: 500;
    color: var(--isis-text);
    word-wrap: break-word;
    line-height: 1.3;
}

.isis-geo-layers__item--rail .isis-geo-layers__actions {
    justify-content: flex-end;
    border-top: 1px dashed var(--isis-border-soft, #f1f2f5);
    padding-top: 0.3rem;
    margin-top: 0.1rem;
}

/* Métriques d'emprise persistées (migration 0852 — EF-57). Ligne de méta sous le
   nom de la couche : c'est une donnée de lecture, jamais une action — d'où le
   niveau de contraste « muted » et l'absence d'affordance. */
.isis-geo-layers__item-metrics {
    display: flex;
    align-items: center;
    gap: 0.3rem;
    font-size: 0.72rem;
    line-height: 1.25;
    color: var(--isis-text-muted);
    font-variant-numeric: tabular-nums;
    overflow: hidden;
}
/* Le rail fait 260 px : un résumé de polygone (surface + contour + points) y
   passerait sur deux lignes et chasserait une couche hors de l'écran. Tronqué,
   avec le texte entier au survol (title). */
.isis-geo-layers__item-metrics > span {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Cumul en pied de rail. Même rôle qu'un pied de tableau : il récapitule, il ne
   se clique pas. La note « n couches non mesurées » n'apparaît que si le cumul
   est incomplet — un total muet se lirait comme exhaustif. */
.isis-geo-layers__rail-total {
    flex: 0 0 auto;
    display: flex;
    flex-direction: column;
    gap: 0.1rem;
    padding: var(--isis-pad-compact);
    border-top: 1px solid var(--isis-border);
    background: var(--isis-surface-alt);
}
.isis-geo-layers__rail-total-label {
    font-size: 0.68rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--isis-text-muted);
}
.isis-geo-layers__rail-total-value {
    font-size: 0.82rem;
    font-weight: 600;
    color: var(--isis-text);
    font-variant-numeric: tabular-nums;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.isis-geo-layers__rail-total-note {
    font-size: 0.7rem;
    color: var(--isis-text-muted);
}

/* Breakpoint < 1280px (C10) — sur laptop 14" / iPad horizontal, le panneau
   proximité 320px + rail 260px laissent < 500px à la carte. On bascule le
   panneau en floating overlay ancré à droite de la carte (sur la carte).
   Largeur 300px, scroll interne, ombre marquée pour le détacher visuellement. */
@media (max-width: 1280px) {
    .isis-zone-map-shell--with-rail > .isis-proximity-panel {
        position: absolute;
        top: 0.6rem;
        right: 0.6rem;
        bottom: 0.6rem;
        z-index: 410;     /* au-dessus de la toolbar carte (400) */
        flex: 0 0 auto;
        width: 300px;
        max-height: calc(100% - 1.2rem);
        box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
    }
    .isis-zone-map-shell--with-rail.isis-zone-map-shell--panel-collapsed > .isis-proximity-panel {
        width: 44px;
    }
    /* Le shell devient position:relative pour ancrer le panneau en absolute. */
    .isis-zone-map-shell--with-rail {
        position: relative;
    }
}

/* Responsive : sur écran étroit < 900px, le shell repasse en column et le rail
   se met au-dessus de la carte. Le panneau revient en position normale (column). */
@media (max-width: 900px) {
    .isis-zone-map-shell--with-rail .isis-geo-layers__rail {
        flex: 0 0 auto;
        max-height: 220px;
    }
    .isis-zone-map-shell--with-rail > .isis-proximity-panel {
        position: static;
        width: auto;
        max-height: none;
        box-shadow: none;
    }
}

/* Dialog dessin de couche (V1.4.1 — 2026-05-22). Layout column : meta compact,
   hint, carte plein-flex, actions. La carte doit prendre toute la hauteur dispo.

   Chaîne flex : le caller (GeoLayersSection.OpenDrawDialogAsync) pose
   CssClass="isis-dialog-flex" + ContentCssClass="isis-dialog-content-flex" sur
   les DialogOptions Radzen. Ces 2 classes (définies plus haut dans ce fichier)
   propagent flex column + min-height: 0 sur .rz-dialog et .rz-dialog-content.
   Ici on prolonge la chaîne : .isis-form-linear--dialog (wrapper combiné avec
   .isis-geo-draw-dialog) doit prendre toute la hauteur sans rompre le flex. */
.isis-form-linear--dialog.isis-geo-draw-dialog,
.isis-geo-draw-dialog {
    display: flex;
    flex-direction: column;
    gap: 0.7rem;
    height: 100%;
    min-height: 0;
    flex: 1 1 auto;
}

.isis-geo-draw__meta {
    display: flex;
    flex-wrap: wrap;
    gap: 0.6rem;
    align-items: flex-end;
    flex: 0 0 auto;
}

.isis-geo-draw__meta-field {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
}

.isis-geo-draw__meta-field--grow {
    flex: 1 1 auto;
    min-width: 200px;
}

.isis-geo-draw__hint {
    display: flex;
    align-items: flex-start;
    gap: 0.4rem;
    padding: 0.45rem 0.65rem;
    background: var(--isis-surface-alt);
    border: 1px solid var(--isis-border);
    border-radius: 4px;
    color: var(--isis-text-muted);
    font-size: 0.8rem;
    line-height: 1.4;
    flex: 0 0 auto;
}

.isis-geo-draw__hint strong {
    color: var(--isis-text);
    font-weight: 600;
}

.isis-geo-draw__map {
    flex: 1 1 auto;
    min-height: 0;       /* indispensable pour qu'un enfant flex stretche correctement */
    height: 100%;         /* fallback navigateurs qui ignorent flex sur l'enfant carte */
}

.isis-geo-draw-dialog .isis-form-linear__actions {
    flex: 0 0 auto;
}

/* Bouton agrandir actif (état "en mode plein écran") : feedback visuel léger. */
.isis-grid__action-btn.is-active {
    background: var(--isis-accent-soft);
    color: var(--isis-accent);
}

/* ============================================================================
   Carte Leaflet (Sprint 3 chantier géo)
   ============================================================================ */

.isis-affaires-map {
    width: 100%;
    border: 1px solid var(--isis-border);
    border-radius: 4px;
    overflow: hidden;
}

/* Hôte de la carte : enveloppe l'élément Leaflet + la barre d'outils overlay
   (<IsisMapToolbar>). position:relative pour ancrer la toolbar absolue. */
.isis-affaires-map-host { position: relative; display: flex; flex-direction: column; min-height: 0; }
.isis-affaires-map-host.isis-focus-zone--expanded { height: auto; }
/* La carte interne remplit l'hôte (qui reçoit le contrat flex du parent). */
.isis-affaires-map-host > .isis-affaires-map { flex: 1 1 auto; min-height: 0; }
/* Consommateurs Height="100%" sous un parent BLOC (pas display:flex) : l'hôte
   n'a pas de hauteur définie via le contrat flex → le height:100% de la carte
   interne résoudrait à auto et Leaflet s'effondrerait. On donne donc à l'hôte
   une hauteur explicite, scopée à ces parents bloc (NE PAS toucher la règle de
   base, qui casserait les consommateurs flex retargetés ci-dessus). */
.isis-parc-carte > .isis-affaires-map-host { height: 100%; }

/* ──────────────────────────────────────────────────────────────────────────
   Vue portfolio (V1.2) — bandeau meta + carte sur AppelOffreListPage et page
   /gesmaff/carte. La carte porte sa propre bordure (.isis-affaires-map),
   le bandeau meta est aligné juste au-dessus.
   ────────────────────────────────────────────────────────────────────────── */
.isis-map-portfolio {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    min-height: 0;
    height: 100%;
}

/* Wrapper qui prend la hauteur restante dans .isis-rich-page (en mode carte
   sur AppelOffreListPage et la future page /gesmaff/carte). Chaîne flex requise
   pour que la carte Leaflet ait une hauteur effective (cf. memory project-isis-grid-pattern). */
.isis-portfolio-wrap {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
}

.isis-portfolio-wrap > .isis-map-portfolio {
    flex: 1 1 auto;
    min-height: 0;
}

.isis-portfolio-wrap > .isis-map-portfolio > .isis-affaires-map-host {
    flex: 1 1 auto;
    min-height: 0;
}

.isis-map-portfolio__empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.4rem;
    padding: 2rem 1rem;
    text-align: center;
    background: var(--isis-surface-alt);
    border: 1px dashed var(--isis-border);
    border-radius: 6px;
    color: var(--isis-text-muted);
}

.isis-map-portfolio__empty strong {
    color: var(--isis-text);
    font-size: 0.95rem;
}

.isis-map-portfolio__meta {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    font-size: 0.8rem;
    color: var(--isis-text-muted);
}

.isis-map-portfolio__meta-count strong {
    color: var(--isis-text);
    font-weight: 600;
}

.isis-map-portfolio__meta-detail {
    opacity: 0.85;
}

.isis-affaires-map__error {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin-top: 0.5rem;
    font-size: 0.85rem;
    color: var(--isis-danger);
}

/* Marker custom — pastille ronde couleur module gesmaff (ambre).
   Le wrapper L.divIcon a className `isis-map-marker-wrap`, l'élément interne
   `isis-map-marker` est le rendu HTML défini dans affaires-map.js. */
.isis-map-marker-wrap {
    background: transparent;
    border: none;
}

.isis-map-marker {
    display: inline-block;
    width: 16px;
    height: 16px;
    background: #d97706;
    border: 2px solid #ffffff;
    border-radius: 50%;
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.35);
    transform: translate(-2px, -2px);
}

/* Popup Leaflet — alignement avec le ton ISIS. */
.leaflet-popup-content-wrapper {
    border-radius: 4px;
    font-family: inherit;
}

.leaflet-popup-content {
    margin: 8px 12px;
    font-size: 0.85rem;
    line-height: 1.4;
}

/* ───────────────────────────────────────────────────────────────────────────
   Markers proximité — pastille ronde colorée par kind d'affaire
   (Ao/Marche → ambre gesmaff ; DemandeClient → bleu ; Commande → teal gesproj)
   ─────────────────────────────────────────────────────────────────────────── */
.isis-nearby-marker-wrap {
    background: transparent;
    border: none;
}

/* Labels distance posés au milieu des lignes pointillées (V1.3 — 2026-05-22).
   Le wrapper L.divIcon n'a pas de fond ; le span interne a un fond blanc
   semi-opaque + bord léger pour rester lisible sur tous les fonds carto
   (OSM/Satellite/Topo). */
.isis-distance-label-wrap {
    background: transparent;
    border: none;
    pointer-events: none;
}

.isis-distance-label {
    display: inline-block;
    padding: 1px 6px;
    background: rgba(255, 255, 255, 0.92);
    color: #374151;
    font-size: 10px;
    font-weight: 600;
    border-radius: 8px;
    border: 1px solid rgba(0, 0, 0, 0.12);
    white-space: nowrap;
    line-height: 1.2;
    font-variant-numeric: tabular-nums;
}

.isis-nearby-marker {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    border-radius: 50%;
    border: 2px solid #ffffff;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
}

.isis-nearby-marker .material-symbols-outlined {
    font-size: 16px;
    color: #ffffff;
    font-variation-settings: 'FILL' 1, 'wght' 500;
}

/* ───────────────────────────────────────────────────────────────────────────
   Popup proximité — header avec pastille + meta + lien fiche
   ─────────────────────────────────────────────────────────────────────────── */
.isis-nearby-popup__header {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    margin-bottom: 0.4rem;
}

.isis-nearby-popup__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    border-radius: 50%;
    flex-shrink: 0;
}

.isis-nearby-popup__icon .material-symbols-outlined {
    font-size: 16px;
    color: #ffffff;
    font-variation-settings: 'FILL' 1, 'wght' 500;
}

.isis-nearby-popup__title {
    line-height: 1.2;
}

.isis-nearby-popup__kind {
    font-size: 0.72rem;
    color: var(--isis-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

.isis-nearby-popup__intitule {
    font-size: 0.82rem;
    color: var(--isis-text);
    margin-bottom: 0.35rem;
}

.isis-nearby-popup__meta {
    font-size: 0.75rem;
    color: var(--isis-text-muted);
    margin-bottom: 0.4rem;
}

.isis-nearby-popup__link {
    display: inline-block;
    font-size: 0.82rem;
    font-weight: 500;
    color: var(--isis-accent);
    text-decoration: none;
}

.isis-nearby-popup__link:hover,
.isis-nearby-popup__link:focus-visible {
    text-decoration: underline;
}

/* ───────────────────────────────────────────────────────────────────────────
   Panneau proximité (V1 chantier "affaires à proximité")
   Apparaît sous la carte dans .isis-geo-layers, n'apparaît que si centroïde
   calculable (zone géo non vide).
   ─────────────────────────────────────────────────────────────────────────── */
.isis-proximity-panel {
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
    padding: var(--isis-pad-compact);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius);
    background: var(--isis-surface);
}

/* Shell carte + panneau proximité côte-à-côte (V1.2 — 2026-05-22)
   La carte et le panneau « À proximité » sont des frères en flex row :
   carte à gauche prend l'espace restant, panneau à droite fixé à 320px.
   Sur mobile (< 900px) on passe en column → panneau sous la carte. */
.isis-zone-map-shell {
    flex: 1 1 auto;
    min-height: 240px;
    display: flex;
    flex-direction: row;
    align-items: stretch;
    gap: 0.75rem;
    min-width: 0;
}

.isis-zone-map-shell > .isis-affaires-map-host {
    flex: 1 1 auto;
    min-width: 0;
    min-height: 0;
}

/* Panneau proximité côte-à-côte de la carte (V1.2).
   - Largeur fixe 320px sur desktop
   - Toujours visible (le header contient le switch d'activation)
   - Quand le toggle est ON, le body scrolle si la liste dépasse la hauteur dispo
   - Override le padding pour rester compact en mode collapsed (juste le switch) */
.isis-zone-map-shell > .isis-proximity-panel {
    flex: 0 0 320px;
    align-self: stretch;
    min-height: 0;
    padding: 0.55rem 0.75rem 0.6rem;
    /* Le body interne scrolle, le header reste figé en tête */
    overflow: hidden;
}

/* Body scrollable — contient controls + list. Le header reste visible en haut. */
.isis-proximity-panel__body {
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
    overflow-y: auto;
    flex: 1 1 auto;
    min-height: 0;
}

/* Responsive : sur écran étroit, repasse en column → panneau sous la carte
   (comportement V1 d'origine). Largeur libérée pour la carte. */
@media (max-width: 900px) {
    .isis-zone-map-shell {
        flex-direction: column;
    }
    .isis-zone-map-shell > .isis-proximity-panel {
        flex: 0 0 auto;
        max-height: 50vh;
    }
}

.isis-proximity-panel__header {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-wrap: wrap;
}

/* Le titre du panneau utilise désormais .isis-section-title (B7). La règle
   ci-dessous reste pour la rétro-compatibilité d'éventuels call-sites externes. */
.isis-proximity-panel__title {
    font-weight: 600;
    font-size: 0.9rem;
    color: var(--isis-text);
}

.isis-proximity-panel__count {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 22px;
    height: 20px;
    padding: 0 6px;
    margin-left: auto;
    background: var(--isis-current-mod, var(--isis-accent));
    color: #ffffff;
    border-radius: var(--isis-radius);
    font-size: 0.72rem;
    font-weight: 600;
}

.isis-proximity-panel__controls {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.6rem;
    padding-top: 0.4rem;
    border-top: 1px dashed var(--isis-border);
}

.isis-proximity-panel__field {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    font-size: 0.82rem;
    color: var(--isis-text-muted);
}

/* ─────────────────────────────────────────────────────────────────────────
   Système de chip toggle unifié (B5 — refonte 2026-05-23)
   Remplace .isis-proximity-panel__lines-btn / __strate-btn / __type-label.
   Une seule classe `.isis-toggle-chip` couvre les 3 usages (toggle simple,
   toggle membre d'un group à choix unique, toggle checkbox couleur module).

   États :
     base : fond surface, border, texte muted
     hover : fond surface-alt, texte normal
     :focus-visible : outline accent
     .is-active : fond accent-soft, border accent-soft, texte accent

   Modificateur via style="..." inline (B8) — pour les chips type-colorés
   (AO/marché/demande/commande/collab/équipement), pose background/border/color
   via les vars `--isis-mod-*` calculées côté Razor (helper TypeChipStyle).
   ───────────────────────────────────────────────────────────────────────── */
.isis-toggle-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0.22rem 0.6rem;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius);
    cursor: pointer;
    color: var(--isis-text-muted);
    font-size: 0.78rem;
    font-weight: 500;
    transition: background-color 120ms, color 120ms, border-color 120ms, box-shadow 120ms;
}
.isis-toggle-chip:hover {
    background: var(--isis-surface-alt);
    color: var(--isis-text);
}
.isis-toggle-chip:focus-visible {
    outline: 2px solid var(--isis-accent);
    outline-offset: 1px;
}
.isis-toggle-chip.is-active {
    background: var(--isis-accent-soft);
    border-color: var(--isis-accent);
    color: var(--isis-accent);
    font-weight: 600;
}
/* Quand un chip a un style inline (B8 — TypeChipStyle), l'état actif est
   géré par les vars module CSS. Sinon (chip neutre genre Lignes/Strate),
   l'état actif retombe sur l'accent. */
.isis-toggle-chip[style*="--isis-mod-"].is-active {
    box-shadow: 0 0 0 1px currentColor;
}

/* Group de chips — segmented control horizontal */
.isis-toggle-chip-group {
    display: inline-flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.3rem;
}

/* Variant checkbox : les chips sont indépendants (toggles multiples),
   contre le pattern segmented (choix unique). Espacement légèrement plus
   généreux pour cliquer sans confusion entre 2 chips voisins. */
.isis-toggle-chip-group--checkbox {
    gap: 0.35rem;
    padding-top: 0.4rem;
    border-top: 1px dashed var(--isis-border);
}

/* Compas de filtre secteur (V1.3 option 7 — pattern boussole conservé).
   Grille 3×3 des 8 directions + bouton « Tous » au centre. Disposition
   spatiale = affordance immédiate (N en haut, S en bas). Pattern visuel
   *différent* du toggle-chip (par design — c'est un compas, pas un toggle). */
.isis-proximity-panel__sector {
    display: flex;
    align-items: flex-start;
    gap: 0.5rem;
    padding-top: 0.4rem;
    border-top: 1px dashed var(--isis-border);
}
.isis-proximity-panel__sector > .isis-section-subtitle {
    padding-top: 0.4rem;
}

.isis-proximity-panel__sector-grid {
    display: grid;
    grid-template-columns: repeat(3, 28px);
    grid-template-rows: repeat(3, 24px);
    gap: 2px;
}

.isis-proximity-panel__sector-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: 3px;
    cursor: pointer;
    color: var(--isis-text-muted);
    font-size: 0.65rem;
    font-weight: 600;
    padding: 0;
    transition: background-color 100ms, color 100ms, border-color 100ms;
}
.isis-proximity-panel__sector-btn:hover {
    background: var(--isis-surface-alt);
    color: var(--isis-text);
}
.isis-proximity-panel__sector-btn:focus-visible {
    outline: 2px solid var(--isis-accent);
    outline-offset: 1px;
}
.isis-proximity-panel__sector-btn.is-active {
    background: var(--isis-current-mod, var(--isis-accent));
    border-color: var(--isis-current-mod, var(--isis-accent));
    color: #ffffff;
}

/* Positionnement spatial dans le grid 3×3 (mime une boussole : N en haut, S en bas) */
.isis-proximity-panel__sector-btn--nw  { grid-column: 1; grid-row: 1; }
.isis-proximity-panel__sector-btn--n   { grid-column: 2; grid-row: 1; }
.isis-proximity-panel__sector-btn--ne  { grid-column: 3; grid-row: 1; }
.isis-proximity-panel__sector-btn--w   { grid-column: 1; grid-row: 2; }
.isis-proximity-panel__sector-btn--all { grid-column: 2; grid-row: 2; }
.isis-proximity-panel__sector-btn--e   { grid-column: 3; grid-row: 2; }
.isis-proximity-panel__sector-btn--sw  { grid-column: 1; grid-row: 3; }
.isis-proximity-panel__sector-btn--s   { grid-column: 2; grid-row: 3; }
.isis-proximity-panel__sector-btn--se  { grid-column: 3; grid-row: 3; }

/* Panneau proximité collapsible (C9) — bouton chevron de repli + variant
   colonne étroite pour le mode collapsed. */
.isis-proximity-panel__collapse-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    padding: 0;
    background: transparent;
    border: 1px solid transparent;
    border-radius: 4px;
    cursor: pointer;
    color: var(--isis-text-muted);
    transition: background-color 120ms, color 120ms;
}
.isis-proximity-panel__collapse-btn:hover {
    background: var(--isis-surface-alt);
    color: var(--isis-text);
}
.isis-proximity-panel__collapse-btn:focus-visible {
    outline: 2px solid var(--isis-accent);
    outline-offset: 1px;
}

/* État collapsed — panneau étroit : juste le chevron (et le compteur si dispo). */
.isis-proximity-panel--collapsed {
    flex: 0 0 44px !important;
    width: 44px !important;
    padding: 0.35rem 0.25rem !important;
}
.isis-proximity-panel--collapsed .isis-proximity-panel__header {
    flex-direction: column;
    align-items: center;
    gap: 0.4rem;
}

.isis-proximity-panel__hint,
.isis-proximity-panel__empty {
    font-size: 0.82rem;
    color: var(--isis-text-muted);
    padding: 0.4rem 0;
}

.isis-proximity-panel__list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    border-top: 1px dashed var(--isis-border);
    padding-top: 0.35rem;
}

.isis-proximity-panel__item {
    display: flex;
    align-items: center;
    gap: 0.55rem;
    padding: 0.3rem 0;
    font-size: 0.82rem;
}

.isis-proximity-panel__item + .isis-proximity-panel__item {
    border-top: 1px solid var(--isis-border);
}

/* Icône d'un item de la liste proximité — couleurs unifiées (B8).
   Le style est appliqué inline via @TypeChipStyle() côté Razor (background +
   border + color en vars module). Le contenu .rzi hérite de la color du parent. */
.isis-proximity-panel__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    border-radius: 50%;
    flex-shrink: 0;
}

.isis-proximity-panel__icon .rzi {
    font-size: 14px;
    color: inherit;
}

/* Ligne entreprise dans le popup ressource (icône domain + label). */
.isis-nearby-popup__entreprise {
    display: flex;
    align-items: center;
    gap: 0.25rem;
    font-size: 0.78rem;
    color: var(--isis-text-muted);
    margin-bottom: 0.35rem;
}

.isis-nearby-popup__entreprise .material-symbols-outlined {
    font-size: 14px;
}

.isis-proximity-panel__link {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    color: var(--isis-text);
    text-decoration: none;
    line-height: 1.2;
}

.isis-proximity-panel__link strong {
    font-weight: 600;
    font-size: 0.82rem;
}

.isis-proximity-panel__intitule {
    font-size: 0.76rem;
    color: var(--isis-text-muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.isis-proximity-panel__link:hover strong,
.isis-proximity-panel__link:focus-visible strong {
    color: var(--isis-accent);
    text-decoration: underline;
}

.isis-proximity-panel__distance {
    flex-shrink: 0;
    font-size: 0.76rem;
    color: var(--isis-text-muted);
    font-variant-numeric: tabular-nums;
}

.isis-proximity-panel__more {
    padding: 0.35rem 0 0;
    font-size: 0.76rem;
    color: var(--isis-text-muted);
    font-style: italic;
    border-top: 1px solid var(--isis-border);
    text-align: center;
}

/* ───────────────────────────────────────────────────────────────────────────
   Dashboard gesmaff V2 — bandeau alertes, funnel, trend, donut, leaderboards.
   ─────────────────────────────────────────────────────────────────────────── */

.isis-alert-banner-list {
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: 10px;
    box-shadow: var(--isis-elevation-1);
    padding: 0.85rem 1rem 0.75rem;
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
}

.isis-alert-banner-list__header {
    display: flex;
    align-items: baseline;
    gap: 0.5rem;
    padding-bottom: 0.4rem;
    border-bottom: 1px solid var(--isis-border);
}
/* INSTRUMENT BENTO : variante BOUTON (alertes dépliables — gescom uniquement, le
   dashboard gesmaff garde son <header> statique non interactif). */
button.isis-alert-banner-list__header {
    align-items: center;
    width: 100%;
    padding: 0 0 0.4rem;
    border: none;
    border-bottom: 1px solid var(--isis-border);
    background: none;
    font-family: inherit;
    text-align: left;
    cursor: pointer;
    color: inherit;
}
button.isis-alert-banner-list__header:hover .isis-alert-banner-list__title { color: var(--isis-danger); }
button.isis-alert-banner-list__header:focus-visible {
    outline: 2px solid color-mix(in srgb, var(--isis-danger) 55%, transparent);
    outline-offset: 2px;
    border-radius: var(--isis-radius-sm);
}
/* Repliée : pas de liste dessous → on retire le filet et le padding du header. */
.isis-alert-banner-list.is-collapsed { padding-bottom: 0.55rem; }
.isis-alert-banner-list.is-collapsed button.isis-alert-banner-list__header { border-bottom: none; padding-bottom: 0; }
.isis-alert-banner-list__summary {
    font-size: 0.82rem;
    color: var(--isis-text-muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
}

.isis-alert-banner-list__title {
    margin: 0;
    font-size: 0.95rem;
    font-weight: 600;
    color: var(--isis-text);
}

.isis-alert-banner-list__subtitle {
    font-size: 0.82rem;
    color: var(--isis-text-muted);
}

.isis-alert-banner-list__items {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
}

.isis-alert-banner-list__row {
    display: grid;
    grid-template-columns: 10px 1fr 32px;
    align-items: center;
    gap: 0.65rem;
    padding: 0.45rem 0.55rem;
    border-radius: 6px;
    background: var(--isis-surface-soft);
}

.isis-alert-banner-list__row.is-danger {
    border-color: var(--isis-danger);
    background: color-mix(in srgb, var(--isis-danger) 7%, var(--isis-surface));
}

.isis-alert-banner-list__row.is-warning {
    border-color: var(--isis-warning);
    background: color-mix(in srgb, var(--isis-warning) 7%, var(--isis-surface));
}

.isis-alert-banner-list__row.is-info {
    border-color: var(--isis-info, #3b82f6);
    background: color-mix(in srgb, var(--isis-info, #3b82f6) 7%, var(--isis-surface));
}

.isis-alert-banner-list__dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: currentColor;
    opacity: 0.85;
}

.isis-alert-banner-list__row.is-danger .isis-alert-banner-list__dot { color: var(--isis-danger); }
.isis-alert-banner-list__row.is-warning .isis-alert-banner-list__dot { color: var(--isis-warning); }
.isis-alert-banner-list__row.is-info .isis-alert-banner-list__dot { color: var(--isis-info, #3b82f6); }

.isis-alert-banner-list__main {
    display: flex;
    flex-direction: column;
    gap: 0.1rem;
    min-width: 0;
}

.isis-alert-banner-list__alert-title {
    font-size: 0.88rem;
    font-weight: 500;
    color: var(--isis-text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.isis-alert-banner-list__alert-detail {
    font-size: 0.78rem;
    color: var(--isis-text-muted);
}

.isis-alert-banner-list__action {
    border: 1px solid var(--isis-border);
    background: var(--isis-surface);
    border-radius: 6px;
    height: 28px;
    width: 28px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    color: var(--isis-text-muted);
    transition: all 0.15s ease;
}

.isis-alert-banner-list__action:hover,
.isis-alert-banner-list__action:focus-visible {
    color: var(--isis-current-mod, var(--isis-accent));
    border-color: var(--isis-current-mod, var(--isis-accent));
    outline: none;
}

.isis-alert-banner-list__footer {
    font-size: 0.8rem;
    color: var(--isis-text-muted);
    padding-top: 0.3rem;
    border-top: 1px dashed var(--isis-border);
}

/* ─── Funnel commercial ─────────────────────────────────────────────────── */

.isis-funnel {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    padding: 0;
}
/* Quand une rich-section ne contient qu'un funnel, on compacte son padding
   bas (le contenu compact rendait le padding 1rem visuellement excessif). */
.isis-rich-section:has(> .isis-funnel) {
    padding-bottom: 0.6rem;
}
.isis-rich-section:has(> .isis-funnel) .isis-rich-section__header {
    margin-bottom: 0;
    padding-bottom: 0.4rem;
}

.isis-funnel__row {
    display: grid;
    grid-template-columns: 140px 1fr 170px;
    align-items: center;
    gap: 0.75rem;
}

.isis-funnel__label {
    font-size: 0.82rem;
    color: var(--isis-text);
    font-weight: 500;
}

.isis-funnel__bar-wrap {
    position: relative;
    height: 18px;
    background: var(--isis-surface-soft);
    border-radius: 3px;
    overflow: hidden;
}

.isis-funnel__bar {
    height: 100%;
    background: var(--isis-current-mod, var(--isis-accent));
    border-radius: 3px;
    transition: width 0.3s ease;
}

.isis-funnel__bar.is-demande       { background: color-mix(in srgb, var(--isis-mod-gesmaff) 70%, var(--isis-text-muted)); }
.isis-funnel__bar.is-ao-cree       { background: color-mix(in srgb, var(--isis-mod-gesmaff) 80%, white); }
.isis-funnel__bar.is-ao-depose     { background: var(--isis-mod-gesmaff); }
.isis-funnel__bar.is-ao-obtenu     { background: var(--isis-success); }
.isis-funnel__bar.is-marche-signe  { background: color-mix(in srgb, var(--isis-success) 80%, var(--isis-mod-gesmaff)); }

.isis-funnel__count {
    position: absolute;
    top: 50%;
    left: 0.45rem;
    transform: translateY(-50%);
    color: #fff;
    font-weight: 600;
    font-size: 0.75rem;
    text-shadow: 0 1px 2px rgba(0,0,0,0.35);
    font-variant-numeric: tabular-nums;
}

.isis-funnel__sub {
    font-size: 0.74rem;
    color: var(--isis-text-muted);
    font-variant-numeric: tabular-nums;
}

/* ─── Layout 2 colonnes pour les sections dashboard ────────────────────── */

.isis-dash-2col {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 1.1rem;
}

/* Variante asymétrique 3 colonnes : la 1re section occupe 2/3, la 2de 1/3
   (mockup ARCHITECT : Funnel|Donut et Quota|Mix). */
.isis-dash-2col--2-1 { grid-template-columns: 2fr 1fr; }

/* Une section seule occupe toute la largeur de la mosaïque (dégradation gracieuse
   quand son binôme n'a pas de données — ex : pas de comparaison multi-entreprises). */
.isis-dash-2col > .isis-span-2 { grid-column: 1 / -1; }


/* Grilles vues lecture seule Gescom (commandes / factures issues des offres de prix). */
.isis-grid--gescom-vente-cmd .isis-grid__head,
.isis-grid--gescom-vente-cmd .isis-grid__row {
    /* Colonne « Offre de prix » 130 → 178px : le badge de référence DEDA-YYYYMM-NNNNNN
       était tronqué et collé à la colonne Client. 178px absorbe les réf. aux chiffres
       larges (0/9) — la police du badge est proportionnelle, pas monospace. */
    grid-template-columns: 40px minmax(160px, 1.5fr) 178px minmax(140px, 1.2fr) 130px 110px 72px;
}
.isis-grid--gescom-vente-fac .isis-grid__head,
.isis-grid--gescom-vente-fac .isis-grid__row {
    grid-template-columns: 40px minmax(150px, 1.4fr) 120px minmax(140px, 1.2fr) 130px 105px 105px 72px;
}

/* Grilles agrégées des hubs (axes Client / Mois / Entreprise). Ici et non dans le .razor.css
   de la page : isis-grid-config.js ne lit que des sélecteurs `.isis-grid--<clé> .isis-grid__row`
   exacts, que l'isolation CSS suffixe en [b-xxx] — la grille perdait son bouton « Colonnes,
   ordre et densité », et la règle isolée, plus spécifique, écraserait de toute façon la sienne.
   Une clé par grille : les réglages sont rangés par clé, et ces six grilles n'ont pas les mêmes
   en-têtes. Commandes : Client/Entreprise = 8 colonnes, Mois = 7 (pas d'Encours/Échu). */
.isis-grid--gescom-hub-cmd-client .isis-grid__head,
.isis-grid--gescom-hub-cmd-client .isis-grid__row,
.isis-grid--gescom-hub-cmd-entreprise .isis-grid__head,
.isis-grid--gescom-hub-cmd-entreprise .isis-grid__row {
    grid-template-columns: minmax(160px, 1.6fr) 84px 64px 116px 116px 130px 104px 96px;
}
/* Dernière colonne (Reste à facturer) à 150px : à 116px l'en-tête en capitales se tronquait. */
.isis-grid--gescom-hub-cmd-mois .isis-grid__head,
.isis-grid--gescom-hub-cmd-mois .isis-grid__row {
    grid-template-columns: minmax(160px, 1.6fr) 84px 64px 116px 116px 116px 150px;
}
/* Factures : les trois axes ont la même forme (libellé, devise, compte, 4 montants). */
.isis-grid--gescom-hub-fac-client .isis-grid__head,
.isis-grid--gescom-hub-fac-client .isis-grid__row,
.isis-grid--gescom-hub-fac-mois .isis-grid__head,
.isis-grid--gescom-hub-fac-mois .isis-grid__row,
.isis-grid--gescom-hub-fac-entreprise .isis-grid__head,
.isis-grid--gescom-hub-fac-entreprise .isis-grid__row {
    grid-template-columns: minmax(160px, 1.6fr) 84px 64px 116px 116px 130px 116px;
}

/* ───────── Catalogue de rapports commerciaux (/gescom/rapports) ───────── */
.isis-master-detail--rapports { grid-template-columns: 340px minmax(0, 1fr); }
@media (max-width: 1000px) { .isis-master-detail--rapports { grid-template-columns: 1fr; } }

.isis-report-cat__group { margin-bottom: 1rem; }
.isis-report-cat__group-title {
    font-size: 0.68rem; text-transform: uppercase; letter-spacing: 0.06em;
    color: var(--isis-text-soft); font-weight: 600; margin: 0 0 0.4rem 0.25rem;
}
.isis-report-cat__item {
    display: flex; align-items: flex-start; gap: 0.6rem; width: 100%;
    text-align: left; background: var(--isis-surface);
    border: 1px solid var(--isis-border); border-radius: var(--isis-radius-sm);
    padding: 0.6rem 0.7rem; margin-bottom: 0.4rem; cursor: pointer;
    transition: border-color .14s ease, background .14s ease, box-shadow .14s ease;
}
.isis-report-cat__item:hover { border-color: var(--isis-mod-gescom); background: var(--isis-surface-alt); }
.isis-report-cat__item:focus-visible { outline: none; box-shadow: var(--isis-elevation-focus); }
.isis-report-cat__item.is-active {
    border-color: var(--isis-mod-gescom);
    box-shadow: inset 3px 0 0 0 var(--isis-mod-gescom);
    background: color-mix(in srgb, var(--isis-mod-gescom) 6%, var(--isis-surface));
}
.isis-report-cat__icon {
    width: 30px; height: 30px; border-radius: 8px; flex-shrink: 0; display: inline-grid; place-items: center;
    background: color-mix(in srgb, var(--isis-mod-gescom) 11%, var(--isis-surface)); color: var(--isis-mod-gescom);
}
.isis-report-cat__text { display: flex; flex-direction: column; gap: 0.1rem; min-width: 0; }
.isis-report-cat__name { font-size: 0.85rem; font-weight: 600; color: var(--isis-text); }
.isis-report-cat__desc { font-size: 0.72rem; color: var(--isis-text-muted); line-height: 1.3; }

/* Entrée de catalogue INDISPONIBLE (reprise de données) : désactivée et explicite, jamais
   masquée — un import qui disparaît sans explication est pire qu'un import refusé qui s'explique
   (DESIGN.md, « une question sans données est DÉSACTIVÉE, jamais masquée »).

   `[aria-disabled="true"]` et NON l'attribut `disabled` : un bouton `disabled` sort de l'ordre de
   tabulation et ne reçoit aucun événement pointeur, donc la RAISON du refus devient inatteignable
   au clavier comme à la souris. Même langage que .isis-filter-facet-btn[aria-disabled] : pas de
   pointer-events:none, qui rebloquerait ce qu'on vient d'ouvrir. Le geste est neutralisé côté
   serveur (Select()), pas par le navigateur.

   PAS D'OPACITÉ GLOBALE. `opacity` composite le bouton ENTIER vers le fond de page : la raison
   tombait alors à 3,28:1 en clair et 3,88:1 en sombre (mesuré contre les tokens :root, seuil AA
   4,5:1). L'état se porte par les tokens — fond -alt, nom atténué, icône neutralisée — et la
   raison, elle, reste en pleine encre : c'est le seul texte qui explique le refus. */
.isis-report-cat__item[aria-disabled="true"] {
    cursor: not-allowed;
    background: var(--isis-surface-alt);
}
.isis-report-cat__item[aria-disabled="true"]:hover {
    border-color: var(--isis-border);
    background: var(--isis-surface-alt);
}
.isis-report-cat__item[aria-disabled="true"] .isis-report-cat__name { color: var(--isis-text-muted); }
.isis-report-cat__item[aria-disabled="true"] .isis-report-cat__icon {
    background: var(--isis-surface);
    color: var(--isis-text-soft);
}
/* Raison d'inaccessibilité, dite UNE fois par périmètre en tête de groupe (gescom porte six
   importeurs). Pleine opacité, encre --isis-text-muted : 6,57:1 en clair, 7,60:1 en sombre. */
.isis-report-cat__group-note {
    margin: 0 0 0.4rem 0.25rem; max-width: 68ch;
    font-size: 0.72rem; line-height: 1.35; color: var(--isis-text-muted);
}
/* Pastille d'état. BadgeStyle.Light tient l'encre (8,66:1 en clair, 10,29:1 en sombre) mais son
   fond Radzen (--rz-base-200 / --rz-base-600) se confond avec la carte : 1,07:1 en clair. Le
   liseré rend la pastille lisible comme FORME — WCAG 1.4.11 n'est pas engagé (l'état est porté
   par le mot, pas par la silhouette), c'est une exigence de charte, pas de conformité. */
.isis-report-cat__acces { display: inline-flex; margin-top: 0.3rem; }
.isis-report-cat__acces .rz-badge { border: 1px solid var(--isis-border-strong); }

.isis-report-result__header {
    display: flex; align-items: flex-start; justify-content: space-between; gap: 1rem;
    margin-bottom: 0.85rem; flex-wrap: wrap;
}
.isis-report-result__title { font-size: 1.05rem; font-weight: 700; color: var(--isis-text); margin: 0; letter-spacing: -0.01em; }
.isis-report-result__subtitle { font-size: 0.75rem; color: var(--isis-text-muted); }

.isis-report-table-wrap { overflow-x: auto; border: 1px solid var(--isis-border); border-radius: var(--isis-radius-sm); }
.isis-report-table { width: 100%; border-collapse: collapse; font-size: 0.82rem; }
.isis-report-table thead th {
    position: sticky; top: 0; background: var(--isis-surface-alt);
    text-align: left; font-size: 0.68rem; text-transform: uppercase; letter-spacing: 0.05em;
    color: var(--isis-text-muted); font-weight: 600; padding: 0.55rem 0.75rem;
    border-bottom: 1px solid var(--isis-border); white-space: nowrap;
}
.isis-report-table tbody td {
    padding: 0.5rem 0.75rem; border-bottom: 1px solid var(--isis-border-soft); color: var(--isis-text);
}
.isis-report-table tbody tr:last-child td { border-bottom: none; }
.isis-report-table tbody tr:hover { background: var(--isis-surface-alt); }
.isis-report-table .is-right { text-align: right; }
.isis-report-table .is-num { font-family: var(--isis-cockpit-mono); font-variant-numeric: tabular-nums; }

/* ───────── Reprise de données (/admin/reprise) ───────── */
.isis-reprise-actions { display: flex; flex-wrap: wrap; gap: 0.6rem; margin-top: 0.85rem; }
.isis-reprise-upload { position: relative; overflow: hidden; cursor: pointer; }
.isis-reprise-upload input[type="file"] {
    position: absolute; inset: 0; opacity: 0; cursor: pointer; font-size: 0; width: 100%; height: 100%;
}
/* Indice de mode fondu dans le header (le bandeau d'info fusionné). */
.isis-rich-header__hint { font-size: var(--isis-fs-sm); color: var(--isis-text-muted); margin-top: .3rem; }
/* Flux d'import : section sans chrome de carte (l'en-tête de l'importeur est fusionné dans le header). */
.isis-rich-section--flush { margin-top: .6rem; padding: 0; border: 0; background: transparent; box-shadow: none; }
.isis-reprise-cols { display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem; margin-top: 0.85rem; }
.isis-reprise-cols__title { font-size: 0.75rem; color: var(--isis-text-muted); margin-right: 0.25rem; }
.isis-reprise-stats { display: flex; flex-wrap: wrap; gap: 0.6rem; margin-bottom: 0.85rem; }
.isis-reprise-stat {
    font-size: 0.85rem; color: var(--isis-text-muted);
    background: var(--isis-surface-alt); border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-pill); padding: 0.25rem 0.7rem;
}
.isis-reprise-stat b { color: var(--isis-text); font-family: var(--isis-cockpit-mono); }
.isis-reprise-stat.is-ok { background: var(--isis-success-soft); border-color: color-mix(in srgb, var(--isis-success) 25%, var(--isis-border)); }
.isis-reprise-stat.is-ok b { color: var(--isis-success); }
.isis-reprise-stat.is-danger { background: var(--isis-danger-soft); border-color: color-mix(in srgb, var(--isis-danger) 25%, var(--isis-border)); }
.isis-reprise-stat.is-danger b { color: var(--isis-danger); }
/* Verdict « à compléter » d'un essai à blanc : une valeur attendue est absente, ce qui n'est ni une
   erreur (la ligne s'importe) ni un succès (elle restera à chiffrer). Texte en --isis-warning-text,
   jamais --isis-warning, qui ne tient pas AA sur son propre soft (DESIGN.md). */
.isis-reprise-stat.is-warn { background: var(--isis-warning-soft); border-color: color-mix(in srgb, var(--isis-warning) 25%, var(--isis-border)); }
.isis-reprise-stat.is-warn b { color: var(--isis-warning-text); }
.isis-reprise-issues { margin-top: 0.6rem; max-height: 360px; overflow-y: auto; }
/* Reprise — barre compacte au-dessus du tableur (compteur / mode / actions / navigateur) */
.isis-reprise-bar { display: flex; align-items: center; gap: .75rem; flex-wrap: wrap; padding: .4rem .6rem; border: 1px solid var(--isis-border); border-radius: var(--isis-radius); background: var(--isis-surface, #fff); margin-bottom: .4rem; }
.isis-reprise-bar__stats { display: flex; flex-wrap: wrap; align-items: center; gap: .4rem; }
.isis-reprise-bar__actions { display: flex; align-items: center; gap: .4rem; }
.isis-reprise-bar__mode { display: flex; align-items: center; gap: .35rem; }
.isis-reprise-bar__nav { display: flex; align-items: center; gap: .25rem; margin-left: auto; }
.isis-reprise-bar__navcount { font-size: var(--isis-fs-sm); color: var(--isis-text-muted); min-width: 2.5rem; text-align: center; }
/* Reprise — habillage tableur (RadzenSpreadsheet ne suit pas les tokens isis) */
.isis-reprise-sheet { border: 1px solid var(--isis-border); border-radius: var(--isis-radius); overflow: hidden; }
.isis-reprise-sheet__toolbar { display: flex; align-items: center; gap: .75rem; padding: .5rem .75rem; border-bottom: 1px solid var(--isis-border); background: color-mix(in srgb, var(--isis-mod-admin) 4%, transparent); }
.isis-reprise-sheet__hint { font-size: var(--isis-fs-sm); color: var(--isis-text-muted); }

@media (max-width: 1100px) {
    .isis-dash-2col { grid-template-columns: 1fr; }
    .isis-dash-2col--2-1 { grid-template-columns: 1fr; }
}

.isis-dash-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.5rem;
    padding: 2rem 1rem;
    color: var(--isis-text-muted);
    text-align: center;
}

.isis-dash-empty strong {
    color: var(--isis-text);
    font-size: 0.95rem;
    font-weight: 600;
}

.isis-dash-empty span {
    font-size: 0.85rem;
}

.isis-dash-empty .rz-icon {
    font-size: 32px !important;
    color: var(--isis-text-muted);
    opacity: 0.6;
}

/* ─── Trend chart SVG ──────────────────────────────────────────────────── */

.isis-trend-chart {
    width: 100%;
    height: auto;
    display: block;
}

.isis-trend-chart__grid {
    stroke: var(--isis-border);
    stroke-width: 1;
    stroke-dasharray: 2 3;
}

.isis-trend-chart__bar {
    fill: color-mix(in srgb, var(--isis-mod-gesmaff) 30%, var(--isis-surface));
    stroke: var(--isis-mod-gesmaff);
    stroke-width: 1;
}

.isis-trend-chart__line {
    fill: none;
    stroke: var(--isis-success);
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.isis-trend-chart__point {
    fill: var(--isis-surface);
    stroke: var(--isis-success);
    stroke-width: 2;
}

.isis-trend-chart__point:hover {
    stroke-width: 3;
    r: 5;
}

.isis-trend-chart__xlabel,
.isis-trend-chart__ylabel,
.isis-trend-chart__ylabel-right {
    font-size: 11px;
    fill: var(--isis-text-muted);
    font-family: var(--isis-font);
}

.isis-trend-chart__legend {
    font-size: 12px;
    fill: var(--isis-text);
    font-family: var(--isis-font);
}

/* ─── Donut chart ──────────────────────────────────────────────────────── */

.isis-donut-wrap {
    display: grid;
    grid-template-columns: 200px 1fr;
    align-items: center;
    gap: 1.2rem;
    padding: 0.5rem 0;
}

@media (max-width: 720px) {
    .isis-donut-wrap { grid-template-columns: 1fr; justify-items: center; }
}

.isis-donut {
    width: 200px;
    height: 200px;
    display: block;
}

.isis-donut__slice {
    stroke: var(--isis-surface);
    stroke-width: 1;
    transition: opacity 0.15s ease;
}

.isis-donut__slice:hover { opacity: 0.85; }

.isis-donut__slice.is-prevu      { fill: color-mix(in srgb, var(--isis-mod-gesmaff) 30%, var(--isis-surface)); }
.isis-donut__slice.is-depose     { fill: color-mix(in srgb, var(--isis-mod-gesmaff) 60%, var(--isis-surface)); }
.isis-donut__slice.is-obtenu     { fill: var(--isis-success); }
.isis-donut__slice.is-perdu      { fill: color-mix(in srgb, var(--isis-danger) 60%, var(--isis-surface)); }
.isis-donut__slice.is-abandonne  { fill: color-mix(in srgb, var(--isis-text-muted) 60%, var(--isis-surface)); }
.isis-donut__slice.is-annule     { fill: color-mix(in srgb, var(--isis-text-muted) 30%, var(--isis-surface)); }

.isis-donut__total {
    font-size: 22px;
    font-weight: 700;
    fill: var(--isis-text);
    font-family: var(--isis-font);
}

.isis-donut__total-label {
    font-size: 11px;
    fill: var(--isis-text-muted);
    font-family: var(--isis-font);
    text-transform: uppercase;
    letter-spacing: 0.05em;
}

.isis-donut__legend {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
}

.isis-donut__legend-item {
    display: grid;
    grid-template-columns: 12px 1fr auto auto;
    align-items: center;
    gap: 0.5rem;
    padding: 0.2rem 0;
}

.isis-donut__legend-dot {
    width: 10px;
    height: 10px;
    border-radius: 2px;
}

.isis-donut__legend-dot.is-prevu      { background: color-mix(in srgb, var(--isis-mod-gesmaff) 30%, var(--isis-surface)); }
.isis-donut__legend-dot.is-depose     { background: color-mix(in srgb, var(--isis-mod-gesmaff) 60%, var(--isis-surface)); }
.isis-donut__legend-dot.is-obtenu     { background: var(--isis-success); }
.isis-donut__legend-dot.is-perdu      { background: color-mix(in srgb, var(--isis-danger) 60%, var(--isis-surface)); }
.isis-donut__legend-dot.is-abandonne  { background: color-mix(in srgb, var(--isis-text-muted) 60%, var(--isis-surface)); }
.isis-donut__legend-dot.is-annule     { background: color-mix(in srgb, var(--isis-text-muted) 30%, var(--isis-surface)); }

.isis-donut__legend-label {
    font-size: 0.85rem;
    color: var(--isis-text);
}

.isis-donut__legend-value {
    font-size: 0.82rem;
    color: var(--isis-text);
    font-variant-numeric: tabular-nums;
    font-weight: 600;
}

.isis-donut__legend-pct {
    font-size: 0.78rem;
    color: var(--isis-text-muted);
    font-variant-numeric: tabular-nums;
}

/* ─── Leaderboard (Top clients / Demandes / Owner perf) ────────────────── */

.isis-leaderboard {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
}

.isis-leaderboard__row {
    display: grid;
    grid-template-columns: 1fr 140px 130px;
    align-items: center;
    gap: 0.75rem;
    padding: 0.45rem 0.55rem;
    border-radius: 6px;
    background: var(--isis-surface-soft);
    transition: background 0.15s ease;
}

.isis-leaderboard__row:hover {
    background: color-mix(in srgb, var(--isis-current-mod, var(--isis-mod-gesmaff)) 6%, var(--isis-surface));
}

.isis-leaderboard--demande .isis-leaderboard__row {
    grid-template-columns: 10px 1fr auto 32px;
}

.isis-leaderboard__label {
    display: flex;
    flex-direction: column;
    gap: 0.1rem;
    min-width: 0;
}

.isis-leaderboard__name {
    font-size: 0.88rem;
    font-weight: 500;
    color: var(--isis-text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.isis-leaderboard__sub {
    font-size: 0.78rem;
    color: var(--isis-text-muted);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.isis-leaderboard__bar-wrap {
    height: 8px;
    background: var(--isis-surface);
    border-radius: 4px;
    overflow: hidden;
    border: 1px solid var(--isis-border);
}

.isis-leaderboard__bar {
    height: 100%;
    background: var(--isis-mod-gesmaff);
    border-radius: 4px;
    transition: width 0.3s ease;
}

.isis-leaderboard__value {
    text-align: right;
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--isis-text);
    font-variant-numeric: tabular-nums;
}

.isis-leaderboard__age {
    font-size: 0.82rem;
    color: var(--isis-text-muted);
    font-variant-numeric: tabular-nums;
}

.isis-leaderboard__dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
}

.isis-leaderboard__dot.is-ok        { background: var(--isis-success); }
.isis-leaderboard__dot.is-warning   { background: var(--isis-warning); }
.isis-leaderboard__dot.is-danger    { background: var(--isis-danger); }

.isis-leaderboard__action {
    border: 1px solid var(--isis-border);
    background: var(--isis-surface);
    border-radius: 6px;
    height: 28px;
    width: 28px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    color: var(--isis-text-muted);
    transition: all 0.15s ease;
}

.isis-leaderboard__action:hover,
.isis-leaderboard__action:focus-visible {
    color: var(--isis-current-mod, var(--isis-accent));
    border-color: var(--isis-current-mod, var(--isis-accent));
    outline: none;
}

/* ─── Carte des affaires (wrapper Leaflet) ─────────────────────────────── */

.isis-dash-map {
    border: 1px solid var(--isis-border);
    border-radius: 8px;
    overflow: hidden;
    background: var(--isis-surface-soft);
}

/* ─── Grille performance par owner ─────────────────────────────────────── */

.isis-grid--gesmaff-owner-perf {
    --isis-grid-min-width: 900px;
}

.isis-grid--gesmaff-owner-perf .isis-grid__head,
.isis-grid--gesmaff-owner-perf .isis-grid__row {
    grid-template-columns: 1.4fr 0.7fr 0.7fr 0.7fr 0.7fr 1fr;
}

.isis-grid__taux {
    font-variant-numeric: tabular-nums;
    font-weight: 600;
}

.isis-grid__taux.is-success { color: var(--isis-success); }
.isis-grid__taux.is-warning { color: var(--isis-warning); }
.isis-grid__taux.is-muted   { color: var(--isis-text-muted); }

/* ───────────────────────────────────────────────────────────────────────────
   Dashboard gescom V2 — couleurs sémantiques funnel + donut statuts devis.
   Calque pattern gesmaff, adapté au cycle devis (10 statuts) et au module
   gescom. La graduation va du brouillon (pâle) vers signé (saturé).
   ─────────────────────────────────────────────────────────────────────────── */

/* Funnel devis — gradient brouillon → envoyé → signé */
.isis-funnel__bar.is-gescom-draft     { background: color-mix(in srgb, var(--isis-mod-gescom) 25%, var(--isis-surface)); }
.isis-funnel__bar.is-gescom-pending   { background: color-mix(in srgb, var(--isis-mod-gescom) 50%, var(--isis-surface)); }
.isis-funnel__bar.is-gescom-approved  { background: color-mix(in srgb, var(--isis-mod-gescom) 75%, var(--isis-surface)); }
.isis-funnel__bar.is-gescom-sent      { background: var(--isis-mod-gescom); }
.isis-funnel__bar.is-gescom-accepted  { background: var(--isis-success); }

/* Donut devis par statut */
.isis-donut__slice.is-gescom-draft        { fill: color-mix(in srgb, var(--isis-mod-gescom) 20%, var(--isis-surface)); }
.isis-donut__slice.is-gescom-pending      { fill: color-mix(in srgb, var(--isis-mod-gescom) 45%, var(--isis-surface)); }
.isis-donut__slice.is-gescom-approved     { fill: color-mix(in srgb, var(--isis-mod-gescom) 70%, var(--isis-surface)); }
.isis-donut__slice.is-gescom-sent         { fill: var(--isis-mod-gescom); }
.isis-donut__slice.is-gescom-accepted     { fill: var(--isis-success); }
.isis-donut__slice.is-gescom-converted    { fill: color-mix(in srgb, var(--isis-success) 75%, var(--isis-mod-gescom)); }
.isis-donut__slice.is-gescom-rejected     { fill: color-mix(in srgb, var(--isis-danger) 70%, var(--isis-surface)); }
.isis-donut__slice.is-gescom-cancelled    { fill: color-mix(in srgb, var(--isis-text-muted) 70%, var(--isis-surface)); }
.isis-donut__slice.is-gescom-expired      { fill: color-mix(in srgb, var(--isis-warning) 70%, var(--isis-surface)); }
.isis-donut__slice.is-gescom-revised      { fill: color-mix(in srgb, var(--isis-mod-gescom) 35%, var(--isis-text-muted)); }
.isis-donut__slice.is-gescom-default      { fill: var(--isis-text-muted); }

/* Legend dots — memes couleurs en background plutot que fill */
.isis-donut__legend-dot.is-gescom-draft        { background: color-mix(in srgb, var(--isis-mod-gescom) 20%, var(--isis-surface)); }
.isis-donut__legend-dot.is-gescom-pending      { background: color-mix(in srgb, var(--isis-mod-gescom) 45%, var(--isis-surface)); }
.isis-donut__legend-dot.is-gescom-approved     { background: color-mix(in srgb, var(--isis-mod-gescom) 70%, var(--isis-surface)); }
.isis-donut__legend-dot.is-gescom-sent         { background: var(--isis-mod-gescom); }
.isis-donut__legend-dot.is-gescom-accepted     { background: var(--isis-success); }
.isis-donut__legend-dot.is-gescom-converted    { background: color-mix(in srgb, var(--isis-success) 75%, var(--isis-mod-gescom)); }
.isis-donut__legend-dot.is-gescom-rejected     { background: color-mix(in srgb, var(--isis-danger) 70%, var(--isis-surface)); }
.isis-donut__legend-dot.is-gescom-cancelled    { background: color-mix(in srgb, var(--isis-text-muted) 70%, var(--isis-surface)); }
.isis-donut__legend-dot.is-gescom-expired      { background: color-mix(in srgb, var(--isis-warning) 70%, var(--isis-surface)); }
.isis-donut__legend-dot.is-gescom-revised      { background: color-mix(in srgb, var(--isis-mod-gescom) 35%, var(--isis-text-muted)); }
.isis-donut__legend-dot.is-gescom-default      { background: var(--isis-text-muted); }

/* Grille performance par owner gescom */
.isis-grid--gescom-owner-perf {
    --isis-grid-min-width: 900px;
}
.isis-grid--gescom-owner-perf .isis-grid__head,
.isis-grid--gescom-owner-perf .isis-grid__row {
    grid-template-columns: 1.4fr 0.7fr 0.7fr 0.7fr 0.7fr 1.1fr;
}

/* ───────────────────────────────────────────────────────────────────────────
   Dashboard gescom — Performance marges (distribution devis vs seuils
   plancher/cible/max). Composé de :
   1. Barre empilée 100% pour vue d'ensemble (proportion par bucket)
   2. Liste détail (label + barre horizontale + count + valeur)
   3. Drill-down "top devis sous plancher" sur leaderboard
   Sémantique couleur : rouge=plancher / orange=sous-cible / vert=sain /
   bleu=au-dessus max / gris=non classable.
   ─────────────────────────────────────────────────────────────────────────── */

.isis-margin-perf {
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

.isis-margin-perf__stack {
    display: flex;
    height: 28px;
    border-radius: 6px;
    overflow: hidden;
    background: var(--isis-surface-soft);
    border: 1px solid var(--isis-border);
}

.isis-margin-perf__stack-seg {
    display: flex;
    align-items: center;
    justify-content: center;
    min-width: 4px;
    transition: width 0.3s ease, opacity 0.15s ease;
}

.isis-margin-perf__stack-seg:hover {
    opacity: 0.88;
}

.isis-margin-perf__stack-label {
    font-size: 0.72rem;
    font-weight: 600;
    color: #fff;
    text-shadow: 0 1px 2px rgba(0,0,0,0.35);
    font-variant-numeric: tabular-nums;
    padding: 0 0.25rem;
}

/* Couleurs sémantiques des 5 buckets */
.isis-margin-perf__stack-seg.is-sous-plancher,
.isis-margin-perf__bar.is-sous-plancher,
.isis-margin-perf__dot.is-sous-plancher        { background: var(--isis-danger); }

.isis-margin-perf__stack-seg.is-entre-plancher-cible,
.isis-margin-perf__bar.is-entre-plancher-cible,
.isis-margin-perf__dot.is-entre-plancher-cible { background: var(--isis-warning); }

.isis-margin-perf__stack-seg.is-entre-cible-max,
.isis-margin-perf__bar.is-entre-cible-max,
.isis-margin-perf__dot.is-entre-cible-max      { background: var(--isis-success); }

.isis-margin-perf__stack-seg.is-au-dessus-max,
.isis-margin-perf__bar.is-au-dessus-max,
.isis-margin-perf__dot.is-au-dessus-max        { background: var(--isis-mod-gescom); }

.isis-margin-perf__stack-seg.is-non-classifie,
.isis-margin-perf__bar.is-non-classifie,
.isis-margin-perf__dot.is-non-classifie        { background: color-mix(in srgb, var(--isis-text-muted) 60%, var(--isis-surface)); }

.isis-margin-perf__list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
}

.isis-margin-perf__row {
    display: grid;
    grid-template-columns: 280px 1fr 180px;
    align-items: center;
    gap: 0.85rem;
    padding: 0.5rem 0.6rem;
    border-radius: 6px;
    background: var(--isis-surface-soft);
    transition: background 0.15s ease;
}

.isis-margin-perf__row:hover {
    background: color-mix(in srgb, var(--isis-mod-gescom) 5%, var(--isis-surface));
}

.isis-margin-perf__label {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    min-width: 0;
}

.isis-margin-perf__dot {
    width: 10px;
    height: 10px;
    border-radius: 50%;
    flex-shrink: 0;
}

.isis-margin-perf__name {
    font-size: 0.88rem;
    font-weight: 500;
    color: var(--isis-text);
    flex-shrink: 0;
}

.isis-margin-perf__hint {
    font-size: 0.76rem;
    color: var(--isis-text-muted);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.isis-margin-perf__bar-wrap {
    height: 10px;
    background: var(--isis-surface);
    border-radius: 5px;
    overflow: hidden;
    border: 1px solid var(--isis-border);
}

.isis-margin-perf__bar {
    height: 100%;
    border-radius: 5px;
    transition: width 0.3s ease;
}

.isis-margin-perf__counts {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 0.1rem;
    font-variant-numeric: tabular-nums;
}

.isis-margin-perf__count {
    font-size: 0.82rem;
    color: var(--isis-text-muted);
}

.isis-margin-perf__value {
    font-size: 0.88rem;
    font-weight: 600;
    color: var(--isis-text);
}

.isis-margin-perf__drill {
    margin-top: 0.6rem;
    padding-top: 0.8rem;
    border-top: 1px dashed var(--isis-border);
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.isis-margin-perf__drill-title {
    margin: 0;
    font-size: 0.88rem;
    font-weight: 600;
    color: var(--isis-text);
    display: flex;
    align-items: center;
    gap: 0.4rem;
}

@media (max-width: 900px) {
    .isis-margin-perf__row {
        grid-template-columns: 1fr;
        gap: 0.4rem;
    }
    .isis-margin-perf__counts {
        flex-direction: row;
        gap: 0.5rem;
    }
}

/* ───────────────────────────────────────────────────────────────────────────
   Phase A — chip warning + section Comparaison entreprises.
   Le chip warn signale une entreprise sans seuils marge configures.
   La section comparaison utilise une grille standard ISIS avec une colonne
   speciale "Contribution" qui affiche une barre + le %.
   ─────────────────────────────────────────────────────────────────────────── */

.isis-chip__warn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 14px;
    height: 14px;
    border-radius: 50%;
    background: var(--isis-warning);
    color: #fff;
    font-size: 0.7rem;
    font-weight: 700;
    margin-left: 0.35rem;
}

.isis-grid--gescom-ent-comparison {
    --isis-grid-min-width: 980px;
}

.isis-grid--gescom-ent-comparison .isis-grid__head,
.isis-grid--gescom-ent-comparison .isis-grid__row {
    grid-template-columns: 1.6fr 1.1fr 1.4fr 1.1fr 0.8fr 0.9fr 50px;
}

.isis-grid__col-sublabel {
    font-size: 0.76rem;
    color: var(--isis-text-muted);
    margin-top: 0.1rem;
}

.isis-ent-comp__contrib {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.isis-ent-comp__contrib-bar-wrap {
    flex: 1;
    height: 8px;
    background: var(--isis-surface);
    border-radius: 4px;
    overflow: hidden;
    border: 1px solid var(--isis-border);
}

.isis-ent-comp__contrib-bar {
    height: 100%;
    background: var(--isis-mod-gescom);
    border-radius: 4px;
    transition: width 0.3s ease;
}

.isis-ent-comp__contrib-pct {
    font-size: 0.82rem;
    color: var(--isis-text);
    font-variant-numeric: tabular-nums;
    font-weight: 600;
    min-width: 50px;
    text-align: right;
}

/* ───────────────────────────────────────────────────────────────────────────
   Phase B — Progression vs quota + grille admin quotas.
   ─────────────────────────────────────────────────────────────────────────── */

.isis-quota-progress {
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
}

.isis-quota-progress__numbers {
    display: flex;
    align-items: baseline;
    gap: 0.4rem;
    font-variant-numeric: tabular-nums;
}

.isis-quota-progress__realise {
    font-size: 1.4rem;
    font-weight: 700;
    color: var(--isis-text);
}

.isis-quota-progress__sep      { color: var(--isis-text-muted); font-size: 1.1rem; }
.isis-quota-progress__quota    { color: var(--isis-text-muted); font-size: 1.1rem; }

.isis-quota-progress__pct {
    margin-left: auto;
    font-size: 1.6rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

.isis-quota-progress__pct.is-success { color: var(--isis-success); }
.isis-quota-progress__pct.is-warning { color: var(--isis-warning); }
.isis-quota-progress__pct.is-danger  { color: var(--isis-danger); }
.isis-quota-progress__pct.is-muted   { color: var(--isis-text-muted); }

.isis-quota-progress__bar-wrap {
    height: 18px;
    background: var(--isis-surface-soft);
    border-radius: 9px;
    overflow: hidden;
    border: 1px solid var(--isis-border);
}

.isis-quota-progress__bar {
    height: 100%;
    border-radius: 9px;
    transition: width 0.5s ease;
    background: var(--isis-mod-gescom);
}

.isis-quota-progress__bar.is-success { background: var(--isis-success); }
.isis-quota-progress__bar.is-warning { background: var(--isis-warning); }
.isis-quota-progress__bar.is-danger  { background: var(--isis-danger); }

.isis-quota-progress__overshoot {
    padding: 0.45rem 0.6rem;
    background: color-mix(in srgb, var(--isis-success) 12%, var(--isis-surface));
    border-radius: 6px;
    color: var(--isis-success);
    font-size: 0.85rem;
    font-weight: 500;
    border: 1px solid var(--isis-success);
    box-sizing: border-box;
}

/* Grille admin quotas */
.isis-grid--gescom-quotas {
    --isis-grid-min-width: 980px;
}

.isis-grid--gescom-quotas .isis-grid__head,
.isis-grid--gescom-quotas .isis-grid__row {
    /* 80px, pas 70 : 2 boutons de 28px + l'écart de 16px des cibles de clic 44×44
       (.isis-grid__action-btn, cf. plus haut dans cette feuille) = 72px, arrondis à 80
       (revue de code du 2026-09-15 — le débordement existait depuis le passage à 16px).
       0.7fr en tête : colonne KPI (EF-140, 0876), un seul badge court. */
    grid-template-columns: 0.7fr 1.4fr 1fr 1fr 1.5fr 0.8fr 80px;
}

/* Variante "danger" du leaderboard pour les motifs de rejet */
.isis-leaderboard__bar.isis-leaderboard__bar--danger {
    background: var(--isis-danger);
}

/* ───────────────────────────────────────────────────────────────────────────
   Phase C — Mix Standard vs BPU. Barre empilée 100% + 2 cards detail.
   ─────────────────────────────────────────────────────────────────────────── */

.isis-typemix {
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

.isis-typemix__stack {
    display: flex;
    height: 32px;
    border-radius: 6px;
    overflow: hidden;
    background: var(--isis-surface-soft);
    border: 1px solid var(--isis-border);
}

.isis-typemix__stack-seg {
    display: flex;
    align-items: center;
    justify-content: center;
    min-width: 4px;
    color: #fff;
    font-size: 0.78rem;
    font-weight: 600;
    text-shadow: 0 1px 2px rgba(0,0,0,0.35);
    transition: width 0.3s ease;
}

.isis-typemix__stack-seg.is-standard { background: var(--isis-mod-gescom); }
.isis-typemix__stack-seg.is-bpu      { background: color-mix(in srgb, var(--isis-mod-gescom) 50%, var(--isis-warning)); }

.isis-typemix__detail {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0.8rem;
}

@media (max-width: 720px) {
    .isis-typemix__detail { grid-template-columns: 1fr; }
}

.isis-typemix__card {
    padding: 0.85rem 1rem;
    border-radius: 8px;
    background: color-mix(in srgb, var(--isis-mod-gescom) 7%, var(--isis-surface));
    border: 1px solid color-mix(in srgb, var(--isis-mod-gescom) 32%, transparent);
    display: flex;
    flex-direction: column;
    gap: 0.2rem;
}

.isis-typemix__card.is-bpu {
    border-color: color-mix(in srgb, var(--isis-mod-gescom) 50%, var(--isis-warning));
}

.isis-typemix__card-label {
    font-size: 0.82rem;
    color: var(--isis-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

.isis-typemix__card-count {
    font-size: 1.6rem;
    font-weight: 700;
    color: var(--isis-text);
    font-variant-numeric: tabular-nums;
}

.isis-typemix__card-value {
    font-size: 0.85rem;
    color: var(--isis-text);
    font-variant-numeric: tabular-nums;
}

/* ───────────────────────────────────────────────────────────────────────────
   Phase D — Cycle détaillé + ligne N-1 sur le trend chart + KPI vélocité.
   ─────────────────────────────────────────────────────────────────────────── */

.isis-cycle-detail {
    display: flex;
    flex-direction: column;
    gap: 0.9rem;
}

.isis-cycle-detail__stack {
    display: flex;
    height: 32px;
    border-radius: 6px;
    overflow: hidden;
    background: var(--isis-surface-soft);
    border: 1px solid var(--isis-border);
}

.isis-cycle-detail__stack-seg {
    display: flex;
    align-items: center;
    justify-content: center;
    min-width: 4px;
    color: #fff;
    font-size: 0.78rem;
    font-weight: 600;
    text-shadow: 0 1px 2px rgba(0,0,0,0.35);
    padding: 0 0.5rem;
    transition: width 0.3s ease;
}

.isis-cycle-detail__stack-seg.is-create { background: var(--isis-mod-gescom); }
.isis-cycle-detail__stack-seg.is-sent   { background: var(--isis-success); }

.isis-cycle-detail__legend {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0.6rem;
}

@media (max-width: 720px) {
    .isis-cycle-detail__legend { grid-template-columns: 1fr; }
}

.isis-cycle-detail__legend-item {
    display: grid;
    grid-template-columns: 12px 1fr auto;
    grid-template-rows: auto auto;
    grid-column-gap: 0.5rem;
    grid-row-gap: 0.1rem;
    padding: 0.45rem 0.6rem;
    border-radius: 6px;
    background: var(--isis-surface-soft);
    align-items: center;
}

.isis-cycle-detail__dot {
    grid-row: 1 / 3;
    width: 10px;
    height: 10px;
    border-radius: 50%;
    align-self: center;
}

.isis-cycle-detail__dot.is-create { background: var(--isis-mod-gescom); }
.isis-cycle-detail__dot.is-sent   { background: var(--isis-success); }

.isis-cycle-detail__label {
    font-size: 0.88rem;
    font-weight: 600;
    color: var(--isis-text);
}

.isis-cycle-detail__value {
    grid-row: 1;
    font-size: 0.95rem;
    font-weight: 700;
    color: var(--isis-text);
    font-variant-numeric: tabular-nums;
}

.isis-cycle-detail__hint {
    grid-column: 2 / 4;
    grid-row: 2;
    font-size: 0.76rem;
    color: var(--isis-text-muted);
}

/* Ligne N-1 en pointillé sur le trend chart */
.isis-trend-chart__line.isis-trend-chart__line--prev {
    stroke: var(--isis-text-muted);
    stroke-width: 1.5;
    stroke-dasharray: 4 3;
    fill: none;
}

/* KPI vélocité — indicateur trend up/down dans le hint */
.isis-kpi-card__trend.is-up   { color: var(--isis-success); font-weight: 600; }
.isis-kpi-card__trend.is-down { color: var(--isis-warning); font-weight: 600; }

/* ───────────────────────────────────────────────────────────────────────────
   Sélecteur de Vue hiérarchique — control segmenté avec icônes Material
   Symbols. Distinct du filter-bar (axe primaire = qui on regarde, alors que
   Entreprise et Période sont secondaires). Refonte 2026-05-21.
   ─────────────────────────────────────────────────────────────────────────── */

.isis-view-selector {
    display: flex;
    align-items: center;
    gap: 0.85rem;
    margin: 0;
}

.isis-view-selector__label {
    font-size: 0.72rem;
    font-weight: 700;
    color: var(--isis-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.08em;
    flex-shrink: 0;
}

.isis-view-selector__group {
    display: inline-flex;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: 10px;
    padding: 3px;
    gap: 2px;
    box-shadow: var(--isis-elevation-1);
}

.isis-view-selector__btn {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.5rem 0.85rem;
    background: transparent;
    border: none;
    border-radius: 7px;
    color: var(--isis-text-muted);
    font-size: 0.86rem;
    font-weight: 500;
    cursor: pointer;
    transition: all 0.15s ease;
    white-space: nowrap;
    font-family: inherit;
}

.isis-view-selector__btn:hover:not(.is-active) {
    background: var(--isis-surface-soft);
    color: var(--isis-text);
}

.isis-view-selector__btn:focus-visible {
    outline: 2px solid color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 60%, transparent);
    outline-offset: 1px;
}

.isis-view-selector__btn.is-active {
    background: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 12%, var(--isis-surface));
    color: var(--isis-current-mod, var(--isis-accent));
    font-weight: 600;
    box-shadow: 0 1px 2px rgba(0,0,0,0.06);
}

.isis-view-selector__btn .rz-icon {
    font-size: 18px !important;
    line-height: 1;
}

.isis-view-selector__btn-label {
    line-height: 1;
}

@media (max-width: 720px) {
    .isis-view-selector {
        flex-direction: column;
        align-items: flex-start;
        gap: 0.4rem;
    }
    .isis-view-selector__group {
        width: 100%;
    }
    .isis-view-selector__btn {
        flex: 1;
        justify-content: center;
        padding: 0.55rem 0.5rem;
    }
    /* En mobile : icônes seulement, libellé masqué (tooltip via title= reste accessible) */
    .isis-view-selector__btn-label {
        display: none;
    }
}

/* Variante text-only : pas d'icône, juste le libellé court (utilisée pour Période). */
.isis-view-selector__btn--text-only {
    padding-left: 1rem;
    padding-right: 1rem;
}

/* ───────────────────────────────────────────────────────────────────────────
   Layout des 3 sélecteurs sur une seule ligne (dashboard gescom V2).
   - Vue : segmented control avec icônes
   - Entreprise : dropdown calqué workspace switcher
   - Période : segmented control texte court
   Sur petit écran : wrap intelligent en colonne, chaque selector pleine largeur.
   ─────────────────────────────────────────────────────────────────────────── */

.isis-dash-filters {
    display: flex;
    align-items: center;
    gap: 1.25rem;
    flex-wrap: wrap;
}
/* Barre de filtres en carte (calque mockup ARCHITECT) — scopé dashboard gescom */
.isis-dash .isis-dash-filters {
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: 0.75rem;
    box-shadow: var(--isis-elevation-1);
    padding: 0.55rem 0.85rem;
    gap: 0.9rem;
}

.isis-dash-filter-group {
    display: flex;
    align-items: center;
    gap: 0.85rem;
}

@media (max-width: 900px) {
    .isis-dash-filters {
        flex-direction: column;
        align-items: stretch;
        gap: 0.75rem;
    }
    .isis-dash-filter-group {
        flex-direction: column;
        align-items: flex-start;
        gap: 0.4rem;
    }
}

/* ───────────────────────────────────────────────────────────────────────────
   DashboardEntrepriseFilter — sélecteur d'entreprise stylé comme le workspace
   switcher du header (avatar pastel + nom + chevron + menu déroulant).
   Calqué sur .isis-header__workspace mais en variante "dashboard local" :
   - taille adaptée au filter-bar (pas pleine hauteur header)
   - bouton "Toutes" en tête de menu (équivalent "no filter")
   - badge warn `!` sur les entreprises sans seuils marge configurés
   ─────────────────────────────────────────────────────────────────────────── */

.isis-dash-entfilter {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.4rem 0.6rem 0.4rem 0.4rem;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: 10px;
    box-shadow: var(--isis-elevation-1);
    cursor: pointer;
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
    min-width: 200px;
    max-width: 320px;
}

.isis-dash-entfilter:hover,
.isis-dash-entfilter:focus-visible {
    border-color: var(--isis-current-mod, var(--isis-accent));
    outline: none;
}

.isis-dash-entfilter:focus-visible {
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 35%, transparent);
}

.isis-dash-entfilter.is-open {
    border-color: var(--isis-current-mod, var(--isis-accent));
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 25%, transparent);
}

.isis-dash-entfilter__avatar {
    width: 30px;
    height: 30px;
    border-radius: 7px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 0.78rem;
    font-weight: 700;
    flex-shrink: 0;
    overflow: hidden;
}

/* Aucun filtre : calque de .isis-dash-entfilter__menu-avatar.is-all, sur le même fond
   (--isis-surface) — la valeur blanche qui vivait en style inline côté C# échappait au
   thème sombre comme au white-label. */
.isis-dash-entfilter__avatar.is-all {
    background: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 12%, var(--isis-surface));
    color: var(--isis-current-mod, var(--isis-accent));
}

.isis-dash-entfilter__name {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: 0.88rem;
    font-weight: 500;
    color: var(--isis-text);
}

.isis-dash-entfilter__warn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 14px;
    height: 14px;
    border-radius: 50%;
    background: var(--isis-warning);
    /* Encre = surface (lot A, 2026-09-18) : le blanc en dur mesurait 2,35:1 sur l'orange éclairci du
       thème sombre (#d6a02a) ; la surface y est sombre, et reste blanche en clair (5,9:1 sur #8f5700). */
    color: var(--isis-surface);
    font-size: 0.7rem;
    font-weight: 700;
    flex-shrink: 0;
}

.isis-dash-entfilter__chevron {
    color: var(--isis-text-muted);
    font-size: 0.85rem;
    transition: transform 0.15s ease;
    flex-shrink: 0;
}

.isis-dash-entfilter.is-open .isis-dash-entfilter__chevron {
    transform: rotate(180deg);
}

/* Menu déroulant */
.isis-dash-entfilter__menu {
    position: absolute;
    top: calc(100% + 6px);
    left: 0;
    z-index: 1000;
    min-width: 280px;
    max-width: 360px;
    max-height: 420px;
    overflow-y: auto;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: 10px;
    box-shadow: var(--isis-elevation-2);
    padding: 0.4rem;
    display: flex;
    flex-direction: column;
    gap: 1px;
}

.isis-dash-entfilter__menu-header {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    padding: 0.5rem 0.7rem 0.4rem;
    font-size: 0.78rem;
    font-weight: 600;
    color: var(--isis-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    border-bottom: 1px solid var(--isis-border);
    margin-bottom: 0.2rem;
}

.isis-dash-entfilter__menu-count {
    font-weight: 400;
    text-transform: none;
    letter-spacing: 0;
}

.isis-dash-entfilter__menu-search {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.4rem 0.6rem;
    margin-bottom: 0.3rem;
    background: var(--isis-surface-soft);
    border-radius: 7px;
    border: 1px solid transparent;
}

.isis-dash-entfilter__menu-search:focus-within {
    border-color: var(--isis-current-mod, var(--isis-accent));
    background: var(--isis-surface);
}

.isis-dash-entfilter__menu-search input {
    flex: 1;
    border: none;
    background: transparent;
    font-size: 0.85rem;
    outline: none;
    color: var(--isis-text);
    font-family: inherit;
}

.isis-dash-entfilter__menu-item {
    display: flex;
    align-items: center;
    gap: 0.55rem;
    /* Indentation par profondeur hiérarchique : 14px par niveau, capped à 56px
       (4 niveaux visibles). Au-delà, l'arbre est probablement trop profond pour
       être lisible — le bullet `└` continue de signaler "enfant" sans tabuler plus. */
    padding: 0.5rem 0.6rem 0.5rem calc(0.6rem + min(var(--ent-depth, 0) * 14px, 56px));
    background: transparent;
    border: none;
    border-radius: 7px;
    color: var(--isis-text);
    font-size: 0.88rem;
    cursor: pointer;
    text-align: left;
    width: 100%;
    transition: background 0.1s ease;
    font-family: inherit;
}

/* Bullet `└` pour les enfants — signal visuel discret de relation parent/enfant.
   Calqué sur WorkspaceSwitcher (memory: workspace switcher pattern). */
.isis-dash-entfilter__menu-bullet {
    color: var(--isis-text-muted);
    font-family: ui-monospace, "JetBrains Mono", monospace;
    font-size: 0.78rem;
    line-height: 1;
    margin-right: -0.2rem;
    flex-shrink: 0;
    user-select: none;
}

.isis-dash-entfilter__menu-item:hover {
    background: var(--isis-surface-soft);
}

.isis-dash-entfilter__menu-item.is-active {
    background: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 10%, var(--isis-surface));
    color: var(--isis-current-mod, var(--isis-accent));
    font-weight: 600;
}

.isis-dash-entfilter__menu-avatar {
    width: 26px;
    height: 26px;
    border-radius: 6px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 0.72rem;
    font-weight: 700;
    flex-shrink: 0;
}

.isis-dash-entfilter__menu-avatar.is-all {
    background: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 12%, var(--isis-surface));
    color: var(--isis-current-mod, var(--isis-accent));
}

.isis-dash-entfilter__menu-name {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.isis-dash-entfilter__menu-warn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 16px;
    height: 16px;
    border-radius: 50%;
    background: var(--isis-warning);
    color: #fff;
    font-size: 0.7rem;
    font-weight: 700;
    flex-shrink: 0;
}

.isis-dash-entfilter__menu-empty {
    padding: 0.85rem 0.7rem;
    font-size: 0.83rem;
    color: var(--isis-text-muted);
    text-align: center;
}

.isis-dash-entfilter__backdrop {
    position: fixed;
    inset: 0;
    z-index: 999;
    background: transparent;
}

/* ============================================================
   ROADMAP — page /roadmap
   Transcription visuelle de CLAUDE.md §6 (chantiers + dette).
   ============================================================ */

.isis-grid--roadmap {
    grid-template-columns:
        40px           /* status dot */
        76px           /* date */
        180px          /* module */
        minmax(0, 1fr) /* titre */
        160px          /* sprint */
        110px;         /* priorité */
    min-width: 920px;
}

.isis-grid--roadmap .isis-grid__head {
    text-transform: uppercase;
    font-size: 0.7rem;
    letter-spacing: 0.04em;
    color: var(--isis-text-muted);
}

.isis-roadmap-row__date {
    font-family: var(--isis-font-mono, "JetBrains Mono", "Consolas", monospace);
    font-size: 0.78rem;
    color: var(--isis-text-muted);
    font-variant-numeric: tabular-nums;
}

.isis-roadmap-row__module {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    font-size: 0.83rem;
    color: var(--isis-text);
}

.isis-roadmap-row__module-dot {
    width: 8px;
    height: 8px;
    border-radius: var(--isis-radius-pill);
    box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.18);
    flex-shrink: 0;
}

.isis-roadmap-row__title {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    min-width: 0;
}

.isis-roadmap-row__title > span:first-child {
    font-weight: 500;
    color: var(--isis-text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.isis-roadmap-row__sub {
    font-size: 0.7rem;
    color: var(--isis-warning, #d97706);
    font-weight: 500;
}

.isis-roadmap-row__sprint {
    font-size: 0.78rem;
    color: var(--isis-text-muted);
    font-family: var(--isis-font-mono, "JetBrains Mono", monospace);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.isis-roadmap-row__priority {
    display: flex;
    align-items: center;
}

/* Status dots roadmap — étend les variantes existantes du design system. */
.isis-grid__status-dot.is-delivered { background: var(--isis-success, #16a34a); }
.isis-grid__status-dot.is-partial   { background: var(--isis-warning, #d97706); }
.isis-grid__status-dot.is-deferred  { background: var(--isis-text-muted, #6e7785); }
.isis-grid__status-dot.is-open      { background: var(--isis-danger, #dc2626); }
.isis-grid__status-dot.is-planned   { background: var(--isis-info, #0ea5e9); }
.isis-grid__status-dot.is-blocked   { background: #6b21a8; }

.isis-grid__group-dot {
    display: inline-block;
    width: 10px;
    height: 10px;
    border-radius: var(--isis-radius-pill);
    margin-right: 0.55rem;
    box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.18);
    vertical-align: middle;
}

/* Sidepanel détail roadmap */
.isis-roadmap-detail {
    padding: 0.5rem 0.25rem 1rem;
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

.isis-roadmap-detail__header {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
}

.isis-roadmap-status {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0.18rem 0.55rem;
    border-radius: var(--isis-radius-pill);
    font-size: 0.72rem;
    font-weight: 600;
    letter-spacing: 0.02em;
}

.isis-roadmap-status--delivered {
    color: var(--isis-success, #16a34a);
    background: color-mix(in srgb, var(--isis-success, #16a34a) 12%, transparent);
}
.isis-roadmap-status--partial {
    color: var(--isis-warning, #d97706);
    background: color-mix(in srgb, var(--isis-warning, #d97706) 14%, transparent);
}
.isis-roadmap-status--deferred {
    color: var(--isis-text-muted, #6e7785);
    background: var(--isis-surface-alt, #ecedf1);
}
.isis-roadmap-status--open {
    color: var(--isis-danger, #dc2626);
    background: color-mix(in srgb, var(--isis-danger, #dc2626) 12%, transparent);
}
.isis-roadmap-status--planned {
    color: var(--isis-info, #0ea5e9);
    background: color-mix(in srgb, var(--isis-info, #0ea5e9) 12%, transparent);
}
.isis-roadmap-status--blocked {
    color: #6b21a8;
    background: #f3e8ff;
}
.isis-roadmap-status--critical {
    color: #ffffff;
    background: var(--isis-danger, #dc2626);
}
.isis-roadmap-status--high {
    color: #ffffff;
    background: var(--isis-warning, #d97706);
}

.isis-roadmap-detail__title {
    font-size: 1.05rem;
    font-weight: 600;
    color: var(--isis-text);
    margin: 0;
    line-height: 1.35;
}

.isis-roadmap-detail__meta {
    display: flex;
    flex-wrap: wrap;
    gap: 0.35rem;
}

.isis-roadmap-meta__chip {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0.15rem 0.5rem;
    border-radius: var(--isis-radius-pill);
    background: var(--isis-surface, var(--isis-surface-alt));
    color: var(--isis-text);
    font-size: 0.72rem;
    font-weight: 500;
    border: 1px solid var(--isis-border, #d6d8dd);
}

.isis-roadmap-meta__chip.is-muted {
    color: var(--isis-text-muted, #6e7785);
}

.isis-roadmap-detail__summary {
    font-size: 0.88rem;
    color: var(--isis-text);
    line-height: 1.55;
    margin: 0;
    padding: 0.75rem 0.85rem;
    background: var(--isis-card-mod-bg);
    border: var(--isis-card-mod-border);
    border-radius: 6px;
}

.isis-roadmap-section {
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
}

.isis-roadmap-section__title {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    font-size: 0.78rem;
    font-weight: 600;
    color: var(--isis-text);
    text-transform: uppercase;
    letter-spacing: 0.03em;
}

.isis-roadmap-list {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
}

.isis-roadmap-list li {
    position: relative;
    padding-left: 1.1rem;
    font-size: 0.83rem;
    color: var(--isis-text);
    line-height: 1.5;
}

.isis-roadmap-list li::before {
    content: "▸";
    position: absolute;
    left: 0;
    color: var(--isis-success, #16a34a);
    font-weight: bold;
}

.isis-roadmap-list--limits li::before {
    content: "⚠";
    color: var(--isis-warning, #d97706);
}

.isis-roadmap-tags {
    display: flex;
    flex-wrap: wrap;
    gap: 0.3rem;
    padding-top: 0.25rem;
}

.isis-roadmap-tag {
    display: inline-block;
    padding: 0.12rem 0.5rem;
    border-radius: var(--isis-radius-pill);
    background: var(--isis-surface-alt, #ecedf1);
    color: var(--isis-text-muted, #6e7785);
    font-size: 0.7rem;
    font-family: var(--isis-font-mono, "JetBrains Mono", monospace);
}

/* KPI variants spécifiques roadmap */
.isis-kpi-card__value--success  { color: var(--isis-success, #16a34a); }
.isis-kpi-card__value--warning  { color: var(--isis-warning, #d97706); }
.isis-kpi-card__value--info     { color: var(--isis-info, #0ea5e9); }
.isis-kpi-card__value--muted    { color: var(--isis-text-muted, #6e7785); }
.isis-kpi-card__value--danger   { color: var(--isis-danger, #dc2626); }
.isis-kpi-card__value--critical {
    color: #ffffff;
    background: var(--isis-danger, #dc2626);
    padding: 0.15rem 0.55rem;
    border-radius: 6px;
    display: inline-block;
    align-self: flex-start;
}

/* ============================================================
   ROADMAP — Panneau « Avancement par module »
   Barres stackées par statut, style GitHub language bars.
   ============================================================ */

.isis-roadmap-progress {
    background: var(--isis-surface, var(--isis-surface-alt));
    border: 1px solid var(--isis-border, #d6d8dd);
    border-radius: 10px;
    padding: 0.95rem 1.1rem;
    display: flex;
    flex-direction: column;
    gap: 0.85rem;
}

.isis-roadmap-progress__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    flex-wrap: wrap;
}

.isis-roadmap-progress__title {
    margin: 0;
    font-size: 0.95rem;
    font-weight: 600;
    color: var(--isis-text);
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
}

.isis-roadmap-progress__legend {
    display: flex;
    flex-wrap: wrap;
    gap: 0.6rem;
    font-size: 0.72rem;
    color: var(--isis-text-muted);
}

.isis-roadmap-progress__legend-item {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
}

.isis-roadmap-progress__legend-dot {
    width: 9px;
    height: 9px;
    border-radius: 2px;
    box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.12);
}

.isis-roadmap-progress__legend-dot.is-delivered { background: var(--isis-success, #16a34a); }
.isis-roadmap-progress__legend-dot.is-partial   { background: var(--isis-warning, #d97706); }
.isis-roadmap-progress__legend-dot.is-deferred  { background: var(--isis-text-muted, #6e7785); }
.isis-roadmap-progress__legend-dot.is-open      { background: var(--isis-danger, #dc2626); }
.isis-roadmap-progress__legend-dot.is-planned   { background: var(--isis-info, #0ea5e9); }

.isis-roadmap-progress__list {
    display: grid;
    grid-template-columns: 1fr;
    gap: 0.4rem;
}

.isis-roadmap-progress__row {
    /* C'est un <button> — on neutralise les styles natifs. */
    all: unset;
    cursor: pointer;
    display: grid;
    grid-template-columns: 220px minmax(0, 1fr) 64px;
    align-items: center;
    gap: 0.85rem;
    padding: 0.45rem 0.55rem;
    border-radius: 7px;
    transition: background 0.12s ease;
}

.isis-roadmap-progress__row:hover {
    background: var(--isis-surface-alt, #ecedf1);
}

.isis-roadmap-progress__row.is-active {
    background: color-mix(in srgb, var(--isis-accent) 9%, transparent);
    box-shadow: inset 3px 0 0 var(--isis-accent);
}

.isis-roadmap-progress__row:focus-visible {
    outline: 2px solid var(--isis-accent);
    outline-offset: 2px;
}

.isis-roadmap-progress__label {
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
    min-width: 0;
}

.isis-roadmap-progress__module-dot {
    width: 10px;
    height: 10px;
    border-radius: 3px;
    box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.18);
    flex-shrink: 0;
}

.isis-roadmap-progress__module-name {
    font-size: 0.85rem;
    font-weight: 500;
    color: var(--isis-text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.isis-roadmap-progress__count {
    font-size: 0.7rem;
    color: var(--isis-text-muted);
    font-variant-numeric: tabular-nums;
    margin-left: auto;
    padding-left: 0.4rem;
    flex-shrink: 0;
}

.isis-roadmap-progress__bar {
    display: flex;
    height: 10px;
    width: 100%;
    background: var(--isis-surface-alt, #ecedf1);
    border-radius: var(--isis-radius-pill);
    overflow: hidden;
    box-shadow: inset 0 0 0 1px var(--isis-border, #d6d8dd);
}

.isis-roadmap-progress__seg {
    display: block;
    height: 100%;
    transition: filter 0.15s ease;
}

.isis-roadmap-progress__seg:hover {
    filter: brightness(1.08);
}

.isis-roadmap-progress__seg.is-delivered { background: var(--isis-success, #16a34a); }
.isis-roadmap-progress__seg.is-partial   { background: var(--isis-warning, #d97706); }
.isis-roadmap-progress__seg.is-deferred  { background: var(--isis-text-muted, #6e7785); }
.isis-roadmap-progress__seg.is-open      { background: var(--isis-danger, #dc2626); }
.isis-roadmap-progress__seg.is-planned   { background: var(--isis-info, #0ea5e9); }

.isis-roadmap-progress__pct {
    font-size: 0.95rem;
    font-weight: 700;
    color: var(--isis-text);
    text-align: right;
    font-variant-numeric: tabular-nums;
    font-family: var(--isis-font-mono, "JetBrains Mono", "Consolas", monospace);
}

.isis-roadmap-progress__pct-unit {
    font-size: 0.7rem;
    color: var(--isis-text-muted);
    font-weight: 500;
    margin-left: 1px;
}

/* Responsive — empile le label / la barre / le % sur tablette */
@media (max-width: 768px) {
    .isis-roadmap-progress__row {
        grid-template-columns: minmax(0, 1fr) 56px;
        grid-template-areas:
            "label pct"
            "bar bar";
        gap: 0.5rem 0.6rem;
    }
    .isis-roadmap-progress__label { grid-area: label; }
    .isis-roadmap-progress__bar { grid-area: bar; }
    .isis-roadmap-progress__pct { grid-area: pct; }
}

/* ============================================================
   ROADMAP — Picker Module (dropdown style workspace switcher)
   Calque visuel de .isis-dash-entfilter (dashboard gescom V2)
   mais simplifié : pastille couleur + nom + compteur, pas d'avatar.
   ============================================================ */

.isis-filter-bar--search-only {
    /* Quand on a seulement la search dans la barre, on retire le contour
       pour ne pas alourdir avant les 3 sélecteurs qui suivent. */
    border: none;
    background: transparent;
    padding: 0;
    box-shadow: none;
}

.isis-roadmap-picker {
    position: relative;
    display: inline-flex;
    /* Le déclencheur est un <button> : on neutralise la police, la couleur et
       l'alignement par défaut du navigateur. */
    font: inherit;
    color: inherit;
    text-align: left;
    align-items: center;
    gap: 0.55rem;
    padding: 0.5rem 0.7rem 0.5rem 0.75rem;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: 10px;
    cursor: pointer;
    transition: all 0.15s ease;
    min-width: 200px;
    max-width: 320px;
    user-select: none;
    box-shadow: var(--isis-elevation-1);
}

.isis-roadmap-picker:hover {
    background: var(--isis-surface-soft);
    border-color: color-mix(in srgb, var(--isis-accent) 40%, var(--isis-border));
}

.isis-roadmap-picker:focus-visible {
    outline: 2px solid color-mix(in srgb, var(--isis-accent) 60%, transparent);
    outline-offset: 1px;
}

.isis-roadmap-picker.is-open {
    border-color: var(--isis-accent);
    background: color-mix(in srgb, var(--isis-accent) 4%, var(--isis-surface));
}

.isis-roadmap-picker__dot {
    width: 12px;
    height: 12px;
    border-radius: 4px;
    box-shadow: inset 0 0 0 1px var(--isis-border-strong);
    flex-shrink: 0;
}

.isis-roadmap-picker__name {
    flex: 1;
    min-width: 0;
    font-size: 0.86rem;
    font-weight: 500;
    color: var(--isis-text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.isis-roadmap-picker__count {
    font-size: 0.72rem;
    font-weight: 600;
    color: var(--isis-text-muted);
    background: var(--isis-surface-alt, #ecedf1);
    padding: 0.1rem 0.45rem;
    border-radius: var(--isis-radius-pill);
    font-variant-numeric: tabular-nums;
    flex-shrink: 0;
}

.isis-roadmap-picker__chevron {
    font-size: 0.65rem;
    color: var(--isis-text-muted);
    transition: transform 0.18s ease;
    flex-shrink: 0;
}

.isis-roadmap-picker.is-open .isis-roadmap-picker__chevron {
    transform: rotate(180deg);
}

/* Menu déroulant */
.isis-roadmap-picker__menu {
    position: absolute;
    top: calc(100% + 6px);
    left: 0;
    z-index: var(--isis-z-dropdown);
    min-width: 100%;
    max-width: 360px;
    max-height: 420px;
    overflow-y: auto;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: 10px;
    box-shadow: var(--isis-elevation-2);   /* dropdown picker roadmap — token (était ad-hoc) */
    padding: 0.35rem;
    display: flex;
    flex-direction: column;
    gap: 1px;
}

.isis-roadmap-picker__menu-header {
    padding: 0.5rem 0.65rem;
    font-size: 0.7rem;
    font-weight: 700;
    color: var(--isis-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    border-bottom: 1px solid var(--isis-border);
    margin-bottom: 0.3rem;
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 0.5rem;
}

.isis-roadmap-picker__menu-count {
    font-size: 0.7rem;
    font-weight: 500;
    color: var(--isis-text-muted);
    text-transform: none;
    letter-spacing: 0;
}

.isis-roadmap-picker__menu-item {
    all: unset;
    cursor: pointer;
    display: flex;
    align-items: center;
    gap: 0.55rem;
    padding: 0.5rem 0.65rem;
    border-radius: 7px;
    color: var(--isis-text);
    font-size: 0.85rem;
    transition: background 0.12s ease;
}

.isis-roadmap-picker__menu-item:hover {
    background: var(--isis-surface-soft);
}

.isis-roadmap-picker__menu-item.is-active {
    background: color-mix(in srgb, var(--isis-accent) 12%, transparent);
    color: var(--isis-accent);
    font-weight: 600;
}

.isis-roadmap-picker__menu-item:focus-visible {
    outline: 2px solid var(--isis-accent);
    outline-offset: 1px;
}

.isis-roadmap-picker__menu-dot {
    width: 12px;
    height: 12px;
    border-radius: 4px;
    box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.18);
    flex-shrink: 0;
}

.isis-roadmap-picker__menu-dot.is-all {
    background: var(--isis-surface-alt, #ecedf1);
    color: var(--isis-text-muted);
    width: 18px;
    height: 18px;
    border-radius: 5px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    margin: -3px 0; /* compenser la taille différente */
}

.isis-roadmap-picker__menu-name {
    flex: 1;
    min-width: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.isis-roadmap-picker__menu-meta {
    font-size: 0.72rem;
    color: var(--isis-text-muted);
    font-variant-numeric: tabular-nums;
    background: var(--isis-surface-alt, #ecedf1);
    padding: 0.08rem 0.4rem;
    border-radius: var(--isis-radius-pill);
    font-weight: 600;
    flex-shrink: 0;
}

.isis-roadmap-picker__menu-item.is-active .isis-roadmap-picker__menu-meta {
    background: color-mix(in srgb, var(--isis-accent) 20%, transparent);
    color: var(--isis-accent);
}

/* Backdrop transparent pour fermer au clic extérieur */
.isis-roadmap-picker__backdrop {
    position: fixed;
    inset: 0;
    z-index: var(--isis-z-overlay);
    background: transparent;
}

/* Responsive — sélecteurs en colonne sur mobile */
@media (max-width: 720px) {
    .isis-roadmap-picker {
        min-width: 0;
        max-width: 100%;
        width: 100%;
    }
}

/* ============================================================
   ROADMAP — Card à onglets (Avancement / Détail)
   .isis-tabs-card pose déjà fond + bordure + radius.
   On ajoute uniquement :
   - le compteur dans l'onglet Liste (pastille nb entrées filtrées)
   - variante "inline" du panneau Avancement (perd son fond redondant)
   ============================================================ */

.isis-tab__counter {
    margin-left: 0.35rem;
    padding: 0.05rem 0.45rem;
    border-radius: var(--isis-radius-pill);
    background: color-mix(in srgb, var(--isis-accent) 14%, transparent);
    color: var(--isis-accent);
    font-size: 0.72rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    line-height: 1.3;
}

.isis-tab:not(.is-active) .isis-tab__counter {
    background: var(--isis-surface-alt, #ecedf1);
    color: var(--isis-text-muted);
}

/* Thème sombre : --isis-accent porte l'accent de MARQUE du tenant, posé par BrandSync.
   Jusqu'au 2026-09-22 le même hex servait en clair et en sombre — l'accent sur sa propre
   teinte à 14 % tombait alors à 1,26:1 sur une carte sombre, compteur illisible (mesuré au
   navigateur le 2026-09-03, page Responsabilités). BrandSync émet désormais une variante
   sombre éclaircie (AccentDarkVariant, 7:1 sur la surface), ce qui ferme la cause ; la règle
   reste parce qu'elle ne dépend d'AUCUNE teinte : sur un fond à 14 % d'accent, un compteur se
   lit à l'encre de texte quelle que soit la marque du client.
   Bornée à l'onglet ACTIF : la règle .isis-tab:not(.is-active) .isis-tab__counter
   ci-dessus a la même spécificité (0,3,0) et vient avant — sans ce garde, le compteur
   des onglets inactifs passait lui aussi à --isis-text et la hiérarchie actif/inactif
   ne tenait plus que par le fond. */
:root[data-theme="dark"] .isis-tab.is-active .isis-tab__counter {
    color: var(--isis-text);
}

/* Panneau Avancement embarqué — pas de double fond/bordure */
.isis-roadmap-progress--inline {
    background: transparent;
    border: none;
    padding: 0;
}

/* Espacement vertical après le bandeau des tabs */
.isis-roadmap-tabs-card .isis-tab-panel--rich:not(.is-hidden) {
    padding-top: 0.85rem;
}

/* ───────────────────────────────────────────────────────────────────────────
   Avenants formalisés (gesmaff_marche_avenant — migration 0226).
   ─────────────────────────────────────────────────────────────────────────── */

/* Utility row 3 colonnes pour saisie deltas HT/TVA/TTC côte à côte dans le dialog */
.isis-form-linear__field-row {
    display: flex;
    gap: 0.75rem;
    align-items: flex-start;
    flex-wrap: wrap;
}

.isis-form-linear__field-row > .isis-form-linear__field {
    flex: 1;
    min-width: 140px;
}

/* Grille de l'onglet Avenants */
.isis-grid--marche-avenants {
    --isis-grid-min-width: 1240px;
}

.isis-grid--marche-avenants .isis-grid__head,
.isis-grid--marche-avenants .isis-grid__row {
    grid-template-columns: 0.7fr 1.5fr 1.3fr 0.9fr 0.9fr 1fr 0.9fr 0.9fr 110px;
}

/* Offres de cotraitants internes en attente de rattachement, en tête de l'onglet Avenants.
   Cinq colonnes seulement : la table tient sans défilement horizontal, d'où une largeur
   minimale bien plus basse que celle des avenants. */
.isis-marche-cotraitance-callout {
    border: 1px solid var(--isis-info);
    background: var(--isis-info-soft);
    border-radius: 8px;
    padding: 0.75rem 0.9rem;
    margin-bottom: var(--isis-space-lg);
    flex: 0 0 auto;
}

.isis-marche-cotraitance-callout .isis-tab-header__title {
    margin-bottom: 0.5rem;
}

.isis-grid--marche-cotraitance {
    --isis-grid-min-width: 720px;
    flex: 0 0 auto;
}

.isis-grid--marche-cotraitance .isis-grid__head,
.isis-grid--marche-cotraitance .isis-grid__row {
    grid-template-columns: 1.4fr 1.6fr 1fr 1fr 60px;
}

/* Grille de l'onglet Flux — Task 11. Position étroite (ordre voulu par le pilote),
   libellé large (porte aussi le marqueur d'orphelin, RG-8), montant/quantités
   tabulaires alignés à droite. */
.isis-grid--marche-flux {
    --isis-grid-min-width: 1336px;
}
.isis-grid--marche-flux .isis-grid__head,
.isis-grid--marche-flux .isis-grid__row {
    /* Dernière colonne à 148px, pas 124 : au statut Terminé elle porte jusqu'à 3 boutons
       de 28px (Ouvrir la commande + les 2 gestes de contrôle qualité de
       FluxCommandeActions) = 3×28 + 2×16 de gap = 116px, même raisonnement que
       .isis-grid--marche-equipe plus bas (cibles de clic 44×44 via ::after) arrondi à
       148 (audit ui-ux-designer, 2026-09-28 — 124px ne laissait que 8px de marge). */
    grid-template-columns: 52px minmax(190px, 1.6fr) minmax(90px, 0.7fr) minmax(170px, 0.9fr)
        64px minmax(120px, 0.9fr) minmax(120px, 0.9fr) 140px minmax(120px, 0.9fr)
        minmax(110px, 0.8fr) 148px;
}
/* Postes / quantités / montant : colonnes comparées verticalement. */
.isis-grid--marche-flux .isis-grid__head > *:nth-child(5),
.isis-grid--marche-flux .isis-grid__head > *:nth-child(6),
.isis-grid--marche-flux .isis-grid__head > *:nth-child(7),
.isis-grid--marche-flux .isis-grid__row > *:nth-child(5),
.isis-grid--marche-flux .isis-grid__row > *:nth-child(6),
.isis-grid--marche-flux .isis-grid__row > *:nth-child(7) {
    justify-content: flex-end; justify-self: end; text-align: right;
    font-variant-numeric: tabular-nums;
}

/* Grille de l'onglet Équipe. Cinq droits, cinq cases à cocher — RG-25 a rendu Livrer,
   Valider et Demander la facturation vérifiés (CommandeWorkflowService + trigger DB) au même
   titre que Prendre en charge, donc composables comme lui ; Task 9 y ajoute Chef de projet, qui
   n'autorise aucun geste mais ouvre la visibilité du marché hors périmètre. Le collaborateur
   (nom + structure + avertissement périmètre) reste le seul champ variable. */
.isis-grid--marche-equipe {
    --isis-grid-min-width: 1030px;
}
.isis-grid--marche-equipe .isis-grid__head,
.isis-grid--marche-equipe .isis-grid__row {
    /* 80px, pas 60 : jusqu'à 2 boutons de 28px + l'écart de 16px des cibles de clic
       44×44 (.isis-grid__action-btn, plus haut) = 72px, arrondis à 80 (revue de code
       du 2026-09-15 — le débordement existait depuis le passage à 16px). */
    /* Les quatre colonnes de cases après « Prendre en charge » se dimensionnent sur leur
       en-tête (majuscules, 0.65rem, letter-spacing 0.06em) : « Demander la facturation »
       est le plus long des cinq libellés et fixe la largeur haute (190px). Livrer/Valider
       à 110/120 (marge de +10 sur l'estimation brute) faute de rendu vérifiable ici — audit
       ui-ux du 2026-09-28, à confirmer à l'œil si le libellé semble encore serré. « Chef de
       projet » (Task 9) tient en 140px, comme « Prendre en charge ». */
    grid-template-columns: minmax(240px, 1.8fr) 140px 110px 120px 190px 140px 80px;
}
.isis-grid--marche-equipe .isis-grid__head > *:nth-child(n+2):nth-child(-n+6),
.isis-grid--marche-equipe .isis-grid__row > *:nth-child(n+2):nth-child(-n+6) {
    justify-content: center; justify-self: center; text-align: center;
}
/* « Chef de projet » (6ᵉ colonne) n'arme aucun geste du flux : elle ouvre la visibilité du
   marché. Le liseré la détache des quatre colonnes d'action. Les deux `stretch` sont
   nécessaires : la règle du dessus centre la cellule, qui se réduit alors à sa case à cocher —
   le liseré ne ferait que 16px de haut. Sélecteur répété en :nth-child(6):nth-child(n+6) : la
   règle de centrage ci-dessus est à spécificité (0,4,0), un simple :nth-child(6) (0,3,0) perdait
   toujours face à elle, et son stretch ne s'appliquait jamais — à (0,4,0) égal, c'est son ORDRE
   SOURCE, après le centrage, qui la fait gagner : ne pas la remonter plus haut dans ce fichier. */
.isis-grid--marche-equipe .isis-grid__head > *:nth-child(6):nth-child(n+6),
.isis-grid--marche-equipe .isis-grid__row > *:nth-child(6):nth-child(n+6) {
    justify-self: stretch;
    align-self: stretch;
    display: flex;
    align-items: center;
    justify-content: center;
    border-left: 1px solid var(--isis-border);
}
.isis-marche-equipe__legende {
    margin: 0 0 0.6rem;
    font-size: 0.78rem;
    line-height: 1.45;
    color: var(--isis-text-muted);
}
.isis-marche-equipe__legende strong { font-weight: 600; color: var(--isis-text); }
.isis-grid--marche-equipe .isis-grid__row { cursor: default; }
.isis-grid--marche-equipe input[type="checkbox"] {
    width: 16px; height: 16px; margin: 0; cursor: pointer;
    accent-color: var(--isis-current-mod, var(--isis-accent));
}
.isis-grid--marche-equipe input[type="checkbox"]:disabled { cursor: not-allowed; opacity: 0.5; }

/* Grille de l'onglet Équipe commerciale de la fiche tiers (migration 0710) : membre, rôle
   (KAM/commercial/support), dates de rattachement, action de clôture. min-width explicite —
   sinon la valeur générique de 1000px (.isis-grid__head/.isis-grid__row) domine et force un
   défilement horizontal que le contenu réel (~660px) ne justifie pas (cf. commentaire
   .isis-grid--flux-postes ci-dessous, même piège déjà rencontré deux fois sur ce fichier). */
.isis-grid--tiers-equipe {
    --isis-grid-min-width: 660px;
}
.isis-grid--tiers-equipe .isis-grid__head,
.isis-grid--tiers-equipe .isis-grid__row {
    grid-template-columns: minmax(220px, 1.6fr) 170px 110px 110px 48px;
    min-width: var(--isis-grid-min-width);
}
.isis-grid--tiers-equipe .isis-grid__head > *:nth-child(n+3):nth-child(-n+4),
.isis-grid--tiers-equipe .isis-grid__row > *:nth-child(n+3):nth-child(-n+4) {
    justify-content: center; justify-self: center; text-align: center;
    font-variant-numeric: tabular-nums;
}
.isis-grid--tiers-equipe .isis-grid__row { cursor: default; }

/* Mini-grille du répéteur de postes dans FluxLigneFormDialog — désignation/unité en lecture
   seule (résolues du bordereau), quantité et charge éditables inline. */
.isis-grid--flux-postes {
    --isis-grid-min-width: 690px;
}
.isis-grid--flux-postes .isis-grid__head,
.isis-grid--flux-postes .isis-grid__row {
    grid-template-columns: minmax(160px, 1.6fr) 64px 110px 110px 100px 100px 44px;
    /* Même défaut que .isis-grid--flux-pec (cf. son commentaire, ligne ~33538) :
       --isis-grid-min-width ci-dessus n'était jamais lue, min-width restait figée à
       1000px par la règle générique — dans un dialog à 760px (DialogOptions.Width),
       cette grille aurait débordé de la même façon. Somme des colonnes = 688px, c'est
       elle qui domine (690px, à peine au-dessus, n'ajoute quasi aucune marge à la
       colonne flexible) : ne pas monter ce chiffre sans recalculer le contenu réel du
       dialog (~710px estimé sur le même ratio que flux-pec, 820px → 770px de contenu),
       une valeur plus haute redéborderait au lieu de corriger le défaut. */
    min-width: var(--isis-grid-min-width);
}
.isis-grid--flux-postes .isis-grid__row { cursor: default; }
.isis-grid--flux-postes .isis-grid__head > *:nth-child(n+3):nth-child(-n+6),
.isis-grid--flux-postes .isis-grid__row > *:nth-child(n+3):nth-child(-n+6) {
    justify-content: flex-end; justify-self: end; text-align: right;
    font-variant-numeric: tabular-nums;
}
/* Bouton « Sous-traitance & notes » (RG-7, tâche 3) logé DANS la cellule Désignation —
   pas dans une colonne à part : les colonnes fixes ci-dessus totalisent déjà 688px contre
   ~710px de contenu réel (cf. commentaire ci-dessus) ; une colonne de plus aurait débordé.
   La colonne Désignation est flexible (minmax(160px, 1.6fr)) : un bouton de 22px n'y coûte
   rien qu'elle ne puisse déjà absorber. Bouton réduit à 22px (icône 15px) — le 28px par
   défaut de .isis-grid__action-btn aurait écrasé le texte sur les désignations longues. */
.isis-grid--flux-postes .isis-flux-poste__designation {
    display: flex;
    align-items: center;
    gap: 0.3rem;
    min-width: 0;
}
.isis-grid--flux-postes .isis-flux-poste__designation-text {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
}
.isis-grid--flux-postes .isis-flux-poste__intention-btn {
    flex: 0 0 auto;
    width: 22px;
    height: 22px;
}

/* Grille des postes du dialogue « Sous-traiter » (CommandeDetail → engagement gesst) : case à
   cocher, désignation, unité, quantité et prix d'achat éditables, montant HT calculé. Même
   piège que .isis-grid--flux-postes ci-dessus (audit UX 2026-08-10, corrigé avant même de
   ship) : min-width doit être réécrit explicitement via --isis-grid-min-width, sinon la règle
   générique impose 1000px et la grille déborde d'un dialog à 760px (DialogOptions.Width).
   Colonnes = 32+160(min)+56+100+116+110 = 574px : marge confortable sous 760px, contrairement
   à flux-postes qui frôlait la limite. */
.isis-grid--soustraiter {
    --isis-grid-min-width: 610px;
}
.isis-grid--soustraiter .isis-grid__head,
.isis-grid--soustraiter .isis-grid__row {
    grid-template-columns: 32px minmax(160px, 1.6fr) 56px 100px 116px 110px;
    min-width: var(--isis-grid-min-width);
    align-items: center;
}
.isis-grid--soustraiter .isis-grid__head > *:nth-child(n+4):nth-child(-n+6),
.isis-grid--soustraiter .isis-grid__row > *:nth-child(n+4):nth-child(-n+6) {
    justify-content: flex-end; justify-self: end; text-align: right;
    font-variant-numeric: tabular-nums;
}
/* Montant HT (6e colonne) : valeur calculée, pas saisie — distinguée des deux champs
   éditables voisins par une couleur atténuée plutôt que par la seule absence de soulignement
   (audit UX 2026-08-10). */
.isis-grid--soustraiter .isis-grid__row > *:nth-child(6) { color: var(--isis-text-muted); }

/* La cellule « Prix d'achat HT » porte, sous son champ, un libellé d'aide (« Pas de prix au
   catalogue — à saisir. ») ou l'avertissement de devise. Ces textes sont plus larges que la
   piste fixe de 116 px : sans min-width:0 la cellule ne peut pas descendre sous la largeur
   min-content de son contenu, elle DÉBORDE la piste, et comme elle est alignée à droite le
   débordement part vers la gauche et recouvre la colonne Quantité (mesuré le 2026-08-10 :
   cellule à x=835 large de 196 px sur la ligne portant le libellé, contre x=915 large de
   116 px sur les autres — 80 px de chevauchement). Le libellé doit donc pouvoir se replier. */
.isis-grid--soustraiter .isis-grid__row > *:nth-child(5) {
    min-width: 0;
    flex-direction: column;
    align-items: flex-end;
}
.isis-grid--soustraiter .isis-grid__row > *:nth-child(5) .isis-form-linear__field-hint {
    max-width: 100%;
    white-space: normal;
    text-align: right;
}

/* ───────────────────────────────────────────────────────────────────────────
   Page FluxPage (« Flux de commandes », /gesproj/flux) et son dialog de prise
   en charge (PriseEnChargeDialog).
   ─────────────────────────────────────────────────────────────────────────── */

/* Champ de recherche de FluxPage — audit critique de conception : s'arrêtait au Tab avec
   outline/box-shadow à none (la règle générique .isis-filter-bar__search input:focus, ligne
   ~8904, ne pose qu'une border-color, sans anneau — partagée par ~90 pages, non touchée ici
   pour ne pas en changer le rendu partout). Classe dédiée, scopée à cette seule page, même
   token que le reste de l'application. */
.isis-flux-search input:focus-visible {
    outline: none;
    border-color: var(--isis-current-mod, var(--isis-accent));
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 18%, transparent);
}

/* Bascule « À prendre / Mes prises » — RadzenSelectBar Size="ButtonSize.Small" mesure 36px,
   sous le plancher WCAG 2.5.5 (44px). Scopé à cette page (17 autres écrans utilisent
   RadzenSelectBar avec d'autres attentes de densité — ne pas généraliser). */
.isis-flux-vue-toggle .rz-button {
    min-height: 44px;
}

/* Vue « À prendre » : marché/libellé larges, période/postes/montant tabulaires,
   une action primaire pleine largeur en fin de ligne. */
.isis-grid--flux-a-prendre {
    --isis-grid-min-width: 1040px;
}
.isis-grid--flux-a-prendre .isis-grid__head,
.isis-grid--flux-a-prendre .isis-grid__row {
    grid-template-columns: minmax(120px, 0.9fr) minmax(200px, 1.6fr) minmax(100px, 0.7fr)
        minmax(180px, 1fr) 80px minmax(150px, 1fr) 60px;
}
.isis-grid--flux-a-prendre .isis-grid__head > *:nth-child(5),
.isis-grid--flux-a-prendre .isis-grid__head > *:nth-child(6),
.isis-grid--flux-a-prendre .isis-grid__row > *:nth-child(5),
.isis-grid--flux-a-prendre .isis-grid__row > *:nth-child(6) {
    justify-content: flex-end; justify-self: end; text-align: right;
    font-variant-numeric: tabular-nums;
}
/* Les lignes sont sélectionnables depuis l'ajout du sidepanel (2026-09-02) : le curseur
   doit le dire. Elles portaient `default` du temps où cliquer ne faisait rien. */
.isis-grid--flux-a-prendre .isis-grid__row { cursor: pointer; }

/* Vue « Mes prises » : même largeur de marché/libellé, statut en badge,
   avancement/période tabulaires. */
.isis-grid--flux-mes-prises {
    --isis-grid-min-width: 1204px;
}
.isis-grid--flux-mes-prises .isis-grid__head,
.isis-grid--flux-mes-prises .isis-grid__row {
    grid-template-columns: minmax(120px, 0.9fr) minmax(200px, 1.6fr) minmax(120px, 0.8fr)
        150px 120px minmax(180px, 1fr) 124px;
}
.isis-grid--flux-mes-prises .isis-grid__head > *:nth-child(5),
.isis-grid--flux-mes-prises .isis-grid__row > *:nth-child(5) {
    justify-content: flex-end; justify-self: end; text-align: right;
    font-variant-numeric: tabular-nums;
}
.isis-grid--flux-mes-prises .isis-grid__row { cursor: pointer; }

/* Grille des postes reçus dans PriseEnChargeDialog — postes annoncés (quantité éditable)
   et postes ajoutés (quantité + charge éditables + retrait) partagent les mêmes colonnes :
   la charge est en lecture seule pour un poste annoncé, éditable pour un ajout. */
.isis-grid--flux-pec {
    --isis-grid-min-width: 620px;
}
.isis-grid--flux-pec .isis-grid__head,
.isis-grid--flux-pec .isis-grid__row {
    grid-template-columns: minmax(160px, 1.6fr) 64px 100px 100px 100px 40px;
    /* Débordement mesuré à l'écran (scrollWidth 1000 pour clientWidth 770 dans le dialog
       820px, quantité reçue hors champ visible) : --isis-grid-min-width est déclarée
       ci-dessus mais la règle générique .isis-grid__head/.isis-grid__row (isis-theme.css
       ~ligne 9716) fige min-width à 1000px en dur, sans jamais lire cette variable — un
       défaut préexistant qui touche potentiellement les ~14 autres grilles du produit
       déclarant --isis-grid-min-width, pas seulement celle-ci. Corrigé ici seulement, en
       spécificité plus élevée que la règle générique, pour ne pas changer le rendu des
       grilles déjà correctes ailleurs sans les avoir vérifiées une à une. Somme des
       colonnes ci-dessus = 564px < 620px : 620px est la contrainte dimensionnante, tient
       dans les 770px de contenu du dialog (820px - paddings) à 1280px comme à 1600px de
       large (DialogOptions.Width="820px" est fixe, pas de breakpoint responsive entre les
       deux sur .rz-dialog). */
    min-width: var(--isis-grid-min-width);
}
.isis-grid--flux-pec .isis-grid__row { cursor: default; }
.isis-grid--flux-pec .isis-grid__head > *:nth-child(n+3):nth-child(-n+5),
.isis-grid--flux-pec .isis-grid__row > *:nth-child(n+3):nth-child(-n+5) {
    justify-content: flex-end; justify-self: end; text-align: right;
    font-variant-numeric: tabular-nums;
}

/* Résultat de la prise en charge, en toutes lettres — une ligne par mobilisation
   (tâche + issue + motif d'échec le cas échéant), jamais réduit à un « Enregistré ». Le conteneur
   (role="status", tabindex="-1") reçoit le focus programmatique après succès (WCAG 4.1.3) — même
   halo que les autres cibles de focus non natives du dépôt (cf. .isis-report-cat__item). */
.isis-pec-result:focus-visible {
    outline: none;
    box-shadow: var(--isis-elevation-focus);
    border-radius: var(--isis-radius);
}
.isis-pec-result__list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
}
.isis-pec-result__item {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    flex-wrap: wrap;
    padding: 0.5rem 0.7rem;
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-sm);
    background: var(--isis-surface-alt);
}
.isis-pec-result__tache {
    flex: 1 1 auto;
    min-width: 140px;
    font-weight: 500;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.isis-pec-result__detail {
    flex-basis: 100%;
    font-size: 0.82rem;
    color: var(--isis-text-muted);
}

/* Bande « À surveiller » — signaux actionnables orientés risque (liste marchés).
   Silencieuse quand aucun signal ; mise en avant douce, non bloquante. */
.isis-watch-band {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
    padding: 0.5rem 0.75rem;
    margin-bottom: 0.75rem;
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius);
    background: var(--isis-surface-alt);
}
.isis-watch-band__label {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    font-size: 0.78rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--isis-text-muted);
}
.isis-watch-item {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.2rem 0.6rem;
    border-radius: var(--isis-radius-pill, 999px);
    font-family: inherit;
    font-size: 0.82rem;
    line-height: 1.5;
    white-space: nowrap;
    border: 1px solid var(--isis-border);
    background: var(--isis-surface);
    color: var(--isis-text);
    cursor: pointer;
    transition: background 0.12s ease, border-color 0.12s ease, box-shadow 0.12s ease;
}
.isis-watch-item strong { font-variant-numeric: tabular-nums; }
.isis-watch-item:hover { border-color: var(--isis-text-muted); }
.isis-watch-item:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 35%, transparent);
}
.isis-watch-item.is-warn {
    border-color: color-mix(in srgb, var(--isis-warning) 50%, var(--isis-border));
    background: color-mix(in srgb, var(--isis-warning) 12%, var(--isis-surface));
}
.isis-watch-item.is-warn:hover {
    border-color: color-mix(in srgb, var(--isis-warning) 70%, var(--isis-border));
}
.isis-watch-item.is-danger {
    border-color: color-mix(in srgb, var(--isis-danger) 50%, var(--isis-border));
    background: color-mix(in srgb, var(--isis-danger) 12%, var(--isis-surface));
    color: var(--isis-danger);
}
.isis-watch-item.is-danger:hover {
    border-color: color-mix(in srgb, var(--isis-danger) 70%, var(--isis-border));
}
/* État actif (filtre appliqué) : surface pleine teintée + anneau interne. */
.isis-watch-item.is-active.is-warn {
    background: color-mix(in srgb, var(--isis-warning) 24%, var(--isis-surface));
    border-color: var(--isis-warning);
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--isis-warning) 50%, transparent);
}
.isis-watch-item.is-active.is-danger {
    background: color-mix(in srgb, var(--isis-danger) 22%, var(--isis-surface));
    border-color: var(--isis-danger);
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--isis-danger) 50%, transparent);
}

/* Section « Préparation » de l'onglet Aperçu des fiches AO / demande client
   (OpportunitePreparationSection.razor) : la checklist avant offre de prix, items satisfaits
   comme manquants. L'état se lit au texte (colonne de droite), l'icône le redouble. */
.isis-preparation__compte {
    margin-left: 0.5rem;
    font-family: var(--isis-font-mono);
    font-size: var(--isis-fs-sm);
    font-weight: 500;
    color: var(--isis-text-muted);
}
.isis-preparation {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
}
.isis-preparation__item {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-size: var(--isis-fs-sm);
    color: var(--isis-text);
}
.isis-preparation__icon { font-size: 16px; flex-shrink: 0; }
.isis-preparation__item.is-ok .isis-preparation__icon { color: var(--isis-success); }
.isis-preparation__item.is-manquant .isis-preparation__icon { color: var(--isis-danger); }
.isis-preparation__item.is-optionnel .isis-preparation__icon { color: var(--isis-text-muted); }
.isis-preparation__label { flex: 1; min-width: 0; }
.isis-preparation__etat { color: var(--isis-text-muted); white-space: nowrap; }
.isis-preparation__item.is-manquant .isis-preparation__etat { color: var(--isis-danger); font-weight: 600; }

/* Cellule Intitulé empilée (titre + bande de méta-visuels) — liste marchés. */
.isis-grid__col-intitule {
    display: flex;
    flex-direction: column;
    gap: 0.2rem;
    min-width: 0;
}
.isis-grid__col-intitule-text {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.isis-marche-row-meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.3rem 0.45rem;
}

/* Colonne Échéance (date de fin + badge d'alerte) — liste marchés. */
.isis-grid__col-echeance {
    display: flex;
    flex-direction: column;
    gap: 0.2rem;
    align-items: flex-start;
}
.isis-grid__echeance-date { font-variant-numeric: tabular-nums; }

/* Jauge de consommation d'un contrat-cadre (consommé / plafond). */
.isis-marche-gauge {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    min-width: 120px;
}
.isis-marche-gauge__track {
    position: relative;
    flex: 1;
    height: 5px;
    min-width: 56px;
    border-radius: 999px;
    background: var(--isis-surface-alt);
    overflow: hidden;
}
.isis-marche-gauge__fill {
    display: block;
    height: 100%;
    border-radius: 999px;
    background: var(--isis-current-mod, var(--isis-accent));
    transition: width 0.2s ease;
}
.isis-marche-gauge__fill.is-ok { background: var(--isis-success); }
.isis-marche-gauge__fill.is-warn { background: var(--isis-warning); }
.isis-marche-gauge__fill.is-danger { background: var(--isis-danger); }
.isis-marche-gauge__label {
    font-size: 0.72rem;
    font-variant-numeric: tabular-nums;
    color: var(--isis-text-muted);
    min-width: 2.6em;
    text-align: right;
}

/* Badges de risque par ligne (échéance / échue / reconduction à dénoncer). */
.isis-marche-badge {
    display: inline-flex;
    align-items: center;
    gap: 0.2rem;
    padding: 0.02rem 0.4rem;
    border-radius: var(--isis-radius-pill, 999px);
    font-size: 0.7rem;
    font-weight: 600;
    line-height: 1.5;
    white-space: nowrap;
    border: 1px solid var(--isis-border);
}
.isis-marche-badge.is-echeance {
    border-color: color-mix(in srgb, var(--isis-warning) 50%, var(--isis-border));
    background: color-mix(in srgb, var(--isis-warning) 12%, var(--isis-surface));
    color: var(--isis-text);
}
.isis-marche-badge.is-echue,
.isis-marche-badge.is-reconduction {
    border-color: color-mix(in srgb, var(--isis-danger) 50%, var(--isis-border));
    background: color-mix(in srgb, var(--isis-danger) 12%, var(--isis-surface));
    color: var(--isis-danger);
}
.isis-marche-badge.is-avenant {
    border-color: color-mix(in srgb, var(--isis-warning) 50%, var(--isis-border));
    background: color-mix(in srgb, var(--isis-warning) 12%, var(--isis-surface));
    color: var(--isis-text);
}

.isis-side-gauge { display: flex; flex-direction: column; gap: 0.3rem; }
.isis-side-gauge__head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    font-size: 0.78rem;
    font-weight: 600;
    color: var(--isis-text);
}
.isis-side-gauge__pct { font-variant-numeric: tabular-nums; }
.isis-side-gauge__pct.is-ok { color: var(--isis-success); }
.isis-side-gauge__pct.is-warn { color: var(--isis-warning); }
.isis-side-gauge__pct.is-danger { color: var(--isis-danger); }
.isis-side-gauge .isis-marche-gauge__track { height: 7px; width: 100%; }
.isis-side-gauge__detail {
    font-size: 0.72rem;
    color: var(--isis-text-muted);
    font-variant-numeric: tabular-nums;
}

/* Puces « Nature » d'un avenant (Prix / Quantité / Poste± / Délai / Plafond / Montant) */
.isis-avenant-impacts {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem;
}
.isis-avenant-impact {
    display: inline-flex;
    align-items: center;
    padding: 0.05rem 0.45rem;
    border-radius: var(--isis-radius-pill, 999px);
    font-size: 0.72rem;
    font-weight: 600;
    line-height: 1.5;
    white-space: nowrap;
    border: 1px solid var(--isis-border);
    background: var(--isis-surface-alt);
    color: var(--isis-text);
}
.isis-avenant-impact.is-prix,
.isis-avenant-impact.is-montant {
    border-color: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 45%, var(--isis-border));
    background: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 10%, var(--isis-surface));
}
.isis-avenant-impact.is-delai {
    border-color: color-mix(in srgb, var(--isis-accent) 45%, var(--isis-border));
    background: color-mix(in srgb, var(--isis-accent) 10%, var(--isis-surface));
    color: var(--isis-accent-strong);
}
.isis-avenant-impacts__none {
    color: var(--isis-text-muted);
}

/* Bouton action vert "Signer" — variante success (calque pattern --danger) */
.isis-grid__action-btn--success {
    color: var(--isis-success);
}
.isis-grid__action-btn--success:hover,
.isis-grid__action-btn--success:focus-visible {
    background: color-mix(in srgb, var(--isis-success) 12%, var(--isis-surface));
    border-color: var(--isis-success);
}

/* ─────────────────────────────────────────────────────────────────────────
   Bordereau de marché versionné (Lot 4, migration 0390)
   — onglet « Bordereau » (lecture) + éditeur d'avenant (4 opérations).
   ───────────────────────────────────────────────────────────────────────── */

.isis-bordereau { display: flex; flex-direction: column; gap: 0.85rem; }

/* Sélecteur de version — chips */
.isis-bordereau__versions { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.isis-bordereau__chip {
    display: inline-flex; align-items: center; gap: 0.45rem;
    padding: 0.3rem 0.6rem;
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-sm);
    background: var(--isis-surface);
    color: var(--isis-text);
    cursor: pointer;
    font-size: 0.82rem;
    transition: background 0.12s ease, border-color 0.12s ease;
}
.isis-bordereau__chip:hover { background: var(--isis-surface-alt); }
.isis-bordereau__chip:focus-visible {
    outline: 2px solid color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 55%, transparent);
    outline-offset: 1px;
}
.isis-bordereau__chip.is-active {
    border-color: var(--isis-current-mod, var(--isis-accent));
    background: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 8%, var(--isis-surface));
}
.isis-bordereau__chip-num { font-family: var(--isis-font-mono); font-weight: 600; }
.isis-bordereau__chip-date { color: var(--isis-text-soft); font-variant-numeric: tabular-nums; }

.isis-bordereau__caption { font-size: 0.84rem; color: var(--isis-text); }
.isis-bordereau__caption-muted { color: var(--isis-text-soft); }

/* Grille postes (lecture) : # / désignation / unité / PU / qté / total / consommé / statut */
.isis-grid--bordereau { --isis-grid-min-width: 980px; }
.isis-grid--bordereau .isis-grid__head,
.isis-grid--bordereau .isis-grid__row,
.isis-grid--bordereau .isis-grid__foot {
    grid-template-columns: 48px 1.8fr 0.7fr 0.9fr 0.9fr 1fr 0.9fr 0.8fr;
}
.isis-grid--bordereau .isis-grid__row.is-muted { opacity: 0.65; }

/* ── Éditeur de bordereau de l'avenant ── */
.isis-bordereau-edit { display: flex; flex-direction: column; gap: 0.85rem; }
.isis-bordereau-edit__hint {
    margin: 0; font-size: 0.84rem; color: var(--isis-text-soft);
    line-height: 1.45;
}
.isis-grid--bordereau-edit { --isis-grid-min-width: 1040px; }
.isis-grid--bordereau-edit .isis-grid__head,
.isis-grid--bordereau-edit .isis-grid__row,
.isis-grid--bordereau-edit .isis-grid__foot {
    grid-template-columns: 44px 1.7fr 0.7fr 0.95fr 0.95fr 0.95fr 0.85fr 0.75fr 60px;
    align-items: center;
}
.isis-grid--bordereau-edit .isis-grid__row.is-muted { opacity: 0.65; }
/* Variante commande (gesproj) : une colonne « Remise » s'insère entre Quantité et
   Total HT dès qu'un poste en porte une — sans elle, le Total HT ne vaut pas PU × Qté
   et rien ne l'explique. Modificateur d'ÉTAT (classe additionnelle), pas un second
   modificateur de grille : les 9 colonnes de base restent celles du bordereau marché. */
/* 10 colonnes au lieu de 9 : la largeur minimale DOIT grandir, sinon la colonne
   supplémentaire se prend sur les autres et les champs numériques s'écrasent. */
.isis-grid--bordereau-edit.has-remise { --isis-grid-min-width: 1120px; }
/* Pas de `__foot` ici : il est en flex space-between, un grid-template n'y ferait rien. */
.isis-grid--bordereau-edit.has-remise .isis-grid__head,
.isis-grid--bordereau-edit.has-remise .isis-grid__row {
    /* La quantité accepte 4 décimales : elle a besoin de plus d'air que le PU. */
    grid-template-columns: 44px 1.5fr 0.6fr 0.95fr 1.2fr 0.55fr 0.95fr 0.85fr 0.7fr 60px;
}
.isis-grid--bordereau-edit .isis-grid__col-num {
    text-align: right;
    font-variant-numeric: tabular-nums;
}
.isis-grid--bordereau-edit .isis-grid__col-num.is-error { color: var(--isis-danger); }
.isis-bordereau-edit__num { width: 100%; }
.isis-bordereau-edit__num.is-error input {
    border-color: var(--isis-danger) !important;
}
.isis-bordereau-edit__consumed-alert { color: var(--isis-danger); font-weight: 600; }

.isis-bordereau-edit__add {
    border: 1px dashed var(--isis-border);
    border-radius: var(--isis-radius-sm);
    padding: 0.7rem 0.85rem;
    background: var(--isis-surface-alt);
}
.isis-bordereau-edit__add-title { font-weight: 600; font-size: 0.85rem; margin-bottom: 0.5rem; }
.isis-bordereau-edit__add-grid {
    display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: center;
}
.isis-bordereau-edit__add-desig { flex: 1 1 240px; }
.isis-bordereau-edit__add-unite { flex: 0 0 120px; }

.isis-form-linear__actions-spacer { flex: 1 1 auto; }

/* ─────────────────────────────────────────────────────────────────────────
   Scheduler visuel scopé commande (onglet Mobilisation de CommandeDetail).
   Calque allégé du planner V3 gespla, deux couches superposées planifié + réalisé.
   ───────────────────────────────────────────────────────────────────────── */

.isis-cmd-scheduler {
    display: flex;
    flex-direction: column;
    gap: 1rem;
    height: 100%;
    min-height: 0;
}

.isis-cmd-scheduler__loading,
.isis-cmd-scheduler__error,
.isis-cmd-scheduler__empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    padding: 3rem 1rem;
    color: var(--isis-text-muted);
    text-align: center;
}

.isis-cmd-scheduler__empty strong { color: var(--isis-text); font-size: 0.95rem; }
.isis-cmd-scheduler__error { color: var(--isis-danger); }

.isis-cmd-scheduler__toolbar {
    display: flex;
    align-items: center;
    gap: 1rem;
    flex-wrap: wrap;
    padding: 0.5rem 0.75rem;
    background: var(--isis-surface-alt);
    border-radius: 8px;
}

.isis-cmd-scheduler__toggle {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    font-size: 0.875rem;
    color: var(--isis-text);
    cursor: pointer;
}

.isis-cmd-scheduler__mode {
    display: inline-flex;
    border: 1px solid var(--isis-border);
    border-radius: 6px;
    overflow: hidden;
}

.isis-cmd-scheduler__mode-btn {
    background: var(--isis-surface);
    border: 0;
    padding: 0.4rem 0.75rem;
    font-size: 0.8rem;
    color: var(--isis-text-muted);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    transition: background 120ms, color 120ms;
}

.isis-cmd-scheduler__mode-btn:not(:last-child) {
    border-right: 1px solid var(--isis-border);
}

.isis-cmd-scheduler__mode-btn:hover {
    background: var(--isis-surface-alt);
    color: var(--isis-text);
}

.isis-cmd-scheduler__mode-btn.is-active {
    background: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 14%, var(--isis-surface));
    color: var(--isis-current-mod, var(--isis-accent));
    font-weight: 600;
}

.isis-cmd-scheduler__mode-btn:focus-visible {
    outline: 2px solid var(--isis-current-mod, var(--isis-accent));
    outline-offset: 1px;
    z-index: 1;
}

.isis-cmd-scheduler__spacer { flex: 1; }

.isis-cmd-scheduler__legend {
    display: flex;
    gap: 1.25rem;
    align-items: center;
    flex-wrap: wrap;
    font-size: 0.75rem;
    color: var(--isis-text-muted);
    padding: 0 0.25rem;
}

.isis-cmd-scheduler__legend-item {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
}

.isis-cmd-scheduler__legend-swatch {
    width: 18px;
    height: 12px;
    border-radius: 3px;
    display: inline-block;
}

/* Audit ui-ux : swatch légende harmonisé avec le bloc planifié réel (color-mix 18% + bordure accent). */
.isis-cmd-scheduler__legend-item.is-planned .isis-cmd-scheduler__legend-swatch {
    background: color-mix(in srgb, var(--isis-accent) 18%, var(--isis-surface));
    border-left: 3px solid var(--isis-accent);
}

/* Temps pointé mais pas encore soumis : même bloc réalisé, contour POINTILLÉ. Le pointillé dit
   « pas arrêté » sans introduire une couleur de plus, et il reste lisible sans la couleur (WCAG
   1.4.1) contrairement à un simple éclaircissement. */
.isis-cmd-scheduler__legend-item.is-brouillon .isis-cmd-scheduler__legend-swatch {
    background: color-mix(in srgb, var(--isis-text-muted) 10%, var(--isis-surface));
    border: 1px dashed var(--isis-text-muted);
}

/* Idem pour le swatch réalisé : motif hachuré 18%/10% calque du bloc .isis-cmd-evt--realized. */
.isis-cmd-scheduler__legend-item.is-realized .isis-cmd-scheduler__legend-swatch {
    background: repeating-linear-gradient(
        135deg,
        color-mix(in srgb, var(--isis-success) 18%, var(--isis-surface)),
        color-mix(in srgb, var(--isis-success) 18%, var(--isis-surface)) 6px,
        color-mix(in srgb, var(--isis-success) 10%, var(--isis-surface)) 6px,
        color-mix(in srgb, var(--isis-success) 10%, var(--isis-surface)) 12px
    );
    border-left: 3px solid var(--isis-success);
}

.isis-cmd-scheduler__host {
    flex: 1;
    min-height: 480px;
    border: 1px solid var(--isis-border);
    border-radius: 8px;
    overflow: hidden;
    background: var(--isis-surface);
}

/* V2.0 — Templates events densifiés (calque pattern PlannerV3 NetLogger).
   2 rows : meta (avatar + chips) + title (libellé tâche). Couleur stable via --isis-event-accent. */
.isis-cmd-evt {
    --isis-event-accent: var(--isis-accent);
    display: flex;
    flex-direction: column;
    gap: 0.1rem;
    padding: 0.2rem 0.4rem;
    height: 100%;
    color: var(--isis-text);
    font-size: 0.72rem;
    border-radius: 4px;
    overflow: hidden;
    border: 1px solid var(--isis-event-accent);
    box-sizing: border-box;
}

.isis-cmd-evt--planned {
    background: color-mix(in srgb, var(--isis-event-accent) 18%, var(--isis-surface));
}

.isis-cmd-evt--realized {
    background: repeating-linear-gradient(
        135deg,
        color-mix(in srgb, var(--isis-event-accent) 22%, var(--isis-surface)),
        color-mix(in srgb, var(--isis-event-accent) 22%, var(--isis-surface)) 5px,
        color-mix(in srgb, var(--isis-event-accent) 12%, var(--isis-surface)) 5px,
        color-mix(in srgb, var(--isis-event-accent) 12%, var(--isis-surface)) 10px
    );
}

.isis-cmd-evt.is-overload {
    border-color: var(--isis-danger);
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--isis-danger) 40%, transparent);
}

/* Heures pointées non encore soumises : contour pointillé. Signal de FORME, pas de couleur —
   la surallocation garde son bord plein rouge et reste donc distincte. */
.isis-cmd-evt.is-brouillon {
    border-style: dashed;
}

.isis-cmd-evt__brouillon {
    font-size: 0.6rem;
    padding: 0.05rem 0.35rem;
    border-radius: var(--isis-radius-pill);
    border: 1px dashed var(--isis-text-muted);
    color: var(--isis-text-muted);
    font-weight: 500;
    white-space: nowrap;
}

.isis-cmd-evt__meta {
    display: flex;
    align-items: center;
    gap: 0.3rem;
    font-weight: 600;
    font-size: 0.68rem;
    line-height: 1.1;
}

.isis-cmd-evt__avatar {
    width: 18px;
    height: 18px;
    border-radius: 50%;
    background: var(--isis-event-accent);
    color: white;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 0.6rem;
    font-weight: 700;
    flex-shrink: 0;
    letter-spacing: -0.02em;
}

.isis-cmd-evt__chip {
    font-variant-numeric: tabular-nums;
    padding: 0.05rem 0.35rem;
    background: var(--isis-surface);
    border-radius: var(--isis-radius-pill);
    color: var(--isis-text);
    font-weight: 600;
}

.isis-cmd-evt__duration {
    font-variant-numeric: tabular-nums;
    color: var(--isis-text-muted);
    font-size: 0.62rem;
    font-weight: 500;
}

.isis-cmd-evt__status {
    margin-left: auto;
    font-size: 0.6rem;
    padding: 0.05rem 0.35rem;
    border-radius: var(--isis-radius-pill);
    background: var(--isis-surface);
    color: var(--isis-text-muted);
    font-weight: 500;
}

.isis-cmd-evt__status.status-brouillon { background: var(--isis-surface-alt); }
.isis-cmd-evt__status.status-soumis { background: color-mix(in srgb, var(--isis-accent) 20%, var(--isis-surface)); color: var(--isis-accent); }
.isis-cmd-evt__status.status-valide_manager { background: color-mix(in srgb, var(--isis-success) 18%, var(--isis-surface)); color: var(--isis-success); }
.isis-cmd-evt__status.status-valide_projet { background: var(--isis-success); color: white; }
.isis-cmd-evt__status.status-rejete { background: color-mix(in srgb, var(--isis-danger) 18%, var(--isis-surface)); color: var(--isis-danger); }

/* État du visa projet sur la couche réalisé. La frise est DÉJÀ colorée par tâche (fond de l'event)
   et par charge (heatmap des cellules) : l'état de visa passe donc par une pastille, jamais par une
   recoloration de l'event, qui entrerait en concurrence avec les deux codes existants.
   Pas de margin-left:auto — le repère de surallocation garde la fin de ligne. */
.isis-cmd-evt__visa {
    font-size: 0.6rem;
    padding: 0.05rem 0.35rem;
    border-radius: var(--isis-radius-pill);
    font-weight: 600;
    white-space: nowrap;
    max-width: 8.5rem;
    overflow: hidden;
    text-overflow: ellipsis;
    background: var(--isis-surface);
    color: var(--isis-text-muted);
    border: 1px solid var(--isis-border);
}

.isis-cmd-evt__visa.is-a-viser {
    background: color-mix(in srgb, var(--isis-warning) 16%, var(--isis-surface));
    color: var(--isis-warning);
    border-color: color-mix(in srgb, var(--isis-warning) 40%, transparent);
}

.isis-cmd-evt__visa.is-vise {
    background: color-mix(in srgb, var(--isis-success) 16%, var(--isis-surface));
    color: var(--isis-success);
    border-color: color-mix(in srgb, var(--isis-success) 40%, transparent);
}

/* Réputé visé : accepté, mais par le silence. Le gris dit qu'aucune décision n'a été prise —
   le confondre avec un visé explicite effacerait précisément ce qui les distingue. */
.isis-cmd-evt__visa.is-repute {
    background: var(--isis-surface-alt);
    color: var(--isis-text-muted);
    border-color: var(--isis-border);
}

.isis-cmd-evt__visa.is-conteste {
    background: color-mix(in srgb, var(--isis-danger) 16%, var(--isis-surface));
    color: var(--isis-danger);
    border-color: color-mix(in srgb, var(--isis-danger) 40%, transparent);
}

/* Journée agrégée dont les saisies ne partagent pas le même état : aucune couleur d'état ne
   serait vraie pour l'ensemble. Contour pointillé = « la lecture est incomplète ici ». */
.isis-cmd-evt__visa.is-multiple {
    background: var(--isis-surface);
    color: var(--isis-text-muted);
    border-style: dotted;
}

.isis-cmd-evt__warn {
    margin-left: auto;
    width: 16px;
    height: 16px;
    border-radius: 50%;
    background: var(--isis-danger);
    color: white;
    font-weight: 700;
    font-size: 0.7rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}

.isis-cmd-evt__title {
    font-size: 0.7rem;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    color: var(--isis-text);
    font-weight: 500;
}

/* V2.0 — Décorations cellule via OnRenderCell. */
.isis-cmd-cell--weekend {
    background: color-mix(in srgb, var(--isis-text-muted) 8%, transparent) !important;
}
.isis-cmd-cell--today {
    box-shadow: inset 0 -2px 0 0 var(--isis-accent);
}
.isis-cmd-cell--today.e-date-header,
.isis-cmd-cell--today .e-date-header-name {
    color: var(--isis-accent);
    font-weight: 700;
}

/* V2.0 — Heatmap charge cumulée par jour (5 paliers, fonds très atténués pour ne pas masquer les events). */
.isis-cmd-heat--cool    { background: color-mix(in srgb, #93c5fd 14%, transparent) !important; }
.isis-cmd-heat--low     { background: color-mix(in srgb, var(--isis-success) 10%, transparent) !important; }
.isis-cmd-heat--normal  { /* 80-100% : neutre, pas de fond pour ne pas saturer */ }
.isis-cmd-heat--warning { background: color-mix(in srgb, var(--isis-warning) 14%, transparent) !important; }
.isis-cmd-heat--high    { background: color-mix(in srgb, var(--isis-danger) 16%, transparent) !important; }

/* V2.0 — KPI hero sticky quand l'utilisateur scrolle dans l'onglet. */
.isis-cmd-scheduler .isis-kpi-hero {
    position: sticky;
    top: 0;
    z-index: 2;
    background: var(--isis-surface);
    padding-top: 0.25rem;
    padding-bottom: 0.25rem;
}

/* V2.0 — Compaction Syncfusion : on cible uniquement le header de ressource (lane à gauche)
   sans toucher la hauteur des work-cells (Syncfusion les calcule en fonction du nombre
   d'events superposés — un override !important rend les events invisibles). */
.isis-cmd-scheduler-schedule.e-schedule .e-resource-cells {
    min-height: 42px;
    height: auto;
}
.isis-cmd-scheduler-schedule.e-schedule .e-date-header-wrap,
.isis-cmd-scheduler-schedule.e-schedule .e-timeline-header-list {
    z-index: 1;
}

/* Resource header (lane gauche) */
.isis-cmd-scheduler__resource-row {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.25rem 0.5rem;
}

.isis-cmd-scheduler__resource-avatar {
    /* V2.0 — couleur stable hashée sur CollabId, posée en variable inline par le composant. */
    width: 26px;
    height: 26px;
    border-radius: 50%;
    background: var(--isis-lane-accent, color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 22%, var(--isis-surface)));
    color: white;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-weight: 700;
    font-size: 0.7rem;
    flex-shrink: 0;
    letter-spacing: -0.02em;
}

.isis-cmd-scheduler__resource-name {
    font-size: 0.82rem;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* KPI hero variantes — calque kpi-card existants */
.isis-cmd-scheduler .isis-kpi-card.is-success .isis-kpi-card__value { color: var(--isis-success); }
.isis-cmd-scheduler .isis-kpi-card.is-warning .isis-kpi-card__value { color: var(--isis-warning); }
.isis-cmd-scheduler .isis-kpi-card.is-danger .isis-kpi-card__value { color: var(--isis-danger); }

/* ============================================================================
   GESFAC — Composant interactif plan d'étage (V1.1, 2026-05-25)
   Container avec aspect-ratio préservé, image de fond (placeholder si absent),
   markers HTML absolus positionnés via coord_x/y_ratio * 100%.
   ============================================================================ */

/* ----------------------------------------------------------------------------
   Plan d'étage V1.3 — refonte Leaflet zone carto.
   Le host wrap le container Leaflet + les overlays (hints) avec position
   absolute. Le card parent doit avoir une hauteur définie pour que .__leaflet
   puisse remplir (sinon Leaflet ne se rend pas, height:0).
   ---------------------------------------------------------------------------- */
.isis-plan-etage-host {
    position: relative;
    width: 100%;
    height: 100%;
    min-height: 480px; /* fallback si le parent n'a pas de hauteur explicite */
}

/* Panneau master du plan : ancre l'overlay .isis-map-toolbar (outils carte). */
.isis-master-detail__master.isis-plan-master { position: relative; }

.isis-plan-etage {
    position: absolute;
    inset: 0;
    /* z-index:0 → crée un contexte d'empilement qui PIÈGE les couches internes de
       Leaflet (panes/contrôles z-index 200–800). Sinon le pane image (z-index 400)
       fuit et passe au-dessus de la toolbar overlay (.isis-map-toolbar, z-index 400). */
    z-index: 0;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: 8px;
    overflow: hidden;
    box-shadow: var(--isis-elevation-1);
}

.isis-plan-etage__leaflet {
    /* Container Leaflet : prend toute la place dispo */
    width: 100%;
    height: 100%;
}

.isis-plan-etage.is-placement-mode {
    outline: 2px dashed color-mix(in srgb, var(--isis-mod-gesfac) 50%, transparent);
    outline-offset: 2px;
}

.isis-plan-etage.is-placement-mode .leaflet-container {
    cursor: crosshair;
}

.isis-plan-etage__placement-hint {
    position: absolute;
    top: 0.75rem;
    left: 50%;
    transform: translateX(-50%);
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.5rem 0.875rem;
    background: var(--isis-mod-gesfac);
    color: white;
    border-radius: var(--isis-radius-pill);
    font-size: 0.8125rem;
    font-weight: 500;
    box-shadow: var(--isis-elevation-2);
    z-index: 10;
    pointer-events: none;
    animation: isis-plan-etage-hint-pulse 1.8s ease-in-out infinite;
}

@keyframes isis-plan-etage-hint-pulse {
    0%, 100% { transform: translateX(-50%) scale(1); }
    50% { transform: translateX(-50%) scale(1.05); }
}

/* ----------------------------------------------------------------------------
   Markers : rendus via L.divIcon Leaflet (HTML custom dans .leaflet-marker-icon).
   Leaflet pose translate3d sur le wrapper externe — donc le marker LUI-MÊME
   doit rester en static (pas de position:absolute ni transform). Le wrapper
   externe `.isis-plan-etage__marker-wrap` neutralise le style par défaut Leaflet
   (qui pose un fond, padding, etc.).
   ---------------------------------------------------------------------------- */
.isis-plan-etage__marker-wrap {
    background: transparent;
    border: none;
}

.isis-plan-etage__marker {
    /* Cercle nu : icône du type au centre, le code est affiché au survol (tooltip).
       Pas de position absolute — Leaflet gère la position via translate3d sur le parent. */
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    padding: 0;
    background: var(--isis-surface);
    color: var(--isis-text);
    border: 2px solid var(--isis-border);
    border-radius: 50%;
    cursor: pointer;
    box-shadow: var(--isis-elevation-1);
    transition: transform 120ms ease, box-shadow 120ms ease, border-color 120ms ease;
}

.isis-plan-etage__marker .material-symbols-rounded { font-size: 18px; line-height: 1; }

.isis-plan-etage__marker:hover {
    transform: scale(1.08);
    box-shadow: var(--isis-elevation-hover);
}

.isis-plan-etage__marker:focus-visible {
    outline: 2px solid var(--isis-mod-gesfac);
    outline-offset: 2px;
}

.isis-plan-etage__marker.is-selected {
    border-color: var(--isis-mod-gesfac);
    background: color-mix(in srgb, var(--isis-mod-gesfac) 14%, var(--isis-surface));
    box-shadow: var(--isis-elevation-2);
}

.isis-plan-etage__marker .rzi { font-size: 14px; }
.isis-plan-etage__marker-code { font-family: var(--isis-font-mono, monospace); }

/* Vue verrouillée : zoom + pan désactivés → curseur normal (pas de main de drag).
   La classe is-view-locked est posée sur le conteneur Leaflet lui-même.
   Les marqueurs gardent leur propre cursor:pointer (cliquables même verrouillé). */
.isis-plan-etage.is-view-locked { cursor: default; }

/* Tooltip de survol du marqueur (code + occupancy) — boîte ISIS */
.isis-plan-etage__tip.leaflet-tooltip {
    background: var(--isis-surface);
    color: var(--isis-text);
    border: 1px solid var(--isis-border);
    border-radius: 8px;
    box-shadow: var(--isis-elevation-2);
    padding: 0.45rem 0.6rem;
    font-size: 0.78rem;
    line-height: 1.4;
    font-weight: 500;
    max-width: 260px;
    white-space: normal;
}
.isis-plan-etage__tip.leaflet-tooltip strong { font-family: var(--isis-font-mono, monospace); }
.isis-plan-etage__tip.leaflet-tooltip-top::before { border-top-color: var(--isis-border); }
.isis-plan-etage__tip .isis-plan-etage__tip-occ  { color: var(--isis-success); }
.isis-plan-etage__tip .isis-plan-etage__tip-eq   { color: var(--isis-info, #3b82f6); }
.isis-plan-etage__tip .isis-plan-etage__tip-free { color: var(--isis-text-muted); }
.isis-plan-etage__tip .isis-plan-etage__tip-hint { color: var(--isis-text-muted); font-style: italic; }

/* Variantes par état */
.isis-plan-etage__marker--ok        { border-color: color-mix(in srgb, var(--isis-success) 50%, var(--isis-border)); }
.isis-plan-etage__marker--ok .rzi   { color: var(--isis-success); }

.isis-plan-etage__marker--warning      { border-color: color-mix(in srgb, var(--isis-warning) 50%, var(--isis-border)); }
.isis-plan-etage__marker--warning .rzi { color: var(--isis-warning); }

.isis-plan-etage__marker--danger       { border-color: color-mix(in srgb, var(--isis-danger) 50%, var(--isis-border)); background: color-mix(in srgb, var(--isis-danger) 8%, var(--isis-surface)); }
.isis-plan-etage__marker--danger .rzi  { color: var(--isis-danger); }

.isis-plan-etage__marker--muted        { opacity: 0.55; }
.isis-plan-etage__marker--muted .rzi   { color: var(--isis-text-muted); }

/* Mode flexible (hot desk) : trait pointillé pour différencier visuellement */
.isis-plan-etage__marker--flexible {
    border-style: dashed;
}

/* ----------------------------------------------------------------------------
   Variantes occupancy V1.3 — couleur de fond selon affectation courante :
   - occupied : un collab est assigné (vert clair = poste vivant)
   - equipped : que des équipements, pas de collab (bleu clair = poste meublé)
   - empty    : ni l'un ni l'autre (gris muet = poste libre, candidat à affecter)
   Coexiste avec les variantes d'état (--ok/--warning/--danger/--muted) qui
   restent visibles via la bordure (occupancy = remplissage, state = bordure).
   ---------------------------------------------------------------------------- */
.isis-plan-etage__marker--occ-occupied {
    background: color-mix(in srgb, var(--isis-success) 14%, var(--isis-surface));
}
.isis-plan-etage__marker--occ-equipped {
    background: color-mix(in srgb, var(--isis-info, #3b82f6) 12%, var(--isis-surface));
}
.isis-plan-etage__marker--occ-empty {
    background: var(--isis-surface);
    opacity: 0.85;
}
.isis-plan-etage__marker--occ-empty:hover {
    opacity: 1;
}

/* Badge occupancy : pastille colorée en haut-droite du marker */
.isis-plan-etage__marker-badge {
    position: absolute;
    top: -6px;
    right: -6px;
    width: 16px;
    height: 16px;
    border-radius: 50%;
    background: var(--isis-surface);
    border: 1.5px solid var(--isis-border);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    box-shadow: var(--isis-elevation-1);
}
.isis-plan-etage__marker-badge .material-symbols-rounded {
    font-size: 10px;
    line-height: 1;
}
.isis-plan-etage__marker-badge--occupant {
    background: var(--isis-success);
    border-color: var(--isis-success);
}
.isis-plan-etage__marker-badge--occupant .material-symbols-rounded { color: white; }

.isis-plan-etage__marker-badge--equip {
    background: var(--isis-info, #3b82f6);
    border-color: var(--isis-info, #3b82f6);
}
.isis-plan-etage__marker-badge--equip .material-symbols-rounded { color: white; }

/* Le marker a besoin de position:relative pour positionner le badge en absolute */
.isis-plan-etage__marker { position: relative; }

/* Mode placement actif : markers atténués pour donner la priorité visuelle au clic vide */
.isis-plan-etage.is-placement-mode .isis-plan-etage__marker {
    opacity: 0.7;
}
.isis-plan-etage.is-placement-mode .isis-plan-etage__marker:hover {
    opacity: 1;
}

/* ----------------------------------------------------------------------------
   V1.2 — Mode édition glisser-déposer.
   Markers draggable affichent un curseur grab/grabbing + visuel pendant le drag.
   ---------------------------------------------------------------------------- */
.isis-plan-etage.is-edit-mode {
    outline: 2px dashed color-mix(in srgb, var(--isis-accent) 60%, transparent);
    outline-offset: 2px;
}

.isis-plan-etage.is-edit-mode .isis-plan-etage__marker[draggable="true"] {
    cursor: grab;
}

.isis-plan-etage.is-edit-mode .isis-plan-etage__marker[draggable="true"]:active,
.isis-plan-etage__marker.is-dragging {
    cursor: grabbing;
    opacity: 0.55;
    transform: scale(0.95);
}

/* En mode édition, le wrapper Leaflet doit indiquer le curseur grab même quand
   le pointeur n'est pas exactement sur le bouton interne. */
.isis-plan-etage.is-edit-mode .leaflet-marker-icon { cursor: grab; }
.isis-plan-etage.is-edit-mode .leaflet-marker-icon:active { cursor: grabbing; }

.isis-plan-etage__placement-hint--edit {
    background: var(--isis-accent);
}

/* ----------------------------------------------------------------------------
   Statut occupancy d'un emplacement sélectionné (sidepanel PlanEtageDetail)
   ---------------------------------------------------------------------------- */
.isis-emplacement-status {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.3rem 0.7rem;
    border-radius: var(--isis-radius-pill);
    font-size: 0.78rem;
    font-weight: 600;
    margin: 0.5rem 0 0.75rem;
}
.isis-emplacement-status .rzi { font-size: 14px; }

.isis-emplacement-status--is-occupied {
    background: color-mix(in srgb, var(--isis-success) 14%, var(--isis-surface));
    color: var(--isis-success);
    border: 1px solid color-mix(in srgb, var(--isis-success) 30%, transparent);
}
.isis-emplacement-status--is-equipped {
    background: color-mix(in srgb, var(--isis-info, #3b82f6) 12%, var(--isis-surface));
    color: var(--isis-info, #3b82f6);
    border: 1px solid color-mix(in srgb, var(--isis-info, #3b82f6) 30%, transparent);
}
.isis-emplacement-status--is-empty {
    background: var(--isis-surface-alt);
    color: var(--isis-text-muted);
    border: 1px solid var(--isis-border);
}
.isis-emplacement-status__more {
    color: var(--isis-text-muted);
    font-size: 0.75rem;
}

/* ----------------------------------------------------------------------------
   Mini-dashboard occupancy au niveau du plan (sidepanel par défaut)
   ---------------------------------------------------------------------------- */
.isis-plan-occupancy-summary {
    margin: 0.5rem 0 1rem;
    padding: 0.75rem;
    background: var(--isis-surface-alt);
    border: 1px solid var(--isis-border);
    border-radius: 8px;
}
.isis-plan-occupancy-summary__pct {
    display: flex;
    align-items: baseline;
    gap: 0.5rem;
}
.isis-plan-occupancy-summary__pct-value {
    font-size: 1.5rem;
    font-weight: 700;
    color: var(--isis-mod-gesfac);
}
.isis-plan-occupancy-summary__pct-label {
    font-size: 0.78rem;
    color: var(--isis-text-muted);
}

.isis-plan-occupancy-summary__bar {
    margin-top: 0.45rem;
    height: 6px;
    background: var(--isis-border);
    border-radius: var(--isis-radius-pill);
    overflow: hidden;
}
.isis-plan-occupancy-summary__bar-fill {
    height: 100%;
    background: var(--isis-success);
    border-radius: var(--isis-radius-pill);
    transition: width 240ms ease;
}

.isis-plan-occupancy-summary__legend {
    list-style: none; padding: 0; margin: 0.65rem 0 0;
    display: grid; gap: 0.3rem;
}
.isis-plan-occupancy-summary__legend li {
    display: grid;
    grid-template-columns: 12px 28px 1fr;
    align-items: center;
    gap: 0.45rem;
    font-size: 0.82rem;
}
.isis-plan-occupancy-summary__legend .dot {
    width: 10px; height: 10px; border-radius: 50%;
    border: 1px solid var(--isis-border);
}
.isis-plan-occupancy-summary__legend .cnt {
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: var(--isis-text);
    text-align: right;
}
.isis-plan-occupancy-summary__legend .lbl {
    color: var(--isis-text-muted);
}
.isis-plan-occupancy-summary__legend .is-occupied .dot { background: var(--isis-success); border-color: var(--isis-success); }
.isis-plan-occupancy-summary__legend .is-equipped .dot { background: var(--isis-info, #3b82f6); border-color: var(--isis-info, #3b82f6); }
.isis-plan-occupancy-summary__legend .is-empty .dot    { background: var(--isis-surface); }


/* ============================================================================
   Kanban — vue pipeline commercial (migrations 0234 pilotage commercial)
   ----------------------------------------------------------------------------
   Utilisé par : /gesmaff/demandes-client/pipeline (V1)
   Pattern : 1 colonne par statut, drag-drop natif HTML5 entre colonnes.
   Conformité DESIGN.md : palette --isis-* uniquement, pas de couleurs ad-hoc.
   ============================================================================ */
.isis-kanban {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: minmax(260px, 1fr);
    gap: 0.75rem;
    overflow-x: auto;
    overflow-y: hidden;
    align-items: stretch;
    padding-bottom: 0.5rem;
    /* Occupe toute la hauteur restante de .isis-rich-page (flex parent).
       Le scroll vertical vit dans chaque colonne (.isis-kanban__col-body),
       jamais sur la page entière. */
    flex: 1 1 auto;
    min-height: 0;
}

.isis-kanban__column {
    display: flex;
    flex-direction: column;
    min-height: 0;
    background: var(--isis-surface-soft);
    border: 1px solid var(--isis-border-soft);
    border-radius: 8px;
    box-shadow: var(--isis-elevation-1);
    transition: box-shadow 0.15s ease, border-color 0.15s ease;
}

.isis-kanban__column.is-drop-target {
    border-color: var(--isis-accent);
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--isis-accent) 25%, transparent),
                var(--isis-elevation-1);
}

.isis-kanban__col-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    padding: 0.75rem 0.85rem;
    border-bottom: 1px solid var(--isis-border-soft);
    position: sticky;
    top: 0;
    background: var(--isis-surface-soft);
    border-radius: 8px 8px 0 0;
    z-index: 1;
}

.isis-kanban__col-title {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--isis-text);
    text-transform: uppercase;
    letter-spacing: 0.02em;
    /* Porté aussi par un <h2> (vue par étape des Opportunités) : la marge et l'interligne du
       titre natif ne doivent pas décaler l'en-tête de colonne. */
    margin: 0;
    line-height: inherit;
}

.isis-kanban__col-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    flex-shrink: 0;
}

.isis-kanban__col-dot.is-aqualifier { background: var(--isis-info); }
.isis-kanban__col-dot.is-qualifiee  { background: var(--isis-success); }
.isis-kanban__col-dot.is-perdue     { background: var(--isis-danger); }
.isis-kanban__col-dot.is-abandonnee { background: var(--isis-text-muted); }
.isis-kanban__col-dot.is-default    { background: var(--isis-text-muted); }

/* Statuts appel d'offre (pipeline marché public) */
.isis-kanban__col-dot.is-identifie    { background: color-mix(in srgb, var(--isis-info) 45%, var(--isis-text-muted)); }
.isis-kanban__col-dot.is-preparation  { background: var(--isis-warning); }
.isis-kanban__col-dot.is-depose       { background: var(--isis-accent); }
.isis-kanban__col-dot.is-obtenu       { background: var(--isis-success); }
.isis-kanban__col-dot.is-perdu        { background: var(--isis-danger); }
.isis-kanban__col-dot.is-abandonne    { background: var(--isis-text-muted); }
.isis-kanban__col-dot.is-annule       { background: var(--isis-text-muted); }

/* Pastille compte à rebours dépôt AO */
.isis-kanban__card-meta { font-size: var(--isis-fs-label); }
.isis-kanban__empty { font-size: var(--isis-fs-base); color: var(--isis-text-muted); }
.isis-kanban__card-deadline {
    display: inline-flex;
    align-items: center;
    gap: 0.2rem;
    font-size: 0.7rem;
    font-weight: 600;
    color: var(--isis-text-muted);
}
.isis-kanban__card-deadline.is-urgent { color: var(--isis-danger); }
.isis-kanban__card-deadline.is-overdue {
    color: var(--isis-danger);
    font-weight: 700;
}
.isis-kanban__card-amount {
    font-size: 0.72rem;
    font-weight: 600;
    color: var(--isis-text);
    font-variant-numeric: tabular-nums;
}

.isis-kanban__col-count {
    font-size: 0.78rem;
    font-weight: 600;
    color: var(--isis-text-muted);
    background: var(--isis-surface);
    border: 1px solid var(--isis-border-soft);
    border-radius: var(--isis-radius-pill);
    padding: 0.15rem 0.55rem;
    min-width: 28px;
    text-align: center;
}

.isis-kanban__col-body {
    flex: 1;
    overflow-y: auto;
    padding: 0.6rem;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.isis-kanban__col-empty {
    padding: 1.5rem 0.5rem;
    text-align: center;
    border: 1px dashed var(--isis-border-soft);
    border-radius: 6px;
    background: color-mix(in srgb, var(--isis-surface) 50%, transparent);
}

/* ── Carte ─────────────────────────────────────────────────────────────── */
.isis-kanban__card {
    background: var(--isis-surface);
    border: 1px solid var(--isis-border-soft);
    border-radius: 6px;
    padding: 0.6rem 0.7rem;
    cursor: grab;
    box-shadow: var(--isis-elevation-1);
    transition: box-shadow 0.15s ease, transform 0.1s ease, opacity 0.1s ease;
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
}

/* Une offre que l'utilisateur ne peut que consulter n'est pas saisissable : le curseur le dit
   en permanence, au lieu de promettre une prise qui ne mordra pas. */
.isis-kanban__card[draggable="false"] {
    cursor: pointer;
}

.isis-kanban__card:hover,
.isis-kanban__card:focus-visible {
    box-shadow: var(--isis-elevation-hover);
    outline: 2px solid color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 25%, transparent);
    outline-offset: 0;
}

.isis-kanban__card.is-dragging {
    opacity: 0.45;
    cursor: grabbing;
    transform: scale(0.97);
}

.isis-kanban__card-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
}

.isis-kanban__card-ref {
    font-family: var(--isis-font-mono);
    font-size: 0.78rem;
    font-weight: 600;
    color: var(--isis-text-soft);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 60%;
}

.isis-kanban__card-canal {
    font-size: 0.7rem;
    color: var(--isis-text-muted);
    padding: 0.1rem 0.4rem;
    background: var(--isis-surface-soft);
    border-radius: 3px;
    text-transform: uppercase;
    letter-spacing: 0.02em;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 40%;
}

.isis-kanban__card-title {
    font-size: 0.88rem;
    font-weight: 500;
    color: var(--isis-text);
    line-height: 1.3;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.isis-kanban__card-tiers {
    font-size: 0.78rem;
    color: var(--isis-text-soft);
    display: flex;
    align-items: center;
    gap: 0.25rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.isis-kanban__card-foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    font-size: 0.75rem;
    color: var(--isis-text-muted);
    border-top: 1px dashed var(--isis-border-soft);
    padding-top: 0.35rem;
    margin-top: 0.15rem;
}

.isis-kanban__card-date,
.isis-kanban__card-owner {
    display: inline-flex;
    align-items: center;
    gap: 0.2rem;
}

.isis-kanban__card-owner.is-unassigned {
    color: var(--isis-accent);
}

/* ── Responsive ────────────────────────────────────────────────────────── */
@media (max-width: 768px) {
    .isis-kanban {
        grid-auto-columns: 85vw;
    }
}

/* Kanban — extensions colonne CONVERTIE virtuelle (read-only) */
.isis-kanban__col-dot.is-convertie {
    background: var(--isis-success);
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--isis-success) 25%, transparent);
}

.isis-kanban__column.is-readonly {
    background: color-mix(in srgb, var(--isis-success) 4%, var(--isis-surface-soft));
    border-color: color-mix(in srgb, var(--isis-success) 25%, var(--isis-border-soft));
}

.isis-kanban__column.is-readonly .isis-kanban__col-head {
    background: color-mix(in srgb, var(--isis-success) 5%, var(--isis-surface-soft));
}

.isis-kanban__col-derived {
    display: inline-flex;
    align-items: center;
    color: var(--isis-success);
    margin-left: 0.3rem;
    cursor: help;
}

.isis-kanban__card.is-readonly {
    cursor: pointer; /* clic = ouvrir fiche, mais pas de drag */
    border: 1px solid var(--isis-success);
    box-sizing: border-box;
}

.isis-kanban__card.is-readonly:hover,
.isis-kanban__card.is-readonly:focus-visible {
    background: color-mix(in srgb, var(--isis-success) 4%, var(--isis-surface));
}

/* Vue par étape des Opportunités — « Voir comme » : la lecture seule se signale en neutre ; le
   vert de .is-readonly signifie ailleurs « gagné / dérivé », sens qui n'a pas cours ici. */
.isis-kanban--lecture-seule .isis-kanban__column.is-readonly {
    background: var(--isis-surface-soft);
    border-color: var(--isis-border-soft);
}

.isis-kanban--lecture-seule .isis-kanban__column.is-readonly .isis-kanban__col-head {
    background: var(--isis-surface-soft);
}

.isis-kanban--lecture-seule .isis-kanban__card.is-readonly {
    border: 1px dashed var(--isis-border);
}

.isis-kanban--lecture-seule .isis-kanban__card.is-readonly:hover,
.isis-kanban--lecture-seule .isis-kanban__card.is-readonly:focus-visible {
    background: var(--isis-surface);
}

/* Changement de statut sans glisser : bouton frère de la carte (jamais imbriqué dans son
   role="button"), liste déroulée dans le flux — un panneau flottant serait rogné par le
   défilement de la colonne. */
.isis-kanban__card-wrap {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
}

.isis-kanban__card-wrap > .isis-kanban__card .isis-kanban__card-head {
    padding-right: 1.75rem;
}

.isis-kanban__card-menu-btn {
    position: absolute;
    top: 0.35rem;
    right: 0.35rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    padding: 0;
    border: 1px solid transparent;
    border-radius: var(--isis-radius-sm);
    background: transparent;
    color: var(--isis-text-soft);
    cursor: pointer;
}

.isis-kanban__card-menu-btn:hover,
.isis-kanban__card-menu-btn[aria-expanded="true"] {
    background: var(--isis-surface-alt);
    border-color: var(--isis-border);
    color: var(--isis-text);
}

.isis-kanban__card-menu-btn:focus-visible {
    outline: 2px solid var(--isis-current-mod, var(--isis-accent));
    outline-offset: 1px;
}

.isis-kanban__card-menu-btn:disabled {
    opacity: 0.5;
    cursor: default;
}

.isis-kanban__card-menu {
    min-width: 0;
    padding: 0.25rem;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: 6px;
    box-shadow: var(--isis-elevation-1);
}

.isis-kanban__card-menu-empty {
    padding: 0.4rem 0.6rem;
    font-size: 0.8125rem;
    color: var(--isis-text-muted);
}

.isis-kanban__card-won-badge {
    display: inline-flex;
    align-items: center;
    gap: 0.2rem;
    font-size: 0.72rem;
    font-weight: 600;
    color: var(--isis-success);
    background: color-mix(in srgb, var(--isis-success) 14%, var(--isis-surface));
    border: 1px solid color-mix(in srgb, var(--isis-success) 30%, transparent);
    padding: 0.1rem 0.45rem;
    border-radius: var(--isis-radius-pill);
    flex-shrink: 0;
}

/* ============================================================================
   Kanban devis (N2.7) — variantes de dot par statut devis + drop forbidden
   Réutilise la majorité du système kanban existant (gesmaff DemandeClient).
   ============================================================================ */
.isis-kanban__col-dot.is-devis-draft            { background: var(--isis-info); }
.isis-kanban__col-dot.is-devis-pending_approval { background: var(--isis-warning); }
.isis-kanban__col-dot.is-devis-approved         { background: var(--isis-info); }
.isis-kanban__col-dot.is-devis-sent             { background: var(--isis-accent); }
.isis-kanban__col-dot.is-devis-accepted         { background: var(--isis-success); }

.isis-kanban__column--devis {
    min-width: 240px;
    max-width: 320px;
}

.isis-kanban__column.is-drop-forbidden {
    border-color: color-mix(in srgb, var(--isis-danger) 35%, var(--isis-border-soft));
    background: color-mix(in srgb, var(--isis-danger) 4%, var(--isis-surface-soft));
}

.isis-kanban__column.is-drop-forbidden::after {
    content: "Transition non autorisée — passer par la fiche";
    display: block;
    margin: 0.4rem 0.6rem;
    padding: 0.3rem 0.5rem;
    font-size: 0.72rem;
    color: var(--isis-danger);
    background: color-mix(in srgb, var(--isis-danger) 8%, var(--isis-surface));
    border: 1px dashed color-mix(in srgb, var(--isis-danger) 40%, transparent);
    border-radius: 4px;
    text-align: center;
}

.isis-kanban__card-owner.is-warning {
    color: var(--isis-warning);
    background: color-mix(in srgb, var(--isis-warning) 12%, var(--isis-surface));
}

.isis-kanban__card-owner.is-expired {
    color: var(--isis-danger);
    background: color-mix(in srgb, var(--isis-danger) 12%, var(--isis-surface));
}


/* ============================================================================
   Panneau de recherche universelle (Ctrl+K)
   Refonte 2026-09-05 : la modale centrée devient un PANNEAU ANCRÉ sous la barre
   de recherche de l'en-tête. La recherche n'est plus une parenthèse hors du
   travail — l'écran courant reste visible derrière, et l'utilisateur voit d'où
   il part. Le backdrop perd donc son voile et son flou : il n'est plus qu'un
   capteur de clic extérieur.

   Ancrage : --isis-cmdp-top / --isis-cmdp-right sont posées par command-palette.js
   (le bord droit du bouton dépend de la largeur des actions de l'en-tête, qui est
   du contenu). Les replis ci-dessous tiennent seuls si le JS ne répond pas.
   ============================================================================ */
.isis-cmdp-backdrop {
    position: fixed;
    inset: 0;
    z-index: 1000;
    /* Ni voile ni flou : l'écran de travail doit rester lisible pendant la recherche. */
    background: transparent;
}
@keyframes isis-cmdp-fade-in {
    from { opacity: 0; }
    to   { opacity: 1; }
}
.isis-cmdp {
    /* Positionnée AU-DESSUS du backdrop (z-index 1000) : sans ça, .isis-cmdp est
       static (z-index auto) → elle passe SOUS lui (fix 2026-06-23). */
    position: fixed;
    top: var(--isis-cmdp-top, calc(var(--isis-header-h, 56px) + 8px));
    /* La largeur passe par une variable parce que l'ancrage droit doit s'en servir :
       `--isis-cmdp-right` est mesurée sur le bord droit du bouton de l'en-tête et ne sait
       rien de la largeur du panneau. À 860 px de fenêtre, 317 px d'ancrage + 642 px de
       panneau mettaient son bord GAUCHE à -99 px — mesuré, pas supposé. Le `min()` le
       ramène dans la fenêtre, le `max()` garde une gouttière à gauche. */
    --isis-cmdp-w: min(940px, calc(100vw - 2rem));
    right: max(0.5rem, min(var(--isis-cmdp-right, 1rem),
                           calc(100vw - var(--isis-cmdp-w) - 0.5rem)));
    z-index: 1001;
    width: var(--isis-cmdp-w);
    max-height: 70vh;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    /* Seule reliure visuelle avec la pilule : la même teinte de module que sa bordure
       une fois ouverte. Le panneau fait 940 px pour 560 px de pilule — les deux ne
       coïncident que par leur bord DROIT, et 380 px de débord à gauche ne se lisent
       pas comme une extension sans ce rappel. */
    border-top-color: var(--isis-current-mod, var(--isis-accent));
    border-radius: var(--isis-radius-lg, 12px);
    box-shadow: var(--isis-elevation-2);
    display: flex;
    flex-direction: column;
    overflow: hidden;
    /* Descente courte depuis la barre : le panneau vient de l'en-tête, il n'apparaît
       pas au milieu de l'écran. */
    animation: isis-cmdp-drop-in 140ms cubic-bezier(0.16, 1, 0.3, 1);
}
@keyframes isis-cmdp-drop-in {
    from { transform: translateY(-6px); opacity: 0; }
    to   { transform: translateY(0);    opacity: 1; }
}
@keyframes isis-cmdp-scale-in {
    from { transform: scale(0.96); opacity: 0; }
    to   { transform: scale(1);    opacity: 1; }
}
.isis-cmdp__header {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.85rem 1rem;
    border-bottom: 1px solid var(--isis-border-soft);
    flex-shrink: 0;
}
/* Au-dessus de 900 px, la saisie vit dans la pilule de l'en-tête : cet en-tête de panneau
   n'a plus lieu d'être. `display: none` et pas une suppression côté Razor, parce que le
   seuil est une affaire de LARGEUR DE FENÊTRE, que le serveur ne connaît pas — et il retire
   le bloc de l'arbre d'accessibilité comme de l'ordre de tabulation, donc pas de second
   combobox concurrent sur le même listbox. Sous le seuil, il reprend tout son rôle.
   Le seuil est le MÊME que celui de la pilule (900 px) : à 1 px près, on obtenait une
   fenêtre où ni la pilule ni le panneau n'offraient de champ. */
@media (min-width: 901px) {
    .isis-cmdp__header { display: none; }
    /* Le filet de l'en-tête disparaissant avec lui, la première rangée touchait l'arrondi
       du panneau. */
    .isis-cmdp__results { padding-top: 0.5rem; }
}
.isis-cmdp__input {
    flex: 1;
    min-width: 0;
    border: none;
    outline: none;
    background: transparent;
    font-size: 1rem;
    color: var(--isis-text);
    font-family: inherit;
}
/* `outline: none` sans substitut : la saisie n'avait aucun indicateur de focus.
   Halo DESIGN.md sur la couleur du module courant. */
.isis-cmdp__input:focus-visible {
    outline: 2px solid var(--isis-current-mod, var(--isis-accent));
    outline-offset: 3px;
    border-radius: var(--isis-radius-sm);
}
.isis-cmdp__input::placeholder {
    color: var(--isis-text-soft);
}
/* Vrai bouton de fermeture : il portait un `title` sur un <kbd>, donc une infobulle
   sur un élément que personne ne pouvait activer — et que tout le monde cliquait. */
.isis-cmdp__esc {
    display: inline-flex;
    align-items: center;
    font-family: var(--isis-font-mono, ui-monospace, monospace);
    font-size: 0.7rem;
    padding: 2px 6px;
    background: var(--isis-surface-alt);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-sm);
    /* --isis-text-soft tombait à 3,82:1 sur la surface : sous le plancher de 4,5. */
    color: var(--isis-text-muted);
    flex-shrink: 0;
    cursor: pointer;
}
.isis-cmdp__esc kbd {
    font: inherit;
    color: inherit;
    background: none;
    border: none;
    padding: 0;
}
.isis-cmdp__esc:hover { color: var(--isis-text); border-color: var(--isis-border-strong); }
.isis-cmdp__esc:focus-visible {
    outline: 2px solid var(--isis-current-mod, var(--isis-accent));
    outline-offset: 2px;
}
/* Indicateur de requête en vol. Volontairement discret : la frappe suivante
   annule la précédente, un spinner franc clignoterait à chaque caractère.
   Le cercle est TOUJOURS monté et ne fait varier que son opacité : la saisie qui le
   précède est en `flex: 1`, donc le monter/démonter lui reprenait 14 px + la
   gouttière à chaque cycle d'antirebond — le texte tapé sautait sous le curseur. */
.isis-cmdp__spinner {
    width: 14px;
    height: 14px;
    flex-shrink: 0;
    border: 2px solid transparent;
    border-radius: var(--isis-radius-pill);
    opacity: 0;
    transition: opacity var(--isis-motion-fast);
}
.isis-cmdp__spinner.is-visible {
    border-color: var(--isis-border);
    border-top-color: var(--isis-current-mod, var(--isis-accent));
    opacity: 1;
    animation: isis-cmdp-spin 700ms linear infinite;
}
@keyframes isis-cmdp-spin {
    to { transform: rotate(360deg); }
}

/* Rangée d'entonnoirs à effectifs — une famille par pastille, l'effectif étant
   celui du périmètre de l'utilisateur, pas de la table. Séparée de la liste par
   un filet : c'est un arbitrage, pas un résultat. */
.isis-cmdp__facets {
    display: flex;
    /* Sans nowrap, onze pastilles occupaient trois lignes et mangeaient quatre-vingt-dix
       pixels avant le premier résultat. Elles défilent latéralement. */
    flex-wrap: nowrap;
    overflow-x: auto;
    scrollbar-width: thin;
    gap: 0.3rem;
    /* Hauteur réservée : la rangée se remonte à chaque frappe, et sans plancher tout le
       panneau montait puis redescendait de quarante pixels sous le curseur. */
    min-height: 2.1rem;
    align-items: center;
    padding: 0.5rem 0.75rem;
    border-bottom: 1px solid var(--isis-border);
    flex-shrink: 0;
}
/* L'entonnoir EST un .isis-chip : forme, survol, focus et compteur viennent du
   système. Il ne reste ici que la densité propre au panneau — onze pastilles dans
   640 px n'ont pas la place d'un chip de barre de filtres. */
.isis-cmdp__facet {
    height: 24px;
    padding: 0 0.55rem;
    font-family: inherit;
    font-size: 0.72rem;
    white-space: nowrap;
    flex-shrink: 0;
}
/* L'état actif s'écarte volontairement de `.isis-chip.is-active`, qui pose du BLANC
   sur la couleur pleine du module : mesuré à 4,20:1 sur l'accent par défaut, et
   cinq des dix-huit accents du système tombent sous le plancher. Ici l'encre reste
   --isis-text — la couleur du module porte le fond, la bordure et la graisse, ce qui
   met le pire cas à 14,8:1 en clair et 11,8:1 en sombre.
   Le sélecteur est délibérément PLUS SPÉCIFIQUE que `.isis-chip.is-active` : à
   spécificité égale l'écrasement ne tenait que par l'ordre des règles dans la feuille,
   et un simple déplacement de bloc aurait silencieusement rétabli le 4,20:1. */
.isis-cmdp__facets .isis-chip.isis-cmdp__facet.is-active {
    background-color: var(--isis-current-mod-soft, var(--isis-accent-soft));
    border-color: var(--isis-current-mod, var(--isis-accent));
    color: var(--isis-text);
    font-weight: 600;
}
.isis-cmdp__facets .isis-chip.isis-cmdp__facet.is-active:hover {
    background-color: var(--isis-current-mod-soft, var(--isis-accent-soft));
    color: var(--isis-text);
}

/* En-tête de famille dans la liste — même registre que .isis-subnav__group-header :
   petites capitales, tertiaire, non cliquable. */
/* Conteneur d'une famille — role="group" nommé par son en-tête. Il reprend la mise
   en colonne que .isis-cmdp__results portait seule avant le groupage. */
.isis-cmdp__group {
    display: flex;
    flex-direction: column;
    gap: 1px;
}

.isis-cmdp__family {
    /* Collant en tête de défilement : passé la dixième ligne de devis, on ne sait
       plus dans quelle famille on est. Le fond opaque est indispensable — sans lui
       les lignes défileraient à travers l'en-tête. */
    position: sticky;
    top: 0;
    z-index: 1;
    background: var(--isis-surface);
    padding: 0.55rem 0.75rem 0.25rem;
    color: var(--isis-text-soft);
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
}
.isis-cmdp__family:first-child {
    padding-top: 0.2rem;
}

/* Échec de recherche : la liste est AMPUTÉE, pas vide. Registre sémantique, pas module. */
.isis-cmdp__erreur {
    display: flex;
    align-items: flex-start;
    gap: 0.5rem;
    margin: 0.35rem;
    padding: 0.5rem 0.6rem;
    /* Les seuls jetons de danger qui existent sont --isis-danger et --isis-danger-soft ;
       l'encre reste --isis-text, qui tient le contraste sur le lavis dans les deux thèmes. */
    border: 1px solid var(--isis-danger);
    border-radius: var(--isis-radius);
    background: var(--isis-danger-soft);
    color: var(--isis-text);
    font-size: 0.78rem;
    line-height: 1.35;
}

/* Passage du corps d'un document trouvé par le moteur plein texte.
   Le lavis du module est à 1,20:1 du fond : « ce passage correspond à votre recherche » ne
   peut pas tenir à cette seule teinte (WCAG 1.4.1). La GRAISSE porte l'information, la
   couleur ne fait que la renforcer — et l'encre passe au texte plein, plus foncée que le
   chemin atténué qui l'entoure. Même règle sur les deux surlignages, liste et aperçu. */
.isis-cmdp__result-extract mark {
    background: var(--isis-current-mod-soft, var(--isis-accent-soft));
    color: var(--isis-text);
    font-weight: 600;
    padding: 0 1px;
    border-radius: var(--isis-radius-sm);
}

/* Note du pied : le filtre de famille est tombé faute de résultat. */
.isis-cmdp__note {
    font-size: 0.7rem;
    color: var(--isis-text-muted);
}

.isis-cmdp__results {
    flex: 1;
    overflow-y: auto;
    padding: 0.35rem 0;
    display: flex;
    flex-direction: column;
    gap: 1px;
    min-height: 0;
}
.isis-cmdp__empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    padding: 3rem 1.5rem;
    color: var(--isis-text-muted);
    font-size: 0.9rem;
    text-align: center;
}
.isis-cmdp__empty strong { color: var(--isis-text); font-weight: 600; }
.isis-cmdp__result {
    /* scrollIntoView ramène la ligne au bord du cadre — que l'en-tête de famille
       collant recouvre. La marge réserve sa hauteur. */
    scroll-margin-top: 26px;
    scroll-margin-bottom: 4px;
    display: flex;
    align-items: center;
    gap: 0.6rem;
    /* Densité resserrée : 12 à 13 lignes visibles au lieu de 9, sans toucher aux polices. */
    padding: 0.45rem 0.75rem;
    border: none;
    background: transparent;
    /* Coins vifs. Le liseré de la ligne courante est un `inset box-shadow` : arrondir
       la ligne le rognait à ses deux extrémités, et un repère de forme qui s'incurve se
       lit comme une pastille, pas comme le bord d'une bande. La bande court de bord à
       bord du panneau (cf. .isis-cmdp__results), le liseré en tient le flanc gauche. */
    border-radius: 0;
    color: var(--isis-text);
    text-align: left;
    cursor: pointer;
    transition: background-color 80ms ease;
    width: 100%;
}
.isis-cmdp__result.is-active {
    background-color: var(--isis-current-mod-soft, var(--isis-accent-soft));
    /* Le lavis seul est à 1,20:1 du fond du panneau — sous le plancher de 3:1 des
       indicateurs non textuels, alors qu'il est l'UNIQUE repère du curseur clavier.
       Le liseré est un indicateur de FORME, il ne dépend pas de la lecture d'une teinte.
       PAS --isis-current-mod-strong : ce jeton mélange vers le NOIR, ce qui donne en
       thème sombre un liseré rgb(0,39,55) sur un panneau rgb(22,28,37) — 1,10:1, soit
       un repère invisible. La teinte pleine du module tient dans les deux thèmes. */
    box-shadow: inset 3px 0 0 0 var(--isis-current-mod, var(--isis-accent));
}
/* Ligne affichée mais non activable : le document remonte mais ne s'ouvre pas encore,
   et la note de frais n'a pas de fiche du tout. Son titre garde la couleur d'un titre —
   le griser à la couleur de son propre sous-titre effaçait la hiérarchie de la ligne et
   se lisait « moins pertinent » au lieu de « ne s'ouvre pas ». Ce que ça ne fait pas est
   dit par un cadenas ET par une étiquette en toutes lettres. */
.isis-cmdp__result.is-inert {
    cursor: default;
}
/* Espace de travail d'un objet, quand ce n'est pas celui où l'on se trouve. Même
   registre que l'étiquette d'une ligne inerte — une mention, pas une alerte : la ligne
   s'ouvre parfaitement, elle emmène simplement ailleurs. */
.isis-cmdp__result-espace {
    flex-shrink: 0;
    padding: 0 0.3rem;
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-sm);
    color: var(--isis-text-muted);
    font-size: 0.7rem;
    line-height: 1.4;
    white-space: nowrap;
    max-width: 11rem;
    overflow: hidden;
    text-overflow: ellipsis;
}
.isis-cmdp__result-tag {
    flex-shrink: 0;
    padding: 0 0.3rem;
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-sm);
    color: var(--isis-text-muted);
    font-size: 0.7rem;
    line-height: 1.4;
    white-space: nowrap;
}
.isis-cmdp__result.is-inert .isis-cmdp__result-hint { opacity: 0.55; }
.isis-cmdp__result-icon {
    width: 28px;
    height: 28px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background-color: var(--isis-surface-alt);
    color: var(--isis-text-muted);
    border-radius: var(--isis-radius);
    flex-shrink: 0;
}
/* Couleur d'icône par module — donne un repère visuel sur la source du résultat. */
.isis-cmdp__result.mod-gescom    .isis-cmdp__result-icon { background-color: var(--isis-mod-gescom-soft);    color: var(--isis-mod-gescom); }
.isis-cmdp__result.mod-gescompta .isis-cmdp__result-icon { background-color: var(--isis-mod-gescompta-soft); color: var(--isis-mod-gescompta); }
.isis-cmdp__result.mod-sirh      .isis-cmdp__result-icon { background-color: var(--isis-mod-sirh-soft);      color: var(--isis-mod-sirh); }
.isis-cmdp__result.mod-admin     .isis-cmdp__result-icon { background-color: var(--isis-mod-admin-soft);     color: var(--isis-mod-admin); }
.isis-cmdp__result.mod-ged       .isis-cmdp__result-icon { background-color: var(--isis-mod-ged-soft);       color: var(--isis-mod-ged); }
.isis-cmdp__result.mod-gesproj   .isis-cmdp__result-icon { background-color: var(--isis-mod-gesproj-soft);   color: var(--isis-mod-gesproj); }
.isis-cmdp__result.mod-gesmaff   .isis-cmdp__result-icon { background-color: var(--isis-mod-gesmaff-soft);   color: var(--isis-mod-gesmaff); }
.isis-cmdp__result.mod-gesst     .isis-cmdp__result-icon { background-color: var(--isis-mod-gesst-soft);     color: var(--isis-mod-gesst); }
.isis-cmdp__result.mod-gesmat    .isis-cmdp__result-icon { background-color: var(--isis-mod-gesmat-soft);    color: var(--isis-mod-gesmat); }
.isis-cmdp__result.mod-gespla    .isis-cmdp__result-icon { background-color: var(--isis-mod-gespla-soft);    color: var(--isis-mod-gespla); }
.isis-cmdp__result.mod-monespace .isis-cmdp__result-icon { background-color: var(--isis-mod-monespace-soft); color: var(--isis-mod-monespace); }

.isis-cmdp__result-body {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.isis-cmdp__result-label {
    font-size: 0.9rem;
    font-weight: 500;
    color: var(--isis-text);
    line-height: 1.2;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.isis-cmdp__result-path {
    font-size: 0.75rem;
    color: var(--isis-text-muted);
    line-height: 1.2;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.isis-cmdp__result-sep {
    margin: 0 0.35rem;
    opacity: 0.5;
}
.isis-cmdp__result-hint {
    color: var(--isis-text-soft);
    opacity: 0;
    transition: opacity 80ms;
    flex-shrink: 0;
    /* Réserve la place du chevron même quand la ligne n'en a pas : sans elle, les
       lignes inertes remontent leur texte de 14 px et la colonne droite ondule. */
    min-width: 14px;
}
.isis-cmdp__result.is-active .isis-cmdp__result-hint {
    opacity: 0.7;
    color: var(--isis-current-mod, var(--isis-accent));
}
/* Sortie vers la liste complète — « Voir les 1 966 devis », en fin de famille épinglée.
   Même gabarit qu'une ligne (mêmes gouttières, même hauteur de rangée) pour qu'elle se lise
   comme la suite de la liste, mais posée sur le fond du pied et séparée par un filet : c'est
   une ACTION, pas un vingt-et-unième devis. Le libellé garde la couleur du texte — la teinte
   du module tomberait sous 4,5:1 à cette taille en thème clair ; ce sont les deux pictos qui
   la portent, et ils ne portent aucune information à eux seuls. */
.isis-cmdp__sortie {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    flex-shrink: 0;
    width: 100%;
    padding: 0.5rem 0.75rem;
    border: none;
    border-top: 1px solid var(--isis-border-soft);
    background-color: var(--isis-surface-alt);
    color: var(--isis-text);
    font-size: 0.8rem;
    font-weight: 600;
    text-align: left;
    cursor: pointer;
    transition: background-color 80ms ease;
}
.isis-cmdp__sortie:hover {
    background-color: var(--isis-current-mod-soft, var(--isis-accent-soft));
}
.isis-cmdp__sortie:focus-visible {
    outline: 2px solid var(--isis-current-mod, var(--isis-accent));
    outline-offset: -2px;
}
.isis-cmdp__sortie-icon {
    width: 28px;
    height: 28px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    border-radius: var(--isis-radius-sm);
    background-color: var(--isis-current-mod-soft, var(--isis-accent-soft));
    color: var(--isis-current-mod, var(--isis-accent));
}
.isis-cmdp__sortie-label {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}
.isis-cmdp__sortie-hint {
    display: inline-flex;
    flex-shrink: 0;
    color: var(--isis-current-mod, var(--isis-accent));
}
/* Variante « Recherche avancée du module ». Elle cohabite avec la sortie famille quand un
   entonnoir est épinglé : deux boutons du même poids se disputeraient le regard, alors que
   l'un ouvre le résultat épinglé et l'autre un écran d'analyse. La graisse et la pastille
   tombent donc d'un cran — la structure, la cible de clic et le contraste du libellé, eux,
   ne bougent pas. */
.isis-cmdp__sortie--avancee {
    font-weight: 500;
    border-top-color: var(--isis-border-soft);
}
.isis-cmdp__sortie--avancee .isis-cmdp__sortie-icon {
    background-color: var(--isis-surface);
    color: var(--isis-text-muted);
    border: 1px solid var(--isis-border-soft);
}
.isis-cmdp__sortie--avancee .isis-cmdp__sortie-hint {
    color: var(--isis-text-muted);
}
/* ────────────────────────────────────────────────────────────────────────────
   Colonne d'aperçu (2026-09-06). Le panneau est à deux colonnes : la liste à
   gauche — 640 px — et l'aperçu de la sélection à droite — 300 px —, soit 940 px.
   Sous 900 px de fenêtre, l'aperçu passe SOUS la liste : il se replie, il ne
   disparaît pas (cf. la règle média plus bas, qui est le seul endroit à en
   décider). La doctrine antérieure — « un aperçu écrasé ne vaut pas mieux que pas
   d'aperçu » — a été renversée par l'audit d'accessibilité : le supprimer sous le
   seuil retirait à qui zoome, 200 % sur 1 512 px donnant 756 px CSS, un service que
   les autres gardent, avec des informations et une action sans autre chemin.
   ──────────────────────────────────────────────────────────────────────────── */
.isis-cmdp__body {
    display: flex;
    flex: 1;
    min-height: 0;
}
/* La colonne de gauche reprend la mise en colonne que .isis-cmdp portait seule :
   la liste défile, la ligne de sortie reste collée sous elle. */
.isis-cmdp__col {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-width: 0;
    min-height: 0;
}
.isis-cmdp__preview {
    /* border-box : sans lui la gouttière s'ajoute aux 300 px et la liste tombe à 612 —
       la géométrie voulue est 640 (liste) + 300 (aperçu). */
    box-sizing: border-box;
    flex: 0 0 300px;
    width: 300px;
    min-width: 0;
    /* Défile indépendamment de la liste : un aperçu à six lignes ne doit pas
       imposer sa hauteur au panneau, ni la subir. */
    overflow-y: auto;
    overscroll-behavior: contain;
    border-left: 1px solid var(--isis-border);
    background-color: var(--isis-surface-alt);
    padding: 0.75rem 0.85rem;
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
}
/* Sous le seuil, l'aperçu SE REPLIE sous la liste — il ne disparaît pas. Le supprimer
   retirait à qui zoome (200 % sur 1 512 px donnent 756 px CSS) le montant, le type, le
   déposant et l'action « Ouvrir l'objet rattaché », qui n'ont aucun autre chemin : une
   fonctionnalité perdue par le seul fait d'avoir grossi le texte.
   La hauteur est BORNÉE, sinon un aperçu à six lignes repousserait la liste hors du cadre. */
@media (max-width: 899px) {
    .isis-cmdp { --isis-cmdp-w: min(640px, calc(100vw - 2rem)); }
    .isis-cmdp__body { flex-direction: column; }
    .isis-cmdp__preview {
        flex: 0 0 auto;
        width: auto;
        max-height: 40vh;
        border-left: none;
        border-top: 1px solid var(--isis-border);
    }
}
.isis-cmdp__preview-thumb {
    display: block;
    width: 100%;
    max-height: 140px;
    object-fit: contain;
    background-color: var(--isis-surface);
    border: 1px solid var(--isis-border-soft);
    border-radius: var(--isis-radius);
}
/* Pastille de famille — même registre que les badges de statut : pilule, lavis,
   encre --isis-text (le blanc sur teinte pleine tombe sous 4,5:1 sur cinq accents). */
.isis-cmdp__preview-kind {
    align-self: flex-start;
    padding: 1px 0.45rem;
    border: 1px solid var(--isis-current-mod, var(--isis-accent));
    border-radius: var(--isis-radius-pill);
    background-color: var(--isis-current-mod-soft, var(--isis-accent-soft));
    color: var(--isis-text);
    font-size: 0.66rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
}
.isis-cmdp__preview-title {
    margin: 0;
    font-size: 0.92rem;
    font-weight: 600;
    line-height: 1.25;
    color: var(--isis-text);
    /* Un numéro de commande ou un nom de fichier peut être long : il se coupe,
       il ne pousse pas la colonne. */
    overflow-wrap: anywhere;
}
.isis-cmdp__preview-subtitle {
    margin: 0;
    font-size: 0.75rem;
    line-height: 1.3;
    color: var(--isis-text-muted);
    overflow-wrap: anywhere;
}
.isis-cmdp__preview-lines {
    display: grid;
    grid-template-columns: minmax(0, 92px) minmax(0, 1fr);
    gap: 0.2rem 0.6rem;
    margin: 0.25rem 0 0;
    padding-top: 0.4rem;
    border-top: 1px solid var(--isis-border-soft);
    font-size: 0.75rem;
    line-height: 1.35;
}
.isis-cmdp__preview-lines dt {
    color: var(--isis-text-muted);
    overflow-wrap: anywhere;
}
.isis-cmdp__preview-lines dd {
    margin: 0;
    color: var(--isis-text);
    font-variant-numeric: tabular-nums;
    overflow-wrap: anywhere;
}
/* Passage du corps d'un document. Filet PÉRIMÉTRIQUE 1px + fond propre (DESIGN.md §1,
   les liserés verticaux épais sont proscrits) : c'est une CITATION du document, pas une
   phrase du panneau. La couleur du module reste portée par le surlignage seul, qui
   disparaîtrait sur un fond déjà teinté de la même encre. */
.isis-cmdp__preview-extract {
    margin: 0.35rem 0 0;
    padding: 0.4rem 0.5rem;
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-sm);
    background-color: var(--isis-surface);
    color: var(--isis-text-muted);
    font-size: 0.73rem;
    line-height: 1.45;
    overflow-wrap: anywhere;
}
.isis-cmdp__preview-extract mark {
    background: var(--isis-current-mod-soft, var(--isis-accent-soft));
    color: var(--isis-text);
    font-weight: 600;
    padding: 0 1px;
    border-radius: var(--isis-radius-sm);
}
.isis-cmdp__preview-note {
    margin: 0;
    padding: 0.35rem 0;
    color: var(--isis-text-muted);
    font-size: 0.75rem;
    line-height: 1.35;
}
.isis-cmdp__preview-skel {
    display: flex;
    flex-direction: column;
    gap: 0.45rem;
    margin-top: 0.15rem;
}
.isis-cmdp__preview-skel-title { height: 14px; width: 62%; }
.isis-cmdp__preview-skel-line  { height: 10px; width: 100%; }
/* .isis-skeleton est peint en --isis-surface-alt, qui est EXACTEMENT le fond de cette
   colonne : les barres y étaient invisibles, seul le scintillement les trahissait. Elles
   reprennent la couleur du filet, qui tranche dans les deux thèmes (clair : #cdd6e0 sur
   #e1e7ef ; sombre : #2a3340 sur #1e2732). */
.isis-cmdp__preview-skel .isis-skeleton {
    background-color: var(--isis-border);
    background-image: linear-gradient(
        90deg,
        var(--isis-border) 0%,
        color-mix(in srgb, var(--isis-border) 45%, var(--isis-border-strong)) 50%,
        var(--isis-border) 100%);
}

.isis-cmdp__preview-actions {
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
    margin-top: 0.5rem;
    padding-top: 0.5rem;
    border-top: 1px solid var(--isis-border-soft);
}
/* La bordure était --isis-border : 1,18:1 contre le fond de la colonne, soit un contrôle
   actionnable délimité par rien (WCAG 1.4.11 exige 3:1). --isis-border-strong ne suffisait pas
   davantage (2,07 en clair, 1,60 en sombre, mesurés). --isis-text-soft tient contre LES DEUX
   voisins : 4,76 sur la surface du bouton et 3,82 sur le fond de colonne en clair ; 5,45 et
   4,80 en sombre. */
.isis-cmdp__action {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    width: 100%;
    padding: 0.35rem 0.5rem;
    border: 1px solid var(--isis-text-soft);
    border-radius: var(--isis-radius);
    background-color: var(--isis-surface);
    color: var(--isis-text);
    font-family: inherit;
    font-size: 0.76rem;
    text-align: left;
    cursor: pointer;
    transition: background-color 80ms ease, border-color 80ms ease;
}
.isis-cmdp__action.is-primary {
    border-color: var(--isis-current-mod, var(--isis-accent));
    font-weight: 600;
}
.isis-cmdp__action:hover {
    background-color: var(--isis-current-mod-soft, var(--isis-accent-soft));
    border-color: var(--isis-current-mod, var(--isis-accent));
}
.isis-cmdp__action:focus-visible {
    outline: 2px solid var(--isis-current-mod, var(--isis-accent));
    outline-offset: 2px;
}
.isis-cmdp__action-label {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.isis-cmdp__action-hint {
    display: inline-flex;
    flex-shrink: 0;
    color: var(--isis-current-mod, var(--isis-accent));
}

.isis-cmdp__footer {
    display: flex;
    align-items: center;
    gap: 1rem;
    padding: 0.6rem 0.9rem;
    border-top: 1px solid var(--isis-border-soft);
    background-color: var(--isis-surface-alt);
    font-size: 0.7rem;
    color: var(--isis-text-muted);
    flex-shrink: 0;
}
.isis-cmdp__shortcut {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
}
.isis-cmdp__shortcut kbd {
    font-family: var(--isis-font-mono, ui-monospace, monospace);
    font-size: 0.7rem;
    padding: 1px 4px;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-sm);
    color: var(--isis-text-muted);
    line-height: 1;
}
.isis-cmdp__count {
    margin-left: auto;
    font-variant-numeric: tabular-nums;
}

/* prefers-reduced-motion : désactive les animations d'entrée. */
@media (prefers-reduced-motion: reduce) {
    /* Le spinner N'y est PAS : figé, l'anneau devient un décor sans signification.
       Sa rotation est le seul signal qu'une requête est en vol. */
    .isis-cmdp-backdrop,
    .isis-cmdp {
        animation: none !important;
    }
}

/* ============================================================================
   Skeleton loading (refonte shell 2026-05-26, 3e chantier « SaaS premium »)
   Composants : IsisSkeleton (atomique) + IsisGridSkeleton (wrapper liste).
   Animation shimmer = gradient horizontal qui défile, 1.6s ease-in-out infini.
   ============================================================================ */
.isis-skeleton {
    display: block;
    background-color: var(--isis-surface-alt);
    background-image: linear-gradient(
        90deg,
        var(--isis-surface-alt) 0%,
        color-mix(in srgb, var(--isis-surface-alt) 50%, var(--isis-border-soft)) 50%,
        var(--isis-surface-alt) 100%);
    background-size: 200% 100%;
    background-repeat: no-repeat;
    border-radius: 4px;
    animation: isis-skeleton-shimmer 1.6s ease-in-out infinite;
}
.isis-skeleton--muted {
    /* Variante un cran plus discrète — utile pour les sub-labels secondaires. */
    opacity: 0.55;
}
@keyframes isis-skeleton-shimmer {
    0%   { background-position: 100% 0; }
    100% { background-position: -100% 0; }
}
@media (prefers-reduced-motion: reduce) {
    .isis-skeleton { animation: none; }
}

/* Wrapper grid skeleton — réplique la hauteur 52px d'une row standard de .isis-grid
   pour éviter le "saut de layout" quand les vraies données arrivent. */
.isis-grid-skeleton {
    display: flex;
    flex-direction: column;
    gap: 0;
}
.isis-grid-skeleton__row {
    display: grid;
    grid-template-columns: 18px minmax(160px, 1.4fr) 100px 110px 80px 32px;
    gap: 0.85rem;
    align-items: center;
    height: 52px;
    padding: 0 1rem;
    border-bottom: 1px solid var(--isis-border-soft);
}
.isis-grid-skeleton__row:last-child {
    border-bottom: none;
}
.isis-grid-skeleton__col-main {
    display: flex;
    flex-direction: column;
    gap: 6px;
    min-width: 0;
}

/* prefers-reduced-motion : skeleton statique (pas d'animation shimmer).
   On garde le fond gris pour signaler le placeholder, juste sans le défilement. */
@media (prefers-reduced-motion: reduce) {
    .isis-skeleton { animation: none !important; }
}

/* ─────────────────────────────────────────────────────────────────────────
   Pages marketing publiques (Landing /, MarketingLayout)
   Layout entièrement autonome — pas de dépendance à .isis-shell.
   ───────────────────────────────────────────────────────────────────────── */

.isis-marketing {
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    background: var(--isis-surface);
    color: var(--isis-text);
    font-family: var(--isis-font, "Geist", -apple-system, BlinkMacSystemFont, system-ui, "Segoe UI", sans-serif);
}

/* Header sticky : logo + nav + CTA */
.isis-marketing__header {
    position: sticky; top: 0; z-index: 50;
    display: flex; align-items: center; gap: 2rem;
    padding: 0.75rem 2rem;
    background: color-mix(in srgb, var(--isis-surface) 92%, transparent);
    backdrop-filter: saturate(180%) blur(8px);
    -webkit-backdrop-filter: saturate(180%) blur(8px);
    border-bottom: 1px solid var(--isis-border);
}
.isis-marketing__brand {
    display: flex; align-items: center; gap: 0.65rem;
    text-decoration: none; color: inherit;
}
.isis-marketing__brand-logo { width: 36px; height: 36px; }
.isis-marketing__brand-text { display: flex; flex-direction: column; line-height: 1.15; }
.isis-marketing__brand-name { font-weight: 700; font-size: 0.95rem; letter-spacing: -0.01em; }
.isis-marketing__brand-tag { font-size: 0.72rem; color: var(--isis-text-muted); letter-spacing: 0.02em; }

.isis-marketing__nav {
    display: flex; align-items: center; gap: 1.5rem;
    margin-left: auto;
}
.isis-marketing__nav a {
    text-decoration: none;
    color: var(--isis-text-muted);
    font-size: 0.9rem;
    font-weight: 500;
    padding: 0.4rem 0;
    transition: color 120ms ease;
}
.isis-marketing__nav a:hover,
.isis-marketing__nav a:focus-visible {
    color: var(--isis-accent);
    outline: none;
}

.isis-marketing__actions { display: flex; align-items: center; gap: 0.75rem; }
.isis-marketing__login {
    display: inline-flex; align-items: center; gap: 0.5rem;
    padding: 0.55rem 1rem;
    background: var(--isis-accent);
    color: var(--isis-on-accent);
    border-radius: var(--isis-radius, 8px);
    text-decoration: none;
    font-size: 0.88rem;
    font-weight: 600;
    box-shadow: var(--isis-elevation-1, 0 2px 6px rgba(0, 0, 0, 0.08));
    transition: background 120ms ease, transform 120ms ease;
}
.isis-marketing__login:hover { background: var(--isis-accent-strong); transform: translateY(-1px); }
.isis-marketing__login:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--isis-accent) 35%, transparent);
}
.isis-marketing__login .material-symbols-outlined { font-size: 18px; }

/* Conteneur principal */
.isis-marketing__main { flex: 1; }

/* Hero — fond dégradé subtil module-accent + warm */
.isis-marketing-hero {
    position: relative;
    padding: 5rem 2rem 4rem;
    background:
        radial-gradient(circle at 15% 20%, color-mix(in srgb, var(--isis-accent) 8%, transparent) 0%, transparent 55%),
        radial-gradient(circle at 85% 10%, color-mix(in srgb, var(--isis-accent) 6%, transparent) 0%, transparent 55%),
        var(--isis-surface);
    overflow: hidden;
}
.isis-marketing-hero::before {
    content: "";
    position: absolute; inset: 0 0 auto 0; height: 4px;
    background: linear-gradient(90deg,
        var(--isis-accent) 0%,
        var(--isis-accent) 50%,
        var(--isis-mod-sirh, #059669) 100%);
    opacity: 0.55;
}
.isis-marketing-hero__inner {
    max-width: 920px; margin: 0 auto; text-align: center;
}
.isis-marketing-hero__eyebrow {
    display: inline-block;
    padding: 0.3rem 0.8rem;
    background: var(--isis-accent-soft);
    color: var(--isis-accent-strong);
    border-radius: var(--isis-radius-pill);
    font-size: 0.78rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    margin-bottom: 1.5rem;
}
.isis-marketing-hero__title {
    font-size: clamp(2rem, 4.5vw, 3.25rem);
    font-weight: 800;
    line-height: 1.1;
    letter-spacing: -0.02em;
    margin: 0 0 1.25rem;
    color: var(--isis-text);
}
.isis-marketing-hero__title-prefix {
    display: block;
    font-size: clamp(0.95rem, 1.4vw, 1.15rem);
    font-weight: 500;
    letter-spacing: 0.02em;
    color: var(--isis-text-muted);
    margin-bottom: 0.6rem;
    text-transform: none;
}
.isis-marketing-hero__subtitle {
    font-size: clamp(1rem, 1.6vw, 1.18rem);
    line-height: 1.55;
    color: var(--isis-text-muted);
    margin: 0 auto 2.25rem;
    max-width: 720px;
}
.isis-marketing-hero__actions {
    display: inline-flex; gap: 0.75rem; flex-wrap: wrap; justify-content: center;
}

/* Boutons marketing */
.isis-marketing-btn {
    display: inline-flex; align-items: center; gap: 0.5rem;
    padding: 0.75rem 1.4rem;
    border-radius: var(--isis-radius, 8px);
    font-size: 0.95rem;
    font-weight: 600;
    text-decoration: none;
    border: 1px solid transparent;
    transition: background 120ms ease, transform 120ms ease, border-color 120ms ease;
}
.isis-marketing-btn .material-symbols-outlined { font-size: 18px; }
.isis-marketing-btn--primary {
    background: var(--isis-accent);
    color: var(--isis-on-accent);
    box-shadow: var(--isis-elevation-1, 0 4px 12px rgba(0, 0, 0, 0.1));
}
.isis-marketing-btn--primary:hover { background: var(--isis-accent-strong); transform: translateY(-1px); }
.isis-marketing-btn--ghost {
    background: transparent;
    color: var(--isis-text);
    border-color: var(--isis-border);
}
.isis-marketing-btn--ghost:hover {
    border-color: var(--isis-accent);
    color: var(--isis-accent);
}
.isis-marketing-btn:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--isis-accent) 35%, transparent);
}

/* Sections génériques */
.isis-marketing-section {
    padding: 4.5rem 2rem;
    max-width: 1200px; margin: 0 auto;
}
.isis-marketing-section--alt {
    background: var(--isis-surface-alt, var(--isis-surface-alt));
    max-width: none;
    padding-left: max(2rem, calc((100vw - 1200px) / 2));
    padding-right: max(2rem, calc((100vw - 1200px) / 2));
}
.isis-marketing-section__head {
    text-align: center;
    margin-bottom: 3rem;
}
.isis-marketing-section__head h2 {
    font-size: clamp(1.5rem, 3vw, 2.25rem);
    font-weight: 700;
    letter-spacing: -0.015em;
    margin: 0 0 0.65rem;
}
.isis-marketing-section__head p {
    font-size: 1rem;
    color: var(--isis-text-muted);
    margin: 0 auto;
    max-width: 640px;
}

/* Grille modules */
.isis-marketing-modules {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
    gap: 1.25rem;
}
.isis-marketing-module {
    position: relative;
    padding: 1.5rem;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius, 12px);
    transition: transform 160ms ease, border-color 160ms ease, box-shadow 160ms ease;
}
.isis-marketing-module:hover {
    transform: translateY(-3px);
    border-color: color-mix(in srgb, var(--isis-accent) 40%, var(--isis-border));
    box-shadow: var(--isis-elevation-hover, 0 12px 28px rgba(0, 0, 0, 0.08));
}
.isis-marketing-module__icon {
    display: inline-flex;
    align-items: center; justify-content: center;
    width: 44px; height: 44px;
    border-radius: 10px;
    background: var(--isis-accent-soft);
    color: var(--isis-accent);
    font-size: 24px !important;
    margin-bottom: 1rem;
}
.isis-marketing-module h3 {
    font-size: 1.1rem; font-weight: 700; letter-spacing: -0.01em;
    margin: 0 0 0.4rem;
}
.isis-marketing-module p {
    color: var(--isis-text-muted);
    font-size: 0.92rem;
    line-height: 1.5;
    margin: 0;
}

/* Couleurs module — icône tinted */
.isis-marketing-module.mod-gescom    .isis-marketing-module__icon { background: var(--isis-mod-gescom-soft);    color: var(--isis-mod-gescom); }
.isis-marketing-module.mod-gescompta .isis-marketing-module__icon { background: var(--isis-mod-gescompta-soft); color: var(--isis-mod-gescompta); }
.isis-marketing-module.mod-sirh      .isis-marketing-module__icon { background: var(--isis-mod-sirh-soft);      color: var(--isis-mod-sirh); }
.isis-marketing-module.mod-gesproj   .isis-marketing-module__icon { background: var(--isis-mod-gesproj-soft, #fef3c7); color: var(--isis-mod-gesproj, #d97706); }
.isis-marketing-module.mod-gesmaff   .isis-marketing-module__icon { background: var(--isis-mod-gesmaff-soft, #fef3c7); color: var(--isis-mod-gesmaff, #d97706); }
.isis-marketing-module.mod-gesst     .isis-marketing-module__icon { background: var(--isis-mod-gesst-soft, #fce7f3);  color: var(--isis-mod-gesst, #be185d); }
.isis-marketing-module.mod-gespla    .isis-marketing-module__icon { background: var(--isis-mod-gespla-soft, #ccfbf1); color: var(--isis-mod-gespla, #0f766e); }
.isis-marketing-module.mod-gesmat    .isis-marketing-module__icon { background: var(--isis-mod-gesmat-soft, #f5f5f4);  color: var(--isis-mod-gesmat, #44403c); }
.isis-marketing-module.mod-ged       .isis-marketing-module__icon { background: var(--isis-accent-soft); color: var(--isis-accent); }

/* Valeurs */
.isis-marketing-values {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
    gap: 1.25rem;
}
.isis-marketing-value {
    padding: 1.5rem;
    background: var(--isis-surface);
    border-radius: var(--isis-radius, 12px);
    border: 1px solid var(--isis-border);
}
.isis-marketing-value__icon {
    display: inline-flex;
    align-items: center; justify-content: center;
    width: 40px; height: 40px;
    border-radius: 10px;
    background: var(--isis-accent-soft);
    color: var(--isis-accent);
    font-size: 22px !important;
    margin-bottom: 0.85rem;
}
.isis-marketing-value h3 {
    font-size: 1.05rem; font-weight: 700;
    margin: 0 0 0.35rem;
}
.isis-marketing-value p {
    color: var(--isis-text-muted);
    font-size: 0.9rem;
    line-height: 1.5;
    margin: 0;
}

/* CTA finale */
.isis-marketing-cta {
    text-align: center;
    padding: 5rem 2rem;
}
.isis-marketing-cta__inner { max-width: 720px; margin: 0 auto; }
.isis-marketing-cta h2 {
    font-size: clamp(1.6rem, 3.2vw, 2.4rem);
    font-weight: 700;
    margin: 0 0 1rem;
    letter-spacing: -0.015em;
}
.isis-marketing-cta > .isis-marketing-cta__inner > p {
    font-size: 1.05rem;
    color: var(--isis-text-muted);
    line-height: 1.55;
    margin: 0 0 2rem;
}
.isis-marketing-cta__actions {
    display: inline-flex; gap: 0.75rem; flex-wrap: wrap; justify-content: center;
    margin-bottom: 1.5rem;
}
.isis-marketing-cta__small {
    font-size: 0.85rem;
    color: var(--isis-text-muted);
}
.isis-marketing-cta__small a {
    color: var(--isis-accent);
    text-decoration: none;
    font-weight: 500;
}
.isis-marketing-cta__small a:hover { text-decoration: underline; }

/* Footer */
.isis-marketing__footer {
    border-top: 1px solid var(--isis-border);
    padding: 1.5rem 2rem;
    background: var(--isis-surface-alt, var(--isis-surface-alt));
    font-size: 0.85rem;
    color: var(--isis-text-muted);
}
.isis-marketing__footer-inner {
    max-width: 1200px; margin: 0 auto;
    display: flex; align-items: center; justify-content: space-between;
    gap: 1rem; flex-wrap: wrap;
}
.isis-marketing__footer-links { display: inline-flex; gap: 0.6rem; align-items: center; }
.isis-marketing__footer-links a {
    color: var(--isis-text-muted);
    text-decoration: none;
}
.isis-marketing__footer-links a:hover { color: var(--isis-accent); }

/* Responsive : nav d'ancres masquée < 720px (CTA Espace client reste visible) */
@media (max-width: 720px) {
    .isis-marketing__nav { display: none; }
    .isis-marketing__header { gap: 1rem; padding: 0.65rem 1rem; }
    .isis-marketing__brand-tag { display: none; }
    .isis-marketing-hero { padding: 3rem 1.25rem 2.5rem; }
    .isis-marketing-section { padding: 3rem 1.25rem; }
    .isis-marketing-section--alt {
        padding-left: 1.25rem; padding-right: 1.25rem;
    }
    .isis-marketing-cta { padding: 3.5rem 1.25rem; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   Landing publique — refonte 2026 « un seul écran » (route /, EmptyLayout).
   Fond CLAIR sur le thème ISIS (near-white + voiles accent/warm subtils), un seul
   écran sans scroll : header transparent + hero (titre cinétique couleur-module +
   tableau de bord produit illustratif animé) + bande modules.
   Tout est namespacé .isis-ld-* / .isis-ld__*. Données maquette illustratives.
   ═══════════════════════════════════════════════════════════════════════════ */
.isis-ld {
    /* Palette IRP LOCALE à la vitrine publique (l'UI de l'app reste sobre/pétrole).
       La marque (rouge/bleu/violet) ne vit que sur la landing, pas dans l'interface. */
    --isis-accent: #0065ac;
    --isis-accent-strong: #00538c;
    /* L'ENCRE SUIT SA PALETTE (bloquant de revue, 2026-09-16). Cette palette est LOCALE et
       FIGEE : elle ne suit pas le theme, contrairement a `--isis-accent` global dont la variante
       sombre est une teinte eclaircie. La variante sombre du jeton d'encre s'appliquait pourtant
       ici par heritage, faisant tomber `.isis-ld__login` et `.isis-ld__btn--p` de 6,07:1 a
       3,07:1 (et leurs `:hover` de 8,03:1 a 2,32:1) pour un visiteur ayant deja choisi le theme
       sombre — la page /presentation etant [AllowAnonymous] et le theme pose avant le premier
       paint. Une palette figee doit figer son encre. */
    --isis-on-accent: #ffffff;
    --isis-ld-w: #e52126;    /* rouge IRP — 2e accent de la maquette */
    --isis-signal: #7237ff;  /* violet IRP — point du H1 + curseur */
    height: 100vh; height: 100dvh; display: flex; flex-direction: column; overflow: hidden;
    position: relative; color: var(--isis-text);
    background-color: var(--isis-bg);
    background-image:
        linear-gradient(color-mix(in srgb, var(--isis-accent) 4%, transparent) 1px, transparent 1px),
        linear-gradient(90deg, color-mix(in srgb, var(--isis-accent) 4%, transparent) 1px, transparent 1px);
    background-size: 22px 22px;
}

/* header transparent (sur fond clair) */
.isis-ld__hd { position: relative; z-index: 3; display: flex; align-items: center; gap: 2rem; padding: 1.1rem clamp(1.5rem, 5vw, 4rem) .6rem; }
.isis-ld__brand { display: flex; align-items: center; gap: .6rem; text-decoration: none; color: inherit; }
.isis-ld__logo { width: 34px; height: 34px; display: block; flex-shrink: 0; }
.isis-ld__brandtext { display: flex; flex-direction: column; line-height: 1.05; }
.isis-ld__bname { font-weight: 800; font-size: .95rem; letter-spacing: -.01em; color: var(--isis-text); }
.isis-ld__bname-suffix { font-weight: 600; color: var(--isis-text-muted); letter-spacing: .1em; }
.isis-ld__sig { font-family: var(--isis-cockpit-mono); font-size: .58rem; font-weight: 600; letter-spacing: .1em; color: var(--isis-accent); }
.isis-ld__by { font-size: .52rem; font-weight: 500; letter-spacing: .02em; color: var(--isis-text-subtle, var(--isis-text-muted)); opacity: .75; }
.isis-ld__nav { display: flex; gap: 1.4rem; margin-left: auto; }
.isis-ld__nav a { color: var(--isis-text-muted); text-decoration: none; font-size: .88rem; font-weight: 500; }
.isis-ld__nav a:hover { color: var(--isis-accent); }
.isis-ld__login { display: inline-flex; align-items: center; gap: .4rem; padding: .5rem .95rem; border-radius: 8px; background: var(--isis-accent); color: var(--isis-on-accent); text-decoration: none; font-size: .85rem; font-weight: 600; box-shadow: 0 4px 12px -5px color-mix(in srgb, var(--isis-accent) 55%, transparent); }
.isis-ld__login:hover { background: var(--isis-accent-strong); }
.isis-ld__login .material-symbols-outlined { font-size: 18px; }

/* hero */
.isis-ld__hero { flex: 1; min-height: 0; display: grid; grid-template-columns: 1.05fr .95fr; gap: clamp(2rem, 4vw, 3.5rem); align-items: center; width: 100%; max-width: 78rem; margin: 0 auto; padding: .5rem clamp(1.5rem, 5vw, 4rem); position: relative; z-index: 1; }
.isis-ld__copy { display: flex; flex-direction: column; align-items: flex-start; gap: 1.1rem; }
.isis-ld__kicker { margin: 0; font-size: clamp(.95rem, 1.5vw, 1.2rem); font-weight: 500; color: var(--isis-text-muted); }
.isis-ld__h1 { margin: 0; font-weight: 800; letter-spacing: -.04em; line-height: 1.0; font-size: clamp(2.6rem, 6vw, 4.6rem); color: var(--isis-text); }
/* Le titre peut recevoir un focus programmatique (a11y au chargement) ; il n'est
   pas navigable au clavier → on masque l'anneau de focus par défaut du navigateur. */
.isis-ld__h1:focus { outline: none; }
.isis-ld__dot { color: var(--isis-signal); }
.isis-ld__rot { color: var(--isis-accent); font-weight: 600; white-space: nowrap; border-bottom: 2px solid var(--isis-signal); padding-bottom: 1px; transition: opacity .34s ease; }
.isis-ld__rot.is-out { opacity: 0; }
.isis-ld__rot::after { content: ""; display: inline-block; width: .5ch; height: 1.05em; vertical-align: -.18em; margin-left: 1px; background: var(--isis-signal); animation: isisLdCaret 1s steps(1) infinite; }
@keyframes isisLdCaret { 50% { opacity: 0; } }
.isis-ld__lead { margin: 0; font-size: clamp(1rem, 1.5vw, 1.18rem); line-height: 1.55; color: var(--isis-text); max-width: 32rem; }
.isis-ld__cta { display: flex; gap: .7rem; flex-wrap: wrap; }
.isis-ld__btn { display: inline-flex; align-items: center; gap: .5rem; padding: .75rem 1.35rem; border-radius: 8px; font-size: .95rem; font-weight: 600; text-decoration: none; border: 1px solid transparent; transition: transform .12s ease, background .12s ease, border-color .12s ease, color .12s ease; }
.isis-ld__btn .material-symbols-outlined { font-size: 18px; }
.isis-ld__btn--p { background: var(--isis-accent); color: var(--isis-on-accent); box-shadow: 0 8px 22px -10px color-mix(in srgb, var(--isis-accent) 70%, transparent); }
.isis-ld__btn--p:hover { transform: translateY(-1px); background: var(--isis-accent-strong); }
.isis-ld__btn--g { background: var(--isis-surface); color: var(--isis-text); border-color: var(--isis-border); }
.isis-ld__btn--g:hover { border-color: var(--isis-accent); color: var(--isis-accent); transform: translateY(-1px); }
.isis-ld__trust { display: flex; flex-wrap: wrap; gap: .45rem; list-style: none; padding: 0; margin: .2rem 0 0; }
.isis-ld__trust li { display: inline-flex; align-items: center; gap: .4rem; font-size: .85rem; font-weight: 600; color: var(--isis-text); background: var(--isis-surface); border: 1px solid var(--isis-border); padding: .4rem .8rem; border-radius: 999px; }
.isis-ld__trust .material-symbols-outlined { font-size: 15px; color: var(--isis-accent); }

/* tableau de bord produit (illustratif, animé) */
.isis-ld__visual { display: flex; justify-content: center; align-items: center; min-height: 0; }
/* Visuel de marque du tenant à droite du hero (asset marketing_page_logo) — remplace
   l'illustration par défaut. Grand, contenu, flottement doux (respecte reduced-motion). */
.isis-ld__hero-logo { width: 100%; max-width: 560px; max-height: min(78vh, 560px); object-fit: contain; filter: drop-shadow(0 30px 60px rgba(31, 35, 40, 0.22)); animation: isis-ld-logo-float 7s ease-in-out infinite; will-change: transform; }
@keyframes isis-ld-logo-float { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-10px); } }
@media (prefers-reduced-motion: reduce) { .isis-ld__hero-logo { animation: none; } }
.isis-ld-dash { width: 100%; max-width: 520px; border-radius: 14px; background: var(--isis-surface); color: var(--isis-text); overflow: hidden; border: 1px solid var(--isis-border); box-shadow: 0 30px 60px -28px rgba(31, 35, 40, 0.22), 0 8px 22px -14px rgba(31, 35, 40, 0.12); transform: perspective(1500px) rotateY(-5deg) rotateX(2deg); }
.isis-ld-dash__bar { display: flex; align-items: center; gap: .5rem; padding: .5rem .7rem; border-bottom: 1px solid var(--isis-border); background: var(--isis-surface-alt); }
.isis-ld-dash__mk { width: 18px; height: 18px; display: block; }
.isis-ld-dash__tab { height: 7px; border-radius: 4px; background: #dfe4e9; width: 32px; }
.isis-ld-dash__tab:nth-child(2) { width: 54px; background: color-mix(in srgb, var(--isis-accent) 35%, #dfe4e9); }
.isis-ld-dash__tab:nth-child(4) { width: 46px; }
.isis-ld-dash__search { margin-left: auto; width: 96px; height: 16px; border-radius: 8px; background: var(--isis-surface); border: 1px solid var(--isis-border); }
.isis-ld-dash__body { display: grid; grid-template-columns: 38px 1fr; }
.isis-ld-dash__rail { display: flex; flex-direction: column; align-items: center; gap: .4rem; padding: .55rem 0; background: var(--isis-surface-alt); border-right: 1px solid var(--isis-border); }
.isis-ld-dash__rd { width: 18px; height: 18px; border-radius: 5px; background: color-mix(in srgb, var(--rc) 24%, #fff); }
.isis-ld-dash__rd.on { box-shadow: 0 0 0 2px color-mix(in srgb, var(--rc) 55%, transparent); }
.isis-ld-dash__main { padding: .7rem; display: flex; flex-direction: column; gap: .6rem; }
.isis-ld-dash__kpis { display: grid; grid-template-columns: repeat(3, 1fr); gap: .5rem; }
.isis-ld-dash__kpi { border: 1px solid var(--isis-border); border-radius: 8px; padding: .45rem .5rem; display: flex; flex-direction: column; gap: .32rem; }
.isis-ld-dash__klab { width: 62%; height: 5px; border-radius: 3px; background: #e3e6eb; }
.isis-ld-dash__kval { height: 11px; border-radius: 4px; transform-origin: left; animation: isisLdGrow 1s cubic-bezier(.16, 1, .3, 1) both; }
.isis-ld-dash__kpi:nth-child(1) .isis-ld-dash__kval { width: 74%; background: color-mix(in srgb, var(--isis-accent) 70%, #fff); animation-delay: .1s; }
.isis-ld-dash__kpi:nth-child(2) .isis-ld-dash__kval { width: 56%; background: color-mix(in srgb, var(--isis-success) 62%, #fff); animation-delay: .22s; }
.isis-ld-dash__kpi:nth-child(3) .isis-ld-dash__kval { width: 66%; background: color-mix(in srgb, var(--isis-ld-w) 70%, #fff); animation-delay: .34s; }
@keyframes isisLdGrow { from { transform: scaleX(0); } to { transform: scaleX(1); } }
.isis-ld-dash__charts { display: grid; grid-template-columns: 1.5fr 1fr; gap: .5rem; }
.isis-ld-dash__card { border: 1px solid var(--isis-border); border-radius: 8px; padding: .5rem; }
.isis-ld-dash__bars { display: flex; align-items: flex-end; gap: .34rem; height: 74px; }
.isis-ld-dash__bars span { flex: 1; border-radius: 3px 3px 0 0; background: linear-gradient(180deg, color-mix(in srgb, var(--isis-accent) 75%, #fff), color-mix(in srgb, var(--isis-accent) 30%, #fff)); transform: scaleY(0); transform-origin: bottom; animation: isisLdBar .7s cubic-bezier(.16, 1, .3, 1) both; }
.isis-ld-dash__bars span:nth-child(1) { height: 42%; animation-delay: .30s; }
.isis-ld-dash__bars span:nth-child(2) { height: 66%; animation-delay: .38s; }
.isis-ld-dash__bars span:nth-child(3) { height: 52%; animation-delay: .46s; }
.isis-ld-dash__bars span:nth-child(4) { height: 84%; background: linear-gradient(180deg, var(--isis-ld-w), color-mix(in srgb, var(--isis-ld-w) 40%, #fff)); animation-delay: .54s; }
.isis-ld-dash__bars span:nth-child(5) { height: 60%; animation-delay: .62s; }
.isis-ld-dash__bars span:nth-child(6) { height: 92%; animation-delay: .70s; }
@keyframes isisLdBar { to { transform: scaleY(1); } }
.isis-ld-dash__donut { display: flex; align-items: center; justify-content: center; height: 74px; }
.isis-ld-dash__donut svg { width: 74px; height: 74px; transform: rotate(-90deg); }
.isis-ld-dash__donut .ring { fill: none; stroke: #eaedf0; stroke-width: 5; }
.isis-ld-dash__donut .seg { fill: none; stroke: var(--isis-accent); stroke-width: 5; stroke-linecap: round; stroke-dasharray: 100; stroke-dashoffset: 100; animation: isisLdDraw 1.1s cubic-bezier(.16, 1, .3, 1) .5s forwards; }
.isis-ld-dash__donut .seg2 { fill: none; stroke: var(--isis-ld-w); stroke-width: 5; stroke-linecap: round; stroke-dasharray: 100; stroke-dashoffset: 100; animation: isisLdDraw2 1.1s cubic-bezier(.16, 1, .3, 1) .7s forwards; }
@keyframes isisLdDraw { to { stroke-dashoffset: 38; } }
@keyframes isisLdDraw2 { to { stroke-dashoffset: 80; } }
.isis-ld-dash__list { display: flex; flex-direction: column; gap: .34rem; }
.isis-ld-dash__row { display: grid; grid-template-columns: 8px 1fr 42px; gap: .45rem; align-items: center; }
.isis-ld-dash__rdot { width: 7px; height: 7px; border-radius: 50%; }
.isis-ld-dash__rc { height: 7px; border-radius: 4px; background: #e8ebee; }
.isis-ld-dash__ra { height: 7px; border-radius: 4px; background: color-mix(in srgb, var(--isis-accent) 22%, #e3e6eb); justify-self: end; width: 100%; }

/* bande modules */
.isis-ld__band { position: relative; z-index: 1; padding: .5rem clamp(1.5rem, 5vw, 4rem) 1.1rem; }
.isis-ld__band-top { display: flex; align-items: center; gap: .6rem; margin: 0 auto .55rem; max-width: 78rem; }
.isis-ld__band-top span,
.isis-ld__band-top h2 { margin: 0; line-height: inherit; font-family: inherit; font-size: .74rem; letter-spacing: .1em; text-transform: uppercase; color: var(--isis-text-subtle, #8b95a3); font-weight: 600; }
.isis-ld__band-top hr { flex: 1; border: 0; border-top: 1px solid var(--isis-border); }
.isis-ld__mods { max-width: 78rem; margin: 0 auto; display: flex; flex-wrap: wrap; gap: .5rem; justify-content: center; }
/* Pastille non cliquable : aucun effet de survol (pas de fausse invitation au clic). */
.isis-ld-mod { display: inline-flex; align-items: center; gap: .5rem; padding: .42rem .7rem; border-radius: 10px; background: var(--isis-surface); border: 1px solid var(--isis-border); text-decoration: none; }
.isis-ld-mod .material-symbols-outlined { font-size: 18px; color: var(--mc); }
.isis-ld-mod b { font-weight: 600; font-size: .82rem; color: var(--isis-text); }

@media (max-width: 900px) {
    .isis-ld { height: auto; min-height: 100vh; overflow: visible; }
    .isis-ld__hero { grid-template-columns: 1fr; gap: 1.6rem; text-align: center; padding-top: 1rem; padding-bottom: 1.4rem; }
    .isis-ld__copy { align-items: center; }
    .isis-ld__nav { display: none; }
    .isis-ld-dash { max-width: 440px; transform: none; }
    /* Anti-troncature du H1 sur petit écran (nom/accroche longs). */
    .isis-ld__h1 { font-size: clamp(1.85rem, 8vw, 2.9rem); overflow-wrap: anywhere; }
    .isis-ld__h1 br { display: none; }
}
/* Repli en hauteur, miroir du repli en largeur ci-dessus : une fenetre large mais
   courte (portable 13 pouces, fenetre non maximisee) garde height:100vh + overflow:
   hidden, et le pied legal (65px) rogne alors le bas du hero sans barre de defilement.
   Mesure : hero rogne de 23px a 1440x650 (scrollHeight 462 vs clientHeight 439).
   A 1440x900/1366x768/1280x720 le hero tient sans repli ; 700px couvre le cas mesure
   avec de la marge sans neutraliser le seul-ecran sur les tailles usuelles. */
@media (max-height: 700px) {
    .isis-ld { height: auto; min-height: 100vh; overflow: visible; }
}
@media (prefers-reduced-motion: reduce) {
    .isis-ld__rot { transition: none; border-bottom-color: var(--isis-accent); }
    .isis-ld__rot::after { animation: none; opacity: 0; }
    .isis-ld-dash__kval, .isis-ld-dash__bars span { animation: none; transform: none; }
    .isis-ld-dash__donut .seg { animation: none; stroke-dashoffset: 38; }
    .isis-ld-dash__donut .seg2 { animation: none; stroke-dashoffset: 80; }
}

/* Pied de page légal — points d'accroche vers /mentions-legales et /confidentialite
   (obligation légale). /cgu n'est volontairement pas lié (contenu vide). */
.isis-ld__legal {
    position: relative;
    z-index: 1;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 24px clamp(1.5rem, 5vw, 4rem);
    border-top: 1px solid var(--isis-border);
    font-size: var(--isis-fs-sm);
    color: var(--isis-text-muted);
}
.isis-ld__legal nav { display: flex; gap: 20px; }
.isis-ld__legal a { color: var(--isis-text-muted); }
.isis-ld__legal a:hover { color: var(--isis-accent); }

/* ═══════════════════════════════════════════════════════════════════════════
   Logigramme animé « De l'AO au paiement » (route /logigramme, EmptyLayout).
   Autoplay : fenêtres modules + cascades système + bonshommes acteurs.
   Tout est namespacé .isis-lg-* ; construit par js/isis-logigramme.js.
   ═══════════════════════════════════════════════════════════════════════════ */
.isis-lg {
    --isis-warm: #f4a06a; --isis-lg-dur: 5s;
    /* Encres posées sur le fond sombre fixe du logigramme (indépendant du thème). */
    --isis-on-dark: #ffffff;
    --isis-on-dark-line: rgba(255, 255, 255, .2);
    --isis-on-dark-fill: rgba(255, 255, 255, .06);
    --isis-on-dark-fill-hover: rgba(255, 255, 255, .12);
    --isis-on-dark-dot: rgba(255, 255, 255, .18);
    height: 100vh; height: 100dvh; display: flex; flex-direction: column;
    padding: 1.6rem clamp(1rem, 4vw, 3rem) 1.2rem; color: #eaf2f4; -webkit-font-smoothing: antialiased;
    background:
        radial-gradient(120% 90% at 28% -10%, #1b515f 0%, transparent 55%),
        radial-gradient(90% 80% at 100% 110%, #123a45 0%, transparent 55%),
        linear-gradient(160deg, #0c2a33 0%, #091e25 100%);
    overflow: hidden;
}
.isis-lg__head { display: flex; align-items: flex-end; justify-content: space-between; gap: 1rem; flex-wrap: wrap; }
.isis-lg__brand { display: flex; align-items: center; gap: .7rem; }
.isis-lg__titles h1 { margin: 0; font-size: clamp(1.05rem, 2vw, 1.45rem); font-weight: 600; letter-spacing: -.02em; }
.isis-lg__titles p { margin: .1rem 0 0; font-size: .82rem; color: rgba(234, 242, 244, .6); }
.isis-lg__phase { text-align: right; }
.isis-lg__phase-n { font-size: .75rem; letter-spacing: .14em; text-transform: uppercase; color: var(--isis-warm); font-weight: 600; }
.isis-lg__phase-t { font-size: clamp(1.1rem, 2.4vw, 1.7rem); font-weight: 600; letter-spacing: -.02em; }
.isis-lg__prog { display: flex; gap: 6px; margin-top: 1rem; }
.isis-lg-seg { flex: 1; height: 4px; border-radius: 3px; background: rgba(255, 255, 255, .10); overflow: hidden; position: relative; }
.isis-lg-seg.is-past { background: rgba(255, 255, 255, .32); }
.isis-lg-seg.is-current .isis-lg-seg__fill { position: absolute; inset: 0; background: var(--isis-warm); transform-origin: left; animation: isisLgSeg var(--isis-lg-dur) linear forwards; }
@keyframes isisLgSeg { from { transform: scaleX(0); } to { transform: scaleX(1); } }
.isis-lg__stage { flex: 1; position: relative; min-height: 0; }
.isis-lg-scene { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: clamp(1rem, 2.5vh, 2rem); opacity: 0; visibility: hidden; }
.isis-lg-scene.is-active { opacity: 1; visibility: visible; }
.isis-lg-scene__main { position: relative; display: flex; align-items: center; justify-content: center; gap: 2.2rem; }
.isis-lg-win { width: clamp(280px, 38vw, 440px); border-radius: 14px; background: #fbfdfe; color: #1f2328; border: 1px solid rgba(255, 255, 255, .6); overflow: hidden; box-shadow: 0 40px 80px -28px rgba(0, 0, 0, .6), 0 0 0 1px rgba(255, 255, 255, .35); }
.isis-lg-scene.is-active .isis-lg-win { animation: isisLgWin .6s cubic-bezier(.16, 1, .3, 1) both; }
@keyframes isisLgWin { from { opacity: 0; transform: translateY(14px) scale(.94); } to { opacity: 1; transform: none; } }
.isis-lg-win__bar { display: flex; align-items: center; gap: .55rem; padding: .6rem .8rem; border-bottom: 1px solid #e3e6eb; background: color-mix(in srgb, var(--wc) 10%, #f6f7fa); }
.isis-lg-win__dot { width: 9px; height: 9px; border-radius: 50%; background: var(--wc); box-shadow: 0 0 0 3px color-mix(in srgb, var(--wc) 20%, transparent); }
.isis-lg-win__title { font-weight: 600; font-size: .9rem; }
.isis-lg-win__badge { margin-left: auto; font-size: .7rem; font-weight: 600; padding: .2rem .55rem; border-radius: 999px; background: color-mix(in srgb, var(--wc) 14%, #fff); color: color-mix(in srgb, var(--wc) 75%, #1f2328); border: 1px solid color-mix(in srgb, var(--wc) 30%, #e3e6eb); }
.isis-lg-win__body { padding: .9rem; display: flex; flex-direction: column; gap: .55rem; }
.isis-lg-win__row { display: grid; grid-template-columns: 10px 1fr 54px; gap: .5rem; align-items: center; }
.isis-lg-win__rd { width: 8px; height: 8px; border-radius: 50%; background: var(--rc, var(--isis-border-strong)); }
.isis-lg-win__rc { height: 9px; border-radius: 5px; background: linear-gradient(90deg, #e3e6eb, #eef1f4); }
.isis-lg-win__ra { height: 9px; border-radius: 5px; background: color-mix(in srgb, var(--wc) 22%, #e3e6eb); }
.isis-lg-scene.is-active .isis-lg-win__row { animation: isisLgRise .5s ease both; }
.isis-lg-win__row:nth-child(1) { animation-delay: .22s; }
.isis-lg-scene.is-active .isis-lg-win__row:nth-child(2) { animation-delay: .34s; }
.isis-lg-scene.is-active .isis-lg-win__row:nth-child(3) { animation-delay: .46s; }
@keyframes isisLgRise { from { opacity: 0; transform: translateY(7px); } to { opacity: 1; transform: none; } }
.isis-lg-cascade { display: flex; flex-direction: column; align-items: center; gap: .4rem; color: var(--isis-warm); }
.isis-lg-cascade__disc { width: 64px; height: 64px; border-radius: 18px; display: flex; align-items: center; justify-content: center; background: color-mix(in srgb, var(--isis-warm) 16%, transparent); border: 1px solid color-mix(in srgb, var(--isis-warm) 45%, transparent); }
.isis-lg-cascade__disc .material-symbols-outlined { font-size: 34px; }
.isis-lg-scene.is-active .isis-lg-cascade__disc { animation: isisLgFire .6s cubic-bezier(.16, 1, .3, 1) both, isisLgPulse 1.8s ease-in-out .6s infinite; }
@keyframes isisLgFire { from { opacity: 0; transform: scale(.4); } to { opacity: 1; transform: scale(1); } }
@keyframes isisLgPulse { 0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--isis-warm) 30%, transparent); } 50% { box-shadow: 0 0 0 14px color-mix(in srgb, var(--isis-warm) 0%, transparent); } }
.isis-lg-cascade__lbl { font-size: .72rem; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; }
.isis-lg-chips { display: flex; align-items: center; gap: .4rem; flex-wrap: wrap; justify-content: center; }
.isis-lg-chip { font-size: .72rem; font-weight: 600; letter-spacing: .04em; padding: .28rem .6rem; border-radius: 999px; background: rgba(255, 255, 255, .07); border: 1px solid rgba(255, 255, 255, .16); color: rgba(234, 242, 244, .75); opacity: 0; }
.isis-lg-chip .material-symbols-outlined { font-size: 13px; vertical-align: -2px; margin-right: 1px; }
.isis-lg-chip.is-final { background: color-mix(in srgb, var(--isis-warm) 22%, transparent); border-color: color-mix(in srgb, var(--isis-warm) 55%, transparent); color: #fff; }
.isis-lg-chip-arrow { color: rgba(234, 242, 244, .4); font-size: .8rem; opacity: 0; }
.isis-lg-scene.is-active .isis-lg-chips > * { animation: isisLgChip .4s ease both; }
.isis-lg-scene.is-active .isis-lg-chips > *:nth-child(1) { animation-delay: .55s; }
.isis-lg-scene.is-active .isis-lg-chips > *:nth-child(2) { animation-delay: .68s; }
.isis-lg-scene.is-active .isis-lg-chips > *:nth-child(3) { animation-delay: .80s; }
.isis-lg-scene.is-active .isis-lg-chips > *:nth-child(4) { animation-delay: .92s; }
.isis-lg-scene.is-active .isis-lg-chips > *:nth-child(5) { animation-delay: 1.04s; }
.isis-lg-scene.is-active .isis-lg-chips > *:nth-child(6) { animation-delay: 1.16s; }
.isis-lg-scene.is-active .isis-lg-chips > *:nth-child(7) { animation-delay: 1.28s; }
@keyframes isisLgChip { to { opacity: 1; } }
.isis-lg-actors { position: relative; display: flex; align-items: flex-end; justify-content: center; gap: clamp(2rem, 7vw, 5rem); min-height: 96px; }
.isis-lg-actor { display: flex; flex-direction: column; align-items: center; gap: .45rem; width: 88px; }
.isis-lg-actor__svg { width: 42px; height: 50px; filter: drop-shadow(0 6px 14px color-mix(in srgb, var(--ac) 45%, transparent)); }
.isis-lg-actor__svg circle, .isis-lg-actor__svg path { fill: var(--ac); }
.isis-lg-actor__label { font-size: .74rem; font-weight: 500; color: rgba(234, 242, 244, .85); white-space: nowrap; }
.isis-lg-scene.is-active .isis-lg-actor { animation: isisLgActor .5s cubic-bezier(.16, 1, .3, 1) both; }
.isis-lg-scene.is-active .isis-lg-actor:nth-child(2) { animation-delay: .12s; }
.isis-lg-scene.is-active .isis-lg-actor:nth-child(3) { animation-delay: .24s; }
@keyframes isisLgActor { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: none; } }
.isis-lg-dossier { position: absolute; top: 6px; left: 12%; width: 30px; height: 30px; border-radius: 8px; display: flex; align-items: center; justify-content: center; background: color-mix(in srgb, var(--isis-warm) 90%, #fff); color: #5a2a12; box-shadow: 0 8px 18px -6px rgba(244, 160, 106, .7); opacity: 0; }
.isis-lg-dossier .material-symbols-outlined { font-size: 18px; }
.isis-lg-scene.is-active .isis-lg-dossier { animation: isisLgTravel 2.6s cubic-bezier(.65, 0, .35, 1) 1s both; }
@keyframes isisLgTravel { 0% { opacity: 0; left: 12%; } 10% { opacity: 1; } 90% { opacity: 1; } 100% { opacity: 1; left: calc(100% - 12% - 30px); } }
.isis-lg-caption { max-width: 42rem; text-align: center; font-size: clamp(.95rem, 1.8vw, 1.15rem); color: rgba(234, 242, 244, .9); line-height: 1.5; min-height: 2.6em; }
.isis-lg-caption b { color: #fff; font-weight: 600; }
.isis-lg-sod { display: inline-flex; align-items: center; gap: .4rem; font-size: .76rem; color: var(--isis-warm); background: color-mix(in srgb, var(--isis-warm) 12%, transparent); border: 1px solid color-mix(in srgb, var(--isis-warm) 35%, transparent); padding: .25rem .6rem; border-radius: 999px; }
.isis-lg-sod .material-symbols-outlined { font-size: 15px; }
.isis-lg__ctrl { display: flex; align-items: center; justify-content: center; gap: 1rem; margin-top: .6rem; }
.isis-lg__btn { width: 40px; height: 40px; border-radius: 50%; border: 1px solid var(--isis-on-dark-line); background: var(--isis-on-dark-fill); color: var(--isis-on-dark); display: flex; align-items: center; justify-content: center; cursor: pointer; }
.isis-lg__btn:hover { background: var(--isis-on-dark-fill-hover); }
.isis-lg__dots { display: flex; gap: 8px; }
.isis-lg-dot { width: 9px; height: 9px; border-radius: 50%; background: var(--isis-on-dark-dot); border: 0; cursor: pointer; padding: 0; }
.isis-lg__btn:focus-visible,
.isis-lg-dot:focus-visible { outline: 2px solid var(--isis-warm); outline-offset: 2px; }
.isis-lg-dot.is-on { background: var(--isis-warm); transform: scale(1.2); }
@media (max-width: 680px) {
    .isis-lg-scene__main { flex-direction: column; gap: 1.2rem; }
    .isis-lg-actors { gap: 1.6rem; }
    .isis-lg__head { align-items: flex-start; }
}
@media (prefers-reduced-motion: reduce) {
    .isis-lg-scene.is-active * { animation-duration: .01ms !important; }
    .isis-lg-seg.is-current .isis-lg-seg__fill { animation: none; transform: scaleX(1); }
}

/* ─── CGV admin page (/gescom/parametres/cgv) — chantier CGV-in-Gescom 2026-05-29 ─── */

/* Grille master : 4 colonnes (état / entreprise / CGV active / versions). */
.isis-grid--cgv .isis-grid__head,
.isis-grid--cgv .isis-grid__row {
    /* 1re colonne à 76px et non 32 : depuis que l'en-tête porte le tri par état (§ B4), son
       bouton « État » mesure 58px et débordait de 26px sur la colonne Entreprise — mesuré au
       navigateur, invisible au build. La pastille du corps est dans un .isis-grid__cell
       ordinaire : elle reste calée à gauche, sous le libellé. */
    grid-template-columns: 76px minmax(220px, 1.6fr) minmax(200px, 1.4fr) 130px;
    min-width: 764px;
}

/* Sidepanel : carte historique CGV par entreprise sélectionnée. */
.isis-cgv-versions {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}

.isis-cgv-version {
    border: 1px solid var(--isis-border-soft, #e5e7eb);
    border-radius: 6px;
    padding: 0.75rem 0.9rem;
    background: var(--isis-surface);
    transition: background 120ms ease;
}

.isis-cgv-version.is-active {
    border-color: var(--isis-success, #16a34a);
    background: color-mix(in srgb, var(--isis-success, #16a34a) 4%, var(--isis-surface));
}

.isis-cgv-version.is-draft {
    border-color: var(--isis-warning, #f59e0b);
    background: color-mix(in srgb, var(--isis-warning, #f59e0b) 4%, var(--isis-surface));
}

.isis-cgv-version.is-archived {
    opacity: 0.78;
}

.isis-cgv-version__head {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin-bottom: 0.4rem;
}

.isis-cgv-version__badge {
    display: inline-block;
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    padding: 0.12rem 0.5rem;
    border-radius: var(--isis-radius-pill);
    background: var(--isis-surface-alt);
    color: var(--isis-text-muted);
    flex-shrink: 0;
}

.isis-cgv-version.is-active .isis-cgv-version__badge {
    background: color-mix(in srgb, var(--isis-success, #16a34a) 18%, var(--isis-surface));
    color: var(--isis-success, #16a34a);
}

.isis-cgv-version.is-draft .isis-cgv-version__badge {
    background: color-mix(in srgb, var(--isis-warning, #f59e0b) 18%, var(--isis-surface));
    color: var(--isis-warning, #f59e0b);
}

.isis-cgv-version__label {
    font-size: 0.9rem;
    font-weight: 600;
    color: var(--isis-text);
}

.isis-cgv-version__meta {
    font-size: 0.72rem;
    color: var(--isis-text-muted);
    margin-bottom: 0.18rem;
}

.isis-cgv-version__notes {
    font-size: 0.78rem;
    color: var(--isis-text);
    font-style: italic;
    background: var(--isis-surface-alt);
    border-radius: 4px;
    padding: 0.35rem 0.5rem;
    margin: 0.4rem 0;
}

.isis-cgv-version__actions {
    display: flex;
    gap: 0.4rem;
    flex-wrap: wrap;
    margin-top: 0.5rem;
}

/* ============================================================================
   Gesmat — Gestion prédictive (plan prévisionnel + santé du parc)
   ============================================================================ */
.isis-kpi-card__unit {
    font-size: 0.6em;
    font-weight: 500;
    color: var(--isis-text-muted);
    margin-left: 0.15rem;
}

.isis-prev-grid {
    display: flex;
    flex-direction: column;
    gap: 0;
    flex: 1 1 auto;
    min-height: 0;
}
/* Zone principale scrollable : Plan de charge (+ Répartition) occupent le reste de la page. */
.isis-prev-main {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    gap: 1.25rem;
    padding-bottom: 0.5rem;
}
.isis-rich-section--fill {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
}
.isis-rich-section--fill > .isis-prev-plan,
.isis-rich-section--fill > .isis-prev-cal {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
}
/* Budget de maintenance : footer collé en bas, séparé de la zone principale. */
.isis-prev-footer {
    flex: 0 0 auto;
    border-top: 1px solid var(--isis-border);
    padding-top: 0.85rem;
    margin-top: 0.25rem;
    background: var(--isis-surface);
}

/* Plan de charge mensuel (barres proportionnelles) */
.isis-prev-plan {
    display: flex;
    flex-direction: column;
    gap: 2px;
    margin-top: 0.5rem;
}
.isis-prev-plan__row {
    display: grid;
    grid-template-columns: 110px 1fr 48px 110px;
    align-items: center;
    gap: 0.75rem;
    padding: 0.3rem 0.5rem;
    border-radius: 6px;
}
.isis-prev-plan__row:hover { background: var(--isis-surface-alt); }
.isis-prev-plan__row.is-overdue {
    background: color-mix(in srgb, var(--isis-danger) 7%, var(--isis-surface));
}
.isis-prev-plan__month {
    font-size: 0.82rem;
    font-weight: 500;
    color: var(--isis-text);
    white-space: nowrap;
}
.isis-prev-plan__row.is-overdue .isis-prev-plan__month {
    color: var(--isis-danger);
    font-weight: 600;
}
.isis-prev-plan__bar-wrap {
    display: flex;
    align-items: center;
    gap: 3px;
    min-height: 16px;
}
.isis-prev-plan__bar {
    height: 14px;
    border-radius: 3px;
    min-width: 0;
    transition: width 0.2s ease;
}
.isis-prev-plan__bar.is-ext { background: var(--isis-accent); }
.isis-prev-plan__bar.is-int { background: color-mix(in srgb, var(--isis-mod-gesmat) 70%, var(--isis-accent)); }
.isis-prev-plan__count {
    font-size: 0.82rem;
    font-weight: 600;
    text-align: right;
    font-variant-numeric: tabular-nums;
    color: var(--isis-text);
}
.isis-prev-plan__cost {
    font-size: 0.78rem;
    text-align: right;
    font-variant-numeric: tabular-nums;
    color: var(--isis-text-muted);
}

.isis-prev-legend {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 1rem;
    margin-top: 0.75rem;
    font-size: 0.78rem;
    color: var(--isis-text-muted);
}
.isis-prev-legend__item { display: inline-flex; align-items: center; gap: 0.35rem; }
.isis-prev-legend__swatch { width: 14px; height: 14px; border-radius: 3px; display: inline-block; }
.isis-prev-legend__swatch.is-ext { background: var(--isis-accent); }
.isis-prev-legend__swatch.is-int { background: color-mix(in srgb, var(--isis-mod-gesmat) 70%, var(--isis-accent)); }
.isis-prev-legend__note { font-style: italic; opacity: 0.85; }

.isis-grid--prev-renouv .isis-grid__head,
.isis-grid--prev-renouv .isis-grid__row,
.isis-grid--prev-renouv .isis-grid__foot {
    grid-template-columns: 1fr 200px 160px 60px;
}

/* Santé du parc (indice de risque) */
.isis-grid--sante .isis-grid__head,
.isis-grid--sante .isis-grid__row {
    grid-template-columns: 60px 1fr 90px 1.4fr 60px;
}
.isis-sante-score {
    display: inline-flex;
    align-items: baseline;
    gap: 2px;
    font-variant-numeric: tabular-nums;
    font-weight: 700;
    font-size: 1.05rem;
}
.isis-sante-score.is-high { color: var(--isis-danger); }
.isis-sante-score.is-mid { color: var(--isis-warning); }
.isis-sante-score.is-low { color: var(--isis-text-muted); }
.isis-sante-bar {
    position: relative;
    height: 8px;
    border-radius: 4px;
    background: var(--isis-surface-alt);
    overflow: hidden;
    min-width: 60px;
}
.isis-sante-bar__fill { position: absolute; left: 0; top: 0; bottom: 0; border-radius: 4px; }
.isis-sante-bar__fill.is-high { background: var(--isis-danger); }
.isis-sante-bar__fill.is-mid { background: var(--isis-warning); }
.isis-sante-bar__fill.is-low { background: var(--isis-success); }
.isis-sante-factors {
    display: flex;
    flex-wrap: wrap;
    gap: 0.3rem;
}
.isis-sante-factor {
    font-size: 0.72rem;
    padding: 0.1rem 0.4rem;
    border-radius: 10px;
    background: var(--isis-surface-alt);
    color: var(--isis-text-muted);
    white-space: nowrap;
}
.isis-sante-factor.is-alert {
    background: color-mix(in srgb, var(--isis-danger) 12%, var(--isis-surface));
    color: var(--isis-danger);
}

/* Gesmat prévisionnel — vue calendrier */
.isis-prev-cal { margin-top: 0.5rem; }
.isis-prev-cal__nav {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 1rem;
    margin-bottom: 0.6rem;
}
.isis-prev-cal__title {
    font-size: 0.95rem;
    font-weight: 600;
    color: var(--isis-text);
    min-width: 160px;
    text-align: center;
}
.isis-prev-cal__grid {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    gap: 4px;
}
.isis-prev-cal__dow {
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--isis-text-muted);
    text-align: center;
    padding: 0.2rem 0;
}
.isis-prev-cal__cell {
    min-height: 78px;
    border: 1px solid var(--isis-border);
    border-radius: 6px;
    padding: 0.25rem;
    background: var(--isis-surface);
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.isis-prev-cal__cell.is-empty { background: transparent; border: none; }
.isis-prev-cal__cell.is-today { border-color: var(--isis-accent); box-shadow: inset 0 0 0 1px var(--isis-accent); }
.isis-prev-cal__cell.has-events { background: var(--isis-surface-alt); }
.isis-prev-cal__daynum {
    font-size: 0.72rem;
    font-weight: 600;
    color: var(--isis-text-muted);
    text-align: right;
}
.isis-prev-cal__cell.is-today .isis-prev-cal__daynum { color: var(--isis-accent); }
.isis-prev-cal__evt {
    /* <button> depuis l'audit 2026-05-30 (accès clavier) — reset des défauts bouton */
    display: block;
    width: 100%;
    border: 0;
    margin: 0;
    text-align: left;
    font-family: inherit;
    font-size: 0.68rem;
    font-weight: 600;
    padding: 0.05rem 0.3rem;
    border-radius: 3px;
    color: #fff;
    cursor: pointer;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.isis-prev-cal__evt:focus-visible { outline: 2px solid var(--isis-accent); outline-offset: 1px; }
.isis-prev-cal__evt.is-ext { background: var(--isis-accent); }
.isis-prev-cal__evt.is-int { background: color-mix(in srgb, var(--isis-mod-gesmat) 70%, var(--isis-accent)); }
.isis-prev-cal__more {
    font-size: 0.66rem;
    color: var(--isis-text-muted);
    text-align: center;
}

/* Gesmat prévisionnel — cartes budget maintenance */
.isis-prev-budget {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
    gap: 0.75rem;
    margin-top: 0.5rem;
}
.isis-prev-budget__card {
    border: 1px solid var(--isis-border);
    border-radius: 8px;
    padding: 0.75rem 0.9rem;
    background: var(--isis-surface);
}
.isis-prev-budget__card.is-total { background: var(--isis-surface-alt); }
.isis-prev-budget__label {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    font-size: 0.78rem;
    font-weight: 600;
    color: var(--isis-text-muted);
}
.isis-prev-budget__value {
    font-size: 1.4rem;
    font-weight: 700;
    color: var(--isis-text);
    margin-top: 0.3rem;
    font-variant-numeric: tabular-nums;
}
.isis-prev-budget__sub {
    font-size: 0.74rem;
    color: var(--isis-text-muted);
    margin-top: 0.15rem;
}

/* Gesmat prévisionnel — répartition analytique par segment */
.isis-grid--prev-seg .isis-grid__head,
.isis-grid--prev-seg .isis-grid__row {
    grid-template-columns: 1.6fr 100px 90px 120px 120px 1.4fr 80px;
}
.isis-prev-seg__bar-cell {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    min-width: 0;
}
.isis-prev-seg__bar {
    height: 10px;
    border-radius: 3px;
    background: color-mix(in srgb, var(--isis-mod-gesmat) 70%, var(--isis-accent));
    flex: 0 0 auto;
    min-width: 2%;
    max-width: 60%;
}
.isis-prev-seg__bar-label {
    font-size: 0.78rem;
    font-variant-numeric: tabular-nums;
    color: var(--isis-text);
    white-space: nowrap;
}

/* Gesmat prévisionnel — liste « À traiter » + compteur de section */
.isis-rich-section__count {
    font-size: 0.78rem;
    font-weight: 600;
    color: var(--isis-text-muted);
    margin-left: 0.5rem;
}
.isis-grid--prev-treat .isis-grid__head,
.isis-grid--prev-treat .isis-grid__row {
    grid-template-columns: 1.8fr 160px 220px 140px 60px;
}

/* Gesmat — grille équipements (10 colonnes : statut / code / libellé / type / marque-modèle / entreprise / service / utilisateur / anomalie / actions) */
.isis-grid--equipement .isis-grid__head,
.isis-grid--equipement .isis-grid__row {
    grid-template-columns: 32px 115px minmax(150px, 1.2fr) 125px minmax(130px, 1fr) 130px 140px 140px minmax(150px, 0.9fr) 120px;
    min-width: 1324px;
}
/* 3 boutons de 28px + gaps : la cellule par défaut (block + overflow:hidden +
   padding 0.35rem) rognait le dernier bouton. */
.isis-grid--equipement .isis-grid__actions {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 0.25rem;
    overflow: visible;
}

/* Gespark — grille parc auto (7 colonnes : statut / immatriculation+code / marque-modèle+type /
   énergie / kilométrage / entreprise / actions). Identifiant primaire = immatriculation
   (le code VH-NNN devient sous-libellé). Libellé synthétisé retiré (redondant). */
/* Élargi le 2026-09-04 : chaque en-tête porte désormais un bouton de tri ET, pour quatre
   d'entre elles, un entonnoir. Aux anciennes largeurs, « Kilométrage » (110px) ne pouvait pas
   loger les deux et son entonnoir chevauchait la colonne « Entreprise ». Mesuré au navigateur,
   pas déduit. */
.isis-grid--gespark-vehicule .isis-grid__head,
.isis-grid--gespark-vehicule .isis-grid__row {
    grid-template-columns: 32px minmax(160px, 1fr) minmax(170px, 1.3fr) 130px 145px minmax(150px, 1fr) 96px;
    min-width: 960px;
}
.isis-grid--gespark-vehicule .isis-grid__col-km {
    text-align: right;
    font-variant-numeric: tabular-nums;
}

/* Gespark — réservations (6 colonnes : statut / véhicule / demandeur / créneau / motif / actions) */
.isis-grid--gespark-reservation .isis-grid__head,
.isis-grid--gespark-reservation .isis-grid__row {
    grid-template-columns: 110px minmax(160px, 1.3fr) minmax(130px, 1fr) 230px minmax(140px, 1fr) 120px;
    min-width: 1000px;
}
.isis-grid--gespark-reservation .isis-grid__col-period { font-variant-numeric: tabular-nums; white-space: nowrap; }

/* Gespark — référentiels du parc auto (page admin Types/Catégories/Modèles = 6 cols, Marques = 3 cols).
   Clone du layout gesmat-ref (les classes gespark-ref n'avaient aucune règle → grille mal présentée). */
.isis-grid--gespark-ref .isis-grid__head,
.isis-grid--gespark-ref .isis-grid__row {
    grid-template-columns: minmax(220px, 2fr) minmax(160px, 1fr) minmax(140px, 1fr) 90px 100px 90px;
    min-width: 880px;
}
.isis-grid--gespark-ref-3col .isis-grid__head,
.isis-grid--gespark-ref-3col .isis-grid__row {
    grid-template-columns: minmax(280px, 2fr) 160px 90px;
    min-width: 540px;
}

/* Gespark — chips du calendrier de réservations (tint clair + accent gauche par statut) */
.isis-resa-chip {
    display: inline-flex; align-items: center; max-width: 100%;
    padding: 1px 5px; border-radius: 4px;
    font-size: 0.62rem; font-weight: 700; line-height: 1.4;
    color: var(--isis-text); background: var(--isis-surface-alt);
    border: 1px solid var(--isis-text-muted);
    box-sizing: border-box;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.isis-resa-chip.is-pending { border-left-color: var(--isis-warning); background: color-mix(in srgb, var(--isis-warning) 14%, var(--isis-surface)); }
.isis-resa-chip.is-ok      { border-left-color: var(--isis-success); background: color-mix(in srgb, var(--isis-success) 14%, var(--isis-surface)); }
.isis-resa-chip.is-danger  { border-left-color: var(--isis-danger);  background: color-mix(in srgb, var(--isis-danger) 14%, var(--isis-surface)); }
.isis-resa-chip.is-info    { border-left-color: var(--isis-accent);   background: color-mix(in srgb, var(--isis-accent) 12%, var(--isis-surface)); }
.isis-resa-chip.is-draft   { border-left-color: var(--isis-text-muted); }
.isis-resa-chip.is-overflow { font-weight: 600; color: var(--isis-text-muted); border-left-color: transparent; background: transparent; }

/* Gespark — calendrier de réservations à BARRES CONTINUES (multi-jours = une seule barre) */
.isis-resa-cal {
    border: 1px solid var(--isis-border);
    border-radius: 10px;
    background: var(--isis-surface);
    /* Occupe toute la hauteur restante de la rich-page (flex parent height:100%). */
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-height: 0;
    overflow: auto;
}
.isis-resa-cal__head {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    background: var(--isis-surface-alt);
    border-bottom: 1px solid var(--isis-border);
    flex-shrink: 0;
    position: sticky;
    top: 0;
    z-index: 2;
}
.isis-resa-cal__head-cell {
    padding: 0.4rem 0.5rem;
    font-size: 0.72rem; font-weight: 700; text-transform: uppercase;
    letter-spacing: 0.03em; color: var(--isis-text-muted);
}
.isis-resa-week {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    position: relative;
    /* Les semaines se répartissent l'espace vertical (le calendrier remplit la page).
       min-height auto respecte le contenu (numéro + lanes) sans l'écraser. */
    flex: 1 1 0;
}
.isis-resa-week__day {
    border-right: 1px solid var(--isis-border-soft, var(--isis-border));
    border-bottom: 1px solid var(--isis-border-soft, var(--isis-border));
    padding: 2px 4px;
    min-width: 0;
}
.isis-resa-week__day:nth-child(7n) { border-right: none; }
.isis-resa-week__day.is-out { background: color-mix(in srgb, var(--isis-text-muted) 6%, var(--isis-surface)); }
.isis-resa-week__day.is-today { background: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 8%, var(--isis-surface)); }
.isis-resa-week__num { font-size: 0.72rem; font-weight: 600; color: var(--isis-text-muted); }
.isis-resa-week__day.is-today .isis-resa-week__num { color: var(--isis-current-mod, var(--isis-accent)); font-weight: 700; }

.isis-resa-bar {
    z-index: 1;
    align-self: center;
    margin: 0 2px;
    padding: 1px 6px;
    border-radius: 4px;
    font-size: 0.66rem; font-weight: 600; line-height: 1.5;
    color: var(--isis-text);
    background: var(--isis-surface-alt);
    border: 1px solid var(--isis-text-muted);
    box-sizing: border-box;
    overflow: hidden;
    cursor: default;
}
.isis-resa-bar__label { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.isis-resa-bar.is-pending { border-left-color: var(--isis-warning); background: color-mix(in srgb, var(--isis-warning) 16%, var(--isis-surface)); }
.isis-resa-bar.is-ok      { border-left-color: var(--isis-success); background: color-mix(in srgb, var(--isis-success) 16%, var(--isis-surface)); }
.isis-resa-bar.is-danger  { border-left-color: var(--isis-danger);  background: color-mix(in srgb, var(--isis-danger) 16%, var(--isis-surface)); }
.isis-resa-bar.is-info    { border-left-color: var(--isis-accent);   background: color-mix(in srgb, var(--isis-accent) 14%, var(--isis-surface)); }
.isis-resa-bar.is-draft   { border-left-color: var(--isis-text-muted); }
/* Continuation : bord plat du côté où la réservation déborde de la semaine */
.isis-resa-bar.is-cont-left  { border-top-left-radius: 0; border-bottom-left-radius: 0; border-left-width: 0; margin-left: 0; }
.isis-resa-bar.is-cont-right { border-top-right-radius: 0; border-bottom-right-radius: 0; margin-right: 0; }

/* Gespark dashboards V2 — utilitaires (audit ui-ux 2026-06-01 : sortir les styles inline). */
.isis-page-note { color: var(--isis-text-muted); font-size: 0.8rem; margin-top: 0.75rem; }
.isis-stats-grid-2col { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; }
.isis-calc-card { max-width: 640px; }
.isis-calc-amount { font-size: 1.2rem; font-weight: 600; font-family: var(--isis-font-mono, ui-monospace, monospace); font-variant-numeric: tabular-nums; }
.isis-calc-hint { color: var(--isis-text-muted); font-size: 0.85rem; }
@media (max-width: 720px) { .isis-stats-grid-2col { grid-template-columns: 1fr; } }

/* Gesproj — encours de production (7 cols : commande / avancement / vendu / produit / facturé / encours / reste). */
.isis-grid--gesproj-encours .isis-grid__head,
.isis-grid--gesproj-encours .isis-grid__row {
    grid-template-columns: minmax(200px, 1.6fr) 110px 130px 130px 130px 130px 140px;
    min-width: 1080px;
}

/* Gespark — historique conducteur (6 colonnes : conducteur / type / du / au / notes / actions) */
.isis-grid--gespark-affectation .isis-grid__head,
.isis-grid--gespark-affectation .isis-grid__row {
    grid-template-columns: minmax(180px, 1.4fr) 120px 110px 110px minmax(140px, 1fr) 60px;
    min-width: 860px;
}

/* Gespark — relevés kilométriques (5 colonnes : date / km / source / notes / actions) */
.isis-grid--gespark-releve .isis-grid__head,
.isis-grid--gespark-releve .isis-grid__row {
    grid-template-columns: 120px 140px 150px minmax(160px, 1fr) 60px;
    min-width: 740px;
}
.isis-grid--gespark-releve .isis-grid__col-km,
.isis-grid--gespark-reparation .isis-grid__col-km,
.isis-grid--gespark-carburant .isis-grid__col-km,
.isis-grid--gespark-sinistre .isis-grid__col-km,
.isis-grid--gespark-contravention .isis-grid__col-km {
    text-align: right;
    font-variant-numeric: tabular-nums;
}

/* Gespark — entretien (7 col : date / type / garage / km / coût / description / actions) */
.isis-grid--gespark-reparation .isis-grid__head,
.isis-grid--gespark-reparation .isis-grid__row {
    grid-template-columns: 110px 120px minmax(140px, 1fr) 90px 110px minmax(160px, 1.2fr) 60px;
    min-width: 920px;
}

/* Gespark — carburant (8 col : date / type / quantité / montant / km / station / payé par / actions) */
.isis-grid--gespark-carburant .isis-grid__head,
.isis-grid--gespark-carburant .isis-grid__row {
    grid-template-columns: 110px 120px 110px 110px 90px minmax(130px, 1fr) 120px 60px;
    min-width: 960px;
}

/* Gespark — sinistres (8 col : date / type / conducteur / lieu / resp / coût / statut / actions) */
.isis-grid--gespark-sinistre .isis-grid__head,
.isis-grid--gespark-sinistre .isis-grid__row {
    grid-template-columns: 110px 120px minmax(140px, 1fr) minmax(120px, 1fr) 80px 110px 110px 60px;
    min-width: 980px;
}

/* Gespark — contraventions (8 col : date / type / conducteur / montant / points / payé par / statut / actions) */
.isis-grid--gespark-contravention .isis-grid__head,
.isis-grid--gespark-contravention .isis-grid__row {
    grid-template-columns: 110px 140px minmax(140px, 1fr) 110px 80px 120px 110px 60px;
    min-width: 980px;
}

/* Gespark — échéancier flotte (7 col : statut / véhicule / échéance / organisme / expire / reste / actions) */
/* Reste à 7 colonnes. Une 8e (« Entreprise ») a été essayée le 2026-09-04 puis RETIRÉE :
   mesurée au navigateur, elle condamnait la grille au défilement horizontal permanent sous
   un panneau de détail qui prend déjà 400px, et le dernier en-tête passait sous le bouton de
   configuration des colonnes. L'axe entreprise reste filtrable (entonnoir de la barre) et
   lisible (ligne du sidepanel) — c'est la COLONNE qui ne tenait pas, pas l'information. */
.isis-grid--gespark-echeancier .isis-grid__head,
.isis-grid--gespark-echeancier .isis-grid__row {
    grid-template-columns: 32px minmax(150px, 1.2fr) 150px minmax(130px, 1fr) 110px 110px 60px;
    min-width: 920px;
}
.isis-grid--gespark-echeancier .isis-grid__col-km { text-align: right; font-variant-numeric: tabular-nums; }
.isis-grid__col-km.is-danger-text { color: var(--isis-danger); font-weight: 600; }
.is-warning-text { color: var(--isis-warning); font-weight: 600; }
.isis-grid__col-km.is-warning-text { color: var(--isis-warning); font-weight: 600; }

/* Gespark — responsables flotte (4 col : entreprise / responsable / depuis / actions) */
.isis-grid--gespark-responsable .isis-grid__head,
.isis-grid--gespark-responsable .isis-grid__row,
.isis-grid--gesmat-responsable .isis-grid__head,
.isis-grid--gesmat-responsable .isis-grid__row,
.isis-grid--gesinfo-responsable .isis-grid__head,
.isis-grid--gesinfo-responsable .isis-grid__row {
    grid-template-columns: minmax(180px, 1.4fr) minmax(180px, 1.4fr) 120px 100px;
    min-width: 680px;
}

/* MonEspace — Mes véhicules (cartes conducteur) */
.isis-mes-vehicules { display: grid; grid-template-columns: repeat(auto-fill, minmax(360px, 1fr)); gap: 1rem; }
.isis-mes-vehicule-card__head { display: flex; align-items: center; gap: 0.75rem; }
.isis-mes-vehicule-card__head > div:first-of-type { flex: 1 1 auto; min-width: 0; }
.isis-mes-vehicule-card__km { text-align: right; white-space: nowrap; }
.isis-mes-vehicule-card__echeances { display: flex; flex-wrap: wrap; gap: 0.4rem; margin: 0.75rem 0; }
.isis-mes-vehicule-card__actions { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 0.5rem; }

/* MonEspace — « Mon matériel » : cartes équipement + logiciels requis (EF-10, lecture seule). */
.isis-mes-materiel { display: grid; grid-template-columns: repeat(auto-fill, minmax(360px, 1fr)); gap: 1rem; }
.isis-mes-materiel-card__head { display: flex; align-items: center; gap: 0.75rem; }
.isis-mes-materiel-card__head > div:first-of-type { flex: 1 1 auto; min-width: 0; }
.isis-mes-materiel-card__requis { margin-top: 0.75rem; padding-top: 0.75rem; border-top: 1px solid var(--isis-border); }
.isis-mes-materiel-card__requis-title { font-size: 0.75rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.03em; color: var(--isis-text-muted); margin-bottom: 0.4rem; }
.isis-mes-materiel-card__requis-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.3rem; }
.isis-mes-materiel-card__requis-list li { display: flex; align-items: baseline; gap: 0.35rem; flex-wrap: wrap; font-size: 0.9rem; }
.isis-mes-materiel-card__requis-name { font-weight: 600; }
.isis-mes-materiel-card__requis-note { color: var(--isis-text-muted); font-size: 0.8rem; font-style: italic; }

/* Gespark — aperçu inline d'un document dans le sidepanel (calque /ged/documents) */
.isis-doc-preview {
    height: 250px; border: 1px solid var(--isis-border); border-radius: var(--isis-radius-sm, 6px);
    overflow: hidden; background: var(--isis-surface);
}
.isis-doc-preview > * { height: 100%; }
.isis-doc-preview__pending {
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 0.4rem; height: 100%; padding: 1rem; text-align: center; color: var(--isis-text-muted);
}
.isis-doc-preview__chips { display: flex; flex-wrap: wrap; gap: 0.35rem; margin-top: 0.5rem; }

/* Gespark — miniatures de justificatifs (sidepanel échéancier) */
.isis-justif-thumbs { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.isis-justif-thumb {
    display: flex; flex-direction: column; align-items: center; gap: 0.25rem;
    width: 96px; padding: 0.4rem; border: 1px solid var(--isis-border); border-radius: 8px;
    background: var(--isis-surface); cursor: pointer; text-align: center;
}
.isis-justif-thumb:hover { border-color: var(--isis-current-mod, var(--isis-accent)); box-shadow: var(--isis-elevation-1); }
.isis-justif-thumb:focus-visible { outline: 2px solid var(--isis-accent); outline-offset: 2px; }
.isis-justif-thumb img { width: 100%; height: 64px; object-fit: cover; border-radius: 4px; }
.isis-justif-thumb__icon { display: flex; align-items: center; justify-content: center; height: 64px; width: 100%; color: var(--isis-text-muted); }
.isis-justif-thumb__icon .rzi { font-size: 36px; }
.isis-justif-thumb__name { font-size: 0.7rem; color: var(--isis-text-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%; }

/* Gespark — contrats de financement (7 col : type / loueur / période / loyer / km / statut / actions) */
.isis-grid--gespark-contrat .isis-grid__head,
.isis-grid--gespark-contrat .isis-grid__row {
    grid-template-columns: 110px minmax(140px, 1fr) 180px 120px 110px 100px 80px;
    min-width: 900px;
}
.isis-grid--gespark-contrat .isis-grid__col-km { text-align: right; font-variant-numeric: tabular-nums; }

/* Gespark — TCO flotte (6 col : véhicule / total / km / coût/km / devise / actions) */
.isis-grid--gespark-tco .isis-grid__head,
.isis-grid--gespark-tco .isis-grid__row {
    grid-template-columns: minmax(180px, 1.4fr) 140px 110px 120px 90px 60px;
    min-width: 760px;
}
.isis-grid--gespark-tco .isis-grid__col-km { text-align: right; font-variant-numeric: tabular-nums; }

/* Gespark — renouvellement (7 col : véhicule / fin contrat / âge / km / coût/km / signal / actions) */
.isis-grid--gespark-renouv .isis-grid__head,
.isis-grid--gespark-renouv .isis-grid__row {
    grid-template-columns: minmax(170px, 1.3fr) 120px 90px 110px 110px minmax(140px, 1fr) 60px;
    min-width: 920px;
}
.isis-grid--gespark-renouv .isis-grid__col-km { text-align: right; font-variant-numeric: tabular-nums; }

/* Gespark — cartes carburant (6 col : fournisseur / numéro / véhicule / plafond / statut / actions) */
.isis-grid--gespark-carte .isis-grid__head,
.isis-grid--gespark-carte .isis-grid__row {
    grid-template-columns: minmax(150px, 1.2fr) 140px minmax(140px, 1fr) 120px 100px 90px;
    min-width: 800px;
}
.isis-grid--gespark-carte .isis-grid__col-km { text-align: right; font-variant-numeric: tabular-nums; }

/* Catalogue logiciels métier (gesmat S2) : status / nom / éditeur / catégorie / version / licence / support / actions */
.isis-grid--logiciel .isis-grid__head,
.isis-grid--logiciel .isis-grid__row {
    grid-template-columns: 32px minmax(180px, 1.4fr) minmax(140px, 1fr) minmax(130px, 0.9fr) 90px 120px 90px 110px;
    min-width: 1020px;
}

/* Licences logiciel (gesmat S3) : status / matricule / logiciel / type / sièges / échéance / coût / actions */
.isis-grid--licence .isis-grid__head,
.isis-grid--licence .isis-grid__row {
    grid-template-columns: 32px 140px minmax(160px, 1.3fr) 120px 90px 110px 120px 110px;
    min-width: 1060px;
}

/* Kits d'équipements (gesmat 2026-07-10) : status / code / libellé / entreprise / membres / statut / actions */
.isis-grid--kit .isis-grid__head,
.isis-grid--kit .isis-grid__row {
    grid-template-columns: 32px 150px minmax(200px, 1.6fr) minmax(150px, 1fr) 110px 120px 90px;
    min-width: 880px;
}
.isis-grid--kit .isis-grid__col-membres { text-align: right; font-variant-numeric: tabular-nums; }

/* Fiche kit — liste des membres (composition) */
.isis-kit-members { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
.isis-kit-members__row {
    display: grid;
    grid-template-columns: 16px minmax(0, 1fr) auto auto;
    align-items: center;
    gap: 0.75rem;
    padding: 0.55rem 0.25rem;
    border-bottom: 1px solid var(--isis-border-subtle);
}
.isis-kit-members__row:last-child { border-bottom: none; }
.isis-kit-members__main { display: flex; flex-direction: column; gap: 0.1rem; min-width: 0; }
.isis-kit-members__label { font-size: 0.78rem; color: var(--isis-text-muted); }
.isis-kit-members__state { justify-self: end; }
.isis-kit-members__add {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    flex-wrap: wrap;
    margin-top: 1rem;
    padding-top: 0.9rem;
    border-top: 1px solid var(--isis-border-subtle);
}

/* Parc logiciel par machine (gesinfo, ITAM niveau 3 polymorphe) :
   logiciel / poste / collaborateur / version / date / conformité / statut / actions */
.isis-grid--parc-logiciel .isis-grid__head,
.isis-grid--parc-logiciel .isis-grid__row {
    grid-template-columns: minmax(180px, 1.4fr) 130px minmax(170px, 1fr) 90px 110px 120px 110px 80px;
    min-width: 1050px;
}

/* Hub déploiement — onglet « Sièges de licence » */
.isis-grid--seat-tracking .isis-grid__head,
.isis-grid--seat-tracking .isis-grid__row {
    grid-template-columns: minmax(180px, 1.4fr) 130px 120px 90px 110px 90px minmax(160px, 1fr);
    min-width: 980px;
}

/* Parc auto — échéances réglementaires véhicule (onglet fiche véhicule) */
.isis-grid--gespark-echeance .isis-grid__head,
.isis-grid--gespark-echeance .isis-grid__row {
    /* 120px, pas 70 : 3 boutons de 28px + 2 écarts de 16px des cibles de clic 44×44
       (.isis-grid__action-btn, plus haut) = 116px, arrondis à 120 (revue de code
       du 2026-09-15 — le débordement existait depuis le passage à 16px). */
    grid-template-columns: minmax(150px, 1fr) 150px 110px minmax(140px, 1fr) 130px 110px 120px;
    min-width: 950px;
}
.isis-seat-bar {
    height: 6px;
    background: var(--isis-surface-alt);
    border-radius: 3px;
    overflow: hidden;
    margin-bottom: 2px;
}
.isis-seat-bar__fill {
    height: 100%;
    background: var(--isis-mod-gesinfo);
    border-radius: 3px;
    transition: width .2s ease;
}
.isis-seat-bar__fill.is-warning { background: var(--isis-warning); }
.isis-seat-bar__fill.is-danger  { background: var(--isis-danger); }

/* Hub déploiement — liste des déploiements dans le sidepanel licence */
.isis-side-deploy-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: .35rem; }
.isis-side-deploy-list__item {
    display: flex; align-items: center; justify-content: space-between; gap: .5rem;
    padding: .4rem .55rem; background: var(--isis-surface-alt); border-radius: 6px;
}
.isis-side-deploy-list__info { display: flex; flex-direction: column; gap: .1rem; min-width: 0; }
.isis-side-deploy-list__machine { font-weight: 600; font-size: .85rem; }

/* Dialog de déploiement — 2 colonnes : formulaire (gauche) + diagnostic machine (droite) */
.isis-deploy-dialog {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(380px, 430px);
    gap: 1.25rem;
    align-items: start;
}
.isis-deploy-dialog__form { min-width: 0; }
.isis-deploy-dialog__diag {
    background: var(--isis-surface-alt);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius);
    padding: 0.85rem;
    display: flex;
    flex-direction: column;
    gap: 0.9rem;
}
.isis-deploy-diag__empty {
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: .5rem; text-align: center; color: var(--isis-text-soft); padding: 1.5rem .5rem; min-height: 200px;
}
.isis-deploy-diag__head { border-bottom: 1px solid var(--isis-border); padding-bottom: .5rem; }
.isis-deploy-diag__title { font-weight: 600; font-size: .95rem; }
.isis-deploy-diag__sub { font-size: .78rem; color: var(--isis-text-muted); }
.isis-deploy-diag__block-title {
    font-size: .76rem; font-weight: 600; text-transform: uppercase; letter-spacing: .03em;
    color: var(--isis-text-muted); display: flex; align-items: center; gap: .3rem; margin-bottom: .35rem;
}
.isis-deploy-diag__block-title .rz-icon,
.isis-deploy-diag__block-title .notranslate { font-size: 15px; }
.isis-deploy-diag__sw { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: .3rem; }
.isis-deploy-diag__sw li { display: flex; justify-content: space-between; gap: .5rem; align-items: baseline; }
.isis-deploy-diag__sw-name { font-size: .85rem; }
@media (max-width: 760px) {
    .isis-deploy-dialog { grid-template-columns: 1fr; }
}

/* Logiciels installés sur une machine (onglet fiche équipement gesinfo) :
   statut / logiciel / licence / version / installé le / conformité / actions */
.isis-grid--machine-soft .isis-grid__head,
.isis-grid--machine-soft .isis-grid__row {
    grid-template-columns: 110px minmax(180px, 1.5fr) 120px 100px 110px 120px 70px;
    min-width: 850px;
}

/* Pastilles de légende de la carte des affaires (Gesmaff) — couleurs des couches
   Leaflet (AO / marché / demande). Centralisées ici (plus d'hex inline en .razor) ;
   synchronisées avec affaires-map.js. */
.isis-chip__dot--carte-ao       { background: #d97706; }
.isis-chip__dot--carte-marche   { background: #92400e; }
.isis-chip__dot--carte-demande  { background: #3b82f6; }

/* Bannière « coût total réel » (AffaireRealCostBlock) — gradient module tokenisé
   (gesst → gesproj), conforme DESIGN.md (gradient module via isis-theme.css). */
.isis-cost-total-banner {
    margin-top: 1rem;
    padding: 0.9rem;
    border-radius: 8px;
    border: 1px solid var(--isis-border);
    background: linear-gradient(90deg,
        color-mix(in srgb, var(--isis-mod-gesst) 6%, var(--isis-surface)),
        color-mix(in srgb, var(--isis-mod-gesproj) 6%, var(--isis-surface)));
}

/* Dashboard SAM/FinOps (gesmat S5) */
.isis-grid--sam-echeance .isis-grid__head,
.isis-grid--sam-echeance .isis-grid__row {
    grid-template-columns: 90px 140px minmax(160px, 1.4fr) 150px 110px 120px;
    min-width: 880px;
}
.isis-grid--sam-soususage .isis-grid__head,
.isis-grid--sam-soususage .isis-grid__row {
    grid-template-columns: 140px minmax(160px, 1.4fr) 100px 90px minmax(150px, 1fr) 120px;
    min-width: 880px;
}
.isis-grid--sam-budget .isis-grid__head,
.isis-grid--sam-budget .isis-grid__row {
    grid-template-columns: 100px 100px 110px minmax(180px, 1fr);
    min-width: 540px;
}
/* Entreprise allégée : texte discret (la criticité est portée par la colonne Anomalie). */
.isis-grid--equipement .isis-grid__col-light {
    color: var(--isis-text-muted);
    font-size: 0.82rem;
}
/* Colonne Anomalie : badges empilés/wrap. */
.isis-grid--equipement .isis-grid__col-anomalie {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem;
    align-content: center;
}

/* Gesmat — onglets du panneau latéral (Détail / Recherche avancée) */
.isis-side-tabs {
    display: flex;
    gap: 0;
    border-bottom: 1px solid var(--isis-border);
    margin-bottom: 0.75rem;
    position: sticky;
    top: 0;
    background: var(--isis-surface);
    z-index: 2;
}
.isis-side-tab {
    flex: 1;
    background: none;
    border: none;
    padding: 0.55rem 0.5rem;
    font-size: 0.82rem;
    font-weight: 600;
    color: var(--isis-text-muted);
    cursor: pointer;
    border-bottom: 2px solid transparent;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.3rem;
}
.isis-side-tab:hover { background: var(--isis-surface-alt); }
.isis-side-tab.is-active {
    color: var(--isis-current-mod, var(--isis-accent));
    border-bottom-color: var(--isis-current-mod, var(--isis-accent));
}
.isis-side-tab__badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 18px;
    height: 18px;
    padding: 0 5px;
    border-radius: 9px;
    background: var(--isis-current-mod, var(--isis-accent));
    color: #fff;
    font-size: 0.7rem;
    font-weight: 700;
}
.isis-side-search { display: flex; flex-direction: column; gap: 0.65rem; padding: 0 0.15rem; }
.isis-side-search .field { display: flex; flex-direction: column; gap: 0.2rem; }
.isis-side-search .label {
    font-size: 0.72rem; font-weight: 600; text-transform: uppercase;
    letter-spacing: 0.04em; color: var(--isis-text-muted);
}
.isis-side-search__actions { display: flex; gap: 0.5rem; margin-top: 0.35rem; }
.isis-side-search__hint { font-size: 0.74rem; color: var(--isis-text-muted); margin: 0.25rem 0 0; line-height: 1.4; }

/* Gesmat — barre d'amortissement (fiche équipement, carte TCO) */
.isis-amort-bar {
    height: 8px;
    border-radius: 4px;
    background: var(--isis-surface-alt);
    overflow: hidden;
    margin: 0.25rem 0 0.15rem;
}
.isis-amort-bar__fill {
    height: 100%;
    border-radius: 4px;
    background: color-mix(in srgb, var(--isis-mod-gesmat) 70%, var(--isis-accent));
}
.isis-amort-bar__fill.is-done { background: var(--isis-text-muted); }
/* Carte TCO : la somme mélange des devises (pas de conversion en V1). */
.isis-tco-mixte {
    display: flex;
    align-items: flex-start;
    gap: 0.3rem;
    margin-top: 0.2rem;
    font-size: 0.74rem;
    color: var(--isis-warning-text);
}
.isis-tco-mixte .rzi { font-size: 14px; }

/* ============================================================================
   Gescompta — Analyse comparative + dashboard (Priorité 3 audit ERP 2026-05-30)
   ============================================================================ */

.isis-quickactions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    padding: 0.5rem 0;
}

/* Grille top impayés : 8 colonnes */
.isis-grid--analyse-impayes .isis-grid__head,
.isis-grid--analyse-impayes .isis-grid__row {
    display: grid;
    grid-template-columns: 130px minmax(180px, 1.4fr) 100px 100px 70px 130px 100px 50px;
    gap: 0.5rem;
    align-items: center;
}

/* Grille top clients : 4 colonnes */
.isis-grid--analyse-top-clients .isis-grid__head,
.isis-grid--analyse-top-clients .isis-grid__row {
    display: grid;
    grid-template-columns: 60px minmax(200px, 1.6fr) 130px 160px;
    gap: 0.5rem;
    align-items: center;
}

/* Indicateurs textuels (positif/négatif/neutre/warning/danger) sur les KPI hero
   et cellules variation : couleurs sémantiques + poids accentué. */
.isis-kpi-card__value.is-positive,
.isis-grid__col-right.is-positive,
.isis-analyse-pivot__col-var.is-positive { color: var(--isis-success); font-weight: 600; }
.isis-kpi-card__value.is-negative,
.isis-grid__col-right.is-negative,
.isis-analyse-pivot__col-var.is-negative { color: var(--isis-danger); font-weight: 600; }
.isis-kpi-card__value.is-neutral,
.isis-grid__col-right.is-neutral,
.isis-analyse-pivot__col-var.is-neutral { color: var(--isis-text-muted); }
.isis-kpi-card__value.is-warning,
.isis-grid__col-right.is-warning,
.isis-analyse-pivot__col-var.is-warning { color: var(--isis-warning); font-weight: 600; }
.isis-kpi-card__value.is-danger,
.isis-grid__col-right.is-danger { color: var(--isis-danger); font-weight: 600; }
.isis-kpi-card__hint .is-positive { color: var(--isis-success); }
.isis-kpi-card__hint .is-negative { color: var(--isis-danger); }
.isis-kpi-card__hint .is-neutral  { color: var(--isis-text-muted); }
.isis-kpi-card__hint .is-warning  { color: var(--isis-warning); }

/* Tableau croisé dynamique pivot */
.isis-analyse-pivot-wrapper {
    width: 100%;
    overflow-x: auto;
    padding-bottom: 0.25rem;
}

.isis-analyse-pivot {
    width: 100%;
    border-collapse: separate;
    border-spacing: 0;
    font-variant-numeric: tabular-nums;
    font-size: 0.875rem;
}

.isis-analyse-pivot thead th {
    position: sticky;
    top: 0;
    background: var(--isis-surface-soft);
    text-transform: uppercase;
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.02em;
    color: var(--isis-text-muted);
    padding: 0.5rem 0.625rem;
    text-align: right;
    border-bottom: 1px solid var(--isis-border);
}

.isis-analyse-pivot thead th.isis-analyse-pivot__year-group {
    text-align: center;
    background: color-mix(in srgb, var(--isis-current-mod) 8%, var(--isis-surface-soft));
    color: var(--isis-text);
    font-size: 0.875rem;
    border-bottom: 1px solid var(--isis-current-mod);
}

.isis-analyse-pivot thead th.isis-analyse-pivot__sticky-col,
.isis-analyse-pivot tbody td.isis-analyse-pivot__sticky-col,
.isis-analyse-pivot tfoot td.isis-analyse-pivot__sticky-col {
    position: sticky;
    left: 0;
    background: var(--isis-surface);
    text-align: left;
    z-index: 2;
    border-right: 1px solid var(--isis-border);
}

.isis-analyse-pivot thead th.isis-analyse-pivot__sticky-col {
    background: var(--isis-surface-soft);
    z-index: 3;
}

.isis-analyse-pivot tbody td {
    padding: 0.4rem 0.625rem;
    text-align: right;
    border-bottom: 1px solid var(--isis-border-soft);
}

.isis-analyse-pivot tbody tr:hover td { background: var(--isis-surface-soft); }

.isis-analyse-pivot__col-month { color: var(--isis-text); font-weight: 500; }
.isis-analyse-pivot__col-cum   { color: var(--isis-text-muted); font-size: 0.8125rem; }
.isis-analyse-pivot__col-var   { font-size: 0.8125rem; font-weight: 600; }

/* Montants du pivot CA : mono tabulaire, aligné sur le pivot trésorerie. */
.isis-analyse-pivot__col-month,
.isis-analyse-pivot__col-cum {
    font-family: var(--isis-font-mono, ui-monospace, monospace);
    font-variant-numeric: tabular-nums;
}

.isis-analyse-pivot tfoot tr.isis-analyse-pivot__total td {
    padding: 0.55rem 0.625rem;
    background: var(--isis-surface-soft);
    font-weight: 600;
    border-top: 2px solid var(--isis-current-mod);
}

.isis-analyse-pivot tfoot tr.isis-analyse-pivot__total td.isis-analyse-pivot__sticky-col {
    background: var(--isis-surface-soft);
}

/* Charts SVG inline */
.isis-analyse-chart-wrap {
    margin-top: 1rem;
    padding: 0.5rem 0;
}

.isis-analyse-chart {
    width: 100%;
    height: auto;
    max-height: 280px;
    display: block;
}

.isis-analyse-chart__legend {
    display: flex;
    gap: 1rem;
    margin-top: 0.5rem;
    font-size: 0.8125rem;
    color: var(--isis-text-muted);
    justify-content: center;
}

.isis-analyse-chart__legend-item { display: inline-flex; align-items: center; gap: 0.375rem; }
.isis-analyse-chart__legend-dot {
    display: inline-block;
    width: 12px;
    height: 12px;
    border-radius: 3px;
}

/* Gesmat — grille des prêts (check-out / check-in) */
.isis-grid--pret .isis-grid__head,
.isis-grid--pret .isis-grid__row {
    grid-template-columns: minmax(180px, 1.4fr) 110px 130px 130px 130px 110px;
}

/* Gesmat — carte du parc (niveau 2 localisation) */
.isis-parc-carte {
    flex: 1 1 auto;
    min-height: 440px;
    border-radius: 10px;
    overflow: hidden;
    box-shadow: var(--isis-elevation-1);
    /* Leaflet empile ses couches jusqu'à 400 (panes) et 800 (contrôles). Sans contexte
       d'empilement propre, ces valeurs jouent dans le contexte RACINE et passent devant
       les panneaux de la page (filtres avancés z-index 50, entonnoirs 61) : on ouvrait
       un filtre et il disparaissait sous la carte.
       `position: relative` + `z-index: 0` enferment tout l'empilement de Leaflet dans ce
       bloc — il ne peut plus en sortir, quelle que soit la valeur interne. C'est préféré
       à relever les z-index des panneaux : eux sont GLOBAUX, et les remonter au-dessus de
       800 les ferait passer devant les dialogs sur toutes les autres pages. */
    position: relative;
    z-index: 0;
}
/* Lignes de détail d'un popup de carte (icône · libellé · valeur). */
.isis-nearby-popup__faits {
    display: flex;
    flex-direction: column;
    gap: 0.2rem;
    margin: 0.45rem 0 0.1rem;
    padding-top: 0.4rem;
    border-top: 1px solid var(--isis-border-soft);
}
.isis-nearby-popup__fait {
    display: grid;
    grid-template-columns: 16px 92px 1fr;
    align-items: baseline;
    gap: 0.35rem;
    font-size: 0.76rem;
    line-height: 1.35;
}
.isis-nearby-popup__fait .material-symbols-outlined {
    font-size: 14px;
    color: var(--isis-text-soft);
    align-self: center;
}
.isis-nearby-popup__fait-k { color: var(--isis-text-muted); }
.isis-nearby-popup__fait-v { color: var(--isis-text); font-weight: 500; overflow-wrap: anywhere; }

/* Légende des couleurs de la carte du parc : sans elle, un marqueur rouge ne dit rien. */
.isis-parc-carte__legende {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.15rem 0.9rem;
    padding: 0.4rem 0.1rem 0;
    font-size: 0.78rem;
    color: var(--isis-text-muted);
}
.isis-parc-carte__legende-item { display: inline-flex; align-items: center; gap: 0.35rem; }
.isis-parc-carte__legende-dot {
    width: 10px; height: 10px; border-radius: 50%;
    box-shadow: 0 0 0 2px var(--isis-surface);
}
.isis-parc-carte__legende-n { color: var(--isis-text-soft); font-variant-numeric: tabular-nums; }

.isis-parc-carte__toggle {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-size: 0.85rem;
    color: var(--isis-text);
}
.isis-parc-carte__unknown {
    margin-top: 0.5rem;
    font-size: 0.85rem;
}
.isis-parc-carte__unknown > summary {
    cursor: pointer;
    color: var(--isis-text-muted);
    padding: 0.35rem 0;
}
.isis-parc-carte__unknown-list {
    list-style: none;
    margin: 0.25rem 0 0;
    padding: 0;
    display: grid;
    gap: 0.3rem;
}
.isis-parc-carte__unknown-list li {
    display: flex;
    align-items: baseline;
    gap: 0.6rem;
}
.isis-parc-carte__unknown-hint {
    color: var(--isis-text-muted);
    font-size: 0.78rem;
}

/* ============================================================================
 * Comptes bancaires (Bloc 1 préalable lettrage — V1 2026-05-30)
 * Page /gescompta/banques + sidepanel détail.
 * Cf. memory project-isis-listpage-with-kpi-header + project-isis-grid-pattern.
 * ============================================================================ */

.isis-grid--bank-accounts .isis-grid__head,
.isis-grid--bank-accounts .isis-grid__row {
    display: grid;
    grid-template-columns:
        40px                            /* Icône compte par défaut */
        60px                            /* Status dot */
        minmax(180px, 1.3fr)            /* Libellé */
        minmax(220px, 1.4fr)            /* IBAN */
        minmax(180px, 1fr)              /* Banque */
        80px                            /* Devise */
        minmax(140px, 1fr)              /* Entreprise */
        80px;                           /* Actions */
    gap: 0.5rem;
    align-items: center;
    padding: 0.45rem 0.75rem;
}

.isis-grid--bank-accounts .isis-grid__col-iban {
    font-family: var(--isis-font-mono, 'JetBrains Mono', 'Geist Mono', 'SF Mono', monospace);
    font-size: 0.8125rem;
    font-variant-numeric: tabular-nums;
    letter-spacing: 0.02em;
    color: var(--isis-text);
}

/* Icône étoile marquant le compte par défaut. Couleur ambre warning (jamais hex
 * inline — variables --isis-* uniquement, cf. DESIGN.md §10). */
.isis-bank-account-default-icon {
    color: var(--isis-warning);
}

/* ── Feedback live IBAN/BIC dans le form dialog (success / error) ─────────── */
.isis-form-linear__hint--success {
    color: var(--isis-success);
}
.isis-form-linear__hint--error {
    color: var(--isis-danger);
    border-color: var(--isis-danger);
    background: var(--isis-danger-soft);
}
.isis-form-linear__hint--warn {
    color: var(--isis-warning);
    border-color: var(--isis-warning);
    background: var(--isis-warning-soft);
}

/* ── Sidepanel détail compte : bloc IBAN en grand (chiffre clé) ───────────── */
.isis-side-iban {
    margin-top: 0.75rem;
    padding: 0.75rem 0.85rem;
    background: color-mix(in srgb, var(--isis-mod-gescompta) 7%, var(--isis-surface));
    border-radius: 6px;
    border: 1px solid color-mix(in srgb, var(--isis-mod-gescompta) 32%, transparent);
}
.isis-side-iban__label {
    font-size: 0.7rem;
    color: var(--isis-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    margin-bottom: 0.25rem;
}
.isis-side-iban__value {
    font-family: var(--isis-font-mono, 'JetBrains Mono', 'Geist Mono', 'SF Mono', monospace);
    font-size: 0.95rem;
    font-weight: 600;
    color: var(--isis-text);
    letter-spacing: 0.03em;
    word-break: break-all;
}
.isis-side-iban__bic {
    margin-top: 0.35rem;
    font-size: 0.8rem;
}
.isis-side-iban__bic-label {
    color: var(--isis-text-muted);
}
.isis-side-iban__bic-value {
    font-family: var(--isis-font-mono, 'JetBrains Mono', 'Geist Mono', 'SF Mono', monospace);
    font-weight: 500;
    color: var(--isis-text);
    margin-left: 0.35rem;
}

/* Gesmat — onglet Localisation (niveau 3) */
.isis-loc-map {
    border-radius: 10px;
    overflow: hidden;
    box-shadow: var(--isis-elevation-1);
    margin-bottom: 0.85rem;
}
.isis-loc-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    gap: 0.85rem;
    margin-bottom: 0.85rem;
}
.isis-loc-card {
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: 10px;
    padding: 0.85rem 1rem;
}
.isis-loc-card__title {
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--isis-text-muted);
    margin-bottom: 0.35rem;
}
.isis-loc-card__main { font-weight: 600; color: var(--isis-text); }
.isis-loc-card__sub { color: var(--isis-text-muted); font-size: 0.85rem; margin-top: 0.15rem; }
.isis-loc-card__coords {
    font-family: var(--isis-font-mono, monospace);
    font-size: 0.8rem;
    color: var(--isis-text-muted);
    margin-top: 0.2rem;
}
.isis-loc-section { margin-top: 0.85rem; }
.isis-loc-section__title {
    font-size: 0.78rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--isis-text-muted);
    margin-bottom: 0.4rem;
}
.isis-loc-section__empty { color: var(--isis-text-muted); font-size: 0.85rem; }
.isis-loc-tracker-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.4rem; }
.isis-loc-tracker-list li {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    padding: 0.4rem 0.6rem;
    border: 1px solid var(--isis-border);
    border-radius: 8px;
    background: var(--isis-surface);
}
.isis-loc-tracker-list li.is-active { border-color: color-mix(in srgb, var(--isis-current-mod) 35%, var(--isis-border)); }
.isis-loc-tracker__dev { font-family: var(--isis-font-mono, monospace); font-size: 0.85rem; color: var(--isis-text); }
.isis-loc-tracker__meta { color: var(--isis-text-muted); font-size: 0.82rem; flex: 1; }
.isis-loc-hist { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.25rem; }
.isis-loc-hist li {
    display: flex;
    align-items: baseline;
    gap: 0.8rem;
    font-size: 0.82rem;
    padding: 0.25rem 0;
    border-bottom: 1px solid var(--isis-border-soft, var(--isis-border));
}
.isis-loc-hist__date { color: var(--isis-text); min-width: 130px; }
.isis-loc-hist__src { color: var(--isis-text-muted); min-width: 64px; }
.isis-loc-hist__coords { font-family: var(--isis-font-mono, monospace); color: var(--isis-text-muted); flex: 1; }
.isis-loc-hist__batt { color: var(--isis-text-muted); }
.isis-tracker-key {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    background: var(--isis-surface-alt);
    border: 1px solid var(--isis-border);
    border-radius: 8px;
    padding: 0.5rem 0.6rem;
    margin-top: 0.3rem;
}
.isis-tracker-key code {
    flex: 1;
    font-family: var(--isis-font-mono, monospace);
    font-size: 0.82rem;
    word-break: break-all;
    color: var(--isis-text);
}

/* Utilitaires audit ui-ux 2026-05-30 (extraction styles inline) */
.isis-tab-toolbar--flush { border: 0; padding-bottom: 0.75rem; }
.isis-tab-toolbar__hint { color: var(--isis-text-muted); font-size: 0.85rem; }
.isis-form-linear__section-title--spaced { margin-top: 0.75rem; }
.isis-parc-carte__toggle-hint { color: var(--isis-text-muted); font-size: 0.8rem; }

/* ── Chantier #2 — Budget d'heures (CommandeBudgetSection) ─────────────────── */
/* (le modificateur .is-ok de la coverage-bar est défini dans le bloc canonique) */
.isis-budget { display: flex; flex-direction: column; gap: 1rem; }
.isis-budget__section-label { font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.04em; color: var(--isis-text-muted); margin: 0.25rem 0 0; }
.isis-budget__loading { display: flex; align-items: center; gap: 0.6rem; padding: 0.75rem 0; }
.isis-budget__head { display: flex; align-items: center; justify-content: space-between; gap: 1rem; flex-wrap: wrap; }
.isis-budget__head-left { display: flex; align-items: center; gap: 0.4rem; flex-wrap: wrap; }
.isis-budget__head-right { display: flex; align-items: center; gap: 0.5rem; }
.isis-budget__summary { display: flex; flex-direction: column; gap: 0.4rem; }
.isis-budget__summary-row { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; font-size: 0.9rem; }
.isis-budget__taches { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.85rem; }
.isis-budget__tache { display: flex; flex-direction: column; gap: 0.3rem; }
.isis-budget__tache-head { display: flex; align-items: baseline; justify-content: space-between; gap: 0.75rem; }
.isis-budget__tache-name { font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.isis-budget__tache-val { font-variant-numeric: tabular-nums; white-space: nowrap; }
/* Couleurs de valeur scopées aux montants (jamais aux badges du header). */
.isis-budget__tache-val.is-warning, .isis-budget__summary-row strong.is-warning { color: var(--isis-warning); }
.isis-budget__tache-val.is-danger,  .isis-budget__summary-row strong.is-danger  { color: var(--isis-danger); }
.isis-budget-divider { height: 1px; background: var(--isis-border); margin: 1.25rem 0 0.5rem; }
.isis-budget-heading { display: flex; align-items: center; gap: 0.4rem; font-size: 1rem; font-weight: 600; margin: 0 0 0.5rem; }

/* ── Chantier #3 — Avenants de commande (CommandeAvenantSection) ───────────── */
.isis-avenants { display: flex; flex-direction: column; gap: 1rem; }
.isis-avenants__toolbar { display: flex; align-items: center; justify-content: space-between; gap: 1rem; }
.isis-avenants__count { font-size: 0.9rem; font-weight: 500; }
.isis-avenants__list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
.isis-avenants__row { display: flex; align-items: center; gap: 1rem; flex-wrap: wrap; padding: 0.65rem 0; border-bottom: 1px solid var(--isis-border); }
.isis-avenants__row:last-child { border-bottom: none; }
.isis-avenants__main { display: flex; align-items: center; gap: 0.5rem; min-width: 0; }
.isis-avenants__numero { font-family: var(--isis-font-mono, monospace); font-weight: 600; }
.isis-avenants__titre { font-weight: 600; }
/* EF-82 — rappel du document parent à côté d'un numéro devenu autonome. */
.isis-avenants__parent { color: var(--isis-text-muted); font-size: 0.8rem; }
.isis-avenants__type { color: var(--isis-text-muted); font-size: 0.85rem; }
.isis-avenants__meta { display: flex; align-items: baseline; gap: 0.75rem; flex-wrap: wrap; font-size: 0.85rem; font-variant-numeric: tabular-nums; }
.isis-avenants__meta .is-danger { color: var(--isis-danger); }
.isis-avenants__motif { color: var(--isis-text-muted); font-style: italic; max-width: 22ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.isis-avenants__actions { display: flex; align-items: center; gap: 0.35rem; margin-left: auto; }
/* ── Lot 4 — dialogue de preuve d'acceptation client (AvenantProofDialog) ──── */
.isis-avenant-proof__impact { margin-top: 0; align-items: center; }
.isis-avenant-proof__docs { list-style: none; margin: 0.35rem 0 0; padding: 0; max-height: 190px; overflow-y: auto; border: 1px solid var(--isis-border); border-radius: var(--isis-radius-sm); }
/* Le bouton d'aperçu vit HORS du <label> (sinon il cocherait la radio) : la ligne porte donc
   elle-même le flex, et le label prend la place restante. */
.isis-avenant-proof__doc { display: flex; align-items: center; gap: 0.25rem; padding-right: 0.35rem; }
.isis-avenant-proof__doc + .isis-avenant-proof__doc { border-top: 1px solid var(--isis-border); }
.isis-avenant-proof__doc.is-selected { background: var(--isis-mod-gesproj-soft, var(--isis-surface-2)); }
.isis-avenant-proof__doc-label { flex: 1; min-width: 0; display: flex; align-items: center; gap: 0.5rem; padding: 0.4rem 0.6rem; cursor: pointer; font-size: 0.85rem; }
.isis-avenant-proof__doc-label:hover { background: var(--isis-surface-alt); }
.isis-avenant-proof__doc-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.isis-avenant-proof__doc-meta { flex: 0 0 auto; color: var(--isis-text-muted); font-size: 0.78rem; font-variant-numeric: tabular-nums; }
.isis-avenant-proof__file { display: flex; align-items: center; gap: 0.35rem; }

/* Message d'erreur de validation dans les dialogs form-linear. */
.isis-form-linear__error { color: var(--isis-danger); font-size: 0.82rem; padding: 0.4rem 0.6rem; background: var(--isis-danger-soft); border-radius: 6px; border: 1px solid var(--isis-danger); }

/* ────────────────────────────────────────────────────────────────────────── *
 *  Bloc 2 — Rapprochement bancaire (V1 2026-05-30, Priorité 2 audit ERP)     *
 *  Convention naming « rapprochement » (cf. memory                           *
 *  feedback_vocabulaire_rapprochement_vs_lettrage) — JAMAIS « lettrage ».    *
 * ────────────────────────────────────────────────────────────────────────── */

/* Grille liste relevés (page /gescompta/rapprochement).
   8 cols : Status / Période / Compte / Format / Fichier / Lignes / Importé / Actions. */
.isis-grid--bank-statements .isis-grid__head,
.isis-grid--bank-statements .isis-grid__row {
    display: grid;
    grid-template-columns: 40px minmax(160px, 1fr) minmax(180px, 1.3fr) 120px minmax(160px, 1fr) 140px 130px 80px;
    gap: 0.5rem;
    align-items: center;
    min-width: 1080px;
}

/* Grille liste lignes (page détail).
   8 cols : Status / Date / Sens / Montant / Libellé / Donneur / État / Actions. */
.isis-grid--bank-lines .isis-grid__head,
.isis-grid--bank-lines .isis-grid__row {
    display: grid;
    grid-template-columns: 40px 90px 60px 110px minmax(220px, 1.6fr) minmax(140px, 1fr) minmax(140px, 1fr) 80px;
    gap: 0.5rem;
    align-items: center;
    min-width: 1020px;
}

/* Colonne montant : alignement droit + monospace tabular pour lecture verticale rapide. */
.isis-grid--bank-lines .isis-grid__col-amount {
    font-family: var(--isis-font-mono, ui-monospace, monospace);
    font-variant-numeric: tabular-nums;
    text-align: right;
}

/* Icônes direction CRÉDIT/DÉBIT (sens du flux financier).
   CRÉDIT = paiement reçu (vert success), DÉBIT = paiement émis (rouge danger). */
.isis-bank-direction-icon--credit {
    color: var(--isis-success);
    font-size: 18px;
}
.isis-bank-direction-icon--debit {
    color: var(--isis-danger);
    font-size: 18px;
}

/* Badge de score match suggéré.
   3 niveaux : ≥ 90 success vert / 60-89 warning orange / < 60 muted gris. */
.isis-rapprochement-score-badge {
    display: inline-block;
    padding: 0.18rem 0.5rem;
    border-radius: var(--isis-radius-pill);
    font-size: 0.78rem;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    letter-spacing: 0.2px;
}
.isis-rapprochement-score-badge--high {
    background: color-mix(in srgb, var(--isis-success) 18%, white);
    color: var(--isis-success);
}
.isis-rapprochement-score-badge--medium {
    background: color-mix(in srgb, var(--isis-warning) 18%, white);
    color: var(--isis-warning);
}
.isis-rapprochement-score-badge--low {
    background: color-mix(in srgb, var(--isis-text-muted) 18%, white);
    color: var(--isis-text-muted);
}

/* Carte « candidat suggéré » dans le sidepanel de la page détail.
   La bordure left reprend la couleur du score (gradation rouge → vert). */
.isis-rapprochement-candidate-card {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    padding: 0.75rem 0.85rem;
    border: 1px solid var(--isis-border);
    border-radius: 6px;
    background: var(--isis-surface);
    transition: border-color 120ms, background 120ms;
}
.isis-rapprochement-candidate-card--high { border-left-color: var(--isis-success); }
.isis-rapprochement-candidate-card--medium { border-left-color: var(--isis-warning); }
.isis-rapprochement-candidate-card--low { border-left-color: var(--isis-text-muted); }
.isis-rapprochement-candidate-card--reconciled {
    border-color: var(--isis-success);
    background: color-mix(in srgb, var(--isis-success) 6%, var(--isis-surface));
}
.isis-rapprochement-candidate-card--rejected {
    border-color: var(--isis-text-muted);
    background: var(--isis-surface-alt);
}
.isis-rapprochement-candidate-card--info {
    border-color: var(--isis-accent);
    background: color-mix(in srgb, var(--isis-accent) 6%, var(--isis-surface));
}
.isis-rapprochement-candidate-card--empty {
    flex-direction: row;
    align-items: center;
    gap: 0.5rem;
    color: var(--isis-text-muted);
    font-size: 0.875rem;
    background: var(--isis-surface-alt);
}

.isis-rapprochement-candidate-card__title {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    font-weight: 600;
    font-size: 0.9rem;
}
.isis-rapprochement-candidate-card__row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
}
.isis-rapprochement-candidate-card__numero {
    font-family: var(--isis-font-mono, ui-monospace, monospace);
    font-weight: 600;
    font-size: 0.95rem;
}
.isis-rapprochement-candidate-card__body {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    font-size: 0.875rem;
    color: var(--isis-text);
}
.isis-rapprochement-candidate-card__reason {
    font-size: 0.82rem;
    color: var(--isis-text-muted);
    font-style: italic;
}
.isis-rapprochement-candidate-card__criteria {
    display: flex;
    flex-wrap: wrap;
    gap: 0.3rem;
    margin-top: 0.15rem;
}

/* Titre de section « Suggérer un rapprochement » dans le sidepanel. */
.isis-rapprochement-candidates {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}
.isis-rapprochement-candidates__title {
    display: flex;
    align-items: center;
    font-size: 0.875rem;
    font-weight: 600;
    color: var(--isis-text);
    margin-top: 0.4rem;
}
.isis-rapprochement-candidates__title .isis-rich-toolbar__btn { margin-left: auto; }

/* KPIs lignes inline dans le sidepanel de la page liste (compteurs par état). */
.isis-rapprochement-stats {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 0.5rem;
    margin: 0.5rem 0 0.75rem;
}
.isis-rapprochement-stat {
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 0.5rem 0.4rem;
    background: var(--isis-surface-alt);
    border-radius: 6px;
}
.isis-rapprochement-stat__value {
    font-size: 1.25rem;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    color: var(--isis-text);
    line-height: 1.1;
}
.isis-rapprochement-stat__value.is-success { color: var(--isis-success); }
.isis-rapprochement-stat__value.is-warning { color: var(--isis-warning); }
.isis-rapprochement-stat__value.is-muted { color: var(--isis-text-muted); }
.isis-rapprochement-stat__label {
    font-size: 0.72rem;
    color: var(--isis-text-muted);
    text-align: center;
    margin-top: 0.15rem;
}

/* ============================================================================
   V1.1 Bloc 2 Session 2 — Rapprochement N-pour-1
   ============================================================================ */

/* Grille candidats factures dans le dialog groupé */
.isis-grid--candidate-factures .isis-grid__head,
.isis-grid--candidate-factures .isis-grid__row {
    display: grid;
    grid-template-columns: 40px 130px minmax(180px, 1.4fr) 100px 110px 110px 120px;
    gap: 0.5rem;
    align-items: center;
}
.isis-grid--candidate-factures .isis-grid__col-amount {
    text-align: right;
    font-variant-numeric: tabular-nums;
    font-family: var(--isis-font-mono, ui-monospace, monospace);
    font-size: 0.85rem;
}
.isis-grid--candidate-factures .isis-grid__col-numero {
    font-family: var(--isis-font-mono, ui-monospace, monospace);
    font-size: 0.85rem;
}
.isis-grid--candidate-factures .isis-grid__row.is-disabled {
    opacity: 0.5;
    pointer-events: none;
}
.isis-grid--candidate-factures .isis-grid__row input[type="checkbox"] {
    cursor: pointer;
    width: 16px;
    height: 16px;
}
.isis-grid--candidate-factures .isis-grid__row.is-disabled input[type="checkbox"] {
    cursor: not-allowed;
}

/* Dialog plein-écran N-pour-1 */
.isis-rapprochement-groupe {
    display: flex;
    flex-direction: column;
    height: 100%;
    min-height: 0;
}
.isis-rapprochement-groupe__body {
    flex: 1 1 auto;
    display: grid;
    grid-template-columns: 40% 60%;
    gap: 1rem;
    min-height: 0;
    overflow: hidden;
}
@media (max-width: 960px) {
    .isis-rapprochement-groupe__body {
        grid-template-columns: 1fr;
        grid-template-rows: auto 1fr;
    }
}
.isis-rapprochement-groupe__line {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    padding: 0.5rem;
    overflow-y: auto;
    min-height: 0;
}
.isis-rapprochement-groupe__factures {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    min-height: 0;
    overflow: hidden;
}
.isis-rapprochement-groupe__factures .isis-grid {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
}

/* Card récap montant à imputer (zone gauche) */
.isis-rapprochement-groupe-summary {
    background: color-mix(in srgb, var(--isis-mod-gescompta) 6%, var(--isis-surface));
    border: 1px solid color-mix(in srgb, var(--isis-mod-gescompta) 32%, transparent);
    padding: 0.85rem 1rem;
    border-radius: 6px;
}
.isis-rapprochement-groupe-summary--remaining {
    border-color: color-mix(in srgb, var(--isis-text-muted) 32%, transparent);
    background: color-mix(in srgb, var(--isis-text-muted) 6%, var(--isis-surface));
}
.isis-rapprochement-groupe-summary--remaining.ok {
    border-color: color-mix(in srgb, var(--isis-success) 40%, transparent);
    background: color-mix(in srgb, var(--isis-success) 8%, var(--isis-surface));
}
.isis-rapprochement-groupe-summary--remaining.warning {
    border-color: color-mix(in srgb, var(--isis-warning) 40%, transparent);
    background: color-mix(in srgb, var(--isis-warning) 8%, var(--isis-surface));
}
.isis-rapprochement-groupe-summary--remaining.danger {
    border-color: var(--isis-danger);
    background: color-mix(in srgb, var(--isis-danger) 8%, white);
}
.isis-rapprochement-groupe-summary__label {
    font-size: 0.78rem;
    color: var(--isis-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.02em;
    margin-bottom: 0.25rem;
}
.isis-rapprochement-groupe-summary__amount-large {
    font-size: 1.55rem;
    font-weight: 700;
    color: var(--isis-text);
    font-variant-numeric: tabular-nums;
    font-family: var(--isis-font-mono, ui-monospace, monospace);
    letter-spacing: -0.01em;
}
.isis-rapprochement-groupe-summary__remaining--ok {
    color: var(--isis-success);
}
.isis-rapprochement-groupe-summary__remaining--warning {
    color: var(--isis-warning);
}
.isis-rapprochement-groupe-summary__remaining--danger {
    color: var(--isis-danger);
}
.isis-rapprochement-groupe-summary__sub {
    font-size: 0.82rem;
    color: var(--isis-text-muted);
    margin-top: 0.2rem;
}

.isis-rapprochement-groupe__facts {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 0.65rem;
}
.isis-rapprochement-groupe__facts li {
    display: flex;
    gap: 0.5rem;
    align-items: flex-start;
}
.isis-rapprochement-groupe__fact-label {
    font-size: 0.75rem;
    color: var(--isis-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.02em;
}
.isis-rapprochement-groupe__fact-value {
    font-size: 0.9rem;
    word-break: break-word;
}
.isis-rapprochement-groupe__fact-value--small {
    font-size: 0.82rem;
}
.isis-rapprochement-groupe__counter {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.4rem 0.7rem;
    background: var(--isis-surface-alt, var(--isis-surface-alt));
    border-radius: 4px;
    font-size: 0.85rem;
}

.isis-filter-bar--inline {
    padding: 0;
    background: transparent;
    border: 0;
}
.isis-filter-bar--inline .isis-filter-bar__chips {
    align-items: center;
    flex-wrap: wrap;
}

/* Footer dialog (sticky bottom) */
.isis-rapprochement-groupe__footer {
    flex: 0 0 auto;
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 0.75rem 1rem;
    border-top: 1px solid var(--isis-border, #e5e7eb);
    background: var(--isis-surface);
    gap: 1rem;
    flex-wrap: wrap;
}
.isis-rapprochement-groupe__footer-status {
    font-size: 0.88rem;
    color: var(--isis-text);
}
.isis-rapprochement-groupe__footer-actions {
    display: flex;
    gap: 0.5rem;
}

/* Badge multi-factures (grille + sidepanel) */
.isis-rapprochement-multifactures-badge {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    padding: 0.125rem 0.55rem;
    background: color-mix(in srgb, var(--isis-mod-gescompta) 14%, white);
    color: var(--isis-mod-gescompta);
    border-radius: var(--isis-radius-pill);
    font-size: 0.8125rem;
    font-weight: 600;
    line-height: 1.4;
    white-space: nowrap;
}

/* Liste factures liées dans sidepanel */
.isis-rapprochement-multifactures-list {
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
    margin: 0.25rem 0 0;
    padding: 0;
    list-style: none;
}
.isis-rapprochement-multifactures-list__item {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 0.5rem;
    padding: 0.35rem 0.55rem;
    background: var(--isis-surface-alt, var(--isis-surface-alt));
    border-radius: 4px;
}
.isis-rapprochement-multifactures-list__amount {
    font-variant-numeric: tabular-nums;
    font-family: var(--isis-font-mono, ui-monospace, monospace);
    font-size: 0.85rem;
    color: var(--isis-text);
    font-weight: 500;
}

.isis-text-muted {
    color: var(--isis-text-muted);
}

/* ── Chantier #1 CRM — journal d'activités commerciales (TiersActiviteSection) ── */
.isis-crm { display: flex; flex-direction: column; gap: 1rem; }
.isis-crm__toolbar { display: flex; align-items: center; justify-content: space-between; gap: 1rem; }
.isis-crm__count { font-size: 0.9rem; font-weight: 500; }
.isis-crm__section-label { font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.04em; color: var(--isis-text-muted); margin: 0.5rem 0 0; }
.isis-crm__tasks { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.4rem; }
.isis-crm__task { display: flex; align-items: center; gap: 0.6rem; padding: 0.5rem 0.7rem; background: var(--isis-surface-alt); border-radius: 8px; border: 1px solid var(--isis-accent); }
.isis-crm__task.is-late { border-left-color: var(--isis-danger); }
.isis-crm__task-check { background: none; border: none; cursor: pointer; color: var(--isis-text-muted); display: flex; padding: 0; }
.isis-crm__task-check:hover { color: var(--isis-success); }
.isis-crm__task-main { display: flex; flex-direction: column; gap: 0.1rem; min-width: 0; flex: 1; }
.isis-crm__task-subject { font-weight: 500; }
.isis-crm__task-due { font-size: 0.78rem; color: var(--isis-text-muted); display: inline-flex; align-items: center; gap: 0.25rem; }
.isis-crm__task-due.is-late { color: var(--isis-danger); }
.isis-crm__timeline { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
.isis-crm__item { display: flex; gap: 0.7rem; padding: 0.6rem 0; border-bottom: 1px solid var(--isis-border); }
.isis-crm__item:last-child { border-bottom: none; }
.isis-crm__item-dot { flex: 0 0 auto; width: 30px; height: 30px; border-radius: 50%; display: flex; align-items: center; justify-content: center; background: color-mix(in srgb, var(--isis-accent) 12%, var(--isis-surface)); color: var(--isis-accent); }
.isis-crm__item-dot.crm-rdv { background: color-mix(in srgb, var(--isis-warning) 14%, var(--isis-surface)); color: var(--isis-warning); }
.isis-crm__item-dot.crm-tache { background: color-mix(in srgb, var(--isis-success) 14%, var(--isis-surface)); color: var(--isis-success); }
.isis-crm__item-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 0.2rem; }
.isis-crm__item-head { display: flex; align-items: baseline; gap: 0.5rem; flex-wrap: wrap; }
.isis-crm__item-type { font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.04em; color: var(--isis-text-muted); }
.isis-crm__item-subject { font-weight: 500; }
.isis-crm__item-text { margin: 0; font-size: 0.85rem; color: var(--isis-text); white-space: pre-wrap; }
.isis-crm__item-date { font-size: 0.75rem; color: var(--isis-text-muted); }
.isis-crm__del { background: none; border: none; cursor: pointer; color: var(--isis-text-muted); padding: 0.2rem; align-self: flex-start; }
.isis-crm__del:hover { color: var(--isis-danger); }

/* ════════════════════════════════════════════════════════════════════════════
   EntityCorrespondencePanel — onglet Correspondance (mails rattachés)
   ════════════════════════════════════════════════════════════════════════════ */
.isis-corr { display: flex; flex-direction: column; gap: 1rem; }
.isis-corr__loading { display: flex; align-items: center; gap: 0.5rem; padding: 1rem 0; color: var(--isis-text-muted); }
.isis-corr__header { display: flex; align-items: center; gap: 0.5rem; }
.isis-corr__title { font-size: 0.85rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.04em; color: var(--isis-text-muted); margin: 0; }
.isis-corr__count { font-size: 0.72rem; font-weight: 600; background: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 14%, var(--isis-surface)); color: var(--isis-current-mod, var(--isis-accent)); border-radius: var(--isis-radius-pill); padding: 0.1rem 0.45rem; }
.isis-corr__list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
.isis-corr__item { display: flex; gap: 0.75rem; padding: 0.65rem 0; border-bottom: 1px solid var(--isis-border-soft); }
.isis-corr__item:last-child { border-bottom: none; }
.isis-corr__item-icon { flex: 0 0 auto; width: 30px; height: 30px; border-radius: 50%; display: flex; align-items: center; justify-content: center; background: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 12%, var(--isis-surface)); color: var(--isis-current-mod, var(--isis-accent)); }
.isis-corr__item-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 0.25rem; }
.isis-corr__item-head { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }
.isis-corr__item-subject { font-weight: 500; font-size: 0.9rem; flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.isis-corr__item-meta { display: flex; align-items: center; gap: 1rem; flex-wrap: wrap; }
.isis-corr__item-sender,
.isis-corr__item-date { display: inline-flex; align-items: center; gap: 0.25rem; font-size: 0.78rem; color: var(--isis-text-muted); }
/* Aperçu inline dépliable */
.isis-corr__preview { margin-top: 0.3rem; }
.isis-corr__preview-toggle { font-size: 0.78rem; color: var(--isis-text-muted); cursor: pointer; list-style: none; display: inline-flex; align-items: center; gap: 0.25rem; }
.isis-corr__preview-toggle::-webkit-details-marker { display: none; }
.isis-corr__preview-toggle::marker { display: none; }
.isis-corr__preview-toggle::after { content: ""; display: inline-block; width: 0.5em; height: 0.5em; border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor; transform: rotate(-45deg); transition: transform var(--isis-motion-fast); }
details[open] .isis-corr__preview-toggle::after { transform: rotate(45deg); }
.isis-corr__preview-toggle:hover { color: var(--isis-text); }
.isis-corr__preview-body { margin-top: 0.4rem; padding: 0.5rem 0.75rem; font-size: 0.82rem; color: var(--isis-text); background: var(--isis-surface-alt); border-radius: var(--isis-radius-sm); border: 1px solid var(--isis-border-strong); white-space: pre-wrap; word-break: break-word; }
/* Barre d'actions par ligne */
.isis-corr__item-actions { display: flex; align-items: center; gap: 0.25rem; margin-top: 0.35rem; }
/* Taille locale uniquement — hover/focus délégués au canal ghost (.isis-action-btn--ghost) */
.isis-corr__action-btn { width: 28px; height: 28px; padding: 0; justify-content: center; }
/* Distinction visuelle au repos : rouge atténué (point 8) */
.isis-corr__action-btn--danger { color: color-mix(in srgb, var(--isis-danger) 65%, var(--isis-text-muted)); }
/* Hover rouge franc hérité du ghost, on surcharge uniquement pour le cas danger (point 7 : var seul, pas de fallback hex) */
.isis-corr__action-btn--danger:hover { background: color-mix(in srgb, var(--isis-danger) 10%, var(--isis-surface)); color: var(--isis-danger); }
/* Séparateur destructif : pousse le bouton Détacher à droite (point 9) */
.isis-corr__item-actions .isis-corr__action-btn--danger { margin-left: auto; }
/* Boutons désactivés : couleur opaque ≥ 4.5:1 (point 1 — remplace opacity:0.38) */
.isis-corr__action-btn--disabled { color: var(--isis-border-strong); cursor: not-allowed; pointer-events: none; }
/* État vide : contraste amélioré (point 13) */
.isis-corr__preview-empty { color: var(--isis-text-soft); font-style: italic; }
.isis-corr__action-btn .rzi { font-size: 16px; }

/* ════════════════════════════════════════════════════════════════════════════
   EntityHistoryPanel — onglet Historique (fil chronologique)
   ════════════════════════════════════════════════════════════════════════════ */
.isis-hist { display: flex; flex-direction: column; gap: 1rem; }
.isis-hist__loading { display: flex; align-items: center; gap: 0.5rem; padding: 1rem 0; color: var(--isis-text-muted); }
.isis-hist__header { display: flex; align-items: center; gap: 0.5rem; }
.isis-hist__title { font-size: 0.85rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.04em; color: var(--isis-text-muted); margin: 0; }
.isis-hist__count { font-size: 0.72rem; font-weight: 600; background: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 14%, var(--isis-surface)); color: var(--isis-current-mod, var(--isis-accent)); border-radius: var(--isis-radius-pill); padding: 0.1rem 0.45rem; }
.isis-hist__timeline { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
.isis-hist__item { display: flex; gap: 0.75rem; padding: 0.65rem 0; border-bottom: 1px solid var(--isis-border-soft); }
.isis-hist__item:last-child { border-bottom: none; }
.isis-hist__dot { flex: 0 0 auto; width: 30px; height: 30px; border-radius: 50%; display: flex; align-items: center; justify-content: center; }
.isis-hist__dot--transition { background: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 12%, var(--isis-surface)); color: var(--isis-current-mod, var(--isis-accent)); }
.isis-hist__dot--change { background: color-mix(in srgb, var(--isis-text-muted) 10%, var(--isis-surface)); color: var(--isis-text-muted); }

/* Circuit de validation d'une livraison présenté comme l'historique : on redécline
   le code couleur par type d'événement sur la pastille .isis-hist__dot (les règles
   d'origine étaient scopées à .isis-audit-trail__dot et ne s'appliquaient pas ici). */
.isis-hist__dot.livraison-wf-evt-created             { background: var(--isis-surface-alt); color: var(--isis-text-muted); }
.isis-hist__dot.livraison-wf-evt-marked-ready        { background: var(--isis-accent-soft); color: var(--isis-accent); }
.isis-hist__dot.livraison-wf-evt-shipped             { background: var(--isis-mod-gesproj-soft); color: var(--isis-mod-gesproj); }
.isis-hist__dot.livraison-wf-evt-received            { background: var(--isis-warning-soft, #fff7ed); color: var(--isis-warning, #d97706); }
.isis-hist__dot.livraison-wf-evt-validated           { background: var(--isis-success-soft); color: var(--isis-success); }
.isis-hist__dot.livraison-wf-evt-partially-validated { background: var(--isis-warning-soft, #fff7ed); color: var(--isis-warning, #d97706); }
.isis-hist__dot.livraison-wf-evt-rejected            { background: var(--isis-danger-soft); color: var(--isis-danger); }
.isis-hist__dot.livraison-wf-evt-reopened            { background: var(--isis-accent-soft); color: var(--isis-accent); }
.isis-hist__dot.livraison-wf-evt-attachment-added    { background: var(--isis-surface-alt); color: var(--isis-text-muted); }
.isis-hist__dot.livraison-wf-evt-ligne-updated       { background: var(--isis-surface-alt); color: var(--isis-text-muted); }

/* Transition de statut (A → B) et motif, sous le résumé de l'entrée. */
.isis-hist__transition {
    display: flex; align-items: center; gap: 0.3rem;
    margin-top: 0.2rem; font-size: 0.8rem; color: var(--isis-text-soft);
}
.isis-hist__reason {
    margin-top: 0.25rem; padding: 0.35rem 0.5rem;
    font-size: 0.82rem; color: var(--isis-text);
    background: var(--isis-surface-alt); border-radius: var(--isis-radius-sm);
}
.isis-hist__more { margin-top: 0.4rem; font-size: 0.82rem; color: var(--isis-text-muted); }
.isis-hist__body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 0.3rem; }
.isis-hist__summary { font-weight: 500; font-size: 0.9rem; }
.isis-hist__meta { display: flex; align-items: center; gap: 1rem; flex-wrap: wrap; }
.isis-hist__actor,
.isis-hist__date { display: inline-flex; align-items: center; gap: 0.25rem; font-size: 0.78rem; color: var(--isis-text-muted); }
.isis-hist__changes { margin-top: 0.25rem; }
.isis-hist__changes-toggle { font-size: 0.78rem; color: var(--isis-text-muted); cursor: pointer; list-style: none; display: inline-flex; align-items: center; gap: 0.25rem; }
.isis-hist__changes-toggle::-webkit-details-marker { display: none; }
.isis-hist__changes-toggle::marker { display: none; }
.isis-hist__changes-toggle::after { content: ""; display: inline-block; width: 0.5em; height: 0.5em; border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor; transform: rotate(-45deg); transition: transform var(--isis-motion-fast); }
details[open] .isis-hist__changes-toggle::after { transform: rotate(45deg); }
.isis-hist__changes-toggle:hover { color: var(--isis-text); }
.isis-hist__fields { list-style: none; margin: 0.4rem 0 0; padding: 0.5rem 0.75rem; display: flex; flex-direction: column; gap: 0.3rem; background: var(--isis-surface-alt); border-radius: var(--isis-radius-sm); border: 1px solid var(--isis-border-strong); }
.isis-hist__field { display: flex; align-items: baseline; gap: 0.4rem; flex-wrap: wrap; font-size: 0.8rem; }
.isis-hist__field-name { font-weight: 600; color: var(--isis-text); min-width: 0; }
.isis-hist__field-old { color: var(--isis-text-muted); text-decoration: line-through; }
.isis-hist__field-new { color: var(--isis-text); }
/* Icônes meta — contraste AA (opacity:1, couleur sémantique) */
.isis-hist__meta .isis-hist__meta-icon,
.isis-hist__meta .rzi { font-size: 13px; color: var(--isis-text-muted); opacity: 1; }
.isis-hist__field-arrow-icon.rzi { font-size: 13px; color: var(--isis-text-muted); opacity: 1; }
/* Icônes meta correspondance — contraste AA */
.isis-corr__item-meta .isis-corr__item-meta-icon,
.isis-corr__item-meta .rzi { font-size: 14px; color: var(--isis-text-muted); opacity: 1; }
/* Icônes état vide */
.isis-corr__empty-icon.rzi,
.isis-hist__empty-icon.rzi { opacity: 0.4; }
/* Skeleton chargement — correspondance */
.isis-corr__loading { flex-direction: column; gap: 0.6rem; padding: 0.75rem 0; }
.isis-corr__skeleton-row,
.isis-hist__skeleton-row { display: flex; align-items: center; gap: 0.6rem; }
.isis-corr__skeleton-dot,
.isis-hist__skeleton-dot { flex: 0 0 30px; height: 30px; border-radius: 50%; }
.isis-corr__skeleton-line,
.isis-hist__skeleton-line { flex: 1; height: 14px; border-radius: var(--isis-radius-sm); }
.isis-corr__skeleton-line--short,
.isis-hist__skeleton-line--short { flex: 0 0 45%; }
.isis-corr__skeleton-line--medium,
.isis-hist__skeleton-line--medium { flex: 0 0 70%; }
/* Skeleton chargement — historique */
.isis-hist__loading { flex-direction: column; gap: 0.6rem; padding: 0.75rem 0; }

/* Marqueur sortant — icône + badge */
.isis-corr__item--outbound .isis-corr__item-icon {
    background: color-mix(in srgb, var(--isis-accent) 10%, var(--isis-surface));
    color: var(--isis-accent);
}
.isis-corr__outbound-badge {
    display: inline-flex; align-items: center; gap: 0.25rem;
    font-size: 0.72rem; font-weight: 600; color: var(--isis-accent);
    background: color-mix(in srgb, var(--isis-accent) 10%, var(--isis-surface));
    border: 1px solid color-mix(in srgb, var(--isis-accent) 30%, transparent);
    border-radius: var(--isis-radius-pill); padding: 0.1rem 0.5rem 0.1rem 0.35rem;
}
.isis-corr__outbound-badge .rzi { font-size: 13px; }

/* Éditeur HTML réponse mail */
.isis-mail-reply-editor { height: 300px; min-height: 300px; width: 100%; }

/* ════════════════════════════════════════════════════════════════════════════
   MonEspace › Mes projets (chantier « Mes projets » — saisie temps + frais)
   ════════════════════════════════════════════════════════════════════════════ */

/* Identité chromatique module monespace (icône header + soft). */
.isis-shell__content.mod-monespace { --isis-module-hue: var(--isis-mod-monespace); }
.isis-rich-header__icon.mod-monespace-soft { background: var(--isis-mod-monespace-soft); color: var(--isis-mod-monespace); }

/* Liste des projets (master). */
.isis-proj-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.25rem; }
.isis-proj-item {
	display: flex; align-items: flex-start; gap: 0.6rem; width: 100%;
	text-align: left; background: transparent; border: none; cursor: pointer;
	padding: 0.6rem 0.7rem; border-radius: 8px; border: 1px solid transparent;
	transition: background 0.12s ease, border-color 0.12s ease;
}
.isis-proj-item:hover { background: var(--isis-surface-alt); }
.isis-proj-item:focus-visible { outline: 2px solid var(--isis-mod-monespace); outline-offset: 1px; }
.isis-proj-item.is-active { background: var(--isis-mod-monespace-soft); border-left-color: var(--isis-mod-monespace); }
.isis-proj-item__dot { width: 9px; height: 9px; border-radius: 50%; margin-top: 0.35rem; flex: 0 0 auto; box-shadow: inset 0 0 0 1px rgba(0,0,0,0.18); }
.isis-proj-item__dot.is-ready { background: var(--isis-success); }
.isis-proj-item__dot.is-pending { background: var(--isis-mod-monespace); }
.isis-proj-item__dot.is-archived { background: var(--isis-text-muted); }
.isis-proj-item__main { display: flex; flex-direction: column; gap: 0.1rem; min-width: 0; flex: 1; }
.isis-proj-item__num { font-family: var(--isis-font-mono, monospace); font-size: 0.78rem; color: var(--isis-text-muted); }
.isis-proj-item__title { font-weight: 600; font-size: 0.9rem; color: var(--isis-text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.isis-proj-item__meta { font-size: 0.76rem; color: var(--isis-text-muted); }
.isis-proj-item__alert {
	flex: 0 0 auto; width: 18px; height: 18px; border-radius: 50%;
	background: var(--isis-danger); color: #fff; font-weight: 700; font-size: 0.75rem;
	display: inline-flex; align-items: center; justify-content: center; margin-top: 0.25rem;
}

/* En-tête du panneau détail. */
.isis-detail-head { padding: 0 0 0.6rem; border-bottom: 1px solid var(--isis-border); margin-bottom: 0.6rem; }
.isis-detail-head__title { font-size: 1rem; font-weight: 600; margin: 0 0 0.2rem; color: var(--isis-text); }
.isis-detail-head__sub { font-size: 0.8rem; color: var(--isis-text-muted); display: flex; flex-wrap: wrap; gap: 0.4rem; }

/* Barre d'action interne à un onglet. */
.isis-panel-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; margin: 0.5rem 0 0.5rem; }
.isis-panel-toolbar__title { font-weight: 600; font-size: 0.88rem; color: var(--isis-text); }
.isis-panel-empty { color: var(--isis-text-muted); font-size: 0.85rem; padding: 0.8rem 0; }
.isis-panel-foot { display: flex; justify-content: flex-end; margin-top: 0.6rem; }
.isis-ndf-detail { margin-top: 0.8rem; padding-top: 0.6rem; border-top: 1px dashed var(--isis-border); }

/* Colonnes utilitaires de grille. */
.isis-tabular { font-variant-numeric: tabular-nums; }
/* Cellule (ou en-tête) de grille centrée : ordres, cases et pastilles d'état. */
.isis-grid__cell--center { text-align: center; }
/* Cellule secondaire en corps réduit (codes, conditions). */
.isis-grid__cell--sm { font-size: var(--isis-fs-sm); }
.isis-fw-semibold { font-weight: var(--isis-fw-semibold); }
/* Texte libre saisi en zone multiligne : les sauts de ligne de la saisie survivent à
   l'affichage, la ligne reste lisible (75 caractères au plus). */
.isis-rich-toolbar__btn.isis-rich-toolbar__btn--sm { font-size: var(--isis-fs-label); padding: 0.15rem 0.5rem; }
.isis-hint { font-size: var(--isis-fs-label); color: var(--isis-text-muted); }
.isis-cell-secondary { font-size: var(--isis-fs-sm); color: var(--isis-text-muted); }
.isis-grid--facturx-structures { min-width: 860px; }
.isis-grid--facturx-structures,
.isis-grid--facturx-structures .isis-grid__head,
.isis-grid--facturx-structures .isis-grid__row {
    grid-template-columns: 50px 100px minmax(220px, 1fr) 100px 140px 250px;
}
.isis-grid--facturx-structures .isis-grid__head,
.isis-grid--facturx-structures .isis-grid__row { display: grid; }

.isis-detail-desc {
    margin: 0;
    white-space: pre-line;
    overflow-wrap: anywhere;
    max-width: 75ch;
}
.isis-grid__col-ellipsis { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Templates de grilles « Mes projets ». */
.isis-grid--proj-temps .isis-grid__head,
.isis-grid--proj-temps .isis-grid__row {
	display: grid; grid-template-columns: 28px 80px minmax(120px, 1fr) 80px 130px; gap: 0.5rem; align-items: center;
}
/* Bandeau de regroupement par semaine + ligne de total projet (full width,
   hors grille — enfants flex directs de .isis-grid). */
.isis-proj-temps__week,
.isis-proj-temps__foot {
	display: flex; align-items: center; justify-content: space-between;
	padding: 0.4rem 0.55rem; font-size: 0.78rem;
}
.isis-proj-temps__week {
	background: var(--isis-surface-alt);
	color: var(--isis-text-muted);
	font-weight: 600; text-transform: uppercase; letter-spacing: 0.02em;
	border-top: 1px solid var(--isis-border-soft, #eef0f3);
}
.isis-proj-temps__foot {
	border-top: 2px solid var(--isis-border);
	margin-top: 0.2rem; font-weight: 700; color: var(--isis-text);
}
.isis-proj-temps__week-total { font-variant-numeric: tabular-nums; }
.isis-grid--proj-ndf .isis-grid__head,
.isis-grid--proj-ndf .isis-grid__row {
	display: grid; grid-template-columns: 130px minmax(140px, 1fr) 120px 130px 80px; gap: 0.5rem; align-items: center;
}
.isis-grid--proj-ndf-ligne .isis-grid__head,
.isis-grid--proj-ndf-ligne .isis-grid__row {
	display: grid; grid-template-columns: 80px minmax(120px, 1fr) minmax(100px, 1fr) 120px 80px; gap: 0.5rem; align-items: center;
}
.isis-grid--proj-mob .isis-grid__head,
.isis-grid--proj-mob .isis-grid__row {
	display: grid; grid-template-columns: minmax(120px, 1fr) 140px 170px 100px; gap: 0.5rem; align-items: center;
}

/* ════════════════════════════════════════════════════════════════════════════
   MonEspace › Mes projets — vue calendrier intelligente de saisie de temps
   ════════════════════════════════════════════════════════════════════════════ */

.isis-filter-bar__hint { font-size: 0.82rem; color: var(--isis-text-muted); }

.isis-ts-cal-wrap { display: flex; flex-direction: column; gap: 0.75rem; flex: 1 1 auto; min-height: 0; overflow: auto; }

.isis-ts-cal-banner {
	display: flex; align-items: center; gap: 0.5rem;
	padding: 0.6rem 0.9rem; border-radius: 8px;
	background: color-mix(in srgb, var(--isis-warning) 12%, var(--isis-surface));
	color: var(--isis-text); font-size: 0.85rem;
	border: 1px solid var(--isis-warning);
	box-sizing: border-box;
}
.isis-ts-cal-banner .rzi { color: var(--isis-warning); }

.isis-ts-cal { display: flex; flex-direction: column; gap: 0.6rem; flex: 1 1 auto; min-height: 0; }

/* Toolbar mois. */
.isis-ts-cal__toolbar { display: flex; align-items: center; gap: 0.5rem; }
.isis-ts-cal__nav {
	display: inline-flex; align-items: center; justify-content: center;
	width: 30px; height: 30px; border-radius: 7px; border: 1px solid var(--isis-border);
	background: var(--isis-surface); cursor: pointer; color: var(--isis-text);
}
.isis-ts-cal__nav:hover { background: var(--isis-surface-alt); }
.isis-ts-cal__nav:focus-visible { outline: 2px solid var(--isis-mod-monespace); outline-offset: 1px; }
.isis-ts-cal__month { font-weight: 600; font-size: 0.95rem; min-width: 140px; text-align: center; }
.isis-ts-cal__today {
	border: 1px solid var(--isis-border); background: var(--isis-surface); cursor: pointer;
	border-radius: 7px; padding: 0.3rem 0.7rem; font-size: 0.8rem; color: var(--isis-text);
}
.isis-ts-cal__today:hover { background: var(--isis-surface-alt); }
.isis-ts-cal__total { margin-left: auto; font-size: 0.85rem; color: var(--isis-text-muted); font-variant-numeric: tabular-nums; }

/* Grille. */
/* Plein écran : la grille prend toute la hauteur restante du wrap (flex), les
   semaines se partagent l'espace à parts égales, les cellules s'étirent. */
.isis-ts-cal__grid { border: 1px solid var(--isis-border); border-radius: 10px; overflow: hidden; flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
.isis-ts-cal__head { display: grid; grid-template-columns: repeat(7, 1fr); background: var(--isis-surface-alt); flex: 0 0 auto; }
.isis-ts-cal__head-cell { padding: 0.45rem 0.5rem; font-size: 0.72rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.03em; color: var(--isis-text-muted); text-align: center; }
.isis-ts-cal__body { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }
.isis-ts-cal__row { display: grid; grid-template-columns: repeat(7, 1fr); flex: 1 1 0; min-height: 64px; }

/* Cellule jour : flex column. Les lanes de barres sont poussées en bas
   (margin-top:auto) et restent alignées entre cellules car chaque cellule de la
   semaine réserve le même nombre de lanes (slots vides inclus). */
.isis-ts-cal__cell {
	min-height: 64px;
	overflow: visible;
	display: flex; flex-direction: column; gap: 0.2rem;
	padding: 0.35rem 0.4rem; text-align: left; cursor: pointer;
	background: var(--isis-surface); border: none;
	border-top: 1px solid var(--isis-border-soft, #eef0f3);
	border-left: 1px solid var(--isis-border-soft, #eef0f3);
	transition: background 0.12s ease;
}
.isis-ts-cal__row > .isis-ts-cal__cell:first-child { border-left: none; }
.isis-ts-cal__cell:hover:not(:disabled) { background: var(--isis-surface-alt); }
.isis-ts-cal__cell:focus-visible { outline: 2px solid var(--isis-mod-monespace); outline-offset: -2px; }
.isis-ts-cal__cell.is-out { background: var(--isis-surface-alt); cursor: default; opacity: 0.5; }
.isis-ts-cal__cell.is-today .isis-ts-cal__cell-num {
	background: var(--isis-mod-monespace); color: var(--isis-surface);
	border-radius: 50%; width: 20px; height: 20px; display: inline-flex; align-items: center; justify-content: center;
}

.isis-ts-cal__cell-top { display: flex; align-items: center; justify-content: space-between; }
.isis-ts-cal__cell-num { font-size: 0.8rem; font-weight: 600; color: var(--isis-text); }
.isis-ts-cal__cell-h { font-size: 0.78rem; font-weight: 600; font-variant-numeric: tabular-nums; color: var(--isis-text); }
.isis-ts-cal__cell-flag {
	width: 16px; height: 16px; border-radius: 50%; background: var(--isis-danger); color: var(--isis-surface);
	font-size: 0.7rem; font-weight: 700; display: inline-flex; align-items: center; justify-content: center;
}

/* Bandeau d'état coloré en bas de cellule (left border accent). */
.isis-ts-cal__cell.is-complet  { box-shadow: inset 3px 0 0 0 var(--isis-success); }
.isis-ts-cal__cell.is-partiel  { box-shadow: inset 3px 0 0 0 var(--isis-warning); }
.isis-ts-cal__cell.is-topoint  { box-shadow: inset 3px 0 0 0 var(--isis-danger); background: color-mix(in srgb, var(--isis-danger) 5%, var(--isis-surface)); }
.isis-ts-cal__cell.is-rejete   { box-shadow: inset 3px 0 0 0 var(--isis-danger); }
.isis-ts-cal__cell.is-repos    { background: var(--isis-surface-alt); }

/* Tag férié (reste dans la cellule). */
.isis-ts-cal__tag { font-size: 0.68rem; border-radius: 4px; padding: 0.05rem 0.3rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; margin: 0 0.3rem; }
.isis-ts-cal__tag.is-holiday { color: var(--isis-mod-monespace); background: var(--isis-mod-monespace-soft); font-style: italic; }

/* ── Barres de mobilisation (mini-Gantt par lanes, DANS les cases) ─────────
   Chaque cellule empile une pile de lanes (1 par tâche se chevauchant). Les
   slots vides réservent la hauteur → alignement vertical parfait entre cellules.
   Une barre multi-jours = un segment par cellule à la MÊME lane, sans gap
   horizontal → continuité visuelle. pointer-events:none : le clic reste sur la
   cellule. Aucune superposition possible (une lane = une seule barre par jour). */
.isis-ts-cal__lanes {
	margin-top: auto;          /* colle la pile de barres au bas de la cellule */
	display: flex;
	flex-direction: column;
	gap: 2px;
	pointer-events: none;
}
.isis-ts-cal__lane-empty { height: 15px; }
.isis-ts-cal__lane-bar {
	position: relative;
	height: 15px;
	display: flex;
	align-items: center;
	border-radius: 0;          /* arrondi seulement aux extrémités du segment */
	overflow: visible;
}
.isis-ts-cal__lane-bar.is-l { border-top-left-radius: 4px; border-bottom-left-radius: 4px; }
.isis-ts-cal__lane-bar.is-r { border-top-right-radius: 4px; border-bottom-right-radius: 4px; }
.isis-ts-cal__lane-label {
	position: absolute;
	left: 6px;
	white-space: nowrap;       /* déborde sur la suite de SA barre (même couleur) */
	font-size: 0.62rem;
	font-weight: 600;
	line-height: 1;
	pointer-events: none;
	z-index: 1;
}
/* Palette stable 6 teintes (fond / texte) — alignée sur ColorClass(Guid). */
.isis-ts-cal__lane-bar.is-c0 { background: #e0e7ff; }
.isis-ts-cal__lane-bar.is-c0 .isis-ts-cal__lane-label { color: #3730a3; }
.isis-ts-cal__lane-bar.is-c1 { background: #ccfbf1; }
.isis-ts-cal__lane-bar.is-c1 .isis-ts-cal__lane-label { color: #115e59; }
.isis-ts-cal__lane-bar.is-c2 { background: #fef3c7; }
.isis-ts-cal__lane-bar.is-c2 .isis-ts-cal__lane-label { color: #92400e; }
.isis-ts-cal__lane-bar.is-c3 { background: #ffe4e6; }
.isis-ts-cal__lane-bar.is-c3 .isis-ts-cal__lane-label { color: #9f1239; }
.isis-ts-cal__lane-bar.is-c4 { background: #e0f2fe; }
.isis-ts-cal__lane-bar.is-c4 .isis-ts-cal__lane-label { color: #075985; }
.isis-ts-cal__lane-bar.is-c5 { background: #ede9fe; }
.isis-ts-cal__lane-bar.is-c5 .isis-ts-cal__lane-label { color: #5b21b6; }

/* Légende. */
.isis-ts-cal__legend { display: flex; flex-wrap: wrap; gap: 0.9rem; padding: 0.3rem 0.1rem; }
.isis-ts-cal__legend-item { display: inline-flex; align-items: center; gap: 0.35rem; font-size: 0.78rem; color: var(--isis-text-muted); }
.isis-ts-cal__dot { width: 10px; height: 10px; border-radius: 3px; }
.isis-ts-cal__dot.is-complet { background: var(--isis-success); }
.isis-ts-cal__dot.is-partiel { background: var(--isis-warning); }
.isis-ts-cal__dot.is-topoint { background: var(--isis-danger); }
.isis-ts-cal__dot.is-rejete  { background: var(--isis-danger); opacity: 0.6; }
.isis-ts-cal__dot.is-repos   { background: var(--isis-text-muted); opacity: 0.5; }

/* (Tâches planifiées désormais rendues en barres mini-Gantt — cf. .isis-ts-cal__bar.) */

/* ── Carte flotte gespark (géoloc temps réel, 0333) ───────────────────────── */
.isis-fleet-map {
    display: grid;
    grid-template-columns: 1fr 320px;
    gap: 1rem;
    align-items: stretch;
    min-height: 0;
}
.isis-fleet-map__canvas { min-width: 0; border-radius: 10px; overflow: hidden; box-shadow: var(--isis-elevation-1); }
.isis-fleet-map__list {
    overflow-y: auto;
    max-height: 68vh;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: 10px;
}
/* En-tête de la liste latérale de la carte flotte : porte le compteur que le bandeau
   affichait (« N véhicules localisés »). Collant, parce que la liste défile sous lui et
   qu'un compteur qui sort de l'écran ne compte plus rien. */
.isis-fleet-list__title-bar {
    position: sticky;
    top: 0;
    z-index: 1;
    display: flex;
    align-items: baseline;
    gap: 0.4rem;
    margin: 0;
    padding: 0.5rem 0.75rem;
    background: var(--isis-surface-alt);
    border-bottom: 1px solid var(--isis-border);
    border-radius: 10px 10px 0 0;
    font-size: 0.7rem;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--isis-text-muted);
}
.isis-fleet-list { list-style: none; margin: 0; padding: 0; }
.isis-fleet-list__item {
    display: flex; gap: 0.6rem; align-items: flex-start;
    padding: 0.6rem 0.75rem; cursor: pointer;
    border-bottom: 1px solid var(--isis-border-soft, var(--isis-border));
}
.isis-fleet-list__item:hover { background: var(--isis-surface-alt); }
.isis-fleet-list__item:focus-visible {
    outline: none;
    box-shadow: inset 3px 0 0 0 var(--isis-current-mod, var(--isis-accent));
    background: var(--isis-surface-alt);
}
.isis-fleet-list__dot {
    width: 10px; height: 10px; border-radius: 50%; margin-top: 0.3rem; flex: 0 0 auto;
    box-shadow: inset 0 0 0 1px rgba(0,0,0,0.18);
}
.isis-fleet-list__dot.is-ok      { background: var(--isis-success); }
.isis-fleet-list__dot.is-pending { background: var(--isis-warning); }
.isis-fleet-list__dot.is-danger  { background: var(--isis-danger); }
.isis-fleet-list__dot.is-draft   { background: var(--isis-text-muted); }
.isis-fleet-list__main { min-width: 0; }
.isis-fleet-list__title { font-weight: 600; font-size: 0.85rem; }
.isis-fleet-list__sub { font-size: 0.8rem; color: var(--isis-text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.isis-fleet-list__meta { font-size: 0.72rem; color: var(--isis-text-muted); margin-top: 0.1rem; }

@media (max-width: 1100px) {
    .isis-fleet-map { grid-template-columns: 1fr; }
    .isis-fleet-map__list { max-height: 32vh; }
}

/* ============================================================================
   Onglet Analyse pivot — factures émises (/gescompta/factures/emises)
   Cadrage : docs/gescompta-pivot-analyse-cadrage.md
   ============================================================================ */
.isis-tabs--page {
    margin: 0.25rem 0 0.5rem;
}

.isis-pivot-tab-panel {
    display: flex;
    flex-direction: column;
    min-height: 0;
    padding-top: 0.25rem;
}

.isis-pivot-analyse {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    min-height: 0;
}

.isis-pivot-analyse__toolbar {
    display: flex;
    align-items: flex-end;
    flex-wrap: wrap;
    gap: 1rem;
    padding: 0.75rem 1rem;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius, 8px);
    box-shadow: var(--isis-elevation-1);
}

.isis-pivot-analyse__field {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
}

.isis-pivot-analyse__field label {
    font-size: 0.72rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--isis-text-muted);
}

.isis-pivot-analyse__hint {
    flex: 1 1 240px;
    align-self: center;
    font-size: 0.82rem;
    color: var(--isis-text-muted);
}

.isis-pivot-analyse__state {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    padding: 3rem 1rem;
    text-align: center;
    color: var(--isis-text-muted);
    background: var(--isis-surface);
    border: 1px dashed var(--isis-border);
    border-radius: var(--isis-radius, 8px);
}

.isis-pivot-analyse__state strong {
    color: var(--isis-text);
}

/* ── Lot 1 — File comptable « À facturer » (handoff commande → facturation) ── */
.isis-grid--billing-worklist .isis-grid__head,
.isis-grid--billing-worklist .isis-grid__row {
    display: grid;
    grid-template-columns:
        60px                     /* Status PV */
        120px                    /* N° */
        minmax(180px, 1.4fr)     /* Client + intitulé */
        minmax(120px, 1fr)       /* Structure */
        110px                    /* Pile */
        130px                    /* Total HT */
        130px;                   /* Reste */
    align-items: center;
}

.isis-grid--billing-devis .isis-grid__head,
.isis-grid--billing-devis .isis-grid__row {
    display: grid;
    grid-template-columns:
        120px                    /* N° */
        minmax(180px, 1.6fr)     /* Client + intitulé */
        minmax(140px, 1fr)       /* Structure */
        140px;                   /* Montant HT */
    align-items: center;
}

.isis-grid--billing-echeance .isis-grid__head,
.isis-grid--billing-echeance .isis-grid__row {
    display: grid;
    grid-template-columns:
        130px                    /* Commande */
        minmax(180px, 1.6fr)     /* Échéance (libellé) */
        minmax(140px, 1fr)       /* Client */
        140px;                   /* Montant HT */
    align-items: center;
}

.isis-grid--billing-returned .isis-grid__head,
.isis-grid--billing-returned .isis-grid__row {
    display: grid;
    grid-template-columns:
        120px                    /* Commande (lien) */
        minmax(150px, 1.4fr)     /* Échéance (libellé + renvois) */
        minmax(120px, 1fr)       /* Client */
        86px                     /* Ancienneté */
        minmax(140px, 1.2fr)     /* Motif + motif sublabel */
        130px;                   /* Montant HT */
    align-items: start;
}

/* Worklist transverse « Demandes à reprendre » (page CDP) — 5 colonnes.
   Sans ce gabarit la grille héritait du template générique 8 colonnes → chevauchement.
   (La navigation vers la commande passe par le n° cliquable + le bouton « Ouvrir la
   commande » du sidepanel — pas de colonne d'action redondante.) */
.isis-grid--reprise-list .isis-grid__head,
.isis-grid--reprise-list .isis-grid__row {
    display: grid;
    /* Recalées le 2026-09-02 : les QUATRE en-têtes triables portent désormais une icône de
       sens (Libellé l'a gagnée), et une largeur calculée pour un libellé nu la coupait. */
    grid-template-columns:
        minmax(165px, 1fr)       /* Commande (lien + badge renvois + tri) */
        minmax(200px, 1.4fr)     /* Libellé (+ tri) */
        150px                    /* Montant (montant fixe ou % calculé + base, + tri) */
        130px                    /* Ancienneté (+ tri) */
        minmax(190px, 1.3fr);    /* Motif + raison — pas de tri, texte libre */
    align-items: start;
    /* Override du min-width: 1000px hérité de la règle générique .isis-grid__row :
       cette grille n'a que 5 colonnes (somme mini 740px). À 1000px elle débordait
       la carte maître → « MOTIF DU RENVOI » tronqué par le bord droit. */
    min-width: 740px;
}

/* EF-90 — temps contestés en attente de correction (gesproj/temps-contestes), 6 colonnes. */
.isis-grid--temps-contestes .isis-grid__head,
.isis-grid--temps-contestes .isis-grid__row {
    display: grid;
    grid-template-columns:
        100px                    /* Jour */
        minmax(140px, 1fr)       /* Collaborateur */
        minmax(180px, 1.3fr)     /* Commande + tâche */
        90px                     /* Heures */
        minmax(180px, 1.4fr)     /* Motif */
        minmax(150px, 1fr);      /* Contesté par + date */
    align-items: start;
    min-width: 840px;
}

/* EF-42 — projets (gesproj/projets), 8 colonnes. */
.isis-grid--projets .isis-grid__head,
.isis-grid--projets .isis-grid__row {
    display: grid;
    grid-template-columns:
        minmax(220px, 2fr)       /* Projet */
        minmax(150px, 1.2fr)     /* Entreprise porteuse */
        minmax(140px, 1fr)       /* Chef de projet */
        110px                    /* Fin prévue */
        150px                    /* Avancement */
        140px                    /* Commandé HT */
        120px                    /* Santé */
        110px;                   /* Statut */
    align-items: center;
    min-width: 1080px;
}

/* EF-42 — commandes d'un projet (gesproj/projets/{id}), 8 colonnes. */
.isis-grid--projet-commandes .isis-grid__head,
.isis-grid--projet-commandes .isis-grid__row {
    display: grid;
    grid-template-columns:
        minmax(200px, 2fr)       /* Commande + intitulé */
        minmax(140px, 1fr)       /* Entreprise */
        190px                    /* Période */
        140px                    /* Montant HT */
        150px                    /* Avancement */
        120px                    /* Santé */
        120px                    /* Statut */
        48px;                    /* Détacher */
    align-items: center;
    min-width: 1100px;
}

/* EF-42 — tâches du projet, 7 colonnes. */
.isis-grid--projet-taches .isis-grid__head,
.isis-grid--projet-taches .isis-grid__row {
    display: grid;
    grid-template-columns:
        minmax(220px, 2fr)       /* Tâche */
        120px                    /* Commande */
        100px                    /* Début */
        100px                    /* Fin */
        80px                     /* Charge */
        150px                    /* Avancement */
        120px;                   /* État */
    align-items: center;
    min-width: 900px;
}

/* EF-42 — jalons du projet, 8 colonnes. */
.isis-grid--projet-jalons .isis-grid__head,
.isis-grid--projet-jalons .isis-grid__row {
    display: grid;
    grid-template-columns:
        100px                    /* Date cible */
        minmax(200px, 2fr)       /* Jalon */
        120px                    /* Commande */
        70px                     /* Poids */
        150px                    /* Complétion */
        110px                    /* Statut */
        110px                    /* Santé */
        100px;                   /* Atteint le */
    align-items: center;
    min-width: 960px;
}

/* Fiche projet, onglets Finances. */
.isis-grid--projet-budget .isis-grid__head,
.isis-grid--projet-budget .isis-grid__row {
    display: grid;
    grid-template-columns:
        minmax(160px, 1.5fr)     /* Commande */
        120px                    /* CA retenu */
        120px                    /* MO prévue */
        150px                    /* MO consommée */
        120px                    /* Sous-traitance */
        120px                    /* Autres coûts */
        120px;                   /* Coût réel */
    align-items: center;
    min-width: 960px;
}

.isis-grid--projet-facturation .isis-grid__head,
.isis-grid--projet-facturation .isis-grid__row {
    display: grid;
    grid-template-columns:
        minmax(200px, 2fr)       /* Commande */
        120px                    /* Commandé */
        120px                    /* Produit */
        150px                    /* Facturé */
        130px                    /* Produit non facturé */
        120px                    /* Reste à facturer */
        100px;                   /* Écarts */
    align-items: center;
    min-width: 1000px;
}

.isis-grid--projet-echeances .isis-grid__head,
.isis-grid--projet-echeances .isis-grid__row {
    display: grid;
    grid-template-columns:
        100px                    /* Date */
        minmax(200px, 2fr)       /* Échéance */
        120px                    /* Commande */
        120px                    /* Montant HT */
        130px                    /* Statut */
        100px;                   /* Payée le */
    align-items: center;
    min-width: 800px;
}

.isis-grid--projet-factures .isis-grid__head,
.isis-grid--projet-factures .isis-grid__row {
    display: grid;
    grid-template-columns:
        100px                    /* Date */
        minmax(160px, 1.5fr)     /* Numéro */
        120px                    /* Commande */
        120px                    /* Montant HT */
        150px;                   /* Statut */
    align-items: center;
    min-width: 680px;
}

.isis-grid--projet-marge .isis-grid__head,
.isis-grid--projet-marge .isis-grid__row {
    display: grid;
    grid-template-columns:
        minmax(160px, 1.5fr)     /* Commande */
        120px                    /* CA retenu */
        120px                    /* Coût réel */
        120px                    /* Marge */
        170px                    /* Taux de marge */
        160px;                   /* Situation */
    align-items: center;
    min-width: 900px;
}

.isis-grid--projet-heures .isis-grid__head,
.isis-grid--projet-heures .isis-grid__row {
    display: grid;
    grid-template-columns:
        minmax(200px, 2fr)       /* Collaborateur */
        100px                    /* Heures */
        170px                    /* Part du projet */
        110px;                   /* En brouillon */
    align-items: center;
    min-width: 600px;
}

.isis-projet-echue { color: var(--isis-danger); }

.isis-grid--projet-mobilisations .isis-grid__head,
.isis-grid--projet-mobilisations .isis-grid__row {
    display: grid;
    grid-template-columns:
        minmax(200px, 2fr)       /* Collaborateur */
        130px                    /* Commande */
        200px                    /* Période */
        90px                     /* Charge */
        130px;                   /* Statut */
    align-items: center;
    min-width: 760px;
}

.isis-grid--projet-livrables .isis-grid__head,
.isis-grid--projet-livrables .isis-grid__row {
    display: grid;
    grid-template-columns:
        minmax(200px, 2fr)       /* Livrable */
        130px                    /* Commande */
        minmax(140px, 1fr)       /* Responsable */
        100px                    /* Prévu le */
        100px                    /* Rendu le */
        120px;                   /* Statut */
    align-items: center;
    min-width: 820px;
}

.isis-grid--projet-avenants .isis-grid__head,
.isis-grid--projet-avenants .isis-grid__row {
    display: grid;
    grid-template-columns:
        minmax(180px, 2fr)       /* Avenant */
        130px                    /* Commande */
        minmax(120px, 1fr)       /* Type */
        150px                    /* Effet */
        100px                    /* Signé le */
        130px                    /* Variation HT */
        110px;                   /* Statut */
    align-items: center;
    min-width: 940px;
}

.isis-grid--projet-risques .isis-grid__head,
.isis-grid--projet-risques .isis-grid__row {
    display: grid;
    grid-template-columns:
        minmax(220px, 2fr)       /* Risque */
        130px                    /* Commande */
        150px                    /* Criticité */
        120px                    /* Prochaine revue */
        130px;                   /* Statut */
    align-items: center;
    min-width: 760px;
}

.isis-grid--projet-problemes .isis-grid__head,
.isis-grid--projet-problemes .isis-grid__row {
    display: grid;
    grid-template-columns:
        minmax(220px, 2fr)       /* Problème */
        130px                    /* Commande */
        110px                    /* Gravité */
        130px                    /* Résolution attendue */
        120px                    /* Coût */
        110px;                   /* Statut */
    align-items: center;
    min-width: 820px;
}

.isis-grid--projet-revues .isis-grid__head,
.isis-grid--projet-revues .isis-grid__row {
    display: grid;
    grid-template-columns:
        100px                    /* Date */
        120px                    /* Sujet */
        minmax(220px, 2fr)       /* Message */
        130px                    /* Commande */
        minmax(160px, 1fr)       /* De → à */
        110px;                   /* État */
    align-items: center;
    min-width: 840px;
}

.isis-projet-cell-message {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Carte de charge : intensité par mélange de la couleur du module, pas les --isis-lvl-* de la matrice de compétences. */
.isis-projet-carte__scroll {
    overflow: auto;
    max-height: 32rem;
    margin-top: 0.5rem;
    border-radius: var(--isis-radius-sm);
}

.isis-projet-anomalie {
    display: block;
    margin-top: 0.125rem;
    font-size: 0.6875rem;
    line-height: 1.3;
    color: var(--isis-text-muted);
}

.isis-projet-carte thead th {
    position: sticky;
    top: 0;
    background: var(--isis-surface);
}

.isis-projet-carte__scroll:focus-visible {
    outline: 2px solid var(--isis-current-mod);
    outline-offset: 2px;
}

.isis-projet-carte {
    border-collapse: separate;
    border-spacing: 2px;
    font-size: 0.75rem;
    font-variant-numeric: tabular-nums;
}

.isis-projet-carte th {
    padding: 0.25rem 0.5rem;
    color: var(--isis-text-muted);
    font-weight: 500;
    white-space: nowrap;
    text-align: center;
}

.isis-projet-carte .isis-projet-carte__nom {
    position: sticky;
    left: 0;
    z-index: 1;
    min-width: 12rem;
    background: var(--isis-surface);
    color: var(--isis-text);
    text-align: left;
}

.isis-projet-carte__case {
    min-width: 3rem;
    height: 1.75rem;
    border-radius: 3px;
    text-align: center;
    color: var(--isis-text);
}

.isis-projet-carte__total {
    padding: 0 0.5rem;
    text-align: right;
    white-space: nowrap;
}

/* Rampe plafonnée à 55 % : le chiffre reste en --isis-text lisible quelle que soit la couleur du module ;
   le dernier palier se distingue par un liseré plutôt que par une teinte pleine. */
.isis-projet-carte__case.is-l0 { background: var(--isis-surface-2); }
.isis-projet-carte__case.is-l1,
.isis-projet-legend__dot.is-l1 { background: color-mix(in srgb, var(--isis-current-mod) 12%, var(--isis-surface)); }
.isis-projet-carte__case.is-l2,
.isis-projet-legend__dot.is-l2 { background: color-mix(in srgb, var(--isis-current-mod) 24%, var(--isis-surface)); }
.isis-projet-carte__case.is-l3,
.isis-projet-legend__dot.is-l3 { background: color-mix(in srgb, var(--isis-current-mod) 38%, var(--isis-surface)); }
.isis-projet-carte__case.is-l4,
.isis-projet-legend__dot.is-l4 {
    background: color-mix(in srgb, var(--isis-current-mod) 55%, var(--isis-surface));
    box-shadow: inset 0 0 0 1px var(--isis-current-mod-strong);
}
.isis-projet-carte__case.is-l4 { font-weight: 600; }

.isis-projet-filtres {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem 1rem;
    margin-bottom: 0.75rem;
}

.isis-projet-filtres__select {
    width: min(26rem, 100%);
}

.isis-projet-gantt .isis-prev-gantt__bar {
    flex-wrap: wrap;
    align-items: center;
    justify-content: flex-start;
}

.isis-projet-gantt .isis-projet-legend {
    margin: 0 0 0 auto;
}

.isis-projet-row--sous > [role="cell"]:first-child {
    padding-left: 1.5rem;
}

.isis-projet-cell-libelle small,
.isis-projet-muted {
    color: var(--isis-text-muted);
    font-size: 0.8125rem;
}

.isis-projet-cell-libelle small {
    display: block;
}

.isis-projet-cell-avct {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.isis-projet-entete {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.isis-projet-entete__ligne {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.25rem 1.25rem;
    color: var(--isis-text-muted);
    font-size: 0.875rem;
}

.isis-projet-entete__ligne b {
    color: var(--isis-text);
    font-weight: 600;
}

.isis-projet-entete__description {
    margin: 0;
    max-width: 72ch;
    white-space: pre-line;
}

/* Volet latéral de la liste. */
.isis-projet-volet__badges {
    display: flex;
    flex-wrap: wrap;
    gap: 0.375rem;
}

.isis-projet-volet__kv {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: 0.25rem 0.75rem;
    margin: 0;
    font-size: 0.875rem;
}

.isis-projet-volet__kv dt {
    color: var(--isis-text-muted);
}

.isis-projet-volet__kv dd {
    margin: 0;
}

/* Barres de mesure (remplacent les cartes à chiffres). */
.isis-projet-bilan {
    display: flex;
    flex-direction: column;
    gap: 0.625rem;
}

.isis-projet-bilan__row {
    display: grid;
    grid-template-columns: minmax(130px, 200px) 1fr minmax(120px, 200px);
    align-items: center;
    gap: 0.75rem;
}

.isis-projet-bilan--volet .isis-projet-bilan__row {
    grid-template-columns: 1fr;
    gap: 0.25rem;
}

.isis-projet-bilan__k,
.isis-projet-bilan__v {
    font-size: 0.875rem;
}

.isis-projet-bilan__k small,
.isis-projet-bilan__v small {
    display: block;
    color: var(--isis-text-muted);
    font-size: 0.75rem;
}

.isis-projet-bilan__v {
    font-family: var(--isis-font-mono);
    font-variant-numeric: tabular-nums;
}

.isis-projet-bilan__v.is-warm { color: var(--isis-warning-text); }
.isis-projet-bilan__v.is-danger { color: var(--isis-danger-text); }
.isis-projet-bilan__v.is-success { color: var(--isis-success-text); }

.isis-projet-meter {
    position: relative;
    display: block;
    height: 0.625rem;
    overflow: visible;
    background: var(--isis-surface-2);
    border-radius: var(--isis-radius-sm);
}

.isis-projet-meter--mini {
    flex: 0 0 72px;
    height: 0.375rem;
}

.isis-projet-meter__fill,
.isis-projet-meter__hatch {
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    border-radius: var(--isis-radius-sm);
}

.isis-projet-meter__fill { background: var(--isis-current-mod); }
.isis-projet-meter__fill.is-success { background: var(--isis-success); }
.isis-projet-meter__fill.is-warning { background: var(--isis-warning); }
.isis-projet-meter__fill.is-danger { background: var(--isis-danger); }
.isis-projet-meter__fill.is-mod { background: var(--isis-current-mod); }
.isis-projet-meter__fill.is-neutral,
.isis-projet-meter__fill.is-unknown { background: var(--isis-text-muted); }
.isis-projet-meter__fill.is-done { background: var(--isis-info); }

.isis-projet-meter__hatch,
.isis-projet-legend__dot.is-hatch {
    background: repeating-linear-gradient(135deg,
        color-mix(in srgb, var(--isis-current-mod) 45%, var(--isis-surface)) 0 4px,
        transparent 4px 8px);
}

.isis-projet-meter__tick {
    position: absolute;
    top: -0.25rem;
    bottom: -0.25rem;
    width: 2px;
    margin-left: -1px;
    background: var(--isis-text);
}

.isis-projet-stack {
    display: flex;
    height: 0.625rem;
    overflow: hidden;
    background: var(--isis-surface-2);
    border-radius: var(--isis-radius-sm);
}

.isis-projet-stack__seg { height: 100%; }
.isis-projet-stack__seg.is-success { background: var(--isis-success); }
.isis-projet-stack__seg.is-warning { background: var(--isis-warning); }
.isis-projet-stack__seg.is-danger { background: var(--isis-danger); }
.isis-projet-stack__seg.is-done { background: var(--isis-info); }
.isis-projet-stack__seg.is-unknown,
.isis-projet-stack__seg.is-neutral { background: var(--isis-text-muted); }
.isis-projet-stack__seg.is-mod { background: var(--isis-current-mod); }
.isis-projet-stack__seg.is-cat-1,
.isis-projet-legend__dot.is-cat-1 { background: var(--isis-cat-1); }
.isis-projet-stack__seg.is-cat-2,
.isis-projet-legend__dot.is-cat-2 { background: var(--isis-cat-2); }
.isis-projet-stack__seg.is-cat-3,
.isis-projet-legend__dot.is-cat-3 { background: var(--isis-cat-3); }
.isis-projet-stack__seg.is-cat-4,
.isis-projet-legend__dot.is-cat-4 { background: var(--isis-cat-4); }
.isis-projet-stack__seg.is-cat-5,
.isis-projet-legend__dot.is-cat-5 { background: var(--isis-cat-5); }
.isis-projet-stack__seg.is-cat-6,
.isis-projet-legend__dot.is-cat-6 { background: var(--isis-cat-6); }
.isis-projet-stack__seg.is-cat-7,
.isis-projet-legend__dot.is-cat-7 { background: var(--isis-cat-7); }
.isis-projet-stack__seg.is-cat-8,
.isis-projet-legend__dot.is-cat-8 { background: var(--isis-cat-8); }

.isis-projet-legend {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem 1rem;
    margin: 0.5rem 0 0;
    padding: 0;
    list-style: none;
    color: var(--isis-text-muted);
    font-size: 0.75rem;
}

.isis-projet-legend > * {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
}

.isis-projet-legend__dot {
    display: inline-block;
    width: 0.625rem;
    height: 0.625rem;
    border-radius: 2px;
    background: var(--isis-current-mod);
}

.isis-projet-legend__dot.is-mod { background: var(--isis-current-mod); }
.isis-projet-legend__dot.is-empty { background: var(--isis-surface-2); border: 1px solid var(--isis-border); }
.isis-projet-legend__dot.is-success { background: var(--isis-success); }
.isis-projet-legend__dot.is-warning { background: var(--isis-warning); }
.isis-projet-legend__dot.is-danger { background: var(--isis-danger); }
.isis-projet-legend__dot.is-done { background: var(--isis-info); }
.isis-projet-legend__dot.is-unknown { background: var(--isis-text-muted); }

.isis-projet-legend__tick {
    display: inline-block;
    width: 2px;
    height: 0.75rem;
    background: var(--isis-text);
}

/* Onglet Synthèse. */
.isis-projet-synthese {
    display: flex;
    flex-direction: column;
    gap: 1.25rem;
}

.isis-projet-block {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    min-width: 0;
}

.isis-projet-block__h {
    margin: 0;
    font-size: 0.8125rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--isis-text-muted);
}

.isis-projet-cols {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
    gap: 1.25rem 2rem;
}

.isis-projet-alertes {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

.isis-projet-alertes > li {
    display: flex;
    align-items: flex-start;
    gap: 0.5rem;
    font-size: 0.875rem;
}

.isis-projet-hbar {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

.isis-projet-hbar > li {
    display: grid;
    grid-template-columns: minmax(90px, 140px) 1fr 52px;
    align-items: center;
    gap: 0.625rem;
    font-size: 0.875rem;
}

.isis-projet-hbar__k {
    overflow: hidden;
    font-family: var(--isis-font-mono);
    text-overflow: ellipsis;
    white-space: nowrap;
}

.isis-projet-hbar__v {
    text-align: right;
    font-family: var(--isis-font-mono);
    font-variant-numeric: tabular-nums;
}

.isis-projet-hbar__m {
    grid-column: 1 / -1;
    color: var(--isis-text-muted);
    font-size: 0.75rem;
}

.isis-projet-frise {
    position: relative;
    height: 1.5rem;
    margin: 0.25rem 0.5rem;
}

.isis-projet-frise__axis,
.isis-projet-frise__done {
    position: absolute;
    top: 50%;
    left: 0;
    height: 2px;
    margin-top: -1px;
}

.isis-projet-frise__axis { right: 0; background: var(--isis-border); }
.isis-projet-frise__done { background: var(--isis-current-mod); }

.isis-projet-frise__today {
    position: absolute;
    top: 0;
    bottom: 0;
    width: 2px;
    margin-left: -1px;
    background: var(--isis-text);
}

.isis-projet-frise__m {
    position: absolute;
    top: 50%;
    width: 0.625rem;
    height: 0.625rem;
    margin: -0.3125rem 0 0 -0.3125rem;
    background: var(--isis-surface);
    border: 2px solid var(--isis-text-muted);
    border-radius: 50%;
}

.isis-projet-frise__m.is-success { background: var(--isis-success); border-color: var(--isis-success); }
.isis-projet-frise__m.is-danger { border-color: var(--isis-danger); }
.isis-projet-frise__m.is-warning { border-color: var(--isis-warning); }
.isis-projet-frise__m.is-neutral { border-color: var(--isis-text-muted); }

.isis-projet-jalons {
    display: flex;
    flex-direction: column;
    gap: 0.375rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

.isis-projet-jalons > li {
    display: grid;
    grid-template-columns: 88px 1fr auto;
    align-items: baseline;
    gap: 0.625rem;
    font-size: 0.875rem;
}

.isis-projet-jalons__d {
    font-family: var(--isis-font-mono);
    font-variant-numeric: tabular-nums;
}

.isis-projet-jalons__l small {
    margin-left: 0.375rem;
    color: var(--isis-text-muted);
    font-family: var(--isis-font-mono);
}

.isis-projet-jalons__e {
    font-size: 0.75rem;
    color: var(--isis-text-muted);
}

.isis-projet-jalons__e.is-danger { color: var(--isis-danger-text); }
.isis-projet-jalons__e.is-success { color: var(--isis-success-text); }

/* EF-42 — dialogue de rattachement d'une commande à un projet. */
.isis-projet-rattacher {
    display: flex;
    margin: 0;
    padding: 0;
    list-style: none;
    flex-direction: column;
    max-height: 360px;
    overflow-y: auto;
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-sm);
}

.isis-projet-rattacher__item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    padding: 0.5rem 0.75rem;
    border-bottom: 1px solid var(--isis-border-soft);
}

.isis-projet-rattacher__item:last-child {
    border-bottom: none;
}

.isis-grid__col-mono {
    font-family: var(--isis-font-mono);
    font-variant-numeric: tabular-nums;
}

/* File de qualification des dossiers tiers (gescompta/dossiers-a-valider) — 3
   grilles distinctes, une par onglet (à valider / incomplets / validés). */
.isis-grid--dossiers-avalider .isis-grid__head,
.isis-grid--dossiers-avalider .isis-grid__row {
    display: grid;
    /* Six cellules : la colonne « Manques fiscaux » s'ajoute aux cinq d'origine, sans quoi la
       cellule Actions passait à la ligne sous chaque dossier, en-tête compris. */
    grid-template-columns:
        minmax(200px, 1.3fr)     /* Compte (raison sociale + code) */
        90px                     /* Pays */
        minmax(180px, 1.2fr)     /* Identifiants légaux */
        130px                    /* Ville */
        minmax(150px, 1fr)       /* Manques fiscaux */
        210px;                   /* Action (Valider) */
    align-items: start;
    min-width: 980px;
}

.isis-grid--dossiers-incomplets .isis-grid__head,
.isis-grid--dossiers-incomplets .isis-grid__row {
    display: grid;
    grid-template-columns:
        minmax(200px, 1fr)       /* Compte */
        minmax(260px, 2fr)       /* Manques (badges) */
        210px;                   /* Action (Signaler au commercial) */
    align-items: start;
    min-width: 740px;
}

.isis-grid--dossiers-valides .isis-grid__head,
.isis-grid--dossiers-valides .isis-grid__row {
    display: grid;
    grid-template-columns:
        minmax(220px, 1.4fr)     /* Compte */
        170px                    /* Validé le */
        170px;                   /* Action (Retirer le visa) */
    align-items: start;
    min-width: 620px;
}

/* Aucune action au clic sur ces lignes : seuls le lien du compte et le bouton d'action
   de la dernière colonne sont interactifs. On neutralise l'affordance héritée de
   .isis-grid__row (cursor: pointer), qui promettrait une sélection inexistante. */
.isis-grid--dossiers-avalider .isis-grid__row,
.isis-grid--dossiers-incomplets .isis-grid__row,
.isis-grid--dossiers-valides .isis-grid__row {
    cursor: default;
}

/* File d'arbitrage commerciale des déclarations client (gescom/declarations) —
   pendant commercial de dossiers-a-valider (gescompta), master + drawer détail. */
.isis-grid--declarations .isis-grid__head,
.isis-grid--declarations .isis-grid__row {
    display: grid;
    grid-template-columns:
        minmax(200px, 1.4fr)     /* Compte (raison sociale + code) */
        minmax(190px, 1fr)       /* Champs déclarés — libellés, pas un compte */
        170px                    /* Reçue le */
        130px;                   /* Attestation */
    align-items: start;
    min-width: 620px;
}

.isis-billing-liv {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.6rem;
    padding: 0.45rem 0;
    border-bottom: 1px solid var(--isis-border);
}

.isis-billing-liv:last-child {
    border-bottom: none;
}

.isis-billing-liv__id {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-variant-numeric: tabular-nums;
}

.isis-billing-liv__hint {
    font-size: 0.8rem;
    color: var(--isis-text-muted);
    margin-bottom: 0.5rem;
    line-height: 1.35;
}

/* ════════════════════════════════════════════════════════════════════════
   ISIS v2 « Instrument » — PROMU GLOBAL le 2026-06-04 dans :root (canvas cool
   near-white, accent pétrole, encre froide, hairlines, rayons resserrés).
   Le bloc de tokens scopé .isis-cmd-v2 a donc été supprimé (redondant).
   La classe .isis-cmd-v2 reste sur les 2 pages gesproj pour les quelques
   touches structurelles ci-dessous + la grille Pilotage / les sous-onglets.
   ════════════════════════════════════════════════════════════════════════ */

/* Mono tabulaire sur les valeurs KPI — signal « instrument » promu global. */
.isis-kpi-card__value {
    font-family: 'Geist Mono', ui-monospace, monospace;
    font-variant-numeric: tabular-nums;
    letter-spacing: -0.01em;
}
/* En-têtes de grille gesproj : tracking un peu plus large (scan de colonnes). */
.isis-cmd-v2 .isis-grid__head { letter-spacing: .05em; }

/* Sous-onglets — regroupement 13→6 onglets de la fiche commande (2026-06-04).
   Rendus sous la barre de 6 groupes ; n'apparaissent que pour les groupes
   multi-feuilles. Pilotés par _tab (la feuille), panneaux inchangés. */
.isis-subtabs {
    display: flex;
    gap: 0.25rem;
    flex-wrap: wrap;
    align-items: center;
    padding: 0.35rem 1rem 0.45rem;
    flex: 0 0 auto;
    border-bottom: 1px solid var(--isis-border);
    margin-bottom: 0.5rem;
}
/* Les 16 px sous la barre de groupes séparent les onglets du CONTENU ; quand une
   sous-barre suit, ils s'ajoutaient à son propre retrait et détachaient les deux niveaux. */
.isis-tabs:has(+ .isis-subtabs) {
    margin-bottom: 0;
}
.isis-subtab {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    border: 0;
    background: transparent;
    padding: 0.4rem 0.75rem;
    border-radius: var(--isis-radius-sm);
    font-size: 0.8125rem;
    font-weight: 500;
    color: var(--isis-text-muted);
    cursor: pointer;
    transition: background 0.15s ease, color 0.15s ease;
}
.isis-subtab:hover { color: var(--isis-text); background: var(--isis-surface-alt); }
.isis-subtab.is-active {
    background: var(--isis-current-mod-soft);
    /* --isis-current-mod (pas -strong) mesurait 4,24:1 sur --isis-current-mod-soft en gescom
       (13px, sous l'AA 4,5:1) — défaut préexistant du thème, révélé par la critique de
       conception de ce chantier. --isis-current-mod-strong recalcule 5,94:1 sur les mêmes
       couleurs réelles (cf. le commentaire de --isis-mod-active-mix dans :root). */
    color: var(--isis-current-mod-strong);
    font-weight: 600;
}
.isis-subtab:focus-visible { outline: 2px solid var(--isis-current-mod); outline-offset: 1px; }

/* Icônes d'onglets — global (2026-07-12, demande utilisateur).
   Le libellé d'un onglet fait 13px, mais RadzenIcon rendait son glyphe à la taille par défaut
   (--rz-icon-size, ~24px) : l'icône écrasait le texte sur les 10 fiches à onglets du produit.
   On la ramène à la mesure du libellé. Les icônes lisent --rz-icon-size via .rzi, pas font-size
   (cf. note ligne 271) — d'où le ciblage explicite de .rzi. */
.isis-tab .rzi,
.isis-subtab .rzi {
    font-size: 16px;
    width: 16px;
    height: 16px;
    line-height: 1;
}

/* Pastilles de compteur des onglets de la fiche devis (refonte 2026-09-21). Le nombre visible
   est aria-hidden : le nom accessible vient d'un .isis-sr-only accolé au libellé
   (« Participants, 2 »). Contrastes mesurés contre :root — clair / sombre : texte atténué sur
   --isis-surface-alt 6,09 / 6,15:1 ; « à décider », --isis-text sur --isis-warning-soft
   16,0 / 12,6:1 (la teinte d'alerte passe par le fond et le bord, pas par le texte). */
.isis-tab-pill {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 1.25rem;
    padding: 0 0.4rem;
    border: 1px solid transparent;
    border-radius: var(--isis-radius-pill);
    background: var(--isis-surface-alt);
    color: var(--isis-text-muted);
    font-size: 0.6875rem;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    line-height: 1rem;
}
.isis-tab:hover .isis-tab-pill,
.isis-tab.is-active .isis-tab-pill,
.isis-subtab:hover .isis-tab-pill,
.isis-subtab.is-active .isis-tab-pill {
    background: var(--isis-surface);
    color: var(--isis-text);
}
.isis-tab-pill--decide,
.isis-tab:hover .isis-tab-pill--decide,
.isis-tab.is-active .isis-tab-pill--decide,
.isis-subtab:hover .isis-tab-pill--decide,
.isis-subtab.is-active .isis-tab-pill--decide {
    background: var(--isis-warning-soft);
    border-color: var(--isis-warning);
    color: var(--isis-text);
}

/* Panneaux Suivi et Dossier de la fiche devis, pleine largeur depuis le retrait du volet
   latéral (2026-09-21) : colonne de lecture bornée, comme les formulaires linéaires. */
.isis-devis-panel-column { max-width: 720px; }
/* Une section qui porte un tableau prend toute la largeur : à 720 px le verdict de TVA laissait
   la moitié de l'écran vide et repliait taux et mentions sur plusieurs lignes. Le texte, lui,
   garde sa largeur de lecture. */
.isis-devis-panel-column--wide { max-width: none; }
.isis-devis-panel-column--wide > p { max-width: 720px; }
.isis-devis-panel-column + .isis-devis-panel-column { margin-top: 1.5rem; }
.isis-devis-approbations { margin-bottom: 1.5rem; }
/* Le fil de commentaires occupe la hauteur du panneau : liste qui défile, saisie en bas. */
.isis-devis-panel-column--fill { height: 100%; }
.isis-devis-panel-column__empty {
    margin: 0;
    font-size: 0.8125rem;
    line-height: 1.4;
    color: var(--isis-text-muted);
}
.isis-devis-panel-column__actions {
    display: flex;
    justify-content: flex-end;
}
.isis-share-list__buttons {
    display: inline-flex;
    gap: 0.25rem;
    flex-shrink: 0;
}
/* La règle globale .isis-share-list__item (partage de commande gesproj) pose un bord à la
   couleur gesproj : neutre ici. */
.isis-devis-panel-column .isis-share-list__item { border-color: var(--isis-border); }

/* Toolbar fiche — indicateur d'étape sans action (ex-style inline opacity/cursor). */
.isis-rich-toolbar__btn--hint { opacity: 0.75; cursor: default; }
.isis-rich-toolbar__btn--hint:hover { border-color: transparent; background: transparent; color: var(--isis-text-soft); box-shadow: none; }

/* Toolbar fiche — menu « Plus » (refonte 2026-06-04) : lignes d'actions dans le
   panneau dropdown réutilisé (.isis-toolbar-dropdown__panel). */
.isis-toolbar-menu { display: flex; flex-direction: column; gap: 2px; min-width: 230px; }
.isis-toolbar-menu__item {
    display: flex;
    align-items: center;
    gap: 0.55rem;
    width: 100%;
    height: 34px;
    padding: 0 0.6rem;
    border: 0;
    background: transparent;
    border-radius: var(--isis-radius-sm);
    font-size: 0.8125rem;
    font-weight: 500;
    color: var(--isis-text);
    text-align: left;
    cursor: pointer;
    transition: background 0.15s ease, color 0.15s ease;
}
.isis-toolbar-menu__item:hover { background: var(--isis-surface-alt); }
/* Une entrée de menu peut être un lien de téléchargement (EF-49) : même rendu qu'un bouton. */
a.isis-toolbar-menu__item { text-decoration: none; }
.isis-toolbar-menu__item:focus-visible { outline: 2px solid var(--isis-current-mod); outline-offset: -1px; }
.isis-toolbar-menu__item:disabled { opacity: 0.5; cursor: default; }
/* aria-disabled, pas seulement :disabled — même convention que .isis-grid__action-btn
   (plus haut dans cette feuille) : l'entrée reste atteignable au clavier avec sa raison
   au title, plutôt que sortie de l'ordre de tabulation par l'attribut disabled natif.
   Sans cette règle, "Paliers de prix" sur une ligne où ce n'est pas applicable restait
   pleinement opaque et avait l'air cliquable (revue de code du 2026-09-15). */
.isis-toolbar-menu__item[aria-disabled="true"] { opacity: 0.5; cursor: default; }
.isis-toolbar-menu__item[aria-disabled="true"]:hover { background: transparent; }
.isis-toolbar-menu__item--danger { color: var(--isis-danger); }
.isis-toolbar-menu__item--danger:hover { background: var(--isis-danger-soft); }
.isis-toolbar-menu__sep { border: 0; border-top: 1px solid var(--isis-border); margin: 0.35rem 0; }
.isis-toolbar-menu__group-label {
    padding: 0.25rem 0.55rem 0.15rem;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.02em;
    text-transform: uppercase;
    color: var(--isis-text-muted);
}
.isis-toolbar-menu__readonly {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.3rem;
    padding: 0.2rem 0.55rem 0.35rem;
}
.isis-toolbar-menu__hint { font-size: var(--isis-fs-xs, 0.7rem); color: var(--isis-text-muted); }
/* Menu « réglages de ligne » du tableur des lignes de devis : intitulé de groupe suivi de
   son mode (« s'applique au clic »), entrées qui ouvrent une fenêtre avec leur état à droite. */
.isis-toolbar-menu__group-label--split { display: flex; justify-content: space-between; align-items: baseline; gap: 0.5rem; }
.isis-toolbar-menu__group-note { font-size: var(--isis-fs-xs); font-weight: 400; text-transform: none; letter-spacing: 0; color: var(--isis-text-soft); }
.isis-toolbar-menu__label { flex: 1; min-width: 0; }
.isis-toolbar-menu__state { font-size: var(--isis-fs-sm, 0.75rem); font-weight: 400; color: var(--isis-text-muted); white-space: nowrap; }
.isis-toolbar-menu__chev { font-size: 16px; color: var(--isis-text-soft); margin-right: -0.2rem; }
/* Sous-menu « Insérer au-dessus / en dessous » du menu de réglages de ligne : en fixed, sinon
   le panneau parent, qui défile, le rognerait. --dd-x / --dd-y viennent d'isisAnchorRight. */
.isis-line-insert { display: flex; flex-direction: column; gap: 2px; }
.isis-toolbar-menu__item.is-sub-open { background: var(--isis-surface-alt); }
.isis-toolbar-dropdown__panel--submenu {
    position: fixed;
    top: min(var(--dd-y, 0px), calc(100vh - 230px));
    left: var(--dd-x, 8px);
    right: auto;
    width: var(--dd-w, 220px);
    min-width: 0;
    box-sizing: border-box;
    padding: 0.4rem;
    z-index: 932;
}
.isis-toolbar-dropdown__panel--submenu .isis-toolbar-menu { min-width: 0; }
.isis-toolbar-menu__alert {
    display: flex;
    gap: 0.4rem;
    align-items: flex-start;
    margin: 0.15rem 0.55rem 0.3rem;
    padding: 0.35rem 0.5rem;
    border-radius: var(--isis-radius-sm);
    background: var(--isis-warning-soft);
    color: var(--isis-warning-text);
    font-size: var(--isis-fs-sm, 0.75rem);
    line-height: 1.35;
}

/* ── Polices d'assurance — onglet « Biens couverts » (migration 0353) ─────── */
.isis-police-biens { display: flex; flex-direction: column; gap: 0.85rem; }
.isis-police-summary {
    display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 0.6rem;
    padding: 0.85rem 1rem; border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius); background: var(--isis-surface-alt);
}
.isis-police-summary__label { font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.03em; color: var(--isis-text-muted); }
.isis-police-summary__value { font-size: 1.05rem; font-weight: 600; color: var(--isis-text); margin-top: 0.15rem; font-variant-numeric: tabular-nums; }
.isis-police-summary__value.is-ok { color: var(--isis-success); }
.isis-police-summary__value.is-warning { color: var(--isis-warning); }
.isis-police-summary__value.is-danger { color: var(--isis-danger); }
.isis-police-summary__hint { font-size: 0.72rem; color: var(--isis-text-muted); margin-top: 0.1rem; }
.isis-police-biens__toolbar { display: flex; gap: 0.5rem; flex-wrap: wrap; }
.isis-grid--police-biens .isis-grid__head,
.isis-grid--police-biens .isis-grid__row {
    grid-template-columns: 64px minmax(180px, 1.4fr) 150px 150px 110px 90px;
}
.isis-module-tag {
    display: inline-block; font-size: 0.68rem; font-weight: 700; letter-spacing: 0.04em;
    padding: 0.1rem 0.4rem; border-radius: var(--isis-radius-sm);
    background: var(--isis-surface-alt); color: var(--isis-text-muted); border: 1px solid var(--isis-border);
}

/* ── Badge « Couverture d'assurance » sur fiche équipement (migration 0353) ── */
.isis-assurance-badge {
    border: 1px solid var(--isis-border); border-radius: var(--isis-radius);
    background: var(--isis-surface); padding: 0.7rem 0.9rem; margin-bottom: 0.85rem;
}
.isis-assurance-badge__head {
    display: flex; align-items: center; gap: 0.4rem;
    font-size: 0.78rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.03em;
    color: var(--isis-text-muted); margin-bottom: 0.4rem;
}
.isis-assurance-badge__head .rz-icon, .isis-assurance-badge__head i { font-size: 18px; color: var(--isis-success); }
.isis-assurance-badge__empty { font-size: 0.82rem; color: var(--isis-text-muted); }
.isis-assurance-badge__list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.3rem; }
.isis-assurance-badge__row {
    display: grid; grid-template-columns: minmax(70px, auto) 1fr auto auto; gap: 0.6rem; align-items: center;
    padding: 0.35rem 0.5rem; border-radius: var(--isis-radius-sm); cursor: pointer;
    border: 1px solid transparent;
}
.isis-assurance-badge__row:hover { background: var(--isis-surface-alt); border-color: var(--isis-border); }
.isis-assurance-badge__num { font-weight: 600; font-variant-numeric: tabular-nums; color: var(--isis-text); }
.isis-assurance-badge__title { color: var(--isis-text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.isis-assurance-badge__fin { font-size: 0.78rem; color: var(--isis-text-muted); }
.isis-assurance-badge__prime { font-size: 0.82rem; font-variant-numeric: tabular-nums; color: var(--isis-text-muted); }

/* ── Polish audit assurance (alignements colonnes + focus badge + utilitaire) ── */
.isis-grid--police-biens .isis-grid__head > div:nth-child(3),
.isis-grid--police-biens .isis-grid__head > div:nth-child(4),
.isis-grid--police-biens .isis-grid__head > div:nth-child(6),
.isis-grid--police-biens .isis-grid__row > div:nth-child(3),
.isis-grid--police-biens .isis-grid__row > div:nth-child(4),
.isis-grid--police-biens .isis-grid__row > div:nth-child(6) {
    text-align: right;
    font-variant-numeric: tabular-nums;
}
.isis-assurance-badge__row:focus-visible {
    outline: 2px solid var(--isis-current-mod, var(--isis-accent));
    outline-offset: -2px;
    background: var(--isis-surface-alt);
}
.isis-mb-sm { margin-bottom: 0.75rem; }

/* ── File « À facturer » — bandeau financier + badge maturité (Lot 1) ── */
.isis-billing-money {
    display: flex; align-items: center; flex-wrap: wrap; gap: 0.85rem;
    padding: 0.5rem 0.85rem;
    background: var(--isis-surface-alt);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius);
    margin-bottom: 0.5rem;
}
.isis-billing-money__label { display: flex; align-items: center; gap: 0.4rem; font-size: 0.8rem; font-weight: 600; color: var(--isis-text-muted); }
.isis-billing-money__amount { font-variant-numeric: tabular-nums; font-size: 1.05rem; font-weight: 700; color: var(--isis-text); }
.isis-billing-money__devise { font-size: 0.72rem; font-weight: 600; color: var(--isis-text-muted); margin-left: 2px; }

/* Badge maturité (1 voyant par ligne) */
.isis-mat-badge { display: inline-flex; align-items: center; gap: 0.3rem; font-size: 0.72rem; font-weight: 600; padding: 1px 7px; border-radius: 999px; white-space: nowrap; }
.isis-mat-badge::before { content: ""; width: 7px; height: 7px; border-radius: 50%; box-shadow: inset 0 0 0 1px rgba(0,0,0,0.18); }
.isis-mat-badge--ok { background: color-mix(in srgb, var(--isis-success) 14%, var(--isis-surface)); color: var(--isis-success); }
.isis-mat-badge--ok::before { background: var(--isis-success); }
.isis-mat-badge--warn { background: color-mix(in srgb, var(--isis-warning) 16%, var(--isis-surface)); color: var(--isis-warning); }
.isis-mat-badge--warn::before { background: var(--isis-warning); }
.isis-mat-badge--blocked { background: color-mix(in srgb, var(--isis-danger) 12%, var(--isis-surface)); color: var(--isis-danger); }
.isis-mat-badge--blocked::before { background: var(--isis-danger); }

/* Retard d'échéance */
.isis-billing-overdue { color: var(--isis-danger); font-weight: 600; }
.isis-billing-soon { color: var(--isis-warning); font-weight: 600; }
.isis-billing-cell-head { display: flex; align-items: center; gap: 0.45rem; flex-wrap: wrap; }

/* File « À facturer » — filtres avancés + tri (Lot 3) */
.isis-filter-bar--adv { margin-top: -0.15rem; gap: 0.5rem; flex-wrap: wrap; align-items: center; }
.isis-filter-select { height: 30px; border: 1px solid var(--isis-border); border-radius: var(--isis-radius-sm, 6px); background: var(--isis-surface); color: var(--isis-text); font-size: 0.82rem; padding: 0 0.5rem; max-width: 210px; }
.isis-filter-bar__sort { display: inline-flex; align-items: center; gap: 0.25rem; flex-wrap: wrap; }
.isis-filter-bar__sort-label { font-size: 0.78rem; font-weight: 600; color: var(--isis-text-muted); margin-right: 0.15rem; }
.isis-chip-sm { font-size: 0.76rem; font-weight: 600; padding: 2px 9px; border-radius: 999px; border: 1px solid var(--isis-border); background: var(--isis-surface); color: var(--isis-text-muted); cursor: pointer; }
.isis-chip-sm:hover { background: var(--isis-surface-alt); }
.isis-chip-sm.is-active { background: var(--isis-current-mod, var(--isis-accent)); color: #fff; border-color: transparent; }

/* File « À facturer » — barre de facturation en lot (Lot 2) */
.isis-batch-bar { display: flex; align-items: center; gap: 0.75rem; flex-wrap: wrap; padding: 0.5rem 0.85rem; margin-bottom: 0.4rem; background: color-mix(in srgb, var(--isis-mod-gescompta, #6d28d9) 8%, var(--isis-surface)); border: 1px solid var(--isis-border); border-radius: var(--isis-radius); }
.isis-batch-bar__count { font-weight: 700; }
.isis-grid__col-check { width: 34px; display: flex; align-items: center; justify-content: center; }

/* ── Sinistres transverses — grille (gesst_sinistre, V2 assurance 0354) ────── */
.isis-grid--sinistre .isis-grid__head,
.isis-grid--sinistre .isis-grid__row {
    grid-template-columns: 110px 130px minmax(140px, 1.4fr) 110px 120px 90px;
}
.isis-grid--sinistre.with-conducteur .isis-grid__head,
.isis-grid--sinistre.with-conducteur .isis-grid__row {
    grid-template-columns: 100px 120px minmax(140px, 1fr) minmax(120px, 1fr) 110px 110px 90px;
}
.isis-grid--sinistre .isis-grid__head > div:nth-last-child(2),
.isis-grid--sinistre .isis-grid__row > div:nth-last-child(2) { font-variant-numeric: tabular-nums; }
.isis-batch-bar__hint { font-size: 0.8rem; color: var(--isis-text-muted); }

/* ── Quittances / échéancier de prime (V2 assurance 0355) ─────────────────── */
.isis-grid--quittance .isis-grid__head,
.isis-grid--quittance .isis-grid__row {
    grid-template-columns: minmax(110px, 1fr) 160px 140px 100px 120px 110px;
}
.isis-grid--quittance .isis-grid__head > div:nth-child(3),
.isis-grid--quittance .isis-grid__row > div:nth-child(3) { font-variant-numeric: tabular-nums; }

/* ── Onglet Communication (marché & commande) ──────────────────────────────
   Deux colonnes (Client / Entreprise) sous une bande de lecture : compteurs,
   couverture par catégorie, écart marché↔commandes. */
.isis-comm-tab { display: flex; flex-direction: column; gap: 1rem; }
.isis-comm-tab__alerte { color: var(--isis-warning); font-weight: 600; }

/* Couverture : une puce par catégorie ; celle à zéro se signale, c'est tout
   l'intérêt de la bande — une liste de copies ne montre jamais ce qui MANQUE. */
.isis-comm-couverture { display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem; }
.isis-comm-couverture__legende {
    font-size: 0.78rem; line-height: 1.3;
    color: var(--isis-text-muted);
    margin-right: 0.2rem;
}
.isis-comm-couverture__chip {
    display: inline-flex; align-items: center; gap: 0.3rem;
    /* La base .isis-chip porte cursor:pointer et un :hover — une affordance que rien
       n'honore sur une puce sans geste. On la neutralise ICI plutôt que par la classe
       partagée .is-static, qui repeindrait le fond en surface et effacerait du même
       coup le signal ambre d'une catégorie à zéro. */
    cursor: default; pointer-events: none;
    background: var(--isis-current-mod-soft);
    color: color-mix(in srgb, var(--isis-current-mod) 72%, var(--isis-text));
    border: 1px solid color-mix(in srgb, var(--isis-current-mod) 20%, transparent);
}
.isis-comm-couverture__chip.is-vide {
    background: var(--isis-warning-soft);
    color: color-mix(in srgb, var(--isis-warning) 72%, var(--isis-text));
    border-color: color-mix(in srgb, var(--isis-warning) 32%, transparent);
}
.isis-comm-couverture__chip .isis-chip__count {
    background: color-mix(in srgb, currentColor 14%, transparent);
    color: inherit;
}

/* Écart marché↔commandes : une ligne de constat, pas un bandeau d'alerte —
   l'information est utile même quand tout concorde. */
.isis-comm-ecart {
    display: flex; align-items: center; gap: 0.55rem; flex-wrap: wrap;
    padding: 0.55rem 0.8rem; border-radius: var(--isis-radius-sm);
    font-size: 0.85rem; line-height: 1.4;
    background: var(--isis-surface-alt);
    border: 1px solid var(--isis-border);
    color: var(--isis-text-muted);
}
.isis-comm-ecart strong { color: var(--isis-text); }
.isis-comm-ecart.is-ecart {
    background: var(--isis-warning-soft);
    border-color: color-mix(in srgb, var(--isis-warning) 32%, transparent);
    color: color-mix(in srgb, var(--isis-warning) 62%, var(--isis-text));
}
.isis-comm-ecart.is-ecart strong { color: inherit; }
.isis-comm-ecart__btn { margin-left: auto; }

/* Avertissement en ligne (adresse manquante, conséquence d'un geste). */
.isis-comm-warn {
    display: flex; align-items: flex-start; gap: 0.45rem;
    padding: 0.45rem 0.6rem; border-radius: var(--isis-radius-sm);
    font-size: 0.78rem; line-height: 1.4;
    background: var(--isis-warning-soft);
    border: 1px solid color-mix(in srgb, var(--isis-warning) 28%, transparent);
    color: color-mix(in srgb, var(--isis-warning) 62%, var(--isis-text));
}
.isis-comm-warn--info {
    background: var(--isis-info-soft);
    border-color: color-mix(in srgb, var(--isis-info) 28%, transparent);
    color: color-mix(in srgb, var(--isis-info) 62%, var(--isis-text));
    margin-bottom: 0.9rem;
}
.isis-comm-warn .rzi, .isis-comm-warn i { flex: 0 0 auto; margin-top: 0.05rem; }

/* Deux colonnes : Client et Entreprise se lisent côte à côte, la comparaison
   « qui a le client, qui a l'entreprise » étant le geste courant. */
.isis-comm-cols { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; align-items: start; }

.isis-comm-section {
    border-radius: var(--isis-radius-lg);
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    box-shadow: var(--isis-elevation-1);
    overflow: hidden;
}
.isis-comm-section__title {
    margin: 0; padding: 0.7rem 1.1rem;
    font-size: 0.98rem; font-weight: 600; color: var(--isis-text);
    display: flex; align-items: center; gap: 0.6rem;
    background: color-mix(in srgb, var(--isis-current-mod) 7%, var(--isis-surface));
    border-bottom: 1px solid var(--isis-border);
}
.isis-comm-section__icon {
    display: inline-flex; align-items: center; justify-content: center;
    width: 28px; height: 28px; border-radius: 50%;
    background: var(--isis-current-mod-soft);
    color: var(--isis-current-mod);
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--isis-current-mod) 20%, transparent);
}
.isis-comm-section__icon .rzi, .isis-comm-section__icon i { font-size: 17px; }

/* Empilé : les deux colonnes de l'onglet portent déjà la mise en regard. */
.isis-comm-section__body { display: flex; flex-direction: column; gap: 1rem; padding: 1.1rem; }

.isis-comm-principal {
    display: flex; flex-direction: column; gap: 0.4rem;
    background: color-mix(in srgb, var(--isis-current-mod) 5%, var(--isis-surface));
    border: 1px solid color-mix(in srgb, var(--isis-current-mod) 16%, var(--isis-border));
    border-radius: var(--isis-radius); padding: 0.85rem;
}
.isis-comm-principal .label {
    font-size: 0.74rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.03em;
    color: color-mix(in srgb, var(--isis-current-mod) 65%, var(--isis-text-muted));
}
.isis-comm-principal__email { font-size: 0.8rem; color: var(--isis-text-muted); word-break: break-all; }
.isis-comm-principal__actions { display: flex; flex-wrap: wrap; gap: 0.4rem; margin-top: 0.15rem; }
/* Légendes d'aide : la règle générique .helper n'existe que sous .isis-form-linear —
   ces panneaux n'en font pas partie, d'où le style par défaut (bug visuel) sans cette règle. */
.isis-comm-principal .helper {
    font-size: 0.7rem; color: var(--isis-text-muted); margin-top: 0.2rem; line-height: 1.35;
}

.isis-comm-copies { display: flex; flex-direction: column; gap: 0.5rem; }
.isis-comm-copies__head { display: flex; align-items: center; justify-content: space-between; gap: 0.6rem; }
.isis-comm-copies__title { font-size: 0.74rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.03em; color: var(--isis-text-muted); }
.isis-comm-copies__empty {
    font-size: 0.85rem; color: var(--isis-text-muted); font-style: italic;
    padding: 0.7rem 0.8rem; background: var(--isis-surface-alt); border-radius: var(--isis-radius-sm);
}

/* Ligne personne : la colonne des catégories passe SOUS l'identité en colonne
   étroite — deux sections côte à côte ne laissent pas la place d'une grille à cinq. */
.isis-comm-person {
    display: grid; grid-template-columns: auto minmax(0, 1fr) auto auto;
    grid-template-areas: "avatar id edit remove" ". cats cats cats";
    gap: 0.35rem 0.65rem; align-items: center;
    padding: 0.5rem 0.7rem; border-radius: var(--isis-radius-sm);
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    box-shadow: var(--isis-elevation-1);
    transition: box-shadow 0.15s ease;
}
.isis-comm-person:hover { box-shadow: var(--isis-elevation-hover); }
.isis-comm-person__avatar {
    grid-area: avatar;
    display: inline-flex; align-items: center; justify-content: center;
    width: 30px; height: 30px; border-radius: 50%;
    font-size: 0.72rem; font-weight: 700; letter-spacing: 0.02em;
    background: var(--isis-current-mod-soft);
    color: color-mix(in srgb, var(--isis-current-mod) 78%, var(--isis-text));
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--isis-current-mod) 18%, transparent);
}
.isis-comm-person__id { grid-area: id; display: flex; flex-direction: column; line-height: 1.25; min-width: 0; }
.isis-comm-person__name { font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.isis-comm-person__email { color: var(--isis-text-muted); font-size: 0.8rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.isis-comm-person__email--absent {
    display: inline-flex; align-items: center; gap: 0.25rem;
    color: color-mix(in srgb, var(--isis-warning) 68%, var(--isis-text));
}
.isis-comm-person__cats { grid-area: cats; display: flex; flex-wrap: wrap; gap: 0.3rem; }
.isis-comm-person__cats .isis-chip {
    background: var(--isis-current-mod-soft);
    color: color-mix(in srgb, var(--isis-current-mod) 72%, var(--isis-text));
    border: 1px solid color-mix(in srgb, var(--isis-current-mod) 20%, transparent);
}
.isis-comm-person > .isis-grid__action-btn:nth-last-of-type(2) { grid-area: edit; }
.isis-comm-person > .isis-grid__action-btn:last-of-type { grid-area: remove; }

@media (max-width: 1100px) { .isis-comm-cols { grid-template-columns: 1fr; } }

/* ───────────────────────── gesqhse — risques & matrice de criticité ───────────────────────── */
.isis-mono { font-family: var(--isis-font-mono, 'Geist Mono', monospace); font-variant-numeric: tabular-nums; }

/* Élargi le 2026-09-05 : cinq des sept en-têtes portent désormais un bouton de tri et/ou
   un entonnoir, qui prennent de la place à côté du libellé. Aux anciennes largeurs le
   libellé « CRITICITÉ » et sa flèche se chevauchaient, et l'entonnoir de « Revue »
   débordait sur « Source ». Sept pistes pour sept cellules d'en-tête — le configurateur de
   colonnes exige l'égalité (DESIGN.md § Grilles). */
.isis-grid--gesqhse-risque .isis-grid__head,
.isis-grid--gesqhse-risque .isis-grid__row {
    grid-template-columns: 120px 165px minmax(200px, 1.4fr) 165px 140px 150px 150px;
    min-width: 1090px;
}

.isis-crit-badge {
    display: inline-flex; align-items: center; gap: 0.3rem;
    padding: 0.1rem 0.5rem; border-radius: var(--isis-radius-pill, 999px);
    font-size: 0.78rem; font-weight: 600; font-variant-numeric: tabular-nums;
    border: 1px solid transparent; white-space: nowrap;
}
/* L'encre des quatre bandes mêle 18 % de --isis-text à la couleur sémantique. Sans ce
   mélange, « 12 · Élevé » mesurait 4,03:1 sur son propre fond en thème clair — sous l'AA de
   4,5 pour du texte de 12,5 px. Le mélange fonctionne dans les DEUX thèmes parce que
   --isis-text s'inverse avec eux : il assombrit en clair, il éclaircit en sombre. Patron déjà
   en service ailleurs dans cette feuille (cf. le color-mix sur --isis-danger, l. ~3692). */
.isis-crit-badge.is-ok      { background: color-mix(in srgb, var(--isis-success) 14%, var(--isis-surface)); color: color-mix(in srgb, var(--isis-success) 82%, var(--isis-text)); border-color: color-mix(in srgb, var(--isis-success) 30%, transparent); }
/* « Moyen » prenait --isis-accent, c'est-à-dire la couleur de MARQUE du tenant, pour dire un
   niveau de GRAVITÉ. Deux conséquences : la bande changeait de sens d'un client à l'autre, et
   en thème sombre elle tombait à 1,29:1 — illisible — parce que BrandSync émettait alors le
   même accent dans les deux thèmes (corrigé le 2026-09-22 ; le motif SÉMANTIQUE reste). Les trois
   autres bandes utilisaient déjà des tokens SÉMANTIQUES, correctement inversés en sombre ;
   celle-ci les rejoint. Mesuré au navigateur le 2026-09-05 : 1,29:1 avant, cf. doc module. */
.isis-crit-badge.is-pending { background: color-mix(in srgb, var(--isis-info) 12%, var(--isis-surface));  color: color-mix(in srgb, var(--isis-info) 82%, var(--isis-text));  border-color: color-mix(in srgb, var(--isis-info) 28%, transparent); }
.isis-crit-badge.is-warning { background: color-mix(in srgb, var(--isis-warning) 16%, var(--isis-surface)); color: color-mix(in srgb, var(--isis-warning) 82%, var(--isis-text)); border-color: color-mix(in srgb, var(--isis-warning) 34%, transparent); }
.isis-crit-badge.is-danger  { background: color-mix(in srgb, var(--isis-danger) 14%, var(--isis-surface));  color: color-mix(in srgb, var(--isis-danger) 82%, var(--isis-text));  border-color: color-mix(in srgb, var(--isis-danger) 32%, transparent); }
.isis-crit-badge.is-draft   { background: var(--isis-surface-alt); color: var(--isis-text-muted); }

/* Matrice cliquable probabilité × impact */
.isis-matrice-grid {
    display: grid; grid-template-columns: auto repeat(5, minmax(44px, 1fr));
    gap: 4px; margin: 0.25rem 0 0.5rem;
    max-width: 540px; /* sinon les cellules aspect-ratio 1/1 deviennent d'énormes carrés sur une page pleine largeur */
}
.isis-matrice-grid__rowlabel,
.isis-matrice-grid__collabel { font-size: 0.72rem; color: var(--isis-text-muted); display: flex; align-items: center; }
.isis-matrice-grid__rowlabel { justify-content: flex-end; padding-right: 0.4rem; text-align: right; }
.isis-matrice-grid__collabel { justify-content: center; text-align: center; padding-top: 0.2rem; }
.isis-matrice-cell {
    aspect-ratio: 1 / 1; min-height: 38px;
    border: 1px solid var(--isis-border); border-radius: var(--isis-radius-sm, 5px);
    font-size: 0.82rem; font-weight: 600; font-variant-numeric: tabular-nums;
    color: var(--isis-text); cursor: pointer;
    display: flex; align-items: center; justify-content: center;
    transition: transform 0.08s ease, box-shadow 0.08s ease;
}
.isis-matrice-cell:hover { transform: scale(1.04); }
.isis-matrice-cell:focus-visible { outline: 2px solid var(--isis-current-mod, var(--isis-accent)); outline-offset: 1px; }
.isis-matrice-cell.is-selected { box-shadow: 0 0 0 2px var(--isis-current-mod, var(--isis-accent)); border-color: var(--isis-current-mod, var(--isis-accent)); }
.isis-matrice-result { display: flex; align-items: center; gap: 0.6rem; margin-top: 0.35rem; font-size: 0.85rem; }

.isis-grid--gesqhse-action .isis-grid__head,
.isis-grid--gesqhse-action .isis-grid__row {
    grid-template-columns: minmax(260px, 1fr) 130px 130px 100px;
}
/* Élargi le 2026-09-05 : quatre des cinq en-têtes portent un bouton de tri ou un entonnoir. */
.isis-grid--gesqhse-categorie .isis-grid__head,
.isis-grid--gesqhse-categorie .isis-grid__row {
    grid-template-columns: minmax(220px, 1.4fr) 160px 120px 150px 100px;
}
/* SMQSER (lot A1) — sans ces modificateurs, les grilles retombent sur le gabarit
   générique à 8 colonnes de la page Tiers : le libellé, contenu principal de la ligne,
   atterrit dans une piste de 32 px prévue pour une pastille. Un écran ne « paraît » pas
   cassé, il l'est colonne par colonne. */
/* Constats de durée du travail — la page d'analyse est devenue une liste (2026-09-05).
   Six pistes pour six cellules d'en-tête : le configurateur de colonnes exige l'égalité
   stricte (DESIGN.md, section Grilles), et ni repeat() ni var() n'y sont lisibles. Quatre
   des six en-têtes portent un bouton de tri ou un entonnoir, d'où des pistes larges. */
.isis-grid--gesqhse-constat .isis-grid__head,
.isis-grid--gesqhse-constat .isis-grid__row {
    grid-template-columns: minmax(240px, 1.7fr) 190px 150px 150px 130px 155px;
    min-width: 1015px;
}
/* Élargi le 2026-09-05 : cinq des six en-têtes portent désormais un bouton de tri et/ou un
   entonnoir, qui prennent de la place à côté du libellé. Six pistes pour six cellules
   d'en-tête — le configurateur de colonnes exige l'égalité (DESIGN.md § Grilles). */
.isis-grid--gesqhse-capa .isis-grid__head,
.isis-grid--gesqhse-capa .isis-grid__row {
    grid-template-columns: minmax(220px, 1.6fr) 140px 165px 150px 150px 160px;
    min-width: 985px;
}
/* Élargi le 2026-09-05 : quatre des six en-têtes portent un bouton de tri et/ou un entonnoir,
   qui prennent de la place à côté du libellé. Six pistes pour six cellules d'en-tête — le
   configurateur de colonnes exige l'égalité (DESIGN.md § Grilles). */
.isis-grid--gesqhse-processus .isis-grid__head,
.isis-grid--gesqhse-processus .isis-grid__row {
    grid-template-columns: minmax(200px, 1.3fr) 140px minmax(150px, 1fr) 120px 140px 110px;
    min-width: 860px;
}
/* Élargi le 2026-09-05 : quatre des cinq en-têtes portent un bouton de tri ou un entonnoir.
   Cinq pistes pour cinq cellules d'en-tête (DESIGN.md § Grilles). */
.isis-grid--gesqhse-famille .isis-grid__head,
.isis-grid--gesqhse-famille .isis-grid__row {
    grid-template-columns: minmax(220px, 1.4fr) 160px 120px 140px 110px;
    min-width: 750px;
}
/* Une entrée suspendue s'atténue, mais l'information ne repose jamais sur cette seule
   atténuation : la ligne porte aussi un badge « Suspendu » (WCAG 1.4.1). */
.isis-grid--gesqhse-processus .isis-grid__row.is-inactive,
.isis-grid--gesqhse-famille .isis-grid__row.is-inactive {
    opacity: 0.6;
}

/* Titre d'un bloc au sein d'une carte de détail — repris du poids des titres de section. */
.isis-detail-card__title {
    font-size: var(--isis-fs-lg, 1.0625rem);
    font-weight: 600;
    margin: 0 0 0.75rem;
    display: flex;
    align-items: center;
    gap: 0.4rem;
}

.isis-grid--gesqhse-probleme .isis-grid__head,
.isis-grid--gesqhse-probleme .isis-grid__row {
    grid-template-columns: 110px 130px minmax(200px, 1.3fr) 110px 120px 90px 112px;
}
/* Élargi le 2026-09-05, même motif que .isis-grid--gesqhse-risque : six des sept en-têtes
   portent désormais un bouton de tri et/ou un entonnoir, qui prennent de la place à côté du
   libellé. Sept pistes pour sept cellules d'en-tête — le configurateur de colonnes exige
   l'égalité (DESIGN.md § Grilles). */
.isis-grid--gesqhse-probleme-suivi .isis-grid__head,
.isis-grid--gesqhse-probleme-suivi .isis-grid__row {
    grid-template-columns: 120px 165px minmax(200px, 1.4fr) 140px 140px 150px 120px;
    min-width: 1035px;
}
/* Paramétrage des types documentaires (pyramide SMQSE) : Rang | Code | Libellé | Préfixe |
   Revue (mois) | Couvre une prestation | Actions. */
.isis-grid--gesqhse-doc-type .isis-grid__head,
.isis-grid--gesqhse-doc-type .isis-grid__row {
    /* 7 colonnes depuis le Lot 2.a : « Couvre une prestation » s'intercale avant Actions.
       Libellé resserré (220→180px min) pour absorber les 150px ajoutés sans pousser la
       somme au-delà de la largeur utile de cette page pleine largeur.
       `min-width` surchargé (mesure 2026-07-30) : la règle générique .isis-grid__head/__row
       impose 1000px, or la somme des gabarits n'est que de 844px — le forfait générique
       faisait donc déborder la grille de 62px dès 1280×800 et de 318px en 1024×768, AVANT
       comme APRÈS l'ajout de la 7e colonne (témoin mesuré à l'identique sur l'ancien
       gabarit 6 colonnes : ce n'est pas la colonne ajoutée qui déborde, c'est le 1000px
       jamais surchargé). 1280×800 est désormais propre ; en 1024×768 la page défile encore
       horizontalement (844 > 709 disponibles), sans régression par rapport à l'existant.

       Révisé le 2026-09-05 : quatre en-têtes portent maintenant un bouton de tri. « Rang »
       débordait de sa piste de 64 px — mesuré au navigateur, le bouton et sa flèche
       dépassaient la cellule — et « Revue (mois) » n'avait plus la place pour la sienne.
       Les deux sont élargies, le libellé resserré en compensation. Le défilement horizontal
       en 1024×768 reste, comme avant (886 > 709). */
    grid-template-columns: 96px 130px minmax(160px, 1.4fr) 100px 150px 150px 100px;
    min-width: 886px;
}
/* Un type suspendu reste au référentiel (avec son historique) mais se distingue visuellement
   des types actifs — sans jamais disparaître de la liste, cf. RadzenBadge "Suspendu" adjacent. */
.isis-grid--gesqhse-doc-type .isis-grid__row.is-inactive {
    opacity: 0.6;
}
.isis-matrice-legend { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 0.75rem; }

/* ── gesqhse — documentaire (référentiel SMQSE opposable, Task 11/12) ─────────
   Bibliothèque paginée : Statut | Code | Titre | Type | Pilote | Indice |
   Date d'application | Prochaine revue | Actions.
   Resserrée (audit ui-ux 2026-07-29) : la page vit en .isis-master-detail, qui réserve
   ~390px au sidepanel — sur un écran de 1600px la grille ne dispose que d'~887px, alors
   que la somme d'origine (130+100+200+130+130+60+115+115+80 ≈ 1060px) l'excédait déjà,
   masquant « Prochaine revue » et « Actions » sans défiler. Type/Pilote/Code/Indice/
   Actions sont resserrés au strict nécessaire (ellipsis déjà porté par la règle de base
   .isis-grid__row > div) ; Titre reste la colonne souple qui absorbe l'espace restant.
   Nouvelle somme ≈ 844px < 880px visés, et le `min-width` de base (1000px, hérité de la
   règle générique .isis-grid__head/.isis-grid__row) est explicitement surchargé plus bas
   — sans quoi il forcerait la ligne à 1000px quels que soient les gabarits de colonnes,
   même pattern que .isis-grid--tiers/--articles/--evenements. */
/* Élargi le 2026-09-05 : les colonnes Statut, Type, Pilote et Prochaine revue portent
   maintenant un entonnoir EN PLUS de leur libellé (et de leur bouton de tri pour trois
   d'entre elles). Aux anciennes largeurs — 84 px pour « Type », 88 px pour « Pilote » —
   l'entonnoir n'avait pas la place de se poser à côté du texte. Neuf pistes pour neuf
   cellules d'en-tête : le configurateur de colonnes exige l'égalité (DESIGN.md § Grilles). */
.isis-grid--gesqhse-documentaire .isis-grid__head,
.isis-grid--gesqhse-documentaire .isis-grid__row {
    grid-template-columns: 140px 110px minmax(160px, 1fr) 150px 150px 62px 120px 160px 60px;
    min-width: 1112px;
}

/* ── gesqhse — couverture documentaire des prestations (Lot 2.a) ──────────────
   Couverture | Code | Prestation | Documents | À revoir | Actions.
   Cette page vit en PLEINE LARGEUR (pas de .isis-master-detail, donc pas de sidepanel
   à ~390px) : la somme des colonnes fixes (132+110+110+84+64 = 500px) laisse tout
   l'espace restant à « Prestation », la seule colonne souple. `min-width` surchargé à
   700px — sans quoi le 1000px de la règle générique .isis-grid__head/.isis-grid__row
   forcerait un défilement horizontal sur tablette alors que les gabarits tiennent,
   même piège que .isis-grid--gesqhse-documentaire ci-dessus. */
.isis-grid--gesqhse-couverture .isis-grid__head,
.isis-grid--gesqhse-couverture .isis-grid__row {
    /* Gabarits resserrés après MESURE (2026-07-30) : la première version (132/110/200/110/
       84/64 = 700px) débordait de 18px sur la cible tablette 1024×768, où le conteneur ne
       laisse que 709px — les 27px de padding horizontal de la grille comptent dans le
       scrollWidth et mangeaient la marge. 624px de somme minimale laissent la réserve.

       Révisé le 2026-09-05 : deux en-têtes portent désormais un bouton de tri, et le premier
       un entonnoir, qui prennent de la place à côté du libellé. Les largeurs sont donc
       redistribuées PLUTÔT QU'AUGMENTÉES, pour tenir la même contrainte. */
    grid-template-columns: 132px 92px minmax(130px, 1fr) 138px 104px 52px;
    min-width: 648px;
}

/* ── gesqhse — fiche document, onglet Portée (Lot 2.a) ────────────────────────
   Code | Prestation | Entreprise | Actions. Vit DANS un panneau d'onglet de la fiche,
   dont la largeur utile est bien inférieure à celle d'une page pleine : quatre colonnes
   seulement, dont une seule souple, et `min-width` surchargé à 560px — le 1000px de la
   règle générique aurait fait déborder le panneau sans qu'aucune relecture de code ne
   le voie (c'est exactement le défaut trouvé à la mesure au Lot 1 : 1074px de colonnes
   pour 887px disponibles). */
.isis-grid--gesqhse-portee .isis-grid__head,
.isis-grid--gesqhse-portee .isis-grid__row {
    grid-template-columns: 110px minmax(180px, 1fr) 160px 64px;
    min-width: 560px;
}

/* Constat de masquage (Lot 2.b) quand il n'y en a aucun : une ligne en sourdine, pas une
   alerte. L'absence de masquage est le cas nominal — la signaler avec le même poids visuel
   que « masqué sur 4 tâches » ferait lire un problème là où il n'y en a pas. */
.isis-doc-masquage__aucun {
    display: flex; align-items: center; gap: var(--isis-space-xs);
    margin: 0; font-size: 0.78rem; color: var(--isis-text-muted);
}
/* Lecture impossible (souvent : migration 0625 non propagée) — un doute, pas un fait. */
.isis-doc-masquage__aucun.is-indisponible { color: var(--isis-warning); }

/* ── gesqhse — fiche document, onglet Indices (refonte 2026-07-29) ────────────
   Historique des indices en grille — pas une liste .isis-eval-histo (réservée à
   l'historique d'évaluation d'un sous-traitant, ReferencementListPage) : chevron |
   Indice | Statut | Période | Approbateur | Actions, avec ligne dépliable
   (.isis-grid__subrow générique) pour le motif de révision, le panneau
   d'approbation et les gestes contextuels — sur le modèle de LivraisonListSection.
   Période élargie 190→235px (audit ui-ux 2026-07-29) : « 29/07/2026 · remplacé
   aussitôt » (cas retrait le jour même) tronquait à 190px. Cette grille dispose de
   marge (elle n'a jamais débordé, Approbateur — seule colonne `fr` — absorbe la
   différence sans risque de dépassement). */
.isis-grid--gesqhse-indice .isis-grid__head,
.isis-grid--gesqhse-indice .isis-grid__row {
    grid-template-columns: 34px 100px 150px 235px minmax(190px, 1fr) 60px;
}
.isis-grid--gesqhse-indice .isis-grid__row.is-expanded {
    background: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 5%, var(--isis-surface));
}

/* Pastille de statut d'un indice/document — dot + libellé, dense (grille + fiche).
   L'anneau interne (assombrissement fixe, indépendant de la teinte) tient le ratio de
   contraste non-textuel 3:1 des objets graphiques (WCAG 1.4.11) : sans lui, un succès clair
   sur une surface claire tomberait sous le seuil. */
.isis-docstatut { display: inline-flex; align-items: center; gap: 0.4rem; white-space: nowrap; }
.isis-docstatut__dot {
    width: 9px; height: 9px; border-radius: 50%; flex-shrink: 0;
    box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.18);
}
/* Sur fond Nocturne (quasi noir), l'anneau noir fixe ci-dessus RÉDUIT la pastille au lieu de
   la détacher — polish P2 : surcharge claire, même logique que l'anneau assombri du thème
   clair, symétrique. */
:root[data-theme="dark"] .isis-docstatut__dot {
    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.22);
}
.isis-docstatut__dot.is-ready    { background: var(--isis-success); }   /* Applicable */
/* En approbation : token SÉMANTIQUE (info = « en circuit »), pas l'accent global (interactif)
   — sur une page d'identité module violette, l'accent cyan lisait comme deux notions
   froides non apparentées (polish P2). */
.isis-docstatut__dot.is-pending  { background: var(--isis-info); }
/* Bloquant (audit a11y 2026-07-29, onglet Indices — contraste) : --isis-border-strong échouait
   WCAG 1.4.11 (3:1, objet graphique) contre la surface RÉELLE des deux thèmes — Brouillon
   ≈1.8:1 en sombre (#3c4756 sur #161c25) et ≈2.6:1 en clair (#94a3b4 sur #ffffff), un défaut
   pré-existant aux deux thèmes, pas seulement au sombre. --isis-text-soft (déjà employé pour
   ce même rôle « neutre » ailleurs dans le thème) passe ≥3.8:1 dans les deux
   thèmes et reste visuellement distinct de --isis-text-muted (is-archived / Périmé). */
.isis-docstatut__dot.is-draft    { background: var(--isis-text-soft); } /* Brouillon */
.isis-docstatut__dot.is-archived { background: var(--isis-text-muted); }    /* Périmé */
/* Revue échue — badge/chip distinct de la pastille de statut (orange sémantique) : signale
   sans jamais déclasser, cf. DocumentDto.RevueEchue. */
.isis-docstatut__dot.is-warning  { background: var(--isis-warning); }
/* Rejeté (circuit d'approbation GED, .docappr) — seul consommateur à ce jour d'un statut
   franchement négatif sur .isis-docstatut ; les autres familles (indice, document) n'ont
   qu'un statut « intermédiaire » (brouillon/en approbation) ou terminal neutre (périmé). */
.isis-docstatut__dot.is-danger   { background: var(--isis-danger); }

/* Vue matrice / cartographie des risques (pastilles + panneau latéral) */
.isis-riskmap__grid {
    display: grid; grid-template-columns: auto repeat(5, minmax(76px, 1fr)); gap: 5px;
}
.isis-riskmap__rowlabel,
.isis-riskmap__collabel { font-size: 0.72rem; color: var(--isis-text-muted); display: flex; align-items: center; }
.isis-riskmap__rowlabel { justify-content: flex-end; padding-right: 0.4rem; text-align: right; }
.isis-riskmap__collabel { justify-content: center; text-align: center; padding-top: 0.2rem; }
.isis-riskmap__cell {
    min-height: 84px; padding: 4px; cursor: pointer; text-align: left;
    border: 1px solid var(--isis-border); border-radius: var(--isis-radius-sm, 5px);
    transition: box-shadow 0.08s ease;
}
.isis-riskmap__cell:hover { box-shadow: 0 0 0 1px var(--isis-current-mod, var(--isis-accent)); }
.isis-riskmap__cell:focus-visible { outline: 2px solid var(--isis-current-mod, var(--isis-accent)); outline-offset: 1px; }
.isis-riskmap__cell.is-selected { box-shadow: 0 0 0 2px var(--isis-current-mod, var(--isis-accent)); border-color: var(--isis-current-mod, var(--isis-accent)); }
.isis-riskmap__pins { display: flex; flex-wrap: wrap; gap: 3px; align-content: flex-start; }
.isis-riskmap__pin {
    display: inline-flex; align-items: center; justify-content: center;
    width: 24px; height: 24px; border-radius: 50%;
    background: var(--isis-surface); border: 1px solid var(--isis-border);
    font-size: 0.62rem; font-weight: 700; color: var(--isis-text);
}
.isis-riskmap__more { display: inline-flex; align-items: center; font-size: 0.66rem; font-weight: 600; color: var(--isis-text-muted); padding: 0 4px; }
.isis-riskmap__footer { display: flex; align-items: center; justify-content: space-between; gap: 0.6rem; margin-top: 0.6rem; }
.isis-riskmap__axislabel { font-size: 0.72rem; color: var(--isis-text-muted); }
.isis-riskmap-list { display: flex; flex-direction: column; gap: 0.35rem; }
.isis-riskmap-item {
    display: flex; align-items: center; gap: 0.5rem; width: 100%; text-align: left;
    padding: 0.4rem 0.5rem; cursor: pointer;
    border: 1px solid var(--isis-border); border-radius: var(--isis-radius-sm, 5px); background: var(--isis-surface);
}
.isis-riskmap-item:hover { background: var(--isis-surface-alt); }
.isis-riskmap-item__titre { flex: 1; font-size: 0.85rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.isis-rich-section__header-actions { display: flex; align-items: center; gap: 0.6rem; }

/* Gantt commande (onglet Tâches) — Axe A : wrapper largeur. La hauteur « occupe le reste de la page
   sans scroll » est posée PRÉCISÉMENT par JS (isisGanttSplit.fitHeight : viewport − top réel du Gantt
   − réserve pour l'aide+légende dessous). Ci-dessous = repli CSS avant que le JS ne s'exécute (évite
   un effondrement de la timeline interne au 1er paint). La hauteur DEFINITE est requise (pas 100%). */
.isis-gantt-host { width: 100%; max-width: 100%; min-width: 0; }
.isis-gantt-host .rz-gantt { height: calc(100vh - 420px); min-height: 340px; }

/* Gantt commande via amCharts (CommandeGanttView) — hauteur fixée par le JS (lignes × ~38px). */
.isis-amgantt-host { width: 100%; max-width: 100%; min-width: 0; min-height: 180px; }

/* ════════════════════ PILOTAGE DU CYCLE COMMERCIAL (V4 — /gescom/pilotage-cycle) ════════════════════
   Vue tour de contrôle : KPI strip + bande {entonnoir · conversion} + cartes par étape.
   Classes cyc- et m- portées de la maquette docs/mockups, scopées sous .isis-pilotage-cycle.
   Le tiret suffit : accoler une étoile et une barre oblique refermerait ce commentaire ici
   même, et le parseur avalerait la règle suivante — c'est ce qui se passait avant 2026-09-05. */
.isis-pilotage-cycle .isis-seg { display: inline-flex; background: var(--isis-surface); border: 1px solid var(--isis-border); border-radius: var(--isis-radius); overflow: hidden; }
.isis-pilotage-cycle .isis-seg__btn { padding: .32rem .7rem; font-size: .8rem; color: var(--isis-text-muted); background: none; border: none; border-right: 1px solid var(--isis-border); cursor: pointer; font-family: inherit; }
.isis-pilotage-cycle .isis-seg__btn:last-child { border-right: none; }
.isis-pilotage-cycle .isis-seg__btn.is-active { background: var(--isis-current-mod, var(--isis-accent)); color: #fff; font-weight: 600; }
.isis-pilotage-cycle .isis-dash-filters { display: flex; gap: .8rem; flex-wrap: wrap; margin-bottom: .6rem; }

/* KPI strip */
.isis-pilotage-cycle .cyc-strip { display: grid; grid-template-columns: repeat(6, 1fr); gap: .55rem; margin-bottom: .9rem; }
.isis-pilotage-cycle .m-kpi { background: var(--isis-surface); border: 1px solid var(--isis-border); border-radius: var(--isis-radius); padding: .55rem .75rem; box-shadow: var(--isis-elevation-1); display: flex; flex-direction: column; gap: .12rem; }
.isis-pilotage-cycle .m-kpi__label { font-size: .64rem; text-transform: uppercase; letter-spacing: .06em; color: var(--isis-text-soft); }
.isis-pilotage-cycle .m-kpi__value { font-family: var(--isis-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace); font-variant-numeric: tabular-nums; font-size: 1.3rem; font-weight: 600; letter-spacing: -.01em; color: var(--isis-mod-gescom); }
.isis-pilotage-cycle .m-kpi__hint { font-size: .68rem; color: var(--isis-text-muted); }
.isis-pilotage-cycle .m-kpi--hero { box-shadow: var(--isis-elevation-hover); background: linear-gradient(160deg, var(--isis-accent-soft), var(--isis-surface) 70%); border-color: color-mix(in srgb, var(--isis-accent) 22%, var(--isis-border)); }
.isis-pilotage-cycle .m-kpi--hero .m-kpi__value { font-size: 1.75rem; color: var(--isis-accent-strong); }

/* Bande graphique (2 col en Phase B ; le globe insère une 3e col en Phase C) */
.isis-pilotage-cycle .cyc-graphs { display: grid; grid-template-columns: 1.05fr 1.5fr 1fr; grid-template-rows: auto auto; gap: .85rem; margin-bottom: .5rem; align-items: stretch; }
.isis-pilotage-cycle .cyc-graphs .isis-rich-section { min-height: 330px; }
/* Entonnoir (haut-gauche) + Conversion (sous l'entonnoir) ; Globe sur 2 lignes (col 2) ; col 3 vide. */
.isis-pilotage-cycle .cyc-g-funnel { grid-column: 1; grid-row: 1; }
.isis-pilotage-cycle .cyc-g-conv   { grid-column: 1; grid-row: 2; }
.isis-pilotage-cycle .cyc-g-globe  { grid-column: 2; grid-row: 1 / span 2; }
.isis-pilotage-cycle .cyc-g-side1  { grid-column: 3; grid-row: 1; }
.isis-pilotage-cycle .cyc-g-side2  { grid-column: 3; grid-row: 2; }
.isis-pilotage-cycle .cyc-g-globe > div[id^="amc-"],
.isis-pilotage-cycle .cyc-g-side1 > div[id^="amc-"] { flex: 1 1 auto; height: auto !important; min-height: 0; }
.isis-pilotage-cycle .cyc-globe-legend-types { display: flex; flex-wrap: wrap; gap: .35rem 1rem; justify-content: center; padding-top: .45rem; margin-top: .2rem; border-top: 1px solid var(--isis-border); }
.isis-pilotage-cycle .cglt { display: inline-flex; align-items: center; gap: .35rem; font-size: .72rem; color: var(--isis-text-muted); }
.isis-pilotage-cycle .cglt i { width: 9px; height: 9px; border-radius: 50%; flex-shrink: 0; }
.isis-pilotage-cycle .cyc-globe-empty { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: .35rem; text-align: center; color: var(--isis-text-muted); padding: 1rem; }
.isis-pilotage-cycle .cyc-globe-empty strong { color: var(--isis-text); font-size: .92rem; }
.isis-pilotage-cycle .cyc-globe-empty span { font-size: .78rem; }
.isis-pilotage-cycle .cyc-funnel-viz { display: flex; gap: .8rem; align-items: center; justify-content: center; width: 100%; height: 100%; }
.isis-pilotage-cycle .cyc-funnel-chart { flex: 1.15; min-width: 0; align-self: stretch; }
.isis-pilotage-cycle .cyc-funnel-svg { height: 300px; width: auto; flex-shrink: 0; }
.isis-pilotage-cycle .cyc-funnel-legend { flex: 1; display: flex; flex-direction: column; justify-content: center; gap: .1rem; font-size: .82rem; min-width: 0; }
.isis-pilotage-cycle .cfl { display: flex; align-items: center; gap: .45rem; }
.isis-pilotage-cycle .cfl i { width: 10px; height: 10px; border-radius: 2px; flex-shrink: 0; }
.isis-pilotage-cycle .cfl b { font-weight: 600; }
.isis-pilotage-cycle .cfl span { margin-left: auto; font-family: var(--isis-font-mono, ui-monospace, monospace); font-variant-numeric: tabular-nums; color: var(--isis-text-muted); white-space: nowrap; }
.isis-pilotage-cycle .cfl-conv { font-size: .69rem; color: var(--isis-text-soft); padding: .05rem 0 .05rem 1.45rem; }

/* Conversion + valeur + stats */
.isis-pilotage-cycle .cyc-conv-body { display: flex; flex-direction: column; gap: .7rem; height: 100%; }
.isis-pilotage-cycle .m-bars { display: flex; flex-direction: column; gap: .35rem; }
.isis-pilotage-cycle .m-bar { display: grid; grid-template-columns: 1fr auto; gap: .15rem .6rem; align-items: center; }
.isis-pilotage-cycle .m-bar__name { font-size: .82rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.isis-pilotage-cycle .m-bar__val { font-family: var(--isis-font-mono, ui-monospace, monospace); font-variant-numeric: tabular-nums; font-size: .82rem; text-align: right; }
.isis-pilotage-cycle .m-bar__track { grid-column: 1 / -1; height: 8px; background: var(--isis-surface-alt); border-radius: 4px; overflow: hidden; }
.isis-pilotage-cycle .m-bar__fill { height: 100%; background: var(--isis-mod-gescom); border-radius: 4px; }
.isis-pilotage-cycle .cyc-mini-h { font-size: .68rem; text-transform: uppercase; letter-spacing: .05em; color: var(--isis-text-soft); border-top: 1px solid var(--isis-border); padding-top: .55rem; }
.isis-pilotage-cycle .cyc-stats { display: flex; gap: .55rem; margin-top: auto; }
.isis-pilotage-cycle .cyc-stat { flex: 1; background: var(--isis-surface-alt); border-radius: var(--isis-radius-sm); padding: .45rem .4rem; text-align: center; }
.isis-pilotage-cycle .cyc-stat b { display: block; font-family: var(--isis-font-mono, ui-monospace, monospace); font-variant-numeric: tabular-nums; font-size: 1.05rem; font-weight: 600; }
.isis-pilotage-cycle .cyc-stat span { font-size: .62rem; color: var(--isis-text-soft); }

/* Cartes par étape */
.isis-pilotage-cycle .cyc-sub { font-size: .8rem; font-weight: 600; color: var(--isis-text-soft); text-transform: uppercase; letter-spacing: .05em; margin: 1rem 0 .5rem; }
.isis-pilotage-cycle .cyc-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(310px, 1fr)); gap: .85rem; }
.isis-pilotage-cycle .cyc-card { background: var(--isis-surface); border: 1px solid var(--isis-border); border-radius: var(--isis-radius-lg); box-shadow: var(--isis-elevation-1); padding: .75rem .8rem; display: flex; flex-direction: column; gap: .55rem; }
.isis-pilotage-cycle .cyc-card__h { display: flex; align-items: center; gap: .5rem; border-bottom: 1px solid var(--isis-border); padding-bottom: .45rem; }
.isis-pilotage-cycle .cyc-card__t { font-size: .9rem; font-weight: 600; margin: 0; flex: 1; }
.isis-pilotage-cycle .cyc-card__mod { font-size: .62rem; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; padding: .12rem .45rem; border-radius: var(--isis-radius-pill); }
.isis-pilotage-cycle .cyc-kpis { display: flex; gap: .8rem; flex-wrap: wrap; }
.isis-pilotage-cycle .cyc-kpi__v { font-family: var(--isis-font-mono, ui-monospace, monospace); font-variant-numeric: tabular-nums; font-size: 1.18rem; font-weight: 600; color: var(--isis-text); line-height: 1.1; }
.isis-pilotage-cycle .cyc-kpi__l { font-size: .62rem; text-transform: uppercase; letter-spacing: .05em; color: var(--isis-text-soft); }
.isis-pilotage-cycle .cyc-alerts { display: flex; gap: .3rem; flex-wrap: wrap; }
.isis-pilotage-cycle .cyc-chip { font-size: .69rem; padding: .12rem .45rem; border-radius: var(--isis-radius-pill); font-weight: 500; }
.isis-pilotage-cycle .cyc-chip--danger { background: var(--isis-danger-soft); color: var(--isis-danger); }
.isis-pilotage-cycle .cyc-chip--warning { background: var(--isis-warning-soft); color: var(--isis-warning); }
.isis-pilotage-cycle .cyc-tab { width: 100%; border-collapse: collapse; font-size: .76rem; }
.isis-pilotage-cycle .cyc-tab td { padding: .3rem .25rem; border-top: 1px solid var(--isis-border); vertical-align: middle; }
.isis-pilotage-cycle .cyc-tab__ref { font-family: var(--isis-font-mono, ui-monospace, monospace); color: var(--isis-text-muted); white-space: nowrap; font-size: .72rem; }
.isis-pilotage-cycle .cyc-tab__val { font-family: var(--isis-font-mono, ui-monospace, monospace); text-align: right; white-space: nowrap; }
.isis-pilotage-cycle .cyc-badge { font-size: .66rem; padding: .07rem .4rem; border-radius: var(--isis-radius-pill); white-space: nowrap; }
.isis-pilotage-cycle .cyc-badge--danger { background: var(--isis-danger-soft); color: var(--isis-danger); }
.isis-pilotage-cycle .cyc-badge--warning { background: var(--isis-warning-soft); color: var(--isis-warning); }
.isis-pilotage-cycle .cyc-badge--ok { background: var(--isis-success-soft); color: var(--isis-success); }
.isis-pilotage-cycle .cyc-badge--muted { background: var(--isis-surface-alt); color: var(--isis-text-muted); }
.isis-pilotage-cycle .cyc-empty { font-size: .76rem; color: var(--isis-text-muted); padding: .4rem 0; }
@media (max-width: 1100px) {
  .isis-pilotage-cycle .cyc-strip { grid-template-columns: repeat(3, 1fr); }
  .isis-pilotage-cycle .cyc-graphs { grid-template-columns: 1fr; grid-template-rows: none; }
  .isis-pilotage-cycle .cyc-g-funnel, .isis-pilotage-cycle .cyc-g-conv, .isis-pilotage-cycle .cyc-g-globe,
  .isis-pilotage-cycle .cyc-g-side1, .isis-pilotage-cycle .cyc-g-side2 { grid-column: auto; grid-row: auto; }
  .isis-pilotage-cycle .cyc-g-globe > div[id^="amc-"], .isis-pilotage-cycle .cyc-g-side1 > div[id^="amc-"] { height: 300px !important; flex: none; }
}
@media (max-width: 640px)  { .isis-pilotage-cycle .cyc-strip { grid-template-columns: repeat(2, 1fr); } }

/* ── What-If : panneau de simulation marge globale ─────────────────────── */
.isis-margin-sim {
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-sm);
    background: var(--isis-surface);
    margin-bottom: 0.6rem;
    font-size: 0.85rem;
}
.isis-margin-sim__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding: 0.4rem 0.6rem;
    flex-wrap: wrap;
}
.isis-margin-sim__toggle {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    background: none;
    border: none;
    cursor: pointer;
    font-weight: 600;
    color: var(--isis-text);
    padding: 0.15rem 0.2rem;
}
.isis-margin-sim__toggle:focus-visible {
    outline: 2px solid color-mix(in srgb, var(--isis-current-mod) 50%, transparent);
    outline-offset: 2px;
}
.isis-margin-sim__target {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
}
.isis-margin-sim__label { color: var(--isis-text-soft); }
.isis-margin-sim__target-ro { font-weight: 600; }
.isis-margin-sim__summary {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-wrap: wrap;
    padding: 0.4rem 0.6rem;
    border-top: 1px solid var(--isis-border);
    background: var(--isis-surface-alt);
}
.isis-margin-sim__summary.is-on-target { color: var(--isis-success); }
.isis-margin-sim__summary.is-below-target { color: var(--isis-warning); }
.isis-margin-sim__gap { font-weight: 600; }
.isis-margin-sim__resulting { color: var(--isis-text-soft); margin-left: auto; }
.isis-margin-sim__table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.82rem;
    /* Sans largeurs fixes, la colonne « Ligne » (désignations longues) écrasait les trois
       colonnes de montants, qui se retrouvaient tronquées ou repliées sur 2 lignes. */
    table-layout: fixed;
}
/* PU actuel · PU cible · Δ HT : de la place pour un montant + sa devise, sur une seule ligne. */
.isis-margin-sim__table th:not(:first-child),
.isis-margin-sim__table td:not(:first-child) {
    width: 160px;
    white-space: nowrap;
}
/* La désignation prend le reste et se coupe proprement plutôt que de pousser les montants. */
.isis-margin-sim__table td:first-child {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.isis-margin-sim__table th {
    text-align: left;
    padding: 0.3rem 0.6rem;
    color: var(--isis-text-soft);
    border-top: 1px solid var(--isis-border);
    font-weight: 600;
}
.isis-margin-sim__table td {
    padding: 0.25rem 0.6rem;
    border-top: 1px solid var(--isis-border-soft, var(--isis-border));
}
.isis-margin-sim__table tr.is-excluded { opacity: 0.55; }
.isis-margin-sim__ghost {
    font-style: italic;
    color: var(--isis-current-mod, var(--isis-accent));
}
.isis-margin-sim__excl { color: var(--isis-text-soft); }
.isis-margin-sim__note {
    padding: 0.35rem 0.6rem;
    font-size: 0.78rem;
    color: var(--isis-text-soft);
    border-top: 1px solid var(--isis-border);
}

/* ── What-If : pastille marge live dans l'éditeur de lignes ────────────── */
.isis-live-margin {
    display: inline-block;
    padding: 0.05rem 0.4rem;
    border-radius: var(--isis-radius-pill, 999px);
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}
.isis-live-margin.is-on-target {
    background: color-mix(in srgb, var(--isis-success) 14%, transparent);
    color: var(--isis-success);
}
.isis-live-margin.is-below-target {
    background: color-mix(in srgb, var(--isis-warning) 16%, transparent);
    color: var(--isis-warning);
}
.isis-live-margin.is-below-floor {
    background: color-mix(in srgb, var(--isis-danger) 14%, transparent);
    color: var(--isis-danger);
}
.isis-live-margin.is-no-cost,
.isis-live-margin.is-unclassified {
    color: var(--isis-text-soft);
}

/* =============================================================================
   PoC MODE SOMBRE (2026-06-10) — re-mapping des tokens uniquement.
   ----------------------------------------------------------------------------
   :root[data-theme="dark"] a une spécificité (0,1,1) > :root (0,1,0) → gagne
   toujours, quelle que soit sa position dans le fichier.
   But du PoC : RÉVÉLER la dette. Tout ce qui reste clair en sombre = couleur
   hex/rgba écrite EN DUR hors :root (cf. ~600 occurrences) → à tokeniser pour
   un dark mode propre. Les composants Radzen/Syncfusion gardent leur thème clair
   (CSS tiers non tokenisé) — attendu.
   ============================================================================= */
:root[data-theme="dark"] {
    color-scheme: dark;

    /* --isis-current-mod-strong (cf. .isis-shell) ne mélange plus de noir en sombre : les
       accents de module y sont déjà des teintes éclaircies qui passent large l'AA sur leur
       fond -soft (5,28:1 au pire, gesinfo) — assombrir comme en clair les ferait chuter
       sous 4,5:1 (vérifié : gesinfo tomberait à 3,53:1 avec le même dosage que le clair). */
    --isis-mod-active-mix: 100%;

    /* === Thème « Nocturne » 2026-07-04 (ex-PoC dark) : bleu-noir profond,
       surfaces élevées franches, accent teal lumineux. Cf. DESIGN.md §2. === */
    --isis-bg:            #0e131a;
    --isis-surface:       #161c25;
    --isis-surface-alt:   #1e2732;
    /* Même rôle qu'en clair et, surtout, MÊME DIRECTION : un cran en retrait de la carte, donc
       plus SOMBRE qu'elle — et non un cran plus clair comme -alt. Ce sens-là est le seul qui
       n'abîme aucun contraste : sur ce fond, tout gagne par rapport à la carte qu'il recouvre
       (texte 15,2:1 contre 14,5 ; tertiaire 5,73 contre 5,45 ; danger 4,86 contre 4,62).
       L'essai inverse (#1b222c, entre surface et -alt) faisait tomber le rouge des cellules de
       variation du pivot d'analyse à 4,32:1 — sous l'AA, mesuré au navigateur. */
    --isis-surface-soft:  #111720;
    --isis-border:        #2a3340;
    --isis-border-soft:   #232c37;
    --isis-border-subtle: var(--isis-border-soft);
    --isis-border-strong: #3c4756;
    --isis-text:          #e6edf3;
    --isis-text-muted:    #9aa7b4;   /* ~6.98:1 sur --isis-surface (6.15 sur -alt, 7.60 sur --isis-bg) */
    --isis-text-soft:     #8593a1;   /* tertiaire — relevé 2026-08-03 (a11y) : #6e7d8c tombait à 3.58:1
                                        sur --isis-surface-alt (échec AA texte <18px). Cette valeur
                                        tient ≥4.5:1 sur les 3 fonds réels (4.81 sur -alt, le pire cas ;
                                        5.45 sur --isis-surface ; 5.93 sur --isis-bg) tout en restant
                                        visiblement en retrait de --isis-text-muted (écart ≥1.35 pt de
                                        ratio partout) — cf. CHANGELOG et ThemeTokenDefaults.cs (à
                                        garder synchronisé, sous peine de dérive tenant white-label). */
    /* Violet « partenaire / scénario » — variante plus claire pour le mode sombre. */
    --isis-violet:        #a78bfa;
    --isis-violet-strong: #c4b5fd;

    /* Tuile logo en sombre : on garde un fond CLAIR (légèrement adouci vs blanc pur pour
       ne pas éblouir) — un logo encre-sombre sur transparent reste lisible. */
    --isis-logo-surface:  #eef1f4;
    --isis-logo-border:   #3c4756;

    /* Vignettes d'entreprise — jeu sombre. Les pastels du thème clair mesuraient 15,78 à
       16,52 contre le panneau nocturne : trois carrés lumineux qui hurlaient plus fort que
       les noms qu'ils accompagnaient. Les fonds SOURDS qui les ont remplacés ont dépassé
       de l'autre côté — 1,71:1 mesuré le 2026-09-05, la pastille disparaissait dans le
       panneau. Les six couples sont recalés au MILIEU de la bande (≈5,2:1 contre le
       panneau, encre ≈4,9:1 contre la pastille) : assez pour se voir, pas assez pour
       éblouir. Teintes claires, encres profondes — le miroir exact du jeu clair. */
    --isis-wsav-1-bg: #c1750a;  --isis-wsav-1-fg: #241603;
    --isis-wsav-2-bg: #5885dc;  --isis-wsav-2-fg: #0a1832;
    --isis-wsav-3-bg: #269a54;  --isis-wsav-3-fg: #071d10;
    --isis-wsav-4-bg: #e75177;  --isis-wsav-4-fg: #350713;
    --isis-wsav-5-bg: #9673e2;  --isis-wsav-5-fg: #1e0d40;
    --isis-wsav-6-bg: #e9571a;  --isis-wsav-6-fg: #2d1004;

    /* === Accent principal — TERRE CUITE éclaircie (Nocturne) — 6,4:1 sur --isis-surface ===
       Reprend tel quel l'ancien --isis-accent-warm sombre, fusionné ici le 2026-09-23. */
    --isis-accent:        #f0803c;
    --isis-accent-soft:   #33200f;
    --isis-accent-strong: #ff9d5c;
    --isis-accent-on-soft: color-mix(in srgb, var(--isis-accent-strong) 85%, var(--isis-text));
    /* ENCRE SOMBRE, et c'est la CORRECTION de la dette nommée ici le 2026-09-07 (« blanc sur
       --isis-accent = 2,24:1 ; corriger est hors périmètre »). Fermée le 2026-09-15.
       Le raisonnement : en thème sombre les accents sont DÉJÀ des teintes ÉCLAIRCIES — c'est ce
       qui les rend lisibles en aplat sur un fond sombre. Poser du blanc dessus était donc une
       double clarté. Mesuré sur les 21 aplats bruts du thème (accent, accent-strong et les 19
       `--isis-mod-*`) : encre #0e131a → pire cas 4,93:1 (`gesfac`), AA tenu ; blanc → 1,51:1
       (`monespace`). L'aplat BRUT contraste par ailleurs à 4,52:1 au pire contre --isis-surface,
       donc l'état se voit AUSSI (WCAG 1.4.11) — ce qu'un aplat assombri ne permettait pas :
       texte et état tiraient en sens inverse tant que l'encre restait blanche.
       Valeur = celle de --isis-bg ci-dessus, idiome déjà employé tel quel dans cette feuille
       (`:root[data-theme="dark"] .isis-rich-toolbar__btn--primary .rzi`, .isis-completude-hub__pays-confirm).
       CONSÉQUENCE VOULUE, hors socle : les 11 autres usages du token (lien d'évitement, avatar de
       tenant, bouton de login, CTA marketing, badge de panneau latéral…) et les trois
       `.isis-seg__btn[aria-pressed="true"]` scopés (HubSerieMensuelle, CommandesLiees,
       FacturesLiees) sont posés sur l'accent BRUT : ils passent de 2,24:1 à 8,58:1. */
    --isis-on-accent:     #0e131a;

    /* === Sémantique (éclaircie + soft = fonds sombres teintés) === */
    --isis-success:       #3fb950;
    --isis-success-soft:  #122c19;
    --isis-warning:       #d6a02a;
    --isis-warning-soft:  #312611;
    --isis-danger:        #e5534b;
    --isis-danger-soft:   #3a1614;
    /* Info (sombre) : bleu éclairci sur fond sombre teinté (contraste ≈ 7:1). */
    --isis-info:          #58a6ff;
    --isis-info-soft:     #0f2942;
    --isis-success-text:  #3fb950;
    --isis-warning-text:  #d6a02a;
    --isis-danger-text:   #f47067;
    --isis-info-text:     #58a6ff;

    /* === Accents par module : teinte principale éclaircie, -soft = fond sombre teinté === */
    --isis-mod-gescom:         #60a5fa;  --isis-mod-gescom-soft:    #16243d;
    --isis-mod-gescompta:      #a78bfa;  --isis-mod-gescompta-soft: #241b3d;
    --isis-mod-sirh:           #34d399;  --isis-mod-sirh-soft:      #0e3326;
    /* En sombre, admin (#94a3b8) et --isis-text-muted (#9aa7b4) étaient à 1,7 d'écart
       perceptuel : pas identiques à l'octet près, mais indiscernables à l'œil. Même
       correction qu'en clair, dans la même famille indigo : 8,3 d'écart minimum. */
    --isis-mod-admin:          #a3e635;  --isis-mod-admin-soft:     #1f2e0a;
    --isis-mod-gesproj:        #22d3ee;  --isis-mod-gesproj-soft:   #0c3540;
    /* Pendant sombre de l'ambre brûlé. La teinte s'éclaircit et se désature davantage que
       les autres modules (C 0,05) : la bande chaude y est déjà occupée par --isis-warning
       et --isis-accent, et toute variante plus saturée retombait à moins de 2
       d'écart de l'accent chaud. Écart minimum obtenu : 10,4 ; contraste 9,76:1. */
    --isis-mod-gesmaff:        #d8c0a1;  --isis-mod-gesmaff-soft:   #3e1f0e;
    --isis-mod-gesst:          #f472b6;  --isis-mod-gesst-soft:     #3a1228;
    --isis-mod-gesmat:         #a8a29e;  --isis-mod-gesmat-soft:    #292524;
    /* Pendants sombres des teintes propres posées en clair (2026-08-11). Mêmes
       collisions qu'en clair : gespark était gescom, gesmob était gesmaff, gesfac
       était gesst — à l'octet près sur les quatre valeurs. gesfac ne suit PAS le
       profil de clarté des autres (L 0,60 au lieu de 0,77) : à 0,77 sa teinte
       tombait à 1,8 d'écart de gesproj sombre, sous les 4,1 de la paire la plus
       serrée du thème ; assombrie, elle s'en écarte de 20,1 et rend encore 4,52:1
       sur la surface sombre. */
    --isis-mod-gespark:        #ee8edf;  --isis-mod-gespark-soft:   #371e33;
    --isis-mod-gesinfo:        #818cf8;  --isis-mod-gesinfo-soft:   #151641;
    --isis-mod-gesmob:         #ceb621;  --isis-mod-gesmob-soft:    #2f2906;
    --isis-mod-gesfac:         #0f919c;  --isis-mod-gesfac-soft:    #002f34;
    --isis-mod-gespla:         #2dd4bf;  --isis-mod-gespla-soft:    #0c352f;
    --isis-mod-gesqhse:        #c084fc;  --isis-mod-gesqhse-soft:   #2a1a3d;
    --isis-mod-ged:            #a5b4fc;  --isis-mod-ged-soft:       #1f1d4a;
    --isis-mod-monespace:      #f0803c;  --isis-mod-monespace-soft: #33200f;
    --isis-mod-m365:           #7cc3e8;  --isis-mod-m365-soft:      #0d2a3b;
    --isis-mod-recette:        #d3b48a;  --isis-mod-recette-soft:   #33261a;
    --isis-mod-default:        #94a3b4;  --isis-mod-default-soft:   #232b36;

    /* Ma planification — luminosité remontée pour fond sombre */
    --isis-planif-mobil:  oklch(0.72 0.10 218);   /* pétrole éclairci */
    --isis-planif-affect: oklch(0.72 0.13 285);    /* violet éclairci */
    /* Palette catégorielle éclaircie (texte sombre --isis-surface en thème sombre) */
    --isis-cat-1: oklch(0.72 0.10 218);
    --isis-cat-2: oklch(0.72 0.13 285);
    --isis-cat-3: oklch(0.72 0.12 155);
    --isis-cat-4: oklch(0.75 0.14 40);
    --isis-cat-5: oklch(0.72 0.13 260);
    --isis-cat-6: oklch(0.72 0.14 340);
    --isis-cat-7: oklch(0.74 0.11 130);
    --isis-cat-8: oklch(0.72 0.15 22);

    /* === Élévation : sur fond sombre l'ombre porte peu → opacités relevées === */
    --isis-elevation-1:     0 1px 2px rgba(0, 0, 0, 0.45),
                            0 10px 22px -6px rgba(0, 0, 0, 0.55);
    --isis-elevation-hover: 0 2px 6px rgba(0, 0, 0, 0.5),
                            0 18px 34px -8px rgba(0, 0, 0, 0.62);
    --isis-elevation-2:     0 28px 54px -14px rgba(0, 0, 0, 0.7);
    --isis-elevation-focus: 0 0 0 4px rgba(56, 190, 201, 0.32);   /* teal Nocturne */

    /* === Marque produit IRIS — déclinaison Nocturne ===
       Tuile nuit, barres éclaircies : l'ardoise du thème clair tomberait à 1,6:1 ici. */
    --isis-brand-ink:            #1e2732;
    --isis-brand-contour:        #2c3845;
    --isis-brand-barre:          #b8cbe0;
    --isis-brand-accent:         #f0803c;
    --isis-brand-ombre-proche:   rgba(0, 0, 0, .6);
    --isis-brand-ombre-portee:   rgba(0, 0, 0, .8);
    --isis-brand-biseau-haut:    rgba(255, 255, 255, .14);
    --isis-brand-biseau-bas:     rgba(0, 0, 0, .35);
    --isis-brand-ombre-barre:    rgba(0, 0, 0, .95);
    --isis-brand-lumiere-barre:  rgba(255, 255, 255, .3);
}

/* Bouton bascule thème dans le header (PoC). */
.isis-theme-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 38px;
    height: 38px;
    border: none;
    border-radius: var(--isis-radius, 8px);
    background: transparent;
    color: var(--isis-text-muted);
    cursor: pointer;
    transition: background var(--isis-motion-fast), color var(--isis-motion-fast);
}
.isis-theme-toggle:hover {
    background: var(--isis-surface-alt);
    color: var(--isis-text);
}
.isis-theme-toggle:focus-visible {
    outline: none;
    box-shadow: var(--isis-elevation-focus);
}

/* --- Page État des services (/admin/surveillance/services) --- */
.isis-svc-health-section { margin-top: 1rem; }
.isis-svc-health-section__title {
    font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.04em;
    color: var(--isis-text-muted); margin: 0 0 0.5rem; font-weight: 600;
}
.isis-svc-health-row {
    display: grid;
    grid-template-columns: 16px minmax(180px, 1.4fr) 110px 80px minmax(0, 2fr);
    align-items: center; gap: 0.75rem;
    padding: 0.6rem 0.75rem; border-radius: var(--isis-radius-sm);
    background: var(--isis-surface); box-shadow: var(--isis-elevation-1);
    margin-bottom: 0.4rem;
}
.isis-svc-health-row.is-down { box-shadow: inset 3px 0 0 0 var(--isis-danger), var(--isis-elevation-1); }
.isis-svc-health-row__dot {
    width: 12px; height: 12px; border-radius: 50%;
    box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.18);
}
.isis-svc-health-row__dot.is-healthy { background: var(--isis-success); }
.isis-svc-health-row__dot.is-degraded { background: var(--isis-warning); }
.isis-svc-health-row__dot.is-down { background: var(--isis-danger); }
.isis-svc-health-row__dot.is-unknown { background: var(--isis-text-muted); }
.isis-svc-health-row__name { font-weight: 600; }
.isis-svc-health-row__status { color: var(--isis-text-muted); }
.isis-svc-health-row__latency {
    font-family: var(--isis-font-mono, monospace);
    font-variant-numeric: tabular-nums; text-align: right; color: var(--isis-text-muted);
}
.isis-svc-health-row__message {
    color: var(--isis-text-muted); font-size: 0.85rem;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* ── Config temps centralisée (onglet « Temps de travail » de la fiche entreprise, 0405) ── */
.isis-config-effective {
    font-weight: 400;
    font-size: 0.82rem;
    color: var(--isis-text-muted);
}
.isis-config-badge {
    display: inline-block;
    margin-left: 0.4rem;
    padding: 0.05rem 0.45rem;
    border-radius: var(--isis-radius-pill, 999px);
    font-size: 0.68rem;
    font-weight: 600;
    vertical-align: middle;
}
.isis-config-badge.is-on  { background: color-mix(in srgb, var(--isis-success) 16%, transparent); color: var(--isis-success); }
.isis-config-badge.is-off { background: var(--isis-surface-alt); color: var(--isis-text-muted); }
.isis-config-baremes {
    display: flex;
    align-items: center;
    gap: 0.55rem;
    margin-top: 1.1rem;
    padding: 0.7rem 0.9rem;
    background: var(--isis-surface-alt);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius);
    font-size: 0.85rem;
    color: var(--isis-text-muted);
}
.isis-config-baremes .isis-text-link { margin-left: auto; white-space: nowrap; }
.isis-grid--regime-history .isis-grid__head,
.isis-grid--regime-history .isis-grid__row {
    grid-template-columns: 1.1fr 1.4fr 1fr 0.9fr 0.9fr 1.2fr;
}

/* « Ce qui est accordé » / « Ce qui est contrôlé » — règles FORFAIT/ALERTE effectives, onglet
   Temps de travail de la fiche entreprise. Séparateurs horizontaux 1px seulement (pas de liseré
   gauche, règle 2026-07-18) : le fond reste neutre, la provenance se lit sur le badge.
   Harmonisation typo 2026-08-03 : ces 2 sections avaient été ajoutées (36c1604b) avec l'échelle
   par défaut de .isis-rich-section (empruntée aux dashboards — titre 1rem, sous-titre muted,
   badges RadzenBadge par défaut), visiblement étrangère au reste de l'onglet, construit sur
   .isis-detail-summary__title (eyebrow 0.65rem) et .isis-config-badge (0.68rem). Les règles
   .isis-config-regles-section ci-dessous ramènent les 2 sections sur cette échelle plutôt que
   d'en inventer une 3e ; valeurs et couleurs copiées littéralement de .isis-detail-summary__title
   / .isis-detail-summary__hint / .isis-config-badge, pas de nouveau nombre. */
.isis-regle-summary-list { display: flex; flex-direction: column; }
.isis-regle-summary-row {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 1rem;
    padding: 0.55rem 0;
    /* --isis-border-soft, pas --isis-border : c'est un séparateur de ligne dans une liste
       (même rôle que .isis-grid__row, cf. DESIGN.md), pas un filet de carte/conteneur.
       L'ancienne valeur --isis-border faisait un trait plus marqué que celui de la grille
       « Historique des versions » juste en dessous dans ce même onglet. */
    border-bottom: 1px solid var(--isis-border-soft);
}
.isis-regle-summary-row:last-child { border-bottom: 0; }
.isis-regle-summary-row__main { display: flex; flex-direction: column; gap: 0.15rem; min-width: 0; }
/* 0.85rem, pas 0.88 : même échelle que la valeur d'un RenderField (.isis-detail-grid__val)
   dont ce libellé de règle tient le rôle — c'est le contenu informatif de la ligne. */
.isis-regle-summary-row__label { font-weight: 600; font-size: 0.85rem; color: var(--isis-text); }
/* 0.72rem + text-soft, pas 0.82rem + text-muted : une phrase de condition est une légende
   secondaire, au même rang que .isis-detail-grid__label / .isis-detail-field__help — pas un
   second niveau de contenu principal. text-soft (tertiaire) partout dans le reste de l'onglet,
   jamais text-muted (secondaire, plus foncé) pour ce rôle. */
.isis-regle-summary-row__desc { font-size: 0.72rem; color: var(--isis-text-soft); line-height: 1.45; }
.isis-regle-summary-row__desc code {
    font-family: var(--isis-font-mono, monospace);
    font-size: 0.78rem;
    padding: 0.05rem 0.3rem;
    background: var(--isis-surface-alt);
    border-radius: 4px;
}
.isis-regle-summary-row__meta { display: flex; align-items: center; gap: 0.4rem; flex-shrink: 0; padding-top: 0.1rem; }
/* Badges de provenance/sévérité de ligne : au gabarit RadzenBadge par défaut (0.75rem,
   padding 0.125rem/0.25rem — cf. --rz-badge-*), ils lisaient plus gros que .isis-config-badge,
   le seul autre badge de cet onglet (0.68rem). Repris ici, pas la taille de l'éditeur de règles
   (RegimeRegleTab, badges non retaillés) d'où ces lignes avaient copié leur markup. */
.isis-regle-summary-row__meta .rz-badge {
    font-size: 0.68rem;
    padding: 0.08rem 0.45rem;
    line-height: 1.3;
}

/* Titre/sous-titre des 2 sections — .isis-rich-section standard vient des dashboards (titre
   1rem/600, sous-titre 0.82rem muted, séparateur sous le header) : rescellé ici sur l'eyebrow
   .isis-detail-summary__title déjà utilisé pour chaque colonne de ce même onglet (« Régime &
   base », « Majorations »…), <h2> gardé pour l'ordre des titres (audit a11y 36c1604b). */
.isis-config-regles-section.isis-rich-section--flush {
    /* 1.2rem : même rupture de bloc que « Historique des versions » plus bas dans cet onglet,
       pas le 0.6rem générique de --flush (pensé pour des sections déjà rapprochées ailleurs). */
    margin-top: 1.2rem;
}
.isis-config-regles-section .isis-rich-section__header {
    margin-bottom: 0;
    padding-bottom: 0;
    border-bottom: 0;
}
.isis-config-regles-section .isis-rich-section__title {
    font-size: 0.65rem;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    /* text-soft, pas text-muted (audit a11y 2026-08-03, revu) : c'est la couleur de
       .isis-detail-summary__title lui-même, la référence posée pour cette harmonisation
       (« Régime & base », « Majorations »… juste au-dessus, même fichier). Basculer isolément
       ces 2 titres en text-muted les aurait rendus plus sombres que leurs voisins immédiats —
       recréant, sur la couleur, exactement le défaut de « deux mains différentes » que cette
       harmonisation corrige sur la taille. À l'époque le token --isis-text-soft en thème sombre
       tombait à ~4.0-4.2:1 (borderline, WCAG 1.4.3) : dette notée « à corriger au niveau du
       token, pas ligne à ligne ». RÉSOLU 2026-08-03 : --isis-text-soft relevé à #8593a1 en
       sombre (≥4.5:1 sur les 3 fonds réels, cf. son commentaire dans :root[data-theme="dark"])
       — ces 2 titres passent maintenant AA sans aucun changement local. */
    color: var(--isis-text-soft);
    margin: 0 0 0.2rem;
}
.isis-config-regles-section .isis-rich-section__subtitle {
    font-size: 0.7rem;
    line-height: 1.4;
    color: var(--isis-text-soft);
}

/* ── Dialog « Configuration du temps » — pattern cartes par disposition (0405) ── */
.isis-config-dialog { display: flex; flex-direction: column; gap: 0.85rem; }

/* Bandeau supérieur : période d'application + régime (toujours actif) */
.isis-config-band {
    background: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 7%, var(--isis-surface));
    border: 1px solid color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 22%, var(--isis-border));
    border-radius: var(--isis-radius-lg, 12px);
    padding: 0.9rem 1rem;
}
.isis-config-band__head { display: flex; align-items: flex-start; gap: 0.7rem; margin-bottom: 0.8rem; }
.isis-config-band__grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(175px, 1fr));
    gap: 0.7rem 1rem;
    align-items: end;
}
.isis-config-band__grid .field { margin: 0; }
.isis-config-band__note {
    display: flex; align-items: center; gap: 0.4rem;
    margin-top: 0.75rem; font-size: 0.78rem; color: var(--isis-text-muted);
}
.isis-config-band__note .rzi, .isis-config-band__note .notranslate { font-size: 1rem; }

/* Carte de disposition (bloc activable) */
.isis-config-card {
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-lg, 12px);
    padding: 0.85rem 1rem;
    background: var(--isis-surface);
    transition: border-color 0.15s, background 0.15s, opacity 0.15s;
}
.isis-config-card.is-on {
    /* Carte active = filet périmétrique teinté module (ex-bande gauche 3px, refonte
       2026-06-14) ; l'état on/off reste porté par le toggle + l'état is-off. */
    background: var(--isis-card-mod-bg);
    border-color: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 32%, transparent);
    box-shadow: var(--isis-elevation-1, 0 1px 3px rgba(0,0,0,0.06));
}
.isis-config-card.is-off { background: var(--isis-surface-alt); border-style: dashed; }
.isis-config-card.is-off .isis-config-card__icon { opacity: 0.55; }
.isis-config-card.is-off .isis-config-card__title { color: var(--isis-text-muted); }

.isis-config-card__head { display: flex; align-items: center; gap: 0.7rem; }
.isis-config-card__icon {
    flex: 0 0 auto;
    width: 36px; height: 36px;
    display: grid; place-items: center;
    border-radius: 50%;
    background: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 14%, transparent);
    color: var(--isis-current-mod, var(--isis-accent));
}
.isis-config-card__icon .rzi, .isis-config-card__icon .notranslate { font-size: 1.25rem; }
.isis-config-card__heading { flex: 1 1 auto; min-width: 0; }
.isis-config-card__title { font-size: 0.95rem; font-weight: 600; color: var(--isis-text); }
.isis-config-card__subtitle { font-size: 0.79rem; color: var(--isis-text-muted); margin-top: 0.1rem; }
.isis-config-card__body { margin-top: 0.85rem; display: flex; flex-direction: column; gap: 0.6rem; }
.isis-config-card__off {
    margin-top: 0.55rem; padding-left: calc(36px + 0.7rem);
    font-size: 0.8rem; font-style: italic; color: var(--isis-text-muted);
}
.isis-config-card__hint {
    display: flex; align-items: center; gap: 0.45rem;
    padding: 0.5rem 0.7rem;
    background: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 8%, var(--isis-surface-alt));
    border-radius: var(--isis-radius, 8px);
    font-size: 0.78rem; color: var(--isis-text);
}
.isis-config-card__hint .rzi, .isis-config-card__hint .notranslate { font-size: 1rem; color: var(--isis-current-mod, var(--isis-accent)); }

/* ── Dialog config temps — refonte « onglets par thème + récap live » (2026-06-25) ── */
.isis-config-dialog--tabbed { gap: 0; padding: 0; }

/* Sous-sections en cartes à l'intérieur d'un onglet (redesign contenu 2026-06-26) */
.isis-config-section { margin-bottom: 0.85rem; }
.isis-config-section:last-child { margin-bottom: 0; }
.isis-config-card__hint.isis-config-section { margin-top: 0; }
.isis-config-shell {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 296px;
    gap: 1.1rem;
    align-items: start;
}
.isis-config-main { min-width: 0; }
.isis-config-tabs { margin-bottom: 1rem; }
/* Pastille on/off sur l'onglet d'un bloc activable */
.isis-config-tab-dot {
    width: 7px; height: 7px; border-radius: 50%;
    margin-left: 0.15rem;
}
.isis-config-tab-dot.is-on  { background: var(--isis-success); }
.isis-config-tab-dot.is-off { background: var(--isis-border); }

.isis-config-panel { min-height: 232px; }
.isis-config-panel.is-hidden { display: none; }
.isis-config-panel__intro {
    font-size: 0.82rem; color: var(--isis-text-muted);
    margin-bottom: 1rem; line-height: 1.45;
}
.isis-config-panel__intro strong { color: var(--isis-text); font-weight: 600; }
.isis-config-panel__switch {
    display: flex; align-items: center; gap: 0.8rem;
    padding-bottom: 0.85rem; margin-bottom: 1rem;
    border-bottom: 1px solid var(--isis-border);
}
.isis-config-panel__switch > div:first-child { flex: 1 1 auto; min-width: 0; }
.isis-config-panel__title { font-size: 0.95rem; font-weight: 600; color: var(--isis-text); }
.isis-config-panel__sub { font-size: 0.79rem; color: var(--isis-text-muted); margin-top: 0.1rem; }
.isis-config-panel__off {
    padding: 0.9rem 1rem;
    background: var(--isis-surface-alt);
    border: 1px dashed var(--isis-border);
    border-radius: var(--isis-radius, 8px);
    font-size: 0.82rem; font-style: italic; color: var(--isis-text-muted);
}
.isis-config-panel .isis-config-card__hint { margin-bottom: 1rem; }

/* Colonne récap live */
.isis-config-recap {
    position: sticky; top: 0;
    background: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 5%, var(--isis-surface-alt));
    border: 1px solid color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 18%, var(--isis-border));
    border-radius: var(--isis-radius-lg, 12px);
    padding: 0.9rem 1rem;
}
.isis-config-recap__head {
    display: flex; align-items: center; gap: 0.4rem;
    font-size: 0.9rem; font-weight: 600; color: var(--isis-text);
}
.isis-config-recap__head .rzi, .isis-config-recap__head .notranslate {
    font-size: 1.05rem; color: var(--isis-current-mod, var(--isis-accent));
}
.isis-config-recap__eff {
    font-size: 0.74rem; color: var(--isis-text-muted);
    margin: 0.15rem 0 0.7rem;
}
.isis-config-recap__group { padding: 0.55rem 0; border-top: 1px solid var(--isis-border); }
.isis-config-recap__group:first-of-type { border-top: none; padding-top: 0; }
.isis-config-recap__gtitle {
    display: flex; align-items: center; gap: 0.4rem;
    font-size: 0.7rem; font-weight: 600; letter-spacing: 0.03em; text-transform: uppercase;
    color: var(--isis-text-muted); margin-bottom: 0.35rem;
}
.isis-config-recap__state {
    font-size: 0.64rem; font-weight: 600; letter-spacing: 0;
    padding: 0.02rem 0.4rem; border-radius: var(--isis-radius-pill, 999px); text-transform: none;
}
.isis-config-recap__state.is-on  { background: color-mix(in srgb, var(--isis-success) 16%, transparent); color: var(--isis-success); }
.isis-config-recap__state.is-off { background: var(--isis-surface); color: var(--isis-text-muted); }
.isis-config-recap__row {
    display: flex; align-items: baseline; justify-content: space-between; gap: 0.6rem;
    font-size: 0.79rem; padding: 0.1rem 0;
}
.isis-config-recap__row > span { color: var(--isis-text-muted); }
.isis-config-recap__row > b {
    font-weight: 600; color: var(--isis-text);
    font-family: var(--isis-font-mono, ui-monospace, monospace); font-variant-numeric: tabular-nums;
    text-align: right;
}
.isis-config-recap__chips { display: flex; flex-wrap: wrap; gap: 0.3rem; margin-bottom: 0.3rem; }
.isis-config-recap__chip {
    font-size: 0.72rem; font-weight: 600;
    padding: 0.08rem 0.45rem; border-radius: var(--isis-radius-pill, 999px);
    background: var(--isis-surface); border: 1px solid var(--isis-border); color: var(--isis-text);
    font-variant-numeric: tabular-nums;
}
/* Diff live : valeur modifiée mais pas encore enregistrée (fond surligné, accent chaud) */
.isis-config-recap__row.is-dirty {
    background: color-mix(in srgb, var(--isis-accent) 14%, transparent);
    border-radius: var(--isis-radius-sm, 5px);
    margin-left: -0.4rem; margin-right: -0.4rem;
    padding-left: 0.4rem; padding-right: 0.4rem;
}
.isis-config-recap__row.is-dirty > span { color: var(--isis-text); }
.isis-config-recap__chip.is-dirty,
.isis-config-recap__state.is-dirty {
    background: color-mix(in srgb, var(--isis-accent) 18%, transparent);
    border-color: color-mix(in srgb, var(--isis-accent) 40%, transparent);
    color: var(--isis-accent);
}
.isis-config-recap__eff.is-dirty {
    color: var(--isis-accent); font-weight: 600;
}
.isis-config-recap__legend {
    display: flex; align-items: center; gap: 0.4rem;
    margin-top: 0.7rem; padding-top: 0.55rem; border-top: 1px dashed var(--isis-border);
    font-size: 0.7rem; color: var(--isis-text-muted);
}
.isis-config-recap__legend-dot {
    width: 10px; height: 10px; border-radius: var(--isis-radius-sm, 4px); flex: 0 0 auto;
    background: color-mix(in srgb, var(--isis-accent) 18%, transparent);
}

.isis-config-actions { margin-top: 1.1rem; padding-top: 0.9rem; border-top: 1px solid var(--isis-border); }
/* Note affichée dans la barre Annuler/Enregistrer sur l'onglet Règles seulement — flex-grow pour
   occuper l'espace libre à gauche (les boutons restent groupés à droite) et min-width:0 pour que
   le texte puisse s'enrouler au lieu de forcer un débordement horizontal. */
.isis-config-actions__note {
    display: flex; align-items: center; gap: 0.4rem;
    flex: 1 1 auto; min-width: 0;
    font-size: 0.82rem; color: var(--isis-text-muted);
}
.isis-config-actions__note .rzi { font-size: 1rem; color: var(--isis-current-mod, var(--isis-accent)); flex: 0 0 auto; }

@media (max-width: 880px) {
    .isis-config-shell { grid-template-columns: 1fr; }
    .isis-config-recap { position: static; }
}

/* ── Bilan annuel (éditeur de feuille de temps, régime annualisé — 0406) ── */
.isis-annual-recap { margin-top: .7rem; padding-top: .55rem; border-top: 1px dashed var(--isis-border); }
.isis-annual-recap__toggle {
    display: inline-flex; align-items: center; gap: .4rem;
    background: var(--isis-surface-alt); border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius, 8px); padding: .35rem .7rem;
    font-size: .82rem; color: var(--isis-text); cursor: pointer;
}
.isis-annual-recap__toggle:hover:not([aria-disabled="true"]) { border-color: var(--isis-current-mod, var(--isis-accent)); }
.isis-annual-recap__toggle[aria-disabled="true"] { opacity: .6; cursor: default; }
.isis-annual-recap__head {
    display: flex; align-items: center; justify-content: space-between;
    font-size: .85rem; font-weight: 600; color: var(--isis-text);
}
.isis-annual-recap__sub { font-weight: 400; font-size: .78rem; color: var(--isis-text-muted); margin-left: .25rem; }
.isis-annual-recap__refresh {
    background: none; border: none; cursor: pointer; color: var(--isis-text-muted); padding: .2rem; line-height: 0;
}
.isis-annual-recap__refresh:hover:not([aria-disabled="true"]) { color: var(--isis-current-mod, var(--isis-accent)); }
.isis-annual-recap__refresh[aria-disabled="true"] { opacity: .6; cursor: default; }

/* ── Alerte garde-fous (bornes de planning dépassées, éditeur feuille — 0405) ── */
.isis-gardefou-alert {
    margin: .55rem 0;
    padding: .6rem .8rem;
    background: color-mix(in srgb, var(--isis-warning) 12%, var(--isis-surface));
    border: 1px solid color-mix(in srgb, var(--isis-warning) 38%, var(--isis-border));
    border-radius: var(--isis-radius, 8px);
}
.isis-gardefou-alert__head { display: flex; align-items: center; gap: .45rem; font-size: .85rem; color: var(--isis-text); }
.isis-gardefou-alert__head .rzi, .isis-gardefou-alert__head .notranslate { color: var(--isis-warning); }
.isis-gardefou-alert__count {
    margin-left: .1rem; padding: .02rem .4rem; border-radius: 999px;
    background: var(--isis-warning); color: #fff; font-size: .7rem; font-weight: 600;
}
.isis-gardefou-alert__list { margin: .35rem 0 0; padding-left: 1.5rem; font-size: .8rem; color: var(--isis-text); }
.isis-gardefou-alert__list li { margin: .1rem 0; }

/* ── Export paie (variables de paie par entreprise/mois — SIRH) ── */
.isis-export-filters { display: flex; align-items: flex-end; gap: .9rem; flex-wrap: wrap; }
.isis-export-summary {
    display: flex; align-items: center; gap: 1rem; margin: .8rem 0 .4rem;
    font-size: .88rem; color: var(--isis-text);
}
.isis-export-summary__missing { display: inline-flex; align-items: center; gap: .35rem; color: var(--isis-warning); font-weight: 600; }
.isis-table-scroll { overflow-x: auto; border: 1px solid var(--isis-border); border-radius: var(--isis-radius, 8px); }
.isis-export-table { width: 100%; border-collapse: collapse; font-size: .82rem; white-space: nowrap; }
.isis-export-table thead th {
    position: sticky; top: 0; background: var(--isis-surface-alt);
    text-align: left; font-weight: 600; padding: .5rem .7rem; border-bottom: 1px solid var(--isis-border);
    text-transform: uppercase; font-size: .7rem; letter-spacing: .02em; color: var(--isis-text-muted);
}
.isis-export-table td { padding: .45rem .7rem; border-bottom: 1px solid var(--isis-border-soft); }
.isis-export-table tbody tr:hover { background: var(--isis-surface-alt); }
.isis-export-table .num { text-align: right; font-variant-numeric: tabular-nums; }
.isis-export-missing {
    margin-top: 1rem; padding: .7rem .9rem;
    background: color-mix(in srgb, var(--isis-warning) 10%, var(--isis-surface));
    border: 1px solid color-mix(in srgb, var(--isis-warning) 35%, var(--isis-border));
    border-radius: var(--isis-radius, 8px);
}
/* margin: 0 — posé le 2026-08-06 : ImportDroitsDialog en fait un <h3> (audit a11y, association
   du titre à sa liste via aria-labelledby) ; ExportPaiePage continue de poser la classe sur un
   <div>, où la marge du navigateur est déjà 0 par défaut, donc la règle ne change rien pour lui. */
.isis-export-missing__head { display: flex; align-items: center; gap: .4rem; font-weight: 600; font-size: .85rem; margin: 0; }
.isis-export-missing__head .rzi, .isis-export-missing__head .notranslate { color: var(--isis-warning); }
.isis-export-missing ul { margin: .4rem 0 0; padding-left: 1.4rem; font-size: .82rem; }
.isis-export-missing__reason { color: var(--isis-text-muted); font-style: italic; }

/* ── Import/Export config temps (onglet Temps de travail) ── */
.isis-tab-header__actions { display: flex; align-items: center; gap: .5rem; }
.isis-import-preview {
    margin: .7rem 0; padding: .7rem .9rem;
    background: var(--isis-surface-alt); border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius, 8px);
}
.isis-import-preview__head { display: flex; align-items: center; gap: .4rem; font-weight: 600; font-size: .85rem; margin-bottom: .5rem; }
.isis-import-preview__head .rzi, .isis-import-preview__head .notranslate { color: var(--isis-current-mod, var(--isis-accent)); }
.isis-import-error {
    display: flex; align-items: center; gap: .4rem; margin: .6rem 0;
    padding: .55rem .8rem; font-size: .82rem;
    background: color-mix(in srgb, var(--isis-danger) 10%, var(--isis-surface));
    border: 1px solid color-mix(in srgb, var(--isis-danger) 35%, var(--isis-border));
    border-radius: var(--isis-radius, 8px); color: var(--isis-text);
}
.isis-import-error .rzi, .isis-import-error .notranslate { color: var(--isis-danger); }
.isis-file-input { font-size: .85rem; }

/* Toggle sensible (écrasement identité) — accent danger discret */
.isis-import-danger-switch {
    padding: .5rem .7rem; border-radius: var(--isis-radius, 8px);
    background: color-mix(in srgb, var(--isis-danger) 7%, transparent);
    border: 1px solid color-mix(in srgb, var(--isis-danger) 22%, var(--isis-border));
}
.isis-import-danger-switch .rzi, .isis-import-danger-switch .notranslate { color: var(--isis-danger); }

/* ── Reprise des droits entre tenants (F2, /admin/roles) ──
   Le plan peut porter une longue liste de NonPosables, jamais tronquée (Task 6) : c'est le CORPS
   du dialogue qui doit défiler, pas la liste elle-même — même recette que
   .isis-module-choice-dialog / .isis-mob-dialog (le thème Radzen pose overflow:hidden sur
   .rz-dialog sans overflow sur .rz-dialog-content, donc les deux règles vont ensemble). */
.rz-dialog.isis-import-droits-dialog { max-height: 90vh; }
.rz-dialog.isis-import-droits-dialog .rz-dialog-content { overflow-y: auto; min-height: 0; }

/* ── Carnet d'adresses tiers (hiérarchie SIREN/SIRET, migration 0409) ── */
.isis-tiers-addr-list { display: flex; flex-direction: column; gap: 0.35rem; margin-bottom: 0.6rem; }
.isis-tiers-addr-row {
    display: flex; align-items: center; gap: 0.5rem;
    padding: 0.4rem 0.55rem; border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-sm); background: var(--isis-surface-alt);
}
.isis-tiers-addr-row__text { flex: 1 1 auto; min-width: 0; font-size: 0.85rem; color: var(--isis-text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.isis-tiers-addr-add {
    margin-top: 0.5rem; padding: 0.7rem; border: 1px dashed var(--isis-border);
    border-radius: var(--isis-radius-sm); background: var(--isis-surface);
    display: flex; flex-direction: column; gap: 0.5rem;
}

/* ── Carnet d'adresses sur la fiche tiers (migration 0409) ── */
.isis-grid--tiers-addresses .isis-grid__head,
.isis-grid--tiers-addresses .isis-grid__row {
    grid-template-columns: 120px minmax(110px, 1fr) minmax(200px, 2fr) 130px 70px 120px;
    min-width: 800px;
}
.isis-grid--tiers-addresses .isis-grid__row { cursor: default; }
.isis-grid--tiers-addresses .isis-grid__col-actions { display: flex; gap: 0.15rem; justify-content: flex-end; }

/* ── Bouton « Aide du module » en pied de sous-navigation (tâche 7, spec 2026-09-19
   aide harmonisée) — juste au-dessus de la signature de marque. ── */
.isis-subnav__help {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    margin: 0.4rem 0.6rem 0;
    padding: 0.5rem 0.6rem;
    border-radius: var(--isis-radius-sm);
    color: var(--isis-text-soft);
    font-size: 0.82rem;
    text-decoration: none;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.isis-subnav__help:hover {
    background-color: var(--isis-surface-alt);
    color: var(--isis-text);
}
.isis-subnav__help:focus-visible {
    outline: 2px solid var(--isis-current-mod);
    outline-offset: 2px;
}
.isis-subnav--collapsed .isis-subnav__help {
    justify-content: center;
    margin: 0.4rem auto 0;
}

/* ── Signature de marque en pied de sous-navigation (Phase 1 « UpDate the System ») ── */
.isis-subnav__signature {
    margin-top: auto;                 /* pousse la signature en bas si l'aside est en flex-column */
    /* Filet retiré 2026-09-05 : il retombait juste sous le bord bas du panneau menu. */
    padding: 0.5rem 1rem 0.7rem;
    font-family: var(--isis-cockpit-mono);
    font-size: 0.62rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    color: var(--isis-text-muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* =============================================================================
   THÈME « UpDate · Blueprint » — overlay de marque (Phase 2, 2026-06-14)
   ----------------------------------------------------------------------------
   Activé par data-brand="update" sur <html>, COMPOSABLE avec data-theme
   (clair/sombre). N'OVERRIDE QUE --isis-signal et les rayons + des utilities
   motif scopées. Ne touche NI l'accent (bleu ardoise hérité de :root et de
   :root[data-theme="dark"] depuis le 2026-09-22 — l'ex-pétrole oklch 222 est
   retiré), NI les couleurs par module (--isis-mod-*), NI la sémantique, NI les
   surfaces.
   ============================================================================= */

/* — UpDate, mode clair (et base commune : rayons valables aussi en sombre) — */
:root[data-brand="update"] {
    /* Signal « à jour / en direct » — aqua. Usage GRAPHIQUE (pastilles, halos,
       filets), pas texte courant. */
    --isis-signal:        #0fb5a8;
    --isis-signal-soft:   #d6f7f2;

    /* Rayons resserrés (mode-indépendant → définis ici, valent aussi en sombre) */
    --isis-radius:        6px;
    --isis-radius-sm:     4px;
    --isis-radius-lg:     10px;
}

/* — UpDate, mode sombre : on ne re-mappe QUE le signal (accent, surfaces et
     texte viennent du bloc :root[data-theme="dark"]). Les rayons restent ceux
     du bloc UpDate clair ci-dessus. — */
:root[data-brand="update"][data-theme="dark"] {
    --isis-signal:        #2dd4bf;
    --isis-signal-soft:   #0c3a35;
}

/* — Signature TOUJOURS ACTIVE : grille « blueprint » en fond du contenu sous
     UpDate. Rend le thème immédiatement reconnaissable partout, en clair comme
     en sombre. Couleurs module PRÉSERVÉES (grille neutre dérivée de l'accent
     générique à faible opacité). N'ajoute QUE background-image → la teinte
     background-color de .isis-shell__content est conservée. — */
:root[data-brand="update"] .isis-shell__content {
    background-image:
        linear-gradient(color-mix(in srgb, var(--isis-accent) 15%, transparent) 1px, transparent 1px),
        linear-gradient(90deg, color-mix(in srgb, var(--isis-accent) 15%, transparent) 1px, transparent 1px);
    background-size: 16px 16px;
}

/* — Utilities motif, INERTES hors UpDate (toutes préfixées data-brand=update) — */

/* Grille hairline « blueprint » en fond de conteneur (opt-in par classe) */
:root[data-brand="update"] .isis-blueprint-grid {
    background-image:
        linear-gradient(color-mix(in srgb, var(--isis-accent) 8%, transparent) 1px, transparent 1px),
        linear-gradient(90deg, color-mix(in srgb, var(--isis-accent) 8%, transparent) 1px, transparent 1px);
    background-size: 16px 16px;
}

/* Pastille « signal » (élément vivant / à jour) */
:root[data-brand="update"] .isis-signal-dot {
    display: inline-block;
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--isis-signal);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--isis-signal) 25%, transparent);
}

/* Valeurs KPI en monospace tabulaire sous UpDate (grammaire ingénierie) */
:root[data-brand="update"] .isis-kpi-card__value {
    font-family: var(--isis-cockpit-mono);
    font-variant-numeric: tabular-nums;
}

/* ── Page /preferences (Phase 3 — sélecteur de thème) ── */
.isis-pref-card { max-width: 560px; margin-top: 1rem; }
.isis-pref-card__title { font-size: 1rem; font-weight: 700; margin: 0 0 1rem; }
.isis-pref-row { display: flex; flex-direction: column; gap: 0.4rem; margin-bottom: 1.25rem; }
.isis-pref-row--vide { display: none; }
.isis-pref-row__label {
    font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.05em;
    color: var(--isis-text-muted); font-weight: 600;
}
.isis-pref-actions { margin-top: 0.5rem; }
.isis-pref-hint { font-size: 0.8rem; color: var(--isis-text-muted); margin-top: 0.75rem; }

/* Rapprochement dossiers Silae ↔ entreprises ISIS par SIRET (page intégration RH) */
.isis-reconcile {
    margin-top: 1rem; padding-top: 1rem; border-top: 1px solid var(--isis-border);
    display: flex; flex-direction: column; gap: 0.75rem;
}
.isis-reconcile__head {
    display: flex; align-items: flex-start; justify-content: space-between;
    gap: 1rem; flex-wrap: wrap;
}
.isis-reconcile__title { font-size: 1rem; font-weight: 600; margin: 0; }
.isis-reconcile__subtitle { font-size: 0.82rem; color: var(--isis-text-muted); margin: 0.15rem 0 0; }
.isis-reconcile__summary { display: flex; gap: 0.5rem; flex-wrap: wrap; }
.isis-grid--silae-reconcile .isis-grid__head,
.isis-grid--silae-reconcile .isis-grid__row {
    grid-template-columns: 100px minmax(150px, 1.2fr) 150px 110px 80px minmax(140px, 1fr) 110px 230px;
}
.isis-recon-actions { display: flex; gap: 0.35rem; flex-wrap: wrap; }

/* .isis-grid--sync-runs — variante pour /sirh/parametres/integration (journal des synchros),
   sortie de son <style> inline (2026-09-03) : appartient à CETTE page uniquement. */
.isis-grid--sync-runs .isis-grid__head,
.isis-grid--sync-runs .isis-grid__row {
    grid-template-columns: 160px minmax(140px, 1fr) 90px 90px 90px;
    min-width: 600px;
}
.isis-grid--sync-runs .is-danger { color: var(--isis-danger); font-weight: 600; }

/* Dialog d'import des absences Silae */
.isis-silae-abspull { display: flex; flex-direction: column; gap: 0.85rem; min-width: 0; max-width: 100%; }
.isis-silae-abspull__context { font-size: 0.85rem; color: var(--isis-text-muted); margin: 0; }
.isis-silae-abspull__period { display: flex; align-items: center; gap: 0.5rem; font-size: 0.85rem; }
.isis-silae-abspull__hint { font-size: 0.82rem; color: var(--isis-text-muted); margin: 0; }
.isis-silae-abspull__summary { display: flex; gap: 0.5rem; flex-wrap: wrap; }
.isis-silae-abspull__actions { display: flex; gap: 0.5rem; justify-content: flex-end; margin-top: 0.25rem; }
.isis-silae-abspull .isis-grid { max-height: 48vh; overflow-y: auto; overflow-x: hidden; min-width: 0; width: 100%; }
.isis-grid--silae-abspull-map .isis-grid__head,
.isis-grid--silae-abspull-map .isis-grid__row {
    grid-template-columns: 96px 64px minmax(0, 1fr);
}
.isis-silae-abspull__create { display: flex; flex-direction: column; gap: 0.3rem; margin-top: 0.35rem; }

/* Dialog d'import des salariés Silae */
.isis-silae-pull { display: flex; flex-direction: column; gap: 0.85rem; }
.isis-silae-pull__context { font-size: 0.85rem; color: var(--isis-text-muted); margin: 0; }
.isis-silae-pull__summary { display: flex; gap: 0.5rem; flex-wrap: wrap; }
.isis-silae-pull__empty { font-size: 0.85rem; color: var(--isis-text-muted); }
.isis-silae-pull__anomalies,
.isis-silae-pull__disappeared { margin-top: 0.75rem; padding: 0.6rem 0.75rem; border-radius: var(--isis-radius-sm); background: var(--isis-surface-alt); }
.isis-silae-pull__section-title { font-size: 0.8rem; font-weight: 600; color: var(--isis-text); margin-bottom: 0.35rem; }
.isis-silae-pull__list { margin: 0; padding-left: 1rem; display: flex; flex-direction: column; gap: 0.25rem; font-size: 0.82rem; color: var(--isis-text); }
.isis-silae-pull__hint { margin-top: 0.4rem; font-size: 0.78rem; color: var(--isis-text-muted); }
.isis-silae-pull__actions { display: flex; gap: 0.5rem; justify-content: flex-end; margin-top: 0.25rem; }
.isis-silae-pull .isis-grid { max-height: 50vh; overflow-y: auto; }
.isis-grid--silae-pull .isis-grid__head,
.isis-grid--silae-pull .isis-grid__row {
    grid-template-columns: 110px minmax(160px, 1fr) 130px;
}

/* ────────────────────────────────────────────────────────────────────────────
   Matrice de compétences (/sirh/competences/matrice)
   Tableau croisé collaborateurs × compétences. 1ʳᵉ colonne + en-têtes gelés,
   cellule = niveau de maîtrise (heatmap) + pastille de péremption. Le markup
   provient de CompetenceMatricePage.razor ; le rendu cible le mockup validé
   docs/mockups/sirh-competences-matrice.html.
   ──────────────────────────────────────────────────────────────────────────── */

/* Conteneur scrollable (la card master borde déjà l'ensemble). */
.isis-mx-wrap {
    overflow: auto;
    max-height: calc(100vh - 320px);
    flex: 1 1 auto;
    min-height: 0;
}

table.isis-mx {
    border-collapse: separate;
    border-spacing: 0;
    width: max-content;
    min-width: 100%;
    font-size: 12px;
    color: var(--isis-text);
}
table.isis-mx th,
table.isis-mx td {
    border-bottom: 1px solid var(--isis-border-soft);
    border-right: 1px solid var(--isis-border-soft);
}

/* ── Coin haut-gauche (libellé « Collaborateur ») : gelé sur les 2 axes ── */
.isis-mx__corner {
    position: sticky;
    left: 0;
    top: 0;
    z-index: 9;
    background: var(--isis-surface);
    padding: 8px 12px;
    text-align: left;
    vertical-align: bottom;
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--isis-text-muted);
    border-right: 1px solid var(--isis-border);
    border-bottom: 1px solid var(--isis-border);
    min-width: 208px;
}

/* ── Ligne 1 d'en-tête : groupes de catégorie (gelée en haut) ── */
.isis-mx__grp {
    position: sticky;
    top: 0;
    z-index: 6;
    background: var(--isis-surface-alt);
    padding: 7px 10px;
    text-align: center;
    font-size: 11px;
    font-weight: 680;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--isis-text);
    border-bottom: 1px solid var(--isis-border);
}
.isis-mx__grp.is-reg   { background: var(--isis-warning-soft);   color: var(--isis-warning); }
.isis-mx__grp.is-tec   { background: var(--isis-mod-sirh-soft);  color: var(--isis-mod-sirh); }
.isis-mx__grp.is-lng   { background: color-mix(in srgb, var(--isis-info, #1d4ed8) 12%, var(--isis-surface)); color: var(--isis-info, #1d4ed8); }
.isis-mx__grp.is-met   { background: color-mix(in srgb, var(--isis-accent) 10%, var(--isis-surface)); color: var(--isis-accent); }
.isis-mx__grp.is-tra   { background: color-mix(in srgb, var(--isis-text-muted) 8%, var(--isis-surface)); color: var(--isis-text); }
.isis-mx__grp.is-other { background: var(--isis-surface-alt);    color: var(--isis-text-muted); }

/* ── Ligne 2 d'en-tête : libellés compétences en vertical (gelée sous la ligne 1) ── */
.isis-mx__chead {
    position: sticky;
    top: 34px;               /* = hauteur réelle de la ligne .isis-mx__grp */
    z-index: 6;
    background: var(--isis-surface);
    padding: 6px 0 8px;
    height: 118px;
    min-width: 46px;
    width: 46px;
    vertical-align: bottom;
    cursor: pointer;
    transition: background-color 120ms;
}
.isis-mx__chead:hover {
    background: color-mix(in srgb, var(--isis-mod-sirh) 6%, var(--isis-surface));
}
.isis-mx__chead.is-on {
    background: color-mix(in srgb, var(--isis-mod-sirh) 12%, var(--isis-surface));
}
.isis-mx__chead:focus-visible {
    outline: 2px solid var(--isis-mod-sirh);
    outline-offset: -2px;
}
.isis-mx__chead-v {
    writing-mode: vertical-rl;
    transform: rotate(180deg);
    margin: 0 auto;
    max-height: 96px;
    font-weight: 600;
    color: var(--isis-text);
    line-height: 1.15;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
/* Indicateur « habilitation à renouveler tous les N mois » sous le libellé. */
.isis-mx__renew {
    display: block;
    text-align: center;
    margin-top: 3px;
    font-size: 9.5px;
    font-weight: 600;
    color: var(--isis-warning);
}

/* ── Ligne « bandeau équipe » (gelée à gauche, fond teinté) ── */
.isis-mx__team td {
    position: sticky;
    left: 0;
    z-index: 5;
    background: var(--isis-surface-alt);
    padding: 6px 12px;
    font-size: 11px;
    font-weight: 680;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--isis-text);
    border-bottom: 1px solid var(--isis-border);
}
.isis-mx__team-count {
    margin-left: 5px;
    font-weight: 600;
    color: var(--isis-text-muted);
}

/* ── Cellule nom collaborateur (gelée à gauche) ── */
.isis-mx__who {
    position: sticky;
    left: 0;
    z-index: 4;
    background: var(--isis-surface);
    padding: 7px 12px;
    min-width: 208px;
    cursor: pointer;
    text-align: left;
    font-weight: inherit;
    transition: background-color 120ms;
}
table.isis-mx tbody tr:hover .isis-mx__who {
    background: color-mix(in srgb, var(--isis-mod-sirh) 5%, var(--isis-surface));
}
.isis-mx__who.is-on {
    background: color-mix(in srgb, var(--isis-mod-sirh) 12%, var(--isis-surface));
}
.isis-mx__who:focus-visible {
    outline: 2px solid var(--isis-mod-sirh);
    outline-offset: -2px;
}
.isis-mx__who-name {
    display: flex;
    align-items: center;
    gap: 8px;
    font-weight: 600;
    color: var(--isis-text);
}
.isis-mx__av {
    flex: none;
    width: 24px;
    height: 24px;
    border-radius: 50%;
    display: grid;
    place-items: center;
    background: var(--isis-mod-sirh-soft);
    color: var(--isis-mod-sirh);
    font-size: 10.5px;
    font-weight: 600;
}
.isis-mx__who-poste {
    margin-left: 32px;       /* aligné sous le nom (24px avatar + 8px gap) */
    margin-top: 1px;
    font-size: 10.5px;
    color: var(--isis-text-muted);
}

/* ── Cellule de croisement (conteneur td) ── */
.isis-mx__cx {
    padding: 4px;
    text-align: center;
}
table.isis-mx tbody tr:hover .isis-mx__cx {
    background: color-mix(in srgb, var(--isis-mod-sirh) 5%, var(--isis-surface));
}

/* ── Pastille de niveau (heatmap) ── */
.isis-mx__cell {
    position: relative;
    width: 34px;
    height: 30px;
    margin: 0 auto;
    border-radius: var(--isis-radius-sm);
    display: grid;
    place-items: center;
    font-family: 'Geist Mono', ui-monospace, monospace;
    font-weight: 600;
    font-size: 12px;
}
.isis-mx__cell.l1 { background: var(--isis-lvl-1); color: var(--isis-lvl-1-ink); }
.isis-mx__cell.l2 { background: var(--isis-lvl-2); color: var(--isis-lvl-2-ink); }
.isis-mx__cell.l3 { background: var(--isis-lvl-3); color: var(--isis-lvl-3-ink); }
.isis-mx__cell.l4 { background: var(--isis-lvl-4); color: var(--isis-lvl-4-ink); }
.isis-mx__cell.is-none {
    background: transparent;
    color: var(--isis-text-soft);
    font-weight: 400;
}
/* ── Écart vs niveau requis (P2) : liseré rouge si sous le requis, hachuré si manquant ── */
.isis-mx__cell.gap { box-shadow: 0 0 0 2px var(--isis-danger); }
.isis-mx__cell.miss {
    background: repeating-linear-gradient(135deg, var(--isis-danger-soft), var(--isis-danger-soft) 4px, #fff 4px, #fff 8px);
    border: 1px dashed var(--isis-danger);
    color: var(--isis-danger);
    font-weight: 700;
}

/* ── Pastille de péremption (coin haut-droit de la cellule) ── */
.isis-mx__dot {
    position: absolute;
    top: -3px;
    right: -3px;
    width: 9px;
    height: 9px;
    border-radius: 50%;
    border: 2px solid #fff;
    box-shadow: 0 0 0 0.5px rgba(16,24,32,.25);
}
.isis-mx__dot.is-exp  { background: var(--isis-danger); }
.isis-mx__dot.is-soon { background: var(--isis-warning); }

/* ── Légende (pied de la card master) ── */
.isis-mx-legend {
    display: flex;
    gap: 22px;
    flex-wrap: wrap;
    align-items: center;
    padding: 11px 16px;
    border-top: 1px solid var(--isis-border-soft);
    background: var(--isis-surface-alt);
    font-size: 11.5px;
    color: var(--isis-text-muted);
}
.isis-mx-legend__grp {
    display: flex;
    gap: 10px;
    align-items: center;
}
.isis-mx-legend__grp b {
    font-size: 10.5px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--isis-text);
}
.isis-mx-legend__item {
    display: inline-flex;
    align-items: center;
    gap: 5px;
}
.isis-mx-legend__sw {
    width: 16px;
    height: 16px;
    border-radius: 4px;
    display: inline-block;
}
.isis-mx-legend__sw.l1 { background: var(--isis-lvl-1); }
.isis-mx-legend__sw.l2 { background: var(--isis-lvl-2); }
.isis-mx-legend__sw.l3 { background: var(--isis-lvl-3); }
.isis-mx-legend__sw.l4 { background: var(--isis-lvl-4); }
.isis-mx-legend__sw.gap { box-shadow: 0 0 0 2px var(--isis-danger); background: var(--isis-lvl-2); }
.isis-mx-legend__sw.miss {
    background: repeating-linear-gradient(135deg, var(--isis-danger-soft), var(--isis-danger-soft) 3px, #fff 3px, #fff 6px);
    border: 1px dashed var(--isis-danger);
}
.isis-mx-legend__dot {
    width: 9px;
    height: 9px;
    border-radius: 50%;
    display: inline-block;
    border: 1.5px solid #fff;
    outline: 1px solid var(--isis-border);
}
.isis-mx-legend__dot.is-soon { background: var(--isis-warning); }
.isis-mx-legend__dot.is-exp  { background: var(--isis-danger); }

/* ── Panneau de focus (detail) ── */
.isis-mx-focus {
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
}
.isis-mx-focus__head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 0.5rem;
}
.isis-mx-focus__ctx {
    font-size: 11.5px;
    color: var(--isis-text-muted);
}
.isis-mx-focus__close {
    flex: none;
    width: 26px;
    height: 26px;
    display: grid;
    place-items: center;
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-sm);
    background: var(--isis-surface);
    color: var(--isis-text-muted);
    font-size: 16px;
    line-height: 1;
    cursor: pointer;
    transition: background-color 120ms, color 120ms;
}
.isis-mx-focus__close:hover { background: var(--isis-surface-alt); color: var(--isis-text); }
.isis-mx-focus__close:focus-visible {
    outline: 2px solid var(--isis-mod-sirh);
    outline-offset: 2px;
}
.isis-mx-focus__title {
    margin: 0.1rem 0 0.2rem;
    font-size: 17px;
    font-weight: 660;
    color: var(--isis-text);
}
.isis-mx-focus__badges {
    display: flex;
    gap: 6px;
    flex-wrap: wrap;
    margin-bottom: 0.4rem;
}
.isis-mx-focus__actions {
    display: flex;
    gap: 0.5rem;
    margin: 0.2rem 0 0.4rem;
}
/* Mini-stats (4 colonnes) en tête du panneau focus compétence. */
.isis-mx-focus__mini {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 8px;
    margin: 0.2rem 0 0.6rem;
}
.isis-mx-focus__mini > div {
    background: var(--isis-surface-alt);
    border: 1px solid var(--isis-border-soft);
    border-radius: var(--isis-radius-sm);
    padding: 8px;
    text-align: center;
}
.isis-mx-focus__mini .v {
    font-size: 18px;
    font-weight: 680;
    font-family: 'Geist Mono', ui-monospace, monospace;
    color: var(--isis-text);
}
.isis-mx-focus__mini .v.is-ok   { color: var(--isis-success); }
.isis-mx-focus__mini .v.is-warn { color: var(--isis-warning); }
.isis-mx-focus__mini .v.is-bad  { color: var(--isis-danger); }
.isis-mx-focus__mini .k {
    font-size: 10px;
    color: var(--isis-text-muted);
    margin-top: 2px;
}
.isis-mx-focus__sechead {
    margin: 0.5rem 0 0.4rem;
    font-size: 11.5px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--isis-text-muted);
}
.isis-mx-focus__holder {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    padding: 7px 0;
    border-bottom: 1px solid var(--isis-border-soft);
    font-size: 12.5px;
}
.isis-mx-focus__holder-name {
    color: var(--isis-text);
    font-weight: 500;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.isis-mx-focus__holder-meta {
    display: flex;
    align-items: center;
    gap: 6px;
    flex: none;
}

/* Pastille de statut de péremption dans le panneau de focus. */
.isis-mx-pill {
    font-size: 10.5px;
    font-weight: 600;
    padding: 2px 8px;
    border-radius: var(--isis-radius-pill);
    white-space: nowrap;
}
.isis-mx-pill.is-ok   { background: var(--isis-success-soft); color: var(--isis-success); }
.isis-mx-pill.is-soon { background: var(--isis-warning-soft); color: var(--isis-warning); }
.isis-mx-pill.is-exp  { background: var(--isis-danger-soft);  color: var(--isis-danger); }
.isis-mx-pill.is-none {
    background: var(--isis-surface-alt);
    color: var(--isis-text-muted);
}

/* ════════════════════════════════════════════════════════════════════════
   Vue « Évolution » des compétences (matrice → onglet) + bascule de vue
   ════════════════════════════════════════════════════════════════════════ */

/* ── Bascule de vue (Matrice / Évolution) ── */
.viewtabs {
    display: inline-flex;
    align-items: stretch;
    gap: 0;
    padding: 2px;
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius);
    background: var(--isis-surface-alt);
}
.viewtabs__btn {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    border: none;
    background: transparent;
    color: var(--isis-text-muted);
    font: inherit;
    font-size: 0.8rem;
    font-weight: 500;
    padding: 0.3rem 0.7rem;
    border-radius: calc(var(--isis-radius) - 3px);
    cursor: pointer;
    transition: background-color 0.12s ease, color 0.12s ease;
}
.viewtabs__btn:hover {
    color: var(--isis-text);
}
.viewtabs__btn.is-active {
    background: var(--isis-surface);
    color: var(--isis-current-mod, var(--isis-mod-sirh));
    box-shadow: var(--isis-elevation-1, 0 1px 2px rgba(0, 0, 0, 0.08));
}
.viewtabs__btn:focus-visible {
    outline: 2px solid var(--isis-current-mod, var(--isis-mod-sirh));
    outline-offset: 2px;
}

/* ── Conteneur Évolution ── */
.isis-evo {
    display: flex;
    flex-direction: column;
    gap: 1rem;
    min-height: 0;
    overflow: auto;
}

/* Barre de filtres période */
.isis-evo__filter {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    flex-wrap: wrap;
}
.isis-evo__filter-axis {
    font-size: 0.72rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--isis-text-muted);
    margin-right: 0.25rem;
}
.isis-evo__hint {
    font-size: 0.75rem;
    color: var(--isis-text-muted);
    margin-left: 0.5rem;
}

/* .isis-evo__kpis et .isis-evo__delta-row RETIRÉES (2026-09-04) : le rail de KPI de la vue
   Évolution ne portait aucun TAUX, §E2 ne le laissait pas survivre sur une page d'analyse.
   Les 5 chiffres sont relogés en sous-titre de section (§F) ; .isis-evo__delta reste, c'est
   elle qui habille les deltas dans ces sous-titres. */
.isis-evo__delta {
    display: inline-flex;
    align-items: center;
    gap: 0.1rem;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}
.isis-evo__delta.is-up   { color: var(--isis-success); }
.isis-evo__delta.is-down { color: var(--isis-danger); }


/* Grille des graphes : 2 colonnes, la dernière carte en pleine largeur */
.isis-evo__charts {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 1rem;
}
.isis-evo__chart-card {
    min-width: 0;
}
.isis-evo__chart-card--full {
    grid-column: 1 / -1;
}
.isis-evo__chart-canvas {
    width: 100%;
    min-height: 220px;
}
@media (max-width: 900px) {
    .isis-evo__charts { grid-template-columns: 1fr; }
}

/* Top compétences — barres proportionnelles */
.isis-evo__top {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.65rem;
}
.isis-evo__top-item {
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
}
.isis-evo__top-head {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}
.isis-evo__top-label {
    flex: 1 1 auto;
    min-width: 0;
    font-size: 0.85rem;
    font-weight: 500;
    color: var(--isis-text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.isis-evo__top-count {
    font-variant-numeric: tabular-nums;
    font-weight: 600;
    color: var(--isis-current-mod, var(--isis-mod-sirh));
    flex: 0 0 auto;
}
.isis-evo__top-track {
    height: 6px;
    border-radius: 999px;
    background: var(--isis-surface-alt);
    overflow: hidden;
}
.isis-evo__top-bar {
    height: 100%;
    border-radius: 999px;
    background: var(--isis-current-mod, var(--isis-mod-sirh));
    min-width: 2px;
}

/* ── Utilitaire accessibilité : contenu réservé aux lecteurs d'écran ── */
.isis-sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* ══════════════════════════════════════════════════════════════════════
   GED — Explorateur : arbre de dossiers lazy (GedFolderTree / GedFolderTreeNode)
   Variables utilisées : --isis-surface-alt, --isis-border-soft, --isis-border,
   --isis-text-soft (↔ --isis-ink-faint du mockup, absent de isis-theme.css),
   --isis-text-muted, --isis-current-mod, --isis-current-mod-soft,
   --isis-radius-sm, --isis-radius-pill.
   ══════════════════════════════════════════════════════════════════════ */

/* Listes racine et sous-listes */
.isis-ged-tree,
.isis-ged-tree__children {
    list-style: none;
    margin: 0;
    padding: 0;
}

/* Sous-liste enfants : indentation + filet gauche pointillé */
.isis-ged-tree__children {
    margin-left: 14px;
    border-left: 1px dashed var(--isis-border-soft);
    padding-left: 2px;
}

/* Ligne d'un nœud */
.isis-ged-tree__row {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 5px 7px;
    border-radius: var(--isis-radius-sm);
    cursor: pointer;
    font-size: 12.5px;
    color: var(--isis-text);
    user-select: none;
    outline: none;
}

.isis-ged-tree__row:hover {
    background: var(--isis-surface-alt);
}

.isis-ged-tree__row:focus-visible {
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 28%, transparent);
}

.isis-ged-tree__row.is-selected {
    background: var(--isis-current-mod-soft, var(--isis-accent-soft));
    color: var(--isis-current-mod, var(--isis-accent));
    font-weight: 600;
}

/* Chevron d'expansion */
.isis-ged-tree__chevron {
    width: 14px;
    height: 14px;
    flex: none;
    color: var(--isis-text-soft);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: transform 0.12s ease;
}

/* Triangle via bordures CSS */
.isis-ged-tree__chevron::before {
    content: "";
    display: block;
    width: 0;
    height: 0;
    border-top: 5px solid transparent;
    border-bottom: 5px solid transparent;
    border-left: 7px solid currentColor;
}

.isis-ged-tree__chevron.is-open {
    transform: rotate(90deg);
}

.isis-ged-tree__chevron.is-leaf {
    visibility: hidden;
}

/* Icône dossier (carré arrondi simulant un dossier) */
.isis-ged-tree__icon {
    width: 16px;
    height: 16px;
    flex: none;
    color: var(--isis-current-mod, var(--isis-accent));
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

.isis-ged-tree__icon::before {
    content: "";
    display: block;
    width: 15px;
    height: 11px;
    border-radius: 2px 3px 2px 2px;
    background: currentColor;
    clip-path: polygon(0 25%, 33% 25%, 40% 0%, 100% 0%, 100% 100%, 0 100%);
}

.isis-ged-tree__icon.is-system {
    color: var(--isis-text-soft);
}

/* Nom du dossier */
.isis-ged-tree__name {
    flex: 1;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Badge compteur de documents */
.isis-ged-tree__count {
    font-size: 10.5px;
    font-weight: 600;
    background: var(--isis-surface-alt);
    color: var(--isis-text-muted);
    border-radius: var(--isis-radius-pill);
    padding: 1px 7px;
    white-space: nowrap;
}

.isis-ged-tree__row.is-selected .isis-ged-tree__count {
    background: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 12%, white);
    color: var(--isis-current-mod, var(--isis-accent));
}

/* ── Carte des rattachements collaborateurs (mode Carte de /sirh/collaborateurs) ── */
.collabmap-lbl{background:rgba(255,255,255,.92);border:1px solid var(--isis-line);border-radius:5px;padding:1px 6px;font-size:.72rem;font-weight:600;color:var(--isis-text);box-shadow:0 1px 3px rgba(0,0,0,.12);white-space:nowrap}
.leaflet-tooltip.collabmap-lbl::before{display:none}
.isis-collabmap{display:grid;grid-template-columns:1fr 300px;height:calc(100vh - 230px);min-height:420px;border:1px solid var(--isis-line);border-radius:var(--isis-radius);overflow:hidden}
.isis-collabmap__map{height:100%;background:#eef2f5}
.isis-collabmap__side{border-left:1px solid var(--isis-line);background:#fff;overflow:auto;padding:1rem}
.isis-collabmap__side h2{font-size:.74rem;text-transform:uppercase;letter-spacing:.06em;color:var(--isis-text-muted);margin:.9rem 0 .5rem}
.isis-collabmap__side h2:first-child{margin-top:0}
.isis-collabmap__side label{display:flex;gap:.5rem;align-items:center;font-size:.85rem;padding:.2rem 0;cursor:pointer}
.isis-collabmap__filter{width:100%;padding:.4rem .5rem;border:1px solid var(--isis-line);border-radius:var(--isis-radius-sm);font:inherit}
.isis-collabmap__leg{display:flex;align-items:center;gap:.5rem;font-size:.83rem;padding:.22rem 0}
.isis-collabmap__sw{width:.85rem;height:.85rem;border-radius:50%;border:2px solid #fff;box-shadow:0 0 0 1px rgba(0,0,0,.15);flex:none}

/* ===== Refonte modal éditeur lignes devis (2026-06-20) ===== */
.isis-devis-items__c { text-align: center; }

/* Cluster compact « réglages de ligne » (Type/Opt/Pal fusionnés, 2026-09-15 — retour
   utilisateur : trop de petits boutons côte à côte). Le déclencheur était d'abord la
   lettre-initiale colorée de l'ancien bouton Type (P/F/S/C) ; second retour le même
   jour : le type Produit/Service ne mérite plus une mise en avant par ligne (il se
   choisit déjà explicitement à la création via la barre d'outils, cf.
   DevisItemsToolbar), donc un « + » neutre suffit — Type reste au menu, seulement
   plus affiché en façade. Cible de clic étendue à 44×44 par pseudo-élément — même
   recette que .isis-grid--vehrh.isis-grid__action-btn (plus haut dans cette feuille,
   cf. sa justification) : le bouton reste visuellement compact (28px, colonne réduite
   à sa largeur stricte), seule la CIBLE de clic s'étend. La ligne de .isis-devis-items
   fait déjà ~43-44px de haut (padding tbody td + convention des contrôles à 32px, cf.
   plus haut dans cette feuille) : pas de débordement sur les lignes voisines malgré
   les 44px verticaux. */
.isis-devis-items__linesettings-cell{overflow:visible!important;position:relative}
/* border-style: solid, pas dashed (lifting 2026-09-15) : le pointillé est le vocabulaire
   des boutons « créer » ailleurs dans cette feuille (.isis-devis-items__add) — sur une
   ligne déjà existante, un bouton en pointillé se lisait comme « ajouter une ligne ici »
   plutôt que « régler cette ligne ». La discrétion voulue du bouton (retrait de la
   lettre colorée P/F/S/C) n'est pas remise en cause, seul le TRAIT change. */
.isis-devis-items__linesettings-btn{position:relative;width:26px;height:26px;border-radius:var(--isis-radius-sm);
  cursor:pointer;border:1px solid var(--isis-border-strong);background:var(--isis-surface);
  color:var(--isis-text-soft);display:inline-flex;align-items:center;justify-content:center}
.isis-devis-items__linesettings-btn:hover{background:var(--isis-surface-alt);color:var(--isis-text)}
.isis-devis-items__linesettings-btn.is-active{border-style:solid;border-color:var(--isis-accent);
  background:color-mix(in srgb,var(--isis-accent) 12%,transparent);color:var(--isis-accent)}
.isis-devis-items__linesettings-btn::after{content:"";position:absolute;top:50%;left:50%;width:44px;height:44px;transform:translate(-50%,-50%)}
.isis-devis-items__linesettings-dot{position:absolute;bottom:-2px;width:7px;height:7px;border-radius:50%;border:1.5px solid var(--isis-surface)}
.isis-devis-items__linesettings-dot--opt{left:-2px;background:var(--isis-accent)}
.isis-devis-items__linesettings-dot--pal{right:-2px;background:var(--isis-mod-gescom)}
/* Nature fiscale non qualifiee : haut-droit, le bas etant pris par option et paliers.
   Ambre comme la pastille de simulation de la barre d'outils — meme sens, « a arbitrer ». */
.isis-devis-items__linesettings-dot--fisc{bottom:auto;top:-2px;right:-2px;background:var(--isis-warning)}

/* Barre d'outils */
.isis-devis-items__toolbar{display:flex;gap:8px;flex-wrap:wrap;align-items:center;padding:10px 0 12px}
.isis-devis-items__toolbar-grow{flex:1}
/* Menu « Options » (2026-09-22) : trait plein, pas le pointillé des boutons « créer ».
   Le point ambre signale le mode simulation une fois le réglage rangé dans le menu. */
.isis-devis-items__options-btn{position:relative;border-style:solid}
.isis-devis-items__options-btn.is-active{border-color:var(--isis-accent);
  background:color-mix(in srgb,var(--isis-accent) 12%,transparent);color:var(--isis-accent)}
.isis-devis-items__options-dot{position:absolute;top:-3px;right:-3px;width:8px;height:8px;border-radius:50%;
  background:var(--isis-warning);border:1.5px solid var(--isis-surface)}
.isis-devis-items__options-panel{min-width:300px}
/* Menu « Ajouter » (2026-10-02) : ouvert à gauche, sous son bouton, au lieu de l'ancrage à
   droite des menus d'outils. Sur une barre étroite, Fiche et Options perdent leur libellé
   (masqué visuellement, il reste leur nom accessible) : six boutons d'ajout y passaient à la ligne. */
.isis-devis-items__add-panel{left:0;right:auto;min-width:280px}
/* Requête média, pas de conteneur : un container-type poserait une containment de mise en page
   sur la barre, et le fond plein écran (position:fixed) des menus s'y retrouverait enfermé. */
@media (max-width: 900px){
  .isis-devis-items__btn-label{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
    clip:rect(0,0,0,0);white-space:nowrap;border:0}
}
.isis-devis-items__options-escguard.rz-popup{display:none!important}
.isis-devis-items__options-item.isis-toolbar-menu__item{height:auto;min-height:34px;padding-top:0.4rem;padding-bottom:0.4rem;align-items:flex-start}
.isis-devis-items__options-text{display:flex;flex-direction:column;gap:1px;text-align:left}
.isis-devis-items__options-text small{font-size:0.72rem;color:var(--isis-text-muted)}

/* Fiche de la ligne (lot 2c) : panneau de 380 px à droite du tableur, en lecture seule.
   Le tableau garde la place restante ; la fiche défile seule. */
.isis-devis-items-dialog__work{flex:1 1 auto;display:flex;gap:12px;min-height:0;min-width:0}
.isis-devis-items-dialog__work > .isis-devis-items-dialog__lines-scroll{flex:1 1 auto;min-width:0}
.isis-devis-fiche{flex:0 0 380px;width:380px;min-height:0;overflow:auto;display:flex;flex-direction:column;
  border:var(--isis-card-mod-border);border-radius:var(--isis-radius);background:var(--isis-surface);
  box-shadow:var(--isis-elevation-1)}
.isis-devis-fiche__head{position:sticky;top:0;z-index:1;display:flex;align-items:center;gap:8px;
  padding:10px 12px;background:var(--isis-card-mod-bg);border-bottom:var(--isis-card-mod-border)}
.isis-devis-fiche__title{flex:1;min-width:0;margin:0;font-size:0.9rem;font-weight:600;color:var(--isis-text);
  font-variant-numeric:tabular-nums;overflow-wrap:anywhere}
.isis-devis-fiche__title:focus{outline:none}
.isis-devis-fiche__title:focus-visible{outline:2px solid var(--isis-current-mod,var(--isis-accent));outline-offset:2px}
.isis-devis-fiche__empty{margin:0;padding:16px 12px;font-size:0.8rem;color:var(--isis-text-muted)}
.isis-devis-fiche__body{display:flex;flex-direction:column;gap:14px;padding:12px}
.isis-devis-fiche__designation{margin:0;font-size:0.85rem;line-height:1.45;color:var(--isis-text);overflow-wrap:anywhere;white-space:pre-line}
.isis-devis-fiche__fields{display:grid;grid-template-columns:1fr 1fr;gap:6px 12px;margin:0}
.isis-devis-fiche__fields > div{display:flex;flex-direction:column;gap:1px;min-width:0}
.isis-devis-fiche__fields dt{font-size:0.68rem;letter-spacing:0.02em;text-transform:uppercase;color:var(--isis-text-muted)}
.isis-devis-fiche__fields dd{margin:0;font-size:0.82rem;color:var(--isis-text);font-variant-numeric:tabular-nums;overflow-wrap:anywhere}
.isis-devis-fiche__fields > .is-total dd{font-weight:600}
/* Qté : la valeur et la pastille de provenance (EF-60) sont deux boîtes, pas deux mots — leur
   écart est un gap, pas un espace HTML, et la pastille ne se comprime jamais. */
.isis-devis-fiche__fields dd.is-qte{display:flex;align-items:center;gap:0.25rem}
.isis-devis-fiche__fields dd.is-qte > .isis-devis-origine{flex-shrink:0}
.isis-devis-fiche__section{display:flex;flex-direction:column;gap:8px;padding-top:12px;border-top:1px solid var(--isis-border)}
.isis-devis-fiche__section > .isis-action-btn{align-self:flex-start;min-height:32px}
.isis-devis-fiche__h{margin:0;font-size:0.72rem;font-weight:600;letter-spacing:0.03em;text-transform:uppercase;color:var(--isis-text-muted)}
.isis-devis-fiche__text,.isis-devis-fiche__note{margin:0;font-size:0.8rem;line-height:1.45}
.isis-devis-fiche__text{color:var(--isis-text)}
.isis-devis-fiche__note{color:var(--isis-text-muted)}
.isis-devis-fiche__list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:4px}
.isis-devis-fiche__list > li{display:flex;justify-content:space-between;align-items:baseline;gap:12px;font-size:0.8rem;color:var(--isis-text)}
.isis-devis-fiche__num{flex:0 0 auto;font-variant-numeric:tabular-nums;white-space:nowrap}
.isis-devis-fiche__history-what{display:flex;flex-direction:column;min-width:0;overflow-wrap:anywhere}
.isis-devis-fiche__history-what small{font-size:0.7rem;color:var(--isis-text-muted)}
.isis-devis-fiche__disclosure{display:inline-flex;align-items:center;gap:4px;min-height:32px;padding:0 6px 0 2px;margin-left:-2px;
  border:0;border-radius:var(--isis-radius-sm);background:transparent;cursor:pointer;
  font:inherit;letter-spacing:inherit;text-transform:inherit;color:inherit}
.isis-devis-fiche__disclosure:hover{color:var(--isis-current-mod,var(--isis-accent))}
.isis-devis-fiche__disclosure:focus-visible{outline:2px solid var(--isis-current-mod,var(--isis-accent));outline-offset:2px}

/* Maître-détail (lot 2d) : lus sur la largeur de l'onglet, pas de l'écran. Sous 1 180 px le
   tableur cède la place à une liste compacte + la fiche ; sous 640 px (téléphone) la liste reste
   seule et la fiche la recouvre une fois une ligne choisie. Le conteneur de requête devient le
   bloc contenant des descendants positionnés : la fiche recouvre la zone de travail, pas la page. */
.isis-devis-items-dialog__work{container:devis-work / inline-size;position:relative}
.isis-devis-lines-list{display:none;min-height:0;min-width:0;overflow:auto;
  border:var(--isis-card-mod-border);border-radius:var(--isis-radius);background:var(--isis-surface)}
.isis-devis-lines-list__head,.isis-devis-lines-list__row,.isis-devis-lines-list__subtotal{display:grid;
  grid-template-columns:2.75rem minmax(0,1fr) 7rem;align-items:center;gap:8px;padding:0 10px}
.isis-devis-lines-list.has-margin .isis-devis-lines-list__head,
.isis-devis-lines-list.has-margin .isis-devis-lines-list__row,
.isis-devis-lines-list.has-margin .isis-devis-lines-list__subtotal{grid-template-columns:2.75rem minmax(0,1fr) 7rem 4.5rem}
.isis-devis-lines-list__head{position:sticky;top:0;z-index:1;min-height:30px;background:var(--isis-card-mod-bg);
  border-bottom:var(--isis-card-mod-border);font-size:0.68rem;font-weight:600;letter-spacing:0.03em;
  text-transform:uppercase;color:var(--isis-text-muted)}
.isis-devis-lines-list__head > span:nth-child(n+3){text-align:right}
.isis-devis-lines-list__rows{list-style:none;margin:0;padding:0}
.isis-devis-lines-list__row{width:100%;min-height:36px;margin:0;border:0;border-bottom:1px solid var(--isis-border);
  background:transparent;color:var(--isis-text);font:inherit;font-size:0.8rem;text-align:left;cursor:pointer}
.isis-devis-lines-list__row:hover{background:var(--isis-surface-alt)}
.isis-devis-lines-list__row:focus{outline:none}
.isis-devis-lines-list__row:focus-visible{outline:2px solid var(--isis-current-mod,var(--isis-accent));outline-offset:-2px}
.isis-devis-lines-list__row[aria-current="true"]{background:var(--isis-current-mod-soft);
  box-shadow:inset 3px 0 0 var(--isis-current-mod,var(--isis-accent))}
.isis-devis-lines-list__row.is-section{font-weight:600;background:var(--isis-surface-alt)}
.isis-devis-lines-list__row.is-section[aria-current="true"]{background:var(--isis-current-mod-soft)}
.isis-devis-lines-list__row.is-subtotal{font-weight:600;background:var(--isis-surface-alt)}
.isis-devis-lines-list__row.is-subtotal[aria-current="true"]{background:var(--isis-current-mod-soft)}
.isis-devis-lines-list__row.is-merge-child .isis-devis-lines-list__label{padding-left:14px}
.isis-devis-lines-list__row.is-comment .isis-devis-lines-list__label{color:var(--isis-text-muted)}
.isis-devis-lines-list__num{color:var(--isis-text-muted);font-variant-numeric:tabular-nums}
.isis-devis-lines-list__label{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.isis-devis-lines-list__amount{text-align:right;white-space:nowrap;font-variant-numeric:tabular-nums}
/* Sous-total de clôture d'une section : posé après la dernière ligne du bloc, jamais sur son
   titre. Le libellé prend la piste du numéro ET celle de la désignation — un sous-total n'a pas
   de numéro de ligne — pour que le montant reste aligné sous « Total HT ». */
.isis-devis-lines-list__subtotal{min-height:32px;border-bottom:1px solid var(--isis-border);
  background:var(--isis-surface-alt);font-size:0.8rem}
.isis-devis-lines-list__subtotal-label{grid-column:1 / 3;min-width:0;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap;font-weight:600;color:var(--isis-text-muted)}
.isis-devis-fiche__edit,.isis-devis-fiche__back{display:none}
.isis-devis-fiche__back{align-items:center;gap:6px;margin:8px 12px 0;padding:0 10px 0 6px;align-self:flex-start;
  border:1px solid var(--isis-border);border-radius:var(--isis-radius-sm);background:var(--isis-surface);
  color:var(--isis-text);font:inherit;font-size:0.8rem;cursor:pointer}
.isis-devis-fiche__back:hover{border-color:var(--isis-current-mod,var(--isis-accent))}
.isis-devis-fiche__back:focus-visible{outline:2px solid var(--isis-current-mod,var(--isis-accent));outline-offset:2px}
@container devis-work (max-width: 1179px){
  .isis-devis-items-dialog__work.has-fiche > .isis-devis-items-dialog__lines-scroll{display:none}
  .isis-devis-items-dialog__work.has-fiche > .isis-devis-lines-list{display:block;flex:0 1 540px}
  .isis-devis-items-dialog__work.has-fiche > .isis-devis-fiche{flex:1 1 380px;width:auto}
  .isis-devis-fiche__edit{display:inline-flex}
}
@container devis-work (max-width: 639px){
  .isis-devis-items-dialog__work.has-fiche > .isis-devis-lines-list{flex:1 1 auto}
  .isis-devis-items-dialog__work.has-fiche:not(.is-list-only) > .isis-devis-fiche{position:absolute;inset:0;z-index:20;
    width:auto;border-radius:0}
  .isis-devis-items-dialog__work.has-fiche.is-list-only > .isis-devis-fiche{display:none}
  .isis-devis-fiche__back{display:inline-flex;min-height:44px}
  .isis-devis-lines-list__row{min-height:44px}
  .isis-devis-fiche__head .isis-action-btn,.isis-devis-fiche__section > .isis-action-btn{min-height:44px;min-width:44px}
  .isis-devis-fiche__disclosure{min-height:44px}
}
.isis-devis-items__options-item--sim[aria-checked="true"] .rz-icon{color:var(--isis-warning)}

/* Overlays ligne (option / paliers) + simulation */
.isis-devis-items__line-overlay,.isis-devis-items__sim-overlay{position:fixed;inset:0;background:rgba(15,23,42,.45);display:flex;align-items:center;justify-content:center;z-index:1200}
.isis-devis-items__line-overlay-card,.isis-devis-items__sim-card{background:var(--isis-surface);border-radius:var(--isis-radius-lg);box-shadow:var(--isis-elevation-2);width:660px;max-width:92vw;max-height:86vh;overflow:auto}
.isis-devis-items__sim-card{width:1040px}
.isis-devis-items__line-overlay-head{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:14px 18px;border-bottom:1px solid var(--isis-border)}
.isis-devis-items__line-overlay-close{border:1px solid var(--isis-border);background:var(--isis-surface);border-radius:var(--isis-radius-sm);width:30px;height:30px;cursor:pointer;color:var(--isis-text-muted);display:inline-flex;align-items:center;justify-content:center}
.isis-devis-items__line-overlay-unset{border:1px solid var(--isis-border);background:var(--isis-surface);border-radius:var(--isis-radius-sm);padding:5px 10px;cursor:pointer;color:var(--isis-text-muted);font-size:12px;margin-left:auto}
.isis-devis-items__line-overlay-unset--set{border-color:var(--isis-accent);color:var(--isis-accent)}
.isis-devis-items__line-overlay .isis-devis-items__option,.isis-devis-items__line-overlay .isis-devis-items__tiers{padding:16px 18px}

/* Modale de choix du type */
.isis-type-picker__grid{display:grid;grid-template-columns:1fr 1fr;gap:10px}
.isis-type-picker__card{display:flex;align-items:center;gap:12px;border:1px solid var(--isis-border-strong);border-radius:var(--isis-radius);padding:13px 14px;cursor:pointer;text-align:left;background:var(--isis-surface)}
.isis-type-picker__card:hover{border-color:var(--isis-mod-gescom);background:color-mix(in srgb,var(--isis-mod-gescom) 8%,transparent)}
.isis-type-picker__card.is-selected{border-color:var(--isis-mod-gescom);box-shadow:inset 0 0 0 1px var(--isis-mod-gescom);background:color-mix(in srgb,var(--isis-mod-gescom) 8%,var(--isis-surface))}
.isis-type-picker__ini{width:38px;height:38px;border-radius:var(--isis-radius-sm);display:flex;align-items:center;justify-content:center;font-weight:700;font-size:18px;flex:0 0 auto}
.isis-type-picker__ini--is-prod{color:var(--isis-mod-gescom);background:color-mix(in srgb,var(--isis-mod-gescom) 14%,transparent)}
.isis-type-picker__ini--is-forf{color:var(--isis-accent);background:color-mix(in srgb,var(--isis-accent) 12%,transparent)}
.isis-type-picker__ini--is-sect,.isis-type-picker__ini--is-comm,.isis-type-picker__ini--is-stot{color:var(--isis-text-muted);background:var(--isis-surface-alt)}
.isis-type-picker__txt{display:flex;flex-direction:column;gap:2px}
.isis-type-picker__label{font-weight:650;font-size:13.5px}
.isis-type-picker__hint{color:var(--isis-text-muted);font-size:11.5px}

/* Halo bleu posé sur le wrapper .rz-dialog par setHalo() (JS) — permanent depuis que
   l'enregistrement automatique n'est plus optionnel (2026-09-11, ex-interrupteur retiré). */
.rz-dialog.isis-autosave-halo{outline:2px solid color-mix(in srgb,var(--isis-mod-gescom) 55%,transparent);outline-offset:0;box-shadow:0 0 0 5px color-mix(in srgb,var(--isis-mod-gescom) 14%,transparent), var(--isis-elevation-2);transition:box-shadow .2s ease, outline-color .2s ease}

/* Footer auto-save */
.isis-devis-items__autosave-foot{display:flex;align-items:center;justify-content:space-between;gap:14px;width:100%;flex-wrap:wrap}
.isis-devis-items__autosave-alert{flex-basis:100%;margin:0 0 6px}
.isis-devis-items__autosave-right{display:inline-flex;align-items:center;gap:16px}
.isis-savestate{display:inline-flex;align-items:center;gap:8px;font-size:12.5px;color:var(--isis-text-muted)}
.isis-savestate__dot{width:8px;height:8px;border-radius:var(--isis-radius-pill);background:var(--isis-text-soft)}
.isis-savestate--idle .isis-savestate__dot{background:color-mix(in srgb,var(--isis-mod-gescom) 55%,transparent)}
.isis-savestate--saving .isis-savestate__dot{background:var(--isis-mod-gescom);animation:isis-savepulse 1s ease-in-out infinite}
.isis-savestate--saved .isis-savestate__dot{background:var(--isis-success)}
.isis-savestate--error{color:var(--isis-danger)}
.isis-savestate--error .isis-savestate__dot{background:var(--isis-danger)}
.isis-savestate--suspended.isis-savestate--idle .isis-savestate__dot{background:var(--isis-warning)}
@keyframes isis-savepulse{0%,100%{opacity:1}50%{opacity:.3}}
/* ════════════════════════════════════════════════════════════════════════
   Coût de revient — refonte commercial-first (2026-06-20)
   4 zones narratives : diagnostic (héros+jauge) · décomposition (stacked) ·
   levier prix (simulateur remise) · détail déboursé (éditeur inline au clic).
   Namespacé .isis-crv-* — couleur module gescom explicite (rendu hors shell).
   ════════════════════════════════════════════════════════════════════════ */
.isis-crv{ --crv-mod: var(--isis-mod-gescom); display:flex; flex-direction:column; gap:18px; }
.isis-crv .mono{ font-family:'Geist Mono',ui-monospace,'SF Mono',Menlo,monospace; font-variant-numeric:tabular-nums; }

/* étape narrative */
.isis-crv-step{ display:flex; align-items:center; gap:9px; margin-bottom:-6px; }
.isis-crv-step__n{ width:21px; height:21px; border-radius:50%; background:var(--crv-mod); color:#fff;
    font-size:11.5px; font-weight:700; display:flex; align-items:center; justify-content:center; flex:none; }
.isis-crv-step__n.is-muted{ background:var(--isis-text-soft); }
.isis-crv-step__t{ font-size:12px; font-weight:700; text-transform:uppercase; letter-spacing:.05em; color:var(--isis-text); }
.isis-crv-step__h{ font-size:11.5px; color:var(--isis-text-soft); }

.isis-crv-card{ background:var(--isis-surface); border:1px solid var(--isis-border); border-radius:var(--isis-radius);
    box-shadow:var(--isis-elevation-1); }

/* ── 1 · Diagnostic (héros) ── */
.isis-crv-hero{ display:grid; grid-template-columns:1.15fr 1fr; overflow:hidden; }
@media (max-width:980px){ .isis-crv-hero{ grid-template-columns:1fr; } }
.isis-crv-hero__main{ padding:20px 22px; background:linear-gradient(180deg,color-mix(in srgb,var(--crv-mod) 6%,var(--isis-surface)),var(--isis-surface)); }
.isis-crv-hero__top{ display:flex; align-items:baseline; gap:14px; flex-wrap:wrap; }
.isis-crv-hero__big{ font-size:46px; font-weight:800; letter-spacing:-.03em; line-height:1; color:var(--isis-accent); transition:color var(--isis-motion-fast); }
.isis-crv-hero.is-on-target    .isis-crv-hero__big{ color:var(--isis-success); }
.isis-crv-hero.is-below-target .isis-crv-hero__big{ color:var(--isis-warning); }
.isis-crv-hero.is-below-floor  .isis-crv-hero__big{ color:var(--isis-danger); }
.isis-crv-hero.is-no-cost .isis-crv-hero__big,
.isis-crv-hero.is-unclassified .isis-crv-hero__big{ color:var(--isis-text-muted); }
.isis-crv-verdict{ transition:background var(--isis-motion-fast),color var(--isis-motion-fast); }
.isis-crv-hero__lbl{ font-size:12px; text-transform:uppercase; letter-spacing:.06em; color:var(--isis-text-soft); font-weight:700; }
.isis-crv-verdict{ display:inline-flex; align-items:center; gap:6px; font-size:12.5px; font-weight:700; padding:4px 12px; border-radius:var(--isis-radius-pill); }
.isis-crv-verdict.is-on-target{ background:var(--isis-success-soft); color:var(--isis-success); }
.isis-crv-verdict.is-below-target{ background:var(--isis-warning-soft); color:var(--isis-warning); }
.isis-crv-verdict.is-below-floor{ background:var(--isis-danger-soft); color:var(--isis-danger); }
.isis-crv-verdict.is-no-cost,.isis-crv-verdict.is-unclassified{ background:var(--isis-surface-alt); color:var(--isis-text-muted); }
.isis-crv-hero__sub{ margin-top:7px; font-size:12.5px; color:var(--isis-text-muted); }
.isis-crv-hero__sub strong{ color:var(--isis-text); font-weight:650; }

/* jauge plancher / cible / plafond */
.isis-crv-gauge{ margin-top:18px; }
.isis-crv-gauge__track{ position:relative; height:14px; border-radius:var(--isis-radius-pill); overflow:hidden;
    border:1px solid var(--isis-border-soft); }
.isis-crv-gauge__zone{ position:absolute; top:0; bottom:0; width:2px; background:color-mix(in srgb,var(--isis-text) 22%,transparent); }
.isis-crv-gauge__cur{ position:absolute; top:-5px; width:3px; height:24px; border-radius:2px; background:var(--isis-text);
    box-shadow:0 0 0 3px color-mix(in srgb,var(--isis-accent) 30%,transparent); }
.isis-crv-gauge__scale{ display:flex; justify-content:space-between; margin-top:9px; font-size:10.5px; color:var(--isis-text-soft); }
.isis-crv-gauge__scale .seg{ text-align:center; }
.isis-crv-gauge__scale b{ display:block; color:var(--isis-text-muted); font-weight:700; font-variant-numeric:tabular-nums; }

/* lignes à risque */
.isis-crv-hero__risk{ padding:18px 20px; border-left:1px solid var(--isis-border-soft); background:var(--isis-surface); }
@media (max-width:980px){ .isis-crv-hero__risk{ border-left:0; border-top:1px solid var(--isis-border-soft); } }
.isis-crv-hero__risk h4{ margin:0 0 11px; font-size:11px; text-transform:uppercase; letter-spacing:.05em;
    color:var(--isis-text-soft); font-weight:700; display:flex; align-items:center; gap:7px; }
.isis-crv-risk{ display:flex; align-items:stretch; gap:10px; width:100%; padding:9px 4px; border:0; background:none;
    border-bottom:1px dashed var(--isis-border-soft); cursor:pointer; text-align:left; color:inherit; font:inherit; }
.isis-crv-risk:last-of-type{ border-bottom:0; }
.isis-crv-risk:hover{ background:var(--isis-surface-alt); }
.isis-crv-risk:focus-visible{ outline:2px solid color-mix(in srgb,var(--crv-mod) 55%,transparent); outline-offset:1px; border-radius:var(--isis-radius-sm); }
.isis-crv-risk__bar{ width:4px; border-radius:3px; flex:none; }
.isis-crv-risk__bar.is-below-floor{ background:var(--isis-danger); }
.isis-crv-risk__bar.is-below-target{ background:var(--isis-warning); }
.isis-crv-risk__nm{ flex:1; min-width:0; font-size:12.5px; font-weight:600; }
.isis-crv-risk__nm small{ display:block; font-weight:500; color:var(--isis-text-soft); font-size:11px;
    white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.isis-crv-risk__pct{ align-self:center; font-weight:700; font-size:13px; font-variant-numeric:tabular-nums; }
.isis-crv-risk__pct.is-below-floor{ color:var(--isis-danger); }
.isis-crv-risk__pct.is-below-target{ color:var(--isis-warning); }
.isis-crv-hero__risk-empty{ display:flex; align-items:center; gap:8px; color:var(--isis-success); font-size:12.5px; font-weight:600; }

/* ── 2 · Décomposition ── */
.isis-crv-grid2{ display:grid; grid-template-columns:1.5fr 1fr; gap:18px; }
@media (max-width:980px){ .isis-crv-grid2{ grid-template-columns:1fr; } }
.isis-crv-pad{ padding:18px 20px; }
.isis-crv-ttl{ font-size:13px; font-weight:700; margin:0 0 4px; }
.isis-crv-ttl__h{ font-size:11.5px; color:var(--isis-text-soft); margin-bottom:15px; }
.isis-crv-stack{ display:flex; height:34px; border-radius:var(--isis-radius-sm); overflow:hidden;
    box-shadow:inset 0 0 0 1px var(--isis-border-soft); }
.isis-crv-stack__s{ display:flex; align-items:center; justify-content:center; color:#fff; font-size:11px; font-weight:700;
    min-width:0; white-space:nowrap; overflow:hidden; }
.isis-crv-legend{ display:flex; flex-direction:column; gap:2px; margin-top:16px; }
.isis-crv-lg{ display:grid; grid-template-columns:13px 1fr auto auto; align-items:center; gap:10px; padding:7px 6px; border-radius:var(--isis-radius-sm); }
.isis-crv-lg:hover{ background:var(--isis-surface-alt); }
.isis-crv-lg__sw{ width:11px; height:11px; border-radius:3px; }
.isis-crv-lg__nm{ font-weight:600; font-size:12.5px; min-width:0; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.isis-crv-lg__pct{ color:var(--isis-text-soft); font-size:11.5px; width:48px; text-align:right; font-variant-numeric:tabular-nums; }
.isis-crv-lg__val{ font-weight:700; font-size:12.5px; width:96px; text-align:right; font-variant-numeric:tabular-nums; }
.isis-crv-note{ margin-top:16px; font-size:12px; color:var(--isis-text-muted); background:var(--isis-surface-alt);
    border:1px solid var(--isis-border-soft); border-radius:var(--isis-radius-sm); padding:10px 12px; }
.isis-crv-note strong{ color:var(--isis-accent-strong); }

/* ── 3 · Levier prix (simulateur remise) ── */
.isis-crv-sim{ display:grid; grid-template-columns:1fr 1.1fr; overflow:hidden; }
@media (max-width:980px){ .isis-crv-sim{ grid-template-columns:1fr; } }
.isis-crv-sim__l{ padding:20px 22px; border-right:1px solid var(--isis-border-soft); }
@media (max-width:980px){ .isis-crv-sim__l{ border-right:0; border-bottom:1px solid var(--isis-border-soft); } }
.isis-crv-sim__row{ display:flex; align-items:baseline; justify-content:space-between; margin-bottom:4px; }
.isis-crv-sim__row .k{ font-size:12.5px; color:var(--isis-text-muted); font-weight:600; }
.isis-crv-sim__row .v{ font-size:15px; font-weight:700; font-variant-numeric:tabular-nums; }
.isis-crv-sim__slider{ width:100%; margin:18px 0 6px; accent-color:var(--crv-mod); }
.isis-crv-sim__cap{ display:flex; justify-content:space-between; font-size:11px; color:var(--isis-text-soft); }
.isis-crv-sim__r{ padding:20px 22px; display:flex; flex-direction:column; justify-content:center; gap:12px;
    background:linear-gradient(180deg,color-mix(in srgb,var(--crv-mod) 4%,var(--isis-surface)),var(--isis-surface)); }
.isis-crv-read{ display:flex; align-items:baseline; justify-content:space-between; }
.isis-crv-read .k{ font-size:11px; text-transform:uppercase; letter-spacing:.05em; color:var(--isis-text-soft); font-weight:700; }
.isis-crv-read .big{ font-size:34px; font-weight:800; letter-spacing:-.02em; font-variant-numeric:tabular-nums; transition:color var(--isis-motion-fast); }
.isis-crv-read .v--lg{ font-size:18px; font-weight:700; }
.isis-crv-read + .isis-crv-read{ margin-top:0.25rem; }
.isis-crv-read .big.is-on-target{ color:var(--isis-success); }
.isis-crv-read .big.is-below-target{ color:var(--isis-warning); }
.isis-crv-read .big.is-below-floor{ color:var(--isis-danger); }
.isis-crv-minigauge{ position:relative; height:9px; border-radius:var(--isis-radius-pill); overflow:hidden; border:1px solid var(--isis-border-soft); }
.isis-crv-minigauge .c{ position:absolute; top:-3px; width:3px; height:15px; background:var(--isis-text); border-radius:2px; }
.isis-crv-floorline{ display:flex; justify-content:space-between; font-size:11px; color:var(--isis-text-soft); }

/* ── 4 · Détail déboursé — éditeur inline au clic ── */
.isis-crv-det__head{ display:flex; align-items:center; gap:10px; padding:14px 18px; cursor:pointer; }
.isis-crv-det__head h3{ margin:0; font-size:13px; font-weight:600; flex:1; }
.isis-crv-det__hint{ color:var(--isis-text-soft); font-size:11.5px; }

/* ── Marge par lot (EF-53) ── */
.isis-crv-lots__lot{ font-weight:600; text-align:left; }
.isis-crv-lots__row[data-niveau="2"] .isis-crv-lots__lot{ padding-left:24px; font-weight:500; }
.isis-crv-lots__row[data-niveau="3"] .isis-crv-lots__lot,
.isis-crv-lots__row[data-niveau="4"] .isis-crv-lots__lot{ padding-left:44px; font-weight:500; }
.isis-crv-lots__alerte{ display:inline-block; margin-left:8px; font-size:11px; font-weight:600;
    color:var(--isis-warning-text); background:var(--isis-warning-soft); border-radius:999px; padding:1px 8px; }
.isis-crv-ventil-toggle{ display:inline-flex; align-items:center; gap:6px; cursor:pointer; font-size:11.5px; color:var(--isis-text-soft); user-select:none; }
.isis-crv-ventil-toggle input[type="checkbox"]{ accent-color:var(--isis-mod-gescom); cursor:pointer; margin:0; }
.isis-crv-det__toolbar{ display:flex; align-items:center; gap:10px; padding:0 18px 8px; border-bottom:1px solid var(--isis-border-soft); }
.isis-crv-ventil-toggle__hint{ font-size:11px; color:var(--isis-mod-gescom); font-weight:600; }
.isis-sidepanel-section{ margin-top:1.75rem; border-top:1px solid var(--isis-border); padding-top:1.25rem; }
.isis-grid--overhead-defaults .isis-grid__head,
.isis-grid--overhead-defaults .isis-grid__row{ grid-template-columns: 110px minmax(120px,1.4fr) 110px 120px 80px 70px; }
.isis-crv-det__body{ border-top:1px solid var(--isis-border-soft); }
.isis-costing-items tr.isis-costing-row-line.is-clickable{ cursor:pointer; }
.isis-costing-items tr.isis-costing-row-line.is-clickable:hover > td{ background:var(--isis-surface-alt); }
/* Le fond teinté porte SEUL le signal « ligne en cours d'édition ». Le rail 3 px
   qui doublait ce fond est retiré (DESIGN.md §1, règle du 2026-07-18 : sur une ligne
   de tableau le liseré est purement supprimé, il décalait en plus le contenu de la
   première colonne). La rangée de l'éditeur juste en dessous garde son filet bas
   teinté, qui ferme le bloc. */
.isis-costing-items tr.isis-costing-row-line.is-editing > td{ background:color-mix(in srgb,var(--crv-mod) 6%,var(--isis-surface)); }
/* ════════════════════════════════════════════════════════════════════════
   Éditeur du déboursé — « continuité stricte » (validé le 2026-09-24)
   L'éditeur EST le bloc de lecture : il rend les mêmes classes
   .isis-ligne-acti* que <DevisLigneActivites> (fin de fichier), donc le rail,
   l'échelle de retrait (activité 31 px, ressource 55 px, filet 25 px) et les
   pistes de chiffres sont définis UNE fois et les deux surfaces les partagent.
   Rien ne bouge au passage de la lecture à l'édition. L'aplat de groupe, la
   carte par allocation et la puce d'activité de l'itération de septembre ont
   disparu avec la refonte sans fond du 2026-09-23 : la hiérarchie tient
   désormais à la seule indentation.
   ════════════════════════════════════════════════════════════════════════ */
.isis-crv-editrow > td{ padding:0 !important; border-bottom:1px solid var(--crv-mod) !important; }
/* Deux colonnes : le détail à gauche, le récap économique à droite. Les enfants
   sont placés par `grid-area` plutôt que par un conteneur de markup — la boîte
   reste le seul élément borné et collé à gauche, et le DOM de l'éditeur ne gagne
   pas un niveau. ⚠ Un enfant ajouté sans `grid-area` tomberait dans une rangée
   implicite sous la grille : lui en donner une. */
.isis-crv-edit{ position:sticky; left:0; width:min(1000px,100%); box-sizing:border-box;
    padding:12px 0 14px 0;
    display:grid; grid-template-columns:minmax(0,1fr) 236px; column-gap:16px;
    grid-template-areas:"hd recap" "ind recap" "tbl recap" "foot recap" "avis avis" "ft ft"; }
.isis-crv-edit__hd{ grid-area:hd; }
.isis-crv-edit__ind{ grid-area:ind; }
.isis-crv-edit > .isis-ligne-acti{ grid-area:tbl; }
.isis-crv-edit__foot{ grid-area:foot; }
/* Région vivante des avis d'application d'un gabarit : montée en permanence (le conteneur
   porteur d'aria-live doit préexister à son contenu), donc vide elle ne doit rien peser —
   pas de marge, la rangée de grille se replie à zéro. */
.isis-crv-edit__avis{ grid-area:avis; }
.isis-crv-edit__avis .rz-alert{ margin:10px 0 0 14px; }
.isis-crv-edit__avis-liste{ margin:4px 0 0 0; padding-left:1.1rem; display:flex;
    flex-direction:column; gap:3px; font-size:.78rem; }
.isis-crv-edit > .isis-ligne-recap{ grid-area:recap; align-self:start; }
.isis-crv-edit__ft{ grid-area:ft; }

/* Le bloc est rendu hors du shell (dialogue d'élaboration) : --isis-current-mod
   n'y existe pas. La couleur de module de cette surface, c'est --crv-mod. */
.isis-crv .isis-ligne-acti{ --acti-mod: var(--crv-mod); }

/* En-tête : aligné sur la première colonne du bloc (13 px, comme l'icône d'activité). */
.isis-crv-edit__hd{ display:flex; align-items:baseline; gap:8px; padding:0 0 7px 14px; }
.isis-crv-edit__t{ font-size:.7rem; font-weight:600; letter-spacing:.05em; text-transform:uppercase;
    color:color-mix(in srgb,var(--crv-mod) 72%,var(--isis-text)); flex:0 0 auto; }
.isis-crv-edit__nm{ font-size:.8rem; font-weight:600; color:var(--isis-text);
    min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.isis-crv-edit__hint{ font-size:.72rem; font-style:italic; color:var(--isis-text-muted); flex:0 0 auto; }
.isis-crv-edit__spacer{ flex:1; }
.isis-crv-edit__close{ display:inline-flex; align-items:center; gap:5px; font-size:.72rem; font-weight:600;
    color:var(--isis-text-muted); background:none; border:0; cursor:pointer;
    padding:4px 7px; border-radius:var(--isis-radius-sm); }
.isis-crv-edit__close:hover{ color:var(--isis-text); background:var(--isis-surface-alt); }

/* Aucune règle générique ne couvre un <button> nu de cette feuille : sans halo
   explicite, ces deux gestes ne devaient leur visibilité au clavier qu'au contour
   par défaut du navigateur (audit a11y du 2026-09-24). */
.isis-crv-edit__close:focus-visible,
.isis-crv-edit__add:focus-visible{
    outline:2px solid var(--crv-mod); outline-offset:2px;
    border-radius:var(--isis-radius-sm);
}

/* Un SEUL écart de piste avec la lecture (`.isis-ligne-acti.has-actions`, à
   `1fr 72px 104px 104px 40px`) : la Quantité passe de 72 à 104 px pour tenir le
   champ et son unité. Les trois autres pistes sont identiques au pixel, sinon les
   colonnes sauteraient horizontalement à chaque ouverture de l'éditeur. Seule la
   hauteur de rangée diffère encore. Le modificateur ne porte JAMAIS
   .has-actions : `.isis-ligne-acti.has-actions .isis-ligne-acti__row` pèse
   (0,3,0) et écraserait cette règle à (0,2,0) — la piste Quantité reviendrait
   au gabarit de lecture, trop étroit pour le champ. */
.isis-ligne-acti--edit .isis-ligne-acti__head,
.isis-ligne-acti--edit .isis-ligne-acti__row{
    grid-template-columns:minmax(0,1fr) 104px 104px 104px 62px;
}
/* TROISIÈME écart assumé avec la lecture (après la piste Quantité et le groupe
   « Mode direct » toujours visible) : la piste d'actions passe de 40 à 62 px
   depuis 0811 — modifier et supprimer, deux cibles de 24 px et leur écart, sans
   descendre sous le minimum de WCAG 2.5.8. */
.isis-ligne-acti--edit .isis-ligne-acti__act{ gap:4px; }

/* La cible élargie à 44x44 du bouton d'action (plus haut dans cette feuille) suppose
   une rangée de 44 px. Ici la rangée fait 32 px et les gestes sont maintenant DEUX :
   deux carrés de 44 px centrés à 32 px l'un de l'autre se chevauchent de 12 px, et
   c'est le dernier du DOM — Supprimer — qui l'emporte dans le recouvrement. Une bande
   du bouton Modifier déclencherait donc une suppression. On ramène la cible à la boîte
   de la rangée : 28 px visibles, au-dessus du minimum de 24x24 de WCAG 2.5.8 (AA), et
   le recouvrement VERTICAL avec la rangée voisine disparaît par la même occasion. */
.isis-ligne-acti--edit .isis-grid__action-btn::after{ width:30px; height:30px; }
.isis-ligne-acti--edit .isis-ligne-acti__row{ min-height:32px; }

/* Rangée d'ajout : à l'indentation d'une ressource, sous son groupe — le geste
   est posé au niveau de ce qu'il crée. Le filet s'arrête à mi-hauteur, sur le
   bouton : il rattache le geste au groupe sans faire croire qu'une ressource
   de plus existe déjà. */
.isis-ligne-acti__row--add .isis-ligne-acti__lbl{ position:relative; padding-left:42px; }
.isis-ligne-acti__row--add .isis-ligne-acti__lbl::before{
    content:""; position:absolute; left:25px; top:0; bottom:50%; width:1px; background:var(--acti-guide);
}
/* Un filet ne sépare que deux GROUPES : à l'intérieur d'un groupe, ni entre
   deux ressources, ni avant son geste d'ajout. */
.isis-ligne-acti__row--res + .isis-ligne-acti__row--add,
.isis-ligne-acti__row--acti + .isis-ligne-acti__row--add{ border-top:none; }

/* Cellule Quantité : le champ et son unité tiennent ensemble, calés à droite
   comme les deux pistes chiffrées voisines. L'unité manquait complètement à
   l'éditeur — « 2,5 » ne disait pas si c'étaient des jours ou des heures. */
.isis-crv-qte{ display:flex; align-items:center; justify-content:flex-end; gap:5px; min-width:0; }
.isis-crv-qte input{ width:100%; text-align:right; font-family:var(--isis-font-mono); font-variant-numeric:tabular-nums; }
.isis-crv-qte__u{ flex:0 0 18px; font-size:.7rem; color:var(--isis-text-muted); text-align:left; }

/* Quantité CALCULÉE (0811) : même gabarit chiffré que le champ voisin, sans la
   boîte — l'absence de cadre est ce qui dit « ne se modifie pas ici ». Le chiffre
   garde la couleur de texte pleine : il vaut autant que celui d'à côté, seule sa
   provenance diffère. */
.isis-crv-qte__ro{ flex:1 1 auto; min-width:0; display:flex; align-items:center;
    justify-content:flex-end; gap:3px; font-family:var(--isis-font-mono);
    font-variant-numeric:tabular-nums; font-size:.78rem; color:var(--isis-text); }
.isis-crv-qte__ro .rzi{ flex:0 0 auto; }
.isis-crv-qte__ro > span{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }

/* Puce de mode, posée contre le libellé de la ressource : sans elle, un champ
   manquant passerait pour une panne plutôt que pour une quantité dérivée.
   --isis-text-muted tient 7.4:1 en clair et 6.15:1 en sombre sur la couche
   intermédiaire — AA large marge, malgré la taille. */
.isis-crv-mode{ flex:0 0 auto; font-size:.68rem; font-weight:600;
    color:var(--isis-text-muted); background:var(--isis-surface-2);
    border:1px solid var(--isis-border); border-radius:var(--isis-radius-sm);
    padding:0 5px; line-height:15px; white-space:nowrap; }

/* Mode dont le reglage d'offre est ETEINT : la mobilisation existe, elle ne pese rien
   (0822). Meme traitement que .isis-crv-cond ci-dessous et pour la meme raison — une
   information qui change ce que vaut la ligne ne peut pas porter le gris de « forfait
   2,5 j », qui est neutre. --isis-warning-text sur --isis-warning-soft : le couple deja
   mesure AA de la maison. */
.isis-crv-mode--inactif{ color:var(--isis-warning-text); background:var(--isis-warning-soft);
    border-color:var(--isis-warning); }

/* Condition de mobilisation majorée (nuit, dimanche, férié — profils de coût 0815).
   Volontairement DISTINCTE de .isis-crv-mode : le mode de calcul est une mécanique
   neutre, la condition est un surcoût — EF-40 demande de l'identifier d'un coup d'œil,
   ce qu'un second badge gris ne permettrait pas. --isis-warning-text sur
   --isis-warning-soft est le couple déjà mesuré AA de la maison. */
.isis-crv-cond{ flex:0 0 auto; font-size:.68rem; font-weight:700;
    color:var(--isis-warning-text); background:var(--isis-warning-soft);
    border:1px solid var(--isis-warning); border-radius:999px;
    padding:0 7px; line-height:15px; white-space:nowrap; }

/* Contraste AA (WCAG 1.4.3) : --crv-mod brut sur --isis-surface ne tient pas les
   4.5:1 exigés à cette taille — même formule éprouvée que l'ancienne puce
   d'activité (assombrie en clair, pleine en sombre, mesurée 5.94:1 sur le fond
   le plus défavorable). */
.isis-crv-edit__add{ display:inline-flex; align-items:center; gap:5px; font-size:.72rem; font-weight:600;
    color:color-mix(in srgb,var(--crv-mod) 80%,black); background:none; border:0; cursor:pointer;
    padding:4px 6px 4px 0; border-radius:var(--isis-radius-sm); }
:root[data-theme="dark"] .isis-crv-edit__add{ color:var(--crv-mod); }
.isis-crv-edit__add:hover{ text-decoration:underline; }

/* Bandeau « Inducteurs comptés » (0821) : les grandeurs physiques de la LIGNE, posées
   AU-DESSUS du déboursé parce qu'elles le précèdent dans le calcul. Aligné sur la même
   première colonne que l'en-tête et le pied (14 px). Il reste affiché vide — c'est lui
   qui dit où débloquer le mode « rendement par inducteur » grisé dans le dialogue. */
.isis-crv-edit__ind{ display:flex; align-items:center; gap:8px; flex-wrap:wrap;
    padding:0 0 8px 14px; }
.isis-crv-edit__ind-lbl{ font-size:.7rem; font-weight:600; letter-spacing:.04em; text-transform:uppercase;
    color:var(--isis-text-soft); flex:0 0 auto; }
.isis-crv-ind-chip{ display:inline-flex; align-items:center; gap:6px; font-size:.74rem;
    color:var(--isis-text); background:var(--isis-surface-alt);
    border:1px solid color-mix(in srgb,var(--isis-border) 70%,transparent);
    border-radius:999px; padding:1px 4px 1px 9px; }
.isis-crv-ind-chip__l{ color:var(--isis-text-soft); }
.isis-crv-ind-chip__q{ font-weight:700; font-variant-numeric:tabular-nums; }
/* Compteur de mobilisations adossées : c'est lui qui explique le retrait grisé à côté. */
.isis-crv-ind-chip__n{ font-size:.66rem; font-weight:700; font-variant-numeric:tabular-nums;
    color:color-mix(in srgb,var(--crv-mod) 80%,black);
    background:color-mix(in srgb,var(--crv-mod) 14%,transparent);
    border-radius:999px; padding:0 5px; line-height:15px; }
:root[data-theme="dark"] .isis-crv-ind-chip__n{ color:var(--crv-mod);
    background:color-mix(in srgb,var(--crv-mod) 22%,transparent); }
/* Cible de 24×24 px (WCAG 2.5.8 AA) tenue par le padding, l'icône restant à 12 px :
   une pastille de 20 px de haut ne doit pas rétrécir la zone cliquable. */
.isis-crv-ind-chip__b{ display:inline-flex; align-items:center; justify-content:center;
    min-width:24px; min-height:24px; padding:0; border:0; background:none; cursor:pointer;
    border-radius:var(--isis-radius-sm); color:var(--isis-text-muted); }
.isis-crv-ind-chip__b:hover:not(:disabled){ color:var(--isis-text); background:var(--isis-surface); }
.isis-crv-ind-chip__b--danger:hover:not(:disabled){ color:var(--isis-danger); }
.isis-crv-ind-chip__b:disabled{ opacity:.4; cursor:not-allowed; }
.isis-crv-ind-chip__b:focus-visible{ outline:2px solid var(--crv-mod); outline-offset:1px; }

/* Pied de bloc : les gestes qui créent un GROUPE, sous le dernier groupe. */
.isis-crv-edit__foot{ display:flex; align-items:center; gap:18px; flex-wrap:wrap;
    padding:7px 0 0 14px; margin-top:2px;
    border-top:1px solid color-mix(in srgb,var(--isis-border) 60%,transparent); }

.isis-crv-edit__ft{ display:flex; align-items:center; gap:16px; flex-wrap:wrap;
    margin-top:10px; padding:10px 0 0 14px; border-top:1px solid var(--isis-border); }
.isis-crv-edit__m{ font-size:11px; text-transform:uppercase; letter-spacing:.04em; color:var(--isis-text-soft); font-weight:700; }
.isis-crv-edit__m b{ display:block; font-size:14px; color:var(--isis-text); font-variant-numeric:tabular-nums; }
.isis-crv-edit__m b.is-below-floor{ color:var(--isis-danger); }
.isis-crv-edit__m b.is-below-target{ color:var(--isis-warning); }
.isis-crv-edit__m b.is-on-target{ color:var(--isis-success); }

/* Bouton de suppression visible en PERMANENCE sur cet écran (retour terrain :
   une icône rouge seule, sans contour, s'y perdait). `.isis-grid__action-btn--danger`
   (~40 usages produit) reste INTACTE — ce contour s'ajoute EN PLUS, scopé ici.
   Contraste AA / non-texte (WCAG 1.4.3 / 1.4.11), ratios mesurés au navigateur sur
   les VRAIES couleurs RadZen (--rz-danger = #f44336, --rz-danger-lighter = un RGBA
   translucide dont le rendu dépend du fond, d'où le fond de survol opaque local) :
   - Texte repos/survol vs surface claire 5.99:1 · vs surface sombre 6.57:1
   - Contour vs surface claire 4.28:1 · sombre 4.00:1 · fonds de survol 3.51 / 3.46:1
   L'en-tête teinté qui imposait les mesures les plus serrées (4.91:1 / 3.50:1) a
   disparu avec l'aplat de groupe : il ne reste que le cas sur surface. */
.isis-ligne-acti--edit .isis-grid__action-btn--danger{
    color:color-mix(in srgb, var(--rz-danger,#dc2626) 75%, black);
    border:1px solid color-mix(in srgb, var(--rz-danger,#dc2626) 92%, black);
    border-radius:var(--isis-radius-sm);
}
:root[data-theme="dark"] .isis-ligne-acti--edit .isis-grid__action-btn--danger{
    color:color-mix(in srgb, var(--rz-danger,#dc2626) 70%, white);
}
.isis-ligne-acti--edit .isis-grid__action-btn--danger:hover{
    background:color-mix(in srgb, var(--rz-danger,#dc2626) 15%, var(--isis-surface));
}

/* Fenêtre étroite : on resserre les trois pistes fixes plutôt que d'en retirer
   une — aucune donnée ne disparaît, et le libellé garde la place qui reste. */
@media (max-width:980px){
    /* Le récap repasse sous le détail plutôt que de l'étrangler : à 236 px de
       piste fixe, le libellé des ressources n'aurait plus de quoi se lire. */
    .isis-crv-edit{ grid-template-columns:minmax(0,1fr);
        grid-template-areas:"hd" "ind" "tbl" "foot" "avis" "recap" "ft"; }
    .isis-ligne-acti--edit .isis-ligne-acti__head,
    .isis-ligne-acti--edit .isis-ligne-acti__row{
        grid-template-columns:minmax(0,1fr) 96px 84px 92px 60px; gap:0 8px; padding-right:8px;
    }
    .isis-ligne-acti--edit .isis-ligne-acti__act{ gap:2px; }
    /* La largeur du champ est portée en ligne par le composant Radzen : seul !important
       la reprend (l'inline bat toute règle de feuille à spécificité égale ou non). */
    .isis-crv-qte > :first-child{ width:64px !important; }
}
.isis-comment-bubble:focus-visible{ outline:2px solid color-mix(in srgb,var(--isis-mod-gescom) 55%,transparent); outline-offset:1px; }

/* légende du simulateur (zone 3) — état au repos / remise active */
.isis-crv-simcap{ font-size:11.5px; color:var(--isis-text-soft); }

/* ── Barre de synthèse compacte (Diagnostic + Décompo + Levier fusionnés, sous le détail) ── */
.isis-crv-synth{ display:flex; align-items:center; gap:16px; flex-wrap:wrap; padding:11px 16px; }
/* Barre de marge ancrée au bas des onglets Réglages du coût et Coût de revient (2026-10-02) :
   margin-top:auto la pousse au bas quand le contenu est court, sticky la garde visible quand
   l'onglet défile — .isis-costing-tab est la zone qui défile. */
.isis-tab-panel--footed > .isis-costing-tab > .isis-crv-synth{ position:sticky; bottom:0; z-index:2;
    margin-top:auto; flex-shrink:0; box-shadow:var(--isis-elevation-2); }
.isis-crv-synth__grp{ display:flex; align-items:center; gap:10px; }
.isis-crv-synth__div{ width:1px; align-self:stretch; min-height:30px; background:var(--isis-border-soft); }
.isis-crv-synth__metric{ display:flex; flex-direction:column; line-height:1.1; }
.isis-crv-synth__lbl{ font-size:10px; text-transform:uppercase; letter-spacing:.05em; color:var(--isis-text-soft); font-weight:700; white-space:nowrap; }
.isis-crv-synth__mpct{ font-size:22px; font-weight:800; font-variant-numeric:tabular-nums; letter-spacing:-.01em; color:var(--isis-text); transition:color var(--isis-motion-fast); }
.isis-crv-synth__mpct.is-on-target{ color:var(--isis-success); }
.isis-crv-synth__mpct.is-below-target{ color:var(--isis-warning); }
.isis-crv-synth__mpct.is-below-floor{ color:var(--isis-danger); }
.isis-crv-synth__mpct.is-no-cost,.isis-crv-synth__mpct.is-unclassified{ color:var(--isis-text-muted); }
.isis-crv-synth__mpct--sm{ font-size:16px; font-weight:700; font-variant-numeric:tabular-nums; color:var(--isis-text); transition:color var(--isis-motion-fast); }
.isis-crv-synth__mpct--sm.is-on-target{ color:var(--isis-success); }
.isis-crv-synth__mpct--sm.is-below-target{ color:var(--isis-warning); }
.isis-crv-synth__mpct--sm.is-below-floor{ color:var(--isis-danger); }
.isis-crv-synth__mpct--sm.is-no-cost,.isis-crv-synth__mpct--sm.is-unclassified{ color:var(--isis-text-muted); }
.isis-crv-synth__sub{ font-size:11.5px; color:var(--isis-text-soft); white-space:nowrap; }
.isis-crv-synth__sub strong{ color:var(--isis-text); }
.isis-crv-synth__risk{ cursor:pointer; border:0; font-family:inherit; }
.isis-crv-synth__sim{ flex-wrap:wrap; }
.isis-crv-gauge--mini{ margin:0; width:165px; }
.isis-crv-gauge--mini .isis-crv-gauge__track{ height:10px; }
.isis-crv-gauge--mini .isis-crv-gauge__cur{ top:-4px; height:18px; }
.isis-crv-gauge--mini .isis-crv-gauge__scale{ margin-top:5px; font-size:9.5px; }
.isis-crv-stack--mini{ width:170px; height:12px; }
.isis-crv-sim__slider--mini{ width:110px; margin:0; }

/* ── Réglages du coût, en cascade (2026-10-02) ──
   Une rangée par étape du calcul : opérateur, titre, réglage, effet en montant. La colonne
   des montants est alignée sur toute la cascade pour que l'œil la lise comme une addition.
   Le dialogue est un .isis-form-linear, dont `.rz-numeric { width:100% !important }`
   écraserait la largeur des champs : on la reborne ici. */
.isis-crv-reglages__head{ display:flex; align-items:flex-start; gap:10px; padding:12px 16px 8px; }
.isis-crv-reglages__titles{ display:flex; flex-direction:column; gap:2px; }
.isis-crv-reglages__head h3{ margin:0; font-size:13px; font-weight:600; }
.isis-crv-reglages__sub{ font-size:11.5px; color:var(--isis-text-soft); }
.isis-crv-cascade{ list-style:none; margin:0; padding:0 0 4px; }
.isis-crv-step{ display:grid; grid-template-columns:36px minmax(200px,1.1fr) minmax(0,2fr) 128px;
    column-gap:12px; row-gap:4px; align-items:center; padding:10px 16px;
    border-top:1px solid var(--isis-border); }
.isis-crv-step__op{ align-self:start; padding-top:1px; font-size:13px; font-weight:600; color:var(--isis-text-muted); text-align:center; }
.isis-crv-step--total .isis-crv-step__op{ align-self:center; padding-top:0; }
.isis-crv-step__titles{ display:flex; flex-direction:column; gap:2px; min-width:0; }
.isis-crv-step__titles h4{ margin:0; font-size:12.5px; font-weight:600; color:var(--isis-text); }
.isis-crv-step__sub{ font-size:11.5px; color:var(--isis-text-soft); }
.isis-crv-step__ctrl{ display:flex; align-items:center; gap:8px; flex-wrap:wrap; min-width:0; }
.isis-crv-step__unit{ font-size:12px; font-weight:600; color:var(--isis-text-muted); }
.isis-crv-step__state{ font-size:11.5px; font-weight:600; color:var(--isis-text-soft); }
.isis-crv-step__state strong{ color:var(--isis-text); }
.isis-crv-step__amount{ text-align:right; font-size:13px; font-weight:600; color:var(--isis-text);
    font-variant-numeric:tabular-nums; white-space:nowrap; }
.isis-crv-step__amount.is-off{ color:var(--isis-text-muted); font-weight:400; }
.isis-crv-step__foot{ grid-column:2 / -1; display:flex; flex-direction:column; gap:2px; }
.isis-crv-step__foot .helper{ margin:0; }
.isis-crv-step__effet{ font-size:12px; color:var(--isis-text-muted); line-height:1.5; }
.isis-crv-step__effet:empty{ display:none; }
.isis-crv-step__effet strong{ color:var(--isis-text); }
.isis-crv-step__toggle{ display:inline-flex; align-items:center; gap:4px; padding:2px 8px 2px 4px;
    font:inherit; font-size:12px; font-weight:600; color:var(--isis-text); background:none;
    border:1px solid var(--isis-border); border-radius:var(--isis-radius-sm); cursor:pointer; }
.isis-crv-step__toggle:hover{ background:var(--isis-surface-2); }
.isis-crv-step__toggle:focus-visible{ outline:2px solid var(--isis-current-mod); outline-offset:2px; }
.isis-crv-step--total{ background:var(--isis-surface-2); padding-top:8px; padding-bottom:8px; }
.isis-crv-step--total .isis-crv-step__op,
.isis-crv-step--total .isis-crv-step__titles h4{ color:var(--isis-text); }
/* --isis-text-soft passe sous 4,5:1 sur la surface grise des totaux. */
.isis-crv-step--total .isis-crv-step__sub{ color:var(--isis-text-muted); }
.isis-crv-step--prix .isis-crv-step__amount{ color:var(--crv-mod); font-size:14px; }
.isis-crv-bilan.is-perte .isis-crv-step__titles h4,
.isis-crv-bilan.is-perte .isis-crv-step__amount{ color:var(--isis-danger-text); }
.isis-crv-bilan.is-aleanoncouvert .isis-crv-step__titles h4,
.isis-crv-bilan.is-souscible .isis-crv-step__titles h4{ color:var(--isis-warning-text); }
.isis-crv-bilan.is-aleanoncouvert .isis-crv-step__amount{ color:var(--isis-danger-text); }
.isis-crv-bilan.is-cibletenue .isis-crv-step__titles h4{ color:var(--isis-success-text); }
/* Le détail du bilan est une phrase : il prend la place de la colonne de réglage, vide ici. */
.isis-crv-bilan .isis-crv-step__titles{ grid-column:2 / 4; }
.isis-form-linear .isis-crv-step .rz-numeric{ width:8.5rem !important; flex:none; }
.isis-form-linear .isis-crv-alea .rz-numeric{ width:7rem !important; }
.isis-crv-alea .isis-crv-step__ctrl{ column-gap:16px; }
.isis-crv-pair{ display:inline-flex; align-items:center; gap:6px; white-space:nowrap; }
.isis-crv-overhead__body{ padding:4px 0 0; }
.isis-crv-overhead__calc{ font-size:11.5px; color:var(--isis-text-soft); font-variant-numeric:tabular-nums; }
.isis-crv-overhead .isis-costing-items tbody > tr.isis-costing-row-line > td{ padding-top:0.3rem; padding-bottom:0.3rem; }
@media (max-width: 900px){
    .isis-crv-step{ grid-template-columns:28px minmax(0,1fr) auto; }
    .isis-crv-step__ctrl{ grid-column:2 / -1; grid-row:2; }
    .isis-crv-step__amount{ grid-column:3; grid-row:1; }
    .isis-crv-step__foot{ grid-column:2 / -1; }
    .isis-crv-bilan .isis-crv-step__titles{ grid-column:2; }
}

/* ============================================================
   Mode Hiérarchie de l'organigramme (org duale) — org-chart vertical.
   Réf maquette docs/mockups/2026-06-20-org-duale-hierarchie.html.
   Connecteurs tracés en JS (org-hierarchy.js) dans .otree__links.
   ============================================================ */
.otree {
    /* Couleurs d'axe répliquées de .isis-pivot-wrap : l'épine est ici hors de
       .isis-pivot-wrap, donc --pj/--pt/--pg ne cascaderaient pas sinon. */
    --pj:#5b4be6; --pj-soft:#ece9fe; --pj-ink:#4338ca;
    --pt:#0d9488; --pt-soft:#d2f3ef; --pt-ink:#0f766e;
    --pg:#7c3aed; --pg-soft:#ede9fe;
    --pmgr:#facc15; --pconn:2px;
    /* Layout de l'arbre — ailes en largeur de contenu (compact) ; pas de min-width
       (sinon ~500px de scroll fantôme), recentrage + connecteurs gérés en JS. */
    --gap:38px; --hsib:16px;
    display:inline-block; position:relative;
}
.otree__links { position:absolute; top:0; left:0; width:100%; height:100%; overflow:visible; pointer-events:none; z-index:0; }
/* Fil d'ascendance (mode Hiérarchie scopé) : Groupe › entreprise parente › … */
.otree-ancestry { position:relative; z-index:1; display:flex; flex-wrap:wrap; align-items:center; gap:6px 8px; margin:0 0 16px; font-size:12px; }
.otree-ancestry__node { display:inline-flex; align-items:center; gap:6px; background:var(--isis-surface); border:1px solid var(--isis-border); border-radius:var(--isis-radius-sm); box-shadow:var(--isis-elevation-1); padding:5px 10px; cursor:pointer; font:inherit; color:var(--isis-text); }
.otree-ancestry__node:hover { border-color:var(--isis-text-muted); }
.otree-ancestry__ic { display:flex; color:var(--isis-text-muted); }
.otree-ancestry__nm { font-weight:600; }
.otree-ancestry__sep { color:var(--isis-text-muted); }
.otree-ancestry__here { color:var(--isis-text-muted); font-style:italic; }

/* Menu déroulant « Exporter » (toolbar org duale) */
.isis-export-menu { position:relative; display:inline-flex; }
.isis-export-menu__pop { position:absolute; top:calc(100% + 4px); right:0; z-index:60; display:flex; flex-direction:column; min-width:260px; background:var(--isis-surface); border:1px solid var(--isis-border); border-radius:var(--isis-radius); box-shadow:var(--isis-elevation-2); padding:4px; }
.isis-export-menu__pop button { display:flex; align-items:center; gap:9px; width:100%; text-align:left; background:none; border:0; border-radius:var(--isis-radius-sm); padding:8px 10px; font:inherit; font-size:12.5px; color:var(--isis-text); cursor:pointer; }
.isis-export-menu__pop button:hover { background:var(--isis-surface-alt); }
.otree ul { position:relative; padding-top:var(--gap); display:flex; justify-content:center; align-items:flex-start; gap:var(--hsib); margin:0; list-style:none; }
.otree li { position:relative; padding:var(--gap) var(--hsib) 0; display:flex; flex-direction:column; align-items:center; }
.otree > ul { padding-top:0; }
.otree > ul > li { padding-top:0; }
.otree .ospine, .otree .ocard, .otree .grpnode { position:relative; z-index:1; }

/* Épine en mode Hiérarchie : ailes en largeur de CONTENU (auto) → chaque épine
   aussi étroite que son contenu réel (compact, pas de vide réservé). Le recentrage
   des sous-arbres + les connecteurs (JS) visent les pivots, pas besoin d'ailes fixes.
   Override plus spécifique que la règle globale .isis-pivot__lane (À plat intact). */
.otree .isis-pivot__lane { grid-template-columns:auto 30px 260px 30px auto; }

/* Bouton repli flottant superposé au pivot de l'épine */
.otree .isis-pivot__centre { position:relative; }
.otree .pivot__exp--float { position:absolute; top:10px; right:10px; z-index:3; width:24px; height:24px; display:flex; align-items:center; justify-content:center; border:1px solid var(--isis-border); border-radius:var(--isis-radius-sm); background:var(--isis-surface-alt); color:var(--isis-text-muted); cursor:pointer; }
.otree .pivot__exp--float:hover { background:var(--pt-soft); color:var(--pt-ink); border-color:transparent; }

/* Carte Groupe (racine de l'arbre) */
.otree .grpnode { display:inline-flex; align-items:center; gap:11px; background:var(--isis-surface); border:1px solid var(--isis-border); border-top:3px solid var(--pg); border-radius:var(--isis-radius); box-shadow:var(--isis-elevation-2); padding:11px 18px; }
.otree .grpnode .gi { width:34px; height:34px; border-radius:9px; background:var(--pg-soft); color:var(--pg); display:flex; align-items:center; justify-content:center; }
.otree .grpnode .gn { font-weight:700; font-size:15px; display:flex; align-items:center; gap:8px; }
.otree .grpnode .gm { font-size:11.5px; color:var(--isis-text-muted); }

/* Chips (même sémantique que les chips du pivot) */
.otree .chip { font-size:10px; padding:2px 8px; border-radius:var(--isis-radius-pill); font-weight:700; letter-spacing:.02em; white-space:nowrap; }
.otree .chip--grp { background:var(--pg-soft); color:var(--pg); }
.otree .chip--jur { background:var(--pj-soft); color:var(--pj-ink); }
.otree .chip--tech { background:var(--pt-soft); color:var(--pt-ink); }

/* Carte compacte (épine repliée) */
.otree .ocard { display:flex; align-items:center; gap:11px; background:var(--isis-surface); border:1px solid var(--isis-border); border-top:3px solid color-mix(in srgb, var(--isis-mod-sirh, var(--pt)) 50%, var(--isis-border)); border-radius:var(--isis-radius); box-shadow:var(--isis-elevation-1); padding:10px 13px; width:360px; box-sizing:border-box; cursor:pointer; font:inherit; text-align:left; }
.otree .ocard:hover { box-shadow:var(--isis-elevation-2); }
.otree .ocard .pivot__ic { width:28px; height:28px; border-radius:8px; background:var(--pj-soft); color:var(--pj-ink); display:flex; align-items:center; justify-content:center; flex:none; }
.otree .ocard__main { flex:1; min-width:0; }
.otree .ocard__nm { font-weight:700; font-size:13.5px; display:flex; align-items:center; gap:7px; min-width:0; }
/* Le nom tronque (ellipsis) et le chip reste insécable : sinon, dans la carte
   compacte, un nom + chip plus larges que la colonne « main » débordaient et le
   chip « Entreprise » chevauchait les compteurs (Ag./Act./Collab.). */
.otree .ocard__nm-txt { min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.otree .ocard__nm .chip { flex:none; }
.otree .ocard__sub { font-size:11px; color:var(--isis-text-muted); }
.otree .ocard__mini { display:flex; gap:12px; align-items:center; }
.otree .ocard__mini .m { text-align:center; }
.otree .ocard__mini .mv { font-family:'Geist Mono',ui-monospace,monospace; font-weight:700; font-size:13px; }
.otree .ocard__mini .mv.j { color:var(--pj); }
.otree .ocard__mini .mv.t { color:var(--pt-ink); }
.otree .ocard__mini .mk { font-size:10px; color:var(--isis-text-muted); text-transform:uppercase; letter-spacing:.04em; }
.otree .ocard__exp { width:24px; height:24px; border-radius:var(--isis-radius-sm); border:1px solid var(--isis-border); background:var(--isis-surface-alt); color:var(--isis-text-muted); display:flex; align-items:center; justify-content:center; flex:none; }
.otree .ocard:hover .ocard__exp { background:var(--pj-soft); color:var(--pj-ink); border-color:transparent; }

/* Segmented À plat / Hiérarchie (filter-bar Organigramme) */
.isis-segmented { display:inline-flex; background:var(--isis-surface-alt); border:1px solid var(--isis-border); border-radius:var(--isis-radius-sm); padding:2px; }
.isis-segmented__btn { border:0; background:transparent; font:inherit; font-size:12px; color:var(--isis-text-muted); padding:5px 12px; border-radius:calc(var(--isis-radius-sm) - 2px); cursor:pointer; display:inline-flex; align-items:center; gap:5px; transition:background 100ms, color 100ms; }
.isis-segmented__btn:hover { color:var(--isis-text); }
/* Anneau de focus explicite : sans lui, un segmented n'a que l'outline par défaut du
   navigateur, rogné par l'overflow du conteneur. Repris du segmented maison du hub de
   responsabilités, dont cette classe a pris la relève (2026-09-20). */
.isis-segmented__btn:focus-visible {
    outline: 2px solid var(--isis-current-mod, var(--isis-accent));
    outline-offset: -2px;
}
.isis-segmented__btn.is-active { background:var(--isis-surface); color:var(--isis-text); box-shadow:var(--isis-elevation-1); font-weight:600; }
/* Modificateur OPT-IN : un segmented qui porte beaucoup de segments à libellés longs
   (le sélecteur de module de /admin/permissions/audit est passé de 3 à 12) déborde de sa
   barre de filtres — .isis-segmented est inline-flex sans flex-wrap, et le flex-wrap de
   .isis-filter-bar ne joue qu'ENTRE les groupes, pas à l'intérieur. La règle globale n'est
   pas touchée : les segmented à 2-3 segments gardent leur ligne unique. */
.isis-segmented--wrap { flex-wrap:wrap; row-gap:var(--isis-space-xs); }

/* Modificateur OPT-IN : segmented posé dans une ligne de saisie dense (ajout d'exception
   du hub de responsabilités) — un cran plus serré, sans toucher la règle globale. */
.isis-segmented--sm .isis-segmented__btn { padding:3px 9px; font-size:11.5px; }

/* ============================================================
   Mode Hiérarchie — orientation « Pivoté 90° » (gauche→droite).
   L'arbre va de gauche à droite (groupe à gauche, sœurs empilées
   verticalement, profondeur vers la droite) ; l'épine est verticale
   (agences au-dessus ← pivot → activités en-dessous). Connecteurs en
   CSS pur (rails type explorateur) — pas de calque JS.
   ============================================================ */
.otree--rot { display:inline-block; }
.otree--rot .otree__links { display:none; }                       /* pas de SVG ici */
/* transposition de l'arbre : frères empilés verticalement, profondeur à droite.
   transform:none annule les translateX laissés par le calque JS du mode vertical. */
.otree--rot ul { flex-direction:column; align-items:flex-start; justify-content:center; gap:14px; padding-top:0; transform:none !important; }
.otree--rot li { flex-direction:row; align-items:center; padding:0; }
/* rails (file-tree) : bus vertical à gauche de la sous-liste + élbow par enfant */
.otree--rot li > ul { position:relative; margin-left:30px; padding-left:18px; border-left:var(--conn,2px) solid var(--isis-border); }
.otree--rot li > ul::before { content:""; position:absolute; left:calc(-30px - var(--conn,2px)); top:50%; width:30px; height:var(--conn,2px); background:var(--isis-border); transform:translateY(-50%); }  /* stub parent → bus */
.otree--rot li > ul > li::before { content:""; position:absolute; left:-18px; top:50%; width:18px; height:var(--conn,2px); background:var(--isis-border); transform:translateY(-50%); }                     /* élbow bus → enfant */

/* ── ÉPINE VERTICALE : grille en 5 RANGÉES (agences haut · pivot · activités bas) ── */
.otree--rot .isis-pivot__lane { grid-template-columns:none; grid-template-rows:auto 20px auto 20px auto; justify-items:center; align-items:center; width:auto; }
.otree--rot .isis-pivot__branch { grid-column:auto; padding:0; flex-direction:column; align-items:center; gap:8px; }
.otree--rot .isis-pivot__branch--jur { grid-row:1; }
.otree--rot .isis-pivot__branch--tech { grid-row:5; }
.otree--rot .isis-pivot__bus { grid-column:auto; margin:0; justify-self:center; align-self:stretch; }
.otree--rot .isis-pivot__bus--jur { grid-row:2; }
.otree--rot .isis-pivot__bus--tech { grid-row:4; }
.otree--rot .isis-pivot__bus--jur::after, .otree--rot .isis-pivot__bus--tech::after { display:none; }
.otree--rot .isis-pivot__centre { grid-column:auto; grid-row:3; width:auto; }
.otree--rot .isis-pivot__centre::before { display:none; }          /* le bus--jur assure le lien vertical */
.otree--rot .isis-pivot__unit::after { display:none; }             /* pas de nubs horizontaux en vertical */
.otree--rot .isis-pivot__unit { width:230px; max-width:230px; }
.otree--rot .isis-pivot__empty { font-size:11px; }

/* ── Modale sélecteur : workspace (arbre visuel) — refonte 2026-06-22 ── */
/* Classes de vignette : la seule chose que le C# choisit est le NUMÉRO — les valeurs
   restent dans les jetons, donc dans le thème, donc surchargeables par le white-label. */
.isis-wsav--1 { background: var(--isis-wsav-1-bg); color: var(--isis-wsav-1-fg); }
.isis-wsav--2 { background: var(--isis-wsav-2-bg); color: var(--isis-wsav-2-fg); }
.isis-wsav--3 { background: var(--isis-wsav-3-bg); color: var(--isis-wsav-3-fg); }
.isis-wsav--4 { background: var(--isis-wsav-4-bg); color: var(--isis-wsav-4-fg); }
.isis-wsav--5 { background: var(--isis-wsav-5-bg); color: var(--isis-wsav-5-fg); }
.isis-wsav--6 { background: var(--isis-wsav-6-bg); color: var(--isis-wsav-6-fg); }
/* ── Sélecteur d'espace de travail — grammaire « légende » (spec 2026-09-05 §3) ──────
   Alignée sur .isis-modleg, à quarante pixels de là, sur l'essentiel : rayons, réserve
   pleine à cran fixe mesuré par thème, plafond de dialogue, pied de rappel clavier. UNE
   divergence assumée : .isis-modleg a banni le filet par ligne (son propre commentaire :
   « ce serait le vocabulaire de .isis-grid__row, que l'application a enseigné comme
   signifiant tableau ») — .isis-wstree en pose un entre chaque ligne (cf. règle
   __node + __node plus bas), parce que l'arbre porte une hiérarchie de filiales là où
   le sélecteur de module est une liste plate ; validé côté utilisateur (spec :
   « lignes séparées par un filet fin »), à ne pas retirer. Ce qui change par ailleurs
   rapport à la version 2026-06-22 :
     · les rayons de 11 px et 10 px, hors de l'échelle du projet (4/6/10/999), s'en vont ;
     · la RACINE perd son remplissage d'accent — elle paraissait sélectionnée alors que
       l'espace courant était ailleurs. Elle porte désormais une étiquette « groupe » ;
     · l'espace COURANT prend la réserve pleine, le même marquage que le module courant. */
.isis-wstree { display: flex; flex-direction: column; }

/* Bandeau de tête : capitales espacées à gauche, méta en mono à droite. */
.isis-wstree__bar { display: flex; align-items: center; justify-content: space-between;
  gap: 12px; padding-bottom: 11px; margin-bottom: 13px;
  border-bottom: 1px solid var(--isis-border); }
.isis-wstree__bar b { font-size: 0.78rem; font-weight: 700; letter-spacing: 0.07em;
  text-transform: uppercase; color: var(--isis-text); }
/* --isis-text-muted et non --isis-text-soft : la méta porte un décompte, donc une
   information. Même arbitrage que .isis-modleg__n, où --isis-border-strong (un jeton
   de FILET employé comme encre) ne rendait que 2,57:1 en clair et 1,82:1 en sombre. */
.isis-wstree__meta { font-size: 0.68rem; color: var(--isis-text-muted);
  letter-spacing: 0.04em; font-family: ui-monospace, "SF Mono", Menlo, monospace;
  white-space: nowrap; }

.isis-wstree__search { display: flex; align-items: center; gap: 9px;
  border: 1px solid var(--isis-border-strong); border-radius: var(--isis-radius-sm);
  padding: 8px 11px; margin-bottom: 13px; }
.isis-wstree__search input { border: none; outline: none; background: transparent; flex: 1;
  font: inherit; font-size: 0.83rem; color: var(--isis-text); }
/* 24x24 minimum (WCAG 2.2 AA 2.5.8) : la croix reste dessinée à 14 px, c'est la BOÎTE
   qui grandit. L'exception d'espacement ne s'applique pas — le champ de saisie, cible
   adjacente, est collé à la croix. Mesure 2026-09-24 : 2 px de padding donnaient 18x18. */
.isis-wstree__clear { border: none; background: transparent; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 24px; min-height: 24px; padding: 2px; border-radius: var(--isis-radius-sm);
  color: var(--isis-text-muted); }
.isis-wstree__clear:focus-visible { outline: none;
  box-shadow: 0 0 0 3px color-mix(in oklch, var(--isis-accent) 28%, transparent); }
.isis-wstree__empty { padding: 22px 10px; text-align: center; color: var(--isis-text-muted);
  font-size: 0.85rem; }

.isis-wstree__roots, .isis-wstree__flat { display: flex; flex-direction: column;
  max-height: 56vh; overflow: auto; }
/* Le listbox porte le focus quand il n'y a pas de champ de recherche (moins de cinq
   entreprises) : sans halo, on ne saurait pas que les flèches s'adressent à lui. */
.isis-wstree__roots:focus-visible, .isis-wstree__flat:focus-visible {
  outline: none; box-shadow: 0 0 0 3px color-mix(in oklch, var(--isis-accent) 28%, transparent); }

/* Réserve de l'espace courant : l'accent poussé à l'opposé de --isis-surface d'un cran
   FIXE. L'accent est white-label — il peut être pâle chez un tenant — donc on ne peut
   pas se fier à sa luminosité. Deux crans mesurés, comme pour .isis-modleg. */
.isis-wstree { --wsleg-shift: 22%; --wsleg-voile: 8%; }
:root[data-theme="dark"] .isis-wstree { --wsleg-shift: 10%; --wsleg-voile: 8%; }

/* box-sizing explicite : ce projet n'a PAS de reset universel. Dans la fenêtre, Radzen en fournit un et width:100% + padding
   tombaient juste ; sur /workspace/choose, qui n'est pas un dialogue Radzen, il n'y en
   a aucun — chaque ligne débordait de son listbox de 16 px sur la DROITE (mesuré :
   listbox 516→976, lignes 516→992). Aucune assertion de contraste ne pouvait le voir. */
.isis-wstree__node { --wsleg-reserve: color-mix(in oklch,
    var(--isis-accent) calc(100% - var(--wsleg-shift)), var(--isis-text));
  box-sizing: border-box;
  display: flex; align-items: center; gap: 11px; width: 100%;
  padding: 8px 6px; border: none; border-radius: 0; background: transparent;
  cursor: pointer; text-align: left; font: inherit; }
/* Le filet SÉPARE, il n'entoure pas : c'est ce qui distingue une légende d'un tableau. */
.isis-wstree__node + .isis-wstree__node,
.isis-wstree__wrap + .isis-wstree__wrap > .isis-wstree__node {
  border-top: 1px solid color-mix(in oklch, var(--isis-border) 60%, var(--isis-surface)); }
.isis-wstree__node:hover { background: var(--isis-surface-alt); }
.isis-wstree__node[aria-disabled="true"] { cursor: default; opacity: 0.55; }

.isis-wstree__avatar { box-sizing: border-box;
  width: 26px; height: 26px; border-radius: var(--isis-radius-sm);
  flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
  font-size: 0.62rem; font-weight: 700; overflow: hidden; }

/* Plus de tuile logo (2026-09-24) : les vignettes d'entreprise et le cartouche de groupe
   ne portent plus d'image — le bloc « respiration + fond clair » posé sur :has(img) pour
   la lisibilité en thème sombre n'avait donc plus de cible. Les tokens --isis-logo-surface
   et --isis-logo-border restent définis (palette) ; les initiales gardent leur pastille de
   WorkspaceAvatarPalette. */

.isis-wstree__text { display: flex; align-items: baseline; gap: 9px; min-width: 0;
  flex: 1; line-height: 1.2; }
.isis-wstree__name { font-size: 0.82rem; font-weight: 600; color: var(--isis-text);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.isis-wstree__sub { font-size: 0.7rem; color: var(--isis-text-soft);
  font-family: ui-monospace, "SF Mono", Menlo, monospace; white-space: nowrap; }

/* Étiquette « groupe » : elle remplace le remplissage d'accent de l'ancienne racine.
   Une étiquette DIT ce que la ligne est ; un fond accentué la faisait passer pour
   sélectionnée. Elle ne s'affiche que si la racine a réellement des filiales — sinon
   « groupe » collé à trois racines indépendantes ne veut rien dire (cf. tâche 6). */
.isis-wstree__tag { flex: 0 0 auto; margin-left: auto; font-size: 0.62rem; font-weight: 700;
  letter-spacing: 0.05em; text-transform: uppercase; color: var(--isis-text-soft);
  border: 1px solid var(--isis-border); border-radius: var(--isis-radius-sm);
  padding: 1px 5px; }

/* Espace courant : réserve pleine. Le texte reste --isis-surface, jamais un blanc
   littéral (l'accent a une valeur PROPRE au thème sombre). Le code court est atténué
   vers la réserve par un mélange OPAQUE, pas vers du transparent — le transparent
   laisse remonter la couleur sous le texte et fait chuter le contraste sans produire
   de gris (défaut corrigé sur le sélecteur de module). */
.isis-wstree__node.is-active { background: var(--wsleg-reserve); }
.isis-wstree__node.is-active .isis-wstree__name { color: var(--isis-surface); }
.isis-wstree__node.is-active .isis-wstree__sub {
  color: color-mix(in oklch, var(--isis-surface) 92%, var(--wsleg-reserve)); }
.isis-wstree__node.is-active .isis-wstree__tag {
  color: color-mix(in oklch, var(--isis-surface) 94%, var(--wsleg-reserve));
  border-color: color-mix(in oklch, var(--isis-surface) 45%, var(--wsleg-reserve)); }
/* La vignette à initiales garderait sa pastille de palette sur la réserve : elle
   jurerait. On la voile vers la réserve. Un LOGO garde sa tuile claire (règle :has(img)
   ci-dessous, en !important) : c'est voulu, un logo client reste lisible. */
/* Le voile était à 18 % : l'encre de la vignette (--isis-surface) n'y rendait plus que
   3,76:1 en clair — le seul signe de la ligne COURANTE tombait sous le seuil. Mesuré, pas
   supposé. Porté par un jeton pour rester réglable par thème. */
.isis-wstree__node.is-active .isis-wstree__avatar {
  background: color-mix(in oklch, var(--isis-surface) var(--wsleg-voile), var(--wsleg-reserve));
  color: var(--isis-surface); }

/* Curseur clavier : un filet intérieur, jamais un fond qui contredirait la réserve
   pleine de la ligne courante. Le curseur n'a PAS le focus DOM (aria-activedescendant) :
   sans marque visuelle propre, rien ne dirait où l'on est. */
.isis-wstree__node.is-cursor:not(.is-active) { background: var(--isis-surface-alt); }
.isis-wstree__node.is-cursor { box-shadow: inset 0 0 0 1.5px var(--isis-border-strong); }
.isis-wstree__node.is-cursor.is-active { box-shadow: inset 0 0 0 1.5px var(--isis-surface); }
/* Sur --isis-surface-alt (survol ET curseur), --isis-text-soft tombe à 3,82:1 en clair :
   le code court passe d'un cran. Mesuré sur le sélecteur de module.
   L'ÉTIQUETTE « groupe » porte la même encre et avait été oubliée : mesurée à 3,82:1 sur
   l'écran de choix, où la ligne de groupe est aussi la ligne désignée par le curseur —
   un état que la fenêtre ne montre jamais, la ligne courante y étant toujours ailleurs. */
.isis-wstree__node:hover:not(.is-active) .isis-wstree__sub,
.isis-wstree__node.is-cursor:not(.is-active) .isis-wstree__sub,
.isis-wstree__node:hover:not(.is-active) .isis-wstree__tag,
.isis-wstree__node.is-cursor:not(.is-active) .isis-wstree__tag { color: var(--isis-text-muted); }

/* Filiales : un liseré 1 px (pas 2), sans nub horizontal — le retrait suffit à dire
   le rattachement dans une légende, le connecteur appartenait au vocabulaire « arbre ». */
.isis-wstree__children { margin-left: 13px; padding-left: 14px;
  border-left: 1px solid var(--isis-border); display: flex; flex-direction: column; }

/* Pied de rappel clavier, calqué sur .isis-modleg__foot. La marge négative vaut le
   padding réel du dialogue Radzen (24 px) : à 18 px il restait un liseré du fond de
   dialogue entre le pied et le bord. Neutralisée hors dialogue (cf. ws-choose). */
.isis-wstree__foot { display: flex; gap: 16px; margin: 14px -24px -24px; padding: 10px 24px;
  border-top: 1px solid var(--isis-border); background: var(--isis-surface-alt);
  font-size: 0.7rem; color: var(--isis-text-muted); }
.isis-wstree__foot kbd { font-family: inherit; font-weight: 700;
  background: var(--isis-surface); border: 1px solid var(--isis-border);
  border-radius: var(--isis-radius-sm); padding: 0 4px; margin-right: 4px; }

/* Plafond de hauteur : le thème Radzen pose overflow:hidden sur .rz-dialog sans overflow
   sur .rz-dialog-content (même recette que .isis-modleg-dialog). Le défilement est porté
   par la LISTE seule : faire défiler tout le contenu emporterait le champ de recherche
   et le pied hors de l'écran. */
.rz-dialog.isis-wstree-dialog { max-height: 90vh; }
.rz-dialog.isis-wstree-dialog .rz-dialog-content {
  display: flex; flex-direction: column; min-height: 0; overflow: hidden; }
.rz-dialog.isis-wstree-dialog .isis-wstree { flex: 1 1 auto; min-height: 0; }
.rz-dialog.isis-wstree-dialog .isis-wstree__roots,
.rz-dialog.isis-wstree-dialog .isis-wstree__flat { flex: 1 1 auto; min-height: 0; }

/* ── Sélecteur de module — « légende de planche » (spec 2026-09-03) ────────────
   Filets 1 px, pas de pastille, pas d'ombre décorative : le monde Cartouche.
   L'overlay Radzen étant rendu hors .isis-shell, la couleur passe par mod-{code}. */
.isis-modleg { display: flex; flex-direction: column; }
.isis-modleg__search { display: flex; align-items: center; gap: 9px;
  border: 1px solid var(--isis-border-strong); border-radius: var(--isis-radius-sm);
  padding: 8px 11px; margin-bottom: 14px; }
.isis-modleg__search input { border: none; outline: none; background: transparent; flex: 1;
  font: inherit; font-size: 0.83rem; color: var(--isis-text); }
.isis-modleg__clear { border: none; background: transparent; cursor: pointer;
  display: inline-flex; padding: 2px; color: var(--isis-text-muted); }
.isis-modleg__empty { padding: 22px 10px; text-align: center; color: var(--isis-text-muted);
  font-size: 0.85rem; }

/* Bande « Récents » — rangée de raccourcis pleine largeur, sous la recherche et au-dessus
   des colonnes. Elle est hors du calcul d'équilibrage (cf. ModulePickerDialog.Colonnes) :
   les blocs ne bougent donc plus quand le nombre de récents change. Le filet la sépare des
   colonnes pour qu'elle se lise comme un raccourci et non comme une ligne de liste répétée. */
.isis-modleg__grp--bande { margin-top: 0; }
.isis-modleg__bande { display: flex; flex-wrap: wrap; gap: 8px; padding-bottom: 12px;
  margin-bottom: 4px; border-bottom: 1px solid var(--isis-border); }
.isis-modleg__bande .isis-modleg__row { width: auto; flex: 0 0 auto; padding: 6px 11px 6px 8px;
  border: 1px solid var(--isis-border); border-radius: var(--isis-radius-sm); }
/* Dans une pastille, le sous-titre et la lettre encombrent : le nom suffit, le reste
   demeure dans l'infobulle et le nom accessible. */
.isis-modleg__bande .isis-modleg__sb,
.isis-modleg__bande .isis-modleg__k { display: none; }
.isis-modleg__plan { display: grid; grid-template-columns: 1fr 1fr; gap: 10px 26px; }
.isis-modleg__plan.is-single { grid-template-columns: 1fr; }
.isis-modleg__col { min-width: 0; }
.isis-modleg__grp { display: flex; align-items: center; gap: 9px; margin: 0 0 3px;
  font-size: 0.7rem; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--isis-text-soft); }
.isis-modleg__grp:not(:first-child) { margin-top: 13px; }
.isis-modleg__grp::after { content: ''; flex: 1; height: 1px; background: var(--isis-border); }
/* Le décompte porte une information (le nombre de modules du bloc) : encre de TEXTE,
   jamais --isis-border-strong, qui est un jeton de filet et ne rendait que 2.57:1 en
   clair et 1.82:1 en sombre. */
.isis-modleg__n { font-size: 0.7rem; font-weight: 600; letter-spacing: 0;
  color: var(--isis-text-muted); }

/* Réserve du module : la couleur du module poussée à l'opposé de --isis-surface
   (donc assombrie en clair, éclaircie en sombre), du MÊME cran pour les seize —
   sans quoi le texte posé dessus n'atteint pas 4.5:1 sur les teintes les plus
   lumineuses (sirh et ged mesurés à 3.77 et 4.47 avant correction).
   L'écart n'est pas le même dans les deux thèmes : les tokens --isis-mod-* sont
   DÉJÀ éclaircis en sombre (cf. :root[data-theme="dark"]), il n'y reste qu'un
   module à rattraper — d'où 22 % en clair et 10 % en sombre, mesurés. */
.isis-modleg { --modleg-shift: 22%; }
:root[data-theme="dark"] .isis-modleg { --modleg-shift: 10%; }
/* Repli : --isis-mod-default (neutre ardoise), jamais --isis-accent — un module
   sans règle de couleur serait alors peint au teal ISIS, indiscernable d'un choix
   délibéré. Le jeton neutre existe pour ce rôle exact (spec §9). */
.isis-modleg__row { --modleg-reserve: color-mix(in oklch,
    var(--modleg-fill, var(--isis-mod-default)) calc(100% - var(--modleg-shift)), var(--isis-text));
  display: flex; align-items: center; gap: 11px; width: 100%;
  padding: 7px 6px; border: none; background: transparent; cursor: pointer;
  text-align: left; font: inherit;
  /* La ligne est un <a> (ouverture dans un autre onglet au geste natif) : l'encre et le
     soulignement de lien du navigateur n'ont rien à faire dans une légende de planche. */
  color: inherit; text-decoration: none; }
/* Pas de filet par ligne : ce serait le vocabulaire de .isis-grid__row, que
   l'application a enseigné comme signifiant « tableau ». Le rythme vertical
   vient de l'espacement, le seul filet restant est celui du titre de bloc. */
.isis-modleg__row:hover { background: var(--isis-surface-alt); }
/* Gouttière de largeur fixe (= la taille du picto) : une clé de picto absente du
   registre laisse la place vide sans faire remonter le nom de 20 px vers la gauche.
   Même réponse que .isis-notif-row__icon — réserver l'espace sans y peindre de signe. */
.isis-modleg__ic { flex: 0 0 20px; display: inline-flex; justify-content: center;
  color: var(--modleg-reserve, var(--isis-text-muted)); }
.isis-modleg__nm { font-size: 0.79rem; font-weight: 600; color: var(--isis-text);
  white-space: nowrap; }
.isis-modleg__sb { flex: 1; min-width: 0; font-size: 0.7rem; color: var(--isis-text-soft);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.isis-modleg__k { flex: 0 0 auto; font-size: 0.7rem; font-weight: 700;
  color: var(--isis-text-soft); border: 1px solid var(--isis-border);
  border-radius: var(--isis-radius-sm); padding: 0 4px; line-height: 1.35; }

/* Marge négative alignée sur le padding réel du dialogue Radzen (24px) : à 18px
   il restait un liseré du fond de dialogue entre le pied et le bord. */
.isis-modleg__foot { display: flex; gap: 16px; margin: 14px -24px -24px; padding: 10px 24px;
  border-top: 1px solid var(--isis-border); background: var(--isis-surface-alt);
  font-size: 0.7rem; color: var(--isis-text-muted); }
.isis-modleg__foot kbd { font-family: inherit; font-weight: 700;
  background: var(--isis-surface); border: 1px solid var(--isis-border);
  border-radius: var(--isis-radius-sm); padding: 0 4px; margin-right: 4px; }

/* Teinte par module de chaque rangée (l'overlay est rendu HORS .isis-shell.mod-* :
   --isis-current-mod n'y est pas en scope → classes par module obligatoires).
   Une seule déclaration par module : tout le reste dérive de --modleg-fill. */
.isis-modleg__row.mod-monespace { --modleg-fill: var(--isis-mod-monespace); }
.isis-modleg__row.mod-gesmaff   { --modleg-fill: var(--isis-mod-gesmaff); }
.isis-modleg__row.mod-gescom    { --modleg-fill: var(--isis-mod-gescom); }
.isis-modleg__row.mod-gescompta { --modleg-fill: var(--isis-mod-gescompta); }
.isis-modleg__row.mod-gesproj   { --modleg-fill: var(--isis-mod-gesproj); }
.isis-modleg__row.mod-gesst     { --modleg-fill: var(--isis-mod-gesst); }
.isis-modleg__row.mod-gespla    { --modleg-fill: var(--isis-mod-gespla); }
.isis-modleg__row.mod-gesqhse   { --modleg-fill: var(--isis-mod-gesqhse); }
.isis-modleg__row.mod-sirh      { --modleg-fill: var(--isis-mod-sirh); }
.isis-modleg__row.mod-gesmat    { --modleg-fill: var(--isis-mod-gesmat); }
.isis-modleg__row.mod-gespark   { --modleg-fill: var(--isis-mod-gespark); }
.isis-modleg__row.mod-gesinfo   { --modleg-fill: var(--isis-mod-gesinfo); }
.isis-modleg__row.mod-gesmob    { --modleg-fill: var(--isis-mod-gesmob); }
.isis-modleg__row.mod-gesfac    { --modleg-fill: var(--isis-mod-gesfac); }
.isis-modleg__row.mod-ged       { --modleg-fill: var(--isis-mod-ged); }
.isis-modleg__row.mod-m365      { --modleg-fill: var(--isis-mod-m365); }
.isis-modleg__row.mod-recette   { --modleg-fill: var(--isis-mod-recette); }
.isis-modleg__row.mod-admin     { --modleg-fill: var(--isis-mod-admin); }

/* Ligne active : réserve pleine. Le texte reste --isis-surface — les tokens
   --isis-mod-* ont une valeur PROPRE au thème sombre (teintes éclaircies, cf.
   :root[data-theme="dark"] et ThemeTokenDefaults), donc l'encre du thème est
   bien la bonne dans les deux cas ; un blanc littéral serait illisible en sombre.
   Sous-titre et pastille sont atténués vers la réserve (mélange OPAQUE) et non
   vers du transparent, qui laissait remonter la couleur du module sous le texte
   et faisait chuter le contraste sans produire de gris. */
.isis-modleg__row.is-active { background: var(--modleg-reserve); }
.isis-modleg__row.is-active .isis-modleg__nm,
.isis-modleg__row.is-active .isis-modleg__ic { color: var(--isis-surface); }
.isis-modleg__row.is-active .isis-modleg__sb {
  color: color-mix(in oklch, var(--isis-surface) 92%, var(--modleg-reserve)); }
.isis-modleg__row.is-active .isis-modleg__k {
  color: color-mix(in oklch, var(--isis-surface) 94%, var(--modleg-reserve));
  border-color: color-mix(in oklch, var(--isis-surface) 45%, var(--modleg-reserve)); }

/* Curseur clavier (↑↓) : un filet, jamais un fond opposé à is-active — la ligne
   courante garde sa réserve pleine, le survol s'y superpose sans la contredire. */
.isis-modleg__row.is-cursor:not(.is-active) { background: var(--isis-surface-alt); }
.isis-modleg__row.is-cursor { box-shadow: inset 0 0 0 1.5px var(--isis-border-strong); }
.isis-modleg__row.is-cursor.is-active { box-shadow: inset 0 0 0 1.5px var(--isis-surface); }

/* Sur --isis-surface-alt (survol ET curseur clavier, l'état normal du parcours au
   clavier), --isis-text-soft tombe à 3.82:1 en clair : le sous-titre et la pastille
   passent d'un cran, à --isis-text-muted. La ligne active garde sa réserve pleine et
   ses encres dérivées — d'où le :not(.is-active). */
.isis-modleg__row:hover:not(.is-active) .isis-modleg__sb,
.isis-modleg__row:hover:not(.is-active) .isis-modleg__k,
.isis-modleg__row.is-cursor:not(.is-active) .isis-modleg__sb,
.isis-modleg__row.is-cursor:not(.is-active) .isis-modleg__k { color: var(--isis-text-muted); }

/* Plafond de hauteur : le thème Radzen pose overflow:hidden sur .rz-dialog sans
   overflow sur .rz-dialog-content (même recette que .isis-mob-dialog). Le défilement
   est porté par le PLAN seul : à 1366×768 la colonne gauche dépasse, et faire défiler
   tout le contenu emporterait le champ de recherche et le pied hors de l'écran. */
.rz-dialog.isis-modleg-dialog { max-height: 90vh; }
.rz-dialog.isis-modleg-dialog .rz-dialog-content {
  display: flex; flex-direction: column; min-height: 0; overflow: hidden; }
.rz-dialog.isis-modleg-dialog .isis-modleg { flex: 1 1 auto; min-height: 0; }
.rz-dialog.isis-modleg-dialog .isis-modleg__plan {
  flex: 1 1 auto; min-height: 0; overflow-y: auto; align-content: start; }

/* ── Récap organigramme dans le sidepanel (vue Organisation des collaborateurs) ── */
.isis-orgrecap { display: flex; flex-direction: column; gap: 0.6rem; padding: 0.2rem; }
.isis-orgrecap__card { background: var(--isis-surface); border: 1px solid var(--isis-border); border-radius: var(--isis-radius); padding: 0.6rem 0.7rem; }
.isis-orgrecap__card.is-warm { border-color: color-mix(in oklch, var(--isis-accent) 30%, var(--isis-border)); background: color-mix(in oklch, var(--isis-accent) 5%, var(--isis-surface)); }
.isis-orgrecap__num { font-size: 1.5rem; font-weight: 700; color: var(--isis-accent); line-height: 1; font-variant-numeric: tabular-nums; }
.isis-orgrecap__lbl { font-size: 0.66rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: var(--isis-text-muted); }
.isis-orgrecap__hint { font-size: 0.72rem; color: var(--isis-text-muted); margin: 0.4rem 0 0.6rem; }
.isis-orgrecap__cta { width: 100%; border: none; border-radius: var(--isis-radius-sm); background: var(--isis-accent); color: var(--isis-surface); font-weight: 600; font-size: 0.76rem; padding: 0.45rem; cursor: pointer; }
.isis-orgrecap__cta:hover { filter: brightness(1.05); }
.isis-orgrecap__cta:focus-visible { outline: none; box-shadow: 0 0 0 2px color-mix(in oklch, var(--isis-accent) 55%, transparent); }
.isis-orgrecap__title { font-size: 0.66rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: var(--isis-text-muted); margin-bottom: 0.35rem; }
.isis-orgrecap__row { display: flex; justify-content: space-between; gap: 0.5rem; font-size: 0.74rem; padding: 0.16rem 0; border-top: 1px solid var(--isis-border); }
.isis-orgrecap__row:first-of-type { border-top: none; }
.isis-orgrecap__row span:last-child { font-variant-numeric: tabular-nums; color: var(--isis-text); }
.isis-orgrecap__row.is-total { font-weight: 700; border-top: 1.5px solid var(--isis-border-strong); }

/* Offres — barre d'actions contextuelle (sélection multiple) */
.isis-offer-selbar {
    display: flex; align-items: center; gap: var(--isis-space-sm);
    padding: var(--isis-space-sm) var(--isis-space-md);
    margin-bottom: var(--isis-space-md);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-sm);
    background: color-mix(in oklab, var(--isis-current-mod) 6%, var(--isis-surface));
}
.isis-offer-selbar__count { font-weight: 600; margin-right: auto; }
/* Les boutons de la barre portent un libellé (icône + texte) : on relâche la
   taille fixe 28×28 de .isis-grid__action-btn pour laisser respirer le texte. */
.isis-offer-selbar .isis-grid__action-btn {
    width: auto; height: auto; gap: var(--isis-space-xs);
    padding: var(--isis-space-xs) var(--isis-space-sm);
    font-size: 0.8125rem; color: var(--isis-text);
}
.isis-offer-selbar .isis-grid__action-btn:hover { background: var(--isis-surface-alt); }
.isis-offer-selbar .isis-grid__action-btn--danger:hover {
    background: color-mix(in oklab, var(--isis-danger) 12%, transparent);
}
.isis-offer-selbar .isis-grid__action-btn:disabled {
    opacity: 0.45; cursor: not-allowed; background: transparent;
}
.isis-offer-selbar .isis-grid__action-btn--danger { color: var(--isis-danger); }
.isis-grid__row.is-selected {
    background: color-mix(in oklab, var(--isis-current-mod) 10%, transparent);
    box-shadow: inset 2px 0 0 var(--isis-current-mod);
}

/* Sélecteur de lignes (combinaison d'offres) */
.isis-offer-picker { display: flex; flex-direction: column; gap: var(--isis-space-md);
    max-height: 360px; overflow-y: auto; }
.isis-offer-picker__group { border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-sm); padding: var(--isis-space-sm); }
.isis-offer-picker__group.is-disabled { opacity: 0.55; }
.isis-offer-picker__group-head { display: flex; align-items: center; gap: var(--isis-space-sm);
    margin-bottom: var(--isis-space-xs); }
.isis-offer-picker__devise { font-size: 0.78rem; color: var(--isis-text-muted); }
.isis-offer-picker__warn { font-size: 0.74rem; color: var(--isis-danger); margin-left: auto; }
.isis-offer-picker__line { display: flex; align-items: center; gap: var(--isis-space-sm);
    padding: 0.2rem 0; cursor: pointer; }
.isis-offer-picker__desc { flex: 1; }
.isis-offer-picker__amt { font-variant-numeric: tabular-nums; color: var(--isis-text-muted); }

/* ══════════════════════════════════════════════════════════════════════
   Admin · Mails à rattacher (triage M365) + TiersPickerDialog
   Tokens uniquement (--isis-*). isis-sr-only existe déjà (ne pas redéfinir).
   ══════════════════════════════════════════════════════════════════════ */

/* Grille de triage : colonnes (check · expéditeur · sujet · date · boîte · rattacher). */
.isis-grid--mails-triage .isis-grid__head,
.isis-grid--mails-triage .isis-grid__row {
    grid-template-columns: 34px minmax(160px, 1.2fr) minmax(200px, 2fr) 130px minmax(140px, 1fr) minmax(220px, 1.6fr);
    min-width: 960px;
}
.isis-grid--mails-triage .isis-grid__col-check input[type="checkbox"] {
    cursor: pointer; width: 14px; height: 14px;
}

/* Cellule à 2 niveaux (primaire + secondaire), tronquée. */
.isis-cell-stack { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.isis-cell-stack__primary {
    font-weight: 500; color: var(--isis-text);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.isis-cell-stack__secondary {
    font-size: 0.78rem; color: var(--isis-text-muted);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* Cellule mono-ligne tronquée. */
.isis-cell-truncate {
    display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0;
}

/* Zone « Rattacher à » : chips candidats + bouton picker. */
.isis-attach { display: flex; align-items: center; flex-wrap: wrap; gap: 0.3rem; }
.isis-attach__chip {
    background: none; border: 0; padding: 0; cursor: pointer; display: inline-flex;
}
.isis-attach__chip:focus-visible {
    outline: 2px solid var(--isis-accent); outline-offset: 2px;
    border-radius: var(--isis-radius-sm);
}
.isis-attach__chip:disabled { cursor: not-allowed; opacity: 0.55; }
.isis-attach__more { font-size: 0.78rem; color: var(--isis-text-muted); align-self: center; }

/* Picker tiers (résultats de recherche). */
.isis-picker-results {
    display: flex; flex-direction: column;
    max-height: 280px; overflow-y: auto;
    border: 1px solid var(--isis-border); border-radius: var(--isis-radius);
    background: var(--isis-surface);
}
.isis-picker-results__empty {
    display: flex; align-items: center; gap: 0.5rem;
    padding: 0.75rem 1rem; color: var(--isis-text-muted); font-size: 0.85rem;
}
.isis-picker-results__item {
    display: flex; align-items: baseline; justify-content: space-between; gap: 0.5rem;
    padding: 0.5rem 1rem; text-align: left;
    background: none; border: 0; border-bottom: 1px solid var(--isis-border-soft);
    cursor: pointer; width: 100%;
}
.isis-picker-results__item:last-child { border-bottom: 0; }
.isis-picker-results__item:hover { background: var(--isis-surface-alt); }
.isis-picker-results__item:focus-visible { outline: 2px solid var(--isis-accent); outline-offset: -2px; }
.isis-picker-results__primary { font-weight: 500; color: var(--isis-text); }
.isis-picker-results__secondary { font-size: 0.78rem; color: var(--isis-text-muted); white-space: nowrap; }
/* Sélection multiple : la case pousse le libellé, qui reste le premier élément flexible —
   le compteur du secondaire garde donc sa place à droite, alignée d'une ligne à l'autre. */
.isis-picker-results__item .rz-icon,
.isis-picker-results__item .rzi { flex: 0 0 auto; color: var(--isis-text-muted); }
.isis-picker-results__item .isis-picker-results__primary { flex: 1 1 auto; }
.isis-picker-results__item.is-selected { background: color-mix(in oklch, var(--isis-current-mod) 8%, transparent); }
.isis-picker-results__item.is-selected .rz-icon,
.isis-picker-results__item.is-selected .rzi { color: var(--isis-current-mod); }
/* MonEspace « Mes projets » : les tâches sous chaque projet, dans la colonne de navigation.
   Compact par nécessité — la colonne est étroite et la liste doit rester parcourable quand un
   collaborateur porte dix projets. */
.isis-proj-item__taches {
    list-style: none;
    margin: 0 0 0.35rem 0;
    padding: 0 0.75rem 0 2.1rem;
}
.isis-proj-tache {
    display: flex; align-items: baseline; gap: 0.5rem;
    padding: 0.15rem 0;
    font-size: 0.78rem; color: var(--isis-text-muted);
    border-left: 1px solid var(--isis-border-soft);
    padding-left: 0.6rem;
}
.isis-proj-tache__label {
    flex: 1 1 auto; min-width: 0;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    color: var(--isis-text);
}
.isis-proj-tache__doc {
    flex: 0 0 auto;
    display: inline-flex; align-items: center; justify-content: center;
    width: 24px; height: 24px;              /* cible de pointeur ≥ 24px (WCAG 2.5.8) */
    padding: 0; margin-left: 0.25rem;
    background: none; border: 0; border-radius: var(--isis-radius-sm);
    color: var(--isis-mod-gesqhse); cursor: pointer;
}
.isis-proj-tache__doc:hover { background: color-mix(in oklch, var(--isis-mod-gesqhse) 12%, transparent); }
.isis-proj-tache__doc:focus-visible { outline: 2px solid var(--isis-accent); outline-offset: 1px; }
.isis-proj-tache__periode { flex: 0 0 auto; font-variant-numeric: tabular-nums; }

.isis-picker-results__toolbar {
    display: flex; align-items: center; gap: 0.5rem;
    padding: 0.45rem 1rem; border-bottom: 1px solid var(--isis-border);
    background: var(--isis-surface-alt); font-size: 0.85rem;
    position: sticky; top: 0; z-index: 1;
}
.isis-picker-results__toolbar label { cursor: pointer; color: var(--isis-text); }
.isis-picker-results__count { margin-left: auto; color: var(--isis-text-muted); font-size: 0.8rem; }

/* Indice contextuel d'un dialog (ex. expéditeur du mail). */
.isis-dialog-hint { font-size: 0.85rem; color: var(--isis-text-muted); margin-bottom: 0.6rem; }

/* Bandeau « tiers retenu » de l'étape 2 du picker d'attache (choix devis facultatif). */
.isis-picker-chosen {
    display: flex; align-items: center; gap: var(--isis-space-sm); flex-wrap: wrap;
    padding: 0.5rem 0.75rem;
    background: var(--isis-surface-alt); border: 1px solid var(--isis-border-soft);
    border-radius: var(--isis-radius); margin-bottom: var(--isis-space-sm);
}
.isis-picker-chosen__label { font-size: 0.78rem; color: var(--isis-text-muted); }
.isis-picker-chosen__value { color: var(--isis-text); margin-right: auto; }

/* ── Table de sélection des lignes déléguables (assistant sous-commande) ──────── */
.isis-deleg-lines { width: 100%; border-collapse: collapse; font-size: 0.85rem; }
.isis-deleg-lines th { font-size: 0.65rem; text-transform: uppercase; letter-spacing: 0.05em; color: var(--isis-text-soft); padding: 0.35rem 0.5rem; border-bottom: 1px solid var(--isis-border); font-weight: 500; }
.isis-deleg-lines td { padding: 0.4rem 0.5rem; border-bottom: 1px solid var(--isis-border-subtle); vertical-align: middle; }
.isis-deleg-lines tr.is-selected td { background: color-mix(in srgb, var(--isis-current-mod) 6%, transparent); }
.isis-deleg-lines tr:last-child td { border-bottom: 0; }

/* ── Réconciliation INSEE (panneau latéral tiers) ───────────────────────────── */
.isis-insee-panel { border-top: 1px solid var(--isis-border); padding-top: .6rem; display: flex; flex-direction: column; gap: .45rem; }
.isis-insee-panel__head { display: flex; align-items: center; gap: .4rem; font-size: .8rem; font-weight: 600; color: var(--isis-text-muted); }
.isis-insee-alert { font-size: .78rem; font-weight: 600; border-radius: var(--isis-radius-sm); padding: .45rem .6rem; display: flex; align-items: center; gap: .35rem; }
.isis-insee-alert.is-danger { background: color-mix(in srgb, var(--isis-danger) 10%, transparent); color: var(--isis-danger); border: 1px solid var(--isis-danger); }
.isis-insee-cmp { width: 100%; border-collapse: collapse; font-size: .76rem; }
.isis-insee-cmp th { text-align: left; color: var(--isis-text-muted); font-weight: 600; padding: .2rem .35rem; border-bottom: 1px solid var(--isis-border); }
.isis-insee-cmp td { padding: .25rem .35rem; border-bottom: 1px solid var(--isis-border); vertical-align: top; max-width: 120px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.isis-insee-cmp td.ours { color: var(--isis-text-muted); }
.isis-insee-cmp td.off { font-weight: 500; color: var(--isis-text); }

/* ============================================================================
   IsisButton — famille canonique .isis-action-btn (lot 1, 2026-06-24)
   2 axes : couleur de rôle (--module/--danger/--success/--warning/--neutral)
   × emphase (--primary plein / --secondary contour / --ghost discret).
   Gabarit calqué sur .isis-rich-toolbar__btn (look « plat compact » de référence,
   ligne ~2489). Émis par <IsisButton> via IsisActionRegistry.
   .isis-rich-toolbar__btn reste tel quel (migré page par page ; supprimé
   quand 0 usage).
   ============================================================================ */
.isis-action-btn {
    --_c: var(--isis-text-muted);          /* couleur de rôle, posée par le modifieur couleur */
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    height: 32px;
    padding: 0 0.7rem;
    border: 1px solid transparent;
    border-radius: 8px;
    background: transparent;
    color: var(--isis-text-muted);
    cursor: pointer;
    font-size: var(--isis-fs-sm);
    font-family: inherit;
    line-height: 1;
    text-decoration: none;
    transition: background-color 120ms, color 120ms, border-color 120ms;
}
.isis-action-btn .rzi { font-size: 16px; }
/* Anneau plein et non halo à 22 % : le halo seul mesure 1,4:1 contre une surface blanche, sous le
   3:1 qu'exige un indicateur de focus (WCAG 1.4.11). */
.isis-action-btn:focus-visible {
    outline: 2px solid var(--isis-current-mod, var(--isis-accent));
    outline-offset: 2px;
}
.isis-action-btn:disabled,
.isis-action-btn[disabled] { opacity: 0.4; cursor: not-allowed; pointer-events: none; }
/* Inerte ≠ désactivé : le bouton garde le clavier ET le survol, parce que son infobulle porte
   la RAISON — donc pas de `pointer-events: none`, qui la rendrait inatteignable.
   Et PAS d'atténuation par `opacity` non plus : sur une emphase Primary, faire fondre le
   bouton entier vers son fond rapproche le libellé de son propre remplissage — mesuré à
   2,17:1 en clair à 0.65. Le bouton perd donc son REMPLISSAGE (il n'est plus l'action
   principale) et garde une encre lisible : 6,09:1 en clair, 6,15:1 en sombre.
   Spécificité 0,2,0 : l'emporte sur .isis-action-btn--primary|secondary|ghost (0,1,0) ;
   le :hover ci-dessous neutralise les repeints de survol, à égalité de spécificité. */
.isis-action-btn.is-inert {
    cursor: not-allowed;
    background: transparent;
    border-color: var(--isis-border-strong);
    color: var(--isis-text-muted);
    font-weight: 400;
}
.isis-action-btn.is-inert .rzi,
.isis-action-btn.is-inert .rz-icon { color: var(--isis-text-muted); }
.isis-action-btn.is-inert:hover {
    background: transparent;
    border-color: var(--isis-border-strong);
    color: var(--isis-text-muted);
}
.isis-action-btn--icon-only { width: 32px; padding: 0; justify-content: center; }

/* --- Couleur de rôle : pose --_c --- */
.isis-action-btn--module  { --_c: var(--isis-current-mod, var(--isis-accent)); }
.isis-action-btn--danger  { --_c: var(--isis-danger); }
.isis-action-btn--success { --_c: var(--isis-success); }
.isis-action-btn--warning { --_c: var(--isis-warning); }
.isis-action-btn--neutral { --_c: var(--isis-text-muted); }

/* --- Emphase Primary : fond plein de la couleur de rôle --- */
.isis-action-btn--primary {
    background: var(--_c);
    border-color: var(--_c);
    color: #fff;
    font-weight: 600;
}
.isis-action-btn--primary .rzi { color: #fff; }
.isis-action-btn--primary:hover { background-color: color-mix(in srgb, var(--_c) 85%, var(--isis-text)); }

/* --- Emphase Secondary : contour + texte colorés, fond transparent --- */
.isis-action-btn--secondary {
    border-color: color-mix(in srgb, var(--_c) 40%, var(--isis-border));
    color: var(--_c);
}
.isis-action-btn--secondary:hover { background-color: color-mix(in srgb, var(--_c) 12%, transparent); }
/* neutre = bouton « gris » de base (texte muted, bordure standard) */
.isis-action-btn--neutral.isis-action-btn--secondary { color: var(--isis-text-muted); border-color: var(--isis-border); }
.isis-action-btn--neutral.isis-action-btn--secondary:hover { background-color: var(--isis-surface-alt); color: var(--isis-text); }

/* --- Emphase Ghost : texte coloré seul --- */
.isis-action-btn--ghost { color: var(--_c); }
.isis-action-btn--ghost:hover { background-color: color-mix(in srgb, var(--_c) 12%, transparent); }
.isis-action-btn--neutral.isis-action-btn--ghost { color: var(--isis-text-muted); }
.isis-action-btn--neutral.isis-action-btn--ghost:hover { background-color: var(--isis-surface-alt); color: var(--isis-text); }

/* --- État Loading : spinner, libellé masqué (largeur préservée) --- */
.isis-action-btn.is-loading { pointer-events: none; }
.isis-action-btn.is-loading .isis-action-btn__label { visibility: hidden; }
.isis-action-btn__spinner {
    width: 14px; height: 14px; border-radius: 50%;
    border: 2px solid color-mix(in srgb, var(--_c) 35%, transparent);
    border-top-color: var(--_c);
    animation: isis-action-btn-spin 0.6s linear infinite;
}
.isis-action-btn--primary .isis-action-btn__spinner { border-color: rgba(255,255,255,0.45); border-top-color: #fff; }
@keyframes isis-action-btn-spin { to { transform: rotate(360deg); } }

/* Taille compacte du bouton d'action (lot boutons — 2026-06-24) : pour remplacer
   les anciens RadzenButton Small/ExtraSmall des zones denses sans les agrandir. */
.isis-action-btn--sm {
    height: 26px;
    padding: 0 0.5rem;
    font-size: var(--isis-fs-label);
    gap: 0.25rem;
}
.isis-action-btn--sm.isis-action-btn--icon-only { width: 26px; padding: 0; }
.isis-action-btn--sm .rzi { font-size: 14px; }

/* Bouton de sortie d'enrôlement MFA : le blanc sur --isis-success sombre plafonne à 2,54:1.
   Encre corrigée pour CETTE instance seulement — le token et le registre servent 53 autres
   usages Validate+Primary (chantier design-system distinct). */
:root[data-theme="dark"] .isis-mfa-recovery-actions .isis-action-btn--success.isis-action-btn--primary,
:root[data-theme="dark"] .isis-mfa-recovery-actions .isis-action-btn--success.isis-action-btn--primary .rzi {
    color: var(--isis-bg);
}
:root[data-theme="dark"] .isis-mfa-recovery-actions .isis-action-btn--success.isis-action-btn--primary .isis-action-btn__spinner {
    border-top-color: var(--isis-bg);
}

.isis-focus-target:focus-visible {
    outline: 2px solid var(--isis-current-mod);
    outline-offset: 2px;
}

/* ── Matrice de gouvernance du parc (onglet Organisation & gouvernance — fiche entreprise) ── */

/* Ligne méta : responsable en haut du panel */
.isis-gov-meta {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.5rem 0 0.75rem;
    font-size: var(--isis-fs-label);
    color: var(--isis-text-muted);
}

/* Conteneur scrollable horizontal pour la table */
.isis-gov-matrix-wrap {
    overflow-x: auto;
    padding: 0.25rem 0 0.75rem;
}

/* Table matrice */
.isis-gov-matrix {
    border-collapse: separate;
    border-spacing: 0;
    width: 100%;
    min-width: 860px;
    font-size: var(--isis-fs-label);
}

/* En-têtes colonnes (fonctions) */
.isis-gov-matrix thead th {
    position: sticky;
    top: 0;
    background: var(--isis-surface);
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.4px;
    color: var(--isis-text-muted);
    font-weight: 600;
    text-align: center;
    padding: 0.6rem 0.5rem 0.5rem;
    border-bottom: 1px solid var(--isis-border);
    vertical-align: bottom;
    white-space: nowrap;
}

/* En-tête de la première colonne (domaines) */
.isis-gov-matrix__row-head {
    text-align: left !important;
    padding-left: 0.75rem !important;
    min-width: 140px;
}

/* En-têtes colonnes fonctions */
.isis-gov-matrix__col-head {
    min-width: 100px;
}

/* Cellule domaine (première colonne) — th scope=row */
.isis-gov-matrix__domain-cell {
    display: table-cell;
    vertical-align: middle;
    padding: 0.6rem 0.75rem;
    font-weight: 600;
    font-size: 13px;
    border-bottom: 1px solid var(--isis-border-subtle);
    white-space: nowrap;
}

/* Wrapper interne flex (th ne peut pas être flex-container fiable) */
.isis-gov-domain-inner {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

/* Point coloré du domaine */
.isis-gov-dot {
    width: 8px;
    height: 8px;
    border-radius: 3px;
    flex-shrink: 0;
}
/* Variante ronde (pastille de domaine inline) */
.isis-gov-dot--round {
    display: inline-block;
    border-radius: 50%;
    margin-right: 4px;
}

/* Cellule data (domaine × fonction) */
.isis-gov-matrix__cell {
    border-bottom: 1px solid var(--isis-border-subtle);
    border-left: 1px solid var(--isis-border-subtle);
    text-align: center;
    padding: 0.4rem 0.35rem;
    vertical-align: middle;
}

/* Chip de cellule — base */
.isis-gov-chip {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.25rem;
    padding: 0.2rem 0.55rem;
    border-radius: var(--isis-radius-sm);
    font-size: 12px;
    font-weight: 500;
    white-space: nowrap;
    line-height: 1.35;
    cursor: default;
}

/* Géré ici : couleur module hôte (SIRH vert) */
.isis-gov-chip--self {
    background: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 12%, transparent);
    color: var(--isis-current-mod, var(--isis-accent));
    border: 1px solid color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 35%, transparent);
    font-weight: 600;
}

/* Hérité : ton neutre, flèche remonte */
.isis-gov-chip--inherited {
    background: var(--isis-surface-alt);
    color: var(--isis-text-muted);
    border: 1px dashed var(--isis-border);
    font-weight: 400;
}

/* Chips « droits effectifs » colorés par niveau de droit (miroir des swatches L/E/V) */
.isis-gov-chip--read {
    background: color-mix(in srgb, var(--isis-read) 12%, transparent);
    color: var(--isis-read);
    border: 1px solid color-mix(in srgb, var(--isis-read) 35%, transparent);
    font-weight: 600;
}
.isis-gov-chip--write {
    background: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 12%, transparent);
    color: var(--isis-current-mod, var(--isis-accent));
    border: 1px solid color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 35%, transparent);
    font-weight: 600;
}
.isis-gov-chip--validate {
    background: color-mix(in srgb, var(--isis-accent) 12%, transparent);
    color: var(--isis-accent-strong);
    border: 1px solid color-mix(in srgb, var(--isis-accent) 35%, transparent);
    font-weight: 600;
}
.isis-gov-chip--none {
    background: var(--isis-surface-alt);
    color: var(--isis-text-muted);
    border: 1px dashed var(--isis-border);
    font-weight: 400;
}

.isis-gov-chip__arrow {
    font-size: 10px;
    opacity: 0.65;
}

/* Sans objet */
.isis-gov-chip--na {
    color: var(--isis-text-muted);
    font-size: 11px;
    font-weight: 400;
    background: none;
    border: none;
    padding: 0;
}

/* Cellule éditable : le chip devient un vrai bouton interactif */
.isis-gov-chip--btn {
    cursor: pointer;
    border: none;
    background: none;
    font-family: inherit;
    transition: opacity 0.12s ease, box-shadow 0.12s ease;
}

.isis-gov-chip--btn:hover {
    opacity: 0.82;
    box-shadow: var(--isis-elevation-hover);
}

.isis-gov-chip--btn:focus-visible {
    outline: 2px solid color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 70%, transparent);
    outline-offset: 2px;
}

/* Légende sous la matrice */
.isis-gov-legend {
    display: flex;
    flex-wrap: wrap;
    gap: 0.9rem 1.4rem;
    padding: 0.65rem 0 0.25rem;
    border-top: 1px solid var(--isis-border-subtle);
    font-size: 12px;
    color: var(--isis-text-muted);
    margin-top: 0.5rem;
}

.isis-gov-legend__item {
    display: flex;
    align-items: center;
    gap: 0.4rem;
}
/* Notes textuelles de la légende (cascade / reporting) */
.isis-gov-legend__item--note { color: var(--isis-text-muted); }
.isis-gov-legend__item--end { margin-left: auto; }

/* Swatches de légende */
.isis-gov-swatch {
    display: inline-block;
    width: 22px;
    height: 13px;
    border-radius: 3px;
    flex-shrink: 0;
}

.isis-gov-swatch--self {
    background: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 12%, transparent);
    border: 1px solid color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 35%, transparent);
}

.isis-gov-swatch--inherited {
    background: var(--isis-surface-alt);
    border: 1px dashed var(--isis-border);
}

.isis-gov-swatch--na {
    background: transparent;
    border: 1px solid var(--isis-border-subtle);
}

/* ── Cellule de cascade « Responsabilités » : boîte 2 lignes (maquette gouvernance-parc-matrice) ── */
.isis-gov-cell {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    width: 100%;
    min-height: 52px;
    padding: 6px 6px;
    border-radius: var(--isis-radius-sm);
    border: 1px dashed var(--isis-border);
    background: transparent;
    text-align: center;
    cursor: default;
    transition: background 0.12s ease, border-color 0.12s ease;
}
button.isis-gov-cell { font: inherit; cursor: pointer; }
button.isis-gov-cell:hover {
    border-color: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 45%, var(--isis-border));
    background: var(--isis-surface-alt);
}
button.isis-gov-cell:focus-visible {
    outline: 2px solid color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 70%, transparent);
    outline-offset: 2px;
}
.isis-gov-cell__state { font-size: 12px; font-weight: 600; line-height: 1.2; }
.isis-gov-cell__who   { font-size: 10.5px; color: var(--isis-text-muted); line-height: 1.15; }
.isis-gov-cell__arrow { font-size: 10px; opacity: 0.7; margin-right: 2px; }

/* Hérité (parent) : pointillé, encre douce + nom du parent en 2ᵉ ligne */
.isis-gov-cell--inherited .isis-gov-cell__state { color: var(--isis-text-muted); font-weight: 500; }

/* Dérogation — géré ici : plein + teinte module */
.isis-gov-cell--self {
    border-style: solid;
    border-color: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 38%, transparent);
    background: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 10%, transparent);
}
.isis-gov-cell--self .isis-gov-cell__state { color: var(--isis-current-mod, var(--isis-accent)); }
.isis-gov-cell--self .isis-gov-cell__who   { color: var(--isis-current-mod, var(--isis-accent)); opacity: 0.85; }

/* Sans objet */
.isis-gov-cell--na { border: none; background: transparent; cursor: not-allowed; }
.isis-gov-cell--na .isis-gov-cell__state { color: var(--isis-text-muted); font-weight: 400; font-size: 11px; }
/* ── fin matrice gouvernance ── */

/* ── Section « Droits par profil — cette entité » (Lot 3) ── */

/* Conteneur principal de la section gabarit */
.isis-gov-gabarit {
    margin-top: 1.5rem;
    padding-top: 1.25rem;
    border-top: 2px solid var(--isis-border);
}

/* En-tête titre + lecture seule */
.isis-gov-gabarit__header {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin-bottom: 0.9rem;
}

.isis-gov-gabarit__title {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    font-size: var(--isis-fs-body);
    font-weight: 600;
    color: var(--isis-ink);
    margin: 0;
}

/* Ligne de sélection du profil */
.isis-gov-gabarit__selector {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    flex-wrap: wrap;
}

.isis-gov-gabarit__role-label {
    font-size: var(--isis-fs-label);
    font-weight: 500;
    color: var(--isis-text-muted);
    white-space: nowrap;
}

/* Cellule de la matrice gabarit — plus large pour accueillir L/E/V */
.isis-gov-gabarit__matrix .isis-gov-matrix__col-head {
    min-width: 120px;
}

.isis-gov-gabarit__cell {
    padding: 0.45rem 0.4rem !important;
    vertical-align: middle;
}

/* Badge origine (local / global) */
.isis-gov-gabarit__cell-origin {
    display: flex;
    justify-content: center;
    margin-bottom: 0.3rem;
}

.isis-gov-gabarit__origin-badge {
    display: inline-block;
    font-size: 10px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.3px;
    padding: 0.05rem 0.35rem;
    border-radius: 3px;
    line-height: 1.5;
    white-space: nowrap;
}

.isis-gov-gabarit__origin-badge--local {
    background: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 14%, transparent);
    color: var(--isis-current-mod, var(--isis-accent));
    border: 1px solid color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 30%, transparent);
}

.isis-gov-gabarit__origin-badge--global {
    background: var(--isis-surface-alt);
    color: var(--isis-text-muted);
    border: 1px dashed var(--isis-border);
}

/* Groupe des 3 droits L / E / V */
.isis-gov-gabarit__rights {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.4rem;
}

/* Chaque case + étiquette */
.isis-gov-gabarit__right-item {
    display: flex;
    align-items: center;
    gap: 0.2rem;
    cursor: pointer;
    user-select: none;
}

.isis-gov-gabarit__right-item:has(input:disabled) {
    cursor: default;
}
/* Atténuer le LIBELLÉ uniquement, pas la case (préserve le contraste de la case) */
.isis-gov-gabarit__right-item:has(input:disabled) .isis-gov-gabarit__right-label {
    opacity: 0.6;
    color: var(--isis-text-muted);
}

.isis-gov-gabarit__chk {
    width: 14px;
    height: 14px;
    accent-color: var(--isis-current-mod, var(--isis-accent));
    cursor: pointer;
    flex-shrink: 0;
}

.isis-gov-gabarit__chk:disabled {
    cursor: not-allowed;
}

.isis-gov-gabarit__right-label {
    font-size: 11px;
    font-weight: 600;
    color: var(--isis-ink-soft);
    letter-spacing: 0.2px;
    line-height: 1;
}

/* ── fin section gabarit par profil ── */

/* ── Section « Partage & visibilité » (Lot 3 / couche 4) ── */
.isis-gov-share {
    margin-top: 1.5rem;
    padding-top: 1.25rem;
    border-top: 2px solid var(--isis-border);
}

.isis-gov-share__intro {
    font-size: var(--isis-fs-label);
    color: var(--isis-text-muted);
    line-height: 1.5;
    margin: 0 0 1rem;
    max-width: 70ch;
}

.isis-gov-share__panel {
    margin-bottom: 1.25rem;
}

.isis-gov-share__panel-title {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    font-size: var(--isis-fs-label);
    font-weight: 600;
    color: var(--isis-ink-soft);
    text-transform: uppercase;
    letter-spacing: 0.4px;
    margin-bottom: 0.6rem;
}

.isis-gov-share__empty {
    font-size: var(--isis-fs-label);
    color: var(--isis-text-muted);
    padding: 0.25rem 0;
    margin: 0;
}

.isis-gov-share__matrix .isis-gov-share__cell { text-align: center; }

.isis-gov-share__peer {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    flex-wrap: wrap;
}

.isis-gov-share__branch-badge {
    display: inline-block;
    font-size: 10px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.3px;
    padding: 1px 6px;
    border-radius: var(--isis-radius-sm);
    color: var(--isis-accent);
    background: color-mix(in srgb, var(--isis-accent) 14%, transparent);
}

.isis-gov-share__inbound {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.isis-gov-share__inbound-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    flex-wrap: wrap;
    padding: 0.6rem 0.75rem;
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-sm);
    background: var(--isis-surface);
    font-size: var(--isis-fs-sm);
}

.isis-gov-share__inbound-main {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    flex-wrap: wrap;
}

.isis-gov-share__domains {
    display: inline-flex;
    gap: 0.3rem;
    flex-wrap: wrap;
}

/* Sous-onglets gouvernance : neutraliser les séparateurs (margin/border-top) hérités
   de l'empilement vertical, quand chaque section est désormais seule dans son panneau
   de sous-onglet (refactor 2026-06-26). */
.isis-tab-panel > .isis-gov-gabarit,
.isis-tab-panel > .isis-gov-share {
    margin-top: 0;
    padding-top: 0.75rem;
    border-top: none;
}

/* Indication discrète « lecture seule » alignée à droite dans la barre de sous-onglets. */
.isis-subtabs__note {
    margin-left: auto;
    align-self: center;
    padding-right: 0.25rem;
    font-size: 0.75rem;
    color: var(--isis-text-muted);
}

/* Sous-onglet « Organisation » : formulaire d'association + groupes de rôle */
.isis-gov-assign {
    display: flex;
    align-items: flex-end;
    gap: 0.75rem;
    flex-wrap: wrap;
    padding: 0.75rem;
    margin-bottom: 1rem;
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-sm);
    background: var(--isis-surface-alt);
}
.isis-gov-assign__field { display: flex; flex-direction: column; gap: 0.25rem; }
.isis-gov-roster-group { margin-bottom: 1rem; }
.isis-gov-effective { list-style: none; margin: 0.5rem 0 0; padding: 0; display: flex; flex-direction: column; gap: 0.5rem; }
.isis-gov-effective__row { display: flex; align-items: flex-start; gap: 0.75rem; flex-wrap: wrap; }
.isis-gov-effective__dom { display: inline-flex; align-items: center; gap: 0.4rem; min-width: 140px; font-weight: 600; font-size: var(--isis-fs-label); }
.isis-gov-effective__cells { display: inline-flex; gap: 0.3rem; flex-wrap: wrap; }

/* Historique des mouvements parc (ParcAffectationHistory) — liste sémantique simple. */
.isis-parc-history { list-style: none; margin: 0.5rem 0 0; padding: 0; display: flex; flex-direction: column; gap: 0.5rem; }
.isis-parc-history__row { display: flex; align-items: center; gap: 0.75rem; flex-wrap: wrap; }
.isis-gov-roster-group__title {
    font-size: var(--isis-fs-label);
    font-weight: 600;
    color: var(--isis-ink-soft);
    text-transform: uppercase;
    letter-spacing: 0.4px;
    margin-bottom: 0.5rem;
}
/* ── Tâche 2 : toggle mode gabarit global / structure ── */
.isis-gov-gabarit__mode-toggle {
    display: inline-flex;
    gap: 0;
    margin: 0.625rem 0 0.25rem;
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-sm);
    overflow: hidden;
    align-self: flex-start;
}
.isis-gov-gabarit__mode-btn {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0.3rem 0.75rem;
    font-size: var(--isis-fs-label);
    font-weight: 500;
    color: var(--isis-text-muted);
    background: var(--isis-surface);
    border: none;
    cursor: pointer;
    white-space: nowrap;
    transition: background 0.12s, color 0.12s;
}
.isis-gov-gabarit__mode-btn + .isis-gov-gabarit__mode-btn {
    border-left: 1px solid var(--isis-border);
}
.isis-gov-gabarit__mode-btn:hover { background: var(--isis-surface-alt); color: var(--isis-text); }
.isis-gov-gabarit__mode-btn.is-active {
    background: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 12%, transparent);
    color: var(--isis-current-mod, var(--isis-accent));
    font-weight: 600;
}
.isis-gov-gabarit__mode-btn:focus-visible {
    outline: 2px solid var(--isis-current-mod, var(--isis-accent));
    outline-offset: -2px;
}
.isis-gov-gabarit__mode-btn:disabled { opacity: 0.45; cursor: not-allowed; }

/* ── Tâche 3 : ligne roster avec boutons d'action ── */
.isis-gov-roster-item__actions {
    display: flex;
    gap: 0.4rem;
    align-items: center;
    flex-shrink: 0;
}
.isis-gov-roster-item--expanded {
    flex-wrap: wrap;
    border-color: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 30%, transparent);
    background: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 4%, var(--isis-surface));
}

/* ── Panneau inline de restriction domaine/fonction ── */
.isis-gov-restrict-panel {
    flex: 0 0 100%;
    margin-top: 0.625rem;
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-sm);
    background: var(--isis-surface);
    overflow: hidden;
}
.isis-gov-restrict-panel__title {
    margin: 0;
    padding: 0.6rem 1rem 0;
    font-size: var(--isis-fs-base);
    font-weight: 600;
    color: var(--isis-text);
}
.isis-gov-restrict-panel__body {
    display: flex;
    gap: 1.5rem;
    flex-wrap: wrap;
    padding: 0.75rem 1rem;
}
.isis-gov-restrict-panel__axis {
    border: none;
    padding: 0;
    margin: 0;
    min-width: 180px;
}
.isis-gov-restrict-panel__axis legend {
    margin-bottom: 0.25rem;
}
.isis-gov-restrict-panel__hint {
    font-size: var(--isis-fs-label);
    color: var(--isis-text-muted);
    margin: 0 0 0.4rem;
}
.isis-gov-restrict-panel__options {
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
}
.isis-gov-restrict-panel__check-item {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    font-size: var(--isis-fs-body);
    cursor: pointer;
    user-select: none;
}
.isis-gov-restrict-panel__footer {
    display: flex;
    gap: 0.5rem;
    align-items: center;
    padding: 0.5rem 1rem;
    border-top: 1px solid var(--isis-border);
    background: var(--isis-surface-alt);
}

/* ── fin section partage & visibilité ── */

/* ===== Gouvernance — matrices gabarit/partage (port mockup 2026-06-27) ===== */
/*
   Port visuel du mockup docs/mockups/gouvernance-parc-matrice.html.
   Toutes les couleurs sont tokenisées (aucun hex en dur) :
     Lecture (read)        → --isis-read        (bleu-gris neutre, découplé de tout module)
     Écriture (write)      → --isis-current-mod (accent module, --isis-accent en repli)
     Validation (val)      → --isis-accent (terre cuite — devenue la primaire le 2026-09-23)
     hérité / atténué      → --isis-text-muted
     sans-objet            → --isis-surface-alt + --isis-border-soft (surface neutre)
   Préfixe .isis-gov-matrix* uniquement, pour ne pas polluer les globales.
*/

/* Fil d'Ariane d'en-tête (crumb du mockup) */
.isis-gov-matrix-crumb {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-wrap: wrap;
    font-size: var(--isis-fs-sm);
    color: var(--isis-text-muted);
    margin: 0 0 0.75rem;
    line-height: 1.45;
}
.isis-gov-matrix-crumb b { color: var(--isis-text); font-weight: 600; }
.isis-gov-matrix-crumb__sep { color: var(--isis-text-soft); }
.isis-gov-matrix-crumb__spacer { margin-left: auto; }

/* Barre d'actions au-dessus d'une matrice (toggle mode + boutons profil) */
.isis-gov-matrix-bar {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    flex-wrap: wrap;
    margin-bottom: 0.5rem;
}
.isis-gov-matrix-bar__spacer { margin-left: auto; }

/* Matrice DROITS PAR PROFIL : lignes = profils, colonnes = domaines.
   Densité compacte façon DataGrid. */
.isis-gov-matrix--profil { min-width: 720px; }

/* Cellule cliquable de drill-in (profil × domaine) */
.isis-gov-matrix__cell-btn {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 3px;
    width: 100%;
    min-height: 48px;
    padding: 6px 5px;
    border-radius: var(--isis-radius-sm);
    border: 1px solid var(--isis-border-soft);
    background: var(--isis-surface);
    font: inherit;
    cursor: pointer;
    transition: border-color 0.12s ease, box-shadow 0.12s ease, background 0.12s ease;
}
.isis-gov-matrix__cell-btn:hover {
    border-color: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 45%, var(--isis-border));
    background: var(--isis-surface-alt);
}
.isis-gov-matrix__cell-btn:focus-visible {
    outline: 2px solid color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 70%, transparent);
    outline-offset: 2px;
}
.isis-gov-matrix__cell-btn.is-active {
    border-color: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 60%, transparent);
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 45%, transparent);
    background: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 8%, var(--isis-surface));
}
.isis-gov-matrix__cell-btn--na {
    cursor: not-allowed;
    border-style: dashed;
    border-color: var(--isis-border-soft);
    background: var(--isis-surface-alt);
}
.isis-gov-matrix__cell-btn--na:hover { background: var(--isis-surface-alt); border-color: var(--isis-border-soft); }

/* Trois pastilles L/E/V dans une cellule agrégée */
.isis-gov-swatches {
    display: inline-flex;
    align-items: center;
    gap: 5px;
}
.isis-gov-swatch-dot {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 17px;
    height: 17px;
    border-radius: 50%;
    font-size: 9.5px;
    font-weight: 700;
    line-height: 1;
    border: 1px solid var(--isis-border);
    background: var(--isis-surface-alt);
    color: var(--isis-text-muted);
}
/* Pastille active selon le droit */
.isis-gov-swatch-dot.is-read {
    background: color-mix(in srgb, var(--isis-read) 14%, transparent);
    border-color: color-mix(in srgb, var(--isis-read) 45%, transparent);
    color: var(--isis-read);
}
.isis-gov-swatch-dot.is-write {
    background: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 14%, transparent);
    border-color: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 45%, transparent);
    color: var(--isis-current-mod, var(--isis-accent));
}
.isis-gov-swatch-dot.is-validate {
    background: color-mix(in srgb, var(--isis-accent) 16%, transparent);
    border-color: color-mix(in srgb, var(--isis-accent) 50%, transparent);
    color: var(--isis-accent-strong);
}
/* État « aucun droit » : tiret atténué */
.isis-gov-matrix__cell-empty {
    font-size: 11px;
    color: var(--isis-text-muted);
    font-weight: 400;
}
.isis-gov-matrix__cell-na {
    font-size: 11px;
    color: var(--isis-text-muted);
    font-weight: 400;
}

/* En-tête de profil (1re colonne) avec libellé + crayon renommer */
.isis-gov-matrix__profil-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    font-weight: 600;
    font-size: 13px;
}

/* Légende L/E/V dédiée aux matrices de droits (réutilise .isis-gov-legend) */
.isis-gov-legend__swatch {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 17px;
    height: 17px;
    border-radius: 50%;
    font-size: 9.5px;
    font-weight: 700;
    line-height: 1;
}
.isis-gov-legend__swatch.is-read {
    background: color-mix(in srgb, var(--isis-read) 22%, transparent);
    border: 1px solid color-mix(in srgb, var(--isis-read) 45%, transparent);
    color: var(--isis-read);
}
.isis-gov-legend__swatch.is-write {
    background: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 22%, transparent);
    border: 1px solid color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 45%, transparent);
    color: var(--isis-current-mod, var(--isis-accent));
}
.isis-gov-legend__swatch.is-validate {
    background: color-mix(in srgb, var(--isis-accent) 22%, transparent);
    border: 1px solid color-mix(in srgb, var(--isis-accent) 50%, transparent);
    color: var(--isis-accent-strong);
}
/* Légende « aucun droit » : surface neutre + pointillés */
.isis-gov-legend__swatch--none {
    background: var(--isis-surface-alt);
    border: 1px dashed var(--isis-border);
}

/* Panneau de drill-in (éditeur par fonction sous la matrice) */
.isis-gov-drill {
    margin-top: 1rem;
    border: 1px solid color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 30%, var(--isis-border));
    border-radius: var(--isis-radius);
    background: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 4%, var(--isis-surface));
    box-shadow: var(--isis-elevation-1);
    overflow: hidden;
}
.isis-gov-drill__head {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    flex-wrap: wrap;
    padding: 0.7rem 1rem;
    border-bottom: 1px solid var(--isis-border-soft);
    font-size: var(--isis-fs-base);
}
.isis-gov-drill__title { font-weight: 600; color: var(--isis-text); display: inline-flex; align-items: center; gap: 0.4rem; }
.isis-gov-drill__close { margin-left: auto; }
.isis-gov-drill__body { padding: 0.5rem 1rem 0.85rem; }
.isis-gov-drill__fn-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
.isis-gov-drill__fn-row {
    display: flex;
    align-items: center;
    gap: 1rem;
    flex-wrap: wrap;
    padding: 0.5rem 0;
    border-bottom: 1px solid var(--isis-border-soft);
}
.isis-gov-drill__fn-row:last-child { border-bottom: none; }
.isis-gov-drill__fn-name { font-size: var(--isis-fs-base); font-weight: 500; min-width: 180px; }
.isis-gov-drill__fn-na { font-size: var(--isis-fs-label); color: var(--isis-text-muted); }
.isis-gov-drill__fn-rights { display: inline-flex; gap: 0.5rem; align-items: center; }

/* Titre de bloc (ex. « Organisation ») — marges tokenisées, plus d'inline */
.isis-gov-block-title { margin: 0 0 var(--isis-space-2, 0.5rem); }
/* Formulaire inline (nouveau/renommer profil) — espacement tokenisé */
.isis-gov-inline-form { margin-top: var(--isis-space-2, 0.5rem); }

/* Action « repartager tout » dans l'en-tête du panneau partages reçus */
.isis-gov-share__panel-action { margin: 0.25rem 0 0.5rem; }

/* Matrices PARTAGE (sortant/entrant) : densité compacte, case à cocher centrée */
.isis-gov-matrix--share { min-width: 720px; }
.isis-gov-matrix--share .isis-gov-matrix__cell { text-align: center; }

/* ── fin matrices gabarit/partage (port mockup) ── */

/* ════════════════════════════════════════════════════════════════════════════
   .isis-orgchart — organigramme humain (managérial) CSS, sans lib externe.
   Arbre récursif : un nœud-carte (avatar + nom + chip profil) ; connecteurs
   dessinés en bordures. Le nœud racine (manager de structure) est légèrement
   élevé. Mode --expanded = focus-zone position:fixed (calque .isis-focus-zone).
   ════════════════════════════════════════════════════════════════════════════ */
.isis-orgchart {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    outline: none;
    /* Le scroll horizontal (arbres larges) vit ici, PAS sur __canvas, sinon
       l'overflow:auto du canvas crée un contexte de rognage qui coupe le popover. */
    overflow: auto;
}
.isis-orgchart__bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
}
.isis-orgchart__title {
    font-size: var(--isis-fs-base);
    font-weight: 600;
    color: var(--isis-text);
}
.isis-orgchart__canvas {
    overflow: visible;
    padding: 0.5rem 0.25rem 0.75rem;
}
.isis-orgchart__empty {
    font-size: var(--isis-fs-sm);
    color: var(--isis-text-muted);
    padding: 0.75rem;
}

/* --- mode plein écran (focus-zone) — calque .isis-focus-zone --- */
.isis-orgchart--expanded {
    position: fixed;
    top: var(--isis-focus-zone-top, calc(var(--isis-header-h, 56px) + 52px));
    left: var(--isis-subnav-w, 280px);
    right: 0;
    bottom: 0;
    z-index: 950;
    background: var(--isis-surface);
    padding: 0.75rem 1rem 1rem;
    border-top: 1px solid var(--isis-border);
    transition: left 200ms cubic-bezier(0.4, 0, 0.2, 1);
}
.isis-shell.is-subnav-collapsed .isis-orgchart--expanded {
    left: var(--isis-subnav-w-collapsed, 64px);
}
.isis-orgchart--expanded:focus-visible {
    box-shadow: inset 0 0 0 2px var(--isis-accent);
}
.isis-orgchart--expanded .isis-orgchart__canvas {
    flex: 1 1 auto;
    min-height: 0;
    /* En plein écran le scroll (h/v) revient au canvas qui occupe la focus-zone. */
    overflow: auto;
}

/* --- arbre récursif (CSS connectors) --- */
.isis-orgchart__tree,
.isis-orgchart__children {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    gap: 1rem;
}
.isis-orgchart__tree { justify-content: center; }
.isis-orgchart__branch {
    display: flex;
    flex-direction: column;
    align-items: center;
    position: relative;
}
/* connecteur vertical sous un nœud qui a des enfants */
.isis-orgchart__children {
    margin-top: 1rem;
    padding-top: 1rem;
    position: relative;
}
.isis-orgchart__children::before {
    content: "";
    position: absolute;
    top: 0;
    left: 50%;
    width: 1px;
    height: 1rem;
    background: var(--isis-border);
    transform: translateX(-50%);
}
/* connecteurs horizontaux + verticaux vers chaque enfant */
.isis-orgchart__children > .isis-orgchart__branch::before {
    content: "";
    position: absolute;
    top: -1rem;
    left: 50%;
    width: 1px;
    height: 1rem;
    background: var(--isis-border);
}
.isis-orgchart__children > .isis-orgchart__branch::after {
    content: "";
    position: absolute;
    top: -1rem;
    /* déborde de la moitié du gap (gap=1rem) de chaque côté pour rejoindre les frères :
       sans ça, le gap inter-branches laisse la barre horizontale coupée. */
    left: -0.5rem;
    right: -0.5rem;
    height: 1px;
    background: var(--isis-border);
}
/* le 1er et le dernier enfant : moitié extérieure absente (s'arrête au centre du nœud),
   moitié intérieure prolongée dans le gap pour rejoindre le voisin. */
.isis-orgchart__children > .isis-orgchart__branch:first-child::after { left: 50%; right: -0.5rem; }
.isis-orgchart__children > .isis-orgchart__branch:last-child::after { left: -0.5rem; right: 50%; }
.isis-orgchart__children > .isis-orgchart__branch:only-child::after { display: none; }

/* --- nœud + carte --- */
.isis-orgchart__node { position: relative; }
.isis-orgchart__card {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.4rem 0.65rem;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius);
    max-width: 240px;
}
.isis-orgchart__card--editable { cursor: pointer; }
.isis-orgchart__card--editable:hover {
    border-color: var(--isis-current-mod, var(--isis-accent));
}
.isis-orgchart__card--editable:focus-visible {
    outline: none;
    box-shadow: 0 0 0 2px color-mix(in oklch, var(--isis-current-mod, var(--isis-accent)) 45%, transparent);
    border-color: var(--isis-current-mod, var(--isis-accent));
}
.isis-orgchart__node--root > .isis-orgchart__card {
    box-shadow: var(--isis-elevation-1);
    border-color: color-mix(in oklch, var(--isis-current-mod, var(--isis-accent)) 35%, var(--isis-border));
}
.isis-orgchart__avatar {
    flex: 0 0 auto;
    width: 28px;
    height: 28px;
    border-radius: 999px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: var(--isis-fs-sm);
    font-weight: 600;
    color: var(--isis-current-mod, var(--isis-accent));
    background: color-mix(in oklch, var(--isis-current-mod, var(--isis-accent)) 14%, var(--isis-surface));
}
.isis-orgchart__ident {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    min-width: 0;
}
.isis-orgchart__name {
    font-size: var(--isis-fs-sm);
    font-weight: 500;
    color: var(--isis-text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.isis-orgchart__chip {
    align-self: flex-start;
    font-size: var(--isis-fs-sm);
    font-weight: 500;
    padding: 0.05rem 0.4rem;
    border-radius: var(--isis-radius-sm);
    color: var(--isis-current-mod, var(--isis-accent));
    background: color-mix(in oklch, var(--isis-current-mod, var(--isis-accent)) 18%, var(--isis-surface));
    border: 1px solid color-mix(in oklch, var(--isis-current-mod, var(--isis-accent)) 35%, transparent);
}

/* --- groupe « Non rattachés » --- */
.isis-orgchart__unattached {
    margin-top: 1.25rem;
    padding-top: 0.75rem;
    border-top: 1px dashed var(--isis-border);
}
.isis-orgchart__unattached-label {
    display: block;
    font-size: var(--isis-fs-sm);
    font-weight: 600;
    color: var(--isis-text-muted);
    margin-bottom: 0.5rem;
}
.isis-orgchart__unattached-list {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
}
.isis-orgchart__node--flat { display: inline-block; }

/* --- popover d'édition inline (calque .isis-gov-restrict-panel) --- */
.isis-orgchart__popover {
    position: absolute;
    top: calc(100% + 0.4rem);
    left: 0;
    z-index: 5;
    min-width: 280px;
    padding: 0.75rem;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius);
    box-shadow: var(--isis-elevation-1);
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
    text-align: left;
}
.isis-orgchart__node.is-editing { z-index: 6; }
.isis-orgchart__popover-title {
    margin: 0;
    font-size: var(--isis-fs-base);
    font-weight: 600;
    color: var(--isis-text);
}
.isis-orgchart__popover-hint {
    margin: 0;
    font-size: var(--isis-fs-sm);
    color: var(--isis-text-muted);
}
.isis-orgchart__popover-footer {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
}


/* ──────────────────────────────────────────────────────────────────────────────
   Gantt commande (SfGantt) — couleur de barre PAR STATUT.
   La classe `isis-gb-*` est posée sur `.e-taskbar-main-container` via
   GanttTaskFields.CssClass (cf. CommandeGanttView.razor). On colore le taskbar
   PAR DÉFAUT de Syncfusion (pas de TaskbarTemplate) afin de préserver le
   drag/resize — un template casse le mouse-up d'édition (NRE ChartMouseUpHandler).
   ────────────────────────────────────────────────────────────────────────────── */
.isis-gb-grey   .e-gantt-child-taskbar-inner-div, .isis-gb-grey   .e-gantt-parent-taskbar-inner-div { background-color: #616161 !important; }
.isis-gb-green  .e-gantt-child-taskbar-inner-div, .isis-gb-green  .e-gantt-parent-taskbar-inner-div { background-color: #4caf50 !important; }
.isis-gb-orange .e-gantt-child-taskbar-inner-div, .isis-gb-orange .e-gantt-parent-taskbar-inner-div { background-color: #ff9800 !important; }
.isis-gb-teal   .e-gantt-child-taskbar-inner-div, .isis-gb-teal   .e-gantt-parent-taskbar-inner-div { background-color: #3a7d8c !important; }
.isis-gb-slate  .e-gantt-child-taskbar-inner-div, .isis-gb-slate  .e-gantt-parent-taskbar-inner-div { background-color: #cbd5e1 !important; }
.isis-gb-blue   .e-gantt-child-taskbar-inner-div, .isis-gb-blue   .e-gantt-parent-taskbar-inner-div { background-color: #2196f3 !important; }
.isis-gb-indigo .e-gantt-child-taskbar-inner-div, .isis-gb-indigo .e-gantt-parent-taskbar-inner-div { background-color: #4340d2 !important; }
.isis-gb-green2 .e-gantt-child-taskbar-inner-div, .isis-gb-green2 .e-gantt-parent-taskbar-inner-div { background-color: #70bf73 !important; }
.isis-gb-red    .e-gantt-child-taskbar-inner-div, .isis-gb-red    .e-gantt-parent-taskbar-inner-div { background-color: #f44336 !important; }
.isis-gb-grey2  .e-gantt-child-taskbar-inner-div, .isis-gb-grey2  .e-gantt-parent-taskbar-inner-div { background-color: #9e9e9e !important; }
/* Surcharge : anneau rouge autour de la barre (conserve la couleur de charge dessous). */
.is-overload .e-gantt-child-taskbar-inner-div { box-shadow: 0 0 0 2px #f44336, inset 0 0 0 1px rgba(255,255,255,.6) !important; }

/* portion « avancement » : voile sombre uniforme par-dessus la couleur de statut */
[class*="isis-gb-"] .e-gantt-child-progressbar-inner-div,
[class*="isis-gb-"] .e-gantt-parent-progressbar-inner-div { background-color: rgba(0,0,0,0.22) !important; }

/* milestones (jalons / livraisons) — diamant construit en bordures CSS */
.isis-gb-grey   .e-milestone-top{border-bottom-color:#616161 !important}.isis-gb-grey   .e-milestone-bottom{border-top-color:#616161 !important}
.isis-gb-green  .e-milestone-top{border-bottom-color:#4caf50 !important}.isis-gb-green  .e-milestone-bottom{border-top-color:#4caf50 !important}
.isis-gb-indigo .e-milestone-top{border-bottom-color:#4340d2 !important}.isis-gb-indigo .e-milestone-bottom{border-top-color:#4340d2 !important}
.isis-gb-green2 .e-milestone-top{border-bottom-color:#70bf73 !important}.isis-gb-green2 .e-milestone-bottom{border-top-color:#70bf73 !important}
.isis-gb-red    .e-milestone-top{border-bottom-color:#f44336 !important}.isis-gb-red    .e-milestone-bottom{border-top-color:#f44336 !important}
.isis-gb-blue   .e-milestone-top{border-bottom-color:#2196f3 !important}.isis-gb-blue   .e-milestone-bottom{border-top-color:#2196f3 !important}
.isis-gb-grey2  .e-milestone-top{border-bottom-color:#9e9e9e !important}.isis-gb-grey2  .e-milestone-bottom{border-top-color:#9e9e9e !important}

/* Repère « aujourd'hui » (GanttEventMarker CssClass="isis-gantt-today") : ligne pointillée + label
   en accent chaud pour le distinguer des échéances (repères neutres). On cible large (la classe peut
   être posée sur le conteneur ou la ligne selon le rendu Syncfusion). */
.e-gantt .isis-gantt-today,
.e-gantt .isis-gantt-today.e-event-markers,
.e-gantt .isis-gantt-today .e-event-markers {
    border-left: 2px dashed var(--isis-accent) !important;
}
.e-gantt .isis-gantt-today .e-span-label,
.e-gantt .isis-gantt-today.e-span-label,
.e-gantt .isis-gantt-today + .e-span-label {
    background: var(--isis-accent) !important;
    color: #fff !important;
    font-weight: 600;
}
/* Tooltip riche du Gantt (GanttTooltipSettings/TaskbarTemplate) */
.isis-gantt-tip { padding: 0.15rem 0.1rem; min-width: 120px; line-height: 1.35; }
.isis-gantt-tip__title { font-weight: 600; font-size: 0.82rem; }
.isis-gantt-tip__dates { font-size: 0.76rem; opacity: 0.92; font-variant-numeric: tabular-nums; }
.isis-gantt-tip__detail { font-size: 0.74rem; opacity: 0.78; margin-top: 0.1rem; }
/* ── Zone pièces jointes GED dans les dialogs mail ─────────────────────────── */
.isis-mail-pj__header {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    flex-wrap: wrap;
}

.isis-mail-pj__chips {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
    margin-top: 0.5rem;
}

.isis-mail-pj__chip {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    padding: 0.2rem 0.5rem;
    border-radius: var(--isis-radius-sm, 5px);
    background: color-mix(in srgb, var(--isis-accent) 10%, var(--isis-surface));
    border: 1px solid color-mix(in srgb, var(--isis-accent) 25%, transparent);
    font-size: var(--isis-fs-sm, 0.875rem);
    color: var(--isis-ink, #1a1a2e);
    max-width: 280px;
}

.isis-mail-pj__chip-name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    flex: 1;
    min-width: 0;
}

.isis-mail-pj__chip-size {
    font-size: var(--isis-fs-xs, 0.75rem);
    color: var(--isis-muted, #6b7280);
    flex-shrink: 0;
    font-variant-numeric: tabular-nums;
}

.isis-mail-pj__chip-remove {
    flex-shrink: 0;
    padding: 0 !important;
    width: 1.1rem;
    height: 1.1rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

.isis-mail-pj__total {
    font-size: var(--isis-fs-xs, 0.75rem);
    color: var(--isis-muted, #6b7280);
    margin-top: 0.25rem;
}

.isis-mail-pj__total--over {
    color: var(--isis-danger);
    font-weight: 600;
}

/* ── Circuit d'approbation d'un document GED (.docappr, DocumentApprovalPanel) ──────────────
   Composant partagé (fiche document gesqhse ET DocumentViewerDialog du gestionnaire GED) —
   centralisé ici (audit design 2026-07-29 : les classes .docappr* vivaient jusque-là dans un
   <style> embarqué au composant, hors design system). Réutilise .isis-docstatut (pastille de
   statut) et .isis-action-btn (bouton × de chip) plutôt que d'inventer un vocabulaire propre. */
.docappr { display: flex; flex-direction: column; gap: var(--isis-space-sm); padding: 0.6rem 0.85rem; font-size: var(--isis-fs-sm); }
.docappr__head { display: flex; align-items: center; gap: var(--isis-space-xs); }
.docappr__title { font-weight: 600; color: var(--isis-text); }
/* Layout seul — la couleur/forme du statut vit dans .isis-docstatut. */
.docappr__status { margin-left: auto; }
.docappr__muted { color: var(--isis-text-muted); display: flex; align-items: center; gap: var(--isis-space-xs); }

/* Chaîne des étapes — le rang « 1. » est écrit dans le markup (@s.Order.), la numérotation
   native de l'<ol> est donc désactivée pour ne pas la doubler (« 1. 1. Kouassi N. »). */
.docappr__chain { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.25rem; }
.docappr__step { display: flex; align-items: center; gap: 0.45rem; padding: 0.3rem 0.5rem; border-radius: var(--isis-radius-sm, 5px); border: 1px solid transparent; }
.docappr__step.is-current { background: var(--isis-current-mod-soft, var(--isis-accent-soft)); border-left-color: var(--isis-current-mod, var(--isis-accent)); }
.docappr__step--approved { color: var(--isis-success); }
.docappr__step--rejected { color: var(--isis-danger); }
.docappr__step--skipped  { opacity: 0.5; }
.docappr__step-name { flex: 1; color: var(--isis-text); }
.docappr__step-state { font-size: var(--isis-fs-xs); color: var(--isis-text-muted); }

.docappr__submit { display: flex; flex-direction: column; gap: 0.4rem; }
.docappr__lbl { font-weight: 600; font-size: var(--isis-fs-sm); color: var(--isis-text); }
.docappr__picker { display: flex; gap: 0.4rem; }
.docappr__chips { display: flex; flex-wrap: wrap; gap: 0.3rem; }
.docappr__chip { display: inline-flex; align-items: center; gap: 0.3rem; padding: 0.15rem 0.5rem; border-radius: 12px; background: var(--isis-accent-soft); color: var(--isis-accent); font-size: var(--isis-fs-sm); }
/* Bouton × d'un chip validateur — .isis-action-btn (même base que le retrait de pièce jointe
   des dialogs mail, .isis-mail-pj__chip-remove) plutôt qu'un <button> nu au chrome système. */
.docappr__chip-remove {
    flex-shrink: 0;
    padding: 0 !important;
    width: 1.1rem;
    height: 1.1rem;
}
.docappr__actions { display: flex; gap: 0.4rem; flex-wrap: wrap; }

/* ── Champ de recherche générique inline ────────────────────────────────────── */
.isis-search-input {
    width: 100%;
    padding: 0.4rem 0.75rem;
    border: 1px solid var(--isis-border, #e5e7eb);
    border-radius: var(--isis-radius-sm, 5px);
    background: var(--isis-surface, #fff);
    color: var(--isis-ink, #1a1a2e);
    font-size: var(--isis-fs-sm, 0.875rem);
    outline: none;
    transition: border-color var(--isis-motion-fast, 120ms);
}

.isis-search-input:focus-visible {
    border-color: var(--isis-accent, oklch(0.52 0.094 218));
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--isis-accent, oklch(0.52 0.094 218)) 20%, transparent);
}


/* ── Champs encadrés = défaut global (promu du pilote .isis-temps-fields, 2026-06-30) ──
   Look « Instrument » : input encadré + numérique Geist Mono. Le pattern .isis-form-linear
   (soulignement, formulaires 720px) conserve son look via des règles plus spécifiques + !important. */
.rz-textbox, .rz-textarea, .rz-numeric {
    border: 1px solid var(--isis-border) !important;
    border-radius: var(--isis-radius-sm) !important;
    background: var(--isis-surface) !important;
    box-shadow: none !important;
    color: var(--isis-text) !important;
    padding: .34rem .5rem !important;
    height: auto !important;
    min-height: 0 !important;
    transition: border-color 150ms ease, box-shadow 150ms ease !important;
}
.rz-numeric { padding: 0 !important; display: flex !important; align-items: stretch !important; overflow: hidden; }
/* ATTENTION — les classes de RadzenNumeric ont changé avec Radzen 11 : `rz-numeric-input`,
   `rz-numeric-up`, `rz-numeric-down`, `rz-numeric-button`. Les anciens sélecteurs
   `.rz-spinner-*` (Radzen 6) ne matchaient plus RIEN — seule survivait la règle qui
   rapetisse `.rz-numeric` ci-dessus, sans les compensations prévues.

   Effet mesuré au navigateur le 2026-09-07, sur TOUS les champs numériques du produit
   (172 fichiers) : le champ tombait à 33px de haut alors que Radzen dimensionne ses deux
   flèches à 36px, positionnées `top:2px` et `bottom:2px`. La flèche « bas » occupait donc
   -5 → 31 et la flèche « haut » 2 → 38 : **la flèche bas était physiquement AU-DESSUS de
   la flèche haut**, avec 29px de recouvrement sur 36. Dans la zone commune, « bas »,
   peinte en dernier, captait le clic — d'où des boutons qui semblaient inversés et
   répondaient mal. Les deux débordaient en plus sur le texte, faute de marge réservée.

   Correction : viser les vraies classes, borner chaque flèche à la moitié du champ pour
   qu'elles ne puissent plus se recouvrir, et réserver leur largeur à droite de l'input. */
.rz-numeric .rz-numeric-input {
    flex: 1; background: transparent !important; border: 0 !important; box-shadow: none !important;
    padding: .34rem 1.6rem .34rem .5rem !important; color: var(--isis-text) !important;
    height: auto !important; min-height: 0 !important;
    font-family: var(--isis-font-mono, 'Geist Mono', ui-monospace, monospace); text-align: right; font-variant-numeric: tabular-nums;
}
.rz-numeric .rz-numeric-up, .rz-numeric .rz-numeric-down, .rz-numeric .rz-numeric-button {
    background: transparent !important; border: 0 !important; box-shadow: none !important;
    color: var(--isis-text-muted) !important; margin: 0 !important; padding: 0 !important;
    width: 1.4rem !important; right: 1px !important;
    /* Chacune la moitié du champ, moins la bordure : deux moitiés ne peuvent pas se recouvrir,
       quelle que soit la hauteur que prend le champ. */
    height: calc(50% - 1px) !important; min-height: 0 !important;
}
/* La place des flèches doit être réservée QUEL QUE SOIT le contexte : plusieurs blocs de
   formulaire remettent le padding de l'input à zéro avec une spécificité supérieure
   (`.isis-form-linear .rz-numeric > input { padding: 0 !important }`), et le texte passe
   alors sous les flèches. Mesuré le 2026-09-07 sur /gespark/indemnites,
   /admin/parametres/geocodage et /gesqhse/parametres/referencement : padding calculé
   « 5.6px 0px », donc zéro place réservée. Ce sélecteur égale leur spécificité et gagne
   par l'ordre de source. */
.rz-numeric > input.rz-numeric-input { padding-right: 1.6rem !important; }

.rz-numeric .rz-numeric-up   { top: 1px !important; bottom: auto !important; }
.rz-numeric .rz-numeric-down { bottom: 1px !important; top: auto !important; }
.rz-numeric .rz-numeric-button .rzi { font-size: 0.9rem; line-height: 1; }
.rz-textbox:focus, .rz-textarea:focus, .rz-numeric:focus-within {
    border-color: var(--isis-current-mod, var(--isis-accent)) !important;
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 18%, transparent) !important;
    outline: none !important;
}

/* ── Harmonisation 2026-07-04 — dropdowns / datepickers / multiselects au même look
   Instrument que les champs texte ci-dessus. Avant : seuls textbox/textarea/numeric
   étaient stylés globalement → les 549 RadzenDropDown et 175 RadzenDatePicker gardaient
   le look Radzen Material brut hors .isis-form-linear (cause principale du « mélange »). */
.rz-dropdown, .rz-multiselect, .rz-datepicker {
    border: 1px solid var(--isis-border) !important;
    border-radius: var(--isis-radius-sm) !important;
    background: var(--isis-surface) !important;
    box-shadow: none !important;
    height: auto !important;
    min-height: 0 !important;
    transition: border-color 150ms ease, box-shadow 150ms ease !important;
}
.rz-dropdown .rz-dropdown-label,
.rz-multiselect .rz-multiselect-label {
    padding: .34rem .5rem !important;
    color: var(--isis-text) !important;
}
.rz-datepicker .rz-inputtext {
    border: 0 !important;
    background: transparent !important;
    box-shadow: none !important;
    padding: .34rem .5rem !important;
    color: var(--isis-text) !important;
    height: auto !important;
    min-height: 0 !important;
}
.rz-dropdown-trigger, .rz-datepicker-trigger {
    background: transparent !important;
    color: var(--isis-text-muted) !important;
    border: 0 !important;
}
.rz-dropdown.rz-state-focused, .rz-multiselect.rz-state-focused, .rz-datepicker:focus-within {
    border-color: var(--isis-current-mod, var(--isis-accent)) !important;
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 18%, transparent) !important;
    outline: none !important;
}
/* Radzen pose `.rz-dropdown { display: inline-flex; flex-direction: column }`. Six règles
   locales (form-linear, barres de filtres, toolbars, devis, planner, matrice des rôles)
   avaient été écrites pour une RANGÉE et y posaient `align-items: center` : en colonne, cela
   centre le libellé HORIZONTALEMENT et le rétrécit à son texte — « geopf_ortho » flottait au
   milieu d'un champ de 541 px sur /master/basemaps (mesuré le 2026-10-07). Le centrage
   vertical d'une colonne passe par `justify-content`. Invariant tenu par
   DropDownLibelleNonCentreTests. */
.rz-dropdown, .rz-multiselect {
    align-items: stretch !important;
    justify-content: center;
}
/* Même invariant côté enfant : un `align-self: center` sur le libellé (barre de filtres,
   pensé pour une rangée) le recentrait malgré le conteneur. */
.rz-dropdown > .rz-dropdown-label,
.rz-multiselect > .rz-multiselect-label-container {
    align-self: stretch !important;
}
/* Radzen 11 pose 7 px × 15 px de rembourrage sur TOUT conteneur `.rz-dropdown` (via
   `.rz-input-md`), pas seulement en mode puces : additionnés à celui du libellé posé plus
   haut → 51 px contre 35 pour un champ texte voisin (mesuré le 2026-10-10 sur
   /sirh/parametres/integration). Le libellé porte seul l'air intérieur ; l'espace droit du
   déclencheur reste. */
.rz-dropdown {
    padding-top: 0 !important;
    padding-bottom: 0 !important;
    padding-left: 0 !important;
}

/* Bouton radio sur la couleur du module (2026-10-08) : Radzen peint contour, point et halo en
   `--rz-primary`, un indigo hors palette, à côté de boutons et d'un menu déjà sur la couleur
   de module. Déclaré sur `.rz-radiobutton` et non sur `:root` : la variable s'y résout là où
   `--isis-current-mod` est connue (posée sur `.isis-shell`), une fenêtre hors coquille
   retombant sur l'accent. `--rz-primary` reste intact, il repeindrait tout Radzen. */
.rz-radiobutton {
    --rz-radio-checked-border: var(--rz-radio-border-width) solid var(--isis-current-mod, var(--isis-accent));
    --rz-radio-circle-background-color: var(--isis-current-mod, var(--isis-accent));
    --rz-radio-circle-hover-background-color: var(--isis-current-mod, var(--isis-accent));
    --rz-radio-focus-outline: var(--rz-outline-width) solid var(--isis-current-mod, var(--isis-accent));
}
.rz-radiobutton-box.rz-state-active:hover:not(.rz-state-disabled)::after {
    background-color: var(--isis-current-mod, var(--isis-accent));
}

/* Case à cocher et interrupteur : même correctif, même portée. La coche est en
   `--isis-surface`, comme le texte d'un bouton primaire : en sombre, la couleur de module
   s'éclaircit et une coche blanche n'y tiendrait plus. */
.rz-chkbox {
    --rz-checkbox-checked-background-color: var(--isis-current-mod, var(--isis-accent));
    --rz-checkbox-checked-border: var(--rz-checkbox-border-width) solid var(--isis-current-mod, var(--isis-accent));
    --rz-checkbox-checked-color: var(--isis-surface);
    --rz-checkbox-checked-hover-background-color: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 88%, black);
    --rz-checkbox-checked-hover-border: var(--rz-checkbox-border-width) solid color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 88%, black);
    --rz-checkbox-focus-outline: var(--rz-outline-width) solid var(--isis-current-mod, var(--isis-accent));
}
.rz-chkbox-box.rz-state-active:hover:not(.rz-state-disabled)::after {
    background-color: var(--isis-current-mod, var(--isis-accent));
}
.rz-switch {
    --rz-switch-checked-background-color: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 38%, transparent);
    --rz-switch-checked-circle-background-color: var(--isis-current-mod, var(--isis-accent));
    --rz-switch-focus-outline: var(--rz-outline-width) solid var(--isis-current-mod, var(--isis-accent));
}
.rz-switch.rz-switch-checked .rz-switch-circle:hover:not(.rz-disabled)::before {
    box-shadow: var(--rz-switch-box-shadow), 0 0 0 10px color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 16%, transparent);
}
/* Sélecteur segmenté (RadzenSelectBar) : option choisie sur le couple de l'onglet actif
   (`-soft` / `-strong`, dosé pour l'AA texte). Les variantes restylées en local
   (.isis-form-linear, .isis-frais-card) gardent leur pastille neutre. */
.rz-selectbar {
    --rz-selectbar-selected-background-color: var(--isis-current-mod-soft, var(--isis-accent-soft));
    --rz-selectbar-selected-color: var(--isis-current-mod-strong, var(--isis-accent-on-soft));
    --rz-selectbar-focus-outline: var(--rz-outline-width) solid var(--isis-current-mod, var(--isis-accent));
}

/* Hauteur unifiée 32 px pour tout contrôle Radzen posé dans une filter-bar ou une toolbar
   riche — les pickers Radzen font 36 px par défaut, dissonants à côté des boutons 32 px
   et chips 28 px (généralise les 2 patchs locaux OrganisationDualePage / PermissionsPage).
   Étendu à .isis-grid__subrow-actions (2026-07-29, ligne dépliée gesqhse/documentaire) :
   même dissonance quand un RadzenDatePicker cohabite avec des IsisButton dans une ligne de
   grille dépliée, hors de tout .isis-rich-toolbar. Étendu de même à .isis-tab-panel__actions
   (barre d'actions d'un panneau d'onglet) pour qu'un futur contrôle Radzen y soit harmonisé
   dès le départ, plutôt que de rouvrir le même piège ailleurs. Étendu à .docappr (même jour) :
   le RadzenDropDown du picker de validateurs y cohabite avec le bouton « Ajouter » à 32px.
   Le RadzenTextArea (motif de rejet / note) N'EST PAS ajouté ici : Radzen le laisse en
   height:auto (cf. material-base.css) pour respecter Rows="2" — le forcer à 32px tronquerait
   le champ à une seule ligne visible. */
.isis-filter-bar .rz-textbox, .isis-filter-bar .rz-dropdown, .isis-filter-bar .rz-multiselect,
.isis-filter-bar .rz-datepicker, .isis-filter-bar .rz-numeric,
.isis-rich-toolbar .rz-textbox, .isis-rich-toolbar .rz-dropdown, .isis-rich-toolbar .rz-multiselect,
.isis-rich-toolbar .rz-datepicker, .isis-rich-toolbar .rz-numeric,
.isis-grid__subrow-actions .rz-textbox, .isis-grid__subrow-actions .rz-dropdown,
.isis-grid__subrow-actions .rz-multiselect, .isis-grid__subrow-actions .rz-datepicker,
.isis-grid__subrow-actions .rz-numeric,
.isis-tab-panel__actions .rz-textbox, .isis-tab-panel__actions .rz-dropdown,
.isis-tab-panel__actions .rz-multiselect, .isis-tab-panel__actions .rz-datepicker,
.isis-tab-panel__actions .rz-numeric,
.docappr .rz-textbox, .docappr .rz-dropdown, .docappr .rz-multiselect,
.docappr .rz-datepicker, .docappr .rz-numeric,
/* Étendu à .isis-habilitation-block__head (2026-08-05) : le sélecteur de fonction du bloc
   « Fonctions » y cohabite avec un .isis-rich-toolbar__btn, dont la hauteur de 32px tient à sa
   propre classe et s'applique donc hors de toute toolbar. Sans harmonisation, le dropdown
   mesurait 50,9px contre 32px pour le bouton (mesuré en navigateur) et poussait l'en-tête du
   bloc à 74,3px, contre 61px pour les quinze blocs de module juste en dessous : le bloc de tête
   cassait le rythme de la liste qu'il ouvre. */
.isis-habilitation-block__head .rz-textbox, .isis-habilitation-block__head .rz-dropdown,
.isis-habilitation-block__head .rz-multiselect, .isis-habilitation-block__head .rz-datepicker,
.isis-habilitation-block__head .rz-numeric {
    height: 32px !important;
    min-height: 32px !important;
    font-size: 0.8125rem !important;
    display: inline-flex;
    align-items: center;
    overflow: hidden;
}
/* Le label interne des pickers garde sinon sa hauteur Radzen (36px) et déborde sous les 32px. */
.isis-filter-bar .rz-dropdown .rz-dropdown-label, .isis-rich-toolbar .rz-dropdown .rz-dropdown-label,
.isis-filter-bar .rz-multiselect .rz-multiselect-label, .isis-rich-toolbar .rz-multiselect .rz-multiselect-label,
.isis-filter-bar .rz-datepicker .rz-inputtext, .isis-rich-toolbar .rz-datepicker .rz-inputtext,
.isis-grid__subrow-actions .rz-datepicker .rz-inputtext,
.isis-tab-panel__actions .rz-dropdown .rz-dropdown-label,
.isis-tab-panel__actions .rz-multiselect .rz-multiselect-label,
.isis-tab-panel__actions .rz-datepicker .rz-inputtext,
.docappr .rz-dropdown .rz-dropdown-label,
.isis-habilitation-block__head .rz-dropdown .rz-dropdown-label,
.isis-habilitation-block__head .rz-multiselect .rz-multiselect-label {
    height: auto !important;
    line-height: 1.2 !important;
    padding: 0 .5rem !important;
    align-self: center;
    flex: 1 1 auto;
    min-width: 0;
}

/* ── Utilitaires « champs Temps » (#4/#7) — conservés scopés ─────────────────────────
   Le markup saisie-temps (fenêtre Frais du jour + récap mensuel) utilise encore .itf-num /
   .itf-lbl / .itf-mono. Les règles input encadrées sont désormais globales (ci-dessus). */
.isis-temps-fields {
    --itf-mono: var(--isis-font-mono, 'Geist Mono', ui-monospace, monospace);
}
/* Numérique mono aligné à droite (montants, km, compteurs, heures). */
.isis-temps-fields .itf-num,
.isis-temps-fields .itf-num input {
    font-family: var(--itf-mono); text-align: right; font-variant-numeric: tabular-nums;
}
/* Labels petits, au-dessus, capitales douces (parité mockup .fld label). */
.isis-temps-fields .itf-lbl {
    display: block; font-size: .66rem; font-weight: 600; color: var(--isis-text-muted);
    text-transform: uppercase; letter-spacing: .03em; margin-bottom: .2rem;
}
/* Valeur numérique en lecture seule (récap mensuel). */
.isis-temps-fields .itf-mono {
    font-family: var(--itf-mono); font-variant-numeric: tabular-nums;
}

/* ──────────────────────────────────────────────────────────────────────────
   C1 — Trésorerie prévisionnelle (page /gescompta/tresorerie-previsionnelle)
   Layout agrégat mensuel (KPI « En retard » + tableau pivot côte à côte) +
   variante de grille pour la liste des échéances. Tokens --isis-* uniquement.
   ────────────────────────────────────────────────────────────────────────── */

/* KPI « En retard » isolé à gauche du tableau pivot ; passe dessous en étroit. */
.isis-treso-layout {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: 1rem;
}
.isis-treso-layout > .isis-analyse-pivot-wrapper { flex: 1 1 360px; min-width: 0; }

/* Carte KPI « En retard » en accent chaud (calque .isis-kpi-card / .isis-badge--warm). */
.isis-treso-overdue {
    flex: 0 0 auto;
    min-width: 180px;
    display: flex;
    flex-direction: column;
    gap: 0.2rem;
    padding: 0.85rem 1rem;
    border-radius: var(--isis-radius-lg, 12px);
    border: 1px solid color-mix(in srgb, var(--isis-accent) 35%, var(--isis-border));
    background: var(--isis-accent-soft);
}
.isis-treso-overdue .isis-kpi-card__label { color: var(--isis-accent-strong); }
.isis-treso-overdue .isis-kpi-card__value {
    color: var(--isis-accent-strong);
    font-family: var(--isis-font-mono, ui-monospace, monospace);
    font-variant-numeric: tabular-nums;
    font-size: 1.6rem;
    font-weight: 600;
}

/* Cellules montant du pivot trésorerie : alignées à droite, mono tabulaire. */
.isis-analyse-pivot--treso .isis-analyse-pivot__col-month {
    text-align: right;
    font-variant-numeric: tabular-nums;
    font-family: var(--isis-font-mono, ui-monospace, monospace);
}

/* Grille des échéances : 8 colonnes (calque .isis-grid--analyse-impayes). */
.isis-grid--treso-echeances .isis-grid__head,
.isis-grid--treso-echeances .isis-grid__row {
    display: grid;
    grid-template-columns: minmax(180px, 1.4fr) minmax(160px, 1.6fr) 130px 110px 150px 150px 110px 40px;
    gap: 0.5rem;
    align-items: center;
}

/* ─────────────────────────────────────────────────────────────────────────────
   Bouton flottant de feedback (EF-07)
   Position fixe bas-droite, teinte module courante, élévation hover.
   ─────────────────────────────────────────────────────────────────────────── */
.isis-feedback-fab {
    /* z-index 990 : le bas-droite est le coin le plus disputé de l'app. À 50 (le niveau
       de l'en-tête) le bouton passait SOUS le drawer de sidepanel (940) et sa languette
       (942), sous toutes les focus-zones plein écran (950), sous le menu de débordement
       de barre d'outils (960/961), sous la barre d'actions en masse (100), sous les
       entonnoirs de colonne (60/61), sous le panneau de filtres flottant (50, mais plus
       bas dans le DOM) et sous les couches Leaflet (200–800). 990 le met au-dessus de
       tout ça et SOUS la couche modale, qui doit continuer de le recouvrir : palette
       Ctrl+K (1000/1001), flyout du sub-nav (1000), dialogs Radzen (1001) et
       notifications Radzen (1002). */
    position: fixed; right: 1rem; bottom: 4.5rem; z-index: 990;
    width: 44px; height: 44px; border-radius: var(--isis-radius-lg);
    border: none; background: var(--isis-current-mod, var(--isis-accent));
    color: #fff; box-shadow: var(--isis-elevation-hover); cursor: pointer;
    display: inline-flex; align-items: center; justify-content: center;
    transition: background var(--isis-motion-fast), box-shadow var(--isis-motion-fast),
                transform var(--isis-motion-fast);
}
.isis-feedback-fab:hover {
    background: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 85%, #000);
    /* Le bouton est en position fixe : ce leger decollage ne deplace rien d'autre. L'ombre monte
       d'un cran (au repos elle vaut deja --isis-elevation-hover, le bouton flottant au-dessus
       du contenu). */
    transform: translateY(-2px) scale(1.06);
    box-shadow: var(--isis-elevation-2);
}
.isis-feedback-fab:active {
    transform: translateY(0) scale(0.96);
}
/* WCAG 2.3.3 : le decollage disparait, la teinte et l'elevation restent — ce sont elles qui
   portent l'information de survol, le mouvement n'etait que du confort. */
@media (prefers-reduced-motion: reduce) {
    .isis-feedback-fab {
        transition: background var(--isis-motion-fast), box-shadow var(--isis-motion-fast);
    }
    .isis-feedback-fab:hover,
    .isis-feedback-fab:active { transform: none; }
}
.isis-feedback-fab:focus-visible {
    outline: 2px solid var(--isis-current-mod, var(--isis-accent)); outline-offset: 2px;
}

/* =========================================================================
   Annotation d'une capture d'écran — dialogue ImageAnnotatorDialog.
   Ajouté 2026-09-26. La barre d'outils réutilise .isis-rich-toolbar__btn
   (+ .is-active pour l'outil courant) : aucun bouton maison, aucune ombre
   ad hoc. Aucun jeton de module n'est redéclaré ici : .is-active porte déjà
   son repli DANS le var() (color-mix(… var(--isis-current-mod, var(--isis-accent)) …)),
   forme qui survit à l'absence du jeton hors du shell — un dialogue Radzen
   étant rendu en dehors de .isis-shell.
   ========================================================================= */
.isis-annot {
    display: flex; flex-direction: column; gap: var(--isis-space-sm);
}
.isis-annot__bar {
    display: flex; align-items: center; flex-wrap: wrap; gap: var(--isis-space-xs);
}
.isis-annot__sep {
    width: 1px; align-self: stretch; min-height: 1.5rem;
    margin: 0 var(--isis-space-xs); background: var(--isis-border);
}
.isis-annot__stage {
    display: flex; justify-content: center;
    background: var(--isis-surface-alt); border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius); padding: var(--isis-space-xs);
    overflow: auto; max-height: 60vh;
}
.isis-annot__canvas {
    max-width: 100%; height: auto; cursor: crosshair;
    /* Sans touch-action, le geste de tracé est confisqué par le défilement tactile. */
    touch-action: none;
    border-radius: var(--isis-radius-sm); background: var(--isis-surface);
}
.isis-annot__help { margin: 0; font-size: 0.75rem; color: var(--isis-text-muted); max-width: 92ch; }
/* Lancement de l'annotation depuis le dialogue de feedback. */
.isis-annot__launch {
    display: flex; align-items: center; flex-wrap: wrap;
    gap: var(--isis-space-sm); margin-top: var(--isis-space-xs);
}

/* Le canevas est opérable au clavier (flèches + Entrée) : sans anneau visible, qui tabule ne sait
   pas que le focus y est entré. */
.isis-annot__canvas:focus-visible {
    outline: 2px solid var(--isis-current-mod, var(--isis-accent));
    outline-offset: 2px;
}

/* -------------------------------------------------------------------------
   Dialogue de signalement (FeedbackDialog) — plancher de la Description,
   aperçu de capture, liste des pièces jointes, ligne de contexte.
   ------------------------------------------------------------------------- */

/* La règle globale de .isis-form-linear ramène un textarea vide à 35 px (field-sizing: content,
   cf. « Textarea auto-croissant ») : sur « Description », un champ d'une ligne n'invite pas à
   détailler un bug. Seul ce champ est relevé — spécificité supérieure ET !important, la règle
   globale portant elle-même !important. */
.isis-form-linear textarea.isis-feedback-body {
    min-height: 92px !important;
}

.isis-feedback-shot {
    display: block;
    max-width: 100%;
    max-height: 140px;
    margin-top: var(--isis-space-xs);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-sm);
}

/* Capture : décision à gauche, aperçu à droite. Empilés, l'étiquette, la case, l'aide, l'aperçu
   et le bouton Annoter mangeaient ~250 px des ~830 px de la fenêtre. Côte à côte, le bloc retombe
   à la hauteur du seul aperçu, et celui-ci n'est PAS réduit : il sert à reconnaître l'écran
   transmis et à y repérer une donnée confidentielle. L'ordre du DOM reste décision puis aperçu
   (« Annoter » est inerte case décochée) — aucun order:-1, qui désaccorderait lecture et vue. */
.isis-feedback-capture {
    display: flex;
    align-items: flex-start;
    gap: var(--isis-space-md);
}
.isis-feedback-capture__side {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: var(--isis-space-xs);
}
.isis-feedback-capture .isis-feedback-shot {
    flex: none;
    max-width: 55%;
    margin-top: 0;
}
@media (max-width: 560px) {
    .isis-feedback-capture { flex-direction: column; }
    .isis-feedback-capture .isis-feedback-shot { max-width: 100%; }
}

/* Plafond de hauteur de la fenêtre de retour : le thème Radzen pose overflow:hidden sur
   .rz-dialog sans overflow sur .rz-dialog-content, donc les deux règles vont ensemble (même
   recette que .isis-mob-dialog / .isis-import-droits-dialog). Classe posée par
   DialogOptions.CssClass dans FeedbackButton. */
.rz-dialog.isis-feedback-dialog { max-height: 90vh; }
.rz-dialog.isis-feedback-dialog .rz-dialog-content { overflow-y: auto; min-height: 0; }

.isis-feedback-files {
    list-style: none;
    margin: 0.5rem 0 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
}
.isis-feedback-files li {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-size: 0.8125rem;
}
.isis-feedback-files__name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.isis-feedback-files__size {
    color: var(--isis-text-muted);
    font-variant-numeric: tabular-nums;
}

/* Sélecteur préfixé par .isis-form-linear : la marge doit battre celle de .isis-form-linear
   .helper, que ce paragraphe porte aussi. */
.isis-form-linear .isis-feedback-ctx {
    display: flex;
    align-items: flex-start;
    gap: 0.35rem;
    margin: 0;
}
.isis-feedback-ctx .rzi {
    font-size: 14px;
    line-height: 1.3;
    flex: none;
}

/* =========================================================================
   Recette collaborative — page de campagne (hero de progression, avancement
   par recetteur, cas groupés par thème, panneau latéral).
   Ajouté 2026-07-09. Réutilise .isis-grid / .isis-master-detail / .isis-kpi-card.
   ========================================================================= */

/* Avancement par recetteur : une ligne = nom + barre + compteur. */
.isis-recette-progress {
    display: flex;
    flex-direction: column;
    gap: var(--isis-space-xs);
    padding: var(--isis-space-sm) var(--isis-space-md);
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius);
    margin-bottom: var(--isis-space-sm);
}
.isis-recette-progress__row {
    display: flex;
    align-items: center;
    gap: var(--isis-space-sm);
}
.isis-recette-progress__name {
    flex: 0 0 auto;
    width: 180px;
    font-size: var(--isis-fs-sm);
    color: var(--isis-text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.isis-recette-progress__count {
    flex: 0 0 auto;
    min-width: 64px;
    text-align: right;
    font-size: var(--isis-fs-xs);
    color: var(--isis-text-muted);
    font-variant-numeric: tabular-nums;
}

/* Grille des cas : # | Cas | Avis | État. La colonne État s'est élargie : elle porte
   désormais son entonnoir à côté du libellé. */
.isis-grid--recette .isis-grid__head,
.isis-grid--recette .isis-grid__row {
    grid-template-columns: 56px minmax(220px, 1.8fr) minmax(150px, 1fr) 168px;
    min-width: 660px;
}
/* L'en-tête du numéro suit son corps (.isis-recette-ordinal, cadré à droite) : sans
   cela le « # » flotte à gauche au-dessus de nombres alignés à droite. */
.isis-grid--recette .isis-grid__head-cell.isis-grid__col-num {
    justify-content: flex-end;
}
.isis-grid__row.is-selected {
    background: var(--isis-current-mod-soft, var(--isis-accent-soft));
}
.isis-grid__row.is-selected:hover {
    background: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 18%, var(--isis-surface));
}
.isis-recette-ordinal {
    text-align: right;
    font-variant-numeric: tabular-nums;
    color: var(--isis-text-muted);
}

/* Résumé compact des avis : initiales + verdict par recetteur. */
.isis-recette-avis-cell {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem;
    overflow: visible !important;
    white-space: normal !important;
}
.isis-recette-avis-cell__none {
    color: var(--isis-text-muted);
}
.isis-recette-avis {
    display: inline-flex;
    align-items: center;
    gap: 0.2rem;
    padding: 0.05rem 0.35rem;
    border-radius: var(--isis-radius-sm);
    background: var(--isis-surface-alt);
    border: 1px solid var(--isis-border);
    font-size: var(--isis-fs-xs);
    line-height: 1.4;
}
.isis-recette-avis__ini {
    font-weight: 600;
    color: var(--isis-text);
}
.isis-recette-avis__verdict {
    font-weight: 600;
}
.isis-recette-avis__verdict.is-ok { color: var(--isis-success); }
.isis-recette-avis__verdict.is-ko { color: var(--isis-danger); }
.isis-recette-avis__verdict.is-reserve { color: var(--isis-warning); }
.isis-recette-avis__verdict.is-neutral { color: var(--isis-text-muted); }

/* Pastille d'agrégation « +N » : avis masqués au-delà de 3, détail en title/aria-label. */
.isis-recette-avis--more {
    background: var(--isis-surface-alt);
    color: var(--isis-text-muted);
    font-weight: 600;
    cursor: default;
}

/* Panneau latéral — placeholder en attendant RecetteCasePanel. */
.isis-recette-case-placeholder {
    padding: var(--isis-space-md);
}
.isis-recette-case-placeholder__ordinal {
    font-size: var(--isis-fs-xs);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--isis-text-muted);
    margin-bottom: 0.25rem;
}
.isis-recette-case-placeholder__title {
    font-size: var(--isis-fs-lg);
    font-weight: 600;
    color: var(--isis-text);
}

/* Panneau latéral d'un cas — en-tête, avis, discussion, actions (RecetteCasePanel). */
.isis-recette-panel {
    display: flex;
    flex-direction: column;
    gap: var(--isis-space-md);
    padding: var(--isis-space-md);
    height: 100%;
    overflow-y: auto;
    min-height: 0;
}
.isis-recette-panel__head {
    display: flex;
    flex-direction: column;
    gap: var(--isis-space-xs);
}
.isis-recette-panel__ordinal {
    font-size: var(--isis-fs-xs);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--isis-text-muted);
}
.isis-recette-panel__title {
    font-size: var(--isis-fs-lg);
    font-weight: 600;
    color: var(--isis-text);
    margin: 0;
}
.isis-recette-panel__refs {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem;
}
.isis-recette-panel__section {
    display: flex;
    flex-direction: column;
    gap: var(--isis-space-xs);
}
.isis-recette-panel__section-title {
    font-size: var(--isis-fs-xs);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--isis-text-muted);
    font-weight: 600;
}
.isis-recette-panel__expected {
    white-space: pre-line;
    font-size: var(--isis-fs-sm);
    color: var(--isis-text);
    background: var(--isis-surface-alt);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-sm);
    padding: var(--isis-space-sm);
}
.isis-recette-panel__empty {
    font-size: var(--isis-fs-sm);
    color: var(--isis-text-muted);
}
.isis-recette-panel__motif {
    display: block;
    margin-top: 0.25rem;
    white-space: pre-line;
}

/* Liste des avis déposés. */
.isis-recette-avis-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: var(--isis-space-xs);
}
.isis-recette-avis-item {
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-sm);
    background: var(--isis-surface);
    padding: var(--isis-space-sm);
}
.isis-recette-avis-item__head {
    display: flex;
    align-items: center;
    gap: var(--isis-space-sm);
}
.isis-recette-avis-item__name {
    font-size: var(--isis-fs-sm);
    font-weight: 600;
    color: var(--isis-text);
}
.isis-recette-avis-item__date {
    font-size: var(--isis-fs-xs);
    color: var(--isis-text-muted);
    font-variant-numeric: tabular-nums;
}
.isis-recette-avis-item__proof {
    margin-left: auto;
    display: inline-flex;
    align-items: center;
    color: var(--isis-current-mod, var(--isis-accent));
    text-decoration: none;
}
.isis-recette-avis-item__note {
    margin-top: 0.35rem;
    font-size: var(--isis-fs-sm);
    color: var(--isis-text);
    white-space: pre-line;
}

/* Fil de discussion. */
.isis-recette-comments {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: var(--isis-space-xs);
}
.isis-recette-comment {
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-sm);
    background: var(--isis-surface-alt);
    padding: var(--isis-space-sm);
}
.isis-recette-comment__head {
    display: flex;
    align-items: center;
    gap: var(--isis-space-sm);
}
.isis-recette-comment__author {
    font-size: var(--isis-fs-sm);
    font-weight: 600;
    color: var(--isis-text);
}
.isis-recette-comment__date {
    font-size: var(--isis-fs-xs);
    color: var(--isis-text-muted);
    font-variant-numeric: tabular-nums;
}
.isis-recette-comment__remove {
    margin-left: auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: none;
    background: transparent;
    color: var(--isis-text-muted);
    cursor: pointer;
    border-radius: var(--isis-radius-sm);
    padding: 0.1rem;
}
.isis-recette-comment__remove:hover:not(:disabled) {
    color: var(--isis-danger);
}
.isis-recette-comment__body {
    margin-top: 0.35rem;
    font-size: var(--isis-fs-sm);
    color: var(--isis-text);
    white-space: pre-line;
}
.isis-recette-comment-form {
    display: flex;
    flex-direction: column;
    gap: var(--isis-space-xs);
    align-items: flex-end;
}

/* Dialogues d'arbitrage et de gestion des membres. */
.isis-recette-arbitrage__intro,
.isis-recette-members__intro {
    font-size: var(--isis-fs-sm);
    color: var(--isis-text-muted);
    margin: 0 0 var(--isis-space-sm);
}
.isis-recette-arbitrage__hint {
    margin-top: 0.35rem;
    font-size: var(--isis-fs-xs);
    color: var(--isis-danger);
}
.isis-recette-members__add {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--isis-space-sm);
}
.isis-recette-members__add > :first-child {
    flex: 1 1 220px;
    min-width: 200px;
}
.isis-recette-members__list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: var(--isis-space-xs);
}
.isis-recette-members__row {
    display: flex;
    align-items: center;
    gap: var(--isis-space-sm);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-sm);
    padding: var(--isis-space-xs) var(--isis-space-sm);
}
.isis-recette-members__name {
    flex: 1 1 auto;
    font-size: var(--isis-fs-sm);
    color: var(--isis-text);
}
.isis-recette-members__empty {
    font-size: var(--isis-fs-sm);
    color: var(--isis-text-muted);
}

/* ── Membres du kit (fiche équipement gesmat, aide « Ce qu'entraîne le kit ») ──
   Le kit est une entité à part entière (fiche /gesmat/kits/{id}), pas un
   sous-objet de l'équipement : l'appartenance vit dans la ligne d'identité, et
   l'aide liste les co-membres qu'engager cet équipement engage aussi. */
.isis-kit-comembres {
    display: flex;
    flex-wrap: wrap;
    gap: 0.35rem;
    margin-top: 0.35rem;
}
.isis-kit-comembre {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    height: 24px;
    padding: 0 0.55rem;
    border-radius: var(--isis-radius-pill);
    border: 1px solid var(--isis-border);
    background: var(--isis-surface);
    color: var(--isis-text);
    font-size: 0.75rem;
    font-weight: 500;
    text-decoration: none;
    transition: border-color 0.15s ease, color 0.15s ease;
}
.isis-kit-comembre:hover {
    border-color: var(--isis-mod-gesmat);
    color: var(--isis-mod-gesmat);
}
.isis-kit-comembre:focus-visible {
    outline: 2px solid color-mix(in srgb, var(--isis-current-mod) 60%, transparent);
    outline-offset: 2px;
}

/* ── Matériel engagé sur une mobilisation (fiche commande, EF-45→53) ───────
   Section sous chaque mobilisation de l'onglet Mobilisations + dialogue
   d'ajout. Un équipement indisponible reste visible dans le dialogue, grisé,
   AVEC son motif inline — jamais un simple disabled muet. */
.isis-mob-equip {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.4rem;
    margin-top: 0.35rem;
}
.isis-mob-equip__label {
    font-size: 0.72rem;
    font-weight: 600;
    color: var(--isis-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.03em;
    margin-right: 0.15rem;
}
.isis-mob-equip__empty {
    font-size: 0.78rem;
    color: var(--isis-text-muted);
    font-style: italic;
}
.isis-mob-equip__chip {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    height: 24px;
    padding: 0 0.3rem 0 0.55rem;
    border-radius: var(--isis-radius-pill);
    border: 1px solid var(--isis-border);
    background: var(--isis-surface);
    color: var(--isis-text);
    font-size: 0.75rem;
    font-weight: 500;
}
.isis-mob-equip__chip-period {
    color: var(--isis-text-muted);
    font-weight: 400;
}
/* Retrait (.isis-grid__action-btn[--danger]) et ajout (.isis-tache-card__add-btn)
   réutilisent les patterns déjà en place ailleurs sur la même fiche (cible tactile
   28×28 WCAG 2.5.5 + un seul pattern « ajouter un sous-élément »). */

/* ── Dialogue d'ajout de matériel sur une mobilisation ─────────────────── */
.isis-mob-equip-picker__list {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    max-height: 280px;
    overflow-y: auto;
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius);
    padding: 0.35rem;
}
.isis-mob-equip-picker__item {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.4rem;
    width: 100%;
    text-align: left;
    padding: 0.45rem 0.6rem;
    border: 1px solid transparent;
    border-radius: var(--isis-radius-sm);
    background: transparent;
    cursor: pointer;
    font: inherit;
    color: var(--isis-text);
}
.isis-mob-equip-picker__item:hover:not(:disabled) {
    background: var(--isis-current-mod-soft, var(--isis-surface-alt));
}
.isis-mob-equip-picker__item.is-selected {
    border-color: var(--isis-current-mod, var(--isis-mod-gesmat));
    background: var(--isis-current-mod-soft, var(--isis-surface-alt));
}
.isis-mob-equip-picker__item:disabled {
    cursor: not-allowed;
    opacity: 0.72;
}
.isis-mob-equip-picker__code { font-weight: 600; }
.isis-mob-equip-picker__libelle { color: var(--isis-text-muted); font-size: 0.82rem; }
.isis-mob-equip-picker__reason {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    color: var(--isis-danger);
    font-size: 0.75rem;
    margin-left: auto;
}
.isis-mob-equip-picker__kit-tag {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    color: var(--isis-mod-gesmat);
    font-size: 0.75rem;
    margin-left: auto;
}
.isis-mob-equip-picker__empty {
    padding: 0.75rem;
    text-align: center;
    color: var(--isis-text-muted);
    font-size: 0.85rem;
}
/* Séparateur disponibles/indisponibles — on réordonne le scan, on ne masque rien
   (le motif de blocage reste affiché en clair sur chaque ligne). */
.isis-mob-equip-picker__separator {
    padding: 0.3rem 0.6rem 0.1rem;
    font-size: 0.68rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--isis-text-muted);
}

/* ── Synthèse de facturation d'une commande (CommandeBillingSummarySection) ──
   Barre empilée « où va le vendu » : facturé → demandé → à demander → non couvert.
   Les segments se cumulent sur le montant de la commande ; le hachuré à droite
   est la part qu'aucune échéance ne couvre — une absence, pas une valeur, d'où
   la trame et non l'aplat.

   Débordement assumé : la somme des segments vaut max(planifié, vendu). Quand
   l'échéancier excède le vendu, les segments (flex-shrink: 0) sont tronqués par
   l'overflow de la piste plutôt que compressés — une compression proportionnelle
   redistribuerait les parts en silence et ferait passer l'excédent pour normal.
   La barre saturée + la bannière « échéancier excédentaire » disent la même chose.
*/
.isis-billing-summary {
    display: flex;
    flex-direction: column;
    gap: var(--isis-space-md);
    padding: var(--isis-space-md);
    /* La section « Échéancier » suit immédiatement dans le même panneau : sans ce filet,
       la carte la touche (écart mesuré : 0 px). */
    margin-bottom: var(--isis-space-lg);
    background-color: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius);
    box-shadow: var(--isis-elevation-1);
}
.isis-billing-summary__head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--isis-space-md);
    flex-wrap: wrap;
}
.isis-billing-summary__title {
    margin: 0;
    font-size: var(--isis-fs-lg);
    font-weight: 600;
    color: var(--isis-text);
}
.isis-billing-summary__total-label {
    color: var(--isis-text-muted);
    font-size: var(--isis-fs-sm);
    margin-right: var(--isis-space-xs);
}
.isis-billing-summary__total-value {
    font-family: var(--isis-font-mono, 'Geist Mono', ui-monospace, monospace);
    font-variant-numeric: tabular-nums;
    font-size: var(--isis-fs-md);
    font-weight: 600;
    color: var(--isis-text);
}

/* La barre a son propre intitulé : elle dit le plan (l'échéancier), là où les KPI de l'onglet
   disent le réel (les factures émises). Le groupe existe pour coller la légende-titre à sa piste,
   sans le gap `md` que .isis-billing-summary pose entre ses blocs. */
.isis-billing-summary__bar-block {
    display: flex;
    flex-direction: column;
    gap: var(--isis-space-xs);
}

/* Filet du passage « combien » → « comment » : au-dessus vivent les chiffres dominants (reste à
   facturer, puis anomalies), en dessous le détail qui les justifie. Porté par le détail et non
   par le reste, qui suit désormais l'en-tête directement. */
.isis-billing-summary__bar-block,
.isis-billing-summary__no-plan {
    padding-top: var(--isis-space-md);
    border-top: 1px solid var(--isis-border);
}

/* Sans échéance, pas de barre : une piste 100 % hachurée ne dirait aucune proportion. */
.isis-billing-summary__no-plan {
    margin: 0;
    font-size: var(--isis-fs-sm);
    color: var(--isis-text-muted);
}
.isis-billing-summary__factures {
    padding-top: var(--isis-space-md);
    border-top: 1px solid var(--isis-border);
}
.isis-billing-summary__factures-title {
    margin: 0 0 var(--isis-space-xs);
    font-size: var(--isis-fs-sm);
    font-weight: 600;
    color: var(--isis-text);
}
.isis-billing-summary__factures-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: var(--isis-space-xs);
}
.isis-billing-summary__factures-item {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--isis-space-sm);
    font-size: var(--isis-fs-sm);
    color: var(--isis-text-muted);
}
.isis-billing-summary__bar-caption {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: var(--isis-space-xs);
    margin: 0;
    font-size: var(--isis-fs-sm);
}
.isis-billing-summary__bar-caption-label {
    font-weight: 600;
    color: var(--isis-text);
}
.isis-billing-summary__bar-caption-hint {
    color: var(--isis-text-muted);
}
/* Tiret décoratif : porté par le CSS pour ne pas polluer la restitution des lecteurs d'écran. */
.isis-billing-summary__bar-caption-hint::before {
    content: "—";
    margin-right: var(--isis-space-xs);
}

/* Piste : décorative (role="img" + aria-label côté composant), le texte vit dans la légende. */
.isis-billing-bar {
    display: flex;
    width: 100%;
    height: 12px;
    border-radius: 999px;
    overflow: hidden;
    background-color: var(--isis-surface-alt);
}
.isis-billing-bar__seg {
    flex-grow: 0;
    flex-shrink: 0;   /* cf. « débordement assumé » ci-dessus */
    min-width: 0;
    height: 100%;
}
.isis-billing-bar__seg--facture      { background-color: var(--isis-success); }
/* Brouillon de facture : même teinte que « facturé », pâlie — la couleur dit la destination,
   l'intensité dit qu'on n'y est pas encore. Neutre par construction : jamais une alerte. */
.isis-billing-bar__seg--encours      { background-color: color-mix(in srgb, var(--isis-success) 35%, transparent); }
.isis-billing-bar__seg--demande      { background-color: var(--isis-mod-gesproj); }
.isis-billing-bar__seg--ademander    { background-color: color-mix(in srgb, var(--isis-mod-gesproj) 35%, transparent); }
.isis-billing-bar__seg--horsecheance {
    background-color: color-mix(in srgb, var(--isis-accent) 12%, transparent);
    background-image: repeating-linear-gradient(
        45deg,
        var(--isis-accent) 0,
        var(--isis-accent) 2px,
        transparent 2px,
        transparent 6px
    );
}

.isis-billing-summary__legend {
    display: flex;
    flex-wrap: wrap;
    gap: var(--isis-space-sm) var(--isis-space-lg);
    margin: 0;
    padding: 0;
    list-style: none;
}
.isis-billing-summary__legend-item {
    display: flex;
    align-items: center;
    gap: var(--isis-space-xs);
    font-size: var(--isis-fs-sm);
    color: var(--isis-text-muted);
    min-width: 0;
}
.isis-billing-summary__legend-dot {
    flex: 0 0 auto;
    width: 10px;
    height: 10px;
    border-radius: 999px;
}
.isis-billing-summary__legend-dot--facture      { background-color: var(--isis-success); }
.isis-billing-summary__legend-dot--encours      { background-color: color-mix(in srgb, var(--isis-success) 35%, transparent); }
.isis-billing-summary__legend-dot--demande      { background-color: var(--isis-mod-gesproj); }
.isis-billing-summary__legend-dot--ademander    { background-color: color-mix(in srgb, var(--isis-mod-gesproj) 35%, transparent); }
.isis-billing-summary__legend-dot--horsecheance {
    border-radius: 2px;   /* carré : la trame « non couvert » ne se lit pas sur un disque de 10px */
    background-color: color-mix(in srgb, var(--isis-accent) 12%, transparent);
    background-image: repeating-linear-gradient(
        45deg,
        var(--isis-accent) 0,
        var(--isis-accent) 1px,
        transparent 1px,
        transparent 3px
    );
}
.isis-billing-summary__legend-value {
    font-family: var(--isis-font-mono, 'Geist Mono', ui-monospace, monospace);
    font-variant-numeric: tabular-nums;
    color: var(--isis-text);
    font-weight: 500;
}

/* Le chiffre dominant du bloc — juste sous l'en-tête, avant le détail qui le justifie. */
.isis-billing-summary__reste {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--isis-space-md);
    flex-wrap: wrap;
}
.isis-billing-summary__reste-label {
    color: var(--isis-text-muted);
    font-size: var(--isis-fs-md);
}
.isis-billing-summary__reste-value {
    font-family: var(--isis-font-mono, 'Geist Mono', ui-monospace, monospace);
    font-variant-numeric: tabular-nums;
    font-size: var(--isis-fs-xl);
    font-weight: 600;
    color: var(--isis-text);
}

.isis-billing-summary__anomalies {
    display: flex;
    flex-direction: column;
    gap: var(--isis-space-sm);
}

@media (max-width: 640px) {
    .isis-billing-summary__legend {
        flex-direction: column;
        gap: var(--isis-space-sm);
    }
    .isis-billing-summary__reste-value { font-size: var(--isis-fs-lg); }
}

/* Lien d'action discret dans un sous-label de grille (ex : lier des livraisons à une
   échéance). Volontairement plat : ce n'est pas une action primaire. La taille de police
   est héritée du sous-label pour rester alignée sur le texte qu'il prolonge. */
.isis-grid__inline-link {
    background: none;
    border: none;
    padding: 0 0 0 var(--isis-space-sm);
    font: inherit;
    color: var(--isis-accent);
    cursor: pointer;
    text-decoration: underline;
    text-underline-offset: 2px;
}
.isis-grid__inline-link:hover { color: var(--isis-accent-strong); }
.isis-grid__inline-link:focus-visible {
    outline: 2px solid var(--isis-accent);
    outline-offset: 2px;
    border-radius: var(--isis-radius-sm);
}

/* Grille du référencement des sous-traitants (0593). Sans gabarit de colonnes dédié,
   la grille hérite d'un modèle générique et les en-têtes se chevauchent.
   Le gabarit a d'abord été écrit pour une version à 5 colonnes (Périmètre / Validité /
   Actions) abandonnée avec le passage au grain article : la colonne « Prestations » a
   remplacé « Périmètre », et les décisions vivent dans le panneau, pas en bout de ligne.
   Les 4 colonnes ci-dessous sont celles réellement rendues par la page. */
.isis-grid--referencement .isis-grid__head,
.isis-grid--referencement .isis-grid__row {
    display: grid;
    /* minmax(0, …) et non minmax(220px, …) : une piste dont le minimum est la largeur du
       contenu refuse de se comprimer, et la grille déborde son conteneur dès que le
       panneau de détail est ouvert — la colonne Échéance passait sous le panneau. */
    grid-template-columns:
        minmax(0, 1.25fr)        /* Prestataire (raison sociale + code) */
        minmax(0, 1.05fr)        /* Dossier — « N pièce(s) à fournir » est le libellé long */
        minmax(0, 1.5fr)         /* Prestations (compteur + jusqu'à 3 pastilles) */
        minmax(0, 0.75fr);       /* Échéance */
    align-items: center;
    column-gap: var(--isis-space-md);
    /* Surcharge le min-width: 1000px de .isis-grid__row : en master-detail le master ne
       fait que ~890px, la colonne Échéance passait sous le panneau (même correctif que
       .isis-grid--m2c-postes, contraint par un dialog de 760px). */
    min-width: 0;
}
/* Hors « Bloqués », la colonne Dossier vaudrait « Complet » sur chaque ligne : la page
   ne la rend pas, le gabarit doit suivre sous peine de colonnes décalées. */
.isis-grid--referencement-sans-dossier .isis-grid__head,
.isis-grid--referencement-sans-dossier .isis-grid__row {
    grid-template-columns:
        minmax(0, 1.4fr)         /* Prestataire */
        minmax(0, 1.6fr)         /* Prestations */
        minmax(0, 0.8fr);        /* Échéance */
}
/* ── Évaluation d'un sous-traitant (dialogue, lot 2) ──────────────────────
   L'échelle est rendue en boutons radio étiquetés plutôt qu'en étoiles ou en curseur :
   « 2 — À améliorer » se lit sans apprentissage, et se relit douze mois plus tard en revue. */
.isis-eval-echelle {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
    gap: var(--isis-space-xs);
}
/* Réglette compacte : au-delà de 5 niveaux, une case étiquetée par note donne trois
   rangées de boîtes à moitié vides. Une seule rangée, le chiffre centré, les deux pôles
   nommés en dessous — la progression se lit d'un trait. */
.isis-eval-echelle--compacte {
    grid-template-columns: repeat(auto-fit, minmax(44px, 1fr));
}
.isis-eval-echelle--compacte .isis-eval-note {
    justify-content: center;
    padding: 0.45rem 0.2rem;
}
/* L'input reste focusable et annonçable : c'est .isis-eval-note:focus-within, déjà défini,
   qui porte le halo. Le masquer visuellement sans le retirer du flux d'accessibilité. */
.isis-eval-echelle--compacte .isis-eval-note input {
    position: absolute;
    width: 1px; height: 1px;
    margin: -1px; padding: 0;
    overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%);
    white-space: nowrap; border: 0;
}
.isis-eval-echelle__poles {
    display: flex;
    justify-content: space-between;
    margin-top: var(--isis-space-xs);
    font-size: 0.78rem;
    color: var(--isis-text-muted);
}

.isis-eval-note {
    display: flex;
    align-items: baseline;
    gap: 0.4rem;
    padding: 0.45rem 0.6rem;
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-sm);
    background: var(--isis-surface);
    cursor: pointer;
    font-size: 0.82rem;
    box-sizing: border-box;
    /* Seules la couleur et le fond transitent : animer une propriété de layout
       ferait sautiller la grille des quatre niveaux à chaque choix. */
    transition: border-color 160ms cubic-bezier(0.22, 1, 0.36, 1),
                background-color 160ms cubic-bezier(0.22, 1, 0.36, 1);
}
.isis-eval-note:hover { border-color: var(--isis-current-mod, var(--isis-accent)); }
/* focus-within et non :focus : l'input natif est un rond de 14 px, mais ce que
   l'utilisateur vise et voit est la cellule entière. Le halo doit être là. */
.isis-eval-note:focus-within {
    outline: 2px solid color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 65%, transparent);
    outline-offset: 2px;
    border-color: var(--isis-current-mod, var(--isis-accent));
}
.isis-eval-note.is-active {
    border-color: var(--isis-current-mod, var(--isis-accent));
    background: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 8%, var(--isis-surface));
    font-weight: 600;
}
.isis-eval-note input { margin: 0; }
.isis-eval-note strong { font-variant-numeric: tabular-nums; }
.isis-eval-note span { color: var(--isis-text-muted); }
.isis-eval-note.is-active span { color: var(--isis-text); }

/* Au doigt, une cible de 28 px se rate. On élargit sur pointeur grossier
   uniquement : la densité de l'ERP reste intacte à la souris. */
@media (pointer: coarse) {
    .isis-eval-note,
    .isis-eval-prestation { min-height: 44px; }
}
@media (prefers-reduced-motion: reduce) {
    .isis-eval-note,
    .isis-eval-prestation,
    .isis-revue-cell { transition: none; }
}

.isis-eval-prestations {
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
    /* Un engagement à quinze lignes ne doit pas étirer le dialogue hors de l'écran. */
    max-height: 220px;
    overflow-y: auto;
}
.isis-eval-prestation {
    display: flex;
    align-items: center;
    gap: 0.45rem;
    padding: 0.15rem 0.25rem;
    border-radius: var(--isis-radius-sm);
    font-size: 0.85rem;
    cursor: pointer;
    transition: background-color 160ms cubic-bezier(0.22, 1, 0.36, 1);
}
.isis-eval-prestation:hover { background: var(--isis-surface-alt); }
.isis-eval-prestation:focus-within {
    outline: 2px solid color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 65%, transparent);
    outline-offset: 1px;
}

/* ── Historique d'évaluation dans le panneau de référencement (lot 2) ─────
   Une évaluation par ligne, ses notes en pastilles. Les notes basses (1-2) prennent
   l'accent chaud : c'est ce qui doit sauter aux yeux de celui qui va décider, sans
   qu'aucune moyenne ne vienne les diluer. */
.isis-eval-histo {
    list-style: none;
    margin: 0.6rem 0 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}
.isis-eval-histo__item {
    border-top: 1px solid var(--isis-border);
    padding-top: 0.55rem;
}
.isis-eval-histo__item:first-child { border-top: none; padding-top: 0; }
.isis-eval-histo__head {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    flex-wrap: wrap;
}
.isis-eval-histo__date {
    font-size: 0.8rem;
    color: var(--isis-text-muted);
    font-variant-numeric: tabular-nums;
    margin-right: 0.2rem;
}
.isis-eval-histo__note {
    display: inline-flex;
    align-items: baseline;
    gap: 0.25rem;
    padding: 0.1rem 0.4rem;
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-sm);
    font-size: 0.78rem;
    color: var(--isis-text-muted);
    background: var(--isis-surface-alt);
}
.isis-eval-histo__note strong {
    font-variant-numeric: tabular-nums;
    color: var(--isis-text);
}
.isis-eval-histo__note.is-basse {
    border-color: color-mix(in srgb, var(--isis-accent) 45%, transparent);
    background: color-mix(in srgb, var(--isis-accent) 8%, transparent);
}
.isis-eval-histo__note.is-basse strong { color: var(--isis-accent); }
.isis-eval-histo__comment {
    margin-top: 0.3rem;
    font-size: 0.82rem;
    color: var(--isis-text-muted);
    overflow-wrap: anywhere;
}

/* ── Revue périodique des sous-traitants (lot 2) ──────────────────────────
   La répartition remplace la moyenne : quatre cases, une par niveau, avec le nombre de
   notes. On voit d'un coup si un prestataire est régulier ou clivant — ce qu'une moyenne
   écraserait précisément. */
/* État d'une campagne de revue : période + avancement + bouton de clôture. Portait la classe
   .isis-filter-bar sans contenir le moindre filtre — la classe promettait une barre de
   recherche et de facettes qui n'a jamais existé sur cet écran (2026-09-05). Mêmes métriques
   que la barre de filtres, dont il reprend la place visuelle. */
.isis-revue-etat {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.6rem;
    flex-wrap: wrap;
    margin-bottom: 0.75rem;
}

.isis-grid--revue .isis-grid__head,
.isis-grid--revue .isis-grid__row {
    display: grid;
    /* Élargi le 2026-09-05 : la grille gagne une case de sélection (décision en lot) et une
       colonne « millésime précédent ». Cinq pistes pour cinq cellules d'en-tête — le
       configurateur de colonnes exige l'égalité stricte. */
    grid-template-columns:
        34px                     /* Sélection */
        minmax(0, 1.5fr)         /* Prestataire */
        minmax(0, 1.2fr)         /* Évaluations */
        minmax(0, 1fr)           /* Décision */
        minmax(0, 0.9fr);        /* Millésime précédent */
    align-items: center;
    column-gap: var(--isis-space-md);
    min-width: 0;
}
.isis-grid--revue [role="cell"],
.isis-grid--revue [role="columnheader"] { min-width: 0; }

.isis-grid__col-evaluations {
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
    flex-wrap: wrap;
}
.isis-revue-critere {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--isis-space-sm);
    padding: 0.3rem 0;
    font-size: 0.83rem;
}
.isis-revue-critere__label { color: var(--isis-text); }
.isis-revue-repartition { display: inline-flex; gap: 0.2rem; }
.isis-revue-cell {
    display: inline-flex;
    flex-direction: column;
    align-items: center;
    min-width: 30px;
    padding: 0.15rem 0.3rem;
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-sm);
    background: var(--isis-surface-alt);
    color: var(--isis-text-muted);
    font-size: 0.7rem;
    line-height: 1.2;
    box-sizing: border-box;
    transition: border-color 160ms cubic-bezier(0.22, 1, 0.36, 1),
                background-color 160ms cubic-bezier(0.22, 1, 0.36, 1);
}
.isis-revue-cell.has-value {
    border-color: var(--isis-current-mod);
    background: color-mix(in srgb, var(--isis-current-mod) 10%, var(--isis-surface));
    color: var(--isis-text);
    font-weight: 600;
}
.isis-revue-cell strong { font-variant-numeric: tabular-nums; }

/* Les trois décisions sont de même niveau et de même poids : empilées pleine largeur,
   elles se lisent comme un choix, pas comme une action principale et deux accessoires. */
.isis-revue-decisions {
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
    margin-top: 0.85rem;
    padding-top: 0.85rem;
    border-top: 1px solid var(--isis-border);
}
.isis-revue-decisions > * { width: 100%; }

.isis-revue-signalement {
    padding: 0.5rem 0;
    border-bottom: 1px solid var(--isis-border);
    /* Un commentaire d'évaluation est du texte libre : il peut contenir une
       référence sans espace plus large que le panneau. */
    overflow-wrap: anywhere;
}
.isis-revue-signalement:last-child { border-bottom: none; }

/* Pièces exigées au dossier (/gesqhse/parametres/referencement). */
/* Grille des critères d'évaluation. La colonne « Notes posées » est étroite mais présente :
   c'est elle qui explique pourquoi certains critères n'ont pas de bouton de suppression. */
.isis-grid--criteres .isis-grid__head,
.isis-grid--criteres .isis-grid__row {
    display: grid;
    grid-template-columns:
        minmax(0, 1.8fr)         /* Critère */
        minmax(0, 1fr)           /* Code */
        minmax(0, 0.9fr)         /* État */
        minmax(0, 0.6fr)         /* Notes posées */
        110px;                   /* Actions */
    align-items: center;
    column-gap: var(--isis-space-md);
    min-width: 0;
}
.isis-grid--criteres [role="cell"],
.isis-grid--criteres [role="columnheader"] { min-width: 0; }

.isis-grid--exigences .isis-grid__head,
.isis-grid--exigences .isis-grid__row {
    display: grid;
    grid-template-columns:
        minmax(0, 1.6fr)         /* Pièce (libellé affiché) */
        minmax(0, 1.2fr)         /* Type de document (kind GED) */
        minmax(0, 0.8fr)         /* Caractère */
        110px;                   /* Actions */
    align-items: center;
    column-gap: var(--isis-space-md);
    min-width: 0;
}

/* Corollaire du minmax(0, …) : sans min-width nulle, le contenu d'une cellule
   (pastilles, raison sociale longue) redevient le plancher de sa piste. */
.isis-grid--referencement [role="cell"],
.isis-grid--referencement [role="columnheader"] { min-width: 0; }
.isis-grid--referencement .isis-chip-group { flex-wrap: wrap; }
/* ─── Console — Sitemap ────────────────────────────────────────────────────────
   Rapprochement des trois registres d'écrans (route-table, navigation, catalogue
   de droits). La page vit de l'ECART entre eux : les compteurs sont donc des
   filtres cliquables, pas de la décoration. */

.isis-sitemap-toolbar {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem 0.75rem;
    align-items: center;
    margin-bottom: 0.75rem;
}

.isis-sitemap-stats {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
    gap: 0.75rem;
}

.isis-sitemap-stat {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    padding: 0.7rem 0.85rem;
    text-align: left;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-sm);
    cursor: pointer;
    font: inherit;
    color: inherit;
    transition: border-color 120ms ease, background-color 120ms ease;
}

.isis-sitemap-stat:hover { border-color: var(--isis-accent); }

.isis-sitemap-stat.is-active {
    border-color: var(--isis-accent);
    background: color-mix(in oklch, var(--isis-accent) 7%, var(--isis-surface));
}

.isis-sitemap-stat:focus-visible {
    outline: 2px solid var(--isis-accent);
    outline-offset: 2px;
}

.isis-sitemap-stat__value {
    font-family: var(--isis-font-mono, "Geist Mono", monospace);
    font-variant-numeric: tabular-nums;
    font-size: var(--isis-fs-xl, 1.35rem);
    line-height: 1.1;
}

.isis-sitemap-stat__label {
    font-size: var(--isis-fs-xs, 0.75rem);
    color: var(--isis-text-muted);
}

/* Anomalie bloquante (lien mort, collision) : l'accent chaud sert d'ancre
   narrative, jamais de surface — cf. DESIGN.md §2. */
.isis-sitemap-stat.is-warm .isis-sitemap-stat__value {
    color: var(--isis-accent-strong);
}

.isis-sitemap-cell {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.isis-sitemap-cell__title {
    overflow-wrap: anywhere;
}

.isis-sitemap-cell__meta {
    font-size: var(--isis-fs-xs, 0.75rem);
    color: var(--isis-text-muted);
}

/* Présence dans chacun des trois registres, en un coup d'oeil. Le libellé reste
   lisible seul (pas seulement une pastille de couleur) — l'information ne doit
   pas dépendre de la seule teinte. */
.isis-sitemap-flags {
    display: flex;
    flex-wrap: wrap;
    gap: 0.3rem;
}

.isis-sitemap-flag {
    padding: 0.1rem 0.4rem;
    font-size: var(--isis-fs-xs, 0.75rem);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-sm);
    color: var(--isis-text-muted);
    opacity: 0.7;
    text-decoration: line-through;
}

.isis-sitemap-flag.is-on {
    opacity: 1;
    text-decoration: none;
    color: var(--isis-text);
    border-color: color-mix(in oklch, var(--isis-accent) 40%, var(--isis-border));
    background: color-mix(in oklch, var(--isis-accent) 8%, var(--isis-surface));
}

/* Aucune action au clic sur ces lignes : on neutralise l'affordance heritee de
   .isis-grid__row (cursor: pointer), qui promettrait une navigation inexistante. */
.isis-grid--platform-sitemap-anomalies .isis-grid__row,
.isis-grid--platform-sitemap-tree .isis-grid__row {
    cursor: default;
}

.isis-grid--platform-sitemap-anomalies .isis-grid__head,
.isis-grid--platform-sitemap-anomalies .isis-grid__row {
    grid-template-columns: 128px minmax(220px, 1.2fr) 110px minmax(240px, 1.6fr);
    min-width: 900px;
}

.isis-grid--platform-sitemap-tree .isis-grid__head,
.isis-grid--platform-sitemap-tree .isis-grid__row {
    grid-template-columns: minmax(200px, 1.1fr) minmax(220px, 1.3fr) 110px 190px;
    min-width: 900px;
}

/* Sitemap — vue couverture (treemap). La legende porte le sens des couleurs :
   sans elle, un pave chaud ne veut rien dire. */
.isis-sitemap-legend {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem 1.1rem;
    margin-bottom: 0.9rem;
    font-size: var(--isis-fs-xs, 0.75rem);
    color: var(--isis-text-muted);
}

.isis-sitemap-legend__item {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
}

.isis-sitemap-legend__swatch {
    width: 12px;
    height: 12px;
    border-radius: 3px;
    flex-shrink: 0;
}

.isis-sitemap-treemap-skeleton {
    height: 560px;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--isis-text-muted);
    background: var(--isis-surface-alt);
    border-radius: var(--isis-radius-sm);
}

/* Equivalent textuel du treemap : meme donnee, atteignable au clavier et au
   lecteur d'ecran, et imprimable. */
.isis-sitemap-treemap-fallback {
    margin-top: 0.9rem;
    font-size: var(--isis-fs-sm, 0.85rem);
}

.isis-sitemap-treemap-fallback summary {
    cursor: pointer;
    color: var(--isis-accent);
}

.isis-sitemap-treemap-fallback summary:focus-visible {
    outline: 2px solid var(--isis-accent);
    outline-offset: 2px;
    border-radius: var(--isis-radius-sm);
}

.isis-sitemap-treemap-fallback ul {
    margin: 0.6rem 0 0;
    padding-left: 1.1rem;
    color: var(--isis-text-muted);
}

.isis-sitemap-treemap-fallback li { margin-bottom: 0.25rem; }

.isis-sitemap-legend__note {
    flex-basis: 100%;
    max-width: 78ch;
    line-height: 1.45;
}

/* ─── Console — Cartographie des ecrans ───────────────────────────────────────
   Lecture d'abord : ce sont les libelles de menu qui portent l'information, la
   route ne vient qu'en second. Colonnes fluides pour tenir les 16 modules sans
   imposer une largeur de viewport. */

.isis-carto-toolbar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem 0.9rem;
    margin-bottom: 1rem;
}

.isis-carto-toolbar label {
    font-size: var(--isis-fs-sm, 0.85rem);
    color: var(--isis-text-muted);
}

.isis-carto-toolbar__count {
    font-size: var(--isis-fs-xs, 0.75rem);
    color: var(--isis-text-muted);
    font-variant-numeric: tabular-nums;
}

.isis-carto {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
    gap: 1.25rem;
    align-items: start;
}

.isis-carto__module {
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-sm);
    padding: 0.85rem 0.95rem;
    background: var(--isis-surface);
}

.isis-carto__module-title {
    display: flex;
    align-items: center;
    gap: 0.45rem;
    margin: 0 0 0.6rem;
    font-size: var(--isis-fs-sm, 0.85rem);
    font-weight: 600;
}

.isis-carto__module-count {
    margin-left: auto;
    font-variant-numeric: tabular-nums;
    font-size: var(--isis-fs-xs, 0.75rem);
    color: var(--isis-text-muted);
}

.isis-carto__group + .isis-carto__group { margin-top: 0.7rem; }

.isis-carto__group-title {
    margin: 0 0 0.3rem;
    font-size: var(--isis-fs-xs, 0.75rem);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--isis-text-muted);
}

.isis-carto__list {
    list-style: none;
    margin: 0;
    padding: 0;
}

.isis-carto__item {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.35rem;
    padding: 0.25rem 0;
    border-bottom: 1px solid var(--isis-border-soft, #f1f2f5);
}

.isis-carto__item:last-child { border-bottom: none; }

.isis-carto__item-label {
    font-size: var(--isis-fs-sm, 0.85rem);
    overflow-wrap: anywhere;
}

.isis-carto__item-route {
    font-family: var(--isis-font-mono, "Geist Mono", monospace);
    font-size: var(--isis-fs-xs, 0.72rem);
    color: var(--isis-text-muted);
    overflow-wrap: anywhere;
}

/* Un ecran desactive reste lisible : on l'attenue, on ne le barre pas — le badge
   porte deja l'etat en toutes lettres. */
.isis-carto__item.is-off .isis-carto__item-label { color: var(--isis-text-muted); }

.isis-carto__item.is-broken .isis-carto__item-route {
    color: var(--isis-accent-strong);
}

/* ─── Console — Sitemap dessine (schema d'arborescence) ───────────────────────
   Boites et connecteurs, un arbre par module. La couleur de la racine et des
   groupes reprend l'identite chromatique du module (--isis-mod-*). */

.isis-schema {
    margin: 0 0 1.5rem;
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-sm);
    background: var(--isis-surface);
    overflow: hidden;
}

.isis-schema__caption {
    display: flex;
    align-items: center;
    gap: 0.45rem;
    padding: 0.6rem 0.9rem;
    border-bottom: 1px solid var(--isis-border);
    font-size: var(--isis-fs-sm, 0.85rem);
    font-weight: 600;
    background: var(--isis-surface-alt);
}

.isis-schema__caption-count {
    margin-left: auto;
    font-weight: 400;
    font-variant-numeric: tabular-nums;
    font-size: var(--isis-fs-xs, 0.75rem);
    color: var(--isis-text-muted);
}

/* Une figure large defile DANS son conteneur ; la page ne deborde jamais. */
.isis-schema__scroll {
    overflow-x: auto;
    padding: 0.9rem;
}

.isis-schema__svg {
    display: block;
    font-family: var(--isis-font, Geist, ui-sans-serif, system-ui, sans-serif);
}

.isis-schema__edge {
    fill: none;
    stroke: var(--isis-border-strong, #c9ccd4);
    stroke-width: 1.5;
}

.isis-schema__node rect {
    fill: var(--isis-surface);
    stroke: var(--isis-current-mod, var(--isis-accent));
    stroke-width: 1.5;
}

.isis-schema__node text {
    font-size: 12px;
    fill: var(--isis-text);
}

.isis-schema__node.is-root rect {
    fill: color-mix(in oklch, var(--isis-current-mod, var(--isis-accent)) 12%, var(--isis-surface));
    stroke-width: 2;
}

.isis-schema__node.is-root text { font-weight: 600; font-size: 13px; }

.isis-schema__node.is-group rect {
    fill: color-mix(in oklch, var(--isis-current-mod, var(--isis-accent)) 6%, var(--isis-surface));
}

.isis-schema__node.is-group text {
    font-weight: 600;
    text-transform: uppercase;
    font-size: 10.5px;
    letter-spacing: 0.04em;
    fill: var(--isis-text-muted);
}

/* Ecran desactive chez le client : trait interrompu, pas une couleur seule. */
.isis-schema__node.is-off rect {
    stroke-dasharray: 4 3;
    fill: var(--isis-surface-alt);
}

.isis-schema__node.is-off text { fill: var(--isis-text-muted); }

/* Aucun composant ne sert cette route : anomalie, pas un etat de gestion. */
.isis-schema__node.is-broken rect {
    stroke: var(--isis-accent-strong);
}

/* ── 2026-07-24 — Marqueur PREVISIONNEL sur le calendrier « Ma planification » (SIRH) ──
   Barre issue d'un scenario gespla prevu (pas encore ferme/realise) : hachure + trait
   pointille, purement visuel (ce calendrier n'a aucune saisie de temps). */
.isis-planif__bar.is-previsionnel {
    background-image: repeating-linear-gradient(135deg,
        rgba(255,255,255,0.35) 0, rgba(255,255,255,0.35) 4px,
        transparent 4px, transparent 8px);
    opacity: 0.85;
    border: 1px dashed rgba(0,0,0,0.35);
}

/* ── 2026-07-25 — Prévisionnel V3 (gespla) : grille maître d'offres dépliable sur leurs
   mobilisations enfants. Remplace le tableur V2 (RadzenSpreadsheet, supprimé). Chevron
   d'expansion + .is-expanded réutilisent .isis-grid__chevron-btn (générique) ; le panneau
   déplié suit le pattern .isis-tache-card__detail (CommandeDetail.razor) — même principe
   (bloc pleine largeur sous la ligne, hors grille de colonnes de la ligne). */
.isis-grid--previsionnel .isis-grid__head,
.isis-grid--previsionnel .isis-grid__row {
    display: grid;
    /* Colonne "Statut" retirée le 2026-07-26 (audit ui-ux) : elle affichait une constante
       ("Envoyé") — la grille ne liste déjà que des offres SENT. Largeur reportée sur Intitulé. */
    grid-template-columns: 34px 120px minmax(140px, 1fr) minmax(220px, 1.8fr) 150px 70px 96px;
    align-items: center;
    column-gap: 0.5rem;
}
.isis-grid--previsionnel .isis-grid__row.is-expanded {
    background: color-mix(in srgb, var(--isis-mod-gespla) 6%, var(--isis-surface));
}
.isis-grid--previsionnel .isis-grid__col-amount {
    text-align: right;
    font-variant-numeric: tabular-nums;
}
.isis-grid--previsionnel .isis-grid__col-mob {
    text-align: center;
    font-variant-numeric: tabular-nums;
}
/* Les en-têtes des deux colonnes chiffrées suivent leur colonne : le bouton de tri est un
   inline-flex, sans quoi « Montant HT » pendrait à gauche au-dessus de montants alignés à
   droite (2026-09-05, revue d'harmonisation gespla). */
.isis-grid--previsionnel .isis-grid__head-cell.isis-grid__col-amount { justify-content: flex-end; }
.isis-grid--previsionnel .isis-grid__head-cell.isis-grid__col-mob { justify-content: center; }
.isis-grid--previsionnel .isis-grid__row {
    cursor: pointer;
}

.isis-grid__subrow {
    padding: 0.65rem 0.9rem 0.9rem 2.6rem;
    /* Générique (pas .isis-grid--previsionnel) : --isis-current-mod suit le module de la
       page courante (posé sur .isis-shell__content.mod-x) — corrigé du hardcode
       --isis-mod-gespla d'origine, qui teintait à tort en gespla toute autre page
       réutilisant cette classe (constaté sur gesqhse/documentaire). */
    background: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 4%, var(--isis-surface));
    border-bottom: 1px solid var(--isis-border);
}

/* Motif de révision d'un indice — texte libre déplié sous la ligne, jamais tronqué
   (contrairement à la cellule de la ligne, contrainte en hauteur par le gabarit grille). */
.isis-grid__subrow-motif {
    margin-bottom: 0.6rem;
}
.isis-grid__subrow-motif p {
    margin: 0.2rem 0 0;
    color: var(--isis-text);
    font-size: 0.85rem;
    line-height: 1.45;
}

/* Barre de gestes contextuels d'une ligne dépliée (ex. Abandonner / Mettre en application /
   Enregistrer le verdict — onglet Indices de la fiche document gesqhse). Générique, jamais
   .isis-rich-toolbar__actions : cette dernière exige un vrai .isis-rich-toolbar parent pour
   l'harmonisation Radzen 32px (cf. règle ci-dessous, étendue à cette classe). */
.isis-grid__subrow-actions {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin-bottom: 0.6rem;
}
.isis-grid__subrow-actions .rz-datepicker {
    width: 160px;
}

/* Case « Régulariser une application antérieure » (audit sécurité 2026-07-29, onglet Indices —
   antidatation) : débloque le Min du RadzenDatePicker voisin pour le seul cas métier réel
   (régularisation d'un document appliqué avant l'informatisation) — geste explicite, jamais le
   défaut. */
.isis-grid__subrow-checkbox {
    display: inline-flex;
    align-items: center;
    gap: var(--isis-space-xs);
    font-size: var(--isis-fs-sm);
    color: var(--isis-text-muted);
    cursor: pointer;
}

.isis-mob-subgrid__empty {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    padding: 0.3rem 0.2rem;
    color: var(--isis-text-muted);
    font-size: 0.85rem;
}

/* Bouton « Ajouter une mobilisation » sous la liste des mobilisations d'une offre déjà peuplée. */
.isis-mob-subgrid__add {
    padding: 0.5rem 0.2rem 0.2rem;
}

/* Bascule Tableau / Chronologie en tête de la zone dépliée d'une offre. */
.isis-mob-subgrid__toolbar {
    display: flex;
    justify-content: flex-start;
    padding: 0.1rem 0.2rem 0.6rem;
}

/* Conteneur inline du Gantt prévisionnel (SfGantt à hauteur bornée). */
.isis-prev-gantt {
    padding: 0.1rem 0.2rem 0.3rem;
}
.isis-prev-gantt__bar {
    display: flex;
    gap: 0.25rem;
    justify-content: flex-end;
    padding: 0 0 0.4rem;
}

/* 7 pistes : Collaborateur · Tâche · Du · Au · Charge · Notes · actions. La charge est passée
   des % (barre de progression, 140px) aux jours-homme (valeur seule) → piste resserrée. */
.isis-grid__subrow { min-width: 0; }
.isis-mob-subgrid { overflow-x: auto; min-width: 0; }
.isis-mob-subgrid__head,
.isis-mob-subgrid__row {
    display: grid;
    grid-template-columns: minmax(180px, 1.4fr) minmax(120px, 1fr) 96px 96px 96px minmax(140px, 1fr) 84px;
    align-items: center;
    column-gap: 0.6rem;
    padding: 0.35rem 0.4rem;
}
.isis-mob-subgrid__head {
    font-size: 0.68rem;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--isis-text-muted);
}
.isis-mob-subgrid__row {
    border-top: 1px solid var(--isis-border);
    font-size: 0.85rem;
}
.isis-mob-subgrid__row:hover { background: var(--isis-surface); }

/* Les badges passent a la ligne plutot que de rogner le nom : a deux badges, la troncature
   reduisait « ABIVEN Anthony » a « ABIVE… » — le nom est l'identite de la ligne, pas un detail
   negociable. Seules les lignes annotees grandissent. */
.isis-mob-subgrid__collab { display: flex; align-items: center; flex-wrap: wrap; gap: 0.35rem 0.5rem; min-width: 0; }
/* Ciblage par classe et non par :last-child : depuis que des badges peuvent suivre le nom,
   :last-child visait le dernier badge — le nom perdait sa troncature précisément sur les
   lignes qui signalent un problème. */
.isis-mob-subgrid__name {
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0;
}
.isis-mob-subgrid__collab .isis-badge { flex-shrink: 0; }
.isis-mob-subgrid__avatar {
    flex-shrink: 0;
    width: 26px;
    height: 26px;
    border-radius: 50%;
    background: var(--isis-mod-gespla-soft);
    color: var(--isis-mod-gespla);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 0.65rem;
    font-weight: 600;
    letter-spacing: 0.03em;
}

/* Colonne numerique : alignee a droite depuis que la barre de progression a disparu
   (une charge en jours-homme n'a pas de plafond a 100, la barre n'avait plus de sens). */
.isis-mob-subgrid__charge { display: flex; align-items: center; justify-content: flex-end; gap: 0.4rem; font-variant-numeric: tabular-nums; }
.isis-mob-subgrid__head > div:nth-child(5) { text-align: right; }

/* ── MonEspace « Ma structure » — centre d'admin (Phase D) ── */
.isis-structure-card__pills {
    display: flex;
    flex-wrap: wrap;
    gap: 0.35rem;
    align-items: center;
}
.isis-structure-card__note {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    font-size: var(--isis-fs-sm, 0.85rem);
    color: var(--isis-text-muted);
}

.isis-structure-defs {
    display: grid;
    gap: 0.4rem;
    margin: 0;
}
.isis-structure-defs__row {
    display: grid;
    grid-template-columns: minmax(180px, 260px) 1fr;
    gap: 1rem;
    padding: 0.35rem 0;
    border-bottom: 1px solid var(--isis-border);
}
.isis-structure-defs__row dt { margin: 0; color: var(--isis-text-muted); }
.isis-structure-defs__row dd { margin: 0; color: var(--isis-text); font-weight: 500; }

.isis-grid--structure-collab .isis-grid__head,
.isis-grid--structure-collab .isis-grid__row {
    grid-template-columns: minmax(180px, 2fr) 130px minmax(160px, 1.5fr) 110px;
    min-width: 580px;
}

/* Panneau « Contrats & charges du lieu » (centre d'administration d'une structure). */
.isis-contrats-panel__toolbar {
    display: flex;
    justify-content: flex-end;
    margin-bottom: 0.6rem;
}
.isis-grid--structure-contrats .isis-grid__head,
.isis-grid--structure-contrats .isis-grid__row {
    grid-template-columns: 110px minmax(180px, 2fr) minmax(150px, 1.4fr) 130px 110px 100px 44px;
    min-width: 760px;
}
.isis-contrats-panel__sub {
    display: block;
    font-size: var(--isis-fs-xs, 0.72rem);
    color: var(--isis-text-muted, #64748b);
}
.isis-contrats-panel__echeance {
    font-variant-numeric: tabular-nums;
}
.isis-contrats-panel__echeance.is-warm {
    color: var(--isis-accent);
    font-weight: 600;
}

/* Panneau « Assurances du lieu » (centre d'administration d'une structure). */
.isis-assurances-panel__toolbar {
    display: flex;
    justify-content: flex-end;
    margin-bottom: 0.6rem;
}
.isis-grid--structure-assurances .isis-grid__head,
.isis-grid--structure-assurances .isis-grid__row {
    grid-template-columns: 150px minmax(180px, 2fr) minmax(150px, 1.4fr) 150px 110px 100px 44px;
    min-width: 800px;
}
.isis-assurances-panel__sub {
    display: block;
    font-size: var(--isis-fs-xs, 0.72rem);
    color: var(--isis-text-muted, #64748b);
}
.isis-assurances-panel__echeance {
    font-variant-numeric: tabular-nums;
}
.isis-assurances-panel__echeance.is-warm {
    color: var(--isis-accent);
    font-weight: 600;
}

/* Panneau « Occupation & emplacements » (centre d'administration d'une structure). */
.isis-occupation-panel__toolbar {
    display: flex;
    justify-content: flex-end;
    margin-bottom: 0.6rem;
}
.isis-occupation-panel__summary {
    margin: 0 0 0.6rem;
    font-size: var(--isis-fs-sm, 0.8rem);
    color: var(--isis-text-muted, #64748b);
}
.isis-grid--structure-occupation .isis-grid__head,
.isis-grid--structure-occupation .isis-grid__row,
.isis-grid--structure-mobilier .isis-grid__head,
.isis-grid--structure-mobilier .isis-grid__row {
    grid-template-columns: 120px minmax(180px, 2fr) minmax(140px, 1.2fr) minmax(150px, 1.4fr) 130px;
    min-width: 720px;
}
.isis-occupation-panel__sub {
    display: block;
    font-size: var(--isis-fs-xs, 0.72rem);
    color: var(--isis-text-muted, #64748b);
}
.isis-occupation-panel__free {
    color: var(--isis-text-muted, #64748b);
    font-style: italic;
}
.isis-occupation-panel__section + .isis-occupation-panel__section {
    margin-top: 1.1rem;
}
.isis-occupation-panel__section-title {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    margin: 0 0 0.5rem;
    font-size: var(--isis-fs-sm, 0.8rem);
    font-weight: 600;
    color: var(--isis-text, #0f172a);
}
.isis-occupation-panel__section-empty {
    margin: 0;
    font-size: var(--isis-fs-sm, 0.8rem);
    color: var(--isis-text-muted, #64748b);
    font-style: italic;
}

/* Panneau « Facturation & cadre légal » (centre d'administration d'une structure ÉMETTRICE).
   Seul panneau du centre exposant des montants en euro — ventilés par devise (pas de somme
   cross-devises). Valeurs en Geist Mono tabulaire, alignées à droite. */
.isis-facturation-panel__toolbar {
    display: flex;
    justify-content: flex-end;
    margin-bottom: 0.6rem;
}
.isis-facturation-panel__kpis {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
    gap: 0.75rem;
    margin-bottom: 1rem;
}
.isis-facturation-panel__kpi {
    display: flex;
    flex-direction: column;
    gap: 0.2rem;
    padding: 0.75rem 0.9rem;
    background: var(--isis-surface-2, #f8fafc);
    border: 1px solid var(--isis-border, #e2e8f0);
    border-radius: var(--isis-radius-sm, 5px);
}
.isis-facturation-panel__kpi.is-warm {
    border-color: color-mix(in oklch, var(--isis-accent) 40%, var(--isis-border, #e2e8f0));
}
.isis-facturation-panel__kpi-label {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    font-size: var(--isis-fs-xs, 0.72rem);
    color: var(--isis-text-muted, #64748b);
}
.isis-facturation-panel__devise {
    font-size: var(--isis-fs-xs, 0.72rem);
    font-weight: 600;
    letter-spacing: 0.03em;
    color: var(--isis-text-muted, #64748b);
    padding: 0.05rem 0.35rem;
    border: 1px solid var(--isis-border, #e2e8f0);
    border-radius: 999px;
}
.isis-facturation-panel__kpi-value {
    font-family: var(--isis-font-mono, ui-monospace, monospace);
    font-variant-numeric: tabular-nums;
    font-size: 1.15rem;
    font-weight: 600;
    color: var(--isis-text, #0f172a);
}
.isis-facturation-panel__kpi.is-warm .isis-facturation-panel__kpi-value {
    color: var(--isis-accent);
}
.isis-facturation-panel__kpi-sub {
    font-size: var(--isis-fs-xs, 0.72rem);
    color: var(--isis-text-muted, #64748b);
}
.isis-facturation-panel__summary {
    margin: 0 0 0.6rem;
    font-size: var(--isis-fs-sm, 0.8rem);
    color: var(--isis-text-muted, #64748b);
}
.isis-grid--structure-factures .isis-grid__head,
.isis-grid--structure-factures .isis-grid__row {
    grid-template-columns: 150px minmax(180px, 2fr) 110px minmax(120px, 1fr) 110px 120px;
    min-width: 760px;
}
.isis-facturation-panel__num {
    text-align: right;
}
.isis-facturation-panel__amount {
    font-family: var(--isis-font-mono, ui-monospace, monospace);
    font-variant-numeric: tabular-nums;
    font-weight: 600;
}
.isis-facturation-panel__echeance.is-warm {
    color: var(--isis-accent);
    font-weight: 600;
}
.isis-facturation-panel__legal {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.6rem;
    margin-top: 1rem;
    padding-top: 0.9rem;
    border-top: 1px solid var(--isis-border, #e2e8f0);
}
.isis-facturation-panel__legal-title {
    font-size: var(--isis-fs-xs, 0.72rem);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--isis-text-muted, #64748b);
}
.isis-facturation-panel__legal-links {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
}

/* ============================================================================
   « Mes structures » — maître-détail (rail sélectionnable + aperçu riche).
   Remplace l'ancienne grille de cartes. Tokens uniquement, mono tabulaire
   pour les valeurs, thème géré par les tokens (clair/sombre).
   ============================================================================ */
.isis-structure-md {
    display: grid;
    grid-template-columns: minmax(240px, 320px) 1fr;
    gap: var(--isis-space-4, 1rem);
    margin-top: var(--isis-space-4, 1rem);
    align-items: start;
}

/* ── Rail maître ── */
.isis-structure-md__rail {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
    min-width: 0;
}
.isis-structure-md__item {
    display: flex;
    align-items: center;
    gap: var(--isis-space-3, 0.75rem);
    width: 100%;
    padding: 0.6rem 0.7rem;
    text-align: left;
    cursor: pointer;
    background: var(--isis-surface, #fff);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-sm, 5px);
    transition: background 0.12s ease, border-color 0.12s ease, box-shadow 0.12s ease;
}
.isis-structure-md__item:hover {
    background: color-mix(in oklch, var(--isis-mod-monespace) 5%, var(--isis-surface));
    box-shadow: var(--isis-elevation-hover);
}
.isis-structure-md__item:focus-visible {
    outline: 2px solid color-mix(in oklch, var(--isis-mod-monespace) 60%, transparent);
    outline-offset: 2px;
}
/* Sélection : filet périmétrique (fond teinté + border module 1px) + accent
   inset gauche tokenisé — remplace l'ancien liseré « étiquette » (DESIGN.md §1). */
.isis-structure-md__item.is-active {
    border-color: color-mix(in oklch, var(--isis-mod-monespace) 55%, var(--isis-border));
    background: color-mix(in oklch, var(--isis-mod-monespace) 8%, var(--isis-surface));
    box-shadow: inset 3px 0 0 var(--isis-mod-monespace);
}
.isis-structure-md__item-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 34px;
    height: 34px;
    border-radius: var(--isis-radius-sm, 5px);
}
.isis-structure-md__item-main {
    display: flex;
    flex-direction: column;
    min-width: 0;
    flex: 1 1 auto;
}
.isis-structure-md__item-name {
    font-size: var(--isis-fs-sm, 0.9rem);
    font-weight: 600;
    color: var(--isis-text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.isis-structure-md__item-type {
    font-size: var(--isis-fs-xs, 0.72rem);
    color: var(--isis-text-muted);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.isis-structure-md__dot {
    flex: 0 0 auto;
    width: 9px;
    height: 9px;
    border-radius: 50%;
}
.isis-structure-md__dot.is-ok { background: color-mix(in oklch, var(--isis-success) 45%, transparent); }
.isis-structure-md__dot.is-warn { background: var(--isis-warning); }

/* ── Panneau détail ── */
.isis-structure-md__detail {
    display: flex;
    flex-direction: column;
    gap: var(--isis-space-4, 1rem);
    min-width: 0;
}
.isis-structure-md__detail-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.5rem;
    padding: var(--isis-space-5, 2rem);
    color: var(--isis-text-muted);
    text-align: center;
}
/* Rail vidé par ses FILTRES (la population, elle, existe) — distinct de l'état vide de la
   page, qui dit « vous n'êtes responsable d'aucune structure ». */
.isis-structure-md__rail-empty {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.5rem;
    padding: var(--isis-space-3, 0.75rem);
    color: var(--isis-text-muted);
    font-size: var(--isis-fs-sm);
}
/* Tuile d'icône de l'aperçu d'une structure — reprise de l'ancienne icône de bandeau, qui
   n'existe plus dans ce module (harmonisation MonEspace). */
.isis-structure-md__detail-icon {
    width: 44px; height: 44px;
    border-radius: 10px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}
.isis-structure-md__detail-icon.mod-monespace-soft {
    background: var(--isis-mod-monespace-soft);
    color: var(--isis-mod-monespace);
}
.isis-structure-md__detail-head {
    display: flex;
    align-items: flex-start;
    gap: var(--isis-space-3, 0.75rem);
}
.isis-structure-md__detail-ident { min-width: 0; }
.isis-structure-md__detail-name {
    margin: 0;
    font-size: var(--isis-fs-lg, 1.15rem);
    font-weight: 600;
    color: var(--isis-text);
}
.isis-structure-md__detail-type {
    font-size: var(--isis-fs-sm, 0.85rem);
    color: var(--isis-text-muted);
}
.isis-structure-md__detail-desc {
    margin: 0.35rem 0 0;
    font-size: var(--isis-fs-sm, 0.85rem);
    color: var(--isis-text-muted);
}

/* ── Tuiles KPI ── */
.isis-structure-md__kpis {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    gap: 0.5rem;
}
.isis-structure-md__kpi {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    padding: 0.55rem 0.7rem;
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-sm, 5px);
    background: color-mix(in oklch, var(--isis-mod-monespace) 4%, var(--isis-surface));
    min-width: 0;
}
.isis-structure-md__kpi-label {
    font-size: var(--isis-fs-xs, 0.72rem);
    color: var(--isis-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}
.isis-structure-md__kpi-value {
    font-family: var(--isis-font-mono, ui-monospace, monospace);
    font-weight: 600;
    font-size: var(--isis-fs-md, 1rem);
    color: var(--isis-text);
    font-variant-numeric: tabular-nums;
    overflow: hidden;
    text-overflow: ellipsis;
}
.isis-structure-md__kpi.is-warm {
    border-color: color-mix(in oklch, var(--isis-accent) 40%, var(--isis-border));
    background: color-mix(in oklch, var(--isis-accent) 6%, var(--isis-surface));
}
.isis-structure-md__kpi.is-warm .isis-structure-md__kpi-value { color: var(--isis-accent); }

.isis-structure-md__actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin-top: auto;
}

/* Empilement sur écran étroit : rail au-dessus, aperçu en dessous. */
@media (max-width: 820px) {
    .isis-structure-md { grid-template-columns: 1fr; }
    .isis-structure-md__rail {
        flex-direction: row;
        flex-wrap: nowrap;
        overflow-x: auto;
        padding-bottom: 0.35rem;
    }
    .isis-structure-md__item { min-width: 220px; }
}

/* ──────────────────────────────────────────────────────────────────────────────
   Frise de portefeuille (SfGantt, page /gesproj/commandes) — CommandesPortfolioGanttView.
   Les jalons/livraisons arrivent TOUJOURS PRÉCHARGÉS (paramètre Children du composant) :
   SfGantt rend donc toute commande qui en a comme ligne PARENTE (.e-gantt-parent-taskbar-
   inner-div), et seulement les commandes sans enfant comme ligne feuille (.e-gantt-child-
   taskbar-inner-div) — ne cibler que l'un des deux ne colorerait qu'une partie des
   commandes. Même recette que le Gantt commande (bloc isis-gb-* ci-dessus), reprise à
   l'identique pour les barres et pour les jalons (.e-milestone-top/-bottom).
   ────────────────────────────────────────────────────────────────────────────── */
.isis-pgantt {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-height: 0;   /* laisse le flex calculer une vraie hauteur — sans ça, height:100% résout à 0 */
    height: 100%;
}
/* Enfant unique de .isis-pgantt (wrapper du SfGantt, Height="100%") : le plancher vit ICI,
   pas sur .e-gantt lui-même — sinon un floor posé plus bas dans l'arbre peut dépasser un
   parent plus contraint et déborder. Remplace l'ancien inline min-height:260px du composant
   (260 → 320, aligné sur le plancher documenté de ce bloc). */
.isis-pgantt__body {
    flex: 1 1 auto;
    min-height: 320px;
}

/* ── Barres commande (ligne parente ET ligne feuille, cf. commentaire ci-dessus) ─── */
.isis-pgantt-bar--en-cours .e-gantt-child-taskbar-inner-div,
.isis-pgantt-bar--en-cours .e-gantt-parent-taskbar-inner-div {
    background-color: var(--isis-mod-gesproj) !important;
}
/* Audit a11y 2026-07-27 (1.4.11, non-text UI) : --isis-border-strong sur --isis-surface CLAIR
   = 2.57:1 (< 3:1 requis). Bascule locale sur --isis-text-muted (7.58:1 sur blanc) EN CLAIR
   uniquement — le SOMBRE garde border-strong (déjà correct) via l'override juste après, plus
   spécifique (:root[data-theme="dark"] > :root). Ne PAS reporter ce swap sur les tokens
   partagés eux-mêmes (--isis-border-strong reste inchangé, utilisé ailleurs dans l'app). */
.isis-pgantt-bar--en-attente .e-gantt-child-taskbar-inner-div,
.isis-pgantt-bar--en-attente .e-gantt-parent-taskbar-inner-div {
    background-color: var(--isis-text-muted) !important;
}
:root[data-theme="dark"] .isis-pgantt-bar--en-attente .e-gantt-child-taskbar-inner-div,
:root[data-theme="dark"] .isis-pgantt-bar--en-attente .e-gantt-parent-taskbar-inner-div {
    background-color: var(--isis-border-strong) !important;
}
.isis-pgantt-bar--a-valider .e-gantt-child-taskbar-inner-div,
.isis-pgantt-bar--a-valider .e-gantt-parent-taskbar-inner-div {
    background-color: var(--isis-info) !important;
}
/* En retard : teinte chaude + hachures — le libellé porte aussi « · en retard »
   (BarLabel, cf. composant), mais la hachure évite de reposer sur la seule teinte pour
   se distinguer d'« en cours » (daltonisme, écran mal calibré). */
.isis-pgantt-bar--retard .e-gantt-child-taskbar-inner-div,
.isis-pgantt-bar--retard .e-gantt-parent-taskbar-inner-div {
    background-color: var(--isis-accent) !important;
    background-image: repeating-linear-gradient(135deg, transparent 0 5px, color-mix(in srgb, var(--isis-text) 20%, transparent) 5px 7px) !important;
}
/* Clôturée / annulée : inerte — teinte neutre ET opacité réduite (double signal). Audit a11y
   2026-07-27 : 0.55 ne passait pas 3:1 en clair (text-soft blend ~2.1:1 sur blanc, le tool
   d'audit avait relevé 1.44:1) ; 0.75 (suggestion initiale) plafonne à ~2.97:1, encore sous le
   seuil — retenu 0.8 (~3.25:1 en clair). L'opacité monte le contraste dans les DEUX thèmes
   (mélange alpha vers un fond plus clair que le texte en clair, vers un fond plus sombre que
   le texte en sombre) : aucun risque de régression côté sombre en la relevant globalement. */
.isis-pgantt-bar--verrouillee .e-gantt-child-taskbar-inner-div,
.isis-pgantt-bar--verrouillee .e-gantt-parent-taskbar-inner-div {
    background-color: var(--isis-text-soft) !important;
    opacity: 0.8 !important;
}
/* Prévisionnelle (devis non encore ferme) : hachures diagonales, jamais une teinte de
   statut — la commande n'a pas encore de statut d'exécution réel. */
.isis-pgantt-bar--previsionnelle .e-gantt-child-taskbar-inner-div,
.isis-pgantt-bar--previsionnelle .e-gantt-parent-taskbar-inner-div {
    background-color: color-mix(in srgb, var(--isis-border-strong) 22%, var(--isis-surface)) !important;
    background-image: repeating-linear-gradient(135deg, transparent 0 6px, color-mix(in srgb, var(--isis-border-strong) 45%, transparent) 6px 8px) !important;
}
/* Ligne de regroupement synthétique (client/pilote) : jamais une vraie commande — la plus
   fondue des barres. Toujours en ligne parente en pratique (un groupe a toujours des
   membres) mais ciblée en double par cohérence avec le reste du bloc.
   Audit a11y/ui 2026-07-27 : confusable avec la barre « verrouillée » (même token
   --isis-text-soft, opacités proches 0.40/0.55). Token dédié --isis-text-muted (plus sombre à
   pleine opacité, mais ici à 0.4 le rendu reste nettement plus pâle que verrouillee à 0.8) pour
   que les deux ne partagent plus la même variable — cf. .isis-pgantt-legend__sw--groupe. */
.isis-pgantt-bar--groupe .e-gantt-child-taskbar-inner-div,
.isis-pgantt-bar--groupe .e-gantt-parent-taskbar-inner-div {
    background-color: var(--isis-text-muted) !important;
    opacity: 0.4 !important;
}

/* ── Jalons / livraisons (toujours en ligne fille — losange en triangles CSS) ────── */
.isis-pgantt-bar--jalon-ok .e-milestone-top { border-bottom-color: var(--isis-success) !important; }
.isis-pgantt-bar--jalon-ok .e-milestone-bottom { border-top-color: var(--isis-success) !important; }
/* Jalon à venir : teinte neutre (pas de statut « alerte ») — le détail du tooltip ne porte
   « · atteint » que pour les jalons franchis, ce qui donne un second signal que le vert.
   Même correctif de contraste clair que .isis-pgantt-bar--en-attente ci-dessus (2.57:1 sur
   blanc avec border-strong, audit a11y 2026-07-27) — text-muted en clair, border-strong
   inchangé en sombre. */
.isis-pgantt-bar--jalon-todo .e-milestone-top { border-bottom-color: var(--isis-text-muted) !important; }
.isis-pgantt-bar--jalon-todo .e-milestone-bottom { border-top-color: var(--isis-text-muted) !important; }
:root[data-theme="dark"] .isis-pgantt-bar--jalon-todo .e-milestone-top { border-bottom-color: var(--isis-border-strong) !important; }
:root[data-theme="dark"] .isis-pgantt-bar--jalon-todo .e-milestone-bottom { border-top-color: var(--isis-border-strong) !important; }
.isis-pgantt-bar--livraison .e-milestone-top { border-bottom-color: var(--isis-info) !important; }
.isis-pgantt-bar--livraison .e-milestone-bottom { border-top-color: var(--isis-info) !important; }

/* ── Déclencheur « Non planifiées » (au-dessus du Gantt) ─────────────────────────── */
/* Remplace l'ancien bandeau de puces numéro-seul (audit 2026-07-28) : à 50 puces il mesurait
   324px dans un master overflow:hidden, écrasait .isis-pgantt__body sous son plancher de
   320px et rognait la légende sur 1366×768. Le détail par commande (numéro/intitulé/client)
   vit désormais dans CommandeUnscheduledPickerDialog — ce conteneur ne porte plus qu'un
   bouton compact sur une seule ligne, qui rend au chart le budget de hauteur qu'il prenait. */
.isis-pgantt-unscheduled {
    display: flex;
    flex: 0 0 auto;
    margin-bottom: var(--isis-space-sm);
}

/* ── Légende (sous la frise) — même vocabulaire de classes que les barres, pour ne pas
   dupliquer la table de couleurs côté page (Task 6 compose <span class="isis-pgantt-
   legend__sw isis-pgantt-legend__sw--xxx">). __item n'est pas dans la liste de classes
   émises par le composant mais reste nécessaire ici : sans lui, gap/flex-wrap sépare la
   pastille de son libellé sur les largeurs étroites. ────────────────────────────────── */
.isis-pgantt-legend {
    display: flex;
    flex: 0 0 auto;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--isis-space-md);
    margin-top: var(--isis-space-sm);
    padding-top: var(--isis-space-sm);
    border-top: 1px solid var(--isis-border);
    font-size: var(--isis-fs-sm);
    color: var(--isis-text-muted);
}
.isis-pgantt-legend__item {
    display: inline-flex;
    align-items: center;
    gap: var(--isis-space-xs);
}
.isis-pgantt-legend__sw {
    flex: 0 0 auto;
    width: 12px;
    height: 12px;
    border-radius: var(--isis-radius-sm);
}
.isis-pgantt-legend__sw--en-cours       { background-color: var(--isis-mod-gesproj); }
/* --en-attente / --jalon-todo : pastilles alignées sur le correctif de contraste clair des
   barres (text-muted en clair, border-strong inchangé en sombre, cf. plus haut) — sinon la
   légende mentirait sur la couleur réellement rendue. */
.isis-pgantt-legend__sw--en-attente     { background-color: var(--isis-text-muted); }
:root[data-theme="dark"] .isis-pgantt-legend__sw--en-attente { background-color: var(--isis-border-strong); }
.isis-pgantt-legend__sw--a-valider      { background-color: var(--isis-info); }
.isis-pgantt-legend__sw--retard         { background-color: var(--isis-accent); }
.isis-pgantt-legend__sw--verrouillee    { background-color: var(--isis-text-soft); opacity: 0.8; }
.isis-pgantt-legend__sw--previsionnelle { background-color: color-mix(in srgb, var(--isis-border-strong) 22%, var(--isis-surface)); border: 1px dashed var(--isis-border-strong); }
.isis-pgantt-legend__sw--groupe         { background-color: var(--isis-text-muted); opacity: 0.4; }
.isis-pgantt-legend__sw--jalon-ok       { background-color: var(--isis-success); border-radius: 999px; }
.isis-pgantt-legend__sw--jalon-todo     { background-color: var(--isis-text-muted); border-radius: 999px; }
:root[data-theme="dark"] .isis-pgantt-legend__sw--jalon-todo { background-color: var(--isis-border-strong); }
.isis-pgantt-legend__sw--livraison      { background-color: var(--isis-info); border-radius: 999px; }

/* ── Mini-dialog CommandeUnscheduledPickerDialog — liste des commandes sans dates
   d'exécution (choisir laquelle planifier), ouverte depuis le déclencheur .isis-pgantt-
   unscheduled ci-dessus. Même recette que .isis-besoin-picker (mini-dialog PlannerV3Page). */
.isis-cmd-unscheduled-picker {
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
    min-width: 560px;
}
/* EF-90 — temps contestés du collaborateur (Ma feuille de temps). */
.isis-temps-contestes {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}
.isis-temps-contestes__list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    max-height: 60vh;
    overflow-y: auto;
}
.isis-temps-contestes__item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    padding: 0.6rem 0.75rem;
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius);
}
.isis-temps-contestes__main {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    min-width: 0;
}
.isis-temps-contestes__motif {
    font-size: 0.85rem;
    color: var(--isis-text-muted);
}
.isis-temps-contestes__actions {
    display: flex;
    justify-content: flex-end;
    gap: 0.5rem;
    padding-top: 0.75rem;
    border-top: 1px solid var(--isis-border);
}

.isis-cmd-unscheduled-picker__hint {
    margin: 0;
    font-size: 0.85rem;
    color: var(--isis-text-muted);
}
.isis-cmd-unscheduled-picker__list {
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
    max-height: 50vh;
    overflow-y: auto;
}
.isis-cmd-unscheduled-picker__item {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 200px) 18px;
    gap: 0.6rem;
    align-items: center;
    width: 100%;
    padding: 0.55rem 0.75rem;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: 6px;
    cursor: pointer;
    text-align: left;
    transition: background 100ms ease, border-color 100ms ease;
}
.isis-cmd-unscheduled-picker__item:hover {
    background: color-mix(in srgb, var(--isis-mod-gesproj) 6%, var(--isis-surface));
    border-color: var(--isis-mod-gesproj);
}
.isis-cmd-unscheduled-picker__item:focus-visible {
    outline: 2px solid var(--isis-mod-gesproj);
    outline-offset: 1px;
}
.isis-cmd-unscheduled-picker__main {
    display: flex;
    flex-direction: column;
    gap: 0.1rem;
    min-width: 0;
}
.isis-cmd-unscheduled-picker__numero {
    font-family: var(--isis-font-mono);
    font-weight: 600;
    color: var(--isis-text);
}
.isis-cmd-unscheduled-picker__intitule {
    font-size: 0.85rem;
    color: var(--isis-text-muted);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.isis-cmd-unscheduled-picker__client {
    font-size: 0.85rem;
    color: var(--isis-text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    text-align: right;
}
/* EF-114 — planification en lot des commandes non planifiées (CommandeFenetreLotDialog). */
.isis-cmd-fenetre-lot {
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
}
.isis-cmd-fenetre-lot__head,
.isis-cmd-fenetre-lot__row {
    display: grid;
    grid-template-columns: 24px minmax(0, 1fr) 140px 140px minmax(0, 180px);
    gap: 0.6rem;
    align-items: center;
}
.isis-cmd-fenetre-lot__head {
    font-size: 0.75rem;
    font-weight: 600;
    color: var(--isis-text-muted);
    padding: 0 0.75rem;
}
.isis-cmd-fenetre-lot__list {
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
    max-height: 55vh;
    overflow-y: auto;
}
.isis-cmd-fenetre-lot__row {
    padding: 0.45rem 0.75rem;
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: 6px;
}
.isis-cmd-fenetre-lot__sources {
    font-size: 0.8rem;
    color: var(--isis-text-muted);
}
.isis-cmd-fenetre-lot__echec {
    font-size: 0.8rem;
    color: var(--isis-danger);
}
@media (max-width: 720px) {
    .isis-cmd-fenetre-lot__head { grid-template-columns: 24px minmax(0, 1fr); }
    .isis-cmd-fenetre-lot__head > span:nth-child(n+3) { display: none; }
    .isis-cmd-fenetre-lot__row { grid-template-columns: 24px minmax(0, 1fr); }
    .isis-cmd-fenetre-lot__row > :nth-child(n+3) { grid-column: 2; }
}

/* ── Responsive : sous 1100px, masquer Client + Début pour laisser sa place au calendrier.
   Colonnes déclarées dans cet ordre (GanttColumns, CommandesPortfolioGanttView.razor) :
   Commande(1, TreeColumnIndex="0") / Client(2) / Début(3) / Fin(4) / Statut(5, ajouté audit
   a11y 2026-07-27) — aucune colonne technique (case à cocher, drag) n'est activée sur ce
   composant, donc l'ordre nth-child suit tel quel l'ordre déclaré des GanttColumn.
   Client + Début restent les colonnes qui cèdent (inchangé — mêmes index 2/3). Fin ET Statut
   restent visibles : Statut ne PEUT PAS céder, sinon la régression 1.4.1 (couleur seule
   porteuse d'« en cours »/« en attente »/« à valider ») réapparaît sous 1100px ; Fin reste pour
   garder au moins une borne de date lisible sans ouvrir le tooltip. Compromis assumé : le
   calendrier perd donc ~112px de plus qu'avant l'ajout de la colonne Statut. ─────────────── */
@media (max-width: 1100px) {
    .isis-pgantt .e-headercell:nth-child(2),
    .isis-pgantt .e-headercell:nth-child(3),
    .isis-pgantt .e-rowcell:nth-child(2),
    .isis-pgantt .e-rowcell:nth-child(3) {
        display: none;
    }
}

/* ───────────────────────────────────────────────────────────────────────────
   Classes utilitaires de couleur Radzen — rattrapage en thème sombre.

   rz-color-base-400/500/600/700 portent des gris FIGÉS, calculés pour un fond
   clair (base-500 = #333333). Sur une surface sombre, ils tombent à 1,32:1 —
   mesuré le 2026-08-06 sur la fiche tenant, où les libellés des cartes du haut
   (« Utilisateurs », « dont 12 actifs », « 166 documents »…) étaient
   pratiquement invisibles. Le seuil AA est 4,5:1.

   Ce n'est pas un défaut local : 137 usages dans 62 écrans. Les corriger un par
   un reviendrait à repasser derrière chaque page et à recommencer à la
   suivante ; on les remappe donc une fois sur les tokens ISIS, qui sont, eux,
   définis dans les deux thèmes et dont les ratios sont mesurés.

   Portée d'abord limitée à [data-theme="dark"]. Le 2026-10-06, base-500 est aussi
   remappé en clair : ~70 écrans l'emploient pour leurs légendes, et seul le token
   garantit le contraste mesuré (7,4:1 sur blanc) dans les deux thèmes.
   ─────────────────────────────────────────────────────────────────────────── */
.rz-color-base-500 { color: var(--isis-text-muted) !important; }
:root[data-theme="dark"] .rz-color-base-400 { color: var(--isis-text-soft) !important; }
:root[data-theme="dark"] .rz-color-base-500 { color: var(--isis-text-muted) !important; }
:root[data-theme="dark"] .rz-color-base-600,
:root[data-theme="dark"] .rz-color-base-700 { color: var(--isis-text) !important; }

/* ───────────────────────────────────────────────────────────────────────────
   Badge de statut CRITIQUE — mise au seuil de contraste.

   DESIGN.md §167/§351 prescrit `Shade.Default` + `BadgeStyle.Danger` pour tous
   les statuts critiques du produit (REFUSE, ANNULE, RETARD, INACTIF, BLOQUE,
   ECHEC, « inaccessible »…) : pleine couleur, texte blanc. L'exception est
   assumée et justifiée — on veut que l'œil tombe dessus en balayant.

   Mais le rouge Radzen de ce badge (#f44336) donne 3,68:1 avec du texte blanc,
   mesuré le 2026-08-06, sous les 4,5 exigés pour du 12,8 px. La règle la plus
   visible du design system était donc la moins lisible.

   On lui applique le rouge sémantique DU PROJET, --isis-danger en thème clair
   (#b91c1c → 6,47:1). Aucune couleur nouvelle n'est introduite : c'est celui
   déjà utilisé par .isis-badge.is-danger et les indicateurs de santé.

   Sélecteur volontairement étroit : `rz-shade-default` ne matche QUE la variante
   pleine couleur. Les badges pâles (`rz-shade-lighter`, texte coloré sur fond
   translucide) sont le standard du produit et ne doivent surtout pas devenir des
   aplats ; en Warning et Danger ils ne passaient PAS le seuil — ils sont recolorés
   juste en dessous.
   ─────────────────────────────────────────────────────────────────────────── */
.rz-badge.rz-badge-danger.rz-shade-default,
:root[data-theme="dark"] .rz-badge.rz-badge-danger.rz-shade-default {
    background-color: #a51b1b;
    color: #ffffff;
}

/* Badges pâles Warning / Danger (décision du propriétaire 2026-09-18 : correction GLOBALE).
   Le Shade.Lighter de Radzen pose sa teinte vive sur la même teinte à 20 % : sous 4,5:1.
   Couple de jetons du projet, ratios calculés contre :root —
   clair : --isis-warning sur --isis-warning-soft 4,51:1 · --isis-danger sur --isis-danger-soft 5,30:1 ;
   sombre : warning 6,30:1 · danger pur 4,35:1 (échoue), d'où le mélange à 80 % avec
   --isis-text : 5,33:1. */
.rz-badge.rz-badge-warning.rz-shade-lighter {
    background-color: var(--isis-warning-soft);
    color: var(--isis-warning);
}
.rz-badge.rz-badge-danger.rz-shade-lighter {
    background-color: var(--isis-danger-soft);
    color: var(--isis-danger);
}
:root[data-theme="dark"] .rz-badge.rz-badge-danger.rz-shade-lighter {
    color: color-mix(in srgb, var(--isis-danger) 80%, var(--isis-text));
}

/* Badges pâles Info / Success : achèvement de la correction ci-dessus (C5, audit a11y
   2026-09-19) — Warning et Danger seuls avaient été traités le 2026-09-18, Info et Success
   gardaient les jetons Radzen translucides d'origine, sous 4,5:1 (« En cours » 2,52:1 clair et
   4,10:1 sombre). Mêmes jetons projet, ratios calculés contre :root, texte sur fond —
   clair : --isis-info sur --isis-info-soft 7,15:1 · --isis-success sur --isis-success-soft 4,57:1 ;
   sombre : --isis-info sur --isis-info-soft 5,87:1 · --isis-success sur --isis-success-soft 5,90:1.
   Portée ERP entière : tout badge info/success pâle, pas seulement Opportunité. */
.rz-badge.rz-badge-info.rz-shade-lighter {
    background-color: var(--isis-info-soft);
    color: var(--isis-info);
}
.rz-badge.rz-badge-success.rz-shade-lighter {
    background-color: var(--isis-success-soft);
    color: var(--isis-success);
}

/* Badges pâles Secondary (C5, balayage a11y 2026-09-21) : 10 usages hétérogènes (avoir,
   sous-traitance, prêt externe, archivé…), sans jeton `--isis-secondary` dédié dans la charte.
   Arbitrage du propriétaire : pas de couleur nouvelle — Secondary pâle devient l'accent du
   projet, sur `--isis-accent-soft`.
   L'encre est un jeton APPARIÉ, `--isis-accent-on-soft`, et non un mélange calculé ici : un
   `var()` se résout là où la propriété est déclarée, donc tout producteur qui redéfinit
   accent-soft doit fournir l'encre qui va avec, au même sélecteur. Producteurs : les 4 jeux
   `:root` de ce fichier (85 % d'accent-strong dans --isis-text — clair 5,31:1, sombre 8,33:1,
   update clair 8,72:1, update sombre 7,92:1) ; `BrandSync.razor` (accent de marque du client sur
   `.isis-shell`, un bloc par mode) ; `ThemeCssBuilder` (thème du client, une encre par mode).
   Ces deux derniers dosent l'accent SAISI, d'où un mélange qui tient 4,5:1 pour tout accent
   (I2, a11y étape 6). */
.rz-badge.rz-badge-secondary.rz-shade-lighter {
    background-color: var(--isis-accent-soft);
    color: var(--isis-accent-on-soft);
}

/* ════════════════════════════════════════════════════════════════════════════
   TABLEAU DE BORD — socle neutre (lot 4, 2026-09-14). Grille 12 colonnes
   générique pour un tableau de bord composé de TROIS BANDES (Repères / Analyse
   / À traiter) — sous-préfixe `isis-tdb-`, pour tout module qui n'est pas
   encore passé au monde « Cartouche topographique » (`isis-pl-`, région
   suivante). Différence assumée avec la planche : CE SOCLE DÉFILE (la page
   défile normalement, pas de cadre pleine hauteur ni de scroll interne) — les
   container queries y fonctionnent donc jusqu'aux paliers bas, ce que la
   planche ne peut pas garantir tant qu'elle ne défile pas elle-même. Le thème
   sombre passe uniquement par `:root[data-theme="dark"]` (posé par
   isis-theme-mode.js) — aucun `prefers-color-scheme` ici, pour ne pas ouvrir
   une 2e source de vérité.
   Maquette de recette : docs/mockups/2026-09-14-socle-tdb.html.
   Sonde de non-régression : e2e/_probe-tdb-paliers.mjs.
   Brief : .superpowers/sdd/2026-09-14-tableaux-de-bord-socle-neutre/lot-4-brief.md.
   ════════════════════════════════════════════════════════════════════════════ */

/* Racine de page. `container-name: tdb` porte les paliers ci-dessous (jamais de
   @media : doctrine docs/DASHBOARD-DESIGN.md, container queries sur la largeur
   RÉELLE du conteneur, pas sur le viewport). Tokens `--tdb-*` : alias directs
   des tokens `--isis-*` existants, jamais de valeur en dur. Set minimal exigé
   par le brief : encre + 2 atténuations, filet + variante douce, papier,
   accent module, teinte projeté/en attente, rayon. */
.isis-tdb {
    container-type: inline-size;
    container-name: tdb;
    display: flex;
    flex-direction: column;
    gap: var(--isis-space-lg);

    --tdb-ink:       var(--isis-text);
    --tdb-ink-muted: var(--isis-text-muted);
    --tdb-ink-soft:  var(--isis-text-soft);
    --tdb-rule:      var(--isis-border);
    --tdb-rule-soft: var(--isis-border-soft);
    --tdb-paper:     var(--isis-surface);
    --tdb-accent:    var(--isis-current-mod, var(--isis-accent));
    --tdb-attente:   var(--isis-accent);
    --tdb-radius:    var(--isis-radius);
    /* PAS de `--tdb-bandeau-h` ici, et il ne faut pas le réintroduire : il a
       existé trois rondes durant pour que `.isis-tdb__filtres`, collant
       indépendamment, connaisse la hauteur du bandeau et s'y pose dessous.
       L'invariant était INDÉMONTRABLE — le bandeau est un `flex-wrap` dont la
       hauteur dépend du contenu de la page hôte (sous-titre, nombre d'actions,
       longueur du titre), donc aucune constante ne peut la dire. Mesuré sur
       /dev/tdb : 37px de recouvrement à 1100 et 1440px, et 44px sans sous-titre
       mais avec cinq actions. Le couplage est supprimé à la racine : bandeau et
       filtres vivent désormais dans UNE seule boîte collante
       (`.isis-tdb__entete`), et plus rien n'a besoin de connaître une hauteur
       qu'un seul des deux connaît. */
}
/* Sombre : chacun des `--tdb-*` ci-dessus est un alias direct d'un token déjà
   redéfini par `:root[data-theme="dark"]` (ligne 42974) — ils cascadent seuls,
   sans rien à réécrire ici (même vérification que les 94/139 tokens `--isis-*`
   redéfinis en sombre : aucun `--tdb-*` n'existe uniquement côté sombre,
   puisqu'aucun n'y est déclaré du tout). Le jour où un usage exige un dosage
   propre au sombre — par exemple peindre un APLAT avec `--tdb-accent`, comme
   `--pl-exist-fx` le fait pour les swatches de planche (lignes 49606-49611,
   parce qu'en sombre `--isis-current-mod` est déjà une teinte éclaircie, pâle
   en aplat) — c'est ici, sous `:root[data-theme="dark"] .isis-tdb { ... }`,
   qu'il vient. Le socle n'en a pas besoin : ses tokens ne servent qu'en texte,
   filet ou fond de carte, jamais en aplat plein. */

/* Aplat de contribution (DashRepartition, lot 6) : premier usage du socle qui peint
   --tdb-accent en FOND PLEIN plutôt qu'en texte/filet — exactement le cas annoncé
   ci-dessus. Même dosage que --pl-exist-fx (ligne 49982, 70 % accent + 30 % blanc en
   oklab) : en sombre, --isis-current-mod est déjà une teinte éclaircie, pâle en aplat.
   Déclarée UNIQUEMENT ici (jamais dans .isis-tdb de base, ronde ci-dessus recettée sur
   12 combinaisons/2 rondes, non rouverte) : le point d'usage lit
   `var(--tdb-accent-fx, var(--tdb-accent))`, qui retombe sur --tdb-accent tant que
   --tdb-accent-fx n'existe pas — donc rien à déclarer côté clair. */
:root[data-theme="dark"] .isis-tdb {
    --tdb-accent-fx: color-mix(in oklab, var(--tdb-accent) 70%, white);
}

/* Les trois modificateurs de bande — `.isis-tdb__bande--reperes`,
   `--analyse`, `--a-traiter` — n'ont VOLONTAIREMENT aucune déclaration ici :
   ce sont des crochets sémantiques, posés par IsisDashboard.razor pour que la
   sonde, une maquette ou un module puissent viser une bande précise. Ne pas
   les « nettoyer » parce qu'ils sont absents de cette feuille : c'est leur
   absence de style qui est le contrat.
   Grille 12 colonnes d'une bande. `minmax(0, 1fr)` et non `1fr` : sans le 0, un
   contenu large (tableau, chaîne sans espace) refuse de se comprimer et fait
   déborder la PAGE horizontalement — voir aussi `.isis-tdb__bloc` plus bas,
   qui absorbe ce qui reste. Une bande sans bloc n'est pas rendue (résolue
   côté serveur, lot 2) : aucune règle `:empty` à écrire ici.
   Rembourrage horizontal `--isis-space-md` — LA gouttière de page, la même que
   celle du bandeau (ronde 1/5) : sans elle, rien d'autre ne l'apporte (ni
   `.isis-tdb`, ni `.isis-shell__content` dans l'app réelle), et les cartes
   touchent le bord du conteneur pendant que le titre du bandeau reste en
   retrait. Verticalement 0 : le `gap` entre bandes s'en charge (`.isis-tdb`). */
.isis-tdb__bande {
    display: grid;
    grid-template-columns: repeat(12, minmax(0, 1fr));
    gap: var(--isis-space-md);
    padding: 0 var(--isis-space-md);
}
.isis-tdb__bande-titre {
    grid-column: 1 / -1;
    margin: 0;
    padding-bottom: var(--isis-space-xs);
    border-bottom: 1px solid var(--tdb-rule);
    font-size: var(--isis-fs-sm);
    font-weight: 600;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--tdb-ink-muted);
}

/* Bloc d'une bande — la carte neutre. `min-width: 0` + `overflow-wrap: anywhere` :
   le débordement d'une chaîne sans espace se coupe DANS le bloc, jamais sur la
   page. C'est un complément obligatoire du `minmax(0, 1fr)` du parent : sans
   lui, un item de grille garde un minimum de taille basé sur son contenu
   (chaîne sans espace) et pousse quand même la piste.
   Pas de `overflow-x` ICI (ronde 1/5) : un contenu plus large que le bloc
   (tableau) va dans `.isis-tdb__bloc-large` ci-dessous, un conteneur DÉDIÉ —
   sinon le scroll du bloc entier emporte aussi son titre et sa valeur hors du
   champ, et la barre masquée (macOS/tactile) ne laisse rien deviner.
   `display: flex` en colonne (2026-09-15, unification du titre) : le bloc porte
   désormais DEUX enfants — le titre rendu par IsisDashboard, puis le fragment du
   module — et c'est le `gap` qui les sépare, une seule fois, pour les sept blocs.
   Avant, chaque bloc reproduisait ce `gap` dans sa propre racine (`.isis-dserie`,
   `.isis-drep`… toutes en `flex column; gap: --isis-space-sm`) ; elles le gardent
   pour leurs propres enfants, mais l'écart titre/contenu, lui, n'est plus une
   convention répétée sept fois. */
.isis-tdb__bloc {
    display: flex;
    flex-direction: column;
    gap: var(--isis-space-sm);
    min-width: 0;
    overflow-wrap: anywhere;
    background: var(--tdb-paper);
    border: 1px solid var(--tdb-rule);
    border-radius: var(--tdb-radius);
    box-shadow: var(--isis-elevation-1);
    padding: var(--isis-space-md);
}

/* Titre d'un bloc — LA classe, et la seule. Elle remplace les sept classes
   parallèles `.isis-dkpi__titre`, `.isis-dserie__titre`, `.isis-drep__titre`,
   `.isis-dlist__titre`, `.isis-dchrono__titre`, `.isis-dcarte__titre` et
   `.isis-dnote__titre` (retirées le 2026-09-15). Elles étaient déclaration pour
   déclaration IDENTIQUES — vérifié avant fusion, six fois la même règle recopiée ;
   seule `.isis-dkpi__titre` n'avait pas `margin: 0`, parce qu'elle habillait un
   <span> sans marge d'origine et non un <p>. La classe unique porte `margin: 0` :
   c'est un sur-ensemble exact des sept, aucune n'y perd une déclaration.
   Rendue par IsisDashboard.razor, sur un <h3> (la page est un <h1>, la bande un
   <h2>) — AVANT le fragment du bloc, donc toujours hors d'un
   `.isis-tdb__bloc-large` et fixe pendant le défilement horizontal. */
.isis-tdb__bloc-titre {
    margin: 0;
    font-size: var(--isis-fs-sm);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--tdb-ink-muted);
}
.isis-tdb__bloc--3  { grid-column: span 3; }
.isis-tdb__bloc--4  { grid-column: span 4; }
.isis-tdb__bloc--6  { grid-column: span 6; }
.isis-tdb__bloc--8  { grid-column: span 8; }
.isis-tdb__bloc--12 { grid-column: span 12; }

/* ATTENDU PAR DashListe (lot à venir) : aucun composant ne pose encore cette
   classe, et ce n'est pas une survivance à supprimer — c'est le conteneur de
   défilement que le bloc « liste » du socle consommera.
   Conteneur de défilement horizontal DÉDIÉ pour un contenu plus large que le
   bloc (tableau). Le titre et la valeur du bloc restent HORS de ce conteneur
   (avant lui dans le HTML) donc fixes pendant le défilement.
   Affordance de bord : reprend TEL QUEL le système « scroll-shadow » déjà
   centralisé de cette feuille (`--isis-scroll-shadow-*`, cf. `.isis-side-panel__body`
   plus haut) — même recette (Lea Verou), tournée à l'horizontale (gauche/droite
   au lieu de haut/bas). Un dégradé fixe au bord RÉVÈLE qu'il reste du contenu ;
   une bande « cover » qui défile AVEC le contenu (`background-attachment: local`)
   le masque tant qu'on est à l'extrémité — donc rien n'apparaît si tout le
   contenu est déjà visible. Fonctionnel, pas décoratif : mêmes tokens que
   partout ailleurs dans le produit, aucune valeur en dur. */
.isis-tdb__bloc-large {
    min-width: 0;
    overflow-x: auto;
    scrollbar-width: none;
    -ms-overflow-style: none;
    background:
        linear-gradient(to right, var(--isis-scroll-shadow-bg) 30%, transparent) left center,
        linear-gradient(to right, transparent, var(--isis-scroll-shadow-bg) 70%) right center,
        radial-gradient(farthest-side at 0 50%, var(--isis-scroll-shadow-ink), transparent) left center,
        radial-gradient(farthest-side at 100% 50%, var(--isis-scroll-shadow-ink), transparent) right center,
        var(--isis-scroll-shadow-bg);
    background-repeat: no-repeat;
    background-size:
        var(--isis-scroll-shadow-cover) 100%,
        var(--isis-scroll-shadow-cover) 100%,
        var(--isis-scroll-shadow-fade) 100%,
        var(--isis-scroll-shadow-fade) 100%,
        auto;
    background-attachment: local, local, scroll, scroll, local;
}
.isis-tdb__bloc-large::-webkit-scrollbar { width: 0; height: 0; display: none; }

/* Valeurs chiffrées du socle : Geist Mono partout, jamais Geist sans
   (DESIGN.md §3 — densité ≥ 7 chiffres). */
.isis-tdb__valeur {
    font-family: var(--isis-font-mono);
    font-variant-numeric: tabular-nums;
}

/* Teinte « projeté / en attente » (doctrine Cartouche : hachures/attente = ce
   qui n'est pas encore réalisé, plein = existant). Emploi minimal de ce lot :
   colore un compteur "en attente" — cf. maquette, bande À traiter. */
.isis-tdb__attente {
    color: var(--tdb-attente);
}

/* En-tête collant du socle : le bandeau ET la barre de filtres, dans UNE SEULE
   boîte. C'est la boîte, jamais ses deux enfants, qui colle en haut du
   défilement — à tous les paliers. Deux boîtes collantes indépendantes ne
   peuvent pas s'accorder : la seconde doit connaître la hauteur de la première,
   qui dépend du contenu de la page hôte (sous-titre, nombre d'actions, titre
   qui s'enroule) et change donc d'une page à l'autre. Les rondes qui ont tenté
   de tenir cette hauteur dans un token (`--tdb-bandeau-h`) ont chaque fois
   soigné une mesure en laissant l'invariant faux : 37px de recouvrement mesurés
   à 1100/1440px sur /dev/tdb, 44px sans sous-titre mais avec cinq actions —
   soit, sur une vraie barre de filtres, la moitié haute d'un contrôle de 44px
   qui ne reçoit plus le clic. Empilées dans un même flux, les deux barres se
   posent l'une sous l'autre par construction : il n'y a plus de hauteur à
   deviner.
   `background` : aucun contenu ne doit transparaître sous l'en-tête pendant le
   défilement, même sur une couture sub-pixel entre les deux barres.
   `z-index: 2` : au-dessus des cartes des bandes, qui défilent dessous.
   Sous 640px, cette boîte sort du collant (cf. le palier ≤ 640 plus bas) : à
   cette largeur elle pèse ~344px, près de la moitié d'un écran de téléphone.
   Sortir UNE SEULE boîte ne coûte rien — c'est sortir l'une de DEUX boîtes
   collantes qui obligeait l'autre à deviner sa hauteur, et c'est cette dette-là
   qui est fermée. */
.isis-tdb__entete {
    position: sticky;
    top: 0;
    z-index: 2;
    background: var(--tdb-paper);
}

/* Bandeau : titre, fraîcheur de la donnée, actions à droite. Collant PAR SON
   PARENT (`.isis-tdb__entete` ci-dessus), jamais par lui-même. `min-width: 0` +
   ellipsis sur le titre : un intitulé long ne doit jamais forcer le bandeau,
   donc la page, à s'élargir — seuls la fraîcheur et les actions gardent leur
   taille naturelle (`flex: 0 0 auto`), le titre absorbe le reste.
   `box-sizing: border-box` : ce dépôt n'a AUCUN reset `box-sizing` global
   (impératif, cf. lignes 2041/2087), sans quoi le rembourrage s'ajoute
   PAR-DESSUS la hauteur (ronde 1/5, ~73px rendus pour 56px annoncés).
   Aucune hauteur imposée, ni `height` ni `min-height` : la hauteur est celle du
   contenu — une cible tactile de 44px (`.isis-tdb__action`) la porte déjà quand
   il y a des actions, et un titre qui s'enroule sur deux lignes n'a plus rien à
   respecter. C'est la disparition du couplage qui permet ça. */
.isis-tdb__bandeau {
    box-sizing: border-box;
    display: flex;
    flex-wrap: wrap;
    align-content: center;
    align-items: center;
    gap: var(--isis-space-md);
    padding: var(--isis-space-sm) var(--isis-space-md);
    background: var(--tdb-paper);
    border-bottom: 1px solid var(--tdb-rule);
}
.isis-tdb__bandeau-titre {
    /* flex-basis 0% et non `auto` (ronde 2/5, trouvé en vérifiant le cas du
       titre très long demandé par la consigne) : avec `auto`, la base de
       flex vaut le contenu — un titre en une seule ligne (white-space:nowrap)
       plus large que le conteneur force `flex-wrap` à le rejeter sur SA
       PROPRE ligne (décision prise sur la taille hypothétique, AVANT toute
       réduction par flex-shrink), même si `min-width:0` lui permettrait de
       rétrécir sans broncher. Résultat observé : bandeau à 2 lignes bien
       au-dessus de 640px, où les filtres restent pourtant sticky et attendus
       sur UNE ligne — chevauchement rouvert. `0%` retire le contenu du calcul
       de la ligne ; `flex-grow:1` continue de lui donner l'espace restant. */
    flex: 1 1 0%;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    margin: 0;
    font-size: var(--isis-fs-xl);
    font-weight: 600;
    color: var(--tdb-ink);
}
/* Sous-titre du bandeau (lot 5, ronde 1/5) — élément FRÈRE du <h1>, jamais imbriqué dedans :
   le titre porte flex-basis:0 + nowrap + ellipsis pour absorber un intitulé long (ronde 2/5,
   lot 4) ; un sous-titre imbriqué s'y battait pour le même budget de largeur et débordait au
   lieu de s'ellipser (mesuré à 1440 comme à 420px). `flex-basis:100%` : dans le flex-wrap du
   bandeau, cet élément démarre systématiquement sa PROPRE ligne, sans jamais réduire l'espace
   dont disposent le titre, la fraîcheur ou les actions sur la ligne du dessus. `min-width:0` +
   retour à la ligne normal (pas d'ellipsis) : un sous-titre est une phrase de contexte, pas une
   valeur — l'enrouler au mot est préférable à le tronquer au caractère. */
.isis-tdb__bandeau-soustitre {
    flex: 1 1 100%;
    min-width: 0;
    margin: 0;
    color: var(--tdb-ink-soft);
    font-weight: 400;
}
.isis-tdb__bandeau-fraicheur {
    flex: 0 0 auto;
    font-family: var(--isis-font-mono);
    font-size: var(--isis-fs-sm);
    color: var(--tdb-ink-soft);
    white-space: nowrap;
}
.isis-tdb__bandeau-actions {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: var(--isis-space-sm);
}
.isis-tdb__action {
    /* border-box impératif (même piège que .isis-tdb__bandeau) : sans lui, la
       bordure 1px s'ajoute PAR-DESSUS min-height:44px et le bouton rend 46px —
       une cible tactile annoncée à 44px qui n'en fait pas 44. Ce 1px a aussi,
       du temps de `--tdb-bandeau-h`, rouvert le chevauchement des filtres ;
       cette conséquence-là a disparu avec le token, la cible tactile reste. */
    box-sizing: border-box;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--isis-space-xs);
    min-width: 44px;
    min-height: 44px;
    padding: 0 var(--isis-space-sm);
    border: 1px solid var(--tdb-rule);
    border-radius: var(--tdb-radius);
    background: var(--tdb-paper);
    color: var(--tdb-ink);
    font-size: var(--isis-fs-sm);
    cursor: pointer;
    transition: background 140ms ease, border-color 140ms ease, color 140ms ease;
}
.isis-tdb__action:hover {
    border-color: var(--tdb-accent);
    color: var(--tdb-accent);
}
/* Offset décidé ici (la règle plancher n'en pose plus aucun, cf. ligne ~49918) :
   POSITIF, à la différence des blocs. Les actions du bandeau vivent dans
   `.isis-tdb__entete`, qui ne porte aucun `overflow` — rien ne peut rogner un
   anneau posé à l'extérieur, et un anneau extérieur se distingue mieux de la
   bordure déjà peinte sur ces boutons. */
.isis-tdb__action:focus-visible {
    outline-offset: 2px;
}

/* Filtres : barre horizontale, DANS `.isis-tdb__entete` et juste après le
   bandeau. Elle ne colle pas elle-même — c'est l'en-tête entier qui colle, donc
   elle suit le bandeau sans avoir à connaître sa hauteur. Passe en pile sous
   768px (palier plus bas) ; plus aucun palier ne la sort du collant, puisqu'il
   n'y a plus de `top` calculé à faire tomber juste. */
.isis-tdb__filtres {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    /* 16 / 8 / 2 — loi de proximité. Mesuré avant (audit UI/UX, 2026-09-15) : 4px entre deux
       boutons d'un même groupe contre 8px entre un groupe et le libellé du groupe SUIVANT. Le
       libellé « Vue » était donc DEUX FOIS plus près du groupe qu'il ne nomme pas que de celui
       qu'il nomme : la barre se lisait « 8 chips d'affilée avec deux mots coincés dedans ».
       L'écart entre filtres (ici) domine l'écart libellé→groupe (.isis-dfiltre), qui domine
       l'écart intra-groupe (.isis-dfiltre__groupe, désormais porté par l'enclos). */
    gap: var(--isis-space-md);
    padding: var(--isis-space-sm) var(--isis-space-md);
    background: var(--tdb-paper);
    border-bottom: 1px solid var(--tdb-rule-soft);
}
.isis-tdb__filtre {
    /* border-box : même raison que .isis-tdb__action juste au-dessus. */
    box-sizing: border-box;
    display: inline-flex;
    align-items: center;
    gap: var(--isis-space-xs);
    min-height: 44px;
    padding: 0 var(--isis-space-sm);
    border: 1px solid var(--tdb-rule);
    border-radius: var(--tdb-radius);
    background: var(--tdb-paper);
    color: var(--tdb-ink-muted);
    font-size: var(--isis-fs-sm);
}

/* DashFiltrePeriode / DashFiltreVue / DashFiltreEntreprise (lot 9, 2026-09-15) — les
   filtres RÉELS du socle, dans la même barre `.isis-tdb__filtres` que `.isis-tdb__filtre`
   ci-dessus (qui reste : un chip purement AFFICHÉ, non interactif, est un usage légitime
   distinct — cf. TdbDemoPageViewModel avant ce lot).
   `.isis-dfiltre` = UN filtre : libellé + contrôle, jamais empilés verticalement même dans le
   flex-wrap de la barre — le libellé nomme le groupe, il ne doit pas s'en détacher visuellement. */
.isis-dfiltre {
    display: inline-flex;
    align-items: center;
    gap: var(--isis-space-sm);
    flex-wrap: wrap;
}
/* Reprend `.isis-view-selector__label` (isis-theme.css:~35559), l'idiome DÉJÀ en production pour
   un libellé de groupe de filtres : capitales et interlettrage le sortent du registre des chips,
   donc « Vue » ne peut plus se lire comme un neuvième bouton. Ce n'est pas un style neuf — c'est
   celui que l'utilisateur connaît depuis le dashboard gescom. */
.isis-dfiltre__label {
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--tdb-ink-muted);
    white-space: nowrap;
    flex-shrink: 0;
}
/* ENCLOS. La Gestalt d'enfermement bat la proximité : cinq boutons dans une piste se lisent
   comme UN contrôle, là où cinq boutons espacés de 4px se lisaient comme cinq chips.
   La piste porte aussi l'état : l'aplat pressé contraste à 6,74:1 contre `--isis-surface-alt` en
   thème sombre (mesuré), soit MIEUX que contre la surface nue (4,52:1).
   RÉSERVE ASSUMÉE, et c'est une dette de PRODUIT, pas de ce socle : le filet d'un bouton NON
   pressé reste `--isis-border`, mesuré 1,47:1 en clair et 1,34:1 en sombre contre la surface —
   sous les 3:1 de WCAG 1.4.11. `--isis-border-strong` ne sauve rien (2,57:1 / 1,82:1, mesuré —
   la valeur de 3,00:1 avancée par l'audit WCAG est fausse). Fermer ce point exigerait de
   retoucher un jeton posé dans TOUT le produit ; le faire ici seul ferait des filtres du socle
   le seul endroit de l'application à filet lourd. Dette nommée, pas traitée. */
.isis-dfiltre__groupe {
    display: inline-flex;
    flex-wrap: wrap;
    gap: 2px;
    padding: 2px;
    background: var(--isis-surface-alt);
    border: 1px solid var(--tdb-rule);
    border-radius: var(--tdb-radius);
}
/* Bouton-bascule (DashFiltrePeriode, DashFiltreVue) — mêmes proportions que
   `.isis-tdb__filtre`/`.isis-tdb__action` (cible ≥44px), plus un ÉTAT.
   Deuxième correction de justification (audit UI/UX, 2026-09-15) : les DEUX versions
   précédentes de ce commentaire décrivaient une conformité que la règle ne réalisait pas.
   La première créditait `aria-pressed` — or ARIA n'est pas un indice VISUEL. La seconde
   annonçait « un changement de FORME/POIDS » — or la règle ne posait que des couleurs, ni
   graisse ni épaisseur. L'indice non chromatique est désormais RÉEL : `font-weight: 600` et un
   filet porté par l'enclos du groupe. La référence correcte est DESIGN.md:652 (« le flash n'est
   jamais le seul vecteur d'information — WCAG 1.4.1 »), pas :846, qui traite du bandeau de page. */
.isis-dfiltre__bouton {
    box-sizing: border-box;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 44px;
    min-height: 44px;
    padding: 0 var(--isis-space-sm);
    /* Le filet et le fond vivent désormais sur l'enclos ; le bouton est transparent pour que la
       piste se voie. Rayon réduit de l'épaisseur du rembourrage de l'enclos, sinon les coins
       intérieurs débordent des coins extérieurs.
       `--isis-fs-base` et non `--isis-fs-sm` : DESIGN.md §3 réserve `sm` au texte secondaire et
       aux badges. Un bouton de 44px de haut portant 12,8px de texte était beaucoup d'air pour
       peu de signal, sur le contrôle principal d'un écran consulté des heures. */
    border: 1px solid transparent;
    border-radius: calc(var(--tdb-radius) - 2px);
    background: transparent;
    color: var(--tdb-ink);
    font-size: var(--isis-fs-base);
    cursor: pointer;
    transition: background 140ms ease, border-color 140ms ease, color 140ms ease;
}
/* `[aria-disabled]` et non `:disabled` : les deux groupes de boutons ont basculé sur l'attribut
   ARIA pour garder leur rang de tabulation (cf. DashFiltrePeriode.razor). Le `<select>`, lui,
   garde `disabled` — un select ne se neutralise pas par ARIA seul, et ce n'est pas un choix perdu
   dans un groupe, c'est un contrôle unique. */
/* `:not([aria-pressed="true"])` — BLOQUANT de revue avant fusion (2026-09-16). Sans lui, la
   regle de survol (specificite 0,3,0) battait la regle d'etat (0,2,0) sur `color` SEULE : le
   libelle du bouton presse reprenait `--tdb-accent` tandis que son fond gardait l'aplat.
   En theme sombre l'aplat EST `var(--tdb-accent)` depuis cette ronde : texte et fond devenaient
   LA MEME COULEUR, 1,00:1, sur les 20 aplats. Le libelle disparaissait au survol — c'est-a-dire
   dans le geste le plus courant, juste apres le clic, le curseur encore sur le bouton.
   Le defaut PREEXISTAIT (2,93:1 en sombre a la ronde 1) ; poser l'aplat brut l'a porte a 1,00.
   Ni le filet unitaire (il ne lisait que `background`) ni la recette (aucun cas de survol) ne
   pouvaient le voir — les deux ont ete repris, cf. FiltresSocleContrasteTests et le cas 1b. */
.isis-dfiltre__bouton:hover:not([aria-disabled="true"]):not([aria-pressed="true"]) {
    border-color: var(--tdb-accent);
    color: var(--tdb-accent);
}
/* ÉTAT PRESSÉ — deux critères, pas un. La ronde du 2026-09-15 n'avait mesuré que WCAG 1.4.3
   (le TEXTE sur l'aplat) et assombri l'accent de 36 % pour y arriver. L'audit WCAG a mesuré
   l'autre moitié, WCAG 1.4.11 (l'APLAT contre le fond de la barre, c'est-à-dire l'indication
   d'état) : assombrir un aplat sur un fond déjà sombre le fait disparaître — 2,61:1 sur le
   tenant de dev, 17 des 20 aplats sous le seuil de 3:1, pire cas `gesfac` à 1,79:1.
   Les deux critères n'étaient pas en tension par malchance de dosage : ils étaient rendus
   MUTUELLEMENT EXCLUSIFS par `--isis-on-accent`, blanc dans les deux thèmes. Ne pas re-doser —
   c'est ce qu'avait déjà fait le monde Cartouche (18 % puis 36 %) sans jamais fermer le dossier.
   La cause est corrigée à sa source (voir le token, thème sombre), et la règle suit :
     · CLAIR  — les accents sont des teintes SOUTENUES : aucun aplat brut ne porte de texte
                (blanc 3,68:1, encre sombre 1,61:1). On assombrit, et le blanc passe à 9,40:1.
     · SOMBRE — les accents sont DÉJÀ des teintes ÉCLAIRCIES : l'aplat BRUT porte l'encre sombre
                à 4,93:1 au pire (`gesfac`) ET se détache du fond à 4,52:1. Les deux d'un coup.
   L'aplat reste « l'accent » dans les deux modes : c'est l'ENCRE qui suit sa clarté, pas
   l'identité du module qui change (DESIGN.md §2). */
.isis-dfiltre__bouton[aria-pressed="true"] {
    background: color-mix(in oklab, var(--tdb-accent) 64%, black 36%);
    border-color: color-mix(in oklab, var(--tdb-accent) 64%, black 36%);
    color: var(--isis-on-accent);
    font-weight: 600;
}
:root[data-theme="dark"] .isis-dfiltre__bouton[aria-pressed="true"] {
    background: var(--tdb-accent);
    border-color: var(--tdb-accent);
}
/* Anneau de focus DÉDIÉ pour l'état pressé (mineur de revue, 2026-09-15) : la règle générique
   `.isis-tdb :where(a, button, [tabindex]):focus-visible` (plus bas) peint `--tdb-accent` sans
   offset — sur un fond DÉJÀ teinté (ci-dessus), un anneau de la MÊME famille de couleur s'y
   fondrait. `--isis-on-accent` est la contre-encre de l'aplat par construction : blanc sur
   l'aplat assombri du thème clair, encre sombre sur l'aplat brut du thème sombre — mesuré
   4,93:1 au pire dans les deux cas, très au-delà des 3:1 de WCAG 1.4.11 ; offset négatif pour
   rester DANS le bouton, jamais hors de lui. */
.isis-dfiltre__bouton[aria-pressed="true"]:focus-visible {
    outline-color: var(--isis-on-accent);
    outline-offset: -3px;
}
.isis-dfiltre__bouton[aria-disabled="true"],
/* `.isis-tdb__action` porte le meme etat depuis que « Reinitialiser » a bascule sur ARIA : sans
   cette ligne il restait d'apparence PLEINE, curseur en main, pendant que les huit boutons de
   filtre s'estompaient a cote. La bascule etait invoquee au nom de la coherence ; sa moitie
   visuelle manquait. */
.isis-tdb__action[aria-disabled="true"] {
    opacity: .5;
    cursor: not-allowed;
}
.isis-dfiltre__note {
    margin: 0;
    flex-basis: 100%;
    font-size: var(--isis-fs-sm);
    color: var(--tdb-ink-soft);
}
/* <select> natif (DashFiltreEntreprise) — mêmes proportions que les boutons ci-dessus, sans
   réinventer un composant : le socle neutre ne dépend pas de Radzen pour ses filtres, à la
   différence du reste du produit (même logique que DashCarte/DashSerie, qui s'appuient sur
   IsisAmChart déjà existant plutôt que sur un composant de graphe Radzen). */
.isis-dfiltre__select {
    box-sizing: border-box;
    min-height: 44px;
    max-width: 220px;
    padding: 0 var(--isis-space-sm);
    border: 1px solid var(--tdb-rule);
    border-radius: var(--tdb-radius);
    background: var(--tdb-paper);
    color: var(--tdb-ink);
    font-size: var(--isis-fs-sm);
}
.isis-dfiltre__select:disabled {
    opacity: .5;
    cursor: not-allowed;
}
/* Insertion PURE, volontairement à côté de la règle `:where(a, button, [tabindex])` plus bas
   plutôt que dedans (celle-ci ne liste pas `select`, et ce lot ne modifie AUCUNE règle
   existante de la région `isis-tdb-`, seulement des ajouts) : un <select> natif est focusable
   sans `tabindex`, la règle générique ne l'aurait donc jamais couvert. */
.isis-dfiltre__select:focus-visible {
    outline: 2px solid var(--tdb-accent);
}

/* DashFiltreAffinage (filtre n°4) — la liste qui AFFINE le périmètre courant (ses membres, ou
   ses structures). Sous-préfixe `isis-daffinage-`, un bloc = un sous-préfixe, comme
   `isis-dfiltre-` juste au-dessus. Ajouts PURS : aucune règle existante de la région
   `isis-tdb-` n'est modifiée.

   Ce filtre ne tient pas sur une ligne de la barre, à la différence des trois autres : il liste
   n options. Il se rend donc en COLONNE, borné en hauteur et défilant, et c'est la page hôte qui
   décide où le poser (`flex-basis: 100%` dans `.isis-tdb__filtres`, ou une colonne latérale). */
/* IL PREND SA PROPRE LIGNE — constat I1 de l'audit UI/UX, PRÉDIT sans pouvoir être vu, puis
   CONSTATÉ à la première recette sur donnée réelle (2026-09-17). La barre de filtres est en
   `flex-wrap` avec `align-items: center` : ce filtre mesure ~345 px (libellé + recherche + liste
   bornée à 17 rem), il imposait donc sa hauteur à TOUTE la ligne et les trois autres filtres — 44 px
   chacun — flottaient centrés au milieu du vide. Sur un en-tête COLLANT, c'est la moitié d'un écran
   de 1024 px confisquée en permanence pour un filtre qu'on touche une fois par session.
   Le commentaire d'origine disait « c'est la page hôte qui décide où le poser » : elle n'en avait
   aucun moyen — `IsisDashboard` n'offre qu'un seul emplacement, et aucune classe modificatrice
   n'existait. Le socle décide donc, au lieu de déléguer ce qu'il est seul à pouvoir faire. */
.isis-daffinage {
    flex-basis: 100%;
    align-self: flex-start;
    /* `max-width: none` SUR LA RACINE — sinon `flex-basis: 100%` est vaincu (constaté sur
       /gescom/cockpit, 2026-09-17). Avec `max-width: 22rem` ici, la boîte faisait 352 px, la
       ligne n'était pas pleine, et les filtres posés APRÈS (bascule Plan/Globe, sélecteur de
       pays) se casaient sur la même ligne et flottaient centrés dans le vide à côté de la liste —
       le symptôme I1 exactement, réapparu. Sur /gescom/dashboard ça passait seulement parce
       qu'aucun filtre ne venait après. La largeur de lecture est désormais bornée sur le CORPS
       (`.isis-daffinage__corps`), la racine occupe toute la ligne. */
    max-width: none;
    box-sizing: border-box;
    display: flex;
    flex-direction: column;
    /* Le libellé nomme le groupe : il reste COLLÉ à lui (loi de proximité, même hiérarchie
       d'écarts que `.isis-dfiltre` — l'écart entre filtres domine l'écart libellé→groupe, qui
       domine l'écart intra-groupe). */
    gap: var(--isis-space-xs);
    min-width: 15rem;
}
/* La borne de largeur de LECTURE porte sur les deux éléments internes, pas sur la racine (qui doit
   occuper toute la ligne, cf. ci-dessus). Aucun conteneur intermédiaire n'est ajouté au markup :
   deux règles valent mieux qu'un div de plus. */
.isis-daffinage__recherche,
.isis-daffinage__liste { max-width: 22rem; }
/* EN-TÊTE DU REPLI — une ligne de 44 px, le libellé et la bascule. La bascule reprend la géométrie
   de `.isis-tdb__action` (cible 44 px, filet, jetons) ; son état ouvert est porté par
   `aria-expanded`, jamais par une classe posée à la main — un seul vecteur d'état, celui que le
   lecteur d'écran lit aussi. */
.isis-daffinage__entete {
    display: flex;
    align-items: center;
    gap: var(--isis-space-sm);
    min-height: 44px;
}
.isis-daffinage__bascule {
    box-sizing: border-box;
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    padding: 0 var(--isis-space-sm);
    border: 1px solid var(--tdb-rule);
    border-radius: var(--tdb-radius);
    background: var(--tdb-paper);
    color: var(--tdb-ink);
    font-size: var(--isis-fs-base);
    cursor: pointer;
}
.isis-daffinage__bascule:hover { border-color: var(--tdb-accent); color: var(--tdb-accent); }
.isis-daffinage__bascule[aria-expanded="true"] { border-color: var(--tdb-accent); font-weight: 600; }
.isis-daffinage__corps { display: flex; flex-direction: column; gap: var(--isis-space-xs); }
/* Même idiome que `.isis-dfiltre__label` — capitales et interlettrage sortent le libellé du
   registre des contrôles, donc « Membres » ne se lit pas comme une première option. */
.isis-daffinage__label {
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--tdb-ink-muted);
    white-space: nowrap;
    flex-shrink: 0;
}
/* CHAMP DE RECHERCHE (filtre local de la liste). Même géométrie que les contrôles de l'enclos,
   mais POSÉ AU-DESSUS de lui et non dedans : il ne fait pas partie du groupe de cases, il le
   filtre. Il n'est jamais neutralisé pendant un rechargement — cf. le commentaire du composant :
   il n'émet rien, et un contrôle à état intrinsèque refusé dans le handler mentirait à l'écran.
   `-webkit-search-cancel-button` laissé au navigateur : c'est une affordance native de `search`,
   et la retirer priverait la souris du seul geste d'effacement en un clic. */
.isis-daffinage__recherche {
    box-sizing: border-box;
    width: 100%;
    min-height: 44px;
    padding: 0 var(--isis-space-sm);
    border: 1px solid var(--tdb-rule);
    border-radius: var(--tdb-radius);
    background: var(--tdb-paper);
    color: var(--tdb-ink);
    font-family: inherit;
    font-size: var(--isis-fs-base);
}
.isis-daffinage__recherche:focus-visible {
    outline: 2px solid var(--tdb-accent, var(--isis-current-mod, var(--isis-accent)));
    outline-offset: 2px;
}

/* ENCLOS, exactement comme `.isis-dfiltre__groupe` : la Gestalt d'enfermement fait lire n lignes
   comme UN contrôle. La piste porte aussi l'état — c'est contre ELLE, et non contre la surface
   nue de la barre, que se mesure le contraste de la case cochée (WCAG 1.4.11 se mesure contre ce
   qui TOUCHE l'aplat ; la même erreur de voisin a été corrigée sur `.isis-dfiltre__bouton` en
   revue le 2026-09-16).
   Hauteur BORNÉE et défilement : une liste de membres n'a pas de plafond raisonnable, et une
   barre de filtres qui grandit avec le nombre de collaborateurs pousserait le contenu de la page
   hors de l'écran. */
.isis-daffinage__liste {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 2px;
    max-height: 17rem;
    overflow-y: auto;
    background: var(--isis-surface-alt);
    border: 1px solid var(--tdb-rule);
    border-radius: var(--tdb-radius);
}
/* ENCLOS D'UN GROUPE NOMMÉ. Il existe pour l'ARBRE D'ACCESSIBILITÉ avant d'exister pour l'œil :
   sans lui, l'en-tête « Équipe commerciale » n'est qu'un FRÈRE des cases qui le suivent, et un
   lecteur d'écran qui atterrit sur une case au milieu de la liste ne peut pas dire de quel groupe
   elle relève (le composant lui pose `role="group" aria-label`).
   PAS `display: contents` — il a longtemps retiré l'élément de l'arbre d'accessibilité dans
   plusieurs moteurs, ce qui emporterait le `role="group"` avec lui, c'est-à-dire précisément ce
   pour quoi cet enclos est posé. Une pile flex reproduit le même rendu sans ce risque. */
.isis-daffinage__grp {
    display: flex;
    flex-direction: column;
    gap: 2px;
}
/* Les trois familles de contrôles de la liste partagent une seule géométrie : cible ≥ 44px
   (DESIGN.md, cibles tactiles), pleine largeur, texte à gauche. Le filet et le fond vivent sur
   l'enclos ; les contrôles sont transparents pour que la piste se voie — rayon réduit du
   rembourrage de l'enclos, sinon les coins intérieurs débordent des coins extérieurs. */
.isis-daffinage__tous,
.isis-daffinage__groupe,
.isis-daffinage__option {
    box-sizing: border-box;
    display: flex;
    align-items: center;
    gap: var(--isis-space-sm);
    width: 100%;
    min-height: 44px;
    padding: 0 var(--isis-space-sm);
    border: 1px solid transparent;
    border-radius: calc(var(--tdb-radius) - 2px);
    background: transparent;
    color: var(--tdb-ink);
    font-family: inherit;
    /* `--isis-fs-base` et non `--isis-fs-sm` : DESIGN.md §3 réserve `sm` au texte secondaire.
       Même arbitrage que `.isis-dfiltre__bouton`. */
    font-size: var(--isis-fs-base);
    text-align: left;
    cursor: pointer;
    transition: background 140ms ease, border-color 140ms ease, color 140ms ease;
}
/* L'indentation d'arbre est portée par une propriété personnalisée posée en style inline par le
   composant (`--isis-daffinage-niveau`, un ENTIER déjà borné côté C#) : la géométrie reste ici,
   la page ne calcule aucun pixel. Repli à 0 si la propriété manque. */
.isis-daffinage__option {
    padding-left: calc(var(--isis-space-sm) + var(--isis-daffinage-niveau, 0) * 0.875rem);
}
/* SURVOL — `:not([aria-disabled="true"])` parce que le refus est dans le handler et non dans un
   attribut natif : sans cette exclusion, un contrôle inerte s'éclairerait comme un contrôle
   actionnable. `:not([aria-pressed="true"])` / `:not([aria-checked="true"])` parce que la règle
   de survol (spécificité 0,3,0) bat la règle d'état (0,2,0) sur `color` SEULE — c'est le
   bloquant mesuré sur `.isis-dfiltre__bouton` le 2026-09-16 : en thème sombre l'aplat EST
   l'accent, donc texte et fond devenaient la même couleur au survol (1,00:1), dans le geste le
   plus courant, juste après le clic, le curseur encore sur le contrôle. */
.isis-daffinage__tous:hover:not([aria-disabled="true"]):not([aria-pressed="true"]),
.isis-daffinage__groupe:hover:not([aria-disabled="true"]),
.isis-daffinage__option:hover:not([aria-disabled="true"]):not([aria-checked="true"]) {
    border-color: var(--tdb-accent);
    color: var(--tdb-accent);
}
/* « TOUS » ACTIF — aplat plein, même dosage et mêmes raisons que
   `.isis-dfiltre__bouton[aria-pressed="true"]` : en CLAIR les accents sont des teintes
   soutenues, on les assombrit pour que la contre-encre passe AA ; en SOMBRE ils sont déjà des
   teintes éclaircies, l'aplat BRUT porte l'encre sombre et se détache du fond. Ne pas re-doser :
   la tension entre WCAG 1.4.3 (texte sur l'aplat) et 1.4.11 (aplat contre la piste) est résolue
   à la source par `--isis-on-accent`, pas par un compromis de pourcentage. */
.isis-daffinage__tous[aria-pressed="true"] {
    background: color-mix(in oklab, var(--tdb-accent) 64%, black 36%);
    border-color: color-mix(in oklab, var(--tdb-accent) 64%, black 36%);
    color: var(--isis-on-accent);
    font-weight: 600;
}
:root[data-theme="dark"] .isis-daffinage__tous[aria-pressed="true"] {
    background: var(--tdb-accent);
    border-color: var(--tdb-accent);
}
/* En-tête de groupe : un CONTRÔLE (il bascule tout le groupe), pas un titre — il garde donc la
   géométrie des autres, et se distingue par la graisse et le compteur poussé à droite. Il
   n'atteint jamais d'état sélectionné : aucune règle ne le repeint. */
.isis-daffinage__groupe {
    font-weight: 600;
    color: var(--tdb-ink-muted);
}
.isis-daffinage__groupe-nom {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.isis-daffinage__compte {
    margin-left: auto;
    font-family: var(--isis-font-mono);
    font-variant-numeric: tabular-nums;
    font-size: var(--isis-fs-sm);
    flex-shrink: 0;
}
/* LA CASE — l'indice d'état PREMIER, et il n'est pas chromatique : vide, pleine avec une coche,
   ou en trait discontinu quand l'inclusion est DÉDUITE. WCAG 1.4.1 est tenu par la forme (fond
   plein / contour / trait discontinu), la couleur ne fait que renforcer.
   LA LIMITE DE CETTE CASE N'EST PAS UNE DETTE DE PRODUIT, et la version précédente de ce
   commentaire se trompait en l'assimilant à celle de `.isis-dfiltre__groupe` (correction
   d'audit WCAG). WCAG 1.4.11 exempte « les parties dont la présentation visuelle est déterminée
   par l'agent utilisateur et non modifiée par l'auteur » : la case NATIVE de
   `PlancheMembresFilter.razor:31` est entièrement peinte par le navigateur (seul `accent-color`
   la retouche), donc exemptée. En la DESSINANT, on reprend la responsabilité que l'exemption
   déchargeait — et `--isis-border-strong` l'assumait en échec (2,57:1 en clair, 1,82:1 en
   sombre). Ce n'est pas un filet de regroupement : c'est LA LIMITE DU CONTRÔLE, et c'est le
   SEUL indice de l'état NON coché.
   D'où `--tdb-ink-soft` (= `--isis-text-soft`), mesuré 3,82:1 en clair et 4,80:1 en sombre
   contre la piste `--isis-surface-alt` : le jeton le plus discret qui passe le seuil.
   `--isis-text-muted` (6,09 / 6,15) passerait aussi, mais dessinerait une bordure lourde sur
   chaque ligne d'une liste qui peut en compter trente.
   Repli explicite `var(--tdb-ink-soft, var(--isis-text-soft))` : hors de `.isis-tdb` le jeton
   `--tdb-*` n'existe pas, et une déclaration invalide est SUPPRIMÉE — la case serait alors sans
   limite, donc sans état visible. Même raisonnement que pour l'anneau de focus plus bas.
   L'état COCHÉ, lui, est porté par l'aplat, dont le dosage est mesuré sur les 20 accents des
   deux thèmes par `FiltresSocleContrasteTests`. */
.isis-daffinage__case {
    box-sizing: border-box;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 18px;
    height: 18px;
    flex-shrink: 0;
    border: 1px solid var(--tdb-ink-soft, var(--isis-text-soft));
    border-radius: var(--isis-radius-sm);
    background: var(--tdb-paper);
    color: var(--isis-on-accent);
}
.isis-daffinage__coche {
    width: 12px;
    height: 12px;
    display: block;
}
/* COCHÉE EXPLICITEMENT. `:not(.is-implicite)` — une option déduite est cochée elle aussi
   (`aria-checked="true"`), et lui donner cet aplat effacerait la seule chose qui les distingue.
   Aucune de ces deux règles ne déclare `color` sur le contrôle : l'encre du libellé reste celle
   de la règle de base, et aucune règle d'état ne peut donc repeindre un texte dont une autre
   règle tiendrait le fond — le défaut fermé sur `.isis-dfiltre__bouton` ne peut pas renaître
   ici par construction. */
.isis-daffinage__option[aria-checked="true"]:not(.is-implicite) {
    background: color-mix(in oklab, var(--tdb-accent) 12%, transparent);
    font-weight: 600;
}
.isis-daffinage__option[aria-checked="true"]:not(.is-implicite) .isis-daffinage__case {
    background: color-mix(in oklab, var(--tdb-accent) 64%, black 36%);
    border-color: color-mix(in oklab, var(--tdb-accent) 64%, black 36%);
}
:root[data-theme="dark"] .isis-daffinage__option[aria-checked="true"]:not(.is-implicite) .isis-daffinage__case {
    background: var(--tdb-accent);
    border-color: var(--tdb-accent);
}
/* DÉDUITE — visiblement AUTRE qu'un choix de l'utilisateur, et non « estompée » : elle n'est pas
   indisponible, elle est acquise. Trait discontinu (forme), case creuse (forme), encre atténuée
   (renfort). Volontairement PAS l'opacité de `[aria-disabled]` plus bas : confondre « inerte
   pendant un rechargement » et « incluse par déduction » ferait croire à un état transitoire.
   La coche reste peinte en `--tdb-ink-muted` et non en accent : mesuré, un accent de module sur
   la piste claire descend sous 3:1 pour au moins un module (sirh), là où l'encre atténuée tient
   largement dans les deux thèmes. */
.isis-daffinage__option.is-implicite {
    color: var(--tdb-ink-muted);
    cursor: default;
}
.isis-daffinage__option.is-implicite .isis-daffinage__case {
    background: transparent;
    border-style: dashed;
    color: var(--tdb-ink-muted);
}
.isis-daffinage__texte {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/* Mention par option (« aussi rattaché ») — descriptive, jamais un statut : pas de badge, pas de
   couleur sémantique. Poussée à droite pour ne pas couper la colonne des libellés. */
.isis-daffinage__mention {
    margin-left: auto;
    padding-left: var(--isis-space-sm);
    font-size: var(--isis-fs-sm);
    font-weight: 400;
    color: var(--tdb-ink-soft);
    white-space: nowrap;
    flex-shrink: 0;
}
/* `[aria-disabled]` et non `:disabled` : ces contrôles gardent leur rang de tabulation pendant un
   rechargement (WCAG 2.4.3 — cf. DashFiltrePeriode.razor), le geste est refusé dans le handler.
   Sans cette règle ils resteraient d'apparence pleine, curseur en main, pendant qu'ils
   n'obéissent plus — c'est la moitié visuelle qui avait manqué à `.isis-tdb__action`. */
.isis-daffinage__tous[aria-disabled="true"],
.isis-daffinage__groupe[aria-disabled="true"],
.isis-daffinage__option[aria-disabled="true"] {
    opacity: .5;
    cursor: not-allowed;
}
.isis-daffinage__note {
    margin: 0;
    font-size: var(--isis-fs-sm);
    color: var(--tdb-ink-soft);
}
/* FOCUS — offset NÉGATIF, obligatoire : `.isis-daffinage__liste` porte `overflow-y: auto`, et un
   anneau posé hors de la boîte y serait rogné (c'est le défaut corrigé sur `.isis-dkpi` au lot 6,
   revenu par un autre chemin au lot 9 ; la règle plancher du socle ne pose donc AUCUN offset et
   laisse chaque composant décider du sien).
   La couleur est déclarée ici avec son repli complet, et pas seulement l'offset : `--tdb-accent`
   n'existe que sous `.isis-tdb`, et une déclaration `outline` invalide serait SUPPRIMÉE — soit
   aucun anneau de focus si ce composant est un jour posé hors du socle. Un fond qui retombe sur
   le défaut est cosmétique ; un anneau qui disparaît est une infraction. */
.isis-daffinage__tous:focus-visible,
.isis-daffinage__groupe:focus-visible,
.isis-daffinage__option:focus-visible {
    outline: 2px solid var(--tdb-accent, var(--isis-current-mod, var(--isis-accent)));
    outline-offset: -2px;
}
/* Anneau dédié sur l'aplat plein de « Tous » : la règle ci-dessus peint `--tdb-accent` sur un
   fond de la MÊME famille de couleur, où il se fondrait. `--isis-on-accent` est la contre-encre
   de cet aplat par construction — même correctif que
   `.isis-dfiltre__bouton[aria-pressed="true"]:focus-visible`. Les options cochées n'en ont pas
   besoin : leur fond est une teinte à 12 %, pas un aplat. */
.isis-daffinage__tous[aria-pressed="true"]:focus-visible {
    outline-color: var(--isis-on-accent);
    outline-offset: -3px;
}
/* Anneau de focus sur une ligne COCHÉE. Le fond y est une teinte d'accent à 12 % : un anneau
   `--tdb-accent` s'y détache mal (estimé ~3,4:1, et non calculé sur les 20 accents des deux
   thèmes — donc invérifiable de tête). L'anneau emprunte ici l'ENCRE que cette même ligne
   utilise DÉJÀ pour imprimer son libellé : si elle n'était pas lisible sur ce fond, le libellé ne
   le serait pas non plus. C'est un argument de construction, pas une estimation, et il vaut pour
   les 20 accents et les deux thèmes sans avoir à les énumérer. Précédent :
   `.isis-dfiltre__bouton[aria-pressed="true"]:focus-visible`, où l'anneau suit déjà le FOND et
   non une identité de couleur fixe. */
.isis-daffinage__option[aria-checked="true"]:not(.is-implicite):focus-visible {
    outline-color: var(--tdb-ink);
}

/* Focus clavier visible partout dans le socle (DESIGN.md §10) — PLANCHER, jamais
   plafond.

   `:where()` et NON `:is()` (corrigé 2026-09-15). `:is()` prend la spécificité de
   son argument le plus fort, ce qui donnait à cette règle (0,3,0) : elle battait
   par spécificité DEUX règles à (0,2,0) qu'elle n'avait aucune raison de battre —
   `.isis-grid__row:focus-visible` (lignes 12210 et 15947, LA norme du dépôt sur
   203 pages de liste) et `.isis-dchrono__row:focus-visible` (ligne ~50455), écrite
   exprès en `-2px` par le lot 8. Mesuré au navigateur : les deux rendaient
   `outline-offset: 2px` au lieu de `-2px`, donc un anneau POSÉ HORS de la ligne.
   `:where()` vaut (0,1,0) : n'importe quelle règle de composant la reprend, et
   celles qui ne disent rien héritent quand même d'un anneau.

   PAS d'`outline-offset` ici : un anneau positif déborde de la boîte focalisée,
   et `.isis-tdb__bloc-large` porte `overflow-x: auto` — ce qui fait calculer
   `overflow-y: auto` par la spec CSS et ROGNE sur les quatre côtés. C'est
   exactement le défaut que le lot 6 avait corrigé sur `.isis-dkpi` (cf. le
   commentaire « PAS d'overflow: hidden ici » ligne ~50014), revenu par un autre
   chemin. Chaque composant décide donc de son offset, et les composants posés
   dans un conteneur de défilement le posent NÉGATIF.

   `--tdb-accent` et non `--isis-accent` : le token est déclaré deux lignes plus
   haut dans cette même région et vaut `var(--isis-current-mod, var(--isis-accent))`
   — le socle peignait une couleur fixe là où tout le dépôt peint la couleur du
   module courant. */
.isis-tdb :where(a, button, [tabindex]):focus-visible {
    outline: 2px solid var(--tdb-accent);
}

/* Paliers — container queries sur `tdb` (jamais `@media` : le socle défile, les
   container queries y atteignent donc leurs seuils bas, contrairement à la
   planche qui n'en profite pas faute de défiler). Seuils maison 1100 / 900 /
   640 (16, 13 et 3 occurrences dans cette feuille) ; 768 imposé par
   DESIGN.md §0 (« collapse 1 colonne < 768 px »), non négociable. */

/* > 1100 : 12 colonnes, spans tels que déclarés — rien à écrire, c'est le défaut. */

/* ≤ 1100 : grille à 8 colonnes — --3 et --4 passent à 4/8 ; --6, --8 et --12
   passent à 8/8 (pleine largeur de la nouvelle grille). */
/* ÉTAT OCCUPÉ (audit UI/UX, 2026-09-15). Deux décisions, et la première est la plus coûteuse à
   défaire plus tard : la GÉOMÉTRIE EST GELÉE. On atténue les bandes, on ne les remplace pas par
   des squelettes — la page défile, et douze blocs qui recollapsent font perdre la position de
   défilement à chaque clic de filtre, donc ce que l'utilisateur regardait. Les squelettes des
   sept blocs restent le bon vecteur pour le PREMIER chargement, où il n'y a rien à préserver.
   Seconde décision, le DÉLAI de 300ms : sans lui, un filtre qui répond en 80ms produit un
   clignotement — le « tic visuel, pas signal » que DESIGN.md §7 proscrit déjà pour GridEnterCss.
   Ce n'est pas une règle neuve, c'est la même doctrine appliquée au socle. L'atténuation ne
   touche QUE les bandes : l'en-tête reste pleinement lisible et ses filtres restent visibles,
   c'est la page hôte qui les rend inertes en leur passant `Disabled`. */
.isis-tdb--occupe .isis-tdb__bande {
    opacity: 0.55;
    pointer-events: none;
    transition: opacity 120ms ease 300ms;
}
/* Point d'annonce unique. Toujours dans le DOM (cf. IsisDashboard.razor), donc vide la plupart
   du temps : `:empty` le retire du flux pour qu'il ne réserve aucune hauteur dans le bandeau. */
.isis-tdb__statut {
    flex: 1 1 100%;
    margin: 0;
    font-size: var(--isis-fs-sm);
    color: var(--tdb-ink-muted);
}
/* `display: none` SORTIRAIT la region de l'arbre d'accessibilite (constat de revue, 2026-09-16) :
   elle y reviendrait EN MEME TEMPS que son texte, soit exactement le cas « region creee avec son
   contenu » que le commentaire d'IsisDashboard dit eviter — l'annonce n'est alors pas fiable.
   Le masquage doit donc laisser l'element RENDU. Il est necessaire : `.isis-tdb__bandeau` est en
   `flex-wrap` avec `gap`, et ce <p> est `flex: 1 1 100%` — vide, il couterait quand meme sa
   gouttiere. Patron `sr-only` standard. */
.isis-tdb__statut:empty {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
}

@container tdb (max-width: 1100px) {
    .isis-tdb__bande { grid-template-columns: repeat(8, minmax(0, 1fr)); }
    .isis-tdb__bloc--3  { grid-column: span 4; }
    .isis-tdb__bloc--4  { grid-column: span 4; }
    .isis-tdb__bloc--6,
    .isis-tdb__bloc--8,
    .isis-tdb__bloc--12 { grid-column: span 8; }
}
/* ≤ 900 : deux blocs par ligne au plus — les petits blocs (--3/--4) se
   pairent sur une grille à 2 colonnes, les grands (--6/--8/--12) prennent la
   ligne entière seuls. */
@container tdb (max-width: 900px) {
    .isis-tdb__bande { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .isis-tdb__bloc--3,
    .isis-tdb__bloc--4  { grid-column: span 1; }
    .isis-tdb__bloc--6,
    .isis-tdb__bloc--8,
    .isis-tdb__bloc--12 { grid-column: span 2; }
}
/* ≤ 768 : une seule colonne (DESIGN.md §0, exigence dure). Les spans sont
   réécrits en `1 / -1` et non `span 1` : sur un `grid-template-columns` à une
   seule piste EXPLICITE, un `span N > 1` hérité d'un palier plus large créerait
   des pistes implicites et romprait la colonne unique. */
@container tdb (max-width: 768px) {
    .isis-tdb__bande { grid-template-columns: minmax(0, 1fr); }
    .isis-tdb__bloc--3,
    .isis-tdb__bloc--4,
    .isis-tdb__bloc--6,
    .isis-tdb__bloc--8,
    .isis-tdb__bloc--12 { grid-column: 1 / -1; }
    .isis-tdb__filtres { flex-direction: column; align-items: stretch; }
    /* En colonne, chaque filtre plaçait son contrôle juste après son libellé, dont la largeur
       varie (« Période » / « Vue » / « Entreprise ») : les trois contrôles démarraient à des
       abscisses différentes (mesuré ≈68 / 47 / 83px sur `tdb9-900-light.png`), l'œil n'avait
       rien sur quoi s'aligner. Une gouttière commune ferme l'escalier. */
    .isis-dfiltre { display: grid; grid-template-columns: 6rem minmax(0, 1fr); align-items: center; }
    /* L'EN-TÊTE SORT DU COLLANT ICI, et non à 640 comme la ronde précédente le posait.
       Le seuil avait été choisi sur la mauvaise variable : la raison de décoller est la HAUTEUR
       de l'en-tête, et cette hauteur saute au palier où les filtres s'EMPILENT — c'est-à-dire
       ici, à 768. Entre les deux paliers l'en-tête était donc à la fois empilé ET figé :
       mesuré ~285px sur `tdb9-900-light.png`, soit plus d'un tiers d'un écran de 768px de haut,
       confisqué en permanence. Et ce n'est pas un cas de bord : le rail de navigation occupe
       280px fixes, donc une FENÊTRE de 1024px — la plus banale du parc — ne donne que 744px de
       conteneur et tombait dans cette bande. La mesure de ~344px invoquée par l'ancien
       commentaire avait été prise à 420px, une largeur qui ne correspond à rien de réel ici
       (le rail ne se repliant pas, la capture « 420 » montre un conteneur de ~140px). */
    .isis-tdb__entete { position: static; }
    /* Le titre prend sa PROPRE ligne dès 768 (et non 640 comme avant) : avec le
       contenu réel d'un bandeau — sous-titre, fraîcheur et TROIS actions — il ne
       lui restait plus que 240px pour 339px de texte, donc « Tableau de bord —
       socle n… ». Trouvé en portant la maquette au markup réel : elle n'avait
       jamais porté que deux actions et aucun sous-titre, et affirmait donc une
       géométrie que le produit ne rend pas. */
    .isis-tdb__bandeau-titre { flex: 1 1 100%; white-space: normal; overflow: visible; text-overflow: clip; }
}
/* ≤ 640 : une colonne, gouttières et rembourrages resserrés — bandeau sur
   2 lignes (ronde 1/5) : sur cette largeur, fraîcheur + actions occupaient
   toute la place et réduisaient le titre à quelques caractères (« Tabl… »),
   alors même que ce titre dit de quelle page il s'agit. Masquer la fraîcheur
   était l'autre option, écartée : elle évite le piège du faux temps réel
   (benchmark).
   L'EN-TÊTE ENTIER sort du collant (`position: static`, désormais posé au palier
   768 ci-dessus) — pas les filtres seuls, comme le faisait la version d'avant la
   fusion. La différence
   est tout sauf cosmétique : sortir UNE des deux boîtes collantes obligeait
   l'autre à connaître sa hauteur (`--tdb-bandeau-h`), et c'est ce couplage qui
   a produit 37px de recouvrement trois rondes durant. Ici il n'y a plus qu'une
   boîte : la sortir ne laisse rien à accorder avec personne.
   Pourquoi la sortir : un en-tête empilé pèse ~285px, figés en permanence.
   Savoir de quelle page il s'agit ne vaut pas un tiers de l'écran.
   CORRECTION (audit UI/UX, 2026-09-15) : la sortie du collant est REMONTÉE au
   palier 768 ci-dessus, qui couvre aussi celui-ci — il n'y a donc plus rien à
   redire ici. L'ancienne justification s'appuyait sur une mesure prise à 420px,
   largeur qui ne correspond à aucun rendu réel (le rail ne se replie pas). */
@container tdb (max-width: 640px) {
    .isis-tdb { gap: var(--isis-space-md); }
    .isis-tdb__bande { gap: var(--isis-space-sm); padding: 0 var(--isis-space-sm); }
    .isis-tdb__bloc { padding: var(--isis-space-sm); }
    .isis-tdb__bandeau,
    .isis-tdb__filtres { padding: var(--isis-space-xs) var(--isis-space-sm); }
    .isis-tdb__bandeau { align-content: center; }
    /* Le titre sur sa propre ligne est désormais posé dès 768px (palier ci-dessus,
       qui s'applique aussi ici) — rien à répéter. */
}

/* ════════════════════════════════════════════════════════════════════════════
   TABLEAU DE BORD — trois premiers blocs du socle (lot 6, 2026-09-14) :
   DashKpi, DashSerie, DashRepartition. Sous-préfixes dédiés `isis-dkpi-`,
   `isis-dserie-`, `isis-drep-` (un bloc = un sous-préfixe, cf. `isis-tdb-`
   ci-dessus) — tokens `--tdb-*` du bloc précédent réemployés tels quels,
   aucun nouveau token de couleur/typo introduit ici.
   Brief : .superpowers/sdd/2026-09-14-tableaux-de-bord-socle-neutre/lot-6-brief.md.
   ════════════════════════════════════════════════════════════════════════════ */

/* ── DashKpi ──────────────────────────────────────────────────────────────────
   Le composant rend un <a> ; `.isis-tdb__bloc` fournit déjà le cadre (fond, filet,
   ombre, rayon) — :has() lui retire son propre padding pour que le survol/focus de
   l'ancre couvre la LARGEUR ENTIÈRE du bloc plutôt que de dessiner un second cadre
   imbriqué, et le padding est rendu au titre et à l'ancre séparément (règles
   ci-dessous).
   ATTENTION — CE QUI A CHANGÉ LE 2026-09-15 (unification du titre) : le titre n'est plus
   DANS l'ancre — c'est IsisDashboard qui le rend, au-dessus, depuis le descripteur
   du bloc. L'ancre ne couvre donc plus le bandeau du titre. C'est délibéré : ce qui
   se teinte au survol est exactement ce qui est cliquable, et une poignée de
   réagencement posée plus tard sur l'en-tête de la carte (lot 11) ne sera pas
   avalée par la zone de clic. L'alternative — un `::after` tendu sur toute la carte
   — aurait gardé le titre cliquable au prix d'une affordance empruntée, d'un
   recouvrement de tout futur contrôle et de la sélection du texte.
   PAS d'`overflow: hidden` ici (corrigé après capture) : un premier jet l'avait
   posé pour arrondir le fond de survol au rayon du bloc parent, et ça coupait
   AUSSI l'anneau `:focus-visible` du lot 4 (`outline-offset: 2px` déborde de la
   boîte de `.isis-dkpi`, donc du bloc — invisible au clavier bien que la valeur
   calculée de `outline` restait correcte, trouvé en capturant un focus RÉEL au
   clavier, pas un `.focus()` JS). `.isis-dkpi { border-radius: inherit }`
   suffit : le fond de survol est déjà peint sur SA PROPRE boîte, donc déjà
   rond sans avoir besoin de clipper le parent. */
.isis-tdb__bloc:has(> .isis-dkpi) {
    padding: 0;
}
/* Le padding retiré au bloc est rendu à ses deux enfants SÉPARÉMENT — c'est ce qui
   aligne le titre et la valeur sur la même gouttière (même `--isis-space-md` à
   gauche) tout en laissant la teinte de survol de l'ancre filer d'un bord à
   l'autre. Pas de padding vertical entre les deux : le `gap` de `.isis-tdb__bloc`
   s'en charge, comme pour les six autres blocs. */
.isis-tdb__bloc:has(> .isis-dkpi) > .isis-tdb__bloc-titre {
    padding: var(--isis-space-md) var(--isis-space-md) 0;
}
.isis-dkpi {
    display: flex;
    flex-direction: column;
    gap: var(--isis-space-xs);
    /* `flex: 1` et non `height: 100%` : le bloc est maintenant un conteneur flex en
       colonne dont le titre occupe une part. `height: 100%` s'y résoudrait sur la
       hauteur ENTIÈRE du bloc et déborderait de la hauteur du titre — l'ancre
       dépassait sous le filet de la carte. `flex: 1` prend ce qui reste, donc la
       teinte de survol descend toujours jusqu'au bas de la carte quand la bande
       étire le bloc sur son voisin le plus haut. */
    flex: 1;
    min-height: 44px; /* cible tactile, DESIGN.md */
    box-sizing: border-box;
    padding: 0 var(--isis-space-md) var(--isis-space-md);
    /* Bas seulement : depuis que le titre est rendu au-dessus par le socle, l'ancre ne touche
       plus que les deux coins BAS de la carte. `border-radius: inherit` arrondissait aussi ses
       coins hauts, au milieu du bloc — deux encoches blanches visibles dès que la teinte de
       survol s'allumait. */
    border-radius: 0 0 var(--tdb-radius) var(--tdb-radius);
    color: inherit;
    text-decoration: none;
    transition: background-color 140ms ease;
}
.isis-dkpi:hover {
    background: var(--isis-current-mod-soft, var(--isis-accent-soft));
}
/* La COULEUR de l'anneau vient de la règle plancher `.isis-tdb :where(a, button,
   [tabindex]):focus-visible` (lot 4, corrigée 2026-09-15) ; l'OFFSET est décidé ici,
   puisque cette règle n'en pose plus aucun. `-2px` (anneau INSCRIT dans la boîte) :
   `.isis-dkpi` remplit `.isis-tdb__bloc` jusqu'à son filet — un anneau posé à
   l'extérieur passerait sous la bordure du bloc et, dès qu'un bloc KPI se
   retrouverait dans un conteneur à `overflow` calculé (`.isis-tdb__bloc-large`),
   serait tout simplement rogné. Même valeur que `.isis-grid__row:focus-visible`,
   la norme du dépôt. */
.isis-dkpi:focus-visible {
    outline-offset: -2px;
}
/* États non nominaux (alignement du contrat d'état, 2026-09-15) : le bloc n'est
   plus un <a> mais un <div> — même classe `.isis-dkpi`, pour que
   `.isis-tdb__bloc:has(> .isis-dkpi)` continue de retirer le padding du bloc
   (le sélecteur porte sur la CLASSE, pas sur le nom de balise). `--etat` ne fait
   qu'annuler ce qu'un <div> n'a pas à porter : le curseur et le survol d'un lien.
   Mêmes couleurs d'erreur/de vide que les six autres blocs. */
.isis-dkpi--etat {
    cursor: default;
}
.isis-dkpi--etat:hover {
    background: transparent;
}
.isis-dkpi__erreur {
    margin: 0;
    color: var(--isis-danger);
    font-size: var(--isis-fs-sm);
}
.isis-dkpi__vide {
    margin: 0;
    color: var(--tdb-ink-soft);
    font-size: var(--isis-fs-sm);
}
/* `--isis-fs-xl` (1.4rem / 22,4px) et NON un neuvième cran maison : la valeur
   précédente, 1,5rem en dur, tombait entre deux marches de l'échelle du dépôt
   (--isis-fs-xl 1.4 / --isis-fs-2xl 1.75) et échappait à design-lint, qui
   exempte cette feuille des règles de valeur en dur. Créer `--isis-fs-kpi` à
   1,5rem aurait officialisé la dispersion que l'échelle a justement rabattue
   (~45 valeurs rem éparses avant sa mise en place, cf. l'en-tête du bloc de
   tokens) pour 1,6px d'écart visuel. Un cran EXISTANT couvre le besoin. */
.isis-dkpi__valeur {
    font-size: var(--isis-fs-xl);
    font-weight: 700;
    letter-spacing: -.02em;
    line-height: 1.1;
    color: var(--tdb-ink);
}
/* « Zéro ≠ mesure » vaut aussi pour la valeur elle-même : une valeur ABSENTE
   s'écrit « — » atténuée, jamais avec le même poids visuel qu'une vraie mesure. */
.isis-dkpi__valeur--absente {
    color: var(--tdb-ink-soft);
    font-weight: 600;
}
.isis-dkpi__ecart {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--isis-space-xs);
    font-size: var(--isis-fs-sm);
}
.isis-dkpi__ecart-icone {
    font-size: 16px;
    line-height: 1;
}
.isis-dkpi__ecart-val {
    font-family: var(--isis-font-mono);
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}
/* Libellé de ton TOUJOURS visible, redondant avec l'icône ET la couleur — la
   règle DESIGN.md:846 (« le ton ne se lit jamais par la couleur seule ») est
   ainsi respectée même pour un daltonisme qui neutralise l'icône. Doublé côté
   lecteur d'écran par le span `.isis-sr-only` du markup (aria-hidden ici pour
   ne pas l'annoncer deux fois). */
.isis-dkpi__ecart-ton {
    color: var(--tdb-ink-muted);
}
.isis-dkpi__ecart-ctx {
    color: var(--tdb-ink-soft);
}
.isis-dkpi__ecart--bon .isis-dkpi__ecart-icone,
.isis-dkpi__ecart--bon .isis-dkpi__ecart-val { color: var(--isis-success); }
.isis-dkpi__ecart--mauvais .isis-dkpi__ecart-icone,
.isis-dkpi__ecart--mauvais .isis-dkpi__ecart-val { color: var(--isis-danger); }
.isis-dkpi__ecart--absent .isis-dkpi__ecart-icone,
.isis-dkpi__ecart--absent .isis-dkpi__ecart-val,
.isis-dkpi__ecart--absent .isis-dkpi__ecart-ton { color: var(--tdb-ink-soft); }

/* ── DashSerie ────────────────────────────────────────────────────────────────
   Chargement : le socle grise à 60 % (même dosage que `.isis-pl-leve__plan`,
   DASHBOARD-DESIGN.md) SANS jamais remplacer le graphe par un spinner — le
   graphe précédent reste visible sous le grisé tant que la page hôte ne vide
   pas Series pendant un rafraîchissement. */
.isis-dserie {
    display: flex;
    flex-direction: column;
    gap: var(--isis-space-sm);
    transition: opacity 140ms ease;
}
.isis-dserie[aria-busy="true"] {
    opacity: .6;
}
.isis-dserie__corps {
    width: 100%;
}
.isis-dserie__vide {
    margin: 0;
    padding: var(--isis-space-lg) var(--isis-space-md);
    text-align: center;
    background: var(--tdb-paper);
    border: 1px dashed var(--tdb-rule);
    border-radius: var(--tdb-radius);
    color: var(--tdb-ink-soft);
    font-size: var(--isis-fs-sm);
}
/* Erreur — même encre que `.isis-dchrono__erreur`/`.isis-dcarte__erreur`/`.isis-dnote__erreur`
   (contrat d'état aligné sur les sept blocs, 2026-09-15). Volontairement SANS le cadre
   pointillé du vide ci-dessus : le pointillé dit « zone non levée, voilà quoi faire »
   (DESIGN.md:855-857) — une panne n'est pas une zone à lever. */
.isis-dserie__erreur {
    margin: 0;
    color: var(--isis-danger);
    font-size: var(--isis-fs-sm);
}

/* ── DashRepartition ──────────────────────────────────────────────────────────
   Patron « liste + barre de contribution » (DASHBOARD-DESIGN.md:379), CSS pur
   jusqu'à 8 catégories — cf. commentaire du composant pour le pourquoi. Le
   TRACK (`.isis-drep__track`) reste peint même à 0 % de remplissage : c'est ce
   qui empêche une catégorie à zéro de disparaître visuellement (« barre
   fantôme » — ici, aucune barre n'est jamais totalement absente, seul le
   remplissage varie). `.isis-drep__fill` est le SEUL aplat plein du socle :
   d'où `--tdb-accent-fx`, posé juste au-dessus pour le sombre. */
.isis-drep {
    display: flex;
    flex-direction: column;
    gap: var(--isis-space-sm);
}
.isis-drep__vide {
    margin: 0;
    color: var(--tdb-ink-soft);
    font-size: var(--isis-fs-sm);
}
.isis-drep__erreur {
    margin: 0;
    color: var(--isis-danger);
    font-size: var(--isis-fs-sm);
}
.isis-drep__liste {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: var(--isis-space-xs);
}
.isis-drep__ligne {
    display: grid;
    grid-template-columns: minmax(80px, 1fr) minmax(60px, 2fr) auto;
    align-items: center;
    gap: var(--isis-space-sm);
}
.isis-drep__libelle {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: var(--isis-fs-sm);
    color: var(--tdb-ink);
}
.isis-drep__track {
    position: relative;
    height: 10px;
    border-radius: 999px;
    background: var(--tdb-rule-soft);
    overflow: hidden;
}
.isis-drep__fill {
    display: block;
    height: 100%;
    border-radius: inherit;
    background: var(--tdb-accent-fx, var(--tdb-accent));
    transition: width 160ms ease;
}
.isis-drep__valeur {
    text-align: right;
    white-space: nowrap;
    font-size: var(--isis-fs-sm);
    color: var(--tdb-ink);
}
.isis-drep__amc {
    width: 100%;
}

/* Paliers du lot 6 — mêmes seuils maison que le socle (cf. plus haut), gap et
   colonnes resserrés là où une carte plus étroite (--3/--4 repassés pleine
   largeur restent inchangés, seul le CONTENU interne des blocs se resserre). */
@container tdb (max-width: 640px) {
    .isis-dkpi { padding: var(--isis-space-sm); }
    .isis-drep__ligne { grid-template-columns: minmax(64px, 1fr) minmax(48px, 1.4fr) auto; gap: var(--isis-space-xs); }
}

/* ── DashListe (lot 7a, 2026-09-15) ──────────────────────────────────────────
   Sous-préfixe `isis-dlist-`, mêmes tokens `--tdb-*` que les trois blocs
   ci-dessus. Consomme `.isis-grid` telle quelle (norme du dépôt) : les règles
   ci-dessous ne redéfinissent NI `.isis-grid`, NI `.isis-grid__row`,
   NI `.isis-grid__head` dans l'absolu — elles les surchargent uniquement sous
   `.isis-dlist`, pour les adapter au conteneur de défilement dédié
   `.isis-tdb__bloc-large` (cf. commentaire de tête de DashListe.razor).
   Brief : .superpowers/sdd/2026-09-14-tableaux-de-bord-socle-neutre/lot-7a-brief.md. */
.isis-dlist {
    display: flex;
    flex-direction: column;
    gap: var(--isis-space-sm);
    min-width: 0;
}
/* Plafond : jamais silencieux (docs/DASHBOARD-DESIGN.md:240) — texte visible, pas
   seulement une troncature muette de la liste. */
.isis-dlist__plafond {
    margin: 0;
    font-size: var(--isis-fs-sm);
    color: var(--tdb-attente);
}
.isis-dlist__vide {
    margin: 0;
    color: var(--tdb-ink-soft);
    font-size: var(--isis-fs-sm);
}
.isis-dlist__erreur {
    margin: 0;
    color: var(--isis-danger);
    font-size: var(--isis-fs-sm);
}

/* `.isis-grid` ne scrolle plus PAR LUI-MÊME sous DashListe : c'est
   `.isis-tdb__bloc-large` (parent direct ici) qui porte `overflow-x: auto` et
   le fondu de bord. Un `.isis-grid` qui garderait son `overflow: auto` par
   défaut déclencherait SON PROPRE scroll interne, désynchronisé du fondu peint
   sur le parent — le contenu défilerait, mais pas l'ombre qui est censée en
   témoigner. Cadre propre retiré (border/ombre/rayon) : la carte
   `.isis-tdb__bloc` fournit déjà un cadre, en dessiner un second par-dessus
   est exactement l'anti-patron déjà écarté par DashKpi (isis-theme.css:50009). */
.isis-dlist__grid {
    overflow: visible;
    border: none;
    border-radius: 0;
    background: transparent;
    box-shadow: none;
    flex: initial;
    min-height: 0;
}
/* Plus de scroll local ⇒ plus de raison de coller l'en-tête à un haut de
   viewport qui n'est pas le sien (sticky top:0 se fixerait au scroll de LA
   PAGE hôte, pas à celui — inexistant ici — de ce bloc). */
.isis-dlist__grid .isis-grid__head {
    position: static;
    z-index: auto;
}
/* Wrapper role="rowgroup" des lignes de données (structure DOM pour les lecteurs d'écran,
   role="table"/"row"/"cell"/"rowgroup" exigés par ce lot) : `display: contents` le retire de
   la mise en page pour que `.isis-grid__row` reste un enfant FLEX DIRECT de `.isis-grid`, sans
   quoi `flex-shrink: 0` de `.isis-grid__row` (isis-theme.css:11936, le bug documenté juste à
   côté) ne s'appliquerait plus — un wrapper intercalé casse ce contrat. Classe et non style
   inline : c'est une valeur FIXE, jamais une donnée fournie par l'appelant (à la différence du
   gabarit, cf. DashListe.razor). */
.isis-dlist__rowgroup {
    display: contents;
}
/* `.isis-grid__head, .isis-grid__row` portent un `min-width: 1000px` GLOBAL
   (isis-theme.css:10920, pensé pour la grille pleine page historique) : sans
   cette surcharge à 0, un gabarit à deux colonnes (cas d'usage « inerte » du
   brief, ex. `140px 1fr`) serait quand même étiré à 1000px et défilerait pour
   rien. `min-width: 0` restaure le calcul NATUREL des pistes du gabarit
   (fourni par l'appelant, cf. DashListe.razor) : les pistes en px fixes
   gardent leur taille, `minmax()` respecte son plancher et peut croître —
   c'est ce qui pousse `.isis-tdb__bloc-large` à défiler quand la somme des
   pistes dépasse la largeur du bloc, sans second paramètre redondant avec
   `Gabarit`.
   ⚠ PAS `min-width: max-content` (essayé puis retiré, capture à l'appui) :
   `max-content` calcule la largeur nécessaire pour ne JAMAIS tronquer le texte
   d'aucune cellule — ce qui désactive l'ellipse de `.isis-grid__row > div`
   partout où une cellule `minmax()`/`1fr` porte un texte plus long que son
   plancher, et fait défiler un bloc qui n'aurait jamais dû l'être (mesuré sur
   « Échéances de facturation », 4 colonnes, gabarit `minmax(180px, 1.6fr)` :
   « Échéance dépassée de 14 jours » poussait la ligne hors du bloc et
   coupait « MONTANT » en « MONTAN » sur la capture). */
.isis-dlist__grid .isis-grid__head,
.isis-dlist__grid .isis-grid__row {
    min-width: 0;
}

/* Ligne non cliquable (Href null) : même neutralisation du hover « cliquable »
   que `.isis-grid__row.isis-offer-subtotal:hover` (isis-theme.css:6811) — cette
   ligne n'est pas interactive, son curseur doit le dire. */
.isis-grid__row.isis-dlist__row--inerte {
    cursor: default;
}
.isis-grid__row.isis-dlist__row--inerte:hover {
    background: var(--isis-surface);
}

/* Ton d'une ligne — fond teinté à 4 %, même dosage que `.isis-grid__row--alert`
   (isis-theme.css:25128). Neutre et PasDeMesure n'ont VOLONTAIREMENT aucun fond
   ici : le badge (ci-dessous) suffit à les distinguer, et Neutre est l'état par
   défaut d'une ligne sur trois — lui donner un fond en ferait un bruit visuel
   permanent plutôt qu'un signal. */
.isis-grid__row.isis-dlist__row--bon {
    background: linear-gradient(to right,
        color-mix(in srgb, var(--isis-success) 4%, transparent) 0%,
        transparent 60%);
}
.isis-grid__row.isis-dlist__row--mauvais {
    background: linear-gradient(to right,
        color-mix(in srgb, var(--isis-danger) 4%, transparent) 0%,
        transparent 60%);
}

/* `.isis-dlist__ref` (référence de la ligne, cf. markup) ne porte AUCUNE règle ici — elle
   hérite telle quelle de `.isis-grid__row > div` (overflow/ellipsis/nowrap) comme un span
   normal, et doit rester TOUJOURS affichée en entier avant que le badge de ton ne cède la
   place (ronde 1/5, capture à l'appui : l'ordre inverse la rognait à zéro pixel). La classe
   existe pour nommer l'intention dans le markup, pas pour porter du style.
   Elle n'est posée QUE sur la première cellule (corrigé 2026-09-15) : c'est la seule qui soit
   une « référence », et la seule devant laquelle le badge de ton vient se ranger. Elle était
   posée sur TOUTES les cellules — sans effet visible, faute de règle, mais en nommant une
   intention fausse sur N−1 d'entre elles.

   Badge de ton — pictogramme + libellé TOUJOURS visible (jamais la couleur
   seule, DESIGN.md:846), posé dans la première cellule de la ligne, APRÈS la référence
   (cf. DashListe.razor pour le pourquoi). Même vocabulaire visuel que
   `.isis-dkpi__ecart*` (isis-theme.css:50071-50104) : icône colorée, texte en
   encre neutre.
   `display: inline` et NON `inline-flex` (ronde 1/5, capture à l'appui) : un `inline-flex` est
   une boîte atomique — le navigateur ne peut pas y insérer l'ellipse de
   `.isis-grid__row > div` quand la cellule déborde, il la fait juste disparaître en entier.
   En `inline`, c'est le TEXTE du badge qui s'ellipse au caractère, jamais la référence qui le
   précède (déjà passée, donc déjà comptée en entier par le navigateur). Pas de `gap` (invalide
   sur `inline`) : l'espacement icône/texte passe par une marge sur l'icône. */
.isis-dlist__ton {
    display: inline;
    white-space: nowrap;
    margin-left: var(--isis-space-xs);
}
.isis-dlist__ton-icone {
    font-size: 14px;
    line-height: 1;
    vertical-align: -2px;
    margin-right: 0.2rem;
}
.isis-dlist__ton-texte {
    color: var(--tdb-ink-muted);
    font-size: var(--isis-fs-sm);
}
.isis-dlist__ton--bon .isis-dlist__ton-icone { color: var(--isis-success); }
.isis-dlist__ton--mauvais .isis-dlist__ton-icone { color: var(--isis-danger); }
.isis-dlist__ton--absent .isis-dlist__ton-texte { color: var(--tdb-ink-soft); }

/* Colonnes numériques : alignées à droite, en mono avec chiffres tabulaires
   (docs/DASHBOARD-DESIGN.md:59 ; `.isis-tdb__valeur` fait la même chose pour
   les KPI). Pas de règle générique `.isis-grid__col-num` ici : cette classe
   n'a pas de style de base dans cette feuille (chaque page le redéfinit sous
   son propre modificateur `.isis-grid--<page>`) — DashListe n'en a pas et
   porte donc son propre nom de classe, scopé sous `.isis-dlist`. */
.isis-dlist__grid .isis-dlist__head-cell--num {
    justify-content: flex-end;
}
.isis-dlist__cellule--num {
    text-align: right;
    font-family: var(--isis-font-mono);
    font-variant-numeric: tabular-nums;
}

/* ── DashChrono / DashCarte / DashNote (lot 8, 2026-09-15) ───────────────────
   Sous-préfixes `isis-dchrono-`/`isis-dcarte-`/`isis-dnote-`, mêmes tokens `--tdb-*`.
   Brief : .superpowers/sdd/2026-09-14-tableaux-de-bord-socle-neutre/lot-8-brief.md.

   DashChrono PORTE le HTML/CSS de PlancheTimeline (`.isis-pl-tl*` ci-dessous, isis-theme.css
   ~50750) SANS ses tokens `--pl-*` — déclarés UNIQUEMENT sur `.isis-planche-page`/`.isis-vq`
   (piège mesuré : hors de ces ancêtres ils sont indéfinis, et une variable CSS inconnue ne lève
   AUCUNE erreur — rendu sans police mono, sans encre, sans filets, rien pour le signaler).
   Correspondances : --pl-ink → --tdb-ink ; --pl-ink-2 → --tdb-ink-muted ; --pl-rule-soft →
   --tdb-rule-soft ; --pl-accent → --tdb-accent ; --pl-paper → --tdb-paper ; --pl-mono →
   var(--isis-font-mono) directement (déjà le choix de .isis-tdb__valeur, ligne ~49749 — même
   police que --isis-cockpit-mono sur ses deux définitions, aucun nouveau token nécessaire).
   --pl-ink-3 → --tdb-ink-muted ÉGALEMENT, pas --tdb-ink-soft : sur SES DEUX sites de
   déclaration (`.isis-planche-page` ET `.isis-vq`), --pl-ink-3 vaut MOT POUR MOT
   var(--isis-text-muted), la valeur EXACTE de --pl-ink-2 — le nommage suggère un troisième
   palier d'atténuation, il n'y en a pas ; --tdb-ink-soft porte une AUTRE valeur
   (--isis-text-soft) et l'y substituer aurait changé le contraste de l'axe des mois.
   Résultat vérifié : ZÉRO token ajouté sur `.isis-tdb` — cette région, recettée sur 12
   combinaisons, n'a pas eu besoin d'être rouverte.
   Barre pleine en `--tdb-accent-fx` (aplat, même dosage que .isis-drep__fill ligne ~50201 : en
   sombre, --isis-current-mod est déjà une teinte éclaircie, pâle en aplat). Barre hachurée en
   teinte NEUTRE `color-mix(in srgb, var(--tdb-ink) 45%, transparent)` FIGÉE dans la feuille —
   aucun paramètre ne l'expose (le hachuré signifie « projeté / engagé non consommé », jamais un
   avertissement : --tdb-attente n'apparaît nulle part ici, cf. DESIGN.md:852-853).
   Lignes à 44px (cible tactile, contre 30px chez PlancheTimeline — celui-ci reste inchangé,
   cette hauteur n'est due qu'à DashChrono). */
.isis-dchrono { display: flex; flex-direction: column; gap: var(--isis-space-sm); }
.isis-dchrono__vide { margin: 0; color: var(--tdb-ink-soft); font-size: var(--isis-fs-sm); }
.isis-dchrono__erreur { margin: 0; color: var(--isis-danger); font-size: var(--isis-fs-sm); }
/* min-width : plancher de lisibilité (12 colonnes d'axe + piste, cf. commentaire de tête du
   composant) — sous `.isis-tdb__bloc-large`, qui prend le défilement horizontal à sa charge
   plutôt que de laisser le flex écraser l'axe à quelques pixels (mesuré : ~12px d'axe pour un
   container réduit à ~105px par le rail de navigation à 420px de VIEWPORT, même dette que
   DashListe lot 7a — le container RÉEL, pas le viewport, est ce qui compte ici). */
.isis-dchrono__corps { display: flex; flex-direction: column; min-height: 0; min-width: 480px;
    font-family: var(--isis-font-mono); }
.isis-dchrono__head { display: flex; align-items: flex-end; padding: 2px 0 4px; }
/* `position: sticky; left: 0` : sous le défilement horizontal de `.isis-tdb__bloc-large`, seuls
   l'axe et les pistes défilent — la colonne de libellés reste épinglée, comme la référence d'une
   ligne DashListe reste toujours visible avant son badge de ton. Fond OPAQUE (`--tdb-paper`,
   identique à celui de `.isis-tdb__bloc`) : sans lui, les barres/repères défilés se liraient EN
   TRANSPARENCE sous le libellé épinglé. */
.isis-dchrono__lbl { flex: 0 0 172px; width: 172px; padding-right: 10px; text-align: right; font-size: 12px;
    color: var(--tdb-ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    position: sticky; left: 0; z-index: 1; background: var(--tdb-paper); }
.isis-dchrono__axis { flex: 1 1 auto; display: grid; grid-template-columns: repeat(12, 1fr); align-items: end; }
/* Exception typographique nommée par sélecteur, docs/DASHBOARD-DESIGN.md:114-115 — étendue à ce
   sélecteur, seule exception à la doctrine "12px minimum" avec `.isis-pl-tl__axis span`. */
.isis-dchrono__axis span { font-size: 11px; letter-spacing: .06em; color: var(--tdb-ink-muted); text-align: center;
    border-left: 1px solid var(--tdb-rule-soft); padding-bottom: 2px; white-space: nowrap; overflow: hidden; min-width: 0; }
.isis-dchrono__axis span small { display: block; font-size: inherit; color: var(--tdb-ink-muted); }
.isis-dchrono__body { position: relative; display: flex; flex-direction: column; }
.isis-dchrono__row { display: flex; align-items: center; height: 44px; text-decoration: none; color: inherit;
    border-bottom: 1px solid var(--tdb-rule-soft); }
.isis-dchrono__row:hover .isis-dchrono__lbl, .isis-dchrono__row:focus-visible .isis-dchrono__lbl {
    color: var(--tdb-accent); text-decoration: underline; }
/* `outline-offset: -2px` — anneau INSCRIT dans la ligne. La règle plancher du socle
   (`.isis-tdb :where(...)`, ligne ~49918) ne pose plus aucun offset justement pour que
   celui-ci s'applique : tant qu'elle était en `:is()` (0,3,0) elle battait cette règle
   (0,2,0) et rendait 2px, un anneau posé HORS de la ligne — donc rogné par le
   `overflow-x: auto` de `.isis-tdb__bloc-large`, le conteneur direct de ce corps.
   Même valeur que `.isis-grid__row:focus-visible`, la norme du dépôt. */
.isis-dchrono__row:focus-visible { outline: 2px solid var(--tdb-accent); outline-offset: -2px; }
/* Ligne sans Href : rendue en <div>, pas en <a> (cf. DashChrono.razor). Elle n'a donc ni
   curseur de lien ni focus — reste la neutralisation du survol, qui autrement laisserait
   croire à une cible cliquable. Même patron que `.isis-dlist__row--inerte`. */
.isis-dchrono__row--inerte { cursor: default; }
.isis-dchrono__row--inerte:hover .isis-dchrono__lbl { color: var(--tdb-ink); text-decoration: none; }
.isis-dchrono__lane { position: relative; flex: 1 1 auto; height: 100%; border-left: 1.2px solid var(--tdb-ink); }
.isis-dchrono__bar { position: absolute; top: 13px; height: 18px; border: 1px solid var(--tdb-accent);
    box-sizing: border-box; display: block; }
.isis-dchrono__bar b { position: absolute; left: 0; top: 0; bottom: 0; display: block; opacity: .85;
    background: var(--tdb-accent-fx, var(--tdb-accent)); }
.isis-dchrono__bar.is-hachuree { border-style: dashed; border-color: color-mix(in srgb, var(--tdb-ink) 45%, transparent); }
.isis-dchrono__bar.is-hachuree b { background: color-mix(in srgb, var(--tdb-ink) 45%, transparent); }
.isis-dchrono__mk { position: absolute; top: 17px; width: 10px; height: 10px; margin-left: -5px; transform: rotate(45deg);
    border: 1px solid var(--tdb-paper); display: block; }
.isis-dchrono__mk--ok { background: var(--isis-success); } .isis-dchrono__mk--warn { background: var(--isis-warning); }
.isis-dchrono__mk--bad { background: var(--isis-danger); } .isis-dchrono__mk--neutral { background: var(--tdb-ink-muted); }
.isis-dchrono__over { position: absolute; top: 0; bottom: 0; left: 172px; right: 0; pointer-events: none; }
.isis-dchrono__today { position: absolute; top: 0; bottom: 0; border-left: 1.2px dashed var(--isis-danger); }
.isis-dchrono__today em { position: absolute; bottom: 2px; left: 4px; font-style: normal; font-size: 12px;
    color: var(--isis-danger); white-space: nowrap; }
@container tdb (max-width: 640px) {
    .isis-dchrono__lbl { flex-basis: 96px; width: 96px; }
    .isis-dchrono__over { left: 96px; }
}

/* DashCarte — AmChartKind.HealthMap uniquement, PAS les basemaps Leaflet (cf. commentaire du
   composant). État "sans point" hachuré, patron `.isis-pl-vide--inset` (ligne ~50781) porté sur
   les `--tdb-*` — même diagonale, mêmes proportions, jamais un vide muet. */
.isis-dcarte { display: flex; flex-direction: column; gap: var(--isis-space-sm); }
.isis-dcarte__erreur { margin: 0; color: var(--isis-danger); font-size: var(--isis-fs-sm); }
.isis-dcarte__corps { width: 100%; border: 1px solid var(--tdb-rule); border-radius: var(--tdb-radius);
    overflow: hidden; background: var(--tdb-paper); }
.isis-dcarte__vide {
    padding: var(--isis-space-lg) var(--isis-space-md);
    text-align: center;
    color: var(--tdb-ink-muted);
    font-size: var(--isis-fs-sm);
    border: 1px dashed var(--tdb-rule);
    background: repeating-linear-gradient(45deg, transparent 0 8px, color-mix(in srgb, var(--tdb-rule) 40%, transparent) 8px 9px);
    border-radius: var(--tdb-radius);
}
.isis-dcarte__vide strong { display: block; color: var(--tdb-ink); font-weight: 600; margin-bottom: 2px; }

/* DashNote — observation + pied "Périmètre · Source", PAS d'horodatage (IsisDashboard.razor le
   porte déjà dans le bandeau). Pied porté sur les `--tdb-*`, patron .isis-pl-cartouche__foot
   (ligne ~50922) SANS son fond teinté (ce bloc vit déjà dans .isis-tdb__bloc). */
.isis-dnote { display: flex; flex-direction: column; gap: var(--isis-space-sm); }
.isis-dnote__observation { margin: 0; font-size: 13px; line-height: 1.45; color: var(--tdb-ink); }
.isis-dnote__vide { margin: 0; color: var(--tdb-ink-soft); font-size: var(--isis-fs-sm); }
.isis-dnote__erreur { margin: 0; color: var(--isis-danger); font-size: var(--isis-fs-sm); }
.isis-dnote__foot { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 0;
    padding-top: var(--isis-space-xs); border-top: 1px solid var(--tdb-rule-soft);
    font-size: var(--isis-fs-sm); line-height: 1.35; color: var(--tdb-ink-muted); }
.isis-dnote__foot > * { min-width: 0; overflow-wrap: anywhere; }
.isis-dnote__foot > * + *::before { content: "·"; margin: 0 6px; color: var(--tdb-ink-muted); }
.isis-dnote__foot b { font-weight: 500; color: var(--tdb-ink); }

/* ════════════════════════════════════════════════════════════════════════════
   PLANCHE — monde visuel « Cartouche topographique » (validé 2026-08-26/31,
   maquette docs/mockups/2026-08-26-dashboard-gescom-cartouche.html).
   Le tableau de bord est composé comme une PLANCHE de plan de géomètre : cadre à
   repères, bandeau de titre, colonne légende (planches = vues par profil, symboles,
   échelles = filtres), corps de planche (profil en long, coupes, carte, détails cerclés)
   et CARTOUCHE portant les chiffres-clés. Encre en filets 1px, cotes en mono, feux
   sémantiques, hachures = projet. Aucune ombre, aucune pastille, aucune carte.
   Remplace PULSE sur gescom ; les autres dashboards migreront planche par planche.
   ════════════════════════════════════════════════════════════════════════════ */
.isis-planche-page { --pl-ink: var(--isis-text); --pl-ink-2: var(--isis-text-muted); --pl-ink-3: var(--isis-text-muted);
    --pl-rule: var(--isis-border); --pl-rule-soft: color-mix(in srgb, var(--isis-border) 55%, var(--isis-surface));
    --pl-line: var(--isis-border); --pl-line-strong: color-mix(in srgb, var(--isis-text) 8%, var(--isis-border));
    /* Bordure des CONTRÔLES de planche (boutons, champs, sélecteurs) — WCAG 1.4.11 exige 3:1 sur
       la limite d'un composant d'interface, que --pl-line ne tenait pas (1,47:1 clair, 1,34:1
       sombre, mesurés au navigateur). 50 % d'encre sur le papier : 3,41:1 clair, 4,54:1 sombre.
       Les filets NON interactifs (tables, cadre du cartouche) restent sur --pl-line/-strong. */
    --pl-line-ctrl: color-mix(in srgb, var(--pl-ink) 50%, var(--pl-paper));
    --pl-accent: var(--isis-current-mod, var(--isis-accent)); --pl-accent-soft: var(--isis-current-mod-soft, var(--isis-accent-soft));
    --pl-radius: var(--isis-radius, 10px);
    --pl-exist: var(--isis-current-mod, var(--isis-accent)); --pl-projet: var(--isis-accent);
    --pl-hach: color-mix(in srgb, var(--isis-text) 45%, transparent);
    --pl-paper: var(--isis-surface); --pl-mono: var(--isis-cockpit-mono);
    --pl-exist-fx: var(--pl-exist); --pl-projet-fx: var(--pl-projet);
    /* Encre lisible SUR un fond d'accent. En sombre, l'accent module devient un ton clair
       (--isis-mod-* sombres) : un #fff en dur y tombe sous le seuil de contraste. */
    --pl-on-accent: #ffffff; }
/* Accent RÉEL (polish 2026-09-01) : la page pose style="--pl-exist: #hex; --pl-projet: #hex" depuis
   IPlancheAccentResolver (couleur du module, ou couleur unifiée du tenant) — la même valeur que
   celle donnée aux graphes amCharts. Les règles ci-dessus ne sont que le repli sans style inline.
   Le thème est choisi côté client (isis-theme-mode.js, préférence par utilisateur) : le serveur ne le connaît
   pas, donc l'hex inline est celui du thème clair. En SOMBRE, tout ce que le CSS peint avec l'accent passe par
   --pl-exist-fx / --pl-projet-fx, éclaircis ici (les --isis-mod-* sombres sont des tons clairs, même logique) ;
   les graphes amCharts reçoivent le même hex clair et le rehaussent EUX-MÊMES au rendu (bundle
   isis-amcharts : mélange oklab vers le blanc, teinte conservée, jusqu'à 3:1 sur la surface réelle du
   graphe — une couleur déjà ≥ 3:1 reste intacte). Détail dans docs/DASHBOARD-DESIGN.md. */
:root[data-theme="dark"] .isis-planche-page { --pl-exist-fx: color-mix(in oklab, var(--pl-exist) 70%, white); --pl-projet-fx: color-mix(in oklab, var(--pl-projet) 70%, white);
    /* Vérifié au navigateur (canvas + formule WCAG) : `color-mix(in oklab, var(--pl-ink) 92%, black)`
       tel qu'écrit dans le brief mesure 1,92:1 sur --pl-exist-fx sombre — --pl-ink y résout DÉJÀ en
       ton clair (--isis-text sombre), donc 92 % de ce clair + 8 % de noir reste clair. Opérandes
       inversés : 92 % de noir teinté par --pl-ink (pour l'harmonie de teinte) mesure 7,27:1. */
    --pl-on-accent: color-mix(in oklab, black 92%, var(--pl-ink)); }
.isis-planche-page .isis-rich-toolbar { margin-bottom: 0.6rem; }

.isis-planche { position: relative; background: var(--pl-paper); border: 1px solid var(--pl-line-strong); border-radius: var(--pl-radius); box-shadow: var(--isis-elevation-1); display: flex; flex-direction: column; overflow: hidden; }
.isis-planche::before, .isis-planche::after { content: ""; position: absolute; left: 0; right: 0; height: 6px; pointer-events: none;
    background: repeating-linear-gradient(90deg, color-mix(in srgb, var(--pl-accent) 22%, transparent) 0 1px, transparent 1px 40px); }
.isis-planche::before { top: 0; } .isis-planche::after { bottom: 0; transform: scaleY(-1); }
.isis-planche__repere { position: absolute; top: 0; bottom: 0; width: 6px; pointer-events: none;
    background: repeating-linear-gradient(180deg, color-mix(in srgb, var(--pl-accent) 22%, transparent) 0 1px, transparent 1px 40px); }
.isis-planche__repere--l { left: 0; } .isis-planche__repere--r { right: 0; transform: scaleX(-1); }

/* Bandeau de titre dans le cadre */
.isis-planche__titre { display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: 24px;
    border-bottom: 1px solid var(--pl-line-strong); padding: 10px 22px 10px 30px; }
.isis-planche__no { display: flex; align-items: center; gap: 10px; font-weight: 600; font-size: 12px;
    letter-spacing: 0; padding-right: 24px; border-right: 1px solid var(--pl-line); color: var(--pl-accent); }
.isis-planche__nav { border: 1px solid var(--pl-line-strong); background: var(--pl-paper); width: 26px; height: 26px; border-radius: 6px; cursor: pointer;
    font-size: 12px; color: var(--pl-ink); display: grid; place-items: center; text-decoration: none; }
.isis-planche__nav:hover { background: var(--pl-accent); border-color: var(--pl-accent); color: #fff; }
.isis-planche__nav.is-disabled { opacity: .3; pointer-events: none; }
.isis-planche__nav:focus-visible, .isis-pl-action:focus-visible, .isis-pl-cta:focus-visible, .isis-pl-planches a:focus-visible { outline: 2px solid var(--pl-exist-fx); outline-offset: 2px; }
.isis-planche .is-dimmed { opacity: .45; }
.isis-sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }
.isis-planche__titre h1, .isis-planche__vue { font-size: 15px; font-weight: 600; letter-spacing: -0.1px; margin: 0; color: var(--pl-ink); }
.isis-planche__titre h1 small { font-weight: 400; color: var(--pl-ink-2); text-transform: none; letter-spacing: 0; margin-left: 10px; font-size: 13px; white-space: nowrap; }
.isis-planche__titre h1, .isis-planche__vue { white-space: nowrap; }
@media (max-width: 1500px) { .isis-planche__titre { grid-template-columns: auto 1fr; } .isis-planche__meta { grid-column: 1 / -1; padding-top: 6px; } .isis-planche__meta span:first-child { border-left: 0; padding-left: 0; } }
.isis-planche__meta { display: flex; flex-wrap: wrap; }
/* Note visible sous la méta (ce que le tampon dit dans son title, lisible sans survol). */
.isis-planche__titre > .isis-pl-carte__note { grid-column: 1 / -1; margin: 0; }
.isis-planche__meta span { font-size: 11.5px; letter-spacing: 0; color: var(--pl-ink-2);
    padding: 4px 12px; border-left: 1px solid var(--pl-rule); }
.isis-planche__meta span b { color: var(--pl-ink); font-weight: 600; }
/* Tampons de signal du bandeau (héritiers des pills du header riche, retiré des pages planche
   le 2026-08-31 — le bandeau EST le titre) : cartouche mono à filet ; --lien = actionnable. */
.isis-planche__meta .isis-planche__tampon { font-size: 11.5px; letter-spacing: 0;
    font-weight: 600; border: 1px solid var(--isis-warning); border-radius: 999px; color: var(--isis-warning);
    padding: 3px 10px; margin-left: 12px; align-self: center; white-space: nowrap; }
.isis-planche__meta .isis-planche__tampon b { color: inherit; }
.isis-planche__meta a.isis-planche__tampon--lien { border-color: var(--pl-accent); color: var(--pl-accent); text-decoration: none; cursor: pointer; }
.isis-planche__meta a.isis-planche__tampon--lien:hover { background: var(--pl-accent); color: #fff; }
.isis-planche__meta a.isis-planche__tampon--lien:focus-visible { outline: 2px solid var(--pl-accent); outline-offset: 1px; }

/* Corps : légende | plan | cartouche */
.isis-planche { container-type: inline-size; container-name: planche; }
.isis-planche__corps { display: grid; grid-template-columns: var(--pl-col-legende, 300px) minmax(0, 1fr) var(--pl-col-cartouche, 360px); }
/* Paliers sur la largeur RÉELLE du cadre (container queries, P0 1366 px du 2026-09-01 : à 1366 avec la
   barre latérale, le cadre fait ~1050 px et le plan tombait à 391 px avec 300/360 fixes) :
   ≤ 1100 → légende 220 / cartouche 300 ; ≤ 900 → cartouche sous le corps (pleine largeur, lignes sur
   2 colonnes) ; ≤ 640 → légende repliée au-dessus du plan. */
@container planche (max-width: 1100px) {
    .isis-planche__corps { grid-template-columns: 220px minmax(0, 1fr) 300px; }
    .isis-planche__legende { padding: 16px 16px 16px 22px; gap: 18px; }
    .isis-planche__cartouche-col { padding: 16px 22px 16px 16px; }
    .isis-pl-cartouche__row { grid-template-columns: 96px minmax(0, 1fr); }
    .isis-planche__plan { padding: 16px 18px 24px; }
}
@container planche (max-width: 900px) {
    .isis-planche__corps { grid-template-columns: 220px minmax(0, 1fr); grid-template-rows: minmax(0, 1fr) auto; }
    /* Le cartouche reste UNE colonne sous le corps : deux blocs côte à côte coupaient chiffres et mots en deux
       dans les cartouches à grille interne (cockpit, RH), mesuré le 2026-09-19 entre 704 et 900 px de planche. */
    .isis-planche__cartouche-col { grid-column: 1 / -1; border-left: 0; border-top: 1px solid var(--pl-line); align-items: start; }
    .isis-pl-cartouche { display: grid; grid-template-columns: 1fr 1fr; }
    .isis-pl-cartouche__row { grid-template-columns: 118px minmax(0, 1fr); }
    .isis-pl-cartouche__row:nth-child(odd) { border-right: 1px solid var(--pl-line); }
    .isis-pl-cartouche__row--head, .isis-pl-cartouche__row--obs, .isis-pl-cartouche__foot { grid-column: 1 / -1; border-right: 0; }
}
@container planche (max-width: 640px) {
    .isis-planche__corps { grid-template-columns: 1fr; grid-template-rows: auto minmax(0, 1fr) auto; }
    .isis-planche__legende { border-right: 0; border-bottom: 1px solid var(--pl-line); flex-direction: row; flex-wrap: wrap; gap: 14px 22px; padding: 12px 22px; max-height: 45%; }
    .isis-planche__legende > * { flex: 1 1 200px; min-width: 0; }
    .isis-pl-cartouche { grid-template-columns: 1fr; }
    .isis-pl-cartouche__row:nth-child(odd) { border-right: 0; }
}
.isis-planche__legende { border-right: 1px solid var(--pl-line); padding: 18px 22px 18px 30px; display: flex; flex-direction: column; gap: 22px; }
.isis-planche__plan { position: relative; padding: 18px 24px 26px; display: flex; flex-direction: column; gap: 22px; overflow: hidden; min-width: 0; }
.isis-planche__contours { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; opacity: .38; }
.isis-planche__plan > :not(.isis-planche__contours) { position: relative; }
.isis-planche__plan { container-type: inline-size; }
.isis-planche__cartouche-col { border-left: 1px solid var(--pl-line); display: flex; flex-direction: column; justify-content: space-between; gap: 18px; padding: 18px 30px 18px 18px; }

/* Légende */
.isis-pl-legtitre { font-size: 11.5px; letter-spacing: 0; font-weight: 600;
    border-bottom: 1px solid var(--pl-line); padding-bottom: 6px; margin: 0 0 10px; color: var(--pl-ink-2); }
.isis-pl-planches { display: flex; flex-direction: column; }
.isis-pl-planches a { display: grid; grid-template-columns: 34px 1fr; gap: 10px; align-items: center; padding: 7px 0;
    text-decoration: none; color: var(--pl-ink); border-bottom: 1px solid var(--pl-rule-soft); }
.isis-pl-planches a:hover .isis-pl-planches__nom { text-decoration: underline; }
.isis-pl-planches__no { font-family: var(--pl-mono); font-size: 12px; color: var(--pl-ink-3); }
.isis-pl-planches__nom { font-size: 13px; }
.isis-pl-planches__nom small { display: block; color: var(--pl-ink-3); font-size: 11.5px; line-height: 1.3; }
.isis-pl-planches a.is-active { background: var(--pl-accent-soft); border: 1px solid var(--pl-line-strong); border-radius: 6px; margin: 0 -8px; padding: 6px 8px; }
.isis-pl-planches a.is-active .isis-pl-planches__no { color: var(--pl-ink); font-weight: 600; }
.isis-pl-planches a.is-active .isis-pl-planches__nom { font-weight: 600; }
/* Anneau de focus à opacité 100 % sur --pl-exist (≥ 3:1) — l'ancien box-shadow à 45 % d'alpha passait sous le seuil. */
.isis-pl-planches a:focus-visible { outline: 2px solid var(--pl-exist-fx); outline-offset: 2px; box-shadow: none; }
.isis-pl-symb { display: flex; flex-direction: column; gap: 7px; }
.isis-pl-symb div { display: grid; grid-template-columns: 34px 1fr; gap: 10px; align-items: center; font-size: 12px; color: var(--pl-ink); }
/* Note de legende : d'ou vient la cible d'une bande (EF-76). Muet comme un sous-texte. */
.isis-pl-legnote { margin: 10px 0 0; font-size: 12px; line-height: 1.45; color: var(--pl-ink-3); }
.isis-pl-sw { height: 12px; border: 1px solid var(--pl-line); }
.isis-pl-sw--exist { background: var(--pl-exist-fx); border-color: var(--pl-exist-fx); }
/* Projet en PLEIN (série tracée en --pl-projet, pas une hachure) : remplace les swatches inline `background: {ProjetHex}`. */
.isis-pl-sw--projet-plein { background: var(--pl-projet-fx); border-color: var(--pl-projet-fx); }
/* Hachuré = projet / à revoir : teinte neutre (encre à 45 %), jamais la teinte danger ni la couleur pleine. */
.isis-pl-sw--projet { background: repeating-linear-gradient(45deg, var(--pl-hach) 0 2px, transparent 2px 6px); border-color: var(--pl-ink-2); }
/* Barre tiretée du chronogramme (ligne Dashed = pas encore engagée / contrôle interne) : cadre tireté en --pl-hach, comme la barre. */
.isis-pl-sw--tiret { background: transparent; border: 1.5px dashed var(--pl-hach); }
.isis-pl-sw--n1 { border: 0; border-top: 1.5px dashed var(--pl-ink-2); height: 0; margin-top: 5px; }
.isis-pl-sw--n2 { border: 0; border-top: 1.5px dotted var(--pl-ink-3); height: 0; margin-top: 5px; }
.isis-pl-sw--ok { background: var(--isis-success); border-color: var(--isis-success); }
.isis-pl-sw--warn { background: var(--isis-warning); border-color: var(--isis-warning); }
.isis-pl-sw--bad { background: var(--isis-danger); border-color: var(--isis-danger); }
/* Non évalué : même gris que le point de la carte (repli `pal.muted` d'isis-amcharts = --isis-text-muted). */
.isis-pl-sw--none { background: var(--isis-text-muted); border-color: var(--isis-text-muted); }
.isis-pl-sw--cercle { border-radius: 50%; width: 12px; justify-self: start; }
.isis-pl-sw--interne { background: color-mix(in srgb, var(--pl-accent) 35%, var(--pl-paper)); border-color: color-mix(in srgb, var(--pl-accent) 55%, var(--pl-paper)); }
.isis-pl-sw--creux { background: var(--pl-paper); border: 1.5px solid var(--pl-ink-2); border-radius: 50%; width: 12px; justify-self: start; }
.isis-pl-sw--creux.isis-pl-sw--carre { border-radius: 0; } /* carré creux = repère ▢ des SVG d'échéances (tacite) */
.isis-pl-sw--neutre { background: var(--pl-ink-3); border-color: var(--pl-ink-3); } /* état neutre tracé en plein (information, non tracé) */
/* Symboles du levé « Ma semaine » (chronogramme monespace). */
.isis-mesp-sw--bureau { background: color-mix(in srgb, var(--pl-exist-fx) 45%, var(--pl-paper)); border-color: var(--pl-exist-fx); }
.isis-mesp-sw--mixte { background: var(--isis-nature-mixte, #5d4a8c); border-color: var(--isis-nature-mixte, #5d4a8c); }
.isis-mesp-sw--trajet { background: var(--isis-nature-trajet, #3f7d58); border-color: var(--isis-nature-trajet, #3f7d58); }
.isis-mesp-sw--planif { background: transparent; border: 1px dashed var(--pl-ink-2); }
.isis-mesp-sw--ferie { background: color-mix(in srgb, var(--pl-ink) 10%, transparent); }
/* Légende liée aux cartes (2026-09-01) : entrées de légende cliquables — survol/focus = catégorie en
   évidence sur la carte, clic = masquer/afficher (aria-pressed = affiché). L'état masqué se voit :
   swatch estompé + libellé barré. Réservé à l'affichage carte des planches. */
.isis-pl-symb button.isis-pl-legbtn { display: grid; grid-template-columns: 34px 1fr; gap: 10px; align-items: center; font-size: 12px; color: var(--pl-ink); background: none; border: 0; padding: 0; margin: 0; font-family: inherit; text-align: left; cursor: pointer; width: 100%; }
.isis-pl-legbtn:hover { color: var(--pl-exist-fx); }
.isis-pl-legbtn:focus-visible { outline: 2px solid var(--pl-exist-fx); outline-offset: 2px; }
.isis-pl-legbtn.is-off { text-decoration: line-through; color: var(--pl-ink-3); }
.isis-pl-legbtn.is-off .isis-pl-sw, .isis-pl-legbtn.is-off .isis-pl-puce { opacity: 0.3; }

/* ── Levé « Ma semaine » : un chronogramme, une bande par jour ──────────────── */
.isis-mesp-chrono { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 8px; align-items: end; }
.isis-mesp-chrono__col { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.isis-mesp-chrono__bars { height: 132px; display: flex; flex-direction: column; justify-content: flex-end;
    gap: 3px; border-bottom: 1px solid var(--pl-line-strong); }
.isis-mesp-chrono__jour { font-size: 12.5px; letter-spacing: 0;
    color: var(--pl-ink-2); display: flex; justify-content: space-between; gap: 4px; }
.isis-mesp-chrono__jour b { color: var(--pl-ink); font-weight: 600; font-variant-numeric: tabular-nums; }
.isis-mesp-chrono__h { font-family: var(--pl-mono); font-size: 12px; color: var(--pl-ink-3); }
.isis-mesp-chrono__h b { color: var(--pl-ink); font-weight: 600; }
.isis-mesp-chrono__col.is-today .isis-mesp-chrono__jour,
.isis-mesp-chrono__col.is-today .isis-mesp-chrono__jour b { color: var(--pl-exist-fx); }
.isis-mesp-chrono__col.is-today .isis-mesp-chrono__bars {
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--pl-exist-fx) 40%, transparent); }

/* Colonne samedi/dimanche : le dénominateur du cartouche exclut déjà ces jours (jours OUVRÉS
   uniquement, cf. JourSemaine.EstWeekEnd) — le levé doit dire la même chose. En-tête atténué en
   permanence ; une barre qui déborde ici (mobilisation à cheval sur le week-end) est nuancée,
   jamais supprimée : la donnée reste réelle, seule sa lecture change — cf. légende « Férié /
   week-end » à gauche, jusqu'ici jamais peinte pour un week-end sans absence posée. */
.isis-mesp-chrono__col.is-weekend .isis-mesp-chrono__jour,
.isis-mesp-chrono__col.is-weekend .isis-mesp-chrono__jour b { color: var(--pl-ink-3); }
.isis-mesp-chrono__col.is-weekend .isis-mesp-bar { opacity: .55; }

.isis-mesp-bar { border: 1px solid transparent; font-family: var(--pl-mono); font-size: 12px;
    color: var(--pl-on-accent); padding: 2px 5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.isis-mesp-bar--terrain { background: var(--pl-exist-fx); }
.isis-mesp-bar--bureau { background: color-mix(in srgb, var(--pl-exist-fx) 45%, var(--pl-paper));
    color: var(--pl-ink); border-color: var(--pl-exist-fx); }
/* Mixte/Trajet peignent les tokens de nature de travail (mêmes --isis-nature-* que
   WorkNatureBadge.razor), PAS --pl-exist-fx : ce ne sont pas des tons d'accent module éclaircis
   en sombre, mais des couleurs FOURNIES PAR LE TENANT (paramétrables, injectées à l'exécution —
   --isis-nature-* n'est défini nulle part dans ce fichier), non éclaircies en sombre. `#ffffff`
   en dur ici n'est PAS une entorse à « aucune couleur en dur » mais le précédent déjà posé par
   ce même dépôt pour ces mêmes tokens : .isis-nature-badge--terrain/mixte/trajet (lignes
   9545-9549) fixent exactement ce blanc, identique dans les 2 thèmes. Ne PAS basculer vers
   --pl-on-accent : ce token s'assombrit en sombre parce que l'accent du MODULE y est éclairci
   par la planche — les couleurs de nature du tenant ne le sont pas, une encre sombre y serait
   illisible. Mesuré : blanc sur #5d4a8c = 7,44:1, sur #3f7d58 = 4,90:1, AA dans les 2 thèmes. */
.isis-mesp-bar--mixte { background: var(--isis-nature-mixte, #5d4a8c); color: #ffffff; }
.isis-mesp-bar--trajet { background: var(--isis-nature-trajet, #3f7d58); color: #ffffff; }
.isis-mesp-bar--planif { background: transparent; border: 1px dashed var(--pl-ink-2); color: var(--pl-ink-2); }
.isis-mesp-bar--abs { background: repeating-linear-gradient(45deg, var(--pl-hach) 0 2px, transparent 2px 6px);
    border-color: var(--pl-ink-2); color: var(--pl-ink); }
.isis-mesp-bar--ferie { background: color-mix(in srgb, var(--pl-ink) 10%, transparent); color: var(--pl-ink-2); }

/* Échelle de semaine (◀ / Cette semaine / ▶) : boutons flèches étroits, bouton central large —
   contrairement aux échelles à colonnes égales (.isis-pl-echelle--deux/trois/une) déjà posées
   ailleurs dans ce fichier. Scopée à mon-espace UNIQUEMENT. `!important` nécessaire : la règle
   générique « 3 boutons exactement → 3 colonnes, quelle que soit la classe posée » (ligne 50254)
   a une spécificité supérieure (:has() + :not()) et s'appliquerait sinon malgré cette classe. */
.isis-mesp-echelle--semaine { grid-template-columns: 32px minmax(0, 1fr) 32px !important; }

/* Scope .isis-mesp-plan (mon-espace UNIQUEMENT — cf. MonEspacePage.razor). Mesuré avant de
   choisir (round 2, tâche 6) : basculer le flex-basis de .isis-pl-details sur `auto` plutôt que
   `calc(50% - 11px)` (le levier « rendre au bloc des détails la hauteur que le levé n'utilise
   pas ») s'est révélé un NO-OP — avec un seul enfant flexible dans un conteneur de hauteur
   définie, la taille finale = conteneur − items fixes − gap, QUEL QUE SOIT le flex-basis déclaré
   (grow et shrink comblent/absorbent l'écart de la même façon quel que soit le point de départ).
   Le vrai manque, c'est que 258 px (ce qui reste une fois le chronogramme logé) ne suffisent pas
   à 3 cartes pleines (~389 px) : pas un défaut de répartition, un déficit d'espace. D'où le seul
   levier qui compte, ci-dessous : signaler sans ambiguïté qu'il reste du contenu. */
/* grid-auto-rows: min-content — sans lui, un item dont l'overflow n'est pas visible (cf.
   .isis-pl-detail, overflow-x: auto plus bas) reçoit une taille minimale automatique de 0
   (spec CSS Box Sizing) : dans un conteneur de hauteur définie, la ligne se compresse sous
   son contenu réel au lieu de déborder proprement dans le défilement interne. */
.isis-mesp-plan .isis-pl-details {
    grid-auto-rows: min-content;
    /* .isis-planche__plan n'a pas de fond propre (celui de .isis-planche, --pl-paper,
       transparaît) : le repli --isis-surface du token centralisé jurerait au raccord. */
    --isis-scroll-shadow-bg: var(--pl-paper);
}

/* Échelles = filtres (grille de cases à filets) */
/* Lot 1 du réalignement (2026-09-20) : la grille de cases à filets partagés devient une rangée de
   boutons séparés — 32 px, rayon, bordure et anneau de focus du produit. Les règles nth-child qui
   géraient les filets partagés (et les `!important` de --une) n'ont plus d'objet. */
.isis-pl-echelle { display: grid; grid-template-columns: repeat(4, 1fr); gap: 6px; }
/* Deux colonnes : pour deux boutons, et pour QUATRE en 2x2 — en 4 colonnes, « Structure » et
   « Ensemble » en 12.5px nowrap débordent d'un quart de la colonne de légende. Les deux noms
   restent distincts bien que la déclaration soit la même : la grille de BASE est repeat(4, 1fr)
   et la règle « quelle que soit la classe posée » plus bas ne mord qu'à 3 boutons exactement —
   un groupe de 4 sans classe prendrait donc 4 colonnes, ce que la mesure refuse. */
.isis-pl-echelle--deux,
.isis-pl-echelle--quatre { grid-template-columns: 1fr 1fr; }
.isis-pl-echelle--une { grid-template-columns: 1fr; }
.isis-pl-echelle--trois { grid-template-columns: 1fr 1fr 1fr; }
.isis-pl-echelle:has(> button:nth-child(3)):not(:has(> button:nth-child(4))) { grid-template-columns: 1fr 1fr 1fr; } /* 3 boutons = 3 colonnes, sans classe (Vue Mienne · Équipe · Structure) */
.isis-pl-echelle button { border: 1px solid var(--pl-line-ctrl); border-radius: var(--isis-radius); background: transparent;
    font-family: inherit; min-height: 32px; font-weight: 500; font-size: 12.5px; letter-spacing: 0; padding: 0 6px; cursor: pointer; color: var(--pl-ink-2); white-space: nowrap; }
.isis-pl-echelle--une button { text-align: left; padding-left: 8px; }
/* Échelle à une colonne qui SUIT une autre échelle ou sa note (filtres actifs sous la période) : respiration. */
.isis-pl-echelle + .isis-pl-echelle--une, .isis-pl-carte__note + .isis-pl-echelle--une { margin-top: 8px; }

/* Échelle de planche inerte pendant un chargement. `aria-disabled` et non `disabled` : le
   bouton garde son title et son rang de tabulation ; le geste est refusé dans le handler
   (ApplyPeriodAsync teste !_busy). Règle ADDITIVE — les 16 autres tableaux de bord posent
   encore `disabled` et gardent le rendu natif jusqu'au lot transverse. */
.isis-pl-echelle button[aria-disabled="true"] { opacity: .65; cursor: not-allowed; }

/* Idem pour un lien-bouton et pour la clé de levée de verrou (seule règle de cette classe :
   elle n'avait aucun style propre, donc aucun état inerte visible). */
button.isis-text-link[aria-disabled="true"] { opacity: .65; cursor: not-allowed; text-decoration: none; }
.isis-wsg__verrou-cle[aria-disabled="true"] { opacity: .65; cursor: not-allowed; }
/* 3 boutons exactement (et pas --une) → 3 colonnes, quelle que soit la classe posée (--deux compris). */
.isis-pl-echelle:not(.isis-pl-echelle--une):has(> button:nth-child(3):last-child) { grid-template-columns: 1fr 1fr 1fr; }
.isis-pl-echelle button.is-active { background: color-mix(in oklab, var(--pl-accent) 64%, black 36%); border-color: color-mix(in oklab, var(--pl-accent) 64%, black 36%); color: #fff; } /* accent assombri vers le noir (jamais --isis-text, qui s'inverse selon le thème). 18% de noir ne suffisait pas : mesuré à 3,74:1 en sombre sur l'accent teal du tenant. Balayé sur les 19 couleurs --isis-mod-* des deux thèmes (isis-theme.css:127-201 clair, :43201-43233 sombre) : 36% de noir est le point où le pire cas (monespace lime #a3e635 en sombre) passe à 4,77:1 ; le pire cas clair (sirh) reste à 9,54:1 — large marge, teinte encore reconnaissable */
:root[data-theme="dark"] .isis-pl-echelle button.is-active { background: var(--pl-accent); border-color: var(--pl-accent); color: var(--pl-paper); } /* B-D18 : en sombre l accent assombri tombait à 2,28:1 du fond ; l accent est déjà lumineux, le texte prend le fond */
.isis-pl-echelle button:disabled { opacity: .65; cursor: default; }
.isis-pl-echelle button:focus-visible { outline: 2px solid var(--pl-exist-fx); outline-offset: 2px; }
.isis-planche__legende .isis-dash-entfilter { width: 100%; min-width: 0; max-width: none; border-radius: 6px; box-shadow: none; border-color: var(--pl-line-ctrl); }
/* Filtre « Membres » (sélection multiple) — panneau déroulant du monde planche */
.isis-pl-membres { position: relative; }
/* `font-family: inherit` explicite ici aussi : un `button` N'HÉRITE PAS la police. Le
   déclencheur portait --pl-mono alors qu'il affiche une phrase française (« 3 / 12
   sélectionnés »), pas un code, et que tout le panneau qu'il ouvre est proportionnel —
   il était le seul élément en chasse fixe de son propre composant (arbitrage 2026-09-20). */
.isis-pl-membres__btn { width: 100%; display: flex; justify-content: space-between; align-items: center; gap: 8px;
    border: 1px solid var(--pl-line-ctrl); border-radius: 6px; background: var(--pl-paper); cursor: pointer;
    font-family: inherit; font-size: 12.5px; letter-spacing: 0; padding: 7px 8px; color: var(--pl-ink); }
.isis-pl-membres__btn:focus-visible { outline: 2px solid var(--pl-accent); outline-offset: 1px; }
.isis-pl-membres__panel { position: absolute; z-index: 30; top: calc(100% + 4px); left: 0; right: 0; max-height: 320px; overflow-y: auto;
    background: var(--pl-paper); border: 1px solid var(--pl-line-strong); border-radius: 8px; box-shadow: var(--isis-elevation-2); padding: 6px; }
.isis-pl-membres__panel--inline { position: static; max-height: 260px; box-shadow: none; border-radius: 6px; } /* Membres par origine (gescom, Vue Équipe) : deux groupes à plat dans la légende */
/* `font-family: inherit` : un <input> n'hérite pas la police, pas plus qu'un <button> — sans
   cette ligne le champ de recherche rendait en Arial (mesuré au navigateur le 2026-09-20). */
.isis-pl-membres__search { width: 100%; border: 1px solid var(--pl-line-ctrl); border-radius: 6px; padding: 5px 8px; font-family: inherit; font-size: 12.5px;
    margin-bottom: 6px; background: var(--pl-paper); color: var(--pl-ink); }
/* `font-family: inherit` explicite sur les deux boutons du panneau : un `button` N'HÉRITE PAS
   la police. Retirer --pl-mono sans le poser les ferait retomber sur la police du navigateur. */
.isis-pl-membres__tous { width: 100%; text-align: left; border: 0; background: transparent; cursor: pointer; padding: 6px 8px;
    font-family: inherit; font-size: 12.5px; letter-spacing: 0; font-weight: 600; color: var(--pl-accent); border-radius: 6px; }
.isis-pl-membres__tous:hover { background: var(--pl-accent-soft); }
.isis-pl-membres__groupe { width: 100%; display: flex; justify-content: space-between; border: 0; border-top: 1px solid var(--pl-rule-soft);
    background: transparent; cursor: pointer; padding: 6px 8px 4px; margin-top: 4px;
    font-family: inherit; font-size: 12.5px; letter-spacing: 0; font-weight: 600; color: var(--pl-ink-2); }
.isis-pl-membres__groupe:hover { color: var(--pl-accent); }
.isis-pl-membres__gn { font-variant-numeric: tabular-nums; }
.isis-pl-membres__item { display: flex; align-items: center; gap: 8px; padding: 5px 8px; font-size: 12.5px; color: var(--pl-ink);
    border-radius: 6px; cursor: pointer; }
.isis-pl-membres__item:hover { background: var(--isis-surface-alt, var(--isis-bg)); }
.isis-pl-membres__item input { accent-color: var(--pl-accent); }

/* Corps de planche : profil / coupe / détails */
.isis-pl-h2 { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; font-size: 14px; font-weight: 600;
    letter-spacing: -0.1px; margin: 0 0 10px; color: var(--pl-ink); }
.isis-pl-h2 small { font-family: var(--pl-mono); font-weight: 500; color: var(--pl-ink-3); letter-spacing: .04em; text-transform: none; font-size: 11.5px; line-height: 1.3; }
.isis-pl-detail .isis-pl-h2 small { flex-basis: 100%; margin-top: -6px; }
/* Titre de levé repliable : le titre EST le bouton, précédé du seul chevron. Aucun fond,
   aucune ombre — la ligne de titre garde exactement la graisse, la casse et l'interlettrage
   de `.isis-pl-h2`. Les agents utilisateurs remettent à zéro `font`, `color`, `letter-spacing`
   et `text-transform` sur les contrôles de formulaire : les réhériter un par un est
   obligatoire, sans quoi le bouton sort en minuscules et à la police du système. */
.isis-pl-h2__toggle {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin: 0;
    padding: 0;
    border: 0;
    background: none;
    cursor: pointer;
    font: inherit;
    color: inherit;
    line-height: inherit;
    letter-spacing: inherit;
    text-transform: inherit;
    text-align: left;
}
.isis-pl-h2__toggle:hover { color: var(--pl-accent); }
/* `--pl-accent` et non `--isis-current-mod` : cette dernière est VOLONTAIREMENT sans repli
   (cf. .isis-shell) et reste invalide quand aucune teinte de module n'est posée — l'anneau de
   focus disparaîtrait. `--pl-accent` porte le repli, et c'est ce qu'emploient les cinq autres
   règles :focus-visible de la famille .isis-pl-*. */
.isis-pl-h2__toggle:focus-visible { outline: 2px solid var(--pl-accent); outline-offset: 3px; border-radius: 3px; }
/* La ligne de titre fait 16 px de haut : la zone cliquable est étendue par un pseudo-élément
   plutôt que par du remplissage, qui décalerait le titre par rapport aux autres levés. Porte
   la cible à 26 × 94 px, au-delà du minimum 24 × 24 de WCAG 2.2 (2.5.8), sans toucher au
   gabarit ni empiéter sur le `<small>` voisin, qui commence 6 px plus loin. */
.isis-pl-h2__toggle { position: relative; }
.isis-pl-h2__toggle::after { content: ""; position: absolute; inset: -5px -4px; }
/* Levé principal (courbe / barres amCharts) : partage la hauteur du corps 50/50 avec les détails. */
.isis-pl-leve { display: flex; flex-direction: column; min-height: 0; }
.isis-pl-leve__chart { flex: 1 1 auto; min-height: 220px; border: 1px solid var(--pl-rule); background: color-mix(in srgb, var(--pl-paper) 72%, transparent); padding: 6px 8px 2px; }
/* Hauteurs de levé par modificateur (plus de min-height inline) ; --nu = sans marge interne (chronogramme). */
.isis-pl-leve__chart--h240 { min-height: 240px; } .isis-pl-leve__chart--h260 { min-height: 260px; } .isis-pl-leve__chart--h280 { min-height: 280px; }
.isis-pl-leve__chart--nu { padding: 0; }
/* SVG d'échelle graphique généré côté serveur : occupe la largeur du levé, jamais plus haut que lui. */
.isis-pl-svg-full { width: 100%; max-height: 100%; display: block; }
/* Chronogramme « En cours » (PlancheTimeline) — HTML/CSS à taille réelle : colonne de libellés fixe,
   piste en %, lignes de 30px, défilement vertical interne si plus de lignes que de place. */
.isis-pl-tl { display: flex; flex-direction: column; min-height: 0; height: 100%; font-family: var(--pl-mono); }
.isis-pl-tl__head { display: flex; align-items: flex-end; padding: 2px 0 4px; }
.isis-pl-tl__lbl { flex: 0 0 172px; width: 172px; padding-right: 10px; text-align: right; font-size: 12px; color: var(--pl-ink);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.isis-pl-tl__axis { flex: 1 1 auto; display: grid; grid-template-columns: repeat(12, 1fr); }
.isis-pl-tl__axis span { font-size: 11px; letter-spacing: .06em; color: var(--pl-ink-3); text-align: center;
    border-left: 1px solid var(--pl-rule-soft); padding-bottom: 2px; white-space: nowrap; overflow: hidden; min-width: 0; }
/* Fenêtre à cheval sur deux années (12 mois glissants) : l'année courte sous le mois, en tête de piste et à chaque janvier. */
.isis-pl-tl__axis span small { display: block; font-size: inherit; color: var(--pl-ink-2); }
.isis-pl-tl__head { align-items: flex-end; }
.isis-pl-tl__axis { align-items: end; }
.isis-pl-tl__body { position: relative; flex: 1 1 auto; min-height: 0; overflow-y: auto; }
.isis-pl-tl__row { display: flex; align-items: center; height: 30px; text-decoration: none; color: inherit; border-bottom: 1px solid var(--pl-rule-soft); }
.isis-pl-tl__row:hover .isis-pl-tl__lbl, .isis-pl-tl__row:focus-visible .isis-pl-tl__lbl { color: var(--pl-accent); text-decoration: underline; }
.isis-pl-tl__row:focus-visible { outline: 2px solid var(--pl-accent); outline-offset: -2px; }
.isis-pl-tl__lane { position: relative; flex: 1 1 auto; height: 100%; border-left: 1.2px solid var(--pl-ink); }
.isis-pl-tl__bar { position: absolute; top: 7px; height: 16px; border: 1px solid; box-sizing: border-box; display: block; }
.isis-pl-tl__bar.is-dashed { border-style: dashed; }
.isis-pl-tl__bar b { position: absolute; left: 0; top: 0; bottom: 0; display: block; opacity: .85; }
.isis-pl-tl__mk { position: absolute; top: 9px; width: 10px; height: 10px; margin-left: -5px; transform: rotate(45deg); border: 1px solid var(--pl-paper); display: block; }
.isis-pl-tl__mk--ok { background: var(--isis-success); } .isis-pl-tl__mk--warn { background: var(--isis-warning); }
.isis-pl-tl__mk--bad { background: var(--isis-danger); } .isis-pl-tl__mk--neutral { background: var(--pl-ink-2); }
.isis-pl-tl__over { position: absolute; top: 0; bottom: 0; left: 172px; right: 0; pointer-events: none; }
.isis-pl-tl__today { position: absolute; top: 0; bottom: 0; border-left: 1.2px dashed var(--isis-danger); }
.isis-pl-tl__today em { position: absolute; bottom: 2px; left: 4px; font-style: normal; font-size: 12px; color: var(--isis-danger); white-space: nowrap; }
.isis-pl-leve__grid { flex: 1 1 auto; min-height: 0; display: grid; grid-template-columns: minmax(0, 1fr) minmax(260px, 340px); gap: 18px; align-items: stretch; }
.isis-pl-leve__grid .isis-pl-nomen { align-self: start; }
.isis-pl-leve__grid .isis-pl-leve__chart { align-self: start; }
@container (max-width: 560px) { .isis-pl-leve__grid { grid-template-columns: 1fr; } }
.isis-planche-page .isis-planche__plan > .isis-pl-leve { flex: 0 0 calc(50% - 11px); }
/* Variante « hauteur au contenu » (planche 4) : le levé ne réserve plus 50 %, les détails remontent. */
.isis-planche-page .isis-planche__plan > .isis-pl-leve--auto { flex: 0 0 auto; }
.isis-planche-page .isis-planche__plan > .isis-pl-leve--auto + .isis-pl-details { flex: 1 1 auto; }
/* Levé réduit à sa zone « pas de données » (titre + .isis-pl-vide, rien d'autre) : même comportement que --auto,
   sans que la page ait à poser la classe — la zone vide ne réserve plus 50 % de la hauteur. */
.isis-planche-page .isis-planche__plan > .isis-pl-leve:has(> .isis-pl-vide):not(:has(> :not(.isis-pl-h2):not(.isis-pl-vide))) { flex: 0 0 auto; }
.isis-planche-page .isis-planche__plan > .isis-pl-leve:has(> .isis-pl-vide):not(:has(> :not(.isis-pl-h2):not(.isis-pl-vide))) + .isis-pl-details { flex: 1 1 auto; }
/* Rechargement (aria-busy posé par la page sur le plan) : le contenu précédent reste visible, grisé à 60 %. */
.isis-planche__plan[aria-busy="true"] > :not(.isis-planche__contours) { opacity: .6; transition: opacity .2s ease; }
.isis-planche-page .isis-planche__plan > .isis-pl-leve + .isis-pl-details { flex: 1 1 calc(50% - 11px); min-height: 0; overflow-y: auto; align-content: start; }
/* Carte de santé (planche Direction) : carte amCharts plan/globe | nomenclature des clients */
.isis-pl-carte__grid { display: grid; grid-template-columns: minmax(0, 1fr) 300px; gap: 18px; align-items: start; }
@container (max-width: 760px) { .isis-pl-carte__grid { grid-template-columns: 1fr; } }
.isis-pl-carte__map { height: 430px; border: 1px solid var(--pl-rule); background: color-mix(in srgb, var(--pl-paper) 72%, transparent); overflow: hidden; }
.isis-pl-carte .isis-pl-h2 .isis-pl-carte__outils { margin-left: auto; display: inline-flex; align-items: center; gap: 10px; }
/* Bascule de levé : largeur au contenu (les 2 cases 1fr s'égalisent sur le libellé le plus
   long — « B · Ponctualité » débordait du 190px fixe), plancher 190px pour garder l'assiette. */
.isis-pl-h2 .isis-pl-leve__lvsel { margin-left: auto; width: max-content; min-width: 190px; display: inline-grid; }
.isis-pl-h2 .isis-pl-leve__lvsel2 { width: max-content; min-width: 190px; display: inline-grid; }
.isis-pl-h2 .isis-pl-leve__lvsel button, .isis-pl-h2 .isis-pl-leve__lvsel2 button { white-space: nowrap; }
/* Onglet « Mes projets » : barre de sélecteurs (indicateur, période, devise) et légende de la photo de nuit. */
.isis-pl-ind__barre { display: flex; flex-wrap: wrap; gap: 8px 12px; margin: 0 0 8px; }
.isis-pl-ind__barre .isis-pl-echelle { display: inline-grid; grid-auto-flow: column; grid-template-columns: none; width: max-content; }
.isis-pl-ind__barre .isis-pl-echelle button { white-space: nowrap; }
.isis-pl-ind__legende.isis-pl-ind__compteurs { margin-top: 8px; }
.isis-pl-ind__compteurs strong { color: var(--pl-ink); font-weight: 600; }
.isis-pl-ind__legende { margin: 6px 0 0; padding: 0; list-style: none; font-size: 12px; line-height: 1.4; color: var(--pl-ink-3); }
.isis-pl-carte .isis-pl-h2 .isis-pl-echelle { width: 170px; display: inline-grid; }
.isis-pl-echelle--projection { width: 150px; display: inline-grid; } /* Plan / Globe hors .isis-pl-carte (gesproj) */
.isis-pl-carte__pays { border: 1px solid var(--pl-line-strong); border-radius: 6px; background: var(--pl-paper);
    font-family: var(--pl-mono); font-size: 12px; letter-spacing: .04em; padding: 5px 6px; color: var(--pl-ink); max-width: 180px; cursor: pointer; }
.isis-pl-carte__pays:focus-visible { outline: 2px solid var(--pl-accent); outline-offset: 1px; }
.isis-pl-carte__note { margin: 6px 0 0; font-size: var(--isis-fs-sm); line-height: 1.35; color: var(--pl-ink-3); }
/* Filtre « Structures du périmètre » (cases à cocher, légende — aucune cochée = toutes) */
.isis-pl-structsel { display: grid; gap: 2px; max-height: 190px; overflow-y: auto; }
.isis-pl-structsel__item { display: flex; align-items: center; gap: 7px; font-size: 12px; color: var(--pl-ink); cursor: pointer; padding: 2px 0; }
.isis-pl-structsel__item input { accent-color: var(--pl-accent); margin: 0; }
.isis-pl-structsel__item.is-implied { color: var(--pl-ink-3); }
.isis-pl-structsel__item input:disabled { opacity: .55; cursor: default; }
.isis-pl-sw--anneau { border-radius: 50%; width: 12px; justify-self: start; border: 2px dashed var(--pl-ink-2); background: transparent; }
.isis-pl-sw--taille { border-radius: 50%; width: 18px; height: 18px; justify-self: start; background: color-mix(in srgb, var(--pl-ink-2) 35%, transparent); border-color: var(--pl-ink-2); }
.isis-pl-sw--reste { background: var(--isis-accent); border-color: var(--isis-accent); }
.isis-pl-sante { display: inline-block; width: 10px; height: 10px; border-radius: 50%; vertical-align: -1px; margin-right: 6px; }
.isis-pl-sante--ok { background: var(--isis-success); } .isis-pl-sante--warn { background: var(--isis-warning); } .isis-pl-sante--bad { background: var(--isis-danger); }
.isis-pl-sante--none { background: transparent; border: 1px dashed var(--pl-ink-3); }
.isis-pl-details { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 22px; }
.isis-pl-detail { background: var(--pl-paper); border: 1px solid var(--pl-line-strong); border-radius: var(--pl-radius); box-shadow: var(--isis-elevation-1); padding: 12px 14px 6px; min-width: 0; }
.isis-pl-nomen { width: 100%; border-collapse: collapse; }
.isis-pl-nomen th { font-size: 11.5px; letter-spacing: 0; color: var(--pl-ink-2); line-height: 1.3;
    text-align: left; padding: 6px 6px; background: color-mix(in srgb, var(--isis-surface-alt, var(--isis-bg)) 70%, var(--pl-paper));
    border-bottom: 1px solid var(--pl-line); font-weight: 600; white-space: nowrap; } /* l'en-tête ne wrappe jamais, la colonne s'adapte (les td wrappent) */
.isis-pl-nomen td { height: 36px; padding: 6px 6px; border-bottom: 1px solid var(--pl-rule-soft); font-size: 12.5px; line-height: 1.3; vertical-align: middle; color: var(--pl-ink); }
.isis-pl-nomen th + th, .isis-pl-nomen td + td { padding-left: 12px; } /* aération inter-colonnes (« 01Relevé MMS » collé, retour proprio 2026-09-01) */
.isis-pl-nomen td > .isis-pl-sub { margin-top: 3px; }
.isis-pl-nomen tr:last-child td { border-bottom: 0; }
.isis-pl-nomen td.is-r, .isis-pl-nomen th.is-r { text-align: right; padding-left: 12px; white-space: nowrap; }
.isis-pl-nomen .is-num { font-family: var(--pl-mono); font-variant-numeric: tabular-nums; }
.isis-pl-sub, .isis-pl-nomen .isis-pl-sub { display: block; font-size: 11.5px; line-height: 1.3; color: var(--pl-ink-3); font-weight: 400; }
.isis-pl-nomen tr.is-dimmed td { opacity: .45; }
.isis-pl-puce { display: inline-block; width: 12px; height: 12px; border: 1px solid var(--pl-line); vertical-align: -2px; margin-right: 6px; }
.isis-pl-puce--exist { background: var(--pl-exist-fx); } .isis-pl-puce--ok { background: var(--isis-success); }
.isis-pl-puce--warn { background: var(--isis-warning); } .isis-pl-puce--bad { background: var(--isis-danger); }
.isis-pl-puce--hach { background: repeating-linear-gradient(45deg, var(--pl-hach) 0 2px, transparent 2px 6px); }
/* Segments de barre de proportion : la largeur reste inline (donnée), la teinte vient d'un modificateur. */
.isis-pl-bar i.is-exist { background: var(--pl-exist-fx); } .isis-pl-bar i.is-projet { background: var(--pl-projet-fx); }
.isis-pl-bar i.is-ok { background: var(--isis-success); } .isis-pl-bar i.is-hach { background: repeating-linear-gradient(45deg, var(--pl-hach) 0 2px, transparent 2px 6px); }
.isis-pl-bar { height: 10px; border: 1px solid var(--pl-line); display: flex; margin: 8px 0 6px; }
.isis-pl-bar i { display: block; height: 100%; }
.isis-pl-age { font-family: var(--pl-mono); font-size: 12px; border: 1px solid var(--pl-line); padding: 1px 5px; white-space: nowrap; color: var(--pl-ink); }
.isis-pl-nomen .is-r .isis-pl-age { margin-left: 6px; } /* chip d'âge collée à la date qui la précède (« 10/09J-9 ») */
.isis-pl-age--warn { border-color: var(--isis-warning); color: var(--isis-warning); }
.isis-pl-age--bad { border-color: var(--isis-danger); color: var(--isis-danger); }
.isis-pl-mini { display: inline-block; width: 70px; height: 7px; border: 1px solid var(--pl-line); vertical-align: middle; margin: 1px 8px 1px 0; position: relative; }
.isis-pl-mini i { position: absolute; left: 0; top: 0; bottom: 0; background: var(--pl-exist-fx); }
.isis-pl-mini i.is-warning { background: var(--isis-warning); } .isis-pl-mini i.is-danger { background: var(--isis-danger); }
.isis-pl-action { border: 1px solid var(--pl-line-strong); border-radius: 5px; background: transparent; width: 26px; height: 26px; display: inline-grid; place-items: center; cursor: pointer; color: var(--pl-ink); padding: 0; }
.isis-pl-action:hover { background: var(--pl-accent); border-color: var(--pl-accent); color: #fff; }
.isis-pl-vide { padding: 18px 14px; text-align: center; color: var(--pl-ink-3); font-size: 12px; border: 1px dashed var(--pl-rule);
    background: repeating-linear-gradient(45deg, transparent 0 8px, color-mix(in srgb, var(--pl-rule) 40%, transparent) 8px 9px); border-radius: 8px; }
.isis-pl-vide strong { display: block; color: var(--pl-ink-2); font-weight: 600; margin-bottom: 2px; }
.isis-pl-vide--inset { margin: 24px; } /* zone vide posée DANS un conteneur de carte (pas en tête de levé) */
.isis-pl-vide__actions { margin-top: 10px; } /* bouton Rafraîchir de l'état d'erreur */
.isis-pl-nomen--spaced { margin-top: 10px; } /* 2ᵉ nomenclature sous une carte ou une 1ʳᵉ table */
/* Lien de pied de carte .isis-pl-detail (ex. « Mes absences → ») : .isis-pl-cta est sinon scopé
   à .isis-pl-scalebar (styles ci-dessous) et .isis-pl-action est un bouton icône 26×26 — ni l'un
   ni l'autre ne convient à un texte de largeur variable en pied de nomenclature. Scopée à
   .isis-mesp-plan (mon-espace UNIQUEMENT, seule consommatrice de ce patron à ce jour) :
   .isis-pl-detail est partagée par 14 autres planches livrées, ne pas les affecter en silence
   le jour où l'une d'elles pose un CTA en pied de nomenclature (revue finale de branche 2026-09-07). */
.isis-mesp-plan .isis-pl-detail > .isis-pl-cta { display: block; margin: 10px -14px 0; padding: 8px 14px;
    border-top: 1px solid var(--pl-rule-soft); font-family: inherit; font-size: 12.5px;
    letter-spacing: 0; font-weight: 600; color: var(--pl-accent); text-decoration: none; text-align: right; }
.isis-mesp-plan .isis-pl-detail > .isis-pl-cta:hover { color: var(--pl-accent); }

/* Cartouche + échelle graphique */
.isis-pl-objectif { border: 1px solid var(--pl-line-strong); border-radius: var(--pl-radius); overflow: hidden; }
.isis-pl-objectif__t { font-size: 12.5px; letter-spacing: 0; font-weight: 600; padding: 6px 10px;
    border-bottom: 1px solid var(--pl-line); display: flex; justify-content: space-between; align-items: baseline; gap: 10px; white-space: normal; line-height: 1.35; color: var(--pl-ink); }
.isis-pl-objectif__t b { flex-shrink: 0; white-space: nowrap; color: var(--pl-exist-fx); }
.isis-pl-scalebar { padding: 14px 10px 10px; }
.isis-pl-scalebar__ticks { position: relative; height: 26px; border-bottom: 1px solid var(--pl-line-strong); }
.isis-pl-scalebar__fill { position: absolute; left: 0; bottom: 0; height: 10px; background: var(--pl-exist-fx); }
.isis-pl-scalebar__fill--hach { background: repeating-linear-gradient(45deg, var(--pl-hach) 0 2px, transparent 2px 6px); }
.isis-pl-scalebar__fill--ok { background: var(--isis-success); } .isis-pl-scalebar__fill--warn { background: var(--isis-warning); } .isis-pl-scalebar__fill--bad { background: var(--isis-danger); }
.isis-pl-scalebar__tk { position: absolute; bottom: -1px; width: 1px; height: 14px; background: var(--pl-ink); }
.isis-pl-scalebar__lb { position: absolute; bottom: -20px; transform: translateX(-50%); font-family: var(--pl-mono); font-size: 12px; color: var(--pl-ink-2); white-space: nowrap; }
.isis-pl-scalebar__lb--end { transform: translateX(-100%); }
/* Graduations : position par modificateur (0 par défaut, quarts, médiane, fin) — plus de left inline dans les pages. */
.isis-pl-scalebar__tk, .isis-pl-scalebar__lb { left: 0; }
.isis-pl-scalebar__tk--q1, .isis-pl-scalebar__lb--q1 { left: 25%; }
.isis-pl-scalebar__tk--mid, .isis-pl-scalebar__lb--mid { left: 50%; }
.isis-pl-scalebar__tk--q3, .isis-pl-scalebar__lb--q3 { left: 75%; }
.isis-pl-scalebar__tk--end, .isis-pl-scalebar__lb--end { left: 100%; }
.isis-pl-scalebar p { margin: 24px 0 0; font-size: 12px; color: var(--pl-ink-2); line-height: 1.45; }
.isis-pl-scalebar > p:first-child { margin-top: 0; }
/* « Chiffres » (PlancheChiffres, 2026-09-01) : quand l'échelle n'est pas un ratio, 2 à 4 comptes alignés en grille —
   clé mono 12 px au-dessus, valeur mono 16 px, feux par classe (is-danger / is-warn / is-muted / is-success). Une seule
   grammaire pour « à traiter » sur les 14 planches (remplace les tables isis-pl-nomen à 2 colonnes ou à 3 en-têtes).
   --chiffres sur l'échelle = pas la marge réservée aux graduations. */
.isis-pl-scalebar--chiffres { padding-top: 10px; }
.isis-pl-scalebar--chiffres p { margin-top: 10px; }
.isis-pl-chiffres { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); border: 1px solid var(--pl-line); }
.isis-pl-chiffres--quatre { grid-auto-flow: row; grid-template-columns: 1fr 1fr; }
.isis-pl-chiffres__cell { display: flex; flex-direction: column; justify-content: space-between; gap: 4px; min-width: 0; padding: 6px 8px;
    border-right: 1px solid var(--pl-line); border-bottom: 1px solid var(--pl-line); }
.isis-pl-chiffres__cell:last-child, .isis-pl-chiffres:not(.isis-pl-chiffres--quatre) .isis-pl-chiffres__cell { border-bottom: 0; }
.isis-pl-chiffres--quatre .isis-pl-chiffres__cell:nth-child(2n), .isis-pl-chiffres:not(.isis-pl-chiffres--quatre) .isis-pl-chiffres__cell:last-child { border-right: 0; }
.isis-pl-chiffres--quatre .isis-pl-chiffres__cell:nth-last-child(-n+2) { border-bottom: 0; }
.isis-pl-chiffres__k { font-family: var(--pl-mono); font-size: 12px; line-height: 1.3; letter-spacing: .02em; color: var(--pl-ink-2); overflow-wrap: break-word; hyphens: auto; }
.isis-pl-chiffres__v { font-family: var(--pl-mono); font-size: 16px; font-weight: 600; font-variant-numeric: tabular-nums; line-height: 1.2; color: var(--pl-ink); white-space: nowrap; }
.isis-pl-chiffres__v.is-danger { color: var(--isis-danger); } .isis-pl-chiffres__v.is-warn, .isis-pl-chiffres__v.is-warning { color: var(--isis-warning); }
.isis-pl-chiffres__v.is-success { color: var(--isis-success); } .isis-pl-chiffres__v.is-muted { color: var(--pl-ink-3); }
.is-nowrap { white-space: nowrap; }
/* `font-family: inherit` : .isis-pl-cta est posée aussi bien sur un <a> que sur un <button>,
   et un bouton n'hérite pas la police — sans cette ligne il retombe sur celle du navigateur. */
.isis-pl-scalebar .isis-pl-cta { display: inline-block; margin-top: 10px; border: 1px solid var(--pl-line-ctrl); border-radius: 6px; background: transparent; color: var(--pl-ink);
    font-family: inherit; font-size: 12.5px; letter-spacing: 0; font-weight: 600; padding: 7px 12px; cursor: pointer; text-decoration: none; }
.isis-pl-scalebar .isis-pl-cta:hover { background: var(--pl-accent); border-color: var(--pl-accent); color: #fff; }
.isis-pl-cartouche { border: 1px solid var(--pl-line-strong); border-radius: var(--pl-radius); overflow: hidden; }
.isis-pl-cartouche__row { display: grid; grid-template-columns: 118px minmax(0, 1fr); border-bottom: 1px solid var(--pl-line); }
.isis-pl-cartouche__row:last-child { border-bottom: 0; }
.isis-pl-cartouche__k { font-size: 12px; letter-spacing: 0; font-weight: 600; color: var(--pl-ink-2);
    padding: 10px 12px; border-right: 1px solid var(--pl-line); background: color-mix(in srgb, var(--isis-surface-alt, var(--isis-bg)) 70%, var(--pl-paper)); display: flex; align-items: center; }
.isis-pl-cartouche__v { padding: 10px 12px; font-family: var(--pl-mono); font-weight: 600; font-size: 18px; font-variant-numeric: tabular-nums; line-height: 1.15; color: var(--pl-ink); min-width: 0; overflow-wrap: anywhere; }
.isis-pl-cartouche__v.is-warning { color: var(--isis-warning); } .isis-pl-cartouche__v.is-danger { color: var(--isis-danger); } .isis-pl-cartouche__v.is-success { color: var(--isis-success); } .isis-pl-cartouche__v.is-muted { color: var(--pl-ink-3); }
.isis-pl-cartouche__v small { display: block; font-family: var(--isis-font-sans, inherit); font-weight: 400; font-size: var(--isis-fs-sm); line-height: 1.3; color: var(--pl-ink-3); margin-top: 3px; }
.isis-pl-cartouche__delta { font-size: 12px; font-weight: 600; }
.isis-pl-cartouche__delta.is-up { color: var(--isis-success); } .isis-pl-cartouche__delta.is-down { color: var(--isis-danger); }
.isis-pl-cartouche__row--meta .isis-pl-cartouche__v { font-family: var(--isis-font-sans, inherit); font-weight: 500; font-size: 12.5px; padding: 7px 10px; line-height: 1.35; }
.isis-pl-cartouche__row--meta .isis-pl-cartouche__k { padding: 8px 12px; }
/* Observation = 1re ligne du cartouche (décision 2026-09-01) : la seule ligne qui juge, en texte lisible
   (13 px, sans, fond papier), avant les chiffres. Le pied regroupe Périmètre · Source · Établi le en une ligne. */
.isis-pl-cartouche__row--obs { background: var(--pl-paper); }
.isis-pl-cartouche__row--obs .isis-pl-cartouche__k { background: transparent; align-items: start; padding-top: 12px; }
.isis-pl-cartouche__row--obs .isis-pl-cartouche__v { font-family: var(--isis-font-sans, inherit); font-weight: 500; font-size: 13px; line-height: 1.45; padding: 10px 12px; color: var(--pl-ink); }
.isis-pl-cartouche__foot { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 0; padding: 7px 12px 8px;
    background: color-mix(in srgb, var(--isis-surface-alt, var(--isis-bg)) 40%, var(--pl-paper));
    font-size: var(--isis-fs-sm); line-height: 1.35; color: var(--pl-ink-3); }
/* Rappel clavier sous la liste des planches (PlancheNav) : ← → planches · 1 2 3 affichages (isis-planche-keys.js). */
.isis-pl-cartouche__foot > * { min-width: 0; overflow-wrap: anywhere; }
.isis-pl-cartouche__foot > * + *::before { content: "·"; margin: 0 6px; color: var(--pl-ink-3); }
.isis-pl-cartouche__foot b { font-weight: 500; color: var(--pl-ink-2); }
/* En-tête : encre du texte sur fond d'encre (lot A, 2026-09-18). L'accent du module peint sur son
   propre fond teinté mesurait 2,76:1 en clair ; l'identité du module passe par le filet de 1 px sous
   l'en-tête (pas de liseré vertical, DESIGN.md §1). */
.isis-pl-cartouche__row--head { grid-template-columns: 1fr; background: var(--pl-ink); border-bottom-color: var(--pl-accent); }
.isis-pl-cartouche__row--head .isis-pl-cartouche__k { color: var(--pl-paper); background: transparent; border-right: 0; font-weight: 600; font-size: 12.5px; letter-spacing: 0; }
/* Lignes d'activité du cartouche d'accueil. */
.isis-accueil-act { display: flex; flex-direction: column; padding: 0.3rem 0; }
.isis-accueil-act + .isis-accueil-act { border-top: 1px dotted var(--pl-rule-soft); }
.isis-accueil-act > small { color: var(--pl-ink-3); font-size: 0.75rem; }
/* Détails : grille adaptée à la largeur RÉELLE du corps de planche (container query) — la zone de
   contenu de l'app est plus étroite que la maquette (barre latérale). Déclaré après .isis-pl-details. */
@container (max-width: 980px) { .isis-pl-details { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@container (max-width: 540px) { .isis-pl-details { grid-template-columns: 1fr; } }
/* Planche Direction hiérarchisée : rang 1 = 2 sections promues (vigilance marge, encours),
   rang 2 = 3 sections compactes (OTD, top valeur, qualité). */
.isis-pl-details.isis-pl-details--duo { grid-template-columns: repeat(2, minmax(0, 1fr)); }
/* Rangee a une seule carte : sans ce gabarit, la carte restante herite des TROIS colonnes de
   .isis-pl-details et n'en occupe qu'un tiers. Sert quand une carte de la rangee est retiree
   faute d'habilitation (migration 0733). */
.isis-pl-details.isis-pl-details--solo { grid-template-columns: minmax(0, 1fr); }
@container (max-width: 540px) { .isis-pl-details.isis-pl-details--duo { grid-template-columns: 1fr; } }
.isis-pl-details--rang2 .isis-pl-detail { padding: 10px 12px 4px; }
/* Lot A, 2026-09-18, sur /gescom/dashboard ; étendu le 2026-09-20 aux 4 autres planches gescom
   (pilotage-cycle, cockpit, action) — les 13 planches des autres modules gardent 300/360 fixes.
   Côtés proportionnels bornés (retour propriétaire : « largeur figée ») ; mesuré sur la maquette :
   191 / 646 / 359 px à 1512 × 982. Les paliers ≤ 1100 / ≤ 900 / ≤ 640 réécrivent la grille et restent
   maîtres ; la grille des détails n'est donc posée qu'au-dessus de 1100.
   Ce modificateur ne porte QUE la largeur du cadre. Le régime de hauteur est `--plan-libre` (plus bas) :
   les 5 planches gescom portent les deux, les autres modules `--plan-libre` seul.
   L'extension du 2026-09-20 aux planches 1/4/5 aligne le cadre des 5 planches d'une même navigation —
   feuilleter ◀ ▶ ne fait plus sauter les colonnes entre 232/395 et 300/360. */
.isis-planche--cartouche-large { --pl-col-legende: clamp(232px, 19%, 272px); --pl-col-cartouche: clamp(380px, 33%, 440px); }
.isis-planche--cartouche-large .isis-planche__legende { padding: 16px 14px 16px 22px; gap: 14px; }
/* Les échelles Période / Vue sont repassées à la taille du socle (12 px, DASHBOARD-DESIGN.md « aucune
   taille < 12 px dans le bloc planche ») le 2026-09-20 : la dérogation à 11 px avait été posée à 191 px
   de légende, elle n'a plus lieu d'être à 232-272 px — mesuré au navigateur sur les 4 planches gescom,
   zéro libellé coupé à 12 px (scrollWidth == clientWidth sur les 33 boutons). Seul l'interlettrage
   resserré est conservé. */
.isis-planche--cartouche-large .isis-pl-echelle button { letter-spacing: .02em; }
.isis-planche--cartouche-large .isis-planche__cartouche-col { justify-content: flex-start; padding-right: 18px; }

/* ── Régime de hauteur du corps — `isis-planche--plan-libre` ─────────────────────────────────────
   Le graphique cède, les listes jamais : à 1512 × 982 les trois blocs de détail étaient réduits à
   106 px pour 340 de contenu (graphique et détails rétrécissaient ensemble). Sous le plancher du
   graphique seulement, le milieu défile.
   Né le 2026-09-18 collé à `--cartouche-large`, SCINDÉ le 2026-09-20 : les deux n'ont rien à voir
   (l'un règle la hauteur, l'autre la largeur du cadre) et les 13 planches des autres modules avaient
   besoin du premier sans vouloir du second — leur cartouche est dessiné pour 360 px.
   Spécificité ≥ au partage 50/50 de `.isis-planche-page .isis-planche__plan > .isis-pl-leve (+ .isis-pl-details)`
   et déclaré APRÈS lui : une première version à spécificité inférieure perdait la cascade sans bruit
   (relevé navigateur du 2026-09-18 — le test de feuille, lui, était vert).
   ATTENTION - le corps devient conteneur de défilement : son `<main>` DOIT porter `tabindex="0"` + `aria-label`
   (WCAG 2.1.1 — le bas des nomenclatures n'a aucune cible de tabulation). */
.isis-planche--plan-libre .isis-planche__plan { overflow-y: auto; gap: 16px; padding-bottom: 18px; }
/* min-height: min-content — le levé ne descend jamais sous son titre + le plancher du graphique ;
   la règle générique `.isis-pl-leve { min-height: 0 }` le laissait tomber à 78 px (1440 × 900). */
.isis-planche--plan-libre .isis-planche__plan > .isis-pl-leve { flex: 1 1 auto; min-height: min-content; }
.isis-planche--plan-libre .isis-pl-leve__chart { min-height: 160px; }
/* … sauf quand la page a posé son propre plancher : `--h240/260/280` n'ont qu'une classe, le plancher
   160 px ci-dessus en a deux et les battait tous, quel que soit l'ordre source. Mesuré le 2026-09-20 :
   le globe de /gescom/pilotage-cycle (vue Carte, `--h280`) tombait à 162 px, inexploitable. Aucun
   risque de chevauchement en retour : sous ce modificateur le levé prend sa hauteur naturelle et c'est
   le corps qui défile. */
.isis-planche--plan-libre .isis-pl-leve__chart--h240 { min-height: 240px; }
.isis-planche--plan-libre .isis-pl-leve__chart--h260 { min-height: 260px; }
.isis-planche--plan-libre .isis-pl-leve__chart--h280 { min-height: 280px; }
.isis-planche--plan-libre .isis-planche__plan > .isis-pl-leve + .isis-pl-details { flex: none; min-height: auto; overflow: visible; }
/* Cartouche à références (lot B, 2026-09-18) : 9 indicateurs, chacun avec T−1 · N−1 · Obj. · Relevé en
   4 colonnes alignées sous un en-tête partagé. Le sens d'un écart est porté par son signe et par le mot
   de l'aria-label ; la couleur n'en est qu'un doublon. Une référence absente garde sa cellule : « — »
   et le numéro du renvoi qui en donne la raison. */
.isis-pl-cartouche--refs .isis-pl-cartouche__row { grid-template-columns: 118px minmax(0, 1fr); }
.isis-pl-cartouche--refs .isis-pl-cartouche__row--head,
.isis-pl-cartouche--refs .isis-pl-cartouche__row--groupe { grid-template-columns: 1fr; }
.isis-pl-cartouche--refs .isis-pl-cartouche__k { padding: 10px; letter-spacing: 0; flex-direction: column; align-items: flex-start; justify-content: center; }
.isis-pl-cartouche--refs .isis-pl-cartouche__v { padding: 9px 12px 10px; font-size: 16px; }
.isis-pl-cartouche--refs .isis-pl-cartouche__row--head .isis-pl-cartouche__k { padding-top: 8px; padding-bottom: 8px; }
.isis-pl-cartouche--refs .isis-pl-cartouche__row--obs .isis-pl-cartouche__v { font-size: 13px; }
/* 11 px : « +88,8 pt » et « > +999 % » mesurent 48,7 / 49,4 px pour une colonne de 51,5 à 1512 × 982 ;
   à 12 px ils débordaient de 1,7 / 2,4 px (mesure navigateur du 2026-09-18). */
.isis-pl-refs { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 4px; margin-top: 3px;
    font-family: var(--pl-mono); font-size: 11px; font-weight: 600; font-variant-numeric: tabular-nums; line-height: 1.3; }
.isis-pl-cartouche__row--entete .isis-pl-cartouche__v { padding-top: 4px; padding-bottom: 4px; }
.isis-pl-cartouche__row--entete .isis-pl-refs { margin-top: 0; font-size: 11px; color: var(--pl-ink-2); letter-spacing: 0; }
.isis-pl-ref { position: relative; min-width: 0; overflow-wrap: anywhere; }
/* 1.4.12 : sous un espacement imposé, un écart passe à la ligne plutôt que de chevaucher sa voisine ;
   en rendu normal l'espace fine insécable (U+202F) garde nombre et unité ensemble. */
.isis-pl-ref--favorable { color: var(--isis-success); }
.isis-pl-ref--defavorable { color: var(--isis-danger); text-decoration: underline dotted; text-underline-offset: 2px; }
/* 1.4.1 : vert et rouge ne se distinguent que par la teinte (1,29:1 entre eux) ; le soulignement pointillé
   marque le défavorable sans coûter de largeur. Le mot reste dans le texte lu. */
.isis-pl-ref--stable { color: var(--pl-ink-2); font-weight: 500; }
/* Une référence absente ne doit pas ressembler à une donnée : maigre et en encre secondaire, pour qu'un
   vrai écart (gras, coloré) ressorte (audit UI du 2026-09-18). */
.isis-pl-ref--nd { color: var(--pl-ink-2); font-weight: 400; }
/* Raison commune à toute une colonne, dite une fois sous son intitulé. */
.isis-pl-refs__renvoi { display: block; text-transform: none; letter-spacing: 0; font-weight: 400; }
.isis-pl-cartouche__row--groupe { background: var(--pl-paper); }
.isis-pl-cartouche__row--groupe .isis-pl-cartouche__k { background: transparent; border-right: 0; font-size: 11px; letter-spacing: 0; padding: 5px 12px; flex-direction: row; align-items: baseline; flex-wrap: wrap; gap: 0 8px; }
.isis-pl-cartouche--refs .isis-pl-cartouche__k small { display: block; text-transform: none; letter-spacing: 0; font-family: 'Geist', system-ui, sans-serif;
    font-weight: 400; font-size: 11px; line-height: 1.3; color: var(--pl-ink-2); }
.isis-pl-cartouche__val small { display: inline; font-family: 'Geist', system-ui, sans-serif; font-weight: 400; font-size: 11.5px; color: var(--pl-ink-2); margin: 0 0 0 6px; }
/* Renvois : sous le cartouche et son pied, en flux continu « (1) … · (2) … » (lot B, arbitrage du
   propriétaire). Un bandeau sous la planche prenait sa hauteur à la colonne du milieu, déjà à son plancher. */
/* Marge droite : le bouton flottant d'aide (44 px, fixé en bas à droite) recouvrait la fin de 6 lignes à 1512 × 982. */
.isis-pl-renvois { margin: 0; padding: 0 30px 0 2px; list-style: none; font-size: 11px; line-height: 1.4; color: var(--pl-ink-2); }
.isis-pl-renvois li { display: inline; }
.isis-pl-renvois li + li::before { content: " · "; color: var(--pl-ink-3); }
.isis-pl-renvois__no { font-family: var(--pl-mono); font-weight: 600; }
/* Chaque renvoi de ligne de groupe dit sa colonne (« T−1 (4) ») : la ligne passe sur deux lignes de texte ;
   son rembourrage vertical réduit rend la hauteur prise (colonne cartouche à 0 px de défilement à 1512 × 982). */
.isis-pl-groupe-renvoi { white-space: nowrap; }
.isis-pl-cartouche--refs .isis-pl-cartouche__row--groupe .isis-pl-cartouche__k { padding-top: 3px; padding-bottom: 3px; }
.isis-pl-cartouche__foot--seul { border: 1px solid var(--pl-line); border-radius: var(--pl-radius); }
/* Titre du cartouche sorti du tableau (1.3.1) : un h2 qui garde l'apparence de la ligne d'en-tête. */
.isis-pl-cartouche__row--head h2.isis-pl-cartouche__k { margin: 0; }
/* Le cartouche à références reste sur UNE colonne à tous les paliers : ≤ 900 le replie sinon en deux
   colonnes et sépare les lignes de leur en-tête (1.4.10, zoom 200 %). Ses lignes gardent 118 px d'intitulé. */
.isis-pl-cartouche.isis-pl-cartouche--refs { display: block; align-self: stretch; container-type: inline-size; container-name: cartouche-refs; }
/* align-self : un conteneur inline-size n'a pas de largeur intrinsèque ; sous `align-items: start` (palier ≤ 900) il tombait à 2 px. */
.isis-pl-cartouche--refs .isis-pl-cartouche__row.isis-pl-cartouche__row { border-right: 0; }
@container planche (max-width: 900px) {
    /* La colonne cartouche est en `column` : une base en % s'y lit sur la HAUTEUR et figeait le cartouche à la
       hauteur de la colonne, le reste étant rogné. */
    .isis-planche-page .isis-planche__cartouche-col > .isis-pl-cartouche--refs { flex-basis: auto; width: 100%; box-sizing: border-box; }
}
/* Cartouche étroit (zoom ≥ 110 %, palier ≤ 1100 à 300 px) : les 4 références passent en 2 × 2 plutôt que
   d'écraser chacune à ~28 px ; l'en-tête suit la même grille. */
@container cartouche-refs (max-width: 350px) {
    .isis-pl-refs { grid-template-columns: repeat(2, minmax(0, 1fr)); row-gap: 1px; }
}
/* Tableau et pied se suivent de près : ils forment un seul document. */
.isis-planche--cartouche-large .isis-planche__cartouche-col:has(.isis-pl-cartouche--refs) { gap: 10px; }
@container planche (min-width: 1101px) {
    .isis-planche--cartouche-large .isis-pl-details--activite { grid-template-columns: minmax(200px, .8fr) minmax(0, 1fr); gap: 16px; }
    .isis-planche--cartouche-large .isis-pl-details--activite > .isis-pl-detail--large { grid-column: 1 / -1; }
}
.isis-pl-detail { overflow-x: auto; }
/* Un bloc de détail ne descend JAMAIS sous son contenu (lot A, 2026-09-18, 17 planches). `overflow-x: auto`
   ci-dessus lui retire sa hauteur minimale automatique : dans un plan à hauteur fixe, la grille des
   détails l'écrasait alors jusqu'à 83 px pour 340 de contenu (gescom, sirh, sécurité, gespla). Avec
   ce plancher, c'est la zone des détails qui défile. */
.isis-planche-page .isis-pl-details > .isis-pl-detail { min-height: min-content; }
.isis-pl-nomen td { overflow-wrap: anywhere; }
.isis-pl-nomen td.is-r { overflow-wrap: normal; }
/* Planche pleine hauteur : la page ne défile plus, c'est le CORPS de planche qui défile
   (légende et cartouche restent en place). Le cadre se cale sur le bas de la zone de contenu. */
.isis-planche-page.isis-rich-page--scrollable { height: 100%; overflow: hidden; display: flex; flex-direction: column; }
.isis-planche-page .isis-planche { flex: 1 1 auto; min-height: 0; }
.isis-planche-page .isis-planche__corps { flex: 1 1 auto; min-height: 0; }
.isis-planche-page .isis-planche__legende, .isis-planche-page .isis-planche__plan, .isis-planche-page .isis-planche__cartouche-col { min-height: 0; overflow-y: auto; }
/* Les blocs de la colonne cartouche (overflow hidden) ne doivent pas être compressés par le flex : ils gardent leur hauteur, la colonne défile. */
.isis-planche-page .isis-planche__cartouche-col > * { flex: none; }
.isis-planche-page .isis-planche__plan { padding-bottom: 32px; }
/* Corps et cartouche défilent (ci-dessus) et leur contenu n'est pas fait que de cibles de tabulation :
relevé du 2026-09-23 à 1440 × 780 — jusqu'à 2825 px cachés dans le corps pour 3 cibles, et 39 à 501 px
dans le cartouche pour AUCUNE cible sur 12 planches sur 14. D'où le cran clavier `tabindex="0"` posé sur
les deux (WCAG 2.1.1, A) ; sans halo, la tabulation les traverserait sans trace. Contour RENTRANT : un
contour sortant serait rogné par leur propre overflow. */
.isis-planche__plan:focus-visible,
.isis-planche__cartouche-col:focus-visible,
/* cran posé à l'exécution par isis-planche-keys.js sur une colonne qui piège du contenu */
.isis-planche [data-isis-cran="auto"]:focus-visible { outline: 2px solid var(--isis-current-mod, var(--isis-accent)); outline-offset: -2px; }

/* Zoom ≥ 125 % : sous 900 px de planche, la planche prend la hauteur de son contenu et la PAGE défile
   (WCAG 1.4.10) au lieu de trois colonnes qui défilent chacune dans une boîte écrasée. Accroche = le parent
   de la page (.isis-shell__content, et .isis-master-main pour la console /master) : une container query
   ne style pas son propre conteneur, et c'est la page puis la planche qu'il faut libérer. Seuil exact :
   900 + 2 × 1rem (padding de .isis-rich-page) + 2 × 1px (bordure de .isis-planche) = 934 px à 16 px de
   police racine, 950 à 24 px. Relevé à 960 : libérer un peu tôt est sans effet visible, libérer trop
   tard ramène la piste du milieu à 0 px. */
.isis-shell__content,
.isis-master-main { container-type: inline-size; container-name: shell-contenu; }
@container shell-contenu (max-width: 960px) {
    .isis-planche-page.isis-rich-page--scrollable { height: auto; min-height: 100%; overflow: visible; }
    .isis-planche-page .isis-planche { flex: none; }
    .isis-planche-page .isis-planche__corps { flex: none; grid-template-rows: none; }
    .isis-planche-page .isis-planche__legende,
    .isis-planche-page .isis-planche__plan,
    .isis-planche-page .isis-planche__cartouche-col { overflow: visible; max-height: none; }
    .isis-planche-page .isis-planche__plan { align-self: start; }
    .isis-planche-page .isis-planche__plan > .isis-pl-leve,
    .isis-planche-page .isis-planche__plan > .isis-pl-leve + .isis-pl-details { flex: none; min-height: auto; overflow: visible; }
    .isis-planche-page .isis-pl-details { overflow: visible; }
}

/* Tuiles de modules du levé d'accueil. Grille auto-ajustée : le nombre de modules
   accessibles varie d'un utilisateur à l'autre, une grille fixe laisserait des trous. */
.isis-accueil-modules {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    gap: 0.5rem;
}
.isis-accueil-module {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    padding: 0.6rem 0.7rem;
    border: 1px solid var(--pl-line);
    border-radius: var(--pl-radius);
    background: var(--pl-paper);
    color: var(--pl-ink);
    text-decoration: none;
    box-shadow: var(--isis-elevation-1);
}
.isis-accueil-module:hover { box-shadow: var(--isis-elevation-hover); }
.isis-accueil-module:focus-visible { outline: 2px solid var(--isis-current-mod); outline-offset: 2px; }
.isis-accueil-module__nom { font-weight: 600; font-size: 0.9rem; }
.isis-accueil-module__sub { font-size: 0.78rem; color: var(--pl-ink-3); }

/* ── Libellé utilisateur (UserLabel) ──────────────────────────────────────
   Le nom domine, le login le situe (journaux, audit, sécurité). */
.isis-userlabel {
    display: inline;
    min-width: 0;
}
.isis-userlabel__login {
    margin-left: 0.3em;
    font-size: 0.85em;
    font-family: var(--isis-font-mono);
    color: var(--isis-text-muted);
    white-space: nowrap;
}

/* ────────────────────────────────────────────────────────────────────────────
   Mode PLAGE du filtre d'en-tête (2026-09-02) — dates et montants.
   Le mode n'est pas un choix de goût : il découle de la CARDINALITÉ de la
   colonne. Cardinalité bornée → cases à cocher ; valeur unique par ligne →
   « contient » ; date ou montant → plage. Des cases à cocher sur une colonne
   unique produiraient une liste aussi longue que la grille.
   ──────────────────────────────────────────────────────────────────────────── */
.isis-head-filter__range {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 8px;
    padding: 8px 10px;
}
.isis-head-filter__range label {
    display: flex;
    flex-direction: column;
    gap: 3px;
    min-width: 0;
}
.isis-head-filter__range span {
    font-size: var(--isis-fs-caption);
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--isis-text-soft);
}
.isis-head-filter__range input {
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-sm);
    padding: 4px 6px;
    font-family: var(--isis-font-mono);
    font-size: var(--isis-fs-sm);
    font-variant-numeric: tabular-nums;
    background: var(--isis-surface);
    color: var(--isis-text);
    min-width: 0;
}
.isis-head-filter__range input:focus-visible {
    outline: 2px solid var(--isis-accent);
    outline-offset: 1px;
}
.isis-head-filter__shortcuts {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    padding: 0 10px 8px;
}
.isis-head-filter__shortcut {
    border: 1px solid var(--isis-border);
    background: var(--isis-surface);
    color: var(--isis-text-muted);
    border-radius: var(--isis-radius-pill);
    padding: 2px 10px;
    font-size: var(--isis-fs-label);
    font-family: inherit;
    cursor: pointer;
    /* WCAG 2.5.8 — le raccourci était haut de 16px environ. */
    min-height: 24px;
}
/* Compteur de facette, rendu à part du libellé : cousu dedans, il devenait cherchable
   (taper « 3 » remontait toutes les valeurs à 3 éléments) et non stylable. */
.isis-head-filter__count {
    margin-left: auto;
    /* Un compteur ne se tronque JAMAIS : « 126 » rogné en « 1.. » n'est pas un nombre plus
       court, c'est un nombre faux. C'est le libellé qui cède (relevé au navigateur le
       2026-09-02 sur un client au nom long). */
    flex: 0 0 auto;
    font-family: var(--isis-font-mono);
    font-variant-numeric: tabular-nums;
    font-size: var(--isis-fs-sm);
    color: var(--isis-text-soft);
}
/* Libellé + seconde grandeur (IsisColumnFilterOption.Hint) empilés, quand une option porte
   un montant en plus de son effectif — « Envoyés / 12,4 M XOF HT » avec 24 à droite. Le
   compteur reste HORS de ce bloc, donc toujours à droite et toujours entier. Deux lignes
   seulement quand Hint est renseigné : sans lui, ce wrapper se comporte comme le <span>
   d'avant. */
.isis-head-filter__text {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.1rem;
    min-width: 0;
    /* Occupe l'espace restant : sans lui, le « space-between » du parent pousse le libellé
       CONTRE le bord droit dès qu'une option n'a pas de compteur — d'où une liste où seules
       les valeurs à effectif non nul restaient alignées à gauche (mesuré sur la facette Statut
       des marchés, où cinq statuts sur six sont à zéro). */
    flex: 1;
}
.isis-head-filter__hint {
    font-family: var(--isis-font-mono);
    font-variant-numeric: tabular-nums;
    font-size: 0.7rem;
    font-weight: 400;
    color: var(--isis-text-soft);
}
/* L'élision porte sur le wrapper, qui est une COLONNE : ses deux lignes sont des enfants flex
   et ne l'héritent pas — sans cette règle un nom trop long est coupé net, sans points de
   suspension, alors que le commentaire du wrapper promet le contraire. */
.isis-head-filter__text > span {
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/* Un <button> et un <input> n'héritent PAS de la famille de police : sans cette règle ils
   retombent sur la valeur du navigateur (Arial, mesuré le 2026-09-23) alors que le panneau
   qui les contient est bien en Geist. Le défaut ne se voyait pas tant que les seuls textes
   du panneau étaient courts ; il concerne tous les entonnoirs de l'application. */
.isis-filter-facet-btn,
.isis-grid__filter-btn,
.isis-head-filter__panel button,
.isis-head-filter__panel input {
    font-family: inherit;
}

/* Un hint qui n'est pas une grandeur : du texte courant, pas une colonne à aligner. */
.isis-head-filter__hint--text {
    font-family: inherit;
    font-variant-numeric: normal;
}
/* Un item à deux lignes ne se centre plus verticalement sur une ligne unique. */
.isis-head-filter__item:has(.isis-head-filter__hint) { align-items: flex-start; }

/* Le libellé, lui, s'élide. */
.isis-head-filter__item > span {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Borne refusée : le champ le dit, et le message porte `role="alert"`. */
.isis-head-filter__range input.is-invalid {
    border-color: var(--isis-danger);
    background: color-mix(in srgb, var(--isis-danger) 6%, var(--isis-surface));
}
.isis-head-filter__erreur {
    margin: 0;
    padding: 0 10px 8px;
    font-size: var(--isis-fs-sm);
    line-height: 1.35;
    color: var(--isis-danger);
}
.isis-head-filter__shortcut:hover {
    border-color: var(--isis-current-mod, var(--isis-accent));
    color: var(--isis-current-mod, var(--isis-accent));
}
.isis-head-filter__shortcut:focus-visible {
    outline: 2px solid var(--isis-accent);
    outline-offset: 1px;
}

/* ════════════════════════════════════════════════════════════════════════════
   VOLET INDICATEURS À QUESTIONS (2026-09-02)
   Maquette de référence : docs/mockups/2026-09-01-volet-questions.html

   Le volet ne répond plus « combien » — une pile de compteurs libellé + nombre —
   mais à UNE question choisie par l'utilisateur : Manques · Portrait · Clients · Où.
   Le vocabulaire est celui des PLANCHES (filets, mono tabulaire, hachures pour le
   projeté) : ce n'est pas un langage de plus, c'est celui déjà validé pour les
   tableaux de bord.

   Deux règles de couleur, apprises en maquette :
   - encre par défaut, la couleur n'apparaît que lorsqu'elle SIGNIFIE (seuil, zéro,
     alerte). Sur les KPI historiques, 314 valeurs sur 446 étaient en couleur de
     module par défaut : la couleur ne disait donc rien.
   - le HACHURÉ signifie « projeté / engagé non consommé ». S'en servir pour
     désigner un manque serait un contresens : les jauges de Manques sont pleines.
   ════════════════════════════════════════════════════════════════════════════ */

/* Le volet n'est pas dans une .isis-planche-page : il pose lui-même ses jetons. */
.isis-vq {
    --pl-ink: var(--isis-text);
    --pl-ink-2: var(--isis-text-muted);
    --pl-ink-3: var(--isis-text-muted);
    --pl-line: var(--isis-border);
    --pl-line-strong: color-mix(in srgb, var(--isis-text) 8%, var(--isis-border));
    --pl-rule-soft: color-mix(in srgb, var(--isis-border) 55%, var(--isis-surface));
    --pl-accent: var(--isis-current-mod, var(--isis-accent));
    --pl-accent-soft: var(--isis-current-mod-soft, var(--isis-accent-soft));
    --pl-exist: var(--isis-current-mod, var(--isis-accent));
    --pl-paper: var(--isis-surface);
    --pl-mono: var(--isis-cockpit-mono);

    border: 1px solid var(--pl-line-strong);
    border-radius: var(--isis-radius);
    background: var(--pl-paper);
    overflow: hidden;
}

/* Sélecteur de question : grille de cases à filets, idiome des « échelles = filtres »
   d'une planche. Colonnes proportionnelles au texte, JAMAIS 4 colonnes égales —
   « Où » perdu au centre d'une case aussi large que « Portrait » est un vide muet. */
.isis-vq__sel {
    display: flex;
    border: 1px solid var(--isis-border-strong);
    border-radius: var(--isis-radius);
    overflow: hidden;
    margin-bottom: 10px;
}
.isis-vq__sel button {
    flex: 1 1 auto;
    border: 0;
    border-left: 1px solid var(--isis-border);
    background: var(--isis-surface);
    color: var(--isis-text-muted);
    font-family: var(--isis-cockpit-mono);
    font-size: 10.5px;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    padding: 5px 10px;
    line-height: 1.2;
    white-space: nowrap;
    cursor: pointer;
    /* WCAG 2.5.8 : mesuré 52×23 au navigateur — un pixel sous le plancher. */
    min-height: 24px;
}
.isis-vq__sel button:first-child { border-left: 0; }
.isis-vq__sel button:hover:not([aria-disabled="true"]) {
    background: color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 8%, transparent);
    color: var(--isis-text);
}
.isis-vq__sel button:focus-visible { outline: 2px solid var(--isis-accent); outline-offset: -2px; }
.isis-vq__sel button[aria-pressed="true"] {
    background: var(--isis-current-mod-soft, var(--isis-accent-soft));
    color: var(--isis-current-mod, var(--isis-accent));
    border-color: var(--isis-current-mod, var(--isis-accent));
    font-weight: 600;
}
/* Une question sans données est DÉSACTIVÉE, jamais masquée : la barre garde la même
   forme d'une page à l'autre, donc la même mémoire musculaire. */
/* `aria-disabled` et non `disabled` : le bouton reste focalisable, donc son `title`
   — « aucune donnée pour cette question » — enfin lisible au clavier.
   Pas de hachuré ici : la charte lui réserve le sens « projeté / engagé non consommé »,
   et l'état vide « zone non levée ». Lui donner un troisième sens dans le même composant
   viderait le signe. L'encre atténuée et le curseur suffisent à dire l'inertie. */
.isis-vq__sel button[aria-disabled="true"] {
    color: var(--isis-text-muted);
    cursor: not-allowed;
    background: var(--isis-surface-alt);
}

.isis-vq__q {
    margin: 0;
    font-family: var(--pl-mono);
    font-size: 10.5px;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    padding: 8px 12px;
    background: var(--pl-accent-soft);
    color: var(--pl-accent);
    font-weight: 600;
}
.isis-vq__body { padding: 12px; }
/* Provenance : UNE ligne mono. Une phrase de trois lignes pour dire ce qu'un clic
   apprend tout seul est du remplissage. */
.isis-vq__foot {
    font-family: var(--pl-mono);
    font-size: 10.5px;
    color: var(--pl-ink-3);
    padding: 8px 12px;
    border-top: 1px solid var(--pl-line);
    line-height: 1.4;
}
.isis-vq__foot em { font-style: normal; font-weight: 600; color: var(--pl-ink-2); }

/* ── Manques : une ligne de nomenclature tient sur UNE ligne ──────────────────
   libellé · mini-barre · valeur · dénominateur. La valeur est reine (17px/600
   mono, proportion du cartouche de planche) ; le libellé la soutient (12.5px) ;
   le dénominateur est un contexte (10.5px, encre pâle). L'inverse — un libellé
   sans-serif qui écrase un nombre de 14px — était le défaut de la 1re maquette. */
.isis-vq-manque { display: flex; flex-direction: column; }
.isis-vq-manque__row,
.isis-vq-part__row {
    /* width:100% + padding débordait de 20 px et tronquait le montant : le padding doit
       être INCLUS dans la largeur (défaut constaté au navigateur le 2026-09-02). */
    box-sizing: border-box;
}
.isis-vq-manque__row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 46px auto minmax(26px, auto);
    gap: 8px;
    align-items: center;
    padding: 7px 12px;
    border-top: 1px solid var(--pl-rule-soft);
    width: 100%;
    background: none;
    border-left: 0; border-right: 0; border-bottom: 0;
    text-align: left;
    font-family: inherit;
    cursor: pointer;
}
.isis-vq-manque__row:first-child { border-top: 0; }
.isis-vq-manque__row:hover:not([aria-disabled="true"]) {
    background: color-mix(in srgb, var(--pl-accent) 7%, transparent);
}
.isis-vq-manque__row[aria-disabled="true"] { cursor: default; }
.isis-vq-manque__row:focus-visible { outline: 2px solid var(--isis-accent); outline-offset: -2px; }
.isis-vq-manque__l {
    font-size: 12.5px;
    color: var(--pl-ink);
    min-width: 0;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.isis-vq-manque__n {
    font-family: var(--pl-mono);
    font-variant-numeric: tabular-nums;
    font-weight: 600;
    font-size: 17px;
    line-height: 1.1;
    letter-spacing: -0.01em;
    color: var(--pl-ink);
    text-align: right;
}
.isis-vq-manque__n.is-hi { color: var(--isis-warning); }
.isis-vq-manque__etat {
    grid-column: span 2;
    font-size: 12px;
    font-weight: 600;
    color: var(--isis-text-muted);
    text-align: right;
    white-space: nowrap;
}
.isis-vq-manque__etat.is-hi { color: var(--isis-warning); }
.isis-vq-manque__of {
    font-family: var(--pl-mono);
    font-size: 10.5px;
    color: var(--pl-ink-3);
    text-align: right;
}
/* Mini-barre à filet (idiome .isis-pl-mini). Remplissage PLEIN : le hachuré est
   réservé au projeté, pas au manquant. */
.isis-vq-manque__gauge {
    height: 7px;
    border: 1px solid var(--pl-line);
    display: flex;
    background: var(--pl-paper);
}
.isis-vq-manque__gauge i { display: block; height: 100%; background: var(--pl-ink-3); }
.isis-vq-manque__gauge.is-hi i { background: var(--isis-warning); }

/* ── Portrait : tranches LISIBLES, jamais des puissances de dix ─────────────── */
.isis-vq-hist {
    display: grid;
    gap: 3px;
    align-items: end;
    height: 112px;
    border-bottom: 1px solid var(--pl-line-strong);
}
.isis-vq-hist__b {
    border: 1px solid var(--pl-ink);
    border-bottom: 0;
    /* Rampe séquentielle sur la teinte du module : --vq-teinte croît avec la tranche.
       Repli sur l'encre du plan si la variable n'est pas posée. */
    background: color-mix(in srgb,
                var(--isis-current-mod, var(--isis-accent)) var(--vq-teinte, 45%),
                var(--isis-surface));
    min-height: 2px;
    position: relative;
}
.isis-vq-hist__b.is-zero { background: transparent; border-style: dashed; opacity: 0.5; }
.isis-vq-hist__b span {
    position: absolute; top: -14px; left: 50%; transform: translateX(-50%);
    font-family: var(--pl-mono); font-size: 10px; color: var(--pl-ink);
}
/* Repère de médiane SOUS la barre : écrit dedans, il devenait illisible sur le
   remplissage (défaut relevé en maquette). */
.isis-vq-hist__b .isis-vq-hist__med {
    position: absolute; left: 0; right: 0; top: auto; bottom: -5px;
    height: 3px; background: var(--isis-warning);
}
.isis-vq-hist__ax { display: grid; gap: 3px; margin-top: 11px; }
.isis-vq-hist__ax i {
    font-style: normal;
    font-family: var(--pl-mono);
    font-size: 8.5px;
    color: var(--pl-ink-3);
    text-align: center;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.isis-vq-hist__axis {
    font-size: 10.5px; color: var(--pl-ink-3); font-family: var(--pl-mono);
    margin-bottom: 6px; line-height: 1.35;
}
.isis-vq-stats {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: 7px 12px;
    /* Filet + marge : les statistiques répondent à une autre question que le graphe,
       elles ne doivent pas lui être collées. */
    margin: 18px 0 0;
    padding-top: 12px;
    border-top: 1px solid var(--pl-rule-soft);
    font-size: 12px;
    align-items: baseline;
}
.isis-vq-stats dt {
    color: var(--pl-ink-3); font-family: var(--pl-mono); font-size: 10px;
    letter-spacing: 0.06em; text-transform: uppercase;
}
/* Attente : le volet dit qu'il calcule plutôt que de se rendre vide sans un mot. */
.isis-vq__attente {
    margin: 0;
    padding: 16px 12px;
    font-family: var(--pl-mono, var(--isis-font-mono));
    font-size: 11px;
    color: var(--isis-text-muted);
}

/* Note de portée : dit sur quelle part du périmètre un calcul porte. Discrète mais
   toujours visible — un portrait calculé sur 60 % des lignes doit le dire. */
.isis-vq__note {
    margin: 10px 0 0;
    padding-top: 8px;
    border-top: 1px dashed var(--pl-rule-soft);
    font-size: 11px;
    line-height: 1.45;
    color: var(--pl-ink-2);
}
.isis-vq-stats dd {
    margin: 0; font-family: var(--pl-mono); font-variant-numeric: tabular-nums;
    font-weight: 600; font-size: 13px; color: var(--pl-ink);
}

/* ── Contreparties ───────────────────────────────────────────────────────────── */
.isis-vq-part { display: flex; flex-direction: column; }
.isis-vq-part__row {
    display: flex; flex-direction: column; gap: 4px;
    padding: 6px 10px; border-top: 1px solid var(--pl-line);
    width: 100%; background: none; border-left: 0; border-right: 0; border-bottom: 0;
    text-align: left; font-family: inherit;
}
.isis-vq-part__row:first-child { border-top: 0; }
.isis-vq-part__top { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; }
.isis-vq-part__n {
    font-size: 12.5px; color: var(--pl-ink); min-width: 0;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.isis-vq-part__v {
    font-family: var(--pl-mono); font-variant-numeric: tabular-nums;
    font-weight: 600; font-size: 17px; line-height: 1.1; letter-spacing: -0.01em;
    color: var(--pl-ink); white-space: nowrap;
}
.isis-vq-part__bar { height: 8px; border: 1px solid var(--pl-line); display: flex; }
.isis-vq-part__bar i { display: block; height: 100%; background: var(--pl-ink-2); }
.isis-vq-part__s { font-family: var(--pl-mono); font-size: 10.5px; color: var(--pl-ink-3); }

/* ── Où : la carte est un <IsisAmChart Kind="HealthMap">, déjà servi par les
   tableaux de bord gescom et gesproj. Ici, seulement son cadre et sa légende. ── */
.isis-vq-geo__map { border: 1px solid var(--pl-line-strong); background: var(--pl-paper); }
.isis-vq-geo__leg {
    display: flex; flex-direction: column; gap: 4px; margin-top: 8px;
    font-size: 11.5px; color: var(--pl-ink-2);
}
.isis-vq-geo__leg div { display: flex; justify-content: space-between; gap: 10px; }
.isis-vq-geo__leg b {
    font-family: var(--pl-mono); font-variant-numeric: tabular-nums;
    font-weight: 600; font-size: 12px; color: var(--pl-ink);
}
/* État vide des planches : « zone non levée », hachurée, qui dit quoi faire pour
   la lever. On n'invente jamais de coordonnées. */
.isis-vq-geo__vide {
    border: 1px solid var(--pl-line);
    background: repeating-linear-gradient(45deg, transparent 0 5px,
        color-mix(in srgb, var(--pl-ink) 8%, transparent) 5px 7px);
    padding: 14px 12px; text-align: center;
    font-size: 12px; color: var(--pl-ink-2); line-height: 1.5;
}
.isis-vq-geo__vide b {
    display: block; font-family: var(--pl-mono); font-size: 10.5px;
    letter-spacing: 0.1em; text-transform: uppercase;
    color: var(--pl-ink-3); margin-bottom: 4px;
}

/* ── Rappel des filtres actifs, au-dessus de la grille ───────────────────────── */
.isis-vq-recall {
    display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
    font-size: var(--isis-fs-sm); color: var(--isis-text-muted);
}
.isis-vq-recall__tag {
    display: inline-flex; align-items: center; gap: 4px;
    border: 1px solid var(--isis-current-mod, var(--isis-accent));
    background: var(--isis-current-mod-soft, var(--isis-accent-soft));
    color: var(--isis-current-mod, var(--isis-accent));
    padding: 1px 4px 1px 8px;
    font-family: var(--isis-font-mono); font-size: var(--isis-fs-sm); font-weight: 500;
}
.isis-vq-recall__x {
    /* WCAG 2.5.8 — la cible mesurait ~10×14. Le plancher porte sur la CIBLE, pas sur le
       glyphe : celui-ci garde sa taille, c'est la zone cliquable qui s'élargit. */
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 24px; min-height: 24px;
    border: none; background: none; color: inherit; cursor: pointer;
    font-size: 14px; line-height: 1; padding: 0;
}
.isis-vq-recall__x:focus-visible { outline: 2px solid var(--isis-accent); outline-offset: 1px; }
.isis-vq-recall__clear {
    background: none; border: none; cursor: pointer; font-family: inherit;
    color: var(--isis-text-muted);
    font-size: var(--isis-fs-sm); text-decoration: underline;
}

/* Miette courante promue en titre de page (listes sans bandeau, 2026-09-01).
   Même position dans le fil, poids d'un titre : c'est un transfert, pas un ajout. */
.isis-breadcrumb__current--heading {
    margin: 0;
    font-size: var(--isis-fs-xl);
    font-weight: 600;
    letter-spacing: -0.02em;
    line-height: 1.2;
    color: var(--isis-text);
    /* Une fiche promeut son identifiant court, mais rien n'empêche une page d'y mettre
       un intitulé : la barre tronque au lieu de pousser la toolbar hors de l'écran.
       Le texte complet reste lisible par l'infobulle posée côté page. */
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* WCAG 2.4.7 — les deux boutons de pied du filtre d'en-tête n'avaient pas d'état
   de focus visible (défaut PRÉEXISTANT, relevé par l'audit du 2026-09-02). */
.isis-head-filter__clear:focus-visible,
.isis-head-filter__apply:focus-visible {
    outline: 2px solid var(--isis-accent);
    outline-offset: 1px;
}

/* En-tête de grille triable (2026-09-02) — le libellé DEVIENT le bouton de tri :
   ajouter un bouton à côté aurait doublé la cible et brouillé la colonne.
   Les propriétés du bouton lui-même vivent dans le bloc unique `.isis-grid__sort-btn`
   (plus haut dans ce fichier) : deux blocs concurrents faisaient s'annuler leur retrait
   et leur halo de focus. Ne restent ici que les indicateurs de sens. */
/* Indicateur de sens, porté par aria-sort — une seule source de vérité.
   Le texte alternatif VIDE (`/ ""`) rend la flèche décorative : sans lui, NVDA et JAWS
   lisent le contenu généré, et l'en-tête s'annonçait « Numéro, flèche haut » EN PLUS de
   l'état déjà porté par `aria-sort`. */
.isis-grid__head-cell[aria-sort="ascending"] .isis-grid__sort-btn::after  { content: " ↑" / ""; opacity: .7; }
.isis-grid__head-cell[aria-sort="descending"] .isis-grid__sort-btn::after { content: " ↓" / ""; opacity: .7; }
/* Un bouton qui porte déjà son icône de sens n'en reçoit pas une seconde (112 écrans à « ↑ ↑ »). */
.isis-grid__head-cell[aria-sort] .isis-grid__sort-btn:has(.isis-grid__sort-icon)::after { content: none; }

/* Compteur sur un chip de statut (2026-09-02) — reprend une part de ce que disait le rail
   KPI supprimé, mais sur le geste qui filtre plutôt que dans un bandeau. */
.isis-chip__count {
    font-family: var(--isis-font-mono);
    font-variant-numeric: tabular-nums;
    font-size: var(--isis-fs-caption);
    color: var(--isis-text-soft);
    margin-left: 5px;
}
.isis-chip.is-active .isis-chip__count { color: inherit; }
/* Un statut à zéro reste affiché — le retirer ferait bouger la barre d'une page à l'autre —
   mais s'estompe pour ne pas peser autant qu'un statut peuplé. */
/* Estompage exprimé par une COULEUR tokenisée et non par `opacity` : l'opacité
   s'appliquait au chip entier — libellé et compteur — et faisait tomber les deux
   autour de 2,5:1 (WCAG 1.4.3). */
.isis-chip.is-empty { color: var(--isis-text-soft); border-color: var(--isis-border-soft); }
.isis-chip.is-empty .isis-chip__count { color: var(--isis-text-soft); }
/* Filtre actif sur un statut vide : l'estompage, déclaré plus bas que l'état actif, posait
   un gris sur le fond module — libellé illisible. L'état actif prime. */
.isis-chip.is-active.is-empty,
.isis-chip.is-active.is-empty .isis-chip__count {
    color: white;
    border-color: var(--isis-current-mod, var(--isis-accent));
}

/* Devise en suffixe du montant : lisible, sans concurrencer le nombre. */
.isis-vq-part__cur {
    font-size: 11px;
    font-weight: 400;
    color: var(--pl-ink-3);
    margin-left: 4px;
}

/* Bouton du configurateur de colonnes — ancré sur le PARENT de .isis-grid, jamais
   dedans : .isis-grid est overflow:auto et son __head fait jusqu'à 1328px, un ancrage
   interne partirait hors écran. `top` n'est PAS posé ici : un parent statique peut
   commencer par une barre d'actions au-dessus de la grille (le bouton recouvrirait un
   vrai bouton de page), et un débord négatif fixe se fait rogner par un parent à
   overflow:hidden (constaté sur .isis-master-detail__master, 42% du bouton coupé,
   2026-09-03). isis-grid-config.js pose `top` en JS, calculé depuis grid.offsetTop —
   le coin de la GRILLE, jamais un décalage fixe depuis celui du parent. */
.isis-grid-cfg-btn {
    position: absolute;
    right: 4px;
    z-index: 6;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    padding: 0;
    border: 1px solid var(--isis-border);
    border-radius: 50%;
    background: var(--isis-surface);
    color: var(--isis-text-muted);
    box-shadow: var(--isis-elevation-1);
    cursor: pointer;
    opacity: 0.65;
    transition: opacity 120ms ease, color 120ms ease;
}
.isis-grid-cfg-btn:hover,
.isis-grid-cfg-btn:focus-visible {
    opacity: 1;
    color: var(--isis-current-mod);
}
.isis-grid-cfg-btn:focus-visible {
    outline: 2px solid var(--isis-current-mod);
    outline-offset: 2px;
}
.isis-grid-cfg-btn .isis-grid-cfg-btn__icon {
    font-size: 14px;
    line-height: 1;
}

/* Panneau du configurateur de colonnes. */
.isis-gridcfg__lede {
    margin: 0 0 0.75rem;
    color: var(--isis-text-muted);
    font-size: 0.8rem;
}
.isis-gridcfg__list { list-style: none; margin: 0; padding: 0; }
/* I3 (revue finale de branche) : cette règle était déclarée TROIS fois à spécificité égale
   (ici, puis deux fois plus bas dans la feuille) — les deux versions antérieures (3 puis 4
   colonnes) étaient du code mort, le rendu n'étant juste que par ordre de source. Consolidée
   ici en une seule déclaration à jour (6 colonnes : déplacement, visibilité, libellé,
   figement, styles, largeur). `padding-left` fait place à la poignée de glisser-déposer
   (`.isis-gridcfg__grip`, positionnée en absolu dans ce renfoncement). */
.isis-gridcfg__row {
    position: relative;
    display: grid;
    grid-template-columns: 34px 24px minmax(0, 1fr) 26px auto 84px;
    align-items: center;
    gap: 0.5rem;
    padding: 0.3rem 0 0.3rem 1rem;
    border-bottom: 1px solid var(--isis-border);
    cursor: grab;
}
.isis-gridcfg__row:active { cursor: grabbing; }
/* Amorce visuelle du glisser-déposer, jusqu'ici totalement absente (ni curseur, ni poignée,
   ni titre) : le geste natif `draggable="true"` ne se devine pas tout seul. `position:
   absolute` la sort de la grille : posée en PREMIER enfant du `<li>` pour l'ordre de lecture,
   elle ne consomme donc pas la 1re piste de `grid-template-columns` (spec CSS Grid : un enfant
   positionné en absolu n'entre pas dans le placement automatique). */
.isis-gridcfg__grip {
    position: absolute;
    left: 0.1rem;
    top: 50%;
    transform: translateY(-50%);
    font-size: 14px;
    line-height: 1;
    color: var(--isis-text-muted);
    pointer-events: none;
}
.isis-gridcfg__label { font-size: 0.85rem; overflow: hidden; text-overflow: ellipsis; }
.isis-gridcfg__label.is-off { color: var(--isis-text-muted); }
.isis-gridcfg__marks { display: inline-flex; gap: 0.2rem; }
.isis-gridcfg__mark {
    width: 26px; height: 26px; padding: 0;
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius);
    background: var(--isis-surface);
    color: var(--isis-text-muted);
    cursor: pointer;
    font-size: 0.8rem;
}
.isis-gridcfg__mark.is-on {
    /* Fallback --isis-accent obligatoire : ce panneau s'ouvre via DialogService, rendu par
       <RadzenComponents> — sibling de .isis-shell dans MainLayout.razor, PAS un descendant.
       --isis-current-mod n'est posée que dans .isis-shell/.isis-shell__content : sans repli,
       la variable est absente ici, pas seulement « non teintée module » (cf. .is-drop-target
       plus bas, même défaut, mesuré au navigateur — bordure de 0px au lieu de 2px). */
    border-color: var(--isis-current-mod, var(--isis-accent));
    color: var(--isis-current-mod, var(--isis-accent));
}
.isis-gridcfg__mark:disabled { opacity: 0.4; cursor: not-allowed; }
.isis-gridcfg__mark:focus-visible {
    outline: 2px solid var(--isis-current-mod, var(--isis-accent));
    outline-offset: 2px;
}
.isis-gridcfg__note {
    margin: 0.6rem 0 0;
    color: var(--isis-text-muted);
    font-size: 0.75rem;
}
.isis-gridcfg__footer {
    display: flex; justify-content: space-between; gap: 0.5rem;
    margin-top: 1rem;
}

/* ═══════════════════════════════════════════════════════════════════════════
   FeuilleTempsEditor — feuille de temps mensuelle.

   Ces règles vivaient dans un <style> inline du composant : injectées dans le
   document dès qu'il se rendait, elles étaient donc GLOBALES sans l'assumer, et
   deux dialogues qui s'en servent (FraisJourDialog pour .isis-frais-badge,
   CommentaireJourDialog pour .isis-wf-motif) n'étaient stylés que tant que
   l'éditeur restait à l'écran. Elles sont ici, avec les autres, où le thème les
   voit — et où un doublon se remarque.

   Trois familles n'ont pas suivi (2026-09-03, lot 5 d'harmonisation SIRH) :
   - .isis-comment-btn, .isis-saisie-help, .isis-valo-meta (base, --lead, __end),
     .isis-wf-visa__meta / __exp / .icn-done / .icn-wait : aucun élément du dépôt
     ne porte ces classes — les visas posent leurs couleurs en style inline ;
   - .isis-temps-selector .rz-dropdown (4 règles, toutes en !important) : le
     thème global harmonise déjà tous les RadzenDropDown (cf. « Harmonisation
     2026-07-04 » plus bas) et, le sélecteur étant descendu dans une
     .isis-filter-bar, la règle de hauteur 32px de la barre s'y applique — la
     copie ne servait plus qu'à faire diverger ce champ des autres.
   ═══════════════════════════════════════════════════════════════════════════ */
/* Bouton commentaire (3 états : vide / rempli / anomalie à justifier) */
/* Header unifié : méta feuille + bande de variables de paie (valorisation live) */
.isis-valo-meta__muted { color:var(--isis-text-muted); }
.isis-valo-meta__cv { display:inline-flex; align-items:center; gap:.35rem; }
/* Indicateurs + bascule « Journée type » poussés à droite de la ligne d'identité. */
.isis-meta-chip { display:inline-flex; align-items:center; gap:.3rem; font-weight:700; font-size:.78rem; padding:.12rem .55rem; border-radius:999px; white-space:nowrap; font-variant-numeric:tabular-nums; }
.isis-meta-chip.is-ok { color:var(--isis-success); background:color-mix(in srgb, var(--isis-success) 15%, transparent); }
.isis-meta-chip.is-warn { color:var(--isis-warning); background:color-mix(in srgb, var(--isis-warning) 20%, transparent); }
/* Sélecteur d'en-tête (Collaborateur / Année / Mois) : même affordance refined que les inputs. */
/* Navigateur de période : stepper mois + mini-calendrier (mois/année) */
.isis-period-field { position:relative; }
.isis-month-nav { display:inline-flex; align-items:center; gap:.1rem; height:33px; padding:0 .2rem;
    background:var(--isis-surface-alt); border:1px solid var(--isis-border-soft); border-bottom:1px solid var(--isis-border); border-radius:6px; }
.isis-month-nav__step { display:inline-flex; align-items:center; justify-content:center; width:28px; height:27px;
    border:1px solid transparent; border-radius:var(--isis-radius-sm); background:transparent; color:var(--isis-text-muted); cursor:pointer; }
.isis-month-nav__step:hover:not([aria-disabled="true"]) { background:var(--isis-surface); color:var(--isis-text); }
/* aria-disabled et non l'attribut `disabled` (2026-09-04) : le contrôle reste dans l'ordre
   de tabulation, donc son title — « Mois à venir : saisie non ouverte », seule explication
   du refus — reste atteignable au clavier. Le geste est refusé dans StepMonthAsync. */
.isis-month-nav__step[aria-disabled="true"] { opacity:.4; cursor:not-allowed; }
.isis-month-nav__step:focus-visible { outline:2px solid color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 55%, transparent); outline-offset:1px; }
.isis-month-nav__label { display:inline-flex; align-items:center; gap:.2rem; min-width:132px; justify-content:center;
    border:0; background:transparent; cursor:pointer; font-family:inherit; font-size:.86rem; font-weight:600; color:var(--isis-text);
    padding:.25rem .5rem; border-radius:var(--isis-radius-sm); white-space:nowrap; }
.isis-month-nav__label:hover { background:var(--isis-surface); }
.isis-month-nav__label:focus-visible { outline:2px solid color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 55%, transparent); outline-offset:1px; }
.isis-month-pop__backdrop { position:fixed; inset:0; z-index:1200; }
.isis-month-pop { position:absolute; top:calc(100% + .3rem); right:0; z-index:1201; width:250px; max-width:calc(100vw - 1rem);
    background:var(--isis-surface); border:1px solid var(--isis-border); border-radius:var(--isis-radius);
    box-shadow:var(--isis-elevation-2); padding:.6rem; }
.isis-month-pop__yr { display:flex; align-items:center; justify-content:space-between; margin-bottom:.5rem; }
.isis-month-pop__yr-lbl { font-weight:700; font-size:.95rem; font-variant-numeric:tabular-nums; color:var(--isis-text); }
.isis-month-pop__grid { display:grid; grid-template-columns:repeat(4, 1fr); gap:.3rem; }
.isis-month-pop__m { border:1px solid var(--isis-border-soft); background:var(--isis-surface); color:var(--isis-text);
    border-radius:var(--isis-radius-sm); padding:.55rem .35rem; font-family:inherit; font-size:.8rem; cursor:pointer; text-transform:capitalize;
    transition:background-color var(--isis-motion-fast), border-color var(--isis-motion-fast); }
.isis-month-pop__m:hover:not([aria-disabled="true"]) { background:var(--isis-surface-alt); border-color:var(--isis-border); }
.isis-month-pop__m[aria-disabled="true"] { opacity:.5; cursor:not-allowed; }
.isis-month-pop__m.is-current { background:color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 14%, var(--isis-surface));
    border-color:color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 45%, transparent);
    color:var(--isis-current-mod, var(--isis-accent)); font-weight:600; }
/* Badge nombre de frais sur le bouton « Frais » */
.isis-frais-badge { display:inline-block; min-width:16px; padding:0 .25rem; margin-left:.05rem; font-size:.68rem; font-weight:700; line-height:16px; text-align:center; border-radius:999px; background:var(--isis-accent); color:var(--isis-surface); vertical-align:middle; }
/* Workflow de validation à 3 visas */
.isis-wf-motif { display:flex; align-items:center; gap:.5rem; padding:.5rem .75rem; border-radius:8px; margin-bottom:.6rem; background:color-mix(in srgb, var(--isis-danger) 12%, var(--isis-surface)); color:var(--isis-danger); border:1px solid color-mix(in srgb, var(--isis-danger) 35%, transparent); font-size:.86rem; }
.isis-wf-frise { display:flex; align-items:center; gap:.4rem; flex-wrap:wrap; }
.isis-wf-status { padding:.12rem .6rem; border-radius:999px; font-size:.76rem; font-weight:700; white-space:nowrap; }
.isis-wf-status.is-brouillon { background:var(--isis-surface-alt); color:var(--isis-text-muted); }
.isis-wf-status.is-soumise   { background:color-mix(in srgb, var(--isis-accent) 16%, transparent); color:var(--isis-accent); }
.isis-wf-status.is-manager   { background:color-mix(in srgb, var(--isis-warning) 18%, transparent); color:var(--isis-warning); }
.isis-wf-status.is-valide    { background:color-mix(in srgb, var(--isis-success) 16%, transparent); color:var(--isis-success); }
.isis-wf-qhse { display:inline-flex; align-items:center; gap:.3rem; padding:.12rem .6rem; border-radius:999px; font-size:.76rem; font-weight:600; white-space:nowrap; text-decoration:none; cursor:pointer; background:color-mix(in srgb, var(--isis-warning) 14%, var(--isis-surface)); color:var(--isis-warning); border:1px solid color-mix(in srgb, var(--isis-warning) 38%, transparent); transition:background var(--isis-motion-fast); }
.isis-wf-qhse:hover { background:color-mix(in srgb, var(--isis-warning) 24%, var(--isis-surface)); }
.isis-wf-qhse:focus-visible { outline:2px solid color-mix(in srgb, var(--isis-warning) 55%, transparent); outline-offset:2px; }
.isis-wf-derog { margin-top:.5rem; padding:.7rem .8rem; border-radius:var(--isis-radius); background:color-mix(in srgb, var(--isis-warning) 8%, var(--isis-surface)); border:1px solid color-mix(in srgb, var(--isis-warning) 35%, transparent); }
.isis-wf-derog__hd { display:flex; align-items:flex-start; gap:.45rem; font-size:.84rem; color:var(--isis-text); margin-bottom:.4rem; }
.isis-wf-derog__hd .rzi { color:var(--isis-warning); flex:0 0 auto; }
.isis-wf-derog__list { margin:.1rem 0 .5rem 1.5rem; padding:0; font-size:.82rem; color:var(--isis-warning); }
.isis-wf-visa { display:inline-flex; align-items:center; gap:.3rem; padding:.1rem .5rem; border-radius:999px; font-size:.76rem; border:1px solid var(--isis-border); white-space:nowrap; }
.isis-wf-visa.is-done { background:color-mix(in srgb, var(--isis-success) 10%, var(--isis-surface)); border-color:color-mix(in srgb, var(--isis-success) 35%, transparent); }
.isis-wf-visa.is-active { font-weight:600; color:var(--isis-current-mod, var(--isis-accent)); background:color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 8%, var(--isis-surface)); border-color:color-mix(in srgb, var(--isis-current-mod, var(--isis-accent)) 40%, transparent); }
.isis-wf-visa.is-pending { color:var(--isis-text-muted); }
.isis-wf-visa__role { font-weight:600; }
.isis-wf-actions { display:flex; align-items:center; gap:.4rem; flex-wrap:wrap; }
.isis-wf-done { display:inline-flex; align-items:center; gap:.25rem; font-weight:700; color:var(--isis-success); font-size:.86rem; }
.isis-wf-hint { display:inline-flex; align-items:center; gap:.3rem; font-size:.8rem; color:var(--isis-text-muted); }
.isis-wf-reject { padding:.6rem .75rem; border-radius:8px; background:var(--isis-surface-alt); border:1px solid var(--isis-border); margin-bottom:.6rem; }
/* Navigation de semaine */
.isis-saisie-viewbar__nav { display:inline-flex; align-items:center; gap:.5rem; padding-left:.85rem; border-left:1px solid var(--isis-border-soft); }
.isis-saisie-loading { display:flex; align-items:center; gap:.6rem; padding:1.4rem .2rem; color:var(--isis-text-muted); font-size:.9rem; }
.isis-saisie-viewbar__range { font-size:.85rem; font-weight:600; font-variant-numeric:tabular-nums; color:var(--isis-text); white-space:nowrap; }
.isis-viewbar__gf-btn {
    display:inline-flex; align-items:center; justify-content:center; gap:.2rem; height:26px;
    padding:0 .45rem; border:none; border-radius:6px; cursor:pointer;
    background:color-mix(in srgb, var(--isis-warning) 20%, var(--isis-surface)); color:var(--isis-warning);
    font-size:.74rem; font-weight:700;
}
.isis-viewbar__gf-btn:hover { background:color-mix(in srgb, var(--isis-warning) 30%, var(--isis-surface)); }
.isis-viewbar__gf-btn:focus-visible { outline:2px solid var(--isis-accent); outline-offset:2px; }
.isis-viewbar__gf-btn .rzi { font-size:16px; }
/* Vue hebdo : la grille semaine s'étire pour occuper la hauteur restante de la page
   (les 7 colonnes-jours grandissent, le « + Ajouter » est poussé en bas via margin-top:auto). */
/* Hauteur bornée (pas min-height) : la grille ne pousse plus la page — chaque colonne-jour
   scrolle en interne (header + pied fixes). */
.isis-week-stretch { display:flex; flex-direction:column; height:calc(100vh - 300px); min-height:340px; }
.isis-week-stretch > .isis-wsg { flex:1; min-height:0; }
.isis-week-stretch .isis-wsg__week { flex:1; min-height:0; }
.isis-week-stretch .isis-wsg__day { height:100%; }

/* Hôte du calendrier de planification — occupe la hauteur restante (comme la vue hebdo) */
.isis-planif-host { display:flex; flex-direction:column; min-height:calc(100vh - 360px); padding:.25rem 0; }
.isis-planif-host > .isis-planif { flex:1; min-height:0; }
/* Option B — barre principale + méta discrète */
.isis-fh-main { display:flex; align-items:center; gap:.55rem; flex-wrap:wrap; padding-bottom:.5rem; }
.isis-fh-id { display:inline-flex; align-items:center; gap:.5rem; white-space:nowrap; }
.isis-fh-id strong { font-weight:600; font-size:1.02rem; }
.isis-fh-spacer { flex:1 1 auto; min-width:0; }
.isis-fh-meta { display:flex; align-items:center; gap:.55rem; flex-wrap:wrap;
    padding:.45rem 0 .1rem; margin-top:.15rem; border-top:1px solid var(--isis-border-soft);
    font-size:.82rem; color:var(--isis-text-muted); }

/* ═══════════════════════════════════════════════════════════════════════════
   Indicateurs sur la ligne de titre d'une section (2026-09-04)
   Deux chiffres qui QUALIFIENT une section n'ont pas besoin d'un rail à eux :
   ils tiennent à droite de son titre. Le passage en flex est porté par `:has()`
   pour ne toucher QUE les en-têtes qui en contiennent — `.isis-rich-section__header`
   est partagée par des dizaines de sections dont la mise en page ne doit pas bouger.
   ═══════════════════════════════════════════════════════════════════════════ */
.isis-rich-section__header:has(.isis-rich-section__stats) {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 0.25rem 0.75rem;
}
.isis-rich-section__stats {
    margin-left: auto;
    display: flex;
    align-items: baseline;
    gap: 1.25rem;
}
.isis-rich-section__stat {
    display: inline-flex;
    align-items: baseline;
    gap: 0.35rem;
}
.isis-rich-section__stat-k {
    font-size: var(--isis-fs-xs);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--isis-text-muted);
}
.isis-rich-section__stat-v {
    font-size: var(--isis-fs-md);
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    color: var(--isis-text);
}

/* Poignée de redimensionnement — posée DANS la cellule d'en-tête, jamais en frère de
   celle-ci : un frère deviendrait un élément de grille et décalerait toutes les pistes. */
.isis-grid-rsz {
    position: absolute;
    top: 0;
    bottom: 0;
    right: 0;
    width: 6px;
    cursor: col-resize;
    touch-action: none;
    background: transparent;
    z-index: 2;
}
.isis-grid-rsz::after {
    content: "";
    position: absolute;
    top: 20%;
    bottom: 20%;
    right: 2px;
    width: 1px;
    background: var(--isis-border);
    opacity: 0;
    transition: opacity 120ms ease;
}
.isis-grid-rsz:hover::after,
.isis-grid-rsz:focus-visible::after,
.isis-grid-rsz.is-dragging::after {
    opacity: 1;
    background: var(--isis-current-mod);
}
.isis-grid-rsz:focus-visible {
    outline: 2px solid var(--isis-current-mod);
    outline-offset: -2px;
}
/* Pendant le geste : plus aucun curseur de texte ni sélection parasite sur la page. */
body.isis-grid-rsz-active,
body.isis-grid-rsz-active * {
    cursor: col-resize !important;
    user-select: none !important;
}

/* Panneau du configurateur de colonnes : champ de largeur exacte, en plus du geste
   de glissement. Gabarit consolidé avec .isis-gridcfg__row plus haut (I3, revue finale). */
.isis-gridcfg__width { width: 84px; }
.isis-gridcfg__width input { text-align: right; }

/* Champ de motif de la décision en lot (revue périodique). Il vit dans la bande d'état de
   campagne, aux côtés des deux boutons : un motif saisi UNE fois pour vingt lignes. */
.isis-revue-lot__motif {
    flex: 1 1 260px;
    min-width: 180px;
    padding: 0.3rem 0.55rem;
    font: inherit;
    font-size: 0.82rem;
    color: var(--isis-text);
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-sm, 5px);
}
.isis-revue-lot__motif::placeholder { color: var(--isis-text-soft); }


/* ── Étape en cours de la reprise de données (/admin/reprise, 2026-09-06) ─────────────
   Le type de données choisi n'est pas un titre de page — il change au clic. Il se rend
   donc en `h2`, comme le libellé d'une planche de tableau de bord (§ E1 de la doctrine
   d'harmonisation). Pas de carte : c'est une ligne d'en-tête d'étape, pas un bloc. */
.isis-reprise-etape { margin: 0 0 0.75rem; }
.isis-reprise-etape__titre {
    margin: 0;
    font-size: var(--isis-fs-lg, 1.05rem);
    font-weight: 600;
    color: var(--isis-text);
}
.isis-reprise-etape__desc {
    margin: 0.2rem 0 0;
    font-size: var(--isis-fs-sm, 0.875rem);
    color: var(--isis-text-muted);
}

/* Panneau : la ligne compte six colonnes (déplacement, visibilité, libellé, figement,
   styles, largeur — gabarit posé sur .isis-gridcfg__row plus haut). Sur les 460px du
   dialogue, le libellé retombe à ~180px — c'est la limite, toute addition ultérieure
   exigera d'élargir le dialogue. */
/* Les deux flèches monter/descendre partagent la même colonne de 34px : elles s'empilent
   plutôt que de s'aligner, faute de place pour les poser côte à côte. */
.isis-gridcfg__moves { display: flex; flex-direction: column; gap: 2px; }
.isis-gridcfg__move,
.isis-gridcfg__pin {
    width: 24px; height: 24px; padding: 0;
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius);
    background: var(--isis-surface);
    color: var(--isis-text-muted);
    cursor: pointer;
    font-size: 0.7rem;
}
.isis-gridcfg__pin.is-on {
    /* Même repli --isis-accent que .isis-gridcfg__mark.is-on ci-dessus, même raison :
       dialogue rendu hors de .isis-shell. */
    border-color: var(--isis-current-mod, var(--isis-accent));
    color: var(--isis-current-mod, var(--isis-accent));
}
.isis-gridcfg__pin-icon { font-size: 14px; line-height: 1; }
.isis-gridcfg__move:disabled,
.isis-gridcfg__pin:disabled { opacity: 0.4; cursor: not-allowed; }
.isis-gridcfg__move:focus-visible,
.isis-gridcfg__pin:focus-visible {
    outline: 2px solid var(--isis-current-mod, var(--isis-accent));
    outline-offset: 2px;
}
.isis-gridcfg__density {
    display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap;
    margin-top: 0.75rem; padding-top: 0.75rem;
    border-top: 1px solid var(--isis-border);
}
.isis-gridcfg__density-label { font-size: 0.8rem; color: var(--isis-text-muted); }
/* Retour visuel du glisser-déposer : la ligne saisie s'estompe, la ligne survolée annonce
   où elle tombera. Sans ça le geste s'opère à l'aveugle. */
.isis-gridcfg__row.is-dragging { opacity: 0.5; }
/* B3 (recette 2026-09-06) : sans repli, --isis-current-mod est ABSENTE (pas seulement non
   teintée module) dans ce dialogue — cf. commentaire de .isis-gridcfg__mark.is-on plus haut.
   `border-top: 2px solid var(--isis-current-mod)` sans repli devenait invalide au calcul de
   la valeur, ce qui réinitialise TOUT le raccourci (y compris border-top-style) à son défaut
   — mesuré au navigateur : bordure de 0px pendant le survol de la cible de dépôt, en clair
   comme en sombre. */
.isis-gridcfg__row.is-drop-target { border-top: 2px solid var(--isis-current-mod, var(--isis-accent)); }

/* Pastille « cette vue porte aussi des colonnes » (UserViewsDialog) — sortie du flux de texte
   pour ne pas se confondre avec les notes personnelles de l'utilisateur (même position visuelle,
   même style italique gris que .isis-saved-views__name-notes). */
.isis-saved-views__col-badge { margin-left: 0.35rem; opacity: 0.6; vertical-align: middle; }

/* ============================================================================
   .isis-hscroll-shadow — ombres de bord pour un conteneur qui défile
   HORIZONTALEMENT (2026-09-07)

   Le dépôt avait déjà ce patron en vertical (`.isis-sidepanel__body`, plus bas)
   et ses tokens `--isis-scroll-shadow-*` sur :root ; il lui manquait la variante
   horizontale. Sans elle, trois conteneurs de la fiche devis cachaient des
   colonnes sans qu'aucun signe ne l'indique — dont Total HT et Marge, et le
   bouton qui retire un participant. Un défilement qu'on ne devine pas n'existe
   pas : « un geste nouveau sur un écran existant exige un indice permanent ».

   Technique : deux dégradés `local` qui défilent avec le contenu et découvrent
   deux ombres `scroll` restées en place. L'ombre ne s'affiche donc QUE du côté
   où il reste quelque chose à voir.

   POSITION VOLONTAIRE — en toute fin de feuille. C'est une classe UTILITAIRE :
   elle se compose avec des classes de composant (`.isis-grid`, ici) qui ont la
   même spécificité qu'elle et posent `background` en RACCOURCI, ce qui remet
   `background-image` à zéro. Déclarée plus haut, elle est silencieusement
   annulée — mesuré le 2026-09-07 : 0 couche de dégradé sur la grille des lignes
   alors que les deux tables voisines en avaient bien 4.
   ============================================================================ */
.isis-hscroll-shadow {
    background-image:
        linear-gradient(to right, var(--isis-scroll-shadow-bg) 30%, transparent),
        linear-gradient(to left,  var(--isis-scroll-shadow-bg) 30%, transparent),
        radial-gradient(farthest-side at 0 50%,    var(--isis-scroll-shadow-ink), transparent),
        radial-gradient(farthest-side at 100% 50%, var(--isis-scroll-shadow-ink), transparent);
    background-position: left center, right center, left center, right center;
    background-repeat: no-repeat;
    background-size:
        var(--isis-scroll-shadow-cover) 100%,
        var(--isis-scroll-shadow-cover) 100%,
        var(--isis-scroll-shadow-fade)  100%,
        var(--isis-scroll-shadow-fade)  100%;
    background-attachment: local, local, scroll, scroll;
    background-color: var(--isis-surface);
}

/* ============================================================================
   .isis-legal-preview — aperçu Markdown de la console d'articles légaux
   (/master/legal-blocs, 2026-09-07)

   POSITION VOLONTAIRE — en toute fin de feuille (cf. avertissement ci-dessus sur
   l'ordre source à spécificité égale) : cette classe ne compose avec aucun autre
   sélecteur de même poids, mais la doctrine du fichier est de placer les
   nouveaux ajouts en fin de feuille par défaut. --isis-border et --isis-surface
   sont définis à la fois sur :root et dans le bloc thème sombre.
   ============================================================================ */
.isis-legal-preview {
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-sm);
    padding: 16px 20px;
    background: var(--isis-surface);
}

.isis-legal-preview table { width: 100%; border-collapse: collapse; }
.isis-legal-preview th,
.isis-legal-preview td {
    text-align: left;
    padding: 6px 10px 6px 0;
    border-bottom: 1px solid var(--isis-border);
}

/* ============================================================================
   .isis-hub-volet — volet d'analyse du hub santé client (lot 1, tâche 6)
   Partagé par /gescom/commandes et /gescom/factures : le CADRE (repliable,
   en-tête, état vide) vit dans le markup de chaque page ; seul le contenu par
   devise (<HubKpiDevises>) est un composant avec sa propre feuille scopée.
   POSITION VOLONTAIRE — en toute fin de feuille (doctrine du fichier).
   ============================================================================ */
.isis-hub-volet {
    display: flex;
    flex-direction: column;
    gap: var(--isis-space-md);
    padding: var(--isis-space-md);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius);
    background: var(--isis-surface);
}

.isis-hub-volet__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--isis-space-sm);
}

.isis-hub-volet__head h2 {
    margin: 0;
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--isis-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

.isis-hub-vide {
    margin: 0;
    font-size: 0.85rem;
    color: var(--isis-text-soft);
}

/* ─────────────────────────────────────────────────────────────────────────────
   Refus d'accès — <AccesRefuse>, slot NotAuthorized de RequirePermission
   Même géométrie que les états vides (DESIGN.md §8) : l'utilisateur est devant
   une zone sans contenu, et la seule différence tient à la RAISON. Lui donner un
   traitement visuel distinct laisserait croire à une panne.
   ───────────────────────────────────────────────────────────────────────────── */
.isis-acces-refuse {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: 0.6rem;
    padding: 2.5rem 1.5rem;
    color: var(--isis-text-soft);
}
.isis-acces-refuse__titre {
    font-size: 0.95rem;
    font-weight: 600;
    color: var(--isis-text);
}
.isis-acces-refuse__texte {
    margin: 0;
    max-width: 46ch;
    font-size: 0.85rem;
    line-height: 1.5;
}
.isis-acces-refuse__texte--discret { color: var(--isis-text-muted); }
/* Une valeur refusée, dans une grille de fiche. Elle se distingue d'un « — » (non renseigné)
   par le mot ET par la couleur — jamais par la couleur seule (WCAG 1.4.1). */
.isis-detail-grid__refuse {
    font-style: italic;
    color: var(--isis-text-muted);
}
/* Un refus d'habilitation dans un rail de synthèse de fiche. Même famille que
   .isis-acces-refuse, en une phrase plutôt qu'en bloc : le rail est étroit et le titre de
   section porte déjà le sujet. */
.isis-detail-refus {
    font-size: 0.82rem;
    line-height: 1.45;
    color: var(--isis-text-muted);
    font-style: italic;
    max-width: 44ch;
}

/* ── Lot 8 — écran « Définir un profil » ────────────────────────────────────
   UNE classe est reprise de la fiche de rôle — .isis-cran-row__ecart-tag, le repère « Réglé à
   part » — pour que le même fait s'y lise de la même façon. Le reste est neuf : le grain
   diffère réellement (le profil a un arbre et une profondeur, le rôle a un détail par action),
   et prétendre une parité qui n'existe pas tromperait qui vient ajouter une classe ici.
   Valeurs par tokens uniquement. */
.isis-cran-incoherences {
    margin: 0.4rem 0 0; padding-left: 1.1rem;
    display: flex; flex-direction: column; gap: 0.3rem;
    font-size: 0.85rem; line-height: 1.45;
}
/* L'heritage ne porte AUCUN repere propre : le selecteur le dit deja, en toutes lettres
   (« herite : Consulter »). Le doubler sous le champ repetait la meme information et ramenait
   un filet vertical, banni par DESIGN.md §2. C'est l'ECART qui merite un repere — lui seul est
   invisible autrement — et il reutilise .isis-cran-row__ecart-tag de la fiche de role, pour que
   les deux ecrans de reglage des droits se lisent pareil. */
.isis-grid__row.is-ecart {
    background: color-mix(in srgb, var(--isis-accent) 5%, transparent);
}
:root[data-theme="dark"] .isis-grid__row.is-ecart {
    background: color-mix(in srgb, var(--isis-accent) 10%, transparent);
}

/* ── Gabarits de colonnes : OBLIGATOIRES ────────────────────────────────────
   Sans modificateur, .isis-grid__head/.isis-grid__row appliquent le gabarit par defaut —
   huit colonnes et 1000 px de largeur minimale, dessines pour la liste des tiers. C'est
   l'incident de DESIGN.md §4 (« le Libelle ecrase a 100 px »), et il se reproduit a
   l'identique sur toute grille qui oublie sa classe. */
.isis-grid--profils .isis-grid__head,
.isis-grid--profils .isis-grid__row {
    grid-template-columns: minmax(220px, 2fr) minmax(180px, 1.2fr) 130px 100px 110px;
    min-width: 860px;
}

/* La fiche : l'ecran (large, il porte le libelle, les badges et l'adresse), le niveau, puis
   les capacites. La colonne comparee s'intercale quand elle existe. */
.isis-grid--profil-ecrans .isis-grid__head,
.isis-grid--profil-ecrans .isis-grid__row {
    grid-template-columns: minmax(280px, 2.2fr) 210px minmax(240px, 1fr);
    min-width: 820px;
    align-items: start;
    padding-top: 0.45rem;
    padding-bottom: 0.45rem;
}
.isis-grid--profil-ecrans-compare .isis-grid__head,
.isis-grid--profil-ecrans-compare .isis-grid__row {
    grid-template-columns: minmax(280px, 2.2fr) 210px 150px minmax(240px, 1fr);
    min-width: 990px;
}
/* La ligne du haut reste alignee au texte : les en-tetes n'ont pas de selecteur a border. */
.isis-grid--profil-ecrans .isis-grid__head { align-items: center; }

/* Une valeur comparee qui DIFFERE : le poids et la couleur la signalent a l'oeil, et une
   mention lue a voix haute la signale au lecteur d'ecran — jamais la couleur seule. */
.isis-profil-compare__ecart {
    font-weight: 600;
    color: var(--isis-accent-strong);
}

/* La barre de reglages au-dessus de la grille : module, comparaison, recherche, filtre. */
.isis-profil-barre {
    display: flex; flex-wrap: wrap; align-items: flex-end; gap: 1rem;
}
.isis-profil-barre__case {
    display: flex; align-items: center; gap: 0.4rem; padding-bottom: 0.35rem;
}

/* La legende : repliee par defaut (elle s'apprend une fois), ouverte elle explique le
   vocabulaire — quatre niveaux et trois capacites que rien d'autre du produit n'enseigne. */
.isis-profil-legende {
    margin-bottom: 0.75rem;
    font-size: 0.82rem;
    color: var(--isis-text-muted);
}
.isis-profil-legende > summary {
    cursor: pointer; font-weight: 600; color: var(--isis-text);
    padding: 0.2rem 0;
}
.isis-profil-legende > summary:focus-visible {
    outline: 2px solid var(--isis-current-mod, var(--isis-accent));
    outline-offset: 2px; border-radius: 3px;
}
.isis-profil-legende dl {
    margin: 0.4rem 0 0; display: grid;
    grid-template-columns: max-content 1fr; gap: 0.25rem 0.8rem;
}
.isis-profil-legende dt { font-weight: 600; color: var(--isis-text); }
.isis-profil-legende dd { margin: 0; }
.isis-cran-capacite {
    display: inline-flex; align-items: center; gap: 0.3rem;
    margin-right: 0.7rem; font-size: 0.8rem; color: var(--isis-text);
    cursor: pointer;
}

/* Le lien d'une ligne de grille : c'est LUI qui est interactif, pas la ligne. Il doit donc
   porter un focus visible — sans quoi l'utilisateur au clavier traverse la liste a l'aveugle. */
.isis-grid__lien {
    color: var(--isis-text); font-weight: 600; text-decoration: none;
}
.isis-grid__lien:hover { text-decoration: underline; }
.isis-grid__lien:focus-visible {
    outline: 2px solid var(--isis-current-mod, var(--isis-accent));
    outline-offset: 2px; border-radius: 3px;
}

/* L'alignement numerique passe par la classe partagee, comme les grilles jumelles du meme
   module (.isis-grid--roles, .isis-grid--fonctions) : le chrome est centralise, on ne le
   surcharge pas ligne a ligne en style en ligne. */
.isis-grid--profils .isis-grid__col-num {
    text-align: right;
    font-variant-numeric: tabular-nums;
}

/* ── Lot 9 — « D'ou vient chaque droit » et les profils portes ──────────────
   Gabarits de colonnes OBLIGATOIRES : sans modificateur, .isis-grid__row applique le gabarit
   par defaut (huit colonnes, 1000 px mini) dessine pour la liste des tiers. C'est l'incident
   de DESIGN.md §4, reproduit a l'identique sur toute grille qui oublie sa classe — mesure au
   navigateur au lot 8. Valeurs par tokens uniquement. */
.isis-grid--profils-portes .isis-grid__head,
.isis-grid--profils-portes .isis-grid__row {
    grid-template-columns: minmax(240px, 2fr) 190px 190px 120px;
    min-width: 760px;
    align-items: start;
    padding-top: 0.45rem;
    padding-bottom: 0.45rem;
}
.isis-grid--profils-portes .isis-grid__head { align-items: center; }

.isis-grid--origines .isis-grid__head,
.isis-grid--origines .isis-grid__row {
    grid-template-columns: minmax(240px, 1.6fr) 120px 170px minmax(280px, 2fr);
    min-width: 900px;
    align-items: start;
    padding-top: 0.45rem;
    padding-bottom: 0.45rem;
}
.isis-grid--origines .isis-grid__head { align-items: center; }

/* La barre d'attribution d'un profil, dans l'en-tete du bloc. */
.isis-profil-attribution {
    display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap;
}
.isis-origine-barre { display: flex; align-items: center; gap: 0.5rem; }
.isis-origine-filtres {
    display: flex; flex-wrap: wrap; gap: 1.2rem; margin-bottom: 0.7rem;
}
.isis-origine-filtres__case { display: flex; align-items: center; gap: 0.4rem; }

/* La liste des origines d'un droit. Une origine par ligne : l'ETAGE d'abord (ou aller la
   retirer), le NOM ensuite (laquelle exactement). */
.isis-origine-liste {
    margin: 0; padding: 0; list-style: none;
    display: flex; flex-direction: column; gap: 0.2rem;
    font-size: 0.8rem;
}
.isis-origine-liste li { display: flex; gap: 0.4rem; flex-wrap: wrap; }
.isis-origine-liste__quoi { color: var(--isis-text-muted); min-width: 13rem; }
.isis-origine-liste__qui { color: var(--isis-text); font-weight: 600; }
/* Un refus n'est jamais signale par la seule couleur : son libelle dit « REFUS, prime sur
   tout », et la graisse le distingue du reste de la liste. */
.isis-origine-liste li.is-refus .isis-origine-liste__quoi {
    color: var(--isis-danger);
    font-weight: 600;
}
.isis-origine-liste__avertissement {
    display: block; margin-top: 0.3rem;
    font-size: 0.75rem; color: var(--isis-accent-strong);
}

/* Le refus, en theme SOMBRE. `--isis-danger` y vaut #e5534b, qui tombe a 3,6-4,2:1 sur une
   ligne teintee `.is-ecart` — sous l'AA. MESURE, pas suppose : la couleur composee a ete lue au
   navigateur au lot 8 et recalculee ici sur les jetons reels. On ne touche PAS au jeton produit
   (plus de cent usages, decision a part) : on remonte la luminance pour CE libelle seulement,
   ou le mot « REFUS » porte deja le sens. #fca5a5 rend 7,0 a 8,1:1 selon la surface. */
:root[data-theme="dark"] .isis-origine-liste li.is-refus .isis-origine-liste__quoi {
    color: #fca5a5;
}

/* La recherche de la synthese d'origines : meme habillage que celle de ChoixModuleDialog. */
.isis-origine-filtres__recherche {
    display: flex; align-items: center; gap: 0.35rem;
    padding: 0.2rem 0.5rem;
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius);
    background: var(--isis-surface);
    min-width: 18rem;
}
.isis-origine-filtres__recherche input {
    border: 0; outline: 0; background: transparent;
    color: var(--isis-text); font: inherit; font-size: 0.85rem;
    width: 100%; padding: 0.15rem 0;
}
.isis-origine-filtres__recherche:focus-within {
    outline: 2px solid var(--isis-current-mod, var(--isis-accent));
    outline-offset: 1px;
}

/* ── Lot 10 — « Qui peut quoi · Hygiene » ───────────────────────────────────
   Gabarit de colonnes OBLIGATOIRE : sans modificateur, .isis-grid__row applique le gabarit par
   defaut (huit colonnes, 1000 px mini) dessine pour la liste des tiers — incident DESIGN.md §4,
   mesure au navigateur au lot 8. Valeurs par tokens uniquement. */
.isis-grid--qui-peut .isis-grid__head,
.isis-grid--qui-peut .isis-grid__row {
    grid-template-columns: minmax(260px, 1.4fr) 210px minmax(300px, 2fr);
    min-width: 820px;
    align-items: start;
    padding-top: 0.45rem;
    padding-bottom: 0.45rem;
}
.isis-grid--qui-peut .isis-grid__head { align-items: center; }

/* ── Lot 12 — « Séparation des tâches » (/admin/permissions/incompatibilites) ───────────
   Deux grilles, un modificateur chacune (DESIGN.md §4 : un modificateur appartient à UNE page).
   Valeurs par tokens uniquement. */
.isis-grid--incompatibilites .isis-grid__head,
.isis-grid--incompatibilites .isis-grid__row {
    grid-template-columns: minmax(240px, 1.4fr) minmax(220px, 1.2fr) minmax(220px, 1.2fr) 110px 90px 96px;
    min-width: 980px;
    align-items: start;
    padding-top: 0.45rem;
    padding-bottom: 0.45rem;
}
.isis-grid--incompatibilites .isis-grid__head { align-items: center; }
/* Règle inactive : l'état est DIT (« Inactive ») ; aucune opacité — elle faisait chuter le
   contraste des sous-lignes sous 4,5:1 (audit a11y du lot). */
.isis-grid--incompatibilites .isis-grid__row.is-inactive strong { font-weight: 500; }

.isis-grid--ecarts .isis-grid__head,
.isis-grid--ecarts .isis-grid__row {
    grid-template-columns: minmax(200px, 1.1fr) minmax(180px, 1fr) minmax(280px, 1.6fr) 190px 130px 72px;
    min-width: 1050px;
    align-items: start;
    padding-top: 0.45rem;
    padding-bottom: 0.45rem;
}
.isis-grid--ecarts .isis-grid__head { align-items: center; }

/* Seconde ligne d'une cellule (code, login, auteur) — la cellule est en nowrap, la sous-ligne
   reprend le retour à la ligne pour rester lisible. */
.isis-sod-sous {
    display: block;
    font-size: 0.78rem;
    color: var(--isis-text-muted);
    white-space: normal;
}
.isis-sod-sous--clamp {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    overflow: hidden;
}
.isis-sod-droit { display: block; white-space: normal; }
/* Un droit figé dans un dialogue (lecture seule) : même chrome qu'un champ, sans en être un. */
.isis-form-linear .isis-sod-droit-fige {
    padding: 0.35rem 0;
    font-size: 0.9rem;
    border-bottom: 1px solid var(--isis-border-soft);
}

.isis-qpq-resume {
    display: flex; align-items: baseline; gap: 0.45rem; flex-wrap: wrap;
    margin-bottom: 0.7rem; font-size: 0.9rem;
}
.isis-qpq-resume > strong { font-size: 1.5rem; line-height: 1; }

/* Le seuil qui declenche la validation : il se lit sous la phrase, pas a sa place. */
.isis-qpq-seuil {
    display: block; margin-top: 0.3rem;
    font-size: 0.8rem; color: var(--isis-text-muted);
}

/* Les constats d'hygiene. Tous sont rendus, meme a zero : un signal absent de la liste se
   confond avec un signal a zero, et le lecteur ne peut plus distinguer « rien a signaler » de
   « pas encore mesure ». Celui qui a quelque chose a dire se distingue par `is-signale`. */
.isis-qpq-constats {
    display: grid; gap: 0.8rem;
    grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
}
.isis-qpq-constat {
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius);
    padding: 0.7rem 0.9rem;
    background: var(--isis-surface);
}
.isis-qpq-constat.is-signale {
    border-color: color-mix(in srgb, var(--isis-accent) 35%, var(--isis-border));
    background: color-mix(in srgb, var(--isis-accent) 4%, var(--isis-surface));
}
:root[data-theme="dark"] .isis-qpq-constat.is-signale {
    background: color-mix(in srgb, var(--isis-accent) 9%, var(--isis-surface));
}
.isis-qpq-constat__tete {
    display: flex; align-items: baseline; gap: 0.5rem;
}
.isis-qpq-constat__nombre {
    font-size: 1.6rem; font-weight: 700; line-height: 1;
    font-variant-numeric: tabular-nums;
    color: var(--isis-text-muted);
}
.isis-qpq-constat.is-signale .isis-qpq-constat__nombre {
    color: var(--isis-accent-strong);
}
.isis-qpq-constat__titre {
    margin: 0; font-size: 0.9rem; font-weight: 600; color: var(--isis-text);
}
.isis-qpq-constat__precision {
    margin: 0.4rem 0 0; font-size: 0.8rem; line-height: 1.45;
    color: var(--isis-text-muted);
}
.isis-qpq-constat__exemples {
    margin: 0.5rem 0 0; padding-left: 1.1rem;
    font-size: 0.78rem; line-height: 1.5; color: var(--isis-text);
}

/* Le titre de section de « Qui peut quoi » : la page enchaine trois cartes, et le premier bloc
   n'avait aucun titre alors que le second en avait un — qui navigue par titres ne trouvait pas
   le sujet principal de la page. */
.isis-qpq-section {
    margin: 0.2rem 0 0.4rem;
    font-size: 1rem; font-weight: 600; color: var(--isis-text);
}
.isis-qpq-entete {
    display: flex; align-items: baseline; gap: 0.6rem; flex-wrap: wrap;
    margin-bottom: 0.6rem;
}
.isis-qpq-entete__meta { font-size: 0.82rem; color: var(--isis-text-muted); }

/* La liste des porteurs PLAFONNE et defile en interne : un geste largement accorde alignait
   des dizaines de lignes et repoussait le bloc « Hygiene » loin sous la ligne de flottaison —
   or c'est lui qui appelle un geste. */
.isis-grid--qui-peut {
    max-height: 32rem;
}

/* ==========================================================================
   Lot 11 — « Ce que son poste propose » (fiche utilisateur)

   Ajoute EN FIN DE FICHIER, comme les blocs des lots 9 et 10 : dans cette feuille la
   specificite se joue a la POSITION, et un bloc insere plus haut se ferait recouvrir par les
   regles de grille qui le suivent.
   ========================================================================== */

/* Le silence, quand le poste ne propose rien. Il DOIT se lire comme une information — jamais
   comme un refus, et jamais comme une erreur : quatre causes distinctes y menent, chacune avec
   son geste. D'ou le ton neutre (surface alternative), et pas un ton d'alerte. */
.isis-qpq-silence {
    display: flex;
    gap: 10px;
    align-items: flex-start;
    padding: 12px 14px;
    background: var(--isis-surface-alt);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius);
}

.isis-qpq-silence .rz-icon {
    font-size: 18px;
    color: var(--isis-text-muted);
    flex: 0 0 auto;
    margin-top: 1px;
}

.isis-qpq-silence strong {
    display: block;
    color: var(--isis-text);
    margin-bottom: 2px;
}

/* La proposition elle-meme. Filet perimetrique (fond teinte + bordure 1px), jamais de lisere
   vertical epais : doctrine DESIGN.md §1. */
.isis-qpq-proposition {
    padding: 12px 14px;
    background: var(--isis-surface-alt);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius);
}

/* L'avertissement qui CHANGE le sens de « Appliquer » : des roles listes juste en dessous ne
   seront pas poses. Jetons ISIS et non `BadgeStyle.Warning` + `Shade.Lighter` — mesure au
   navigateur, cette nuance Radzen rend de l'orange sur un orange a 20 % d'alpha, ratio 1:1.
   Ici les deux couleurs sont opaques et se mesurent. */
.isis-qpq-proposition__avertissement {
    display: flex;
    gap: 8px;
    align-items: flex-start;
    margin: 0 0 10px;
    padding: 8px 10px;
    color: var(--isis-warning);
    background: var(--isis-warning-soft);
    border: 1px solid var(--isis-warning);
    border-radius: var(--isis-radius-sm);
}

.isis-qpq-proposition__avertissement .rz-icon {
    font-size: 16px;
    flex: 0 0 auto;
}

/* L'en-tete de colonnes, comme les deux sections voisines : sans lui, l'ordre « module puis
   role » n'etait dit que dans un commentaire, invisible a l'ecran. */
.isis-qpq-proposition__liste-head {
    display: flex;
    gap: 10px;
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--isis-text-muted);
    padding-bottom: 4px;
    margin-bottom: 4px;
    border-bottom: 1px solid var(--isis-border);
}

.isis-qpq-proposition__liste-head span:first-child { flex: 0 0 160px; }

.isis-qpq-proposition__liste {
    list-style: none;
    margin: 0 0 10px;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.isis-qpq-proposition__liste li {
    display: flex;
    gap: 10px;
    align-items: baseline;
    padding: 4px 0;
    border-bottom: 1px solid var(--isis-border-soft);
}

.isis-qpq-proposition__liste li:last-child { border-bottom: 0; }

/* Le module d'abord, en colonne fixe : l'oeil balaie « quel module » avant « quel role », et
   c'est dans cet ordre que l'administrateur decide. */
.isis-qpq-proposition__module {
    flex: 0 0 160px;
    color: var(--isis-text-muted);
    font-size: 0.8125rem;
}

.isis-qpq-proposition__role {
    color: var(--isis-text);
    font-weight: 500;
}

.isis-qpq-proposition__actions {
    display: flex;
    gap: 8px;
    align-items: center;
    flex-wrap: wrap;
    margin-top: 12px;
    padding-top: 12px;
    border-top: 1px solid var(--isis-border);
}

.isis-qpq-proposition__actions input[type="search"],
.isis-qpq-proposition__actions input[type="text"] {
    flex: 1 1 220px;
    min-width: 180px;
    padding: 6px 10px;
    font: inherit;
    color: var(--isis-text);
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius-sm, 6px);
}

.isis-qpq-proposition__actions input[type="text"]:focus-visible {
    outline: none;
    box-shadow: var(--isis-elevation-focus);
    border-color: var(--isis-current-mod);
}

@media (max-width: 720px) {
    .isis-qpq-proposition__liste li { flex-direction: column; gap: 2px; }
    .isis-qpq-proposition__module { flex: none; }
    .isis-qpq-proposition__liste-head { display: none; }
}

/* Le lien du geste, dans le bloc de silence du lot 11.
   `.isis-text-link` est atone et ne se souligne QU'AU SURVOL : mesure au navigateur, il rendait
   rgb(71,85,105) — exactement la couleur du texte qui l'entoure. Un lien qui ne se distingue
   qu'au survol est une affordance empruntee : rien n'indique qu'il y a quelque chose a cliquer,
   et c'est le seul geste que ce bloc propose. Indice PERMANENT, donc, et local : on ne touche
   pas la classe partagee du produit entier depuis ce lot. */
.isis-qpq-silence a.isis-text-link {
    /* PAS `--isis-current-mod` : mesure au navigateur, l'accent du module admin rend
       rgb(0,97,255) sur ce fond teinte, soit 4,06:1 — sous le seuil. Et l'accent CHANGE d'un
       module a l'autre : un lien colore par lui a un contraste imprevisible par construction,
       ce qu'aucune relecture de jetons n'aurait montre.
       Le soulignement PERMANENT porte donc seul l'affordance, ce qui est le patron accessible
       classique, et la couleur reste celle du texte. */
    color: var(--isis-text);
    font-size: inherit;
    font-weight: 500;
    text-decoration: underline;
    text-underline-offset: 2px;
}

.isis-qpq-silence a.isis-text-link:hover,
.isis-qpq-silence a.isis-text-link:focus-visible {
    text-decoration-thickness: 2px;
}

/* ── Lot 14 — bandeau « Vous agissez pour X » (ActingForBanner) ───────────────────────────
   Un état choisi, visible partout, réversible d'un clic. Tokens uniquement ; contraste : texte
   --isis-text sur --isis-accent-soft. */
.isis-actingfor-banner {
    display: flex; align-items: center; gap: 0.75rem;
    padding: 0.5rem 1rem;
    background: var(--isis-accent-soft);
    color: var(--isis-text);
    border-bottom: 1px solid var(--isis-border);
    font-size: 0.875rem;
}
.isis-actingfor-banner__icon { display: inline-flex; color: var(--isis-accent); }
.isis-actingfor-banner__text { flex: 1 1 auto; min-width: 0; }
.isis-actingfor-banner__btn {
    flex: 0 0 auto;
    padding: 0.35rem 0.75rem;
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius);
    background: var(--isis-surface);
    color: var(--isis-text);
    font: inherit; font-weight: 600; cursor: pointer;
}
.isis-actingfor-banner__btn:hover { background: var(--isis-surface-alt); }
.isis-actingfor-banner__btn:focus-visible { outline: 2px solid var(--isis-accent); outline-offset: 2px; }

/* ── Lot 15 — « voir comme » (variante du bandeau) et grilles des demandes / revues ─────── */
.isis-actingfor-banner--vue { background: var(--isis-surface-alt); border-bottom: 2px solid var(--isis-accent); }
.isis-grid--demandes-acces .isis-grid__head,
.isis-grid--demandes-acces .isis-grid__row {
    grid-template-columns: minmax(180px, 1fr) 120px minmax(220px, 1.4fr) minmax(220px, 1.4fr) 130px 120px 96px;
    min-width: 1080px; align-items: start; padding-top: 0.45rem; padding-bottom: 0.45rem;
}
.isis-grid--demandes-acces .isis-grid__head { align-items: center; }
.isis-grid--revue-items .isis-grid__head,
.isis-grid--revue-items .isis-grid__row {
    grid-template-columns: 40px minmax(200px, 1.1fr) 110px minmax(200px, 1.3fr) minmax(160px, 1fr) minmax(160px, 1fr) 130px;
    min-width: 1040px; align-items: start; padding-top: 0.45rem; padding-bottom: 0.45rem;
}
.isis-grid--revue-items .isis-grid__head { align-items: center; }
.isis-grid--revue-campagnes .isis-grid__head,
.isis-grid--revue-campagnes .isis-grid__row {
    grid-template-columns: minmax(220px, 1.4fr) 110px minmax(160px, 1fr) 90px 100px 100px 100px 130px;
    min-width: 1060px; align-items: start; padding-top: 0.45rem; padding-bottom: 0.45rem;
}
.isis-grid--revue-campagnes .isis-grid__head { align-items: center; }
/* Lot 15 — motif saisi sur une ligne pleine largeur sous la demande ; pageur des items de revue. */
.isis-l15-motif { display: flex; gap: 0.5rem; align-items: flex-start; padding: 0.25rem 0 0.4rem; }
.isis-l15-pager { display: flex; gap: 0.75rem; align-items: center; justify-content: flex-end; padding: 0.6rem 0 0; font-size: 0.85rem; color: var(--isis-text-muted); }

/* ── Fiche rôle, onglet Permissions : matrice écran × (cran | capacités) (2026-09-18) ──────────
   Remplace le bandeau « Cran du module », la liste à sélecteurs et la légende dépliée. Les crans
   sont des radios mutuellement exclusifs (une colonne par cran), les capacités des cases (une
   colonne par capacité) ; la case d'en-tête d'une colonne agit sur tout le module. */
.isis-role-matrice__outils {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem 1rem;
    margin: 0.25rem 0 0.5rem;
}
.isis-role-matrice__outils .isis-filter-bar__search { flex: 0 1 22rem; }
.isis-role-matrice__compte { color: var(--isis-text-muted); font-size: 0.8125rem; }
.isis-role-matrice__copie {
    margin-left: auto;
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.25rem 0.25rem 0.25rem 0.6rem;
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius);
}
.isis-role-matrice__copie.is-armee {
    background: color-mix(in srgb, var(--isis-accent) 9%, transparent);
    border-color: var(--isis-accent);
}
.isis-role-matrice__copie.is-armee .isis-action-btn.isis-action-btn--secondary {
    color: var(--isis-accent-strong);
    border-color: var(--isis-accent);
    font-weight: 600;
}
.isis-role-matrice__copie-label {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    font-size: 0.8125rem;
    color: var(--isis-text-muted);
    white-space: nowrap;
}
/* Le sélecteur hérite de rz-input-md (padding 7/15 + libellé 24 px de haut) : 51 px. Compacté
   à la hauteur des boutons, comme la barre du planning. */
.isis-role-matrice__copie .rz-dropdown {
    min-width: 14rem;
    min-height: 32px;
    padding: 0 0.55rem;
    display: inline-flex;
    justify-content: center;
}
.isis-role-matrice__copie .rz-dropdown .rz-dropdown-label {
    padding: 0;
    line-height: 1.5;
    font-size: var(--isis-fs-sm);
}
.isis-role-matrice__norme {
    margin: 0 0 0.5rem;
    font-size: 0.8125rem;
    color: var(--isis-text-muted);
    display: flex;
    align-items: center;
    gap: 0.35rem;
    flex-wrap: wrap;
}
.isis-role-matrice__norme #cran-module-norme { color: var(--isis-text); font-weight: 500; }
.isis-role-matrice__legende { margin: 0 0 0.75rem; font-size: 0.8125rem; }
.isis-role-matrice__legende > summary {
    cursor: pointer;
    color: var(--isis-text-muted);
    width: fit-content;
}
.isis-role-matrice__legende > summary:focus-visible { outline: 2px solid var(--isis-accent); outline-offset: 2px; }
.isis-role-matrice__legende[open] > summary { margin-bottom: 0.4rem; }

.isis-role-matrice__scroll {
    position: relative;
    overflow: auto;
    /* Le tableau défile DANS sa carte (en-tête et colonne Écran figés) : cadre calé sur la hauteur
       de la fenêtre, jamais moins de 18 rem pour rester utilisable sur un petit écran. */
    /* ~15 rem = en-tête de la fiche + onglets + barre d'outils, au-dessus du cadre (mesuré :
       232 px à 1512 × 982, résumé, norme et légende étant passés dans l'onglet Résumé) ; plus
       haut, le cadre débordait et la page défilait aussi. */
    max-height: calc(100vh - 16.5rem);
    min-height: 18rem;
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius);
    background: var(--isis-surface);
}
.isis-role-matrice {
    width: 100%;
    min-width: 56rem;
    border-collapse: separate;   /* sticky + bordures : « collapse » perd les filets des cellules figées */
    border-spacing: 0;
    font-size: 0.8125rem;
}
.isis-role-matrice th,
.isis-role-matrice td {
    padding: 0.45rem 0.6rem;
    border-bottom: 1px solid var(--isis-border);
    text-align: left;
    vertical-align: middle;
    background-clip: padding-box;
}

/* ── En-tête : figé EN BLOC (deux lignes collées chacune à top:0 se chevauchaient) ── */
.isis-role-matrice thead {
    position: sticky;
    top: 0;
    z-index: 3;
}
.isis-role-matrice thead th {
    background: var(--isis-surface-alt);
    color: var(--isis-text-muted);
    font-size: 0.6875rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    white-space: nowrap;
    vertical-align: bottom;
}
.isis-role-matrice__groupes th.is-groupe {
    text-align: center;
    color: var(--isis-text);
    letter-spacing: 0.08em;
    padding-top: 0.5rem;
    padding-bottom: 0.35rem;
    border-bottom: 2px solid var(--isis-border-strong);
}
.isis-role-matrice thead tr:last-child th { border-bottom: 2px solid var(--isis-border-strong); }
.isis-role-matrice thead th.is-ecran { vertical-align: bottom; border-bottom: 2px solid var(--isis-border-strong); }

/* ── Colonne Écran figée au défilement horizontal ── */
.isis-role-matrice th.is-ecran {
    position: sticky;
    left: 0;
    z-index: 2;
    width: 30%;
    min-width: 16rem;
    background: var(--isis-surface);
    border-right: 1px solid var(--isis-border-strong);
}
.isis-role-matrice thead th.is-ecran { z-index: 4; background: var(--isis-surface-alt); }

/* ── Blocs Cran / Capacités : filet vertical marqué au début de chaque bloc, fond teinté pour
      les capacités — les deux familles de colonnes ne se confondent plus à la lecture. ── */
.isis-role-matrice .is-choix { text-align: center; width: 6.5rem; }
.isis-role-matrice .is-bloc-cap.is-debut,
.isis-role-matrice .is-bloc-cran.is-debut { border-left: 1px solid var(--isis-border-strong); }
.isis-role-matrice tbody td.is-bloc-cap { background: color-mix(in oklch, var(--isis-accent) 4%, var(--isis-surface)); }
.isis-role-matrice thead th.is-bloc-cap { background: color-mix(in oklch, var(--isis-accent) 7%, var(--isis-surface-alt)); }
.isis-role-matrice .is-detail { width: 2.75rem; text-align: center; border-left: 1px solid var(--isis-border); }

/* ── Case d'en-tête : libellé AU-DESSUS, case en dessous, alignée sur les cases des lignes ── */
.isis-role-matrice__tous {
    display: inline-flex;
    flex-direction: column;
    align-items: center;
    gap: 0.3rem;
}
.isis-role-matrice__tous > span:not(.isis-role-matrice__partiel) { order: 1; }
.isis-role-matrice__tous > .isis-role-matrice__partiel { order: 2; margin-top: -0.2rem; }
.isis-role-matrice__tous > input,
.isis-role-matrice__tous > .rz-progressbar-circular { order: 3; }

/* ── Corps ── */
.isis-role-matrice tbody th {
    font-weight: 400;
    color: var(--isis-text);
}
.isis-role-matrice tbody th .isis-cran-row__label { display: block; font-weight: 500; }
.isis-role-matrice tbody th .isis-cran-row__code { display: block; }
.isis-role-matrice tbody tr.is-ecart > * { background: color-mix(in oklch, var(--isis-accent) 9%, var(--isis-surface)); }
/* Survol : suivre une ligne de l'écran jusqu'à la dernière capacité sans perdre le fil. */
.isis-role-matrice tbody tr:hover > * { background: color-mix(in oklch, var(--isis-accent) 12%, var(--isis-surface)); }
.isis-role-matrice input[type="radio"],
.isis-role-matrice input[type="checkbox"] {
    accent-color: var(--isis-accent);
    width: 1.125rem;
    height: 1.125rem;
    margin: 0;
    cursor: pointer;
    vertical-align: middle;
}
.isis-role-matrice input:disabled { cursor: not-allowed; }
.isis-role-matrice input:focus-visible { outline: 2px solid var(--isis-accent); outline-offset: 2px; }
.isis-role-matrice__sans { color: var(--isis-text-muted); }
.isis-role-matrice__perso {
    display: inline-block;
    margin-top: 0.2rem;
    font-size: 0.75rem;
    color: var(--isis-text-muted);
    font-style: italic;
}
.isis-role-matrice__detail-ligne > td { background: var(--isis-surface-alt); padding: 0.5rem 1rem; }
.isis-role-matrice tbody tr:last-child > * { border-bottom: none; }
.isis-role-matrice__sensible {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    margin-top: 0.2rem;
    font-size: 0.75rem;
    color: var(--isis-text-muted);
}
.isis-role-matrice__partiel {
    font-size: 0.6875rem;
    font-weight: 500;
    text-transform: none;
    letter-spacing: 0;
    color: var(--isis-text-muted);
}

/* Fiche rôle, onglet Résumé : la fiche de faits qui vivait sous le fil d'Ariane. */
.isis-role-resume {
    display: grid;
    grid-template-columns: minmax(11rem, max-content) 1fr;
    gap: 0.6rem 1.5rem;
    margin: 1rem 0 0.5rem;
    font-size: 0.875rem;
}
.isis-role-resume dt {
    color: var(--isis-text-muted);
    font-size: 0.75rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    align-self: baseline;
}
.isis-role-resume dd { margin: 0; color: var(--isis-text); align-self: baseline; }
.isis-role-resume dd strong { font-variant-numeric: tabular-nums; margin-right: 0.5rem; }
.isis-role-resume dd strong.is-warm { color: var(--isis-accent); }
.isis-role-resume__h { color: var(--isis-text-muted); font-size: 0.8125rem; }
.isis-role-resume__bloc { display: block; margin-top: 0.2rem; }
.isis-role-resume__legende {
    margin-top: 1.25rem;
    padding-top: 1rem;
    border-top: 1px solid var(--isis-border);
    font-size: 0.8125rem;
}
/* Légende repliée par défaut : le vocabulaire des crans se lit une fois, il ne doit pas
   pousser le reste du résumé vers le bas à chaque ouverture de fiche. */
.isis-role-resume__legende > summary {
    cursor: pointer;
    padding: 0.2rem 0;
}
.isis-role-resume__legende > summary:focus-visible {
    outline: 2px solid var(--isis-current-mod, var(--isis-accent));
    outline-offset: 2px;
    border-radius: 3px;
}
.isis-role-resume__legende > summary > .isis-role-resume__titre {
    display: inline;
    margin: 0;
}

.isis-role-resume__titre {
    margin: 0 0 0.5rem;
    font-size: 0.75rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--isis-text-muted);
}

/* Matrice rangée comme le menu : titres de groupe, sous-menus, écrans indentés sous leur écran. */
.isis-role-matrice tbody tr.isis-role-matrice__groupe-menu > th {
    position: sticky;
    left: 0;
    background: var(--isis-surface-alt);
    color: var(--isis-text);
    font-size: 0.6875rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    padding-top: 0.55rem;
    padding-bottom: 0.4rem;
    border-bottom: 1px solid var(--isis-border-strong);
}
.isis-role-matrice tbody tr.isis-role-matrice__sous-menu > th {
    background: var(--isis-surface);
    color: var(--isis-text-muted);
    font-size: 0.75rem;
    font-weight: 600;
    padding: 0.35rem 0.6rem 0.25rem 1.25rem;
}
.isis-role-matrice tbody tr.isis-role-matrice__groupe-menu:hover > *,
.isis-role-matrice tbody tr.isis-role-matrice__sous-menu:hover > * { background: inherit; }
.isis-role-matrice tbody th.is-ecran.is-niveau-1 { padding-left: 1.5rem; }
.isis-role-matrice tbody th.is-ecran.is-niveau-2 { padding-left: 2.5rem; }
.isis-role-matrice tbody th.is-ecran.is-niveau-3 { padding-left: 3.5rem; }
/* Le filet coudé dit « dépend de l'écran au-dessus » sans reposer sur la seule indentation. */
.isis-role-matrice tbody th.is-ecran.is-niveau-1 .isis-cran-row__label::before,
.isis-role-matrice tbody th.is-ecran.is-niveau-2 .isis-cran-row__label::before,
.isis-role-matrice tbody th.is-ecran.is-niveau-3 .isis-cran-row__label::before {
    content: "↳ " / "";
    color: var(--isis-text-muted);
}

/* ── Accueil — monde carte ─────────────────────────────────────────── */
:root {
    --isis-dash-gap: var(--isis-space-md);
    --isis-dash-card-pad: var(--isis-space-md);
    /* surface-soft et non surface-2 : sur surface-2, le halo de focus et le délai en retard
       tombent sous 3:1 en clair. */
    --isis-dash-band-bg: var(--isis-surface-soft);
    --isis-dash-late: var(--isis-danger);
}

.isis-dash-corps {
    position: relative;
    display: flex; flex-direction: column;
    gap: var(--isis-dash-gap);
}
.isis-dash-progress {
    position: absolute; top: 0; left: 0; right: 0;
    height: 2px;
}

/* En-tête de section : titre, précision, lien d'historique. */
.isis-dash-sec-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--isis-space-sm); margin-bottom: var(--isis-space-sm); }
.isis-dash-sec-titre { margin: 0; font-size: var(--isis-fs-md); font-weight: 600; color: var(--isis-text); }
.isis-dash-sec-sous { font-size: var(--isis-fs-sm); color: var(--isis-text-muted); }
.isis-dash-sec-lien {
    margin-left: auto; font-size: var(--isis-fs-sm); color: var(--isis-accent-strong);
    text-decoration: none;
}
.isis-dash-sec-lien:hover { text-decoration: underline; text-underline-offset: 2px; }
.isis-dash-sec-lien:focus-visible { outline: 2px solid var(--isis-current-mod); outline-offset: 2px; }

/* Pastille d'urgence : le texte porte le sens, la teinte ne fait que le doubler. */
.isis-dash-pill {
    display: inline-flex; align-items: center;
    padding: 0 var(--isis-space-sm);
    border-radius: var(--isis-radius-pill);
    font-size: var(--isis-fs-xs); font-weight: 600; line-height: 1.5;
    background: var(--isis-surface-2); color: var(--isis-text);
}
.isis-dash-pill.is-late { background: var(--isis-danger-soft); color: var(--isis-danger-text); }
.isis-dash-pill.is-due { background: var(--isis-warning-soft); color: var(--isis-warning-text); }
.isis-dash-pill.is-waiting { background: var(--isis-info-soft); color: var(--isis-info-text); }
.isis-dash-pastille {
    display: inline-block; width: .5rem; height: .5rem; border-radius: 50%;
    margin-right: var(--isis-space-xs);
    background: var(--isis-module-hue, var(--isis-text-muted));
}

/* En premier */
.isis-dash-prio {
    display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
    gap: var(--isis-space-md);
    padding: var(--isis-space-md);
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius);
    box-shadow: var(--isis-elevation-1);
}
.isis-dash-prio.is-late { background: var(--isis-danger-soft); border-color: var(--isis-danger); }
.isis-dash-prio.is-due { background: var(--isis-warning-soft); border-color: var(--isis-warning-text); }
.isis-dash-prio.is-waiting { background: var(--isis-info-soft); border-color: var(--isis-info); }
.isis-dash-prio__corps { display: flex; flex-wrap: wrap; align-items: center; gap: var(--isis-space-sm); min-width: 0; }
.isis-dash-prio__texte { margin: 0; font-size: var(--isis-fs-md); color: var(--isis-text); }
.isis-dash-prio__action {
    display: inline-flex; align-items: center;
    padding: var(--isis-space-xs) var(--isis-space-md);
    border: 1px solid var(--isis-border-strong); border-radius: var(--isis-radius);
    background: var(--isis-surface); color: var(--isis-text);
    font-size: var(--isis-fs-base); font-weight: 500; text-decoration: none;
}
.isis-dash-prio__action:hover { border-color: var(--isis-text-muted); }
.isis-dash-prio__action:focus-visible { outline: 2px solid var(--isis-current-mod); outline-offset: 2px; }

/* Raccourcis et reprise */
.isis-dash-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--isis-space-sm); }
.isis-dash-actions__sep { width: 1px; align-self: stretch; background: var(--isis-border); }
.isis-dash-actions__fin { margin-left: auto; display: inline-flex; align-items: center; }
.isis-dash-action {
    display: inline-flex; align-items: center; gap: var(--isis-space-sm);
    padding: var(--isis-space-sm) var(--isis-space-md);
    background: var(--isis-surface); color: var(--isis-text);
    border: 1px solid var(--isis-border); border-radius: var(--isis-radius);
    font: inherit; font-size: var(--isis-fs-base); font-weight: 500;
    text-decoration: none; cursor: pointer;
}
.isis-dash-action:hover { border-color: var(--isis-text-muted); }
.isis-dash-action:focus-visible { outline: 2px solid var(--isis-current-mod); outline-offset: 2px; }
.isis-dash-action__touches {
    font-family: var(--isis-font-mono); font-size: var(--isis-fs-xs);
    padding: 0 var(--isis-space-xs);
    background: var(--isis-surface-2); color: var(--isis-text-muted);
    border: 1px solid var(--isis-border-soft); border-radius: var(--isis-radius-sm);
}
.isis-dash-reprise { background: var(--isis-accent-soft); color: var(--isis-accent-strong); border-color: transparent; }
.isis-dash-reprise .rzi { font-size: var(--isis-fs-lg); }

/* Liste de travail */
.isis-dash-band {
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius);
    box-shadow: var(--isis-elevation-1);
}
.isis-dash-band__groupe + .isis-dash-band__groupe { border-top: 1px solid var(--isis-border-soft); }
.isis-dash-band__strate {
    display: flex; align-items: center; gap: var(--isis-space-sm);
    padding: var(--isis-space-sm) var(--isis-space-md);
    background: var(--isis-dash-band-bg);
}
.isis-dash-band__strate-n { font-size: var(--isis-fs-sm); color: var(--isis-text-muted); }
.isis-dash-band__liste { list-style: none; margin: 0; padding: 0; }
.isis-dash-band__item {
    display: flex; align-items: center; justify-content: space-between; gap: var(--isis-space-md);
    padding: var(--isis-space-sm) var(--isis-space-md);
    border-top: 1px solid var(--isis-border-soft);
}
.isis-dash-band__principal { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.isis-dash-band__lien {
    color: var(--isis-text); font-size: var(--isis-fs-base); font-weight: 500; text-decoration: none;
    overflow-wrap: anywhere;
}
.isis-dash-band__lien:hover { text-decoration: underline; text-underline-offset: 2px; }
.isis-dash-band__item a:focus-visible { outline: 2px solid var(--isis-current-mod); outline-offset: 2px; }
.isis-dash-band__lien:focus-visible { outline: 2px solid var(--isis-current-mod); outline-offset: 2px; }
.isis-dash-band__meta {
    display: flex; flex-wrap: wrap; align-items: center; gap: var(--isis-space-xs);
    font-size: var(--isis-fs-sm); color: var(--isis-text-muted);
}
.isis-dash-band__module { display: inline-flex; align-items: center; }
.isis-dash-band__marge.is-sous-seuil { color: var(--isis-danger-text); font-weight: 600; }
.isis-dash-band__delai {
    flex: 0 0 auto; font-size: var(--isis-fs-sm); font-variant-numeric: tabular-nums;
    color: var(--isis-text-muted);
}
.isis-dash-band__item.is-late .isis-dash-band__delai { color: var(--isis-dash-late); font-weight: 600; }
.isis-dash-band__pied {
    display: flex; flex-wrap: wrap; align-items: center; gap: var(--isis-space-md);
    padding: var(--isis-space-sm) var(--isis-space-md);
    border-top: 1px solid var(--isis-border-soft);
}
.isis-dash-band__plus {
    background: none; border: 1px solid var(--isis-border-strong); border-radius: var(--isis-radius);
    padding: var(--isis-space-xs) var(--isis-space-md);
    font: inherit; font-size: var(--isis-fs-sm); color: var(--isis-text); cursor: pointer;
}
.isis-dash-band__plus:hover { border-color: var(--isis-text-muted); }
.isis-dash-band__plus:focus-visible { outline: 2px solid var(--isis-current-mod); outline-offset: 2px; }
.isis-dash-band__note { margin: 0; font-size: var(--isis-fs-sm); color: var(--isis-text-muted); }

/* Cartes par module */
.isis-dash-grid {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--isis-dash-gap);
}

/* Palier intermédiaire AVANT la règle 980 : à position égale, la dernière règle l'emporte. */
@media (max-width: 1280px) {
    .isis-dash-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 980px) {
    .isis-dash-grid { grid-template-columns: minmax(0, 1fr); }
}

.isis-dash-card {
    background: var(--isis-surface);
    border: 1px solid var(--isis-border);
    border-radius: var(--isis-radius);
    box-shadow: var(--isis-elevation-1);
    padding: var(--isis-dash-card-pad);
}

.isis-dash-card__head { display: flex; align-items: center; gap: var(--isis-space-sm); }
.isis-dash-card__tuile {
    display: inline-flex; align-items: center; justify-content: center;
    width: 1.75rem; height: 1.75rem; flex: 0 0 auto;
    border-radius: var(--isis-radius);
    background: var(--isis-module-hue, var(--isis-text-muted));
    color: var(--isis-surface);
}
.isis-dash-card__tuile.is-ok { background: var(--isis-success-soft); color: var(--isis-success-text); }
.isis-dash-card__titre { font-size: var(--isis-fs-md); font-weight: 600; margin: 0; flex: 1 1 auto; }
.isis-dash-card__total { font-size: var(--isis-fs-sm); font-weight: 600; font-variant-numeric: tabular-nums; color: var(--isis-text-muted); }
.isis-dash-card__files { list-style: none; margin: var(--isis-space-sm) 0 0; padding: 0; }
.isis-dash-card__noms { margin: var(--isis-space-sm) 0 0; font-size: var(--isis-fs-base); color: var(--isis-text); }
.isis-dash-card__pied {
    margin: var(--isis-space-sm) 0 0; padding-top: var(--isis-space-sm);
    border-top: 1px solid var(--isis-border-soft);
    font-size: var(--isis-fs-sm); color: var(--isis-text-muted);
}
.isis-dash-card.is-info { background: var(--isis-surface-soft); }

.isis-dash-line {
    display: flex; align-items: center; justify-content: space-between; gap: var(--isis-space-sm);
    padding: var(--isis-space-xs) 0;
    color: var(--isis-text); text-decoration: none;
    border-radius: var(--isis-radius-sm);
}
a.isis-dash-line:hover { background: var(--isis-surface-soft); }
.isis-dash-line:focus-visible { outline: 2px solid var(--isis-current-mod); outline-offset: 2px; }
.isis-dash-line__texte { display: flex; flex-direction: column; min-width: 0; }
.isis-dash-line__libelle { display: inline-flex; flex-wrap: wrap; align-items: center; gap: var(--isis-space-xs); font-size: var(--isis-fs-base); }
.isis-dash-line__sous { font-size: var(--isis-fs-sm); color: var(--isis-text-muted); }
.isis-dash-line__sous.is-retard { color: var(--isis-danger-text); }
.isis-dash-line__sous.is-alerte { color: var(--isis-warning-text); }
.isis-dash-line__sous.is-panne { color: var(--isis-text-muted); font-style: italic; }
.isis-dash-line__note { font-size: var(--isis-fs-xs); color: var(--isis-text-muted); }
.isis-dash-line__compte { font-weight: 600; font-variant-numeric: tabular-nums; }
.isis-dash-line__compte.is-ko { color: var(--isis-text-muted); }

.isis-dash-ajour-liste { list-style: none; margin: var(--isis-space-sm) 0 0; padding: 0; display: flex; flex-direction: column; gap: var(--isis-space-xs); font-size: var(--isis-fs-base); }

/* Note d'information (aucun accès) */
.isis-dash-note {
    display: flex; flex-wrap: wrap; align-items: flex-start; gap: var(--isis-space-sm);
    padding: var(--isis-space-md);
    background: var(--isis-info-soft); color: var(--isis-info-text);
    border-radius: var(--isis-radius);
}
.isis-dash-note__icone { flex: 0 0 auto; }
.isis-dash-note__titre { margin: 0; font-size: var(--isis-fs-base); font-weight: 600; }
.isis-dash-note__detail { margin: var(--isis-space-xs) 0 0; font-size: var(--isis-fs-base); }

/* Activité récente */
.isis-dash-activite__panneau {
    background: var(--isis-surface);
    border: 1px solid var(--isis-border); border-radius: var(--isis-radius);
    box-shadow: var(--isis-elevation-1);
    padding: var(--isis-space-sm) var(--isis-space-md);
}
.isis-dash-activite__vide { margin: 0; font-size: var(--isis-fs-base); color: var(--isis-text-muted); }
.isis-dash-activite__liste { list-style: none; margin: 0; padding: 0; }
.isis-dash-activite__item {
    display: flex; justify-content: space-between; gap: var(--isis-space-md);
    padding: var(--isis-space-xs) 0;
    border-top: 1px solid var(--isis-border-soft);
}
.isis-dash-activite__item:first-child { border-top: 0; }
.isis-dash-activite__titre-ligne { color: var(--isis-text); font-size: var(--isis-fs-base); text-decoration: none; }
a.isis-dash-activite__titre-ligne:hover { text-decoration: underline; text-underline-offset: 2px; }
a.isis-dash-activite__titre-ligne:focus-visible { outline: 2px solid var(--isis-current-mod); outline-offset: 2px; }
.isis-dash-activite__quand { flex: 0 0 auto; font-size: var(--isis-fs-sm); color: var(--isis-text-muted); font-variant-numeric: tabular-nums; }

/* En-tête de page */
.isis-dash-head {
    display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between;
    gap: var(--isis-space-md);
    padding-top: var(--isis-space-sm);
}
.isis-dash-head__accueil { display: flex; flex-direction: column; gap: var(--isis-space-xs); min-width: 0; }
.isis-dash-head__date { margin: 0; font-size: var(--isis-fs-base); font-weight: 500; color: var(--isis-text-muted); }
.isis-dash-head__salut {
    margin: 0;
    font-size: var(--isis-fs-2xl); font-weight: 600; line-height: 1.15; letter-spacing: -0.02em;
    color: var(--isis-text);
}
.isis-dash-head__sous-titre { margin: var(--isis-space-xs) 0 0; color: var(--isis-text); font-size: var(--isis-fs-md); }
.isis-dash-head__heure { color: var(--isis-text-muted); font-size: var(--isis-fs-sm); margin-left: var(--isis-space-xs); }
/* Bascule segmentée. Vue active : surface claire et contour de la couleur courante, ni aplat de
   couleur de module ni texte blanc — l'accueil n'appartient à aucun module. */
.isis-dash-head__vues {
    display: inline-flex; flex-wrap: wrap; gap: 2px;
    padding: 3px;
    background: var(--isis-surface-2);
    border-radius: var(--isis-radius-lg);
}
.isis-dash-head__vue {
    background: none; border: 1px solid transparent;
    font: inherit; font-size: var(--isis-fs-sm);
    padding: var(--isis-space-xs) var(--isis-space-md);
    border-radius: var(--isis-radius); cursor: pointer;
    color: var(--isis-text-muted);
}
.isis-dash-head__vue.is-active {
    background: var(--isis-surface); border-color: var(--isis-current-mod);
    color: var(--isis-text); font-weight: 600;
    box-shadow: var(--isis-elevation-1);
}
.isis-dash-head__vue[aria-disabled="true"] { opacity: .5; cursor: not-allowed; }
.isis-dash-head__vue:focus-visible { outline: 2px solid var(--isis-current-mod); outline-offset: 2px; }
@media (max-width: 980px) {
    .isis-dash-head__vues { display: flex; width: 100%; }
    .isis-dash-head__vue { flex: 1 1 0; }
    .isis-dash-band__item { flex-direction: column; align-items: flex-start; }
}
@media (pointer: coarse) {
    .isis-dash-head__vue,
    .isis-dash-line,
    .isis-dash-action,
    .isis-dash-prio__action,
    .isis-dash-band__lien,
    .isis-dash-band__plus { min-height: 44px; }
}

/* Couleur de carte par domaine : même convention que le rail — un token de module, jamais
   une valeur. */
.isis-dash-card.mod-monespace { --isis-module-hue: var(--isis-mod-monespace); }
.isis-dash-card.mod-gescompta { --isis-module-hue: var(--isis-mod-gescompta); }
.isis-dash-card.mod-gesst { --isis-module-hue: var(--isis-mod-gesst); }
.isis-dash-card.mod-gescom { --isis-module-hue: var(--isis-mod-gescom); }
.isis-dash-card.mod-gesproj { --isis-module-hue: var(--isis-mod-gesproj); }
.isis-dash-card.mod-ged { --isis-module-hue: var(--isis-mod-ged); }
.isis-dash-card.mod-gesmaff { --isis-module-hue: var(--isis-mod-gesmaff); }
.isis-dash-card.mod-sirh { --isis-module-hue: var(--isis-mod-sirh); }

/* Couleur de module des lignes de la liste et de l'à-jour : la pastille seule la porte. */
.isis-dash-band__item.mod-gescom, .isis-dash-ajour-liste li.mod-gescom { --isis-module-hue: var(--isis-mod-gescom); }
.isis-dash-band__item.mod-gescompta, .isis-dash-ajour-liste li.mod-gescompta { --isis-module-hue: var(--isis-mod-gescompta); }
.isis-dash-band__item.mod-sirh, .isis-dash-ajour-liste li.mod-sirh { --isis-module-hue: var(--isis-mod-sirh); }
.isis-dash-band__item.mod-admin, .isis-dash-ajour-liste li.mod-admin { --isis-module-hue: var(--isis-mod-admin); }
.isis-dash-band__item.mod-gesproj, .isis-dash-ajour-liste li.mod-gesproj { --isis-module-hue: var(--isis-mod-gesproj); }
.isis-dash-band__item.mod-gesmaff, .isis-dash-ajour-liste li.mod-gesmaff { --isis-module-hue: var(--isis-mod-gesmaff); }
.isis-dash-band__item.mod-gesst, .isis-dash-ajour-liste li.mod-gesst { --isis-module-hue: var(--isis-mod-gesst); }
.isis-dash-band__item.mod-gesmat, .isis-dash-ajour-liste li.mod-gesmat { --isis-module-hue: var(--isis-mod-gesmat); }
.isis-dash-band__item.mod-gespark, .isis-dash-ajour-liste li.mod-gespark { --isis-module-hue: var(--isis-mod-gespark); }
.isis-dash-band__item.mod-gesinfo, .isis-dash-ajour-liste li.mod-gesinfo { --isis-module-hue: var(--isis-mod-gesinfo); }
.isis-dash-band__item.mod-gesmob, .isis-dash-ajour-liste li.mod-gesmob { --isis-module-hue: var(--isis-mod-gesmob); }
.isis-dash-band__item.mod-gesfac, .isis-dash-ajour-liste li.mod-gesfac { --isis-module-hue: var(--isis-mod-gesfac); }
.isis-dash-band__item.mod-gespla, .isis-dash-ajour-liste li.mod-gespla { --isis-module-hue: var(--isis-mod-gespla); }
.isis-dash-band__item.mod-gesqhse, .isis-dash-ajour-liste li.mod-gesqhse { --isis-module-hue: var(--isis-mod-gesqhse); }
.isis-dash-band__item.mod-ged, .isis-dash-ajour-liste li.mod-ged { --isis-module-hue: var(--isis-mod-ged); }
.isis-dash-band__item.mod-monespace, .isis-dash-ajour-liste li.mod-monespace { --isis-module-hue: var(--isis-mod-monespace); }
.isis-dash-band__item.mod-recette, .isis-dash-ajour-liste li.mod-recette { --isis-module-hue: var(--isis-mod-recette); }

/* ── Marque produit IRIS — composant IrisMarque ────────────────────────────────
   Trois barres de planning qui composent un I. La tuile est le <span>, les barres des
   <rect> unis, embossés par un filtre CSS : aucun <defs>, aucun id, donc aucune collision entre deux
   instances d'une même page.
   La marque ne suit PAS --isis-accent : elle est immuable, elle ne se teinte pas de
   l'accent d'un tenant (BrandSync). */
.isis-marque {
    --isis-marque-taille: 36px;

    position: relative;
    display: inline-block;
    flex: none;
    width: var(--isis-marque-taille);
    height: var(--isis-marque-taille);
    border-radius: 21.875%;                                                    /* 14/64 */
    background: var(--isis-brand-ink);
    /* Unité du relief : 1px à 56 px de côté, plafonnée pour la grande marque de l'ouverture.
       Des ombres en pixels fixes écraseraient une petite tuile et brouilleraient ses barres. */
    --isis-marque-u: min(var(--isis-marque-taille) / 56, 1.6px);
    /* Flou et reflet des barres nuls jusqu'à 36 px : en dessous, ils ne se lisent que comme du
       flou. Ils montent ensuite jusqu'à leur pleine valeur, atteinte vers 56 px. */
    --isis-marque-flou: clamp(0px, (var(--isis-marque-taille) - 36px) * .075, 1.5px);
    --isis-marque-reflet: clamp(0px, (var(--isis-marque-taille) - 36px) * .05, 1px);
    /* Inset : une `border` déplacerait la boîte de contenu et rétrécirait le glyphe. */
    box-shadow:
        inset 0 0 0 1px var(--isis-brand-contour),
        0 calc(var(--isis-marque-u) * 2) calc(var(--isis-marque-u) * 3) var(--isis-brand-ombre-proche),
        0 calc(var(--isis-marque-u) * 8) calc(var(--isis-marque-u) * 18) calc(var(--isis-marque-u) * -4) var(--isis-brand-ombre-portee),
        inset 0 max(1px, var(--isis-marque-u) * 2) 0 var(--isis-brand-biseau-haut),
        inset 0 min(-1px, var(--isis-marque-u) * -2) 0 var(--isis-brand-biseau-bas);
}

.isis-marque__glyphe {
    position: absolute;
    inset: 0;
    display: block;
    width: 100%;
    height: 100%;
    /* Un filtre CSS et non un <filter> SVG : ce dernier exigerait un id, dupliqué dès la
       deuxième instance. */
    filter:
        drop-shadow(0 max(1px, var(--isis-marque-u) * 2.5) var(--isis-marque-flou) var(--isis-brand-ombre-barre))
        drop-shadow(0 calc(var(--isis-marque-reflet) * -1) 0 var(--isis-brand-lumiere-barre));
}

.isis-marque__barre          { fill: var(--isis-brand-barre); }
.isis-marque__barre--accent  { fill: var(--isis-brand-accent); }

/* Déclinaisons figées : une surface qui impose son fond (carte de connexion, en-tête
   d'e-mail) ne peut pas laisser la marque suivre le thème. */
.isis-marque--clair {
    --isis-brand-ink:     #e6edf3;
    --isis-brand-contour: #d3dce6;
    --isis-brand-barre:   #335171;
    --isis-brand-accent:  #b23d07;
    --isis-brand-ombre-proche:   rgba(16, 24, 40, .18);
    --isis-brand-ombre-portee:   rgba(16, 24, 40, .35);
    --isis-brand-biseau-haut:    rgba(255, 255, 255, .9);
    --isis-brand-biseau-bas:     rgba(16, 24, 40, .12);
    --isis-brand-ombre-barre:    rgba(16, 24, 40, .55);
    --isis-brand-lumiere-barre:  #fff;
}

.isis-marque--nocturne {
    --isis-brand-ink:     #1e2732;
    --isis-brand-contour: #2c3845;
    --isis-brand-barre:   #b8cbe0;
    --isis-brand-accent:  #f0803c;
    --isis-brand-ombre-proche:   rgba(0, 0, 0, .6);
    --isis-brand-ombre-portee:   rgba(0, 0, 0, .8);
    --isis-brand-biseau-haut:    rgba(255, 255, 255, .14);
    --isis-brand-biseau-bas:     rgba(0, 0, 0, .35);
    --isis-brand-ombre-barre:    rgba(0, 0, 0, .95);
    --isis-brand-lumiere-barre:  rgba(255, 255, 255, .3);
}
/* ════════════════════════════════════════════════════════════════════════════════════
   CHAMPS FORM-LINEAR : PADDINGS À ZÉRO, HAUTEUR UNIQUE 35 px (propriétaire, 2026-09-23)
   ════════════════════════════════════════════════════════════════════════════════════
   Les contrôles Radzen n'ont pas de hauteur propre : elle se CALCULE (bordures + padding
   vertical + ligne de texte). Passer les paddings à 0 les a donc fait maigrir, chacun de
   sa propre quantité — 26 px pour textbox/datepicker, 28 pour dropdown, 23,6 pour numeric.
   La hauteur est désormais POSÉE, pas subie : 35 px pour tout champ d'une ligne.
   Mesuré à l'injection, dialogue « Nouvelle offre de prix », 15 contrôles sur 15 à 35,0 px,
   aucun texte rogné (`scrollHeight == clientHeight` partout).
   Les zones de texte multilignes (`rz-textarea`) suivent le même PLANCHER de 35 px, mais
   gardent une hauteur libre au-delà : elles se dimensionnent au contenu (partie 3c).
   35 px passe largement le plancher 24×24 px CSS du critère WCAG 2.5.8 (AA, taille de
   cible), que le numeric à 23,6 px violait avant la pose de la hauteur.
   Trois temps, tous NÉCESSAIRES :
     1. l'input interne des contrôles composés, qui garde sinon son padding vertical propre
        et, au focus, celui de la règle F9 (`padding-bottom: calc(0.35rem - 1px)`) ;
     2. l'enveloppe, qui porte la bordure et le fond ;
     3. la hauteur elle-même — enveloppe à 35, contenu et déclencheur à 33 (= 35 moins les
        deux bordures), sans quoi le texte se recentre mal ou le chevron déborde ; pour les
        zones multilignes, un plancher au lieu d'une hauteur (partie 3c).
   La réserve de place des flèches du numeric (`.rz-numeric > input.rz-numeric-input`,
   padding-right 1.6rem) est délibérément laissée : elle gagne en spécificité, sans quoi
   le texte passerait sous les flèches.
   Bloc autonome : le SUPPRIMER restaure intégralement l'état antérieur, sans autre geste. */

/* 1 — input interne des contrôles composés (datepicker, numeric, spinner, dropdown) */
.isis-form-linear .rz-numeric > input,
.isis-form-linear .rz-dropdown input,
.isis-form-linear .rz-datepicker input,
.isis-form-linear .rz-spinner > input {
    padding-block: 0 !important;
}
.isis-form-linear :is(.rz-numeric, .rz-dropdown, .rz-datepicker, .rz-spinner) input:focus {
    background: transparent !important;
    padding-block: 0 !important;
    border-bottom-width: 0 !important;
}

/* 2 — enveloppes et champs simples */
.isis-form-linear .rz-textbox,
.isis-form-linear .rz-textarea,
.isis-form-linear .rz-dropdown,
.isis-form-linear .rz-numeric,
.isis-form-linear .rz-datepicker,
.isis-form-linear .rz-multiselect,
.isis-form-linear input,
.isis-form-linear textarea {
    padding: 0 !important;
}
.isis-form-linear .rz-dropdown .rz-dropdown-label,
.isis-form-linear .rz-multiselect .rz-multiselect-label {
    padding: 0 !important;
}
/* 2b — retrait gauche (2026-10-07) : depuis que le champ est un cadre blanc, un texte collé
   au bord se lit comme un défaut. Seul le retrait HORIZONTAL revient ; le vertical reste à 0
   (la hauteur est posée en 3). Le padding-right du numeric (réserve des flèches) est intact. */
.isis-form-linear :is(input.rz-textbox, .rz-textarea, textarea),
.isis-form-linear :is(.rz-numeric, .rz-datepicker, .rz-spinner) > input,
.isis-form-linear .rz-dropdown .rz-dropdown-label,
.isis-form-linear .rz-multiselect .rz-multiselect-label {
    padding-left: .5rem !important;
}
.isis-form-linear :is(input.rz-textbox, .rz-textarea, textarea) {
    padding-right: .5rem !important;
}

/* 3 — hauteur unique : 35 px pour le champ et son bouton d'appoint de ligne */
.isis-form-linear input.rz-textbox,
.isis-form-linear .rz-numeric,
.isis-form-linear .rz-datepicker,
.isis-form-linear .rz-dropdown,
.isis-form-linear .rz-multiselect,
.isis-form-linear .rz-spinner,
.isis-form-linear .isis-form-linear__inline-add-btn {
    box-sizing: border-box !important;
    height: 35px !important;
    min-height: 35px !important;
}

/* 3b — contenu et déclencheurs : 33 px = 35 moins les deux bordures */
.isis-form-linear .rz-numeric > input,
.isis-form-linear .rz-datepicker > input,
.isis-form-linear .rz-spinner > input,
.isis-form-linear .rz-dropdown .rz-dropdown-label,
.isis-form-linear .rz-multiselect .rz-multiselect-label {
    height: 33px !important;
    line-height: 33px !important;
}
.isis-form-linear .rz-datepicker .rz-datepicker-field-button,
.isis-form-linear .rz-dropdown .rz-dropdown-trigger,
.isis-form-linear .rz-multiselect .rz-multiselect-trigger {
    height: 33px !important;
}

/* 3c — zones multilignes : plancher à 35 px, hauteur libre au-delà
   Une zone multiligne ne peut pas recevoir la hauteur FIXE des champs d'une ligne sans
   perdre sa raison d'être. Elle reçoit donc le même chiffre en PLANCHER.
   Seul, `min-height` ne changerait rien : la hauteur d'un `<textarea>` est dictée par son
   attribut `rows` (2 ou 3 ici, soit 43,8 et 64,6 px), toujours au-dessus du plancher.
   `field-sizing: content` (Chrome 123+, Safari 17.4+, Edge 123+, Firefox 144+ — idiome
   déjà en place pour la Désignation des lignes de devis) fait dimensionner la zone sur le
   CONTENU réel et non sur `rows` : vide, elle descend sous le plancher, que `min-height`
   relève à 35 px ; à la saisie, elle grandit d'elle-même.
   Navigateur sans `field-sizing` : retour au comportement `rows`, donc à l'état antérieur
   — jamais plus bas que 35 px. */
.isis-form-linear .rz-textarea,
.isis-form-linear textarea {
    box-sizing: border-box !important;
    field-sizing: content;
    min-height: 35px !important;
}

/* ============================================================================
   .isis-op-equipe — listes de rattachement d'une Opportunité : équipe nommée
   (OpportuniteEquipePanel) et contreparties (OpportuniteContrepartiesPanel).
   Liste sobre de lignes, avec le formulaire d'ajout en pied. Nom
   distinct de .isis-equipe-member, qui est une cellule de la grille Équipe
   gescom et ne porte pas la même géométrie.
   ============================================================================ */
.isis-op-equipe {
    list-style: none;
    margin: 0.5rem 0 0;
    padding: 0;
    display: flex;
    flex-direction: column;
}

.isis-op-equipe__item {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.5rem;
    min-height: 35px;
    padding: 0.25rem 0;
    border-bottom: 1px solid var(--isis-border-soft, var(--isis-border));
}

.isis-op-equipe__item:last-child { border-bottom: none; }

/* min-width: 0 est load-bearing — sans lui un enfant de flex ne descend pas sous la
   largeur de son contenu, l'ellipse ne se déclenche jamais et un nom long pousse
   l'action de retrait hors du champ visible. */
.isis-op-equipe__name {
    flex: 1 1 auto;
    min-width: 0;
    font-weight: 500;
    color: var(--isis-text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Pousse l'action de retrait en bout de ligne sans la coller au libellé. */
.isis-op-equipe__meta {
    margin-left: auto;
    max-width: 40%;
    flex-shrink: 1;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: 0.75rem;
    color: var(--isis-text-soft);
}

/* AUCUNE action de ligne ne se comprime : le retrait ferme un accès, et la modification est
   la seule porte vers le rôle. Porter flex-shrink sur :last-child seul laissait « Modifier »
   se réduire le premier sur une ligne à deux boutons — invisible tant que __name absorbe le
   déficit, réel dès qu'une quote-part le ramène à zéro. */
.isis-op-equipe__item > button { flex-shrink: 0; }
.isis-op-equipe__item > button:last-child { margin-left: auto; }
/* :last-of-type reprend le rôle de :last-child dès qu'un <p> d'attendu clôt la ligne — sans lui
   le dernier bouton perd son margin-left:auto et se recolle au libellé sur les lignes sans
   « Associé par ». Même spécificité que la règle ci-dessus : comportement inchangé sinon. */
.isis-op-equipe__item > button:last-of-type { margin-left: auto; }
.isis-op-equipe__meta ~ button { margin-left: 0; }

/* Secondes lignes du <li> : les métadonnées, puis l'attendu. flex-basis:100% les renvoie
   seules sur leur ligne, et elles sont les DERNIERS enfants — l'ordre de lecture ne s'écarte
   donc jamais de l'ordre visuel. Valeurs en rem brut comme tout le bloc : --isis-space-*
   n'offre ni 0.125 ni 0.35rem, et n'en tokéniser que la moitié le fendrait en deux échelles. */
.isis-op-equipe__metas {
    flex-basis: 100%;
    display: flex;
    min-width: 0;
    gap: 0.35rem;
}

/* __meta reste tel quel pour le panneau Contreparties, qui le pose AVANT ses boutons et
   dépend de son margin-left:auto. Ici il est déjà sur sa propre ligne : les deux réglages
   de poussée n'y ont plus d'objet. */
.isis-op-equipe__metas > .isis-op-equipe__meta { margin-left: 0; max-width: none; }
.isis-op-equipe__metas > .isis-op-equipe__meta + .isis-op-equipe__meta::before { content: "· "; }

.isis-op-equipe__attendu {
    flex-basis: 100%;
    margin: 0.125rem 0 0.25rem;
    font-size: 0.75rem;
    color: var(--isis-text-soft);
}

.isis-op-equipe__add {
    display: flex;
    align-items: flex-end;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin-top: 0.75rem;
}

/* Champ propre au bloc plutôt qu'emprunt à .isis-champs-panel__field : ce panneau ne doit
   pas hériter d'une évolution de densité décidée pour les champs personnalisés. */
.isis-op-equipe__field {
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
    flex: 1 1 260px;
    max-width: 360px;
}

.isis-op-equipe__label {
    font-size: 0.8rem;
    font-weight: 500;
    color: var(--isis-text-soft);
}

/* ==========================================================================
   Activités opérationnelles d'une ligne de devis — DevisLigneActivites.razor
   Un seul rendu pour les trois surfaces (fiche, tableur d'édition, Coût de
   revient). Maquette validée le 2026-09-23 : aucun aplat de fond, le bloc
   tient par son rail gauche et la règle sous son en-tête ; hiérarchie par la
   seule indentation. Échelle de retrait, mesurée et opposable :
     0 px  bord du bloc (rail 1 px : DESIGN.md §1 proscrit tout liseré
           vertical >= 2 px depuis le 2026-07-18 — arbitrage du 2026-09-24)
    13 px  icône de l'activité
    31 px  libellé de l'ACTIVITÉ         (13 + 12 d'icône + 6 de gouttière)
    38 px  filet vertical de rattachement (13 + 25 dans la boîte du libellé)
    55 px  libellé de la RESSOURCE       (31 + 24)
   Le gris ne dit plus qu'une chose, « secondaire » : seuls la note et les
   zéros sont atténués, jamais les libellés ni le fond.
   ========================================================================== */
.isis-ligne-acti {
    /* --isis-current-mod n'est posé que par .isis-shell / .isis-shell__content, et
       <RadzenComponents /> est monté EN DEHORS du shell : dans un dialogue (l'élaboration
       d'une offre, par exemple) le token n'existe pas, le color-mix devient invalide au
       calcul et `border-left` retombe sur `none` — le rail, le filet et la couleur de
       titre disparaissaient sans le moindre message. Le repli les garde ; les surfaces
       qui connaissent leur module hors shell redéfinissent --acti-mod (cf. .isis-crv). */
    --acti-mod: var(--isis-current-mod, var(--isis-accent));
    --acti-rail: color-mix(in srgb, var(--acti-mod) 55%, var(--isis-border));
    --acti-sep: color-mix(in srgb, var(--isis-border) 60%, transparent);
    --acti-guide: color-mix(in srgb, var(--acti-mod) 28%, transparent);
    border-left: 1px solid var(--acti-rail);
    padding-bottom: 2px;
}

.isis-ligne-acti__head,
.isis-ligne-acti__row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 72px 104px 104px;
    gap: 0 12px;
    padding: 0 12px 0 13px;
}

.isis-ligne-acti.has-actions .isis-ligne-acti__head,
.isis-ligne-acti.has-actions .isis-ligne-acti__row {
    grid-template-columns: minmax(0, 1fr) 72px 104px 104px 40px;
}

.isis-ligne-acti__head {
    align-items: baseline;
    padding-top: 5px;
    padding-bottom: 4px;
    border-bottom: 1px solid var(--acti-sep);
}

.isis-ligne-acti__title {
    font-size: 0.65rem;
    font-weight: 600;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: color-mix(in srgb, var(--acti-mod) 72%, var(--isis-text));
}

.isis-ligne-acti__c {
    font-size: 0.65rem;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: var(--isis-text-muted);
    text-align: right;
}

.isis-ligne-acti__row {
    align-items: center;
    min-height: 26px;
    font-size: 0.78rem;
}

.isis-ligne-acti__row + .isis-ligne-acti__row {
    border-top: 1px solid var(--acti-sep);
}

/* Deux ressources consécutives ne se séparent pas : le filet vertical suffit
   à les rattacher, une règle par rangée redécouperait le bloc. */
.isis-ligne-acti__row--res + .isis-ligne-acti__row--res {
    border-top: none;
}

.isis-ligne-acti__lbl {
    display: flex;
    align-items: center;
    gap: 6px;
    min-width: 0;
}

.isis-ligne-acti__ico {
    color: var(--acti-rail);
    flex: 0 0 auto;
}

/* flex et min-width ne sont pas décoratifs : les puces de mode et de condition sont en
   flex:0 0 auto, donc incompressibles, et le suffixe (flex:0 5 auto) s'épuise d'abord.
   Sans plancher, c'est le NOM DE LA RESSOURCE qui se faisait raboter en dernier alors que
   deux badges annexes restaient pleinement lisibles — l'information la plus identifiante
   de la rangée cédait la place à ses annotations. Au-delà de ce plancher la rangée déborde
   et se clippe, mais les puces portent un title= qui les révèle au survol ; un nom réduit
   à trois caractères, lui, ne se lit nulle part. */
.isis-ligne-acti__txt {
    flex: 1 1 auto;
    min-width: 6ch;
    font-weight: 600;
    color: var(--isis-text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.isis-ligne-acti__row--res .isis-ligne-acti__txt {
    font-weight: 400;
}

.isis-ligne-acti__suffix {
    flex: 0 5 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: 0.72rem;
    font-style: italic;
    font-weight: 400;
    color: var(--isis-text-muted);
}

.isis-ligne-acti__row--res .isis-ligne-acti__lbl {
    position: relative;
    padding-left: 42px;
}

.isis-ligne-acti__row--res .isis-ligne-acti__lbl::before {
    content: "";
    position: absolute;
    left: 25px;
    top: 0;
    bottom: 0;
    width: 1px;
    background: var(--acti-guide);
}

.isis-ligne-acti__n {
    text-align: right;
    font-family: var(--isis-font-mono);
    font-size: 0.75rem;
    font-variant-numeric: tabular-nums;
    color: var(--isis-text);
}

.isis-ligne-acti__n.is-total {
    font-weight: 600;
}

.isis-ligne-acti__n.is-zero {
    font-weight: 400;
    color: var(--isis-text-muted);
}

.isis-ligne-acti__n.is-surcharge {
    color: var(--isis-warning-text);
    font-weight: 600;
}

.isis-ligne-acti__act {
    display: flex;
    align-items: center;
    justify-content: flex-end;
}

/* Cellule hôte du bloc dans un tableau (tableur d'édition, onglet Coût de
   revient) : le bloc gère lui-même ses marges internes. */
td.isis-costing-row__acti-cell {
    padding: 0 0 4px 0;
    background: var(--isis-surface);
}

/* Le tableur d'édition fait 1724 px de large et défile horizontalement : un bloc
   posé au fil de la cellule sortirait du champ dès le premier défilement — c'est
   exactement le défaut signalé sur la rangée de sous-total. Il reste donc collé au
   bord gauche du champ visible, à une largeur qui tient dans la plus petite
   fenêtre où la boîte s'ouvre. */
/* Même plancher de rangée que l'éditeur du déboursé : ouvrir puis fermer l'édition
   ne doit pas faire changer la densité du bloc. */
td.isis-costing-row__acti-cell .isis-ligne-acti__row { min-height: 32px; }

td.isis-costing-row__acti-cell > .isis-ligne-acti {
    position: sticky;
    left: 0;
    width: min(720px, 100%);
}

/* ── Récap économique, à droite du bloc de déboursé ──────────────────────────
   Les chiffres qu'il porte (Vente HT, déboursé, marge, couverture) existent déjà
   dans la rangée de la ligne — mais à ~1000 px à droite, dans une table de
   1724 px qui défile. Quand on lit la composition du déboursé ils sont hors du
   champ visible, et réciproquement : le récap ne les duplique pas pour décorer,
   il les tient dans le même coup d'œil que le détail.
   Même parti que le bloc de lecture (maquette du 2026-09-23) : aucun aplat,
   aucune ombre — il se tient par son seul filet gauche. */
.isis-ligne-recap {
    /* Même raison qu'au bloc voisin : hors du shell (dialogue d'élaboration),
       --isis-current-mod n'existe pas et le color-mix deviendrait invalide au
       calcul — la propriété qui s'en sert retomberait sur sa valeur initiale. */
    --recap-mod: var(--isis-current-mod, var(--isis-accent));
    box-sizing: border-box;
    padding: 2px 0 2px 13px;
    /* Filet NEUTRE, pas teinté module : le détail juste à gauche porte déjà un rail
       teinté à 16 px d'ici, et deux traits de la même couleur se lisent comme deux
       débuts de bloc alors qu'un seul objet en ouvre un. Ici le trait sépare deux
       colonnes, il n'annonce rien — c'est un séparateur, pas une identité. La teinte
       module reste, une seule fois, sur le titre. 1 px : hors du bannissement des
       liserés ≥ 2 px (DESIGN.md §1, 2026-07-18), et même épaisseur que le rail du
       bloc voisin validé le 2026-09-23. */
    border-left: 1px solid var(--isis-border);
    font-size: 12px;
}
.isis-crv .isis-ligne-recap { --recap-mod: var(--crv-mod); }

.isis-ligne-recap__hd {
    font-size: 11px;
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: color-mix(in srgb, var(--recap-mod) 72%, var(--isis-text));
    padding-bottom: 6px;
}

.isis-ligne-recap__l {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    gap: 3px 10px;
    margin: 0;
    padding: 5px 0;
}
.isis-ligne-recap__l + .isis-ligne-recap__l {
    border-top: 1px solid color-mix(in srgb, var(--isis-border) 60%, transparent);
}
.isis-ligne-recap__l dt {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--isis-text-soft);
}
.isis-ligne-recap__l dd {
    margin: 0;
    text-align: right;
    font-variant-numeric: tabular-nums;
    color: var(--isis-text);
}
.isis-ligne-recap__l--sum dt { color: var(--isis-text); font-weight: 600; }
.isis-ligne-recap__l--sum dd { font-weight: 600; }
.isis-ligne-recap__l--sum dd.is-on-target    { color: var(--isis-success); }
.isis-ligne-recap__l--sum dd.is-below-target { color: var(--isis-warning); }
.isis-ligne-recap__l--sum dd.is-below-floor  { color: var(--isis-danger); font-weight: 700; }
.isis-ligne-recap__l--sum dd.is-no-cost      { color: var(--isis-text-muted); font-weight: 500; }
.isis-ligne-recap__l--live dd.is-up   { color: var(--isis-danger); }
.isis-ligne-recap__l--live dd.is-down { color: var(--isis-success); }

/* Boîte hôte en lecture : c'est ELLE qui est bornée et collée à gauche, plus le
   bloc seul. La règle `> .isis-ligne-acti` juste au-dessus cesse de matcher dès
   qu'un récap est posé — c'est exactement l'intention, et elle reste en vigueur
   sur le tableur d'édition, qui n'en pose pas. */
td.isis-costing-row__acti-cell > .isis-ligne-acti-wrap {
    position: sticky;
    left: 0;
    width: min(1000px, 100%);
    display: flex;
    align-items: flex-start;
    gap: 16px;
}
.isis-ligne-acti-wrap > .isis-ligne-acti  { flex: 1 1 auto; min-width: 0; }
.isis-ligne-acti-wrap > .isis-ligne-recap { flex: 0 0 236px; }

@media (max-width: 980px) {
    td.isis-costing-row__acti-cell > .isis-ligne-acti-wrap { flex-direction: column; gap: 10px; }
    .isis-ligne-acti-wrap > .isis-ligne-recap { flex: 0 0 auto; width: 100%; }
}

/* La zone dépliée d'une ligne de devis hérite de `.isis-devis-ligne__depliant`, qui
   pose un aplat gris (`#devis-panel-items …` à (1,1,0) et `.isis-devis-carte > …` à
   (0,2,0)) et un retrait de 1.5rem. La maquette du 2026-09-23 veut ce bloc SANS fond,
   tenu par son seul rail gauche : on neutralise ici, à spécificité égale et en fin de
   feuille, puisque à égalité c'est la POSITION qui tranche — une règle posée plus haut
   n'aurait servi à rien. */
#devis-panel-items .isis-devis-detail__acti-row,
#devis-panel-items .isis-devis-detail__acti-row:hover,
.isis-devis-carte > .isis-devis-detail__acti-row {
    background: transparent;
    border-radius: 0;
}

#devis-panel-items .isis-grid__row.isis-devis-detail__acti-row > div {
    padding: 6px 10px 10px 34px;
}

/* Carte (conteneur étroit) : les trois pistes chiffrées fixes pèsent 280 px + 36 px de
   gouttières, soit plus que la carte entière ne laisse — le libellé, qui porte
   l'information, tombait sous la dizaine de caractères. On resserre les pistes plutôt
   que de retirer une colonne : aucune donnée ne disparaît. */
@container devis-lignes (max-width: 559px) {
    .isis-ligne-acti__head,
    .isis-ligne-acti__row {
        grid-template-columns: minmax(0, 1fr) 52px 72px 78px;
        gap: 0 8px;
        padding-right: 8px;
    }

    .isis-ligne-acti.has-actions .isis-ligne-acti__head,
    .isis-ligne-acti.has-actions .isis-ligne-acti__row {
        grid-template-columns: minmax(0, 1fr) 52px 72px 78px 32px;
    }
}


/* ── Qualification fiscale d'un document (tâche 30, élargi EF-168) ──────────
   Le dossier lu par le moteur, le verdict ligne par ligne et les réserves. Deux surfaces
   le consomment : le dialogue d'émission d'une facture, qui n'offre que DEUX portes, et le
   sous-onglet TVA d'une offre de prix, où les mêmes refus sont des AVIS (EF-53). D'où le nom
   neutre : il ne nomme plus la seule facture. Tables et champs viennent de .isis-recap-table*
   et .isis-detail-field* — rien n'est redéfini ici, seuls les conteneurs manquaient. */
.isis-qualif__regime {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.6rem;
}

/* Deux colonnes : émetteur / preneur se lisent en regard, c'est leur OPPOSITION qui porte
   le verdict. Une seule colonne sous 520 px — le libellé d'un territoire déborde avant. */
.isis-qualif__dossier {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0.6rem 1.25rem;
}
@media (max-width: 520px) {
    .isis-qualif__dossier { grid-template-columns: minmax(0, 1fr); }
}

/* Dans ce dialogue la glose est TOUJOURS une seconde ligne (numéro de TVA sous un statut,
   fondement sous une mention, lignes nommées sous un refus), jamais une incise. */
.isis-qualif .isis-recap-table__gloss {
    display: block;
}

/* Note « aucun verdict » posée entre deux sections : sans marge basse, elle colle au titre suivant. */
.isis-qualif > .helper {
    margin: 0.25rem 0 1rem;
}

.isis-qualif__refus,
.isis-qualif__causes,
.isis-qualif__obligations {
    margin: 0;
    padding-left: 1.1rem;
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
}
.isis-qualif__causes {
    font-size: 0.82rem;
    color: var(--isis-text-muted);
}

/* Fait non établi : dit à côté de la catégorie retenue, pas à la place. Le moteur tranche
   quand même — c'est la CERTITUDE qui manque, pas le verdict. */
.isis-qualif__doute {
    display: inline-flex;
    align-items: center;
    gap: 0.2rem;
    margin-left: 0.4rem;
    font-size: 0.72rem;
    color: var(--isis-warning);
    white-space: nowrap;
}
.isis-qualif__doute .rzi { font-size: 0.85rem; }

/* La case d'assomption du forçage : le <label> enveloppe la case, donc toute la phrase est
   cliquable — la cible de 24x24 (WCAG 2.5.8) ne repose pas sur la seule case. */
.isis-qualif__ack {
    display: flex;
    align-items: flex-start;
    gap: 0.5rem;
    cursor: pointer;
    font-size: 0.85rem;
    line-height: 1.4;
}


/* ── Écran de référence des régimes de TVA (tâche 31) ──────────────────────────────
   Deux sections explicatives sous le tableau : l'ordre dans lequel le moteur tranche,
   puis les catégories EN 16931 et leurs fondements. Sections, tables de récapitulation
   et encart d'information viennent de .isis-rich-section*, .isis-recap-table* et
   .isis-inline-info — seules les deux listes manquaient. */

/* L'ordre des règles EST le fond : les intervertir changerait le verdict. Le numéro est
   donc porté visuellement, pas laissé au marqueur par défaut du navigateur. */
.isis-regimes-etapes {
    counter-reset: isis-regime-etape;
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.55rem;
}
.isis-regimes-etapes > li {
    counter-increment: isis-regime-etape;
    position: relative;
    padding-left: 2.1rem;
    font-size: 0.86rem;
    line-height: 1.5;
    color: var(--isis-text);
}
.isis-regimes-etapes > li::before {
    content: counter(isis-regime-etape);
    position: absolute;
    left: 0;
    top: 0.05rem;
    width: 1.5rem;
    height: 1.5rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: var(--isis-surface-alt);
    border: 1px solid var(--isis-border);
    color: var(--isis-text-muted);
    font-size: 0.75rem;
    font-weight: 600;
}

/* Les précisions qui ne sont pas des étapes : elles valent à TOUTES les étapes, donc un
   numéro les ferait passer pour une sixième règle. */
.isis-regimes-notes {
    margin: 0;
    padding-left: 1.15rem;
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
    font-size: 0.82rem;
    line-height: 1.5;
    color: var(--isis-text-muted);
}

.isis-regimes__note {
    margin: 0;
    font-size: 0.8rem;
    line-height: 1.5;
    color: var(--isis-text-muted);
}

/* Un régime peut porter DEUX mentions (autoliquidation domestique ou intracommunautaire,
   hors champ ou exportation) : la seconde est une alternative, pas une incise. */
.isis-regimes-categories .isis-recap-table__gloss {
    display: block;
}

/* Les codes de catégorie et d'article cités dans la prose : lisibles sans crier. */
.isis-regimes-etapes code,
.isis-regimes-notes code,
.isis-regimes__note code {
    font-size: 0.82em;
    padding: 0.05rem 0.25rem;
    border-radius: 3px;
    background: var(--isis-surface-alt);
    color: var(--isis-text);
}
/* ============================================================================
   .isis-form-shell — coquille des formulaires de SAISIE (norme 2026-09-26)
   ----------------------------------------------------------------------------
   Le grief d'origine (« les écrans add/edit sont longs en hauteur ») ne vient
   pas de la longueur du formulaire mais du CONTENEUR non borné : un dialogue
   Radzen n'a ni plafond ni zone défilante, donc dès 12 champs c'est l'overlay
   entier qui défile et le bouton Enregistrer sort de l'écran.
   Plafond par max-height, et NON par DialogOptions.Height : une hauteur fixe
   gonflerait un formulaire de trois champs. 90vh et non 85vh — les plafonds
   déjà posés dans cette feuille sont tous à 90vh.
   Pied visible par CHAÎNE FLEX, jamais position:sticky — recette de
   RegimeEditorPage (cf. 14449), la seule du produit qui tienne à 44 champs :
   rien à empiler, aucun z-index à arbitrer, aucun fond opaque à maintenir.
   Même mécanique que .isis-dialog-flex (cf. 4963) mais en classes DISTINCTES :
   celles-là sont déjà consommées par 4 dialogues NON formulaires, et le maillon
   « > form » ci-dessous n'a rien à leur faire.
   Posé en fin de feuille : à spécificité égale, c'est la POSITION qui tranche.
   ============================================================================ */
.rz-dialog.isis-form-dialog {
    max-height: 90vh;
    display: flex;
    flex-direction: column;
}

.rz-dialog.isis-form-dialog > .rz-dialog-content,
.rz-dialog-content.isis-form-dialog-content {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

/* ── Le maillon qui manquait ─────────────────────────────────────────────────
   RadzenTemplateForm rend un <form> que rien ne rend flex : la chaîne s'arrête
   là, le corps ne défile pas et le pied repart hors écran. Ciblé par la classe
   de contenu (et non par :has(), déjà écarté ici — cf. 4965) : aucun autre
   dialogue n'est touché. */
.rz-dialog-content.isis-form-dialog-content > form {
    display: flex;
    flex-direction: column;
    min-height: 0;
    flex: 1 1 auto;
}

.isis-form-shell {
    display: flex;
    flex-direction: column;
    min-height: 0;
    flex: 1 1 auto;
}

/* Variante page : le parent doit être une colonne flex bornée (.isis-rich-page,
   cf. 2669). Sans lui, height:100% n'a pas de référence : la page reprend le
   défilement et le pied repart en fin de flux — sans aucun signe. */
.isis-form-shell--page {
    height: 100%;
    overflow: hidden;
}

.isis-form-shell__body {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
}

/* Le pied garde le filet et l'alignement de .isis-form-linear__actions (4188),
   ainsi que le padding-top: 1rem de 4240 : la respiration sous le filet reste
   souhaitable. On ne lui retire que la marge haute, qui servait à décoller un
   pied en fin de flux — hors flux, elle ne fait plus qu'un trou. */
.isis-form-shell__footer {
    flex: 0 0 auto;
}

/* ATTENTION, sélecteur DOUBLÉ à dessein, exactement comme le pied QC de 30624 :
   `.isis-form-shell__footer` seul pèse (0,1,0) et PERD contre
   `.isis-form-linear--dialog .isis-form-linear__actions` de 4240 (0,2,0) — le pied
   porte les deux classes et la racine porte --dialog. Écrite simplement, cette
   neutralisation était donc INERTE en variante Dialog, quelle que soit sa position
   dans la feuille : mesuré le 2026-09-26 sur le pilote 1, margin-top résolu à 20px
   (1.25rem), soit une bande vide entre la zone défilante et le filet du pied, sur
   TOUS les dialogues de saisie. Le premier `.isis-form-shell` porte le sélecteur à
   (0,2,0), qui l'emporte par position. Ne pas le retirer comme redondant ;
   la sonde manuelle e2e/_forme-coquille-geometrie.mjs tient l'invariant (0px). */
.isis-form-shell .isis-form-shell__footer {
    margin-top: 0;
}

/* ── Un seul défileur, et pas de saut entre onglets ──────────────────────────
   La règle globale (cf. 14349) fait de chaque panneau d'onglet son propre
   défileur : imbriqué dans le corps défilant de la coquille, cela donnerait
   deux régions de défilement dont l'extérieure ne bougerait jamais. Dans la
   coquille, le défileur unique est __body.
   Le plancher corrige l'autre défaut d'un conteneur borné : passer d'un onglet
   de 12 champs à un onglet de 3 fait sauter le dialogue et déplace le pied
   sous le curseur. 18rem reste très en dessous du plafond de 90vh.
   ⚠ Les deux derniers :not() ne filtrent AUCUN cas d'usage — ils sont là pour
   la SPÉCIFICITÉ. La règle globale de 14349 s'écrit avec trois :not() et pèse
   donc (0,4,0) (chaque :not() compte la spécificité de son argument) ; sans eux
   ce sélecteur pèse (0,3,0), perd, et le bloc est INERTE quelle que soit sa
   position dans la feuille — mesuré le 2026-09-26 sur le pilote 1 : min-height
   résolu à 0px et overflow-y à auto. Ne pas les retirer comme redondants.
   Filet : e2e/_forme-coquille-geometrie.mjs, sonde MANUELLE — rien ne l'exécute
   automatiquement (la convention `_*.mjs` du répertoire, et `e2e/package.json` ne
   lance que `playwright test` et `unit/**`). À rejouer à la main en touchant à ces
   règles : sans ça, personne ne verra la régression. */
.isis-form-shell .isis-tab-panel:not(.is-hidden):not(.isis-tab-panel--rich):not(.isis-tab-panel--footed) {
    overflow-y: visible;
    min-height: 18rem;
}

/* ── Titre et sous-titre de l'en-tête de coquille ────────────────────────────
   La règle d'en-tête de 3669 ne vise que `h1`. Dans une coquille, le titre du
   FORMULAIRE n'est pas celui de la page (un dialogue n'a pas de h1, et la
   variante Page en a déjà un) : le composant rend un <h2>, et sans la règle
   ci-dessous ce titre repartirait avec la typographie par défaut du navigateur.
   Les six déclarations sont donc dupliquées à dessein — éditer 3669 en place
   sortirait de la voie d'ajout en fin de feuille. Toute évolution de 3669 doit
   être reportée ici. */
.isis-form-shell .isis-form-linear__header h2 {
    font-size: 1.5rem;
    font-weight: 600;
    letter-spacing: -0.01em;
    line-height: 1.2;
    margin: 0;
    color: var(--isis-text);
}

/* Le sous-titre est un <p> : la règle de 3677 ne reprend que sa marge HAUTE,
   la marge basse par défaut du navigateur gonflerait l'en-tête d'un 1em. */
.isis-form-shell .isis-form-linear__header p {
    margin-bottom: 0;
}

/* ── Variante Page : pas de padding bas sous un pied épinglé ─────────────────
   `.isis-form-linear` (3595) pose `padding: 1.25rem 1.5rem 2.5rem`. En dialogue,
   3609 (`.rz-dialog-content .isis-form-linear`) le remet à zéro — mais en PAGE,
   rien ne le fait : les 2,5rem du bas tomberaient SOUS le pied épinglé, hors de
   la zone défilante, en pure bande vide en bas d'écran. On ne retire que le bas :
   les paddings haut et latéraux sont la respiration de la page, ils restent.
   Posé avant que la variante Page ait un consommateur, délibérément. */
.isis-form-shell--page {
    padding-bottom: 0;
}

/* ── Icône d'en-tête : module COURANT, pas gescom ────────────────────────────
   `.isis-form-linear__header-icon` (3658) peint l'icône avec
   `--isis-mod-gescom-soft` / `--isis-mod-gescom` : hérité d'un temps où
   form-linear ne servait que gescom. La coquille est TRANSVERSE (gesmat, sirh,
   gescompta…) : sans cette reprise, tout en-tête de coquille afficherait une
   pastille gescom au milieu d'un autre module.
   ⚠ REPLI OBLIGATOIRE, pas décoratif. `--isis-current-mod*` n'est posé que sur
   `.isis-shell__content` (678/696-697), `.isis-shell` (771-773) et
   `.isis-shell.isis-mod-unified` (787-788) — or `<RadzenComponents />` est un FRÈRE
   de `.isis-shell` dans MainLayout.razor (ligne 12 contre ligne 43) : TOUT dialogue
   est rendu hors de cette portée, et la variante Dialog est justement le cas normal
   de la coquille. Le repli interne de 696-697 (`var(--isis-module-hue, var(--isis-accent))`)
   ne joue pas : c'est la règle de DÉFINITION qui ne s'applique pas. Mesuré le 2026-09-26
   sur le pilote 1 avec un Title temporaire, AVANT le repli : `background-color` résolu à
   `rgba(0, 0, 0, 0)` (var vide = propriété invalide au calcul = valeur initiale, pastille
   invisible) et `color` à `rgb(15, 23, 42)` (texte ambiant hérité), tandis que les mêmes
   jetons valaient `#fff1ec` / `#c2410c` sur `.isis-shell__content`. Le repli est écrit AU
   POINT D'USAGE, comme les ~40 autres occurrences de la feuille ; `--isis-accent*` est bien
   défini sur `:root` (86-87) et en sombre sur `:root[data-theme="dark"]` (45615-45616),
   donc dans l'ascendance réelle d'un dialogue. Ne pas « simplifier » en retirant le repli :
   en dialogue, il est le SEUL terme qui résout.
   Corollaire à ne pas se cacher : en variante Dialog, la pastille prend donc l'ACCENT, pas la
   teinte du module courant — inatteignable hors du shell. C'est le comportement de toutes les
   autres occurrences de la feuille, et c'est déjà le défaut d'origine corrigé (plus de pastille
   gescom dans un autre module) ; teindre un dialogue par module exigerait de poser les jetons
   sur la racine ou sur l'hôte des dialogues, ce qui dépasse cette norme. */
.isis-form-shell .isis-form-linear__header-icon {
    background: var(--isis-current-mod-soft, var(--isis-accent-soft));
    color: var(--isis-current-mod, var(--isis-accent));
}

/* ── Barre d'onglets hors de la zone défilante ───────────────────────────────
   Même grief que le pied : une barre d'onglets placée DANS le corps défilant
   sort de l'écran dès qu'on descend dans les champs, et il faut remonter tout le
   formulaire pour changer d'onglet. Le slot `Tabs` de la coquille la rend donc
   entre l'erreur et le corps, dans ce conteneur.
   `flex: 0 0 auto` pour la même raison que le pied : dans une colonne flex
   BORNÉE, le shrink par défaut (1) écraserait la barre quand les champs
   débordent. La barre ne porte aucun espacement propre ici : `.isis-tabs`
   apporte déjà son `margin-bottom: 16px` et son `border-bottom: 1px solid` —
   mesurés le 2026-09-26 sur le pilote 1 avant déplacement (margin-top: 0px,
   padding-bottom: 0px), donc l'écart sous la barre est conservé tel quel et
   AUCUNE règle de `.isis-tabs` n'est neutralisée. */
.isis-form-shell__tabs {
    flex: 0 0 auto;
}

/* ── RoleEntrepriseScopeDialog : espacements à tokens, plus de style="margin-*" inline
   (audit UI/UX 2026-09-30, finding 2). Échelle --isis-space-* de la ligne 296. */
.isis-scope-dialog__intro {
    margin-bottom: var(--isis-space-md);
}
.isis-scope-dialog__row-gap-top {
    margin-top: var(--isis-space-md);
}
.isis-scope-dialog__note {
    color: var(--isis-text-muted);
}
.isis-scope-dialog__note--after {
    margin-top: var(--isis-space-md);
}
.isis-scope-dialog__note--before {
    margin-bottom: var(--isis-space-md);
}
.isis-scope-dialog__axis-row {
    margin-bottom: var(--isis-space-md);
}
.isis-scope-dialog__axis-head {
    display: flex;
    align-items: center;
    gap: var(--isis-space-md);
    margin-bottom: var(--isis-space-sm);
}
.isis-scope-dialog__axis-head .label {
    margin: 0;
}
.isis-scope-dialog__axis-value {
    margin-top: var(--isis-space-sm);
}

/* Import du programme de commandes d'un marché-cadre (FluxImportDialog). */
.isis-rich-toolbar--start {
    justify-content: flex-start;
}
.isis-flux-import__motif {
    white-space: normal;
    overflow-wrap: anywhere;
    line-height: 1.3;
}
.isis-flux-import__note {
    font-size: var(--isis-fs-sm);
    color: var(--isis-text-muted);
}
.isis-flux-import__requis {
    color: var(--isis-danger-text);
}
.isis-flux-import__etape {
    border-radius: var(--isis-radius-sm);
}
.isis-flux-import__etape:focus {
    outline: none;
}
.isis-flux-import__etape:focus-visible {
    outline: 2px solid var(--isis-current-mod);
    outline-offset: 2px;
}
.isis-flux-import__avis {
    color: var(--isis-warning-text);
}
.isis-flux-import__bilan > summary {
    cursor: pointer;
    color: var(--isis-text-muted);
    font-size: var(--isis-fs-sm);
}
.isis-flux-import__bilan > summary:focus-visible {
    outline: 2px solid var(--isis-current-mod);
    outline-offset: 2px;
}
.isis-flux-import__bilan-liste {
    margin: var(--isis-space-xs) 0 0;
    padding-left: var(--isis-space-md);
}

/* CA par structure (/gesproj/ca-par-structure) : tableau à colonnes de période variables. */
.isis-ca-scroll { overflow-x: auto; }
.isis-ca-table {
    width: 100%;
    border-collapse: collapse;
    font-size: var(--isis-fs-sm);
}
.isis-ca-table th,
.isis-ca-table td {
    padding: var(--isis-space-xs) var(--isis-space-sm);
    border-bottom: 1px solid var(--isis-border-soft);
    white-space: nowrap;
    font-weight: normal;
}
.isis-ca-table thead th {
    color: var(--isis-text-muted);
    font-weight: 600;
    border-bottom-color: var(--isis-border);
}
.isis-ca-table__nom { text-align: left; }
.isis-ca-table tbody th.isis-ca-table__nom {
    padding-left: calc(var(--isis-space-sm) + var(--niv, 0) * var(--isis-space-md));
    color: var(--isis-text);
}
.isis-ca-table__num {
    text-align: right;
    font-family: var(--isis-font-mono);
    font-variant-numeric: tabular-nums;
}
.isis-ca-table tfoot th,
.isis-ca-table tfoot td {
    font-weight: 600;
    border-top: 1px solid var(--isis-border);
    border-bottom: 0;
}
.isis-ca-table__orphan { color: var(--isis-text-muted); font-style: italic; }
.isis-ca-table__ecart {
    border: 0;
    background: transparent;
    color: var(--isis-text-muted);
    cursor: pointer;
    padding: 0 0 0 var(--isis-space-xs);
    border-radius: var(--isis-radius-sm);
}
.isis-ca-table__ecart:hover { color: var(--isis-text); }
.isis-ca-table__ecart:focus-visible {
    outline: 2px solid var(--isis-current-mod);
    outline-offset: 2px;
}
.isis-ca-note {
    color: var(--isis-text-muted);
    font-size: var(--isis-fs-sm);
    margin: var(--isis-space-xs) 0;
}
.isis-ca-ecart { margin-top: var(--isis-space-md); }
.isis-ca-ecart__head {
    display: flex;
    align-items: center;
    gap: var(--isis-space-sm);
    flex-wrap: wrap;
}

/* Variante grille « lignes au prix d'achat » de la fiche engagement (gesst) : 4 colonnes
   désignation / quantité / prix d'achat unitaire / total. Lignes d'un document : ni tri ni
   pagination (DESIGN.md §4) — hauteur bornée, défilement interne, en-tête collant. */
.isis-grid--engagement-lignes {
    --isis-lignes-max-h: 24rem;
    max-height: var(--isis-lignes-max-h);
}
.isis-grid--engagement-lignes .isis-grid__head,
.isis-grid--engagement-lignes .isis-grid__row {
    grid-template-columns: minmax(240px, 3fr) 130px 190px 150px;
    min-width: 710px;
}
.isis-grid--engagement-lignes .isis-grid__row { cursor: default; }
.isis-grid--engagement-lignes .isis-grid__row:hover { background: transparent; }
.isis-grid--engagement-lignes .isis-grid__col-num {
    text-align: right;
    font-variant-numeric: tabular-nums;
}
.isis-grid--engagement-lignes .isis-grid__head-cell.isis-grid__col-num { justify-content: flex-end; }
.isis-engagement-lignes__total {
    display: flex;
    justify-content: flex-end;
    gap: var(--isis-space-md);
    margin-top: var(--isis-space-sm);
    font-size: var(--isis-fs-base);
    font-variant-numeric: tabular-nums;
}

/* Choix des lignes d'un modèle (dialogue « Enregistrer comme modèle ») */
.isis-modele-lignes {
    list-style: none;
    margin: var(--isis-space-sm) 0 0;
    padding: var(--isis-space-xs) var(--isis-space-sm);
    max-height: 240px;
    overflow-y: auto;
    border: 1px solid var(--isis-border-soft);
    border-radius: var(--isis-radius-sm);
}
.isis-modele-lignes li {
    display: flex;
    align-items: baseline;
    gap: var(--isis-space-xs);
    padding: var(--isis-space-xs) 0;
}
.isis-modele-lignes__outils {
    display: flex;
    gap: var(--isis-space-xs);
    margin-top: var(--isis-space-sm);
}

/* Modèles de lignes d'offre de prix (/gescom/devis/modeles) — 8 pistes = 8 en-têtes. */
.isis-grid--devis-modeles .isis-grid__head,
.isis-grid--devis-modeles .isis-grid__row {
    grid-template-columns:
        minmax(200px, 1.4fr) minmax(200px, 2fr) minmax(180px, 1.2fr)
        80px 90px minmax(140px, 1fr) 120px 112px;
    min-width: 1160px;
}

/* Tableau de bord des événements : empilement des trois récapitulatifs. */
.isis-evt-dash-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: 1rem;
    margin-top: 1rem;
    border: none;
    background: none;
}
.isis-evt-dash-grid__titre { margin: 0 0 0.5rem; }

/* Coût par événement (/gescom/evenements/dashboard) — 5 pistes = 5 en-têtes. */
.isis-grid--evt-cout-evenement .isis-grid__head,
.isis-grid--evt-cout-evenement .isis-grid__row {
    grid-template-columns: minmax(200px, 2fr) 140px 110px minmax(130px, 1fr) minmax(130px, 1fr);
    min-width: 760px;
}

/* Coût par entreprise — 3 pistes = 3 en-têtes. */
.isis-grid--evt-cout-entreprise .isis-grid__head,
.isis-grid--evt-cout-entreprise .isis-grid__row {
    grid-template-columns: minmax(220px, 2fr) 120px minmax(160px, 1fr);
    min-width: 520px;
}

/* Participations par collaborateur — 2 pistes = 2 en-têtes. */
.isis-grid--evt-participations .isis-grid__head,
.isis-grid--evt-participations .isis-grid__row {
    grid-template-columns: minmax(220px, 2fr) 140px;
    min-width: 360px;
}

/* Questions sans réponse de l'assistant d'aide (/admin/aide-assistant) — 4 pistes = 4 en-têtes. */
.isis-grid--help-questions .isis-grid__head,
.isis-grid--help-questions .isis-grid__row {
    grid-template-columns: 130px minmax(160px, 1fr) 130px minmax(280px, 3fr);
    min-width: 700px;
}
.isis-grid--help-questions .isis-grid__row > div { white-space: normal; overflow-wrap: anywhere; }

/* Collaborateurs sans compte (/admin/users) — 7 pistes = 7 en-têtes. */
.isis-grid--sans-compte .isis-grid__head,
.isis-grid--sans-compte .isis-grid__row {
    grid-template-columns:
        44px minmax(180px, 1.4fr) 110px minmax(160px, 1.2fr)
        minmax(180px, 1.4fr) minmax(280px, 1.6fr) 72px;
    min-width: 1030px;
}
.isis-grid--sans-compte .isis-sans-compte__signal {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--isis-space-sm);
}

/* Catalogue d'achat d'un sous-traitant, remises globales (onglet Catalogue) — 6 pistes = 6 en-têtes. */
.isis-grid--catalogue-tiers-remises .isis-grid__head,
.isis-grid--catalogue-tiers-remises .isis-grid__row {
    grid-template-columns: minmax(180px, 1.4fr) 100px 110px 130px 110px 90px;
    align-items: center;
    min-width: 750px;
}

/* Choix d'un modèle de lignes à charger (dialogue) — 5 pistes = 5 en-têtes. */
.isis-grid--devis-modele-charger .isis-grid__head,
.isis-grid--devis-modele-charger .isis-grid__row {
    grid-template-columns: 60px minmax(200px, 2fr) 130px 80px 80px;
    align-items: center;
    min-width: 590px;
}

/* Offres rattachées à un contrat-cadre (fiche marché) — 5 pistes = 5 en-têtes. */
.isis-grid--marche-offres-cadre .isis-grid__head,
.isis-grid--marche-offres-cadre .isis-grid__row {
    grid-template-columns: 150px minmax(200px, 1.6fr) 150px 130px 170px;
    min-width: 830px;
}
.isis-grid--marche-offres-cadre .isis-grid__link {
    color: var(--isis-text);
    font-family: var(--isis-font-mono);
    text-decoration: underline;
    text-decoration-thickness: 1px;
    text-underline-offset: 2px;
}

/* Habilitations exigées d'une activité (dialogue) — 5 pistes = 5 en-têtes. */
.isis-grid--activite-habilitations .isis-grid__head,
.isis-grid--activite-habilitations .isis-grid__row {
    grid-template-columns: minmax(160px, 1.4fr) 130px 130px minmax(120px, 1fr) 90px;
    min-width: 670px;
}

/* Reprise des lots d'une consultation antérieure (dialogue) — 3 pistes = 3 en-têtes. */
.isis-grid--opportunite-lot-reprise .isis-grid__head,
.isis-grid--opportunite-lot-reprise .isis-grid__row {
    grid-template-columns: 140px minmax(200px, 1fr) 80px;
    min-width: 470px;
}

/* Réservations (gesfac, MonEspace) — même objet, mêmes pistes pour les mêmes colonnes :
   Jour et créneau 250 | Espace élastique | Site élastique | Type 140 | Personne 160 | Places 110 |
   Statut 120 | Actions 130. Une grille par page, chacune autant de pistes que d'en-têtes
   (6, 6, 5 et 6 ; min-width = somme des pistes minimales). */
.isis-grid--gesfac-reservations .isis-grid__head,
.isis-grid--gesfac-reservations .isis-grid__row {
    grid-template-columns: 250px minmax(220px, 1.6fr) minmax(140px, 1fr) minmax(160px, 1fr) 120px 130px;
    min-width: 1020px;
}

.isis-grid--mes-resa-places .isis-grid__head,
.isis-grid--mes-resa-places .isis-grid__row {
    grid-template-columns: 250px minmax(220px, 1.6fr) minmax(140px, 1fr) 140px 110px 130px;
    min-width: 990px;
}

.isis-grid--mes-resa-venir .isis-grid__head,
.isis-grid--mes-resa-venir .isis-grid__row {
    grid-template-columns: 250px minmax(220px, 1.6fr) minmax(140px, 1fr) minmax(160px, 1fr) 130px;
    min-width: 900px;
}

.isis-grid--gesfac-dialog-places .isis-grid__head,
.isis-grid--gesfac-dialog-places .isis-grid__row {
    grid-template-columns: 250px minmax(220px, 1.6fr) minmax(140px, 1fr) 140px 110px 130px;
    min-width: 990px;
}

/* Horaires des sites (gesfac) — Site | Fuseau | 7 jours | Règles | Actions = 11 pistes. */
.isis-grid--gesfac-horaires .isis-grid__head,
.isis-grid--gesfac-horaires .isis-grid__row {
    grid-template-columns: minmax(160px, 1.2fr) 150px 110px 110px 110px 110px 110px 110px 110px 190px 90px;
    min-width: 1360px;
}
