/* =========================================================================
   DESIGN SYSTEM — socle visuel de la plateforme
   =========================================================================

   Chargé APRÈS colors.css et le thème actif : cette feuille réinterprète les
   couleurs de marque (--coul-*, pilotées depuis le back-office) en un système
   cohérent, sans jamais les remplacer. Changer la couleur primaire dans
   l'admin fait donc évoluer toute l'interface de façon harmonieuse.

   Organisation
     1. Jetons          — couleur, espacement, rayon, élévation, typographie
     2. Thème sombre    — redéfinition des jetons uniquement
     3. Pont Bootstrap  — les jetons alimentent les variables --bs-*
     4. Base            — corps de page, typographie, focus
     5. Composants      — boutons, cartes, formulaires, navigation, tableaux…
     6. Mouvement       — transitions et prefers-reduced-motion

   Convention : on ne se bat avec `!important` que là où le thème historique
   en pose un. Ces endroits sont signalés par un commentaire.
   ========================================================================= */

/* =========================================================================
   1. JETONS
   ========================================================================= */

:root {
  /* --- Marque -----------------------------------------------------------
     Rampe dérivée de la couleur primaire du back-office via color-mix().
     Une seule source de vérité : --coul-principale. */
  --ds-brand: var(--coul-principale, #0077bd);
  --ds-brand-050: color-mix(in oklab, var(--ds-brand) 6%, white);
  --ds-brand-100: color-mix(in oklab, var(--ds-brand) 14%, white);
  --ds-brand-200: color-mix(in oklab, var(--ds-brand) 28%, white);
  --ds-brand-300: color-mix(in oklab, var(--ds-brand) 45%, white);
  --ds-brand-400: color-mix(in oklab, var(--ds-brand) 70%, white);
  --ds-brand-500: var(--ds-brand);
  --ds-brand-600: color-mix(in oklab, var(--ds-brand) 86%, black);
  --ds-brand-700: color-mix(in oklab, var(--ds-brand) 72%, black);
  --ds-brand-800: color-mix(in oklab, var(--ds-brand) 58%, black);
  --ds-brand-900: color-mix(in oklab, var(--ds-brand) 42%, black);

  /* Teinte d'accent secondaire (navy du back-office) */
  --ds-accent: var(--coul-quaternaire, #163460);

  /* --- Neutres ----------------------------------------------------------
     Ramp neutre légèrement teintée de la marque : évite le gris « sale »
     et donne une cohérence chromatique à toute l'interface. */
  --ds-neutral-tint: color-mix(in oklab, var(--ds-brand) 8%, #78808c);
  --ds-neutral-000: #ffffff;
  --ds-neutral-025: color-mix(in oklab, var(--ds-neutral-tint) 4%, white);
  --ds-neutral-050: color-mix(in oklab, var(--ds-neutral-tint) 8%, white);
  --ds-neutral-100: color-mix(in oklab, var(--ds-neutral-tint) 14%, white);
  --ds-neutral-200: color-mix(in oklab, var(--ds-neutral-tint) 24%, white);
  --ds-neutral-300: color-mix(in oklab, var(--ds-neutral-tint) 40%, white);
  --ds-neutral-400: color-mix(in oklab, var(--ds-neutral-tint) 62%, white);
  --ds-neutral-500: var(--ds-neutral-tint);
  --ds-neutral-600: color-mix(in oklab, var(--ds-neutral-tint) 78%, black);
  --ds-neutral-700: color-mix(in oklab, var(--ds-neutral-tint) 58%, black);
  --ds-neutral-800: color-mix(in oklab, var(--ds-neutral-tint) 38%, black);
  --ds-neutral-900: color-mix(in oklab, var(--ds-neutral-tint) 22%, black);
  --ds-neutral-950: color-mix(in oklab, var(--ds-neutral-tint) 12%, black);

  /* --- Rôles sémantiques (mode clair) ---------------------------------- */
  --ds-bg: var(--ds-neutral-050);          /* fond de page */
  --ds-surface: var(--ds-neutral-000);     /* cartes, panneaux */
  --ds-surface-raised: var(--ds-neutral-000);
  --ds-surface-sunken: var(--ds-neutral-100);
  --ds-surface-hover: var(--ds-neutral-050);

  --ds-text: var(--ds-neutral-900);
  --ds-text-muted: var(--ds-neutral-600);
  /* Valeur explicite plutôt que --ds-neutral-500 : ce dernier tombait à 3,6:1
     sur le fond de page, sous le seuil AA. Celle-ci est conforme sur les trois
     surfaces claires (carte, fond, surface creusée). */
  --ds-text-subtle: #646b75;
  --ds-text-on-brand: #ffffff;

  --ds-border: color-mix(in oklab, var(--ds-neutral-500) 22%, transparent);
  --ds-border-strong: color-mix(in oklab, var(--ds-neutral-500) 40%, transparent);

  /* --- États ------------------------------------------------------------ */
  --ds-success: #12805c;
  --ds-warning: #b45309;
  --ds-danger: #be123c;
  --ds-info: var(--ds-brand-600);

  /* Fonds d'état : lisibles en clair comme en sombre */
  --ds-success-bg: color-mix(in oklab, var(--ds-success) 12%, transparent);
  --ds-warning-bg: color-mix(in oklab, var(--ds-warning) 12%, transparent);
  --ds-danger-bg: color-mix(in oklab, var(--ds-danger) 12%, transparent);
  --ds-info-bg: color-mix(in oklab, var(--ds-info) 12%, transparent);

  /* --- Espacement (base 4px) ------------------------------------------- */
  --ds-space-1: 0.25rem;
  --ds-space-2: 0.5rem;
  --ds-space-3: 0.75rem;
  --ds-space-4: 1rem;
  --ds-space-5: 1.5rem;
  --ds-space-6: 2rem;
  --ds-space-7: 3rem;
  --ds-space-8: 4rem;

  /* --- Rayons ----------------------------------------------------------- */
  /* Un thème peut resserrer (--theme-radius-scale: 0 pour un rendu
     brutaliste) ou arrondir davantage toute l'interface d'un seul réglage. */
  /* Repli via var() plutôt que déclaration : le socle étant chargé APRÈS le
     thème, redéclarer --theme-radius-scale ici écraserait le choix du thème. */
  --ds-radius-xs: calc(6px * var(--theme-radius-scale, 1));
  --ds-radius-sm: calc(8px * var(--theme-radius-scale, 1));
  --ds-radius-md: calc(12px * var(--theme-radius-scale, 1));
  --ds-radius-lg: calc(16px * var(--theme-radius-scale, 1));
  --ds-radius-xl: calc(24px * var(--theme-radius-scale, 1));
  /* À l'échelle 0 (thème brutaliste), même les pastilles deviennent
     rectangulaires : la cohérence du thème prime sur la forme. */
  --ds-radius-pill: calc(999px * var(--theme-radius-scale, 1));

  /* --- Élévation --------------------------------------------------------
     Ombres à deux couches (contact + diffusion) : plus proche du rendu
     physique qu'une ombre unique, et bien plus discret. */
  --ds-shadow-color: 220 30% 20%;
  --ds-shadow-xs: 0 1px 2px hsl(var(--ds-shadow-color) / 0.06);
  --ds-shadow-sm:
    0 1px 2px hsl(var(--ds-shadow-color) / 0.06),
    0 2px 6px hsl(var(--ds-shadow-color) / 0.06);
  --ds-shadow-md:
    0 2px 4px hsl(var(--ds-shadow-color) / 0.05),
    0 6px 16px hsl(var(--ds-shadow-color) / 0.08);
  --ds-shadow-lg:
    0 4px 8px hsl(var(--ds-shadow-color) / 0.05),
    0 16px 32px hsl(var(--ds-shadow-color) / 0.10);
  --ds-shadow-xl:
    0 8px 16px hsl(var(--ds-shadow-color) / 0.06),
    0 32px 64px hsl(var(--ds-shadow-color) / 0.14);
  --ds-shadow-brand: 0 8px 24px color-mix(in oklab, var(--ds-brand) 28%, transparent);

  /* --- Typographie ------------------------------------------------------
     Échelle fluide : le texte s'adapte à la largeur sans media query. */
  /* La fiche de style du thème actif déclare --theme-font-* ; le socle s'y
     conforme au lieu d'imposer sa propre typographie. Sans cette indirection,
     un thème comme « personalized » (Plus Jakarta Sans) se retrouvait rendu
     avec la police du thème par défaut. */
  --ds-font-body: var(--theme-font-body, 'Roboto', system-ui, -apple-system, 'Segoe UI', sans-serif);
  --ds-font-heading: var(--theme-font-heading, 'Montserrat', system-ui, -apple-system, 'Segoe UI', sans-serif);
  --ds-font-mono: var(--theme-font-mono, ui-monospace, 'SFMono-Regular', 'Cascadia Code', monospace);

  --ds-text-xs: 0.75rem;
  --ds-text-sm: 0.875rem;
  --ds-text-base: 1rem;
  --ds-text-lg: 1.125rem;
  --ds-text-xl: clamp(1.25rem, 1.1rem + 0.5vw, 1.5rem);
  --ds-text-2xl: clamp(1.5rem, 1.3rem + 0.9vw, 2rem);
  --ds-text-3xl: clamp(1.875rem, 1.5rem + 1.6vw, 2.75rem);
  --ds-text-4xl: clamp(2.25rem, 1.7rem + 2.6vw, 3.75rem);

  --ds-leading-tight: 1.2;
  --ds-leading-snug: 1.4;
  --ds-leading-normal: 1.6;
  --ds-leading-relaxed: 1.75;

  /* --- Mouvement -------------------------------------------------------- */
  --ds-ease: cubic-bezier(0.4, 0, 0.2, 1);
  --ds-ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --ds-ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
  --ds-duration-fast: 120ms;
  --ds-duration: 200ms;
  --ds-duration-slow: 320ms;

  /* --- Focus ------------------------------------------------------------ */
  --ds-focus-ring: 0 0 0 3px color-mix(in oklab, var(--ds-brand) 40%, transparent);
  --ds-focus-offset: 2px;
}

/* =========================================================================
   2. THÈME SOMBRE
   -------------------------------------------------------------------------
   On ne redéfinit QUE les jetons de rôle. Aucun composant n'a besoin d'être
   redéclaré plus bas : ils consomment tous ces variables.

   Le thème est piloté par [data-theme] / [data-bs-theme] (dayNight.js), avec
   repli sur la préférence système si l'utilisateur n'a jamais choisi.
   ========================================================================= */

[data-theme='dark'],
[data-bs-theme='dark'] {
  /* Échelle explicite plutôt que dérivée.
     Les valeurs étaient calculées par color-mix() vers le noir, ce qui écrasait
     l'écart entre le fond de page et les surfaces : cartes et champs se
     confondaient avec l'arrière-plan et l'interface paraissait plate.
     Chaque niveau est désormais nettement distinct, avec une pointe de bleu
     qui rattache le gris à la couleur de marque. */
  --ds-bg: #0d131a;
  --ds-surface-sunken: #090e14;
  --ds-surface: #151d27;
  --ds-surface-raised: #1c2733;
  --ds-surface-hover: #22303e;

  --ds-text: #e9eff7;
  --ds-text-muted: #a3b4c6;
  /* Conforme AA sur les quatre niveaux de surface du thème sombre,
     y compris l'état de survol (le plus clair). */
  --ds-text-subtle: #8898aa;

  /* En sombre, la couleur de marque doit remonter en luminosité pour rester
     lisible sur fond foncé (contraste AA sur --ds-surface). */
  --ds-brand-500: var(--ds-brand-300);
  --ds-info: var(--ds-brand-300);
  --ds-success: #34d399;
  --ds-warning: #fbbf24;
  --ds-danger: #fb7185;

  --ds-border: rgba(255, 255, 255, 0.09);
  --ds-border-strong: rgba(255, 255, 255, 0.17);

  /* Sur fond sombre une ombre noire est invisible : la profondeur vient d'un
     liseré clair en haut des surfaces, qui simule une lumière rasante. */
  --ds-shadow-color: 220 45% 2%;
  --ds-shadow-xs: 0 1px 2px hsl(var(--ds-shadow-color) / 0.5);
  --ds-shadow-sm:
    inset 0 1px 0 rgba(255, 255, 255, 0.04),
    0 1px 2px hsl(var(--ds-shadow-color) / 0.5),
    0 2px 6px hsl(var(--ds-shadow-color) / 0.35);
  --ds-shadow-md:
    inset 0 1px 0 rgba(255, 255, 255, 0.05),
    0 2px 4px hsl(var(--ds-shadow-color) / 0.45),
    0 8px 20px hsl(var(--ds-shadow-color) / 0.45);
  --ds-shadow-lg:
    inset 0 1px 0 rgba(255, 255, 255, 0.06),
    0 4px 8px hsl(var(--ds-shadow-color) / 0.45),
    0 18px 36px hsl(var(--ds-shadow-color) / 0.55);
  --ds-shadow-xl:
    inset 0 1px 0 rgba(255, 255, 255, 0.07),
    0 8px 16px hsl(var(--ds-shadow-color) / 0.45),
    0 36px 68px hsl(var(--ds-shadow-color) / 0.65);
}

/* =========================================================================
   3. PONT BOOTSTRAP
   -------------------------------------------------------------------------
   Les templates sont écrits en classes utilitaires Bootstrap. Plutôt que de
   les réécrire, on réalimente les variables --bs-* : tout le markup existant
   hérite du nouveau système sans être touché.
   ========================================================================= */

:root,
[data-bs-theme='light'] {
  --bs-primary: var(--ds-brand-500);
  --bs-primary-rgb: 0, 119, 189;
  --bs-body-bg: var(--ds-bg);
  --bs-body-color: var(--ds-text);
  --bs-body-font-family: var(--ds-font-body);
  --bs-body-line-height: var(--ds-leading-normal);
  --bs-secondary-color: var(--ds-text-muted);
  --bs-tertiary-bg: var(--ds-surface-sunken);
  --bs-border-color: var(--ds-border);
  --bs-border-color-translucent: var(--ds-border);
  --bs-emphasis-color: var(--ds-text);
  --bs-link-color: var(--ds-brand-600);
  --bs-link-hover-color: var(--ds-brand-700);
  --bs-border-radius: var(--ds-radius-md);
  --bs-border-radius-sm: var(--ds-radius-sm);
  --bs-border-radius-lg: var(--ds-radius-lg);
  --bs-border-radius-xl: var(--ds-radius-xl);
  --bs-box-shadow: var(--ds-shadow-md);
  --bs-box-shadow-sm: var(--ds-shadow-sm);
  --bs-box-shadow-lg: var(--ds-shadow-lg);
}

[data-bs-theme='dark'] {
  --bs-primary: var(--ds-brand-300);
  --bs-body-bg: var(--ds-bg);
  --bs-body-color: var(--ds-text);
  --bs-secondary-color: var(--ds-text-muted);
  --bs-tertiary-bg: var(--ds-surface-raised);
  --bs-border-color: var(--ds-border);
  --bs-border-color-translucent: var(--ds-border);
  --bs-emphasis-color: var(--ds-text);
  --bs-link-color: var(--ds-brand-300);
  --bs-link-hover-color: var(--ds-brand-200);
}

/* =========================================================================
   4. BASE
   ========================================================================= */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* Compense la navbar fixe lors des ancres */
  scroll-padding-top: 5rem;
}

body {
  /* !important : le thème historique force le fond du body. */
  background-color: var(--ds-bg) !important;
  color: var(--ds-text);
  font-family: var(--ds-font-body);
  font-size: var(--ds-text-base);
  line-height: var(--ds-leading-normal);
  /* Rendu de texte plus net sur écrans HiDPI */
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  /* Évite les débordements horizontaux causés par les grilles imbriquées */
  overflow-x: hidden;
}

/* --- Typographie ------------------------------------------------------- */

h1, h2, h3, h4, h5, h6,
.h1, .h2, .h3, .h4, .h5, .h6 {
  font-family: var(--ds-font-heading);
  line-height: var(--ds-leading-tight);
  color: var(--ds-text);
  /* Le resserrement optique fait « respirer » les gros titres */
  letter-spacing: -0.02em;
  text-wrap: balance;
}

h1, .h1 { font-size: var(--ds-text-3xl); font-weight: 700; }
h2, .h2 { font-size: var(--ds-text-2xl); font-weight: 700; }
h3, .h3 { font-size: var(--ds-text-xl); font-weight: 600; }
h4, .h4 { font-size: var(--ds-text-lg); font-weight: 600; letter-spacing: -0.01em; }
h5, .h5 { font-size: var(--ds-text-base); font-weight: 600; letter-spacing: 0; }
h6, .h6 { font-size: var(--ds-text-sm); font-weight: 600; letter-spacing: 0; }

/* Le thème « éditorial » souligne chaque h1 d'une barre noire de 4 px sur
   toute la largeur. Sur une carte de connexion, cela ressemble à un défaut de
   rendu plus qu'à un parti pris. On garde l'idée — un accent sous le titre —
   en la ramenant à un filet court, dans la couleur de marque. */
h1 {
  border-bottom: 0 !important;
}

.ds-underline::after,
.card h1::after,
.login-card h1::after {
  content: '';
  display: block;
  width: 2.5rem;
  height: 3px;
  margin-top: 0.6rem;
  border-radius: 2px;
  background: var(--ds-brand-500);
}

/* Le thème historique met tous les h1 en capitales : très pénalisant pour la
   lisibilité (les capitales suppriment les repères d'ascendantes) et pour les
   lecteurs d'écran qui peuvent les épeler. On revient à la casse d'origine. */
h1, .h1 { text-transform: none !important; }

.display-1, .display-2, .display-3,
.display-4, .display-5, .display-6 {
  font-family: var(--ds-font-heading);
  font-weight: 800;
  letter-spacing: -0.035em;
  line-height: 1.05;
  text-wrap: balance;
}

.display-5 { font-size: var(--ds-text-4xl); }
.display-6 { font-size: var(--ds-text-3xl); }

.lead {
  font-size: var(--ds-text-lg);
  line-height: var(--ds-leading-relaxed);
  color: var(--ds-text-muted);
  font-weight: 400;
  /* Une ligne de lecture confortable plafonne autour de 70 caractères */
  max-width: 68ch;
  text-wrap: pretty;
}

p { text-wrap: pretty; }

small, .small { font-size: var(--ds-text-sm); }

code, kbd, samp, pre { font-family: var(--ds-font-mono); }

code {
  background: var(--ds-surface-sunken);
  padding: 0.15em 0.4em;
  border-radius: var(--ds-radius-xs);
  font-size: 0.875em;
  color: var(--ds-brand-700);
}

[data-theme='dark'] code { color: var(--ds-brand-200); }

hr {
  border: 0;
  border-top: 1px solid var(--ds-border);
  opacity: 1;
  margin: var(--ds-space-5) 0;
}

/* --- Texte utilitaire --------------------------------------------------- */

.text-muted,
.text-secondary {
  color: var(--ds-text-muted) !important;
}

/* --- Liens -------------------------------------------------------------- */

a {
  color: var(--ds-brand-600);
  text-decoration-thickness: 1px;
  text-underline-offset: 0.18em;
  transition: color var(--ds-duration-fast) var(--ds-ease);
}

a:hover { color: var(--ds-brand-700); }

[data-theme='dark'] a { color: var(--ds-brand-300); }
[data-theme='dark'] a:hover { color: var(--ds-brand-200); }

/* =========================================================================
   ACCESSIBILITÉ — focus visible
   -------------------------------------------------------------------------
   Bootstrap remplace l'outline natif par une ombre bleue peu contrastée.
   On rétablit un anneau net, visible sur les deux thèmes, uniquement pour la
   navigation clavier (:focus-visible) afin de ne pas gêner la souris.
   ========================================================================= */

:focus-visible {
  outline: 2px solid var(--ds-brand-500);
  outline-offset: var(--ds-focus-offset);
  border-radius: var(--ds-radius-xs);
}

/* On neutralise l'ombre Bootstrap au profit de l'outline ci-dessus */
.btn:focus-visible,
.form-control:focus-visible,
.form-select:focus-visible,
.form-check-input:focus-visible,
.nav-link:focus-visible,
.dropdown-item:focus-visible,
.page-link:focus-visible {
  box-shadow: none;
  outline: 2px solid var(--ds-brand-500);
  outline-offset: var(--ds-focus-offset);
}

/* La cible du lien d'évitement porte tabindex="-1" pour être focalisable au
   clavier. Sans cette exception, la recevoir dessinait un anneau autour de
   TOUT le contenu de la page — un grand cadre inattendu après le premier clic
   sur le lien d'évitement. Le repère de position vient du titre atteint. */
main[tabindex='-1']:focus,
main[tabindex='-1']:focus-visible {
  outline: none;
}

/* Lien d'évitement : caché jusqu'à ce qu'il reçoive le focus clavier */
.ds-skip-link {
  position: absolute;
  top: var(--ds-space-2);
  left: var(--ds-space-2);
  z-index: 2000;
  padding: var(--ds-space-3) var(--ds-space-5);
  background: var(--ds-brand-600);
  color: #fff;
  font-weight: 600;
  border-radius: var(--ds-radius-sm);
  box-shadow: var(--ds-shadow-lg);
  transform: translateY(-150%);
  transition: transform var(--ds-duration) var(--ds-ease-out);
}

.ds-skip-link:focus { transform: translateY(0); color: #fff; }

/* =========================================================================
   5. COMPOSANTS
   ========================================================================= */

/* --- Boutons ------------------------------------------------------------
   Deux détails font tout le rendu « moderne » :
   - un léger soulèvement au survol, annulé à l'appui (retour tactile) ;
   - une ombre teintée de la couleur du bouton plutôt qu'une ombre grise. */

.btn {
  --ds-btn-lift: -1px;
  font-family: var(--ds-font-body);
  font-weight: 600;
  letter-spacing: 0.01em;
  border-radius: var(--ds-radius-sm);
  padding: 0.625rem 1.25rem;
  border-width: 1px;
  transition:
    background-color var(--ds-duration-fast) var(--ds-ease),
    border-color var(--ds-duration-fast) var(--ds-ease),
    color var(--ds-duration-fast) var(--ds-ease),
    box-shadow var(--ds-duration) var(--ds-ease),
    transform var(--ds-duration-fast) var(--ds-ease);
}

.btn:hover { transform: translateY(var(--ds-btn-lift)); }
.btn:active { transform: translateY(0); }

.btn-lg { padding: 0.875rem 1.75rem; font-size: var(--ds-text-base); border-radius: var(--ds-radius-md); }
.btn-sm { padding: 0.375rem 0.875rem; font-size: var(--ds-text-sm); border-radius: var(--ds-radius-xs); }

.btn-primary {
  /* !important : le thème historique force ces deux propriétés. */
  background-color: var(--ds-brand-600) !important;
  color: var(--ds-text-on-brand) !important;
  border-color: var(--ds-brand-600);
  box-shadow: var(--ds-shadow-xs);
}

.btn-primary:hover {
  background-color: var(--ds-brand-700) !important;
  border-color: var(--ds-brand-700);
  box-shadow: var(--ds-shadow-brand);
}

.btn-primary:active { background-color: var(--ds-brand-800) !important; }

.btn-outline-primary {
  color: var(--ds-brand-600);
  border-color: color-mix(in oklab, var(--ds-brand) 45%, transparent);
  background-color: transparent;
}

.btn-outline-primary:hover {
  background-color: var(--ds-brand-600);
  border-color: var(--ds-brand-600);
  color: var(--ds-text-on-brand);
  box-shadow: var(--ds-shadow-brand);
}

[data-theme='dark'] .btn-outline-primary { color: var(--ds-brand-300); }

.btn-secondary {
  background-color: var(--ds-surface-raised);
  border-color: var(--ds-border-strong);
  color: var(--ds-text);
}

.btn-secondary:hover {
  background-color: var(--ds-surface-hover);
  border-color: var(--ds-border-strong);
  color: var(--ds-text);
}

.btn-light,
.btn-outline-light {
  border-color: var(--ds-border);
}

[data-theme='dark'] .btn-light {
  background-color: var(--ds-surface-raised);
  border-color: var(--ds-border);
  color: var(--ds-text);
}

[data-theme='dark'] .btn-light:hover {
  background-color: var(--ds-surface-hover);
  color: var(--ds-text);
}

.btn:disabled,
.btn.disabled {
  opacity: 0.55;
  transform: none;
  box-shadow: none;
  cursor: not-allowed;
}

/* --- Cartes -------------------------------------------------------------
   Le rendu par défaut de Bootstrap (bordure grise + coins peu arrondis)
   date visuellement. On passe sur surface + ombre douce + coin généreux. */

.card {
  /* !important : le thème historique force fond et bordure en mode sombre. */
  background-color: var(--ds-surface) !important;
  border: 1px solid var(--ds-border) !important;
  border-radius: var(--ds-radius-lg);
  /* Un dégradé très court en haut de carte suffit à lui donner du relief,
     là où un aplat uniforme donnait une interface sans profondeur. */
  background-image: linear-gradient(
    to bottom,
    color-mix(in oklab, var(--ds-text) 3%, transparent),
    transparent 88px
  );
  box-shadow: var(--ds-shadow-sm);
  color: var(--ds-text);
  overflow: hidden;
  transition:
    box-shadow var(--ds-duration) var(--ds-ease),
    transform var(--ds-duration) var(--ds-ease),
    border-color var(--ds-duration) var(--ds-ease);
}

/* Le soulèvement n'est appliqué qu'aux cartes réellement cliquables :
   animer une carte statique au survol est un faux affordance. */
a > .card:hover,
.card-hoverable:hover,
.card.fake-link:hover {
  transform: translateY(-3px);
  box-shadow: var(--ds-shadow-lg);
  border-color: color-mix(in oklab, var(--ds-brand) 35%, transparent) !important;
}

.card-header {
  background-color: transparent;
  border-bottom: 1px solid var(--ds-border);
  font-family: var(--ds-font-heading);
  font-weight: 600;
  padding: var(--ds-space-4) var(--ds-space-5);
}

.card-body { padding: var(--ds-space-5); }

.card-footer {
  background-color: var(--ds-surface-sunken);
  border-top: 1px solid var(--ds-border);
  padding: var(--ds-space-3) var(--ds-space-5);
}

.card-title {
  font-family: var(--ds-font-heading);
  font-weight: 600;
  letter-spacing: -0.01em;
  margin-bottom: var(--ds-space-2);
}

/* --- Formulaires --------------------------------------------------------- */

.form-control,
.form-select {
  /* Les champs se posaient sur la même surface que la carte : sur fond sombre
     ils disparaissaient en rectangles noirs. Ils sont désormais légèrement
     surélevés, donc identifiables comme zones de saisie. */
  background-color: var(--ds-surface-raised);
  border: 1px solid var(--ds-border-strong);
  border-radius: var(--ds-radius-sm);
  color: var(--ds-text);
  padding: 0.625rem 0.875rem;
  font-size: var(--ds-text-base);
  transition:
    border-color var(--ds-duration-fast) var(--ds-ease),
    box-shadow var(--ds-duration-fast) var(--ds-ease),
    background-color var(--ds-duration-fast) var(--ds-ease);
}

.form-control:hover:not(:disabled),
.form-select:hover:not(:disabled) {
  border-color: color-mix(in oklab, var(--ds-brand) 40%, var(--ds-border-strong));
}

.form-control:focus,
.form-select:focus {
  background-color: var(--ds-surface-raised);
  border-color: var(--ds-brand-500);
  color: var(--ds-text);
  box-shadow: var(--ds-focus-ring);
}

.form-control::placeholder { color: var(--ds-text-subtle); opacity: 1; }

.form-label {
  font-weight: 500;
  font-size: var(--ds-text-sm);
  color: var(--ds-text-muted);
  margin-bottom: var(--ds-space-2);
}

/* Champ flottant : l'étiquette doit rester lisible en thème sombre */
.form-floating > label { color: var(--ds-text-subtle); }

.form-floating > .form-control:focus ~ label,
.form-floating > .form-control:not(:placeholder-shown) ~ label {
  color: var(--ds-text-muted);
  opacity: 1;
}

/* Bootstrap peint un fond blanc opaque derrière l'étiquette flottante,
   ce qui crée un rectangle clair disgracieux en thème sombre. */
.form-floating > label::after {
  background-color: transparent !important;
}

.form-check-input {
  border-color: var(--ds-border-strong);
  transition:
    background-color var(--ds-duration-fast) var(--ds-ease),
    border-color var(--ds-duration-fast) var(--ds-ease);
}

.form-check-input:checked {
  background-color: var(--ds-brand-600);
  border-color: var(--ds-brand-600);
}

.input-group-text {
  background-color: var(--ds-surface-sunken);
  border-color: var(--ds-border-strong);
  color: var(--ds-text-muted);
  border-radius: var(--ds-radius-sm);
}

/* --- Navigation ---------------------------------------------------------
   Barre translucide avec flou d'arrière-plan : donne de la profondeur au
   défilement tout en gardant le contenu lisible dessous. */

.navbar {
  background-color: color-mix(in oklab, var(--ds-surface) 85%, transparent) !important;
  border-bottom: 1px solid var(--ds-border);
  box-shadow: var(--ds-shadow-xs);
  padding-block: var(--ds-space-3);
}

@supports (backdrop-filter: blur(1px)) {
  .navbar {
    backdrop-filter: saturate(180%) blur(14px);
    -webkit-backdrop-filter: saturate(180%) blur(14px);
  }
}

.navbar-brand {
  font-family: var(--ds-font-heading);
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--ds-text);
}

.nav-link {
  color: var(--ds-text-muted);
  font-weight: 500;
  border-radius: var(--ds-radius-sm);
  padding: var(--ds-space-2) var(--ds-space-3);
  transition:
    color var(--ds-duration-fast) var(--ds-ease),
    background-color var(--ds-duration-fast) var(--ds-ease);
}

.nav-link:hover,
.nav-link:focus {
  color: var(--ds-text);
  background-color: var(--ds-surface-hover);
}

.nav-link.active {
  color: var(--ds-brand-600) !important;
  background-color: color-mix(in oklab, var(--ds-brand) 10%, transparent);
  font-weight: 600;
}

[data-theme='dark'] .nav-link.active { color: var(--ds-brand-200) !important; }

/* Onglets : le thème historique pose une bordure haute de 5px très lourde.
   On la remplace par un souligné bas, plus courant et moins bruyant. */
.nav-tabs { border-bottom: 1px solid var(--ds-border); gap: var(--ds-space-1); }

.nav-tabs .nav-link {
  border: 0;
  border-bottom: 2px solid transparent;
  border-radius: var(--ds-radius-sm) var(--ds-radius-sm) 0 0;
  margin-bottom: -1px;
}

.nav-tabs .nav-link.active {
  border-top: 0 !important;
  border-bottom: 2px solid var(--ds-brand-500);
  background-color: transparent;
  color: var(--ds-brand-600) !important;
}

/* --- Menus déroulants ---------------------------------------------------- */

.dropdown-menu {
  /* !important : le thème historique force le fond en mode sombre. */
  background-color: var(--ds-surface-raised) !important;
  border: 1px solid var(--ds-border);
  border-radius: var(--ds-radius-md);
  box-shadow: var(--ds-shadow-lg);
  padding: var(--ds-space-2);
  /* Empêche le menu de traverser l'écran sur petits écrans */
  max-width: min(92vw, 22rem);
}

.dropdown-item {
  border-radius: var(--ds-radius-xs);
  padding: var(--ds-space-2) var(--ds-space-3);
  color: var(--ds-text);
  transition: background-color var(--ds-duration-fast) var(--ds-ease);
}

.dropdown-item:hover,
.dropdown-item:focus {
  background-color: var(--ds-surface-hover);
  color: var(--ds-text);
}

.dropdown-divider { border-color: var(--ds-border); }

/* --- Badges -------------------------------------------------------------- */

.badge {
  font-weight: 600;
  font-size: var(--ds-text-xs);
  letter-spacing: 0.02em;
  padding: 0.35em 0.7em;
  border-radius: var(--ds-radius-pill);
}

/* --- Alertes ------------------------------------------------------------
   Fond très légèrement teinté + filet coloré à gauche : lisible dans les
   deux thèmes, contrairement aux fonds pastel opaques de Bootstrap. */

.alert {
  border: 1px solid var(--ds-border);
  border-left: 3px solid var(--ds-border-strong);
  border-radius: var(--ds-radius-md);
  padding: var(--ds-space-4) var(--ds-space-5);
  box-shadow: var(--ds-shadow-xs);
  color: var(--ds-text);
}

.alert-success { background-color: var(--ds-success-bg); border-left-color: var(--ds-success); }
.alert-warning { background-color: var(--ds-warning-bg); border-left-color: var(--ds-warning); }
.alert-danger  { background-color: var(--ds-danger-bg);  border-left-color: var(--ds-danger); }
.alert-info,
.alert-primary { background-color: var(--ds-info-bg);    border-left-color: var(--ds-info); }

.alert-heading { font-family: var(--ds-font-heading); font-weight: 700; color: var(--ds-text); }

/* --- Tableaux ------------------------------------------------------------ */

.table {
  --bs-table-bg: transparent;
  --bs-table-color: var(--ds-text);
  --bs-table-border-color: var(--ds-border);
  --bs-table-striped-bg: var(--ds-surface-sunken);
  --bs-table-hover-bg: var(--ds-surface-hover);
  border-color: var(--ds-border);
}

.table > thead {
  border-bottom: 2px solid var(--ds-border-strong);
}

.table > thead th {
  font-family: var(--ds-font-heading);
  font-size: var(--ds-text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ds-text-muted);
  padding: var(--ds-space-3) var(--ds-space-4);
  background-color: transparent;
}

.table > tbody td {
  padding: var(--ds-space-3) var(--ds-space-4);
  vertical-align: middle;
  border-color: var(--ds-border);
}

/* Un tableau large doit défiler dans son conteneur, jamais faire défiler
   la page entière horizontalement. */
.table-responsive { border-radius: var(--ds-radius-md); }

/* --- Modales ------------------------------------------------------------- */

.modal-content {
  background-color: var(--ds-surface);
  border: 1px solid var(--ds-border);
  border-radius: var(--ds-radius-lg);
  box-shadow: var(--ds-shadow-xl);
  color: var(--ds-text);
}

.modal-header,
.modal-footer { border-color: var(--ds-border); padding: var(--ds-space-4) var(--ds-space-5); }
.modal-body { padding: var(--ds-space-5); }
.modal-title { font-family: var(--ds-font-heading); font-weight: 600; }
.modal-backdrop.show { opacity: 0.6; }

/* --- Pagination ---------------------------------------------------------- */

.page-link {
  color: var(--ds-text-muted);
  background-color: transparent;
  border-color: var(--ds-border);
  border-radius: var(--ds-radius-xs);
  margin: 0 2px;
  transition:
    background-color var(--ds-duration-fast) var(--ds-ease),
    color var(--ds-duration-fast) var(--ds-ease);
}

.page-link:hover { background-color: var(--ds-surface-hover); color: var(--ds-text); }

.page-item.active .page-link {
  background-color: var(--ds-brand-600);
  border-color: var(--ds-brand-600);
  color: var(--ds-text-on-brand);
}

/* =========================================================================
   PAGES D'AUTHENTIFICATION
   -------------------------------------------------------------------------
   Connexion, récupération, saisie de code et définition du mot de passe
   partagent la même enveloppe : en-tête aéré, carte centrée, pied de page.
   Ces règles évitent que chaque gabarit redéfinisse sa propre mise en forme,
   comme c'était le cas — la carte de récupération était grise sur fond gris,
   avec un champ blanc, quand celle de connexion était blanche.
   ========================================================================= */

.auth-header {
  padding: var(--ds-space-4) clamp(1rem, 4vw, 2.5rem);
  gap: var(--ds-space-3);
}

.auth-header img {
  height: 40px;
  width: auto;
  object-fit: contain;
}

.auth-shell { min-height: 100dvh; }

/* Carte commune aux quatre pages */
.auth-card {
  background-color: var(--ds-surface) !important;
  border: 1px solid var(--ds-border) !important;
  border-radius: var(--ds-radius-xl);
  box-shadow: var(--ds-shadow-lg);
  padding: clamp(1.75rem, 4vw, 3rem);
}

.auth-card h1 {
  font-size: var(--ds-text-2xl);
  margin-bottom: var(--ds-space-2);
}

.auth-card .form-control {
  background-color: var(--ds-surface-raised) !important;
  border: 1px solid var(--ds-border-strong) !important;
}

.auth-card .form-control:focus {
  border-color: var(--ds-brand-500) !important;
  box-shadow: var(--ds-focus-ring);
}

.auth-intro {
  color: var(--ds-text-muted);
  margin-bottom: var(--ds-space-5);
  max-width: 40ch;
}

/* --- Contrôles d'en-tête (thème, langue) --------------------------------
   Utilisés par _components/_header.html.twig. La définition était dupliquée
   à l'identique dans les quatre gabarits qui incluent ce composant ; elle est
   désormais centralisée ici. */

.header-control-btn {
  height: 38px;
  padding: 0 0.75rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  border: 1px solid var(--ds-border);
  background-color: var(--ds-surface);
  color: var(--ds-text);
  border-radius: var(--ds-radius-pill);
  font-size: var(--ds-text-sm);
  font-weight: 500;
  transition:
    background-color var(--ds-duration-fast) var(--ds-ease),
    border-color var(--ds-duration-fast) var(--ds-ease),
    color var(--ds-duration-fast) var(--ds-ease);
}

.header-control-btn:hover,
.header-control-btn:focus {
  background-color: var(--ds-surface-hover);
  border-color: var(--ds-border-strong);
  color: var(--ds-text);
}

.header-control-btn.btn-icon-only { width: 38px; padding: 0; }

/* Bascule des icônes soleil/lune selon le thème actif */
[data-bs-theme='dark'] .icon-sun { display: inline-block; }
[data-bs-theme='dark'] .icon-moon { display: none; }
[data-bs-theme='light'] .icon-sun { display: none; }
[data-bs-theme='light'] .icon-moon { display: inline-block; }

/* =========================================================================
   COQUILLE — barre latérale + barre supérieure
   -------------------------------------------------------------------------
   La navigation principale occupait toute la largeur de l'en-tête et passait
   sur deux lignes dès que le nom de la plateforme était long. Elle est ici
   déplacée sur le côté, ce qui rend au contenu la hauteur qu'elle consommait.
   ========================================================================= */

:root {
  --ds-sidebar-w: 16rem;
  --ds-sidebar-w-collapsed: 4.5rem;
  --ds-topbar-h: 3.5rem;
}

.app-shell { min-height: 100dvh; }

.app-shell__main { display: flex; flex-direction: column; min-height: 100dvh; }

/* --- Barre latérale ----------------------------------------------------- */

.app-sidebar {
  position: fixed;
  inset-block: 0;
  inset-inline-start: 0;
  z-index: 1045;
  width: var(--ds-sidebar-w);
  display: flex;
  flex-direction: column;
  background-color: var(--ds-surface);
  border-inline-end: 1px solid var(--ds-border);
  overflow: hidden auto;
  overscroll-behavior: contain;
  transition: width var(--ds-duration) var(--ds-ease),
              transform var(--ds-duration) var(--ds-ease);
}

.app-sidebar__head {
  display: flex;
  align-items: center;
  gap: var(--ds-space-2);
  padding: var(--ds-space-4) var(--ds-space-3);
  border-bottom: 1px solid var(--ds-border);
  min-height: var(--ds-topbar-h);
}

.app-sidebar__brand {
  display: flex;
  align-items: center;
  gap: var(--ds-space-2);
  min-width: 0;
  flex: 1;
  color: var(--ds-text);
  text-decoration: none;
  font-family: var(--ds-font-heading);
  font-weight: 700;
  font-size: 1.05rem;
  letter-spacing: -0.02em;
}

.app-sidebar__brand img {
  height: 32px;
  width: auto;
  flex-shrink: 0;
  object-fit: contain;
}

.app-sidebar__brand-text {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.app-sidebar__toggle {
  flex-shrink: 0;
  width: 2rem;
  height: 2rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--ds-border);
  border-radius: var(--ds-radius-sm);
  background: transparent;
  color: var(--ds-text-muted);
  cursor: pointer;
  transition: background-color var(--ds-duration-fast) var(--ds-ease),
              color var(--ds-duration-fast) var(--ds-ease);
}

.app-sidebar__toggle:hover { background-color: var(--ds-surface-hover); color: var(--ds-text); }
.app-sidebar__toggle i { transition: transform var(--ds-duration) var(--ds-ease); }

.app-sidebar__nav { flex: 1; padding: var(--ds-space-3) var(--ds-space-2); }
.app-sidebar__foot { padding: var(--ds-space-2); border-top: 1px solid var(--ds-border); }

.app-sidebar__nav li + li,
.app-sidebar__foot li + li { margin-top: 2px; }

.app-sidebar__link {
  display: flex;
  align-items: center;
  gap: var(--ds-space-3);
  width: 100%;
  padding: 0.6rem 0.75rem;
  border: 0;
  border-radius: var(--ds-radius-sm);
  background: transparent;
  color: var(--ds-text-muted);
  font-size: 0.9rem;
  font-weight: 500;
  text-align: start;
  text-decoration: none;
  cursor: pointer;
  white-space: nowrap;
  transition: background-color var(--ds-duration-fast) var(--ds-ease),
              color var(--ds-duration-fast) var(--ds-ease);
}

.app-sidebar__link i {
  flex-shrink: 0;
  width: 1.25rem;
  text-align: center;
  font-size: 0.95rem;
}

.app-sidebar__link:hover { background-color: var(--ds-surface-hover); color: var(--ds-text); }

.app-sidebar__link.is-active {
  background-color: color-mix(in oklab, var(--ds-brand) 14%, transparent);
  color: var(--ds-brand-600);
  font-weight: 600;
  position: relative;
}

/* Filet vertical sur le bord : le repère de page courante reste lisible même
   quand la barre est repliée en icônes. */
.app-sidebar__link.is-active::before {
  content: '';
  position: absolute;
  inset-block: 20%;
  inset-inline-start: -0.5rem;
  width: 3px;
  border-radius: 0 3px 3px 0;
  background: var(--ds-brand-500);
}

[data-theme='dark'] .app-sidebar__link.is-active { color: var(--ds-brand-200); }

.app-sidebar__link--danger { color: var(--ds-danger); }
.app-sidebar__link--danger:hover {
  background-color: var(--ds-danger-bg);
  color: var(--ds-danger);
}

.app-sidebar__link--warning { color: var(--ds-warning); }
.app-sidebar__link--warning:hover {
  background-color: var(--ds-warning-bg);
  color: var(--ds-warning);
}

.app-sidebar__link--switch { cursor: pointer; }

/* --- État replié (icônes seules) ---------------------------------------- */

@media (min-width: 992px) {
  .app-sidebar { transform: none; }

  .app-shell--with-sidebar .app-shell__main {
    margin-inline-start: var(--ds-sidebar-w);
    transition: margin-inline-start var(--ds-duration) var(--ds-ease);
  }

  .sidebar-collapsed .app-sidebar { width: var(--ds-sidebar-w-collapsed); }

  .sidebar-collapsed .app-shell--with-sidebar .app-shell__main {
    margin-inline-start: var(--ds-sidebar-w-collapsed);
  }

  .sidebar-collapsed .app-sidebar__label { display: none; }

  /* Replié, l'en-tête ne fait plus que 4,5 rem : un logo de 34 px et un bouton
     de 32 px ne peuvent pas y tenir côte à côte, ils se chevauchaient. Le logo
     part dans la barre supérieure et le bouton occupe seul la largeur. */
  .sidebar-collapsed .app-sidebar__brand { display: none; }

  .sidebar-collapsed .app-sidebar__head {
    justify-content: center;
    padding-inline: 0;
  }

  .sidebar-collapsed .app-sidebar__link { justify-content: center; padding-inline: 0; }
  .sidebar-collapsed .app-sidebar__toggle i { transform: rotate(180deg); }

  /* Le libellé disparaissant, une infobulle prend le relais pour que chaque
     icône reste identifiable. */
  .sidebar-collapsed .app-sidebar__link { position: relative; }

  .sidebar-collapsed .app-sidebar__link::after {
    content: attr(data-sidebar-tip);
    position: absolute;
    inset-inline-start: calc(100% + 0.5rem);
    top: 50%;
    transform: translateY(-50%);
    padding: 0.3rem 0.6rem;
    border-radius: var(--ds-radius-xs);
    background: var(--ds-neutral-900);
    color: var(--ds-neutral-025);
    font-size: 0.75rem;
    white-space: nowrap;
    opacity: 0;
    pointer-events: none;
    box-shadow: var(--ds-shadow-md);
    transition: opacity var(--ds-duration-fast) var(--ds-ease);
    z-index: 10;
  }

  .sidebar-collapsed .app-sidebar__link:hover::after,
  .sidebar-collapsed .app-sidebar__link:focus-visible::after { opacity: 1; }
}

/* --- Mode coulissant sous lg -------------------------------------------- */

@media (max-width: 991.98px) {
  .app-sidebar {
    transform: translateX(-100%);
    box-shadow: var(--ds-shadow-xl);
  }

  .sidebar-open .app-sidebar { transform: translateX(0); }

  .app-sidebar__scrim {
    position: fixed;
    inset: 0;
    z-index: 1040;
    background: color-mix(in oklab, var(--ds-neutral-950) 55%, transparent);
  }
}

/* --- Barre supérieure --------------------------------------------------- */

.app-topbar {
  position: sticky;
  top: 0;
  z-index: 1030;
  background-color: color-mix(in oklab, var(--ds-surface) 88%, transparent);
  border-bottom: 1px solid var(--ds-border);
}

@supports (backdrop-filter: blur(1px)) {
  .app-topbar {
    backdrop-filter: saturate(180%) blur(14px);
    -webkit-backdrop-filter: saturate(180%) blur(14px);
  }
}

.app-topbar__inner {
  display: flex;
  align-items: center;
  gap: var(--ds-space-2);
  min-height: var(--ds-topbar-h);
  padding-inline: var(--ds-space-3);
}

.app-topbar__brand {
  align-items: center;
  gap: var(--ds-space-2);
  min-width: 0;
  color: var(--ds-text);
  text-decoration: none;
  font-family: var(--ds-font-heading);
  font-weight: 700;
  font-size: 1.05rem;
  letter-spacing: -0.02em;
}

.app-topbar__brand:hover { color: var(--ds-text); }

.app-topbar__brand-text {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.app-topbar__brand-logo {
  height: 30px;
  width: auto;
  flex-shrink: 0;
}

/* La marque n'apparaît en haut que lorsque la barre latérale ne la porte
   plus : repliée à partir de lg, ou masquée en dessous. Logo et nom se
   déplacent ensemble, jamais séparément. */
.app-topbar__brand { display: none; }

.sidebar-collapsed .app-topbar__brand { display: flex; }

@media (max-width: 991.98px) {
  .app-topbar__brand { display: flex; }
}

.app-topbar__title {
  font-family: var(--ds-font-heading);
  font-weight: 600;
  font-size: 0.95rem;
  color: var(--ds-text-muted);
  margin-inline-end: auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Sépare le titre de page de la marque quand les deux sont présents */
.app-topbar__title:not(:empty) {
  padding-inline-start: var(--ds-space-3);
  margin-inline-start: var(--ds-space-1);
  border-inline-start: 1px solid var(--ds-border);
}

.app-topbar__actions {
  display: flex;
  align-items: center;
  gap: var(--ds-space-2);
  margin-inline-start: auto;
}

.app-topbar__burger,
.app-topbar__icon {
  width: 2.25rem;
  height: 2.25rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 0;
  border-radius: var(--ds-radius-sm);
  background: transparent;
  color: var(--ds-text-muted);
  text-decoration: none;
  cursor: pointer;
  transition: background-color var(--ds-duration-fast) var(--ds-ease),
              color var(--ds-duration-fast) var(--ds-ease);
}

.app-topbar__burger:hover,
.app-topbar__icon:hover { background-color: var(--ds-surface-hover); color: var(--ds-text); }

.app-topbar__search #searchBox {
  border: 1px solid var(--ds-border);
  border-radius: var(--ds-radius-pill);
  background-color: var(--ds-surface-sunken);
  color: var(--ds-text-muted);
}

.app-topbar__search input { color: var(--ds-text); width: 9rem; outline: none; }
.app-topbar__search input::placeholder { color: var(--ds-text-subtle); }

.app-topbar__avatar {
  width: 2.1rem;
  height: 2.1rem;
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background-color: var(--ds-brand-600);
  color: #fff;
  font-size: 0.75rem;
  font-weight: 700;
  text-decoration: none;
  transition: transform var(--ds-duration-fast) var(--ds-ease);
}

.app-topbar__avatar:hover { transform: scale(1.06); color: #fff; }

/* Le contenu se cale sous la barre supérieure collante */
.app-shell__main > main { flex: 1; }

/* =========================================================================
   COMPATIBILITÉ — surfaces héritées insensibles au thème
   -------------------------------------------------------------------------
   Ces composants sont peints en dur par les fiches de style des thèmes, avec
   une couleur claire (`--coul-claire`, blanc opaque) quel que soit le mode.
   Leur contenu, lui, suit le thème : en mode sombre on obtenait donc du texte
   clair sur un fond clair — illisible.

   Le socle étant chargé après les thèmes, ces règles reprennent la main. Elles
   corrigent les quatre thèmes d'un seul endroit.
   ========================================================================= */

/* Résultats de la recherche globale */
#containerSearchResults {
  background-color: var(--ds-surface-raised) !important;
  color: var(--ds-text) !important;
  border: 1px solid var(--ds-border) !important;
  border-radius: var(--ds-radius-md);
  box-shadow: var(--ds-shadow-lg);
}

#containerSearchResults a,
#containerSearchResults .list-group-item {
  background-color: transparent !important;
  color: var(--ds-text) !important;
  border-color: var(--ds-border) !important;
}

#containerSearchResults a:hover,
#containerSearchResults .list-group-item:hover {
  background-color: var(--ds-surface-hover) !important;
}

/* Lignes de résultat : les classes utilitaires employées par le script de
   recherche (btn-light, bg-body-tertiary) produisaient des boutons blancs et
   des étiquettes quasi noires en thème sombre. On les recale explicitement. */
.search-result-item {
  border-radius: var(--ds-radius-sm);
  transition: background-color var(--ds-duration-fast) var(--ds-ease);
}

.search-result-item:hover { background-color: var(--ds-surface-hover) !important; }

.search-result-item .badge {
  background-color: var(--ds-surface-raised) !important;
  color: var(--ds-text-muted) !important;
  border-color: var(--ds-border) !important;
  font-weight: 600;
}

.search-result-item .btn-light,
#containerSearchResults .btn-light {
  background-color: var(--ds-surface-raised) !important;
  border-color: var(--ds-border) !important;
  color: var(--ds-text-muted) !important;
}

