/* =========================================================================
   SWISS LINGUA - DESIGN SYSTEM v1
   Feuille de style partagée. Tous les cockpits l'importent :
       <link rel="stylesheet" href="design-system.css">
   Source unique de vérité visuelle (voir ../tokens.md).
   Premium · suisse · avant-gardiste. Un seul design system, cohérence totale.
   ========================================================================= */

/* -------------------------------------------------------------------------
   Polices
   - Inter (UI, corps, champs) via Google Fonts.
   - Bembo (serif éditorial) en local. ⚠️ Regular SEULEMENT : le navigateur
     synthétise gras/italique en proto. Prod = Bembo complète (Monotype) OU
     substitut open (ET Book / EB Garamond). Voir ../tokens.md.
   ------------------------------------------------------------------------- */
@import url("https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap");

@font-face {
  font-family: "Bembo";
  /* Servie depuis public/fonts de CHAQUE cockpit. Le chemin precedent
     (../fonts/bembo-src/) ne pointait sur rien : aucune app n'a de dossier
     fonts a la racine, la requete tombait en 404 et tous les titres, tous les
     chiffres passaient au serif generique du systeme. Verifie au navigateur :
     document.fonts.check('16px Bembo') renvoyait false dans les 4 cockpits. */
  src: url("/fonts/bembo-regular.woff2") format("woff2"), url("/fonts/bembo-regular.woff")
    format("woff");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

/* =========================================================================
   TOKENS (variables CSS) - repris de ../tokens.md
   ========================================================================= */
:root {
  /* ── Couleurs de marque ─────────────────────────────────────────────── */
  --ink: #14140f; /* Texte principal                            */
  --navy: #2a317d; /* Primaire : titres, boutons, liens, nav     */
  --navy-700: #222a6e; /* Marine au survol                           */
  --coral: #e84647; /* Accent fort : CTA, emphase, badge live     */
  --coral-700: #c73132; /* Corail au survol                           */
  --coral-800: #ab2829; /* Corail au survol d'un bouton plein         */
  --salmon: #f6bcb3; /* Accent doux, tints                         */
  --salmon-soft: #fceae5; /* Tint corail très léger                     */
  --ivory: #fff7ee; /* Surface chaude principale (fond de page)   */
  --greige: #f0ede6; /* Surface secondaire                         */
  --surface: #ffffff; /* Cartes                                     */
  --on-dark: #ffffff; /* Texte/éléments sur fond foncé (navy, corail)*/
  /* Muet assombri pour viser AA texte normal sur les DEUX surfaces :
     ≈ 4.7:1 sur blanc, ≈ 4.4:1 sur ivoire (vs 4.2/3.9 avant). WCAG 2.2 AA. */
  --muted: #5c5c56; /* Texte secondaire                           */
  --line: #e7e2d8; /* Bordures, séparateurs                      */
  --line-strong: #d8d2c5; /* Bordures appuyées                          */
  /* Bordure des CHAMPS de saisie : sur une carte blanche, elle est le seul
     indice qui délimite le contrôle, donc WCAG 2.2 AA (1.4.11) exige 3:1.
     #8f8878 mesure 3.52:1 sur blanc, 3.32:1 sur ivoire, 3.01:1 sur greige.
     Les bordures décoratives (cartes, séparateurs) gardent la teinte douce. */
  --field-border: #8f8878; /* Bordure de champ, contraste AA             */

  /* ── États ──────────────────────────────────────────────────────────── */
  /* Teintes de TEXTE assombries pour viser ≥ 4.5:1 sur leur fond -soft
     (petit texte 12px des badges). Voir revue contraste WCAG 2.2 AA. */
  --success: #27684c;
  --success-soft: #e3f1ea; /* 5.5:1 sur soft */
  --warning: #8a5a12;
  --warning-soft: #fbefd9; /* 5.6:1 sur soft */
  --danger: #c73132;
  --danger-soft: #fceae5;
  --info: #2a317d;
  --info-soft: #e8e9f3;

  /* ── Typographie ────────────────────────────────────────────────────── */
  --font-serif: "Bembo", "ET Book", "EB Garamond", Georgia, serif;
  --font-sans: "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-mono: ui-monospace, "SF Mono", "JetBrains Mono", monospace;

  --text-display: 3.5rem;
  --text-h1: 2.5rem;
  --text-h2: 1.875rem;
  --text-h3: 1.375rem;
  --text-h4: 1.125rem;
  --text-lead: 1.25rem;
  --text-body: 1rem;
  --text-sm: 0.875rem;
  --text-xs: 0.75rem;
  --text-2xs: 0.6875rem; /* 11px : libellés ultra-denses (scale CECRL, tabbar) */
  --text-stat: 1.75rem; /* KPI compact (cartes résumé), entre h3 et kpi */
  /* Valeur d'indicateur. Descendue de 2.25rem a 1.875rem apres retour de
     Patrick : a 36px, un chiffre a cinq caracteres ecrasait sa tuile et le
     tableau de bord ressemblait a une vitrine de chiffres. La graisse de la
     serif suffit a porter la hierarchie. */
  --text-kpi: 1.875rem;

  --tracking-tight: -0.02em;
  --tracking-normal: 0;
  --tracking-wide: 0.08em;

  /* ── Espace (4 / 8 pt) ──────────────────────────────────────────────── */
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.5rem;
  --space-6: 2rem;
  --space-7: 3rem;
  --space-8: 4rem;
  --space-9: 6rem;
  --space-10: 8rem;

  /* ── Rayons ─────────────────────────────────────────────────────────── */
  --radius-sm: 0.375rem;
  --radius-md: 0.625rem;
  --radius-lg: 1rem;
  --radius-xl: 1.5rem;
  --radius-pill: 999px;

  /* ── Ombres (chaudes, teintées encre) ───────────────────────────────── */
  --shadow-xs: 0 1px 2px rgba(20, 20, 15, 0.04);
  --shadow-sm: 0 2px 8px rgba(20, 20, 15, 0.06);
  --shadow-md: 0 8px 24px rgba(20, 20, 15, 0.08);
  --shadow-lg: 0 16px 48px rgba(20, 20, 15, 0.12);
  --shadow-focus: 0 0 0 3px rgba(42, 49, 125, 0.35);

  /* ── Mouvement ──────────────────────────────────────────────────────── */
  --dur-fast: 120ms;
  --dur-base: 240ms;
  --dur-slow: 480ms;
  --dur-counter: 1200ms;
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
  --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);

  /* ── Layout ─────────────────────────────────────────────────────────── */
  --container: 1200px;
  --sidebar-w: 264px;
  --topbar-h: 64px;
}

/* =========================================================================
   RESET LÉGER
   ========================================================================= */
*,
*::before,
*::after {
  box-sizing: border-box;
}
* {
  margin: 0;
}

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

body {
  font-family: var(--font-sans);
  font-size: var(--text-body);
  line-height: 1.6;
  color: var(--ink);
  background: var(--ivory); /* surface chaude principale */
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

img,
svg,
video,
canvas {
  display: block;
  max-width: 100%;
}
button,
input,
select,
textarea {
  font: inherit;
  color: inherit;
}
ul,
ol {
  list-style: none;
  padding: 0;
}
a {
  color: var(--navy);
  text-decoration: none;
  transition: color var(--dur-fast) var(--ease-out);
}
a:hover {
  color: var(--navy-700);
}
a:focus-visible {
  outline: none;
  box-shadow: var(--shadow-focus);
  border-radius: var(--radius-sm);
}

/* =========================================================================
   TYPOGRAPHIE DE BASE
   Titres en Bembo (chaleur éditoriale), corps en Inter.
   ========================================================================= */
h1,
h2,
h3,
h4 {
  font-family: var(--font-serif);
  color: var(--navy);
  font-weight: 400; /* Bembo Regular ; le gras est synthétisé */
  line-height: 1.15;
  letter-spacing: var(--tracking-tight);
}
h1 {
  font-size: var(--text-h1);
  line-height: 1.1;
}
h2 {
  font-size: var(--text-h2);
}
h3 {
  font-size: var(--text-h3);
  line-height: 1.25;
}
h4 {
  font-size: var(--text-h4);
  line-height: 1.3;
}

p {
  max-width: 68ch;
}

small,
.text-xs {
  font-size: var(--text-xs);
}
.text-sm {
  font-size: var(--text-sm);
}
.lead {
  font-size: var(--text-lead);
  color: var(--ink);
  line-height: 1.5;
}
.muted {
  color: var(--muted);
}

/* Titre d'affichage vitrine : Inter Bold majuscules (style hero marque) */
.display {
  font-family: var(--font-sans);
  font-weight: 700;
  font-size: var(--text-display);
  line-height: 1.05;
  letter-spacing: var(--tracking-tight);
  text-transform: uppercase;
  color: var(--navy);
}

/* Sur-titre / label de section.
   Corail pur en petit texte échoue l'AA (3.67:1 sur ivoire) : on prend le
   marine (10.8:1). Le corail reste pour les gros titres, icônes et fonds
   pleins (brief). Variante .eyebrow--coral disponible si fond plein. */
/* Micro-titre en capitales espacees. Deux emplois, un seul rendu :
   - en <p>, c'est un SUR-TITRE, pose au-dessus du titre reel ;
   - en <h3>/<h4>, c'est le TITRE d'une sous-section, quand le dessin ne veut
     pas d'un titre de carte plein.
   La balise porte le role, la classe porte l'apparence : ne jamais choisir la
   balise pour son look. */
.eyebrow {
  font-family: var(--font-sans);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--navy);
}

