/* =========================================================
   KLASSIO — Design System
   Palette: crème chaude + forêt profonde + lime vif + or doux
   ========================================================= */

:root {
  /* Neutrals — warm, never pure white */
  --bg: #FAF8EF;
  --bg-alt: #F1EEDC;
  --surface: #FFFFFF;
  --surface-soft: #F6F4E9;
  --line: #E6E1CD;
  --line-soft: #EFEBDB;

  /* Ink */
  --ink: #16241C;
  --ink-soft: #4B5A4F;
  --ink-faint: #8A9389;

  /* Brand — lime family */
  --lime: #9FE300;
  --lime-strong: #7BC400;
  --lime-deep: #5C9600;
  --lime-tint: #EEFBCB;

  /* Forest — deep green for contrast/dark sections */
  --forest: #16301F;
  --forest-800: #1E3D28;
  --forest-700: #274A32;
  --forest-tint: #E7EFE3;

  /* Gold — warm secondary accent */
  --gold: #F0B429;
  --gold-tint: #FDF1D6;

  /* Boutons "sombres" (ex. Commencer) : volontairement invariants entre les
     thèmes clair/sombre. Bug réel trouvé : ce bouton utilisait --ink comme
     fond et --lime-tint comme texte — deux tokens qui s'inversent en thème
     sombre (--ink devient clair, --lime-tint devient un vert olive sombre),
     ce qui rendait le bouton illisible (texte sombre sur fond sombre) au
     survol en mode sombre. Ces deux tokens-ci ne changent jamais. */
  --btn-dark-bg: #16241C;
  --btn-dark-bg-hover: #0E170F;
  --btn-dark-text: #EEFBCB;

  --radius-sm: 10px;
  --radius-md: 16px;
  --radius-lg: 24px;
  --radius-xl: 32px;

  --shadow-sm: 0 1px 2px rgba(22, 36, 28, 0.06), 0 1px 1px rgba(22, 36, 28, 0.04);
  --shadow-md: 0 8px 24px rgba(22, 36, 28, 0.08), 0 2px 6px rgba(22, 36, 28, 0.04);
  --shadow-lg: 0 24px 64px rgba(22, 36, 28, 0.14), 0 4px 12px rgba(22, 36, 28, 0.06);
  --shadow-glow: 0 0 0 1px rgba(159, 227, 0, 0.15), 0 20px 60px rgba(124, 196, 0, 0.18);

  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);

  --container: 1180px;
  --nav-h: 72px;
  --font-sans: "Plus Jakarta Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --font-display: "Fraunces", "Plus Jakarta Sans", serif;
}

/* -------------------- Thème sombre --------------------
   Un vrai système de tokens, pas une inversion de couleurs : le lime reste un
   accent (jamais la couleur dominante), fond charbon plutôt que noir pur,
   contrastes vérifiés pour rester lisible. Appliqué via [data-theme="dark"]
   sur <html>, résolu par assets/js/theme.js (gère aussi le mode "Système"). */
:root[data-theme="dark"] {
  --bg: #111111;
  --bg-alt: #171717;
  --surface: #1A1A1A;
  --surface-soft: #202020;
  --line: #2D2D2D;
  --line-soft: #242424;

  --ink: #F2F2EC;
  --ink-soft: #ABB2A6;
  --ink-faint: #767C73;

  --lime: #B8FF00;
  --lime-strong: #A3E600;
  --lime-deep: #8FCC00;
  --lime-tint: #223300;

  --forest-tint: #1B2A1F;
  --gold-tint: #2E2308;

  --shadow-sm: 0 1px 2px rgba(0,0,0,0.45), 0 1px 1px rgba(0,0,0,0.3);
  --shadow-md: 0 8px 24px rgba(0,0,0,0.5), 0 2px 6px rgba(0,0,0,0.3);
  --shadow-lg: 0 24px 64px rgba(0,0,0,0.6), 0 4px 12px rgba(0,0,0,0.35);
  --shadow-glow: 0 0 0 1px rgba(184,255,0,0.18), 0 20px 60px rgba(184,255,0,0.14);
}
:root[data-theme="dark"] .info-card .v.warn,
:root[data-theme="dark"] .text-warn { color: #E8A05C; }
:root[data-theme="dark"] .badge.due { background: #3A241B; color: #E8A05C; }
:root[data-theme="dark"] .badge.partial { color: #E0C066; }
:root[data-theme="dark"] .form-msg.error { color: #E8A05C; }
:root[data-theme="dark"] #splash { background: radial-gradient(120% 120% at 50% 0%, #1B2A00 0%, #171717 45%, #111111 100%); }
:root[data-theme="dark"] .navbar.scrolled { background: rgba(17,17,17,0.85); }
:root[data-theme="dark"] .topbar { background: rgba(17,17,17,0.92); }

* { box-sizing: border-box; }
/* Bug réel trouvé (démo interactive) : overflow-x:hidden posé sur <body> avec
   overflow-y laissé à sa valeur par défaut ("visible") déclenche une règle du
   spec CSS qui "promeut" automatiquement cet axe visible en "auto" — <body>
   devient alors lui-même l'élément défilant à la place de <html>/la fenêtre.
   window.scrollTo / window.scrollY / l'événement "scroll" sur window ne
   s'appliquaient donc plus du tout. En posant overflow-x:hidden sur <html>
   plutôt que sur <body>, c'est <html> qui hérite de cette promotion — exactement
   ce que window.scroll* attend (document.scrollingElement reste <html>). */
html { scroll-behavior: smooth; overflow-x: hidden; }
/* Bug réel trouvé (démo interactive) : l'attribut [hidden] perd face à
   n'importe quelle classe qui pose "display" (même spécificité, mais une
   règle d'auteur l'emporte toujours sur la feuille de style par défaut du
   navigateur) — un élément "hidden" avec une classe display:flex restait
   visible. [hidden] doit toujours gagner. */
[hidden] { display: none !important; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-sans);
  -webkit-font-smoothing: antialiased;
}

body.no-scroll { overflow: hidden; height: 100%; }

img { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }
button { font-family: inherit; cursor: pointer; }

.container {
  max-width: var(--container);
  margin: 0 auto;
  padding: 0 32px;
}

.em { font-family: var(--font-display); font-style: italic; font-weight: 500; color: var(--lime-deep); }

/* -------------------- FlowButtons -------------------- */
.btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  font-weight: 600;
  font-size: 15px;
  padding: 13px 26px;
  border-radius: 100px;
  border: 1.5px solid transparent;
  cursor: pointer;
  overflow: hidden;
  isolation: isolate;
  white-space: nowrap;
  text-decoration: none;
  transition:
    border-radius 0.6s cubic-bezier(0.23, 1, 0.32, 1),
    border-color 0.4s ease,
    background 0.4s ease,
    color 0.4s ease,
    box-shadow 0.35s ease,
    transform 0.25s cubic-bezier(0.16, 1, 0.3, 1);
}
.btn:active { transform: scale(0.96); }

/* Cercle magnétique qui s'ouvre au survol.

   z-index: -1, et surtout PAS 0. Dans l'ordre de peinture d'un contexte
   d'empilement, un élément positionné en z-index 0 passe APRÈS le contenu
   en ligne non positionné : le cercle recouvrait donc le texte de tout bouton
   dont le libellé est un simple nœud de texte — « Connexion » devenait un
   ovale blanc au survol. Vingt-six boutons étaient dans ce cas, plus tous ceux
   que les écrans fabriquent à l'exécution.
   En -1, le cercle se peint au-dessus du fond du bouton mais SOUS tout son
   contenu, libellé enveloppé ou non. `isolation: isolate` sur .btn le retient
   à l'intérieur : il ne peut pas passer derrière le bouton lui-même.
   Ne pas remettre 0 en pensant « ranger » : c'est le défaut qui revient. */
.btn::before {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  transform: translate(-50%, -50%) scale(0);
  opacity: 0;
  z-index: -1;
  pointer-events: none;
  transition:
    transform 0.75s cubic-bezier(0.19, 1, 0.22, 1),
    opacity 0.4s ease;
}
.btn:hover { border-radius: 14px; }
.btn:hover::before {
  transform: translate(-50%, -50%) scale(30);
  opacity: 1;
}

/* Label & Arrow positioning */
.btn-label,
.btn-text {
  position: relative;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  transition: transform 0.65s cubic-bezier(0.23, 1, 0.32, 1);
}

/* Dual sliding arrows (arr-left and arr-right) */
.btn-arr {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
}
.btn-arr-left {
  position: absolute;
  left: -24px;
  opacity: 0;
  z-index: 2;
  transition:
    left 0.7s cubic-bezier(0.34, 1.56, 0.64, 1),
    opacity 0.35s ease;
}
.btn-arr-right {
  position: relative;
  z-index: 2;
  margin-left: 2px;
  transition:
    transform 0.65s cubic-bezier(0.34, 1.56, 0.64, 1),
    opacity 0.35s ease;
}
.btn:hover .btn-arr-left {
  left: 18px;
  opacity: 1;
}
.btn:hover .btn-label,
.btn:hover .btn-text {
  transform: translateX(10px);
}
.btn:hover .btn-arr-right {
  transform: translateX(24px);
  opacity: 0;
}

/* Primary Button (Charcoal / Ink) */
.btn-primary {
  background: var(--btn-dark-bg);
  color: var(--btn-dark-text);
  border-color: rgba(255, 255, 255, 0.08);
  box-shadow: var(--shadow-sm);
}
.btn-primary::before {
  background: var(--btn-dark-bg-hover);
}
.btn-primary:hover {
  box-shadow: var(--shadow-md);
  border-color: rgba(184, 255, 0, 0.25);
  color: #FFFFFF;
}

/* Lime Button (High-performance accent) */
.btn-lime {
  background: var(--lime);
  color: var(--forest);
  border-color: transparent;
  box-shadow: 0 1px 3px rgba(22, 36, 28, 0.12);
}
.btn-lime::before {
  background: var(--forest);
}
.btn-lime:hover {
  box-shadow: var(--shadow-md), 0 0 24px rgba(184, 255, 0, 0.25);
  color: #FFFFFF;
  border-color: transparent;
}
.btn-lime:hover .btn-arr-left {
  stroke: var(--lime);
}

/* Ghost Button */
.btn-ghost {
  background: transparent;
  color: var(--ink);
  border-color: var(--line);
}
.btn-ghost::before {
  background: var(--surface);
}
:root[data-theme="dark"] .btn-ghost::before {
  background: var(--surface-soft);
}
.btn-ghost:hover {
  border-color: var(--ink-faint);
  color: var(--ink);
  box-shadow: var(--shadow-sm);
}

.btn-sm {
  padding: 9px 18px;
  font-size: 14px;
}
.btn-sm:hover .btn-label,
.btn-sm:hover .btn-text {
  transform: translateX(6px);
}
.btn-sm:hover .btn-arr-left {
  left: 12px;
}

/* -------------------- Splash / greeting -------------------- */
#splash {
  position: fixed;
  inset: 0;
  z-index: 999;
  display: flex;
  align-items: center;
  justify-content: center;
  background: radial-gradient(120% 120% at 50% 0%, #EAF7C7 0%, #F7F5E6 45%, #FAF8EF 100%);
  transition: opacity 0.9s var(--ease-in-out), visibility 0.9s;
}
#splash.hide { opacity: 0; visibility: hidden; pointer-events: none; }

.splash-inner { text-align: center; }
.splash-logo {
  display: block;
  width: 64px; height: 64px;
  margin: 0 auto 22px;
  border-radius: 16px;
  object-fit: cover;
  box-shadow: 0 6px 20px rgba(22,36,28,0.16);
  opacity: 0;
  transform: translateY(10px) scale(0.94);
  animation: splashTextCinematic 0.9s var(--ease-out) 0s forwards;
}
.splash-greeting {
  display: block;
  font-family: var(--font-display);
  font-style: italic;
  font-weight: 500;
  font-size: clamp(48px, 9vw, 96px);
  color: var(--forest);
  opacity: 0;
  transform: translateY(16px);
  animation: splashTextCinematic 1s var(--ease-out) 0.15s forwards;
}
:root[data-theme="dark"] .splash-greeting { color: var(--lime); }
.splash-sub {
  display: block;
  margin-top: 10px;
  font-size: 15px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-faint);
  font-weight: 600;
  opacity: 0;
  animation: splashTextCinematic 0.8s var(--ease-out) 0.45s forwards;
}
/* Le splash est court et on peut l'écourter (clic, touche, molette) : encore
   faut-il que le visiteur le sache. */
.splash-skip {
  display: block;
  margin-top: 26px;
  font-size: 11.5px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-faint);
  opacity: 0;
  animation: splashTextCinematic 0.8s var(--ease-out) 0.75s forwards;
}
#splash { cursor: pointer; }

@keyframes splashTextCinematic {
  0% {
    opacity: 0;
    transform: translateY(18px) scale(0.96);
    filter: blur(10px);
  }
  100% {
    opacity: 1;
    transform: translateY(0) scale(1);
    filter: blur(0px);
  }
}
.splash-wave {
  display: inline-block;
  margin-left: 10px;
  animation: wave 1.4s ease-in-out 1.1s 2;
  transform-origin: 70% 70%;
}
@keyframes wave {
  0%, 100% { transform: rotate(0deg); }
  20% { transform: rotate(16deg); }
  40% { transform: rotate(-10deg); }
  60% { transform: rotate(12deg); }
  80% { transform: rotate(0deg); }
}

/* -------------------- Navbar -------------------- */
.navbar {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 18px 32px;
  transition: background 0.3s ease, box-shadow 0.3s ease, backdrop-filter 0.3s ease;
}
.navbar.scrolled {
  background: rgba(250, 248, 239, 0.82);
  backdrop-filter: saturate(160%) blur(14px);
  box-shadow: 0 1px 0 var(--line);
}
.brand {
  display: flex;
  align-items: center;
  gap: 9px;
  font-weight: 800;
  font-size: 19px;
  letter-spacing: -0.01em;
  color: var(--ink);
}
.brand-mark {
  width: 30px; height: 30px;
  border-radius: 9px;
  object-fit: cover;
  display: block;
  flex-shrink: 0;
  box-shadow: 0 1px 3px rgba(22,36,28,0.14), inset 0 0 0 1px rgba(255,255,255,0.25);
}
/* Tubelight floating navigation pill */
.nav-links {
  position: relative;
  display: flex;
  align-items: center;
  gap: 2px;
  background: rgba(255, 255, 255, 0.72);
  border: 1px solid var(--line);
  padding: 4px;
  border-radius: 9999px;
  box-shadow: 0 4px 20px -2px rgba(0, 0, 0, 0.05), inset 0 1px 1px rgba(255, 255, 255, 0.8);
  backdrop-filter: blur(12px);
}
:root[data-theme="dark"] .nav-links {
  background: rgba(28, 30, 26, 0.72);
  border-color: rgba(255, 255, 255, 0.08);
  box-shadow: 0 8px 30px rgba(0, 0, 0, 0.35);
}
.nav-links a {
  position: relative;
  /* Un libellé qui se replie sur deux lignes déforme la pilule et fait
     chevaucher l'îlot avec la marque : entre 920 et 1060 px, « Démo
     interactive » et « Centre d'aide » passaient à la ligne. */
  white-space: nowrap;
  padding: 6px 16px;
  font-size: 13.5px;
  font-weight: 600;
  border-radius: 9999px;
  color: var(--ink-soft);
  text-decoration: none;
  transition: color 0.22s ease;
  z-index: 2;
}
.nav-links a:hover,
.nav-links a.active {
  color: var(--forest);
}
:root[data-theme="dark"] .nav-links a:hover,
:root[data-theme="dark"] .nav-links a.active {
  color: #ffffff;
}

/* Lueur et curseur Tubelight */
.tubelight-lamp {
  position: absolute;
  top: -1px;
  left: 0;
  height: 2.5px;
  width: 32px;
  background: var(--lime);
  border-radius: 9999px;
  box-shadow: 0 0 12px 2px var(--lime), 0 0 4px var(--lime);
  transition: transform 0.32s cubic-bezier(0.16, 1, 0.3, 1), width 0.32s ease, opacity 0.25s ease;
  pointer-events: none;
  z-index: 10;
  opacity: 0;
}
.tubelight-lamp.active { opacity: 1; }
.tubelight-glow {
  position: absolute;
  top: -6px;
  left: 50%;
  transform: translateX(-50%);
  width: 44px;
  height: 18px;
  background: radial-gradient(circle, rgba(159, 227, 0, 0.45) 0%, transparent 70%);
  filter: blur(4px);
  pointer-events: none;
}
.nav-actions { display: flex; align-items: center; gap: 10px; }
.nav-toggle { display: none; }

/* =========================================================
   KLASSIO — Hero « question → réponse », puis entrée dans le « O »

   Règle de composition, demandée explicitement et à ne pas défaire :
   au repos, AVANT tout défilement, le premier écran montre la phrase
   « Toute la gestion de votre école, dans un seul espace clair » et, juste en
   dessous, KLASSIO comme RÉPONSE. Le mot-marque ne doit jamais « apparaître »
   en cours de défilement — il est là dès la première image. Défiler ne fait
   qu'une chose : entrer dans le « O ».

   Le « O » est un hublot, et c'est l'OUVERTURE qui grandit, pas ce qu'on voit
   dedans. Le contenu intérieur (.portal-reveal) est une couche plein écran,
   jamais mise à l'échelle, découpée par un disque dont main.js pilote le rayon
   et le centre. Deux raisons, toutes deux constatées :
     - une couche opaque, donc on ne lit jamais la page à travers le trou ;
     - un contenu à l'échelle 1, donc net. La version précédente agrandissait
       le contenu avec l'ouverture : on n'y voyait que des fragments de lettres
       géantes, et une contre-échelle CSS (scale(1/n)) le rendait illisible,
       le navigateur tramant la couche à sa petite échelle avant de l'agrandir.
   Corollaire : aucune opacité < 1 ne doit être posée sur le mot-marque ni sur
   un de ses ancêtres pendant la plongée — une couche translucide rendrait
   l'ouverture translucide avec elle, et la page repasserait à travers le trou.
   ========================================================= */

.portal-container {
  position: relative;
  width: 100%;
  /* 1 écran de repos + ~1 écran de plongée. Au-delà, le portail mange la page
     sans rien ajouter (il occupait 250vh, soit un tiers du document). */
  min-height: 210vh;
}

.portal-viewport {
  position: sticky;
  top: 0;
  left: 0;
  width: 100%;
  height: 100vh;
  height: 100svh;
  overflow: hidden;
  background: var(--bg);
  z-index: 5;
}

/* ---- Scène au repos ---------------------------------------------------- */

.hero {
  position: relative;
  width: 100%;
  /* Le mot-marque grandit jusqu'à couvrir l'écran : c'est ici qu'il est
     découpé, et nulle part ailleurs. */
  overflow: hidden;
}
.hero::before {
  content: "";
  position: absolute;
  top: -220px; right: -160px;
  width: 640px; height: 640px;
  background: radial-gradient(circle, rgba(159,227,0,0.35) 0%, rgba(159,227,0,0) 70%);
  filter: blur(10px);
  z-index: 0;
  pointer-events: none;
}
/* Le même halo sur fond sombre verdit tout l'écran : il faut l'assourdir. */
:root[data-theme="dark"] .hero::before {
  background: radial-gradient(circle, rgba(159,227,0,0.16) 0%, rgba(159,227,0,0) 70%);
}

.hero-stage {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: calc(var(--nav-h) + 10px) 0 24px;
}

.hero-inner {
  position: relative;
  z-index: 1;
  width: 100%;
  /* Sans min-width: 0, cet élément flex refuse de descendre sous la largeur
     mini de son contenu : à 390 px, le hero mesurait 498 px et se faisait
     COUPER par l'overflow:hidden du viewport — pas défiler, couper. */
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: clamp(16px, 2.2vh, 26px);
  text-align: center;
}

/* La question */
.hero-question {
  font-family: var(--font-sans);
  font-weight: 800;
  font-size: clamp(25px, min(5.2vw, 5.4vh), 54px);
  line-height: 1.1;
  letter-spacing: -0.03em;
  max-width: 880px;
  margin: 0;
  color: var(--ink);
  text-wrap: balance;
  will-change: transform, opacity;
}
.hero-question .accent {
  font-family: var(--font-display);
  font-style: italic;
  font-weight: 500;
  color: var(--lime-deep);
}
/* Le fil qui relie la question à la réponse */
.answer-cue {
  width: 1px;
  height: clamp(16px, 3vh, 38px);
  background: linear-gradient(to bottom, transparent, var(--line));
  flex-shrink: 0;
}

/* ---- La réponse : le mot-marque ---------------------------------------- */

.glyph-wordmark-wrap {
  position: relative;
  z-index: 3;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-sans);
  font-weight: 800;
  font-size: clamp(50px, min(14.5vw, 18vh), 164px);
  line-height: 0.84;
  letter-spacing: -0.045em;
  color: var(--ink);
  transform-origin: 50% 50%;
  will-change: transform;
  user-select: none;
}

.glyph-char {
  display: inline-block;
  position: relative;
}

/* Le « O » — l'ouverture */
.glyph-o-wrap {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  margin-left: 0.012em;
}

.glyph-o-outer {
  position: relative;
  display: inline-flex;
  width: 0.845em;
  height: 0.845em;
  border-radius: 50%;
  border: 0.175em solid var(--ink);
  overflow: hidden;
  background: var(--bg);
  isolation: isolate;
}

:root[data-theme="dark"] .glyph-o-outer {
  border-color: #FFFFFF;
  box-shadow: 0 0 50px rgba(184, 255, 0, 0.14);
}

/* La chambre intérieure. Opaque, sans exception : c'est cette opacité qui
   empêche de lire la page à travers le trou du O. Ne pas y remettre de
   couleur semi-transparente. */
/* LE « O » RESTE UNE LETTRE TANT QU'ON N'Y EST PAS ENTRÉ.
   On a essayé de le remplir de blanc pour que la plongée soit aussi un
   changement de couleur. Résultat : dès le premier écran, AVANT tout
   défilement, le mot-marque se lisait « KLASSI » suivi d'un disque blanc —
   le cerclage clair et l'intérieur clair se rejoignaient et la lettre
   disparaissait. Une ouverture ne doit se voir qu'en s'ouvrant.
   L'intérieur reprend donc le fond de la page : le « O » est un « O ». */
.glyph-o-interior {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  overflow: hidden;
  background: var(--bg);
}

/* Ce qu'on découvre en entrant. Couche plein écran, opaque, à l'échelle 1 :
   seule la découpe circulaire bouge. --portal-r / --portal-cx / --portal-cy
   sont posés par main.js et suivent exactement le trou du « O » à l'écran. */
.portal-reveal {
  position: absolute;
  inset: 0;
  z-index: 4;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: clamp(18px, 4vw, 48px);
  /* AU REPOS, CETTE COUCHE EST LE TROU DU « O » : main.js pose
     --portal-r = rayon du trou dès la première image, donc ce fond-ci est
     exactement ce qu'on voit dans la lettre avant tout défilement. La
     peindre en clair peignait le « O » en blanc. Elle suit le fond de la
     page, et c'est l'OUVERTURE — pas la couleur — qui raconte l'entrée. */
  background: var(--bg);
  clip-path: circle(var(--portal-r, 0px) at var(--portal-cx, 50%) var(--portal-cy, 50%));
  pointer-events: none;
  contain: paint;
}

.telemetry-grid {
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(to right, var(--line-soft) 1px, transparent 1px),
    linear-gradient(to bottom, var(--line-soft) 1px, transparent 1px);
  background-size: 48px 48px;
  opacity: 0.5;
  pointer-events: none;
}

/* Au repos l'ouverture ne fait que quelques dizaines de pixels : c'est ce
   halo qu'on y aperçoit, pas un morceau de texte. */
.portal-core-glow {
  position: absolute;
  inset: 0;
  /* Deux rayons FIXES, pas des pourcentages : en pourcentage le dégradé se
     mesure sur l'écran entier, et l'ouverture au repos (quelques dizaines de
     pixels) n'attrape qu'une teinte fade. Le petit cercle allume le hublot au
     repos, le grand donne l'atmosphère une fois grand ouvert. */
  background:
    radial-gradient(circle 92px at 50% 50%, rgba(184, 255, 0, 0.55) 0%, rgba(184, 255, 0, 0) 100%),
    radial-gradient(circle 520px at 50% 50%, rgba(184, 255, 0, 0.14) 0%, rgba(184, 255, 0, 0) 70%);
  pointer-events: none;
}

.telemetry-hud {
  position: relative;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(10px, 1.8vh, 18px);
  width: 100%;
  max-width: 980px;
  text-align: center;
  /* Révélé par main.js seulement quand l'ouverture est assez large pour
     qu'on lise autre chose qu'un fragment. */
  opacity: 0;
}

.hud-pill {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 16px;
  border-radius: 100px;
  background: rgba(184, 255, 0, 0.15);
  border: 1px solid rgba(184, 255, 0, 0.35);
  color: var(--forest-700);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

:root[data-theme="dark"] .hud-pill {
  color: var(--lime);
  border-color: rgba(184, 255, 0, 0.4);
}

.hud-pill .hud-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--lime);
  box-shadow: 0 0 8px var(--lime);
  animation: pulseDot 2s infinite ease-in-out;
}

@keyframes pulseDot {
  0%, 100% { opacity: 1; transform: scale(1); }
  50% { opacity: 0.35; transform: scale(0.75); }
}

.hud-headline {
  font-family: var(--font-sans);
  font-size: clamp(22px, 3.4vw, 40px);
  font-weight: 800;
  letter-spacing: -0.02em;
  line-height: 1.15;
  color: var(--ink);
  margin: 0;
}

.hud-headline .em {
  font-family: var(--font-display);
  font-style: italic;
  font-weight: 500;
  color: var(--lime-deep);
}

:root[data-theme="dark"] .hud-headline .em {
  color: var(--lime);
}

/* Le mock produit vit maintenant à l'intérieur du O : c'est ce qu'on trouve
   en entrant, et non plus une bande tronquée sous les boutons du hero. */
.portal-preview {
  width: 100%;
  max-width: 900px;
  margin: 0;
  /* Borné : sur un écran bas, un mock à sa taille naturelle pousse le titre
     hors du cadre. Tronqué, il se lit comme un aperçu — ce qu'il est. */
  max-height: min(54vh, 440px);
}

/* ---- Appui : sous-titre et boutons -------------------------------------- */

.hero-support {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(12px, 2vh, 22px);
  width: 100%;
  will-change: transform, opacity;
}

.hero-sub {
  max-width: 560px;
  margin: 0;
  font-size: clamp(14.5px, 1.5vw, 17.5px);
  line-height: 1.55;
  color: var(--ink-soft);
}

.hero-ctas {
  display: flex;
  align-items: center;
  justify-content: center;
  /* Deux boutons côte à côte mesurent ~498 px : sans repli, ils débordaient
     d'un téléphone de 390 px. */
  flex-wrap: wrap;
  gap: 12px;
  margin: 0;
}

/* ---- Replis : mouvement réduit, et page sans JavaScript ----------------- */

@media (prefers-reduced-motion: reduce) {
  .portal-container { min-height: auto !important; }
  .portal-viewport {
    position: relative !important;
    height: auto !important;
    overflow: visible !important;
  }
  .hero-stage {
    position: relative !important;
    inset: auto !important;
    padding: calc(var(--nav-h) + 48px) 0 80px !important;
  }
  .glyph-wordmark-wrap { transform: none !important; }
  .portal-reveal { display: none !important; }
  .glyph-o-interior { background: var(--surface-soft) !important; }
}