.search-result-item .btn-light:hover,
#containerSearchResults .btn-light:hover {
  background-color: var(--ds-surface-hover) !important;
  color: var(--ds-text) !important;
}

/* `.hover-bg` est repeint par plusieurs thèmes avec une couleur claire fixe */
.hover-bg:hover {
  background-color: var(--ds-surface-hover) !important;
  color: var(--ds-text) !important;
}

/* Champ de recherche de la barre de navigation */
#searchBox {
  background-color: var(--ds-surface-sunken) !important;
  color: var(--ds-text);
  border: 1px solid var(--ds-border);
  border-radius: var(--ds-radius-pill);
}

/* Cartes d'authentification (connexion, récupération, inscription) */
.form-security {
  background-color: var(--ds-surface) !important;
  color: var(--ds-text);
  border: 1px solid var(--ds-border);
}

/* Bandeaux éphémères et notifications de bas de page */
.toast-flash {
  background: var(--ds-surface-raised) !important;
  color: var(--ds-text) !important;
  border: 1px solid var(--ds-border);
  box-shadow: var(--ds-shadow-lg);
}

.alert-temporary {
  color: var(--ds-text) !important;
}
/* --- Notifications ------------------------------------------------------
   Les thèmes posaient chaque bandeau en `position: fixed; right: 0` sans
   `top` : la boîte se calait à sa position naturelle, c'est-à-dire sous la
   barre supérieure, dont le fond translucide recouvrait le début du message.
   Deux notifications simultanées se superposaient au pixel près, et rien ne
   les faisait disparaître : elles finissaient par masquer les commandes
   situées en haut à droite. La pile prend désormais le positionnement à sa
   charge, le bandeau redevient un bloc ordinaire à l'intérieur. */
