/* =====================================================================================
   OPTIMA HUB — Système de design (jetons + finitions + base + composants)       version 2.3.1
   Contrat : design/SPEC.md (§2 jetons, §7 composants, §8 finitions) ; mode d'emploi des lots :
   design/MIGRATION.md. Servi depuis /hub/hub.css, chargé sur TOUTES les pages par /auth.js (inséré
   en tête du <head>, bloquant le rendu) ; une page peut aussi le lier elle-même avant /auth.js.
   Fichier réservé au lot A : les lots de pages ne le modifient pas (demande : design/REQUESTS.md).

   Quatre couches
   1. JETONS (§2) : variables --hub-* sur :root ; accent de module par <html data-hub-module="…">.
   2. FINITIONS GLOBALES (§4a) : s'appliquent à TOUTE page qui charge ce fichier, migrée ou non :
      color-scheme, barres de défilement, sélection, focus, curseur, autofill, cibles, ancres.
      Quelques !important assumés (barres de défilement, sélection, focus) : l'uniformité prime sur
      les styles historiques des pages (SPEC §8). Les réglages qui pourraient modifier le
      comportement d'une page non migrée (défilement doux, décalage des ancres, gouttière réservée)
      sont limités au mode « complète » de la coque.
   3. BASE (§4b) : police, fond, rendu typographique — seulement si <html class="hub">, en
      spécificité nulle (:where) pour que les composants l'emportent toujours.
   4. COMPOSANTS (§5 →) : classes préfixées hub-…, sans effet tant qu'on ne les emploie pas.

   Modes de la coque (attribut posé sur <html> par /auth.js ou /hub/shell.js, design/MIGRATION.md §4)
   - data-hub-shell="complete" : page migrée (<hub-topbar> statique) : barre collante, sous-navigation ;
   - "injectee" : page non migrée : barre insérée en tête de <body>, dans le flux (non collante) ;
   - "discrete" : page non migrée fragile : aucune barre, bouton flottant + recherche ⌘K ;
   - "aucune"   : finitions seules (éditeur plein écran, page sans session).
   Règles : jamais de texte < 12 px ; jamais de texte de couleur --hub-brand sur fond sombre
   (utiliser --hub-brand-text) ; z-index des pages ≤ 900 (la coque est à 1000).
   ===================================================================================== */