/* Variante corail réservée aux fonds pleins sombres (jamais sur clair). */
.eyebrow--coral {
  color: var(--coral);
}

/* Sur-titre sur fond foncé : saumon clair (≈ 7:1 sur navy), lisible et chaud. */
.eyebrow--on-dark {
  color: var(--salmon);
}

/* Mot d'emphase au fil du texte : Bembo corail, DROIT (pas d'italique).
   L'accent se fait par la couleur, pas par l'italique.
   ⚠️ Sur fond clair uniquement. Sur fond foncé, utiliser .emphasis--on-dark. */
.emphasis {
  font-family: var(--font-serif);
  color: var(--coral);
}
/* Variante italique : réservée aux NOMS et VALEURS DYNAMIQUES (langue d'un
   apprenant, nom de personne, ville…). Ne pas utiliser pour de l'emphase
   purement stylistique. NB : Bembo Regular seul → italique synthétisé en proto. */
.emphasis--dynamic {
  font-style: italic;
}
/* Emphase sur fond foncé : corail pur sur navy ≈ 2:1 (illisible). On passe
   au saumon clair (≈ 7:1 sur navy), cohérent avec .eyebrow--on-dark. */
.emphasis--on-dark {
  color: var(--salmon);
}

/* Utilitaire texte corail foncé (AA sur fond clair, ≈ 5.3:1 sur blanc) */
.text-coral-700 {
  color: var(--coral-700);
}

/* Utilitaire texte vert (AA sur fond clair, ≈ 6.4:1 sur blanc). Pendant de
   .text-coral-700 pour les variations positives : la couleur ACCOMPAGNE le
   signe, elle ne le remplace jamais. */
.text-success {
  color: var(--success);
}

/* Séparateur horizontal doux (remplace les <hr> inline) */
.divider {
  border: 0;
  border-top: 1px solid var(--line);
  margin: var(--space-5) 0;
}

/* =========================================================================
   CARTE
   ========================================================================= */
.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: var(--space-6);
  box-shadow: var(--shadow-sm);
  transition: box-shadow var(--dur-base) var(--ease-out), transform var(--dur-base) var(--ease-out);
}
.card--hover:hover {
  box-shadow: var(--shadow-md);
  transform: translateY(-2px);
}
.card__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  margin-bottom: var(--space-5);
}
.card__title {
  font-size: var(--text-h3);
  margin: 0;
}

/* =========================================================================
   KPI - label + grand chiffre Bembo
   ========================================================================= */
.kpi {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  min-width: 0;
  /* Contexte de dimensionnement pour le chiffre (voir .kpi__value). */
  container-type: inline-size;
}
.kpi__label {
  font-family: var(--font-sans);
  /* Remonté de --text-xs : en capitales et en gris, 12px était le maillon
     faible de la tuile, le libellé se lisait moins bien que le chiffre. */
  font-size: var(--text-sm);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--muted);
  text-wrap: balance;
}
.kpi__value {
  font-family: var(--font-serif);
  /* Le chiffre se cale sur la largeur DE SA TUILE (cqi), pas sur la fenêtre :
     dans une grid--4 une valeur longue se réduit au lieu de casser sur trois
     lignes. Le plafond reste --text-kpi, le plancher garde la valeur lisible.
     Repli --text-stat pour les navigateurs sans requêtes de conteneur. */
  font-size: var(--text-stat);
  font-size: clamp(1.625rem, 12cqi, var(--text-kpi));
  line-height: 1.1;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
  min-width: 0;
  /* Plus de break-word : un nombre ne doit jamais se couper au milieu. Les
     séparateurs produits par shared/format.ts sont insécables, donc un montant
     reste d'un bloc ; seule une VALEUR TEXTUELLE (« Aucun score ») peut encore
     passer à la ligne, entre deux mots. */
  overflow-wrap: normal;
}
.kpi__value--navy {
  color: var(--navy);
}
.kpi__unit {
  font-size: 0.5em;
  color: var(--muted);
  margin-left: var(--space-1);
}
.kpi__delta {
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  font-weight: 600;
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
}
.kpi__delta--up {
  color: var(--success);
}
.kpi__delta--down {
  color: var(--danger);
}

/* Badge de fraîcheur neutre (« Synchronisé », « Mis à jour il y a 16 s ») */
.badge-fresh {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-xs);
  font-weight: 500;
  color: var(--muted);
}
.badge-fresh::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: var(--radius-pill);
  background: var(--success);
}

/* =========================================================================
   BADGE DE STATUT
   ========================================================================= */
.badge {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.01em;
  padding: var(--space-1) var(--space-3);
  border-radius: var(--radius-pill);
  white-space: nowrap;
  background: var(--greige);
  color: var(--ink);
}
.badge--success {
  background: var(--success-soft);
  color: var(--success);
}
.badge--warning {
  background: var(--warning-soft);
  color: var(--warning);
}
.badge--danger {
  background: var(--danger-soft);
  color: var(--danger);
}
.badge--info {
  background: var(--info-soft);
  color: var(--info);
}
.badge--navy {
  background: var(--navy);
  color: var(--on-dark);
}
/* Corail plein : fond coral-700 (#C73132) + texte blanc gras → ~5.0:1 (AA).
   Le coral pur #E84647 en fond de badge échoue (3.89:1 avec blanc, 12px). */
.badge--coral {
  background: var(--coral-700);
  color: var(--on-dark);
  font-weight: 700;
}

/* =========================================================================
   BOUTONS
   ========================================================================= */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  font-weight: 600;
  line-height: 1;
  padding: var(--space-3) var(--space-5);
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  cursor: pointer;
  white-space: nowrap; /* un bouton ne casse jamais son libellé */
  transition:
    background var(--dur-fast) var(--ease-out),
    border-color var(--dur-fast) var(--ease-out),
    color var(--dur-fast) var(--ease-out),
    transform var(--dur-fast) var(--ease-out),
    box-shadow var(--dur-fast) var(--ease-out);
  user-select: none;
}
.btn:active {
  transform: translateY(1px);
}
.btn:focus-visible {
  outline: none;
  box-shadow: var(--shadow-focus);
}
.btn:disabled,
.btn[aria-disabled="true"] {
  opacity: 0.5;
  cursor: not-allowed;
  pointer-events: none;
}

/* Primaire marine plein */
.btn-primary {
  background: var(--navy);
  color: var(--on-dark);
  border-color: var(--navy);
}
.btn-primary:hover {
  background: var(--navy-700);
  border-color: var(--navy-700);
}

/* Accent corail plein. Le corail de marque (--coral) porte du blanc a 3.89:1,
   sous le seuil AA de 4.5:1 pour ce corps de texte : le REMPLISSAGE du bouton
   descend a --coral-700 (5.37:1) et le survol a --coral-800 (6.85:1). Le corail
   vif reste partout ailleurs, ou il ne porte pas de texte (barre d'accent de la
   nav, pastilles, filets). */
.btn-coral {
  background: var(--coral-700);
  color: var(--on-dark);
  border-color: var(--coral-700);
  font-weight: 700;
}
.btn-coral:hover {
  background: var(--coral-800);
  border-color: var(--coral-800);
}

/* Fantôme (contour) */
.btn-ghost {
  background: transparent;
  color: var(--navy);
  border-color: var(--line-strong);
}
.btn-ghost:hover {
  background: var(--greige);
  border-color: var(--navy);
}

/* Discret (lien-bouton) */
.btn-quiet {
  background: transparent;
  color: var(--navy);
  padding-inline: var(--space-3);
}
.btn-quiet:hover {
  background: var(--greige);
}

.btn--sm {
  padding: var(--space-2) var(--space-4);
  font-size: var(--text-xs);
}
.btn--lg {
  padding: var(--space-4) var(--space-7);
  font-size: var(--text-body);
}
.btn--block {
  width: 100%;
}

/* Corail plein en PETITE taille (texte blanc < 14px gras) : on bascule le fond
   sur coral-700 (#C73132). Blanc sur coral-700 ≈ 5.0:1 → AA même en 12px, alors
   que le coral pur (#E84647) échouerait (≈4.0:1). S'applique à .btn-coral.btn--sm. */
.btn-coral.btn--sm {
  background: var(--coral-700);
  border-color: var(--coral-700);
}
.btn-coral.btn--sm:hover {
  background: var(--coral-800);
  border-color: var(--coral-700);
  filter: brightness(0.94);
}

/* =========================================================================
   PROGRESSION (barre animable)
   ========================================================================= */
.progress {
  width: 100%;
  height: 8px;
  background: var(--greige);
  border-radius: var(--radius-pill);
  overflow: hidden;
}
.progress__bar {
  height: 100%;
  /* Largeur pilotée par --value, posé en style inline par le composant.
     Le repli à 0 couvre le cas « pas encore de valeur ». */
  width: var(--value, 0);
  background: var(--navy);
  border-radius: var(--radius-pill);
  transition: width var(--dur-counter) var(--ease-out);
}
.progress__bar--coral {
  background: var(--coral);
}
.progress__bar--salmon {
  background: var(--salmon);
}
.progress__bar--success {
  background: var(--success);
}
.progress__bar--warning {
  background: var(--warning);
}
.progress__bar--critical {
  background: var(--coral-700);
}

/* =========================================================================
   PILL (étiquette douce, ex : langue, niveau CECRL)
   ========================================================================= */