.flash-stack {
  position: fixed;
  top: calc(var(--ds-topbar-h, 3.5rem) + var(--ds-space-3));
  right: var(--ds-space-3);
  z-index: 1040; /* au-dessus de la barre supérieure (1030) */
  display: flex;
  flex-direction: column;
  gap: var(--ds-space-2);
  width: min(26rem, calc(100vw - 2 * var(--ds-space-3)));
  /* La page reste cliquable entre les bandeaux. */
  pointer-events: none;
}

/* Le bandeau lui-même redevient un bloc ordinaire : c'est la pile qui le
   place. Les quatre thèmes le fixaient chacun de leur côté. */
.alert-temporary {
  position: static !important;
  right: auto !important;
  margin: 0 !important;
  max-width: none !important;
  width: 100%;
  display: flex !important;
  align-items: flex-start !important;
  gap: var(--ds-space-3);
  padding: var(--ds-space-3) var(--ds-space-4) !important;
}

.flash-stack > .alert-temporary {
  pointer-events: auto;
}

.alert-temporary .flash-message {
  flex: 1 1 auto;
  min-width: 0;
  /* Un lien ou un identifiant sans espace ne doit pas élargir la boîte. */
  overflow-wrap: anywhere;
}

.alert-temporary .flash-icon {
  flex: 0 0 auto;
  margin-top: 0.15em;
}

