/* =============================================
   CRM Always Improving — Main CSS
   Stack : Flask + Jinja2 + HTMX + Alpine.js
   ============================================= */

/* ---- Variables ---- */
:root {
  --sidebar-width: 240px;
  --sidebar-collapsed-width: 60px;
  --topbar-height: 56px;

  --color-bg:          #F6F7F9;
  --color-card:        #FFFFFF;
  --color-border:      #E4E7EC;
  /* Contour des commandes (champs, boutons secondaires) : un cran plus marqué
     que le filet des cartes, pour qu'un champ se lise comme un champ. */
  --color-border-strong: #D0D5DD;
  --color-text:        #101828;
  --color-text-muted:  #475467;
  /* #94A3B8 ne donnait que 2,45:1 sur blanc — sous le seuil AA (4,5) alors que
     ce jeton sert à du texte de 10-11 px, précisément là où la lisibilité
     compte le plus. #667085 atteint 5,0:1 tout en restant nettement plus clair
     que `--color-text-muted` (7,5:1) : la hiérarchie à trois niveaux tient. */
  --color-text-light:  #667085;

  /* Teintes de marque — calibrées pour le TEXTE.
     Elles servent 152 fois comme couleur de texte contre 5 fois comme aplat :
     c'est donc la lisibilité qui doit primer. Les valeurs « 500 » d'origine
     étaient des couleurs d'aplat employées comme texte, d'où des libellés de
     9-12 px en gras à peine lisibles sur blanc :

         #3B82F6  3,68:1   (89 occurrences)
         #10B981  2,54:1   (41)
         #F59E0B  2,15:1   (15)

     On descend d'un à deux crans dans la même rampe : la teinte et la lecture
     sémantique sont conservées, le contraste passe au-dessus de 4,5:1.
     Les aplats gardent leurs valeurs vives via les jetons `-solid` ci-dessous. */
  --color-accent:      #1D4ED8;   /* 5,4:1 sur blanc */
  --color-accent-pale: #EFF4FF;
  --color-emerald:     #047857;   /* 4,9:1 */
  --color-emerald-pale:#ECFDF5;
  --color-amber:       #B45309;   /* 4,9:1 */
  --color-amber-pale:  #FFFBEB;
  --color-rose:        #BE123C;   /* 5,9:1 */
  --color-rose-pale:   #FFF1F2;
  --color-purple:      #6D28D9;   /* 5,9:1 */
  --color-purple-pale: #F5F3FF;

  /* Variantes « pleines » : fond des boutons à texte blanc.
     Distinctes des accents ci-dessus car les deux usages tirent en sens
     opposés — un accent doit *s'éclaircir* en mode sombre pour rester lisible
     en texte sur fond ardoise, mais un aplat sous du texte blanc doit rester
     *soutenu*, sinon le blanc ne ressort plus. En clair les deux coïncident. */
  --color-accent-solid:  #2563EB;   /* blanc dessus : 4,6:1 */
  --color-emerald-solid: #047857;   /* 4,9:1 */
  --color-rose-solid:    #BE123C;   /* 5,9:1 */
  --color-amber-solid:   #B45309;   /* 4,9:1 */
  --color-purple-solid:  #6D28D9;   /* 5,9:1 */

  /* Teintes vives conservées pour le décoratif pur — jauges, séries de
     graphiques, pastilles de couleur — où rien n'est posé par-dessus et où
     l'éclat porte l'information. */
  --color-accent-vivid:  #3B82F6;
  --color-emerald-vivid: #10B981;
  --color-amber-vivid:   #F59E0B;
  --color-rose-vivid:    #F43F5E;
  --color-purple-vivid:  #8B5CF6;

  /* Pastilles teintées à couleur *dynamique*.
     Le motif `background:{{ x.color }}18; color:{{ x.color }}` est répandu : un
     fond à 9 % d'opacité et le même ton en pleine force pour le texte. La
     couleur venant des données, aucune valeur ne peut être corrigée à la main.
     Sur blanc, ce ton plein plafonne à 2,15:1 (ambre) ou 2,54:1 (émeraude).

     On la retravaille donc à la volée avec `color-mix`. Le sens du mélange doit
     dépendre du thème : sur blanc il faut assombrir, sur ardoise le même ton est
     déjà lisible et l'assombrir le rendrait invisible — c'est précisément
     l'erreur commise plus haut avec les teintes statiques. D'où deux jetons. */
  --tint-text-pct: 55%;
  --tint-text-mix: #0B1220;
  /* Même idée pour les classes `.tone-*` : en sombre on éclaircit davantage,
     car la teinte reçue peut elle-même être sombre (ardoise, bleu nuit). */
  --tone-pct: 55%;
  --tone-mix: #0B1220;

  --color-sidebar-bg:  #0F1B33;
  --color-sidebar-text:#C7D0E0;
  --color-sidebar-hover:#1A2A4A;
  --color-sidebar-active:#3B82F6;

  --radius-sm: 6px;
  --radius-md: 10px;
  --radius-lg: 14px;

  --shadow-sm: 0 1px 2px rgba(16,24,40,.06);
  --shadow-md: 0 4px 12px rgba(16,24,40,.08);
  --shadow-lg: 0 12px 32px rgba(16,24,40,.16);

  --transition: .15s ease-out;

  /* Échelle typographique — six crans, rien sous 12 px.
     Les gabarits portaient 83 tailles distinctes (9 px, 9,8 px, 10,08 px,
     11,9 px…) et 79 % du texte rendu passait sous 12 px. Toutes les tailles
     écrites en dur ont été ramenées à ces six jetons : régler un cran se fait
     désormais ici, pas dans 94 gabarits. */
  --text-xs:   12px;
  --text-sm:   13px;
  --text-base: 14px;
  --text-md:   16px;
  --text-lg:   20px;
  --text-xl:   24px;

  /* Alias — dix-huit noms de variables étaient employés dans les gabarits
     (`--color-slate` 34 fois, `--color-border-light` 21, `--color-navy` 17…)
     sans avoir jamais été déclarés. Une déclaration invalide retombe sur la
     valeur héritée : les libellés censés être atténués sortaient en plein
     noir, les filets censés être pâles disparaissaient. On les rattache aux
     jetons existants, si bien qu'ils suivent aussi le thème sombre. */
  --color-slate:        var(--color-text-muted);
  --color-slate-light:  var(--color-text-light);
  --color-muted:        var(--color-text-muted);
  --color-navy:         var(--color-text);
  --color-surface:      var(--color-card);
  --color-bg-secondary: var(--color-bg);
  --color-bg-alt:       var(--color-bg);
  --color-border-light: var(--color-border);
  --color-success:      var(--color-emerald);
  --color-warning:      var(--color-amber);
  --color-orange:       var(--color-amber);
  --color-rose-bg:      var(--color-rose-pale);
  --radius:             var(--radius-sm);
  --color-accent-rgb:   37, 99, 235;
  --rgb-accent:         37, 99, 235;
  --color-rose-rgb:     190, 18, 60;
  --color-warning-rgb:  180, 83, 9;
  --rgb-purple:         109, 40, 217;

  /* Hauteur des commandes — trois tailles au lieu des 23 mesurées. */
  --ctl-h:    36px;
  --ctl-h-sm: 30px;
  --ctl-h-xs: 28px;
}

/* Dark mode
   Le thème est porté par <html data-theme="dark"> (voir le script de base.html).
   `.dark` reste accepté comme alias : c'est le sélecteur historique.

   La version précédente ne redéfinissait que 6 variables. Les teintes « pale »
   (fonds de badges) et `--color-text-light` restaient sur leurs valeurs claires,
   quasi blanches : les pastilles de statut ressortaient en aplats lumineux sur
   fond sombre. On redéfinit ici l'ensemble du jeu de tokens. */
:root[data-theme="dark"],
.dark {
  color-scheme: dark;

  --color-bg:          #0B1220;
  --color-card:        #131C2E;
  --color-border:      #243047;
  --color-border-strong: #33415C;
  --color-text:        #F2F4F7;
  --color-text-muted:  #98A2B3;
  --color-text-light:  #8493AD;

  /* Accents : mêmes teintes, remontées en luminosité pour rester lisibles sur
     fond sombre. Les fonds « pale » deviennent des voiles translucides. */
  --color-accent:      #60A5FA;
  --color-accent-pale: rgba(96,165,250,.14);
  --color-emerald:     #34D399;
  --color-emerald-pale:rgba(52,211,153,.14);
  --color-amber:       #FBBF24;
  --color-amber-pale:  rgba(251,191,36,.14);
  --color-rose:        #FB7185;
  --color-rose-pale:   rgba(251,113,133,.14);
  --color-purple:      #A78BFA;
  --color-purple-pale: rgba(167,139,250,.14);

  /* Éclaircir `--color-accent` a fait chuter le texte blanc des boutons pleins
     à 2,54:1 (« + Ajouter une entreprise ») — une régression introduite par ce
     thème. Les aplats repassent donc sur des teintes soutenues, où le blanc
     tient : #2563EB ≈ 5,2:1, #047857 ≈ 5,0:1, #BE123C ≈ 5,9:1. */
  --color-accent-solid:  #2563EB;
  --color-emerald-solid: #047857;
  --color-rose-solid:    #BE123C;
  --color-amber-solid:   #B45309;
  --color-purple-solid:  #6D28D9;

  /* En sombre, les teintes vives servent aussi de couleur de texte : elles sont
     déjà claires, donc lisibles sur ardoise. */
  --color-accent-vivid:  #60A5FA;
  --color-emerald-vivid: #34D399;
  --color-amber-vivid:   #FBBF24;
  --color-rose-vivid:    #FB7185;
  --color-purple-vivid:  #A78BFA;

  /* Sur ardoise, le ton plein est déjà lisible : on l'éclaircit à peine, juste
     de quoi compenser le voile sombre du fond teinté. */
  --tint-text-pct: 82%;
  --tint-text-mix: #FFFFFF;
  --tone-pct: 55%;
  --tone-mix: #FFFFFF;

  --color-sidebar-bg:    #0A1324;
  --color-sidebar-hover: #14213B;

  /* Les ombres noires sont invisibles sur fond sombre : on les renforce. */
  --shadow-sm: 0 1px 3px rgba(0,0,0,.4);
  --shadow-md: 0 4px 16px rgba(0,0,0,.5);
  --shadow-lg: 0 8px 32px rgba(0,0,0,.6);
}

:root { color-scheme: light; }

/* ---- Police ----
   `font-family: 'Inter'` était déclaré sans qu'aucun fichier ne soit chargé :
   l'interface ne s'affichait en Inter que sur les postes où la police était
   installée, et en Segoe UI ou San Francisco ailleurs — chacun voyait un CRM
   différent. Le fichier variable existe déjà pour les propositions ; on le
   réutilise, découpé par plage pour ne télécharger que le latin de base tant
   qu'aucun caractère étendu n'est affiché. */