/* Product preview mock */
.preview-frame {
  position: relative;
  max-width: 980px;
  margin: 0 auto;
  border-radius: var(--radius-xl);
  background: var(--surface);
  box-shadow: var(--shadow-lg);
  border: 1px solid var(--line);
  overflow: hidden;
}
.preview-topbar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 14px 18px;
  border-bottom: 1px solid var(--line-soft);
  background: var(--surface-soft);
}
.preview-topbar span { width: 10px; height: 10px; border-radius: 50%; background: var(--line); }
.preview-body {
  display: grid;
  grid-template-columns: 220px 1fr;
  min-height: 420px;
}
.preview-side {
  background: var(--forest);
  padding: 22px 16px;
  color: var(--forest-tint);
}
.preview-side .p-logo { font-weight: 700; font-size: 14px; color: #fff; margin-bottom: 26px; padding-left: 8px; }
.preview-side .p-item {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 10px; border-radius: 10px;
  font-size: 13px; color: rgba(231,239,227,0.65);
  margin-bottom: 4px;
}
.preview-side .p-item.active { background: rgba(159,227,0,0.16); color: var(--lime); font-weight: 600; }
.preview-side .p-item .ic { width: 7px; height: 7px; border-radius: 2px; background: currentColor; opacity: 0.7; }
.preview-main { padding: 26px 28px; }
.preview-search {
  display: flex; align-items: center; gap: 10px;
  padding: 13px 18px; border-radius: 100px;
  background: var(--surface-soft); border: 1px solid var(--line);
  color: var(--ink-faint); font-size: 14px; margin-bottom: 22px;
}
.preview-cards { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; margin-bottom: 16px; }
.preview-card { padding: 16px; border-radius: 14px; background: var(--surface-soft); border: 1px solid var(--line-soft); }
.preview-card .k { font-size: 12px; color: var(--ink-faint); margin-bottom: 6px; }
.preview-card .v { font-size: 20px; font-weight: 700; }
.preview-card .v.lime { color: var(--lime-deep); }
.preview-row { height: 108px; border-radius: 14px; background: var(--surface-soft); border: 1px solid var(--line-soft); }

/* -------------------- Story sections -------------------- */
/* Les sections du récit n'étaient bornées par rien : le texte venait toucher
   le bord de l'écran à toutes les largeurs, et « Trésorerie » (positionné en
   right: -2%) sortait franchement du cadre. Même gabarit que .container. */
.story {
  max-width: var(--container);
  margin: 0 auto;
  padding: 30px 32px;
}
.story-section {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 72px;
  align-items: center;
  padding: 100px 0;
  border-top: 1px solid var(--line-soft);
}
.story-section:first-child { border-top: none; }
.story-section.reverse .story-visual { order: 2; }
.story-index {
  font-family: var(--font-display);
  font-style: italic;
  color: var(--lime-deep);
  font-size: 15px;
  margin-bottom: 14px;
  display: block;
}
.story-copy h2 {
  font-size: clamp(26px, 3.4vw, 36px);
  font-weight: 800;
  letter-spacing: -0.02em;
  line-height: 1.2;
  margin: 0 0 16px;
}
.story-copy p {
  font-size: 16.5px;
  line-height: 1.7;
  color: var(--ink-soft);
  max-width: 460px;
  margin: 0;
}
.story-visual { min-height: 300px; }

.reveal {
  opacity: 0;
  transform: translateY(28px);
  transition: opacity 0.8s var(--ease-out), transform 0.8s var(--ease-out);
}
.reveal.in-view { opacity: 1; transform: none; }

/* UN BLOC QUI CONTIENT DES MOTS ÉCHELONNÉS NE FAIT PAS DE FONDU.
   `.reveal` fait apparaître tout le bloc en 0,8 s. Quand ce bloc porte aussi
   un `[data-mo]`, les deux animations se superposent : le fondu global
   l'emporte visuellement et on ne voit plus les mots arriver un à un — juste
   un bloc qui apparaît. Ce sont les mots qui portent la révélation ; le
   conteneur, lui, est là dès le départ. */
.reveal:has([data-mo]) {
  opacity: 1;
  transform: none;
  transition: none;
}

/* visual: scattered tools (problem) */
.tools-chaos {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 16px;
}
/* Ces règles DOIVENT rester portées par .tools-chaos : le nom « chip » est
   aussi celui des pastilles de filtre des écrans de gestion, définies plus bas
   dans cette même feuille. À spécificité égale, c'est la dernière qui gagne —
   les cartes de la landing héritaient donc d'un padding de pastille, d'un
   rayon de 100px et d'un curseur « pointer » sur un élément non cliquable. */
.tools-chaos .chip {
  display: flex; align-items: center; gap: 14px;
  padding: 18px 20px;
  border-radius: 16px;
  background: var(--surface);
  border: 1px solid var(--line);
  box-shadow: var(--shadow-sm);
  cursor: default;
  transition: transform 0.25s var(--ease-out), box-shadow 0.25s var(--ease-out);
}
.tools-chaos .chip:hover { transform: translateY(-3px) rotate(0deg) !important; box-shadow: var(--shadow-md); }
.tools-chaos .chip.c1 { transform: rotate(-1.2deg); }
.tools-chaos .chip.c2 { transform: rotate(1deg); margin-top: 14px; }
.tools-chaos .chip.c3 { transform: rotate(0.8deg); }
.tools-chaos .chip.c4 { transform: rotate(-0.8deg); margin-top: 14px; }
.tools-chaos .chip.c5 { transform: rotate(-1deg); }
.tools-chaos .chip.c6 { transform: rotate(1.2deg); margin-top: 14px; }
.tools-chaos .chip .c-ic {
  flex-shrink: 0;
  width: 40px; height: 40px; border-radius: 11px;
  background: var(--surface-soft);
  display: flex; align-items: center; justify-content: center;
  font-size: 17px;
}
.tools-chaos .chip .c-label {
  font-size: 13.5px;
  font-weight: 600;
  color: var(--ink-soft);
  line-height: 1.4;
}

/* visual: centralize (vision) */
.hub {
  position: relative;
  height: 300px;
  display: flex; align-items: center; justify-content: center;
}
.hub-core {
  position: relative;
  width: 108px; height: 108px; border-radius: 26px;
  background: linear-gradient(145deg, var(--lime) 0%, var(--lime-strong) 100%);
  display: flex; align-items: center; justify-content: center;
  color: var(--forest); font-weight: 800; font-size: 13px;
  box-shadow: var(--shadow-glow);
  z-index: 2;
  text-align: center; line-height: 1.3;
}
.hub-core-label { position: relative; z-index: 2; }
/* LE LOGO REMPLACE LE MOT.
   « Source unique » nommait ce que le schéma montre déjà : tout converge vers
   le centre. Le logo dit la même chose sans le dire, et rattache la
   démonstration au produit. Mêmes dimensions que le carré qu'il remplace —
   le reste de la composition ne bouge pas d'un pixel. */
.hub-core-logo {
  position: relative;
  z-index: 2;
  width: 76px;
  height: 76px;
  object-fit: contain;
  /* Le noyau est vert vif : le logo y serait noyé. On l'assombrit pour qu'il
     se lise comme une marque posée dessus, pas comme une image collée. */
  filter: brightness(0) saturate(100%) invert(9%) sepia(28%) saturate(1200%) hue-rotate(96deg) brightness(95%);
}

/* L'onde qui part du noyau chaque fois qu'un satellite en sort. Elle est
   pilotée par --hub-pulse (0 → 1) plutôt que par une animation en boucle :
   l'effet appartient au défilement, pas à une horloge. */
.hub-pulse {
  position: absolute;
  inset: 0;
  border-radius: inherit;
  border: 2px solid var(--lime-strong);
  opacity: calc(1 - var(--hub-pulse, 1));
  transform: scale(calc(1 + var(--hub-pulse, 1) * 1.15));
  pointer-events: none;
  z-index: 1;
}

.hub-node {
  position: absolute;
  padding: 9px 14px;
  border-radius: 10px;
  background: var(--surface);
  border: 1px solid var(--line);
  font-size: 12.5px;
  font-weight: 600;
  color: var(--ink-soft);
  box-shadow: var(--shadow-sm);
  /* État d'ARRIVÉE décrit ici ; le départ (collé au noyau) est calculé par
     main.js, qui seul connaît la distance réelle de chaque satellite. */
  will-change: transform, opacity;
}

/* Le satellite tout juste sorti est mis en avant un court instant. */
.hub-node.emitting {
  border-color: var(--lime-strong);
  color: var(--ink);
  box-shadow: var(--shadow-md), 0 0 0 3px rgba(184, 255, 0, 0.18);
}

.hub svg.lines { position: absolute; inset: 0; width: 100%; height: 100%; z-index: 1; overflow: visible; }
.hub-line {
  stroke: var(--line);
  stroke-width: 1.5;
  fill: none;
  /* pathLength="1" dans le balisage : le trait se dessine du noyau vers
     l'extérieur par un simple décalage de 1 vers 0. */
  stroke-dasharray: 1;
  stroke-dashoffset: var(--hl, 0);
}

/* Notifications de la démonstration — même grammaire visuelle que les listes
   de l'application, avec l'audience rendue explicite : c'est le point du
   chapitre (personne ne reçoit ce qui ne le regarde pas). */
.demo-notif {
  display: flex; align-items: flex-start; gap: 13px;
  padding: 14px 0;
}
.demo-notif + .demo-notif { border-top: 1px solid var(--line-soft); }
.demo-notif .dn-ic {
  flex-shrink: 0; width: 34px; height: 34px; border-radius: 10px;
  display: flex; align-items: center; justify-content: center; font-size: 15px;
  background: var(--lime-tint); border: 1px solid var(--line-soft);
}
.demo-notif .dn-body { min-width: 0; }
.demo-notif .dn-title { font-size: 14px; font-weight: 700; color: var(--ink); margin-bottom: 3px; }
.demo-notif .dn-text { font-size: 13.5px; line-height: 1.55; color: var(--ink-soft); }
.demo-notif .dn-meta { font-size: 12px; color: var(--ink-faint); margin-top: 5px; }

/* -------------------- Bande de capacités (bandeau défilant) --------------

   Elle vivait auparavant DANS la colonne d'une section en grille : elle
   partageait donc sa ligne avec un paragraphe, et la mise en page cassait.
   Une bande défilante ne peut pas cohabiter avec du texte sur la même ligne —
   elle occupe maintenant toute la largeur, seule, entre deux sections.

   Le contenu est le vocabulaire réel du produit. Aucun nom d'établissement
   partenaire n'y figure : rien n'est inventé tant qu'aucun partenariat n'est
   signé. */
.capability-band {
  padding: clamp(26px, 4vw, 40px) 0;
  border-top: 1px solid var(--line-soft);
  border-bottom: 1px solid var(--line-soft);
  background: var(--surface-soft);
  overflow: hidden;
}
.band-label {
  display: block;
  text-align: center;
  margin: 0 0 clamp(16px, 2.4vw, 24px);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-soft);
}
.logo-marquee {
  overflow: hidden;
  -webkit-mask-image: linear-gradient(90deg, transparent, black 10%, black 90%, transparent);
  mask-image: linear-gradient(90deg, transparent, black 10%, black 90%, transparent);
}
.logo-track {
  display: flex; align-items: center; width: max-content;
  animation: marqueeScroll 48s linear infinite;
}
.band-word {
  flex-shrink: 0;
  display: inline-flex; align-items: center; gap: clamp(20px, 3vw, 34px);
  padding-right: clamp(20px, 3vw, 34px);
  font-size: clamp(15px, 1.6vw, 20px);
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--ink);
  white-space: nowrap;
}
/* Le séparateur est décoratif : il ne doit pas être lu à voix haute, d'où
   l'usage d'un ::after plutôt que d'un caractère dans le texte. */
.band-word::after {
  content: "";
  flex-shrink: 0;
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--lime-strong);
}
@keyframes marqueeScroll { from { transform: translateX(0); } to { transform: translateX(-50%); } }
@media (prefers-reduced-motion: reduce) {
  .logo-track { animation: none; }
  .logo-marquee { overflow-x: auto; }
}

/* visual: la réalité locale (section « Pensé pour Kinshasa »)
   Chaque carte glisse depuis un côté, en alternance, au rythme du défilement,
   puis se fixe. --rc-p (0 → 1) est posé par main.js ; overflow-x: clip sur le
   conteneur empêche l'entrée de créer une barre de défilement horizontale. */
.local-reality {
  display: grid;
  gap: 14px;
  overflow-x: clip;
}
.reality-card {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 18px 20px;
  border-radius: 16px;
  background: var(--surface);
  border: 1px solid var(--line);
  box-shadow: var(--shadow-sm);
  transform: translateX(calc(var(--rc-dir, 1) * (1 - var(--rc-p, 1)) * 115%));
  opacity: var(--rc-p, 1);
  will-change: transform, opacity;
}
.reality-card[data-from="left"] { --rc-dir: -1; }
.reality-card[data-from="right"] { --rc-dir: 1; }
.reality-card .rc-ic {
  flex-shrink: 0;
  width: 40px; height: 40px; border-radius: 11px;
  background: var(--surface-soft);
  display: flex; align-items: center; justify-content: center;
  font-size: 17px;
}
.reality-card .rc-label {
  font-size: 13.5px;
  font-weight: 600;
  color: var(--ink-soft);
  line-height: 1.45;
}


/* visual: intelligence (search + AI) */
.ai-visual {
  border-radius: 20px; border: 1px solid var(--line); background: var(--surface);
  box-shadow: var(--shadow-md); padding: 22px; position: relative;
}
.ai-bar {
  display: flex; align-items: center; gap: 10px;
  padding: 14px 18px; border-radius: 100px;
  background: var(--surface-soft); border: 1px solid var(--line);
  font-size: 14px; color: var(--ink); margin-bottom: 16px;
}
.ai-answer {
  border-radius: 14px; padding: 14px 16px; font-size: 13.5px;
  line-height: 1.55; color: var(--ink-soft); background: var(--surface-soft);
  border: 1px solid var(--line-soft); margin-bottom: 12px;
}
.ai-answer strong { color: var(--ink); }
.ai-insight-preview {
  display: flex; align-items: center; gap: 10px;
  padding: 12px 16px; border-radius: 14px;
  background: var(--forest-tint); color: var(--forest-700);
  font-size: 12.5px; line-height: 1.5;
}
.ai-insight-preview span { flex-shrink: 0; }

/* visual: trust */
/* -------------------- 05 — Le décompte de la confiance -------------------

   Les quatre garanties se présentent une à une : celle du moment est nette et
   numérotée, les autres restent en retrait, floues. Il faut du défilement pour
   égrener quatre étapes, d'où la piste (.trust-runway) et la grille épinglée.
   Sans JavaScript ni en mouvement réduit, tout redevient une grille ordinaire
   et parfaitement lisible — voir les replis en fin de fichier. */

.trust-section { align-items: start; }
.trust-section .story-copy { position: sticky; top: calc(var(--nav-h) + 40px); }

.trust-runway { min-height: 200vh; }
.trust-grid {
  position: sticky;
  top: calc(var(--nav-h) + 40px);
  display: grid; grid-template-columns: 1fr 1fr; gap: 14px;
}

.trust-card {
  position: relative;
  border-radius: 16px; border: 1px solid var(--line); background: var(--surface);
  padding: 18px; box-shadow: var(--shadow-sm);
  /* Les cartes en attente s'effacent ; l'active reprend toute sa netteté.
     Les valeurs sont posées par main.js sur chaque carte. */
  filter: blur(var(--tc-blur, 0px));
  opacity: var(--tc-op, 1);
  transform: scale(var(--tc-scale, 1));
  transition: filter 0.45s var(--ease-out), opacity 0.45s var(--ease-out),
              transform 0.45s var(--ease-out), border-color 0.45s var(--ease-out),
              box-shadow 0.45s var(--ease-out);
}
.trust-card.active {
  border-color: var(--lime-strong);
  box-shadow: var(--shadow-md), 0 0 0 3px rgba(184, 255, 0, 0.16);
}
.trust-card .tc-num {
  position: absolute;
  top: 14px; right: 16px;
  font-size: 13px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  color: var(--ink-faint);
  opacity: 0.45;
  transition: color 0.45s var(--ease-out), opacity 0.45s var(--ease-out);
}
.trust-card.active .tc-num { color: var(--lime-deep); opacity: 1; }
:root[data-theme="dark"] .trust-card.active .tc-num { color: var(--lime); }

.trust-card .ic {
  width: 34px; height: 34px; border-radius: 10px; margin-bottom: 12px;
  background: var(--forest-tint); display: flex; align-items: center; justify-content: center;
  color: var(--forest-700);
}
.trust-card h4 { font-size: 14.5px; margin: 0 0 4px; font-weight: 700; }
.trust-card p { font-size: 12.5px; color: var(--ink-faint); margin: 0; line-height: 1.5; }

/* Le compteur, dans la colonne de texte : où en est-on des quatre. */
.trust-progress {
  display: flex; align-items: baseline; gap: 4px;
  margin: 26px 0 0;
  font-variant-numeric: tabular-nums;
  line-height: 1;
}
.trust-progress .tp-current {
  font-size: 42px; font-weight: 800; letter-spacing: -0.03em;
  color: var(--lime-deep);
}
:root[data-theme="dark"] .trust-progress .tp-current { color: var(--lime); }
.trust-progress .tp-sep,
.trust-progress .tp-total { font-size: 17px; font-weight: 700; color: var(--ink-faint); }

/* -------------------- Nappe (unrolling feature banner) -------------------- */
.nappe-section { padding: 60px 0 120px; }
.nappe-heading { text-align: center; max-width: 640px; margin: 0 auto 48px; }
.nappe-heading .story-index { text-align: center; }
.nappe-heading h2 { font-size: clamp(26px, 3.4vw, 38px); font-weight: 800; letter-spacing: -0.02em; margin: 0 0 12px; }
.nappe-heading p { color: var(--ink-soft); font-size: 16px; margin: 0; }

.nappe-wrap { max-width: 980px; margin: 0 auto; perspective: 1400px; }
.nappe {
  position: relative;
  border-radius: var(--radius-xl);
  background: linear-gradient(160deg, var(--forest) 0%, var(--forest-800) 100%);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
  transform-origin: top center;
  transform: scaleY(0.04);
  opacity: 0;
  transition: transform 1.1s var(--ease-out), opacity 0.6s ease;
}
.nappe.unroll { transform: scaleY(1); opacity: 1; }
.nappe-fold {
  position: absolute; top: 0; left: 0; right: 0; height: 10px;
  background: linear-gradient(90deg, var(--lime) 0%, var(--gold) 100%);
}
.nappe-content {
  padding: 56px 48px 48px;
  opacity: 0;
  transition: opacity 0.6s ease 0.5s;
}
.nappe.unroll .nappe-content { opacity: 1; }
.nappe-content > p.lead {
  color: rgba(231,239,227,0.7);
  font-size: 14px; text-transform: uppercase; letter-spacing: 0.08em; font-weight: 700;
  margin: 0 0 26px;
}
.feature-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 14px;
}
.feature-chip {
  background: rgba(255,255,255,0.06);
  border: 1px solid rgba(255,255,255,0.1);
  border-radius: 14px;
  padding: 18px 16px;
  color: #fff;
  opacity: 0;
  transform: translateY(14px);
  transition: opacity 0.55s var(--ease-out), transform 0.55s var(--ease-out), background 0.2s ease, border-color 0.2s ease;
}
.nappe.unroll .feature-chip { opacity: 1; transform: none; }
.feature-chip:hover { background: rgba(159,227,0,0.12); border-color: rgba(159,227,0,0.35); }
.feature-chip .ic {
  width: 30px; height: 30px; border-radius: 9px;
  background: rgba(159,227,0,0.16); color: var(--lime);
  display: flex; align-items: center; justify-content: center;
  margin-bottom: 14px;
}
.feature-chip h5 { margin: 0 0 4px; font-size: 14px; font-weight: 700; }
.feature-chip p { margin: 0; font-size: 12px; color: rgba(231,239,227,0.62); line-height: 1.5; }

/* -------------------- Final CTA -------------------- */
.final-cta {
  margin: 20px auto 100px;
  max-width: var(--container);
  padding: 0 32px;
}
.cta-box {
  border-radius: var(--radius-xl);
  background: var(--lime-tint);
  padding: 72px 48px;
  text-align: center;
  position: relative;
  overflow: hidden;
  border: 1px solid rgba(124,196,0,0.25);
}
.cta-box h2 {
  font-size: clamp(28px, 4vw, 42px);
  font-weight: 800; letter-spacing: -0.02em;
  margin: 0 0 14px;
  position: relative; z-index: 1;
}
.cta-box p { color: var(--forest-700); font-size: 16px; margin: 0 0 32px; position: relative; z-index: 1; }
.cta-actions { display: flex; align-items: center; justify-content: center; gap: 14px; position: relative; z-index: 1; }

/* -------------------- Footer -------------------- */
footer { border-top: 1px solid var(--line-soft); padding: 56px 0 40px; }
.footer-top { display: flex; justify-content: space-between; align-items: flex-start; gap: 40px; flex-wrap: wrap; margin-bottom: 40px; }
.footer-tag { max-width: 300px; color: var(--ink-faint); font-size: 14px; line-height: 1.6; margin-top: 10px; }
.footer-cols { display: flex; gap: 64px; flex-wrap: wrap; }
.footer-col h5 { font-size: 12.5px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--ink-faint); margin: 0 0 14px; }
.footer-col a { display: block; font-size: 14px; color: var(--ink-soft); margin-bottom: 10px; }
.footer-col a:hover { color: var(--ink); }
.footer-bottom { display: flex; justify-content: space-between; align-items: center; padding-top: 26px; border-top: 1px solid var(--line-soft); font-size: 13px; color: var(--ink-faint); }

/* -------------------- Responsive -------------------- */
@media (max-width: 920px) {
  .story-section { grid-template-columns: 1fr; gap: 36px; padding: 64px 0; }
  .trust-runway { min-height: 160vh; }
  .trust-section .story-copy { position: static; }
  .story-section.reverse .story-visual { order: 0; }
  .preview-body { grid-template-columns: 1fr; }
  .preview-side { display: none; }
  .feature-grid { grid-template-columns: repeat(2, 1fr); }
  .trust-grid { grid-template-columns: 1fr; }
  .nav-links { display: none; }
}
/* L'îlot de navigation mesure ~508 px ; avec la marque (104 px) et les actions
   de droite (~300 px), il lui faut au moins 1060 px pour respirer. Il se
   masquait à 920 px : entre les deux, il touchait la marque. On le retire au
   moment où il cesse de tenir, pas 140 px trop tard. */
@media (max-width: 1060px) {
  .nav-links { display: none; }
}
/* À 375 px, la barre de navigation mesurait 452 px de contenu pour 383 px de
   large : le bouton « Commencer » — l'action principale de la page — sortait
   de l'écran et devenait invisible. On resserre, et le nom de la marque cède
   la place à sa seule pastille (qui reste un lien vers l'accueil). */
@media (max-width: 480px) {
  .navbar { padding: 12px 16px; }
  .nav-actions { gap: 7px; }
  /* font-size: 0 masque le nœud texte sans toucher à l'image : la pastille
     reste cliquable et reste le lien d'accueil. Portée limitée à la barre —
     le pied de page garde son nom en entier. */
  .navbar .brand { font-size: 0; gap: 0; }
  .navbar .brand-mark { width: 28px; height: 28px; }
  .navbar .btn-sm { padding: 8px 12px; font-size: 12.5px; }
}

@media (max-width: 600px) {
  .container { padding: 0 20px; }
  .story { padding: 30px 20px; }
  .preview-cards { grid-template-columns: 1fr; }
  .feature-grid { grid-template-columns: 1fr; }
  .footer-top { flex-direction: column; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  * { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; }

  /* Les trois effets du récit s'effacent : l'étoile est complète, les cartes
     sont en place, les quatre garanties sont nettes en même temps. Rien n'est
     caché — un mouvement en moins ne doit jamais coûter une information. */
  .hub-node { transform: none !important; opacity: 1 !important; }
  .hub-line { stroke-dashoffset: 0 !important; }
  .hub-pulse { display: none !important; }
  .reality-card { transform: none !important; opacity: 1 !important; }
  .trust-runway { min-height: 0 !important; }
  .trust-grid, .trust-section .story-copy { position: static !important; }
  .trust-card { filter: none !important; opacity: 1 !important; transform: none !important; }
  .trust-progress { display: none !important; }
}

/* =========================================================
   APP SHELL — inscription / connexion / dashboard
   ========================================================= */

.auth-page {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  background: var(--bg);
}
.auth-topbar {
  display: flex; align-items: center; justify-content: space-between;
  padding: 22px 32px;
}
.auth-main {
  flex: 1;
  display: flex; align-items: center; justify-content: center;
  padding: 20px 20px 80px;
}
.auth-card {
  width: 100%; max-width: 620px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-md);
  padding: 48px 44px;
  position: relative;
  overflow: hidden;
}
.auth-step { animation: stepIn 0.5s var(--ease-out); }
@keyframes stepIn { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }
.auth-kicker { font-size: 13px; font-weight: 700; letter-spacing: 0.05em; text-transform: uppercase; color: var(--lime-deep); margin-bottom: 10px; }
.auth-card h1 { font-size: 26px; font-weight: 800; letter-spacing: -0.02em; margin: 0 0 8px; }
.auth-card .sub { color: var(--ink-soft); font-size: 15px; margin: 0 0 30px; }

.role-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.role-card {
  display: flex; align-items: center; gap: 12px;
  padding: 16px 16px; border-radius: 14px;
  border: 1.5px solid var(--line);
  background: var(--surface);
  text-align: left;
  transition: border-color 0.2s ease, background 0.2s ease, transform 0.15s ease;
}
.role-card:hover { border-color: var(--lime-strong); background: var(--lime-tint); transform: translateY(-1px); }
.role-card.selected { border-color: var(--lime-strong); background: var(--lime-tint); box-shadow: 0 0 0 3px rgba(159,227,0,0.18); }
.role-card .r-ic { font-size: 20px; width: 38px; height: 38px; border-radius: 10px; background: var(--forest-tint); display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
.role-card .r-text { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.role-card .r-label { display: block; font-size: 14.5px; font-weight: 700; color: var(--ink); line-height: 1.3; }
.role-card .r-desc { display: block; font-size: 12px; color: var(--ink-faint); }

.field { margin-bottom: 16px; }
.field label { display: block; font-size: 13px; font-weight: 600; color: var(--ink-soft); margin-bottom: 7px; }
.field input, .field select {
  width: 100%; padding: 12px 14px; border-radius: 10px;
  border: 1.5px solid var(--line); background: var(--surface-soft);
  font-size: 14.5px; font-family: inherit; color: var(--ink);
  transition: border-color 0.2s ease, background 0.2s ease;
}
.field input:focus, .field select:focus { outline: none; border-color: var(--lime-strong); background: var(--surface); }
.field-row { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }

.pw-rules { list-style: none; margin: 9px 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: 6px 14px; }
.pw-rules li { font-size: 12px; color: var(--ink-faint); display: flex; align-items: center; gap: 5px; transition: color 0.15s ease; }
.pw-rules li::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--line); flex-shrink: 0; transition: background 0.15s ease; }
.pw-rules li.met { color: var(--forest-700); font-weight: 600; }
.pw-rules li.met::before { background: var(--lime-strong); }

.auth-actions { display: flex; align-items: center; justify-content: space-between; margin-top: 26px; gap: 12px; }
.auth-back { font-size: 13.5px; font-weight: 600; color: var(--ink-faint); display: flex; align-items: center; gap: 6px; }
.auth-back:hover { color: var(--ink); }
.step-dots { display: flex; gap: 6px; justify-content: center; margin-top: 28px; }
.step-dots span { width: 6px; height: 6px; border-radius: 50%; background: var(--line); transition: background 0.2s ease, width 0.2s ease; }
.step-dots span.active { background: var(--lime-strong); width: 18px; border-radius: 3px; }