.alert-temporary .flash-close {
  flex: 0 0 auto;
  padding: 0 0 0 var(--ds-space-2);
  background: none;
  border: 0;
  color: inherit;
  opacity: 0.75;
  cursor: pointer;
}

.alert-temporary .flash-close:hover {
  opacity: 1;
}

/* Disparition automatique : la classe est posée par js/app.js. */
.alert-temporary.flash-leaving {
  opacity: 0;
  transform: translateX(0.75rem);
  transition: opacity 0.3s ease, transform 0.3s ease;
}

@media (prefers-reduced-motion: reduce) {
  .alert-temporary.flash-leaving {
    transition: none;
  }
}


/* --- Visite guidée ------------------------------------------------------
   Les thèmes ciblaient `.tourguide-dialog *`, appliquant à CHAQUE descendant
   une bordure de 3 px et une ombre portée décalée : la boîte se retrouvait
   striée de cadres et de barres colorées, jusque sur la barre de progression
   et les boutons. On remet la décoration sur la boîte seule, et on neutralise
   ce qui a été posé sur les enfants. */
.tourguide-dialog {
  background-color: var(--ds-surface-raised) !important;
  color: var(--ds-text) !important;
  border: 1px solid var(--ds-border-strong) !important;
  border-radius: var(--ds-radius-lg) !important;
  box-shadow: var(--ds-shadow-xl) !important;
  padding: var(--ds-space-2);
}