.pill {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-xs);
  font-weight: 600;
  padding: var(--space-1) var(--space-3);
  border-radius: var(--radius-pill);
  background: var(--greige);
  color: var(--ink);
  border: 1px solid var(--line);
}
.pill--navy {
  background: var(--info-soft);
  color: var(--navy);
  border-color: transparent;
}
.pill--salmon {
  background: var(--salmon-soft);
  color: var(--coral-700);
  border-color: transparent;
}

/* =========================================================================
   TABLE (serveur, élégante, lignes aérées)
   ========================================================================= */
.table-wrap {
  width: 100%;
  overflow-x: auto;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--surface);
}
.table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--text-sm);
}
.table thead th {
  text-align: left;
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  font-size: var(--text-xs);
  color: var(--muted);
  background: var(--greige);
  padding: var(--space-3) var(--space-5);
  white-space: nowrap;
}
.table tbody td {
  padding: var(--space-4) var(--space-5);
  border-top: 1px solid var(--line);
  color: var(--ink);
  vertical-align: middle;
}
.table tbody tr {
  transition: background var(--dur-fast) var(--ease-out);
}
.table tbody tr:hover {
  background: var(--ivory);
}
.table--num td,
.table--num th {
  font-variant-numeric: tabular-nums;
}
/* En-tête de colonne triable */
.table th[aria-sort] {
  cursor: pointer;
}
.table th[aria-sort]:hover {
  color: var(--navy);
}

/* =========================================================================
   DÉFILEMENT HORIZONTAL (tableaux larges) - flèches + fondus de bord
   Les flèches n'apparaissent que s'il reste du contenu à faire défiler
   (classes .scrollx--l / .scrollx--r posées par le composant ScrollX).
   ========================================================================= */
.scrollx {
  position: relative;
}
.scrollx__viewport {
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: thin;
}
.scrollx__arrow {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 3;
  width: 36px;
  height: 36px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-pill);
  border: 1px solid var(--line-strong);
  background: var(--surface);
  color: var(--navy);
  cursor: pointer;
  box-shadow: var(--shadow-md);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--dur-fast) var(--ease-out), background var(--dur-fast) var(--ease-out),
    transform var(--dur-fast) var(--ease-out);
}
.scrollx__arrow:hover {
  background: var(--greige);
  border-color: var(--navy);
}
.scrollx__arrow:active {
  transform: translateY(-50%) scale(0.92);
}
.scrollx__arrow:focus-visible {
  outline: none;
  box-shadow: var(--shadow-focus);
}
.scrollx__arrow svg {
  width: 18px;
  height: 18px;
}
.scrollx__arrow--left {
  left: var(--space-3);
}
.scrollx__arrow--right {
  right: var(--space-3);
}
.scrollx--l .scrollx__arrow--left {
  opacity: 1;
  pointer-events: auto;
}
.scrollx--r .scrollx__arrow--right {
  opacity: 1;
  pointer-events: auto;
}
/* Fondus de bord : signalent visuellement le contenu masqué à gauche/droite. */
.scrollx::before,
.scrollx::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  width: 56px;
  z-index: 2;
  pointer-events: none;
  opacity: 0;
  transition: opacity var(--dur-fast) var(--ease-out);
}
.scrollx::before {
  left: 0;
  background: linear-gradient(90deg, var(--surface) 25%, transparent);
}
.scrollx::after {
  right: 0;
  background: linear-gradient(270deg, var(--surface) 25%, transparent);
}
.scrollx--l::before {
  opacity: 1;
}
.scrollx--r::after {
  opacity: 1;
}

/* =========================================================================
   NAVIGATION - SIDEBAR
   ========================================================================= */
/* Sidebar MARINE (couleur primaire de marque) : tranche avec le panneau ivoire,
   rendu bancaire-grade. Collante (reste en vue quand le contenu défile). */
.sidebar {
  width: var(--sidebar-w);
  height: 100vh;
  position: sticky;
  top: 0;
  align-self: start;
  overflow-y: auto;
  overflow-x: hidden;
  background: var(--navy);
  border-right: 1px solid rgba(255, 255, 255, 0.06);
  padding: var(--space-5) var(--space-3);
  display: flex;
  flex-direction: column;
  gap: 2px;
  transition: width var(--dur-base) var(--ease-out);
}
/* Filet lumineux discret en haut (profondeur premium). */
.sidebar::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 1px;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.12), transparent);
}

/* Tête : pastille de marque + libellé + bouton replier. */
.sidebar__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  margin-bottom: var(--space-5);
  padding: 0 var(--space-2);
}
.sidebar__brand {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-width: 0;
  padding: 0;
  font-family: var(--font-serif);
  font-size: var(--text-h4);
  color: var(--on-dark);
}
.sidebar__mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  flex: none;
  border-radius: var(--radius-md);
  background: var(--coral);
  color: var(--on-dark);
  font-family: var(--font-serif);
  font-size: 1.05rem;
  letter-spacing: 0.01em;
  box-shadow: 0 4px 12px rgba(232, 70, 71, 0.35);
}
.sidebar__brand-text {
  color: var(--on-dark);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.sidebar__toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  flex: none;
  border-radius: var(--radius-sm);
  border: 1px solid transparent;
  background: transparent;
  color: rgba(255, 255, 255, 0.6);
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
}
.sidebar__toggle:hover {
  background: rgba(255, 255, 255, 0.1);
  color: var(--on-dark);
}
.sidebar__toggle:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px rgba(246, 188, 179, 0.5);
}
.sidebar__toggle svg {
  width: 18px;
  height: 18px;
}

.sidebar__group-label {
  font-size: var(--text-2xs);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.42);
  padding: var(--space-4) var(--space-3) var(--space-2);
}

/* Item de nav (peut être un <button> : reset propre). */
.nav-item {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-3);
  border: 0;
  border-radius: var(--radius-md);
  background: transparent;
  width: 100%;
  cursor: pointer;
  font-family: inherit;
  text-align: left;
  color: rgba(255, 255, 255, 0.72);
  font-size: var(--text-sm);
  font-weight: 500;
  transition: background var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
}
.nav-item:hover {
  background: rgba(255, 255, 255, 0.07);
  color: var(--on-dark);
}
.nav-item:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px rgba(246, 188, 179, 0.5);
}
.nav-item--active {
  background: rgba(255, 255, 255, 0.1);
  color: var(--on-dark);
  font-weight: 600;
}
.nav-item--active:hover {
  background: rgba(255, 255, 255, 0.13);
}
/* Barre d'accent corail à gauche de l'item actif (signature de marque). */
.nav-item--active::before {
  content: "";
  position: absolute;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
  width: 3px;
  height: 22px;
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  background: var(--coral);
}
.nav-item__icon {
  width: 20px;
  height: 20px;
  flex: none;
  color: rgba(255, 255, 255, 0.55);
  transition: color var(--dur-fast) var(--ease-out);
}
.nav-item:hover .nav-item__icon {
  color: var(--on-dark);
}
.nav-item--active .nav-item__icon {
  color: var(--salmon);
}
.nav-item__label {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* État RÉTRACTÉ : icônes seules. La pastille de marque reste (identité). */
.sidebar--collapsed {
  padding-inline: var(--space-2);
}
.sidebar--collapsed .sidebar__head {
  flex-direction: column;
  gap: var(--space-3);
  margin-bottom: var(--space-4);
  padding: 0;
}
.sidebar--collapsed .sidebar__brand-text,
.sidebar--collapsed .sidebar__group-label,
.sidebar--collapsed .nav-item__label {
  display: none;
}
.sidebar--collapsed .nav-item {
  justify-content: center;
  padding-inline: 0;
}
.sidebar--collapsed .nav-item--active::before {
  display: none;
}

/* La colonne de contenu suit la largeur de la sidebar en douceur. */
.app-shell {
  transition: grid-template-columns var(--dur-base) var(--ease-out);
}

/* =========================================================================
   NAVIGATION - TOPBAR
   ========================================================================= */
.topbar {
  height: var(--topbar-h);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-5);
  padding: 0 var(--space-7);
  background: color-mix(in srgb, var(--ivory) 88%, transparent);
  backdrop-filter: saturate(140%) blur(8px);
  border-bottom: 1px solid var(--line);
  position: sticky;
  top: 0;
  z-index: 20;
}
.topbar__title {
  font-size: var(--text-h4);
  margin: 0;
}
.topbar__actions {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

/* Bouton burger (caché en desktop, affiché sous --bp-nav par les cockpits) */
.topbar__burger {
  display: none;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: var(--radius-md);
  border: 1px solid var(--line-strong);
  background: var(--surface);
  color: var(--navy);
  cursor: pointer;
}
.topbar__burger:hover {
  background: var(--greige);
  border-color: var(--navy);
}
.topbar__burger:focus-visible {
  outline: none;
  box-shadow: var(--shadow-focus);
}

/* =========================================================================
   NAVIGATION MOBILE - DRAWER (partagé, piloté par les cockpits sous 1100px)
   Réutilise les .nav-item. Ouvert via [data-nav-open] sur le drawer.
   ========================================================================= */
.nav-drawer {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: none; /* activé en .is-open */
}
.nav-drawer.is-open {
  display: block;
}
.nav-drawer__scrim {
  position: absolute;
  inset: 0;
  background: rgba(20, 20, 15, 0.45);
  opacity: 0;
  transition: opacity var(--dur-base) var(--ease-out);
}
.nav-drawer.is-open .nav-drawer__scrim {
  opacity: 1;
}
.nav-drawer__panel {
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  width: min(84vw, var(--sidebar-w));
  background: var(--surface);
  border-right: 1px solid var(--line);
  padding: var(--space-5) var(--space-4);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  overflow-y: auto;
  transform: translateX(-100%);
  transition: transform var(--dur-base) var(--ease-out);
  box-shadow: var(--shadow-lg);
}
.nav-drawer.is-open .nav-drawer__panel {
  transform: translateX(0);
}
.nav-drawer__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: var(--space-3);
}
.nav-drawer__close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: var(--radius-md);
  border: 1px solid var(--line-strong);
  background: var(--surface);
  color: var(--navy);
  cursor: pointer;
}
.nav-drawer__close:hover {
  background: var(--greige);
}
.nav-drawer__close:focus-visible {
  outline: none;
  box-shadow: var(--shadow-focus);
}
@media (prefers-reduced-motion: reduce) {
  .nav-drawer__scrim,
  .nav-drawer__panel {
    transition: none;
  }
}