/* Import-based space creation (alternative onboarding) */
.import-option { margin-top: 22px; }
.import-divider { display: flex; align-items: center; gap: 12px; margin-bottom: 16px; }
.import-divider::before, .import-divider::after { content: ""; flex: 1; height: 1px; background: var(--line); }
.import-divider span { font-size: 12px; font-weight: 600; color: var(--ink-faint); text-transform: uppercase; letter-spacing: 0.05em; }
.import-card {
  width: 100%; display: flex; align-items: center; gap: 14px;
  padding: 16px 18px; border-radius: 14px;
  border: 1.5px dashed var(--line);
  background: var(--surface-soft);
  text-align: left;
  transition: border-color 0.2s ease, background 0.2s ease;
}
.import-card:hover { border-color: var(--lime-strong); background: var(--lime-tint); border-style: solid; }
.import-ic { width: 38px; height: 38px; border-radius: 10px; background: var(--surface); border: 1px solid var(--line); display: flex; align-items: center; justify-content: center; font-size: 17px; flex-shrink: 0; }
.import-text { display: flex; flex-direction: column; gap: 3px; flex: 1; min-width: 0; }
.import-title { font-size: 13.5px; font-weight: 700; color: var(--ink); }
.import-sub { font-size: 12px; color: var(--ink-faint); line-height: 1.4; }
.import-arrow { color: var(--ink-faint); font-size: 15px; }

.import-pipeline {
  margin-top: 18px; padding: 20px; border-radius: 14px;
  background: var(--forest); color: #fff;
  display: none;
}
.import-pipeline.shown { display: block; animation: stepIn 0.4s var(--ease-out); }
.import-pipeline .ip-title { font-size: 12.5px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; color: var(--lime); margin-bottom: 14px; }
.import-pipeline .ip-steps { display: flex; align-items: center; justify-content: space-between; }
.import-pipeline .ip-step { display: flex; flex-direction: column; align-items: center; gap: 8px; font-size: 11px; color: rgba(231,239,227,0.6); flex: 1; }
.import-pipeline .ip-dot { width: 26px; height: 26px; border-radius: 50%; background: rgba(255,255,255,0.1); display: flex; align-items: center; justify-content: center; font-size: 12px; }
.import-pipeline .ip-line { flex: 1; height: 1px; background: rgba(255,255,255,0.15); margin: 0 4px; margin-bottom: 20px; }
.import-pipeline .ip-note { margin-top: 16px; font-size: 12px; color: rgba(231,239,227,0.65); line-height: 1.5; text-align: center; }

/* Sidebar reveal — appears only once space is created */
.space-reveal { text-align: center; }
.space-reveal .check {
  width: 64px; height: 64px; border-radius: 50%;
  background: var(--lime-tint); color: var(--lime-deep);
  display: flex; align-items: center; justify-content: center;
  font-size: 28px; margin: 0 auto 20px;
}
.mini-shell {
  margin-top: 26px; border: 1px solid var(--line); border-radius: 16px;
  overflow: hidden; display: flex; height: 240px; background: var(--surface-soft);
  position: relative;
}
.mini-sidebar {
  width: 200px; background: var(--forest); color: #fff; padding: 16px 12px;
  transform: translateX(-100%); opacity: 0;
  transition: transform 0.55s var(--ease-out), opacity 0.4s ease;
  flex-shrink: 0;
}
.mini-sidebar.shown { transform: translateX(0); opacity: 1; }
.mini-sidebar .m-item { padding: 9px 12px; border-radius: 8px; font-size: 12.5px; line-height: 1.4; margin-bottom: 3px; color: rgba(231,239,227,0.7); }
.mini-sidebar .m-item.active { background: rgba(159,227,0,0.16); color: var(--lime); font-weight: 700; }
.mini-main { flex: 1; padding: 18px; display: flex; flex-direction: column; align-items: flex-start; gap: 10px; }
.mini-toggle {
  position: absolute; top: 10px; left: 10px; z-index: 3;
  width: 30px; height: 30px; border-radius: 8px;
  background: var(--surface); border: 1px solid var(--line);
  display: flex; align-items: center; justify-content: center; font-size: 14px;
  transition: left 0.55s var(--ease-out);
}
.mini-toggle.shifted { left: 212px; }

/* ---------- Dashboard shell ---------- */
.app-shell { display: flex; min-height: 100vh; background: var(--bg); }

.sidebar {
  width: 248px; flex-shrink: 0;
  background: var(--forest); color: rgba(231,239,227,0.85);
  padding: 20px 14px; position: sticky; top: 0; height: 100vh;
  display: flex; flex-direction: column;
  transition: margin-left 0.32s cubic-bezier(0.16, 1, 0.3, 1), opacity 0.25s ease, box-shadow 0.3s ease;
  overflow: hidden;
  z-index: 50;
  box-shadow: 4px 0 24px rgba(0, 0, 0, 0.15);
}
/* REPLIÉE VEUT DIRE ABSENTE, PAS SEULEMENT INVISIBLE.
   `opacity: 0` seul laissait la barre dans le flux du clavier et sous le
   curseur : on tabulait dans un menu qu'on ne voyait pas, et un clic au bord
   gauche atteignait des liens invisibles. `visibility: hidden` la retire de
   l'ordre de tabulation ; la transition la conserve jusqu'à la fin du
   glissement pour que le repli reste animé. */
.sidebar.collapsed {
  margin-left: -248px;
  opacity: 0;
  box-shadow: none;
  visibility: hidden;
  pointer-events: none;
  transition: margin-left 0.26s var(--ease-out), opacity 0.26s var(--ease-out),
              visibility 0s linear 0.26s;
}
.sidebar {
  transition: margin-left 0.26s var(--ease-out), opacity 0.26s var(--ease-out),
              visibility 0s;
}
/* Le clavier n'a pas de survol : si le focus entre dans la barre par le
   bouton de menu, elle doit se montrer d'elle-même. */