/* ---------- 1. Polices (auto-hébergées, variables, sous-ensembles latin / latin-ext) ---------- */
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("/hub/fonts/inter-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("/hub/fonts/inter-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "JetBrains Mono";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("/hub/fonts/jetbrains-mono-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* Repli à métriques ajustées : la bascule Arial → Inter (font-display: swap) ne décale rien. */
@font-face {
  font-family: "Inter Fallback";
  src: local("Arial"), local("ArialMT"), local("Helvetica"), local("Liberation Sans");
  ascent-override: 90.44%;
  descent-override: 22.52%;
  line-gap-override: 0%;
  size-adjust: 107.12%;
}

/* Bouton « Se connecter avec Google » : iframe tierce en schéma clair. Si son color-scheme diffère
   de celui de la page (dark), le navigateur peint un fond blanc opaque derrière l'iframe. */
iframe[src*="accounts.google.com"] { color-scheme: normal; }

/* ---------- 2. Jetons ---------- */
:root {
  color-scheme: dark;

  /* Surfaces — noirs légèrement violets (héritage Optima #0D0820, plus neutres) */
  --hub-bg: #0b0a13;              /* fond de page */
  --hub-bg-subtle: #100f1a;       /* barres, tiroirs, zones secondaires */
  --hub-surface: #15141f;         /* cartes, tableaux */
  --hub-surface-2: #1b1a27;       /* survol, champs, en-têtes de tableau */
  --hub-surface-3: #23212f;       /* menus, palette, modales */
  --hub-surface-hover: rgba(255, 255, 255, .04);
  --hub-surface-active: rgba(255, 255, 255, .07);
  --hub-overlay: rgba(6, 5, 12, .66);

  /* Bordures */
  --hub-border-subtle: rgba(255, 255, 255, .06);
  --hub-border: rgba(255, 255, 255, .10);
  --hub-border-strong: rgba(255, 255, 255, .16);
  --hub-border-input: #66627b;    /* 3,2:1 sur --hub-surface, 3,4:1 sur --hub-bg (WCAG 1.4.11) */

  /* Texte (contrastes mesurés sur --hub-surface #15141f) */
  --hub-text-1: #f3f1f8;          /* 16,4:1 — titres, valeurs */
  --hub-text-2: #b9b5c8;          /*  9,2:1 — texte courant secondaire */
  --hub-text-3: #8e8aa3;          /*  5,5:1 — méta, libellés, aide (minimum pour du texte) */
  --hub-text-3-raised: #9e9ab2;   /*  5,1:1 sur une ligne survolée de --hub-surface-3 (menus, palette, modales) */
  --hub-text-disabled: #625e76;   /*  3,6:1 — désactivé uniquement (exempté WCAG) */
  --hub-text-inverse: #0b0a13;

  /* Marque Optima */
  --hub-brand: #d00b8d;           /* aplats (boutons primaires, indicateurs) — blanc dessus : 5,1:1 */
  --hub-brand-hover: #b8097c;     /* blanc dessus : 6,2:1 */
  --hub-brand-active: #a0086e;
  --hub-brand-text: #f472c4;      /* magenta lisible sur fond sombre : 7,0:1 */
  --hub-brand-soft: rgba(208, 11, 141, .14);
  --hub-brand-soft-2: rgba(208, 11, 141, .24);
  --hub-brand-border: rgba(244, 114, 196, .38);
  --hub-on-brand: #ffffff;

  /* Focus */
  --hub-focus: #f472c4;
  --hub-focus-ring: 0 0 0 2px var(--hub-bg), 0 0 0 4px var(--hub-focus);

  /* États (texte lisible sur toutes les surfaces sombres) */
  --hub-success: #3fcf8e;  --hub-success-soft: rgba(63, 207, 142, .12);  --hub-success-border: rgba(63, 207, 142, .32);
  --hub-warning: #f5b544;  --hub-warning-soft: rgba(245, 181, 68, .12);  --hub-warning-border: rgba(245, 181, 68, .32);
  --hub-danger:  #ff6b6b;  --hub-danger-soft:  rgba(255, 107, 107, .12); --hub-danger-border:  rgba(255, 107, 107, .34);
  --hub-info:    #6ea8ff;  --hub-info-soft:    rgba(110, 168, 255, .12); --hub-info-border:    rgba(110, 168, 255, .32);

  /* Données (palette catégorielle validée : daltonisme ΔE ≥ 8,4, contraste ≥ 3:1 sur --hub-surface).
     Ordre fixe, jamais cyclé ; au-delà de 8 séries → « Autres ». */
  --hub-viz-1: #3987e5; --hub-viz-2: #d95926; --hub-viz-3: #199e70; --hub-viz-4: #c98500;
  --hub-viz-5: #d55181; --hub-viz-6: #008300; --hub-viz-7: #9085e9; --hub-viz-8: #e66767;
  --hub-viz-grid: rgba(255, 255, 255, .06);
  --hub-viz-axis: rgba(255, 255, 255, .16);
  /* Séquentielle (magnitude, une teinte) : du plus faible au plus fort */
  --hub-seq-1: #3a1231; --hub-seq-2: #651050; --hub-seq-3: #970d74; --hub-seq-4: #d00b8d; --hub-seq-5: #f472c4;

  /* Accent de module (défaut : Optima) — redéfini par [data-hub-module] */
  --hub-accent: var(--hub-brand);
  --hub-accent-text: var(--hub-brand-text);
  --hub-accent-soft: color-mix(in srgb, var(--hub-accent) 14%, transparent);
  --hub-accent-border: color-mix(in srgb, var(--hub-accent-text) 40%, transparent);

  /* Typographie */
  --hub-font-sans: "Inter", "Inter Fallback", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --hub-font-mono: "JetBrains Mono", ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
  --hub-fs-xs: .75rem;    /* 12 / 16 — méta, en-têtes de tableau, badges */
  --hub-fs-sm: .8125rem;  /* 13 / 20 — UI dense : tableaux, navigation, boutons */
  --hub-fs-md: .875rem;   /* 14 / 22 — texte courant des applications */
  --hub-fs-lg: 1rem;      /* 16 / 24 — texte de document, titres de carte larges */
  --hub-fs-xl: 1.125rem;  /* 18 / 26 — titres de section */
  --hub-fs-2xl: 1.375rem; /* 22 / 30 — titre de page (mobile) */
  --hub-fs-3xl: 1.75rem;  /* 28 / 36 — titre de page, valeur KPI */
  --hub-fs-4xl: 2.25rem;  /* 36 / 44 — salutation de l'accueil */
  --hub-fs-5xl: 3rem;     /* 48 / 56 — chiffre héros */
  --hub-lh-xs: 1rem; --hub-lh-sm: 1.25rem; --hub-lh-md: 1.375rem; --hub-lh-lg: 1.5rem; --hub-lh-xl: 1.625rem;
  --hub-lh-2xl: 1.875rem; --hub-lh-3xl: 2.25rem; --hub-lh-4xl: 2.75rem; --hub-lh-5xl: 3.5rem;
  --hub-fw-regular: 400; --hub-fw-medium: 500; --hub-fw-semibold: 600; --hub-fw-bold: 700;
  --hub-tracking-tight: -.022em; --hub-tracking-snug: -.011em; --hub-tracking-wide: .04em;

  /* Espacements (grille de 4 px) */
  --hub-space-0-5: 2px; --hub-space-1: 4px; --hub-space-1-5: 6px; --hub-space-2: 8px; --hub-space-3: 12px;
  --hub-space-4: 16px; --hub-space-5: 20px; --hub-space-6: 24px; --hub-space-8: 32px; --hub-space-10: 40px;
  --hub-space-12: 48px; --hub-space-16: 64px; --hub-space-20: 80px;

  /* Rayons */
  --hub-radius-xs: 4px; --hub-radius-sm: 6px; --hub-radius-md: 8px; --hub-radius-lg: 12px;
  --hub-radius-xl: 16px; --hub-radius-2xl: 20px; --hub-radius-full: 999px;

  /* Ombres (sombre : ombre + liseré clair interne) */
  --hub-highlight: inset 0 1px 0 rgba(255, 255, 255, .04);
  --hub-shadow-1: 0 1px 2px rgba(0, 0, 0, .35);
  --hub-shadow-2: 0 4px 12px rgba(0, 0, 0, .32), 0 1px 2px rgba(0, 0, 0, .28);
  --hub-shadow-3: 0 12px 32px rgba(0, 0, 0, .48), 0 2px 6px rgba(0, 0, 0, .32);
  --hub-shadow-4: 0 24px 64px rgba(0, 0, 0, .6), 0 4px 16px rgba(0, 0, 0, .4);

  /* Plans (z-index). La coque utilise aussi la « top layer » (dialog, popover) : aucun conflit. */
  --hub-z-raised: 10; --hub-z-sticky: 100; --hub-z-page-max: 900; --hub-z-shell: 1000;
  --hub-z-dropdown: 1100; --hub-z-overlay: 1200; --hub-z-toast: 1400; --hub-z-tooltip: 1500;

  /* Élévations (ombres multicouches subtiles + reflet intérieur 1 px) */
  --hub-elev-1: inset 0 1px 0 rgba(255, 255, 255, .04), 0 1px 2px rgba(0, 0, 0, .28);
  --hub-elev-2: inset 0 1px 0 rgba(255, 255, 255, .05), 0 1px 2px rgba(0, 0, 0, .28), 0 6px 16px -4px rgba(0, 0, 0, .35);
  --hub-elev-3: 0 0 0 1px rgba(0, 0, 0, .25), 0 2px 4px rgba(0, 0, 0, .2), 0 12px 32px -6px rgba(0, 0, 0, .55);
  --hub-elev-4: 0 0 0 1px rgba(0, 0, 0, .3), 0 4px 8px rgba(0, 0, 0, .25), 0 24px 64px -8px rgba(0, 0, 0, .7);

  /* Finitions : défilement, sélection, saisie.
     Barres de défilement (décision du 29/10/2026) : pouce NEUTRE au repos, partout ; couleur de la
     marque (accent du module, magenta Optima par défaut) seulement au survol et à l'appui du pouce. */
  --hub-scrollbar-size: 12px;
  --hub-scrollbar-thumb: rgba(255, 255, 255, .14);
  --hub-scrollbar-thumb-hover: color-mix(in srgb, var(--hub-accent) 62%, transparent);
  --hub-scrollbar-thumb-active: color-mix(in srgb, var(--hub-accent) 88%, transparent);
  --hub-selection-bg: rgba(208, 11, 141, .42);
  --hub-selection-fg: #ffffff;
  --hub-caret: var(--hub-brand-text);
  --hub-grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 1  0 0 0 0 1  0 0 0 0 1  0 0 0 .55 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");

  /* Mouvement */
  --hub-dur-1: 100ms; --hub-dur-2: 160ms; --hub-dur-3: 240ms; --hub-dur-4: 360ms;
  --hub-ease-out: cubic-bezier(.16, 1, .3, 1);
  --hub-ease-in-out: cubic-bezier(.65, 0, .35, 1);
  --hub-ease-in: cubic-bezier(.4, 0, 1, 1);

  /* Mise en page — points de rupture (documentés, non utilisables dans @media) :
     sm 480 · md 768 · lg 1024 · xl 1280 · 2xl 1536 */
  --hub-topbar-h: 56px;
  --hub-subnav-h: 44px;
  --hub-viewbar-h: 44px;          /* barre des vues collante d'une application (.hub-viewbar) */
  /* Hauteur cumulée de la coque COLLANTE : à utiliser par TOUT élément sticky des pages
     (top: var(--hub-sticky-top)). Vaut 0 quand la barre n'est pas collante (modes de compatibilité). */
  --hub-sticky-top: var(--hub-topbar-h);
  /* Décalage des ancres (scroll-margin-top) : coque collante + 16 px ; 0 hors mode « complète ». */
  --hub-anchor-offset: calc(var(--hub-sticky-top) + 16px);
  --hub-container: 1440px;
  --hub-container-narrow: 1040px;
  --hub-container-text: 720px;
  --hub-gutter: 24px;
}
@media (min-width: 768px) {
  :root:not(.hub-embed):has(hub-subnav:not([hidden])) { --hub-sticky-top: calc(var(--hub-topbar-h) + var(--hub-subnav-h)); }
}
@media (max-width: 767.98px) {
  :root { --hub-topbar-h: 52px; --hub-gutter: 16px; }
}
/* Pages non migrées (barre injectée non collante, mode discret, aucune coque) et iframes : rien de
   collant en haut, aucun décalage d'ancre (comportement historique des pages inchangé). */
html[data-hub-shell="injectee"], html[data-hub-shell="discrete"], html[data-hub-shell="aucune"] { --hub-sticky-top: 0px; --hub-anchor-offset: 0px; }
html.hub-embed { --hub-sticky-top: 0px; --hub-topbar-h: 0px; --hub-subnav-h: 0px; --hub-anchor-offset: 0px; }
/* Pages claires : <html data-hub-theme="light"> (seul usage du clair, SPEC §3.1 : Rapport imprimable).
   La page reste sombre pour la coque (la barre garde ses couleurs, Shadow DOM). */
html[data-hub-theme="light"] {
  color-scheme: light;
  --hub-scrollbar-thumb: rgba(0, 0, 0, .2);
  --hub-selection-bg: rgba(208, 11, 141, .22); --hub-selection-fg: inherit; --hub-caret: var(--hub-brand); --hub-focus: #a0086e;
}
/* Contraste renforcé demandé par le système */
@media (prefers-contrast: more) {
  :root {
    --hub-text-3: #b9b5c8; --hub-text-3-raised: #c9c5d6; --hub-text-2: #d6d3e0;
    --hub-border-subtle: rgba(255, 255, 255, .16); --hub-border: rgba(255, 255, 255, .26); --hub-border-strong: rgba(255, 255, 255, .4);
    --hub-border-input: #9a96b0; --hub-scrollbar-thumb: rgba(255, 255, 255, .4);
  }
  html[data-hub-theme="light"] { --hub-scrollbar-thumb: rgba(0, 0, 0, .45); }
}

/* Accents de module (couleur d'aplat / couleur de texte AA sur fond sombre) */
[data-hub-module="okr"]             { --hub-accent: #d00b8d; --hub-accent-text: #f472c4; }
[data-hub-module="reporting"]       { --hub-accent: #6366f1; --hub-accent-text: #8f91ff; }
[data-hub-module="commissions"]     { --hub-accent: #d4a843; --hub-accent-text: #d4a843; }
[data-hub-module="vivovojo"]        { --hub-accent: #fe0100; --hub-accent-text: #ff5c57; }
[data-hub-module="bebooda"]         { --hub-accent: #f5b000; --hub-accent-text: #f5b000; }
[data-hub-module="btlv"]            { --hub-accent: #3dbdb5; --hub-accent-text: #4fd1c9; }
[data-hub-module="explora-tv"]      { --hub-accent: #e8b44c; --hub-accent-text: #e8b44c; }
[data-hub-module="biomevia"]        { --hub-accent: #a8c462; --hub-accent-text: #a8c462; }
[data-hub-module="adntv"]           { --hub-accent: #00e676; --hub-accent-text: #00e676; }
[data-hub-module="slides"]          { --hub-accent: #9da0b4; --hub-accent-text: #b4b7c8; }
[data-hub-module="vivara"]          { --hub-accent: #4ae8a0; --hub-accent-text: #4ae8a0; }
[data-hub-module="novera"]          { --hub-accent: #60a5fa; --hub-accent-text: #60a5fa; }
[data-hub-module="pages"]           { --hub-accent: #e83da5; --hub-accent-text: #f472c4; }
[data-hub-module="image-optimizer"] { --hub-accent: #f5b041; --hub-accent-text: #f5b041; }
[data-hub-module="organigramme"]    { --hub-accent: #a78bfa; --hub-accent-text: #b9a3fb; }
[data-hub-module="site"]            { --hub-accent: #9da0b4; --hub-accent-text: #b4b7c8; }
[data-hub-module="admin"]           { --hub-accent: #d00b8d; --hub-accent-text: #f472c4; }

/* ---------- 3. Coque : réservation de place (aucun décalage de mise en page) ----------
   <hub-topbar> occupe sa hauteur dès le premier rendu (avant même que /hub/shell.js ne le définisse) ;
   le logo est peint en fond tant que l'élément n'est pas défini. */
hub-topbar {
  display: block;
  position: sticky;
  top: 0;
  z-index: var(--hub-z-shell);
  height: var(--hub-topbar-h);
  width: 100%;
  box-sizing: border-box;
  margin: 0;
}
hub-topbar:not(:defined) {
  background: #100f1a url("/hub/img/optima-icon-64.png") no-repeat 20px center / 24px 24px;
  border-bottom: 1px solid var(--hub-border-subtle);
}
/* Barre injectée par /auth.js dans une page non migrée : même dessin, mais dans le flux (non collante)
   et au plan 1 : les en-têtes collants, tiroirs et modales historiques de la page (top: 0, z-index
   ≥ 2) passent au-dessus d'elle, comme au-dessus du reste du contenu. Menus, palette et tiroir de la
   coque restent au premier plan (top layer). */
html hub-topbar[data-hub-injected] { position: relative; top: auto; z-index: 1; flex: none; float: none; max-width: none; padding: 0; }
/* Mode discret : aucune place occupée ; la coque n'affiche qu'un bouton flottant (Shadow DOM), sous les
   voiles et modales des pages (z-index ≥ 900). */
html hub-topbar[data-hub-discrete] { position: fixed; top: 0; left: 0; z-index: 890; width: 0; height: 0; overflow: visible; background: none; border: 0; }
hub-subnav {
  display: block;
  position: sticky;
  top: var(--hub-topbar-h);
  z-index: calc(var(--hub-z-shell) - 1);
  height: var(--hub-subnav-h);
  width: 100%;
}
hub-subnav:not(:defined) { background: #100f1a; border-bottom: 1px solid var(--hub-border-subtle); }
hub-subnav[hidden] { display: none; }
@media (max-width: 767.98px) {
  hub-topbar:not(:defined) { background-position: 56px center; }
  hub-subnav { position: relative; top: auto; }
}
html.hub-embed hub-topbar, html.hub-embed hub-subnav { display: none !important; }
@media print { hub-topbar, hub-subnav, hub-toasts, hub-dialogs { display: none !important; } }
/* Page claire (Rapport imprimable : data-hub-theme ; bascule « Thème clair » d'un dashboard de marque :
   data-theme) : la coque reste sombre et devient OPAQUE — son fond translucide laisserait transparaître la
   page claire (barre délavée, liens peu contrastés au défilement). background-color seul : le logo peint
   en attendant la définition de l'élément est conservé. */
:is(html[data-hub-theme="light"], html[data-theme="light"]) :is(hub-topbar:not([data-hub-discrete]), hub-subnav) { background-color: #100f1a; }
/* … et la gouttière de la barre de défilement (fond de <html>, clair) prolonge la coque sombre en haut de la
   fenêtre au lieu d'y dessiner une encoche claire de 12 px. */
@media screen and (hover: hover) and (pointer: fine) {
  :is(html[data-hub-theme="light"], html[data-theme="light"])[data-hub-shell="complete"]:not(.hub-embed) {
    background-image: linear-gradient(#100f1a, #100f1a); background-size: 100% var(--hub-sticky-top); background-repeat: no-repeat; background-attachment: fixed;
  }
}

/* ---------- 4a. Finitions globales (toute page qui charge hub.css, migrée ou non) ---------- */
html { -webkit-tap-highlight-color: transparent; }
/* Gouttière réservée : pas de saut horizontal quand la hauteur du contenu change (bascule d'onglet,
   données chargées). Souris seulement (les barres tactiles superposées ne prennent pas de place) ;
   pas en modes « discrete » / « aucune » : une page historique en plein écran (html { overflow:
   hidden }) garderait sinon une bande vide de 12 px à droite. */
@media (hover: hover) and (pointer: fine) {
  html[data-hub-shell="complete"], html[data-hub-shell="injectee"] { scrollbar-gutter: stable; }
}
/* Barres de défilement — une seule apparence partout (page, panneaux, tableaux, tiroirs, menus) :
   piste transparente, pouce neutre arrondi (6 px visibles, 8 px au survol), couleur de l'accent au
   survol et à l'appui. Souris / pavé tactile seulement : sur écran tactile, les barres natives
   superposées (fines, masquées au repos, sans place réservée) sont conservées et seulement
   neutralisées. WebKit / Blink : pseudo-éléments ; Chrome les ignore dès qu'un élément porte
   scrollbar-color / scrollbar-width, d'où la remise à « auto » (les barres aux couleurs des pages
   disparaissent sans retoucher les pages). Firefox : couleurs + finesse (pas d'état de survol).
   Barre masquée volontairement (bandeau d'onglets défilant) : classe .hub-scrollbar-none. */
@media (hover: hover) and (pointer: fine) {
  @supports selector(::-webkit-scrollbar) {
    html, html *:not(.hub-scrollbar-none, .hub-tabs, .hub-doc-nav > ul, .hub-doc-nav > ol) { scrollbar-color: auto !important; scrollbar-width: auto !important; }
    ::-webkit-scrollbar { width: var(--hub-scrollbar-size) !important; height: var(--hub-scrollbar-size) !important; background: transparent !important; }
    ::-webkit-scrollbar-track, ::-webkit-scrollbar-track-piece, ::-webkit-scrollbar-corner { background: transparent !important; border: 0 !important; box-shadow: none !important; }
    ::-webkit-scrollbar-thumb {
      background: var(--hub-scrollbar-thumb) padding-box !important;
      border: 3px solid transparent !important; border-radius: 999px !important; box-shadow: none !important; min-height: 40px; min-width: 40px;
    }
    ::-webkit-scrollbar-thumb:hover { background-color: var(--hub-scrollbar-thumb-hover) !important; border-width: 2px !important; }
    ::-webkit-scrollbar-thumb:active { background-color: var(--hub-scrollbar-thumb-active) !important; border-width: 2px !important; }
    ::-webkit-scrollbar-button { display: none !important; width: 0 !important; height: 0 !important; }
    .hub-scrollbar-none::-webkit-scrollbar, .hub-tabs::-webkit-scrollbar, .hub-doc-nav > :is(ul, ol)::-webkit-scrollbar { display: none !important; width: 0 !important; height: 0 !important; }
  }
  @supports not selector(::-webkit-scrollbar) {
    html, html *:not(.hub-scrollbar-none, .hub-tabs, .hub-doc-nav > ul, .hub-doc-nav > ol) { scrollbar-color: var(--hub-scrollbar-thumb) transparent !important; scrollbar-width: thin !important; }
  }
}
@media (hover: none), (pointer: coarse) {
  /* Tactile : couleurs des barres historiques neutralisées, sans en changer la taille. */
  html, html *:not(.hub-scrollbar-none, .hub-tabs, .hub-doc-nav > ul, .hub-doc-nav > ol) { scrollbar-color: auto !important; }
  ::-webkit-scrollbar-thumb { background: var(--hub-scrollbar-thumb) !important; border-radius: 999px !important; box-shadow: none !important; }
  ::-webkit-scrollbar-track, ::-webkit-scrollbar-corner { background: transparent !important; box-shadow: none !important; }
}
.hub-scrollbar-none { scrollbar-width: none !important; }
.hub-scrollbar-none::-webkit-scrollbar { display: none !important; }
::selection { background: var(--hub-selection-bg) !important; color: var(--hub-selection-fg) !important; text-shadow: none !important; }
:root { accent-color: var(--hub-brand); }
:where(input, textarea, [contenteditable="true"], [contenteditable=""]) { caret-color: var(--hub-caret); }
:where(input, textarea)::placeholder { color: var(--hub-text-3); opacity: 1; }
:where(button, input, select, textarea, [role="button"]):disabled, :where([aria-disabled="true"]) { cursor: not-allowed; }
:where(button, [role="button"], [role="tab"], [role="option"], summary, label[for], select, a[href]) { cursor: pointer; touch-action: manipulation; }
/* Autofill Chrome / Safari : fond et texte du thème au lieu du jaune / bleu clair */
:where(input, textarea, select):-webkit-autofill,
:where(input, textarea, select):-webkit-autofill:hover,
:where(input, textarea, select):-webkit-autofill:focus {
  -webkit-text-fill-color: var(--hub-text-1);
  caret-color: var(--hub-caret);
  -webkit-box-shadow: 0 0 0 1000px var(--hub-surface-2) inset;
  box-shadow: 0 0 0 1000px var(--hub-surface-2) inset;
  transition: background-color 600000s 0s, color 600000s 0s;
}
/* Focus : un seul anneau, jamais supprimé (les champs de saisie gardent bordure + halo). Les conteneurs
   focalisés par script seulement (tabindex="-1" : contenu après le lien d'évitement, panneau d'onglet,
   titre) n'en ont pas ; un contrôle en tabindex="-1" (onglets à focus itinérant) le garde.
   Décalage réglable sans lutte de spécificité : --hub-focus-offset (2 px par défaut), hérité. Les bandeaux
   défilants (onglets, sommaires, barres masquées) le passent à -3 px : l'anneau est dessiné À L'INTÉRIEUR
   et n'est plus rogné par le défilement (règle globale de spécificité élevée, qu'une page ne peut pas
   écraser par mégarde ; elle règle seulement la variable sur l'élément ou un ancêtre). */
:focus-visible:not(input, textarea, select, [contenteditable], :is(main, section, article, h1, h2, h3, h4, dialog, [role="main"], [role="tabpanel"], [role="region"], [role="document"])[tabindex="-1"]) { outline: 2px solid var(--hub-focus) !important; outline-offset: var(--hub-focus-offset, 2px) !important; }
:where(.hub-tabs, .hub-tab, .hub-scrollbar-none, .hub-doc-nav, .hub-viewbar) { --hub-focus-offset: -3px; }
:where(input, textarea, select, [contenteditable]):focus-visible { outline: 2px solid var(--hub-focus); outline-offset: 1px; }
/* Ancres : jamais masquées sous la barre collante (0 sur les pages non migrées : inchangées) */
:where([id]) { scroll-margin-top: var(--hub-anchor-offset); }
@media (prefers-reduced-motion: no-preference) { html[data-hub-shell="complete"]:focus-within { scroll-behavior: smooth; } }
/* Chiffres : sélectionnables et tabulaires dans les données */
:where(table, .hub-num, .hub-kpi__value, .hub-table) { font-variant-numeric: tabular-nums; }
:where(.hub-kpi__value, .hub-num, td) { -webkit-user-select: text; user-select: text; }

/* ---------- 4b. Base (pages migrées : <html class="hub">) ---------- */
html.hub { background: var(--hub-bg); -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }
html.hub body {
  margin: 0;
  background: transparent;        /* le fond est porté par <html> : le grain (z-index -1) reste visible */
  color: var(--hub-text-1);
  font-family: var(--hub-font-sans);
  font-size: var(--hub-fs-md);
  line-height: var(--hub-lh-md);
  font-feature-settings: "cv05" 1, "cv08" 1, "calt" 1;   /* l minuscule à crochet, I à empattements : Il1 lisibles */
  font-optical-sizing: auto;
  font-kerning: normal;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  overflow-x: clip;               /* jamais « hidden » : casserait position: sticky */
}
/* Grain très léger (profondeur, évite les aplats « plastique ») */
html.hub body::before {
  content: ""; position: fixed; inset: 0; z-index: -1; pointer-events: none;
  background-image: var(--hub-grain); background-size: 160px 160px; opacity: .028; mix-blend-mode: overlay;
}
:where(html.hub) :where(h1, h2, h3, .hub-page-title, .hub-h1, .hub-h2, .hub-card__title, .hub-empty__title, .hub-mcard__title) { text-wrap: balance; }
:where(html.hub) :where(p, li, .hub-page-subtitle, .hub-card__body, .hub-empty__text, .hub-alert__text, .hub-mcard__desc) { text-wrap: pretty; }
.hub-prose { font-size: var(--hub-fs-lg); line-height: 1.65; color: var(--hub-text-2); max-width: 70ch; hyphens: auto; -webkit-hyphens: auto; hyphenate-limit-chars: 7 3 3; }
.hub-prose a { color: var(--hub-brand-text); text-underline-offset: 3px; }
.hub-prose a:visited { color: #d79bc4; }
:where(html.hub) :focus { outline: none; }
:where(html.hub) a { color: inherit; }
html.hub [hidden] { display: none !important; }
:where(html.hub) :where(h1, h2, h3, h4, p, figure, blockquote, dl, dd) { margin: 0; }
:where(html.hub) :where(button, input, select, textarea) { font: inherit; color: inherit; }
:where(html.hub) :where(img, svg, video, canvas) { max-width: 100%; }

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

/* ---------- 5. Mise en page ---------- */
.hub-container { width: 100%; max-width: var(--hub-container); margin-inline: auto; padding-inline: var(--hub-gutter); box-sizing: border-box; }
.hub-container--narrow { max-width: var(--hub-container-narrow); }
.hub-container--text { max-width: calc(var(--hub-container-text) + 2 * var(--hub-gutter)); }
.hub-main { display: block; padding-block: var(--hub-space-6) var(--hub-space-16); }
.hub-stack { display: flex; flex-direction: column; gap: var(--hub-gap, var(--hub-space-4)); }
.hub-cluster { display: flex; flex-wrap: wrap; align-items: center; gap: var(--hub-gap, var(--hub-space-2)); }
.hub-grid { display: grid; gap: var(--hub-gap, var(--hub-space-3)); grid-template-columns: repeat(auto-fill, minmax(min(var(--hub-grid-min, 280px), 100%), 1fr)); }
.hub-spacer { flex: 1 1 auto; }
.hub-divider { height: 1px; border: 0; margin: var(--hub-space-4) 0; background: var(--hub-border-subtle); }
.hub-sr-only { position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
.hub-num { font-variant-numeric: tabular-nums; font-feature-settings: "tnum"; }
.hub-mono { font-family: var(--hub-font-mono); font-size: max(12px, .92em); }
.hub-text-2 { color: var(--hub-text-2); }
.hub-text-3 { color: var(--hub-text-3); }
.hub-truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
@media (max-width: 767.98px) { .hub-hide-mobile { display: none !important; } }
@media (min-width: 768px) { .hub-only-mobile { display: none !important; } }

/* ---------- 6. Typographie ---------- */
.hub-eyebrow {
  display: inline-flex; align-items: center; gap: var(--hub-space-2);
  font-size: var(--hub-fs-xs); line-height: var(--hub-lh-xs); font-weight: var(--hub-fw-medium);
  color: var(--hub-text-3);
}
.hub-eyebrow::before { content: ""; width: 6px; height: 6px; border-radius: 2px; background: var(--hub-accent); }
.hub-h1 { font-size: var(--hub-fs-3xl); line-height: var(--hub-lh-3xl); font-weight: var(--hub-fw-semibold); letter-spacing: var(--hub-tracking-tight); color: var(--hub-text-1); }
.hub-h2 { font-size: var(--hub-fs-xl); line-height: var(--hub-lh-xl); font-weight: var(--hub-fw-semibold); letter-spacing: var(--hub-tracking-snug); color: var(--hub-text-1); }
.hub-h3 { font-size: var(--hub-fs-md); line-height: var(--hub-lh-md); font-weight: var(--hub-fw-semibold); color: var(--hub-text-1); }
.hub-body { font-size: var(--hub-fs-md); line-height: var(--hub-lh-md); color: var(--hub-text-2); }
.hub-small { font-size: var(--hub-fs-xs); line-height: var(--hub-lh-xs); color: var(--hub-text-3); }
.hub-link { color: var(--hub-brand-text); text-decoration: underline; text-decoration-color: color-mix(in srgb, var(--hub-brand-text) 40%, transparent); text-underline-offset: 3px; }
.hub-link:hover { text-decoration-color: currentColor; }
.hub-link:visited { color: #d79bc4; }
.hub-kbd {
  display: inline-flex; align-items: center; justify-content: center; min-width: 20px; height: 20px; padding: 0 5px;
  border-radius: 5px; border: 1px solid var(--hub-border-strong); border-bottom-width: 2px; background: var(--hub-surface-2);
  font: 500 var(--hub-fs-xs)/1 var(--hub-font-sans); color: var(--hub-text-2); box-sizing: border-box;
}

/* ---------- 7. En-tête de page standard ---------- */
.hub-page-header {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-areas: "main actions" "meta meta" "tabs tabs";
  gap: var(--hub-space-2) var(--hub-space-6);
  align-items: end;
  padding-block: var(--hub-space-8) var(--hub-space-6);
}
.hub-page-header__main { grid-area: main; min-width: 0; display: flex; flex-direction: column; gap: var(--hub-space-2); }
.hub-page-header__title-row { display: flex; align-items: center; gap: var(--hub-space-3); min-width: 0; }
.hub-page-header__logo { height: 24px; width: auto; flex: none; display: block; }
.hub-page-title { margin: 0; font-size: var(--hub-fs-3xl); line-height: var(--hub-lh-3xl); font-weight: var(--hub-fw-semibold); letter-spacing: var(--hub-tracking-tight); color: var(--hub-text-1); }
.hub-page-subtitle { margin: 0; font-size: var(--hub-fs-md); line-height: var(--hub-lh-md); color: var(--hub-text-2); max-width: 72ch; }
.hub-page-header__actions { grid-area: actions; display: flex; flex-wrap: wrap; gap: var(--hub-space-2); justify-content: flex-end; }
.hub-page-header__meta { grid-area: meta; display: flex; flex-wrap: wrap; gap: var(--hub-space-2) var(--hub-space-4); align-items: center; }
.hub-page-header__tabs { grid-area: tabs; margin-top: var(--hub-space-4); }
.hub-page-header--compact { padding-block: var(--hub-space-5) 0; gap: var(--hub-space-1) var(--hub-space-4); }
.hub-page-header--compact .hub-page-title { font-size: var(--hub-fs-xl); line-height: var(--hub-lh-xl); letter-spacing: var(--hub-tracking-snug); }
.hub-page-header--compact .hub-page-header__tabs { margin-top: var(--hub-space-3); }
@media (max-width: 767.98px) {
  .hub-page-header { grid-template-columns: minmax(0, 1fr); grid-template-areas: "main" "actions" "meta" "tabs"; padding-block: var(--hub-space-6) var(--hub-space-4); }
  .hub-page-header__actions { justify-content: flex-start; }
  .hub-page-title { font-size: var(--hub-fs-2xl); line-height: var(--hub-lh-2xl); }
}
.hub-meta { display: inline-flex; align-items: center; gap: var(--hub-space-1-5); font-size: var(--hub-fs-xs); line-height: var(--hub-lh-xs); color: var(--hub-text-3); }
.hub-meta b, .hub-meta strong { color: var(--hub-text-2); font-weight: var(--hub-fw-medium); }
.hub-status-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--hub-text-3); flex: none; }
.hub-status-dot--live { background: var(--hub-success); box-shadow: 0 0 0 3px var(--hub-success-soft); }
.hub-status-dot--stale { background: var(--hub-warning); box-shadow: 0 0 0 3px var(--hub-warning-soft); }
.hub-status-dot--error { background: var(--hub-danger); box-shadow: 0 0 0 3px var(--hub-danger-soft); }

/* Barre d'outils (filtres d'une vue) */
.hub-toolbar {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--hub-space-2);
  padding: var(--hub-space-3) 0;
}
.hub-toolbar--sticky {
  position: sticky; top: var(--hub-sticky-top); z-index: var(--hub-z-sticky);
  background: color-mix(in srgb, var(--hub-bg) 88%, transparent);
  backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--hub-border-subtle);
}
.hub-toolbar__count { margin-left: auto; font-size: var(--hub-fs-xs); color: var(--hub-text-3); font-variant-numeric: tabular-nums; white-space: nowrap; }
.hub-toolbar__sep { width: 1px; height: 20px; background: var(--hub-border); flex: none; }

/* Section */
.hub-section { margin-top: var(--hub-space-10); }
.hub-section:first-child { margin-top: 0; }
.hub-section__header { display: flex; align-items: baseline; gap: var(--hub-space-3); margin-bottom: var(--hub-space-3); }
.hub-section__title { margin: 0; font-size: var(--hub-fs-sm); line-height: var(--hub-lh-sm); font-weight: var(--hub-fw-semibold); color: var(--hub-text-2); letter-spacing: 0; }
.hub-section__count { font-size: var(--hub-fs-xs); color: var(--hub-text-3); font-variant-numeric: tabular-nums; }
.hub-section__action { margin-left: auto; }

/* ---------- 8. Boutons ---------- */
.hub-btn {
  --_h: 32px;
  display: inline-flex; align-items: center; justify-content: center; gap: var(--hub-space-1-5);
  height: var(--_h); min-width: var(--_h); padding: 0 var(--hub-space-3); box-sizing: border-box;
  border-radius: var(--hub-radius-md); border: 1px solid var(--hub-border); background: var(--hub-surface-2);
  color: var(--hub-text-1); font: var(--hub-fw-medium) var(--hub-fs-sm)/1 var(--hub-font-sans); letter-spacing: 0;
  text-decoration: none; white-space: nowrap; cursor: pointer; user-select: none;
  box-shadow: var(--hub-highlight);
  transition: background-color var(--hub-dur-1) ease, border-color var(--hub-dur-1) ease, color var(--hub-dur-1) ease, box-shadow var(--hub-dur-1) ease;
}
.hub-btn:hover { background: var(--hub-surface-3); border-color: var(--hub-border-strong); }
.hub-btn:active { transform: scale(.98); transition-duration: 60ms; }
/* focus : règle globale §4a */
.hub-btn svg { width: 16px; height: 16px; flex: none; }
.hub-btn--primary { background: var(--hub-brand); border-color: transparent; color: var(--hub-on-brand); box-shadow: inset 0 1px 0 rgba(255, 255, 255, .14), 0 1px 2px rgba(0, 0, 0, .3); }
.hub-btn--primary:hover { background: var(--hub-brand-hover); border-color: transparent; }
.hub-btn--primary:active { background: var(--hub-brand-active); }
.hub-btn--ghost { background: transparent; border-color: transparent; color: var(--hub-text-2); box-shadow: none; }
.hub-btn--ghost:hover { background: var(--hub-surface-hover); color: var(--hub-text-1); border-color: transparent; }
.hub-btn--danger { background: var(--hub-danger-soft); border-color: var(--hub-danger-border); color: var(--hub-danger); box-shadow: none; }
.hub-btn--danger:hover { background: rgba(255, 107, 107, .2); border-color: var(--hub-danger); }
.hub-btn--accent { background: var(--hub-accent-soft); border-color: var(--hub-accent-border); color: var(--hub-accent-text); box-shadow: none; }
.hub-btn--accent:hover { background: color-mix(in srgb, var(--hub-accent) 24%, transparent); }
.hub-btn--link { height: auto; min-width: 0; padding: 0; border: 0; background: none; box-shadow: none; color: var(--hub-brand-text); }
.hub-btn--link:hover { background: none; text-decoration: underline; text-underline-offset: 3px; }
.hub-btn--sm { --_h: 28px; padding: 0 var(--hub-space-2); font-size: var(--hub-fs-xs); border-radius: var(--hub-radius-sm); }
.hub-btn--sm svg { width: 14px; height: 14px; }
.hub-btn--lg { --_h: 40px; padding: 0 var(--hub-space-4); font-size: var(--hub-fs-md); }
.hub-btn--icon { padding: 0; width: var(--_h); }
.hub-btn:disabled, .hub-btn[aria-disabled="true"] { opacity: .45; cursor: not-allowed; transform: none; }
.hub-btn[aria-busy="true"] { position: relative; color: transparent !important; pointer-events: none; }
.hub-btn[aria-busy="true"]::after {
  content: ""; position: absolute; inset: 0; margin: auto; width: 14px; height: 14px; border-radius: 50%;
  border: 2px solid rgba(255, 255, 255, .35); border-top-color: #fff; animation: hub-spin .7s linear infinite;
}
.hub-btn-group { display: inline-flex; }
.hub-btn-group > .hub-btn:not(:first-child) { border-top-left-radius: 0; border-bottom-left-radius: 0; margin-left: -1px; }
.hub-btn-group > .hub-btn:not(:last-child) { border-top-right-radius: 0; border-bottom-right-radius: 0; }

/* ---------- 9. Champs ---------- */
.hub-field { display: flex; flex-direction: column; gap: var(--hub-space-1-5); min-width: 0; }
.hub-label { font-size: var(--hub-fs-xs); line-height: var(--hub-lh-xs); font-weight: var(--hub-fw-medium); color: var(--hub-text-2); }
.hub-hint { font-size: var(--hub-fs-xs); line-height: var(--hub-lh-xs); color: var(--hub-text-3); }
.hub-error-text { font-size: var(--hub-fs-xs); line-height: var(--hub-lh-xs); color: var(--hub-danger); }
.hub-input, .hub-select, .hub-textarea {
  --_h: 32px;
  box-sizing: border-box; height: var(--_h); min-width: 0; width: 100%;
  padding: 0 var(--hub-space-3); border-radius: var(--hub-radius-md);
  border: 1px solid var(--hub-border-input); background: var(--hub-bg-subtle); color: var(--hub-text-1);
  font: var(--hub-fw-regular) var(--hub-fs-sm)/1.2 var(--hub-font-sans);
  transition: border-color var(--hub-dur-1) ease, box-shadow var(--hub-dur-1) ease, background-color var(--hub-dur-1) ease;
}
.hub-input::placeholder, .hub-textarea::placeholder { color: var(--hub-text-3); opacity: 1; }
.hub-input:hover, .hub-select:hover, .hub-textarea:hover { border-color: #7d7994; }
.hub-input:focus, .hub-select:focus, .hub-textarea:focus { outline: none; border-color: var(--hub-brand-text); box-shadow: 0 0 0 3px var(--hub-brand-soft-2); }
.hub-input[aria-invalid="true"], .hub-select[aria-invalid="true"] { border-color: var(--hub-danger); }
.hub-input:disabled, .hub-select:disabled { opacity: .5; cursor: not-allowed; }
.hub-textarea { height: auto; min-height: 88px; padding: var(--hub-space-2) var(--hub-space-3); line-height: var(--hub-lh-sm); resize: vertical; }
.hub-select {
  appearance: none; -webkit-appearance: none; padding-right: 30px; cursor: pointer; width: auto;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%238e8aa3' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 8px center; background-size: 16px;
}
.hub-select option { background: var(--hub-surface-3); color: var(--hub-text-1); }
.hub-input--sm, .hub-select--sm { --_h: 28px; font-size: var(--hub-fs-xs); }
/* Tailles au doigt (44 px) : section 22 bis, APRÈS les composants (à spécificité égale, la dernière règle gagne). */

.hub-search { position: relative; display: flex; align-items: center; min-width: 0; }
.hub-search > svg { position: absolute; left: 10px; width: 16px; height: 16px; color: var(--hub-text-3); pointer-events: none; }
.hub-search > .hub-input { padding-left: 32px; padding-right: 36px; }
.hub-search > .hub-kbd { position: absolute; right: 6px; pointer-events: none; }
.hub-search > .hub-input:not(:placeholder-shown) ~ .hub-kbd { display: none; }

.hub-check { display: inline-flex; align-items: center; gap: var(--hub-space-2); font-size: var(--hub-fs-sm); color: var(--hub-text-1); cursor: pointer; }
.hub-check input { width: 16px; height: 16px; margin: 0; accent-color: var(--hub-brand); cursor: pointer; }
.hub-switch { appearance: none; -webkit-appearance: none; position: relative; width: 32px; height: 18px; margin: 0; border-radius: 999px; background: #3a3849; cursor: pointer; transition: background-color var(--hub-dur-2) ease; flex: none; }
.hub-switch::after { content: ""; position: absolute; top: 2px; left: 2px; width: 14px; height: 14px; border-radius: 50%; background: #fff; box-shadow: 0 1px 2px rgba(0, 0, 0, .4); transition: transform var(--hub-dur-2) var(--hub-ease-out); }
.hub-switch:checked { background: var(--hub-brand); }
.hub-switch:checked::after { transform: translateX(14px); }
/* focus : règle globale §4a */
.hub-range { -webkit-appearance: none; appearance: none; width: 96px; height: 20px; background: transparent; cursor: pointer; margin: 0; }
.hub-range::-webkit-slider-runnable-track { height: 4px; border-radius: 4px; background: #34324a; }
.hub-range::-moz-range-track { height: 4px; border-radius: 4px; background: #34324a; }
.hub-range::-webkit-slider-thumb { -webkit-appearance: none; width: 14px; height: 14px; margin-top: -5px; border-radius: 50%; background: var(--hub-accent-text); border: 2px solid var(--hub-bg); box-shadow: 0 0 0 1px var(--hub-accent-text); }
.hub-range::-moz-range-thumb { width: 12px; height: 12px; border-radius: 50%; background: var(--hub-accent-text); border: 2px solid var(--hub-bg); }
.hub-range:focus-visible { outline: none; }
.hub-range:focus-visible::-webkit-slider-thumb { box-shadow: var(--hub-focus-ring); }

/* Contrôle segmenté */
.hub-segmented { display: inline-flex; padding: 2px; gap: 2px; border-radius: var(--hub-radius-md); background: var(--hub-bg-subtle); border: 1px solid var(--hub-border); }
.hub-segmented > button {
  height: 26px; padding: 0 var(--hub-space-3); border: 0; border-radius: var(--hub-radius-sm); background: transparent;
  color: var(--hub-text-2); font: var(--hub-fw-medium) var(--hub-fs-xs)/1 var(--hub-font-sans); cursor: pointer; white-space: nowrap;
}
.hub-segmented > button:hover { color: var(--hub-text-1); }
.hub-segmented > button[aria-pressed="true"], .hub-segmented > button[aria-checked="true"] { background: var(--hub-surface-3); color: var(--hub-text-1); box-shadow: var(--hub-shadow-1), var(--hub-highlight); }
/* focus : règle globale §4a */

/* ---------- 10. Onglets ---------- */
.hub-tabs {
  display: flex; gap: var(--hub-space-1); overflow-x: auto; overscroll-behavior-x: contain; scrollbar-width: none;
  border-bottom: 1px solid var(--hub-border-subtle);
  -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 24px), transparent);
          mask-image: linear-gradient(90deg, #000 calc(100% - 24px), transparent);
}
.hub-tabs::-webkit-scrollbar { display: none; }
.hub-tabs[data-scroll-end] { -webkit-mask-image: none; mask-image: none; }
.hub-tab {
  position: relative; flex: none; display: inline-flex; align-items: center; gap: var(--hub-space-1-5);
  height: 40px; padding: 0 var(--hub-space-3); border: 0; background: none; cursor: pointer;
  color: var(--hub-text-3); font: var(--hub-fw-medium) var(--hub-fs-sm)/1 var(--hub-font-sans); white-space: nowrap; text-decoration: none;
  border-radius: var(--hub-radius-sm) var(--hub-radius-sm) 0 0;
  transition: color var(--hub-dur-1) ease;
}
.hub-tab:hover { color: var(--hub-text-1); }
.hub-tab svg { width: 15px; height: 15px; }
.hub-tab[aria-selected="true"], .hub-tab[aria-current="page"], .hub-tab.is-active { color: var(--hub-text-1); }
.hub-tab[aria-selected="true"]::after, .hub-tab[aria-current="page"]::after, .hub-tab.is-active::after {
  content: ""; position: absolute; left: var(--hub-space-3); right: var(--hub-space-3); bottom: -1px; height: 2px; border-radius: 2px 2px 0 0; background: var(--hub-accent);
}
.hub-tab:focus-visible { border-radius: 8px; }   /* anneau intérieur : --hub-focus-offset (§4a) */
.hub-tab__count { min-width: 18px; height: 18px; padding: 0 5px; border-radius: 999px; background: var(--hub-surface-3); color: var(--hub-text-2); font-size: var(--hub-fs-xs); line-height: 18px; text-align: center; font-variant-numeric: tabular-nums; box-sizing: border-box; }
.hub-tab[aria-selected="true"] .hub-tab__count { background: var(--hub-accent-soft); color: var(--hub-accent-text); }
.hub-tab__count:empty { display: none; }
.hub-tab-panel:focus-visible { outline: none; }

/* Barre des vues collante (onglets d'une application de données, sous la coque) :
   <div class="hub-viewbar"><div class="hub-container"><div class="hub-tabs" role="tablist">…</div></div></div> */
.hub-viewbar {
  position: sticky; top: var(--hub-sticky-top); z-index: var(--hub-z-sticky);
  background: color-mix(in srgb, var(--hub-bg) 88%, transparent);
  -webkit-backdrop-filter: blur(12px) saturate(140%); backdrop-filter: blur(12px) saturate(140%);
  box-shadow: inset 0 -1px 0 var(--hub-border-subtle);
}
.hub-viewbar .hub-tabs { border-bottom: 0; min-height: var(--hub-viewbar-h); align-items: flex-end; }

/* Sommaire de document collant (documents de marque : Brand bible, Projet complet…) :
   <nav class="hub-doc-nav" aria-label="Sommaire"><ul><li><a href="#…">…</a></li></ul></nav>
   Liens de 44 px, bandeau défilant à fondu, section courante = aria-current (posé par la page) + filet
   d'accent. Couleurs et typographie de la marque : la page les redéfinit (structure seule ici). */
.hub-doc-nav {
  position: sticky; top: var(--hub-sticky-top); z-index: var(--hub-z-sticky);
  display: flex; align-items: center; gap: var(--hub-space-4); min-height: var(--hub-viewbar-h); box-sizing: border-box;
  background: color-mix(in srgb, var(--hub-bg) 88%, transparent);
  -webkit-backdrop-filter: blur(16px) saturate(140%); backdrop-filter: blur(16px) saturate(140%);
  box-shadow: inset 0 -1px 0 var(--hub-border-subtle);
}
.hub-doc-nav > :is(ul, ol) {
  display: flex; align-items: center; gap: var(--hub-space-1); min-width: 0; margin: 0; padding: 0; list-style: none;
  overflow-x: auto; overscroll-behavior-x: contain; scrollbar-width: none;
}
.hub-doc-nav li { flex: none; }
.hub-doc-nav a {
  position: relative; display: inline-flex; align-items: center; min-height: 44px; padding: 0 var(--hub-space-3); box-sizing: border-box;
  border-radius: var(--hub-radius-sm) var(--hub-radius-sm) 0 0; color: var(--hub-text-3); text-decoration: none; white-space: nowrap;
  transition: color var(--hub-dur-1) ease;
}
.hub-doc-nav a:hover { color: var(--hub-text-1); }
.hub-doc-nav a:is([aria-current="true"], [aria-current="location"], [aria-current="page"]) { color: var(--hub-text-1); box-shadow: inset 0 -2px 0 var(--hub-accent); }
@media (max-width: 1279.98px) {
  .hub-doc-nav > :is(ul, ol) { -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 24px), transparent); mask-image: linear-gradient(90deg, #000 calc(100% - 24px), transparent); }
}

/* Repliable (pondérations, réglages secondaires) — ouvert sur ordinateur, replié sur mobile ; état initial
   décidé en CSS (aucun décalage au chargement). Conteneur [data-hub-collapsible] ; bouton [data-hub-collapse]
   à l'intérieur (aria-expanded tenu par /hub/shell.js, qui bascule data-collapsed ≥ 768 px, data-expanded
   < 768 px). Repliés : les enfants directs qui ne sont pas (et ne contiennent pas) le bouton, sauf
   [data-hub-keep]. Chevron : <span class="hub-chev" aria-hidden="true"></span> dans le bouton. */
.hub-chev {
  display: inline-block; flex: none; width: 7px; height: 7px; margin: 0 2px; box-sizing: border-box;
  border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor; color: var(--hub-text-3);
  transform: translateY(-2px) rotate(45deg); transition: transform var(--hub-dur-2) var(--hub-ease-out);
}
@media (min-width: 768px) {
  [data-hub-collapsible][data-collapsed] > :not([data-hub-collapse], :has([data-hub-collapse]), [data-hub-keep]) { display: none !important; }
  [data-hub-collapsible][data-collapsed] .hub-chev { transform: rotate(-45deg); }
}
@media (max-width: 767.98px) {
  [data-hub-collapsible]:not([data-expanded]) > :not([data-hub-collapse], :has([data-hub-collapse]), [data-hub-keep]) { display: none !important; }
  [data-hub-collapsible]:not([data-expanded]) .hub-chev { transform: rotate(-45deg); }
}

/* ---------- 11. Puces (filtres) et badges ---------- */
.hub-chip {
  display: inline-flex; align-items: center; gap: var(--hub-space-1-5); height: 28px; padding: 0 var(--hub-space-3); box-sizing: border-box;
  border-radius: var(--hub-radius-full); border: 1px solid var(--hub-border); background: transparent;
  color: var(--hub-text-2); font: var(--hub-fw-medium) var(--hub-fs-xs)/1 var(--hub-font-sans); cursor: pointer; white-space: nowrap;
  transition: background-color var(--hub-dur-1) ease, border-color var(--hub-dur-1) ease, color var(--hub-dur-1) ease;
}
.hub-chip:hover { border-color: var(--hub-border-strong); color: var(--hub-text-1); background: var(--hub-surface-hover); }
.hub-chip[aria-pressed="true"], .hub-chip.is-active { background: var(--hub-accent-soft); border-color: var(--hub-accent-border); color: var(--hub-text-1); }
/* focus : règle globale §4a */
.hub-chip__count { color: var(--hub-text-3); font-variant-numeric: tabular-nums; }
.hub-chip__dot { width: 8px; height: 8px; border-radius: 50%; background: var(--_dot, var(--hub-accent)); }
.hub-chip__remove { display: inline-flex; margin-right: -4px; color: var(--hub-text-3); }
.hub-chip__remove:hover { color: var(--hub-text-1); }

.hub-badge {
  display: inline-flex; align-items: center; gap: 5px; height: 20px; padding: 0 7px; box-sizing: border-box;
  border-radius: var(--hub-radius-sm); border: 1px solid transparent; vertical-align: middle;
  background: var(--hub-surface-3); color: var(--hub-text-2);
  font: var(--hub-fw-medium) var(--hub-fs-xs)/1 var(--hub-font-sans); white-space: nowrap; font-variant-numeric: tabular-nums;
}
.hub-badge--brand   { background: var(--hub-brand-soft);   color: var(--hub-brand-text); border-color: var(--hub-brand-border); }
.hub-badge--accent  { background: var(--hub-accent-soft);  color: var(--hub-accent-text); border-color: var(--hub-accent-border); }
.hub-badge--success { background: var(--hub-success-soft); color: var(--hub-success); border-color: var(--hub-success-border); }
.hub-badge--warning { background: var(--hub-warning-soft); color: var(--hub-warning); border-color: var(--hub-warning-border); }
.hub-badge--danger  { background: var(--hub-danger-soft);  color: var(--hub-danger);  border-color: var(--hub-danger-border); }
.hub-badge--info    { background: var(--hub-info-soft);    color: var(--hub-info);    border-color: var(--hub-info-border); }
.hub-badge--outline { background: transparent; border-color: var(--hub-border-strong); }
.hub-badge--dot::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
.hub-badge--pill { border-radius: var(--hub-radius-full); }
.hub-count { display: inline-flex; align-items: center; justify-content: center; min-width: 20px; height: 20px; padding: 0 6px; box-sizing: border-box; border-radius: 999px; background: var(--hub-brand); color: #fff; font: var(--hub-fw-semibold) var(--hub-fs-xs)/1 var(--hub-font-sans); font-variant-numeric: tabular-nums; }

/* ---------- 12. Cartes ---------- */
.hub-card {
  position: relative; display: flex; flex-direction: column; gap: var(--hub-space-3); min-width: 0;
  padding: var(--hub-space-5); border-radius: var(--hub-radius-lg);
  background: var(--hub-surface); border: 1px solid var(--hub-border-subtle); box-shadow: var(--hub-highlight);
}
.hub-card--flush { padding: 0; overflow: hidden; }
.hub-card--interactive { text-decoration: none; color: inherit; cursor: pointer; transition: background-color var(--hub-dur-2) ease, border-color var(--hub-dur-2) ease, transform var(--hub-dur-2) var(--hub-ease-out); }
.hub-card--interactive:hover { background: var(--hub-surface-2); border-color: var(--hub-border); }
/* focus : règle globale §4a */
.hub-card__header { display: flex; align-items: flex-start; gap: var(--hub-space-3); min-width: 0; }
.hub-card__title { margin: 0; font-size: var(--hub-fs-md); line-height: var(--hub-lh-md); font-weight: var(--hub-fw-semibold); color: var(--hub-text-1); }
.hub-card__subtitle { margin: 0; font-size: var(--hub-fs-xs); line-height: var(--hub-lh-xs); color: var(--hub-text-3); }
.hub-card__body { font-size: var(--hub-fs-sm); line-height: var(--hub-lh-sm); color: var(--hub-text-2); }
.hub-card__actions { margin-left: auto; display: flex; gap: var(--hub-space-1); }
.hub-card__footer { display: flex; align-items: center; gap: var(--hub-space-3); padding-top: var(--hub-space-3); margin-top: auto; border-top: 1px solid var(--hub-border-subtle); font-size: var(--hub-fs-xs); color: var(--hub-text-3); }
.hub-icon-tile {
  display: inline-flex; align-items: center; justify-content: center; flex: none;
  width: var(--_s, 36px); height: var(--_s, 36px); border-radius: var(--hub-radius-md);
  background: color-mix(in srgb, var(--hub-accent) 16%, transparent); color: var(--hub-accent-text);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--hub-accent-text) 22%, transparent);
}
.hub-icon-tile svg { width: 55%; height: 55%; }

/* Carte de module (accueil, index de module) — le lien EST la carte (crochet data-hub) */
.hub-mcard { position: relative; display: flex; min-width: 0; }
.hub-mcard__link {
  position: relative; flex: 1; display: grid; min-width: 0;
  grid-template-columns: auto minmax(0, 1fr); grid-template-rows: auto 1fr auto; column-gap: var(--hub-space-3); row-gap: var(--hub-space-3);
  padding: var(--hub-space-4) var(--hub-space-4) var(--hub-space-3); border-radius: var(--hub-radius-lg);
  background: var(--hub-surface); border: 1px solid var(--hub-border-subtle); box-shadow: var(--hub-highlight);
  color: inherit; text-decoration: none; overflow: hidden;
  transition: background-color var(--hub-dur-2) ease, border-color var(--hub-dur-2) ease;
}
.hub-mcard__link::before {
  content: ""; position: absolute; inset: 0 0 auto; height: 1px;
  background: linear-gradient(90deg, transparent, var(--hub-accent) 30%, var(--hub-accent) 50%, transparent 85%);
  opacity: 0; transition: opacity var(--hub-dur-2) ease;
}
.hub-mcard__link:hover { background: var(--hub-surface-2); border-color: var(--hub-border); box-shadow: var(--hub-elev-2); }
.hub-mcard__link:active { transform: scale(.995); }
.hub-mcard__link:hover::before { opacity: .9; }
/* focus : règle globale §4a */
.hub-mcard__icon { grid-row: 1 / span 2; --_s: 40px; }
.hub-mcard__head { display: flex; flex-wrap: wrap; align-items: center; gap: var(--hub-space-1) var(--hub-space-2); min-width: 0; padding-right: 28px; min-height: 22px; }  /* badge renvoyé à la ligne plutôt qu'un titre coupé */
.hub-mcard__title { font-size: var(--hub-fs-md); line-height: var(--hub-lh-md); font-weight: var(--hub-fw-semibold); color: var(--hub-text-1); letter-spacing: -.005em; }
.hub-mcard__desc {
  grid-column: 2; font-size: var(--hub-fs-sm); line-height: var(--hub-lh-sm); color: var(--hub-text-2); margin-top: -6px;
  display: -webkit-box; -webkit-line-clamp: var(--hub-mcard-lines, 2); line-clamp: var(--hub-mcard-lines, 2); -webkit-box-orient: vertical; overflow: hidden;
}
/* Description sur 3 lignes (index de module aux descriptions longues) : sur la carte ou sur la grille */
.hub-mcard--desc-3, .hub-mcards--desc-3 { --hub-mcard-lines: 3; }
.hub-mcard__meta {
  grid-column: 1 / -1; display: flex; align-items: center; flex-wrap: wrap; gap: var(--hub-space-1) var(--hub-space-4);
  padding-top: var(--hub-space-3); border-top: 1px solid var(--hub-border-subtle);
  font-size: var(--hub-fs-xs); line-height: var(--hub-lh-xs); color: var(--hub-text-3); font-variant-numeric: tabular-nums;
}
.hub-mcard__meta b { color: var(--hub-text-1); font-weight: var(--hub-fw-semibold); }
.hub-mcard__go { margin-left: auto; display: inline-flex; color: var(--hub-text-3); transition: transform var(--hub-dur-2) var(--hub-ease-out), color var(--hub-dur-2) ease; }
.hub-mcard__go svg { width: 16px; height: 16px; }
.hub-mcard__link:hover .hub-mcard__go { color: var(--hub-accent-text); transform: translateX(2px); }
.hub-mcard__pin {
  position: absolute; top: 10px; right: 10px; z-index: 1; display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; border-radius: var(--hub-radius-sm); border: 0; background: transparent; color: var(--hub-text-3);
  cursor: pointer; opacity: 0; transition: opacity var(--hub-dur-2) ease, color var(--hub-dur-1) ease, background-color var(--hub-dur-1) ease;
}
.hub-mcard__pin svg { width: 16px; height: 16px; }
.hub-mcard:hover .hub-mcard__pin, .hub-mcard__pin:focus-visible, .hub-mcard__pin[aria-pressed="true"] { opacity: 1; }
.hub-mcard__pin:hover { background: var(--hub-surface-hover); color: var(--hub-text-1); }
.hub-mcard__pin[aria-pressed="true"] { color: var(--hub-brand-text); }
.hub-mcard__pin[aria-pressed="true"] svg { fill: currentColor; }
/* focus : règle globale §4a */
@media (hover: none) { .hub-mcard__pin { opacity: 1; } }

/* Élément compact (récents, épinglés) */
.hub-quick {
  display: flex; align-items: center; gap: var(--hub-space-3); min-width: 0; height: 56px; padding: 0 var(--hub-space-3);
  border-radius: var(--hub-radius-md); background: var(--hub-surface); border: 1px solid var(--hub-border-subtle);
  color: inherit; text-decoration: none; transition: background-color var(--hub-dur-2) ease, border-color var(--hub-dur-2) ease;
}
.hub-quick:hover { background: var(--hub-surface-2); border-color: var(--hub-border); }
/* focus : règle globale §4a */
.hub-quick .hub-icon-tile { --_s: 32px; }
.hub-quick__text { display: flex; flex-direction: column; min-width: 0; gap: 2px; }
.hub-quick__title { font-size: var(--hub-fs-sm); line-height: var(--hub-lh-sm); font-weight: var(--hub-fw-medium); color: var(--hub-text-1); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hub-quick__meta { font-size: var(--hub-fs-xs); line-height: var(--hub-lh-xs); color: var(--hub-text-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ---------- 13. Tuiles KPI ---------- */
.hub-kpi-grid { display: grid; gap: var(--hub-space-3); grid-template-columns: repeat(auto-fit, minmax(min(176px, 100%), 1fr)); }
@media (max-width: 479.98px) { .hub-kpi-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.hub-kpi {
  position: relative; display: flex; flex-direction: column; gap: var(--hub-space-1); min-width: 0;
  padding: var(--hub-space-4); border-radius: var(--hub-radius-lg);
  background: var(--hub-surface); border: 1px solid var(--hub-border-subtle); box-shadow: var(--hub-highlight);
}
.hub-kpi__label { font-size: var(--hub-fs-xs); line-height: var(--hub-lh-xs); font-weight: var(--hub-fw-medium); color: var(--hub-text-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hub-kpi__value {
  font-size: var(--hub-fs-3xl); line-height: var(--hub-lh-3xl); font-weight: var(--hub-fw-semibold); letter-spacing: var(--hub-tracking-tight);
  color: var(--hub-text-1); font-variant-numeric: tabular-nums; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.hub-kpi__unit { font-size: var(--hub-fs-md); font-weight: var(--hub-fw-medium); color: var(--hub-text-3); margin-left: 2px; letter-spacing: 0; }
.hub-kpi__foot { display: flex; align-items: center; gap: var(--hub-space-2); flex-wrap: wrap; font-size: var(--hub-fs-xs); line-height: var(--hub-lh-xs); color: var(--hub-text-3); }
.hub-kpi--accent::before { content: ""; position: absolute; left: var(--hub-space-4); top: -1px; width: 24px; height: 2px; border-radius: 0 0 2px 2px; background: var(--hub-accent); }
.hub-kpi--hero .hub-kpi__value { font-size: var(--hub-fs-5xl); line-height: var(--hub-lh-5xl); }
.hub-kpi--compact { padding: var(--hub-space-3) var(--hub-space-4); }
.hub-kpi--compact .hub-kpi__value { font-size: var(--hub-fs-2xl); line-height: var(--hub-lh-2xl); }
.hub-delta { display: inline-flex; align-items: center; gap: 2px; font-weight: var(--hub-fw-medium); font-variant-numeric: tabular-nums; }
.hub-delta svg { width: 12px; height: 12px; }
.hub-delta--up { color: var(--hub-success); }
.hub-delta--down { color: var(--hub-danger); }
.hub-delta--flat { color: var(--hub-text-3); }
.hub-spark { display: block; width: 100%; height: 32px; margin-top: var(--hub-space-1); color: var(--hub-accent); }

/* ---------- 14. Tableaux ---------- */
.hub-table-wrap {
  position: relative; overflow: auto; max-width: 100%; overscroll-behavior-x: contain;
  border-radius: var(--hub-radius-lg); border: 1px solid var(--hub-border-subtle); background: var(--hub-surface);
  box-shadow: var(--hub-highlight);
}
.hub-table-wrap--fill { max-height: calc(100dvh - var(--hub-sticky-top) - 24px); }
.hub-scroll { overflow: auto; overscroll-behavior: contain; scrollbar-gutter: stable; }
.hub-table { width: 100%; border-collapse: separate; border-spacing: 0; font-size: var(--hub-fs-sm); line-height: var(--hub-lh-sm); color: var(--hub-text-1); }
.hub-table th {
  position: sticky; top: 0; z-index: 2; height: 36px; padding: 0 var(--hub-space-3); box-sizing: border-box;
  background: var(--hub-surface-2); border-bottom: 1px solid var(--hub-border);
  font-size: var(--hub-fs-xs); line-height: var(--hub-lh-xs); font-weight: var(--hub-fw-medium); color: var(--hub-text-3);
  text-align: left; white-space: nowrap; vertical-align: middle;
}
.hub-table td { padding: var(--hub-space-2) var(--hub-space-3); border-bottom: 1px solid var(--hub-border-subtle); vertical-align: middle; }
.hub-table tbody tr:last-child td { border-bottom: 0; }
.hub-table tbody tr { transition: background-color var(--hub-dur-1) ease; }
.hub-table tbody tr:nth-child(even) td { background: rgba(255, 255, 255, .014); }
.hub-table tbody tr:hover td { background: rgba(255, 255, 255, .04); }
.hub-table th, .hub-table td { font-variant-numeric: tabular-nums; }
.hub-table tbody tr[aria-selected="true"] td { background: var(--hub-brand-soft); }
.hub-table .hub-num, .hub-table th.hub-num { text-align: right; font-variant-numeric: tabular-nums; }
.hub-table td.hub-strong { font-weight: var(--hub-fw-medium); color: var(--hub-text-1); }
.hub-table td.hub-muted { color: var(--hub-text-3); }
.hub-table tfoot td { position: sticky; bottom: 0; background: var(--hub-surface-2); border-top: 1px solid var(--hub-border); border-bottom: 0; font-weight: var(--hub-fw-semibold); }
.hub-table--dense td { padding: 5px var(--hub-space-2-5, 10px); }
.hub-table--dense th { height: 32px; padding: 0 10px; }
.hub-table--sticky-first th:first-child, .hub-table--sticky-first td:first-child { position: sticky; left: 0; z-index: 1; background: var(--hub-surface); box-shadow: 1px 0 0 var(--hub-border-subtle); }
.hub-table--sticky-first th:first-child { z-index: 3; background: var(--hub-surface-2); }
.hub-table--sticky-first tbody tr:hover td:first-child { background: #191825; }
/* Tri = bouton dans le <th> (aria-sort sur le th). Le bouton garde la mise en page de l'en-tête (texte aligné
   par le th) ; sa zone de clic (::before) couvre la hauteur de l'en-tête : ≥ 24 px à la souris, 44 px au
   doigt (§22 bis). Flèche : jamais écrasée dans une colonne étroite, visible au survol / au focus et sur la
   colonne triée seulement (moins de bruit sur les tableaux larges) ; colonnes numériques (à droite) : flèche
   avant le libellé, qui reste aligné sur les chiffres. L'en-tête lui-même n'a pas de curseur main. */
.hub-th-sort {
  all: unset; box-sizing: border-box; position: relative; display: inline-flex; align-items: center; gap: 4px;
  max-width: 100%; min-height: 24px; vertical-align: middle; cursor: pointer; color: inherit; font: inherit; border-radius: 4px; white-space: nowrap;
}
.hub-th-sort::before { content: ""; position: absolute; inset: -6px -8px; }
.hub-th-sort:hover { color: var(--hub-text-1); }
/* focus : règle globale §4a */
.hub-th-sort svg { flex: none; width: 12px; height: 12px; opacity: 0; transition: opacity var(--hub-dur-1) ease; }
th:hover .hub-th-sort svg, .hub-th-sort:focus-visible svg { opacity: .55; }
th:has(> .hub-th-sort) { cursor: default; }
:is(th.hub-num, th[align="right"], th[style*="text-align:right"], th[style*="text-align: right"]) > .hub-th-sort { flex-direction: row-reverse; }
th[aria-sort="ascending"] .hub-th-sort, th[aria-sort="descending"] .hub-th-sort { color: var(--hub-text-1); }
th[aria-sort="ascending"] .hub-th-sort svg, th[aria-sort="descending"] .hub-th-sort svg { opacity: 1; color: var(--hub-accent-text); }
th[aria-sort="ascending"] .hub-th-sort svg { transform: rotate(180deg); }
@media (hover: none) { .hub-th-sort svg { opacity: .4; } }
/* Cellule cliquable (ouvre un détail) : bouton plein cadre DANS la cellule (sémantique de tableau conservée),
   aspect de lien discret. Posée par /hub/pont.js sur les cellules à onclick des scripts historiques. */
.hub-cell-btn {
  all: unset; box-sizing: border-box; display: block; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: inherit;
  cursor: pointer; border-radius: 4px; text-decoration: underline; text-decoration-color: var(--hub-border-strong); text-underline-offset: 3px;
}
.hub-cell-btn:hover { text-decoration-color: currentColor; }
/* État vide d'un tableau : <tr class="hub-empty-row"><td colspan="n"><div class="hub-empty hub-empty--compact">…
   Le bloc reste dans la partie visible d'un tableau large (collant à gauche). */
.hub-empty-row td { padding: 0 !important; background: none !important; border: 0 !important; }
.hub-empty-row:hover td { background: none !important; }
.hub-empty-row .hub-empty {
  position: sticky; left: var(--hub-space-4); box-sizing: border-box; margin: var(--hub-space-4);
  max-width: calc(100vw - 2 * var(--hub-gutter) - 2 * var(--hub-space-4)); border-radius: var(--hub-radius-md); white-space: normal;
}
.hub-cell-title { font-weight: var(--hub-fw-medium); color: var(--hub-text-1); }
.hub-cell-sub { display: block; font-size: var(--hub-fs-xs); color: var(--hub-text-3); }

/* Barre de valeur, score, progression */
.hub-bar { display: inline-flex; align-items: center; gap: var(--hub-space-2); min-width: 72px; font-variant-numeric: tabular-nums; }
.hub-bar__track { flex: 1; height: 4px; border-radius: 4px; background: rgba(255, 255, 255, .08); overflow: hidden; min-width: 40px; }
.hub-bar__fill { display: block; height: 100%; border-radius: 4px; background: var(--_c, var(--hub-accent)); }
.hub-bar__value { font-size: var(--hub-fs-xs); color: var(--hub-text-2); min-width: 2ch; text-align: right; }
.hub-score {
  display: inline-flex; align-items: center; justify-content: center; min-width: 32px; height: 22px; padding: 0 6px; box-sizing: border-box;
  border-radius: var(--hub-radius-sm); font: var(--hub-fw-semibold) var(--hub-fs-xs)/1 var(--hub-font-sans); font-variant-numeric: tabular-nums;
  background: var(--hub-surface-3); color: var(--hub-text-1);
}
.hub-score--high { background: var(--hub-success-soft); color: var(--hub-success); box-shadow: inset 0 0 0 1px var(--hub-success-border); }
.hub-score--mid  { background: var(--hub-warning-soft); color: var(--hub-warning); box-shadow: inset 0 0 0 1px var(--hub-warning-border); }
.hub-score--low  { background: var(--hub-danger-soft);  color: var(--hub-danger);  box-shadow: inset 0 0 0 1px var(--hub-danger-border); }
.hub-progress { height: 6px; border-radius: 999px; background: rgba(255, 255, 255, .08); overflow: hidden; }
.hub-progress > span { display: block; height: 100%; border-radius: inherit; background: var(--hub-accent); transition: width var(--hub-dur-4) var(--hub-ease-out); }

/* ---------- 15. Graphiques (conteneur ; le rendu reste celui de la page) ---------- */
.hub-chart { display: flex; flex-direction: column; gap: var(--hub-space-3); }
.hub-chart__header { display: flex; align-items: flex-start; gap: var(--hub-space-3); flex-wrap: wrap; }
.hub-chart__title { margin: 0; font-size: var(--hub-fs-md); line-height: var(--hub-lh-md); font-weight: var(--hub-fw-semibold); color: var(--hub-text-1); }
.hub-chart__note { font-size: var(--hub-fs-xs); color: var(--hub-text-3); }
.hub-chart__plot { position: relative; min-height: 160px; }
.hub-legend { display: flex; flex-wrap: wrap; gap: var(--hub-space-1) var(--hub-space-4); font-size: var(--hub-fs-xs); color: var(--hub-text-2); margin-left: auto; }
.hub-legend__item { display: inline-flex; align-items: center; gap: var(--hub-space-1-5); }
.hub-legend__swatch { width: 10px; height: 10px; border-radius: 3px; background: var(--_c, var(--hub-viz-1)); }

/* ---------- 16. Alertes ---------- */
.hub-alert {
  --_c: var(--hub-info); --_bg: var(--hub-info-soft); --_bd: var(--hub-info-border);
  display: flex; align-items: flex-start; gap: var(--hub-space-3); padding: var(--hub-space-3) var(--hub-space-4);
  border-radius: var(--hub-radius-md); background: var(--_bg); border: 1px solid var(--_bd); color: var(--hub-text-1);
  font-size: var(--hub-fs-sm); line-height: var(--hub-lh-sm);
}
.hub-alert > svg { width: 18px; height: 18px; flex: none; margin-top: 1px; color: var(--_c); }
.hub-alert__body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.hub-alert__title { font-weight: var(--hub-fw-semibold); }
.hub-alert__text { color: var(--hub-text-2); }
.hub-alert__actions { display: flex; gap: var(--hub-space-2); align-items: center; flex: none; align-self: center; }
.hub-alert--success { --_c: var(--hub-success); --_bg: var(--hub-success-soft); --_bd: var(--hub-success-border); }
.hub-alert--warning { --_c: var(--hub-warning); --_bg: var(--hub-warning-soft); --_bd: var(--hub-warning-border); }
.hub-alert--danger  { --_c: var(--hub-danger);  --_bg: var(--hub-danger-soft);  --_bd: var(--hub-danger-border); }
.hub-alert--brand   { --_c: var(--hub-brand-text); --_bg: var(--hub-brand-soft); --_bd: var(--hub-brand-border); }
@media (max-width: 599.98px) { .hub-alert { flex-wrap: wrap; } .hub-alert__actions { width: 100%; padding-left: 30px; } }

/* ---------- 17. Modales et tiroirs (<dialog>) ---------- */
dialog.hub-modal, dialog.hub-drawer {
  padding: 0; border: 1px solid var(--hub-border); color: var(--hub-text-1); background: var(--hub-surface-3);
  box-shadow: var(--hub-shadow-4); font-family: var(--hub-font-sans); max-height: calc(100dvh - 32px); overflow: hidden;
}
dialog.hub-modal { width: min(560px, calc(100vw - 32px)); border-radius: var(--hub-radius-xl); }
dialog.hub-modal, dialog.hub-drawer, .hub-popover { --hub-text-3: var(--hub-text-3-raised); --hub-border-input: #7d7994; /* 3,4:1 sur --hub-surface-3 */ }
dialog.hub-modal[open] { display: flex; flex-direction: column; animation: hub-pop-in var(--hub-dur-3) var(--hub-ease-out); }
dialog.hub-modal::backdrop, dialog.hub-drawer::backdrop { background: var(--hub-overlay); backdrop-filter: blur(2px); }
dialog.hub-drawer { margin: 0 0 0 auto; height: 100dvh; max-height: 100dvh; width: min(480px, 100vw); border-width: 0 0 0 1px; border-radius: 0; background: var(--hub-bg-subtle); }
dialog.hub-drawer[open] { display: flex; flex-direction: column; animation: hub-slide-in-right var(--hub-dur-3) var(--hub-ease-out); }
.hub-modal__header { display: flex; align-items: center; gap: var(--hub-space-3); padding: var(--hub-space-4) var(--hub-space-5); border-bottom: 1px solid var(--hub-border-subtle); }
.hub-modal__title { margin: 0; font-size: var(--hub-fs-lg); line-height: var(--hub-lh-lg); font-weight: var(--hub-fw-semibold); flex: 1; min-width: 0; }
.hub-modal__body { padding: var(--hub-space-5); overflow: auto; font-size: var(--hub-fs-sm); line-height: var(--hub-lh-sm); color: var(--hub-text-2); }
.hub-modal__footer { display: flex; justify-content: flex-end; gap: var(--hub-space-2); padding: var(--hub-space-3) var(--hub-space-5); border-top: 1px solid var(--hub-border-subtle); background: rgba(0, 0, 0, .12); }

/* ---------- 18. Info-bulles (CSS seul ; l'élément porte aussi aria-label ou aria-describedby) ---------- */
[data-hub-tooltip] { position: relative; }
[data-hub-tooltip]::after {
  content: attr(data-hub-tooltip); position: absolute; left: 50%; bottom: calc(100% + 8px); transform: translate(-50%, 4px);
  z-index: var(--hub-z-tooltip); padding: 6px 8px; border-radius: var(--hub-radius-sm); background: #f3f1f8; color: #15141f;
  font: var(--hub-fw-medium) var(--hub-fs-xs)/1.3 var(--hub-font-sans); white-space: nowrap; pointer-events: none;
  opacity: 0; transition: opacity var(--hub-dur-1) ease, transform var(--hub-dur-1) ease; box-shadow: var(--hub-shadow-2);
}
[data-hub-tooltip]:hover::after, [data-hub-tooltip]:focus-visible::after { opacity: 1; transform: translate(-50%, 0); transition-delay: 300ms; }
[data-hub-tooltip-pos="bottom"]::after { bottom: auto; top: calc(100% + 8px); }

/* ---------- 19. États : vide, chargement, erreur ---------- */
.hub-empty {
  display: flex; flex-direction: column; align-items: center; text-align: center; gap: var(--hub-space-3);
  padding: var(--hub-space-12) var(--hub-space-6); border-radius: var(--hub-radius-lg); border: 1px dashed var(--hub-border);
  background: rgba(255, 255, 255, .012);
}
.hub-empty__icon { display: inline-flex; align-items: center; justify-content: center; width: 44px; height: 44px; border-radius: var(--hub-radius-lg); background: var(--hub-surface-2); color: var(--hub-text-2); box-shadow: inset 0 0 0 1px var(--hub-border); }
.hub-empty__icon svg { width: 22px; height: 22px; }
.hub-empty__title { margin: 0; font-size: var(--hub-fs-lg); line-height: var(--hub-lh-lg); font-weight: var(--hub-fw-semibold); color: var(--hub-text-1); }
.hub-empty__text { margin: 0; max-width: 46ch; font-size: var(--hub-fs-sm); line-height: var(--hub-lh-sm); color: var(--hub-text-2); }
.hub-empty__actions { display: flex; flex-wrap: wrap; gap: var(--hub-space-2); justify-content: center; margin-top: var(--hub-space-1); }
.hub-empty--error .hub-empty__icon { background: var(--hub-danger-soft); color: var(--hub-danger); box-shadow: inset 0 0 0 1px var(--hub-danger-border); }
.hub-empty--compact { padding: var(--hub-space-6); }

.hub-skeleton {
  display: block; border-radius: var(--hub-radius-sm); min-height: 12px;
  background: linear-gradient(90deg, rgba(255, 255, 255, .04) 0%, rgba(255, 255, 255, .08) 40%, rgba(255, 255, 255, .04) 80%);
  background-size: 300% 100%; animation: hub-shimmer 1.6s ease-in-out infinite;
}
.hub-skeleton--text { height: 12px; width: var(--_w, 100%); }
.hub-skeleton--title { height: 20px; width: var(--_w, 40%); }
.hub-skeleton--block { height: var(--_h, 120px); border-radius: var(--hub-radius-lg); }
.hub-skeleton--circle { width: var(--_s, 32px); height: var(--_s, 32px); border-radius: 50%; }
.hub-spinner { display: inline-block; width: 16px; height: 16px; border-radius: 50%; border: 2px solid rgba(255, 255, 255, .16); border-top-color: var(--hub-accent-text); animation: hub-spin .7s linear infinite; vertical-align: middle; flex: none; }
.hub-loading { display: flex; align-items: center; justify-content: center; gap: var(--hub-space-3); padding: var(--hub-space-10); color: var(--hub-text-3); font-size: var(--hub-fs-sm); }

/* Zone de dépôt (fichiers) */
.hub-dropzone {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--hub-space-2); text-align: center;
  min-height: 160px; padding: var(--hub-space-8); border-radius: var(--hub-radius-lg); border: 1.5px dashed var(--hub-border-strong);
  background: rgba(255, 255, 255, .015); color: var(--hub-text-2); cursor: pointer; transition: border-color var(--hub-dur-2) ease, background-color var(--hub-dur-2) ease;
}
.hub-dropzone:hover, .hub-dropzone.is-over { border-color: var(--hub-accent-text); background: var(--hub-accent-soft); }
.hub-dropzone:focus-within { box-shadow: var(--hub-focus-ring); }

/* ---------- 20. Avatar ---------- */
.hub-avatar { display: inline-flex; align-items: center; justify-content: center; flex: none; width: var(--_s, 28px); height: var(--_s, 28px); border-radius: 50%; overflow: hidden; background: linear-gradient(135deg, #3b2350, #23212f); color: var(--hub-text-1); font: var(--hub-fw-semibold) var(--hub-fs-xs)/1 var(--hub-font-sans); box-shadow: inset 0 0 0 1px var(--hub-border); }
.hub-avatar img { width: 100%; height: 100%; object-fit: cover; }

/* ---------- 21. Pied de page ---------- */
.hub-footer { border-top: 1px solid var(--hub-border-subtle); margin-top: var(--hub-space-16); }
.hub-footer__inner { display: flex; flex-wrap: wrap; gap: var(--hub-space-2) var(--hub-space-6); align-items: center; padding-block: var(--hub-space-5); font-size: var(--hub-fs-xs); color: var(--hub-text-3); }
.hub-footer__inner a { color: var(--hub-text-2); text-decoration: none; }
.hub-footer__inner a:hover { color: var(--hub-text-1); }

/* Apparition échelonnée (accueil, listes) : style="--i: n" */
.hub-appear { animation: hub-rise var(--hub-dur-3) var(--hub-ease-out) both; animation-delay: calc(min(var(--i, 0), 10) * 24ms); }
/* Troncature : la coque ajoute title= au survol quand le texte est réellement coupé */
.hub-truncate[title] { cursor: default; }

/* ---------- 22. Animations ---------- */
@keyframes hub-spin { to { transform: rotate(360deg); } }
@keyframes hub-shimmer { 0% { background-position: 100% 0; } 100% { background-position: -100% 0; } }
@keyframes hub-pop-in { from { opacity: 0; transform: translateY(6px) scale(.985); } to { opacity: 1; transform: none; } }
@keyframes hub-slide-in-right { from { transform: translateX(24px); opacity: 0; } to { transform: none; opacity: 1; } }
@keyframes hub-fade-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes hub-rise { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) {
  .hub-skeleton, .hub-spinner, .hub-btn[aria-busy="true"]::after { animation-duration: 2.4s; }
  .hub-skeleton { animation: none; }
  dialog.hub-modal[open], dialog.hub-drawer[open], .hub-appear { animation: none; }
}

/* ---------- 22 bis. Tailles au doigt (pointeur grossier) ----------
   Placées APRÈS les composants : à spécificité égale, la dernière règle l'emporte (avant 2.2.0, ce bloc
   précédait les composants et restait sans effet : onglets 40 px, segments 26 px, épingles 28 px). */
@media (pointer: coarse) {
  .hub-btn, .hub-btn--sm, .hub-btn--lg { --_h: 44px; }
  .hub-input, .hub-select, .hub-input--sm, .hub-select--sm { --_h: 44px; font-size: 16px; }  /* 16 px : pas de zoom iOS */
  .hub-range { height: 44px; }
  .hub-tab { height: 44px; }
  .hub-chip { height: 36px; position: relative; }
  .hub-chip::after { content: ""; position: absolute; inset: -4px 0; }                        /* zone tactile 44 px */
  .hub-segmented > button { height: 40px; position: relative; }
  .hub-segmented > button::after { content: ""; position: absolute; inset: -3px 0; }          /* 46 px avec le cadre */
  .hub-mcard__pin { width: 44px; height: 44px; top: 4px; right: 4px; }
  .hub-th-sort::before { inset: -10px -8px; }                                                  /* 24 + 2 × 10 = 44 px */
  .hub-doc-nav a { min-height: 44px; }
}

/* ---------- 23. Contraste forcé (Windows) et impression ---------- */
@media (forced-colors: active) {
  .hub-btn, .hub-chip, .hub-input, .hub-select, .hub-card, .hub-kpi, .hub-mcard__link, .hub-quick, .hub-badge { border: 1px solid CanvasText; }
  .hub-tab[aria-selected="true"]::after, .hub-tab[aria-current="page"]::after { background: Highlight; }
  html.hub :focus-visible { outline: 2px solid Highlight; }
}
@media print {
  @page { margin: 14mm 12mm; }
  /* Encre sombre sur papier blanc : jetons de texte, de surface, de bordure et d'accent redéfinis pour les
     pages de type A (les documents de marque, type B, s'impriment avec leurs propres fonds). */
  html.hub {
    color-scheme: light;
    --hub-bg: #fff; --hub-bg-subtle: #fff; --hub-surface: #fff; --hub-surface-2: #f3f3f5; --hub-surface-3: #e9e9ee;
    --hub-surface-hover: transparent; --hub-surface-active: transparent;
    --hub-border-subtle: #dedee4; --hub-border: #cfcfd8; --hub-border-strong: #b5b5c2; --hub-border-input: #8b889c;
    --hub-text-1: #111; --hub-text-2: #333; --hub-text-3: #555; --hub-text-3-raised: #555; --hub-text-disabled: #777;
    --hub-brand-text: #a0086e; --hub-accent-text: color-mix(in srgb, var(--hub-accent) 55%, #000);
    --hub-accent-soft: color-mix(in srgb, var(--hub-accent) 10%, #fff); --hub-accent-border: color-mix(in srgb, var(--hub-accent) 45%, #fff);
    --hub-success: #18794e; --hub-warning: #8a5a00; --hub-danger: #b42318; --hub-info: #1f5fbf;
    --hub-highlight: none; --hub-elev-1: none; --hub-elev-2: none; --hub-shadow-1: none;
  }
  html.hub, html.hub body { background: #fff !important; color: #111 !important; }
  html.hub body::before { display: none; }
  .hub-card, .hub-kpi, .hub-table-wrap, .hub-mcard__link { box-shadow: none !important; border-color: #ccc !important; background: #fff !important; color: #111 !important; }
  .hub-table-wrap { overflow: visible !important; max-height: none !important; }
  .hub-table th { position: static; background: #f1f1f1 !important; color: #333 !important; }
  .hub-table thead { display: table-header-group; }
  .hub-table tr, .hub-card, .hub-kpi, figure, img, .hub-chart { break-inside: avoid; }
  .hub-btn, .hub-toolbar, .hub-tabs, .hub-viewbar, .hub-doc-nav, .hub-mcard__pin, [data-hub-collapse], [data-hub-noprint] { display: none !important; }
  /* Les règles d'impression historiques masquent souvent tous les boutons : en-têtes de tri et cellules
     cliquables portent du CONTENU (libellé, nom) et restent imprimés. */
  th .hub-th-sort { display: inline-flex !important; }
  .hub-th-sort::before { display: none; }
  .hub-cell-btn { display: block !important; text-decoration: none; }
  .hub-empty-row .hub-empty { position: static; }
  .hub-prose a[href^="http"]::after { content: " (" attr(href) ")"; font-size: .85em; color: #555; }
  .hub-kpi__value, .hub-page-title, .hub-text-1 { color: #111 !important; }
}