/* =========================================================================
   AVATAR
   ========================================================================= */
.avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: var(--radius-pill);
  background: var(--navy);
  color: var(--on-dark);
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  font-weight: 600;
  flex: none;
  overflow: hidden;
}
.avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.avatar--sm {
  width: 28px;
  height: 28px;
  font-size: var(--text-xs);
}
.avatar--lg {
  width: 56px;
  height: 56px;
  font-size: var(--text-h4);
}
.avatar--coral {
  background: var(--coral);
}

/* =========================================================================
   BOUTON-ICÔNE (cible tactile 44px, ex : cloche de notifications)
   ========================================================================= */
.icon-btn {
  width: 44px;
  height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-md);
  border: 1px solid var(--line-strong);
  background: var(--surface);
  color: var(--muted);
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease-out), border-color var(--dur-fast)
    var(--ease-out), color var(--dur-fast) var(--ease-out), transform var(--dur-fast)
    var(--ease-out);
}
.icon-btn svg {
  width: 22px;
  height: 22px;
}
.icon-btn:hover {
  border-color: var(--navy);
  color: var(--navy);
}
.icon-btn:active {
  transform: scale(0.94);
}
.icon-btn:focus-visible {
  outline: none;
  box-shadow: var(--shadow-focus);
}

/* =========================================================================
   CHIP DE FILTRE
   ========================================================================= */
.chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-sm);
  font-weight: 500;
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius-pill);
  background: var(--surface);
  border: 1px solid var(--line-strong);
  color: var(--ink);
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease-out), border-color var(--dur-fast)
    var(--ease-out), color var(--dur-fast) var(--ease-out);
}
.chip:hover {
  border-color: var(--navy);
}
.chip:focus-visible {
  outline: none;
  box-shadow: var(--shadow-focus);
}
.chip--active {
  background: var(--navy);
  border-color: var(--navy);
  color: var(--on-dark);
}
.chip__close {
  font-size: 1em;
  line-height: 1;
  opacity: 0.7;
}
.chip__close:hover {
  opacity: 1;
}

/* =========================================================================
   CHAMPS DE SAISIE (toujours Inter, jamais de serif)
   ========================================================================= */
.field {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}
.label {
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--ink);
}
.input,
.select,
.textarea {
  font-family: var(--font-sans);
  font-size: var(--text-body);
  line-height: 1.4;
  color: var(--ink);
  background-color: var(--surface);
  border: 1px solid var(--field-border);
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-4);
  width: 100%;
  appearance: none; /* tue le rendu natif (flèche système, ombrages OS) */
  -webkit-appearance: none;
  transition: border-color var(--dur-fast) var(--ease-out), box-shadow var(--dur-fast)
    var(--ease-out), background-color var(--dur-fast) var(--ease-out);
}
.input::placeholder,
.textarea::placeholder {
  color: var(--muted);
}

/* Survol : la bordure se renforce discrètement (retour d'interactivité). */
.input:hover:not(:disabled):not(:focus),
.select:hover:not(:disabled):not(:focus),
.textarea:hover:not(:disabled):not(:focus) {
  border-color: var(--muted);
}

/* Focus : bordure marine + halo DOUX (pas le halo dur des boutons). */
.input:focus,
.select:focus,
.textarea:focus {
  outline: none;
  border-color: var(--navy);
  box-shadow: 0 0 0 3px rgba(42, 49, 125, 0.14);
}
.input:disabled,
.select:disabled,
.textarea:disabled {
  background-color: var(--greige);
  color: var(--muted);
  cursor: not-allowed;
}
.textarea {
  min-height: 120px;
  resize: vertical;
}

/* Menu déroulant : chevron maison (marine muet), plus la flèche système. Le
   fond reste blanc ; on ne pose QUE l'image de chevron par-dessus. */
.select {
  cursor: pointer;
  padding-right: calc(var(--space-4) + 1.25rem);
  background-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='16'%20height='16'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='%235C5C56'%20stroke-width='2'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='m6%209%206%206%206-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right var(--space-3) center;
  background-size: 1rem;
}
/* Chevron marine au focus/survol (petit soin d'état). */
.select:hover:not(:disabled),
.select:focus {
  background-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='16'%20height='16'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='%232A317D'%20stroke-width='2'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='m6%209%206%206%206-6'/%3E%3C/svg%3E");
}

/* Contrôles compacts pour barres d'action inline (formulaires d'ajout d'un
   profil, d'un enfant, d'une inscription…). Largeur auto : ils s'alignent aux
   boutons dans une .row au lieu de s'étirer à 100 %. */
.input--sm,
.select--sm {
  width: auto;
  padding: var(--space-2) var(--space-3);
  font-size: var(--text-sm);
}
.select--sm {
  padding-right: calc(var(--space-3) + 1.15rem);
  background-position: right var(--space-2) center;
  background-size: 0.9rem;
}

/* Barre de formulaire inline : champs + action alignés, aérés, retour ligne
   propre sur mobile. Remplace les style= flex répétés dans les cockpits. */
.form-inline {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex-wrap: wrap;
}
/* Chaque contrôle garde sa taille naturelle et passe à la ligne en bloc,
   plutôt que d'être écrasé (bouton dont le libellé se coupe sur 2 lignes). */
.form-inline > * {
  flex: 0 0 auto;
}
/* Champs et boutons d'une même barre à la MÊME hauteur (alignement propre). */
.form-inline > .btn,
.form-inline > .input,
.form-inline > .select {
  min-height: 2.375rem;
}

/* =========================================================================
   ALERTE (info / succès / avertissement / danger)
   ========================================================================= */
.alert {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-5);
  border-radius: var(--radius-md);
  border: 1px solid transparent;
  font-size: var(--text-sm);
  color: var(--ink);
}
.alert__icon {
  flex: none;
  width: 20px;
  height: 20px;
  margin-top: 1px;
}
.alert__title {
  font-weight: 600;
  margin-bottom: var(--space-1);
}
.alert--info {
  background: var(--info-soft);
  border-color: color-mix(in srgb, var(--navy) 20%, transparent);
}
.alert--info .alert__icon {
  color: var(--navy);
}
.alert--success {
  background: var(--success-soft);
  border-color: color-mix(in srgb, var(--success) 25%, transparent);
}
.alert--success .alert__icon {
  color: var(--success);
}
.alert--warning {
  background: var(--warning-soft);
  border-color: color-mix(in srgb, var(--warning) 25%, transparent);
}
.alert--warning .alert__icon {
  color: var(--warning);
}
.alert--danger {
  background: var(--danger-soft);
  border-color: color-mix(in srgb, var(--danger) 25%, transparent);
}
.alert--danger .alert__icon {
  color: var(--danger);
}

/* =========================================================================
   RÉVÉLATION AU SCROLL (.reveal)
   À combiner avec un IntersectionObserver qui ajoute .is-visible.
   Cascade : --reveal-delay sur l'élément (ex: style="--reveal-delay: 120ms").
   ========================================================================= */
.reveal {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity var(--dur-slow) var(--ease-out), transform var(--dur-slow) var(--ease-out);
  transition-delay: var(--reveal-delay, 0ms);
  will-change: opacity, transform;
}
.reveal.is-visible {
  opacity: 1;
  transform: none;
  will-change: auto; /* libère la GPU une fois révélé */
}
/* Filet de sécurité : si JS échoue ou est bloqué, le contenu .reveal ne doit
   jamais rester invisible. La classe .no-js est posée sur <html> par défaut et
   retirée en tête de script ; sans JS, elle reste et force l'affichage. */
.no-js .reveal {
  opacity: 1;
  transform: none;
}

/* =========================================================================
   UTILITAIRES MINIMAUX
   ========================================================================= */
.container {
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--space-6);
}
.stack > * + * {
  margin-top: var(--space-4);
}
.stack--tight > * + * {
  margin-top: var(--space-3);
}
/* Pile COMPACTE pour une cellule de tableau (chiffre, détail, commentaire).
   Contrairement à .stack, qui se contente d'espacer des blocs, celle-ci
   EMPILE réellement : des <span> inline resteraient sinon sur une seule
   ligne et la cellule deviendrait illisible. */
.stack-cell {
  display: flex;
  flex-direction: column;
  gap: 2px;
  white-space: nowrap;
}
.row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}
.row--between {
  justify-content: space-between;
}

/* Espacements verticaux courants (remplacent les style= inline structurels). */
.mt-2 {
  margin-top: var(--space-2);
}
.mt-5 {
  margin-top: var(--space-5);
}
.mt-6 {
  margin-top: var(--space-6);
}

/* Cible du lien d'évitement : focus posé sur le conteneur, sans halo visuel. */
[tabindex="-1"]:focus {
  outline: none;
}