.tourguide-dialog * {
  background-color: transparent !important;
  color: inherit !important;
  border: 0 !important;
  box-shadow: none !important;
  border-radius: var(--ds-radius-sm) !important;
}

/* On rétablit ensuite ce qui doit rester visible */
.tourguide-dialog button,
.tourguide-dialog .tg-dialog-btn {
  background-color: var(--ds-brand-600) !important;
  color: #fff !important;
  border: 0 !important;
  padding: 0.45rem 1rem;
  font-weight: 600;
}

.tourguide-dialog button:hover,
.tourguide-dialog .tg-dialog-btn:hover {
  background-color: var(--ds-brand-700) !important;
}

#tg-dialog-progbar {
  background-color: var(--ds-brand-500) !important;
  border: 0 !important;
  height: 4px !important;
  border-radius: var(--ds-radius-pill) !important;
}

#tg-dialog-close-btn,
#tg-dialog-spinner {
  background-color: transparent !important;
  fill: var(--ds-text-muted) !important;
}

.tourguide-dialog #tg-dialog-title {
  font-family: var(--ds-font-heading);
  font-weight: 700;
  font-size: 1.05rem;
}

.tourguide-backdrop {
  background-color: color-mix(in oklab, var(--ds-neutral-950) 72%, transparent) !important;
}