@font-face {
  font-family: 'Inter'; font-style: normal; font-weight: 100 900; font-display: swap;
  src: url('../proposal/fonts/inter-400-normal-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('../proposal/fonts/inter-400-normal-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* ---- Reset léger ---- */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html, body { height: 100%; font-family: 'Inter', 'Segoe UI', system-ui, -apple-system, sans-serif; font-size: 14px; }
body { background: var(--color-bg); color: var(--color-text); line-height: 1.45; -webkit-font-smoothing: antialiased; }
/* Les champs n'héritent pas de la police par défaut : les saisies sortaient en
   Arial, les zones de texte et les dates en monospace. */
input, select, textarea, button { font: inherit; color: inherit; }
a { color: var(--color-accent); text-decoration: none; }
a:hover { text-decoration: underline; }
button { cursor: pointer; }
[x-cloak] { display: none !important; }

/* ---- Focus clavier ----
   Le projet ne définissait aucun style de focus : les champs supprimaient même
   l'anneau natif (`outline: none`) sans toujours le remplacer, et boutons,
   liens, entrées de navigation et actions de tableau n'avaient rien. Un
   utilisateur au clavier ne pouvait donc pas savoir où il se trouvait.

   `:focus-visible` ne se déclenche qu'au clavier : à la souris, l'apparence est
   strictement inchangée. `outline-offset` évite que l'anneau ne colle au bord,
   et `outline` (plutôt qu'un `box-shadow`) suit la forme même en coin arrondi
   et reste visible en mode contraste élevé. */
:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}
/* Dans la sidebar (fond ardoise), l'accent manque de contraste : anneau clair. */
.sidebar :focus-visible { outline-color: #fff; }

/* 18 attributs `style="…outline:none…"` subsistent dans 10 templates ; un style
   en ligne l'emporte sur toute règle de feuille de style. `!important` est ici
   justifié : il s'agit d'un plancher d'accessibilité au clavier, et la règle ne
   s'applique qu'à `:focus-visible` (donc jamais à la souris). Couvre aussi les
   occurrences futures, sans reprendre chaque template. */
:focus-visible {
  outline: 2px solid var(--color-accent) !important;
  outline-offset: 2px !important;
}
.sidebar :focus-visible { outline-color: #fff !important; }

/* ---- Filter pill buttons (Todos, etc.) ---- */
.todo-filter-active {
  background: var(--color-card);
  color: var(--color-accent);
  border-color: var(--color-accent) !important;
  box-shadow: 0 1px 6px rgba(0,0,0,0.10);
  font-weight: 600;
}
.todo-filter-inactive {
  background: transparent;
  color: var(--color-text-muted);
  border-color: var(--color-border) !important;
  box-shadow: none;
  font-weight: 400;
}
.todo-filter-inactive:hover {
  background: var(--color-accent-pale);
  color: var(--color-accent);
  border-color: var(--color-accent) !important;
}

/* ---- Layout ---- */
body { display: flex; min-height: 100vh; }

.sidebar {
  width: var(--sidebar-width);
  min-width: var(--sidebar-width);
  background: var(--color-sidebar-bg);
  display: flex;
  flex-direction: column;
  transition: width var(--transition), min-width var(--transition);
  overflow: hidden;
  position: fixed;
  top: 0; bottom: 0; left: 0;
  z-index: 100;
}
/* Lien d'évitement (base.html) : hors de l'écran jusqu'à ce que Tab l'atteigne. */
.skip-link {
  position: fixed; top: 8px; left: 8px; z-index: 2000;
  padding: 8px 14px; border-radius: var(--radius-sm);
  background: var(--color-card); color: var(--color-accent);
  font-weight: 600; text-decoration: none;
  box-shadow: var(--shadow-md);
  transform: translateY(-200%);
}
.skip-link:focus { transform: none; }
/* Cible du lien : reçoit le focus pour que Tab reparte du contenu, sans cadre. */
#main-content:focus { outline: none; }
.sidebar.collapsed {
  width: var(--sidebar-collapsed-width);
  min-width: var(--sidebar-collapsed-width);
}

.main-wrapper {
  margin-left: var(--sidebar-width);
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  transition: margin-left var(--transition);
  /* Sans `min-width: 0`, ce conteneur est un flex item dont le plancher
     (min-width: auto) vaut sa largeur min-content. Dès qu'une page contient un
     tableau large, il refuse de se réduire à la place disponible à côté de la
     sidebar : la topbar et le contenu débordent à droite, hors écran et hors
     d'atteinte (cf. /contacts, qui débordait de 74 px en 1440). */
  min-width: 0;
}
.main-wrapper.sidebar-collapsed {
  margin-left: var(--sidebar-collapsed-width);
}

/* ---- Sidebar ---- */
.sidebar-logo {
  display: flex;
  align-items: center;
  gap: .75rem;
  padding: .75rem 1rem;
  border-bottom: 1px solid rgba(255,255,255,.08);
  white-space: nowrap;
}
.logo-icon { font-size: var(--text-lg); }
.logo-text  { font-size: var(--text-sm); font-weight: 700; color: #F1F5F9; }

.sidebar-nav {
  flex: 1;
  /* `hidden` rendait les dernières entrées (Sécurité, Paramètres) inatteignables
     dès que la hauteur de fenêtre passait sous ~750 px — 20 modules ne tiennent
     pas sur un portable court. */
  overflow-y: auto;
  padding: .25rem 0;
  scrollbar-width: thin;
}

.nav-item {
  display: flex;
  align-items: center;
  gap: .75rem;
  /* 20 modules demandaient 679 px pour 591 px disponibles sur une fenêtre de
     706 px : Sécurité, Knowledge Base et Paramètres passaient sous la ligne de
     flottaison. En resserrant la rythmique on les fait rentrer sans descendre
     sous une cible tactile confortable (~30 px de haut). */
  padding: .35rem 1rem;
  color: var(--color-sidebar-text);
  border-radius: var(--radius-sm);
  margin: 0 .5rem;
  white-space: nowrap;
  transition: background var(--transition), color var(--transition);
  text-decoration: none;
}
.nav-item:hover { background: var(--color-sidebar-hover); color: #fff; text-decoration: none; }
/* Pastille de comptage d'une entrée de menu (« Ma journée »). Remplie après
   coup par HTMX : vide, elle ne prend aucune place. */
.nav-badge {
  margin-left: auto;
  min-width: 20px; padding: 0 6px;
  border-radius: 99px;
  background: rgba(255,255,255,.14); color: #fff;
  font-size: 12px; font-weight: 600; line-height: 18px; text-align: center;
  font-variant-numeric: tabular-nums;
}
.nav-badge:empty { display: none; }
/* Menu replié : le libellé disparaît, pas le compte. Il se pose en coin de
   l'icône au lieu de disparaître avec lui. */
.sidebar.collapsed .nav-item { position: relative; }
.sidebar.collapsed .nav-badge {
  position: absolute; top: 1px; right: 4px; margin: 0;
  min-width: 16px; padding: 0 4px;
  background: var(--color-accent); font-size: 10px; line-height: 16px;
}
.nav-item-danger:hover { background: rgba(244,63,94,.2); color: var(--color-rose); }

/* État actif — repère porté par une barre d'accent plutôt que par un aplat
   plein sur toute la ligne : l'aplat dominait la colonne et écrasait la lecture
   des autres entrées. La barre situe la page courante sans capter le regard. */
.nav-item { position: relative; }
.nav-item.active {
  background: color-mix(in srgb, var(--color-sidebar-active) 20%, transparent);
  color: #fff;
  font-weight: 600;
}
.nav-item.active::before {
  content: "";
  position: absolute;
  left: -.5rem;
  top: 50%;
  transform: translateY(-50%);
  width: 3px;
  height: 60%;
  border-radius: 0 3px 3px 0;
  background: var(--color-sidebar-active);
}
.nav-item.active .ico { color: var(--color-sidebar-active); }
/* Repli à 60 px : la barre sortirait du cadre, on la masque. */
.sidebar.collapsed .nav-item.active::before { display: none; }

/* Icônes SVG — `currentColor` les fait suivre l'état et le thème, ce que les
   emoji (police couleur) ne savaient pas faire. Largeur fixe : la chasse
   variable des emoji désalignait les libellés d'une ligne à l'autre. */
.nav-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  min-width: 20px;
  flex-shrink: 0;
}
/* `inline-block` et non `block` : la plupart des icônes sont désormais posées
   au fil du texte (« [cal] Aujourd'hui »), où `block` provoquait un retour à la
   ligne et faisait passer l'icône au-dessus du libellé. Le décalage vertical
   aligne le tracé sur la ligne de base plutôt que sur le bas de la boîte. */
.ico {
  display: inline-block;
  vertical-align: -.125em;
  flex-shrink: 0;
}
/* Dans la sidebar, `.nav-icon` est un conteneur flex : `block` y est correct. */
.nav-icon .ico { display: block; vertical-align: baseline; }
.nav-label { font-size: var(--text-sm); font-weight: 500; }
/* En-têtes de département. Ils remplacent les filets nus : à 20 modules, un
   filet disait qu'il y avait une rupture sans dire laquelle. Rythmique serrée
   (~24 px) — sept en-têtes s'ajoutent à la colonne, qui défile déjà sur les
   fenêtres courtes. */
.sidebar-group {
  display: flex;
  align-items: center;
  gap: .35rem;
  width: 100%;
  padding: .55rem 1rem .1rem;
  min-height: 1rem;
  line-height: 1.2;
  /* C'est un <button> : on annule le style natif pour retrouver l'en-tête. */
  background: none;
  border: 0;
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.sidebar-nav .nav-group:first-child .sidebar-group { padding-top: .2rem; }
.sidebar-group:hover .sidebar-group-label,
.sidebar-group:hover .sidebar-group-caret { color: #fff; }
.sidebar-group:focus-visible {
  outline: 2px solid var(--color-sidebar-active);
  outline-offset: -2px;
  border-radius: var(--radius-sm);
}
.sidebar-group-label {
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: color-mix(in srgb, var(--color-sidebar-text) 70%, transparent);
  white-space: nowrap;
  transition: color var(--transition);
}
/* Le chevron est poussé à droite et n'apparaît franchement qu'au survol : sept
   chevrons pleine opacité feraient une seconde colonne de bruit à côté des
   icônes de modules. */
.sidebar-group-caret {
  display: inline-flex;
  margin-left: auto;
  color: color-mix(in srgb, var(--color-sidebar-text) 70%, transparent);
  opacity: .45;
  transition: transform var(--transition), opacity var(--transition), color var(--transition);
}
.sidebar-group:hover .sidebar-group-caret { opacity: 1; }
.nav-group--collapsed .sidebar-group-caret { transform: rotate(-90deg); opacity: .75; }

/* Repli d'un groupe. Le sélecteur est piloté par une classe (et non par
   `x-show`) pour que la restauration se fasse avant peinture — voir le script
   de <head>. */
.nav-group--collapsed .nav-group-items { display: none; }

/* Variante repliée (60 px) : le libellé sortirait du cadre, le filet le
   remplace. Les groupes y sont toujours dépliés — sans nom lisible, un groupe
   fermé ne serait qu'un filet muet, impossible à rouvrir à l'aveugle. */
.sidebar-group-rule {
  display: block;
  width: 100%;
  height: 1px;
  background: rgba(255,255,255,.08);
}
.sidebar.collapsed .sidebar-group { pointer-events: none; }
.sidebar.collapsed .nav-group--collapsed .nav-group-items { display: block; }

.sidebar-footer {
  border-top: 1px solid rgba(255,255,255,.08);
  padding: .4rem .5rem;
}
.sidebar-user {
  display: flex;
  align-items: center;
  gap: .6rem;
  padding: .5rem .5rem .75rem;
  overflow: hidden;
}
.user-avatar {
  min-width: 32px;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--text-sm);
}
.user-name  { font-size: var(--text-xs); font-weight: 600; color: #F1F5F9; }
.user-role  { font-size: var(--text-xs); color: var(--color-sidebar-text); }

/* ---- Topbar ---- */
.topbar {
  height: var(--topbar-height);
  background: var(--color-card);
  border-bottom: 1px solid var(--color-border);
  display: flex;
  align-items: center;
  gap: .75rem;
  padding: 0 1.25rem;
  position: sticky;
  top: 0;
  z-index: 50;
}
.topbar-title { flex: 1; font-weight: 600; font-size: var(--text-base); color: var(--color-text-muted); }
.topbar-right { display: flex; align-items: center; gap: .5rem; }
.topbar-btn {
  background: none;
  border: none;
  padding: .4rem .5rem;
  border-radius: var(--radius-sm);
  font-size: var(--text-base);
  color: var(--color-text-muted);
  transition: background var(--transition), color var(--transition);
  /* Les actions de la topbar sont désormais des SVG : on les centre et on
     garantit une hauteur constante, les emoji précédents ayant des métriques
     verticales différentes selon la plateforme. */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .35rem;
  line-height: 1;
}
.topbar-btn { min-width: var(--ctl-h); min-height: var(--ctl-h); }
.topbar-btn:hover { background: var(--color-bg); color: var(--color-text); }

/* ---- Lang switch ---- */
.lang-switch { display: flex; gap: 2px; }
.lang-btn {
  padding: .25rem .5rem;
  border-radius: var(--radius-sm);
  font-size: var(--text-xs);
  font-weight: 600;
  color: var(--color-text-muted);
  transition: background var(--transition);
}
.lang-btn:hover  { background: var(--color-accent-pale); text-decoration: none; }
.lang-btn.active { background: var(--color-accent-solid); color: #fff; }

/* ---- Notifications ---- */
.notif-wrapper { position: relative; }
.notif-btn     { position: relative; }
.notif-badge {
  position: absolute;
  top: 2px; right: 2px;
  background: var(--color-rose);
  color: #fff;
  font-size: 10px;
  line-height: 14px;
  font-weight: 700;
  border-radius: 99px;
  padding: 0 4px;
  min-width: 16px;
  text-align: center;
}
.notif-panel {
  position: absolute;
  right: 0;
  top: calc(100% + 8px);
  width: 320px;
  background: var(--color-card);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
  z-index: 200;
  max-height: 400px;
  overflow-y: auto;
}
/* Téléphone : le panneau ancré à la cloche débordait à gauche de l'écran ; il
   prend la largeur de l'écran sous la barre, et plus de hauteur — les rappels
   de relance y sont lus en premier. */
@media (max-width: 480px) {
  .notif-panel {
    position: fixed;
    left: 8px;
    right: 8px;
    top: 60px;
    width: auto;
    max-height: calc(100vh - 80px);
  }
}

/* ---- Recherche globale (barre du haut) ----
   Sur bureau, une case toujours visible entre le titre et les actions. Sous
   768 px, une loupe : la case se déplie alors par-dessus toute la barre, et la
   liste prend la largeur de l'écran moins les marges — à 390 px, rien ne
   déborde. Uniquement des variables de thème : le mode sombre suit seul. */
.gsearch { position: relative; flex: 0 1 340px; min-width: 0; }
.gsearch-toggle { display: none; }
.gsearch-field {
  display: flex;
  align-items: center;
  gap: .4rem;
  height: 34px;
  padding: 0 .5rem 0 .6rem;
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  transition: border-color var(--transition), background var(--transition);
}
.gsearch-field:focus-within { border-color: var(--color-accent); background: var(--color-card); }
.gsearch-icon { display: inline-flex; color: var(--color-text-muted); flex-shrink: 0; }
.gsearch-input {
  flex: 1;
  min-width: 0;
  border: none;
  outline: none;
  background: transparent;
  color: var(--color-text);
  font-size: .85rem;
}
/* Le contour de focus est porté par la case entière (`:focus-within`). */
.gsearch-input:focus-visible { outline: none !important; }
.gsearch-input::placeholder { color: var(--color-text-muted); }
.gsearch-kbd {
  font: 600 .7rem/1 inherit;
  color: var(--color-text-muted);
  border: 1px solid var(--color-border);
  border-radius: 4px;
  padding: 2px 6px;
  flex-shrink: 0;
}
.gsearch-field:focus-within .gsearch-kbd { display: none; }
.gsearch-panel {
  position: absolute;
  left: 0;
  right: 0;
  top: calc(100% + 6px);
  min-width: 300px;
  background: var(--color-card);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
  z-index: 200;
  max-height: min(70vh, 520px);
  overflow-y: auto;
  padding: .35rem 0;
}
.gs-group + .gs-group { border-top: 1px solid var(--color-border); margin-top: .25rem; padding-top: .25rem; }
.gs-heading {
  font-size: .68rem;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--color-text-muted);
  padding: .35rem .85rem .2rem;
}
.gs-item {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: .75rem;
  padding: .45rem .85rem;
  color: var(--color-text);
  text-decoration: none;
}
.gs-item:hover, .gs-item.is-active { background: var(--color-accent-pale); text-decoration: none; }
.gs-item.is-active .gs-name { color: var(--color-accent); }
.gs-name {
  font-size: .85rem;
  font-weight: 600;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.gs-detail {
  font-size: .75rem;
  color: var(--color-text-muted);
  white-space: nowrap;
  flex-shrink: 0;
  max-width: 55%;
  overflow: hidden;
  text-overflow: ellipsis;
}
.gs-empty { padding: .75rem .85rem; font-size: .85rem; color: var(--color-text-muted); }
.gs-more { padding: .35rem .85rem .5rem; font-size: .75rem; color: var(--color-text-muted); font-style: italic; }

@media (max-width: 768px) {
  .gsearch { flex: 0 0 auto; position: static; }
  .gsearch-toggle { display: inline-flex; }
  .gsearch-field { display: none; }
  .gsearch-kbd { display: none; }
  /* Dépliée : la case recouvre la barre (positionnée par rapport à `.topbar`,
     qui est `sticky`), la liste tombe dessous sur toute la largeur. */
  .gsearch.is-expanded .gsearch-field {
    display: flex;
    position: absolute;
    left: .75rem;
    right: .75rem;
    top: 50%;
    transform: translateY(-50%);
    background: var(--color-card);
    z-index: 210;
  }
  .gsearch-panel { left: .75rem; right: .75rem; top: calc(100% + 4px); min-width: 0; }
}

/* ---- Page content ---- */
.page-content {
  flex: 1;
  padding: 24px;
  overflow-y: auto;
  overflow-x: hidden;
}

/* ---- Cards ---- */
.card {
  background: var(--color-card);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
  padding: 1.25rem;
}
.card-title {
  font-size: var(--text-base);
  font-weight: 600;
  margin-bottom: 1rem;
  color: var(--color-text);
}

/* ---- KPI Cards ---- */
.kpi-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 1rem;
  margin-bottom: 1.5rem;
}
.kpi-card {
  background: var(--color-card);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: 1rem;
  box-shadow: var(--shadow-sm);
  transition: border-color var(--transition), box-shadow var(--transition);
}
/* Seules les cartes qui mènent quelque part réagissent au survol. Le curseur
   « main » et le soulèvement s'appliquaient à toutes : une carte de simple
   lecture promettait un clic qui ne faisait rien. */
a.kpi-card--link { text-decoration: none; color: inherit; display: block; }
a.kpi-card, .kpi-card[\@click], .kpi-card[x-on\:click], .kpi-card[onclick], .kpi-card[hx-get] { cursor: pointer; }
a.kpi-card:hover, .kpi-card[\@click]:hover, .kpi-card[x-on\:click]:hover, .kpi-card[onclick]:hover, .kpi-card[hx-get]:hover {
  border-color: var(--color-border-strong); box-shadow: var(--shadow-md); color: inherit;
}
.kpi-label { font-size: var(--text-xs); color: var(--color-text-muted); font-weight: 500; margin-bottom: .25rem; }
.kpi-value { font-size: var(--text-xl); font-weight: 600; letter-spacing: -.01em; line-height: 1.2; font-variant-numeric: tabular-nums; }
.kpi-sub   { font-size: var(--text-xs); color: var(--color-text-light); margin-top: .25rem; }

/* ---- Tables ---- */
.table-wrapper { overflow-x: auto; }

/* Les tableaux larges doivent défiler *dans* leur carte, pas être rognés par
   `.page-content { overflow-x: hidden }` — sinon la colonne Actions devient
   inatteignable (cf. /contacts : tableau de 1230 px dans une carte de 1200).
   Seuls 3 des 34 tableaux du projet sont enveloppés dans `.table-wrapper` ;
   plutôt que d'éditer chaque template, on rend la carte porteuse défilante. */
.card:has(> table),
.card:has(> .data-table) { overflow-x: auto; }
table { width: 100%; border-collapse: collapse; }
/* En-têtes en bas de casse à 12 px : des capitales à 10 px demandaient plus
   d'effort de lecture que la donnée qu'elles titraient. */
thead th {
  padding: .6rem 1rem;
  text-align: left;
  font-size: var(--text-xs);
  font-weight: 600;
  color: var(--color-text-muted);
  background: var(--color-bg);
  border-bottom: 1px solid var(--color-border);
  white-space: nowrap;
}
tbody td {
  padding: .7rem 1rem;
  border-bottom: 1px solid var(--color-border);
  font-size: var(--text-sm);
}
/* Survol neutre : le voile bleu faisait passer chaque ligne survolée pour une
   ligne sélectionnée. */
tbody tr:hover { background: color-mix(in srgb, var(--color-text) 3.5%, transparent); }
tbody tr:last-child td { border-bottom: none; }
/* Ligne qui ouvre sa fiche au clic (voir main.js). */
/* Grille à deux colonnes posée en style inline : sur un téléphone elle passe à
   une colonne. Sans cela le formulaire de lead gardait deux colonnes de 65 px
   et la seconde sortait de l'écran. */
@media (max-width: 760px) {
  .stack-on-phone { grid-template-columns: minmax(0, 1fr) !important; }
  .stack-on-phone > * { grid-column: auto !important; min-width: 0; }
}

/* ---- Téléphone (≤ 640 px) : rien de rogné, rien d'inatteignable ----
   `.page-content` coupe ce qui dépasse à droite (overflow-x: hidden) : à 390 px,
   vingt-trois types de page perdaient une colonne entière — le volet droit des
   fiches Contact/Société/Process, le panneau de publication de la base de
   connaissances, les boutons d'en-tête, les colonnes Actions des tableaux. Les
   grilles en cause sont posées en style inline dans des gabarits que d'autres
   écrans réutilisent ; plutôt que de les réécrire une à une, on les reprend
   ici par leur motif, uniquement sous 640 px — le bureau ne bouge pas. */
@media (max-width: 640px) {
  /* 1. Les tableaux défilent dans leur cadre au lieu d'être coupés.
     `.table-responsive` était employé par 17 gabarits sans jamais avoir été
     défini ; les autres tableaux sont enfants directs d'un `.card-body`, d'une
     section ou d'un div quelconque. Les menus d'action des lignes sont en
     `position: fixed` (voir `.actions-cell`) : le défilement ne les coupe pas. */
  .page-content .table-responsive,
  .page-content :is(div, section, form):has(> table) { overflow-x: auto; }

  /* 2. Mises en page à deux volets → un seul, le volet droit passe dessous. */
  .page-content :is(
    [style*="grid-template-columns:2fr 1fr"], [style*="grid-template-columns: 2fr 1fr"],
    [style*="grid-template-columns:1.4fr 1fr"], [style*="grid-template-columns: 1.4fr 1fr"],
    [style*="grid-template-columns:220px 1fr"], [style*="grid-template-columns:260px 1fr"],
    [style*="grid-template-columns:1fr 320px"], [style*="grid-template-columns:1fr 280px"],
    [style*="grid-template-columns:1fr 2fr"], [style*="grid-template-columns:1.2fr .8fr"],
    [style*="grid-template-columns:1.25fr .75fr"],
    [style*="grid-template-columns:minmax(0,2fr) minmax(280px,1fr)"],
    [style*="grid-template-columns:2fr 1.4fr 2fr"], [style*="grid-template-columns:1.3fr 1fr 1fr 1fr 1fr auto"],
    [style*="grid-template-columns:1fr 1fr 1fr auto"], [style*="grid-template-columns:1fr 1fr auto auto"]
  ) { grid-template-columns: minmax(0, 1fr) !important; }
  .page-content :is(
    [style*="grid-template-columns:2fr 1fr"], [style*="grid-template-columns: 2fr 1fr"],
    [style*="grid-template-columns:1.4fr 1fr"], [style*="grid-template-columns: 1.4fr 1fr"],
    [style*="grid-template-columns:220px 1fr"], [style*="grid-template-columns:260px 1fr"],
    [style*="grid-template-columns:1fr 320px"], [style*="grid-template-columns:1fr 280px"],
    [style*="grid-template-columns:1fr 2fr"], [style*="grid-template-columns:1.2fr .8fr"],
    [style*="grid-template-columns:1.25fr .75fr"],
    [style*="grid-template-columns:minmax(0,2fr) minmax(280px,1fr)"],
    [style*="grid-template-columns:2fr 1.4fr 2fr"], [style*="grid-template-columns:1.3fr 1fr 1fr 1fr 1fr auto"],
    [style*="grid-template-columns:1fr 1fr 1fr auto"], [style*="grid-template-columns:1fr 1fr auto auto"]
  ) > * { grid-column: auto !important; min-width: 0; }

  /* 3. Rangées de 4 à 6 tuiles (chiffres du jour, compteurs) → deux par ligne. */
  .page-content :is(
    [style*="grid-template-columns:repeat(4,1fr)"], [style*="grid-template-columns: repeat(4, 1fr)"],
    [style*="grid-template-columns:repeat(4,minmax(0,1fr))"], [style*="grid-template-columns:repeat(6,1fr)"]
  ) { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; }
  /* Dans un formulaire, trois champs côte à côte laissaient 80 px à chacun
     (date d'expiration du visa illisible) : deux par ligne. Les rangées de
     trois chiffres hors formulaire gardent leurs trois colonnes. */
  .page-content form :is([style*="grid-template-columns:1fr 1fr 1fr"], [style*="grid-template-columns: 1fr 1fr 1fr"]) {
    grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
  }

  /* 4. Ligne d'étape d'un type de process (pastille, FR, EN, délai, portée,
     flèches) : pastille + deux libellés, puis délai et portée dessous, les
     flèches en dernier. */
  .page-content [style*="grid-template-columns: 28px 1fr 1fr 90px 130px auto"] {
    grid-template-columns: 28px minmax(0, 1fr) minmax(0, 1fr) !important;
  }
  .page-content [style*="grid-template-columns: 28px 1fr 1fr 90px 130px auto"] > :nth-child(4) { grid-column: 2; }
  .page-content [style*="grid-template-columns: 28px 1fr 1fr 90px 130px auto"] > :nth-child(5) { grid-column: 3; }
  .page-content [style*="grid-template-columns: 28px 1fr 1fr 90px 130px auto"] > :nth-child(6) { grid-column: 2 / -1; }

  /* 5. Grille implicite à une colonne (`auto`) : son plancher est la largeur
     du tableau le plus large qu'elle contient, et elle sortait de l'écran
     (Analyse des juridictions). */
  .page-content .ja-grid { grid-template-columns: minmax(0, 1fr); }
  .page-content .ja-grid > * { min-width: 0; }

  /* 6. Rangées de boutons et en-têtes en flex : elles passent à la ligne au
     lieu de pousser leurs derniers boutons hors de l'écran. Le retour à la
     ligne n'intervient que si la rangée déborde ; celles qui défilent
     volontairement (overflow) ou refusent le retour (nowrap) sont laissées. */
  .page-content :is(.d-flex, [style*="display:flex"], [style*="display: flex"], [style*="display:inline-flex"], .exp-tab-bar):not([style*="nowrap"]):not([style*="overflow"]):not([style*="flex-direction:column"]):not([style*="flex-direction: column"]) {
    flex-wrap: wrap;
  }
  /* Un groupe de boutons en `flex-shrink:0` garde la largeur de tous ses
     boutons côte à côte (en-tête d'une fiche Société) : on le laisse rétrécir
     pour que ses boutons passent à la ligne. */
  .page-content :is([style*="display:flex"], [style*="display: flex"])[style*="flex-shrink:0"] { flex-shrink: 1 !important; min-width: 0; }

  /* 7. Petit menu déroulant ancré à droite de son bouton (« Écarter » des
     suggestions de vente croisée) : 260 px calés sur le bord droit d'un bouton
     placé à gauche, il s'ouvrait à moitié hors de l'écran, côté gauche — un
     débordement qu'aucun défilement ne rattrape. Il prend la largeur de l'écran. */
  .page-content details[style*="position:relative"] > form[style*="position:absolute"] {
    position: fixed !important;
    left: 16px !important;
    right: 16px !important;
    min-width: 0 !important;
  }
}
tr[data-href] { cursor: pointer; }

/* ---- Badges ---- */
.badge {
  display: inline-flex;
  align-items: center;
  gap: .3rem;
  padding: .12rem .55rem;
  border-radius: 99px;
  font-size: var(--text-xs);
  font-weight: 600;
  line-height: 1.5;
  white-space: nowrap;
}
.badge-active   { color: var(--color-emerald); background: var(--color-emerald-pale); }
.badge-success  { color: var(--color-emerald); background: var(--color-emerald-pale); }
.badge-warning  { color: var(--color-amber);   background: var(--color-amber-pale); }
.badge-danger   { color: var(--color-rose);    background: var(--color-rose-pale); }
.badge-info     { color: var(--color-accent);  background: var(--color-accent-pale); }
.badge-purple   { color: var(--color-purple);  background: var(--color-purple-pale); }
.badge-muted    { color: var(--color-text-muted); background: var(--color-bg); }
.badge-green  { color: var(--color-emerald);      background: var(--color-emerald-pale); }
.badge-yellow { color: var(--color-amber);        background: var(--color-amber-pale); }
.badge-red    { color: var(--color-rose);         background: var(--color-rose-pale); }
.badge-blue   { color: var(--color-accent);       background: var(--color-accent-pale); }
.badge-gray   { color: var(--color-text-muted);   background: var(--color-bg); }
/* Noms par couleur de thème, employés par plusieurs gabarits (Juridictions,
   Analyse…) sans avoir jamais été définis : ces pastilles s'affichaient sans
   couleur, « Expiré » ou « Coût manquant » aussi neutres qu'une étiquette. */
.badge-emerald { color: var(--color-emerald); background: var(--color-emerald-pale); }
.badge-amber   { color: var(--color-amber);   background: var(--color-amber-pale); }
.badge-rose    { color: var(--color-rose);    background: var(--color-rose-pale); }
.badge-accent  { color: var(--color-accent);  background: var(--color-accent-pale); }
.badge-count  { display:inline-flex;align-items:center;justify-content:center;min-width:18px;height:18px;padding:0 5px;border-radius:9px;font-size:var(--text-xs);font-weight:700;background:var(--color-accent-pale);color:var(--color-accent);margin-left:4px; }
.badge-count--red    { background: var(--color-rose-pale);  color: var(--color-rose); }
.badge-count--yellow { background: var(--color-amber-pale); color: var(--color-amber); }

/* ---- Buttons ---- */
/* Trois hauteurs — 36, 30 et 28 px — au lieu des 23 mesurées. La hauteur est
   portée par `min-height` et non par le padding vertical : un bouton à icône
   seule, à libellé court ou sur deux mots tombe sur la même ligne de base que
   le champ voisin. */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .4rem;
  min-height: var(--ctl-h);
  padding: .3rem .9rem;
  border-radius: var(--radius-sm);
  font-size: var(--text-sm);
  font-weight: 600;
  line-height: 1.2;
  border: 1px solid transparent;
  text-decoration: none;
  transition: background var(--transition), border-color var(--transition), color var(--transition), opacity var(--transition);
}
.btn:hover { text-decoration: none; }
/* Un bouton qui fixe lui-même son padding en ligne a choisi sa hauteur (36
   emplois, surtout dans des lignes denses) : on ne lui impose pas 36 px. */
.btn[style*="padding"]:not(.btn-full):not(.btn-sm):not(.btn-xs) { min-height: 0; }
/* Les boutons sans variante (fond posé en ligne) gardent un retour au survol. */
.btn:not(.btn-primary):not(.btn-secondary):not(.btn-ghost):not(.btn-red-ghost):not(.btn-amber-ghost):hover { opacity: .9; }
.btn-primary   { background: var(--color-accent-solid); color: #fff; }
.btn-primary:hover { background: color-mix(in srgb, var(--color-accent-solid) 86%, #000); color: #fff; }
/* Le secondaire se confondait avec le fond de page (même teinte, filet pâle) :
   fond de carte et contour marqué, il se lit comme un bouton. */
.btn-secondary { background: var(--color-card); color: var(--color-text); border-color: var(--color-border-strong); }
.btn-secondary:hover { background: var(--color-bg); color: var(--color-text); }
.btn-danger    { background: var(--color-rose-solid); color: #fff; }
.btn-success   { background: var(--color-emerald-solid); color: #fff; }
.btn-danger:hover, .btn-success:hover { opacity: .9; }
.btn-sm        { min-height: var(--ctl-h-sm); padding: .2rem .7rem; font-size: var(--text-xs); }
/* `.btn-xs` sert deux fois sur trois SANS `.btn` à côté — c'est le cas de toutes
   les colonnes d'actions des tableaux. Il n'apportait pourtant que du padding et
   une taille de police : ces boutons-là gardaient donc le chrome natif du
   navigateur (pavé gris biseauté, angles carrés), sans rapport avec le reste du
   jeu de boutons. On lui donne la base de `.btn` pour qu'il tienne seul. */
.btn-xs {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .3rem;
  padding: .15rem .5rem !important;
  font-size: var(--text-xs) !important;
  height: auto !important;
  min-width: var(--ctl-h-xs);
  min-height: var(--ctl-h-xs);
  border-radius: var(--radius-sm);
  font-weight: 600;
  border: 1px solid transparent;
  cursor: pointer;
  transition: background var(--transition), opacity var(--transition);
}
/* Les icônes sont émises à 18 px par le macro `ico.icon`. Dans une pastille de
   28 px, elles remplissent toute la boîte et les boutons se touchent visuellement
   même quand l'espacement est correct. */
.btn-xs .ico { width: 14px; height: 14px; }
.btn-full      { width: 100%; justify-content: center; }
.btn-green     { background: var(--color-emerald-solid); color: #fff; border: none; }
.btn-green:hover { background: #059669; }
.btn-red       { background: var(--color-rose-solid); color: #fff; border: none; }
.btn-red:hover { background: #DC2626; }
.btn-yellow    { background: var(--color-amber-solid); color: #fff; border: none; }
.btn-yellow:hover { background: #D97706; }
.btn-blue      { background: var(--color-accent-solid); color: #fff; border: none; }
.btn-blue:hover { background: #1D4ED8; }

/* ---- Boutons discrets ----
   `.btn-ghost` (97 emplois, 12 gabarits), `.btn-red-ghost` et `.btn-blue`
   étaient écrits dans les gabarits sans avoir jamais été définis ici. Faute de
   règle, ils retombaient sur le bouton natif : c'est l'origine des pavés gris
   qui parasitaient les colonnes d'actions.

   Le survol se mélange à `currentColor` plutôt que d'appeler un jeton de fond :
   un voile teinté de la couleur du bouton marche dans les deux thèmes, alors
   que `--color-bg` est plus clair que la carte en clair et plus sombre en
   sombre — le même survol s'y inverserait. */
.btn-ghost {
  background: transparent;
  color: var(--color-text-muted);
  border: 1px solid transparent;
}
.btn-red-ghost {
  background: transparent;
  color: var(--color-rose);
  border: 1px solid transparent;
}
.btn-amber-ghost {
  background: transparent;
  color: var(--color-amber);
  border: 1px solid transparent;
}
.btn-ghost:hover      { color: var(--color-text); }
.btn-ghost:hover,
.btn-red-ghost:hover,
.btn-amber-ghost:hover {
  background: color-mix(in srgb, currentColor 14%, transparent);
  opacity: 1;
}

/* ---- Pastilles d'action teintées ----
   Pour les actions qui changent l'état d'un enregistrement (envoyer, accepter,
   refuser). Les aplats pleins `.btn-green` / `.btn-red` / `.btn-yellow` sont
   dimensionnés pour un bouton à libellé ; réduits à une pastille d'icône et
   alignés à six ou huit, ils devenaient des taches de couleur qui pesaient plus
   lourd que la donnée de la ligne. Le fond « pale » garde la lecture sémantique
   avec le même vocabulaire que les badges de la colonne Statut, juste à côté. */
.btn-green-soft { background: var(--color-emerald-pale); color: var(--color-emerald); border: 1px solid transparent; }
.btn-red-soft   { background: var(--color-rose-pale);    color: var(--color-rose);    border: 1px solid transparent; }
.btn-amber-soft { background: var(--color-amber-pale);   color: var(--color-amber);   border: 1px solid transparent; }
.btn-blue-soft  { background: var(--color-accent-pale);  color: var(--color-accent);  border: 1px solid transparent; }
.btn-green-soft:hover,
.btn-red-soft:hover,
.btn-amber-soft:hover,
.btn-blue-soft:hover { border-color: currentColor; opacity: 1; }

/* ---- Colonne « Actions » des tableaux ----
   Une grille fixe plutôt qu'un `flex-wrap`. Le nombre de boutons varie selon le
   statut de la ligne et les droits du compte : en enroulement libre chaque ligne
   cassait à un endroit différent et la colonne devenait un damier. Sur quatre
   colonnes, les boutons s'alignent aussi verticalement d'une ligne à l'autre. */
.row-actions {
  display: grid;
  grid-template-columns: repeat(4, var(--ctl-h-xs));
  gap: .25rem;
  justify-content: start;
}
/* Les `<form>` d'action portent `style="display:inline"` ; la grille les
   blockifie, ils comptent donc bien pour une case. Le bouton la remplit. */
.row-actions > .btn-xs,
.row-actions > form > .btn-xs { width: 100%; }

/* Un élément large — un badge de statut, pas un bouton — dans une grille de
   cases de 1,75 rem. Sans cette règle il déborde de sa case et se superpose au
   bouton voisin : c'est ce qui faisait passer « Remise à approuver » par-dessus
   la colonne d'actions. Il prend une ligne entière, sous les boutons. */
.row-actions > .row-actions-wide {
  grid-column: 1 / -1;
  width: fit-content;
  max-width: 100%;
}

/* ---- Colonne « Actions » : une action principale, le reste au menu ----
   La grille ci-dessus rangeait les boutons, elle ne les rendait pas lisibles :
   jusqu'à neuf pastilles d'icône sans libellé, sur trois rangs, dont la
   composition change avec le statut de la ligne — la troisième icône n'est pas
   la même d'une ligne à l'autre. Impossible de savoir ce que fait un bouton
   sans le survoler un par un, et deux d'entre eux sont irréversibles.

   On ne garde donc en ligne que l'action attendue à ce stade du devis (une
   seule, avec son libellé) et on renvoie le reste dans un menu où chaque entrée
   est écrite en toutes lettres. Le menu est en `position: fixed` : posé en
   absolu, il serait coupé par le défilement horizontal de `.table-responsive`. */
.actions-cell { display: flex; align-items: center; gap: .3rem; }
.action-primary {
  display: inline-flex; align-items: center; gap: .3rem;
  padding: .25rem .6rem;
  border: 1px solid transparent; border-radius: var(--radius-sm);
  font-size: var(--text-xs); font-weight: 600; white-space: nowrap; cursor: pointer;
  text-decoration: none;
}
.action-primary:hover { border-color: currentColor; text-decoration: none; }
/* Libellé « Plus » plutôt qu-un chevron seul : c-est le bouton qui remplace
   sept pastilles muettes, il doit dire qu-il y a autre chose derrière. */
.action-more {
  display: inline-flex; align-items: center; gap: .2rem;
  padding: .25rem .45rem .25rem .55rem;
  border: 1px solid var(--color-border); border-radius: var(--radius-sm);
  background: transparent; color: var(--color-text-muted);
  font-size: var(--text-xs); font-weight: 600; white-space: nowrap; cursor: pointer;
}
.action-more:hover, .action-more[aria-expanded="true"] {
  background: color-mix(in srgb, currentColor 14%, transparent);
  color: var(--color-text);
}
.action-menu {
  position: fixed; z-index: 1200;
  min-width: 212px; padding: .3rem;
  transform: translateX(-100%);
  background: var(--color-card);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  box-shadow: 0 12px 34px rgba(15, 23, 42, .22);
}
/* Ligne basse du tableau : le menu s-ouvre vers le haut plutôt que sous le pli. */
.action-menu--up { transform: translate(-100%, -100%); }
.action-menu form { display: block; }
.action-menu__head {
  padding: .35rem .55rem .2rem;
  font-size: var(--text-xs); font-weight: 700; text-transform: uppercase; letter-spacing: .5px;
  color: var(--color-text-muted);
}
.action-menu__item {
  display: flex; align-items: center; gap: .5rem;
  width: 100%; padding: .4rem .55rem;
  border: none; background: none; border-radius: var(--radius-sm);
  font-size: var(--text-xs); font-weight: 500; text-align: left; text-decoration: none;
  color: var(--color-text); cursor: pointer;
}
.action-menu__item:hover { background: var(--color-accent-pale); color: var(--color-accent); text-decoration: none; }
.action-menu__item > svg { flex-shrink: 0; opacity: .8; }
/* Refuser, supprimer : teintés au repos, pas seulement au survol — ce sont les
   deux entrées qu'on ne veut pas choisir par erreur en parcourant la liste. */
.action-menu__item--danger { color: var(--color-rose); }
.action-menu__item--danger:hover { background: var(--color-rose-pale); color: var(--color-rose); }
.action-menu__sep { height: 1px; margin: .25rem 0; background: var(--color-border); }

/* ---- Empty state ---- */
.empty-icon  { font-size: 2.5rem; margin-bottom: .75rem; }
.empty-title { font-weight: 600; color: var(--color-text); margin-bottom: .35rem; }
.empty-sub   { font-size: var(--text-sm); color: var(--color-text-muted); }

/* ---- Forms ---- */
.form-group { margin-bottom: 1rem; }
.form-label {
  display: block;
  font-size: var(--text-xs);
  font-weight: 600;
  color: var(--color-text-muted);
  margin-bottom: .35rem;
}
.form-input, .form-select, .form-textarea {
  width: 100%;
  min-height: var(--ctl-h);
  padding: .4rem .75rem;
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-sm);
  background: var(--color-card);
  color: var(--color-text);
  font-size: var(--text-sm);
  transition: border-color var(--transition), box-shadow var(--transition);
}
/* À la souris : bordure d'accent + halo, sans anneau (comportement d'origine).
   Ces sélecteurs sont plus spécifiques que la règle `:focus-visible` globale,
   donc `outline: none` l'emporterait aussi au clavier — d'où la règle dédiée
   ci-dessous, qui restaure l'anneau pour la navigation au clavier seulement. */
.form-input:focus, .form-select:focus, .form-textarea:focus {
  outline: none;
  border-color: var(--color-accent);
  box-shadow: 0 0 0 3px rgba(59,130,246,.15);
}
.form-input:focus-visible, .form-select:focus-visible, .form-textarea:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}
.form-textarea { resize: vertical; min-height: 80px; }
.pw-toggle {
  position: absolute;
  right: .5rem;
  top: 50%;
  transform: translateY(-50%);
  background: none;
  border: none;
  font-size: var(--text-sm);
  color: var(--color-text-muted);
  padding: .25rem;
}

/* ---- Search ---- */
.search-bar {
  position: relative;
  max-width: 280px;
}
.search-bar input {
  padding-left: 2.2rem;
}
.search-icon {
  position: absolute;
  left: .6rem;
  top: 50%;
  transform: translateY(-50%);
  color: var(--color-text-muted);
  font-size: var(--text-sm);
  pointer-events: none;
}

/* ---- Tabs ---- */
.tab-bar {
  display: flex;
  gap: 2px;
  border-bottom: 1px solid var(--color-border);
  margin-bottom: 1.25rem;
  flex-wrap: wrap;
}
.tab-btn {
  padding: .5rem 1rem;
  background: none;
  border: none;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  min-height: var(--ctl-h);
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--color-text-muted);
  transition: color var(--transition), border-color var(--transition);
  cursor: pointer;
  white-space: nowrap;
}
.tab-btn:hover        { color: var(--color-text); }
.tab-btn.active,
.tab-btn--active      { color: var(--color-accent); border-bottom-color: var(--color-accent); font-weight: 600; }

/* Settings / KB sidebar nav */
.settings-nav-item {
  display: block;
  width: 100%;
  text-align: left;
  background: none;
  border: none;
  padding: .55rem 1rem;
  font-size: var(--text-xs);
  color: var(--color-text);
  cursor: pointer;
  transition: background var(--transition);
  text-decoration: none;
}
.settings-nav-item:hover  { background: var(--color-accent-pale); color: var(--color-accent); }
.settings-nav-item.active { background: var(--color-accent-pale); color: var(--color-accent); font-weight: 600; }

/* ---- Alerts / Flash ---- */
.flash-container { padding: 0 1.5rem; margin-top: .75rem; }
.flash {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: .75rem 1rem;
  border-radius: var(--radius-sm);
  font-size: var(--text-xs);
  margin-bottom: .5rem;
  animation: fadeIn .2s ease;
}
.flash-success { background: var(--color-emerald-pale); color: var(--color-emerald); border: 1px solid var(--color-emerald); }
.flash-danger,
.flash-error   { background: var(--color-rose-pale);    color: var(--color-rose);    border: 1px solid var(--color-rose); }
.flash-warning { background: var(--color-amber-pale);   color: var(--color-amber);   border: 1px solid var(--color-amber); }
.flash-info    { background: var(--color-accent-pale);  color: var(--color-accent);  border: 1px solid var(--color-accent); }
.flash-close   { background: none; border: none; font-size: var(--text-md); cursor: pointer; }
/* Champ obligatoire resté vide après un refus (voir main.js). */
main [aria-invalid="true"] { border-color: var(--color-rose) !important; box-shadow: 0 0 0 2px var(--color-rose-pale); }

.alert { padding: .75rem 1rem; border-radius: var(--radius-sm); font-size: var(--text-xs); margin-bottom: 1rem; }
.alert-danger { background: var(--color-rose-pale); color: var(--color-rose); border: 1px solid var(--color-rose); }

/* ---- Bandeaux d'état (notices) ----
   « Configuration incomplète », « période de préavis », alertes d'expiration :
   trois bandeaux écrits à la main, chacun avec ses couleurs en dur (#fef2f2,
   #fffbeb, #991b1b…). En thème sombre ces teintes claires produisaient une
   bande blanche en haut de l'application, texte bordeaux sur rose — le défaut
   le plus visible de l'interface, et il annonçait justement les pannes.

   Un seul composant, tiré des tokens de thème, sert les trois cas. La couleur
   d'accent passe par `--notice-color`, si bien qu'une variante se déclare en
   une ligne. `--notice-tint` est déjà semi-transparent en sombre : le fond
   reste celui de la page, à peine teinté, au lieu d'un aplat lumineux. */
.notice {
  display: flex;
  align-items: flex-start;
  gap: .65rem;
  padding: .7rem .9rem;
  border: 1px solid var(--notice-line);
  border-left: 3px solid var(--notice-color);
  border-radius: var(--radius-sm);
  background: var(--notice-tint);
  color: var(--color-text);
  font-size: var(--text-xs);
  line-height: 1.5;
}
.notice + .notice { margin-top: .4rem; }
.notice__icon  { flex-shrink: 0; display: flex; color: var(--notice-color); margin-top: .05rem; }
.notice__body  { flex: 1; min-width: 0; }
.notice__title {
  display: flex; align-items: center; gap: .4rem;
  font-weight: 700; color: var(--notice-color);
}
.notice__title + * { margin-top: .3rem; }
.notice__text  { color: var(--color-text); }
.notice__hint  { display: block; color: var(--color-text-muted); font-size: var(--text-xs); }
.notice__refs  { font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace); font-size: var(--text-xs); color: var(--notice-color); }
/* Pastille de comptage : le nombre de pannes se lit avant la phrase. */
.notice__count {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 18px; height: 18px; padding: 0 5px;
  border-radius: 9px; font-size: var(--text-xs); font-weight: 700;
  background: var(--notice-color); color: var(--color-card);
}
.notice__list { margin: 0; padding: 0; list-style: none; display: grid; gap: .3rem; }
.notice__list > li { position: relative; padding-left: .85rem; }
.notice__list > li::before {
  content: ""; position: absolute; left: 0; top: .55em;
  width: 5px; height: 5px; border-radius: 50%;
  background: var(--notice-color); opacity: .75;
}
.notice__close {
  flex-shrink: 0; display: flex; align-items: center;
  background: none; border: none; cursor: pointer; padding: .15rem;
  border-radius: var(--radius-sm); color: var(--color-text-muted);
}
.notice__close:hover { background: color-mix(in srgb, var(--notice-color) 16%, transparent); color: var(--notice-color); }
/* Pleine largeur, collé sous la topbar : pas de rayon, pas de bordure
   flottante, seulement un filet de séparation et le liseré de gauche. */
.notice--bar {
  border: 0;
  border-bottom: 1px solid var(--notice-line);
  box-shadow: inset 3px 0 0 var(--notice-color);
  border-radius: 0;
  padding: .7rem 1.5rem;
}
.notice--danger  { --notice-color: var(--color-rose);    --notice-tint: var(--color-rose-pale);    --notice-line: color-mix(in srgb, var(--color-rose) 32%, transparent); }
.notice--warning { --notice-color: var(--color-amber);   --notice-tint: var(--color-amber-pale);   --notice-line: color-mix(in srgb, var(--color-amber) 32%, transparent); }
.notice--info    { --notice-color: var(--color-accent);  --notice-tint: var(--color-accent-pale);  --notice-line: color-mix(in srgb, var(--color-accent) 32%, transparent); }
.notice--success { --notice-color: var(--color-emerald); --notice-tint: var(--color-emerald-pale); --notice-line: color-mix(in srgb, var(--color-emerald) 32%, transparent); }

/* ---- Barre de filtres ----
   Les champs étaient sans bordure ni fond : sur la liste des devis, « Tous les
   statuts » et les deux dates flottaient dans la barre sans qu'on les voie
   comme des commandes. Ici chaque filtre est une pastille, et une pastille
   renseignée prend la couleur d'accent — l'état du filtrage se lit d'un coup
   d'œil, sans avoir à lire les valeurs. */
.filter-bar {
  display: flex; flex-wrap: wrap; align-items: center; gap: .45rem;
  padding: .5rem .6rem; margin-bottom: .9rem;
  background: var(--color-card);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
}
.filter-search {
  display: flex; align-items: center; gap: .45rem;
  flex: 1 1 200px; min-width: 160px; padding-left: .3rem;
  color: var(--color-text-muted);
}
.filter-search input {
  flex: 1; min-width: 0;
  border: none; outline: none; background: transparent;
  color: var(--color-text); font-size: var(--text-xs);
}
.filter-select, .filter-date {
  padding: .28rem .6rem;
  border: 1px solid var(--color-border);
  border-radius: 99px;
  background: var(--color-bg);
  color: var(--color-text);
  font-size: var(--text-xs); font-weight: 600;
  cursor: pointer; max-width: 180px;
}
.filter-select {
  appearance: none; -webkit-appearance: none;
  padding-right: 1.5rem;
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2394A3B8' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right .45rem center;
  background-size: 11px;
  text-overflow: ellipsis;
}
.filter-date { font-weight: 500; }
.filter-select:hover, .filter-date:hover { border-color: var(--color-text-muted); }
.filter-select.is-active, .filter-date.is-active {
  border-color: var(--color-accent);
  background-color: var(--color-accent-pale);
  color: var(--color-accent);
}
.filter-sep   { width: 1px; height: 20px; background: var(--color-border); flex-shrink: 0; }
.filter-count { margin-left: auto; font-size: var(--text-xs); color: var(--color-text-muted); white-space: nowrap; padding-right: .2rem; }
.filter-reset {
  display: inline-flex; align-items: center; gap: .3rem;
  padding: .28rem .6rem; border-radius: 99px;
  border: 1px solid var(--color-rose); background: var(--color-rose-pale);
  color: var(--color-rose); font-size: var(--text-xs); font-weight: 600; cursor: pointer;
}
.filter-reset:hover { background: color-mix(in srgb, var(--color-rose) 22%, transparent); }

/* ---- Login page ---- */
.login-page {
  background: linear-gradient(135deg, #14244A 0%, #0A1324 100%);
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
}
.login-card {
  background: var(--color-card);
  border-radius: var(--radius-lg);
  padding: 2.5rem;
  width: 100%;
  max-width: 420px;
  box-shadow: var(--shadow-lg);
}
.login-logo  { text-align: center; margin-bottom: 2rem; }
.login-title { font-size: var(--text-lg); font-weight: 700; margin-top: .5rem; }
.login-sub   { color: var(--color-text-muted); font-size: var(--text-xs); margin-top: .25rem; }
.link-muted  { color: var(--color-text-muted); font-size: var(--text-xs); }
.link-muted:hover { color: var(--color-accent); }
/* Pages de connexion en sombre : le logo à texte marine disparaissait sur la
   carte ardoise. On prend la version blanche, déjà employée par la sidebar. */
:root[data-theme="dark"] .login-logo img[src*="Creer_Societe_Dubai.svg"] {
  content: url("../img/Creer_Societe_Dubai_white.svg");
}

/* ---- Modal ---- */
.modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,.5);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 500;
}

/* Variante héritée des écrans Alpine, recopiée à l'identique dans cinq gabarits
   — et absente d'`invoices/index.html`, qui l'utilise pourtant trois fois sans
   avoir de bloc `<style>` du tout. Les modales « Nouvelle facture », « Paiement
   partiel » et « Avoir » s'affichaient donc dans le flux du document : ni fond
   assombri, ni centrage, ni superposition. La règle vit ici désormais ; les
   gabarits qui la redéfinissent après `main.css` continuent de l'emporter. */
.qmodal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,.45);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
  z-index: 9999;
}
.modal-box {
  background: var(--color-card);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  width: 100%;
  max-width: 560px;
  max-height: 90vh;
  overflow-y: auto;
}
.modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 1.1rem 1.5rem;
  border-bottom: 1px solid var(--color-border);
}
.modal-title  { font-weight: 600; font-size: var(--text-md); }
.modal-close  { background: none; border: none; font-size: var(--text-md); color: var(--color-text-muted); }
.modal-body   { padding: 1.5rem; }
.modal-footer { padding: 1rem 1.5rem; border-top: 1px solid var(--color-border); display: flex; gap: .75rem; justify-content: flex-end; }

/* ---- Progress bar ---- */
.progress { background: var(--color-border); border-radius: 99px; overflow: hidden; }
.progress-bar { height: 100%; border-radius: 99px; transition: width .3s ease; background: var(--color-accent-vivid); }

/* ---- Empty state ---- */
.empty-state {
  text-align: center;
  padding: 3.5rem 1rem;
  color: var(--color-text-muted);
}
.empty-state-icon  { font-size: 2.5rem; margin-bottom: .75rem; }
.empty-state-title { font-weight: 600; color: var(--color-text); margin-bottom: .35rem; }

/* ---- HTMX loading indicator ---- */
.htmx-indicator { display: none; }
.htmx-request .htmx-indicator { display: inline-block; }
.htmx-request.htmx-indicator  { display: inline-block; }

/* ---- Animations ---- */
@keyframes fadeIn { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: translateY(0); } }

/* Voile du tiroir mobile — masqué au-dessus de 768 px, où la sidebar est
   affichée en permanence. Défini AVANT la media query : à spécificité égale,
   c'est l'ordre source qui tranche. */
.sidebar-backdrop {
  display: none;
  position: fixed;
  inset: 0;
  background: rgba(2, 6, 23, .5);
  z-index: 90;             /* sous la sidebar (100), au-dessus du contenu */
}

/* ---- Responsive ---- */
@media (max-width: 768px) {
  /* Tiroir fermé : `visibility` le sort aussi du parcours clavier et des
     lecteurs d'écran — hors écran, ses liens prenaient encore le focus. */
  .sidebar { transform: translateX(-100%); visibility: hidden; }
  .sidebar.mobile-open { transform: translateX(0); visibility: visible; }
  .main-wrapper { margin-left: 0 !important; }
  .kpi-grid { grid-template-columns: repeat(2, 1fr); }

  /* La topbar ne se réduisait pas : sélecteur d'impersonation, libellé du rôle
     et titre de page en `nowrap` la maintenaient à 448 px de large, ce qui
     débordait de 183 px sur un écran de 390 px. On dégrade par priorité —
     l'impersonation (super-admin, usage bureau) et le texte d'identité passent
     à la trappe ; l'avatar et les actions restent atteignables. */
  .topbar { padding: 0 .75rem; gap: .35rem; }
  .topbar-title {
    min-width: 0;
    font-size: var(--text-sm);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .topbar-right { min-width: 0; }
  .topbar-impersonate,
  .topbar-user-meta { display: none; }
  .topbar-user { padding-left: .5rem; margin-left: 0; }

  /* Tiroir de navigation : toujours pleine largeur, même si l'état bureau
     persisté est « replié ». */
  .sidebar.mobile-open {
    width: var(--sidebar-width);
    min-width: var(--sidebar-width);
    box-shadow: var(--shadow-lg);
  }
  .sidebar-nav { overflow-y: auto; }
  .sidebar-backdrop { display: block; }
}

/* =============================================
   DASHBOARD — Composants spécifiques
   ============================================= */

/* ---- Utilitaires Flexbox ---- */
.d-flex           { display: flex; }
.align-items-center { align-items: center; }
.justify-between  { justify-content: space-between; }
.justify-end      { justify-content: flex-end; }
.flex-wrap        { flex-wrap: wrap; }
.flex-col         { flex-direction: column; }
.gap-1            { gap: .25rem; }
.gap-2            { gap: .5rem; }
.gap-3            { gap: .75rem; }
.gap-4            { gap: 1rem; }
.flex-1           { flex: 1; }

/* ---- Utilitaires Spacing ---- */
.mb-1 { margin-bottom: .25rem; }
.mb-2 { margin-bottom: .5rem; }
.mb-3 { margin-bottom: .75rem; }
.mb-4 { margin-bottom: 1rem; }
.mb-5 { margin-bottom: 1.5rem; }
.mt-1 { margin-top: .25rem; }
.mt-2 { margin-top: .5rem; }
.mt-3 { margin-top: .75rem; }
.mt-4 { margin-top: 1rem; }
.ml-auto { margin-left: auto; }

/* ---- Utilitaires Texte ---- */
.text-muted       { color: var(--color-text-muted); }
.text-light       { color: var(--color-text-light); }
.text-sm          { font-size: var(--text-xs); }
.font-bold        { font-weight: 700; }
.text-center      { text-align: center; }

/* ---- Page title ---- */
.page-title {
  font-size: var(--text-xl);
  font-weight: 600;
  letter-spacing: -.01em;
  line-height: 1.2;
  color: var(--color-text);
}

/* ---- Card header / body ---- */
.card {
  /* override pour permettre padding interne custom */
  padding: 0;
}
.card-header {
  padding: .75rem 1.1rem;
  border-bottom: 1px solid var(--color-border);
  font-weight: 600;
  display: flex;
  align-items: center;
  justify-content: space-between;
  background: var(--color-card);
  border-radius: var(--radius-md) var(--radius-md) 0 0;
}
.card-body {
  padding: 1rem 1.1rem;
}

/* ---- KPI card — amélioré ---- */
.kpi-card {
  position: relative;
  padding: 14px 16px;
}
/* La couleur d'une carte se portait par un liseré gauche de 3 px. Dix cartes
   côte à côte donnaient dix liserés de dix teintes : la couleur ne distinguait
   plus rien. Elle passe sur l'icône — présente quand la carte a un sens — et
   le contour redevient celui de toutes les cartes. */
.kpi-icon {
  font-size: var(--text-lg);
  margin-bottom: .35rem;
  display: block;
  color: var(--kpi-color, var(--color-text-muted));
}
/* Les gabarits passent des teintes foncées (#065f46, #4338ca…), choisies pour
   un liseré sur fond clair : sur la carte sombre elles tombaient à 2,3:1. */
:root[data-theme="dark"] .kpi-icon,
.dark .kpi-icon { color: color-mix(in srgb, var(--kpi-color, var(--color-text-muted)) 55%, #fff); }
.kpi-trend {
  display: inline-flex;
  align-items: center;
  font-size: var(--text-xs);
  font-weight: 600;
  margin-top: .35rem;
}
.kpi-trend.positive { color: var(--color-emerald); }
.kpi-trend.negative { color: var(--color-rose); }

/* ---- Today widget ---- */
.today-widget-item {
  padding: 14px 16px;
  border-radius: var(--radius-sm);
  background: var(--color-card);
  border-left: 3px solid var(--tw-color, var(--color-accent));
}
.tw-value {
  font-size: var(--text-xl);
  font-weight: 700;
  color: var(--tw-color, var(--color-accent));
}
.tw-label {
  font-size: var(--text-xs);
  font-weight: 600;
  color: var(--color-text);
  margin-top: 3px;
}

/* « Tout voir » en tête de carte du tableau de bord : chaque bloc résume une
   page, ce lien y mène. */
.card-more {
  display: inline-flex;
  align-items: center;
  gap: .25rem;
  font-size: var(--text-xs);
  font-weight: 600;
  color: var(--color-accent);
  text-decoration: none;
  white-space: nowrap;
}
.card-more:hover { text-decoration: underline; color: var(--color-accent); }
/* Tuiles du tableau de bord qui mènent à la liste qu'elles comptent. */
a.today-widget-item--link { display: block; text-decoration: none; color: inherit; transition: box-shadow var(--transition), transform var(--transition); }
a.today-widget-item--link:hover { box-shadow: var(--shadow-md); transform: translateY(-2px); color: inherit; }
a.score-tile { display: block; text-decoration: none; color: inherit; border-radius: var(--radius-sm); transition: background var(--transition); }
a.score-tile:hover { background: var(--color-bg); color: inherit; }

/* ---- Badge process statuses ---- */
.badge-on_track   { color: var(--color-emerald); background: var(--color-emerald-pale); }
.badge-delayed    { color: var(--color-rose);    background: var(--color-rose-pale); }
.badge-completed  { color: #6366F1;              background: #EEF2FF; }
.badge-cancelled  { color: var(--color-text-muted); background: var(--color-bg); }

/* ---- Table variants ---- */
.table     { width: 100%; border-collapse: collapse; }
.table-sm thead th { padding: .5rem .75rem; font-size: var(--text-xs); }
.table-sm tbody td { padding: .55rem .75rem; font-size: var(--text-xs); }

/* ---- Button close ---- */
.btn-close {
  background: none;
  border: none;
  font-size: var(--text-md);
  color: var(--color-text-muted);
  cursor: pointer;
  padding: .1rem .35rem;
  border-radius: var(--radius-sm);
  transition: background var(--transition);
}
.btn-close:hover { background: var(--color-bg); }

/* =============================================
   PHASE 3 — Composants modules
   ============================================= */

/* ---- Page header ---- */
.page-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  margin-bottom: 1.5rem;
  flex-wrap: wrap;
  gap: .75rem;
}
.page-title .ico { width: .8em; height: .8em; }
.page-subtitle { font-size: var(--text-sm); color: var(--color-text-muted); margin-top: .2rem; }
.back-link { font-size: var(--text-xs); color: var(--color-accent); text-decoration: none; display: inline-flex; align-items: center; gap: .3rem; }
.back-link:hover { text-decoration: underline; }

/* ---- Link helpers ---- */
.company-link { font-weight: 600; color: var(--color-accent); text-decoration: none; }
.company-link:hover { text-decoration: underline; }
.hover-underline:hover { text-decoration: underline; }

/* ---- Filter bar ---- */
.filter-bar {
  display: flex;
  flex-wrap: wrap;
  gap: .5rem;
  align-items: center;
  margin-bottom: 1rem;
}
.input-search {
  min-height: var(--ctl-h);
  padding: .4rem .75rem;
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-sm);
  font-size: var(--text-sm);
  min-width: 200px;
  background: var(--color-card);
  color: var(--color-text);
  transition: border-color var(--transition);
}
.input-search:focus { outline: none; border-color: var(--color-accent); }
.input-search:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }
.input-select {
  min-height: var(--ctl-h);
  padding: .4rem .75rem;
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-sm);
  font-size: var(--text-sm);
  background: var(--color-card);
  color: var(--color-text);
  transition: border-color var(--transition);
}
.input-select:focus { outline: none; border-color: var(--color-accent); }
.input-select:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }

/* ---- Data table (composant card) ---- */
.data-table { width: 100%; border-collapse: collapse; font-size: var(--text-sm); }
.data-table th {
  text-align: left;
  padding: .6rem .75rem;
  font-size: var(--text-xs);
  font-weight: 600;
  color: var(--color-text-muted);
  border-bottom: 1px solid var(--color-border);
}
.data-table td {
  padding: .65rem .75rem;
  border-bottom: 1px solid var(--color-border);
  vertical-align: middle;
}
.data-table tbody tr:hover { background: color-mix(in srgb, var(--color-text) 3.5%, transparent); }
.data-table tbody tr:last-child td { border-bottom: none; }

/* Tableaux à forte densité de colonnes (Contacts : 13 colonnes).
   Comprimés dans la largeur disponible, les cellules se replient sur 4-5 lignes
   et la hauteur de ligne explose. Mesuré sur /contacts en 1440 :

       largeur table   ligne max   ligne médiane
       1230 (auto)       130 px        96 px
       1400               93 px        70 px
       1500               68 px        66 px   ← palier
       1600               68 px        62 px

   À partir de 1500 px le gain s'annule : on s'arrête là. Le tableau défile
   horizontalement dans sa carte (voir `.card:has(> .data-table)`), au profit
   d'environ deux fois plus de lignes visibles sans défilement vertical.

   Classe opt-in : appliquée aux seuls tableaux larges, pour ne pas imposer un
   défilement horizontal aux tableaux de 4 colonnes. */
.data-table--wide { min-width: 1500px; }
.data-table--wide th { white-space: nowrap; }

/* ---- Info grid / block ---- */
.info-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 1.5rem; }
.info-block {
  background: var(--color-card);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: 1.25rem;
  box-shadow: var(--shadow-sm);
}
.info-block-title {
  font-size: var(--text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .07em;
  color: var(--color-text-muted);
  margin-bottom: .75rem;
}
.info-dl { display: grid; grid-template-columns: 1fr 1.6fr; gap: .4rem .75rem; font-size: var(--text-xs); }
.info-dl dt { color: var(--color-text-muted); align-self: start; padding-top: .1rem; }
.info-dl dd { color: var(--color-text); font-weight: 500; margin: 0; word-break: break-word; }

/* ---- Tabs Alpine.js ---- */
.tabs-nav { margin-top: 1.5rem; }
.tabs-list {
  display: flex;
  gap: .25rem;
  border-bottom: 1px solid var(--color-border);
  margin-bottom: 1.25rem;
  flex-wrap: wrap;
}
.tab-active { color: var(--color-accent) !important; border-bottom-color: var(--color-accent) !important; font-weight: 600 !important; }
.tab-panel { padding: .5rem 0; }

/* ---- Progress bar (wrap variant) ---- */
.progress-bar-wrap {
  background: var(--color-border);
  border-radius: 99px;
  height: 6px;
  overflow: hidden;
}
.progress-bar-success { background: var(--color-emerald-vivid); }
.progress-bar-danger  { background: var(--color-rose-vivid); }
.progress-bar-info    { background: var(--color-accent-vivid); }
.progress-bar-muted   { background: var(--color-text-light); }

/* ---- KPI row ---- */
.kpi-row { display: flex; gap: 1rem; flex-wrap: wrap; margin-bottom: 1.5rem; }
.kpi-row .kpi-card { flex: 1; min-width: 150px; }

/* ---- Kanban ---- */
.kanban-board { display: flex; gap: .75rem; overflow-x: auto; padding-bottom: 1rem; }
.kanban-col {
  min-width: 210px;
  background: var(--color-card);
  border-radius: var(--radius-md);
  border: 1px solid var(--color-border);
  display: flex;
  flex-direction: column;
  box-shadow: var(--shadow-sm);
}
.kanban-col-header {
  padding: .55rem .85rem;
  font-size: var(--text-xs);
  font-weight: 600;
  border-bottom: 1px solid var(--color-border);
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.kanban-count {
  background: var(--color-border);
  border-radius: 99px;
  min-width: 1.4rem;
  height: 1.4rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: var(--text-xs);
  color: var(--color-text-muted);
  padding: 0 .3rem;
}
.kanban-card {
  margin: .4rem .5rem;
  padding: .7rem .85rem;
  background: var(--color-bg);
  border-radius: var(--radius-sm);
  border: 1px solid var(--color-border);
  font-size: var(--text-xs);
}
.kanban-card-title { font-weight: 600; font-size: var(--text-xs); margin-bottom: .2rem; }
.kanban-empty { padding: 1rem; text-align: center; color: var(--color-text-muted); font-size: var(--text-xs); }

/* Le défilement du kanban doit s'annoncer. Sur macOS les barres flottantes
   n'apparaissent qu'au geste : sur un type à douze étapes, rien ne signalait
   que cinq colonnes attendaient hors champ. On force une piste permanente. */
#kanban-grid, .kanban-board {
  scrollbar-width: thin;
  scrollbar-color: var(--color-border) transparent;
}
#kanban-grid::-webkit-scrollbar,
.kanban-board::-webkit-scrollbar { height: 8px; }
#kanban-grid::-webkit-scrollbar-track,
.kanban-board::-webkit-scrollbar-track { background: transparent; }
#kanban-grid::-webkit-scrollbar-thumb,
.kanban-board::-webkit-scrollbar-thumb { background: var(--color-border); border-radius: 99px; }
#kanban-grid::-webkit-scrollbar-thumb:hover,
.kanban-board::-webkit-scrollbar-thumb:hover { background: var(--color-text-light); }

/* ---- Form extras ---- */
.form-control {
  width: 100%;
  min-height: var(--ctl-h);
  padding: .4rem .75rem;
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-sm);
  font-size: var(--text-sm);
  background: var(--color-card);
  color: var(--color-text);
  transition: border-color var(--transition);
}
.form-control:focus { outline: none; border-color: var(--color-accent); box-shadow: 0 0 0 3px rgba(59,130,246,.15); }
.form-control:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }
.form-row  { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; margin-bottom: 1rem; }
.grid-3    { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem; margin-bottom: 1rem; }
.grid-4    { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1rem; margin-bottom: 1rem; }
.form-check { display: flex; align-items: center; gap: .5rem; font-size: var(--text-xs); cursor: pointer; }
.form-checks { display: flex; gap: 1.25rem; flex-wrap: wrap; margin-top: .5rem; }
.form-section-title {
  font-size: var(--text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .07em;
  color: var(--color-accent);
  padding-bottom: .5rem;
  border-bottom: 1px solid var(--color-border);
  margin-bottom: 1rem;
}

/* ---- Badge extras ---- */
.badge-outline { border: 1px solid var(--color-border); color: var(--color-text-muted); background: transparent; font-size: var(--text-xs); padding: .15rem .5rem; border-radius: 99px; }

/* ---- Alert extras ---- */
.alert-warning { background: var(--color-amber-pale); color: var(--color-amber); border: 1px solid var(--color-amber); }
.alert-info    { background: var(--color-accent-pale); color: var(--color-accent); border: 1px solid var(--color-accent); }
.alert-success { background: var(--color-emerald-pale); color: var(--color-emerald); border: 1px solid var(--color-emerald); }

/* ---- Utility aliases ---- */
.flex         { display: flex; }
.items-center { align-items: center; }
.mt-6         { margin-top: 1.5rem; }
.text-xs      { font-size: var(--text-xs); }
.text-danger  { color: var(--color-rose); }
.text-warning { color: var(--color-amber); }
.text-success { color: var(--color-emerald); }

/* ---- Surface alt (ex: row hover) ---- */
.bg-surface-alt { background: var(--color-bg); }

/* ---- Toggle switch ---- */
.toggle-track {
  display: inline-flex;
  align-items: center;
  width: 44px;
  height: 24px;
  border-radius: 12px;
  background: #CBD5E1;
  cursor: pointer;
  transition: background .2s;
  flex-shrink: 0;
  position: relative;
}
.toggle-track.is-on { background: #3B82F6; }
.toggle-thumb {
  position: absolute;
  left: 2px;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 1px 3px rgba(0,0,0,.3);
  transition: transform .2s;
}
.toggle-track.is-on .toggle-thumb { transform: translateX(20px); }


/* =============================================
   Matrice des permissions — Paramètres › Rôles & accès
   =============================================
   Cet écran était entièrement stylé en ligne, avec un `:style` Alpine posé
   par-dessus pour la couleur d'état. Or `x-bind:style` en forme *chaîne* fait
   `setAttribute('style', …)` : il ne fusionne pas, il REMPLACE l'attribut. À
   chaque rendu les lignes perdaient donc leur `display:flex`, les boutons leur
   `width:36px` et les pastilles leur forme — d'où les carrés noirs et la
   colonne en escalier.

   La correction est structurelle : la mise en forme vit ici, l'état ne voyage
   plus que par `:class`. Rien à écraser, donc rien à perdre.

   Second effet : les teintes codées en dur (#f0fdf420, #d1fae5…) faisaient
   mordre le pont de compatibilité ci-dessous — ses sélecteurs `[style*=…]`
   travaillent par sous-chaîne et ne voient pas l'alpha `20`. Un voile à 12 %
   sur ardoise était donc traité comme un aplat clair et recevait
   `color:#1E293B !important` : du texte quasi noir sur fond sombre. Plus
   aucune valeur littérale ici, le problème ne peut pas se reposer. */

.perm-legend {
  display: flex;
  gap: 1.5rem;
  padding: .4rem 1rem .75rem;
  border-bottom: 1px solid var(--color-border);
  font-size: var(--text-xs);
  color: var(--color-text-muted);
}
.perm-legend > span { display: flex; align-items: center; gap: 4px; }
.perm-swatch {
  display: inline-block;
  width: 12px; height: 12px;
  border-radius: 3px;
  background: var(--color-bg);
  border: 1px solid var(--color-border);
}
.perm-swatch.is-read  { background: var(--color-accent-pale);  border-color: var(--color-accent); }
.perm-swatch.is-write { background: var(--color-emerald-pale); border-color: var(--color-emerald); }

/* Actions en masse */
.perm-bulk { display: flex; gap: .4rem; }
.perm-bulk-btn {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: var(--text-xs);
  padding: 3px 8px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--color-border);
  background: var(--color-bg);
  color: var(--color-text-muted);
  cursor: pointer;
  transition: var(--transition);
}
.perm-bulk-btn:hover { border-color: var(--color-text-muted); color: var(--color-text); }
.perm-bulk-btn.is-read  { border-color: var(--color-accent);  background: var(--color-accent-pale);  color: var(--color-accent); }
.perm-bulk-btn.is-write { border-color: var(--color-emerald); background: var(--color-emerald-pale); color: var(--color-emerald); }
.perm-bulk-btn .ico { flex: none; }

/* Groupes et lignes */
.perm-group-title {
  padding: .5rem 1rem .25rem;
  font-size: var(--text-xs);
  font-weight: 700;
  color: var(--color-text-muted);
  text-transform: uppercase;
  letter-spacing: .07em;
}
.perm-row {
  display: flex;
  align-items: center;
  gap: .35rem;
  padding: .45rem 1rem;
  border-bottom: 1px solid var(--color-border);
  transition: background var(--transition);
}
/* Voile d'état : dérivé du jeton de thème, jamais d'une valeur littérale. */
.perm-row.is-read  { background: color-mix(in srgb, var(--color-accent-vivid)  8%, transparent); }
.perm-row.is-write { background: color-mix(in srgb, var(--color-emerald-vivid) 8%, transparent); }

.perm-row-icon  { flex: none; width: 22px; font-size: var(--text-base); }
.perm-row-label { flex: 1; min-width: 0; font-size: var(--text-xs); font-weight: 500; color: var(--color-text); }

/* Sélecteur trois états */
.perm-toggle {
  display: inline-flex;
  flex: none;
  border-radius: var(--radius-sm);
  overflow: hidden;
  border: 1px solid var(--color-border);
}
.perm-toggle button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  padding: 5px 0;
  font-size: var(--text-sm);
  line-height: 1;
  border: none;
  background: var(--color-card);
  color: var(--color-text-muted);
  cursor: pointer;
  transition: var(--transition);
}
.perm-toggle button + button { border-left: 1px solid var(--color-border); }
.perm-toggle button:hover { color: var(--color-text); }
.perm-toggle button.is-active { font-weight: 700; }
.perm-toggle button.is-active[data-level="none"]  { background: var(--color-rose-pale);    color: var(--color-rose); }
.perm-toggle button.is-active[data-level="read"]  { background: var(--color-accent-pale);  color: var(--color-accent); }
.perm-toggle button.is-active[data-level="write"] { background: var(--color-emerald-pale); color: var(--color-emerald); }

/* Pastille de statut */
.perm-badge {
  flex: none;
  margin-left: .6rem;
  width: 64px;
  text-align: center;
  font-size: var(--text-xs);
  font-weight: 600;
  padding: 2px 6px;
  border-radius: 10px;
  background: var(--color-bg);
  color: var(--color-text-muted);
  transition: var(--transition);
}
.perm-badge.is-read  { background: var(--color-accent-pale);  color: var(--color-accent); }
.perm-badge.is-write { background: var(--color-emerald-pale); color: var(--color-emerald); }

/* Suppression d'un rôle */
.perm-delete-btn {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  border: 1px solid var(--color-rose);
  background: var(--color-rose-pale);
  color: var(--color-rose);
  padding: 6px 12px;
  border-radius: var(--radius-sm);
  font-size: var(--text-xs);
  font-weight: 600;
  cursor: pointer;
  transition: var(--transition);
}
.perm-delete-btn:hover { background: var(--color-rose-solid); color: #fff; border-color: var(--color-rose-solid); }


/* =============================================
   Pont de compatibilité — styles en ligne & mode sombre
   =============================================
   Les templates portent 5 465 attributs `style=` et 2 972 couleurs codées en
   dur. Un style en ligne l'emporte sur toute règle de feuille de style : en
   mode sombre, un `color:#0f172a` reste donc noir sur fond ardoise. Mesuré sur
   les 19 modules : 259 éléments sous 3:1, dont du texte à 1,0:1 (invisible).

   Reprendre les 5 465 attributs est la migration écartée. Cette couche traite
   les deux causes systémiques sans toucher aux templates.

   Garde-fou central : on ne requalifie un texte sombre que si l'élément ne
   porte PAS lui-même de fond. Les pastilles sémantiques (`background:#fee2e2`
   + `color:#991b1b`) sont cohérentes seules et restent lisibles dans les deux
   thèmes — les toucher les casserait. `:not([style*="background"])` exprime
   exactement cette distinction.

   À supprimer intégralement une fois la migration des styles en ligne faite. */

:root[data-theme="dark"] :is(
  [style*="color:#1e293b;" i],
  [style*="color:#1e293b" i],
  [style*="color: #1e293b;" i],
  [style*="color: #1e293b" i],
  [style*="color:#0f172a;" i],
  [style*="color:#0f172a" i],
  [style*="color: #0f172a;" i],
  [style*="color: #0f172a" i],
  [style*="color:#374151;" i],
  [style*="color:#374151" i],
  [style*="color: #374151;" i],
  [style*="color: #374151" i],
  [style*="color:#334155;" i],
  [style*="color:#334155" i],
  [style*="color: #334155;" i],
  [style*="color: #334155" i],
  [style*="color:#475569;" i],
  [style*="color:#475569" i],
  [style*="color: #475569;" i],
  [style*="color: #475569" i],
  [style*="color:#111827;" i],
  [style*="color:#111827" i],
  [style*="color: #111827;" i],
  [style*="color: #111827" i],
  [style*="color:#1f2937;" i],
  [style*="color:#1f2937" i],
  [style*="color: #1f2937;" i],
  [style*="color: #1f2937" i],
  [style*="color:#1e3a5f;" i],
  [style*="color:#1e3a5f" i],
  [style*="color: #1e3a5f;" i],
  [style*="color: #1e3a5f" i],
  [style*="color:#1a3a5c;" i],
  [style*="color:#1a3a5c" i],
  [style*="color: #1a3a5c;" i],
  [style*="color: #1a3a5c" i],
  [style*="color:#3f3f46;" i],
  [style*="color:#3f3f46" i],
  [style*="color: #3f3f46;" i],
  [style*="color: #3f3f46" i],
  [style*="color:#18181b;" i],
  [style*="color:#18181b" i],
  [style*="color: #18181b;" i],
  [style*="color: #18181b" i],
  [style*="color:#333;" i],
  [style*="color:#333;" i],
  [style*="color: #333;" i],
  [style*="color: #333;" i],
  [style*="color:#555;" i],
  [style*="color:#555;" i],
  [style*="color: #555;" i],
  [style*="color: #555;" i]
):not([style*="background" i]) {
  color: var(--color-text) !important;
}

/* Fonds neutres clairs codés en dur : la surface reste blanche en sombre,
   et le texte thémé (quasi blanc) devient illisible dessus (1,05:1). */
:root[data-theme="dark"] :is(
  [style*="background:#ffffff;" i],
  [style*="background:#ffffff" i],
  [style*="background: #ffffff;" i],
  [style*="background: #ffffff" i],
  [style*="background:#fff;" i],
  [style*="background:#fff;" i],
  [style*="background: #fff;" i],
  [style*="background: #fff;" i],
  [style*="background:#f8fafc;" i],
  [style*="background:#f8fafc" i],
  [style*="background: #f8fafc;" i],
  [style*="background: #f8fafc" i],
  [style*="background:#f1f5f9;" i],
  [style*="background:#f1f5f9" i],
  [style*="background: #f1f5f9;" i],
  [style*="background: #f1f5f9" i],
  [style*="background:#fafafa;" i],
  [style*="background:#fafafa" i],
  [style*="background: #fafafa;" i],
  [style*="background: #fafafa" i],
  [style*="background:#f9fafb;" i],
  [style*="background:#f9fafb" i],
  [style*="background: #f9fafb;" i],
  [style*="background: #f9fafb" i],
  [style*="background:#f5f5f5;" i],
  [style*="background:#f5f5f5" i],
  [style*="background: #f5f5f5;" i],
  [style*="background: #f5f5f5" i],
  [style*="background:#e2e8f0;" i],
  [style*="background:#e2e8f0" i],
  [style*="background: #e2e8f0;" i],
  [style*="background: #e2e8f0" i],
  [style*="background-color:#ffffff;" i],
  [style*="background-color:#ffffff" i],
  [style*="background-color: #ffffff;" i],
  [style*="background-color: #ffffff" i],
  [style*="background-color:#fff;" i],
  [style*="background-color:#fff;" i],
  [style*="background-color: #fff;" i],
  [style*="background-color: #fff;" i],
  [style*="background-color:#f8fafc;" i],
  [style*="background-color:#f8fafc" i],
  [style*="background-color: #f8fafc;" i],
  [style*="background-color: #f8fafc" i],
  [style*="background-color:#f1f5f9;" i],
  [style*="background-color:#f1f5f9" i],
  [style*="background-color: #f1f5f9;" i],
  [style*="background-color: #f1f5f9" i],
  [style*="background-color:#fafafa;" i],
  [style*="background-color:#fafafa" i],
  [style*="background-color: #fafafa;" i],
  [style*="background-color: #fafafa" i],
  [style*="background-color:#f9fafb;" i],
  [style*="background-color:#f9fafb" i],
  [style*="background-color: #f9fafb;" i],
  [style*="background-color: #f9fafb" i],
  [style*="background-color:#f5f5f5;" i],
  [style*="background-color:#f5f5f5" i],
  [style*="background-color: #f5f5f5;" i],
  [style*="background-color: #f5f5f5" i],
  [style*="background-color:#e2e8f0;" i],
  [style*="background-color:#e2e8f0" i],
  [style*="background-color: #e2e8f0;" i],
  [style*="background-color: #e2e8f0" i]
) {
  background: var(--color-card) !important;
  color: var(--color-text) !important;
}


/* ---- Fonds « pâles » sémantiques : contexte clair au sein du thème sombre ----
   Les pastilles cohérentes (`background:#fee2e2` + `color:#991b1b`) sont
   volontairement épargnées par les règles ci-dessus. Restait un cas : le même
   fond pâle SANS couleur de texte associée — la ligne d'audit
   « export_attempt — BLOQUÉ » de /security/, dont le texte héritait du thème
   (quasi blanc) et disparaissait sur fond rosé.

   Le fond pâle étant codé en dur, il reste clair en mode sombre : tout son
   sous-arbre doit donc être traité comme un îlot clair. On force un texte
   sombre sur le conteneur et sur les descendants qui n'imposent pas déjà leur
   propre couleur — `:not([style*="color"])` préserve exactement les pastilles
   sémantiques que l'on ne veut pas écraser. */
:root[data-theme="dark"] :is(
  [style*="background:#fee2e2" i],
  [style*="background: #fee2e2" i],
  [style*="background-color:#fee2e2" i],
  [style*="background-color: #fee2e2" i],
  [style*="background:#fef2f2" i],
  [style*="background: #fef2f2" i],
  [style*="background-color:#fef2f2" i],
  [style*="background-color: #fef2f2" i],
  [style*="background:#fff1f2" i],
  [style*="background: #fff1f2" i],
  [style*="background-color:#fff1f2" i],
  [style*="background-color: #fff1f2" i],
  [style*="background:#d1fae5" i],
  [style*="background: #d1fae5" i],
  [style*="background-color:#d1fae5" i],
  [style*="background-color: #d1fae5" i],
  [style*="background:#dcfce7" i],
  [style*="background: #dcfce7" i],
  [style*="background-color:#dcfce7" i],
  [style*="background-color: #dcfce7" i],
  [style*="background:#ecfdf5" i],
  [style*="background: #ecfdf5" i],
  [style*="background-color:#ecfdf5" i],
  [style*="background-color: #ecfdf5" i],
  [style*="background:#f0fdf4" i],
  [style*="background: #f0fdf4" i],
  [style*="background-color:#f0fdf4" i],
  [style*="background-color: #f0fdf4" i],
  [style*="background:#fef3c7" i],
  [style*="background: #fef3c7" i],
  [style*="background-color:#fef3c7" i],
  [style*="background-color: #fef3c7" i],
  [style*="background:#fef9c3" i],
  [style*="background: #fef9c3" i],
  [style*="background-color:#fef9c3" i],
  [style*="background-color: #fef9c3" i],
  [style*="background:#fffbeb" i],
  [style*="background: #fffbeb" i],
  [style*="background-color:#fffbeb" i],
  [style*="background-color: #fffbeb" i],
  [style*="background:#fff7ed" i],
  [style*="background: #fff7ed" i],
  [style*="background-color:#fff7ed" i],
  [style*="background-color: #fff7ed" i],
  [style*="background:#dbeafe" i],
  [style*="background: #dbeafe" i],
  [style*="background-color:#dbeafe" i],
  [style*="background-color: #dbeafe" i],
  [style*="background:#eff6ff" i],
  [style*="background: #eff6ff" i],
  [style*="background-color:#eff6ff" i],
  [style*="background-color: #eff6ff" i],
  [style*="background:#e0e7ff" i],
  [style*="background: #e0e7ff" i],
  [style*="background-color:#e0e7ff" i],
  [style*="background-color: #e0e7ff" i],
  [style*="background:#eef2ff" i],
  [style*="background: #eef2ff" i],
  [style*="background-color:#eef2ff" i],
  [style*="background-color: #eef2ff" i],
  [style*="background:#f5f3ff" i],
  [style*="background: #f5f3ff" i],
  [style*="background-color:#f5f3ff" i],
  [style*="background-color: #f5f3ff" i],
  [style*="background:#ede9fe" i],
  [style*="background: #ede9fe" i],
  [style*="background-color:#ede9fe" i],
  [style*="background-color: #ede9fe" i],
  [style*="background:#f3e8ff" i],
  [style*="background: #f3e8ff" i],
  [style*="background-color:#f3e8ff" i],
  [style*="background-color: #f3e8ff" i],
  [style*="background:#fce7f3" i],
  [style*="background: #fce7f3" i],
  [style*="background-color:#fce7f3" i],
  [style*="background-color: #fce7f3" i],
  [style*="background:#f3f4f6" i],
  [style*="background: #f3f4f6" i],
  [style*="background-color:#f3f4f6" i],
  [style*="background-color: #f3f4f6" i],
  [style*="background:#7c3aed22" i],
  [style*="background: #7c3aed22" i],
  [style*="background-color:#7c3aed22" i],
  [style*="background-color: #7c3aed22" i]
) {
  color: #1E293B !important;
}

:root[data-theme="dark"] :is(
  [style*="background:#fee2e2" i],
  [style*="background: #fee2e2" i],
  [style*="background-color:#fee2e2" i],
  [style*="background-color: #fee2e2" i],
  [style*="background:#fef2f2" i],
  [style*="background: #fef2f2" i],
  [style*="background-color:#fef2f2" i],
  [style*="background-color: #fef2f2" i],
  [style*="background:#fff1f2" i],
  [style*="background: #fff1f2" i],
  [style*="background-color:#fff1f2" i],
  [style*="background-color: #fff1f2" i],
  [style*="background:#d1fae5" i],
  [style*="background: #d1fae5" i],
  [style*="background-color:#d1fae5" i],
  [style*="background-color: #d1fae5" i],
  [style*="background:#dcfce7" i],
  [style*="background: #dcfce7" i],
  [style*="background-color:#dcfce7" i],
  [style*="background-color: #dcfce7" i],
  [style*="background:#ecfdf5" i],
  [style*="background: #ecfdf5" i],
  [style*="background-color:#ecfdf5" i],
  [style*="background-color: #ecfdf5" i],
  [style*="background:#f0fdf4" i],
  [style*="background: #f0fdf4" i],
  [style*="background-color:#f0fdf4" i],
  [style*="background-color: #f0fdf4" i],
  [style*="background:#fef3c7" i],
  [style*="background: #fef3c7" i],
  [style*="background-color:#fef3c7" i],
  [style*="background-color: #fef3c7" i],
  [style*="background:#fef9c3" i],
  [style*="background: #fef9c3" i],
  [style*="background-color:#fef9c3" i],
  [style*="background-color: #fef9c3" i],
  [style*="background:#fffbeb" i],
  [style*="background: #fffbeb" i],
  [style*="background-color:#fffbeb" i],
  [style*="background-color: #fffbeb" i],
  [style*="background:#fff7ed" i],
  [style*="background: #fff7ed" i],
  [style*="background-color:#fff7ed" i],
  [style*="background-color: #fff7ed" i],
  [style*="background:#dbeafe" i],
  [style*="background: #dbeafe" i],
  [style*="background-color:#dbeafe" i],
  [style*="background-color: #dbeafe" i],
  [style*="background:#eff6ff" i],
  [style*="background: #eff6ff" i],
  [style*="background-color:#eff6ff" i],
  [style*="background-color: #eff6ff" i],
  [style*="background:#e0e7ff" i],
  [style*="background: #e0e7ff" i],
  [style*="background-color:#e0e7ff" i],
  [style*="background-color: #e0e7ff" i],
  [style*="background:#eef2ff" i],
  [style*="background: #eef2ff" i],
  [style*="background-color:#eef2ff" i],
  [style*="background-color: #eef2ff" i],
  [style*="background:#f5f3ff" i],
  [style*="background: #f5f3ff" i],
  [style*="background-color:#f5f3ff" i],
  [style*="background-color: #f5f3ff" i],
  [style*="background:#ede9fe" i],
  [style*="background: #ede9fe" i],
  [style*="background-color:#ede9fe" i],
  [style*="background-color: #ede9fe" i],
  [style*="background:#f3e8ff" i],
  [style*="background: #f3e8ff" i],
  [style*="background-color:#f3e8ff" i],
  [style*="background-color: #f3e8ff" i],
  [style*="background:#fce7f3" i],
  [style*="background: #fce7f3" i],
  [style*="background-color:#fce7f3" i],
  [style*="background-color: #fce7f3" i],
  [style*="background:#f3f4f6" i],
  [style*="background: #f3f4f6" i],
  [style*="background-color:#f3f4f6" i],
  [style*="background-color: #f3f4f6" i],
  [style*="background:#7c3aed22" i],
  [style*="background: #7c3aed22" i],
  [style*="background-color:#7c3aed22" i],
  [style*="background-color: #7c3aed22" i]
) *:not([style*="color" i]) {
  color: #1E293B !important;
}


/* =============================================
   Teintes de marque en texte — conformité AA (thème clair)
   =============================================
   Mesuré sur les 19 modules en thème clair : 396 éléments sous 3:1. Il ne
   s'agit pas d'un défaut du mode sombre mais du langage chromatique lui-même —
   les teintes « 500 » de la palette servent aussi bien d'aplat que de texte, or
   #F59E0B sur blanc plafonne à 2,15:1 et #10B981 à 2,54:1.

   On ne redéfinit ici que l'usage *texte*, en descendant d'un ou deux crans
   dans la même rampe : la teinte est conservée, la lisibilité passe au-dessus
   de 4,5:1. Les aplats (fonds de pastilles, barres de graphiques, bordures)
   ne sont pas touchés — seule la propriété `color` est réécrite.

   Même garde-fou que la couche sombre : `:not([style*="background"])`. Un texte
   coloré posé sur sa propre pastille forme un couple cohérent qu'il ne faut pas
   dissocier ; c'est le texte de couleur sur surface thémée qui pose problème. */
:root:not([data-theme="dark"]) :is(
  [style*="color:#10b981" i]:not([style*="background" i]),
  [style*="color: #10b981" i]:not([style*="background" i])
) {
  color: #047857 !important;
}
:root:not([data-theme="dark"]) :is(
  [style*="color:#34d399" i]:not([style*="background" i]),
  [style*="color: #34d399" i]:not([style*="background" i])
) {
  color: #047857 !important;
}
:root:not([data-theme="dark"]) :is(
  [style*="color:#22c55e" i]:not([style*="background" i]),
  [style*="color: #22c55e" i]:not([style*="background" i])
) {
  color: #15803D !important;
}
:root:not([data-theme="dark"]) :is(
  [style*="color:#4ade80" i]:not([style*="background" i]),
  [style*="color: #4ade80" i]:not([style*="background" i])
) {
  color: #15803D !important;
}
:root:not([data-theme="dark"]) :is(
  [style*="color:#16a34a" i]:not([style*="background" i]),
  [style*="color: #16a34a" i]:not([style*="background" i])
) {
  color: #15803D !important;
}
:root:not([data-theme="dark"]) :is(
  [style*="color:#059669" i]:not([style*="background" i]),
  [style*="color: #059669" i]:not([style*="background" i])
) {
  color: #047857 !important;
}
:root:not([data-theme="dark"]) :is(
  [style*="color:#f59e0b" i]:not([style*="background" i]),
  [style*="color: #f59e0b" i]:not([style*="background" i])
) {
  color: #B45309 !important;
}
:root:not([data-theme="dark"]) :is(
  [style*="color:#fbbf24" i]:not([style*="background" i]),
  [style*="color: #fbbf24" i]:not([style*="background" i])
) {
  color: #B45309 !important;
}
:root:not([data-theme="dark"]) :is(
  [style*="color:#fcd34d" i]:not([style*="background" i]),
  [style*="color: #fcd34d" i]:not([style*="background" i])
) {
  color: #B45309 !important;
}
:root:not([data-theme="dark"]) :is(
  [style*="color:#eab308" i]:not([style*="background" i]),
  [style*="color: #eab308" i]:not([style*="background" i])
) {
  color: #A16207 !important;
}
:root:not([data-theme="dark"]) :is(
  [style*="color:#facc15" i]:not([style*="background" i]),
  [style*="color: #facc15" i]:not([style*="background" i])
) {
  color: #A16207 !important;
}
:root:not([data-theme="dark"]) :is(
  [style*="color:#ca8a04" i]:not([style*="background" i]),
  [style*="color: #ca8a04" i]:not([style*="background" i])
) {
  color: #A16207 !important;
}
:root:not([data-theme="dark"]) :is(
  [style*="color:#d97706" i]:not([style*="background" i]),
  [style*="color: #d97706" i]:not([style*="background" i])
) {
  color: #B45309 !important;
}
:root:not([data-theme="dark"]) :is(
  [style*="color:#ef4444" i]:not([style*="background" i]),
  [style*="color: #ef4444" i]:not([style*="background" i])
) {
  color: #DC2626 !important;
}
:root:not([data-theme="dark"]) :is(
  [style*="color:#f87171" i]:not([style*="background" i]),
  [style*="color: #f87171" i]:not([style*="background" i])
) {
  color: #DC2626 !important;
}
:root:not([data-theme="dark"]) :is(
  [style*="color:#fb7185" i]:not([style*="background" i]),
  [style*="color: #fb7185" i]:not([style*="background" i])
) {
  color: #BE123C !important;
}
:root:not([data-theme="dark"]) :is(
  [style*="color:#f43f5e" i]:not([style*="background" i]),
  [style*="color: #f43f5e" i]:not([style*="background" i])
) {
  color: #BE123C !important;
}
:root:not([data-theme="dark"]) :is(
  [style*="color:#3b82f6" i]:not([style*="background" i]),
  [style*="color: #3b82f6" i]:not([style*="background" i])
) {
  color: #1D4ED8 !important;
}
:root:not([data-theme="dark"]) :is(
  [style*="color:#60a5fa" i]:not([style*="background" i]),
  [style*="color: #60a5fa" i]:not([style*="background" i])
) {
  color: #1D4ED8 !important;
}
:root:not([data-theme="dark"]) :is(
  [style*="color:#93c5fd" i]:not([style*="background" i]),
  [style*="color: #93c5fd" i]:not([style*="background" i])
) {
  color: #1D4ED8 !important;
}
:root:not([data-theme="dark"]) :is(
  [style*="color:#0ea5e9" i]:not([style*="background" i]),
  [style*="color: #0ea5e9" i]:not([style*="background" i])
) {
  color: #0369A1 !important;
}
:root:not([data-theme="dark"]) :is(
  [style*="color:#38bdf8" i]:not([style*="background" i]),
  [style*="color: #38bdf8" i]:not([style*="background" i])
) {
  color: #0369A1 !important;
}
:root:not([data-theme="dark"]) :is(
  [style*="color:#06b6d4" i]:not([style*="background" i]),
  [style*="color: #06b6d4" i]:not([style*="background" i])
) {
  color: #0E7490 !important;
}
:root:not([data-theme="dark"]) :is(
  [style*="color:#22d3ee" i]:not([style*="background" i]),
  [style*="color: #22d3ee" i]:not([style*="background" i])
) {
  color: #0E7490 !important;
}
:root:not([data-theme="dark"]) :is(
  [style*="color:#8b5cf6" i]:not([style*="background" i]),
  [style*="color: #8b5cf6" i]:not([style*="background" i])
) {
  color: #6D28D9 !important;
}
:root:not([data-theme="dark"]) :is(
  [style*="color:#a78bfa" i]:not([style*="background" i]),
  [style*="color: #a78bfa" i]:not([style*="background" i])
) {
  color: #6D28D9 !important;
}
:root:not([data-theme="dark"]) :is(
  [style*="color:#c4b5fd" i]:not([style*="background" i]),
  [style*="color: #c4b5fd" i]:not([style*="background" i])
) {
  color: #6D28D9 !important;
}
:root:not([data-theme="dark"]) :is(
  [style*="color:#a855f7" i]:not([style*="background" i]),
  [style*="color: #a855f7" i]:not([style*="background" i])
) {
  color: #7E22CE !important;
}
:root:not([data-theme="dark"]) :is(
  [style*="color:#6366f1" i]:not([style*="background" i]),
  [style*="color: #6366f1" i]:not([style*="background" i])
) {
  color: #4338CA !important;
}
:root:not([data-theme="dark"]) :is(
  [style*="color:#818cf8" i]:not([style*="background" i]),
  [style*="color: #818cf8" i]:not([style*="background" i])
) {
  color: #4338CA !important;
}
:root:not([data-theme="dark"]) :is(
  [style*="color:#ec4899" i]:not([style*="background" i]),
  [style*="color: #ec4899" i]:not([style*="background" i])
) {
  color: #BE185D !important;
}
:root:not([data-theme="dark"]) :is(
  [style*="color:#f472b6" i]:not([style*="background" i]),
  [style*="color: #f472b6" i]:not([style*="background" i])
) {
  color: #BE185D !important;
}
:root:not([data-theme="dark"]) :is(
  [style*="color:#14b8a6" i]:not([style*="background" i]),
  [style*="color: #14b8a6" i]:not([style*="background" i])
) {
  color: #0F766E !important;
}
:root:not([data-theme="dark"]) :is(
  [style*="color:#2dd4bf" i]:not([style*="background" i]),
  [style*="color: #2dd4bf" i]:not([style*="background" i])
) {
  color: #0F766E !important;
}
:root:not([data-theme="dark"]) :is(
  [style*="color:#f97316" i]:not([style*="background" i]),
  [style*="color: #f97316" i]:not([style*="background" i])
) {
  color: #C2410C !important;
}
:root:not([data-theme="dark"]) :is(
  [style*="color:#fb923c" i]:not([style*="background" i]),
  [style*="color: #fb923c" i]:not([style*="background" i])
) {
  color: #C2410C !important;
}
:root:not([data-theme="dark"]) :is(
  [style*="color:#94a3b8" i]:not([style*="background" i]),
  [style*="color: #94a3b8" i]:not([style*="background" i])
) {
  color: #64748B !important;
}
:root:not([data-theme="dark"]) :is(
  [style*="color:#cbd5e1" i]:not([style*="background" i]),
  [style*="color: #cbd5e1" i]:not([style*="background" i])
) {
  color: #64748B !important;
}
:root:not([data-theme="dark"]) :is(
  [style*="color:#a1a1aa" i]:not([style*="background" i]),
  [style*="color: #a1a1aa" i]:not([style*="background" i])
) {
  color: #64748B !important;
}


/* ---- Contrepartie sombre des teintes assombries pour le thème clair ----
   La passe de contraste du thème clair a descendu les teintes de marque d'un
   ou deux crans (#10B981 -> #065f46, #F59E0B -> #92400e …) directement dans les
   templates. Correct sur blanc ; catastrophique sur ardoise, où ce vert foncé
   retombe sous 2:1. Mesuré : les éléments sous 2:1 en sombre étaient passés de
   23 à 69 juste après cette passe.

   On remonte donc ces mêmes teintes en mode sombre. Même garde-fou que partout
   ailleurs : uniquement quand l'élément ne porte pas son propre fond — sur une
   pastille pâle codée en dur, le texte foncé est au contraire le bon choix, et
   la règle « îlot clair » plus haut s'en occupe déjà. */
:root[data-theme="dark"] :is(
  [style*="color:#065f46" i]:not([style*="background" i]),
  [style*="color: #065f46" i]:not([style*="background" i])
) {
  color: #34D399 !important;
}
:root[data-theme="dark"] :is(
  [style*="color:#166534" i]:not([style*="background" i]),
  [style*="color: #166534" i]:not([style*="background" i])
) {
  color: #4ADE80 !important;
}
:root[data-theme="dark"] :is(
  [style*="color:#115e59" i]:not([style*="background" i]),
  [style*="color: #115e59" i]:not([style*="background" i])
) {
  color: #2DD4BF !important;
}
:root[data-theme="dark"] :is(
  [style*="color:#047857" i]:not([style*="background" i]),
  [style*="color: #047857" i]:not([style*="background" i])
) {
  color: #34D399 !important;
}
:root[data-theme="dark"] :is(
  [style*="color:#92400e" i]:not([style*="background" i]),
  [style*="color: #92400e" i]:not([style*="background" i])
) {
  color: #FBBF24 !important;
}
:root[data-theme="dark"] :is(
  [style*="color:#854d0e" i]:not([style*="background" i]),
  [style*="color: #854d0e" i]:not([style*="background" i])
) {
  color: #FDE047 !important;
}
:root[data-theme="dark"] :is(
  [style*="color:#b45309" i]:not([style*="background" i]),
  [style*="color: #b45309" i]:not([style*="background" i])
) {
  color: #FBBF24 !important;
}
:root[data-theme="dark"] :is(
  [style*="color:#b91c1c" i]:not([style*="background" i]),
  [style*="color: #b91c1c" i]:not([style*="background" i])
) {
  color: #F87171 !important;
}
:root[data-theme="dark"] :is(
  [style*="color:#be123c" i]:not([style*="background" i]),
  [style*="color: #be123c" i]:not([style*="background" i])
) {
  color: #FB7185 !important;
}
:root[data-theme="dark"] :is(
  [style*="color:#991b1b" i]:not([style*="background" i]),
  [style*="color: #991b1b" i]:not([style*="background" i])
) {
  color: #F87171 !important;
}
:root[data-theme="dark"] :is(
  [style*="color:#1d4ed8" i]:not([style*="background" i]),
  [style*="color: #1d4ed8" i]:not([style*="background" i])
) {
  color: #60A5FA !important;
}
:root[data-theme="dark"] :is(
  [style*="color:#0369a1" i]:not([style*="background" i]),
  [style*="color: #0369a1" i]:not([style*="background" i])
) {
  color: #38BDF8 !important;
}
:root[data-theme="dark"] :is(
  [style*="color:#0e7490" i]:not([style*="background" i]),
  [style*="color: #0e7490" i]:not([style*="background" i])
) {
  color: #22D3EE !important;
}
:root[data-theme="dark"] :is(
  [style*="color:#1e40af" i]:not([style*="background" i]),
  [style*="color: #1e40af" i]:not([style*="background" i])
) {
  color: #60A5FA !important;
}
:root[data-theme="dark"] :is(
  [style*="color:#4338ca" i]:not([style*="background" i]),
  [style*="color: #4338ca" i]:not([style*="background" i])
) {
  color: #818CF8 !important;
}
:root[data-theme="dark"] :is(
  [style*="color:#6d28d9" i]:not([style*="background" i]),
  [style*="color: #6d28d9" i]:not([style*="background" i])
) {
  color: #A78BFA !important;
}
:root[data-theme="dark"] :is(
  [style*="color:#6b21a8" i]:not([style*="background" i]),
  [style*="color: #6b21a8" i]:not([style*="background" i])
) {
  color: #C084FC !important;
}
:root[data-theme="dark"] :is(
  [style*="color:#9d174d" i]:not([style*="background" i]),
  [style*="color: #9d174d" i]:not([style*="background" i])
) {
  color: #F472B6 !important;
}
:root[data-theme="dark"] :is(
  [style*="color:#9a3412" i]:not([style*="background" i]),
  [style*="color: #9a3412" i]:not([style*="background" i])
) {
  color: #FB923C !important;
}
:root[data-theme="dark"] :is(
  [style*="color:#c2410c" i]:not([style*="background" i]),
  [style*="color: #c2410c" i]:not([style*="background" i])
) {
  color: #FB923C !important;
}
:root[data-theme="dark"] :is(
  [style*="color:#475569" i]:not([style*="background" i]),
  [style*="color: #475569" i]:not([style*="background" i])
) {
  color: #94A3B8 !important;
}
:root[data-theme="dark"] :is(
  [style*="color:#4b5563" i]:not([style*="background" i]),
  [style*="color: #4b5563" i]:not([style*="background" i])
) {
  color: #9CA3AF !important;
}


/* ---- Îlots clairs : inverser le sens du mélange des pastilles ----
   `--tint-text-*` part du principe qu'en thème sombre la pastille teintée
   repose sur une surface sombre : on éclaircit donc son texte. Mais lorsqu'elle
   se trouve à l'intérieur d'un panneau au fond pâle codé en dur — que le thème
   sombre conserve volontairement clair — l'hypothèse tombe : le texte éclairci
   se retrouve clair sur clair (mesuré à 1,17:1).

   Les propriétés personnalisées étant héritées, il suffit de redéfinir les deux
   jetons sur l'îlot : tout son sous-arbre bascule alors sur le mélange
   « assombrissant » du thème clair. Aucune règle de couleur n'est dupliquée. */
:root[data-theme="dark"] :is(
  [style*="background:#fee2e2" i],
  [style*="background: #fee2e2" i],
  [style*="background-color:#fee2e2" i],
  [style*="background-color: #fee2e2" i],
  [style*="background:#fef2f2" i],
  [style*="background: #fef2f2" i],
  [style*="background-color:#fef2f2" i],
  [style*="background-color: #fef2f2" i],
  [style*="background:#fff1f2" i],
  [style*="background: #fff1f2" i],
  [style*="background-color:#fff1f2" i],
  [style*="background-color: #fff1f2" i],
  [style*="background:#d1fae5" i],
  [style*="background: #d1fae5" i],
  [style*="background-color:#d1fae5" i],
  [style*="background-color: #d1fae5" i],
  [style*="background:#dcfce7" i],
  [style*="background: #dcfce7" i],
  [style*="background-color:#dcfce7" i],
  [style*="background-color: #dcfce7" i],
  [style*="background:#ecfdf5" i],
  [style*="background: #ecfdf5" i],
  [style*="background-color:#ecfdf5" i],
  [style*="background-color: #ecfdf5" i],
  [style*="background:#f0fdf4" i],
  [style*="background: #f0fdf4" i],
  [style*="background-color:#f0fdf4" i],
  [style*="background-color: #f0fdf4" i],
  [style*="background:#fef3c7" i],
  [style*="background: #fef3c7" i],
  [style*="background-color:#fef3c7" i],
  [style*="background-color: #fef3c7" i],
  [style*="background:#fef9c3" i],
  [style*="background: #fef9c3" i],
  [style*="background-color:#fef9c3" i],
  [style*="background-color: #fef9c3" i],
  [style*="background:#fffbeb" i],
  [style*="background: #fffbeb" i],
  [style*="background-color:#fffbeb" i],
  [style*="background-color: #fffbeb" i],
  [style*="background:#fff7ed" i],
  [style*="background: #fff7ed" i],
  [style*="background-color:#fff7ed" i],
  [style*="background-color: #fff7ed" i],
  [style*="background:#dbeafe" i],
  [style*="background: #dbeafe" i],
  [style*="background-color:#dbeafe" i],
  [style*="background-color: #dbeafe" i],
  [style*="background:#eff6ff" i],
  [style*="background: #eff6ff" i],
  [style*="background-color:#eff6ff" i],
  [style*="background-color: #eff6ff" i],
  [style*="background:#e0e7ff" i],
  [style*="background: #e0e7ff" i],
  [style*="background-color:#e0e7ff" i],
  [style*="background-color: #e0e7ff" i],
  [style*="background:#eef2ff" i],
  [style*="background: #eef2ff" i],
  [style*="background-color:#eef2ff" i],
  [style*="background-color: #eef2ff" i],
  [style*="background:#f5f3ff" i],
  [style*="background: #f5f3ff" i],
  [style*="background-color:#f5f3ff" i],
  [style*="background-color: #f5f3ff" i],
  [style*="background:#ede9fe" i],
  [style*="background: #ede9fe" i],
  [style*="background-color:#ede9fe" i],
  [style*="background-color: #ede9fe" i],
  [style*="background:#f3e8ff" i],
  [style*="background: #f3e8ff" i],
  [style*="background-color:#f3e8ff" i],
  [style*="background-color: #f3e8ff" i],
  [style*="background:#fce7f3" i],
  [style*="background: #fce7f3" i],
  [style*="background-color:#fce7f3" i],
  [style*="background-color: #fce7f3" i],
  [style*="background:#f3f4f6" i],
  [style*="background: #f3f4f6" i],
  [style*="background-color:#f3f4f6" i],
  [style*="background-color: #f3f4f6" i]
) {
  --tint-text-pct: 55%;
  --tint-text-mix: #0B1220;
}

/* ---- Texte foncé sur fond translucide (relevé QA du 05/10) ----
   La garde `:not([style*="background"])` épargne les pastilles à fond pâle
   opaque. Un fond `rgba(…, .05)` est différent : translucide, il laisse voir
   l'ardoise en sombre, et le texte foncé qu'il porte tombait à 2,2:1
   (« Ouvrir Clients compta » d'une fiche Société, titre « Arrêtés de
   commission »). Même remontée de teinte que pour le texte sans fond.
   Alpine écrit ses liaisons `:style` en `rgb(…)` : les titres des guides de
   relance (Comptabilité → « Relance documentaire ») sont repris sous cette
   forme. Cibles mesurées après correction : 7,9:1 à 9,3:1 sur la carte. */
:root[data-theme="dark"] :is(
  [style*="color:#065f46" i][style*="background:rgba(" i],
  [style*="color: rgb(6, 95, 70)"]:not([style*="background" i]),
  [style*="color: rgb(4, 120, 87)"]:not([style*="background" i])
) {
  color: #34D399 !important;
}
:root[data-theme="dark"] :is(
  [style*="color:#4338ca" i]:not([style*="background" i]),
  [style*="color:#4338ca" i][style*="background:rgba(" i],
  [style*="color: rgb(67, 56, 202)"]:not([style*="background" i])
) {
  color: #A5B4FC !important;
}
:root[data-theme="dark"] [style*="color: rgb(185, 28, 28)"]:not([style*="background" i]) {
  color: #FCA5A5 !important;
}
/* Les autres en-têtes de section des Commissions et les liens de la fiche
   Société suivent le même motif (teinte pâle translucide + texte foncé) : mêmes
   teintes d'arrivée que la rampe sombre plus haut. */
:root[data-theme="dark"] :is(
  [style*="color:#1d4ed8" i][style*="background:rgba(" i]
) { color: #60A5FA !important; }
:root[data-theme="dark"] :is(
  [style*="color:#6d28d9" i][style*="background:rgba(" i],
  [style*="color: rgb(124, 58, 237)"]:not([style*="background" i])
) { color: #A78BFA !important; }
:root[data-theme="dark"] :is(
  [style*="color:#92400e" i][style*="background:rgba(" i]
) { color: #FBBF24 !important; }
:root[data-theme="dark"] :is(
  [style*="color:#0f766e" i][style*="background:rgba(" i],
  [style*="color:#0f766e" i]:not([style*="background" i]),
  [style*="color: rgb(15, 118, 110)"]:not([style*="background" i])
) { color: #2DD4BF !important; }
:root[data-theme="dark"] [style*="color:#1e3a5f" i][style*="background:rgba(" i] {
  color: var(--color-text) !important;
}
/* État vide des Automatisations : `#475569` posé par une classe du gabarit,
   hors de portée des règles sur styles inline (2,5:1 sur l'ardoise). */
:root[data-theme="dark"] .at-empty { color: var(--color-text-muted); }
/* Aperçu du devis : la feuille reste blanche dans les deux thèmes (c'est le
   papier imprimé). Les règles sombres ci-dessus y éclaircissaient le vert de la
   remise — #34D399 sur blanc, 1,9:1. Sur le papier, on rend sa teinte d'origine. */
:root[data-theme="dark"] .qb-sheet [style*="color:#065f46" i] { color: #065F46 !important; }
/* Bandeau « aucun tarif » du constructeur de devis : fond ambre clair codé en
   dur, conservé en sombre ; son lien prenait l'accent sombre (bleu clair,
   2,3:1). Bleu foncé du thème clair : 6,9:1 sur l'ambre. */
:root[data-theme="dark"] .qb-warn a { color: #1D4ED8; }


/* =============================================
   Assistant IA — lanceur flottant, tiroir, surface de conversation
   =============================================
   L'assistant occupait une page entière, atteignable seulement par le menu :
   pour lui poser une question sur l'écran qu'on regardait, il fallait le
   quitter, puis y revenir. Il vit désormais dans un tiroir ouvert par un bouton
   flottant, disponible sur n'importe quelle page — et la page /ai/ réutilise
   exactement la même surface (`.ai-panel`), pour qu'un seul jeu de règles
   décrive les deux et qu'aucune des deux ne dérive.

   Ces composants sont écrits en CSS et non en styles inline, contrairement au
   reste des gabarits : la conversation est le seul écran où le fond, la
   couleur, l'arrondi et l'alignement changent selon l'auteur du message. Les
   répéter à la main dans le gabarit rendait la moindre retouche illisible. */

/* ---- Lanceur ---- */
.ai-fab {
  position: fixed;
  right: 22px;
  bottom: 22px;
  /* Au-dessus de la sidebar (100) et du voile mobile (90), sous les modales
     (500) : un dialogue de confirmation doit toujours passer devant. */
  z-index: 480;
  width: 52px;
  height: 52px;
  padding: 0;
  border: none;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  /* Les jetons `-solid` et non `-vivid` : le glyphe est blanc, il lui faut un
     aplat soutenu dans les deux thèmes. */
  background: linear-gradient(140deg, var(--color-accent-solid), var(--color-purple-solid));
  box-shadow: var(--shadow-lg);
  transition: transform var(--transition), filter var(--transition);
}
.ai-fab:hover  { transform: translateY(-2px) scale(1.04); filter: brightness(1.08); }
.ai-fab:active { transform: translateY(0) scale(.96); }

/* ---- Tiroir ---- */
.ai-drawer {
  position: fixed;
  right: 22px;
  bottom: 86px;
  z-index: 479;
  width: min(420px, calc(100vw - 32px));
  height: min(640px, calc(100vh - 130px));
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: var(--color-card);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
}
.ai-drawer__head {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 10px 10px 14px;
  border-bottom: 1px solid var(--color-border);
}
.ai-drawer__title {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: var(--text-sm);
  font-weight: 700;
  letter-spacing: -.01em;
}
.ai-drawer__title .ico { color: var(--color-accent); }
.ai-drawer__sub {
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: .02em;
  text-transform: uppercase;
  color: var(--color-text-light);
}
.ai-drawer__body { flex: 1; min-height: 0; display: flex; }
.ai-push { margin-left: auto; }

/* ---- Surface de conversation, commune au tiroir et à la page ---- */
.ai-panel {
  flex: 1;
  min-width: 0;
  min-height: 0;
  display: flex;
  flex-direction: column;
  background: var(--color-bg);
}
.ai-panel__bar {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 7px 9px;
  background: var(--color-card);
  border-bottom: 1px solid var(--color-border);
}
.ai-panel__hint { font-size: var(--text-xs); color: var(--color-text-light); }
.ai-panel__scroll {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 14px;
}
/* Colonne de lecture. Dans le tiroir elle prend toute la place ; en pleine
   page elle borne la largeur du texte et centre le fil, la saisie et la note
   sur le même axe. Elle ne fixe pas `display` : `.ai-composer__row` la porte
   aussi et doit rester en ligne. */
.ai-column {
  width: 100%;
  max-width: 720px;
  margin-left: auto;
  margin-right: auto;
}
.ai-panel__scroll > .ai-column {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.ai-thread { display: flex; flex-direction: column; gap: 16px; }

.ai-select {
  flex: 1;
  min-width: 0;
  font-family: inherit;
  font-size: var(--text-xs);
  padding: 5px 8px;
  color: var(--color-text);
  background: var(--color-card);
  border: 1px solid var(--color-border);
  border-radius: 8px;
}
.ai-icon-btn {
  width: 28px;
  height: 28px;
  flex: none;
  padding: 0;
  border: none;
  border-radius: 8px;
  background: transparent;
  color: var(--color-text-muted);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: background var(--transition), color var(--transition);
}
.ai-icon-btn:hover { background: var(--color-bg); color: var(--color-text); }

/* ---- Un échange ---- */
.ai-exchange { display: flex; flex-direction: column; gap: 8px; }
.ai-ask {
  align-self: flex-end;
  max-width: 82%;
  padding: 8px 12px;
  border-radius: 14px 14px 4px 14px;
  background: var(--color-accent-solid);
  color: #fff;
  font-size: var(--text-sm);
  line-height: 1.55;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.ai-answer {
  align-self: flex-start;
  max-width: 95%;
  padding: 11px 13px;
  border-radius: 14px 14px 14px 4px;
  background: var(--color-card);
  border: 1px solid var(--color-border);
  box-shadow: var(--shadow-sm);
  color: var(--color-text);
  font-size: var(--text-sm);
  line-height: 1.62;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

/* La ligne « sources » n'est pas décorative : elle sépare un chiffre vérifié
   d'un chiffre approché. Discrète au repos, jamais absente. */
.ai-sources { align-self: flex-start; max-width: 95%; font-size: var(--text-xs); }
.ai-sources > summary {
  list-style: none;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 2px 0;
  color: var(--color-text-light);
}
.ai-sources > summary::-webkit-details-marker { display: none; }
.ai-sources > summary:hover { color: var(--color-text-muted); }
.ai-sources ul {
  margin: 6px 0 0;
  padding-left: 15px;
  color: var(--color-text-muted);
  line-height: 1.65;
}
.ai-sources code {
  font-size: var(--text-xs);
  padding: 1px 4px;
  border-radius: 4px;
  background: var(--color-bg);
  border: 1px solid var(--color-border);
}
.ai-flag { color: var(--color-amber); font-weight: 600; }
.ai-warn {
  align-self: flex-start;
  font-size: var(--text-xs);
  line-height: 1.55;
  color: var(--color-amber);
}

/* ---- État vide : des exemples cliquables plutôt qu'une liste à puces ---- */
.ai-empty__lead {
  font-size: var(--text-sm);
  line-height: 1.6;
  color: var(--color-text-muted);
  margin-bottom: 10px;
}
.ai-chips { display: flex; flex-direction: column; gap: 6px; }
.ai-chip {
  text-align: left;
  font-family: inherit;
  font-size: var(--text-xs);
  line-height: 1.45;
  padding: 8px 11px;
  border-radius: 10px;
  border: 1px solid var(--color-border);
  background: var(--color-card);
  color: var(--color-text);
  transition: border-color var(--transition), transform var(--transition);
}
.ai-chip:hover { border-color: var(--color-accent); transform: translateX(2px); }

/* ---- Attente ----
   L'appel au modèle prend plusieurs secondes ; sans repère visible, l'écran
   semble n'avoir rien reçu et l'on renvoie la question. */
.ai-typing {
  align-self: flex-start;
  display: none;
  gap: 4px;
  align-items: center;
  padding: 12px 14px;
  border-radius: 14px 14px 14px 4px;
  background: var(--color-card);
  border: 1px solid var(--color-border);
}
.ai-typing.htmx-request { display: inline-flex; }
.ai-typing span {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--color-text-light);
  animation: ai-bounce 1s infinite;
}
.ai-typing span:nth-child(2) { animation-delay: .15s; }
.ai-typing span:nth-child(3) { animation-delay: .30s; }
@keyframes ai-bounce {
  0%, 80%, 100% { transform: translateY(0);    opacity: .35; }
  40%           { transform: translateY(-4px); opacity: 1; }
}

/* ---- Saisie ---- */
.ai-composer {
  padding: 10px 12px 11px;
  background: var(--color-card);
  border-top: 1px solid var(--color-border);
}
.ai-composer__row { display: flex; align-items: flex-end; gap: 8px; }
.ai-composer textarea {
  flex: 1;
  min-width: 0;
  min-height: 38px;
  max-height: 132px;
  resize: none;
  padding: 9px 11px;
  font-family: inherit;
  font-size: var(--text-sm);
  line-height: 1.5;
  color: var(--color-text);
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: 10px;
  outline: none;
}
.ai-composer textarea:focus {
  border-color: var(--color-accent);
  box-shadow: 0 0 0 3px rgba(59,130,246,.15);
}
.ai-send {
  width: 38px;
  height: 38px;
  flex: none;
  padding: 0;
  border: none;
  border-radius: 10px;
  background: var(--color-accent-solid);
  color: #fff;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: filter var(--transition);
}
.ai-send:hover:not(:disabled) { filter: brightness(1.1); }
.ai-send:disabled { opacity: .45; cursor: default; }
.ai-note {
  margin-top: 7px;
  font-size: var(--text-xs);
  line-height: 1.5;
  color: var(--color-text-light);
}

/* ---- Absence de clé : expliquer plutôt qu'offrir un champ qui échouera ---- */
.ai-notice {
  margin: 14px;
  padding: 12px 14px;
  border-radius: var(--radius-md);
  border: 1px solid var(--color-border);
  border-left: 3px solid var(--color-amber);
  background: var(--color-card);
  font-size: var(--text-sm);
  line-height: 1.6;
  color: var(--color-text-muted);
}
.ai-notice strong {
  display: block;
  margin-bottom: 4px;
  font-size: var(--text-sm);
  color: var(--color-text);
}

/* ---- Variante pleine page (/ai/) ----
   Même surface, encadrée : le fil doit défiler à l'intérieur, jamais entraîner
   la page entière.

   La hauteur ne se déduit pas de la fenêtre seule : au-dessus du contenu
   peuvent s'empiler la bannière de préavis, celle de configuration incomplète
   et les messages flash, dont aucune n'est de hauteur connue. On plafonne donc
   par la fenêtre sans s'y fier — si les bannières poussent la surface trop bas,
   la page défile, ce qui vaut mieux qu'une zone de saisie hors de l'écran. */
.ai-page {
  display: flex;
  width: 100%;
  max-width: 900px;
  height: min(620px, calc(100vh - 210px));
  min-height: 380px;
  overflow: hidden;
  background: var(--color-card);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
}

@media (max-width: 760px) {
  /* Le lanceur s'efface au défilement vers le bas (voir ai_widget.html) ; la
     fin de page garde la place du bouton, la dernière ligne reste lisible. */
  .ai-fab.is-tucked { transform: translateY(96px); opacity: 0; pointer-events: none; }
  .ai-fab { transition: transform .2s ease, opacity .2s ease, filter var(--transition); }
  .page-content::after { content: ""; display: block; height: 72px; }
}

@media (max-width: 560px) {
  .ai-fab    { right: 14px; bottom: 14px; }
  .ai-drawer { right: 12px; left: 12px; bottom: 78px; width: auto;
               height: calc(100vh - 104px); }
}

@media (prefers-reduced-motion: reduce) {
  .ai-typing span { animation: none; opacity: .6; }
  .ai-fab, .ai-chip, .ai-icon-btn, .ai-send { transition: none; }
  .ai-fab:hover, .ai-chip:hover { transform: none; }
}


/* ═══════════════════════════════════════════════════════════════════════
   Performance commerciale (/reporting)
   ─────────────────────────────────────────────────────────────────────
   L'écran était peint en dur — bordures #E2E8F0, séparateurs #F1F5F9,
   bannière #FFFBEB/#B45309, rouge #B91C1C, ligne du commercial #EFF6FF.
   Autant de valeurs de thème clair posées sur un fond sombre : la note de
   consentement redevenait un pavé blanc en pleine largeur, les séparateurs
   de lignes disparaissaient, et le « −66,7 % » tombait sous 3:1. Tout passe
   désormais par les jetons, et les deux thèmes suivent d'eux-mêmes.

   Le second défaut était de lecture. Cinq boîtes de même largeur ne font pas
   un entonnoir : la barre centrée sous chaque nombre ne se comparait à rien,
   et la déperdition, posée sous la carte, ne disait pas de quelle étape à
   quelle autre elle se produisait. Les étapes sont maintenant empilées, la
   largeur porte l'effectif, et la déperdition est placée *entre* deux étapes.

   Enfin `data.revenue` était calculé à chaque requête et jamais affiché :
   l'écran des chiffres n'avait pas de chiffre d'en-tête. Il est en haut. */

/* — En-tête et période — */
.rp-head {
  display: flex; align-items: flex-end; justify-content: space-between;
  flex-wrap: wrap; gap: 12px; margin-bottom: 16px;
}
.rp-head__sub { font-size: var(--text-xs); color: var(--color-text-muted); margin-top: 4px; }
.rp-period { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.rp-presets {
  display: inline-flex; gap: 2px; padding: 3px;
  background: var(--color-bg); border: 1px solid var(--color-border);
  border-radius: 999px;
}
.rp-preset {
  padding: 5px 11px; border-radius: 999px; white-space: nowrap;
  font-size: var(--text-xs); font-weight: 600; text-decoration: none;
  color: var(--color-text-muted);
  transition: color var(--transition), background var(--transition);
}
.rp-preset:hover { color: var(--color-text); }
.rp-preset[aria-current="true"] {
  background: var(--color-card); color: var(--color-accent);
  box-shadow: var(--shadow-sm);
}
.rp-dates { display: flex; align-items: center; gap: 6px; }
.rp-dates .form-control { height: 32px; font-size: var(--text-xs); padding: 0 8px; width: auto; }
.rp-dates__arrow { color: var(--color-text-light); font-size: var(--text-xs); }

/* — Bandeau de chiffres clés — */
.rp-kpis {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(168px, 1fr));
  gap: 12px; margin-bottom: 16px;
}
.rp-kpi {
  background: var(--color-card);
  border: 1px solid var(--color-border);
  border-left: 3px solid var(--rp-accent, var(--color-accent));
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
  padding: 12px 15px;
}
.rp-kpi__label {
  font-size: var(--text-xs); font-weight: 700; text-transform: uppercase;
  letter-spacing: .06em; color: var(--color-text-muted);
}
.rp-kpi__value {
  margin-top: 6px; font-size: var(--text-lg); font-weight: 700; line-height: 1.1;
  color: var(--color-text); font-variant-numeric: tabular-nums;
}
.rp-kpi__unit { font-size: var(--text-xs); font-weight: 700; color: var(--color-text-muted); margin-left: 4px; }
.rp-kpi__sub { margin-top: 5px; font-size: var(--text-xs); color: var(--color-text-light); }
.rp-kpi--void .rp-kpi__value { color: var(--color-text-light); }

/* — Cartes de section — */
.rp-card {
  background: var(--color-card); border: 1px solid var(--color-border);
  border-radius: var(--radius-md); box-shadow: var(--shadow-sm);
  padding: 15px 18px; margin-bottom: 16px;
}
.rp-card__title {
  margin: 0; font-size: var(--text-sm); font-weight: 700; color: var(--color-text);
  display: flex; align-items: center; gap: 7px;
}
.rp-card__hint {
  margin: 5px 0 0; font-size: var(--text-xs); line-height: 1.5; max-width: 84ch;
  color: var(--color-text-muted);
}
.rp-card__head { margin-bottom: 14px; }

/* — Entonnoir — */
.rp-funnel { --rp-label: 148px; list-style: none; margin: 0; padding: 0; }
.rp-stage { display: flex; align-items: center; gap: 12px; padding: 5px 0; }
.rp-stage__label {
  flex: 0 0 var(--rp-label); font-size: var(--text-xs); font-weight: 600;
  color: var(--color-text);
}
.rp-stage__track {
  flex: 1 1 auto; height: 24px; border-radius: 5px;
  background: var(--color-bg); overflow: hidden;
}
.rp-stage__fill {
  display: block; height: 100%; border-radius: 5px;
  background: linear-gradient(90deg, var(--color-accent-vivid), var(--color-accent));
}
.rp-stage__count {
  flex: 0 0 4ch; text-align: right; font-size: var(--text-base); font-weight: 700;
  font-variant-numeric: tabular-nums; color: var(--color-text);
}
.rp-stage--void .rp-stage__count { color: var(--color-text-light); }
.rp-connector {
  display: flex; align-items: center; gap: 8px;
  padding-left: calc(var(--rp-label) + 12px);
}
.rp-connector::before {
  content: ""; width: 1px; height: 14px; flex: 0 0 auto;
  background: var(--color-border); margin-left: 10px;
}
.rp-drop {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: var(--text-xs); font-weight: 700; padding: 2px 8px; border-radius: 999px;
  background: var(--color-bg); color: var(--color-text-muted);
  border: 1px solid var(--color-border);
}
.rp-drop--bad {
  background: var(--color-rose-pale); color: var(--color-rose);
  border-color: transparent;
}
.rp-connector__note { font-size: var(--text-xs); color: var(--color-text-light); }

/* — Tableaux — */
/* `.data-table th` pose `text-align:left` avec une spécificité (0,1,1) que
   `.rp-num` (0,1,0) ne bat pas : les en-têtes restaient à gauche au-dessus de
   colonnes de nombres alignées à droite. D'où le sélecteur qualifié. */
.rp-num,
.data-table th.rp-num,
.data-table td.rp-num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.rp-strong { font-weight: 700; color: var(--color-text); }
.rp-dim { color: var(--color-text-light); font-weight: 400; }
.rp-name { font-weight: 600; color: var(--color-text); }
.rp-sub { display: block; font-size: var(--text-xs); color: var(--color-text-light); font-weight: 400; }
.rp-rate {
  display: inline-block; min-width: 54px; padding: 2px 9px; border-radius: 999px;
  font-size: var(--text-xs); font-weight: 700; text-align: center;
  background: var(--color-bg); color: var(--color-text-muted);
}
.rp-rate--good { background: var(--color-emerald-pale); color: var(--color-emerald); }
.rp-rate--warn { background: var(--color-amber-pale);   color: var(--color-amber); }
.rp-row--me { background: var(--color-accent-pale); }
.rp-row--me td:first-child { box-shadow: inset 3px 0 0 var(--color-accent); }
.rp-you {
  margin-left: 6px; padding: 1px 6px; border-radius: 999px; vertical-align: 1px;
  font-size: var(--text-xs); font-weight: 700; text-transform: uppercase; letter-spacing: .05em;
  color: var(--color-accent); background: var(--color-accent-pale);
}
/* Jauge de volume sous l'effectif d'un canal. Le tableau est classé par taux
   de closing : sans elle, comparer les volumes demande de lire huit nombres
   d'une colonne à l'autre. La piste est indispensable — une barre seule se
   lisait comme un soulignement mal placé. */
.rp-gauge {
  display: block; height: 3px; margin-top: 5px; border-radius: 2px;
  background: var(--color-border); overflow: hidden;
}
.rp-gauge > i {
  display: block; height: 100%; border-radius: 2px;
  background: var(--color-accent-vivid); opacity: .8;
}
.rp-reasons { display: flex; flex-wrap: wrap; gap: 4px; }
.rp-reason {
  padding: 1px 7px; border-radius: 999px; white-space: nowrap;
  font-size: var(--text-xs); font-weight: 600;
  background: var(--color-rose-pale); color: var(--color-rose);
}

/* — Note de consentement — */
.rp-note {
  display: flex; align-items: flex-start; gap: 9px; margin: 0 0 14px;
  padding: 9px 12px; max-width: 96ch;
  font-size: var(--text-xs); line-height: 1.5; color: var(--color-text);
  background: var(--color-amber-pale);
  border-left: 3px solid var(--color-amber);
  border-radius: var(--radius-sm);
}
.rp-note .ico { color: var(--color-amber); flex: 0 0 auto; margin-top: 1px; }

.rp-empty {
  padding: 26px 10px; text-align: center;
  font-size: var(--text-xs); color: var(--color-text-muted);
}

/* — Refonte : définitions uniques, filtres, tendance, détail d'un chiffre —
   Tout passe par les jetons de thème, comme le reste du bloc : aucune couleur
   de thème clair posée en dur. */
.rp-head__vs { color: var(--color-text-light); }
.rp-btn { font-size: var(--text-xs); padding: 6px 13px; display: inline-flex; align-items: center; gap: 6px; }

.rp-filters {
  display: flex; align-items: flex-end; flex-wrap: wrap; gap: 10px;
  margin: -4px 0 16px; padding: 10px 12px;
  background: var(--color-card); border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
}
.rp-filters__icon { color: var(--color-text-light); align-self: center; }
.rp-filter { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.rp-filter__label {
  font-size: var(--text-xs); font-weight: 700; text-transform: uppercase; letter-spacing: .06em;
  color: var(--color-text-muted);
}
.rp-filter .form-control { height: 32px; font-size: var(--text-xs); padding: 0 8px; min-width: 150px; max-width: 100%; }
.rp-filters__reset {
  display: inline-flex; align-items: center; gap: 4px; align-self: center;
  font-size: var(--text-xs); font-weight: 600; color: var(--color-accent); text-decoration: none;
}
.rp-filters__reset:hover { text-decoration: underline; }

/* Nombre cliquable : ouvre le détail. Il garde l'allure d'un chiffre. */
.rp-link {
  appearance: none; background: none; border: 0; padding: 0; margin: 0;
  font: inherit; color: inherit; cursor: pointer; text-align: inherit;
  text-decoration: underline dotted transparent; text-underline-offset: 3px;
  transition: color var(--transition), text-decoration-color var(--transition);
}
.rp-link:hover { color: var(--color-accent); text-decoration-color: currentColor; }
.rp-link:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; border-radius: 3px; }

.rp-kpi { position: relative; overflow: hidden; display: flex; flex-direction: column; }
.rp-kpi__top { display: flex; align-items: center; justify-content: space-between; gap: 6px; flex-wrap: wrap; }
/* `.rp-link` remet `font: inherit` : sans ces sélecteurs qualifiés, les
   chiffres cliquables tombaient à la taille du texte courant, plus petits que
   leurs voisins non cliquables. */
.rp-kpi__value.rp-link {
  display: block; width: fit-content;
  margin-top: 6px; font-size: var(--text-lg); font-weight: 700; line-height: 1.1;
  color: var(--color-text); font-variant-numeric: tabular-nums;
}
.rp-stage__count.rp-link { font-size: var(--text-base); font-weight: 700; color: var(--color-text); }
.rp-stage--void .rp-stage__count.rp-link { color: var(--color-text-light); }
.rp-kpi__tag {
  font-size: var(--text-xs); font-weight: 700; text-transform: uppercase; letter-spacing: .05em;
  color: var(--color-text-light);
}
.rp-kpi__sub { position: relative; z-index: 1; }
.rp-spark {
  display: block; width: 100%; height: 22px; margin-top: 8px;
  color: var(--rp-accent, var(--color-accent)); opacity: .75;
}
.rp-spark polyline {
  fill: none; stroke: currentColor; stroke-width: 1.6;
  vector-effect: non-scaling-stroke; stroke-linejoin: round; stroke-linecap: round;
}
.rp-delta {
  display: inline-flex; align-items: center; gap: 2px; white-space: nowrap;
  font-size: var(--text-xs); font-weight: 700; padding: 1px 6px; border-radius: 999px;
  background: var(--color-bg); color: var(--color-text-muted);
}
.rp-delta--up   { background: var(--color-emerald-pale); color: var(--color-emerald); }
.rp-delta--down { background: var(--color-rose-pale);    color: var(--color-rose); }

.rp-card__head--row {
  display: flex; align-items: baseline; justify-content: space-between; flex-wrap: wrap; gap: 4px 14px;
}
.rp-card__head--row .rp-card__hint { margin: 0; }
.rp-card__action { font-size: var(--text-xs); font-weight: 600; color: var(--color-accent); }

/* Objectifs */
.rp-targets { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 10px 18px; }
.rp-target {
  display: grid; grid-template-columns: 1fr auto; align-items: center; gap: 5px 10px;
  padding: 8px 10px; border-radius: var(--radius-sm);
}
.rp-target--team { background: var(--color-bg); }
.rp-target__head { grid-column: 1 / -1; display: flex; justify-content: space-between; gap: 8px; font-size: var(--text-xs); }
.rp-target__figure { color: var(--color-text-muted); font-variant-numeric: tabular-nums; white-space: nowrap; }
.rp-target__pct { font-size: var(--text-xs); font-weight: 700; color: var(--color-text); font-variant-numeric: tabular-nums; }
.rp-target__empty { grid-column: 1 / -1; margin: 0; font-size: var(--text-xs); color: var(--color-text-muted); }
.rp-meter { display: block; height: 6px; border-radius: 3px; background: var(--color-border); overflow: hidden; }
.rp-meter > i { display: block; height: 100%; border-radius: 3px; background: var(--color-accent-vivid); }
.rp-meter > i.rp-meter--done { background: var(--color-emerald-vivid); }

/* Tendance */
.rp-chart { position: relative; height: 240px; }

/* Entonnoir : trois niveaux de perte, et une hausse qui ne se lit pas comme une perte */
.rp-drop--warn { background: var(--color-amber-pale); color: var(--color-amber); border-color: transparent; }
.rp-drop--rise { background: var(--color-emerald-pale); color: var(--color-emerald); border-color: transparent; }
.rp-connector__time { display: inline-flex; align-items: center; gap: 3px; margin-left: 6px; }
.rp-stage__count.rp-link { flex: 0 0 4ch; text-align: right; }
.rp-stage__fill--paid { background: linear-gradient(90deg, var(--color-emerald-vivid), var(--color-emerald)); }
.rp-meetings {
  display: flex; align-items: center; flex-wrap: wrap; gap: 6px;
  margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--color-border);
  font-size: var(--text-xs);
}
.rp-meetings__title { display: inline-flex; align-items: center; gap: 5px; font-weight: 700; color: var(--color-text); margin-right: 4px; }
.rp-meetings__rate { margin-left: auto; font-weight: 700; color: var(--color-text); }
.rp-chip {
  display: inline-flex; align-items: center; gap: 4px; padding: 2px 8px; border-radius: 999px;
  background: var(--color-bg); color: var(--color-text-muted); border: 1px solid var(--color-border);
}
.rp-chip b { color: var(--color-text); font-variant-numeric: tabular-nums; }
.rp-chip--good { background: var(--color-emerald-pale); border-color: transparent; }
.rp-chip--good b { color: var(--color-emerald); }
.rp-chip--bad { background: var(--color-rose-pale); border-color: transparent; }
.rp-chip--bad b { color: var(--color-rose); }
.rp-chip--warn { background: var(--color-amber-pale); border-color: transparent; }
.rp-chip--warn b { color: var(--color-amber); }

/* Tableaux */
.rp-table tfoot td {
  font-weight: 700; color: var(--color-text);
  border-top: 2px solid var(--color-border); background: var(--color-bg);
}
.rp-row--unassigned .rp-name { font-style: italic; color: var(--color-text-muted); }
.rp-footnote {
  display: flex; align-items: center; gap: 6px; margin: 10px 0 0;
  font-size: var(--text-xs); color: var(--color-amber);
}
.rp-campaigns { margin-top: 4px; font-size: var(--text-xs); color: var(--color-text-muted); }
.rp-campaigns summary { cursor: pointer; width: fit-content; }
.rp-campaigns ul { list-style: none; margin: 4px 0 0; padding: 0 0 0 10px; border-left: 2px solid var(--color-border); }
.rp-campaigns li { display: flex; justify-content: space-between; gap: 10px; padding: 1px 0; }

/* Deux colonnes : à relancer, pertes */
.rp-split { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 16px 28px; }
.rp-subtitle {
  display: flex; align-items: baseline; justify-content: space-between; gap: 8px;
  margin: 0 0 8px; font-size: var(--text-xs); font-weight: 700; text-transform: uppercase;
  letter-spacing: .05em; color: var(--color-text-muted);
}
.rp-subtitle__more { font-size: var(--text-xs); font-weight: 600; text-transform: none; letter-spacing: 0; color: var(--color-accent); }
.rp-muted { margin: 0; font-size: var(--text-xs); color: var(--color-text-muted); }
.rp-list { list-style: none; margin: 0; padding: 0; }
.rp-list li {
  display: grid; grid-template-columns: minmax(0, auto) minmax(0, 1fr) auto; align-items: center; gap: 8px;
  padding: 6px 0; border-bottom: 1px solid var(--color-border); font-size: var(--text-xs);
}
.rp-list li:last-child { border-bottom: 0; }
.rp-list .rp-name { text-decoration: none; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rp-list .rp-name:hover { color: var(--color-accent); }
.rp-list .rp-dim { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rp-list--compact { margin-top: 10px; }
.rp-list--compact li { grid-template-columns: auto minmax(0, 1fr); }
.rp-badge {
  font-size: var(--text-xs); font-weight: 700; padding: 1px 7px; border-radius: 999px; white-space: nowrap;
  background: var(--color-bg); color: var(--color-text-muted);
}
.rp-badge--warn { background: var(--color-amber-pale); color: var(--color-amber); }
.rp-badge--bad  { background: var(--color-rose-pale);  color: var(--color-rose); }

.rp-bars { list-style: none; margin: 0; padding: 0; display: grid; gap: 9px; }
.rp-bar {
  display: grid; grid-template-columns: minmax(90px, 34%) 1fr auto; align-items: center; gap: 4px 10px;
  font-size: var(--text-xs);
}
.rp-bar__label { color: var(--color-text); font-weight: 600; }
.rp-bar__track { height: 8px; border-radius: 4px; background: var(--color-bg); overflow: hidden; }
.rp-bar__track > i { display: block; height: 100%; border-radius: 4px; background: var(--color-rose-vivid); opacity: .85; }
.rp-bar__value { font-weight: 700; font-variant-numeric: tabular-nums; white-space: nowrap; }
.rp-bar__note { grid-column: 1 / -1; font-size: var(--text-xs); color: var(--color-text-light); }

.rp-facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(110px, 1fr)); gap: 8px; margin: 0; }
.rp-facts > div { padding: 7px 9px; border-radius: var(--radius-sm); background: var(--color-bg); }
.rp-facts dt { font-size: var(--text-xs); font-weight: 700; text-transform: uppercase; letter-spacing: .05em; color: var(--color-text-muted); }
.rp-facts dd { margin: 2px 0 0; font-size: var(--text-sm); font-weight: 700; color: var(--color-text); font-variant-numeric: tabular-nums; }

.rp-note--info { background: var(--color-accent-pale); border-left-color: var(--color-accent); }

/* Panneau latéral du détail */
.rp-drawer { position: fixed; inset: 0; z-index: 9000; }
.rp-drawer__backdrop { position: absolute; inset: 0; background: rgba(15, 23, 42, .45); }
.rp-drawer__panel {
  position: absolute; top: 0; right: 0; bottom: 0; width: min(460px, 100%);
  display: flex; flex-direction: column;
  background: var(--color-card); border-left: 1px solid var(--color-border);
  box-shadow: -12px 0 32px rgba(15, 23, 42, .18);
  animation: rp-drawer-in .16s ease-out;
}
.rp-drawer__close {
  position: absolute; top: 12px; right: 12px; display: inline-flex; padding: 6px;
  background: none; border: 0; border-radius: var(--radius-sm); cursor: pointer; color: var(--color-text-muted);
}
.rp-drawer__close:hover { background: var(--color-bg); color: var(--color-text); }
.rp-drawer__body { overflow-y: auto; padding: 18px 20px 24px; }
.rp-drawer__title { margin: 0 32px 2px 0; font-size: var(--text-base); font-weight: 700; color: var(--color-text); }
.rp-drawer__sub { margin: 0 0 14px; font-size: var(--text-xs); color: var(--color-text-muted); }
html.rp-drawer-open { overflow: hidden; }
@keyframes rp-drawer-in { from { transform: translateX(24px); opacity: 0; } to { transform: none; opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .rp-drawer__panel { animation: none; } }

.rp-deals { list-style: none; margin: 0; padding: 0; }
.rp-deal {
  display: flex; justify-content: space-between; gap: 12px;
  padding: 9px 0; border-bottom: 1px solid var(--color-border);
}
.rp-deal__main { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.rp-deal__name { font-size: var(--text-xs); font-weight: 600; color: var(--color-text); text-decoration: none; }
.rp-deal__name:hover { color: var(--color-accent); }
.rp-deal__meta { font-size: var(--text-xs); color: var(--color-text-muted); }
.rp-deal__side { display: flex; flex-direction: column; align-items: flex-end; gap: 2px; font-size: var(--text-xs); white-space: nowrap; }

@media (max-width: 760px) {
  .rp-funnel { --rp-label: 92px; }
  .rp-period { width: 100%; }
  .rp-kpi__value { font-size: var(--text-lg); }
  .rp-filters { align-items: stretch; }
  .rp-filter { flex: 1 1 140px; }
  .rp-filter .form-control { min-width: 0; width: 100%; }
  .rp-meetings__rate { margin-left: 0; }
  .rp-bar { grid-template-columns: 1fr auto; }
  .rp-bar__track { grid-column: 1 / -1; grid-row: 2; }
}
@media (max-width: 900px) {
  /* Six périodes ne tiennent pas sur un téléphone : la barre défile plutôt
     que de couper « 12 mois » au bord de l'écran. */
  .rp-presets { max-width: 100%; overflow-x: auto; scrollbar-width: none; }
  .rp-presets::-webkit-scrollbar { display: none; }
}
@media (max-width: 760px) {
  .rp-kpi__value.rp-link { font-size: var(--text-lg); }
}
@media (max-width: 480px) {
  .rp-funnel { --rp-label: 76px; }
  .rp-stage__label { font-size: var(--text-xs); }
  .rp-connector { padding-left: 0; flex-wrap: wrap; }
  .rp-dates { flex-wrap: wrap; }
}

/* ---- Boîtes de dialogue internes (static/js/dialogs.js) ----
   Remplacent confirm() / prompt() / alert() du navigateur : même thème, même
   langue, même boutons que le reste du CRM. */
.crm-dialog-overlay {
  position: fixed; inset: 0; z-index: 10000;
  display: flex; align-items: center; justify-content: center;
  padding: 16px; background: rgba(15, 23, 42, .55);
  animation: crm-dialog-fade .12s ease-out;
}
.crm-dialog {
  width: 100%; max-width: 440px;
  background: var(--color-card); color: var(--color-text);
  border: 1px solid var(--color-border); border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg); padding: 20px;
  animation: crm-dialog-pop .14s ease-out;
}
.crm-dialog--danger { border-top: 3px solid var(--color-rose-solid); }
.crm-dialog__title { font-weight: 600; font-size: var(--text-md); margin-bottom: 6px; }
.crm-dialog__msg { font-size: var(--text-sm); line-height: 1.55; white-space: pre-line; overflow-wrap: anywhere; }
.crm-dialog__field {
  display: block; width: 100%; margin-top: 14px; padding: .5rem .7rem;
  font: inherit; font-size: var(--text-xs); color: var(--color-text);
  background: var(--color-bg); border: 1px solid var(--color-border); border-radius: var(--radius-sm);
}
.crm-dialog__field:focus { outline: 2px solid var(--color-accent); outline-offset: 1px; }
.crm-dialog__actions { display: flex; justify-content: flex-end; flex-wrap: wrap; gap: 8px; margin-top: 18px; }
.crm-dialog__actions .btn { cursor: pointer; }
.crm-dialog__actions .btn:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }

.crm-toasts {
  position: fixed; right: 16px; bottom: 16px; z-index: 10001;
  display: flex; flex-direction: column; gap: 8px;
  max-width: min(380px, calc(100vw - 32px));
}
.crm-toast {
  padding: 10px 14px; font-size: var(--text-xs); line-height: 1.45; cursor: pointer;
  background: var(--color-card); color: var(--color-text);
  border: 1px solid var(--color-border); border-left: 3px solid var(--color-accent);
  border-radius: var(--radius-sm); box-shadow: var(--shadow-md);
  overflow-wrap: anywhere; animation: crm-dialog-pop .14s ease-out;
}
.crm-toast--error   { border-left-color: var(--color-rose-solid); }
.crm-toast--success { border-left-color: var(--color-emerald-solid); }

@keyframes crm-dialog-fade { from { opacity: 0; } }
@keyframes crm-dialog-pop  { from { opacity: 0; transform: translateY(6px) scale(.98); } }
@media (prefers-reduced-motion: reduce) {
  .crm-dialog-overlay, .crm-dialog, .crm-toast { animation: none; }
}

/* ---- Fiche contact (contacts/detail.html) ----
   Classes sur jetons plutôt que styles en ligne : les couleurs en dur de
   l'ancien en-tête ne suivaient le thème sombre qu'à travers les sélecteurs
   `[style*=…]` de rattrapage, et le bouton WhatsApp restait un aplat clair. */
.contact-back { margin-bottom: .5rem; }
.contact-head {
  display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center;
  gap: 12px 20px; padding: 16px 20px;
}
.contact-head__identity { display: flex; align-items: center; gap: 14px; min-width: 0; }
.contact-head__text { min-width: 0; }
.contact-head__name {
  display: flex; flex-wrap: wrap; align-items: center; gap: 4px 10px;
  margin: 0; font-size: var(--text-lg); font-weight: 700; color: var(--color-text); overflow-wrap: anywhere;
}
.contact-head__badges { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-top: 6px; }
.contact-head__badges .badge { display: inline-flex; align-items: center; gap: 4px; }
.contact-company-badge { text-decoration: none; font-weight: 700; }
.contact-head__meta { margin-top: 6px; font-size: var(--text-xs); color: var(--color-text-muted); }
.contact-head__actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.contact-head__actions .btn { display: inline-flex; align-items: center; gap: 6px; text-decoration: none; }
.contact-avatar {
  display: flex; align-items: center; justify-content: center; flex-shrink: 0;
  width: 52px; height: 52px; border-radius: 50%;
  font-size: var(--text-md); font-weight: 700; color: var(--color-accent); background: var(--color-accent-pale);
}
.contact-avatar--vip { color: #fff; background: linear-gradient(135deg, #FBBF24, #B45309); }
.contact-star { display: inline-flex; align-items: center; gap: 3px; font-size: var(--text-xs); font-weight: 700; color: var(--color-amber); }
/* Vert WhatsApp assombri : le blanc dessus passe 5:1, dans les deux thèmes. */
.btn-whatsapp { background: #0F7A3F; color: #fff; border: 1px solid transparent; }
.btn-whatsapp:hover { background: #0B6433; color: #fff; }

.contact-menu { position: relative; }
.contact-menu__panel {
  position: absolute; top: calc(100% + 6px); right: 0; z-index: 50;
  min-width: 220px; max-width: calc(100vw - 32px); padding: 6px;
  background: var(--color-card); border: 1px solid var(--color-border);
  border-radius: var(--radius-md); box-shadow: var(--shadow-lg);
}
.contact-menu__panel form { margin: 0; }
.contact-menu__item {
  display: flex; align-items: center; gap: 8px; width: 100%; padding: 8px 10px;
  border: 0; border-radius: var(--radius-sm); background: transparent;
  font: inherit; font-size: var(--text-xs); color: var(--color-text); text-align: left; text-decoration: none; cursor: pointer;
}
.contact-menu__item:hover, .contact-menu__item:focus-visible { background: var(--color-bg); outline: none; }
.contact-menu__item--danger { color: var(--color-rose); }
.contact-menu__sep { height: 1px; margin: 6px 4px; background: var(--color-border); }

.contact-alerts { display: flex; flex-wrap: wrap; gap: 8px 16px; padding: 10px 16px; }
.contact-alert { display: inline-flex; align-items: center; gap: 6px; font-size: var(--text-xs); font-weight: 600; }
.contact-alert--danger  { color: var(--color-rose); }
.contact-alert--warning { color: var(--color-amber); }
.contact-trashed {
  display: flex; align-items: center; gap: 10px; padding: 10px 16px; font-size: var(--text-xs);
  color: var(--color-rose); background: var(--color-rose-pale); border: 1px solid var(--color-rose);
}

.tab-btn .ico { vertical-align: -3px; }
.tab-count {
  display: inline-block; min-width: 1.5em; margin-left: 2px; padding: 0 .4em;
  border: 1px solid var(--color-border); border-radius: 99px; background: var(--color-bg);
  font-size: var(--text-xs); font-weight: 600; line-height: 1.5; text-align: center; color: var(--color-text-muted);
}

.contact-stack { display: flex; flex-direction: column; gap: 16px; }
.detail-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; align-items: start; }
.contact-more { margin-top: 12px; }
.contact-more summary { cursor: pointer; font-size: var(--text-xs); font-weight: 700; color: var(--color-accent); }
.contact-more .info-dl { margin-top: 10px; }
.contact-channel { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.contact-channel__wa { display: inline-flex; color: var(--color-emerald); }
.contact-copy {
  display: inline-flex; align-items: center; padding: 2px; border: 0; border-radius: 4px;
  background: transparent; color: var(--color-text-muted); cursor: pointer;
}
.contact-copy:hover, .contact-copy:focus-visible { color: var(--color-accent); background: var(--color-bg); outline: none; }
.contact-empty { margin: 0; font-size: var(--text-xs); color: var(--color-text-muted); }
.contact-multiline { white-space: pre-line; }
.contact-notes {
  padding: 10px 12px; border-radius: var(--radius-sm); background: var(--color-bg);
  font-size: var(--text-xs); color: var(--color-text); white-space: pre-wrap;
}

@media (max-width: 768px) {
  .detail-grid { grid-template-columns: minmax(0, 1fr); }
  .contact-head { padding: 14px; }
  .contact-head__actions { width: 100%; }
}

/* ── Pastille juridiction (logo ou initiales) — partials/jur.html ──────────
   Fond blanc même en thème sombre : la plupart des logos de free zones sont
   sombres sur transparent et disparaîtraient sur l'ardoise. */
.jm { display: inline-flex; align-items: center; gap: 6px; vertical-align: middle; max-width: 100%; }
.jm-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.jm-chip {
  display: inline-grid; place-items: center; flex: none; overflow: hidden;
  background: #fff; border-radius: 5px; box-shadow: 0 0 0 1px rgba(15, 23, 42, .08);
}
.jm-chip img { width: 88%; height: 88%; object-fit: contain; display: block; }
.jm-init {
  background: var(--color-accent-pale); color: var(--color-accent);
  font-weight: 700; letter-spacing: .02em; line-height: 1; box-shadow: none;
}
:root[data-theme="dark"] .jm-chip:not(.jm-init), .dark .jm-chip:not(.jm-init) { box-shadow: 0 0 0 1px rgba(255, 255, 255, .12); }

/* ── Photo de profil — partials/avatar.html ────────────────────────────────
   Ronde, recadrée : elle prend la place de l'emoji de la personne. */
.user-photo {
  display: inline-block; flex: none; vertical-align: middle;
  border-radius: 50%; object-fit: cover; background: var(--color-border);
}

/* =============================================
   Système visuel — unification des modules
   =============================================
   Chaque module a écrit ses propres cartes de synthèse dans le bloc `<style>`
   de son gabarit : `.it-kpi`, `.sec-kpi`, `.ac-stat`, `.exp-kpi`, `.com-kpi`…
   Douze variantes d'un même objet — liseré à gauche ici, en haut là, texte
   centré ailleurs, aplat dégradé en Marketing, fond teinté en Juridictions —
   et autant de tailles de chiffre (17 à 26 px, graisse 800).

   Cette couche leur donne une seule apparence sans réécrire les gabarits. Elle
   est préfixée par `.page-content` : à spécificité 0,2,0 elle l'emporte sur la
   règle du module (0,1,0, chargée après), mais cède devant ses variantes d'état
   (`.ld-kpi.bad`, `.ac-stat.is-active`), qui restent donc lisibles. */
.page-content :is(.kpi-card, .it-kpi, .sec-kpi, .ac-kpi, .ac-stat, .at-kpi, .com-kpi, .exp-kpi, .mkt-kpi, .ld-kpi, .pt-stat, .rp-kpi) {
  background: var(--color-card);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
  text-align: left;
}
.page-content :is(.ac-kpi, .at-kpi):hover { transform: none; border-color: var(--color-border-strong); }

/* Le chiffre : 24 px, graisse 600, chiffres tabulaires. */
.page-content :is(.kpi-value, .ac-kpi-val, .ac-stat-val, .at-kpi-val, .com-kpi-val, .exp-kpi-val, .mkt-kpi-val, .pt-stat-val, .rp-kpi__value, .tw-value),
.page-content :where(.it-kpi, .sec-kpi) .kv {
  font-size: var(--text-xl);
  font-weight: 600;
  letter-spacing: -.01em;
  line-height: 1.2;
  font-variant-numeric: tabular-nums;
}
.page-content :where(.ld-kpi) .v { font-size: var(--text-md); font-weight: 600; letter-spacing: -.01em; font-variant-numeric: tabular-nums; }

/* Le libellé : 12 px en bas de casse. Les capitales espacées à 10 px étaient
   la partie la moins lisible de la carte alors qu'elles en donnent le sens. */
.page-content :is(.kpi-label, .ac-kpi-label, .ac-stat-label, .at-kpi-label, .com-kpi-label, .exp-kpi-label, .mkt-kpi-label, .pt-stat-label, .rp-kpi__label, .tw-label),
.page-content :where(.it-kpi, .sec-kpi) .kl {
  font-size: var(--text-xs);
  font-weight: 500;
  text-transform: none;
  letter-spacing: 0;
  color: var(--color-text-muted);
}
.page-content :is(.kpi-sub, .ac-stat-sub, .at-kpi-sub, .com-kpi-sub),
.page-content :where(.sec-kpi) .ks,
.page-content :where(.ld-kpi) .s {
  font-size: var(--text-xs);
  color: var(--color-text-light);
}
/* Widget « Aujourd'hui » du tableau de bord : même contour, sans liseré. */
.page-content .today-widget-item { border: 1px solid var(--color-border); border-radius: var(--radius-md); }

/* ---- Barres d'onglets des modules ----
   Même logique : `.it-tabs`, `.sec-tabs`, `.ac-tabs`… reprennent tous le motif
   « soulignement », à un filet de 2 px près. On aligne le filet et la graisse. */
.page-content :is(.it-tabs, .sec-tabs, .ac-tabs, .hr-tabs, .exp-tabs, .fin-tabs, .jur-tabs, .pl-tabs, .tabs-list, .tab-bar) {
  border-bottom-width: 1px;
}
.page-content :is(.it-tab, .sec-tab, .ac-tab, .hr-tab, .exp-tab, .fin-tab, .jur-tab, .pl-tab) {
  margin-bottom: -1px;
  font-size: var(--text-sm);
  font-weight: 500;
}

/* ---- Champs écrits sans classe ----
   Une partie des formulaires pose ses champs en style inline, sans `.form-input`.
   On leur donne au moins la hauteur commune, sans
   toucher au reste : seul le plancher de hauteur est posé ici. */
.page-content :is(input[type="text"], input[type="email"], input[type="tel"], input[type="number"], input[type="date"], input[type="time"], input[type="search"], input[type="password"], input[type="url"], input:not([type]), select):not(.filter-select):not(.filter-date):not([class*="ai-"]) {
  min-height: var(--ctl-h-sm);
}
.page-content textarea { line-height: 1.5; }

/* ---- Bandeau de configuration : une ligne, détail à la demande ----
   Le bandeau reste non refermable (c'est un état, pas une notification), mais
   il occupait 180 px sur chaque page — et il est posé hors de la zone qui
   défile, donc jamais hors champ. Replié, il tient sur une ligne ; le détail
   et la marche à suivre s'ouvrent au clic. */
.notice--compact { padding-top: .45rem; padding-bottom: .45rem; align-items: center; }
.notice--compact > .notice__icon { margin-top: 0; }
.notice--compact:has(details[open]) { align-items: flex-start; }
.notice-details > summary {
  display: flex; align-items: center; gap: .5rem;
  cursor: pointer; list-style: none;
  font-weight: 600; color: var(--notice-color);
}
.notice-details > summary::-webkit-details-marker { display: none; }
.notice-details__toggle {
  margin-left: auto;
  font-size: var(--text-xs); font-weight: 600;
  text-decoration: underline; text-underline-offset: 2px;
}
.notice-details[open] .notice-details__toggle--more,
.notice-details:not([open]) .notice-details__toggle--less { display: none; }
.notice-details[open] > summary { margin-bottom: .45rem; }

/* ---- Téléphone : les cartes de synthèse défilent en bandeau ----
   Empilées deux par deux, dix cartes repoussaient la liste trois écrans plus
   bas. En bandeau horizontal elles tiennent sur une rangée et la première
   ligne utile reste visible. */
@media (max-width: 640px) {
  .page-content { padding: 16px; }
  .page-content :is(.kpi-grid, .kpi-row, .it-kpi-grid, .sec-kpi-grid, .ac-kpi-grid, .ac-stat-grid, .at-kpi-grid, .com-kpi-grid, .exp-kpi-grid, .mkt-kpi-grid, .pt-stats, .rp-kpis) {
    display: flex; flex-wrap: nowrap; overflow-x: auto;
    scroll-snap-type: x proximity; padding-bottom: 4px;
    scrollbar-width: none;
  }
  .page-content :is(.kpi-grid, .kpi-row, .it-kpi-grid, .sec-kpi-grid, .ac-kpi-grid, .ac-stat-grid, .at-kpi-grid, .com-kpi-grid, .exp-kpi-grid, .mkt-kpi-grid, .pt-stats, .rp-kpis)::-webkit-scrollbar { display: none; }
  .page-content :is(.kpi-grid, .kpi-row, .it-kpi-grid, .sec-kpi-grid, .ac-kpi-grid, .ac-stat-grid, .at-kpi-grid, .com-kpi-grid, .exp-kpi-grid, .mkt-kpi-grid, .pt-stats, .rp-kpis) > * {
    flex: 0 0 auto; min-width: 150px; scroll-snap-align: start;
  }
}

/* ---- Interrupteur ----
   Une case à cocher suivie de « ON » / « OFF » en vert pâle (2,4:1) : l'état se
   lisait mal et la cible faisait 13 px. Même `<input>`, donc même sémantique
   et même clavier ; seule l'apparence change. */
input[type="checkbox"].switch {
  appearance: none; -webkit-appearance: none;
  position: relative; flex-shrink: 0;
  width: 36px; height: 20px; min-height: 0;
  border-radius: 99px; border: 0;
  background: var(--color-border-strong);
  cursor: pointer;
  transition: background var(--transition);
}
input[type="checkbox"].switch::after {
  content: ""; position: absolute; top: 2px; left: 2px;
  width: 16px; height: 16px; border-radius: 50%;
  background: #fff; box-shadow: 0 1px 2px rgba(16,24,40,.3);
  transition: transform var(--transition);
}
input[type="checkbox"].switch:checked { background: var(--color-accent-solid); }
input[type="checkbox"].switch:checked::after { transform: translateX(16px); }

/* ---- Teinte venue des données ----
   Un statut, une catégorie ou un score apportent leur couleur depuis la base
   ou depuis Alpine. Le motif d'origine — `background: <ton>22; color: <ton>` —
   pose le ton plein sur son propre voile : 2,1:1 pour l'ambre, 2,5:1 pour
   l'émeraude. Ces deux classes reçoivent le ton par `--tone` et en tirent un
   texte lisible dans les deux thèmes (mêmes jetons que le pont de contraste). */
.tone-text { color: color-mix(in srgb, var(--tone, var(--color-text-muted)) var(--tone-pct), var(--tone-mix)); }
.tone-chip {
  background: color-mix(in srgb, var(--tone, var(--color-text-muted)) 13%, transparent);
  color: color-mix(in srgb, var(--tone, var(--color-text-muted)) var(--tone-pct), var(--tone-mix));
}

/* En-têtes de tableau : bas de casse partout, y compris quand le gabarit ou
   le module demandait des capitales en ligne. */
.page-content th { text-transform: none !important; letter-spacing: 0 !important; }

/* Cibles de clic : 28 px au moins pour les actions de ligne et de carte. */
.page-content :is(.at-btn-sm, .ac-btn-sm, .pl-seg-btn, .action-more, .at-pill) { min-height: var(--ctl-h-xs); }
.page-content .kb-act { min-height: 26px; }

/* Grille de synthèse (liste Clients) : même bandeau défilant sur téléphone. */
.summary-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 12px; margin-top: 14px; }
@media (max-width: 640px) {
  .summary-grid { display: flex; overflow-x: auto; scroll-snap-type: x proximity; padding-bottom: 4px; scrollbar-width: none; }
  .summary-grid::-webkit-scrollbar { display: none; }
  .summary-grid > * { flex: 0 0 auto; min-width: 190px; scroll-snap-align: start; }
}

@media (max-width: 760px) {
  .page-content .rp-kpi__value { font-size: var(--text-lg); }
}

/* ---- Retours de la recette navigateur (rôle commercial) ---- */
/* Compteurs « Aujourd'hui » : teintes foncées passées par le gabarit, illisibles sur carte sombre. */
:root[data-theme="dark"] .tw-value,
.dark .tw-value { color: color-mix(in srgb, var(--tw-color, var(--color-accent)) 55%, #fff); }
/* Champs date et heure : le navigateur ajoute un padding interne qui les rendait
   2 px plus hauts que le champ texte voisin. */
input[type="date"]::-webkit-datetime-edit,
input[type="time"]::-webkit-datetime-edit,
input[type="datetime-local"]::-webkit-datetime-edit { padding-top: 0; padding-bottom: 0; line-height: 1.2; }
input[type="date"]::-webkit-datetime-edit-fields-wrapper,
input[type="time"]::-webkit-datetime-edit-fields-wrapper { padding: 0; }
/* Action principale d'une ligne : même hauteur que le menu « Plus » voisin. */
.page-content .action-primary { min-height: var(--ctl-h-xs); }

/* ── Formulaires : en-tête commun (forms/_header.html) ─────────────────────
   Partagé par l'éditeur, le partage, les résultats, les intégrations et les
   réglages : il vit ici plutôt que dans builder.css, que les pages de
   résultats ne chargent pas. */
.forms-header { margin-bottom: 1.25rem; }
.forms-header-top { display: flex; align-items: center; gap: .75rem; flex-wrap: wrap; }
.forms-back { color: var(--color-text-muted); text-decoration: none; font-size: var(--text-sm); }
.forms-back:hover { color: var(--color-text); }
.forms-title { margin: 0; font-size: var(--text-lg); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.forms-status { font-size: var(--text-xs); }
.forms-status-draft     { background: var(--color-bg); color: var(--color-text-muted); border: 1px solid var(--color-border); }
.forms-status-published { background: var(--color-emerald); color: #fff; }
.forms-status-closed    { background: var(--color-rose-pale, var(--color-bg)); color: var(--color-text); border: 1px solid var(--color-border); }
.forms-tabs { display: flex; gap: .25rem; margin-top: .75rem; border-bottom: 1px solid var(--color-border); overflow-x: auto; }
.forms-tabs a {
  padding: .55rem .9rem; color: var(--color-text-muted); text-decoration: none; font-size: var(--text-sm);
  font-weight: 500; border-bottom: 2px solid transparent; margin-bottom: -1px; white-space: nowrap;
}
.forms-tabs a:hover { color: var(--color-text); }
.forms-tabs a.active { color: var(--color-accent); border-bottom-color: var(--color-accent); }

/* ---- Navigation par jour (Récap du jour) ----
   Les flèches étaient des liens stylés en ligne : pas de survol, pas d'état
   pressé, un glyphe « ‹ » de 14 px dans une case de 60 px. Trois commandes de
   même hauteur, avec retour visuel au survol, au clic et au clavier. */
.date-nav { display: inline-flex; align-items: center; gap: .5rem; }
.date-nav__btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: var(--ctl-h); height: var(--ctl-h);
  border-radius: var(--radius-sm);
  border: 1px solid var(--color-border-strong);
  background: var(--color-card);
  color: var(--color-text);
  box-shadow: var(--shadow-sm);
  cursor: pointer;
  transition: background var(--transition), border-color var(--transition), color var(--transition), transform var(--transition);
}
.date-nav__btn:hover { background: var(--color-accent-pale); border-color: var(--color-accent); color: var(--color-accent); text-decoration: none; }
.date-nav__btn:active { transform: scale(.94); }
.date-nav__input {
  height: var(--ctl-h);
  padding: 0 .75rem;
  border-radius: var(--radius-sm);
  border: 1px solid var(--color-border-strong);
  background: var(--color-card);
  color: var(--color-text);
  box-shadow: var(--shadow-sm);
  font-weight: 700;
  font-size: var(--text-base);
  font-variant-numeric: tabular-nums;
  cursor: pointer;
  transition: background var(--transition), border-color var(--transition);
}
.date-nav__input:hover { border-color: var(--color-accent); }
.date-nav__input::-webkit-calendar-picker-indicator { cursor: pointer; opacity: .65; }
.date-nav__input:hover::-webkit-calendar-picker-indicator { opacity: 1; }
.date-nav.is-loading { opacity: .55; pointer-events: none; }

/* ── Tableaux de bord des départements (`dd-*`, app/static/js/dept_dash.js) ──
   Licence, Visa, Banque, Logistique, IT, RH et la carte « Départements » de
   l'accueil. Même vocabulaire que le tableau de bord du marketing (`md-*`),
   jetons de couleur seulement : le thème sombre suit sans règle à part. */
.dd-bar{display:flex;gap:8px;align-items:center;flex-wrap:wrap;margin-bottom:12px}
.dd-bar input[type=date]{width:auto}
.dd-select,.dd-input{padding:6px 10px;border:1px solid var(--color-border);border-radius:6px;font-size:var(--text-xs);background:var(--color-bg);color:var(--color-text)}
.dd-select{cursor:pointer}
.dd-chips{display:flex;gap:6px;flex-wrap:wrap}
.dd-chip{padding:5px 12px;border:1px solid var(--color-border);border-radius:999px;font-size:var(--text-xs);font-weight:600;background:var(--color-card);color:var(--color-text-muted);cursor:pointer;text-decoration:none}
.dd-chip:hover{border-color:var(--color-accent-solid);color:var(--color-text)}
.dd-chip.active{background:var(--color-accent-solid);border-color:var(--color-accent-solid);color:#fff}
.dd-note{font-size:var(--text-xs);color:var(--color-text-muted);margin:0 0 14px}
.dd-kpis{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:10px;margin-bottom:16px}
.dd-kpi{display:block;background:var(--color-card);border:1px solid var(--color-border);border-radius:10px;padding:12px 14px;text-decoration:none;color:inherit}
a.dd-kpi:hover{border-color:var(--color-accent-solid)}
.dd-kpi-l{font-size:var(--text-xs);font-weight:600;color:var(--color-text-muted);margin-bottom:4px}
.dd-kpi-v{font-size:var(--text-xl);font-weight:700;color:var(--color-text);line-height:1.1;font-variant-numeric:tabular-nums}
.dd-kpi-d{font-size:var(--text-xs);font-weight:600;color:var(--color-text-muted);margin-top:2px;font-variant-numeric:tabular-nums}
.dd-kpi-d.up{color:var(--color-emerald,#059669)}.dd-kpi-d.down{color:var(--color-rose,#dc2626)}
.dd-kpi.warn .dd-kpi-v{color:var(--color-amber,#d97706)}
.dd-kpi.bad .dd-kpi-v{color:var(--color-rose,#dc2626)}
.dd-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(340px,100%),1fr));gap:14px}
.dd-card{background:var(--color-card);border:1px solid var(--color-border);border-radius:10px;overflow:hidden;margin-bottom:14px}
.dd-card-h{padding:11px 16px;border-bottom:1px solid var(--color-border);font-weight:700;font-size:var(--text-sm);display:flex;align-items:center;justify-content:space-between;gap:8px}
.dd-card-h a{font-size:var(--text-xs);font-weight:600;color:var(--color-accent-solid);text-decoration:none}
.dd-card-b{padding:14px 16px}
.dd-empty{display:flex;align-items:center;justify-content:center;min-height:70px;color:var(--color-text-muted);font-size:var(--text-xs);text-align:center}
.dd-donut{display:flex;gap:18px;align-items:center;flex-wrap:wrap}
.dd-donut svg{width:140px;height:140px;flex:none;color:var(--color-text)}
.dd-leg{display:flex;flex-direction:column;gap:6px;font-size:var(--text-xs);min-width:140px;flex:1}
.dd-leg div{display:grid;grid-template-columns:12px 1fr auto auto;gap:8px;align-items:center}
.dd-leg i{width:10px;height:10px;border-radius:3px}
.dd-leg b{font-variant-numeric:tabular-nums}
.dd-hbar{display:grid;grid-template-columns:minmax(90px,42%) 1fr auto;gap:8px;align-items:center;font-size:var(--text-xs);padding:4px 0;text-decoration:none;color:var(--color-text)}
a.dd-hbar:hover span:first-child{text-decoration:underline}
.dd-hbar-t{height:8px;background:var(--color-bg);border-radius:4px;overflow:hidden}
.dd-hbar-f{height:100%;background:var(--color-accent-solid);border-radius:4px}
.dd-hbar b{font-variant-numeric:tabular-nums}
.dd-steps{display:flex;gap:4px;flex-wrap:wrap;align-items:stretch}
.dd-step{flex:1;min-width:92px;border:1px solid var(--color-border);border-radius:8px;padding:8px 10px;text-decoration:none;color:inherit;background:var(--color-bg)}
a.dd-step:hover{border-color:var(--color-accent-solid)}
.dd-step b{display:block;font-size:var(--text-lg);font-variant-numeric:tabular-nums;color:var(--color-text)}
.dd-step span{font-size:var(--text-xs);color:var(--color-text-muted)}
.dd-table{width:100%;border-collapse:collapse;font-size:var(--text-xs)}
.dd-table th{text-align:left;color:var(--color-text-muted);font-weight:700;padding:6px 8px;border-bottom:1px solid var(--color-border);white-space:nowrap}
.dd-table td{padding:6px 8px;border-bottom:1px solid var(--color-border);vertical-align:middle;font-variant-numeric:tabular-nums}
.dd-table tr:last-child td{border-bottom:none}
.dd-table td.n,.dd-table th.n{text-align:right;white-space:nowrap}
.dd-table a{color:var(--color-text);font-weight:600;text-decoration:none}
.dd-table a:hover{text-decoration:underline}
.dd-sub{font-size:var(--text-xs);color:var(--color-text-muted)}
.dd-pill{display:inline-block;font-size:10px;font-weight:700;border-radius:999px;padding:1px 7px;white-space:nowrap;background:var(--color-bg);border:1px solid var(--color-border);color:var(--color-text-muted)}
.dd-pill.bad{color:var(--color-rose,#dc2626);border-color:currentColor}
.dd-pill.warn{color:var(--color-amber,#d97706);border-color:currentColor}
.dd-scroll{overflow-x:auto}
/* Carte « Départements » de l'accueil : une ligne par département. */
.dd-depts{display:flex;flex-direction:column}
.dd-dept{display:grid;grid-template-columns:minmax(110px,22%) 1fr auto;gap:10px;align-items:center;padding:9px 16px;border-bottom:1px solid var(--color-border);text-decoration:none;color:var(--color-text);font-size:var(--text-xs)}
.dd-dept:last-child{border-bottom:none}
.dd-dept:hover{background:var(--color-bg)}
.dd-dept strong{font-size:var(--text-sm)}
.dd-dept-n{display:flex;gap:6px 14px;flex-wrap:wrap;color:var(--color-text-muted)}
.dd-dept-n b{color:var(--color-text);font-variant-numeric:tabular-nums}
.dd-dept-n .bad b{color:var(--color-rose,#dc2626)}
.dd-dept-n .warn b{color:var(--color-amber,#d97706)}
@media (max-width:640px){
  .dd-dept{grid-template-columns:1fr auto}
  .dd-dept-n{grid-column:1 / -1;order:3}
}

/* ═══════════════════════════════════════════════════════════════════════════
   Design system 2026-10 (from the SEO redesign) — classes `ds-*`
   ───────────────────────────────────────────────────────────────────────────
   Vocabulaire commun aux sections refaites (SEO d'abord, puis Pipeline,
   Clients, Factures…). Chaque classe reproduit à l'identique son homologue
   `seo-*` de app/templates/seo/index.html ; la page SEO garde ses propres
   classes pour l'instant.

   Couleur d'état : `[data-s]` pose trois variables lues par les pastilles,
   les colonnes du kanban, les étiquettes —
     --s        texte (lisible sur blanc comme sur ardoise)
     --s-vivid  point / accent / liseré
     --s-pale   fond
   Clés sémantiques (slate, blue, purple, amber, teal, emerald, indigo, rose)
   et clés métier (étapes du pipeline, statuts SEO) : une étape = une teinte,
   reprise partout. L'échelle des étapes suit `status_color()` côté serveur.
   ═══════════════════════════════════════════════════════════════════════════ */
:root{
  --ds-slate:#475569;--ds-slate-vivid:#64748B;--ds-slate-pale:#EEF2F7;
  --ds-teal:#0F766E;--ds-teal-vivid:#14B8A6;--ds-teal-pale:#F0FDFA;
  --ds-indigo:#4338CA;--ds-indigo-vivid:#6366F1;--ds-indigo-pale:#EEF2FF;
}
:root[data-theme="dark"]{
  --ds-slate:#CBD5E1;--ds-slate-vivid:#94A3B8;--ds-slate-pale:rgba(148,163,184,.16);
  --ds-teal:#5EEAD4;--ds-teal-vivid:#2DD4BF;--ds-teal-pale:rgba(45,212,191,.14);
  --ds-indigo:#A5B4FC;--ds-indigo-vivid:#818CF8;--ds-indigo-pale:rgba(129,140,248,.16);
}

/* ── Bande d'en-tête : titre, sélecteur, actions ── */
.ds-head{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;margin-bottom:8px}
.ds-head .page-title{margin:0}
.ds-head-l,.ds-head-r{display:flex;align-items:center;gap:10px;flex-wrap:wrap;min-width:0}
.ds-sub{font-size:var(--text-sm);color:var(--color-text-muted);font-variant-numeric:tabular-nums}

/* ── Sélecteur segmenté ──
   `.ds-seg` : bascule de vue (fond page, bouton actif en carte).
   `.ds-seg--solid` : sélecteur d'entité (carte, bouton actif plein) — le
   sélecteur de site de la page SEO. */
.ds-seg{display:inline-flex;padding:3px;border:1px solid var(--color-border);border-radius:9px;background:var(--color-bg)}
.ds-seg button{display:inline-flex;align-items:center;gap:6px;height:26px;padding:0 12px;border:none;border-radius:6px;background:none;color:var(--color-text-muted);font:inherit;font-size:var(--text-sm);font-weight:500;cursor:pointer;white-space:nowrap;transition:background .12s,color .12s}
.ds-seg button:hover{color:var(--color-text)}
.ds-seg button.on{background:var(--color-card);color:var(--color-text);font-weight:600;box-shadow:var(--shadow-sm)}
.ds-seg--solid{gap:2px;border-radius:10px;background:var(--color-card);box-shadow:var(--shadow-sm)}
.ds-seg--solid button{height:30px;border-radius:7px;gap:7px}
.ds-seg--solid button:hover{background:var(--color-bg)}
.ds-seg--solid button.on{background:var(--color-sidebar-bg);color:#fff;box-shadow:none}
:root[data-theme="dark"] .ds-seg--solid button.on{background:var(--color-accent-solid)}
.ds-seg--solid img{width:18px;height:18px;border-radius:5px;object-fit:contain;background:#fff;box-shadow:0 0 0 1px rgba(16,24,40,.08)}
.ds-seg .ds-n{font-size:11px;font-weight:600;opacity:.65;font-variant-numeric:tabular-nums}
.ds-seg button.on .ds-n{opacity:.85}

/* ── Onglets soulignés + compteur ── */
.ds-tabs{display:flex;gap:26px;border-bottom:1px solid var(--color-border);margin-bottom:14px;overflow-x:auto;scrollbar-width:none}
.ds-tabs::-webkit-scrollbar{display:none}
.ds-tabs button,.ds-tabs a{display:inline-flex;align-items:center;gap:8px;padding:10px 2px 11px;border:none;border-bottom:2px solid transparent;margin-bottom:-1px;background:none;color:var(--color-text-muted);font:inherit;font-size:var(--text-base);font-weight:600;cursor:pointer;white-space:nowrap;text-decoration:none;transition:color .12s}
.ds-tabs button:hover,.ds-tabs a:hover{color:var(--color-text)}
.ds-tabs button.on,.ds-tabs a.on{color:var(--color-text);border-bottom-color:var(--color-accent-solid)}
.ds-tabs svg{color:var(--color-text-light)}
.ds-tabs .on svg{color:var(--color-accent)}
.ds-count{min-width:20px;padding:1px 7px;border-radius:99px;background:var(--color-bg);border:1px solid var(--color-border);color:var(--color-text-muted);font-size:11px;font-weight:600;font-variant-numeric:tabular-nums;text-align:center;line-height:1.5}
.ds-tabs .on .ds-count{background:var(--color-accent-pale);border-color:transparent;color:var(--color-accent)}
.ds-count.warn{background:var(--color-rose-pale);border-color:transparent;color:var(--color-rose)}

/* ── Barre d'outils ── */
.ds-bar{display:flex;align-items:flex-start;justify-content:space-between;gap:10px;flex-wrap:wrap;margin-bottom:12px}
.ds-bar-l,.ds-bar-r{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.ds-bar-l{flex:1 1 0;min-width:0}
.ds-bar-r{flex:0 0 auto}
.ds-search{position:relative;display:inline-flex;align-items:center;color:var(--color-text-light)}
.ds-search svg{position:absolute;left:10px;pointer-events:none}
.ds-search input{height:32px;width:210px;padding:0 10px 0 32px;border:1px solid var(--color-border);border-radius:8px;background:var(--color-card);color:var(--color-text);font:inherit;font-size:var(--text-sm)}
.ds-search input:focus{outline:none;border-color:var(--color-accent-solid);box-shadow:0 0 0 3px color-mix(in srgb,var(--color-accent-solid) 15%,transparent)}
.ds-search input::placeholder{color:var(--color-text-light)}
.ds-pill{display:inline-flex;align-items:center;gap:6px;height:32px;max-width:190px;padding:0 26px 0 12px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;border:1px solid var(--color-border);border-radius:99px;background:var(--color-card) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 24 24' fill='none' stroke='%23667085' stroke-width='2.5' stroke-linecap='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E") no-repeat right 11px center;appearance:none;-webkit-appearance:none;color:var(--color-text);font:inherit;font-size:var(--text-sm);font-weight:500;cursor:pointer}
.ds-pill:hover{border-color:var(--color-border-strong)}
.ds-pill:focus-visible{outline:2px solid var(--color-accent-solid);outline-offset:1px}
.ds-pill.on{border-color:color-mix(in srgb,var(--color-accent-solid) 40%,transparent);background-color:var(--color-accent-pale);color:var(--color-accent);font-weight:600}
.ds-pill--btn{background-image:none;padding-right:12px;max-width:none}
.ds-pill--btn .ds-count{margin-left:2px}
.ds-pill--btn.on .ds-count{background:var(--color-card);border-color:transparent;color:var(--color-accent)}
.ds-pill--danger.on{border-color:color-mix(in srgb,var(--color-rose) 40%,transparent);background-color:var(--color-rose-pale);color:var(--color-rose)}
.ds-pill--danger.on .ds-count{color:var(--color-rose)}
input.ds-pill{background-image:none;padding-right:12px;cursor:text}
input.ds-pill:focus{outline:none;border-color:var(--color-accent-solid);box-shadow:0 0 0 3px color-mix(in srgb,var(--color-accent-solid) 15%,transparent)}
.ds-clear{border:none;background:none;color:var(--color-text-light);font:inherit;font-size:var(--text-sm);cursor:pointer;padding:0 4px}
.ds-clear:hover{color:var(--color-text)}
.ds-clear.on{display:inline-flex;align-items:center;gap:4px;height:26px;padding:0 9px;border-radius:99px;background:color-mix(in srgb,var(--color-text) 7%,transparent);color:var(--color-text);font-size:var(--text-xs);font-weight:600}
.ds-clear.on:hover{background:color-mix(in srgb,var(--color-text) 12%,transparent)}
.ds-meta{font-size:var(--text-sm);color:var(--color-text-light);font-variant-numeric:tabular-nums;margin-left:4px}
.ds-btn-primary{display:inline-flex;align-items:center;gap:6px;height:32px;padding:0 14px;border:none;border-radius:8px;background:var(--color-accent-solid);color:#fff;font:inherit;font-size:var(--text-sm);font-weight:600;cursor:pointer;text-decoration:none;white-space:nowrap;box-shadow:0 1px 2px rgba(37,99,235,.35)}
.ds-btn-primary:hover{filter:brightness(1.07);color:#fff;text-decoration:none}
.ds-btn{display:inline-flex;align-items:center;gap:6px;height:32px;padding:0 12px;border:1px solid var(--color-border);border-radius:8px;background:var(--color-card);color:var(--color-text);font:inherit;font-size:var(--text-sm);font-weight:500;cursor:pointer;text-decoration:none;white-space:nowrap}
.ds-btn:hover{border-color:var(--color-border-strong);color:var(--color-text);text-decoration:none}
.ds-btn.sm,.ds-btn-primary.sm{height:28px;padding:0 10px;font-size:var(--text-xs)}
.ds-btn.on{background:var(--color-accent-pale);border-color:color-mix(in srgb,var(--color-accent-solid) 40%,transparent);color:var(--color-accent);font-weight:600}
.ds-btn.danger{color:var(--color-rose)}
.ds-btn.danger:hover{border-color:color-mix(in srgb,var(--color-rose) 40%,transparent);background:var(--color-rose-pale)}

/* ── Panneau de filtres repliable ── */
.ds-filters{margin:-4px 0 12px;padding:12px;background:color-mix(in srgb,var(--color-card) 55%,var(--color-bg));border:1px solid var(--color-border);border-radius:12px}
.ds-filters-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(180px,1fr));gap:10px}
.ds-field{display:flex;flex-direction:column;gap:4px;min-width:0}
.ds-field>span{font-size:11px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:var(--color-text-light)}
.ds-field .ds-pill{width:100%;max-width:none}
.ds-field-pair{display:flex;gap:6px}
.ds-field-pair .ds-pill{flex:1;min-width:0}
.ds-filters-foot{display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin-top:10px}

/* ── Tableau silencieux : en-tête figé, lignes de 40 px, pas de filets verticaux ── */
.ds-table-wrap{overflow:auto;max-height:calc(100vh - 250px);border:1px solid var(--color-border);border-radius:12px;background:var(--color-card);box-shadow:var(--shadow-sm)}
.ds-table-wrap.auto{max-height:none}
.ds-table{border-collapse:separate;border-spacing:0;width:100%;font-size:var(--text-sm);font-variant-numeric:tabular-nums}
.ds-table th{position:sticky;top:0;z-index:3;height:36px;padding:0 10px;background:color-mix(in srgb,var(--color-bg) 55%,var(--color-card));border-bottom:1px solid var(--color-border);text-align:left;font-size:11px;font-weight:600;letter-spacing:.05em;text-transform:uppercase;color:var(--color-text-light);white-space:nowrap}
.ds-table th.r,.ds-table td.r{text-align:right}
.ds-table th.sort{cursor:pointer;user-select:none}
.ds-table th.sort:hover{color:var(--color-text)}
.ds-table td{height:40px;padding:0 10px;border-bottom:1px solid color-mix(in srgb,var(--color-border) 70%,transparent);vertical-align:middle;background:var(--color-card);color:var(--color-text)}
.ds-table tbody tr:last-child td{border-bottom:none}
.ds-table tbody tr:hover td{background:color-mix(in srgb,var(--color-accent-solid) 3.5%,var(--color-card))}
.ds-table tbody tr.link{cursor:pointer}
.ds-table td.muted,.ds-table .muted{color:var(--color-text-muted)}
.ds-table td.faint{color:var(--color-text-light)}
.ds-table td.strong,.ds-table .strong{font-weight:600}
.ds-table td.num{font-weight:600;white-space:nowrap}
.ds-table td.nowrap{white-space:nowrap}
.ds-table td.c-act{white-space:nowrap;text-align:right;padding-right:8px}
.ds-table td.c-act .ds-ico{opacity:0;transition:opacity .12s}
.ds-table tr:hover td.c-act .ds-ico,.ds-table td.c-act .ds-ico:focus-visible,.ds-table td.c-act .ds-ico.keep{opacity:1}
.ds-table .ds-av{vertical-align:middle;margin-right:6px}
.ds-table tr.late td:first-child{box-shadow:inset 3px 0 0 var(--color-rose)}
.ds-table tr.due td:first-child{box-shadow:inset 3px 0 0 var(--color-amber)}
.ds-sub{display:block;font-size:var(--text-xs);color:var(--color-text-muted);line-height:1.3;margin-top:1px}
.ds-empty{padding:28px;text-align:center;color:var(--color-text-light);font-size:var(--text-sm)}
.ds-empty svg{display:block;margin:0 auto 8px;color:var(--color-border-strong)}

/* Actions de ligne et de carte : icônes nues, révélées au survol */
.ds-ico{display:inline-flex;align-items:center;justify-content:center;width:26px;height:26px;padding:0;border:none;border-radius:6px;background:none;color:var(--color-text-light);cursor:pointer;text-decoration:none;font:inherit}
.ds-ico:hover{background:color-mix(in srgb,var(--color-text) 7%,transparent);color:var(--color-text)}
.ds-ico.del:hover{background:var(--color-rose-pale);color:var(--color-rose)}
.ds-ico.ok{color:var(--color-emerald)}
.ds-ico.ok:hover{background:var(--color-emerald-pale);color:var(--color-emerald)}
.ds-ico.acc:hover{background:var(--color-accent-pale);color:var(--color-accent)}
.ds-ico.txt{width:auto;padding:0 8px;gap:4px;font-size:11px;font-weight:700}
.ds-ico.on{background:var(--color-accent-pale);color:var(--color-accent)}
.ds-ico[disabled]{opacity:.3;cursor:default;pointer-events:none}

/* ── Statut : pastille teintée, point de couleur ── */
.ds-status{--s:var(--ds-slate);--s-vivid:var(--ds-slate-vivid);--s-pale:var(--ds-slate-pale);display:inline-flex;align-items:center;height:24px;padding:0 10px 0 22px;border:none;border-radius:99px;appearance:none;-webkit-appearance:none;font:inherit;font-size:12px;font-weight:600;line-height:1;white-space:nowrap;cursor:default;
  background:var(--s-pale) radial-gradient(circle at 11px 50%,var(--s-vivid) 3.5px,transparent 4px);color:var(--s);box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--s-vivid) 22%,transparent)}
select.ds-status{cursor:pointer;padding-right:24px;background-image:radial-gradient(circle at 11px 50%,var(--s-vivid) 3.5px,transparent 4px),url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 24 24' fill='none' stroke='%23667085' stroke-width='2.5' stroke-linecap='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:0 0,right 9px center}
select.ds-status option{background:var(--color-card);color:var(--color-text)}
.ds-status[disabled]{cursor:default}
.ds-status:focus-visible{outline:2px solid var(--color-accent-solid);outline-offset:1px}
.ds-status.sm{height:22px;font-size:11px}

/* Responsable : initiales sur pastel stable (window.dsAvatarStyle) */
.ds-av{width:22px;height:22px;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;font-size:10px;font-weight:700;letter-spacing:.02em;background:var(--color-bg);color:var(--color-text)}
.ds-av.ext{box-shadow:inset 0 0 0 1.5px currentColor;opacity:.85}
.ds-av.lg{width:44px;height:44px;font-size:16px}
.ds-who{display:inline-flex;align-items:center;gap:6px;min-width:0;font-size:var(--text-xs);color:var(--color-text)}
.ds-who span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* Étiquettes : fond neutre, ou teintées par `data-s` */
.ds-tag{display:inline-flex;align-items:center;gap:4px;height:20px;padding:0 7px;border-radius:6px;background:color-mix(in srgb,var(--color-text) 6%,transparent);color:var(--color-text-muted);font-size:11px;font-weight:600;line-height:1;white-space:nowrap;max-width:100%}
.ds-tag>span{overflow:hidden;text-overflow:ellipsis}
.ds-tag svg{flex-shrink:0}
.ds-tag[data-s]{background:var(--s-pale);color:var(--s)}
.ds-tag.hi{background:var(--color-rose-pale);color:var(--color-rose)}
.ds-tag.warn{background:var(--color-amber-pale);color:var(--color-amber)}
.ds-tag.ok{background:var(--color-emerald-pale);color:var(--color-emerald)}
.ds-tag.acc{background:var(--color-accent-pale);color:var(--color-accent)}
.ds-tag.outline{background:transparent;box-shadow:inset 0 0 0 1px var(--color-border);color:var(--color-text-muted)}
.ds-tag.num{font-variant-numeric:tabular-nums;color:var(--color-text);background:var(--color-bg);box-shadow:inset 0 0 0 1px var(--color-border)}
.ds-tag.num b{font-weight:700}
.ds-tag.num i{font-style:normal;font-weight:500;color:var(--color-text-light);font-size:10px}

/* Puces : filtres à bascule (`.on`) ou repères (`.now`, `.ok`, `.warn`) */
.ds-chip{display:inline-flex;align-items:center;gap:4px;padding:2px 8px;border-radius:99px;background:var(--color-card);border:1px solid var(--color-border);color:var(--color-text-muted);font:inherit;font-size:11px;font-weight:600;line-height:1.5;vertical-align:1px;white-space:nowrap}
button.ds-chip{cursor:pointer;transition:border-color .12s,color .12s,background .12s}
button.ds-chip:hover{border-color:var(--color-accent-solid);color:var(--color-accent)}
.ds-chip.on{background:var(--color-accent-pale);color:var(--color-accent);border-color:color-mix(in srgb,var(--color-accent-solid) 45%,transparent)}
.ds-chip.now{background:var(--color-accent-solid);border-color:transparent;color:#fff;text-transform:uppercase;letter-spacing:.04em;font-size:10px}
.ds-chip.ok{color:var(--color-emerald);border-color:color-mix(in srgb,var(--color-emerald) 25%,transparent);background:var(--color-emerald-pale)}
.ds-chip.warn{color:var(--color-amber);border-color:color-mix(in srgb,var(--color-amber) 25%,transparent);background:var(--color-amber-pale)}

/* ── Tuiles de chiffres (compactes, pour les sections où l'on travaille) ── */
.ds-stats{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:12px}
.ds-stat{--t:var(--color-text-muted);flex:1 1 150px;display:flex;align-items:center;gap:10px;min-width:0;height:56px;padding:0 14px 0 12px;border:1px solid var(--color-border);border-radius:12px;background:var(--color-card);box-shadow:var(--shadow-sm)}
.ds-stat::before{content:"";width:3px;height:28px;border-radius:2px;background:var(--t);flex-shrink:0}
.ds-stat-v{font-size:var(--text-lg);font-weight:700;letter-spacing:-.01em;line-height:1.1;font-variant-numeric:tabular-nums;color:var(--color-text);white-space:nowrap}
.ds-stat-v small{font-size:var(--text-xs);font-weight:600;color:var(--color-text-muted);margin-left:3px;letter-spacing:0}
.ds-stat-l{font-size:var(--text-xs);color:var(--color-text-muted);line-height:1.25;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ds-stat-l b{display:block;font-weight:600;color:var(--color-text)}
.ds-stat.zero .ds-stat-v{color:var(--color-text-light)}
/* Carte-filtre : la carte est un lien qui filtre le tableau. */
a.ds-stat{color:inherit;text-decoration:none;transition:border-color .12s,box-shadow .12s}
a.ds-stat:hover{border-color:var(--color-border-strong);text-decoration:none}
a.ds-stat.on{border-color:var(--t);box-shadow:0 0 0 3px color-mix(in srgb,var(--t) 15%,transparent)}

/* ── Bandeau d'alerte discret ── */
.ds-note{display:flex;align-items:center;gap:10px;margin-bottom:12px;padding:8px 12px;border:1px solid var(--color-border);border-left:3px solid var(--color-text-light);border-radius:10px;background:color-mix(in srgb,var(--color-card) 55%,var(--color-bg));font-size:var(--text-xs);color:var(--color-text-muted)}
.ds-note svg{flex-shrink:0;color:var(--color-text-light)}
.ds-note b{color:var(--color-text);font-weight:600}
.ds-note.warn{border-left-color:var(--color-amber-vivid);background:var(--color-amber-pale)}
.ds-note.warn svg,.ds-note.warn b{color:var(--color-amber)}
.ds-note .clip{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ds-note a{color:var(--color-accent);text-decoration:none}
.ds-note a:hover{text-decoration:underline}

/* ── Kanban : une colonne par état, dans sa couleur ── */
.ds-kanban{display:grid;grid-template-columns:repeat(4,1fr);gap:14px;align-items:start}
.ds-kanban--3{grid-template-columns:repeat(3,1fr)}
/* Variante défilante (sept étapes) : colonnes à largeur fixe, barre native
   visible — pas de curseur de défilement au-dessus (décision du 02/10). */
/* Toutes les étapes tiennent dans la largeur (flex, 1 part chacune, 172 px au
   moins — 7 étapes tiennent sur un écran de 1 600 px) ; une colonne repliée devient une bande de 46 px. En dessous de la
   largeur minimale seulement, le tableau défile de côté. */
.ds-kanban--scroll{display:flex;gap:10px;align-items:stretch;overflow-x:auto;padding-bottom:6px}
.ds-kanban--scroll > .ds-kcol{flex:1 1 0;min-width:172px}
.ds-kanban--scroll > .ds-kcol.collapsed{flex:0 0 46px;min-width:46px}
.ds-kcol-strip{display:flex;flex-direction:column;align-items:center;gap:10px;width:100%;height:100%;min-height:220px;padding:10px 0;border:none;background:none;color:var(--s);cursor:pointer}
.ds-kcol-strip:hover{background:color-mix(in srgb,var(--s-vivid) 10%,transparent)}
.ds-kcol-strip-label{display:flex;align-items:center;gap:8px;writing-mode:vertical-rl;font-size:var(--text-sm);font-weight:700;white-space:nowrap}
.ds-kcol.collapsed.drop{box-shadow:0 0 0 2px var(--s-vivid)}
.ds-kanban--scroll::-webkit-scrollbar{height:10px}
.ds-kanban--scroll::-webkit-scrollbar-track{background:transparent}
.ds-kanban--scroll::-webkit-scrollbar-thumb{background:var(--color-border-strong);border-radius:99px}
.ds-kanban--scroll::-webkit-scrollbar-thumb:hover{background:var(--color-text-light)}
@media (max-width:900px){.ds-kanban:not(.ds-kanban--scroll){grid-template-columns:1fr}}
.ds-kcol{--s:var(--ds-slate);--s-vivid:var(--ds-slate-vivid);--s-pale:var(--ds-slate-pale);position:relative;display:flex;flex-direction:column;min-width:0;background:color-mix(in srgb,var(--s-vivid) 7%,var(--color-bg));border:1px solid color-mix(in srgb,var(--s-vivid) 22%,var(--color-border));border-top:3px solid var(--s-vivid);border-radius:12px;overflow:hidden;transition:box-shadow .12s}
.ds-kanban--scroll .ds-kcol{max-height:var(--kb-col-h,calc(100vh - 190px))}
.ds-kcol.drop{box-shadow:0 0 0 2px var(--s-vivid)}
.ds-kcol-head{display:flex;align-items:center;gap:8px;padding:11px 12px 7px}
.ds-kcol-title{display:flex;align-items:center;gap:9px;min-width:0;font-size:var(--text-sm);font-weight:700;color:var(--s)}
/* En-tête avec outils (nombre + filtre + replier, Leads) : dans une colonne
   étroite, les outils passent sous le nom au lieu de le couper (« Nouve… »).
   La règle suit la largeur de la colonne, donc toutes basculent ensemble. */
.ds-kcol-head.tools{flex-wrap:wrap;row-gap:4px;container-type:inline-size}
.ds-kcol-tools{display:flex;align-items:center;gap:6px;margin-left:auto;flex-shrink:0}
.ds-kcol-tools .ds-kcount{margin-left:0}
@container (max-width:280px){.ds-kcol-head.tools > .ds-kcol-title{flex-basis:100%}}
.ds-kcol-title span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ds-kdot{width:9px;height:9px;border-radius:50%;flex-shrink:0;background:var(--s-vivid);box-shadow:0 0 0 3px color-mix(in srgb,var(--s-vivid) 22%,transparent)}
.ds-kcount{margin-left:auto;flex-shrink:0;min-width:22px;padding:2px 8px;border-radius:99px;background:color-mix(in srgb,var(--s-vivid) 16%,var(--color-card));color:var(--s);font-size:11px;font-weight:700;font-variant-numeric:tabular-nums;text-align:center;white-space:nowrap}
.ds-kcol-head .ds-ico{color:var(--s);opacity:.6}
.ds-kcol-head .ds-ico:hover,.ds-kcol-head .ds-ico.on{opacity:1;background:color-mix(in srgb,var(--s-vivid) 18%,transparent)}
.ds-kcol-body{flex:1;display:flex;flex-direction:column;gap:8px;padding:4px 10px 10px;min-height:80px;border-radius:10px;overflow-y:auto;overflow-x:hidden;overscroll-behavior:contain;scrollbar-width:thin;transition:background .12s}
.ds-kcol-body.drag-over{background:color-mix(in srgb,var(--s-vivid) 16%,transparent);outline:2px dashed var(--s-vivid);outline-offset:-5px}
.ds-kempty{margin:4px 0 2px;padding:22px 10px;border:1.5px dashed color-mix(in srgb,var(--s-vivid) 35%,var(--color-border));border-radius:10px;text-align:center;color:var(--color-text-light);font-size:var(--text-xs);font-weight:500}
.ds-kmore{flex-shrink:0;padding:8px;border:1px dashed color-mix(in srgb,var(--s-vivid) 35%,var(--color-border));border-radius:10px;background:transparent;font:inherit;font-size:var(--text-xs);font-weight:600;color:var(--color-text-muted);cursor:pointer}
.ds-kmore:hover{border-color:var(--s-vivid);color:var(--s)}
.ds-kmore span{font-weight:500;opacity:.75}

/* Cartes */
.ds-kcard{position:relative;flex-shrink:0;background:var(--color-card);border:1px solid var(--color-border);border-radius:10px;padding:10px 12px 9px;box-shadow:var(--shadow-sm);cursor:grab;transition:box-shadow .15s,border-color .15s,transform .15s,opacity .15s}
.ds-kcard:hover{border-color:color-mix(in srgb,var(--s-vivid) 50%,var(--color-border));box-shadow:0 4px 14px color-mix(in srgb,var(--s-vivid) 16%,rgba(16,24,40,.06))}
.ds-kcard.dragging{opacity:.45}
.ds-kcard[draggable="false"]{cursor:pointer}
.ds-kcard-top{display:flex;align-items:flex-start;justify-content:space-between;gap:8px}
.ds-kcard-title{font-size:var(--text-sm);font-weight:600;line-height:1.4;color:var(--color-text);display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;overflow-wrap:anywhere}
[data-s="done"] .ds-kcard-title,[data-s="published"] .ds-kcard-title,[data-s="completed"] .ds-kcard-title,[data-s="lost"] .ds-kcard-title{color:var(--color-text-muted)}
.ds-kcard-sub{display:flex;align-items:center;gap:5px;margin-top:2px;font-size:var(--text-xs);color:var(--color-text-muted);min-width:0}
.ds-kcard-sub span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ds-kcard-sub svg{flex-shrink:0;opacity:.7}
.ds-kcard-tags{display:flex;flex-wrap:wrap;gap:4px;margin-top:7px}
.ds-kcard-tags:empty{display:none}
.ds-kcard-meta{display:flex;align-items:center;gap:6px;margin-top:8px;min-height:20px;font-size:var(--text-xs);color:var(--color-text-muted)}
.ds-kcard-meta .sep{opacity:.5}
.ds-kcard-meta .ds-av{width:20px;height:20px;font-size:9px}
.ds-kcard-meta .who{font-weight:500;color:var(--color-text);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}
.ds-kcard-meta .r{display:inline-flex;align-items:center;gap:8px;margin-left:auto;flex-shrink:0}
.ds-kcard-meta .cnt{display:inline-flex;align-items:center;gap:3px;color:var(--color-text-light);font-variant-numeric:tabular-nums}
/* Actions révélées au survol, en surimpression dans l'angle inférieur droit :
   aucune place réservée, aucun décalage. */
.ds-kcard-actions{position:absolute;right:8px;bottom:7px;display:flex;gap:2px;padding:2px;border-radius:8px;background:var(--color-card);box-shadow:-12px 0 10px -6px var(--color-card),0 0 0 1px var(--color-border),0 4px 12px rgba(16,24,40,.12);opacity:0;visibility:hidden;transition:opacity .12s,visibility 0s .12s}
/* Les actions n'arrivent qu'après un court arrêt sur la carte : saisir la carte
   pour la glisser tombe sur la carte, pas sur un bouton (un glisser qui part d'un
   bouton ne démarre pas). Au clavier, elles sont là tout de suite. */
.ds-kcard:hover .ds-kcard-actions{opacity:1;visibility:visible;transition:opacity .12s .35s,visibility 0s .35s}
.ds-kcard:focus-within .ds-kcard-actions{opacity:1;visibility:visible;transition:none}
/* La barre prend la place de la ligne de pied (responsable, dernier contact)
   le temps du survol : elle la recouvrait à moitié. */
.ds-kcard-meta{transition:visibility 0s .35s}
.ds-kcard:hover .ds-kcard-meta{visibility:hidden}
.ds-kcard:focus-within .ds-kcard-meta{visibility:hidden;transition:none}
.ds-kcard-actions .ds-ico{width:24px;height:24px}
.ds-kcard-actions .ds-ico.txt{width:auto}
@media (hover:none){
  .ds-kcard:hover .ds-kcard-meta,.ds-kcard:focus-within .ds-kcard-meta{visibility:visible}
  .ds-kcard-actions{position:static;opacity:1;pointer-events:auto;margin-top:8px;padding:8px 0 0;background:none;box-shadow:none;border-radius:0;border-top:1px solid var(--color-border);justify-content:flex-end}
  .ds-kcard-actions .ds-ico{width:36px;height:36px}
  .ds-table td.c-act .ds-ico{opacity:1}
}
/* Leads : rangée d'actions toujours visible, sous le pied de carte — rien ne
   surgit au survol, rien ne déborde, le commercial reste affiché. Au repos les
   icônes sont discrètes ; elles prennent leur couleur au survol de la carte. */
.ds-kcard .ds-kcard-actions--row{position:static;opacity:1;visibility:visible;transition:none;align-items:center;gap:0;margin:8px -4px -3px;padding:6px 0 0;border-radius:0;border-top:1px solid var(--color-border);background:none;box-shadow:none;justify-content:flex-start;container-type:inline-size}
.ds-kcard--actrow:hover .ds-kcard-meta,.ds-kcard--actrow:focus-within .ds-kcard-meta{visibility:visible;transition:none}
/* Jamais tassés : une carte de 150 px (sept colonnes sur 1440 px) les
   écrasait les uns contre les autres. */
.ds-kcard .ds-kcard-actions--row .ds-ico{flex-shrink:0;width:26px;color:var(--color-text-light)}
.ds-kcard .ds-kcard-actions--row .ds-ico.txt{width:auto;gap:4px;padding:0 6px}
/* Carte étroite : « Brief » garde son icône et son infobulle, perd son libellé. */
@container (max-width:170px){.ds-kcard-actions--row .kc-lbl{display:none}.ds-kcard .ds-kcard-actions--row .ds-ico.txt{width:26px;padding:0}}
@media (hover:none){.ds-kcard .ds-kcard-actions--row .ds-ico,.ds-kcard .ds-kcard-actions--row .ds-ico.txt{min-width:36px;height:36px}}
.ds-kcard .ds-kcard-actions--row .ds-ico:disabled{opacity:.35;cursor:default;background:none}
.ds-kcard:hover .ds-kcard-actions--row .ds-ico.ok:not(:disabled){color:var(--color-emerald)}
.ds-kcard:hover .ds-kcard-actions--row .ds-ico.acc:not(:disabled){color:var(--color-accent)}
.ds-kcard-actions--row .kc-more{margin-left:auto}
/* Le menu ⋯ s'ouvre vers le haut, dans la largeur de la carte : vers le bas,
   la colonne (qui défile) le couperait sous la dernière carte. */
.ds-kcard-actions--row .ds-menu{top:auto;bottom:calc(100% + 4px);min-width:0;width:max-content}
/* Anneau de score (chaud / tiède / froid), à droite du titre */
.ds-ring{flex-shrink:0;width:24px;height:24px;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;font-size:10px;font-weight:700;line-height:1;font-variant-numeric:tabular-nums;color:var(--tone,var(--color-text-muted));background:color-mix(in srgb,var(--tone,var(--color-text-muted)) 12%,var(--color-card));box-shadow:inset 0 0 0 1.5px currentColor}

/* ── État → couleur (déclaré en dernier : prime sur les valeurs par défaut) ──
   Sémantique                 Pipeline            SEO
   slate   non qualifié       new                 todo
   blue    en contact         contacted           doing / writing
   purple  rencontre          rdv_done            review
   amber   la balle au client quote_sent          idea / carried
   teal    accord             quote_accepted      —
   emerald encaissé / clos    paid / completed    done / published
   indigo  livraison          in_progress         —
   rose    perdu              lost                — */
[data-s="slate"],[data-s="neutral"],[data-s="new"],[data-s="todo"],[data-s="draft"]{--s:var(--ds-slate);--s-vivid:var(--ds-slate-vivid);--s-pale:var(--ds-slate-pale)}
[data-s="blue"],[data-s="contacted"],[data-s="doing"],[data-s="writing"],[data-s="sent"]{--s:var(--color-accent);--s-vivid:var(--color-accent-vivid);--s-pale:var(--color-accent-pale)}
[data-s="purple"],[data-s="rdv_done"],[data-s="review"]{--s:var(--color-purple);--s-vivid:var(--color-purple-vivid);--s-pale:var(--color-purple-pale)}
[data-s="amber"],[data-s="quote_sent"],[data-s="idea"],[data-s="carried"],[data-s="pending"]{--s:var(--color-amber);--s-vivid:var(--color-amber-vivid);--s-pale:var(--color-amber-pale)}
[data-s="teal"],[data-s="quote_accepted"],[data-s="accepted"]{--s:var(--ds-teal);--s-vivid:var(--ds-teal-vivid);--s-pale:var(--ds-teal-pale)}
[data-s="emerald"],[data-s="paid"],[data-s="completed"],[data-s="done"],[data-s="published"]{--s:var(--color-emerald);--s-vivid:var(--color-emerald-vivid);--s-pale:var(--color-emerald-pale)}
[data-s="indigo"],[data-s="in_progress"]{--s:var(--ds-indigo);--s-vivid:var(--ds-indigo-vivid);--s-pale:var(--ds-indigo-pale)}
[data-s="rose"],[data-s="lost"],[data-s="overdue"],[data-s="refused"]{--s:var(--color-rose);--s-vivid:var(--color-rose-vivid);--s-pale:var(--color-rose-pale)}

/* ═══════════════════════════════════════════════════════════════════════════
   Design system 2026-10 — fiches et listes (ajouté avec Clients & Sociétés)
   ───────────────────────────────────────────────────────────────────────────
   Pièces réutilisables par les sections suivantes (Factures, Finance) :
   fil d'Ariane `ds-crumb`, en-tête de fiche `ds-hero`, menu `ds-menu`,
   cartes de section `ds-card`, grilles `ds-cols`, clé/valeur `ds-kv`,
   journal `ds-tl`, lignes de pièces `ds-doc`, jauge `ds-meter`, listes
   `ds-rows`, pagination `ds-pager`, formulaires `ds-fgrid` / `ds-check` /
   `ds-form-foot`, et la table d'états des visas, sociétés, pièces, dossiers.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── Fil d'Ariane ── */
.ds-crumb{display:flex;align-items:center;gap:6px;margin-bottom:10px;font-size:var(--text-xs);color:var(--color-text-muted);min-width:0}
.ds-crumb a{display:inline-flex;align-items:center;gap:4px;color:var(--color-accent);text-decoration:none;white-space:nowrap}
.ds-crumb a:hover{text-decoration:underline}
.ds-crumb b{font-weight:600;color:var(--color-text);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:460px}
.ds-crumb .sep{opacity:.5}

/* ── En-tête de fiche : marque, nom, méta, étiquettes, actions alignées ── */
.ds-hero,.contact-head{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:12px 20px;padding:16px 20px;margin-bottom:14px;background:var(--color-card);border:1px solid var(--color-border);border-radius:12px;box-shadow:var(--shadow-sm)}
.ds-hero-id{display:flex;align-items:center;gap:14px;min-width:0;flex:1 1 380px}
.ds-hero-t{min-width:0}
.ds-hero h1{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin:0;font-size:var(--text-lg);font-weight:700;letter-spacing:-.01em;line-height:1.25;color:var(--color-text);overflow-wrap:anywhere}
.ds-hero-meta{display:flex;align-items:center;gap:6px;flex-wrap:wrap;margin-top:3px;font-size:var(--text-xs);color:var(--color-text-muted)}
.ds-hero-meta b{font-weight:600;color:var(--color-text)}
.ds-hero-meta a{color:var(--color-accent);text-decoration:none;font-weight:600}
.ds-hero-meta a:hover{text-decoration:underline}
.ds-hero-meta .sep{opacity:.45}
.ds-hero-meta .ds-av{width:18px;height:18px;font-size:9px}
.ds-hero-tags{display:flex;align-items:center;gap:6px;flex-wrap:wrap;margin-top:7px}
.ds-hero-actions{display:flex;align-items:center;gap:6px;flex-wrap:wrap;justify-content:flex-end}
.ds-hero-actions form{margin:0}
/* Marque d'une société : carré arrondi aux initiales (même palette que `ds-av`). */
.ds-logo{width:44px;height:44px;border-radius:10px;display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;font-size:14px;font-weight:700;letter-spacing:.02em;background:var(--color-bg);color:var(--color-text)}
.ds-logo.sm{width:24px;height:24px;border-radius:6px;font-size:9px}
/* VIP : anneau ambre autour des initiales. */
.ds-av.vip{box-shadow:0 0 0 2px var(--color-card),0 0 0 3.5px var(--color-amber-vivid)}
/* Tuile dont la valeur est un mot (« Sous contrôle », « Expiré ») : verticale —
   libellé, précision (date), puis l'état en couleur ; rien n'est tronqué. */
.ds-stat.txt{flex-direction:column;align-items:flex-start;justify-content:center;gap:2px;height:auto;min-height:56px;padding:9px 14px 9px 12px;border-left:3px solid var(--t)}
.ds-stat.txt::before{display:none}
.ds-stat.txt .ds-stat-l{order:-1;white-space:normal;overflow:visible}
.ds-stat.txt .ds-stat-v{font-size:var(--text-sm);color:var(--t);white-space:normal}
.ds-stat.txt.zero .ds-stat-v{color:var(--color-text-light)}
.ds-table .ds-logo{vertical-align:middle;margin-right:8px}
.ds-btn.wa{color:var(--color-emerald)}
.ds-btn.wa:hover{border-color:color-mix(in srgb,var(--color-emerald) 40%,transparent);background:var(--color-emerald-pale)}
.ds-btn.ico{padding:0 8px}
@media (hover:none),(max-width:760px){.ds-hero-actions .ds-btn,.ds-hero-actions .ds-btn-primary{min-height:40px}}

/* ── Menu déroulant (« Plus d'actions ») ── */
.ds-menu-wrap{position:relative}
.ds-menu{position:absolute;right:0;top:calc(100% + 6px);z-index:40;min-width:240px;max-width:calc(100vw - 32px);padding:6px;background:var(--color-card);border:1px solid var(--color-border);border-radius:10px;box-shadow:var(--shadow-lg,0 10px 30px rgba(16,24,40,.18))}
.ds-menu form{margin:0}
.ds-menu button,.ds-menu a{display:flex;align-items:center;gap:8px;width:100%;padding:8px 10px;border:0;border-radius:6px;background:none;font:inherit;font-size:var(--text-xs);font-weight:600;color:var(--color-text);text-align:left;text-decoration:none;cursor:pointer}
.ds-menu button:hover,.ds-menu a:hover,.ds-menu button:focus-visible,.ds-menu a:focus-visible{background:var(--color-bg);outline:none}
.ds-menu .danger{color:var(--color-rose)}
.ds-menu-sep{height:1px;margin:6px 4px;background:var(--color-border)}

/* ── Cartes de section ── */
.ds-card{background:var(--color-card);border:1px solid var(--color-border);border-radius:12px;box-shadow:var(--shadow-sm);margin-bottom:14px;min-width:0}
.ds-card-h{display:flex;align-items:center;justify-content:space-between;gap:8px 12px;flex-wrap:wrap;padding:10px 16px;border-bottom:1px solid var(--color-border)}
.ds-card-h h3{display:flex;align-items:center;gap:8px;margin:0;font-size:var(--text-sm);font-weight:700;color:var(--color-text);min-width:0}
.ds-card-h h3 svg{color:var(--color-text-light);flex-shrink:0}
.ds-card-h h3 .ds-count{margin-left:2px}
.ds-card-h .r{display:flex;align-items:center;gap:6px;flex-wrap:wrap;margin-left:auto}
.ds-card-h .r form{margin:0}
.ds-card-b{padding:14px 16px}
.ds-card-b.flush{padding:0}
.ds-card-b+.ds-card-b{border-top:1px solid var(--color-border)}
.ds-card-f{padding:9px 16px;border-top:1px solid var(--color-border);background:color-mix(in srgb,var(--color-bg) 55%,var(--color-card));border-radius:0 0 12px 12px;font-size:var(--text-xs);color:var(--color-text-muted)}
.ds-card>.ds-table-wrap,.ds-card-b.flush>.ds-table-wrap{border:none;border-radius:0 0 12px 12px;box-shadow:none;max-height:none}
.ds-card>.ds-table-wrap .ds-table th{border-radius:0}
.ds-card .ds-note{margin:0 0 12px}
.ds-card.tone{border-left:3px solid var(--tone,var(--color-accent-vivid))}
.ds-card.accent{border-color:color-mix(in srgb,var(--color-accent-solid) 40%,var(--color-border))}
.ds-sub-h{display:flex;align-items:center;gap:6px;font-size:11px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:var(--color-text-light);margin:0 0 8px}
.ds-sub-h svg{color:var(--color-text-light)}
.ds-hint{font-size:var(--text-xs);color:var(--color-text-muted);line-height:1.5}
.ds-hint a,.ds-link{color:var(--color-accent);text-decoration:none;font-weight:600}
.ds-hint a:hover,.ds-link:hover{text-decoration:underline}
.ds-mono{font-family:var(--font-mono,ui-monospace,SFMono-Regular,Menlo,monospace);font-size:var(--text-xs)}
.ds-empty.sm{padding:16px}

/* ── Grilles ── */
.ds-cols{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:14px;align-items:start}
.ds-cols--3{grid-template-columns:repeat(3,minmax(0,1fr))}
.ds-cols--4{grid-template-columns:repeat(4,minmax(0,1fr))}
.ds-cols--main{grid-template-columns:minmax(0,1.5fr) minmax(300px,1fr)}
.ds-cols--fill{grid-template-columns:repeat(auto-fill,minmax(280px,1fr))}
.ds-cols>.ds-card{margin-bottom:0}
.ds-stack{display:flex;flex-direction:column;gap:14px;min-width:0}
.ds-stack>.ds-card{margin-bottom:0}
@media (max-width:1100px){.ds-cols--3,.ds-cols--4{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media (max-width:760px){.ds-cols,.ds-cols--3,.ds-cols--4,.ds-cols--main{grid-template-columns:1fr}}

/* ── Clé / valeur ── */
.ds-kv{display:grid;grid-template-columns:minmax(110px,36%) 1fr;gap:0 12px;margin:0;font-size:var(--text-sm)}
.ds-kv dt,.ds-kv dd{padding:6px 0;margin:0;border-top:1px solid color-mix(in srgb,var(--color-border) 60%,transparent);line-height:1.5;min-width:0}
.ds-kv dt{color:var(--color-text-muted);font-size:var(--text-xs);align-self:start;padding-top:7px}
.ds-kv dd{color:var(--color-text);font-weight:500;overflow-wrap:anywhere}
.ds-kv>dt:first-child,.ds-kv>dt:first-child+dd{border-top:none;padding-top:0}
.ds-kv .mono{font-family:var(--font-mono,ui-monospace,SFMono-Regular,Menlo,monospace);font-size:var(--text-xs)}
.ds-kv .empty{color:var(--color-text-light);font-weight:400}
.ds-kv .pre{white-space:pre-line}
.ds-kv dd .ds-status,.ds-kv dd .ds-tag{vertical-align:middle}
.ds-kv dd small{font-size:var(--text-xs);color:var(--color-text-muted);font-weight:400}
.ds-kv.tight dt,.ds-kv.tight dd{padding:4px 0}
.ds-kv.tight>dt:first-child,.ds-kv.tight>dt:first-child+dd{padding-top:0}
.ds-kv .due{color:var(--color-amber);font-weight:600}
.ds-kv .late{color:var(--color-rose);font-weight:600}

/* ── Journal / historique ── */
.ds-tl{list-style:none;margin:0;padding:0}
.ds-tl li{display:flex;gap:12px;padding:10px 16px;border-top:1px solid color-mix(in srgb,var(--color-border) 70%,transparent)}
.ds-tl li:first-child{border-top:none}
.ds-tl-dot{--s:var(--ds-slate);--s-vivid:var(--ds-slate-vivid);--s-pale:var(--ds-slate-pale);width:28px;height:28px;border-radius:50%;flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;background:var(--s-pale);color:var(--s);font-size:12px;margin-top:1px}
.ds-tl-b{flex:1;min-width:0}
.ds-tl-t{display:flex;justify-content:space-between;align-items:baseline;gap:10px;flex-wrap:wrap;font-size:var(--text-sm);font-weight:600;color:var(--color-text);overflow-wrap:anywhere}
.ds-tl-t time,.ds-tl-t .when{font-size:var(--text-xs);font-weight:500;color:var(--color-text-light);white-space:nowrap;font-variant-numeric:tabular-nums}
.ds-tl-d{font-size:var(--text-xs);color:var(--color-text-muted);margin-top:2px;line-height:1.45;overflow-wrap:anywhere}
.ds-tl-m{display:flex;align-items:center;gap:6px;margin-top:4px;font-size:var(--text-xs);color:var(--color-text-muted)}
.ds-tl.scroll{max-height:560px;overflow-y:auto}

/* ── Pièces : lignes compactes, grille qui se replie ── */
.ds-docs{display:grid;grid-template-columns:repeat(auto-fill,minmax(300px,1fr))}
.ds-doc{display:flex;align-items:center;gap:10px;padding:7px 14px;min-height:46px;border-bottom:1px solid color-mix(in srgb,var(--color-border) 70%,transparent);border-right:1px solid color-mix(in srgb,var(--color-border) 70%,transparent)}
.ds-doc-ic{--s:var(--ds-slate);--s-vivid:var(--ds-slate-vivid);--s-pale:var(--ds-slate-pale);width:26px;height:26px;border-radius:7px;flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;background:var(--s-pale);color:var(--s)}
.ds-doc-b{flex:1;min-width:0}
.ds-doc-n{font-size:var(--text-xs);font-weight:600;color:var(--color-text);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ds-doc-s{font-size:11px;color:var(--color-text-muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ds-doc-s.hi{color:var(--color-rose);font-weight:600}
.ds-doc-s.warn{color:var(--color-amber);font-weight:600}
.ds-doc .act{display:flex;gap:2px;flex-shrink:0;opacity:0;transition:opacity .12s}
.ds-doc:hover .act,.ds-doc:focus-within .act{opacity:1}
.ds-doc form{margin:0}
.ds-doc.missing{background:color-mix(in srgb,var(--color-rose) 3%,transparent)}
@media (hover:none){.ds-doc .act{opacity:1}}

/* ── Jauge fine ── */
.ds-meter{height:6px;border-radius:99px;background:var(--color-bg);border:1px solid var(--color-border);overflow:hidden;min-width:60px}
.ds-meter>i{display:block;height:100%;border-radius:99px;background:var(--t,var(--color-accent-vivid))}
.ds-meter.ok>i{background:var(--color-emerald-vivid)}
.ds-meter.warn>i{background:var(--color-amber-vivid)}
.ds-meter.bad>i{background:var(--color-rose-vivid)}
.ds-meter-row{display:flex;align-items:center;gap:10px}
.ds-meter-row .ds-meter{flex:1}
.ds-meter-row b{font-size:var(--text-xs);font-weight:700;font-variant-numeric:tabular-nums;white-space:nowrap}

/* ── Bandeaux : variantes ── */
.ds-note.danger{border-left-color:var(--color-rose-vivid);background:var(--color-rose-pale)}
.ds-note.danger svg,.ds-note.danger b{color:var(--color-rose)}
.ds-note.ok{border-left-color:var(--color-emerald-vivid);background:var(--color-emerald-pale)}
.ds-note.ok svg,.ds-note.ok b{color:var(--color-emerald)}
.ds-note.info{border-left-color:var(--color-accent-vivid);background:var(--color-accent-pale)}
.ds-note.info svg,.ds-note.info b{color:var(--color-accent)}
.ds-note .r{margin-left:auto;flex-shrink:0;display:flex;gap:6px;align-items:center}
.ds-note .ds-btn,.ds-note .ds-btn-primary{height:28px;padding:0 10px;font-size:var(--text-xs)}

/* ── Listes de lignes (rattachements, suggestions, alertes) ── */
.ds-rows{display:flex;flex-direction:column}
.ds-row{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:9px 0;border-top:1px solid color-mix(in srgb,var(--color-border) 70%,transparent)}
.ds-row:first-child{border-top:none;padding-top:0}
.ds-row-b{min-width:0;flex:1}
.ds-row-t{display:flex;align-items:center;gap:6px;flex-wrap:wrap;font-size:var(--text-sm);font-weight:600;color:var(--color-text)}
.ds-row-t a{color:var(--color-accent);text-decoration:none}
.ds-row-t a:hover{text-decoration:underline}
.ds-row-s{font-size:var(--text-xs);color:var(--color-text-muted);margin-top:2px;line-height:1.45}
.ds-row .act{display:flex;align-items:center;gap:4px;flex-shrink:0;flex-wrap:wrap;justify-content:flex-end}
.ds-row .act form{margin:0}

/* ── Pagination ── */
.ds-pager{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:8px;margin-top:12px}
.ds-pager-n{display:flex;gap:4px;flex-wrap:wrap}
.ds-pager-n a,.ds-pager-n button,.ds-pager-n span{display:inline-flex;align-items:center;justify-content:center;min-width:28px;height:28px;padding:0 8px;border:1px solid var(--color-border);border-radius:7px;background:var(--color-card);color:var(--color-text-muted);font:inherit;font-size:var(--text-xs);font-weight:600;text-decoration:none;cursor:pointer;font-variant-numeric:tabular-nums}
.ds-pager-n a:hover{border-color:var(--color-border-strong);color:var(--color-text)}
.ds-pager-n .on{background:var(--color-accent-solid);border-color:var(--color-accent-solid);color:#fff;cursor:default}
.ds-pager-n [disabled]{opacity:.4;cursor:default}
.ds-pager-n span.gap{border:none;background:none;min-width:auto;padding:0 2px}

/* ── Formulaires : grille de champs, cases, pied collant ── */
.ds-fgrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:10px 12px;align-items:end}
.ds-fgrid--2{grid-template-columns:repeat(2,minmax(0,1fr))}
.ds-fgrid--3{grid-template-columns:repeat(3,minmax(0,1fr))}
.ds-fgrid .full{grid-column:1/-1}
.ds-fgrid .form-label,.ds-card .form-label{display:block;font-size:11px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:var(--color-text-light);margin:0 0 4px}
.ds-fgrid .form-input,.ds-card .form-input,.ds-card .form-control,.ds-card .form-select{height:34px;padding:0 10px;border:1px solid var(--color-border);border-radius:8px;background:var(--color-card);color:var(--color-text);font:inherit;font-size:var(--text-sm);width:100%;box-sizing:border-box}
.ds-card textarea.form-input{height:auto;padding:8px 10px;resize:vertical;line-height:1.5}
.ds-card select.form-input,.ds-card .form-select{appearance:none;-webkit-appearance:none;padding-right:28px;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 24 24' fill='none' stroke='%23667085' stroke-width='2.5' stroke-linecap='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 11px center}
.ds-card input[type=file].form-input{padding:5px 10px;line-height:1.5}
.ds-card .form-input:focus,.ds-card .form-control:focus,.ds-card .form-select:focus{outline:none;border-color:var(--color-accent-solid);box-shadow:0 0 0 3px color-mix(in srgb,var(--color-accent-solid) 15%,transparent)}
.ds-check{display:inline-flex;align-items:center;gap:8px;min-height:34px;font-size:var(--text-sm);font-weight:500;color:var(--color-text);cursor:pointer}
.ds-check input{width:15px;height:15px;accent-color:var(--color-accent-solid);margin:0;flex-shrink:0}
.ds-check svg{color:var(--color-text-light)}
.ds-checks{display:flex;gap:4px 18px;flex-wrap:wrap}
.ds-form-foot{position:sticky;bottom:0;z-index:10;display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding:12px 0;margin-top:14px;background:var(--color-bg);border-top:1px solid var(--color-border)}
.ds-form-foot .ds-meta{margin-left:auto}
.ds-req{color:var(--color-rose)}
.ds-ro{display:flex;align-items:center;min-height:34px;padding:0 10px;border:1px dashed var(--color-border);border-radius:8px;background:var(--color-bg);color:var(--color-text-muted);font-size:var(--text-sm)}
.ds-ferr{color:var(--color-rose);font-size:var(--text-xs);margin-top:4px;font-weight:600}
details.ds-more>summary{cursor:pointer;font-size:var(--text-xs);font-weight:700;color:var(--color-accent);list-style:none;display:inline-flex;align-items:center;gap:6px;user-select:none}
details.ds-more>summary::-webkit-details-marker{display:none}
details.ds-more>summary::before{content:"";width:0;height:0;border:4px solid transparent;border-left:6px solid currentColor;margin-right:2px;transition:transform .15s}
details.ds-more[open]>summary::before{transform:rotate(90deg)}
details.ds-more>summary+*{margin-top:10px}

/* Cellules tronquées : une ligne, points de suspension, l'infobulle garde tout. */
.ds-table td.clip{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ds-clip{min-width:0}
.ds-clip>*{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ds-clip>.ds-tag{display:inline-flex}

/* ── Onglets de fiche : nombreux, ils se serrent (gap réduit, texte sm) et
   peuvent se replier sur deux lignes ── */
.ds-tabs.wrap{flex-wrap:wrap;gap:0 18px;overflow:visible}
.ds-tabs.wrap button,.ds-tabs.wrap a{font-size:var(--text-sm);gap:6px;padding:9px 1px 10px}
.ds-tabs .tab-count{display:inline-block;min-width:20px;padding:1px 7px;border-radius:99px;background:var(--color-bg);border:1px solid var(--color-border);color:var(--color-text-muted);font-size:11px;font-weight:600;font-variant-numeric:tabular-nums;text-align:center;line-height:1.5}
.ds-tabs .on .tab-count{background:var(--color-accent-pale);border-color:transparent;color:var(--color-accent)}

/* Étiquettes historiques (`.badge`) dans une fiche refaite : même dessin que `ds-tag`. */
.ds-hero-tags .badge,.ds-card .badge,.ds-table .badge{display:inline-flex;align-items:center;gap:4px;height:20px;padding:0 7px;border-radius:6px;font-size:11px;font-weight:600;line-height:1;white-space:nowrap}
.ds-hero-tags .badge-outline,.ds-card .badge-outline,.ds-table .badge-outline{background:transparent;box-shadow:inset 0 0 0 1px var(--color-border);color:var(--color-text-muted)}
.ds-table td.c-act .ds-btn.sm{height:26px}
/* Les boutons texte (« Brief », « Relance », « Contacté »…) gardent leur largeur :
   fixés à 24 px, leur texte débordait sur les boutons voisins. */
.ds-table td.c-act .ds-ico:not(.txt){width:24px}
.ds-table td .ds-status{vertical-align:middle}
.ds-table td.wrap{white-space:normal;line-height:1.35}
.ds-table tbody tr[data-href]{cursor:pointer}
.ds-table td a.strong{color:var(--color-text);text-decoration:none;font-weight:600}
.ds-table td a.strong:hover{color:var(--color-accent)}
.ds-table td.c-act form{display:inline;margin:0}

/* ── État → couleur : visas, sociétés, pièces, dossiers, banque, CT/TVA ──
   emerald  actif / présent / en ordre / enregistré / approuvé
   amber    en cours / expirant / partiel / renouvellement imminent / attention
   rose     expiré / manquant / retard / licence expirée / échec / refusé
   slate    aucun / annulé / fermée / non démarré / radiée
   blue     en création / client
   indigo   renouvellement en cours
   purple   annulation en cours / lead
   teal     exempté / non requis */
[data-s="active"],[data-s="ok"],[data-s="on_track"],[data-s="registered"],[data-s="approved"],[data-s="good"],[data-s="present"]{--s:var(--color-emerald);--s-vivid:var(--color-emerald-vivid);--s-pale:var(--color-emerald-pale)}
[data-s="processing"],[data-s="expiring"],[data-s="partial"],[data-s="renouvellement_imminent"],[data-s="warning"],[data-s="filing_due"],[data-s="prospect"],[data-s="soon"]{--s:var(--color-amber);--s-vivid:var(--color-amber-vivid);--s-pale:var(--color-amber-pale)}
[data-s="expired"],[data-s="missing"],[data-s="delayed"],[data-s="licence_expiree"],[data-s="failed"],[data-s="rejected"],[data-s="danger"],[data-s="bad"]{--s:var(--color-rose);--s-vivid:var(--color-rose-vivid);--s-pale:var(--color-rose-pale)}
[data-s="none"],[data-s="cancelled"],[data-s="fermee_liquidee"],[data-s="not_started"],[data-s="deregistered"],[data-s="muted"],[data-s="former client"]{--s:var(--ds-slate);--s-vivid:var(--ds-slate-vivid);--s-pale:var(--ds-slate-pale)}
[data-s="creation_en_cours"],[data-s="client"],[data-s="info"]{--s:var(--color-accent);--s-vivid:var(--color-accent-vivid);--s-pale:var(--color-accent-pale)}
[data-s="renouvellement_en_cours"],[data-s="family"]{--s:var(--ds-indigo);--s-vivid:var(--ds-indigo-vivid);--s-pale:var(--ds-indigo-pale)}
[data-s="annulation_en_cours"],[data-s="lead"],[data-s="partner"]{--s:var(--color-purple);--s-vivid:var(--color-purple-vivid);--s-pale:var(--color-purple-pale)}
[data-s="exempted"],[data-s="exempt"],[data-s="not_required"],[data-s="supplier"]{--s:var(--ds-teal);--s-vivid:var(--ds-teal-vivid);--s-pale:var(--ds-teal-pale)}

/* ═══════════════════════════════════════════════════════════════════════════
   Design system 2026-10 — Finance (ajouté avec Devis, Factures, Dépenses)
   ───────────────────────────────────────────────────────────────────────────
   Montants `ds-money`, bloc de totaux `ds-totals`, pied de tableau, fenêtre
   modale `ds-modal`, repli `ds-fold`, zone de dépôt `ds-drop`, et la table
   d'états propre à l'argent : devis, factures, reçus, avoirs, imports,
   dépenses. Les montants se lisent en chiffres tabulaires, la devise en
   retrait ; le retard en rose, l'encaissé en émeraude.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── Montant : chiffres tabulaires, devise estompée ── */
.ds-money{font-variant-numeric:tabular-nums;white-space:nowrap;font-weight:600;color:var(--color-text)}
.ds-money i,.ds-money small{font-style:normal;font-weight:500;font-size:.82em;color:var(--color-text-light);margin-left:3px}
.kpi-value.ds-money{font-size:var(--text-lg)}
.ds-money.pos{color:var(--color-emerald)}
.ds-money.neg{color:var(--color-rose)}
.ds-money.warn{color:var(--color-amber)}
.ds-money.muted{color:var(--color-text-muted);font-weight:500}
.ds-money.lg{font-size:var(--text-lg);font-weight:700;letter-spacing:-.01em}
.ds-money.xl{font-size:var(--text-xl);font-weight:700;letter-spacing:-.02em}
.ds-money s{color:var(--color-text-light);font-weight:400}
.ds-table td .ds-money{font-weight:600}
.ds-table td.r .ds-sub{text-align:right}
.ds-stat .ds-money i{font-size:var(--text-xs)}
/* Tuile dont la valeur est un montant : plus large, pour que le libellé tienne. */
.ds-stat.wide{flex-basis:220px}

/* ── Totaux d'une pièce : lignes clé/valeur, dernier rang en évidence ── */
.ds-totals{display:flex;flex-direction:column;gap:0;min-width:240px;margin:0;font-size:var(--text-sm)}
.ds-totals>div{display:flex;justify-content:space-between;align-items:baseline;gap:16px;padding:5px 0;border-top:1px solid color-mix(in srgb,var(--color-border) 60%,transparent)}
.ds-totals>div:first-child{border-top:none}
.ds-totals>div>span:first-child{color:var(--color-text-muted)}
.ds-totals>div.grand{margin-top:2px;padding-top:8px;border-top:2px solid var(--color-border);font-weight:700;color:var(--color-text)}
.ds-totals>div.grand>span:first-child{color:var(--color-text)}
.ds-totals>div.grand .ds-money{font-size:var(--text-md);font-weight:700}
.ds-totals>div.disc .ds-money{color:var(--color-emerald)}
.ds-totals .kpi-label{display:inline;margin:0;font:inherit;font-size:inherit;color:inherit;text-transform:none;letter-spacing:0}
.ds-totals-wrap{display:flex;justify-content:flex-end;padding:10px 16px 12px;border-top:1px solid var(--color-border);background:color-mix(in srgb,var(--color-bg) 55%,var(--color-card));border-radius:0 0 12px 12px}

/* ── Pied de tableau (totaux de colonne) ── */
.ds-table tfoot td{height:40px;padding:0 10px;background:color-mix(in srgb,var(--color-bg) 55%,var(--color-card));border-top:1px solid var(--color-border);border-bottom:none;font-weight:700;color:var(--color-text);font-variant-numeric:tabular-nums}
.ds-table tfoot td.r{text-align:right}
.ds-table tbody tr.dim td{color:var(--color-text-light)}
.ds-table tbody tr.dim td .ds-money{color:var(--color-text-light);font-weight:500}
.ds-table tbody tr.hl td{background:color-mix(in srgb,var(--color-amber-vivid) 7%,var(--color-card))}
.ds-table tbody tr.sec td{height:32px;background:color-mix(in srgb,var(--color-bg) 70%,var(--color-card));font-size:11px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:var(--color-text-muted)}
.ds-table td .ds-mono{font-size:var(--text-xs);font-weight:600}
.ds-table td a.ds-ref,.ds-ref{font-family:var(--font-mono,ui-monospace,SFMono-Regular,Menlo,monospace);font-size:var(--text-xs);font-weight:700;color:var(--color-text);text-decoration:none;letter-spacing:.01em}
.ds-table td a.ds-ref:hover,a.ds-ref:hover{color:var(--color-accent)}
.ds-hero h1 .ds-ref{font-size:var(--text-lg)}

/* ── Fenêtre modale : voile, panneau, en-tête, corps, pied ── */
.ds-modal{position:fixed;inset:0;z-index:9999;display:flex;align-items:center;justify-content:center;padding:16px;background:rgba(15,23,42,.48);backdrop-filter:blur(2px)}
.ds-modal-p{display:flex;flex-direction:column;width:100%;max-width:520px;max-height:92vh;background:var(--color-card);border:1px solid var(--color-border);border-radius:14px;box-shadow:0 24px 60px rgba(15,23,42,.28);overflow:hidden}
.ds-modal-p.md{max-width:760px}
.ds-modal-p.lg{max-width:960px}
.ds-modal-h{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:14px 18px;border-bottom:1px solid var(--color-border)}
.ds-modal-h h2{display:flex;align-items:center;gap:8px;margin:0;font-size:var(--text-md);font-weight:700;color:var(--color-text);min-width:0}
.ds-modal-h h2 svg{color:var(--color-text-light)}
.ds-modal-b{padding:16px 18px;overflow-y:auto}
.ds-modal-f{display:flex;align-items:center;justify-content:flex-end;gap:8px;flex-wrap:wrap;padding:12px 18px;border-top:1px solid var(--color-border);background:color-mix(in srgb,var(--color-bg) 55%,var(--color-card))}
.ds-modal-f .l{margin-right:auto}
.ds-modal .form-label{display:block;font-size:11px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:var(--color-text-light);margin:0 0 4px}
.ds-modal .form-control,.ds-modal .form-input,.ds-modal .form-select{height:34px;padding:0 10px;border:1px solid var(--color-border);border-radius:8px;background:var(--color-card);color:var(--color-text);font:inherit;font-size:var(--text-sm);width:100%;box-sizing:border-box}
.ds-modal textarea.form-control{height:auto;padding:8px 10px;resize:vertical;line-height:1.5}
.ds-modal select.form-control{appearance:none;-webkit-appearance:none;padding-right:28px;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 24 24' fill='none' stroke='%23667085' stroke-width='2.5' stroke-linecap='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 11px center}
.ds-modal .form-control:focus{outline:none;border-color:var(--color-accent-solid);box-shadow:0 0 0 3px color-mix(in srgb,var(--color-accent-solid) 15%,transparent)}
.ds-modal .ds-table-wrap{max-height:none}
.ds-modal .ds-table td{height:auto;padding:5px 6px}
.ds-modal .ds-table td .form-control{height:32px}
.ds-modal-tabs{padding:0 18px}
.ds-modal-tabs .ds-tabs{margin-bottom:0}

/* ── Repli : un geste par bloc (Solder, Enregistrer un versement, Avoir…) ── */
details.ds-fold{border:1px solid var(--color-border);border-radius:10px;background:var(--color-card)}
details.ds-fold+details.ds-fold{margin-top:8px}
details.ds-fold>summary{display:flex;align-items:center;gap:10px;padding:10px 14px;cursor:pointer;list-style:none;font-size:var(--text-sm);font-weight:600;color:var(--color-text);user-select:none}
details.ds-fold>summary::-webkit-details-marker{display:none}
details.ds-fold>summary::before{content:"";width:0;height:0;border:4px solid transparent;border-left:6px solid var(--color-text-light);margin-left:2px;transition:transform .15s;flex-shrink:0}
details.ds-fold[open]>summary::before{transform:rotate(90deg)}
details.ds-fold[open]>summary{border-bottom:1px solid var(--color-border)}
details.ds-fold>summary .ds-money{margin-left:auto}
details.ds-fold>summary .ds-tag{margin-left:6px}
details.ds-fold>:not(summary){padding:12px 14px}
details.ds-fold .form-label{display:block;font-size:11px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:var(--color-text-light);margin:0 0 4px}
details.ds-fold .form-control{height:34px;padding:0 10px;border:1px solid var(--color-border);border-radius:8px;background:var(--color-card);color:var(--color-text);font:inherit;font-size:var(--text-sm);width:100%;box-sizing:border-box}
details.ds-fold select.form-control{appearance:none;-webkit-appearance:none;padding-right:28px;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 24 24' fill='none' stroke='%23667085' stroke-width='2.5' stroke-linecap='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 11px center}
details.ds-fold .form-control:focus{outline:none;border-color:var(--color-accent-solid);box-shadow:0 0 0 3px color-mix(in srgb,var(--color-accent-solid) 15%,transparent)}
details.ds-fold.danger>summary{color:var(--color-rose)}
/* Micro-repli dans une cellule (Corriger, Contre-passer, Rembourser) */
details.ds-pop{display:inline-block;position:relative;text-align:left}
details.ds-pop>summary{list-style:none;display:inline-flex}
details.ds-pop>summary::-webkit-details-marker{display:none}
details.ds-pop>form,details.ds-pop>div{position:absolute;right:0;top:calc(100% + 6px);z-index:30;display:grid;gap:6px;min-width:240px;padding:10px;background:var(--color-card);border:1px solid var(--color-border);border-radius:10px;box-shadow:var(--shadow-lg,0 10px 30px rgba(16,24,40,.18))}
details.ds-pop .form-control{height:32px;padding:0 10px;border:1px solid var(--color-border);border-radius:8px;background:var(--color-card);color:var(--color-text);font:inherit;font-size:var(--text-xs);width:100%;box-sizing:border-box}
details.ds-pop .form-label{font-size:10px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:var(--color-text-light);margin:0}

/* ── Zone de dépôt ── */
.ds-drop{display:block;padding:26px 16px;border:1.5px dashed var(--color-border-strong);border-radius:12px;background:color-mix(in srgb,var(--color-bg) 55%,var(--color-card));text-align:center;cursor:pointer;transition:border-color .12s,background .12s}
.ds-drop:hover,.ds-drop.over{border-color:var(--color-accent-solid);background:var(--color-accent-pale)}
.ds-drop b{display:block;font-size:var(--text-sm);font-weight:600;color:var(--color-text)}
.ds-drop span{display:block;margin-top:3px;font-size:var(--text-xs);color:var(--color-text-muted)}
.ds-drop svg{display:block;margin:0 auto 8px;color:var(--color-text-light)}

/* ── Tuile de balance âgée : la couleur dit l'ancienneté ── */
.ds-stat.age-0{--t:var(--color-emerald-vivid)}
.ds-stat.age-30{--t:var(--color-amber-vivid)}
.ds-stat.age-60{--t:#F97316}
.ds-stat.age-90{--t:var(--color-rose-vivid)}

/* ── Compteur de validité : « J-5 » en couleur ── */
.ds-days{display:inline-flex;align-items:center;font-size:var(--text-xs);font-weight:700;font-variant-numeric:tabular-nums;color:var(--color-emerald)}
.ds-days.soon{color:var(--color-amber)}
.ds-days.late{color:var(--color-rose)}
.ds-days.off{color:var(--color-text-light);font-weight:500}

/* ── Grille d'information dans une carte (clé / valeur en colonnes) ── */
.ds-info{display:grid;grid-template-columns:repeat(auto-fill,minmax(160px,1fr));gap:12px 18px}
.ds-info>div>span{display:block;font-size:11px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:var(--color-text-light);margin-bottom:2px}
.ds-info>div>b{font-weight:600;color:var(--color-text);font-size:var(--text-sm);overflow-wrap:anywhere}
.ds-info>div>b.empty{color:var(--color-text-light);font-weight:400}

/* ── Fil de section dans une table de lignes (Partie Entreprise, Volet Visa…) ── */
.ds-sec-dot{display:inline-block;width:8px;height:8px;border-radius:50%;background:var(--s-vivid,var(--color-accent-vivid));margin-right:6px;vertical-align:1px}

/* ── Formulaires hérités posés dans une carte ds : même dessin que ds-fgrid ── */
.ds-card .form-textarea{height:auto;padding:8px 10px;border:1px solid var(--color-border);border-radius:8px;background:var(--color-card);color:var(--color-text);font:inherit;font-size:var(--text-sm);width:100%;box-sizing:border-box;resize:vertical;line-height:1.5}
.ds-card .form-textarea:focus{outline:none;border-color:var(--color-accent-solid);box-shadow:0 0 0 3px color-mix(in srgb,var(--color-accent-solid) 15%,transparent)}
.ds-card .btn-xs,.ds-card .btn{font:inherit}

/* ── État → couleur : l'argent ──
   slate    brouillon / non émise / annulée / avoir / périmé / en file
   blue     envoyé(e) / émise / en lecture
   purple   révisé / complémentaire
   amber    en attente / à valider / à vérifier / approbation
   teal     accepté (accord) / partiellement payée / remboursée
   emerald  payée / encaissé / classée / renouvelé
   rose     en retard / refusé(e) / échec / rejetée */
[data-s="void"],[data-s="not_issued"],[data-s="credit_note"],[data-s="queued"],[data-s="discarded"],[data-s="not_due"],[data-s="revoked"]{--s:var(--ds-slate);--s-vivid:var(--ds-slate-vivid);--s-pale:var(--ds-slate-pale)}
[data-s="issued"],[data-s="reading"],[data-s="alert_sent"],[data-s="renewal"]{--s:var(--color-accent);--s-vivid:var(--color-accent-vivid);--s-pale:var(--color-accent-pale)}
[data-s="revised"],[data-s="supplementary"],[data-s="relanced"]{--s:var(--color-purple);--s-vivid:var(--color-purple-vivid);--s-pale:var(--color-purple-pale)}
[data-s="to_validate"],[data-s="pending_approval"],[data-s="review"],[data-s="manual"],[data-s="alert"],[data-s="expiring_soon"]{--s:var(--color-amber);--s-vivid:var(--color-amber-vivid);--s-pale:var(--color-amber-pale)}
[data-s="partial_paid"],[data-s="reimbursed"],[data-s="contacted"]{--s:var(--ds-teal);--s-vivid:var(--ds-teal-vivid);--s-pale:var(--ds-teal-pale)}
[data-s="filed"],[data-s="renewed"],[data-s="validated"],[data-s="collected"]{--s:var(--color-emerald);--s-vivid:var(--color-emerald-vivid);--s-pale:var(--color-emerald-pale)}
[data-s="rejected"],[data-s="refused_receipt"],[data-s="late"],[data-s="failed"]{--s:var(--color-rose);--s-vivid:var(--color-rose-vivid);--s-pale:var(--color-rose-pale)}

/* ═══════════════════════════════════════════════════════════════════════════
   Performance (/reporting) dans le style commun ds-* — 2026-10
   ───────────────────────────────────────────────────────────────────────────
   En-tête, onglets et période partagés (reporting/_nav.html). Les cartes
   `rp-*` gardent leur structure et prennent l'allure des `ds-card` : rayon
   12 px, filet plus discret, accent en barre courte comme les `ds-stat`.
   Impression : seul le contenu du rapport reste, en A4.
   ═══════════════════════════════════════════════════════════════════════════ */
.ds-seg a{display:inline-flex;align-items:center;gap:6px;height:26px;padding:0 12px;border-radius:6px;color:var(--color-text-muted);font-size:var(--text-sm);font-weight:500;text-decoration:none;white-space:nowrap}
.ds-seg a:hover{color:var(--color-text);text-decoration:none}
.ds-seg a.on{background:var(--color-card);color:var(--color-text);font-weight:600;box-shadow:var(--shadow-sm)}
.rp-ds-head{margin-bottom:4px}
.rp-periodbar{align-items:center}
.rp-periodbar .ds-bar-l{flex:0 1 auto}
.rp-periodbar .ds-seg{overflow-x:auto;max-width:100%;scrollbar-width:none}
.rp-dates{display:flex;align-items:center;gap:6px;flex-wrap:wrap;margin:0}
.rp-dates input[type=date].ds-pill{max-width:none;padding-right:10px;font-variant-numeric:tabular-nums}
.rp-filterbar{margin-top:-4px}
.rp-card{border-radius:12px;padding:14px 16px;margin-bottom:14px}
.rp-kpi{border-radius:12px;border-left:1px solid var(--color-border);position:relative;padding:12px 14px 12px 18px}
.rp-kpi::before{content:"";position:absolute;left:8px;top:14px;width:3px;height:28px;border-radius:2px;background:var(--rp-accent,var(--color-accent))}
.rp-kpi__label{font-size:11px;letter-spacing:.05em}

/* Barres horizontales des tableaux de mix et du commercial. */
.rp-bar{position:relative;height:6px;border-radius:99px;background:var(--color-bg);overflow:hidden;min-width:60px}
.rp-bar>i{position:absolute;inset:0 auto 0 0;border-radius:99px;background:var(--rp-accent,var(--color-accent-vivid))}
.rp-compare td.vs{color:var(--color-text-muted)}
.rp-compare .up{color:var(--color-emerald);font-weight:600}
.rp-compare .down{color:var(--color-rose);font-weight:600}
.rp-months{display:grid;grid-template-columns:repeat(6,minmax(0,1fr));gap:8px;align-items:end;height:150px;padding-top:8px}
.rp-month{display:flex;flex-direction:column;align-items:center;justify-content:flex-end;gap:4px;height:100%;min-width:0}
.rp-month__bar{width:100%;max-width:44px;border-radius:6px 6px 2px 2px;background:var(--color-accent-vivid);min-height:2px}
.rp-month__v{font-size:var(--text-xs);font-weight:700;font-variant-numeric:tabular-nums}
.rp-month__l{font-size:11px;color:var(--color-text-muted);white-space:nowrap}

/* Rapport imprimable */
.rp-report{max-width:1000px}
.rp-report__cover{display:flex;justify-content:space-between;gap:16px;flex-wrap:wrap;align-items:flex-end;padding:18px 20px;margin-bottom:14px;border:1px solid var(--color-border);border-radius:12px;background:var(--color-card)}
.rp-report__cover h2{margin:0;font-size:var(--text-xl,1.4rem)}
.rp-report__meta{font-size:var(--text-xs);color:var(--color-text-muted);line-height:1.6;text-align:right}
.rp-report h3{font-size:var(--text-sm);margin:0}
.rp-report .ds-table td{height:32px}

@media (max-width:720px){
  .rp-months{grid-template-columns:repeat(3,minmax(0,1fr));height:auto}
  .rp-report__meta{text-align:left}
}

@media print{
  @page{size:A4;margin:12mm}
  .sidebar,.sidebar-backdrop,.topbar,.notice--bar,.ai-fab,.ai-chip,.rp-no-print{display:none!important}
  /* Le contenu défile dans `.page-content` (flex, hauteur d'écran) : à
     l'impression, seule la première page sortait. */
  html,body{display:block!important;height:auto!important;min-height:0!important;overflow:visible!important}
  .main-wrapper,.main-wrapper.sidebar-collapsed,.page-content{display:block!important;margin:0!important;padding:0!important;max-width:none!important;width:auto!important;height:auto!important;min-height:0!important;overflow:visible!important}
  body{background:#fff!important;color:#000!important}
  .rp-report{max-width:none}
  .ds-card,.rp-card,.rp-report__cover{box-shadow:none!important;break-inside:avoid;border-color:#cbd5e1!important;background:#fff!important}
  .ds-table-wrap{max-height:none!important;overflow:visible!important;box-shadow:none!important}
  .ds-table th{position:static;background:#f1f5f9!important;-webkit-print-color-adjust:exact;print-color-adjust:exact}
  .rp-bar>i,.rp-month__bar,.rp-kpi::before{-webkit-print-color-adjust:exact;print-color-adjust:exact}
  .rp-page-break{break-before:page}
  a{color:inherit!important;text-decoration:none!important}
}
.rp-kpis{grid-template-columns:repeat(auto-fit,minmax(148px,1fr))}