/* Masquage visuel mais lisible au lecteur d'écran (en-têtes d'actions, etc.). */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.grid {
  display: grid;
  gap: var(--space-4);
}
.grid > * {
  min-width: 0;
} /* enfants de grille : rétrécir au lieu de déborder */
.grid--2 {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}
.grid--3 {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}
.grid--4 {
  grid-template-columns: repeat(4, minmax(0, 1fr));
}
.app-shell {
  display: grid;
  grid-template-columns: var(--sidebar-w) minmax(0, 1fr);
  min-height: 100vh;
}
.app-shell > * {
  min-width: 0;
} /* colonne de contenu : rétrécir au lieu de déborder */
.app-main {
  padding: var(--space-6);
  min-width: 0;
}

@media (max-width: 1024px) {
  .grid--4 {
    grid-template-columns: repeat(2, 1fr);
  }
  .grid--3 {
    grid-template-columns: repeat(2, 1fr);
  }
}
@media (max-width: 768px) {
  .grid--2,
  .grid--3,
  .grid--4 {
    grid-template-columns: 1fr;
  }
  .app-shell {
    grid-template-columns: 1fr;
  }
  .sidebar {
    display: none;
  } /* nav mobile gérée par les cockpits */
  .app-main {
    padding: var(--space-5);
  }
  :root {
    --text-display: 2.25rem;
    --text-h1: 1.75rem;
    --text-kpi: 1.625rem;
  }
}

/* =========================================================================
   ACCESSIBILITÉ - mouvement réduit
   Neutralise toutes les animations/transitions et fige les états révélés.
   ========================================================================= */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
  .reveal {
    opacity: 1;
    transform: none;
  }
}

/* =========================================================================
   LARGEUR DE CONTENU - respiration sur grands écrans
   Le contenu (--content-max) reste à 1240px jusqu'à 1600px, puis s'élargit
   par paliers pour éviter le vide latéral sur les très grands moniteurs, sans
   allonger les lignes de texte au point de nuire à la lecture.
   ========================================================================= */
@media (min-width: 1600px) {
  :root {
    --content-max: 1360px;
  }
}
@media (min-width: 1920px) {
  :root {
    --content-max: 1500px;
  }
}

/* ============ Board / kanban (CRM pipeline) ============ */
.board {
  display: flex;
  gap: var(--space-3);
  overflow-x: auto;
  padding-bottom: var(--space-2);
}
.board__col {
  flex: 0 0 15rem;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  background: var(--ivory, #f6f1e7);
  border: 1px solid rgba(31, 48, 71, 0.1);
  border-radius: 0.5rem;
  padding: var(--space-2);
}
.board__col--over {
  border-color: var(--navy, #1f3047);
  background: #eee6d6;
}
.board__col-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-weight: 600;
  font-size: 0.85rem;
}
.board__col-total {
  color: var(--text-muted, #6b7280);
  font-weight: 500;
}
.board__card {
  background: #fff;
  border: 1px solid rgba(31, 48, 71, 0.12);
  border-radius: 0.375rem;
  padding: var(--space-2);
  cursor: grab;
  font-size: 0.8rem;
}
.board__card--drag {
  opacity: 0.5;
}
.board__card-title {
  font-weight: 600;
}
.board__card-meta {
  color: var(--text-muted, #6b7280);
  margin-top: 0.15rem;
}

/* =========================================================================
   COQUILLE APPLICATIVE v1.1 - commune aux quatre cockpits
   Console (admin) : sidebar marine + topbar collante + tiroir mobile.
   Portails (prof, apprenant, entreprise) : masthead clair + onglets.
   Un seul design system, meme grammaire visuelle partout.
   ========================================================================= */

/* Colonne de droite d'une coquille a sidebar : topbar collante puis contenu. */
.app-col {
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 100vh;
}
.app-col > .app-main {
  flex: 1 1 auto;
}

/* Burger : masque en desktop, revele quand la sidebar disparait (<= 768px). */
@media (max-width: 768px) {
  .topbar__burger {
    display: inline-flex;
  }
}

/* Intitule de page dans la topbar : sur-titre discret + page courante. */
.topbar__heading {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.topbar__eyebrow {
  font-size: var(--text-2xs);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--muted);
}
.topbar__page {
  font-family: var(--font-serif);
  font-size: var(--text-h4);
  color: var(--navy);
  line-height: 1.1;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Menu utilisateur : avatar + identite + role + deconnexion, homogene partout. */
.usermenu {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  min-width: 0;
}
/* L'identite mene a « Mon compte » : lien discret, jamais souligne, qui reprend
   l'alignement de l'ancien groupe avatar + identite. */
.usermenu__link {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  min-width: 0;
  text-decoration: none;
  border-radius: var(--radius-sm);
  padding: 2px 4px;
  margin: -2px -4px;
  transition: background-color 120ms ease;
}
.usermenu__link:hover,
.usermenu__link:focus-visible {
  background: var(--greige);
}
.usermenu__id {
  display: flex;
  flex-direction: column;
  line-height: 1.15;
  min-width: 0;
}
.usermenu__name {
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 20ch;
}
.usermenu__role {
  font-size: var(--text-2xs);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--muted);
}
@media (max-width: 600px) {
  .usermenu__id {
    display: none;
  }
}

/* Pastille de marque reutilisable (masthead des portails, ecran de connexion). */
.brand-mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  flex: none;
  border-radius: var(--radius-md);
  background: var(--coral);
  color: var(--on-dark);
  font-family: var(--font-serif);
  font-size: 1.05rem;
  letter-spacing: 0.01em;
  box-shadow: 0 4px 12px rgba(232, 70, 71, 0.35);
}

/* Bas de sidebar : selecteur d'espaces SSO, pousse en pied de colonne. */
.sidebar__foot {
  margin-top: auto;
  padding-top: var(--space-5);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}
.sidebar__foot-label {
  font-size: var(--text-2xs);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.42);
  padding: 0 var(--space-3);
}
/* Chips d'espaces sur fond marine (lisibles, etat courant en corail fonce AA). */
.space-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-xs);
  font-weight: 600;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-md);
  color: rgba(255, 255, 255, 0.8);
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.08);
  transition: background var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
}
.space-chip:hover {
  background: rgba(255, 255, 255, 0.13);
  color: var(--on-dark);
}
.space-chip:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px rgba(246, 188, 179, 0.5);
}
.space-chip--current {
  background: var(--coral-700);
  border-color: var(--coral-700);
  color: var(--on-dark);
}
.space-chip--current:hover {
  background: var(--coral-700);
  color: var(--on-dark);
  filter: brightness(0.96);
}
.sidebar--collapsed .sidebar__foot {
  display: none;
}

/* -------------------------------------------------------------------------
   Ecrans d'authentification des cockpits : chargement, redirection (vers la
   connexion ou vers l'espace du role), deconnexion, refus.
   Meme famille visuelle que l'application de connexion SWISS LINGUA
   (apps/login) : marque en tete, carte centree sur fond creme, pied discret.
   Aucun masthead ni navigation : le layout ne monte le chrome qu'une fois
   l'acces accorde. C'est la premiere impression.
   ------------------------------------------------------------------------- */
.auth-screen {
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: var(--space-5) var(--space-4) var(--space-6);
  background: radial-gradient(130% 120% at 50% -20%, rgba(42, 49, 125, 0.1), transparent 55%),
    radial-gradient(90% 90% at 100% 100%, rgba(246, 188, 179, 0.22), transparent 60%), var(--ivory);
}
/* Marque sortie de la carte, comme sur l'ecran de connexion : ces ecrans
   restent des ecrans du site, pas des pages isolees. */
.auth-topbar {
  width: 100%;
  max-width: 1080px;
  display: flex;
  align-items: center;
}
.auth-topbar__logo {
  display: block;
  height: 34px;
  width: auto;
}
.auth-middle {
  flex: 1;
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-4);
  padding: var(--space-5) 0;
}
.auth-card {
  width: 100%;
  max-width: 31.5rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  padding: clamp(1.75rem, 5.5vw, 3.25rem) clamp(1.25rem, 5vw, 2.25rem) clamp(1.5rem, 5vw, 2.9rem);
  text-align: center;
}
.auth-card__title {
  font-family: var(--font-serif);
  font-weight: 600;
  color: var(--navy);
  font-size: clamp(1.45rem, 5.2vw, 1.8rem);
  line-height: 1.18;
  letter-spacing: var(--tracking-tight);
  margin: 0 0 var(--space-2);
}
.auth-card__body {
  color: var(--muted);
  font-size: var(--text-sm);
  line-height: 1.55;
  margin: 0 auto;
  max-width: 40ch;
}
/* Rappel du role du compte : c'est l'information qui permet a la personne de
   dire au secretariat ce qui ne va pas. */
.auth-card__role {
  margin-top: var(--space-4);
}
.auth-card__cta {
  width: 100%;
  justify-content: center;
  margin-top: var(--space-5);
}
/* Etats transitoires (chargement, redirection) : une ligne sobre, sans carte.
   Rien a lire, rien a faire, l'ecran va disparaitre. */