/* La neutralisation ci-dessus (`.tourguide-dialog *`) emportait aussi trois
   éléments qui ont besoin d'un fond ou d'une ombre pour exister. */

/* La flèche qui relie la boîte à l'élément mis en avant : sans fond, elle
   disparaissait et la boîte semblait flotter sans rapport avec la cible. */
.tourguide-dialog #tg-arrow {
  background-color: var(--ds-surface-raised) !important;
  border: 1px solid var(--ds-border-strong) !important;
}

/* Rail de la barre de progression : sans lui, on ne voit que la portion
   parcourue, sans repère de ce qu'il reste. */
.tourguide-dialog .tg-dialog-progress-bar {
  background-color: var(--ds-surface-sunken) !important;
}

/* « Précédent » et « Suivant » recevaient exactement le même aplat : l'action
   principale ne se distinguait plus de l'action de repli. */
.tourguide-dialog #tg-dialog-prev-btn {
  background-color: transparent !important;
  color: var(--ds-text-muted) !important;
  border: 1px solid var(--ds-border-strong) !important;
}

.tourguide-dialog #tg-dialog-prev-btn:hover {
  background-color: var(--ds-surface-sunken) !important;
  color: var(--ds-text) !important;
}

/* L'anneau de focus était supprimé avec les autres ombres : la visite se
   parcourt aussi au clavier. */