.sidebar:focus-within {
  margin-left: 0;
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
}
.sidebar .s-brand { display: flex; align-items: center; gap: 9px; color: #fff; font-weight: 800; font-size: 15px; padding: 4px 8px 22px; }
.sidebar .s-brand .brand-mark { width: 26px; height: 26px; }
/* Le menu DÉFILE quand il est plus haut que l'écran.

   Sans cela : `.sidebar` est en `height: 100vh; overflow: hidden`, et son nav
   n'avait aucun débordement — les derniers éléments du menu Direction (seize
   entrées : Abonnement, Paramètres…) étaient simplement COUPÉS, sans barre ni
   indice, dès que la fenêtre manquait de hauteur : portable 768 px, navigateur
   zoomé, fenêtre réduite. Une entrée de menu inatteignable est une
   fonctionnalité perdue.

   `min-height: 0` est indispensable : un enfant flex refuse par défaut de
   descendre sous la hauteur de son contenu, et `overflow-y` ne s'enclenche
   jamais sans lui. */
.sidebar nav {
  display: flex; flex-direction: column; gap: 2px;
  flex: 1; min-height: 0; overflow-y: auto;
  scrollbar-width: thin; scrollbar-color: rgba(231,239,227,0.25) transparent;
}
.sidebar nav::-webkit-scrollbar { width: 6px; }
.sidebar nav::-webkit-scrollbar-thumb { background: rgba(231,239,227,0.22); border-radius: 100px; }
.sidebar nav::-webkit-scrollbar-track { background: transparent; }
.s-item {
  display: flex; align-items: center; gap: 11px;
  padding: 10px 12px; border-radius: 10px; font-size: 13.5px; font-weight: 500;
  color: rgba(231,239,227,0.68);
  transition: background 0.15s ease, color 0.15s ease;
}
.s-item .s-ic { width: 18px; text-align: center; font-size: 14px; }
.s-item:hover { background: rgba(255,255,255,0.06); color: #fff; }
.s-item.active { background: rgba(159,227,0,0.16); color: var(--lime); font-weight: 700; }
.sidebar .s-role {
  margin-top: auto; padding: 12px; border-radius: 12px;
  background: rgba(255,255,255,0.05); font-size: 12px; color: rgba(231,239,227,0.6);
}
.sidebar .s-role strong { display: block; color: #fff; font-size: 13px; margin-bottom: 2px; }

.main-col { flex: 1; min-width: 0; }
.topbar {
  display: flex; align-items: center; justify-content: space-between;
  padding: 16px 32px; border-bottom: 1px solid var(--line-soft);
  position: sticky; top: 0; background: rgba(250,248,239,0.9); backdrop-filter: blur(10px); z-index: 20;
}
.topbar-left { display: flex; align-items: center; gap: 14px; }
.icon-btn {
  width: 38px; height: 38px; border-radius: 10px; border: 1px solid var(--line);
  background: var(--surface); display: flex; align-items: center; justify-content: center;
  font-size: 15px; color: var(--ink-soft); flex-shrink: 0;
  transition: background 0.15s ease, border-color 0.15s ease;
}
.icon-btn:hover { background: var(--surface-soft); border-color: var(--ink-faint); }
.topbar-right { display: flex; align-items: center; gap: 12px; }
.school-badge {
  display: flex; flex-direction: column; line-height: 1.25; padding-left: 14px;
  border-left: 1px solid var(--line); margin-left: 2px;
}
.school-badge .sb-kicker { font-size: 10.5px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: var(--ink-faint); }
.school-badge .sb-name { font-size: 13.5px; font-weight: 700; color: var(--ink); }

/* ---- Fil d'Ariane de la topbar ----
   La topbar portait « Klassio » et le nom de l'établissement — les deux mêmes
   informations que la barre latérale, à vingt centimètres. Elle dit désormais
   OÙ L'ON EST. Sur petit écran le détail passe avant la section : « 6e A »
   compte plus que « Élèves & classes » quand la place manque. */
.topbar-context { display: flex; align-items: center; gap: 8px; min-width: 0; font-size: 13.5px; }
.topbar-context .tc-section { font-weight: 700; color: var(--ink-soft); white-space: nowrap; }
.topbar-context .tc-sep { display: inline-flex; color: var(--ink-faint); flex: 0 0 auto; }
.topbar-context .tc-detail { font-weight: 700; color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* Historique des invitations closes — replié par défaut : c'est une archive,
   pas une file de travail. */
.inv-historique { margin-top: 16px; border-top: 1px solid var(--line-soft); padding-top: 12px; }
.inv-historique > summary { cursor: pointer; font-size: 13px; font-weight: 700; color: var(--ink-soft); list-style: none; display: flex; align-items: center; gap: 8px; }
.inv-historique > summary::before { content: "▸"; font-size: 11px; transition: transform 0.15s ease; }
.inv-historique[open] > summary::before { transform: rotate(90deg); }
.inv-historique > summary:hover { color: var(--ink); }
.inv-historique > summary:focus-visible { box-shadow: var(--focus); border-radius: 6px; }
.inv-historique .table-wrap { margin-top: 10px; }
@media (max-width: 560px) {
  .topbar-context .tc-section, .topbar-context .tc-sep { display: none; }
  .topbar-context .tc-detail { font-size: 13px; }
  .topbar-context:not(:has(.tc-detail)) .tc-section { display: inline; }
}

/* -------------------- Compte dans la barre latérale --------------------
   Le compte a quitté le coin de la topbar : nom, rôle, établissement, puis
   Paramètres / Abonnement / Déconnexion. La topbar ne garde que la cloche. */
.s-account { position: relative; margin-top: 10px; flex-shrink: 0; }
.s-account-btn {
  display: flex; align-items: center; gap: 10px; width: 100%;
  padding: 10px; border: none; border-radius: 12px; cursor: pointer;
  background: rgba(255,255,255,0.05); color: inherit; font: inherit; text-align: left;
  transition: background 0.2s ease;
}
.s-account-btn:hover { background: rgba(255,255,255,0.10); }
.s-account-btn:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--lime-strong); }
.s-account .s-av {
  flex-shrink: 0; width: 32px; height: 32px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--lime); color: var(--forest); font-weight: 800; font-size: 13.5px;
}
.s-account .s-acc-id { min-width: 0; flex: 1; display: flex; flex-direction: column; }
.s-account .s-acc-id strong {
  font-size: 13px; color: #fff; font-weight: 700;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.s-account .s-acc-id span {
  font-size: 11.5px; color: rgba(231,239,227,0.6);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.s-account .s-acc-chev { flex-shrink: 0; color: rgba(231,239,227,0.5); transition: transform 0.25s ease; }
.s-account.open .s-acc-chev { transform: rotate(180deg); }

.s-account-menu {
  position: absolute; bottom: calc(100% + 6px); left: 0; right: 0;
  background: var(--forest-800, #10241A); border: 1px solid rgba(255,255,255,0.10);
  border-radius: 12px; padding: 6px; z-index: 30;
  box-shadow: 0 18px 40px -12px rgba(0,0,0,0.6);
  display: flex; flex-direction: column; gap: 2px;
}
.s-acc-item {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 11px; border: none; border-radius: 9px; width: 100%;
  background: none; color: rgba(231,239,227,0.85); font: inherit; font-size: 13px;
  text-align: left; cursor: pointer; transition: background 0.15s ease, color 0.15s ease;
}
.s-acc-item:hover { background: rgba(255,255,255,0.08); color: #fff; }
.s-acc-item:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--lime-strong); }

/* -------------------- Apparence (Paramètres) -------------------- */
.theme-choice { display: flex; flex-wrap: wrap; gap: 10px; }
.theme-choice button {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 16px 10px 10px; border-radius: 12px;
  border: 1.5px solid var(--line); background: var(--surface);
  font: inherit; font-size: 13.5px; font-weight: 600; color: var(--ink);
  cursor: pointer; transition: border-color 0.2s ease, box-shadow 0.2s ease;
}
.theme-choice button:hover { border-color: var(--ink-faint); }
.theme-choice button.active { border-color: var(--lime-strong); box-shadow: 0 0 0 3px rgba(184,255,0,0.18); }
.theme-choice button:focus-visible { outline: none; box-shadow: var(--focus); }
.theme-choice .tc-sample {
  width: 30px; height: 22px; border-radius: 6px; flex-shrink: 0;
  border: 1px solid var(--line);
}
.theme-choice .tc-light { background: #F7F7F2; }
.theme-choice .tc-dark { background: #111111; }
.theme-choice .tc-system { background: linear-gradient(105deg, #F7F7F2 0 50%, #111111 50% 100%); }

/* -------------------- Boosted Theme Toggle -------------------- */
.theme-toggle {
  position: relative;
  display: inline-flex;
  align-items: center;
  background: var(--surface-soft);
  border: 1px solid var(--line);
  border-radius: 100px;
  padding: 3px;
  gap: 3px;
  flex-shrink: 0;
  box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.05);
  user-select: none;
}

.theme-toggle-glider {
  position: absolute;
  top: 3px;
  left: 3px;
  width: 30px;
  height: 30px;
  border-radius: 100px;
  background: var(--surface);
  box-shadow: var(--shadow-sm), 0 0 0 1px var(--line);
  transition: transform 0.42s cubic-bezier(0.34, 1.56, 0.64, 1), background 0.3s ease, box-shadow 0.3s ease;
  z-index: 1;
  pointer-events: none;
}

:root[data-theme="dark"] .theme-toggle-glider {
  transform: translateX(33px);
  background: #252525;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.5), inset 0 0 0 1px rgba(184, 255, 0, 0.2);
}

.theme-toggle button {
  position: relative;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  border: none;
  background: transparent !important;
  box-shadow: none !important;
  width: 30px;
  height: 30px;
  padding: 0;
  border-radius: 100px;
  color: var(--ink-faint);
  cursor: pointer;
  transition: color 0.3s ease, transform 0.2s cubic-bezier(0.34, 1.56, 0.64, 1);
}

.theme-toggle button:active {
  transform: scale(0.88);
}

.theme-toggle button svg {
  display: block;
  transition: transform 0.45s cubic-bezier(0.34, 1.56, 0.64, 1), filter 0.35s ease, color 0.3s ease;
}

/* Sun active micro-animation */
.theme-toggle button[data-theme-choice="light"].active {
  color: #D98200;
}
.theme-toggle button[data-theme-choice="light"].active svg {
  transform: rotate(45deg) scale(1.1);
  filter: drop-shadow(0 0 6px rgba(240, 180, 41, 0.6));
  color: #D98200;
}
.theme-toggle button[data-theme-choice="light"]:not(.active) svg {
  transform: rotate(0deg) scale(0.92);
}

/* Moon active micro-animation */
.theme-toggle button[data-theme-choice="dark"].active {
  color: var(--lime);
}
.theme-toggle button[data-theme-choice="dark"].active svg {
  transform: rotate(-12deg) scale(1.12);
  filter: drop-shadow(0 0 7px rgba(184, 255, 0, 0.65));
  color: var(--lime);
}
.theme-toggle button[data-theme-choice="dark"]:not(.active) svg {
  transform: rotate(20deg) scale(0.92);
}
.role-select {
  font-size: 12.5px; font-weight: 600; border: 1px solid var(--line); border-radius: 100px;
  padding: 7px 12px; background: var(--surface-soft); color: var(--ink-soft);
}
.avatar { width: 36px; height: 36px; border-radius: 50%; background: var(--lime); color: var(--forest); display: flex; align-items: center; justify-content: center; font-weight: 800; font-size: 13px; }
.bell { position: relative; }
.bell::after { content: ""; position: absolute; top: 8px; right: 9px; width: 7px; height: 7px; border-radius: 50%; background: var(--gold); border: 1.5px solid var(--surface); }

.dash-body { max-width: 920px; margin: 0 auto; padding: 56px 32px 100px; }
.dash-greet { font-size: 30px; font-weight: 800; letter-spacing: -0.02em; margin: 0 0 6px; text-align: center; }
.dash-question { text-align: center; color: var(--ink-faint); font-size: 15px; margin: 0 0 26px; }
.dash-search {
  display: flex; align-items: center; gap: 12px;
  padding: 16px 22px; border-radius: 100px;
  background: var(--surface); border: 1.5px solid var(--line);
  box-shadow: var(--shadow-sm); font-size: 15px; color: var(--ink-faint);
  margin: 0 auto 48px; max-width: 560px;
  transition: border-color 0.2s ease, box-shadow 0.2s ease;
}
.dash-search:hover { border-color: var(--lime-strong); box-shadow: var(--shadow-md); }
.dash-search input { border: none; background: transparent; outline: none; font-size: 15px; font-family: inherit; color: var(--ink); flex: 1; }
.dash-search input::placeholder { color: var(--ink-faint); }

.dash-section-title { font-size: 12.5px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em; color: var(--ink-faint); margin: 0 0 14px; }
.info-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; margin-bottom: 44px; }
.info-card { padding: 18px; border-radius: 16px; background: var(--surface); border: 1px solid var(--line); box-shadow: var(--shadow-sm); }
.info-card .k { font-size: 12.5px; color: var(--ink-faint); margin-bottom: 6px; }
.info-card .v { font-size: 21px; font-weight: 800; }
.info-card .v.lime { color: var(--lime-deep); }
.info-card .v.warn { color: #C4670A; }

.quick-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; }
.quick-card {
  padding: 20px 16px; border-radius: 14px; background: var(--surface); border: 1px solid var(--line);
  text-align: center; line-height: 1.4; transition: border-color 0.2s ease, transform 0.15s ease, box-shadow 0.2s ease;
}
.quick-card:hover { border-color: var(--lime-strong); transform: translateY(-2px); box-shadow: var(--shadow-sm); }
.quick-card .q-ic { font-size: 20px; margin-bottom: 10px; }
.quick-card .q-label { font-size: 12.5px; font-weight: 600; color: var(--ink); }

/* Ambient AI — pas de chatbot : réponse en ligne + carte d'insight intégrée */
.dash-search-wrap { max-width: 560px; margin: 0 auto 20px; }
.dash-search-wrap .dash-search { margin-bottom: 0; }

.search-answer {
  max-height: 0; opacity: 0; overflow: hidden;
  margin-top: 0;
  border-radius: 16px;
  background: var(--surface); border: 1px solid var(--line);
  transition: max-height 0.35s var(--ease-out), opacity 0.3s ease, margin-top 0.35s var(--ease-out);
}
.search-answer.shown { max-height: 160px; opacity: 1; margin-top: 10px; box-shadow: var(--shadow-sm); }
.search-answer-text { padding: 14px 18px; font-size: 13.5px; line-height: 1.55; color: var(--ink-soft); }
.search-answer-text strong { color: var(--ink); }

.ai-insight {
  max-width: 720px; margin: 0 auto 40px;
  display: flex; align-items: flex-start; gap: 14px;
  padding: 18px 20px; border-radius: 16px;
  background: var(--forest-tint); border: 1px solid rgba(39,74,50,0.12);
}
.ai-insight-ic {
  flex-shrink: 0; width: 32px; height: 32px; border-radius: 9px;
  background: var(--forest); color: var(--lime);
  display: flex; align-items: center; justify-content: center; font-size: 14px;
}
.ai-insight-body { flex: 1; min-width: 0; }
.ai-insight-text { font-size: 13.5px; line-height: 1.6; color: var(--forest-700); margin-bottom: 8px; }
.ai-insight-action {
  border: none; background: none; padding: 0;
  font-size: 12.5px; font-weight: 700; color: var(--lime-deep);
  text-decoration: underline; text-underline-offset: 2px;
}
.ai-insight-action:hover { color: var(--forest); }

@media (max-width: 860px) {
  .sidebar { position: fixed; left: 0; top: 0; z-index: 50; box-shadow: var(--shadow-lg); }
  .sidebar.collapsed { margin-left: -248px; }
  .info-grid { grid-template-columns: 1fr 1fr; }
  .quick-grid { grid-template-columns: 1fr 1fr; }
  .role-grid { grid-template-columns: 1fr; }
  .field-row { grid-template-columns: 1fr; }
  .auth-card { padding: 32px 24px; }
}

/* =========================================================
   Écrans de gestion (élèves, classes, catalogue, dossier)
   ========================================================= */

.page-header {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: 24px; flex-wrap: wrap; gap: 12px;
}
.page-header h1 { font-size: 22px; font-weight: 800; letter-spacing: -0.01em; margin: 0; }
.page-header p { margin: 4px 0 0; font-size: 13.5px; color: var(--ink-faint); }
.page-back { font-size: 13px; font-weight: 600; color: var(--ink-faint); display: inline-flex; align-items: center; gap: 6px; margin-bottom: 14px; }
.page-back:hover { color: var(--ink); }

.panel {
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm); padding: 22px; margin-bottom: 22px;
}
.panel h2 { font-size: 15px; font-weight: 700; margin: 0 0 16px; }

.data-table { width: 100%; border-collapse: collapse; font-size: 13.5px; }
.data-table th {
  text-align: left; font-size: 11.5px; text-transform: uppercase; letter-spacing: 0.05em;
  color: var(--ink-faint); font-weight: 700; padding: 0 12px 10px; border-bottom: 1px solid var(--line);
}
.data-table td { padding: 12px; border-bottom: 1px solid var(--line-soft); vertical-align: middle; }
.data-table tr:last-child td { border-bottom: none; }
.data-table tr.clickable { cursor: pointer; transition: background 0.15s ease; }
.data-table tr.clickable:hover { background: var(--surface-soft); }
.data-table .empty-row td { text-align: center; color: var(--ink-faint); padding: 32px 12px; }

.badge { display: inline-flex; align-items: center; padding: 3px 10px; border-radius: 100px; font-size: 12px; font-weight: 700; }
.badge.paid { background: var(--forest-tint); color: var(--forest-700); }
.badge.partial { background: var(--gold-tint); color: #8A5A00; }
.badge.due { background: #FDE8DD; color: #A6420F; }

.inline-form { display: flex; flex-wrap: wrap; gap: 10px; align-items: flex-end; }
.inline-form .field { margin-bottom: 0; flex: 1; min-width: 150px; }
.inline-form .field-sm { flex: 0 0 110px; min-width: 110px; }
.form-toggle-row { display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px; }
.form-msg { font-size: 13px; margin: 10px 0 0; }
.form-msg.error { color: #A6420F; }
.form-msg.success { color: var(--lime-deep); }

.summary-strip { display: flex; gap: 14px; margin-bottom: 22px; flex-wrap: wrap; }
.summary-strip .info-card { flex: 1; min-width: 150px; margin: 0; }

.obligation-card { border: 1px solid var(--line); border-radius: 14px; padding: 16px 18px; margin-bottom: 12px; }
.obligation-card .ob-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px; }
.obligation-card .ob-label { font-weight: 700; font-size: 14px; }
.obligation-card .ob-amounts { font-size: 12.5px; color: var(--ink-faint); }
.payment-row { display: flex; justify-content: space-between; font-size: 12.5px; color: var(--ink-soft); padding: 4px 0; }

.text-warn { color: #C4670A; font-weight: 700; }
.text-lime { color: var(--lime-deep); font-weight: 700; }

/* -------------------- Démonstration interactive (/demo.html) --------------------
   Réutilise volontairement les classes du vrai produit (app-shell, sidebar,
   panel, data-table, summary-strip, info-card, badge...) : la démo doit
   ressembler à Klassio, pas être une seconde interface. Tout ce bloc n'ajoute
   que le "chrome" propre à la démo (ruban, intro, navigation par étapes). */
.demo-intro {
  position: fixed; inset: 0; z-index: 500; display: flex; align-items: center; justify-content: center;
  background: radial-gradient(120% 120% at 50% 0%, var(--surface-soft) 0%, var(--bg) 60%);
  padding: 24px; cursor: pointer;
  transition: opacity 0.6s var(--ease-in-out), visibility 0.6s;
}
.demo-intro.hide { opacity: 0; visibility: hidden; pointer-events: none; }
.demo-intro-card { max-width: 480px; text-align: center; }
.demo-intro-card h1 {
  font-family: var(--font-display); font-style: italic; font-weight: 500; font-size: 34px; margin: 0 0 12px;
  opacity: 0; transform: translateY(10px); animation: splashIn 0.8s var(--ease-out) 0.1s forwards;
}
.demo-intro-card p {
  color: var(--ink-soft); font-size: 15px; line-height: 1.6; margin: 0 0 6px;
  opacity: 0; animation: splashIn 0.7s var(--ease-out) 0.35s forwards;
}
.demo-exit-link { font-size: 13px; color: var(--ink-faint); }
.demo-exit-link:hover { color: var(--ink); }

.demo-shell { min-height: 100vh; }
.demo-ribbon {
  display: flex; align-items: center; justify-content: center; gap: 18px;
  background: var(--forest); color: #fff; font-size: 12.5px; font-weight: 600;
  padding: 8px 20px; text-align: center;
}
.demo-ribbon .demo-exit-link { color: rgba(255,255,255,0.75); }
.demo-ribbon .demo-exit-link:hover { color: #fff; }

/* Le bandeau de progression reste visible sous la topbar pendant le défilement
   — c'est lui qui indique où on se trouve puisqu'il n'y a plus de boutons
   Suivant/Précédent : on avance en scrollant, comme une longue page produit. */
.demo-progress {
  display: flex; gap: 6px; padding: 12px 32px; flex-wrap: wrap;
  position: sticky; top: 61px; z-index: 15;
  background: var(--bg); border-bottom: 1px solid var(--line-soft);
}
.demo-progress .dp-step {
  font-size: 11px; font-weight: 700; letter-spacing: 0.02em; padding: 5px 12px;
  border-radius: 100px; background: var(--surface-soft); color: var(--ink-faint);
  border: 1px solid transparent; cursor: pointer;
}
.demo-progress .dp-step.active { background: var(--lime-tint); color: var(--lime-deep); border-color: var(--lime); }
.demo-progress .dp-step.done { color: var(--ink-soft); }

.demo-step { scroll-margin-top: 116px; padding-top: 12px; }
.demo-step + .demo-step { margin-top: 56px; padding-top: 56px; border-top: 1px solid var(--line-soft); }

.demo-checklist { display: flex; flex-direction: column; gap: 8px; margin: 4px 0 18px; font-size: 14px; }
.demo-checklist .dc-item { opacity: 0; transform: translateY(4px); animation: stepIn 0.35s var(--ease-out) forwards; }
.demo-checklist .dc-item.pending { color: var(--ink-faint); }
.demo-checklist .dc-item.done { color: var(--ink); }
.demo-checklist .dc-item .dc-mark { display:inline-block; width:18px; }

.demo-mapping { display: flex; flex-direction: column; gap: 8px; margin: 8px 0 18px; font-size: 13.5px; }
.demo-mapping .dm-row { display: flex; align-items: center; gap: 10px; color: var(--ink-soft); }
.demo-mapping .dm-arrow { color: var(--ink-faint); }
.demo-mapping .dm-target { font-weight: 700; color: var(--ink); }

.demo-quality-list { list-style: none; margin: 0 0 8px; padding: 0; font-size: 13.5px; color: var(--ink-soft); }
.demo-quality-list li { padding: 3px 0; }
.demo-quality-list li::before { content: "✓ "; color: var(--lime-deep); font-weight: 700; }
.demo-quality-list.warn li::before { content: "⚠ "; color: #C4670A; }

.payment-chain { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; font-size: 13px; font-weight: 600; margin-bottom: 18px; }
.payment-chain span:not(.pc-arrow) { padding: 7px 14px; border-radius: 100px; background: var(--surface-soft); border: 1px solid var(--line); }
.pc-arrow { color: var(--ink-faint); font-weight: 400; }
.demo-payment-sample { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; padding: 14px 16px; border-radius: var(--radius-md); background: var(--surface-soft); font-size: 13.5px; }

.role-switch { display: flex; gap: 8px; margin-bottom: 20px; }
.role-switch button {
  padding: 9px 18px; border-radius: 100px; border: 1px solid var(--line); background: var(--surface);
  font-size: 13.5px; font-weight: 600; color: var(--ink-soft);
}
.role-switch button.active { background: var(--forest); color: #fff; border-color: var(--forest); }

.demo-cta { max-width: 560px; margin: 60px auto; text-align: center; padding: 0 24px; }
.demo-cta h2 { font-family: var(--font-display); font-style: italic; font-weight: 500; font-size: 28px; margin: 0 0 12px; }
.demo-cta p { color: var(--ink-soft); font-size: 14.5px; line-height: 1.6; margin: 0 0 24px; }
.demo-cta-actions { display: flex; gap: 10px; justify-content: center; flex-wrap: wrap; }

.demo-nav { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 18px 32px 32px; }
.demo-nav .step-dots { margin: 0; }
.s-item.locked-flash { background: var(--gold-tint); }

/* =========================================================
   DÉMONSTRATION — ouverture cinématique (/demo.html)

   Principe repris d'une référence React/GSAP fournie par le propriétaire du
   produit : scène plein écran épinglée, carte centrale qui monte puis occupe
   tout l'écran, objet produit qui arrive en profondeur, badges flottants,
   parallaxe à la souris, puis recul de la carte et passage à la visite.

   Ce qui a été ÉCARTÉ de cette référence, volontairement :
   - son contenu (application de sobriété : sponsors, jours d'abstinence,
     boutons App Store / Google Play). Klassio est un SaaS scolaire ;
   - sa palette bleu nuit. Ici : charbon, blanc cassé, et le lime EN ACCENT ;
   - la maquette d'iPhone. Klassio se pilote depuis un poste de direction :
     l'objet montré est une fenêtre d'application, pas un téléphone ;
   - GSAP et son ScrollTrigger. Le projet n'a ni Node ni npm, et sa CSP
     (`script-src 'self'`) interdit un script de CDN. Le moteur de défilement
     maison de la landing fait déjà ce travail : mesure unique, écriture de
     transformations seulement, nettoyage au démontage. Une seconde solution de
     défilement n'apporterait rien et pèserait davantage.
   ========================================================= */

.demo-cinema {
  position: relative;
  width: 100%;
  min-height: 300vh;              /* la piste : 1 écran de repos + la plongée */
}
.cinema-viewport {
  position: sticky;
  top: 0;
  height: 100vh;
  height: 100svh;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--bg);
  perspective: 1500px;
}

/* Trame de fond, estompée sur les bords. Décorative. */
.cinema-grid {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-size: 58px 58px;
  background-image:
    linear-gradient(to right, var(--line-soft) 1px, transparent 1px),
    linear-gradient(to bottom, var(--line-soft) 1px, transparent 1px);
  -webkit-mask-image: radial-gradient(ellipse at center, #000 0%, transparent 72%);
  mask-image: radial-gradient(ellipse at center, #000 0%, transparent 72%);
  opacity: 0.7;
}

/* ---- Le texte d'ouverture ---------------------------------------------- */
.cinema-intro {
  position: absolute;
  z-index: 2;
  width: 100%;
  padding: 0 24px;
  text-align: center;
  will-change: transform, opacity;
}
.cinema-kicker {
  display: inline-flex; align-items: center; gap: 9px;
  padding: 7px 16px; border-radius: 100px;
  background: var(--lime-tint); color: var(--forest-700);
  border: 1px solid var(--lime);
  font-size: 12px; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase;
  margin-bottom: clamp(16px, 3vh, 30px);
}
:root[data-theme="dark"] .cinema-kicker { color: var(--lime); background: rgba(184,255,0,0.12); }
.cinema-kicker .ck-dot {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--lime-strong); box-shadow: 0 0 8px var(--lime-strong);
}
.cinema-title {
  font-family: var(--font-sans);
  font-weight: 800;
  font-size: clamp(28px, min(5.6vw, 6vh), 62px);
  line-height: 1.06;
  letter-spacing: -0.03em;
  margin: 0;
  color: var(--ink);
  text-wrap: balance;
}
.cinema-title .ct-em {
  font-family: var(--font-display);
  font-style: italic; font-weight: 500;
  color: var(--lime-deep);
}
:root[data-theme="dark"] .cinema-title .ct-em { color: var(--lime); }
.cinema-sub {
  max-width: 560px; margin: clamp(14px, 2.4vh, 22px) auto 0;
  font-size: clamp(14.5px, 1.5vw, 17px); line-height: 1.6; color: var(--ink-soft);
}
.cinema-hint {
  display: inline-flex; align-items: center; gap: 9px;
  margin-top: clamp(18px, 3vh, 34px);
  font-size: 12px; font-weight: 600; letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--ink-soft);
}
.cinema-hint .ch-rail {
  position: relative; width: 18px; height: 28px; flex-shrink: 0;
  border: 1.5px solid var(--line); border-radius: 100px;
}
.cinema-hint .ch-rail::after {
  content: ""; position: absolute; left: 50%; top: 6px;
  width: 3px; height: 6px; margin-left: -1.5px; border-radius: 2px;
  background: var(--lime-deep);
  animation: cinemaHintDrop 1.9s var(--ease-in-out) infinite;
}
@keyframes cinemaHintDrop {
  0%, 100% { transform: translateY(0); opacity: 1; }
  55% { transform: translateY(9px); opacity: 0.15; }
}

/* ---- La carte centrale -------------------------------------------------- */
.cinema-stage {
  position: absolute; inset: 0; z-index: 3;
  display: flex; align-items: center; justify-content: center;
  pointer-events: none;
  perspective: 1500px;
}
.cinema-card {
  position: relative;
  width: 92vw; height: 88svh;
  max-width: 1320px;
  border-radius: 32px;
  overflow: hidden;
  pointer-events: auto;
  /* Charbon Klassio, pas le bleu nuit de la référence. */
  background: linear-gradient(150deg, #1E1E1C 0%, #111111 62%, #0C0C0B 100%);
  border: 1px solid rgba(255, 255, 255, 0.06);
  box-shadow:
    0 40px 100px -20px rgba(0, 0, 0, 0.55),
    0 18px 40px -18px rgba(0, 0, 0, 0.45),
    inset 0 1px 1px rgba(255, 255, 255, 0.10),
    inset 0 -2px 4px rgba(0, 0, 0, 0.6);
  will-change: transform, width, height, border-radius;
}
/* Lueur qui suit le curseur. Purement décorative. */
.cinema-sheen {
  position: absolute; inset: 0; border-radius: inherit; z-index: 6;
  pointer-events: none; mix-blend-mode: screen;
  background: radial-gradient(620px circle at var(--mx, 50%) var(--my, 40%),
    rgba(184, 255, 0, 0.10) 0%, rgba(255, 255, 255, 0.04) 26%, transparent 55%);
}

.cinema-inner {
  position: relative; z-index: 3;
  width: 100%; height: 100%;
  display: grid;
  grid-template-columns: 1fr;
  align-content: center;
  gap: clamp(14px, 2.4vh, 26px);
  padding: clamp(18px, 3vw, 44px);
  overflow: hidden;
}
@media (min-width: 1000px) {
  .cinema-inner {
    grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.5fr) minmax(0, 0.8fr);
    align-items: center;
    gap: clamp(20px, 2.4vw, 44px);
  }
}

.cinema-col { min-width: 0; will-change: transform, opacity; }
.cinema-col-left { order: 3; text-align: center; }
.cinema-col-mid { order: 1; }
.cinema-col-right { order: 2; }
@media (min-width: 1000px) {
  .cinema-col-left { order: 1; text-align: left; }
  .cinema-col-mid { order: 2; }
  .cinema-col-right { order: 3; }
}

.cinema-col-left h3 {
  margin: 0 0 12px;
  font-size: clamp(19px, 2.2vw, 30px); font-weight: 800; letter-spacing: -0.02em;
  color: #FFFFFF; line-height: 1.2;
}
.cinema-col-left p {
  margin: 0; font-size: clamp(13px, 1.1vw, 15.5px); line-height: 1.65;
  color: rgba(247, 247, 242, 0.62);
}
.cinema-col-left .ccl-em { color: var(--lime); font-weight: 700; }
@media (max-width: 999px) { .cinema-col-left p { display: none; } }

/* Les quatre rôles, colonne de droite */
.cinema-roles { display: flex; flex-direction: column; gap: 8px; }
@media (max-width: 999px) {
  .cinema-roles { flex-direction: row; flex-wrap: wrap; justify-content: center; }
}
.cinema-role {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 14px; border-radius: 14px;
  background: rgba(255, 255, 255, 0.035);
  border: 1px solid rgba(255, 255, 255, 0.06);
  color: rgba(247, 247, 242, 0.72);
  font-size: 13px; font-weight: 600; white-space: nowrap;
  box-shadow: inset 0 1px 1px rgba(255,255,255,0.05);
}
.cinema-role .cr-dot {
  width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0;
  background: rgba(184, 255, 0, 0.45);
}
.cinema-role.is-on {
  background: rgba(184, 255, 0, 0.10);
  border-color: rgba(184, 255, 0, 0.35);
  color: #FFFFFF;
}
.cinema-role.is-on .cr-dot { background: var(--lime); box-shadow: 0 0 8px var(--lime); }

/* ---- L'objet produit : une fenêtre d'application ------------------------ */
.cinema-device-wrap {
  position: relative;
  display: flex; align-items: center; justify-content: center;
  perspective: 1200px;
  will-change: transform, opacity;
}
.cinema-device {
  position: relative;
  width: 100%; max-width: 680px;
  border-radius: 16px;
  overflow: hidden;
  background: #0A0A09;
  border: 1px solid rgba(255,255,255,0.09);
  box-shadow:
    0 40px 80px -18px rgba(0,0,0,0.8),
    0 14px 26px -8px rgba(0,0,0,0.6),
    inset 0 1px 1px rgba(255,255,255,0.08);
  transform-style: preserve-3d;
  will-change: transform;
}
.cinema-device-bar {
  display: flex; align-items: center; gap: 7px;
  padding: 10px 14px;
  background: rgba(255,255,255,0.04);
  border-bottom: 1px solid rgba(255,255,255,0.06);
}
.cinema-device-bar i { width: 9px; height: 9px; border-radius: 50%; background: rgba(255,255,255,0.14); }
.cinema-device-bar .cdb-url {
  flex: 1; margin-left: 8px; padding: 4px 12px; border-radius: 100px;
  background: rgba(0,0,0,0.35); border: 1px solid rgba(255,255,255,0.05);
  font-size: 10.5px; color: rgba(247,247,242,0.4); text-align: center;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.cinema-device-body { padding: clamp(12px, 1.6vw, 20px); }
.cinema-device-head {
  display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
  margin-bottom: 14px;
}
.cinema-device-head b { font-size: clamp(13px, 1.2vw, 16px); color: #fff; font-weight: 700; letter-spacing: -0.01em; }
.cinema-device-head span { font-size: 11px; color: rgba(247,247,242,0.38); }

.cinema-kpis { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; margin-bottom: 12px; }
@media (max-width: 640px) { .cinema-kpis { grid-template-columns: repeat(2, 1fr); } }
.cinema-kpi {
  padding: 10px 12px; border-radius: 12px;
  background: linear-gradient(180deg, rgba(255,255,255,0.05) 0%, rgba(255,255,255,0.015) 100%);
  border: 1px solid rgba(255,255,255,0.05);
  box-shadow: inset 0 1px 1px rgba(255,255,255,0.05);
}
.cinema-kpi .ck-k {
  font-size: 9.5px; text-transform: uppercase; letter-spacing: 0.07em; font-weight: 700;
  color: rgba(247,247,242,0.4); margin-bottom: 5px;
}
.cinema-kpi .ck-v {
  font-size: clamp(14px, 1.5vw, 19px); font-weight: 800; color: #fff;
  font-variant-numeric: tabular-nums; letter-spacing: -0.02em;
}
.cinema-kpi .ck-v.lime { color: var(--lime); }

.cinema-rows { display: flex; flex-direction: column; gap: 7px; }
.cinema-row {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 12px; border-radius: 11px;
  background: rgba(255,255,255,0.025);
  border: 1px solid rgba(255,255,255,0.04);
  font-size: 11.5px; color: rgba(247,247,242,0.72);
}
.cinema-row .cr-ic {
  width: 24px; height: 24px; border-radius: 7px; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center; font-size: 12px;
  background: rgba(184,255,0,0.10); border: 1px solid rgba(184,255,0,0.18);
}
.cinema-row .cr-main { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cinema-row .cr-val { font-weight: 700; color: #fff; font-variant-numeric: tabular-nums; }
@media (max-width: 640px) { .cinema-row:nth-child(n+3) { display: none; } }

/* ---- Badges flottants --------------------------------------------------- */
.cinema-badge {
  position: absolute; z-index: 8;
  display: flex; align-items: center; gap: 11px;
  padding: 11px 14px; border-radius: 15px;
  background: linear-gradient(135deg, rgba(255,255,255,0.10) 0%, rgba(255,255,255,0.02) 100%);
  -webkit-backdrop-filter: blur(20px); backdrop-filter: blur(20px);
  box-shadow:
    0 0 0 1px rgba(255,255,255,0.10),
    0 22px 44px -14px rgba(0,0,0,0.75),
    inset 0 1px 1px rgba(255,255,255,0.18);
  will-change: transform, opacity;
}
.cinema-badge .cb-ic {
  width: 30px; height: 30px; border-radius: 50%; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center; font-size: 14px;
  background: rgba(184,255,0,0.12); border: 1px solid rgba(184,255,0,0.28);
}
.cinema-badge .cb-t { font-size: 12px; font-weight: 700; color: #fff; letter-spacing: -0.01em; }
.cinema-badge .cb-s { font-size: 10.5px; color: rgba(247,247,242,0.46); margin-top: 1px; }
.cinema-badge-a { top: 4%; left: -10px; }
.cinema-badge-b { bottom: 8%; right: -10px; }
@media (min-width: 1000px) {
  .cinema-badge-a { top: 2%; left: -56px; }
  .cinema-badge-b { bottom: 4%; right: -56px; }
}
@media (max-width: 720px) {
  .cinema-badge { padding: 8px 11px; border-radius: 12px; gap: 8px; }
  .cinema-badge .cb-ic { width: 24px; height: 24px; font-size: 12px; }
  .cinema-badge .cb-t { font-size: 10.5px; }
  .cinema-badge .cb-s { display: none; }
  /* Sur petit écran les badges doivent border la fenêtre, pas s'asseoir
     dessus : ils masquaient une ligne d'information. */
  .cinema-badge-a { top: -14px; left: -4px; }
  .cinema-badge-b { bottom: -14px; right: -4px; }
}

/* ---- Le relais vers la visite ------------------------------------------- */
.cinema-outro {
  position: absolute; z-index: 2; width: 100%; padding: 0 24px; text-align: center;
  opacity: 0; will-change: transform, opacity;
}
.cinema-outro h2 {
  margin: 0 0 14px;
  font-size: clamp(24px, 4.4vw, 48px); font-weight: 800; letter-spacing: -0.03em; color: var(--ink);
}
.cinema-outro h2 .ct-em { font-family: var(--font-display); font-style: italic; font-weight: 500; color: var(--lime-deep); }
:root[data-theme="dark"] .cinema-outro h2 .ct-em { color: var(--lime); }
.cinema-outro p {
  max-width: 540px; margin: 0 auto clamp(22px, 4vh, 36px);
  font-size: clamp(14px, 1.4vw, 16.5px); line-height: 1.6; color: var(--ink-soft);
}
.cinema-outro-actions { display: flex; flex-wrap: wrap; gap: 12px; justify-content: center; }

/* ---- Replis : mouvement réduit et absence de script ---------------------- */
@media (prefers-reduced-motion: reduce) {
  .demo-cinema { min-height: 0 !important; }
  .cinema-viewport {
    position: relative !important; height: auto !important; overflow: visible !important;
    padding: calc(var(--nav-h) + 40px) 0 64px; flex-direction: column; gap: 32px;
  }
  .cinema-intro, .cinema-stage, .cinema-outro {
    position: relative !important; inset: auto !important;
    opacity: 1 !important; transform: none !important;
  }
  .cinema-card {
    width: min(92vw, 1320px) !important; height: auto !important;
    transform: none !important;
  }
  /* Une seule colonne : à trois colonnes sans la mise en scène, la fenêtre
     produit se retrouve écrasée au milieu et devient illisible. */
  .cinema-inner { height: auto; grid-template-columns: 1fr !important; gap: 28px; }
  .cinema-col-left { order: 1 !important; text-align: center !important; }
  .cinema-col-mid { order: 2 !important; }
  .cinema-col-right { order: 3 !important; }
  .cinema-col-left p { display: block !important; max-width: 620px; margin: 0 auto; }
  .cinema-roles { flex-direction: row; flex-wrap: wrap; justify-content: center; }
  .cinema-role.is-on, .cinema-role { background: rgba(255,255,255,0.05); }
  .cinema-device, .cinema-badge, .cinema-col { transform: none !important; opacity: 1 !important; }
  .cinema-badge { position: static; margin: 10px 6px 0; display: inline-flex; }
  .cinema-device-wrap { flex-direction: column; }
  .cinema-sheen, .cinema-hint { display: none !important; }
}

/* -------------------- Loader 3D (création d'espace / import) --------------------
   Recréation vanilla de l'effet "boîtes qui s'assemblent en cube" (inspiré d'un
   loader CSS trouvé par l'utilisateur) — recoloré en lime/forêt, jamais en
   bleu. Les animations box-move, box-scale et ground reprennent la logique
   d'origine (chaque boîte part d'un point autour du centre, se met à l'échelle
   en cube isométrique, retombe, un plan "ground" apparaît en dessous). */
.klassio-loader-overlay {
  position: fixed; inset: 0; z-index: 600;
  display: flex; align-items: center; justify-content: center;
  background: rgba(250, 248, 239, 0.92); backdrop-filter: blur(6px);
  opacity: 0; visibility: hidden; transition: opacity 0.35s var(--ease-out), visibility 0.35s;
}
:root[data-theme="dark"] .klassio-loader-overlay { background: rgba(17, 17, 17, 0.92); }
.klassio-loader-overlay.shown { opacity: 1; visibility: visible; }
.klassio-loader { display: flex; flex-direction: column; align-items: center; gap: 26px; }
.klassio-loader-text { font-size: 14px; font-weight: 600; color: var(--ink-soft); }

.loader {
  --clr: var(--lime-strong);
  position: relative; width: 1px; height: 1px;
  transform-style: preserve-3d;
  transform: rotateX(55deg) rotateZ(45deg);
  perspective: 700px;
}
.loader .box { position: absolute; top: 0; left: 0; transform-style: preserve-3d; }
.loader .box > div {
  position: absolute; top: -8px; left: -8px; width: 16px; height: 16px;
  background: var(--clr); box-shadow: 0 0 0 1px rgba(0,0,0,0.06);
}
.loader .box0 { --x: 0px; --y: -74px; animation: box-move0 3s ease-in-out infinite; }
.loader .box0 > div { animation: box-scale0 3s ease-in-out infinite; }
.loader .box1 { --x: 52px; --y: -52px; animation: box-move1 3s ease-in-out infinite; }
.loader .box1 > div { animation: box-scale1 3s ease-in-out infinite; }
.loader .box2 { --x: 74px; --y: 0px; animation: box-move2 3s ease-in-out infinite; }
.loader .box2 > div { animation: box-scale2 3s ease-in-out infinite; }
.loader .box3 { --x: 52px; --y: 52px; animation: box-move3 3s ease-in-out infinite; }
.loader .box3 > div { animation: box-scale3 3s ease-in-out infinite; }
.loader .box4 { --x: 0px; --y: 74px; animation: box-move4 3s ease-in-out infinite; }
.loader .box4 > div { animation: box-scale4 3s ease-in-out infinite; }
.loader .box5 { --x: -52px; --y: 52px; animation: box-move5 3s ease-in-out infinite; }
.loader .box5 > div { animation: box-scale5 3s ease-in-out infinite; }
.loader .box6 { --x: -74px; --y: 0px; animation: box-move6 3s ease-in-out infinite; }
.loader .box6 > div { animation: box-scale6 3s ease-in-out infinite; }
.loader .box7 { --x: -52px; --y: -52px; animation: box-move7 3s ease-in-out infinite; }
.loader .box7 > div { animation: box-scale7 3s ease-in-out infinite; }
.loader .ground { position: absolute; top: 0; left: 0; }
.loader .ground > div {
  position: absolute; top: -30px; left: -30px; width: 60px; height: 60px;
  border-radius: 50%; background: var(--clr); opacity: 0.16;
  animation: ground 3s ease-in-out infinite;
}

@keyframes box-move0 {
  12% { transform: translate(var(--x), var(--y)); }
  25%, 52% { transform: translate(0, 0); }
  80% { transform: translate(0, -32px); }
  90%, 100% { transform: translate(0, 188px); }
}
@keyframes box-scale0 {
  6% { transform: rotateY(-47deg) rotateX(-15deg) rotateZ(15deg) scale(0); }
  14%, 100% { transform: rotateY(-47deg) rotateX(-15deg) rotateZ(15deg) scale(1); }
}
@keyframes box-move1 {
  16% { transform: translate(var(--x), var(--y)); }
  29%, 52% { transform: translate(0, 0); }
  80% { transform: translate(0, -32px); }
  90%, 100% { transform: translate(0, 188px); }
}
@keyframes box-scale1 {
  10% { transform: rotateY(-47deg) rotateX(-15deg) rotateZ(15deg) scale(0); }
  18%, 100% { transform: rotateY(-47deg) rotateX(-15deg) rotateZ(15deg) scale(1); }
}
@keyframes box-move2 {
  20% { transform: translate(var(--x), var(--y)); }
  33%, 52% { transform: translate(0, 0); }
  80% { transform: translate(0, -32px); }
  90%, 100% { transform: translate(0, 188px); }
}
@keyframes box-scale2 {
  14% { transform: rotateY(-47deg) rotateX(-15deg) rotateZ(15deg) scale(0); }
  22%, 100% { transform: rotateY(-47deg) rotateX(-15deg) rotateZ(15deg) scale(1); }
}
@keyframes box-move3 {
  24% { transform: translate(var(--x), var(--y)); }
  37%, 52% { transform: translate(0, 0); }
  80% { transform: translate(0, -32px); }
  90%, 100% { transform: translate(0, 188px); }
}
@keyframes box-scale3 {
  18% { transform: rotateY(-47deg) rotateX(-15deg) rotateZ(15deg) scale(0); }
  26%, 100% { transform: rotateY(-47deg) rotateX(-15deg) rotateZ(15deg) scale(1); }
}
@keyframes box-move4 {
  28% { transform: translate(var(--x), var(--y)); }
  41%, 52% { transform: translate(0, 0); }
  80% { transform: translate(0, -32px); }
  90%, 100% { transform: translate(0, 188px); }
}
@keyframes box-scale4 {
  22% { transform: rotateY(-47deg) rotateX(-15deg) rotateZ(15deg) scale(0); }
  30%, 100% { transform: rotateY(-47deg) rotateX(-15deg) rotateZ(15deg) scale(1); }
}
@keyframes box-move5 {
  32% { transform: translate(var(--x), var(--y)); }
  45%, 52% { transform: translate(0, 0); }
  80% { transform: translate(0, -32px); }
  90%, 100% { transform: translate(0, 188px); }
}
@keyframes box-scale5 {
  26% { transform: rotateY(-47deg) rotateX(-15deg) rotateZ(15deg) scale(0); }
  34%, 100% { transform: rotateY(-47deg) rotateX(-15deg) rotateZ(15deg) scale(1); }
}
@keyframes box-move6 {
  36% { transform: translate(var(--x), var(--y)); }
  49%, 52% { transform: translate(0, 0); }
  80% { transform: translate(0, -32px); }
  90%, 100% { transform: translate(0, 188px); }
}
@keyframes box-scale6 {
  30% { transform: rotateY(-47deg) rotateX(-15deg) rotateZ(15deg) scale(0); }
  38%, 100% { transform: rotateY(-47deg) rotateX(-15deg) rotateZ(15deg) scale(1); }
}
@keyframes box-move7 {
  40% { transform: translate(var(--x), var(--y)); }
  53%, 52% { transform: translate(0, 0); }
  80% { transform: translate(0, -32px); }
  90%, 100% { transform: translate(0, 188px); }
}
@keyframes box-scale7 {
  34% { transform: rotateY(-47deg) rotateX(-15deg) rotateZ(15deg) scale(0); }
  42%, 100% { transform: rotateY(-47deg) rotateX(-15deg) rotateZ(15deg) scale(1); }
}
@keyframes ground {
  0%, 65% { transform: scale(0); }
  75%, 90% { transform: scale(1); }
  100% { transform: scale(0); }
}

/* -------------------- Dossiers par classe (page Élèves) --------------------
   Recréation vanilla de l'effet "dossier qui s'ouvre en éventail" — au survol
   d'une classe, les élèves apparaissent en éventail au-dessus du dossier ;
   cliquer ouvre le vrai dossier de l'élève (pas d'image, pas de fausse photo :
   des avatars à initiales, comme partout ailleurs dans Klassio). */
.folder-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 56px 18px; padding-top: 24px;
}
.folder-card {
  position: relative; display: flex; flex-direction: column; align-items: center;
  cursor: default; padding-top: 74px;
}
.folder-shape {
  position: relative; width: 96px; height: 68px;
  transition: transform 0.4s var(--ease-out);
}
.folder-card:hover .folder-shape { transform: translateY(-4px); }
.folder-shape .f-tab {
  position: absolute; top: -8px; left: 8px; width: 38px; height: 12px;
  border-radius: 6px 6px 0 0; background: var(--lime-deep);
}
.folder-shape .f-body {
  position: absolute; inset: 0; border-radius: 8px 10px 10px 10px;
  background: linear-gradient(160deg, var(--lime-deep) 0%, var(--forest) 100%);
  box-shadow: var(--shadow-sm);
}
.folder-fan {
  position: absolute; top: 0; left: 50%; width: 0; height: 0; z-index: 5;
}
.fan-avatar {
  position: absolute; width: 34px; height: 34px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-size: 11px; font-weight: 800; color: var(--forest); background: var(--lime);
  border: 2px solid var(--surface); box-shadow: var(--shadow-sm);
  top: 0; left: -17px;
  transform: translate(0, 10px) scale(0.4) rotate(0deg);
  opacity: 0; pointer-events: none;
  transition: transform 0.45s var(--ease-out), opacity 0.35s ease;
}
.folder-card:hover .fan-avatar {
  opacity: 1; pointer-events: auto; cursor: pointer;
  transform: translate(var(--tx), var(--ty)) rotate(var(--rot)) scale(1);
}
.fan-more {
  position: absolute; top: 0; left: -17px; width: 34px; height: 34px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-size: 10px; font-weight: 800; color: var(--ink-soft); background: var(--surface-soft);
  border: 2px solid var(--surface); box-shadow: var(--shadow-sm);
  transform: translate(0, 10px) scale(0.4); opacity: 0; pointer-events: none;
  transition: transform 0.45s var(--ease-out), opacity 0.35s ease;
}
.folder-card:hover .fan-more { opacity: 1; transform: translate(var(--tx), var(--ty)) scale(1); }
.fan-avatar:hover { z-index: 20; box-shadow: var(--shadow-md); }
.folder-label { margin-top: 12px; text-align: center; }
.folder-label .fl-name { font-size: 13px; font-weight: 700; color: var(--ink); }
.folder-label .fl-count { display: block; font-size: 11.5px; color: var(--ink-faint); }

/* -------------------- Diagramme classes (page Établissement) -------------------- */
.class-diagram { display: flex; flex-direction: column; gap: 10px; }
.class-diagram .cd-row { display: flex; align-items: center; gap: 12px; }
.class-diagram .cd-label { flex: 0 0 130px; font-size: 12.5px; color: var(--ink-soft); text-align: right; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.class-diagram .cd-track { flex: 1; height: 16px; border-radius: 8px; background: var(--surface-soft); overflow: hidden; }
.class-diagram .cd-bar { height: 100%; border-radius: 8px; background: linear-gradient(90deg, var(--lime-deep), var(--lime)); transition: width 0.6s var(--ease-out); }
.class-diagram .cd-count { flex: 0 0 30px; font-size: 12.5px; font-weight: 700; color: var(--ink); }

/* -------------------- Assistant IA (lecture seule) -------------------- */
.ia-page.dash-body { display: flex; flex-direction: column; height: calc(100vh - 65px); padding-bottom: 0; }
.ia-layout { display: flex; gap: 20px; flex: 1; min-height: 0; }

.ia-history-panel { width: 220px; flex-shrink: 0; display: flex; flex-direction: column; gap: 12px; }
.ia-history-list { display: flex; flex-direction: column; gap: 3px; overflow-y: auto; }
.ia-history-item {
  padding: 9px 11px; border-radius: 9px; font-size: 12.5px; color: var(--ink-soft);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; cursor: pointer;
}
.ia-history-item:hover { background: var(--surface-soft); }
.ia-history-item.active { background: var(--lime-tint); color: var(--lime-deep); font-weight: 700; }
.ia-history-empty { font-size: 12px; color: var(--ink-faint); padding: 8px 11px; }

.ia-chat { flex: 1; min-width: 0; display: flex; flex-direction: column; background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-lg); overflow: hidden; }
.ia-thread { flex: 1; overflow-y: auto; padding: 24px; display: flex; flex-direction: column; gap: 18px; }

.ia-empty-state { margin: auto; text-align: center; max-width: 480px; }
.ia-empty-title { font-family: var(--font-display); font-style: italic; font-weight: 500; font-size: 26px; margin: 0 0 22px; color: var(--ink); }
.ia-suggestions { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.ia-suggestion-chip {
  padding: 13px 16px; border-radius: var(--radius-md); border: 1px solid var(--line);
  background: var(--surface-soft); font-size: 13px; color: var(--ink-soft); text-align: left;
  transition: border-color 0.15s ease, background 0.15s ease;
}
.ia-suggestion-chip:hover { border-color: var(--lime); background: var(--lime-tint); color: var(--ink); }

.ia-msg { display: flex; max-width: 78%; }
.ia-msg.user { align-self: flex-end; }
.ia-msg.assistant { align-self: flex-start; }
.ia-msg-bubble { padding: 12px 16px; border-radius: 16px; font-size: 14px; line-height: 1.55; }
.ia-msg.user .ia-msg-bubble { background: var(--forest); color: #fff; border-bottom-right-radius: 4px; }
.ia-msg.assistant .ia-msg-bubble { background: var(--surface-soft); color: var(--ink); border-bottom-left-radius: 4px; }
.ia-msg-bubble strong { color: inherit; }
.ia-msg.assistant .ia-msg-bubble strong { color: var(--lime-deep); }

.ia-rich { margin-top: 10px; }
.ia-rich-stats { display: flex; gap: 10px; flex-wrap: wrap; }
.ia-rich-stat { padding: 10px 14px; border-radius: 10px; background: var(--surface); border: 1px solid var(--line); }
.ia-rich-stat .k { font-size: 11px; color: var(--ink-faint); }
.ia-rich-stat .v { font-size: 15px; font-weight: 800; color: var(--ink); }
.ia-rich-table { width: 100%; border-collapse: collapse; font-size: 12.5px; margin-top: 4px; background: var(--surface); border-radius: 10px; overflow: hidden; }
.ia-rich-table th { text-align: left; padding: 8px 10px; background: var(--surface-soft); font-size: 11px; text-transform: uppercase; color: var(--ink-faint); }
.ia-rich-table td { padding: 8px 10px; border-top: 1px solid var(--line-soft); }

.ia-msg-actions { display: flex; gap: 8px; margin-top: 10px; flex-wrap: wrap; }
.ia-action-btn { padding: 7px 14px; border-radius: 100px; background: var(--lime); color: var(--forest); font-size: 12.5px; font-weight: 700; }
.ia-action-btn:hover { background: var(--lime-strong); }

.ia-typing { display: flex; gap: 4px; padding: 6px 2px; }
.ia-typing span { width: 6px; height: 6px; border-radius: 50%; background: var(--ink-faint); animation: iaTyping 1.1s ease-in-out infinite; }
.ia-typing span:nth-child(2) { animation-delay: 0.15s; }
.ia-typing span:nth-child(3) { animation-delay: 0.3s; }
@keyframes iaTyping { 0%, 60%, 100% { opacity: 0.3; transform: translateY(0); } 30% { opacity: 1; transform: translateY(-3px); } }

.ia-composer { display: flex; align-items: center; gap: 10px; padding: 14px 18px; border-top: 1px solid var(--line-soft); }
.ia-composer input {
  flex: 1; border: 1px solid var(--line); background: var(--surface-soft); border-radius: 100px;
  padding: 12px 18px; font-size: 14px; font-family: inherit; color: var(--ink);
}
.ia-composer input:focus { outline: none; border-color: var(--lime-strong); background: var(--surface); }
.ia-send-btn {
  width: 40px; height: 40px; flex-shrink: 0; border-radius: 50%; background: var(--lime);
  color: var(--forest); font-size: 16px; font-weight: 800; display: flex; align-items: center; justify-content: center;
}
.ia-send-btn:hover { background: var(--lime-strong); }
.ia-send-btn:disabled { opacity: 0.5; }

@media (max-width: 860px) {
  .ia-history-panel { display: none; }
  .ia-suggestions { grid-template-columns: 1fr; }
  .ia-msg { max-width: 92%; }
}

/* =========================================================
   DESIGN SYSTEM — composants applicatifs (ui.js)
   Tout état interactif a un feedback : hover, active, focus-visible,
   disabled, loading, success, error. Durées 150–450 ms, easing naturel.
   ========================================================= */

:root {
  --ok: #2E7D32; --ok-bg: #E7F3E8;
  --warn: #B5620A; --warn-bg: #FBEEDC;
  --bad: #B23A1F; --bad-bg: #FBE4DE;
  --info: #1F5FA8; --info-bg: #E3EDF9;
  --focus: 0 0 0 3px rgba(159,227,0,0.35);
  --shadow-pop: 0 18px 48px rgba(22,36,28,0.16), 0 2px 8px rgba(22,36,28,0.06);
}
:root[data-theme="dark"] {
  --ok: #8FDB8F; --ok-bg: #163A1C;
  --warn: #E8A05C; --warn-bg: #3A2612;
  --bad: #F08C7A; --bad-bg: #3E1E17;
  --info: #8FB8F0; --info-bg: #17263C;
  --focus: 0 0 0 3px rgba(184,255,0,0.3);
  --shadow-pop: 0 18px 48px rgba(0,0,0,0.6), 0 2px 8px rgba(0,0,0,0.4);
}

:focus-visible { outline: none; box-shadow: var(--focus); border-radius: 8px; }
.ic { flex-shrink: 0; vertical-align: middle; }
.muted { color: var(--ink-faint); font-size: 13px; margin: 0; }
.mt-8 { margin-top: 8px; } .mt-16 { margin-top: 16px; } .mb-0 { margin-bottom: 0; }
.row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.row.between { justify-content: space-between; }
.grow { flex: 1; min-width: 0; }
.dash-body { max-width: 1120px; }
.dash-body.narrow { max-width: 760px; }

/* ---- Boutons : états complets ---- */
.btn { position: relative; gap: 7px; }
.btn:focus-visible { box-shadow: var(--focus), var(--shadow-sm); }
.btn:disabled, .btn[aria-disabled="true"] { opacity: 0.55; cursor: not-allowed; transform: none !important; box-shadow: none !important; }
.btn.is-loading { pointer-events: none; }
.btn.is-success { background: var(--ok-bg) !important; color: var(--ok) !important; border-color: transparent; }
.btn.is-error { background: var(--bad-bg) !important; color: var(--bad) !important; border-color: transparent; }
.btn-danger { background: transparent; color: var(--bad); border-color: var(--line); }
.btn-danger:hover { background: var(--bad-bg); border-color: var(--bad); }
.btn-xs { padding: 6px 12px; font-size: 12.5px; }
.btn.block { width: 100%; }
.link-btn { background: none; border: none; padding: 0; font: inherit; font-size: 12.5px; font-weight: 700; color: var(--lime-deep); cursor: pointer; }
.link-btn:hover { color: var(--forest); text-decoration: underline; }
.spinner {
  width: 14px; height: 14px; border-radius: 50%; flex-shrink: 0;
  border: 2px solid currentColor; border-right-color: transparent;
  animation: spin 0.7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
.icon-btn:focus-visible { box-shadow: var(--focus); }
.icon-btn.active { background: var(--lime-tint); color: var(--lime-deep); border-color: var(--lime); }

/* ---- Champs ---- */
.field textarea {
  width: 100%; padding: 12px 14px; border-radius: 10px; min-height: 84px; resize: vertical;
  border: 1.5px solid var(--line); background: var(--surface-soft); font-size: 14px; font-family: inherit; color: var(--ink);
  transition: border-color 0.2s ease, background 0.2s ease;
}
.field textarea:focus { outline: none; border-color: var(--lime-strong); background: var(--surface); }
.field input:focus-visible, .field select:focus-visible, .field textarea:focus-visible { box-shadow: var(--focus); border-radius: 10px; }
.field .hint { display: block; font-size: 12px; color: var(--ink-faint); margin-top: 6px; }
.field input:disabled, .field select:disabled { opacity: 0.6; cursor: not-allowed; }
.check { display: flex; align-items: center; gap: 10px; font-size: 13.5px; color: var(--ink); cursor: pointer; padding: 6px 0; }
.check input { width: 17px; height: 17px; accent-color: var(--lime-deep); flex-shrink: 0; }
.switch { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 12px 0; border-bottom: 1px solid var(--line-soft); }
.switch:last-child { border-bottom: none; }
.switch .sw-text strong { display: block; font-size: 14px; }
.switch .sw-text span { font-size: 12.5px; color: var(--ink-faint); line-height: 1.5; }
.switch input { appearance: none; width: 42px; height: 24px; border-radius: 100px; background: var(--line); position: relative; cursor: pointer; flex-shrink: 0; transition: background 0.2s ease; }
.switch input::after { content: ""; position: absolute; top: 3px; left: 3px; width: 18px; height: 18px; border-radius: 50%; background: #fff; box-shadow: 0 1px 3px rgba(0,0,0,0.25); transition: transform 0.25s var(--ease-out); }
.switch input:checked { background: var(--lime-deep); }
.switch input:checked::after { transform: translateX(18px); }
.switch input:focus-visible { box-shadow: var(--focus); }
.form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px 14px; }
.form-grid .field { margin-bottom: 0; }
.form-grid .full { grid-column: 1 / -1; }
.form-error { color: var(--bad); font-size: 13px; margin: 0 0 12px; }
.form-msg.error { color: var(--bad); }
.form-msg.success { color: var(--ok); }

/* ---- Sidebar (icônes SVG, mobile) ---- */
.s-item { gap: 12px; }
.s-item .s-ic { width: 20px; display: flex; align-items: center; justify-content: center; opacity: 0.85; }
.s-item.active .s-ic { opacity: 1; }
.s-item:focus-visible { box-shadow: var(--focus); }
.sidebar-scrim { position: fixed; inset: 0; background: rgba(17,17,17,0.45); z-index: 45; backdrop-filter: blur(2px); }
.topbar { padding: 12px 24px; }
.topbar-right { position: relative; }
.avatar { cursor: pointer; transition: transform 0.15s ease, box-shadow 0.15s ease; }
.avatar:hover { transform: translateY(-1px); box-shadow: var(--shadow-sm); }
.avatar:focus-visible { box-shadow: var(--focus); }
.bell::after { content: none; }
.bell { position: relative; }
.bell-count {
  position: absolute; top: -5px; right: -5px; min-width: 18px; height: 18px; padding: 0 5px; border-radius: 100px;
  background: var(--gold); color: #1a1200; font-size: 10.5px; font-weight: 800; display: flex; align-items: center; justify-content: center;
  border: 2px solid var(--bg);
}

/* ---- Popovers (compte, notifications) ---- */
.popover {
  position: absolute; top: calc(100% + 10px); right: 0; z-index: 60; min-width: 240px;
  background: var(--surface); border: 1px solid var(--line); border-radius: 16px; box-shadow: var(--shadow-pop);
  animation: popIn 0.22s var(--ease-out);
}
@keyframes popIn { from { opacity: 0; transform: translateY(-6px) scale(0.98); } to { opacity: 1; transform: none; } }
.pop-head { display: flex; justify-content: space-between; align-items: center; gap: 12px; padding: 14px 16px 10px; border-bottom: 1px solid var(--line-soft); }
.pop-head strong { font-size: 14px; display: block; }
.pop-head span { font-size: 12px; color: var(--ink-faint); }
.pop-item { display: flex; align-items: center; gap: 10px; padding: 11px 16px; font-size: 13.5px; color: var(--ink); width: 100%; background: none; border: none; text-align: left; font-family: inherit; cursor: pointer; }
.pop-item:hover { background: var(--surface-soft); }
.pop-foot { display: flex; align-items: center; justify-content: center; gap: 4px; padding: 11px; font-size: 12.5px; font-weight: 700; color: var(--lime-deep); border-top: 1px solid var(--line-soft); }
.pop-foot:hover { background: var(--surface-soft); }
.notif-pop { width: 360px; max-width: calc(100vw - 32px); }
.notif-list { max-height: 380px; overflow-y: auto; }
.notif-item { display: flex; gap: 10px; padding: 11px 16px; border-bottom: 1px solid var(--line-soft); color: var(--ink); }
.notif-item:hover { background: var(--surface-soft); }
.notif-item .notif-dot { width: 8px; height: 8px; border-radius: 50%; background: transparent; margin-top: 6px; flex-shrink: 0; }
.notif-item.unread .notif-dot { background: var(--lime-deep); }
.notif-item .notif-body { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.notif-item .notif-body strong { font-size: 13px; }
.notif-item .notif-body span { font-size: 12.5px; color: var(--ink-soft); line-height: 1.45; }
.notif-item .notif-body em { font-style: normal; font-size: 11.5px; color: var(--ink-faint); }
.notif-page-list .notif-item { padding: 14px 18px; border-radius: 12px; border: 1px solid var(--line-soft); margin-bottom: 8px; background: var(--surface); }
.notif-page-list .notif-item.unread { border-color: rgba(124,196,0,0.4); background: var(--lime-tint); }
:root[data-theme="dark"] .notif-page-list .notif-item.unread { background: #1B2A0A; }

/* ---- KPI ---- */
.kpi-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 14px; margin-bottom: 24px; }
.kpi-grid.cols-3 { grid-template-columns: repeat(3, 1fr); }
.kpi-grid.cols-5 { grid-template-columns: repeat(5, 1fr); }
.kpi-card {
  position: relative; display: flex; flex-direction: column; gap: 4px; padding: 18px 18px 16px; border-radius: 16px;
  background: var(--surface); border: 1px solid var(--line); box-shadow: var(--shadow-sm);
  transition: transform 0.25s var(--ease-out), box-shadow 0.25s var(--ease-out), border-color 0.2s ease;
}
.kpi-card.clickable { cursor: pointer; }
.kpi-card.clickable:hover { transform: translateY(-2px); box-shadow: var(--shadow-md); border-color: var(--lime-strong); }
.kpi-card .kpi-ic { position: absolute; top: 14px; right: 14px; width: 30px; height: 30px; border-radius: 9px; background: var(--surface-soft); color: var(--ink-soft); display: flex; align-items: center; justify-content: center; }
.kpi-card .kpi-k { font-size: 12.5px; color: var(--ink-faint); font-weight: 600; padding-right: 36px; }
.kpi-card .kpi-v { font-size: 24px; font-weight: 800; letter-spacing: -0.02em; line-height: 1.15; }
.kpi-card .kpi-v.ok, .kpi-card .kpi-v.lime { color: var(--lime-deep); }
.kpi-card .kpi-v.warn { color: var(--warn); }
.kpi-card .kpi-v.bad { color: var(--bad); }
.kpi-card .kpi-sub { font-size: 12px; color: var(--ink-faint); }
.kpi-card.accent { background: var(--forest); border-color: var(--forest); color: #fff; }
.kpi-card.accent .kpi-k, .kpi-card.accent .kpi-sub { color: rgba(231,239,227,0.7); }
.kpi-card.accent .kpi-v { color: var(--lime); }
.kpi-card.accent .kpi-ic { background: rgba(255,255,255,0.08); color: var(--lime); }

/* ---- Graphiques légers ---- */
.bar-rows { display: flex; flex-direction: column; gap: 9px; }
.bar-row { display: flex; align-items: center; gap: 12px; }
.bar-row.clickable { cursor: pointer; border-radius: 8px; }
.bar-row.clickable:hover .br-label { color: var(--ink); }
.br-label { flex: 0 0 140px; font-size: 12.5px; color: var(--ink-soft); text-align: right; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.br-track { flex: 1; height: 14px; border-radius: 7px; background: var(--surface-soft); overflow: hidden; }
.br-bar { display: block; height: 100%; border-radius: 7px; background: linear-gradient(90deg, var(--lime-deep), var(--lime)); transition: width 0.7s var(--ease-out); }
.br-bar.warn { background: linear-gradient(90deg, #C77A1C, #F0B429); }
.br-bar.bad { background: linear-gradient(90deg, #A6420F, #E8836A); }
.br-bar.neutral { background: var(--ink-faint); }
.br-value { flex: 0 0 70px; font-size: 12.5px; font-weight: 700; color: var(--ink); }
.stack-bar { display: flex; height: 12px; border-radius: 6px; overflow: hidden; background: var(--surface-soft); }
.stack-bar .sb { display: block; height: 100%; }
.sb.ok { background: var(--lime-deep); } .sb.warn { background: var(--gold); } .sb.bad { background: #D9583B; } .sb.neutral { background: var(--ink-faint); }
.legend { display: flex; gap: 14px; flex-wrap: wrap; font-size: 12px; color: var(--ink-soft); margin-top: 10px; }
.legend span::before { content: ""; display: inline-block; width: 9px; height: 9px; border-radius: 3px; margin-right: 6px; vertical-align: middle; background: var(--ink-faint); }
.legend .ok::before { background: var(--lime-deep); } .legend .warn::before { background: var(--gold); } .legend .bad::before { background: #D9583B; }
.ring { display: flex; align-items: center; gap: 12px; }
.ring svg { transform: rotate(-90deg); flex-shrink: 0; }
.ring-bg { fill: none; stroke: var(--surface-soft); stroke-width: 7; }
.ring-fg { fill: none; stroke: var(--lime-deep); stroke-width: 7; stroke-linecap: round; transition: stroke-dashoffset 0.9s var(--ease-out); }
.ring.warn .ring-fg { stroke: var(--gold); }
.ring-txt strong { display: block; font-size: 20px; font-weight: 800; letter-spacing: -0.02em; }
.ring-txt span { font-size: 12px; color: var(--ink-faint); }
.two-col { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; }
.three-col { display: grid; grid-template-columns: repeat(3, 1fr); gap: 18px; }
.panel .panel-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 14px; flex-wrap: wrap; }
.panel .panel-head h2 { margin: 0; }
.panel .panel-head .sub { font-size: 12.5px; color: var(--ink-faint); }
.panel.compact { padding: 16px 18px; }

/* ---- Badges ---- */
.badge { gap: 5px; }
.badge.ok { background: var(--ok-bg); color: var(--ok); }
.badge.warn { background: var(--warn-bg); color: var(--warn); }
.badge.bad { background: var(--bad-bg); color: var(--bad); }
.badge.neutral { background: var(--surface-soft); color: var(--ink-soft); }
.badge.info { background: var(--info-bg); color: var(--info); }
.badge.lg { padding: 6px 14px; font-size: 13px; }
.chip-code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; letter-spacing: 0.04em; color: var(--ink-soft); background: var(--surface-soft); border: 1px solid var(--line-soft); padding: 3px 8px; border-radius: 6px; }

/* ---- Avatars ---- */
.avatar-init, .avatar-img { display: inline-flex; align-items: center; justify-content: center; border-radius: 50%; flex-shrink: 0; overflow: hidden; font-weight: 800; background: var(--lime); color: var(--forest); }
.avatar-img img { width: 100%; height: 100%; object-fit: cover; }
.avatar-init.soft { background: var(--forest-tint); color: var(--forest-700); }

/* ---- Skeletons ---- */
.sk { display: block; border-radius: 6px; background: linear-gradient(90deg, var(--surface-soft) 25%, var(--line-soft) 50%, var(--surface-soft) 75%); background-size: 200% 100%; animation: shimmer 1.3s ease-in-out infinite; }
@keyframes shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }
.sk-text { height: 12px; margin: 6px 0; } .sk-title { height: 20px; margin: 8px 0; }
.sk-circle { width: 34px; height: 34px; border-radius: 50%; flex-shrink: 0; } .sk-circle.lg { width: 56px; height: 56px; margin: 0 auto 10px; }
.w20 { width: 20%; } .w40 { width: 40%; } .w50 { width: 50%; } .w60 { width: 60%; } .w70 { width: 70%; } .w80 { width: 80%; } .w90 { width: 90%; }
.sk-row { display: flex; align-items: center; gap: 12px; padding: 10px 0; }
.sk-row .sk-text { margin: 0; }
.sk-wrap { width: 100%; }
.kpi-grid .sk-wrap { display: contents; }
.panel.is-skeleton { pointer-events: none; }
.sfolder.is-skeleton { pointer-events: none; padding-top: 20px; }

/* ---- États vides / erreur ---- */
.empty-state, .error-state { text-align: center; padding: 40px 20px; color: var(--ink-faint); display: flex; flex-direction: column; align-items: center; gap: 8px; }
.empty-state h3, .error-state h3 { margin: 6px 0 0; font-size: 15px; color: var(--ink); }
.empty-state p, .error-state p { margin: 0; font-size: 13.5px; max-width: 380px; line-height: 1.55; }
.empty-state .btn, .error-state .btn { margin-top: 10px; }
.error-state .ic { color: var(--bad); }
.empty-state .ic { color: var(--ink-faint); }

/* ---- Toasts ---- */
.toast-host { position: fixed; bottom: 22px; right: 22px; z-index: 900; display: flex; flex-direction: column; gap: 8px; pointer-events: none; }
.toast { display: flex; align-items: center; gap: 10px; padding: 12px 16px; border-radius: 12px; background: var(--forest); color: #fff; font-size: 13.5px; box-shadow: var(--shadow-lg); opacity: 0; transform: translateY(8px); transition: opacity 0.25s ease, transform 0.3s var(--ease-out); max-width: 360px; }
.toast.shown { opacity: 1; transform: none; }
.toast.success { background: #1F5A2A; } .toast.error { background: #7A2A1C; }
.toast .ic { color: var(--lime); }
.toast.error .ic { color: #FFB4A3; }

/* ---- Modales ---- */
.modal-backdrop { position: fixed; inset: 0; z-index: 700; display: flex; align-items: center; justify-content: center; padding: 20px; background: rgba(17,17,17,0.35); backdrop-filter: blur(4px); opacity: 0; transition: opacity 0.22s ease; }
.modal-backdrop.shown { opacity: 1; }
.modal { width: 100%; max-width: 520px; max-height: calc(100vh - 40px); display: flex; flex-direction: column; background: var(--surface); border: 1px solid var(--line); border-radius: 20px; box-shadow: var(--shadow-lg); transform: scale(0.96) translateY(8px); transition: transform 0.28s var(--ease-out); }
.modal.lg { max-width: 760px; }
.modal-backdrop.shown .modal { transform: none; }
.modal-head { display: flex; align-items: center; justify-content: space-between; padding: 18px 22px 12px; }
.modal-head h2 { margin: 0; font-size: 17px; font-weight: 800; }
.modal-body { padding: 4px 22px 18px; overflow-y: auto; }
.modal-foot { display: flex; justify-content: flex-end; gap: 10px; padding: 14px 22px 18px; border-top: 1px solid var(--line-soft); }
.modal-text { font-size: 14px; color: var(--ink-soft); line-height: 1.6; margin: 0; }

/* ---- Onglets ---- */
/* Les onglets PASSENT À LA LIGNE, ils ne défilent pas.

   Avant : `overflow-x: auto` + `scrollbar-width: none` + scrollbar WebKit
   masquée. Le dossier élève porte neuf onglets ; à 1024 px, quatre d'entre eux
   — dont **Finance**, d'où l'on crée les obligations — sortaient du cadre sans
   la moindre indication, et aucune barre ne permettait d'y aller. À la souris,
   ces écrans étaient tout simplement inatteignables.

   Un bandeau qui se replie est plus haut, mais tout y est cliquable. Ne pas
   remettre un défilement horizontal sans affordance visible. */
.tabs { display: flex; flex-wrap: wrap; gap: 4px 4px; border-bottom: 1px solid var(--line); margin-bottom: 20px; }
.tab-btn { background: none; border: none; padding: 11px 14px; font: inherit; font-size: 13.5px; font-weight: 600; color: var(--ink-faint); border-bottom: 2px solid transparent; margin-bottom: -1px; white-space: nowrap; display: inline-flex; align-items: center; gap: 7px; transition: color 0.15s ease, border-color 0.15s ease; }
.tab-btn:hover { color: var(--ink); }
.tab-btn.active { color: var(--ink); border-bottom-color: var(--lime-deep); }
.tab-btn:focus-visible { box-shadow: var(--focus); border-radius: 8px; }
.tab-btn .cnt { font-size: 11px; padding: 1px 7px; border-radius: 100px; background: var(--surface-soft); color: var(--ink-soft); }
[data-tab-panel] { animation: stepIn 0.3s var(--ease-out); }

/* ---- Calendrier académique : échéances et période en cours ----
   Les jetons de couleur viennent des variables de thème, donc clair ET sombre
   suivent sans règle en double. Une échéance dépassée est signalée par le
   texte (« — dépassée ») autant que par la couleur : la couleur seule ne dit
   rien à qui ne la distingue pas. */
.ech-row { display: flex; flex-wrap: wrap; gap: 4px 10px; }
.ech { font-size: 12.5px; color: var(--ink-soft); white-space: nowrap; }
.ech-passee { color: var(--bad); font-weight: 600; }
.row-courante > td { background: var(--surface-soft); }
.row-courante > td:first-child { box-shadow: inset 3px 0 0 var(--lime-deep); }
.nowrap { white-space: nowrap; }
.act-liens { display: block; margin-top: 4px; }
.act-liens .link-btn + .link-btn { margin-left: 10px; }
.link-btn.danger { color: var(--bad); }
.link-btn.danger:hover { color: var(--bad); }

/* ==== Espace parent — frais scolaires =================================
   Pensé pour le téléphone d'abord : cibles tactiles d'au moins 44 px, le
   montant à payer en gros, une seule action principale par écran. Toutes les
   couleurs passent par les jetons de thème — clair et sombre suivent sans
   règle dupliquée, et le lime reste un ACCENT, jamais un fond de page. */

/* Sélecteur d'enfant : il ne s'affiche qu'à partir de deux enfants. */
.enfant-tabs { display: flex; gap: 8px; overflow-x: auto; padding-bottom: 4px; margin-bottom: 14px; -webkit-overflow-scrolling: touch; }
.enfant-tab {
  display: flex; align-items: center; gap: 9px; flex: 0 0 auto;
  min-height: 52px; padding: 8px 14px 8px 8px;
  background: var(--surface); border: 1.5px solid var(--line); border-radius: 100px;
  font: inherit; color: var(--ink-soft); cursor: pointer;
  transition: border-color 0.18s ease, color 0.18s ease;
}
.enfant-tab:hover { color: var(--ink); }
.enfant-tab.active { border-color: var(--lime-deep); color: var(--ink); }
.enfant-tab:focus-visible { box-shadow: var(--focus); }
.et-id { display: flex; flex-direction: column; align-items: flex-start; line-height: 1.25; }
.et-id strong { font-size: 13.5px; font-weight: 700; }
.et-id span { font-size: 11.5px; color: var(--ink-faint); }

.enfant-tete { margin-bottom: 14px; }

/* Le bloc d'action : ce qu'il faut payer maintenant, et rien d'autre. */
.bloc-payer { margin-bottom: 16px; }
.bp-kicker { display: block; font-size: 11.5px; font-weight: 800; letter-spacing: 0.06em; text-transform: uppercase; color: var(--ink-faint); margin-bottom: 8px; }
.bp-ligne { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.bp-montant { font-size: 30px; font-weight: 800; letter-spacing: -0.02em; line-height: 1.1; }
.bp-label { font-size: 14px; color: var(--ink-soft); }
.bp-date { display: flex; align-items: center; gap: 7px; margin: 8px 0 0; font-size: 13px; color: var(--ink-soft); }
.bp-btn { width: 100%; min-height: 50px; margin-top: 14px; font-size: 15px; }
.bloc-payer.est-retard { border-color: var(--bad); }
.bloc-payer.est-retard .bp-kicker, .bloc-payer.est-retard .bp-date { color: var(--bad); }
.bloc-payer.est-attente { border-color: var(--gold); }
.bloc-payer.est-attente .bp-kicker { color: var(--warn); }

/* Échéancier : un frais, ses tranches. */
.frais-bloc + .frais-bloc { margin-top: 18px; }
.frais-titre { margin: 0 0 8px; font-size: 14px; font-weight: 700; }
.obligation-card.ob-retard { border-color: var(--bad); }

/* Résultat d'un paiement — reflète l'état RENVOYÉ PAR LE SERVEUR.
   Aucune coche verte n'apparaît avant une réponse réelle : l'état « attente »
   est le cas normal tant qu'aucun fournisseur n'a confirmé la transaction. */
.pay-resultat { text-align: center; padding: 18px 8px 6px; }
.pay-resultat .pr-ic { display: inline-flex; align-items: center; justify-content: center; width: 58px; height: 58px; border-radius: 100px; margin-bottom: 12px; }
.pay-resultat.ok .pr-ic { background: var(--ok-bg); color: var(--ok); }
.pay-resultat.attente .pr-ic { background: var(--warn-bg); color: var(--warn); }
.pay-resultat h3 { margin: 0 0 8px; font-size: 18px; font-weight: 800; }
.pay-resultat p { margin: 0; font-size: 13.5px; color: var(--ink-soft); line-height: 1.6; }

@media (max-width: 560px) {
  .bp-montant { font-size: 26px; }
  .enfant-tab { min-height: 48px; }
}

/* Échéancier saisi par la Direction (dossier élève → Ajouter un frais). */
.tranche-liste { display: flex; flex-direction: column; gap: 8px; margin-top: 6px; }
.tranche-ligne { display: grid; grid-template-columns: 92px 1fr auto 150px; align-items: center; gap: 8px; }
.tranche-ligne .tl-num { font-size: 12.5px; font-weight: 700; color: var(--ink-soft); }
.tranche-ligne .tl-cur { font-size: 12.5px; color: var(--ink-faint); }
.hint-alerte { color: var(--warn); font-weight: 600; }
@media (max-width: 620px) {
  .tranche-ligne { grid-template-columns: 1fr auto; grid-template-areas: "num num" "montant cur" "date date"; }
  .tranche-ligne .tl-num { grid-area: num; }
  .tranche-ligne .tl-montant { grid-area: montant; }
  .tranche-ligne .tl-cur { grid-area: cur; }
  .tranche-ligne .tl-date { grid-area: date; }
}

/* ---- Filtres / barre d'outils ---- */
.toolbar { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 18px; }
.toolbar .search { display: flex; align-items: center; gap: 8px; flex: 1; min-width: 220px; padding: 0 14px; height: 42px; border-radius: 100px; background: var(--surface); border: 1.5px solid var(--line); color: var(--ink-faint); transition: border-color 0.2s ease, box-shadow 0.2s ease; }
.toolbar .search:focus-within { border-color: var(--lime-strong); box-shadow: var(--focus); }
.toolbar .search input { border: none; background: none; outline: none; flex: 1; font: inherit; font-size: 14px; color: var(--ink); min-width: 0; }
.toolbar select, .field-inline select { height: 42px; padding: 0 34px 0 14px; border-radius: 100px; border: 1.5px solid var(--line); background: var(--surface); font: inherit; font-size: 13.5px; color: var(--ink); appearance: none; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%238A9389' stroke-width='2'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right 12px center; background-size: 14px; }
.toolbar select:focus { outline: none; border-color: var(--lime-strong); }
.chips { display: flex; gap: 6px; flex-wrap: wrap; }
.chip { padding: 8px 14px; border-radius: 100px; border: 1px solid var(--line); background: var(--surface); font: inherit; font-size: 12.5px; font-weight: 600; color: var(--ink-soft); cursor: pointer; transition: all 0.15s ease; }
.chip:hover { border-color: var(--ink-faint); color: var(--ink); }
.chip.active { background: var(--forest); color: #fff; border-color: var(--forest); }
.chip:focus-visible { box-shadow: var(--focus); }
.view-toggle { display: flex; border: 1px solid var(--line); border-radius: 100px; padding: 3px; background: var(--surface-soft); }
.view-toggle button { border: none; background: none; width: 34px; height: 32px; border-radius: 100px; color: var(--ink-faint); display: flex; align-items: center; justify-content: center; cursor: pointer; }
.view-toggle button.active { background: var(--surface); color: var(--ink); box-shadow: var(--shadow-sm); }
.count-label { font-size: 12.5px; color: var(--ink-faint); white-space: nowrap; }

/* ---- Tableaux améliorés & responsive ---- */
.table-wrap { overflow-x: auto; }
.data-table th.sortable { cursor: pointer; user-select: none; }
.data-table th.sortable:hover { color: var(--ink); }
.data-table th.sortable.asc::after { content: " ↑"; } .data-table th.sortable.desc::after { content: " ↓"; }
.data-table td .cell-main { font-weight: 600; color: var(--ink); display: flex; align-items: center; gap: 10px; }
.data-table td .cell-sub { font-size: 12px; color: var(--ink-faint); display: block; margin-top: 1px; }
.data-table td.num { text-align: right; font-variant-numeric: tabular-nums; }
.data-table th.num { text-align: right; }
.data-table td.actions { text-align: right; white-space: nowrap; }
.data-table tr.clickable:focus-visible { box-shadow: inset var(--focus); }
.pagination { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-top: 14px; font-size: 12.5px; color: var(--ink-faint); flex-wrap: wrap; }
.pagination .pg-btns { display: flex; gap: 6px; }
.pagination button { border: 1px solid var(--line); background: var(--surface); width: 34px; height: 34px; border-radius: 10px; color: var(--ink-soft); display: flex; align-items: center; justify-content: center; cursor: pointer; }
.pagination button:disabled { opacity: 0.4; cursor: not-allowed; }
.pagination button:hover:not(:disabled) { border-color: var(--ink-faint); color: var(--ink); }
@media (max-width: 700px) {
  .data-table.responsive thead { display: none; }
  .data-table.responsive tr { display: block; border: 1px solid var(--line-soft); border-radius: 12px; margin-bottom: 10px; padding: 6px 4px; }
  .data-table.responsive td { display: flex; justify-content: space-between; gap: 12px; padding: 8px 10px; border: none; text-align: left !important; }
  .data-table.responsive td::before { content: attr(data-label); font-size: 11px; text-transform: uppercase; letter-spacing: 0.05em; color: var(--ink-faint); font-weight: 700; }
  .data-table.responsive td.actions { justify-content: flex-end; }
  .data-table.responsive .empty-row td { display: block; text-align: center !important; }
}

/* ---- Dossier élève 3D (page Élèves) ----
   Recréation vanilla de l'effet "3D Folder" : dossier en perspective, dont
   les documents (Profil / Scolarité / Présence / Finance) sortent en éventail
   au survol, avant que le clic n'ouvre le vrai dossier. Tap sur mobile,
   Entrée au clavier, aucune 3D avec prefers-reduced-motion. */
.sfolder-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(178px, 1fr)); gap: 22px 18px; }
.sfolder {
  position: relative; display: flex; flex-direction: column; align-items: center; text-align: center;
  padding: 104px 12px 16px; border-radius: 18px; background: var(--surface); border: 1px solid var(--line);
  cursor: pointer; color: inherit; transition: transform 0.35s var(--ease-out), box-shadow 0.35s var(--ease-out), border-color 0.2s ease;
  perspective: 900px;
}
.sfolder:hover, .sfolder:focus-visible { transform: translateY(-4px); box-shadow: var(--shadow-md); border-color: rgba(124,196,0,0.5); outline: none; z-index: 6; }
.sfolder:focus-visible { box-shadow: var(--focus), var(--shadow-md); }
.sfolder.selected { border-color: var(--lime-strong); box-shadow: 0 0 0 1px var(--lime-strong), var(--shadow-md); }
.sfolder .sf-scene { position: absolute; top: 30px; left: 50%; width: 112px; height: 74px; transform: translateX(-50%); transform-style: preserve-3d; }
.sfolder .sf-back { position: absolute; inset: 0; border-radius: 6px 10px 10px 10px; background: linear-gradient(160deg, var(--lime-deep), var(--forest)); box-shadow: var(--shadow-sm); }
.sfolder .sf-back::before { content: ""; position: absolute; top: -9px; left: 8px; width: 40px; height: 12px; border-radius: 6px 6px 0 0; background: var(--lime-deep); }
.sfolder .sf-doc {
  position: absolute; left: 12px; right: 12px; bottom: 8px; height: 58px; border-radius: 6px; background: var(--surface-soft); border: 1px solid var(--line); box-shadow: var(--shadow-sm);
  display: flex; align-items: flex-end; padding: 0 0 6px 8px; font-size: 9.5px; font-weight: 700; color: var(--ink-soft); letter-spacing: 0.02em;
  transform-origin: bottom center; transform: translateY(0) rotate(0deg); transition: transform 0.45s var(--ease-out), opacity 0.3s ease; opacity: 0.001;
}
.sfolder .sf-doc::before { content: ""; position: absolute; top: 8px; left: 8px; right: 8px; height: 3px; border-radius: 2px; background: var(--line); box-shadow: 0 7px 0 var(--line-soft), 0 14px 0 var(--line-soft); }
.sfolder .sf-doc.d1 { --tx: -34px; --rot: -14deg; }
.sfolder .sf-doc.d2 { --tx: -11px; --rot: -5deg; }
.sfolder .sf-doc.d3 { --tx: 11px; --rot: 5deg; }
.sfolder .sf-doc.d4 { --tx: 34px; --rot: 14deg; }
.sfolder:hover .sf-doc, .sfolder:focus-visible .sf-doc, .sfolder.open .sf-doc { opacity: 1; transform: translate(var(--tx), -36px) rotate(var(--rot)); }
.sfolder .sf-front {
  position: absolute; left: 0; right: 0; bottom: 0; height: 60px; border-radius: 6px 6px 10px 10px;
  background: linear-gradient(170deg, var(--lime) 0%, var(--lime-strong) 100%); transform-origin: bottom center;
  transition: transform 0.45s var(--ease-out); box-shadow: inset 0 1px 0 rgba(255,255,255,0.35);
}
.sfolder:hover .sf-front, .sfolder:focus-visible .sf-front, .sfolder.open .sf-front { transform: rotateX(-24deg) translateY(4px); }
.sfolder .sf-avatar { position: absolute; left: 50%; bottom: -18px; transform: translateX(-50%); border: 3px solid var(--surface); box-shadow: var(--shadow-sm); z-index: 3; }
.sfolder .sf-name { font-size: 14px; font-weight: 700; margin-top: 14px; line-height: 1.25; color: var(--ink); }
.sfolder .sf-class { font-size: 12.5px; color: var(--ink-soft); margin-top: 2px; }
.sfolder .sf-code { margin-top: 8px; }
.sfolder .sf-status { position: absolute; top: 8px; left: 8px; z-index: 4; }
.sfolder .sf-status .badge { font-size: 10.5px; padding: 2px 8px; }
.sfolder .sf-foot { display: flex; gap: 6px; margin-top: 10px; flex-wrap: wrap; justify-content: center; }
@media (hover: none) { .sfolder .sf-doc { opacity: 0.001; } .sfolder .sf-front { transform: none !important; } }

/* ---- Dossier élève : en-tête, timeline, présences ---- */
.dossier-head { display: flex; align-items: center; gap: 20px; padding: 22px 24px; border-radius: 20px; background: var(--surface); border: 1px solid var(--line); box-shadow: var(--shadow-sm); margin-bottom: 20px; flex-wrap: wrap; }
.dossier-head .dh-photo { position: relative; }
.dossier-head .dh-photo .photo-btn { position: absolute; bottom: -4px; right: -4px; width: 28px; height: 28px; border-radius: 50%; background: var(--surface); border: 1px solid var(--line); display: flex; align-items: center; justify-content: center; color: var(--ink-soft); cursor: pointer; }
.dossier-head .dh-photo .photo-btn:hover { color: var(--ink); border-color: var(--ink-faint); }
.dossier-head h1 { font-size: 24px; font-weight: 800; letter-spacing: -0.02em; margin: 0 0 4px; }
.dossier-head .dh-meta { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; font-size: 13px; color: var(--ink-soft); }
.dossier-head .dh-actions { margin-left: auto; display: flex; gap: 8px; flex-wrap: wrap; }
.dossier-head .dh-kpis { display: flex; gap: 18px; width: 100%; margin-top: 8px; padding-top: 14px; border-top: 1px solid var(--line-soft); flex-wrap: wrap; }
.dossier-head .dh-kpi { display: flex; flex-direction: column; gap: 2px; min-width: 110px; }
.dossier-head .dh-kpi .k { font-size: 11.5px; color: var(--ink-faint); font-weight: 600; text-transform: uppercase; letter-spacing: 0.04em; }
.dossier-head .dh-kpi .v { font-size: 16px; font-weight: 800; }
.dl { display: grid; grid-template-columns: 160px 1fr; gap: 10px 16px; font-size: 13.5px; margin: 0; }
.dl dt { color: var(--ink-faint); } .dl dd { margin: 0; color: var(--ink); font-weight: 600; }
.timeline { display: flex; flex-direction: column; gap: 0; }
.tl-item { display: grid; grid-template-columns: 20px 1fr; gap: 12px; padding: 0 0 18px; position: relative; }
.tl-item::before { content: ""; position: absolute; left: 9px; top: 18px; bottom: -2px; width: 2px; background: var(--line-soft); }
.tl-item:last-child::before { display: none; }
.tl-dot { width: 20px; height: 20px; border-radius: 50%; background: var(--surface-soft); border: 2px solid var(--line); margin-top: 1px; }
.tl-dot.bad { border-color: #D9583B; background: var(--bad-bg); } .tl-dot.warn { border-color: var(--gold); background: var(--warn-bg); } .tl-dot.ok { border-color: var(--lime-deep); background: var(--lime-tint); }
.tl-body strong { display: block; font-size: 14px; }
.tl-body span { font-size: 13px; color: var(--ink-soft); line-height: 1.5; }
.tl-body em { display: block; font-style: normal; font-size: 12px; color: var(--ink-faint); margin-top: 3px; }
.att-grid { display: flex; flex-wrap: wrap; gap: 5px; }
.att-day { width: 30px; height: 30px; border-radius: 8px; display: flex; align-items: center; justify-content: center; font-size: 10px; font-weight: 700; background: var(--surface-soft); color: var(--ink-faint); }
.att-day.present { background: var(--lime-tint); color: var(--lime-deep); } .att-day.late { background: var(--warn-bg); color: var(--warn); }
.att-day.absent { background: var(--bad-bg); color: var(--bad); } .att-day.excused { background: var(--info-bg); color: var(--info); }

/* ---- Appel (présence) : rapide au doigt ---- */
.roll-list { display: flex; flex-direction: column; gap: 8px; }
.roll-row { display: flex; align-items: center; gap: 12px; padding: 10px 12px; border-radius: 12px; border: 1px solid var(--line-soft); background: var(--surface); }
.roll-row .roll-name { flex: 1; min-width: 0; font-size: 14px; font-weight: 600; }
.roll-row .roll-name span { display: block; font-size: 12px; color: var(--ink-faint); font-weight: 400; }
.seg { display: flex; border: 1px solid var(--line); border-radius: 100px; padding: 3px; background: var(--surface-soft); gap: 2px; }
.seg button { border: none; background: none; padding: 7px 12px; border-radius: 100px; font: inherit; font-size: 12.5px; font-weight: 700; color: var(--ink-faint); cursor: pointer; transition: all 0.15s ease; min-width: 40px; }
.seg button:hover { color: var(--ink); }
.seg button.active.present { background: var(--lime-deep); color: #fff; }
.seg button.active.late { background: var(--gold); color: #1a1200; }
.seg button.active.absent { background: #D9583B; color: #fff; }
.seg button.active.excused { background: var(--info); color: #fff; }
.seg button:focus-visible { box-shadow: var(--focus); }
.roll-summary { display: flex; gap: 14px; flex-wrap: wrap; font-size: 13px; color: var(--ink-soft); }
.roll-summary strong { color: var(--ink); }
.sticky-actions { position: sticky; bottom: 0; background: var(--bg); padding: 14px 0 4px; margin-top: 8px; border-top: 1px solid var(--line-soft); display: flex; justify-content: space-between; align-items: center; gap: 12px; flex-wrap: wrap; z-index: 5; }

/* ---- Notes ---- */
.grade-input { width: 74px; text-align: center; padding: 8px 6px !important; }
.grades-table td .grade-cell { display: flex; align-items: center; gap: 6px; justify-content: flex-end; }
.bulletin { background: var(--surface); border: 1px solid var(--line); border-radius: 16px; padding: 24px; }
.bulletin table { width: 100%; border-collapse: collapse; font-size: 13.5px; }
.bulletin th { text-align: left; font-size: 11.5px; text-transform: uppercase; letter-spacing: 0.05em; color: var(--ink-faint); padding: 8px 10px; border-bottom: 1px solid var(--line); }
.bulletin td { padding: 9px 10px; border-bottom: 1px solid var(--line-soft); }
.bulletin .avg { font-weight: 800; text-align: right; }

/* ---- Classes ---- */
.class-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 16px; }
.class-card { display: flex; flex-direction: column; gap: 10px; padding: 18px; border-radius: 18px; background: var(--surface); border: 1px solid var(--line); box-shadow: var(--shadow-sm); color: inherit; transition: transform 0.25s var(--ease-out), box-shadow 0.25s var(--ease-out), border-color 0.2s ease; }
.class-card:hover { transform: translateY(-3px); box-shadow: var(--shadow-md); border-color: var(--lime-strong); }
.class-card .cc-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 8px; }
.class-card h3 { margin: 0; font-size: 17px; font-weight: 800; }
.class-card .cc-meta { font-size: 12.5px; color: var(--ink-soft); display: flex; flex-direction: column; gap: 4px; }
.class-card .cc-meta span { display: flex; align-items: center; gap: 6px; }
.class-card .cc-foot { display: flex; justify-content: space-between; align-items: center; font-size: 12px; color: var(--ink-faint); padding-top: 8px; border-top: 1px solid var(--line-soft); }
.schedule-grid { display: grid; grid-template-columns: repeat(5, 1fr); gap: 10px; }
.schedule-col h4 { margin: 0 0 8px; font-size: 12px; text-transform: uppercase; letter-spacing: 0.05em; color: var(--ink-faint); }
.slot { padding: 9px 10px; border-radius: 10px; background: var(--surface-soft); border: 1px solid var(--line-soft); margin-bottom: 6px; font-size: 12.5px; position: relative; }
.slot strong { display: block; font-size: 13px; } .slot span { color: var(--ink-faint); }
.slot .slot-del { position: absolute; top: 6px; right: 6px; opacity: 0; background: none; border: none; color: var(--bad); cursor: pointer; padding: 2px; }
.slot:hover .slot-del { opacity: 1; }

/* ---- Boutique ---- */
.product-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 14px; }
.product-card { padding: 16px; border-radius: 16px; background: var(--surface); border: 1px solid var(--line); display: flex; flex-direction: column; gap: 6px; }
.product-card .pc-cat { font-size: 11px; text-transform: uppercase; letter-spacing: 0.05em; color: var(--ink-faint); font-weight: 700; }
.product-card h3 { margin: 0; font-size: 15px; }
.product-card .pc-price { font-size: 18px; font-weight: 800; }
.product-card .pc-stock { font-size: 12px; color: var(--ink-faint); }
.product-card .pc-actions { display: flex; gap: 8px; align-items: center; margin-top: 6px; }
.qty { display: flex; align-items: center; border: 1px solid var(--line); border-radius: 100px; overflow: hidden; }
.qty button { border: none; background: none; width: 30px; height: 32px; cursor: pointer; color: var(--ink-soft); font-size: 16px; }
.qty span { min-width: 26px; text-align: center; font-size: 13px; font-weight: 700; }
.cart-panel { position: sticky; top: 80px; }
.cart-line { display: flex; justify-content: space-between; gap: 10px; font-size: 13.5px; padding: 8px 0; border-bottom: 1px solid var(--line-soft); }
.cart-total { display: flex; justify-content: space-between; font-weight: 800; font-size: 15px; padding-top: 12px; }

/* ---- Import (inscription) ---- */
.import-card.drag { border-color: var(--lime-strong); background: var(--lime-tint); border-style: solid; }
.import-card.busy { opacity: 0.6; pointer-events: none; }
.quality-bar { height: 10px; border-radius: 5px; background: var(--surface-soft); overflow: hidden; margin: 6px 0 4px; }
.quality-bar span { display: block; height: 100%; background: linear-gradient(90deg, var(--lime-deep), var(--lime)); transition: width 0.8s var(--ease-out); }
.import-stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; margin-bottom: 14px; }
.import-stat { padding: 12px 14px; border-radius: 12px; background: var(--surface-soft); border: 1px solid var(--line-soft); }
.import-stat .k { font-size: 11.5px; color: var(--ink-faint); } .import-stat .v { font-size: 18px; font-weight: 800; }
.map-row { display: grid; grid-template-columns: 1fr 20px 1fr 48px; align-items: center; gap: 8px; font-size: 12.5px; padding: 6px 0; border-bottom: 1px solid var(--line-soft); }
.map-row .map-src { color: var(--ink-soft); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .map-row .map-dst { font-weight: 700; } .map-row .map-conf { text-align: right; color: var(--ink-faint); }
.map-row.unmapped .map-dst { color: var(--ink-faint); font-weight: 500; }
.map-row .map-arrow { color: var(--ink-faint); }
#anomaliesList div { display: flex; gap: 8px; align-items: flex-start; }
#anomaliesList .ic { color: var(--warn); margin-top: 2px; }
.note-inline { display: flex; gap: 10px; align-items: flex-start; padding: 12px 14px; border-radius: 12px; background: var(--gold-tint); color: #6B4400; font-size: 13px; line-height: 1.5; margin: 12px 0; }
:root[data-theme="dark"] .note-inline { color: #F0C070; }
.note-inline .ic { flex-shrink: 0; margin-top: 1px; }
.mini-sidebar .m-item { display: flex; align-items: center; gap: 8px; }

/* ---- Loader : étapes réelles ---- */
.klassio-loader-text { font-size: 16px; font-weight: 800; letter-spacing: -0.01em; color: var(--ink); margin: 0; }
.klassio-loader-steps { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 9px; min-width: 300px; }
.klassio-loader-steps .ls { display: flex; align-items: center; gap: 10px; font-size: 13.5px; color: var(--ink-faint); }
.klassio-loader-steps .ls.done { color: var(--ink-soft); } .klassio-loader-steps .ls.doing { color: var(--ink); font-weight: 600; }
.klassio-loader-steps .ls-mark { width: 20px; height: 20px; border-radius: 50%; display: flex; align-items: center; justify-content: center; background: var(--surface-soft); border: 1px solid var(--line); flex-shrink: 0; }
.klassio-loader-steps .ls.done .ls-mark { background: var(--lime-tint); border-color: var(--lime-strong); color: var(--lime-deep); }
.klassio-loader-steps .ls-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--line); }
.klassio-loader-steps .ls-spin { width: 10px; height: 10px; border-radius: 50%; border: 2px solid var(--lime-deep); border-right-color: transparent; animation: spin 0.7s linear infinite; }
.klassio-loader { gap: 34px; }
.klassio-loader .loader { margin-bottom: 70px; margin-top: 20px; }

/* ---- Auth : cartes plus larges pour l'import ---- */
.auth-card { max-width: 680px; }
.auth-step[hidden] { display: none; }
.auth-card .panel { padding: 16px 18px; border-radius: 14px; }

/* ---- Impression (reçu, bulletin) ---- */
.print-sheet { background: var(--surface); border: 1px solid var(--line); border-radius: 16px; padding: 28px; }
.print-sheet .ps-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 20px; padding-bottom: 16px; border-bottom: 2px solid var(--ink); margin-bottom: 18px; }
.print-sheet .ps-head h2 { margin: 0; font-size: 20px; }
.print-sheet .ps-head .ps-school strong { display: block; font-size: 16px; }
.print-sheet .ps-head .ps-school span { font-size: 12.5px; color: var(--ink-faint); display: block; }
.print-sheet .ps-total { display: flex; justify-content: space-between; align-items: center; padding: 14px 16px; border-radius: 12px; background: var(--lime-tint); font-weight: 800; font-size: 17px; margin-top: 16px; }
.print-sheet .ps-foot { font-size: 11.5px; color: var(--ink-faint); margin-top: 18px; line-height: 1.5; }
@media print {
  body { background: #fff; }
  .sidebar, .topbar, .no-print, .toast-host, .sidebar-scrim { display: none !important; }
  .dash-body { padding: 0; max-width: none; }
  .print-sheet, .bulletin { border: none; border-radius: 0; padding: 0; box-shadow: none; }
  .main-col { width: 100%; }
}

/* ---- Responsive ---- */
@media (max-width: 1080px) { .kpi-grid, .kpi-grid.cols-5 { grid-template-columns: repeat(2, 1fr); } .three-col { grid-template-columns: 1fr 1fr; } }
@media (max-width: 860px) {
  .two-col, .three-col { grid-template-columns: 1fr; }
  .form-grid { grid-template-columns: 1fr; }
  .dash-body { padding: 28px 18px 80px; }
  .dossier-head .dh-actions { margin-left: 0; width: 100%; }
  .schedule-grid { grid-template-columns: 1fr; }
  .import-stats { grid-template-columns: 1fr 1fr; }
  .sfolder-grid { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); }
  .br-label { flex-basis: 90px; }
  .dl { grid-template-columns: 1fr; gap: 2px 0; } .dl dd { margin-bottom: 8px; }
  .school-badge { display: none; }
  .topbar .brand { display: none; }
}
@media (max-width: 480px) { .kpi-grid, .kpi-grid.cols-3, .kpi-grid.cols-5 { grid-template-columns: 1fr 1fr; } .kpi-card .kpi-v { font-size: 20px; } }

/* ---- Mouvement réduit : aucune 3D, aucune animation décorative ---- */
@media (prefers-reduced-motion: reduce) {
  .sfolder, .sfolder .sf-doc, .sfolder .sf-front, .kpi-card, .class-card, .modal, .toast, .br-bar, .ring-fg { transition: none !important; }
  .sfolder:hover .sf-front { transform: none; }
  .sfolder:hover .sf-doc { transform: translate(var(--tx), -36px); }
  .sk { animation: none; }
}


/* =========================================================
   PORTAIL PAR ÉTABLISSEMENT — le logiciel s'efface derrière l'école
   ========================================================= */
:root { --accent: var(--lime-deep); }
.btn-accent { background: var(--accent); color: #fff; box-shadow: var(--shadow-sm); }
.btn-accent:hover { filter: brightness(1.08); transform: translateY(-1px); box-shadow: var(--shadow-md); }
.portal { position: relative; min-height: 100vh; display: flex; align-items: center; justify-content: center; padding: 24px; background: var(--forest); }
.portal-cover { position: absolute; inset: 0; background: linear-gradient(160deg, var(--forest) 0%, var(--forest-800) 60%, #0e1a12 100%) center/cover no-repeat; }
.portal-scrim { position: absolute; inset: 0; background: linear-gradient(180deg, rgba(10,16,12,0.35), rgba(10,16,12,0.7)); }
.portal-card { position: relative; width: 100%; max-width: 460px; background: var(--surface); border-radius: 24px; box-shadow: var(--shadow-lg); padding: 30px 30px 20px; animation: stepIn 0.5s var(--ease-out); }
.portal-head { display: flex; align-items: center; gap: 14px; padding-bottom: 18px; margin-bottom: 18px; border-bottom: 1px solid var(--line-soft); }
.portal-logo { width: 58px; height: 58px; border-radius: 16px; background: var(--accent); color: #fff; display: flex; align-items: center; justify-content: center; font-weight: 800; font-size: 18px; overflow: hidden; flex-shrink: 0; }
.portal-logo img { width: 100%; height: 100%; object-fit: cover; }
.portal-id h1 { margin: 0; font-size: 19px; font-weight: 800; letter-spacing: -0.01em; line-height: 1.2; }
.portal-id p { margin: 3px 0 0; font-size: 12.5px; color: var(--ink-faint); }
.portal-flag { margin-left: auto; flex-shrink: 0; border-radius: 3px; box-shadow: 0 0 0 1px var(--line); }
.portal-h2 { font-size: 17px; font-weight: 800; margin: 0 0 8px; }
.portal-links { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 16px; font-size: 12.5px; }
.portal-links a { color: var(--accent); font-weight: 700; }
.portal-foot { display: flex; align-items: center; justify-content: center; gap: 6px; margin-top: 22px; padding-top: 14px; border-top: 1px solid var(--line-soft); font-size: 11.5px; color: var(--ink-faint); }
.portal-foot a { display: inline-flex; align-items: center; gap: 5px; font-weight: 700; color: var(--ink-soft); }
.s-brand .school-logo { width: 26px; height: 26px; border-radius: 8px; object-fit: cover; }
.s-brand .s-school { display: flex; flex-direction: column; line-height: 1.15; min-width: 0; }
.s-brand .s-school span { font-size: 10px; font-weight: 600; color: rgba(231,239,227,0.55); text-transform: uppercase; letter-spacing: 0.05em; }
.s-brand .s-school strong { font-size: 13px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.brand-upload { display: flex; align-items: center; gap: 14px; padding: 12px; border: 1.5px dashed var(--line); border-radius: 14px; }
.brand-upload .bu-preview { width: 64px; height: 64px; border-radius: 12px; background: var(--surface-soft); display: flex; align-items: center; justify-content: center; overflow: hidden; flex-shrink: 0; color: var(--ink-faint); }
.brand-upload .bu-preview.wide { width: 120px; height: 64px; }
.brand-upload .bu-preview img { width: 100%; height: 100%; object-fit: cover; }
.brand-upload .bu-text { flex: 1; font-size: 12.5px; color: var(--ink-soft); }
.brand-upload .bu-text strong { display: block; font-size: 13.5px; color: var(--ink); }
.color-row { display: flex; align-items: center; gap: 10px; }
.color-row input[type=color] { width: 44px; height: 38px; border: 1px solid var(--line); border-radius: 10px; padding: 2px; background: var(--surface); cursor: pointer; }
.portal-url { display: flex; align-items: center; gap: 0; border: 1.5px solid var(--line); border-radius: 10px; overflow: hidden; background: var(--surface-soft); }
.portal-url span { padding: 0 10px; font-size: 12.5px; color: var(--ink-faint); white-space: nowrap; }
.portal-url input { border: none !important; border-radius: 0 !important; background: var(--surface) !important; }
@media (max-width: 480px) { .portal-card { padding: 22px 18px 16px; } }

/* =========================================================
   LOTS 2–5 — calendrier, messages, jauge de conduite, pointage, abonnement
   ========================================================= */
.sub-banner { display: flex; align-items: center; gap: 10px; padding: 10px 24px; font-size: 13px; font-weight: 600; border-bottom: 1px solid var(--line-soft); }
.sub-banner.warn { background: var(--warn-bg); color: var(--warn); }
.sub-banner.bad { background: var(--bad-bg); color: var(--bad); }
.sub-banner .link-btn { margin-left: auto; color: inherit; }

.gauge { display: flex; flex-direction: column; gap: 6px; }
.gauge-track { height: 12px; border-radius: 6px; background: var(--surface-soft); overflow: hidden; }
.gauge-fill { display: block; height: 100%; border-radius: 6px; background: var(--lime-deep); transition: width 0.7s var(--ease-out); }
.gauge.warn .gauge-fill { background: var(--gold); } .gauge.bad .gauge-fill { background: #D9583B; }
.gauge-txt { font-size: 12.5px; color: var(--ink-soft); } .gauge-txt strong { font-size: 15px; color: var(--ink); } .gauge-txt em { font-style: normal; font-weight: 700; color: var(--ink); }
.threshold-list { display: flex; flex-direction: column; gap: 6px; font-size: 12.5px; }
.threshold-list .th { display: flex; align-items: center; gap: 10px; padding: 8px 10px; border-radius: 10px; background: var(--surface-soft); }
.threshold-list .th strong { min-width: 34px; text-align: right; }
.threshold-list .th.reached { background: var(--bad-bg); color: var(--bad); }

/* Calendrier mensuel */
.cal-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 12px; }
.cal-head h2 { margin: 0; font-size: 18px; text-transform: capitalize; }
.cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 6px; }
.cal-dow { font-size: 11px; text-transform: uppercase; letter-spacing: 0.05em; color: var(--ink-faint); font-weight: 700; text-align: center; padding: 4px 0; }
.cal-cell { min-height: 84px; border-radius: 12px; border: 1px solid var(--line-soft); background: var(--surface); padding: 6px; display: flex; flex-direction: column; gap: 3px; cursor: pointer; transition: border-color 0.15s ease, box-shadow 0.15s ease; }
.cal-cell:hover { border-color: var(--lime-strong); box-shadow: var(--shadow-sm); }
.cal-cell.other { opacity: 0.45; } .cal-cell.today { border-color: var(--lime-deep); box-shadow: inset 0 0 0 1px var(--lime-deep); }
.cal-cell.exam-period { background: var(--warn-bg); }
.cal-cell .cd { font-size: 12px; font-weight: 700; color: var(--ink-soft); }
.cal-cell.today .cd { color: var(--lime-deep); }
.cal-pill { font-size: 10.5px; font-weight: 700; padding: 2px 6px; border-radius: 6px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; background: var(--surface-soft); color: var(--ink-soft); }
.cal-pill.ok { background: var(--ok-bg); color: var(--ok); } .cal-pill.warn { background: var(--warn-bg); color: var(--warn); } .cal-pill.bad { background: var(--bad-bg); color: var(--bad); } .cal-pill.info { background: var(--info-bg); color: var(--info); }
.cal-more { font-size: 10.5px; color: var(--ink-faint); }
.cal-list .tl-item { padding-bottom: 14px; }
@media (max-width: 700px) { .cal-grid { gap: 3px; } .cal-cell { min-height: 54px; padding: 4px; border-radius: 8px; } .cal-pill { display: none; } .cal-cell .dots { display: flex; gap: 2px; flex-wrap: wrap; } .cal-cell .dot { width: 6px; height: 6px; border-radius: 50%; background: var(--ink-faint); } .cal-cell .dot.ok { background: var(--lime-deep); } .cal-cell .dot.warn { background: var(--gold); } .cal-cell .dot.bad { background: #D9583B; } .cal-cell .dot.info { background: var(--info); } }
@media (min-width: 701px) { .cal-cell .dots { display: none; } }

/* Messagerie */
.msg-layout { display: grid; grid-template-columns: 300px 1fr; gap: 18px; min-height: 60vh; }
.msg-threads { display: flex; flex-direction: column; gap: 4px; max-height: 70vh; overflow-y: auto; }
.msg-thread { display: flex; align-items: center; gap: 10px; padding: 10px 12px; border-radius: 12px; cursor: pointer; border: 1px solid transparent; }
.msg-thread:hover { background: var(--surface-soft); } .msg-thread.active { background: var(--lime-tint); border-color: rgba(124,196,0,0.4); }
.msg-thread .mt-body { min-width: 0; flex: 1; } .msg-thread .mt-body strong { display: block; font-size: 13.5px; } .msg-thread .mt-body span { display: block; font-size: 12px; color: var(--ink-faint); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.msg-thread .mt-unread { min-width: 20px; height: 20px; border-radius: 100px; background: var(--lime-deep); color: #fff; font-size: 11px; font-weight: 800; display: flex; align-items: center; justify-content: center; padding: 0 6px; }
.msg-pane { display: flex; flex-direction: column; background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-lg); overflow: hidden; min-height: 60vh; }
.msg-pane-head { padding: 14px 18px; border-bottom: 1px solid var(--line-soft); display: flex; align-items: center; gap: 10px; }
.msg-list { flex: 1; overflow-y: auto; padding: 18px; display: flex; flex-direction: column; gap: 12px; }
.msg { max-width: 78%; display: flex; flex-direction: column; gap: 3px; }
.msg.mine { align-self: flex-end; align-items: flex-end; }
.msg .bubble { padding: 10px 14px; border-radius: 14px; font-size: 14px; line-height: 1.5; background: var(--surface-soft); color: var(--ink); border-bottom-left-radius: 4px; }
.msg.mine .bubble { background: var(--forest); color: #fff; border-bottom-left-radius: 14px; border-bottom-right-radius: 4px; }
.msg .meta { font-size: 11px; color: var(--ink-faint); }
.msg-compose { display: flex; gap: 10px; padding: 12px 16px; border-top: 1px solid var(--line-soft); }
.msg-compose textarea { flex: 1; min-height: 44px; max-height: 140px; border: 1px solid var(--line); border-radius: 14px; padding: 10px 14px; font: inherit; font-size: 14px; background: var(--surface-soft); color: var(--ink); resize: vertical; }
@media (max-width: 860px) { .msg-layout { grid-template-columns: 1fr; } .msg-threads { max-height: 40vh; } }

/* Pointage portail */
.gate-search { font-size: 18px; padding: 14px 18px; }
.gate-result { display: flex; align-items: center; gap: 12px; padding: 12px 14px; border-radius: 14px; border: 1px solid var(--line); background: var(--surface); margin-bottom: 8px; }
.gate-result .btn { margin-left: auto; }
.gate-log { display: flex; flex-direction: column; gap: 6px; }

/* Abonnement */
.plan-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 12px; }
.plan-card { padding: 18px; border-radius: 16px; border: 1px solid var(--line); background: var(--surface); display: flex; flex-direction: column; gap: 6px; }
.plan-card.current { border-color: var(--lime-deep); box-shadow: 0 0 0 1px var(--lime-deep); }
.plan-card h3 { margin: 0; font-size: 16px; } .plan-card .pc-range { font-size: 12px; color: var(--ink-faint); } .plan-card .pc-price { font-size: 22px; font-weight: 800; letter-spacing: -0.02em; } .plan-card .pc-price small { font-size: 12px; font-weight: 500; color: var(--ink-faint); }
.plan-card p { margin: 4px 0 0; font-size: 12.5px; color: var(--ink-soft); line-height: 1.5; }
/* ---- Proposer un mot de passe (motdepasse.js) — préfixe pws- ----
   Sous chaque champ « nouveau mot de passe » : proposer une phrase de passe,
   afficher / masquer, copier. Rien ici ne touche un autre écran. */
.pws-bar { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }
.pws-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px;
  border-radius: 99px;
  border: 1px solid var(--line);
  background: var(--surface-soft);
  color: var(--ink);
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  transition: border-color 0.2s, background 0.2s;
}
.pws-btn:hover, .pws-btn:focus-visible { border-color: var(--lime-deep); }
.pws-proposer { border-color: var(--lime-deep); }
.pws-panel { margin-top: 10px; padding: 12px 14px; border-radius: 12px; border: 1px solid var(--lime-deep); background: var(--surface); }
.pws-kicker { display: block; font-size: 11px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-soft); }
.pws-valeur { display: block; margin: 6px 0 10px; font: 700 16px/1.4 ui-monospace, "SFMono-Regular", Menlo, monospace; letter-spacing: 0.02em; color: var(--ink); overflow-wrap: anywhere; user-select: all; }
.pws-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.pws-msg { font-size: 12.5px; font-weight: 600; color: var(--ink-soft); }
.pws-panel p { margin: 10px 0 0; font-size: 12.5px; line-height: 1.5; color: var(--ink-soft); }
@media (prefers-reduced-motion: reduce) { .pws-btn { transition: none; } }

/* ---- Le choix de l'offre (offres.js) — inscription et espace pas encore ouvert ----
   Préfixe of- : ces règles ne touchent aucun autre écran. */
.of-grid { margin-top: 4px; }
.of-card { position: relative; cursor: pointer; transition: border-color 0.2s, box-shadow 0.2s; }
.of-card input[type="radio"] { position: absolute; top: 16px; right: 16px; width: 18px; height: 18px; accent-color: var(--lime-deep); }
.of-card .pc-range { color: var(--ink-soft); }
.of-card .btn { margin-top: 8px; align-self: flex-start; }
.of-card.of-off { cursor: not-allowed; opacity: 0.55; }
.of-note { font-size: 12px; font-weight: 600; color: var(--bad); }
.of-actions { display: flex; justify-content: flex-end; margin-top: 18px; }
.of-tester { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; padding: 12px 14px; margin-bottom: 16px; border-radius: 12px; border: 1px dashed var(--line); background: var(--surface-soft); font-size: 13px; color: var(--ink-soft); }
.of-tester span { flex: 1; min-width: 220px; }
.of-pay { margin-top: 18px; padding: 18px; border-radius: 16px; border: 1px solid var(--lime-deep); background: var(--surface); }
.of-pay-head strong { font-size: 24px; font-weight: 800; letter-spacing: -0.02em; }
.of-pay-head small { color: var(--ink-soft); }
.of-kicker { display: block; font-size: 11px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-soft); }
.of-steps { margin: 12px 0 14px; padding-left: 20px; font-size: 13.5px; line-height: 1.6; color: var(--ink-soft); }
.of-steps a { color: var(--ink); font-weight: 700; text-decoration: underline; }
.of-form { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr) auto; gap: 12px; align-items: end; }
.of-form .field { margin: 0; }
.of-wait { display: flex; gap: 14px; padding: 18px; border-radius: 16px; border: 1px solid var(--line); background: var(--surface); }
.of-wait-ic { flex: none; width: 40px; height: 40px; border-radius: 50%; display: grid; place-items: center; background: var(--surface-soft); color: var(--ink); }
.of-wait > div { min-width: 0; }
.of-wait p { margin: 6px 0 12px; font-size: 13.5px; color: var(--ink-soft); line-height: 1.55; overflow-wrap: anywhere; }
.of-wait .btn { white-space: normal; text-align: left; }
@media (max-width: 640px) { .of-form { grid-template-columns: 1fr; } }
.status-hero { display: flex; align-items: center; gap: 18px; padding: 22px; border-radius: 20px; background: var(--forest); color: #fff; margin-bottom: 20px; flex-wrap: wrap; }
.status-hero .sh-main strong { display: block; font-size: 22px; letter-spacing: -0.02em; } .status-hero .sh-main span { color: rgba(231,239,227,0.75); font-size: 13.5px; }
.status-hero .sh-badge { padding: 6px 14px; border-radius: 100px; font-size: 12.5px; font-weight: 800; background: rgba(159,227,0,0.18); color: var(--lime); }
.status-hero .sh-badge.warn { background: rgba(240,180,41,0.2); color: #F0B429; } .status-hero .sh-badge.bad { background: rgba(217,88,59,0.22); color: #FFB4A3; }

/* Registres imprimables */
.register { width: 100%; border-collapse: collapse; font-size: 11.5px; }
.register th, .register td { border: 1px solid var(--line); padding: 4px 5px; text-align: center; }
.register th.name, .register td.name { text-align: left; min-width: 160px; }
.register td.R { background: var(--warn-bg); } .register td.A { background: var(--bad-bg); } .register td.E { background: var(--info-bg); } .register td.P { color: var(--ok); }

.pill-row { display: flex; gap: 6px; flex-wrap: wrap; }
.doc-card { display: flex; align-items: center; gap: 12px; padding: 12px 14px; border-radius: 14px; border: 1px solid var(--line); background: var(--surface); }
.doc-card .dc-ic { width: 40px; height: 40px; border-radius: 10px; background: var(--surface-soft); display: flex; align-items: center; justify-content: center; color: var(--ink-soft); flex-shrink: 0; }
.doc-card .dc-body { flex: 1; min-width: 0; } .doc-card .dc-body strong { display: block; font-size: 14px; } .doc-card .dc-body span { font-size: 12px; color: var(--ink-faint); }
.doc-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 10px; }
.appr-level { display: flex; gap: 4px; } .appr-level button { width: 30px; height: 30px; border-radius: 8px; border: 1px solid var(--line); background: var(--surface); font: inherit; font-size: 12px; font-weight: 700; cursor: pointer; color: var(--ink-soft); }
.appr-level button.active { background: var(--lime-deep); color: #fff; border-color: var(--lime-deep); }
.step-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.step-list li { display: flex; gap: 10px; align-items: flex-start; font-size: 13.5px; }
.step-list .num { width: 22px; height: 22px; border-radius: 50%; background: var(--forest); color: var(--lime); font-size: 11px; font-weight: 800; display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
@media print { .sub-banner { display: none !important; } }

/* ===========================================================================
   WELCOME EXPERIENCE — accueil d'invitation (app/invitation.html)

   Tout repose sur les jetons existants (--lime, --forest, --ink, --line…) :
   l'habillage par établissement (--accent, logo, couverture) continue de
   primer, et le thème sombre fonctionne sans règle supplémentaire.

   Aucune animation n'est nécessaire à la compréhension : sous
   prefers-reduced-motion, tout s'affiche d'emblée et le parcours reste
   entièrement utilisable.
   =========================================================================== */

.wx-card { overflow: hidden; }
.wx-in { animation: wxIn 0.34s var(--ease-out); }
@keyframes wxIn { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }

/* Fil de progression */
.wx-steps { display: flex; gap: 6px; justify-content: center; margin: 0 0 18px; }
.wx-dot { width: 26px; height: 3px; border-radius: 2px; background: var(--line); transition: background 0.3s ease, width 0.3s ease; }
.wx-dot.is-done { background: var(--lime-strong); }
.wx-dot.is-current { background: var(--accent); width: 38px; }

/* Accueil : les lignes arrivent l'une après l'autre, le bouton est là d'emblée */
.wx-hero { text-align: center; padding: 14px 0 4px; }
.wx-line { font-size: 21px; font-weight: 700; letter-spacing: -0.02em; margin: 0 0 10px; color: var(--ink); }
.wx-line-2 { font-size: 17px; font-weight: 600; color: var(--ink-soft); }
.wx-line-3 { font-size: 14.5px; font-weight: 500; }
.wx-hero .wx-line { animation: wxLine 0.5s var(--ease-out) both; }
.wx-hero .wx-line-2 { animation-delay: 0.34s; }
.wx-hero .wx-line-3 { animation-delay: 0.62s; }
.wx-hero .btn { animation: wxLine 0.5s var(--ease-out) 0.84s both; }
@keyframes wxLine { from { opacity: 0; transform: translateY(10px); filter: blur(3px); } to { opacity: 1; transform: none; filter: none; } }

/* Contexte réel : enfants, classes, périmètre */
.wx-list { display: flex; flex-direction: column; gap: 8px; margin-top: 14px; }
.wx-item { display: flex; align-items: center; gap: 12px; padding: 11px 13px; border: 1px solid var(--line-soft);
           border-radius: 14px; background: var(--surface-soft); }
.wx-avatar { width: 38px; height: 38px; border-radius: 12px; background: var(--forest); color: var(--lime);
             display: flex; align-items: center; justify-content: center; font-size: 13px; font-weight: 800;
             flex-shrink: 0; letter-spacing: 0.02em; }
.wx-avatar-class { background: var(--lime-tint); color: var(--lime-deep); }
.wx-item-body { display: flex; flex-direction: column; gap: 1px; min-width: 0; flex: 1; }
.wx-item-body strong { font-size: 14.5px; font-weight: 700; }
/* --ink-soft et non --ink-faint : la classe de l'enfant est une information,
   pas une décoration. Mesuré en thème sombre, --ink-faint sur le fond des
   cartes donne 3,80:1, sous le seuil AA de 4,5:1. */
.wx-item-sub { font-size: 12.5px; color: var(--ink-soft); }
.wx-tag { font-size: 11px; font-weight: 800; text-transform: uppercase; letter-spacing: 0.04em;
          color: var(--lime-deep); background: var(--lime-tint); border-radius: 999px; padding: 4px 9px; flex-shrink: 0; }
/* Même raison que .wx-item-sub : cette note dit au parent qu'il ne peut pas
   rattacher un enfant lui-même, et à l'enseignant que ses affectations ne se
   modifient pas ici. Mesuré avec --ink-faint : 3,17:1 en thème clair. */
.wx-note { font-size: 12.5px; color: var(--ink-soft); line-height: 1.55; margin: 12px 0 0; }

/* Acceptation des conditions */
.wx-consent { display: flex; gap: 10px; align-items: flex-start; margin-top: 14px; font-size: 13px;
              color: var(--ink-soft); line-height: 1.5; cursor: pointer; }
.wx-consent input { margin-top: 2px; width: 16px; height: 16px; accent-color: var(--lime-deep); flex-shrink: 0; }

/* Chargement — un état réel, jamais décoratif */
.wx-spinner { width: 26px; height: 26px; border-radius: 50%; border: 2.5px solid var(--line);
              border-top-color: var(--accent); animation: wxSpin 0.7s linear infinite; margin: 0 auto 14px; }
.wx-spinner-lg { width: 46px; height: 46px; border-width: 3px; margin: 0; }
@keyframes wxSpin { to { transform: rotate(360deg); } }

/* Traitement puis succès */
.wx-processing { text-align: center; padding: 10px 0 6px; }
.wx-stage { height: 76px; display: flex; align-items: center; justify-content: center; margin-bottom: 16px; }
.wx-stage[data-phase="working"] .wx-check { display: none; }
.wx-stage[data-phase="done"] .wx-spinner { display: none; }
.wx-check { width: 62px; height: 62px; }
.wx-check-ring { stroke: var(--lime-strong); stroke-width: 2.5; stroke-dasharray: 145; stroke-dashoffset: 145;
                 animation: wxRing 0.45s var(--ease-out) forwards; }
.wx-check-mark { stroke: var(--lime-deep); stroke-width: 3.4; stroke-linecap: round; stroke-linejoin: round;
                 stroke-dasharray: 48; stroke-dashoffset: 48; animation: wxMark 0.32s var(--ease-out) 0.34s forwards; }
@keyframes wxRing { to { stroke-dashoffset: 0; } }
@keyframes wxMark { to { stroke-dashoffset: 0; } }

.wx-icon { width: 52px; height: 52px; margin: 0 auto 14px; border-radius: 50%; display: flex;
           align-items: center; justify-content: center; }
.wx-icon svg { width: 30px; height: 30px; }
.wx-icon-warn { background: var(--gold-tint); color: #9A6B00; }

/* Téléphone d'abord : la plupart des invitations s'ouvrent depuis WhatsApp. */
@media (max-width: 520px) {
  .portal { padding: 0; align-items: stretch; }
  .portal-card.wx-card { max-width: none; border-radius: 0; min-height: 100vh;
                         display: flex; flex-direction: column; justify-content: center; padding: 26px 20px 16px; }
  .wx-line { font-size: 19px; }
  .wx-item { padding: 10px 11px; }
  .wx-avatar { width: 34px; height: 34px; }
}

@media (prefers-reduced-motion: reduce) {
  .wx-in, .wx-hero .wx-line, .wx-hero .btn { animation: none; }
  .wx-spinner { animation: wxSpin 1.4s linear infinite; }   /* conservé : il signale une attente réelle */
  .wx-check-ring, .wx-check-mark { animation: none; stroke-dashoffset: 0; }
  .wx-dot { transition: none; }
}

/* Bandeau d'arrivée, affiché une seule fois à la fin de la Welcome Experience. */
.wx-arrivee { margin: 10px 0 0; padding: 10px 14px; border-radius: 12px; font-size: 13.5px;
              color: var(--forest-700); background: var(--lime-tint);
              border: 1px solid rgba(124, 196, 0, 0.28); line-height: 1.5; }
:root[data-theme="dark"] .wx-arrivee { color: var(--lime); background: rgba(124, 196, 0, 0.12); }

/* Encadré d'information contextuelle — manquait comme primitive : les pages
   fabriquaient jusqu'ici leurs propres blocs. Utilisé par l'import des
   résultats pour distinguer nettement une ERREUR bloquante d'un simple
   avertissement, ce que la Direction doit saisir d'un coup d'œil. */
.notice { padding: 11px 14px; border-radius: 12px; font-size: 13.5px; line-height: 1.55;
          margin: 12px 0 0; border: 1px solid transparent; }
.notice strong { font-weight: 800; }
/* Teintes propres au composant en thème clair : mesurés sur --ok-bg/--warn-bg,
   les jetons globaux --ok et --warn donnent 4,49 et 3,89 pour 1 — sous le seuil
   AA de 4,5. Ces encadrés portent des informations décisives (« l'import est
   bloqué »), ils doivent se lire sans effort. Les jetons globaux, eux, ne sont
   pas touchés : ils servent ailleurs et relèvent d'une décision produit. */
.notice.ok   { background: var(--ok-bg);   color: #1C5720; border-color: rgba(46, 125, 50, 0.22); }
.notice.warn { background: var(--warn-bg); color: #7A4206; border-color: rgba(181, 98, 10, 0.22); }
.notice.bad  { background: var(--bad-bg);  color: #8E2D18; border-color: rgba(178, 58, 31, 0.22); }
/* En thème sombre les jetons passent déjà largement (6,2 à 7,7 pour 1). */
:root[data-theme="dark"] .notice.ok   { color: var(--ok); }
:root[data-theme="dark"] .notice.warn { color: var(--warn); }
:root[data-theme="dark"] .notice.bad  { color: var(--bad); }
.import-card { cursor: pointer; }

/* ==========================================================================
   PAGES PUBLIQUES — à propos, aide, FAQ, contact, sécurité, légal
   ==========================================================================
   Ces pages partagent la barre et le pied de la landing pour qu'on ne sente
   pas la couture en passant de l'une à l'autre. Elles n'ont en revanche AUCUN
   des effets de défilement du hero : ce sont des pages qu'on lit, pas une
   mise en scène. Le lime reste un accent — jamais un fond de page.
   ========================================================================== */

.pub-page { padding-top: 92px; padding-bottom: 72px; }
.pub-hero { padding: 48px 0 40px; }
.pub-hero .kicker { display: inline-block; font-size: 12px; font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase; color: var(--lime-deep); margin-bottom: 14px; }
.pub-hero h1 { font-size: clamp(30px, 5vw, 46px); line-height: 1.1; letter-spacing: -0.02em; margin: 0 0 16px; }
.pub-hero .chapo { font-size: clamp(16px, 2vw, 18.5px); line-height: 1.65; color: var(--ink-soft); max-width: 62ch; margin: 0; }

.pub-section { padding: 40px 0; border-top: 1px solid var(--line-soft); }
.pub-section:first-of-type { border-top: 0; }
.pub-section h2 { font-size: clamp(22px, 3vw, 28px); letter-spacing: -0.01em; margin: 0 0 8px; }
.pub-section .sous { font-size: 15px; color: var(--ink-soft); margin: 0 0 24px; max-width: 66ch; line-height: 1.6; }
.pub-section h3 { font-size: 17px; margin: 28px 0 8px; }
.pub-prose p, .pub-prose li { font-size: 15px; line-height: 1.75; color: var(--ink-soft); }
.pub-prose strong { color: var(--ink); }
.pub-prose ul { padding-left: 20px; margin: 10px 0 18px; }
.pub-prose li { margin-bottom: 7px; }
.pub-prose h2 { margin-top: 38px; }
.pub-prose > p:first-child { margin-top: 0; }

/* Grille de cartes — rôles, étapes, catégories d'aide */
.pub-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 16px; }
.pub-carte { background: var(--surface); border: 1px solid var(--line); border-radius: 18px; padding: 22px; }
.pub-carte h3 { margin: 0 0 8px; font-size: 16.5px; }
.pub-carte p { margin: 0; font-size: 14px; line-height: 1.65; color: var(--ink-soft); }
.pub-carte .pc-ic { display: inline-flex; align-items: center; justify-content: center; width: 40px; height: 40px; border-radius: 12px; background: var(--surface-soft); color: var(--lime-deep); margin-bottom: 14px; }
.pub-carte ul { margin: 12px 0 0; padding-left: 18px; }
.pub-carte li { font-size: 13.5px; line-height: 1.6; color: var(--ink-soft); margin-bottom: 5px; }
.pub-carte .pc-non { color: var(--ink-faint); }

/* Le flux « comment ça marche » */
.pub-flux { display: flex; flex-direction: column; gap: 10px; }
.pub-etape { display: flex; gap: 16px; align-items: flex-start; background: var(--surface); border: 1px solid var(--line); border-radius: 16px; padding: 18px 20px; }
.pub-etape .pe-num { flex: 0 0 auto; width: 30px; height: 30px; border-radius: 100px; background: var(--lime); color: #111; display: flex; align-items: center; justify-content: center; font-weight: 800; font-size: 13.5px; }
.pub-etape h3 { margin: 2px 0 5px; font-size: 16px; }
.pub-etape p { margin: 0; font-size: 14px; line-height: 1.6; color: var(--ink-soft); }

/* Accordéon FAQ / aide — <details> natif : clavier et lecteur d'écran gratuits */
.pub-acc { border: 1px solid var(--line); border-radius: 14px; background: var(--surface); margin-bottom: 10px; overflow: hidden; }
.pub-acc > summary { cursor: pointer; padding: 17px 20px; font-size: 15.5px; font-weight: 700; list-style: none; display: flex; align-items: center; justify-content: space-between; gap: 14px; }
.pub-acc > summary::-webkit-details-marker { display: none; }
.pub-acc > summary::after { content: "+"; font-size: 20px; font-weight: 400; color: var(--ink-faint); flex: 0 0 auto; line-height: 1; }
.pub-acc[open] > summary::after { content: "−"; }
.pub-acc > summary:hover { background: var(--surface-soft); }
.pub-acc > summary:focus-visible { box-shadow: inset var(--focus); }
.pub-acc .acc-corps { padding: 0 20px 18px; font-size: 14.5px; line-height: 1.7; color: var(--ink-soft); }
.pub-acc .acc-corps p { margin: 0 0 10px; }
.pub-acc .acc-corps ol, .pub-acc .acc-corps ul { margin: 8px 0 10px; padding-left: 20px; }
.pub-acc .acc-corps li { margin-bottom: 6px; }

/* Recherche du centre d'aide */
.aide-recherche { display: flex; align-items: center; gap: 10px; background: var(--surface); border: 1.5px solid var(--line); border-radius: 100px; padding: 0 20px; height: 54px; margin-bottom: 8px; }
.aide-recherche input { flex: 1; border: 0; background: none; font: inherit; font-size: 15px; color: var(--ink); outline: none; min-width: 0; }
.aide-recherche:focus-within { border-color: var(--lime-deep); }
.aide-compte { font-size: 13px; color: var(--ink-faint); margin: 0 0 22px; padding-left: 4px; }
.aide-cat { font-size: 12px; font-weight: 800; letter-spacing: 0.06em; text-transform: uppercase; color: var(--lime-deep); margin: 26px 0 10px; }

/* Encadré d'avertissement — surtout sur les pages légales, où il dit ce qui
   doit encore être validé par un juriste. On ne prétend pas être conforme. */
.pub-note { display: flex; gap: 12px; background: var(--surface-soft); border: 1px solid var(--line); border-left: 3px solid var(--gold); border-radius: 12px; padding: 16px 18px; margin: 22px 0; }
.pub-note p { margin: 0; font-size: 14px; line-height: 1.65; color: var(--ink-soft); }

.pub-cta { text-align: center; padding: 56px 0 8px; border-top: 1px solid var(--line-soft); margin-top: 20px; }
.pub-cta h2 { margin: 0 0 10px; }
.pub-cta p { color: var(--ink-soft); margin: 0 0 22px; }
.pub-cta .row { justify-content: center; }

.pub-maj { font-size: 13px; color: var(--ink-faint); margin-top: 8px; }

/* Barre publique : le burger n'apparaît qu'en dessous de 860 px. */
.pub-burger { display: none; background: none; border: 0; color: var(--ink); cursor: pointer; padding: 6px; }
.pub-nav .nav-links a.actif { color: var(--ink); font-weight: 700; }
@media (max-width: 860px) {
  .pub-burger { display: inline-flex; }
  .pub-nav .nav-links { display: none; }
  .pub-nav .nav-actions { display: none; }
  /* Le menu ouvert doit être OPAQUE. La barre est `position: fixed` et ne
     reçoit son fond qu'au défilement : déployée en haut de page, elle laissait
     le texte de la page transparaître à travers les liens. */
  body.pub-menu-ouvert .pub-nav {
    flex-wrap: wrap; row-gap: 12px;
    background: var(--bg);
    box-shadow: 0 1px 0 var(--line), 0 12px 32px rgba(0, 0, 0, 0.08);
    padding-bottom: 18px;
  }
  body.pub-menu-ouvert .pub-nav .nav-links,
  body.pub-menu-ouvert .pub-nav .nav-actions { display: flex; width: 100%; flex-wrap: wrap; gap: 10px; }
  body.pub-menu-ouvert .pub-nav .nav-links { flex-direction: column; }
  .pub-page { padding-top: 84px; }
}

/* Zone de suppression de compte — visuellement distincte, pour qu'on ne la
   déclenche pas en cherchant autre chose. */
.danger-zone { border-color: color-mix(in srgb, var(--bad) 35%, var(--line)); }
.danger-zone .panel-head h2 { color: var(--bad); }

/* Bandeau de consentement aux témoins (Cookies) */
.cookie-banner {
  position: fixed;
  bottom: 24px;
  right: 24px;
  max-width: 440px;
  width: calc(100vw - 48px);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 18px;
  padding: 18px 20px;
  box-shadow: 0 12px 36px rgba(0, 0, 0, 0.16);
  z-index: 998;
  backdrop-filter: blur(14px);
  transition: opacity 0.35s ease, transform 0.35s ease;
  animation: cookieSlideUp 0.4s var(--ease-out);
}
.cookie-banner-hide {
  opacity: 0;
  transform: translateY(16px);
  pointer-events: none;
}
.cookie-content { display: flex; flex-direction: column; gap: 14px; }
/* UNE BANDE, PAS UNE CARTE — et surtout pas par-dessus un bouton.
   Le bandeau mesurait 182 px de haut en bas à droite ; les appels à l'action
   du hero, centrés, tombent exactement à cette hauteur. « Voir la
   démonstration » était recouvert sur 180 px, donc incliquable. En passant le
   contenu sur une ligne, la bande fait ~90 px et dégage les boutons. */
@media (min-width: 720px) {
  .cookie-banner {
    right: 16px;
    bottom: 16px;
    max-width: min(780px, calc(100vw - 32px));
    padding: 14px 18px;
  }
  .cookie-content {
    flex-direction: row;
    align-items: center;
    gap: 20px;
  }
  .cookie-text strong { margin-bottom: 2px; }
  .cookie-actions { flex-shrink: 0; }
}
.cookie-text strong { display: block; font-size: 14px; margin-bottom: 4px; color: var(--ink); }
.cookie-text p { margin: 0; font-size: 12.5px; line-height: 1.55; color: var(--ink-soft); }
.cookie-text a { color: var(--lime-deep); text-decoration: underline; }
:root[data-theme="dark"] .cookie-text a { color: var(--lime); }
.cookie-actions { display: flex; gap: 8px; justify-content: flex-end; }
@keyframes cookieSlideUp {
  from { opacity: 0; transform: translateY(20px); }
  to { opacity: 1; transform: translateY(0); }
}

/* =========================================================================
   MOTEUR DE MOUVEMENT — révélations, curseur, typographie cinétique
   =========================================================================

   Le JS ne fait que poser un index (`--mo-i`) et basculer une classe. Tout ce
   qui bouge est décrit ici, donc composé par le GPU. Une animation pilotée
   image par image en JavaScript tombe dès que le fil principal travaille —
   et sur cette page il travaille : portail, nappe, observateurs.

   `--mo-i` est l'index de l'unité dans son bloc. Le décalage se calcule en
   CSS : c'est ce qui fait arriver les mots UN À UN plutôt qu'ensemble. */

@property --mo-stretch { syntax: "<number>"; inherits: true; initial-value: 100; }
@property --mo-blur { syntax: "<length>"; inherits: true; initial-value: 0px; }

:root { --mo-stretch: 100; --mo-blur: 0px; --mo-delay: 0ms; --mo-pas: 34ms; }

/* Le masque : chaque unité monte depuis SOUS sa propre ligne, elle ne
   surgit pas depuis le néant. C'est ce qui distingue une révélation
   éditoriale d'un simple fondu. */
.mo-w { display: inline-block; overflow: hidden; vertical-align: bottom; }
.mo-w-i,
.mo-c {
  display: inline-block;
  will-change: transform, opacity;
}

[data-mo].mo-prep .mo-w-i,
[data-mo].mo-prep .mo-c {
  opacity: 0;
  transform: translateY(110%) rotate(1.2deg);
}
[data-mo].mo-prep .mo-c { transform: translateY(80%); }

[data-mo].mo-in .mo-w-i,
[data-mo].mo-in .mo-c {
  opacity: 1;
  transform: none;
  transition:
    opacity 0.62s cubic-bezier(0.16, 1, 0.3, 1),
    transform 0.86s cubic-bezier(0.16, 1, 0.3, 1);
  transition-delay: calc(var(--mo-delay, 0ms) + var(--mo-i, 0) * var(--mo-pas));
}
/* Les caractères se succèdent plus vite que les mots : à 34 ms par lettre,
   un titre de trente signes mettrait une seconde à finir de s'écrire. */
[data-mo="chars"].mo-in .mo-c { --mo-pas: 17ms; }

/* Mouvement réduit, ou repli sans JavaScript : l'état d'arrivée, tout de
   suite. Le trajet disparaît, le contenu jamais. */
[data-mo].mo-instant .mo-w-i,
[data-mo].mo-instant .mo-c { transition: none !important; }
.no-js [data-mo] .mo-w-i,
.no-js [data-mo] .mo-c { opacity: 1; transform: none; }

/* ---- Typographie cinétique ---------------------------------------------
   La largeur de l'axe variable suit la vitesse de défilement. Le texte n'est
   plus posé sur la page : il subit le mouvement. Réservé aux titres — sur un
   paragraphe, la compression gênerait la lecture. */
.mo-kinetic {
  /* L'AXE `wdth` N'EXISTE QUE SUR UNE POLICE VARIABLE.
     Plus Jakarta Sans, la police de titre du produit, n'en a pas : la règle
     s'appliquait sans rien produire. Archivo porte l'axe 62..125, et ne sert
     QU'ICI — l'identité typographique du reste de la page ne change pas, et
     la serif italique (Fraunces) garde son rôle de contraste. */
  font-family: "Archivo", "Plus Jakarta Sans", system-ui, sans-serif;
  font-variation-settings: "wdth" var(--mo-stretch, 100);
  letter-spacing: -0.022em;
  filter: blur(var(--mo-blur, 0px));
  will-change: filter, font-variation-settings;
}

/* ---- Curseur ------------------------------------------------------------
   `difference` inverse ce qu'il recouvre : un seul curseur reste lisible sur
   le clair comme sur le sombre, sans qu'on ait à le redéclarer par thème. */
.mo-cursor,
.mo-ring {
  position: fixed;
  top: 0; left: 0;
  pointer-events: none;
  z-index: 9999;
  mix-blend-mode: difference;
  will-change: transform;
  transition: opacity 0.2s ease;
}
.mo-cursor {
  width: 7px; height: 7px;
  margin: -3.5px 0 0 -3.5px;
  border-radius: 50%;
  background: #fff;
}
.mo-ring {
  width: 34px; height: 34px;
  margin: -17px 0 0 -17px;
  border: 1px solid rgba(255, 255, 255, 0.55);
  border-radius: 50%;
}
.mo-ring-on { border-color: rgba(255, 255, 255, 0.9); }
/* On ne masque le curseur système QUE là où le nôtre existe réellement :
   la classe n'est posée que sur un pointeur fin, hors mouvement réduit. */
.mo-cursor-on,
.mo-cursor-on a,
.mo-cursor-on button,
.mo-cursor-on [role="button"] { cursor: none; }
/* …sauf dans un champ de saisie, où la barre d'insertion est une
   information : la masquer ferait perdre le point de frappe. */
.mo-cursor-on input,
.mo-cursor-on textarea,
.mo-cursor-on select { cursor: auto; }

@media (prefers-reduced-motion: reduce) {
  .mo-cursor, .mo-ring { display: none !important; }
  .mo-kinetic { filter: none !important; font-variation-settings: "wdth" 100 !important; }
  [data-mo] .mo-w-i, [data-mo] .mo-c { opacity: 1 !important; transform: none !important; }
}

/* =========================================================================
   DÉMONSTRATION — la couche narrative
   =========================================================================
   Esthétique d'instrumentation : libellés en chasse fixe très espacés,
   chiffres alignés, accent employé comme PONCTUATION et jamais comme décor.
   L'identité reste celle de Klassio : le vert est l'accent. */

.rc-chapitre {
  margin: 0 0 30px;
  padding-bottom: 22px;
  border-bottom: 1px solid var(--line);
}
.rc-ligne {
  display: flex;
  align-items: baseline;
  gap: 14px;
  flex-wrap: wrap;
}
.rc-num,
.rc-tiret {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11px;
  letter-spacing: 0.26em;
  font-variant-numeric: tabular-nums;
  flex-shrink: 0;
}
.rc-num { color: var(--lime-deep); }
:root[data-theme="dark"] .rc-num { color: var(--lime); }
.rc-tiret { color: var(--ink-faint, var(--ink-soft)); opacity: 0.5; }

.rc-titre {
  margin: 0;
  font-family: "Archivo", "Plus Jakarta Sans", system-ui, sans-serif;
  font-variation-settings: "wdth" var(--mo-stretch, 100);
  font-size: clamp(22px, 3.1vw, 36px);
  font-weight: 700;
  letter-spacing: -0.025em;
  line-height: 1.1;
  color: var(--ink);
  flex: 1 1 320px;
}
.rc-texte {
  margin: 14px 0 0;
  max-width: 62ch;
  font-size: 15px;
  line-height: 1.68;
  color: var(--ink-soft);
}

/* Les chiffres d'un écran technique s'alignent en colonne. Sans
   `tabular-nums`, « 2 340 » et « 86 » ne tombent pas sur la même grille et
   la lecture d'un tableau devient pénible. */
.demo-step .info-card .v,
.demo-step .table td,
.demo-step .kpi-value { font-variant-numeric: tabular-nums; }

/* ---- Rail de progression ------------------------------------------------ */
.rc-rail {
  position: fixed;
  right: 22px;
  top: 50%;
  transform: translateY(-50%);
  z-index: 40;
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 10px 8px;
  border-radius: 9999px;
  background: color-mix(in srgb, var(--surface) 72%, transparent);
  border: 1px solid var(--line);
  backdrop-filter: blur(14px);
}
.rc-pastille {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 22px; height: 22px;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
}
.rc-p-point {
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--ink-soft);
  opacity: 0.32;
  transition: opacity 0.3s ease, transform 0.3s cubic-bezier(0.16, 1, 0.3, 1), background 0.3s ease;
}
.rc-pastille:hover .rc-p-point { opacity: 0.7; }
.rc-pastille.rc-actif .rc-p-point {
  background: var(--lime-deep);
  opacity: 1;
  transform: scale(1.7);
}
:root[data-theme="dark"] .rc-pastille.rc-actif .rc-p-point { background: var(--lime); }
/* Le numéro n'apparaît qu'au survol : le rail doit se lire sans mots, et
   ne s'expliquer que si on le regarde. */
.rc-p-nom {
  position: absolute;
  right: calc(100% + 10px);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 10px;
  letter-spacing: 0.22em;
  font-variant-numeric: tabular-nums;
  color: var(--ink-soft);
  white-space: nowrap;
  opacity: 0;
  transform: translateX(6px);
  pointer-events: none;
  transition: opacity 0.26s ease, transform 0.26s cubic-bezier(0.16, 1, 0.3, 1);
}
.rc-pastille:hover .rc-p-nom,
.rc-pastille:focus-visible .rc-p-nom { opacity: 1; transform: none; }
.rc-pastille:focus-visible { outline: 2px solid var(--lime-deep); outline-offset: 3px; border-radius: 50%; }

/* ---- La barre latérale quitte la démonstration --------------------------
   Elle dupliquait ce que le rail de droite dit déjà — où l'on en est — et
   surtout : dans une DÉMONSTRATION, une navigation latérale invite à cliquer
   ailleurs, alors que tout l'intérêt est de suivre le récit jusqu'au bout.
   Elle reste entière dans l'application réelle ; seule la visite s'en passe. */
body[data-page="demo"] .demo-shell .sidebar,
body[data-page="demo"] .demo-shell .sidebar-scrim,
body[data-page="demo"] .demo-shell #sidebarToggle { display: none !important; }
body[data-page="demo"] .demo-shell .main-col { margin-left: 0 !important; width: 100% !important; }
body[data-page="demo"] .demo-shell { grid-template-columns: 1fr !important; }

/* ---- Grain -------------------------------------------------------------- */
.rc-grain {
  position: fixed;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  opacity: 0.032;
  mix-blend-mode: overlay;
  background-repeat: repeat;
}

@media (max-width: 820px) {
  /* Une colonne fixe à droite mange une largeur qu'un téléphone n'a pas, et
     la barre du haut reste atteignable au pouce. */
  .rc-rail { display: none; }
  .rc-titre { font-size: 21px; }
  .rc-chapitre { margin-bottom: 22px; }
}
@media (prefers-reduced-motion: reduce) {
  .rc-grain { display: none; }
  .rc-p-point { transition: none; }
}

/* =========================================================================
   ORBITE — le moyeu en volume
   =========================================================================
   Le schéma précédent était plat : six étiquettes posées autour d'un carré,
   reliées par des traits. Il DISAIT la convergence sans la faire sentir.
   Ici les modules tournent réellement autour du logo sur une orbite inclinée,
   avec perspective : ceux qui passent derrière rapetissent, pâlissent et
   passent sous le noyau. La profondeur n'est pas dessinée, elle est calculée.

   Tout est en transformations CSS 3D : composées par le GPU, elles tiennent
   60 images/seconde sur un téléphone d'entrée de gamme — ce qu'une scène
   WebGL avec post-traitement ne ferait pas sur une connexion kinoise. */

.orbite {
  position: relative;
  display: grid;
  place-items: center;
  min-height: 360px;
  perspective: 1100px;
}
.orb-scene {
  position: relative;
  width: 100%;
  max-width: 420px;
  aspect-ratio: 1 / 0.86;
  transform-style: preserve-3d;
  /* L'orbite est vue de trois quarts : une orbite vue de face redevient un
     cercle plat, et tout l'effet de volume disparaît. */
  transform: rotateX(58deg);
}

.orb-anneau {
  position: absolute;
  inset: 8%;
  border-radius: 50%;
  border: 1px solid color-mix(in srgb, var(--ink-soft) 22%, transparent);
  transform-style: preserve-3d;
}
.orb-anneau-2 {
  inset: 24%;
  border-style: dashed;
  border-color: color-mix(in srgb, var(--ink-soft) 14%, transparent);
}

/* Le noyau se redresse pour faire face au lecteur : sans ce contre-pivot, le
   logo serait couché avec le plan de l'orbite et deviendrait illisible. */
.orb-noyau {
  position: absolute;
  top: 50%; left: 50%;
  width: 116px; height: 116px;
  margin: -58px 0 0 -58px;
  border-radius: 30px;
  background: linear-gradient(145deg, var(--lime) 0%, var(--lime-strong) 100%);
  display: grid;
  place-items: center;
  box-shadow: var(--shadow-glow);
  transform: rotateX(-58deg) translateZ(36px);
  z-index: 50;
}
.orb-logo {
  width: 68px; height: 68px;
  object-fit: contain;
  filter: brightness(0) saturate(100%) invert(9%) sepia(28%) saturate(1200%) hue-rotate(96deg) brightness(95%);
}
.orb-halo {
  position: absolute;
  inset: -18px;
  border-radius: 40px;
  background: radial-gradient(circle, color-mix(in srgb, var(--lime) 34%, transparent) 0%, transparent 68%);
  opacity: 0;
  transition: opacity 0.5s var(--ease-out);
}
.orbite[data-actif] .orb-halo { opacity: 1; }

/* Chaque module. `--a` est l'angle posé par le JS ; tout le reste — position,
   profondeur, échelle, opacité — se déduit de lui en CSS. */
.orb-node {
  position: absolute;
  top: 50%; left: 50%;
  margin: -21px 0 0 -58px;
  width: 116px; height: 42px;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 9999px;
  background: color-mix(in srgb, var(--surface) 92%, transparent);
  color: var(--ink);
  font: 600 12.5px/1 inherit;
  cursor: pointer;
  backdrop-filter: blur(8px);
  transform:
    rotate(calc(var(--a, 0) * 1deg))
    translateX(var(--r, 168px))
    rotate(calc(var(--a, 0) * -1deg))
    rotateX(-58deg);
  transition: border-color 0.3s ease, background 0.3s ease, box-shadow 0.3s ease;
  z-index: calc(20 + var(--z, 0));
}
.orb-node > span {
  display: block;
  /* L'étiquette se redresse en sens inverse de l'inclinaison de l'orbite. */
  transform: scale(var(--s, 1));
  opacity: var(--o, 1);
  transition: transform 0.25s var(--ease-out), opacity 0.25s ease;
}
.orb-node:hover,
.orb-node:focus-visible {
  border-color: var(--lime-deep);
  box-shadow: 0 6px 22px -6px color-mix(in srgb, var(--lime) 55%, transparent);
  outline: none;
}
.orb-node[aria-pressed="true"] {
  border-color: var(--lime-deep);
  background: var(--lime);
  color: var(--forest);
}

.orb-legende {
  position: absolute;
  bottom: 2%;
  margin: 0;
  text-align: center;
  font-size: 13.5px;
  color: var(--ink-soft);
  max-width: 34ch;
  min-height: 2.6em;
}

@media (max-width: 720px) {
  .orbite { min-height: 300px; perspective: 800px; }
  .orb-scene { transform: rotateX(52deg); }
  .orb-noyau { width: 92px; height: 92px; margin: -46px 0 0 -46px; transform: rotateX(-52deg) translateZ(28px); }
  .orb-logo { width: 54px; height: 54px; }
  .orb-node { width: 96px; font-size: 11.5px; transform:
    rotate(calc(var(--a, 0) * 1deg)) translateX(var(--r, 124px))
    rotate(calc(var(--a, 0) * -1deg)) rotateX(-52deg); margin-left: -48px; }
}
@media (prefers-reduced-motion: reduce) {
  /* Une orbite qui tourne sans arrêt est exactement ce que ce réglage
     demande d'éteindre. On la fige à plat, lisible, sans rotation. */
  .orb-scene { transform: none; }
  .orb-noyau, .orb-node { transform: none; position: relative; margin: 6px; top: auto; left: auto; }
  .orb-scene { display: flex; flex-wrap: wrap; justify-content: center; align-items: center; aspect-ratio: auto; }
  .orb-anneau { display: none; }
}