.auth-note {
  color: var(--muted);
  font-size: var(--text-sm);
  text-align: center;
  margin: 0;
}
.auth-foot {
  color: var(--muted);
  font-size: var(--text-xs);
  letter-spacing: var(--tracking-wide);
  margin: 0;
}
@media (max-width: 720px) {
  .auth-topbar {
    justify-content: center;
  }
}
@media (prefers-reduced-motion: no-preference) {
  .auth-card {
    animation: auth-rise var(--dur-slow) var(--ease-out) both;
  }
}
@keyframes auth-rise {
  from {
    opacity: 0;
    transform: translateY(12px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

/* Masthead des portails (prof, apprenant, entreprise) : bloc de marque + actions. */
.masthead {
  margin-bottom: var(--space-6);
}
.masthead__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  flex-wrap: wrap;
}
.masthead__brand {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-width: 0;
}
.masthead__space {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.masthead__eyebrow {
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--navy);
}
.masthead__title {
  font-family: var(--font-serif);
  font-size: var(--text-h2);
  color: var(--navy);
  line-height: 1.1;
}
.masthead__switcher {
  margin-top: var(--space-4);
}
.masthead__lead {
  margin-top: var(--space-3);
}

/* Sous-navigation de section : onglets soulignes, scrollables en mobile. */
.tabnav {
  display: flex;
  gap: var(--space-1);
  border-bottom: 1px solid var(--line);
  overflow-x: auto;
  scrollbar-width: none;
  margin-top: var(--space-5);
}
.tabnav::-webkit-scrollbar {
  display: none;
}
.tabnav__link {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-4);
  white-space: nowrap;
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--muted);
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  min-height: 44px;
  transition: color var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out);
}
.tabnav__link:hover {
  color: var(--navy);
}
.tabnav__link:focus-visible {
  outline: none;
  box-shadow: var(--shadow-focus);
  border-radius: var(--radius-sm);
}
.tabnav__link--active {
  color: var(--navy);
  border-bottom-color: var(--coral);
}

/* Cartes d'orientation : tuile d'icone + intitule + accroche + fleche. */
.orient-grid {
  display: grid;
  gap: var(--space-4);
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
}
.orient-card {
  display: flex;
  align-items: flex-start;
  gap: var(--space-4);
  text-align: left;
  color: inherit;
}
.orient-card__tile {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  flex: none;
  border-radius: var(--radius-md);
  background: var(--salmon-soft);
  color: var(--coral-700);
}
.orient-card__tile svg {
  width: 22px;
  height: 22px;
}
.orient-card__body {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  min-width: 0;
}
.orient-card__title {
  font-family: var(--font-serif);
  font-size: var(--text-h4);
  color: var(--navy);
}
.orient-card__text {
  font-size: var(--text-sm);
  color: var(--muted);
}
.orient-card__arrow {
  margin-left: auto;
  color: var(--navy);
  flex: none;
  transition: transform var(--dur-fast) var(--ease-out);
}
.orient-card__arrow svg {
  width: 20px;
  height: 20px;
}
.orient-card:hover .orient-card__arrow {
  transform: translateX(3px);
}

/* Etat vide elegant : jamais un ecran brut "aucune donnee". */
.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--space-3);
  padding: var(--space-7) var(--space-5);
}
.empty-state__tile {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 56px;
  height: 56px;
  border-radius: var(--radius-lg);
  background: var(--greige);
  color: var(--navy);
}
.empty-state__tile svg {
  width: 28px;
  height: 28px;
}
.empty-state__title {
  font-family: var(--font-serif);
  font-size: var(--text-h4);
  color: var(--navy);
}
.empty-state__text {
  font-size: var(--text-sm);
  color: var(--muted);
  max-width: 46ch;
}

/* Page 404 : marque, code, message, retour. */
.notfound {
  min-height: 60vh;
  display: grid;
  place-items: center;
  text-align: center;
  padding: var(--space-7) var(--space-4);
}
.notfound__inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-4);
  max-width: 48ch;
}
.notfound__code {
  font-family: var(--font-serif);
  font-size: var(--text-display);
  line-height: 1;
  color: var(--coral);
}
.notfound__title {
  font-family: var(--font-serif);
  font-size: var(--text-h2);
  color: var(--navy);
}
.notfound__text {
  font-size: var(--text-body);
  color: var(--muted);
}

/* Tailles d'icone explicites (trait 24x24 mis a l'echelle du contexte). */
.ic {
  width: 20px;
  height: 20px;
  flex: none;
}
.ic--sm {
  width: 16px;
  height: 16px;
  flex: none;
}
.ic--lg {
  width: 24px;
  height: 24px;
  flex: none;
}
.topbar__burger svg {
  width: 22px;
  height: 22px;
}
.nav-drawer__close svg {
  width: 20px;
  height: 20px;
}

/* Tiroir mobile en teinte marine : reprend la sidebar (nav-item lisibles sur marine). */
.nav-drawer__panel--navy {
  background: var(--navy);
  border-right-color: rgba(255, 255, 255, 0.08);
}
.nav-drawer__panel--navy .nav-drawer__head {
  margin-bottom: var(--space-4);
}
.nav-drawer__panel--navy .sidebar__foot {
  margin-top: var(--space-5);
}

/* Topbar en mobile : respiration reduite. */
@media (max-width: 768px) {
  .topbar {
    padding-inline: var(--space-5);
    gap: var(--space-3);
  }
}

/* =========================================================================
   ÉTATS DE CHARGEMENT
   Deux registres, jamais mélangés :
   - le SQUELETTE (.skeleton) pour une première lecture, quand la forme du
     contenu est connue d'avance (tableau, tuile d'indicateur, ligne de texte) ;
   - l'INDICATEUR D'ACTIVITÉ (.spinner) pour une action déclenchée par
     l'utilisateur, dont on ne peut pas dessiner le résultat à l'avance.
   Le balayage du squelette et la rotation de l'indicateur s'arrêtent sous
   prefers-reduced-motion (voir le bloc dédié en fin de section).
   ========================================================================= */
.skeleton {
  display: block;
  border-radius: var(--radius-sm);
  background-color: var(--greige);
  background-image: linear-gradient(
    90deg,
    rgba(255, 255, 255, 0) 0%,
    rgba(255, 255, 255, 0.65) 50%,
    rgba(255, 255, 255, 0) 100%
  );
  background-size: 200% 100%;
  background-repeat: no-repeat;
  animation: skeleton-sweep 1.4s var(--ease-in-out) infinite;
}
@keyframes skeleton-sweep {
  0% {
    background-position: 150% 0;
  }
  100% {
    background-position: -50% 0;
  }
}
/* Variantes calées sur les hauteurs de texte réelles du design system. */
.skeleton--text {
  height: 0.875rem;
}
.skeleton--title {
  height: 1.375rem;
  border-radius: var(--radius-md);
}
.skeleton--kpi {
  height: 2.25rem;
  width: 60%;
  border-radius: var(--radius-md);
}
.skeleton--pill {
  height: 1.25rem;
  width: 5rem;
  border-radius: var(--radius-pill);
}
/* Largeurs décroissantes : un pavé de barres strictement égales se lit comme
   un bug d'affichage, pas comme du texte en cours d'arrivée. */
.skeleton-lines {
  display: grid;
  gap: var(--space-3);
}
.skeleton-lines > .skeleton:nth-child(2) {
  width: 92%;
}
.skeleton-lines > .skeleton:nth-child(3) {
  width: 78%;
}
.skeleton-lines > .skeleton:last-child:not(:only-child) {
  width: 64%;
}
/* Squelette de tableau : même gouttière que .table pour que le contenu réel
   prenne exactement la place du squelette (aucun saut à l'arrivée des données). */
.skeleton-table {
  display: grid;
  gap: var(--space-4);
  padding: var(--space-2) 0;
}
.skeleton-row {
  display: grid;
  grid-template-columns: repeat(var(--skeleton-cols, 4), minmax(0, 1fr));
  gap: var(--space-4);
  align-items: center;
}
.skeleton-row > .skeleton {
  height: 0.875rem;
}
.skeleton-row--head > .skeleton {
  height: 0.75rem;
  opacity: 0.7;
}

/* Indicateur d'activité. Hérite de currentColor : lisible sur un bouton
   primaire marine comme sur une surface ivoire, sans variante de couleur. */
.spinner {
  display: inline-block;
  width: 1rem;
  height: 1rem;
  flex: none;
  border-radius: var(--radius-pill);
  border: 2px solid currentColor;
  border-top-color: transparent;
  opacity: 0.85;
  animation: spinner-turn 700ms linear infinite;
}
.spinner--sm {
  width: 0.75rem;
  height: 0.75rem;
  border-width: 2px;
}
.spinner--lg {
  width: 1.5rem;
  height: 1.5rem;
  border-width: 3px;
}
@keyframes spinner-turn {
  to {
    transform: rotate(360deg);
  }
}
/* Bloc d'attente centré (chargement d'une carte entière sans forme connue). */
.loading-block {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-3);
  padding: var(--space-6) var(--space-4);
  color: var(--muted);
  font-size: var(--text-sm);
}

/* Élément occupé : l'action est partie, le bouton reste lisible mais inerte.
   Le libellé ne bouge pas (l'indicateur s'ajoute), pour ne pas décaler la
   mise en page au clic. */
.btn[aria-busy="true"],
.btn:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}
.btn[aria-busy="true"] {
  pointer-events: none;
}
[aria-busy="true"] > .skeleton-table,
[aria-busy="true"] > .skeleton-lines {
  margin-block: var(--space-2);
}

/* =========================================================================
   NOTIFICATIONS ÉPHÉMÈRES (toasts)
   Confirmation d'une action réussie, ou échec d'une action lancée depuis un
   endroit qui n'a pas de place pour une alerte en ligne (suppression dans un
   tableau, transfert, envoi). Les erreurs de saisie d'un formulaire restent
   en ALERTE EN LIGNE, près du champ fautif : un toast qui disparaît ne peut
   pas porter une correction à faire.
   La région est annoncée en aria-live="polite" (voir ToastRegion).
   ========================================================================= */