.tourguide-dialog button:focus-visible,
.tourguide-dialog #tg-dialog-close-btn:focus-visible {
  outline: 2px solid var(--ds-brand-500) !important;
  outline-offset: 2px;
}

/* Assistant conversationnel : la bulle reçue gardait un fond clair figé
   (#f0f2f5) avec un texte sombre, au milieu d'une fenêtre passée en sombre. */
#chatbot .chat-message-received {
  background-color: var(--ds-surface-sunken) !important;
  color: var(--ds-text) !important;
}

#chatbot.main-card,
#chatbot .chat-area {
  background-color: var(--ds-surface) !important;
  color: var(--ds-text);
}

.feedback-button:hover {
  background-color: var(--ds-surface-hover) !important;
  color: var(--ds-text) !important;
}

/* Champs désactivés : chaque thème y posait une couleur opaque différente
   (noir, #555, #000, #e0e0dc) qui masquait la valeur saisie. */
form input:not([type='submit']):disabled,
form select:disabled,
textarea:disabled,
.form-control:disabled,
.form-select:disabled {
  background-color: var(--ds-surface-sunken) !important;
  color: var(--ds-text-subtle) !important;
  opacity: 1;
  cursor: not-allowed;
}

/* --- Panneau de notifications -------------------------------------------
   Le panneau était figé à 340 px (débordement sous 360 px de large) et sa
   hauteur maximale rognait les listes longues sans permettre de les faire
   défiler : les notifications au-delà de la cinquième étaient inatteignables. */