.toast-region {
  position: fixed;
  z-index: 80;
  right: var(--space-5);
  bottom: var(--space-5);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  width: min(380px, calc(100vw - var(--space-6)));
  pointer-events: none;
}
.toast {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  padding: var(--space-4);
  padding-left: var(--space-5);
  border-radius: var(--radius-md);
  border: 1px solid var(--line);
  border-left: 3px solid var(--navy);
  background: var(--surface);
  box-shadow: var(--shadow-md);
  color: var(--ink);
  font-size: var(--text-sm);
  pointer-events: auto;
  /* Pas de fill-mode `both` : l'etat de depart de l'animation est opacity:0,
     et un moteur qui ne joue pas l'animation laisserait la notification
     invisible. Sans fill-mode, l'element est visible par defaut et
     l'animation n'ajoute que l'entree (constate au navigateur). */
  animation: toast-in var(--dur-base) var(--ease-out);
}
@keyframes toast-in {
  from {
    opacity: 0;
    transform: translateY(8px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}
.toast--success {
  border-left-color: var(--success);
}
.toast--danger {
  border-left-color: var(--danger);
}
.toast__icon {
  flex: none;
  width: 20px;
  height: 20px;
  margin-top: 1px;
  color: var(--navy);
}
.toast--success .toast__icon {
  color: var(--success);
}
.toast--danger .toast__icon {
  color: var(--danger);
}
.toast__body {
  flex: 1 1 auto;
  min-width: 0;
  overflow-wrap: break-word;
}
.toast__title {
  font-weight: 600;
}
.toast__text {
  color: var(--muted);
  margin-top: var(--space-1);
}
.toast__close {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  margin: -2px -2px 0 0;
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--muted);
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
}
.toast__close:hover {
  background: var(--greige);
  color: var(--ink);
}
.toast__close:focus-visible {
  outline: none;
  box-shadow: var(--shadow-focus);
}
.toast__close svg {
  width: 16px;
  height: 16px;
}
@media (max-width: 600px) {
  .toast-region {
    right: var(--space-4);
    left: var(--space-4);
    bottom: var(--space-4);
    width: auto;
  }
}

/* =========================================================================
   DIALOGUE DE CONFIRMATION
   Élément <dialog> natif ouvert par showModal() : le piège de focus, la
   fermeture par Échap et l'inertage du fond sont fournis par le navigateur,
   aucune réimplémentation maison. Réservé aux actions à conséquence
   (suppression, transfert de crédits, annulation d'une inscription).
   ========================================================================= */
.modal {
  width: min(480px, calc(100vw - var(--space-6)));
  /* Le reset de cette feuille pose margin:0 partout, ce qui ECRASE le
     `margin:auto` que le navigateur applique a dialog:modal : sans cette ligne,
     le dialogue se colle en haut a gauche du viewport (constate au navigateur). */
  margin: auto;
  max-height: calc(100vh - var(--space-7));
  overflow: auto;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--surface);
  color: var(--ink);
  box-shadow: var(--shadow-lg);
}
.modal::backdrop {
  background: rgba(20, 20, 15, 0.45);
}
.modal[open] {
  /* Meme raison que pour .toast : jamais de fill-mode sur une animation
     d'entree dont l'etat de depart est invisible. */
  animation: modal-in var(--dur-base) var(--ease-out);
}
@keyframes modal-in {
  from {
    opacity: 0;
    transform: translateY(8px) scale(0.99);
  }
  to {
    opacity: 1;
    transform: none;
  }
}
.modal__panel {
  padding: var(--space-6);
}
.modal__title {
  font-family: var(--font-serif);
  font-size: var(--text-h3);
  line-height: 1.2;
  color: var(--navy);
  margin: 0;
}
.modal__body {
  margin-top: var(--space-3);
  font-size: var(--text-sm);
  color: var(--muted);
}
.modal__actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: var(--space-3);
  margin-top: var(--space-6);
}
.modal__actions > * {
  flex: 0 0 auto;
}

/* Mouvement réduit : on garde le changement d'état (donc l'information), on
   retire le déplacement et les boucles. */
@media (prefers-reduced-motion: reduce) {
  .skeleton {
    animation: none;
    background-image: none;
  }
  .spinner {
    animation-duration: 2s;
  }
  .toast,
  .modal[open] {
    animation: none;
  }
}

/* =========================================================================
   LIEN D'ÉVITEMENT (WCAG 2.4.1)
   Premier élément focusable de la page : il saute la navigation (jusqu'à 30
   entrées dans la console) pour poser le focus sur le contenu. Hors focus, il
   est masqué visuellement mais reste dans l'ordre de tabulation.
   ========================================================================= */
.skip-link {
  position: absolute;
  z-index: 100;
  top: var(--space-2);
  left: var(--space-2);
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-md);
  background: var(--navy);
  color: var(--on-dark);
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  font-weight: 600;
  text-decoration: none;
  /* Hors focus : retire du rendu visuel par la meme technique que .sr-only,
     sans quitter l'ordre de tabulation. Volontairement PAS un translate anime :
     la visibilite du lien ne doit dependre d'aucune transition (un moteur qui
     ne la joue pas laisserait le lien invisible au clavier). */
  width: 1px;
  height: 1px;
  padding: 0;
  overflow: hidden;
  white-space: nowrap;
  clip-path: inset(50%);
}
.skip-link:focus-visible {
  width: auto;
  height: auto;
  padding: var(--space-3) var(--space-4);
  overflow: visible;
  clip-path: none;
  outline: none;
  box-shadow: 0 0 0 3px var(--salmon);
}

/* Titre de page de la topbar : c'est le <h1> du document, pas une simple
   etiquette. La regle reprend exactement l'ancienne apparence du <span>. */
h1.topbar__page {
  margin: 0;
  font-family: var(--font-serif);
}

/* =========================================================================
   TAILLES DE CIBLE (WCAG 2.2 AA, critere 2.5.8 : 24 x 24 px minimum)
   La pastille (.pill) tombait a 22px : le plancher est pose sans changer la
   silhouette. Sur un pointeur grossier (tactile), les commandes montent a
   44px, la recommandation ergonomique, sans alourdir l'affichage au bureau.
   ========================================================================= */
.pill {
  min-height: 24px;
}
@media (pointer: coarse) {
  .btn,
  .pill,
  .nav-item,
  .tabnav__link,
  .space-chip,
  .toast__close,
  .scrollx__arrow {
    min-height: 44px;
  }
  .btn--sm {
    padding-block: var(--space-3);
  }
}

/* Coquille des espaces (mon, pro, prof) : porte la respiration et la largeur
   maximale qui vivaient jusqu'ici en style en ligne sur le <main>. Le <main>
   n'enveloppe plus que le contenu de page. */
.portal-shell {
  padding: var(--space-6);
  max-width: var(--content-max, 1240px);
  margin-inline: auto;
  width: 100%;
  min-width: 0;
}

/* =========================================================================
   RÉCAPITULATIF DE TOTAUX (détail d'une offre, « Mes achats »)
   Liste libellé / montant sous un tableau de lignes. Pas un tfoot : le tableau
   ne style que `tbody td`, et un tfoot à colSpan se désaligne des colonnes.
   ========================================================================= */
.order-totals {
  margin: var(--space-4) 0 0;
  display: grid;
  gap: var(--space-2);
  font-size: var(--text-sm);
}
.order-totals > div {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--space-4);
}
.order-totals dt {
  color: var(--muted);
}
.order-totals dd {
  margin: 0;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.order-totals__total {
  padding-top: var(--space-2);
  border-top: 1px solid var(--line);
}
.order-totals__total dt,
.order-totals__total dd {
  color: var(--ink);
  font-weight: 600;
}

/* =========================================================================
   SOCLE VISUEL v1.2 - passe de design d'ensemble des quatre cockpits
   Deux moitiés dans cette section :
   1. des CORRECTIONS RÉTROACTIVES, qui redressent l'existant sans toucher au
      balisage des écrans (cartes imbriquées, tableaux dans une carte, tuiles
      d'indicateurs, densité mobile) ;
   2. des CLASSES NEUVES (.page, .page-head, .stat-strip, .card--flush, .rows)
      que les écrans adoptent au fil de l'eau, à la place des style= en ligne.
   Aucune couleur, aucun rayon, aucune ombre hors des tokens du fichier.
   ========================================================================= */

/* -------------------------------------------------------------------------
   1. Corrections rétroactives
   ------------------------------------------------------------------------- */

/* Carte dans une carte : le fond blanc est déjà posé par la carte parente, la
   seconde bordure et la seconde ombre ne délimitent plus rien et brouillent la
   hiérarchie (tout pèse pareil). La carte fille garde sa bordure, perd son
   ombre et son rayon large. */
.card .card {
  box-shadow: none;
  border-radius: var(--radius-md);
}
/* Carte fille cliquable : l'affordance passe du relief au fond chaud. Le
   soulèvement d'une carte posée dans une autre donnait un effet de calque. */
.card .card--hover:hover {
  box-shadow: none;
  transform: none;
  background: var(--ivory);
  border-color: var(--line-strong);
}

/* Tuile d'indicateur posée dans une carte : fond ivoire, sans cadre. Les
   indicateurs de premier niveau (posés directement sur la page) gardent la
   carte blanche, ce qui rétablit la différence entre les deux rangs. */
.card .card.kpi {
  background: var(--ivory);
  border-color: transparent;
}

/* Tableau dans une carte : `.table-wrap` porte bordure, rayon et fond blanc,
   qui redoublaient ceux de la carte. Dans une carte, il n'est plus qu'une
   zone de défilement. Hors carte, il garde son cadre. */
.card .table-wrap {
  border: 0;
  border-radius: 0;
  background: transparent;
}
/* L'en-tête du tableau reprend alors le rôle de séparateur. */
.card .table-wrap > .table thead th {
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}

/* -------------------------------------------------------------------------
   2. Classes neuves
   ------------------------------------------------------------------------- */

/* Rythme vertical d'un écran. Remplace les `style="display:grid; gap:…"`
   répétés en tête de chaque route. */
.page {
  display: grid;
  gap: var(--space-6);
  align-content: start;
}

/* En-tête d'écran : ce qu'on regarde, pourquoi, et ce qu'on peut y faire.
   Se pose SUR le fond, jamais dans une carte : une carte annonce un contenu,
   pas un écran. Les actions primaires vivent ici, à droite. */
.page-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--space-5);
  flex-wrap: wrap;
  padding-bottom: var(--space-4);
  border-bottom: 1px solid var(--line);
}
.page-head__text {
  min-width: 0;
  display: grid;
  gap: var(--space-1);
}
.page-head__title {
  font-family: var(--font-serif);
  font-size: var(--text-h2);
  color: var(--navy);
  line-height: 1.1;
  letter-spacing: var(--tracking-tight);
  margin: 0;
}
.page-head__lead {
  color: var(--muted);
  font-size: var(--text-sm);
  max-width: 60ch;
}
.page-head__actions {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex-wrap: wrap;
}