.notif-panel {
  width: min(22rem, calc(100vw - 1.5rem));
}

.notif-scroll {
  max-height: min(24rem, 60vh);
  overflow-y: auto;
  overscroll-behavior: contain;
}

.notification-list-item + .notification-list-item {
  border-top: 1px solid var(--ds-border);
}

.notification-link {
  transition: background-color var(--ds-duration-fast) var(--ds-ease);
}

.notification-link:hover,
.notification-link:focus-visible {
  background-color: var(--ds-surface-hover);
}

.notification-list-item .message {
  font-size: 0.85rem;
  line-height: 1.45;
  color: var(--ds-text);
}

.notification-list-item .item-footer {
  font-size: 0.72rem;
  color: var(--ds-text-subtle);
}

.notification-list-item .from {
  font-weight: 600;
  color: var(--ds-brand-600);
}

[data-theme='dark'] .notification-list-item .from { color: var(--ds-brand-300); }

/* Compteur sur la cloche */
.notif-count {
  font-size: 0.62rem;
  font-weight: 700;
  padding: 0.15rem 0.35rem;
  min-width: 1.15rem;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  border: 2px solid var(--ds-surface);
}

/* Onglets du panneau : plus compacts que les onglets par défaut */
.notif-panel .nav-tabs .nav-link {
  padding-block: 0.5rem;
  font-size: 0.7rem;
}

.notif-panel .nav-tabs .nav-link i { font-size: 0.95rem; }

/* --- Fils d'Ariane ------------------------------------------------------- */

.breadcrumb { font-size: var(--ds-text-sm); }
.breadcrumb-item + .breadcrumb-item::before { color: var(--ds-text-subtle); }
.breadcrumb-item.active { color: var(--ds-text-muted); }

/* --- Barres de progression ----------------------------------------------- */

.progress {
  background-color: var(--ds-surface-sunken);
  border-radius: var(--ds-radius-pill);
  height: 0.5rem;
  overflow: hidden;
}

.progress-bar {
  background-color: var(--ds-brand-500);
  transition: width var(--ds-duration-slow) var(--ds-ease-out);
}

/* --- Accordéons ---------------------------------------------------------- */

.accordion {
  --bs-accordion-bg: var(--ds-surface);
  --bs-accordion-color: var(--ds-text);
  --bs-accordion-border-color: var(--ds-border);
  --bs-accordion-btn-color: var(--ds-text);
  --bs-accordion-btn-bg: var(--ds-surface);
  --bs-accordion-active-bg: color-mix(in oklab, var(--ds-brand) 8%, transparent);
  --bs-accordion-active-color: var(--ds-brand-600);
  --bs-accordion-border-radius: var(--ds-radius-md);
}

.accordion-button { font-weight: 600; font-family: var(--ds-font-heading); }
.accordion-button:not(.collapsed) { box-shadow: none; }

/* --- Info-bulles et popovers --------------------------------------------- */

.tooltip-inner {
  background-color: var(--ds-neutral-900);
  border-radius: var(--ds-radius-xs);
  padding: var(--ds-space-2) var(--ds-space-3);
  font-size: var(--ds-text-xs);
  box-shadow: var(--ds-shadow-md);
}

.popover {
  border: 1px solid var(--ds-border);
  border-radius: var(--ds-radius-md);
  box-shadow: var(--ds-shadow-lg);
  background-color: var(--ds-surface-raised);
}

/* --- Surfaces héritées ---------------------------------------------------
   Classes utilitaires définies par le thème historique, réalignées sur les
   jetons pour rester cohérentes avec le reste. */

.bg-v1-primary { background-color: var(--ds-surface) !important; }
.bg-body { background-color: var(--ds-surface) !important; }
.bg-body-tertiary { background-color: var(--ds-surface-sunken) !important; }
.border-translucent { border-color: var(--ds-border) !important; }

.fake-link { cursor: pointer; border-radius: var(--ds-radius-md); }
.fake-link:hover { background-color: var(--ds-surface-hover) !important; }

blockquote {
  border-left: 3px solid var(--ds-brand-400);
  background-color: var(--ds-surface-sunken) !important;
  border-radius: 0 var(--ds-radius-md) var(--ds-radius-md) 0;
  padding: var(--ds-space-4) var(--ds-space-5);
  color: var(--ds-text-muted);
  font-style: italic;
}

/* --- Effet squelette ----------------------------------------------------- */

.shimmer {
  background: linear-gradient(
    90deg,
    var(--ds-surface-sunken) 25%,
    var(--ds-surface-hover) 50%,
    var(--ds-surface-sunken) 75%
  );
  background-size: 400% 100%;
  border-radius: var(--ds-radius-sm);
}

/* =========================================================================
   UTILITAIRES DU SYSTÈME
   ========================================================================= */

/* Dégradé de marque, pour les titres d'accroche */
.ds-gradient-text {
  background: linear-gradient(135deg, var(--ds-brand-500), var(--ds-accent));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  /* Repli si background-clip:text n'est pas supporté */
  -webkit-text-fill-color: transparent;
}

/* Surface vitrée */
.ds-glass {
  background-color: color-mix(in oklab, var(--ds-surface) 70%, transparent);
  border: 1px solid var(--ds-border);
  border-radius: var(--ds-radius-lg);
}

@supports (backdrop-filter: blur(1px)) {
  .ds-glass {
    backdrop-filter: saturate(160%) blur(16px);
    -webkit-backdrop-filter: saturate(160%) blur(16px);
  }
}

/* Halo décoratif d'arrière-plan (pages d'accueil, connexion) */
.ds-aurora {
  position: relative;
  isolation: isolate;
}

.ds-aurora::before {
  content: '';
  position: absolute;
  inset: -20% -10% auto -10%;
  height: 60vh;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(50% 50% at 20% 20%, color-mix(in oklab, var(--ds-brand) 22%, transparent), transparent 70%),
    radial-gradient(45% 45% at 80% 10%, color-mix(in oklab, var(--ds-accent) 20%, transparent), transparent 70%);
  filter: blur(40px);
}

.ds-elevation-sm { box-shadow: var(--ds-shadow-sm); }
.ds-elevation-md { box-shadow: var(--ds-shadow-md); }
.ds-elevation-lg { box-shadow: var(--ds-shadow-lg); }

.ds-stack > * + * { margin-top: var(--ds-space-4); }

/* =========================================================================
   6. MOUVEMENT
   ========================================================================= */

/* Apparition douce à l'arrivée sur la page */
@keyframes ds-fade-up {
  from { opacity: 0; transform: translateY(12px); }
  to   { opacity: 1; transform: none; }
}

.ds-animate-in {
  animation: ds-fade-up var(--ds-duration-slow) var(--ds-ease-out) both;
}

/* -------------------------------------------------------------------------
   Respect de prefers-reduced-motion.
   Obligatoire : les animations de déplacement peuvent déclencher nausées et
   migraines chez les personnes sensibles au mouvement (WCAG 2.3.3).
   ------------------------------------------------------------------------- */

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

  .btn:hover,
  a > .card:hover,
  .card-hoverable:hover {
    transform: none;
  }
}

/* =========================================================================
   IMPRESSION
   -------------------------------------------------------------------------
   La plateforme génère des attestations et conventions : les pages doivent
   rester propres à l'impression.
   ========================================================================= */

@media print {
  .navbar,
  .ds-skip-link,
  footer,
  .no-print {
    display: none !important;
  }

  body {
    background: #fff !important;
    color: #000 !important;
  }

  .card {
    box-shadow: none !important;
    border: 1px solid #ccc !important;
    break-inside: avoid;
  }

  a[href^='http']::after {
    content: ' (' attr(href) ')';
    font-size: 0.8em;
    color: #555;
  }
}