/* Bandeau d'indicateurs : une seule surface, des colonnes séparées par un
   filet, des valeurs alignées sur la même ligne de base. Remplace la rangée
   de cartes autonomes, dont les libellés sur deux lignes décalaient les
   chiffres les uns par rapport aux autres. */
.stat-strip {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  overflow: hidden;
}
.stat {
  display: grid;
  grid-template-rows: auto 1fr auto;
  gap: var(--space-2);
  padding: var(--space-5);
  border-left: 1px solid var(--line);
  min-width: 0;
  container-type: inline-size;
}
.stat:first-child {
  border-left: 0;
}
.stat__label {
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--muted);
  /* Le libellé passe à la ligne au lieu d'être tronqué : dans une colonne
     étroite (bandeau à deux colonnes sur mobile), « Crédit entreprise »
     devenait « Crédit entrepr… », de l'information perdue. */
  overflow-wrap: break-word;
}
.stat__value {
  font-family: var(--font-serif);
  font-size: clamp(1.5rem, 14cqi, var(--text-kpi));
  line-height: 1;
  color: var(--navy);
  font-variant-numeric: tabular-nums;
  display: flex;
  align-items: baseline;
  /* La devise passe sous le chiffre plutôt que de rester sur la même ligne et
     de sortir de la carte quand la place manque. Le montant lui-même est
     insécable (séparateurs de milliers U+202F) : c'est la largeur de colonne
     qui doit suivre (voir la bascule à une colonne sous 600px). */
  flex-wrap: wrap;
  gap: var(--space-2);
  min-width: 0;
}
/* Unité et devise : jamais dans le corps du chiffre, sinon la valeur casse sur
   deux lignes et la rangée perd son alignement. */
.stat__unit {
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--muted);
  letter-spacing: var(--tracking-wide);
}
/* Ligne de contexte sous le chiffre : ce qui rend l'indicateur lisible (une
   échéance de jetons, une période, une part). Un nombre seul ne se lit pas. */
.stat__meta {
  font-size: var(--text-xs);
  color: var(--muted);
}
.stat__meta--warning {
  color: var(--warning);
}

/* Carte à contenu bord à bord : l'en-tête, la barre d'outils et le pied
   gardent la respiration, le tableau ou la liste prend toute la largeur. */
.card--flush {
  padding: 0;
  overflow: hidden;
}
.card--flush > .card__header,
.card__toolbar,
.card__foot {
  padding: var(--space-5) var(--space-6);
  margin: 0;
}
.card--flush > .card__header {
  border-bottom: 1px solid var(--line);
}
/* Barre d'outils d'une liste : recherche, filtres, compteur de résultats. */
.card__toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  flex-wrap: wrap;
  border-bottom: 1px solid var(--line);
  background: var(--ivory);
}
/* Pied d'une liste : volumétrie et pagination. */
.card__foot {
  border-top: 1px solid var(--line);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  font-size: var(--text-sm);
  color: var(--muted);
}
.card--flush > .table-wrap,
.card--flush > .scrollx > .table-wrap {
  border: 0;
  border-radius: 0;
}
/* Contenus qui ne portent pas leur propre respiration : dans une carte a
   contenu bord a bord, ils colleraient aux aretes. Les listes, les tableaux et
   l'etat vide (qui a deja son cadrage) ne sont volontairement pas de la
   partie. */
.card--flush > .skeleton-lines,
.card--flush > .skeleton-table,
.card--flush > .alert,
.card--flush > p {
  margin: var(--space-5) var(--space-6);
}

/* Liste de lignes séparées par un filet. Remplace les sous-cartes empilées
   dans une carte (deux cadres, deux ombres, deux marges pour une ligne). */
.rows {
  list-style: none;
  margin: 0;
  padding: 0;
}
.rows > li + li {
  border-top: 1px solid var(--line);
}
.row-link {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-4) var(--space-6);
  color: inherit;
  transition: background var(--dur-fast) var(--ease-out);
}
.row-link:hover {
  background: var(--ivory);
}
.row-link:focus-visible {
  outline: none;
  box-shadow: var(--shadow-focus);
}
.row-link__title {
  display: block;
  font-weight: 600;
  color: var(--navy);
}
.row-link__meta {
  font-size: var(--text-sm);
  color: var(--muted);
}

/* Tableau de gestion : la variante dense sert les écrans qui listent des
   milliers de lignes (clients, factures, commandes). L'en-tête reste visible
   pendant le défilement de sa zone. */
.table--dense tbody td {
  padding: var(--space-3) var(--space-5);
}
.table--dense thead th {
  padding: var(--space-2) var(--space-5);
  position: sticky;
  top: 0;
  z-index: 1;
}

/* -------------------------------------------------------------------------
   3. Compacité des portails et du mobile
   ------------------------------------------------------------------------- */

/* Le bloc de tête des portails empilait marque, espaces et onglets sur trois
   rangées largement espacées : plus de 170 px avant la première donnée. */
.masthead {
  margin-bottom: var(--space-5);
}
.masthead__switcher {
  margin-top: var(--space-3);
}
.tabnav {
  margin-top: var(--space-4);
}

@media (max-width: 768px) {
  .portal-shell {
    padding: var(--space-4);
  }
  /* Le nom de l'espace ne doit pas être le plus gros élément de l'écran. */
  .masthead__title {
    font-size: var(--text-h4);
  }
  .masthead {
    margin-bottom: var(--space-4);
  }
  /* Le rôle est redit dans « Mon profil » : sur 375 px, il coûte une ligne. */
  .usermenu__role {
    display: none;
  }
  .usermenu__name {
    max-width: 12ch;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  /* Rangées d'indicateurs à valeurs courtes : deux colonnes, comparables d'un
     coup d'œil, au lieu de 800 px de défilement pour quatre chiffres. Opt-in
     par `.grid--dense` UNIQUEMENT : une rangée qui affiche un montant ou un
     grand nombre reste sur une colonne, car un montant suisse est insécable
     (séparateurs de milliers U+202F) et déborderait une demi-colonne (cf. le
     même écueil corrigé sur `.stat`). L'ancien sélecteur `:has(> .kpi)` ne
     visait jamais rien : KpiCard rend `.card > .kpi`, donc `.kpi` n'est pas
     enfant direct de la grille. */
  .grid--dense {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  .card.kpi {
    padding: var(--space-4);
  }
  /* Le bandeau d'indicateurs tombait a une colonne (auto-fit, minmax 180px),
     soit quatre pleins ecrans pour quatre chiffres. Deux colonnes, avec les
     filets recalcules pour la grille a deux colonnes. */
  .stat-strip {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  .stat {
    padding: var(--space-4);
  }
  .stat:nth-child(odd) {
    border-left: 0;
  }
  .stat:nth-child(n + 3) {
    border-top: 1px solid var(--line);
  }
  .kpi__label {
    font-size: var(--text-xs);
  }
  /* Onglets : des libellés plus serrés en montrent davantage avant défilement. */
  .tabnav__link {
    padding-inline: var(--space-3);
  }
}

/* Bandeau d'indicateurs contenant un montant : sous 600px, les deux colonnes
   tombent sous la largeur d'un montant. Comme un montant suisse est insécable
   (séparateurs de milliers U+202F, devise accolée), il déborderait la colonne
   et serait rogné par l'overflow de la surface (« CHF » coupé sur le filet).
   On rend la pleine largeur à ces bandeaux ; ceux qui n'affichent que des
   compteurs courts gardent leurs deux colonnes, plus denses. Filets recalculés
   pour une pile verticale. */
@media (max-width: 600px) {
  .stat-strip:has(.stat__unit) {
    grid-template-columns: 1fr;
  }
  .stat-strip:has(.stat__unit) .stat {
    border-left: 0;
    border-top: 1px solid var(--line);
  }
  .stat-strip:has(.stat__unit) .stat:first-child {
    border-top: 0;
  }
}
