﻿:root {
  /* Palette — verts biologiques désaturés, conformité AA */
  --bg: #f7f9f8;
  --surface: #ffffff;
  --surface-2: #f0f4f1;
  --text: #1c2b23;
  --muted: #57655d;
  --primary: #1e6b47;
  --primary-dark: #145033;
  --primary-soft: #e9f2ed;
  --accent: #2c5f8a;
  --warning: #9c6414;
  --danger: #b42c2c;
  --border: #dce4df;

  /* Typographie */
  --font-body: Inter, 'Segoe UI', Arial, sans-serif;
  --font-heading: 'Source Serif 4', Georgia, 'Times New Roman', serif;
  /* Arabe (darija de la section paiement) — ni Inter ni Source Serif 4 ne
     couvrent l'arabe : sans jeton dédié, chaque système choisirait sa police
     de secours et la bulle du guichet changerait d'aspect d'un appareil à
     l'autre. */
  --font-ar: 'Noto Sans Arabic', 'Segoe UI', Tahoma, sans-serif;

  /* Élévation — 2 niveaux discrets, neutres */
  --shadow-sm: 0 1px 2px rgba(28, 43, 35, 0.06);
  --shadow: 0 2px 10px rgba(28, 43, 35, 0.08);

  /* Rayons — échelle réduite */
  --radius-sm: 4px;
  --radius-md: 8px;
  --radius: 12px;
}

* {
  box-sizing: border-box;
}

html {
  scroll-behavior: smooth;

  /* Échelle générale ramenée à 93,75 % (1rem = 15px au lieu de 16). Toute la
     typographie du site est en rem : titres, corps, formules KaTeX et champs
     de formulaire suivent d'un bloc, sans retoucher chaque règle. Exprimé en
     pourcentage et non en px, pour respecter la taille de police choisie par
     l'utilisateur dans son navigateur. */
  font-size: 93.75%;
}

body {
  margin: 0;
  min-height: 100vh;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-body);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 {
  font-family: var(--font-heading);
  font-weight: 600;
  line-height: 1.25;
  letter-spacing: 0;
  color: var(--text);
}

a {
  color: inherit;
  text-decoration: none;
}

button,
input,
select,
textarea {
  font: inherit;
}

button {
  cursor: pointer;
}

.site-header {
  position: sticky;
  top: 0;
  z-index: 30;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  padding: 9px clamp(14px, 3.4vw, 44px);
  background: rgba(255, 255, 255, 0.96);
  border-bottom: 1px solid var(--border);
  box-shadow: var(--shadow);
  backdrop-filter: blur(16px);
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  min-width: max-content;
}

.brand-logo {
  display: grid;
  width: 54px;
  height: 54px;
  place-items: center;
  border: 2px solid var(--primary);
  border-radius: 999px;
  background: var(--primary-soft);
  box-shadow: var(--shadow);
}

.brand-logo svg {
  width: 38px;
  height: 38px;
  fill: none;
  stroke: var(--primary);
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-width: 3.4;
}

.brand strong {
  display: block;
}

.brand strong {
  color: var(--primary-dark);
  font-size: 1.42rem;
  font-weight: 700;
  letter-spacing: 0;
}

.top-nav {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 8px;
  flex-wrap: wrap;
}

.top-nav a,
.logout-button {
  position: relative;
  border: 0;
  border-radius: 4px;
  padding: 12px 14px;
  color: #263c32;
  background: transparent;
  font-weight: 700;
  font-size: 0.9rem;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  transition: color 0.22s ease, background 0.22s ease, transform 0.22s ease;
}

.top-nav a::after {
  content: "";
  position: absolute;
  left: 12px;
  right: 12px;
  bottom: 5px;
  height: 3px;
  border-radius: 999px;
  background: var(--primary);
  transform: scaleX(0);
  transform-origin: center;
  transition: transform 0.24s ease;
}

.top-nav a:hover,
.top-nav a.active,
.logout-button:hover {
  background: var(--primary-soft);
  color: var(--primary-dark);
  transform: translateY(-1px);
}

.top-nav a:hover::after,
.top-nav a.active::after {
  transform: scaleX(1);
}

.mobile-toggle {
  display: none;
  border: 1px solid var(--border);
  border-radius: 12px;
  background: var(--surface);
  padding: 9px 12px;
  color: var(--primary-dark);
  font-weight: 700;
}

/* Espacements resserrés d'environ 15 % en même temps que l'échelle typographique
   (voir html{font-size}) : réduire les seules polices aurait laissé des marges
   surdimensionnées et la page aurait paru encore trop aérée. */
.app-shell {
  display: grid;
  grid-template-columns: 262px minmax(0, 1fr);
  gap: 20px;
  width: min(1440px, calc(100% - 32px));
  margin: 22px auto;
  align-items: start;
}

.semester-sidebar,
.content-area,
.site-footer {
  border: 1px solid var(--border);
  background: rgba(255, 255, 255, 0.86);
  box-shadow: var(--shadow);
  backdrop-filter: blur(12px);
}

.semester-sidebar {
  position: sticky;
  top: 92px;
  padding: 14px;
  border-radius: 12px;
}

.sidebar-title {
  margin-bottom: 12px;
  color: var(--muted);
  font-size: 0.86rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

.semester-button,
.module-link {
  width: 100%;
  border: 0;
  text-align: left;
}

.semester-button {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin: 6px 0;
  padding: 10px 12px;
  border: 1px solid #d8ead1;
  border-radius: 6px;
  background: #f7fcf4;
  font-weight: 700;
  color: #23401a;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  transition: transform 0.18s ease, background 0.18s ease, border-color 0.18s ease;
}

.semester-button.active {
  background: var(--primary);
  border-color: var(--primary);
  color: #fff;
}

.semester-button:hover {
  transform: translateX(3px);
  border-color: var(--primary);
}

.module-list {
  display: block;
  max-height: 0;
  opacity: 0;
  overflow: hidden;
  padding: 2px 0 9px 9px;
  transform: translateY(-4px);
  transition: max-height 0.28s ease, opacity 0.22s ease, transform 0.22s ease;
}

.module-list.open {
  /* Plafond de l'accordéon, pas la hauteur réelle — `max-height` ne peut pas
     transitionner vers `auto` en CSS pur, donc on fixe un plafond au-dessus
     du nécessaire et `overflow: hidden` rogne le reste. Posé à 260px pour SIX
     modules le 20 septembre 2026, il a rogné en SILENCE le 7ᵉ module de S3
     (« Informatique pour la biologie ») — présent dans le DOM, cliquable par
     son lien direct, invisible dans le menu. Relevé le 20 septembre 2026 sur
     signalement du propriétaire. 460px couvre confortablement jusqu'à une
     dizaine de modules : vérifier ce plafond après tout ajout de module à un
     semestre qui en a déjà beaucoup.
  */
  max-height: 460px;
  opacity: 1;
  transform: translateY(0);
}

.module-link {
  display: block;
  margin: 3px 0;
  padding: 8px 10px;
  border-left: 2px solid #cbe7c0;
  background: transparent;
  color: #40564b;
  border-radius: 0 8px 8px 0;
  font-weight: 700;
  font-size: 0.92rem;
  transition: color 0.18s ease, background 0.18s ease, border-color 0.18s ease, transform 0.18s ease;
}

.module-link:hover,
.module-link.active {
  border-left-color: var(--primary);
  background: #f0fbf5;
  color: var(--primary-dark);
  transform: translateX(3px);
}

.access-card {
  margin-top: 16px;
  padding: 14px;
  border-radius: 8px;
  background: var(--primary-dark);
  color: #fff;
}

.access-card strong {
  display: block;
  margin-bottom: 7px;
}

.access-card p {
  margin: 0;
  color: rgba(255, 255, 255, 0.76);
  font-size: 0.9rem;
  line-height: 1.5;
}

.content-area {
  min-height: 620px;
  padding: clamp(17px, 3.4vw, 38px);
  border-radius: var(--radius);
}

.content-area.page-enter {
  animation: pageEnter 0.42s cubic-bezier(0.2, 0.8, 0.2, 1) both;
}

@keyframes pageEnter {
  from {
    opacity: 0;
    transform: translateY(18px) scale(0.992);
    filter: blur(4px);
  }
  to {
    opacity: 1;
    transform: translateY(0) scale(1);
    filter: blur(0);
  }
}

.hero {
  display: grid;
  grid-template-columns: 1.25fr 0.75fr;
  gap: 28px;
  align-items: center;
}

.hero-stacked {
  grid-template-columns: 1fr;
  gap: 24px;
}

.hero-text {
  max-width: 960px;
}

.home-lab {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 0.9fr) minmax(360px, 1.1fr);
  gap: clamp(16px, 4vw, 46px);
  min-height: clamp(470px, 58vw, 640px);
  align-items: center;
  overflow: hidden;
  border: 1px solid rgba(30, 107, 71, 0.18);
  border-radius: 16px;
  background:
    radial-gradient(circle at 78% 22%, rgba(30, 107, 71, 0.4), transparent 30%),
    radial-gradient(circle at 15% 85%, rgba(122, 190, 150, 0.16), transparent 30%),
    linear-gradient(135deg, #0a2417, #14402b 48%, #f4f8f6);
  box-shadow: var(--shadow);
}

.home-lab::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(rgba(255, 255, 255, 0.045) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, 0.045) 1px, transparent 1px);
  background-size: 34px 34px;
  mask-image: linear-gradient(90deg, #000, transparent 76%);
  pointer-events: none;
}

.home-lab::after {
  content: "";
  position: absolute;
  left: 30%;
  top: -35%;
  width: 640px;
  height: 640px;
  border-radius: 999px;
  background: radial-gradient(circle, rgba(30, 107, 71, 0.28), transparent 65%);
  animation: glowPulse 4.8s ease-in-out infinite;
}

.lab-visual {
  position: relative;
  z-index: 2;
  min-height: 450px;
  margin-right: clamp(10px, 3vw, 42px);
}

.orbit {
  position: absolute;
  border: 1px solid rgba(143, 207, 168, 0.3);
  border-radius: 999px;
  inset: 12%;
  animation: rotateOrbit 18s linear infinite;
}

.orbit-two {
  inset: 22% 6% 10% 20%;
  border-color: rgba(255, 255, 255, 0.3);
  animation-duration: 26s;
  animation-direction: reverse;
}

.dna-helix {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 170px;
  height: 380px;
  transform: translate(-50%, -50%);
}

.dna-helix span {
  position: absolute;
  left: 50%;
  top: calc(var(--i) * 34px);
  width: 110px;
  height: 16px;
  transform: translateX(-50%) rotate(calc(var(--i) * 24deg));
  transform-origin: center;
  background: linear-gradient(90deg, rgba(255, 255, 255, 0.8), rgba(143, 207, 168, 0.72));
  border-radius: 999px;
  animation: dnaFloat 3.8s ease-in-out infinite;
  animation-delay: calc(var(--i) * -0.12s);
}

.dna-helix span::before,
.dna-helix span::after {
  content: "";
  position: absolute;
  top: 50%;
  width: 18px;
  height: 18px;
  border-radius: 999px;
  background: #fff;
  box-shadow: 0 0 24px rgba(255, 255, 255, 0.7);
}

.dna-helix span::before {
  left: 0;
  transform: translateY(-50%);
}

.dna-helix span::after {
  right: 0;
  transform: translateY(-50%);
  background: #8fcfa8;
}

.floating-card {
  position: absolute;
  display: grid;
  gap: 4px;
  min-width: 150px;
  border: 1px solid rgba(255, 255, 255, 0.44);
  border-radius: var(--radius);
  padding: 16px;
  background: rgba(255, 255, 255, 0.78);
  box-shadow: var(--shadow);
  backdrop-filter: blur(16px);
  animation: cardFloat 4.4s ease-in-out infinite;
}

/* Même police que le titre du hero placé à côté (Source Serif 4) */
.floating-card strong {
  color: var(--primary-dark);
  font-family: var(--font-heading);
  font-size: 1.15rem;
  font-weight: 600;
}

.floating-card span {
  color: var(--muted);
  font-size: 0.86rem;
  font-weight: 600;
}

.card-resume {
  left: 4%;
  top: 16%;
}

.card-exercice {
  right: 4%;
  top: 38%;
  animation-delay: -1.4s;
}

.card-examen {
  left: 10%;
  bottom: 11%;
  animation-delay: -2.4s;
}

.cell-bubble {
  position: absolute;
  border-radius: 999px;
  background:
    radial-gradient(circle at 35% 35%, rgba(255, 255, 255, 0.95), rgba(143, 207, 168, 0.2) 38%, rgba(30, 107, 71, 0.32));
  border: 1px solid rgba(255, 255, 255, 0.42);
  box-shadow: var(--shadow-sm);
  animation: bubbleDrift 7s ease-in-out infinite;
}

.bubble-one {
  width: 82px;
  height: 82px;
  right: 17%;
  top: 9%;
}

.bubble-two {
  width: 48px;
  height: 48px;
  left: 27%;
  top: 7%;
  animation-delay: -2s;
}

.bubble-three {
  width: 64px;
  height: 64px;
  right: 19%;
  bottom: 13%;
  animation-delay: -4s;
}

.showcase-content {
  position: relative;
  z-index: 2;
  display: grid;
  align-content: center;
  width: min(760px, 100%);
  padding: clamp(24px, 5.8vw, 62px);
}

.showcase-content h1 {
  color: #fff;
  font-size: clamp(2.15rem, 4.4vw, 3.6rem);
}

.showcase-content .lead {
  color: rgba(255, 255, 255, 0.86);
  font-size: clamp(0.98rem, 1.45vw, 1.14rem);
}

/* Libellés informatifs, pas des commandes : ni bordure, ni pastille — le hero
   ne doit proposer qu'une seule zone cliquable, celle des boutons .actions. */
.showcase-badges {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 14px;
  margin-top: 14px;
  color: rgba(255, 255, 255, 0.82);
  font-size: 0.82rem;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.showcase-badges span:not(:last-child)::after {
  content: "·";
  margin-left: 14px;
  color: rgba(255, 255, 255, 0.5);
}

@keyframes rotateOrbit {
  to {
    transform: rotate(360deg);
  }
}

@keyframes glowPulse {
  50% {
    opacity: 0.55;
    transform: scale(1.12);
  }
}

@keyframes dnaFloat {
  50% {
    transform: translateX(-50%) rotate(calc(var(--i) * 24deg + 10deg)) scaleX(0.92);
  }
}

@keyframes cardFloat {
  50% {
    transform: translateY(-12px);
  }
}

@keyframes bubbleDrift {
  50% {
    transform: translate(12px, -18px) scale(1.05);
  }
}

/* Accessibilité : désactiver les animations décoratives si demandé */
@media (prefers-reduced-motion: reduce) {
  .home-lab::after,
  .orbit,
  .dna-helix span,
  .floating-card,
  .cell-bubble {
    animation: none;
  }
}

.learning-path {
  display: grid;
  grid-template-columns: 0.82fr 1.18fr;
  gap: 24px;
  align-items: start;
}

.path-steps {
  display: grid;
  gap: 14px;
}

.path-steps article,
.dashboard-grid article,
.start-panel {
  border: 1px solid #d6edcd;
  border-radius: 16px;
  background: #ffffff;
  box-shadow: var(--shadow);
}

.path-steps article {
  position: relative;
  padding: 22px 22px 22px 78px;
}

.path-steps article span {
  position: absolute;
  left: 20px;
  top: 22px;
  display: grid;
  width: 42px;
  height: 42px;
  place-items: center;
  border-radius: 12px;
  background: var(--primary);
  color: #fff;
  font-weight: 700;
}

.path-steps p,
.dashboard-grid p,
.start-panel p {
  color: var(--muted);
  line-height: 1.7;
}

.home-dashboard {
  display: grid;
  gap: 22px;
}

.dashboard-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 16px;
}

.dashboard-grid article {
  padding: 24px;
  transition: transform 0.22s ease, box-shadow 0.22s ease;
}

.dashboard-grid article:hover,
.path-steps article:hover {
  transform: translateY(-4px);
  box-shadow: var(--shadow);
}

.start-panel {
  padding: clamp(24px, 4vw, 38px);
}

.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin: 0 0 18px;
  padding: 8px 12px;
  border-radius: 999px;
  background: var(--primary-soft);
  color: var(--primary-dark);
  font-weight: 700;
  font-size: 0.86rem;
}

h1,
h2,
h3 {
  margin: 0;
  line-height: 1.08;
}

/* Échelle typographique (revue juillet 2026)
   ------------------------------------------
   Sur écran large : h1 41,6 px / h2 29,6 px / h3 20,5 px, soit des rapports
   de 1,4 entre niveaux consécutifs. Auparavant h1 et h2 plafonnaient à 60,8
   et 49,6 px : des tailles de hero appliquées à *tous* les titres, ce qui
   laissait une marche de 2,1 entre h2 et h3 et faisait lire un intertitre
   comme une seconde bannière. Le hero de l accueil garde sa grande taille,
   mais par sa propre règle (.showcase-content h1), pas par le défaut. */
h1 {
  max-width: 840px;
  font-size: clamp(1.9rem, 3.4vw, 2.6rem);
  letter-spacing: 0;
}

h2 {
  font-size: clamp(1.45rem, 2.3vw, 1.85rem);
  letter-spacing: 0;
}

h3 {
  font-size: 1.28rem;
}

.lead {
  max-width: 780px;
  color: var(--muted);
  font-size: 1.1rem;
  line-height: 1.75;
}

.actions {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 24px;
}

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 44px;
  border: 0;
  border-radius: 6px;
  padding: 12px 18px;
  background: var(--primary);
  color: #fff;
  font-weight: 700;
  box-shadow: var(--shadow);
}

.btn:hover {
  background: var(--primary-dark);
}

.btn.secondary {
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--primary-dark);
  box-shadow: none;
}

.btn.danger {
  background: var(--danger);
  box-shadow: 0 14px 28px rgba(197, 48, 48, 0.18);
}

.hero-card,
.card,
.module-card,
.form-card,
.admin-user {
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--surface);
  box-shadow: 0 14px 38px rgba(8, 54, 35, 0.08);
}

.hero-card {
  padding: 0;
  overflow: hidden;
}

.instructor-visual {
  position: relative;
  min-height: clamp(340px, 45vw, 540px);
  border-radius: 10px;
  overflow: hidden;
  background: #17230f;
}

.instructor-visual img {
  display: block;
  width: 100%;
  min-height: clamp(340px, 45vw, 540px);
  object-fit: cover;
  object-position: center;
  filter: saturate(0.95) hue-rotate(35deg);
}

.instructor-visual::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(12, 38, 0, 0.28), rgba(20, 75, 0, 0.72));
}

.instructor-overlay {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: grid;
  place-content: end center;
  gap: 10px;
  padding: clamp(28px, 5vw, 58px);
  color: #fff;
  text-align: center;
  text-transform: uppercase;
  letter-spacing: 0.18em;
}

.instructor-overlay span,
.instructor-overlay em {
  font-size: clamp(0.8rem, 1.6vw, 1rem);
  font-style: normal;
  font-weight: 700;
}

.instructor-overlay strong {
  font-size: clamp(2rem, 4vw, 3.3rem);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-shadow: 0 4px 20px rgba(0, 0, 0, 0.34);
}

.quote-panel {
  position: relative;
  border-left: 6px solid var(--primary);
  border-radius: 6px;
  padding: 24px 28px;
  background: #ffffff;
  box-shadow: var(--shadow);
}

.quote-panel p {
  margin: 0;
  color: #24411b;
  font-size: clamp(1.1rem, 2vw, 1.45rem);
  font-weight: 700;
  line-height: 1.65;
}

.quote-panel p::before {
  content: "“";
  color: var(--primary);
  font-size: 2.4rem;
  line-height: 0;
  margin-right: 6px;
  vertical-align: -0.24em;
}

.grid {
  display: grid;
  gap: 18px;
}

.grid.three {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}

.grid.two {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

.section {
  margin-top: 36px;
}

.card,
.module-card {
  padding: 22px;
}

.card p,
.module-card p {
  color: var(--muted);
  line-height: 1.7;
}

.stat {
  display: block;
  color: var(--primary);
  font-size: 2rem;
  font-weight: 700;
}

.status-pill {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  width: max-content;
  border-radius: 999px;
  padding: 8px 12px;
  background: #edf2f7;
  color: #344054;
  font-weight: 700;
  font-size: 0.86rem;
}

.status-pill.pending_payment {
  background: #fff7e6;
  color: var(--warning);
}

.status-pill.awaiting_approval {
  background: #e8f1ff;
  color: var(--accent);
}

.status-pill.approved {
  background: var(--primary-soft);
  color: var(--primary-dark);
}

.status-pill.rejected {
  background: #ffecec;
  color: var(--danger);
}

.form-card {
  max-width: 760px;
  padding: 26px;
}

.form-grid {
  display: grid;
  gap: 16px;
}

.form-grid.two {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

label {
  display: grid;
  gap: 7px;
  color: #334a3f;
  font-weight: 700;
}

input,
select,
textarea {
  width: 100%;
  border: 1px solid var(--border);
  border-radius: 14px;
  background: #fbfefc;
  padding: 13px 14px;
  color: var(--text);
}

textarea {
  min-height: 120px;
  resize: vertical;
}

input:focus,
select:focus,
textarea:focus {
  outline: 3px solid rgba(30, 107, 71, 0.14);
  border-color: var(--primary);
}

.contact-highlight {
  border: 1px solid #d6edcd;
  border-radius: 10px;
  padding: 24px;
  background: #ffffff;
  box-shadow: var(--shadow);
}

.contact-highlight h3 {
  color: var(--primary-dark);
}

.contact-highlight p {
  color: var(--muted);
  line-height: 1.75;
}

.contact-form-card {
  max-width: 880px;
}

/* Le formulaire est la raison d'être de la page : il s'ouvre à hauteur du
   titre, sans défilement. Empilé sous l'accroche et les trois rubriques, il
   commençait à 860 px du haut, soit une page entière plus bas. */
.contact-layout {
  display: grid;
  grid-template-columns: minmax(280px, 1fr) minmax(360px, 0.95fr);
  gap: clamp(22px, 3vw, 40px);
  align-items: start;
}

.contact-intro {
  display: grid;
  gap: 14px;
  align-content: start;
}

.contact-intro h1 {
  font-size: clamp(1.6rem, 2.4vw, 2rem);
  margin: 0;
}

.contact-intro .lead {
  margin: 0;
}

.contact-layout .contact-grid {
  grid-template-columns: 1fr;
  gap: 12px;
  margin-top: 4px;
}

/* Trois sélecteurs : .contact-grid .contact-highlight impose 190px plus bas
   dans la feuille, à égalité de spécificité. */
.contact-layout .contact-grid .contact-highlight {
  min-height: 0;
  padding: 14px 16px;
}

.contact-layout .contact-highlight h3 {
  font-size: 1.02rem;
}

.contact-layout .contact-highlight p {
  margin: 4px 0 0;
  font-size: 0.92rem;
  line-height: 1.6;
}

.contact-layout .contact-form-card {
  max-width: 100%;
  padding: 20px;
}

.contact-form-card h2 {
  margin: 0;
  font-size: 1.35rem;
}

.contact-form-note {
  margin: 8px 0 14px;
  color: var(--muted);
  font-size: 0.92rem;
  line-height: 1.6;
}

.contact-layout .form-grid {
  gap: 13px;
}

.contact-layout label {
  gap: 6px;
}

.contact-layout input,
.contact-layout select {
  padding: 11px 14px;
}

.contact-layout textarea {
  min-height: 86px;
  padding: 11px 14px;
}

/* Tant qu'aucun message d'envoi n'est affiché, la ligne ne réserve pas de place */
.contact-layout .form-message:empty {
  display: none;
}

@media (max-width: 1080px) {
  .contact-layout {
    grid-template-columns: 1fr;
  }

  .contact-layout .contact-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

.auth-card {
  animation: authEnter 0.34s ease both;
  overflow: hidden;
}

.auth-card.leaving {
  animation: authLeave 0.2s ease both;
}

.auth-form-panel {
  animation: panelSlide 0.34s ease both;
}

@keyframes authEnter {
  from {
    opacity: 0;
    transform: translateY(14px) scale(0.985);
  }
  to {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
}

@keyframes authLeave {
  to {
    opacity: 0;
    transform: translateY(10px) scale(0.985);
  }
}

@keyframes panelSlide {
  from {
    opacity: 0;
    transform: translateX(18px);
  }
  to {
    opacity: 1;
    transform: translateX(0);
  }
}

.form-message {
  min-height: 24px;
  margin: 14px 0 0;
  color: var(--danger);
  font-weight: 700;
}

.form-message.success {
  color: var(--primary-dark);
}

.auth-forgot {
  margin: 12px 0 0;
  font-size: 0.95rem;
}

.auth-forgot a {
  color: var(--primary-dark);
  font-weight: 600;
  text-decoration: none;
}

.auth-forgot a:hover {
  text-decoration: underline;
}

/* ── Connexion Google ──

   LE BOUTON EST BLANC, PAS VERT. `.btn` seul le peindrait du vert de la marque,
   et l'étudiant y lirait l'action principale de la carte — or l'action
   principale est le formulaire au-dessus. Le blanc bordé est aussi la forme
   qu'impose Google à ses boutons de connexion : c'est celle que l'étudiant
   reconnaît sans lire. */
.auth-sep {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 18px 0 14px;
  color: var(--muted);
  font-size: 0.85rem;
}

.auth-sep::before,
.auth-sep::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--border);
}

.btn.google-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  width: 100%;
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-sm);
}

.btn.google-btn:hover {
  background: var(--surface-2);
  border-color: #c8d2cc;
}

.google-mark {
  display: inline-flex;
  align-items: center;
}

.auth-google-note {
  margin: 10px 0 0;
  font-size: 0.85rem;
  color: var(--muted);
  text-align: center;
}

.tabs {
  display: flex;
  gap: 10px;
  margin-bottom: 20px;
  flex-wrap: wrap;
}

.tab {
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 10px 15px;
  background: var(--surface);
  color: var(--muted);
  font-weight: 700;
}

.tab.active {
  border-color: var(--primary);
  background: var(--primary-soft);
  color: var(--primary-dark);
}

.locked {
  border: 1px dashed rgba(183, 121, 31, 0.5);
  border-radius: 18px;
  padding: 18px;
  background: #fffaf0;
  color: #7a4b0d;
  font-weight: 700;
}

.content-list {
  margin: 16px 0 0;
  padding-left: 20px;
  color: var(--muted);
  line-height: 1.8;
}

.stats-hero {
  display: grid;
  gap: 24px;
  align-items: center;
  overflow: hidden;
  background:
    #ffffff;
  border-color: #d7dee8;
}

.chapter-pill {
  display: inline-flex;
  margin-bottom: 12px;
  border-radius: 999px;
  padding: 8px 12px;
  background: #243447;
  color: #fff;
  font-size: 0.82rem;
  font-weight: 700;
}

.course-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 18px;
}

.course-meta span {
  border: 1px solid #d2dae5;
  border-radius: 999px;
  padding: 7px 11px;
  background: #fff;
  color: #415064;
  font-size: 0.86rem;
  font-weight: 700;
}

.chapter-map-container {
  margin: 0 0 24px 0;
  padding: 20px;
  background: #f8fafc;
  border-radius: 12px;
  border: 1px solid var(--border);
}

.stats-hero-mini {
  margin-bottom: 16px;
  padding-bottom: 16px;
  border-bottom: 1px solid var(--border);
}

.stats-hero-mini h3 {
  margin: 8px 0;
  font-size: 1.25rem;
  color: var(--text);
}

.stats-hero-mini p {
  margin: 0;
  color: var(--muted);
  font-size: 0.9rem;
}

.chapter-map {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 12px;
}

.chapter-map button {
  display: grid;
  text-align: left;
  gap: 5px;
  border: 1px solid var(--border);
  border-radius: 16px;
  padding: 14px;
  background: #fff;
  cursor: pointer;
  font: inherit;
  transition: border-color 0.2s ease, background 0.2s ease, transform 0.2s ease;
}

.chapter-map button:hover:not(:disabled) {
  border-color: #94a3b8;
  transform: translateY(-2px);
}

.chapter-map button.active {
  border-color: #243447;
  background: #f6f8fb;
}

.chapter-map button:disabled {
  cursor: not-allowed;
  opacity: 0.5;
  background: #f1f5f9;
  border-color: #e2e8f0;
}

.chapter-map button:disabled strong {
  color: #94a3b8;
}

.chapter-map button:disabled em {
  color: #64748b;
  font-style: italic;
}

.chapter-map span {
  color: #243447;
  font-weight: 700;
}

.chapter-map strong {
  color: var(--text);
}

.chapter-map em {
  color: var(--muted);
  font-size: 0.82rem;
  font-style: normal;
  font-weight: 700;
}

.course-flow{
  display: grid;
  gap: 18px;
}

.mature-course {
  gap: 28px;
}

.course-section {
  display: grid;
  gap: 16px;
}

.course-section-header {
  border-left: 5px solid #243447;
  padding: 10px 0 10px 16px;
}

.course-section-header span {
  display: block;
  margin-bottom: 4px;
  color: #64748b;
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.course-section-header h2 {
  margin: 0;
  /* Sous le h2 global : un titre de section de cours ne peut pas être le
     plus gros h2 du site. */
  color: #172033;
  font-size: clamp(1.35rem, 2.1vw, 1.7rem);
}

.lesson-card {
  border: 1px solid #d8e0ea;
  border-radius: 14px;
  padding: clamp(18px, 3vw, 28px);
  background: #fff;
  box-shadow: 0 12px 34px rgba(15, 23, 42, 0.06);
}

.lesson-card h3 {
  margin-bottom: 18px;
  /* Doit rester nettement sous le titre de section (.course-section-header
     h2) : à 1,55rem il n en était plus distinct que de 9 %. */
  color: #172033;
  font-size: clamp(1.16rem, 1.7vw, 1.35rem);
}

.lesson-card h4 {
  margin-bottom: 8px;
  color: #243447;
  font-size: 1.02rem;
}

.subsection {
  border-top: 1px solid #e5eaf0;
  padding-top: 16px;
  margin-top: 16px;
}

.subsection:first-of-type {
  border-top: 0;
  padding-top: 0;
  margin-top: 0;
}

.concept-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 14px;
}

.concept-card {
  border: 1px solid #d8e0ea;
  border-radius: 14px;
  padding: 18px;
  background: #fff;
  box-shadow: 0 10px 28px rgba(15, 23, 42, 0.04);
}

.concept-card h3 {
  margin-bottom: 10px;
  color: #172033;
  font-size: 1.08rem;
}

.set-visual {
  position: relative;
  min-height: 180px;
  margin: 18px 0;
  border-radius: 18px;
  background: #ffffff;
}

.set-circle {
  position: absolute;
  top: 34px;
  display: grid;
  place-items: center;
  width: 128px;
  height: 128px;
  border: 2px solid rgba(30, 107, 71, 0.42);
  border-radius: 999px;
  background: rgba(30, 107, 71, 0.12);
  color: var(--primary-dark);
  font-weight: 700;
}

.set-a {
  left: calc(50% - 118px);
}

.set-b {
  right: calc(50% - 118px);
  background: rgba(145, 230, 109, 0.18);
}

.set-visual strong {
  position: absolute;
  left: 50%;
  top: 82px;
  transform: translateX(-50%);
  color: var(--primary-dark);
}

.law-grid,
.repeat-grid,
.checkpoint-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
}

.law-grid span,
.repeat-grid div,
.checkpoint-grid article {
  border: 1px solid #d8e0ea;
  border-radius: 14px;
  padding: 14px;
  background: #f8fafc;
  color: #334155;
  font-weight: 600;
}

.law-grid.compact {
  grid-template-columns: 1fr;
  gap: 8px;
}

.law-grid.compact span {
  padding: 10px 12px;
}

.formula-box {
  display: grid;
  gap: 6px;
  margin: 16px 0;
  border-left: 4px solid #475569;
  border-radius: 10px;
  padding: 12px 14px;
  background: #f8fafc;
  color: #1f2937;
}

.formula-box strong {
  font-size: clamp(1rem, 1.35vw, 1.18rem);
}

.formula-box span {
  color: #475569;
  font-weight: 700;
}

.example-block {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(320px, 0.82fr);
  gap: 18px;
  align-items: start;
}

.token-cloud {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  align-items: center;
}

.token-cloud span {
  border-radius: 999px;
  padding: 8px 12px;
  background: #eef2f7;
  color: #263244;
  font-weight: 700;
}

.token-cloud.sober span {
  border-radius: 8px;
  background: #f8fafc;
  border: 1px solid #d8e0ea;
  color: #334155;
}

.repeat-grid {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}

.repeat-grid strong,
.repeat-grid span {
  display: block;
  margin-top: 8px;
  color: #243447;
  font-weight: 700;
}

.checkpoint-grid article {
  display: grid;
  gap: 8px;
}

.checkpoint-grid span {
  color: var(--primary);
  font-weight: 700;
}

.checkpoint-grid strong,
.checkpoint-grid em {
  display: block;
}

.checkpoint-grid em {
  color: var(--muted);
  font-style: normal;
  font-weight: 700;
}

.letter-source,
.demo-slots{
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: center;
}

.letter-source span,
.demo-slots span{
  display: inline-grid;
  place-items: center;
  min-width: 42px;
  min-height: 42px;
  border: 1px solid #cbd5e1;
  border-radius: 10px;
  background: #fff;
  color: #243447;
  font-weight: 700;
}

.lab-panel {
  border: 1px solid #d8e0ea;
  border-radius: 16px;
  padding: 16px;
  background: #fbfdff;
}

.lab-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  margin-bottom: 12px;
}

.lab-header strong {
  color: #172033;
}

.lab-tag {
  border: 1px solid #cbd5e1;
  border-radius: 999px;
  padding: 4px 10px;
  color: #64748b;
  font-size: 0.74rem;
  font-weight: 700;
  white-space: nowrap;
}

.lab-readout {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 10px;
  margin-top: 14px;
}

.lab-readout div {
  display: grid;
  gap: 6px;
  border: 1px solid #e2e8f0;
  border-radius: 12px;
  padding: 10px;
  background: #fff;
}

.lab-readout span {
  color: #64748b;
  font-size: 0.78rem;
  font-weight: 700;
}

.lab-readout strong {
  color: #172033;
  font-size: 1.05rem;
}

.law-table {
  width: 100%;
  border-collapse: collapse;
  margin: 4px 0 6px;
  font-size: 0.92rem;
}

.law-table th,
.law-table td {
  border: 1px solid #e2e8f0;
  padding: 8px 10px;
  text-align: center;
}

.law-table th {
  background: #f1f5fb;
  color: #243447;
  font-weight: 700;
}

.law-table thead th {
  color: #64748b;
}

.worked-solution {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 10px;
  margin-top: 12px;
}

.worked-solution div {
  display: grid;
  gap: 8px;
  border: 1px solid #d8e0ea;
  border-radius: 14px;
  padding: 12px;
  background: #f8fafc;
}

.worked-solution span {
  color: #64748b;
  font-size: 0.84rem;
  font-weight: 700;
}

.worked-solution strong {
  color: #172033;
}

.static-example-card {
  border-left: 5px solid #243447;
}

.urn {
  position: relative;
  display: flex;
  justify-content: center;
  gap: 8px;
  min-height: 112px;
  border: 2px solid #94a3b8;
  border-top: 0;
  border-radius: 10px 10px 34px 34px;
  padding: 36px 12px 12px;
  background: #ffffff;
}

.admin-list {
  display: grid;
  gap: 18px;
  margin-top: 20px;
}

.admin-user {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 220px;
  gap: 18px;
  padding: 20px;
  border-left: 6px solid var(--border);
}

.admin-user p {
  margin: 6px 0;
  color: var(--muted);
}

.admin-user.approved {
  border-left-color: var(--primary);
}

.admin-user.rejected {
  border-left-color: var(--danger);
}

.admin-user-heading {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  align-items: flex-start;
}

.access-summary {
  display: grid;
  gap: 4px;
  margin: 14px 0;
  border-radius: 12px;
  padding: 12px 14px;
  background: #f6f8f7;
  color: var(--muted);
}

.access-summary.active {
  border: 1px solid #c8efba;
  background: #f1fcec;
  color: var(--primary-dark);
}

.access-summary.inactive {
  border: 1px dashed var(--border);
}

.access-summary strong,
.access-summary span {
  display: block;
}

.admin-actions {
  display: grid;
  gap: 8px;
  align-content: start;
}

.btn:disabled {
  cursor: not-allowed;
  opacity: 0.72;
  box-shadow: none;
}

.custom-access {
  display: grid;
  gap: 14px;
  margin-top: 16px;
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 14px;
  background: #fbfefc;
}

.custom-access-title {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  align-items: center;
  flex-wrap: wrap;
}

.custom-access-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
}

.custom-access fieldset {
  display: grid;
  gap: 8px;
  margin: 0;
  border: 1px solid #dcebdd;
  border-radius: 12px;
  padding: 12px;
  background: #ffffff;
}

.custom-access legend {
  padding: 0 6px;
  color: var(--primary-dark);
  font-weight: 700;
}

.check-line {
  display: flex;
  grid-template-columns: none;
  gap: 8px;
  align-items: center;
  color: #334a3f;
  font-size: 0.9rem;
  font-weight: 700;
}

.check-line input {
  width: auto;
  accent-color: var(--primary);
}

.module-check {
  color: var(--muted);
  font-weight: 700;
}

.empty-state {
  border: 1px dashed var(--border);
  border-radius: 18px;
  padding: 24px;
  background: #fbfefc;
  color: var(--muted);
  text-align: center;
}

.site-footer {
  display: grid;
  grid-template-columns: 1fr auto;
  justify-content: space-between;
  gap: 18px;
  width: min(1440px, calc(100% - 32px));
  margin: 0 auto 28px;
  padding: 22px clamp(18px, 4vw, 34px);
  border-radius: var(--radius);
  color: var(--muted);
}

.site-footer strong,
.site-footer span {
  display: block;
}

.site-footer strong {
  color: var(--text);
}

.site-footer a {
  color: var(--primary-dark);
  font-weight: 700;
}

.footer-links {
  display: grid;
  justify-items: end;
  gap: 6px;
  text-align: right;
}

.toast {
  position: fixed;
  right: 22px;
  bottom: 22px;
  z-index: 100;
  max-width: 320px;
  border-left: 5px solid var(--primary);
  border-radius: 8px;
  padding: 14px 16px;
  background: #fff;
  color: var(--text);
  box-shadow: 0 18px 42px rgba(0, 0, 0, 0.16);
  font-weight: 700;
  opacity: 0;
  transform: translateY(16px);
  pointer-events: none;
  transition: opacity 0.24s ease, transform 0.24s ease;
}

.toast.show {
  opacity: 1;
  transform: translateY(0);
}

.logout-button.loading {
  opacity: 0.72;
}

[hidden] {
  display: none !important;
}

@media (max-width: 1020px) {
  .app-shell,
  .learning-path,
  .dashboard-grid,
  .grid.three,
  .grid.two,
  .form-grid.two {
    grid-template-columns: 1fr;
  }

  .semester-sidebar {
    position: static;
  }

  .home-lab {
    grid-template-columns: 1fr;
    min-height: auto;
  }

  .lab-visual {
    min-height: 420px;
    margin: 0 20px 30px;
  }

  .custom-access-grid {
    grid-template-columns: 1fr;
  }

  .stats-hero,
  .chapter-map-container,
  .chapter-map,
  .repeat-grid,
  .concept-grid,
  .example-block,
  .worked-solution,
  .lab-readout {
    grid-template-columns: 1fr;
  }

}

@media (max-width: 760px) {
  .site-header {
    align-items: flex-start;
    flex-wrap: wrap;
  }
  
  .chapter-map {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  
  .chapter-map-container {
    padding: 12px;
  }
  
  .td-tab {
    font-size: 0.8rem;
    padding: 8px 12px;
  }

  .mobile-toggle {
    display: inline-flex;
  }

  .top-nav {
    display: none;
    width: 100%;
    justify-content: stretch;
  }

  .top-nav.open {
    display: grid;
  }

  .top-nav a,
  .logout-button {
    width: 100%;
    text-align: left;
  }

  .content-area,
  .semester-sidebar {
    padding: 18px;
  }

  .home-lab {
    border-radius: 16px;
  }

  .showcase-content {
    padding: 26px;
  }

  .lab-visual {
    min-height: 390px;
    margin: 0 0 24px;
  }

  .floating-card {
    min-width: 126px;
    padding: 12px;
  }

  .card-resume {
    left: 0;
  }

  .card-exercice {
    right: 0;
  }

  .showcase-badges {
    display: grid;
    justify-items: start;
  }

  /* Empilés : le point médian de séparation n'a plus de sens */
  .showcase-badges span:not(:last-child)::after {
    content: none;
  }

  .path-steps article {
    padding: 72px 18px 18px;
  }

  .admin-user {
    grid-template-columns: 1fr;
  }

  .admin-user-heading,
  .custom-access-title {
    display: grid;
  }

  .stats-hero {
    padding: 18px;
  }

  .law-grid,
  .checkpoint-grid {
    grid-template-columns: 1fr;
  }

  .course-section-header h2 {
    font-size: 1.35rem;
  }

  .set-circle {
    width: 108px;
    height: 108px;
  }

  .set-a {
    left: calc(50% - 96px);
  }

  .set-b {
    right: calc(50% - 96px);
  }

  .site-footer {
    display: grid;
    grid-template-columns: 1fr;
  }

  .footer-links {
    justify-items: start;
    text-align: left;
  }
}

/* Maintenance Styles - Academic gray theme */
.semester-button.maintenance {
  background: #f1f5f9;
  border-color: #cbd5e1;
  color: #475569;
  cursor: pointer;
}

.semester-button.maintenance:hover {
  transform: translateY(-2px);
  border-color: #94a3b8;
  box-shadow: 0 8px 24px rgba(100, 116, 139, 0.1);
}

.maintenance-badge {
  background: #64748b;
  color: #fff;
  font-size: 0.65rem;
  padding: 3px 10px;
  border-radius: 999px;
  font-weight: 700;
  display: inline-flex;
  align-items: center;
  line-height: 1;
  white-space: nowrap;
}

/* Maintenance Page Styles */
.maintenance-hero {
  text-align: center;
  padding: 40px 20px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

.maintenance-hero h1 {
  width: 100%;
  max-width: 600px;
  margin: 0 auto 16px;
  line-height: 1.3;
}

.maintenance-icon {
  font-size: 3rem;
  margin-bottom: 20px;
  color: var(--primary);
  opacity: 0.8;
  display: flex;
  justify-content: center;
  align-items: center;
}

@keyframes pulse {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.1); }
}

.maintenance-subtitle {
  color: var(--muted);
  font-size: 1.1rem;
  margin-bottom: 30px;
  text-align: center;
  width: 100%;
  max-width: 500px;
  margin-left: auto;
  margin-right: auto;
}

.maintenance-content {
  max-width: 700px;
  margin: 0 auto;
}

.maintenance-card {
  background: #ffffff;
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 32px;
  margin-bottom: 24px;
  text-align: left;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
}

.maintenance-card h3 {
  color: var(--text);
  margin-bottom: 16px;
  font-size: 1.2rem;
  font-weight: 600;
  border-bottom: 2px solid var(--border);
  padding-bottom: 12px;
}

.maintenance-card p {
  color: var(--text);
  line-height: 1.7;
  margin-bottom: 12px;
}

.maintenance-list {
  list-style: none;
  padding: 0;
  margin: 20px 0;
}

.maintenance-list li {
  padding: 10px 0;
  padding-left: 28px;
  position: relative;
  border-bottom: 1px dashed var(--border);
}

.maintenance-list li:before {
  content: "▸";
  color: var(--primary);
  position: absolute;
  left: 0;
  font-size: 1.1rem;
}

.maintenance-list li:last-child {
  border-bottom: none;
}

.maintenance-notify {
  background: var(--primary-soft);
  border-radius: 10px;
  padding: 16px;
  margin-top: 24px;
  text-align: center;
}

.maintenance-notify p {
  margin: 0;
  color: var(--primary-dark);
  font-weight: 600;
}

.maintenance-actions {
  display: flex;
  gap: 16px;
  justify-content: center;
  flex-wrap: wrap;
}

/* Fraction Display Styles */
.fraction {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  vertical-align: middle;
  font-size: 0.95em;
  line-height: 1;
}

.fraction .num {
  border-bottom: 1.5px solid currentColor;
  padding: 0 4px 2px;
  text-align: center;
}

.fraction .den {
  padding: 2px 4px 0;
  text-align: center;
}

.fraction-inline {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  vertical-align: middle;
}


/* Exercise Split View Styles - Academic Design */
.exercise-split-view {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 28px;
  min-height: 500px;
}

.exercise-panel,
.solution-panel {
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 32px;
  background: #ffffff;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.04);
  font-family: 'Georgia', 'Times New Roman', serif;
  line-height: 1.8;
}

.exercise-panel {
  border-top: 4px solid var(--primary);
}

.solution-panel {
  border-top: 4px solid var(--accent);
  position: relative;
}

.solution-panel.hidden {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  background: #ffffff;
  border: 2px dashed var(--border);
}

.solution-panel.hidden .solution-content {
  display: none;
}

.reveal-solution-btn {
  padding: 14px 28px;
  font-size: 1rem;
  font-weight: 700;
}

.exercise-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 24px;
  padding-bottom: 16px;
  border-bottom: 2px solid var(--border);
}

.exercise-title {
  font-size: 1.15rem;
  font-weight: 700;
  color: var(--text);
  font-family: Inter, Arial, sans-serif;
  letter-spacing: 0;
}

.exercise-badge {
  background: var(--primary-soft);
  color: var(--primary-dark);
  padding: 6px 14px;
  border-radius: 6px;
  font-size: 0.75rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  font-family: Inter, Arial, sans-serif;
}

.solution-badge {
  background: #dbeafe;
  color: #1e40af;
  padding: 6px 14px;
  border-radius: 6px;
  font-size: 0.75rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  font-family: Inter, Arial, sans-serif;
}

.exercise-content {
  font-size: 1rem;
  color: #334155;
  text-align: justify;
}

.exercise-content strong {
  color: var(--primary-dark);
  font-weight: 600;
}

.solution-content {
  font-size: 0.95rem;
  color: #334155;
  text-align: justify;
}

.solution-content strong {
  color: var(--accent);
  font-weight: 600;
}

.exercise-navigation {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-top: 24px;
  padding-top: 16px;
  border-top: 1px solid var(--border);
}

.nav-btn {
  padding: 10px 20px;
  font-weight: 700;
}

.nav-btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.exercise-counter {
  font-weight: 700;
  color: var(--muted);
}

/* TD Series Navigation - Academic Style */
.td-series-nav {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-bottom: 28px;
  padding: 20px 24px;
  background: #ffffff;
  border-radius: 10px;
  border: 1px solid var(--border);
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.03);
}

.td-series-btn {
  padding: 12px 24px;
  border-radius: 8px;
  font-weight: 600;
  font-size: 0.95rem;
  transition: all 0.2s ease;
  border: 1px solid var(--border);
  background: #ffffff;
  color: var(--text);
}

.td-series-btn:hover {
  border-color: var(--primary);
  color: var(--primary);
  transform: translateY(-1px);
}

.td-series-btn.active {
  background: var(--primary);
  color: #fff;
  border-color: var(--primary);
  box-shadow: var(--shadow);
}

.td-tabs {
  display: flex;
  gap: 4px;
  margin-bottom: 16px;
  flex-wrap: nowrap;
  overflow-x: auto;
  border-bottom: 2px solid var(--border);
  padding-bottom: 0;
}

.td-tab {
  padding: 10px 16px;
  border-radius: 8px 8px 0 0;
  font-weight: 600;
  font-size: 0.85rem;
  white-space: nowrap;
  transition: all 0.2s ease;
  border: none;
  border-bottom: 3px solid transparent;
  background: transparent;
  color: var(--muted);
  margin-bottom: -2px;
}

.td-tab:hover {
  color: var(--primary-dark);
  background: var(--primary-soft);
}

.td-tab.active {
  background: #ffffff;
  color: var(--primary-dark);
  border-bottom-color: var(--primary);
  font-weight: 700;
}

/* Onglet dont le corpus n'est pas encore lu : le clic doit se voir pendant
   l'aller-retour réseau, sinon il paraît sans effet. */
.td-tab.is-loading {
  color: var(--primary-dark);
  cursor: progress;
}

.td-tab.is-loading::after {
  content: '';
  display: inline-block;
  width: 11px;
  height: 11px;
  margin-left: 7px;
  vertical-align: -1px;
  border: 2px solid var(--border);
  border-top-color: var(--primary);
  border-radius: 50%;
  animation: td-tab-spin 0.7s linear infinite;
}

@keyframes td-tab-spin {
  to { transform: rotate(360deg); }
}

@media (prefers-reduced-motion: reduce) {
  .td-tab.is-loading::after { animation-duration: 2.4s; }
}

/* Random Exercise Generator - Academic Style */
.random-exercise-panel {
  text-align: center;
  padding: 48px;
  background: #ffffff;
  border-radius: 12px;
  border: 1px solid var(--border);
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.05);
}

.random-exercise-panel h2 {
  font-size: 1.5rem;
  margin-bottom: 12px;
  color: var(--text);
}

.random-exercise-panel p {
  color: var(--muted);
  margin-bottom: 24px;
}

.random-exercise-btn {
  padding: 14px 32px;
  font-size: 1rem;
  font-weight: 700;
  border-radius: 8px;
}

.generator-info {
  color: var(--muted);
  margin-top: 16px;
  font-size: 0.9rem;
  font-style: italic;
}

/* Math and Table Styles for Exercises */
.math-table {
  width: 100%;
  border-collapse: collapse;
  margin: 20px 0;
  font-family: Georgia, 'Times New Roman', serif;
  font-size: 1rem;
  background: #ffffff;
  border: 1px solid var(--border);
  border-radius: 8px;
  overflow: hidden;
}

.math-table th,
.math-table td {
  border: 1px solid var(--border);
  padding: 12px 16px;
  text-align: center;
}

.math-table th {
  background: #f0fdf4;
  font-weight: 600;
  color: var(--text);
  border-bottom: 2px solid var(--primary);
}

.math-table td {
  background: #ffffff;
}

.math-table tr:nth-child(even) td {
  background: #fafbfc;
}

/* Combination notation C(n,k) */
.combination {
  display: inline-block;
  font-family: Georgia, serif;
  font-style: italic;
  position: relative;
  vertical-align: middle;
}

.combination sub,
.combination sup {
  font-size: 0.7em;
  display: inline-block;
}

.exercise-content sub,
.solution-content sub,
.exercise-content sup,
.solution-content sup {
  font-size: 0.75em;
  vertical-align: baseline;
  position: relative;
  top: -0.4em;
}

.exercise-content sub,
.solution-content sub {
  top: 0.4em;
}

/* Legacy table styles */
.exercise-content table {
  width: 100%;
  border-collapse: collapse;
  margin: 20px 0;
  font-family: Georgia, 'Times New Roman', serif;
  font-size: 1rem;
}

.exercise-content th,
.exercise-content td {
  border: 1px solid var(--border);
  padding: 12px 16px;
  text-align: center;
}

.exercise-content th {
  background: #f8fafc;
  font-weight: 600;
  color: var(--text);
}

.exercise-content td {
  background: #ffffff;
}

.exercise-content tr:nth-child(even) td {
  background: #fafbfc;
}

/* Math notation styling */
.exercise-content sup,
.solution-content sup {
  font-size: 0.75em;
  vertical-align: super;
  line-height: 0;
}

.exercise-content sub,
.solution-content sub {
  font-size: 0.75em;
  vertical-align: sub;
  line-height: 0;
}

/* Fraction display */
.fraction {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  vertical-align: middle;
  font-size: 0.9em;
  margin: 0 4px;
}

.fraction .numerator {
  border-bottom: 1px solid var(--text);
  padding: 0 4px;
}

.fraction .denominator {
  padding: 0 4px;
}

/* Greek letters and math symbols */
.math-symbol {
  font-family: 'Times New Roman', Georgia, serif;
  font-style: italic;
}

/* Probability notation */
.prob-not {
  font-family: Georgia, serif;
  letter-spacing: 0.5px;
}

/* Exam Display Styles - Academic */
.exam-container {
  display: grid;
  gap: 32px;
}

.exam-section {
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 40px;
  background: #ffffff;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.04);
}

.exam-section-title {
  font-size: 1.25rem;
  font-weight: 700;
  margin-bottom: 24px;
  color: var(--text);
  padding-bottom: 16px;
  border-bottom: 3px solid var(--primary);
  font-family: Inter, Arial, sans-serif;
}

.exam-content {
  font-family: 'Georgia', 'Times New Roman', serif;
  line-height: 1.9;
  font-size: 0.98rem;
  color: #334155;
}

.exam-content table {
  width: 100%;
  border-collapse: collapse;
  margin: 20px 0;
  font-family: Inter, Arial, sans-serif;
  font-size: 0.9rem;
}

.exam-content th,
.exam-content td {
  border: 1px solid var(--border);
  padding: 10px 12px;
  text-align: center;
}

.exam-content th {
  background: var(--primary-soft);
  color: var(--primary-dark);
  font-weight: 600;
}

.exam-content tr:nth-child(even) {
  background: #f8fafc;
}

.exam-content sub,
.exam-content sup {
  font-size: 0.75em;
  vertical-align: baseline;
  position: relative;
  top: -0.4em;
}

.exam-content sub {
  top: 0.4em;
}

/* Math tables in exam content */
.exam-content-doc .math-table {
  width: 100%;
  border-collapse: collapse;
  margin: 0 0 16px 0 !important;
  font-family: Georgia, 'Times New Roman', serif;
  font-size: 0.95rem;
  background: #ffffff;
  border: 1px solid var(--border);
  border-radius: 6px;
  overflow: hidden;
}

.exam-content-doc .math-table th,
.exam-content-doc .math-table td {
  border: 1px solid var(--border);
  padding: 10px 14px;
  text-align: center;
}

.exam-content-doc .math-table th {
  background: #f0fdf4;
  font-weight: 600;
  color: var(--text);
}

.exam-content-doc .math-table tr:nth-child(even) td {
  background: #fafbfc;
}

/* Exam Selector Tabs */
.exam-selector {
  display: flex;
  gap: 12px;
  margin-bottom: 24px;
  flex-wrap: wrap;
}

.exam-tab {
  padding: 12px 20px;
  border: 1px solid var(--border);
  background: #ffffff;
  border-radius: 8px;
  cursor: pointer;
  font-size: 0.9rem;
  font-weight: 500;
  transition: all 0.2s ease;
}

.exam-tab:hover {
  background: #f0fdf4;
  border-color: var(--primary);
}

.exam-tab.active {
  background: var(--primary);
  color: white;
  border-color: var(--primary);
}

/* Exam Document - Word-like Style */
.exam-document {
  display: flex;
  flex-direction: column;
  gap: 32px;
}

.exam-paper,
.correction-paper {
  background: #ffffff;
  border: 1px solid var(--border);
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
  overflow: hidden;
}

.correction-paper {
  border-top: 4px solid var(--accent);
}

.exam-header-doc {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 20px 28px;
  background: #f8fafc;
  border-bottom: 1px solid var(--border);
}

.correction-header {
  background: #fdf0d5;
}

.exam-title-doc {
  font-size: 1.25rem;
  font-weight: 700;
  color: var(--text);
  margin: 0;
}

.exam-badge {
  display: inline-block;
  padding: 6px 16px;
  background: var(--primary);
  color: white;
  font-size: 0.75rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  border-radius: 4px;
}

.correction-badge {
  background: var(--accent);
  color: #78350f;
}

.exam-content-doc {
  padding: 32px;
  font-family: Georgia, 'Times New Roman', serif;
  font-size: 1rem;
  line-height: 1.9;
  color: #334155;
}

.correction-section {
  border-top: 4px solid var(--accent);
  background: #ffffff;
}

.correction-section .exam-section-title {
  border-bottom-color: var(--accent);
}

/* Summary Tree Styles */
.summary-tree {
  display: grid;
  gap: 16px;
}

/* ── Résumé statistiques : hiérarchie des titres ─────────────── */
.summary-content {
  color: var(--text);
  line-height: 1.6;
}

.summary-content .md-h {
  font-family: var(--font-heading);
  color: var(--text);
  line-height: 1.25;
}

/* Titre principal du résumé */
.summary-content .md-h2 {
  font-size: 1.5rem;
  font-weight: 700;
  margin: 4px 0 20px;
  padding-bottom: 12px;
  border-bottom: 2px solid var(--primary);
}

/* Sections numérotées (1., 2., …) */
.summary-content .md-h3 {
  font-size: 1.2rem;
  font-weight: 700;
  color: var(--primary);
  margin: 28px 0 10px;
  padding: 8px 14px;
  background: var(--primary-soft);
  border-radius: var(--radius-md);
}

/* Sous-titres */
.summary-content .md-h4 {
  font-size: 1.02rem;
  font-weight: 700;
  margin: 20px 0 8px;
  padding-left: 12px;
  border-left: 3px solid var(--primary);
}

.summary-content .md-h5 {
  font-size: 0.95rem;
  font-weight: 700;
  color: var(--muted);
  margin: 16px 0 6px;
}

.summary-content p {
  margin: 8px 0;
}

.summary-content ul,
.summary-content li {
  line-height: 1.65;
}

.summary-content .math-table {
  margin: 12px 0 20px;
}

/* Résumé Maths S1 = aide-mémoire compact : un seul document, 8 chapitres à la
   suite, tableaux et espacements resserrés (à parcourir/imprimer). */
.maths-resume-intro {
  margin: 0 0 18px;
  color: var(--muted);
  font-size: 0.92rem;
}
.maths-resume-sheet .maths-resume-chapter {
  padding: 18px 0;
  border-top: 1px solid var(--border);
}
.maths-resume-sheet .maths-resume-chapter:first-of-type {
  border-top: 0;
  padding-top: 0;
}
.maths-resume-sheet .maths-resume-chapter h2 {
  font-size: 1.06rem;
  color: var(--primary-dark);
  margin: 0 0 10px;
}
.maths-resume-sheet .math-table {
  margin: 12px 0;
  font-size: 0.92rem;
}
.maths-resume-sheet .math-table th,
.maths-resume-sheet .math-table td {
  padding: 7px 12px;
}

/* Un tableau plus large que la place disponible doit DÉFILER DANS SON CADRE,
   jamais pousser la page — même principe que `.bc-cours-table` pour les
   tableaux du cours.

   Le cas qui l'a imposé : les deux chaînes d'ordre énergétique des orbitales
   moléculaires, au chapitre 6 du résumé de Chimie. Ce sont des formules KaTeX
   INSÉCABLES de ~375 px ; dans une cellule, elles poussaient la page 210 px
   hors cadre dès que la colonne de contenu descendait sous ~400 px.

   PAS de media query ici, et c'est délibéré : la largeur utile ne dépend pas de
   celle de la FENÊTRE mais de la colonne de contenu, que le menu latéral
   rétrécit. Une règle conditionnée à la fenêtre laisserait passer le
   débordement sur un écran large au menu déplié. `min-width: 0` empêche les
   conteneurs de grille de se dilater à la largeur min-content du tableau.

   Le défilement et le centrage eux-mêmes (20 septembre 2026) ne sont plus une
   règle à part ici : chaque résumé enveloppe désormais ses tableaux dans
   `.bc-cours-table` (`enrouleTableauxCours()`, comme le cours et les corpus),
   qui porte `display: flex; justify-content: center; overflow-x: auto` — une
   seule règle pour toute la plateforme, au lieu d'une copie par contexte. */
.maths-resume-sheet .maths-resume-chapter,
.maths-resume-sheet .maths-resume-content { min-width: 0; }

.tree-node {
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 16px;
  background: var(--surface);
  position: relative;
}

.tree-node.main {
  background: var(--primary-soft);
  border-color: var(--primary);
}

.tree-children {
  display: grid;
  gap: 12px;
  margin-left: 24px;
  margin-top: 12px;
  padding-left: 16px;
  border-left: 2px solid var(--border);
}

.tree-node-title {
  font-weight: 700;
  color: var(--text);
  display: flex;
  align-items: center;
  gap: 8px;
}

.tree-node-content {
  margin-top: 8px;
  color: var(--muted);
  font-size: 0.95rem;
}

.tree-icon {
  font-size: 1.2rem;
}

@media (max-width: 1020px) {
  .exercise-split-view {
    grid-template-columns: 1fr;
  }
}

/* ── Maths S1 Module ──────────────────────────────────────────── */

.maths-chapters {
  display: flex;
  flex-direction: column;
  gap: 20px;
  margin-top: 20px;
}

.maths-chapter-card {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 24px 28px;
}

.maths-chapter-card h3 {
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--primary-dark);
  margin-bottom: 14px;
  padding-bottom: 10px;
  border-bottom: 2px solid var(--primary-soft);
}

.maths-chapter-content {
  font-size: 0.95rem;
  color: var(--text);
  line-height: 1.75;
}

.maths-chapter-content table {
  width: 100%;
  border-collapse: collapse;
  margin: 12px 0;
  font-size: 0.9rem;
}

.maths-chapter-content table th,
.maths-chapter-content table td {
  border: 1px solid var(--border);
  padding: 8px 12px;
  text-align: left;
}

.maths-chapter-content table th {
  background: var(--primary-soft);
  font-weight: 600;
  color: var(--primary-dark);
}

.series-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 16px;
  margin-top: 20px;
}

.series-card {
  background: var(--surface);
  border: 2px solid var(--border);
  border-radius: 14px;
  padding: 20px;
  cursor: pointer;
  display: flex;
  flex-direction: column;
  gap: 6px;
  text-align: left;
  transition: border-color 0.2s, box-shadow 0.2s, transform 0.15s;
}

.series-card:hover {
  border-color: var(--primary);
  box-shadow: var(--shadow);
  transform: translateY(-2px);
}

.series-num {
  font-size: 1rem;
  font-weight: 700;
  color: var(--primary-dark);
}

.series-subtitle {
  font-size: 0.9rem;
  font-weight: 500;
  color: var(--text);
}

.series-meta {
  font-size: 0.8rem;
  color: var(--muted);
  margin-top: 4px;
}

.exam-card {
  border-color: var(--accent);
}

.exam-card:hover {
  border-color: var(--accent);
  box-shadow: var(--shadow);
}

.maths-chapitres-tag {
  font-size: 0.85rem;
  color: var(--muted);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 8px 14px;
  margin-bottom: 20px;
  display: inline-block;
}

.maths-exercises {
  display: flex;
  flex-direction: column;
  gap: 24px;
  margin-top: 20px;
}

.maths-exercise {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 24px;
  box-shadow: 0 2px 8px rgba(0,0,0,0.04);
}

.maths-exercise-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 14px;
}

.exercise-num {
  font-size: 0.9rem;
  font-weight: 700;
  color: var(--primary-dark);
  background: var(--primary-soft);
  border-radius: 8px;
  padding: 4px 12px;
}

/* Biologie cellulaire — intitulé de partie au-dessus du premier bloc */
.bc-part-heading {
  font-family: var(--font-heading);
  font-size: 1.05rem;
  color: var(--primary-dark);
  margin: 12px 0 -4px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--border);
}

.bc-part-heading:first-child {
  margin-top: 0;
}

/* Les figures des examens de biologie cellulaire sont des schémas à légender :
   le flottant 320px de `.md-img` les rend illisibles. Pleine largeur, centrées. */
.bc-statement .md-img {
  float: none;
  display: block;
  max-width: 100%;
  margin: 16px auto;
}

/* Tableaux à compléter : les cellules vides sont l'espace de réponse, elles
   doivent rester visibles et alignées au lieu de s'écraser. */
.bc-statement .math-table td:empty,
.bc-statement .math-table th:empty {
  height: 2.4rem;
}

/* Hiérarchie visuelle des corrigés de biologie cellulaire.
   Sans ces trois niveaux, la réponse, son explication et les réserves de
   relecture se lisaient au même plan — tout en gras ou en italique. */

/* La réponse elle-même : repérable d'un coup d'œil, sans lire le paragraphe. */
.maths-solution .bc-answer,
.qcm-correction .bc-answer,
.qcm-explication .bc-answer {
  margin: 14px 0;
  padding: 12px 16px;
  background: var(--primary-soft);
  border-left: 3px solid var(--primary);
  border-radius: var(--radius-md, 8px);
  font-size: 0.96rem;
  line-height: 1.6;
  color: var(--text);
}

/* Une formule d'affichage trop large défile DANS SON PROPRE CADRE, elle ne
   pousse jamais la page. Sans cette règle, les chaînes de pivot de Gauss des
   séries de maths (matrice augmentée → flèche → matrice augmentée, ~630 px de
   large) débordaient sur mobile : 11 blocs sur 57 mesurés à 340 px de large.
   Même principe que `.bc-cours-table` pour les tableaux du cours.
   `padding-bottom` réserve la place de la barre de défilement, sans quoi elle
   recouvre le bas des fractions. */
.maths-solution .katex-display,
.maths-exercise-statement .katex-display,
.qcm-correction .katex-display,
.qcm-preamble .katex-display,
.qcm-explication .katex-display,
.physics-solution .katex-display,
.physics-statement .katex-display {
  overflow-x: auto;
  overflow-y: hidden;
  padding-bottom: 4px;
}
/* `.qcm-preamble` et `.qcm-explication` ont été ajoutés le 27 août 2026 : la
   règle ne couvrait que le corrigé détaillé d'un QCM (`.qcm-correction`), pas
   les deux autres endroits où un bloc `qcm[]` accueille du display math —
   l'énoncé commun placé en tête d'exercice et l'explication par question. Sur
   le sujet de Maths S1 en QCM, 11 blocs sur 53 débordaient de leur cadre à
   375 px (systèmes en `cases`, produits matrice × colonne). Même défaut, même
   cause et même remède que pour `.maths-solution` ci-dessus ; la règle vaut
   pour tout module au moteur `qcm[]` partagé. */

/* L'aparté explicatif : « pourquoi cette réponse », « le piège ». */
.maths-solution .bc-aside,
.qcm-correction .bc-aside,
.qcm-explication .bc-aside {
  margin: 12px 0;
  padding: 10px 14px;
  background: #fbfdfc;
  border: 1px solid var(--border);
  border-radius: var(--radius-md, 8px);
  font-size: 0.9rem;
  line-height: 1.55;
  color: var(--muted);
}

/* Réserve de relecture : doit sauter aux yeux du propriétaire, discrètement
   pour l'étudiant. Repérable au balayage, pas alarmant. */
.maths-solution .bc-todo,
.qcm-correction .bc-todo {
  margin: 12px 0;
  padding: 10px 14px;
  background: #fdf8ec;
  border-left: 3px solid #c9922f;
  border-radius: var(--radius-md, 8px);
  font-size: 0.86rem;
  line-height: 1.5;
  color: #7a5a18;
}

.bc-solution-pending {
  margin: 14px 0 0;
  font-size: 0.9rem;
  color: var(--muted);
  font-style: italic;
}

/* Provenance d'UN corrigé, quand elle varie d'un exercice à l'autre du même
   document (moteur de corpus partagé, champ `origine`). Discret et en tête du
   corrigé : l'étudiant doit savoir s'il lit la parole de l'enseignant ou un
   corrigé rédigé pour BioPrep, sans que la mention prenne le pas sur le fond. */
.corpus-origine {
  margin: 0 0 12px;
  font-size: 0.82rem;
  color: var(--muted);
  font-style: italic;
  letter-spacing: 0.01em;
}

.exercise-points {
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--accent);
  background: #e8f0fe;
  border-radius: 8px;
  padding: 4px 12px;
}

.maths-exercise-statement {
  font-size: 0.95rem;
  line-height: 1.75;
  color: var(--text);
  margin-bottom: 16px;
}

.solution-toggle {
  background: none;
  border: 2px solid var(--primary);
  color: var(--primary-dark);
  border-radius: 8px;
  padding: 8px 18px;
  font-size: 0.88rem;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.2s, color 0.2s;
}

.solution-toggle:hover {
  background: var(--primary-soft);
}

.maths-solution {
  margin-top: 16px;
  padding: 20px;
  background: var(--surface-2);
  border-left: 4px solid var(--primary);
  border-radius: 0 10px 10px 0;
  font-size: 0.93rem;
  line-height: 1.75;
  color: var(--text);
}

.maths-solution table {
  width: 100%;
  border-collapse: collapse;
  margin: 12px 0;
  font-size: 0.88rem;
}

.maths-solution table th,
.maths-solution table td {
  border: 1px solid var(--border);
  padding: 7px 10px;
  text-align: left;
}

.maths-solution table th {
  background: var(--primary-soft);
  font-weight: 600;
}

.btn-back {
  background: none;
  border: none;
  color: var(--primary-dark);
  font-size: 0.9rem;
  font-weight: 600;
  cursor: pointer;
  padding: 0;
  margin-bottom: 20px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.btn-back:hover {
  text-decoration: underline;
}

.exam-header-info {
  margin-bottom: 24px;
}

.exam-meta-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 10px;
}

.exam-tag {
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--accent);
  background: #e8f0fe;
  border-radius: 20px;
  padding: 4px 12px;
}

/* Navigation compacte du module physique : sous-module + partie + onglets */
.physics-nav {
  margin-bottom: 14px;
}

.physics-track-map {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 0 0 10px;
}

.physics-part-selector {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 0 0 14px;
}

.physics-nav-btn {
  padding: 8px 16px;
  border: 1.5px solid var(--border);
  border-radius: 999px;
  background: var(--surface);
  color: var(--text);
  font-family: var(--font-body);
  font-size: 0.9rem;
  font-weight: 600;
  cursor: pointer;
  transition: border-color 0.15s, background 0.15s, color 0.15s;
}

.physics-nav-btn:hover {
  border-color: var(--primary);
  background: var(--primary-soft);
}

.physics-nav-btn.active {
  border-color: var(--primary);
  background: var(--primary);
  color: #fff;
}

.physics-nav-btn.subtle {
  padding: 6px 14px;
  font-weight: 500;
  font-size: 0.86rem;
}

.physics-nav-btn.subtle.active {
  background: var(--primary-soft);
  color: var(--primary-dark);
  border-color: var(--primary);
}

.physics-course,
.physics-resume {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 16px;
  padding: 24px;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.035);
}

.physics-course h2,
.physics-resume h2 {
  color: var(--primary-dark);
  margin-top: 0;
}

.physics-course-content,
.physics-resume-content,
.maths-course-content {
  line-height: 1.8;
  color: var(--text);
}

/* ── Cours en chapitres : sommaire cliquable + accordéon ── */
.course-reader-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
}

.course-reader-count {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--primary-dark);
  background: var(--primary-soft);
  border-radius: 999px;
  padding: 4px 12px;
  white-space: nowrap;
}

.course-intro {
  padding-bottom: 18px;
  margin-bottom: 22px;
  border-bottom: 1px solid var(--border);
}

.course-reader-grid {
  display: grid;
  grid-template-columns: 210px minmax(0, 1fr);
  gap: 22px;
  align-items: start;
}

/* Sommaire latéral collant — compact et sobre */
.course-toc {
  position: sticky;
  top: 84px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 12px 12px;
}

.course-toc-title {
  margin: 0 0 8px;
  font-family: var(--font-heading);
  font-size: 0.72rem;
  font-weight: 700;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

.course-toc-list {
  list-style: none;
  margin: 0;
  padding: 0;
  counter-reset: none;
  max-height: min(56vh, 440px);
  overflow-y: auto;
}

.course-toc-list li { margin: 0; }

.course-toc-link {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  width: 100%;
  text-align: left;
  background: transparent;
  border: none;
  border-radius: var(--radius-sm);
  padding: 4px 8px;
  cursor: pointer;
  color: var(--text);
  font-size: 0.8rem;
  line-height: 1.3;
  transition: background 0.15s ease, color 0.15s ease;
}

.course-toc-link:hover,
.course-toc-link:focus-visible {
  background: var(--primary-soft);
  color: var(--primary-dark);
  outline: none;
}

.course-toc-num {
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  font-size: 0.7rem;
  color: var(--primary);
  padding-top: 1px;
}

.course-toc-actions {
  display: flex;
  gap: 6px;
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid var(--border);
}

.course-toc-btn {
  flex: 1;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 5px 6px;
  font-size: 0.72rem;
  font-weight: 600;
  color: var(--muted);
  cursor: pointer;
  transition: border-color 0.15s ease, color 0.15s ease;
}

.course-toc-btn:hover {
  border-color: var(--primary);
  color: var(--primary-dark);
}

/* Chapitres en accordéon */
.course-chapters {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.course-chapter {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  overflow: hidden;
  scroll-margin-top: 80px;
}

.course-chapter.open {
  border-color: var(--primary);
  box-shadow: var(--shadow-sm);
}

.course-chapter-head {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  text-align: left;
  background: transparent;
  border: none;
  padding: 14px 16px;
  cursor: pointer;
  color: var(--text);
}

.course-chapter-head:hover { background: var(--surface-2); }

.course-chapter-num {
  flex: none;
  width: 30px;
  height: 30px;
  display: grid;
  place-items: center;
  border-radius: 8px;
  background: var(--primary-soft);
  color: var(--primary-dark);
  font-weight: 700;
  font-size: 0.82rem;
  font-variant-numeric: tabular-nums;
}

.course-chapter.open .course-chapter-num {
  background: var(--primary);
  color: #fff;
}

.course-chapter-title {
  flex: 1;
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 1.02rem;
  color: var(--primary-dark);
  line-height: 1.3;
}

.course-chapter-caret {
  flex: none;
  display: inline-flex;
  color: var(--muted);
  transition: transform 0.2s ease;
}

.course-chapter.open .course-chapter-caret {
  transform: rotate(180deg);
  color: var(--primary);
}

.course-chapter-body {
  max-height: 0;
  overflow: hidden;
  padding: 0 18px;
  transition: max-height 0.3s ease, padding 0.3s ease;
}

.course-chapter.open .course-chapter-body {
  max-height: none;
  padding: 4px 18px 18px;
  border-top: 1px solid var(--border);
}

.course-chapter-foot {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  margin-top: 22px;
  padding-top: 14px;
  border-top: 1px dashed var(--border);
}

.course-nav-btn {
  display: flex;
  flex-direction: column;
  gap: 2px;
  max-width: 48%;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 8px 12px;
  cursor: pointer;
  transition: border-color 0.15s ease, background 0.15s ease;
}

.course-nav-btn:hover {
  border-color: var(--primary);
  background: var(--primary-soft);
}

.course-nav-btn.next { text-align: right; margin-left: auto; }

.course-nav-btn span {
  font-size: 0.76rem;
  font-weight: 700;
  color: var(--primary);
}

.course-nav-btn em {
  font-style: normal;
  font-size: 0.82rem;
  color: var(--muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

@media (max-width: 860px) {
  .course-reader-grid { grid-template-columns: 1fr; }
  .course-toc { position: static; top: auto; }
}

@media (prefers-reduced-motion: reduce) {
  .course-chapter-body,
  .course-chapter-caret { transition: none; }
}

.physics-exercise-card .exercise-num {
  max-width: 100%;
  white-space: normal;
}

.module-placeholder {
  min-height: 360px;
  display: grid;
  place-items: center;
  padding: 36px;
}

.placeholder-content {
  width: min(720px, 100%);
  background: #ffffff;
  border: 1px solid var(--border);
  border-radius: 24px;
  padding: 36px;
  box-shadow: var(--shadow);
  text-align: center;
}

.placeholder-icon {
  width: 72px;
  height: 72px;
  margin: 0 auto 18px;
  border-radius: 24px;
  display: grid;
  place-items: center;
  background: var(--primary-soft);
  color: var(--primary-dark);
  font-size: 2rem;
}

.placeholder-content h3 {
  margin: 0 0 10px;
  font-size: 1.45rem;
  color: var(--primary-dark);
}

.placeholder-content p {
  color: var(--muted);
  line-height: 1.7;
}

.placeholder-features {
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 20px;
}

.placeholder-features span {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 8px 14px;
  color: var(--text);
  font-weight: 700;
  font-size: 0.86rem;
}

.institution-page {
  display: grid;
  gap: 22px;
}

.institutional-hero,
.institutional-quote,
.academic-start {
  border-color: rgba(30, 107, 71, 0.2);
}

.institution-cards .card,
.terms-grid article,
.contact-highlight {
  position: relative;
  overflow: hidden;
}

.card-kicker,
.terms-grid span {
  display: inline-flex;
  margin-bottom: 10px;
  border-radius: 999px;
  padding: 6px 10px;
  background: var(--primary-soft);
  color: var(--primary-dark);
  font-size: 0.78rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

.contact-grid .contact-highlight {
  min-height: 190px;
  background: #ffffff;
}

.terms-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 16px;
}

.terms-grid article {
  border: 1px solid var(--border);
  border-radius: 16px;
  padding: 22px;
  background: var(--surface);
  box-shadow: var(--shadow);
}

.terms-grid h3 {
  margin: 0 0 10px;
  color: var(--text);
}

.terms-grid p {
  margin: 0;
  color: var(--muted);
  line-height: 1.7;
}

/* ── Pages institutionnelles (À propos, Règlement) : composants enrichis ── */
.institution-heading {
  margin: 14px 0 -6px;
  /* Titres de section des pages À propos / CGU : ils étaient à la taille
     exacte des h3 qu ils surplombent, donc indiscernables d eux. */
  font-size: 1.5rem;
  color: var(--primary-dark);
}

/* Pastille d'icône ronde (badge de section/carte) */
.page-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: 12px;
  margin-bottom: 12px;
  background: var(--primary);
  color: #fff;
}
.page-icon.soft {
  background: var(--primary-soft);
  color: var(--primary-dark);
}

.value-card {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}
.value-card h3 { margin: 6px 0 8px; }
.value-card p { margin: 0; color: var(--muted); line-height: 1.7; }

/* « Ce que vous trouverez » : lignes icône + texte */
.about-features .feature-row {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 16px;
  align-items: start;
  padding: 18px 20px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 16px;
  box-shadow: var(--shadow-sm);
}
.about-features .feature-row .page-icon { margin-bottom: 0; }
.about-features .feature-row h3 { margin: 2px 0 6px; font-size: 1.05rem; }
.about-features .feature-row p { margin: 0; color: var(--muted); line-height: 1.65; }

/* Règlement : engagements réciproques (2 colonnes) */
.reciprocal-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 18px;
}
.reciprocal-col {
  padding: 24px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 18px;
  box-shadow: var(--shadow);
}
.check-list {
  list-style: none;
  margin: 14px 0 0;
  padding: 0;
  display: grid;
  gap: 12px;
}
.check-list li {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 10px;
  align-items: start;
  color: var(--text);
  line-height: 1.6;
}
.check-list li svg {
  color: var(--primary);
  margin-top: 3px;
  flex-shrink: 0;
}

/* ===================== Page de paiement premium ===================== */
.checkout-page {
  max-width: 1180px;
  margin: 0 auto;
}

.checkout-hero {
  text-align: center;
  padding: 8px 0 4px;
}

.checkout-hero h1 {
  margin: 6px auto 10px;
  max-width: 760px;
}

.checkout-hero .lead {
  margin: 0 auto;
  max-width: 560px;
}

.trust-badges {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 12px;
  margin-top: 22px;
}

.trust-badge {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 9px 16px;
  background: var(--surface);
  font-weight: 700;
  font-size: 0.88rem;
  color: var(--text);
  box-shadow: 0 4px 14px rgba(20, 60, 10, 0.05);
}

.tb-icon {
  display: inline-flex;
  color: var(--primary);
}

.pricing-section {
  margin-top: 40px;
}

.pricing-grid {
  display: grid;
  grid-template-columns: 1fr 1.1fr;
  gap: 20px;
  align-items: stretch;
  max-width: 760px;
  margin: 0 auto;
}

.pricing-card {
  position: relative;
  display: flex;
  flex-direction: column;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 28px 24px;
  background: var(--surface);
  box-shadow: var(--shadow-sm);
}

.pricing-featured {
  border: 2px solid var(--primary);
  box-shadow: var(--shadow);
}

.pricing-ribbon {
  position: absolute;
  top: 16px;
  right: 16px;
  border-radius: var(--radius-sm);
  padding: 5px 12px;
  background: var(--primary-soft);
  color: var(--primary-dark);
  font-size: 0.74rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

.featured-ribbon {
  top: -13px;
  right: 50%;
  transform: translateX(50%);
  background: var(--primary);
  color: #fff;
}

.pricing-head h3 {
  margin: 0;
  font-size: 1.25rem;
  color: var(--primary-dark);
}

.pricing-featured .pricing-head h3 {
  margin-top: 8px;
}

.best-value-tag {
  display: inline-block;
  margin-top: 8px;
  border-radius: 999px;
  padding: 3px 10px;
  background: var(--primary-soft);
  color: var(--primary-dark);
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.pricing-tagline {
  margin: 8px 0 0;
  color: var(--muted);
  font-size: 0.9rem;
  line-height: 1.5;
}

.pricing-price {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 6px;
  margin: 20px 0 4px;
}

.price-old {
  color: var(--muted);
  text-decoration: line-through;
  font-weight: 700;
  font-size: 0.95rem;
  order: -1;
  width: 100%;
}

.price-from {
  order: -1;
  width: 100%;
  color: var(--muted);
  font-weight: 700;
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.pricing-breakdown {
  margin: 14px 0 0;
  text-align: center;
  font-size: 0.78rem;
  color: var(--muted);
  line-height: 1.5;
}

.price-amount {
  font-size: 2.8rem;
  font-weight: 700;
  line-height: 1;
  color: var(--text);
}

.pricing-featured .price-amount {
  color: var(--primary-dark);
}

.price-currency {
  font-size: 1.1rem;
  font-weight: 700;
  color: var(--muted);
}

.price-context {
  margin: 0 0 18px;
  color: var(--muted);
  font-size: 0.85rem;
}

.pricing-benefits {
  list-style: none;
  padding: 0;
  margin: 0 0 22px;
  display: grid;
  gap: 11px;
  flex: 1;
}

.pricing-benefits li {
  position: relative;
  padding-left: 28px;
  color: var(--text);
  font-size: 0.92rem;
  line-height: 1.5;
}

.pricing-benefits li::before {
  content: "✓";
  position: absolute;
  left: 0;
  top: 0;
  display: grid;
  place-items: center;
  width: 19px;
  height: 19px;
  border-radius: 999px;
  background: var(--primary-soft);
  color: var(--primary-dark);
  font-size: 0.72rem;
  font-weight: 700;
}

.pricing-cta {
  width: 100%;
  justify-content: center;
  text-align: center;
  padding: 13px 18px;
  font-size: 0.98rem;
}

.btn.ghost {
  border: 1px solid var(--border);
  background: transparent;
  color: var(--primary-dark);
}

.btn.ghost:hover {
  background: var(--primary-soft);
}

.cta-featured {
  font-size: 1.05rem;
  padding: 15px 18px;
  box-shadow: var(--shadow);
}

.pricing-compare,
.pricing-saving {
  margin: 13px 0 0;
  text-align: center;
  font-size: 0.82rem;
}

.pricing-compare {
  color: var(--muted);
}

.pricing-saving {
  color: var(--primary-dark);
  font-weight: 700;
}

.semester-price-intro {
  margin: 0 0 10px;
  font-size: 0.9rem;
  font-weight: 700;
  color: var(--muted);
}

.semester-price-list {
  list-style: none;
  margin: 0 0 16px;
  padding: 0;
  display: grid;
  gap: 8px;
}

.sem-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 14px;
  border: 1px solid var(--border);
  border-radius: 12px;
  background: #fbfefb;
  transition: border-color 0.18s ease, background 0.18s ease;
}

.sem-row:hover {
  border-color: var(--primary);
  background: var(--primary-soft);
}

.sem-label {
  display: grid;
  gap: 1px;
  color: var(--text);
  font-weight: 700;
  font-size: 0.9rem;
}

.sem-label em {
  font-style: normal;
  font-weight: 700;
  color: var(--muted);
  font-size: 0.74rem;
}

.sem-prices {
  display: flex;
  align-items: baseline;
  gap: 8px;
  white-space: nowrap;
}

.sem-prices s {
  color: var(--muted);
  font-size: 0.82rem;
}

.sem-prices strong {
  color: var(--primary-dark);
  font-size: 1.1rem;
  font-weight: 700;
}

.anchor-strip {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 14px;
  margin-top: 30px;
  padding: 18px;
  border: 1px dashed var(--border);
  border-radius: 16px;
  background: #fbfefb;
}

.anchor-item {
  display: grid;
  justify-items: center;
  gap: 2px;
  text-align: center;
}

.anchor-item span {
  color: var(--muted);
  font-size: 0.8rem;
  font-weight: 700;
}

.anchor-item strong {
  font-size: 1.1rem;
  color: var(--text);
}

.anchor-item strong.strike {
  text-decoration: line-through;
  color: var(--muted);
}

.anchor-item em {
  font-style: normal;
  font-size: 0.74rem;
  font-weight: 700;
  color: var(--primary-dark);
}

.anchor-item.highlight strong,
.anchor-item.best strong {
  color: var(--primary-dark);
}

.anchor-item.best {
  background: var(--primary-soft);
  border-radius: 12px;
  padding: 8px 14px;
}

.anchor-arrow {
  color: var(--muted);
  font-weight: 700;
}

.friction-row {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 10px 24px;
  margin-top: 24px;
}

.friction-row span {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--primary-dark);
  font-weight: 600;
  font-size: 0.9rem;
}

.trust-section {
  margin-top: 56px;
  text-align: center;
}

.trust-section h2 {
  margin-bottom: 26px;
}

/* Quatre rubriques, quatre colonnes : jamais de carte orpheline sur une
   seconde ligne (auto-fit n'en plaçait que trois dans cette largeur). */
.trust-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 16px;
}

@media (max-width: 1180px) {
  .trust-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 620px) {
  .trust-grid {
    grid-template-columns: 1fr;
  }
}

.trust-card {
  border: 1px solid var(--border);
  border-radius: 16px;
  padding: 22px 16px;
  background: var(--surface);
  transition: transform 0.18s ease, box-shadow 0.18s ease;
}

.trust-card:hover {
  transform: translateY(-4px);
  box-shadow: 0 16px 34px rgba(20, 60, 10, 0.1);
}

.trust-ico {
  display: inline-flex;
  color: var(--primary);
}

.trust-card h3 {
  margin: 12px 0 8px;
  font-size: 1.02rem;
  color: var(--primary-dark);
}

.trust-card p {
  margin: 0;
  color: var(--muted);
  font-size: 0.88rem;
  line-height: 1.6;
}

@media (max-width: 940px) {
  .pricing-grid {
    grid-template-columns: 1fr;
  }
  .featured-ribbon {
    top: 16px;
    right: 16px;
    transform: none;
  }
}

.maintenance-status-card {
  display: flex;
  align-items: center;
  gap: 18px;
  border-left: 5px solid var(--primary);
  background: #ffffff;
}

.maintenance-status-icon {
  display: grid;
  place-items: center;
  width: 64px;
  height: 64px;
  border-radius: 18px;
  background: var(--surface);
  font-size: 1.9rem;
  flex-shrink: 0;
  box-shadow: var(--shadow);
}

.maintenance-status-card h3 {
  margin: 0 0 6px;
  color: var(--primary-dark);
}

.maintenance-status-card p {
  margin: 0;
  color: var(--muted);
  line-height: 1.65;
}

.maintenance-section-title {
  margin-top: 0;
}

.maintenance-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 14px;
  margin-top: 16px;
}

.maintenance-item {
  display: flex;
  gap: 14px;
  align-items: flex-start;
  border: 1px solid var(--border);
  border-radius: 16px;
  padding: 18px;
  background: var(--surface);
  transition: transform 0.18s ease, box-shadow 0.18s ease;
}

.maintenance-item:hover {
  transform: translateY(-3px);
  box-shadow: var(--shadow);
}

.maintenance-item-num {
  display: inline-grid;
  place-items: center;
  width: 38px;
  height: 38px;
  border-radius: 12px;
  background: var(--primary-soft);
  color: var(--primary-dark);
  font-weight: 700;
  flex-shrink: 0;
}

.maintenance-item h3 {
  margin: 0 0 6px;
  font-size: 1.02rem;
  color: var(--text);
}

.maintenance-item p {
  margin: 0;
  color: var(--muted);
  line-height: 1.6;
  font-size: 0.9rem;
}

.admin-loading,
.admin-error,
.admin-empty {
  color: var(--muted);
  font-weight: 700;
}

.admin-error {
  color: var(--danger);
}

/* ── Tableau de bord (statistiques) ── */
.admin-stats-row {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 14px;
  margin-bottom: 18px;
}

.admin-stat {
  display: grid;
  gap: 4px;
  border: 1px solid var(--border);
  border-radius: 16px;
  padding: 16px 18px;
  background: var(--surface);
}

.admin-stat-value {
  font-size: 1.7rem;
  font-weight: 700;
  line-height: 1;
  color: var(--text);
}

.admin-stat-label {
  font-size: 0.78rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
}

.admin-stat.approved {
  border-color: rgba(30, 107, 71, 0.35);
  background: var(--primary-soft);
}
.admin-stat.approved .admin-stat-value { color: var(--primary-dark); }

.admin-stat.pending {
  border-color: #ffe2b8;
  background: #fff8ee;
}
.admin-stat.pending .admin-stat-value { color: var(--warning); }

.admin-stat.rejected {
  border-color: #ffd4d4;
  background: #fff1f1;
}
.admin-stat.rejected .admin-stat-value { color: var(--danger); }

/* ── Grille de cartes étudiants ── */
.admin-user-list {
  display: grid;
  gap: 8px;
  max-height: 640px;
  overflow-y: auto;
  padding-right: 4px;
}

.admin-user-item {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 12px 14px;
  background: var(--surface);
  text-align: left;
  transition: border-color 0.18s ease, background 0.18s ease, transform 0.18s ease;
}

.admin-user-item:hover {
  border-color: var(--primary);
  transform: translateY(-1px);
}

.admin-user-item.active {
  border-color: var(--primary);
  background: var(--primary-soft);
  box-shadow: var(--shadow);
}

.admin-avatar {
  display: inline-grid;
  place-items: center;
  width: 42px;
  height: 42px;
  border-radius: 12px;
  background: var(--surface-2);
  color: var(--primary-dark);
  font-weight: 700;
  font-size: 0.92rem;
  flex-shrink: 0;
}

.admin-avatar.large {
  width: 58px;
  height: 58px;
  font-size: 1.2rem;
}

.admin-avatar.approved {
  background: var(--primary-soft);
  color: var(--primary-dark);
}

.admin-avatar.rejected {
  background: #ffecec;
  color: var(--danger);
}

.admin-user-meta {
  display: grid;
  gap: 2px;
  flex: 1;
  min-width: 0;
}

.admin-user-meta strong {
  color: var(--text);
  font-size: 0.94rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.admin-user-meta span {
  color: var(--muted);
  font-size: 0.82rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.status-dot {
  width: 11px;
  height: 11px;
  border-radius: 999px;
  background: var(--warning);
  flex-shrink: 0;
}

.status-dot.approved {
  background: var(--primary);
}

.status-dot.rejected {
  background: var(--danger);
}

.admin-detail {
  border: 1px solid var(--border);
  border-radius: 18px;
  background: var(--surface);
  padding: 22px;
  min-height: 420px;
}

.admin-detail-empty {
  display: grid;
  place-items: center;
  min-height: 360px;
  text-align: center;
  color: var(--muted);
}

.admin-full-toggle {
  display: flex;
  align-items: center;
  gap: 12px;
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 14px 16px;
  background: #fbfefc;
  cursor: pointer;
  margin-bottom: 18px;
}

.admin-full-toggle input {
  width: 20px;
  height: 20px;
  accent-color: var(--primary);
}

.admin-full-toggle span {
  display: grid;
  gap: 2px;
}

.admin-full-toggle small {
  color: var(--muted);
}

.admin-access-body h4 {
  margin: 0 0 12px;
  color: var(--primary-dark);
}

/* Menu des semestres et modules du panneau admin.
   Les cases heritaient du `input { width: 100% }` global : chacune s'etirait sur
   la moitie de sa carte, poussait son libelle contre le bord droit et le cassait
   sur deux ou trois lignes. Elles sont dimensionnees ici, et le libelle prend le
   reste de la ligne — colonne de cases alignee, une ligne par module. */
.admin-access-groups {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(232px, 1fr));
  align-items: start;
  gap: 12px;
}

.admin-access-groups input[type="checkbox"] {
  flex: 0 0 auto;
  width: 17px;
  height: 17px;
  margin: 0;
  padding: 0;
  border-radius: var(--radius-sm);
}

.admin-access-group {
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 12px 14px 13px;
  background: var(--surface);
}

.admin-group-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 10px;
  padding: 0 6px 9px;
  margin-bottom: 9px;
  border-bottom: 1px solid var(--border);
  color: var(--primary-dark);
  font-weight: 700;
  line-height: 1.3;
  cursor: pointer;
}

/* Base de 140px : un titre long (le parcours concours) garde une largeur
   lisible et renvoie la pastille << en preparation >> a la ligne suivante,
   au lieu d etre casse a un mot par ligne. */
.admin-group-head > span {
  flex: 1 1 140px;
  min-width: 0;
}

.admin-group-tag {
  flex: 0 0 auto;
  margin-left: auto;
  border-radius: 999px;
  padding: 2px 9px;
  background: #fff4e0;
  color: var(--warning);
  font-size: 0.72rem;
  font-style: normal;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.admin-group-empty {
  margin: 0;
  padding: 0 6px;
  color: var(--muted);
  font-size: 0.82rem;
  font-style: italic;
}

.admin-group-modules {
  display: grid;
  gap: 1px;
}

.admin-group-modules label {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 5px 6px;
  border-radius: var(--radius-sm);
  color: #334a3f;
  font-weight: 600;
  font-size: 0.86rem;
  line-height: 1.3;
  cursor: pointer;
}

.admin-group-modules label > span {
  flex: 1 1 auto;
  min-width: 0;
}

.admin-group-modules label:hover {
  background: var(--primary-soft);
}

.admin-row-editor input[type="checkbox"] {
  accent-color: var(--primary);
}

.admin-row-editor.full-mode .admin-access-groups {
  opacity: 0.45;
  pointer-events: none;
}

.admin-detail-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 20px;
}

/* Encaissement et journal — la trace d'une activation d'accès.
   Le virement se déclare hors plateforme ; ces champs notent ce qui a été reçu. */
.admin-paiement {
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 14px;
  background: var(--surface);
  display: grid;
  gap: 12px;
}

.admin-paiement-intro {
  margin: 0;
  color: var(--muted);
  font-size: 0.82rem;
  line-height: 1.5;
}

.admin-paiement-fields {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 10px;
}

.admin-paiement label,
.admin-paiement-note {
  display: grid;
  gap: 5px;
  color: #334a3f;
  font-weight: 700;
  font-size: 0.82rem;
}

.admin-paiement input,
.admin-paiement select {
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 9px 11px;
  background: #fff;
  font: inherit;
  font-weight: 400;
  color: var(--text);
}

.admin-paiement input:focus,
.admin-paiement select:focus {
  outline: 2px solid var(--primary);
  outline-offset: 1px;
}

.admin-journal {
  border-top: 1px dashed var(--border);
  padding-top: 12px;
}

.admin-journal-title {
  margin: 0 0 8px;
  font-size: 0.9rem;
  color: var(--primary-dark);
}

.admin-journal-empty {
  margin: 0;
  color: var(--muted);
  font-size: 0.82rem;
  font-style: italic;
}

.admin-journal-list {
  display: grid;
  gap: 8px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.admin-journal-list li {
  display: grid;
  gap: 2px;
  border-left: 3px solid var(--border);
  padding-left: 10px;
  font-size: 0.82rem;
}

.admin-journal-date {
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

.admin-journal-action {
  font-weight: 700;
  color: var(--primary-dark);
}

.admin-journal-delta {
  color: var(--text);
}

.admin-journal-meta {
  color: var(--muted);
  font-size: 0.78rem;
}

@media (max-width: 940px) {
  .admin-workspace {
    grid-template-columns: 1fr;
  }

  .admin-user-list {
    max-height: 320px;
  }

  .admin-stats-row {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 760px) {
  .admin-panel-header {
    display: grid;
  }
}

@media (max-width: 640px) {
  .series-grid {
    grid-template-columns: 1fr 1fr;
  }

  .placeholder-content {
    padding: 24px;
  }

  .admin-stats-row {
    grid-template-columns: 1fr;
  }
}



/* ── Accessibilité : focus clavier ── */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

.placeholder-icon svg {
  color: var(--primary);
}

/* Icône de chargement en rotation (écran « Chargement du module ») */
.placeholder-icon.loading svg {
  animation: bp-spin 0.9s linear infinite;
}

@keyframes bp-spin {
  to { transform: rotate(360deg); }
}

@media (prefers-reduced-motion: reduce) {
  .placeholder-icon.loading svg { animation: none; }
}

.placeholder-features span {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}


/* ── Bandeau de vérification email ──

   UN AVERTISSEMENT, PAS UNE ALARME. Ce bandeau était en ambre, sur
   `--warning`, avec la barre latérale des messages d'erreur — le registre
   qu'emploie le reste du site pour dire « quelque chose ne va pas ». Or il
   n'annonce aucun incident : la vérification ne conditionne aucun accès, et
   l'étudiant peut acheter, payer et lire sans y toucher. Habillé en alerte, il
   se lisait comme un barrage, et c'est ce qui a envoyé le premier étudiant
   testé fouiller ses spams au lieu de faire son virement.

   Le bleu `--accent` est celui des repères d'information du site. Il se
   distingue du vert `--primary`, qui signale un accès ouvert : on ne veut pas
   qu'un compte non vérifié se lise comme un compte activé. */
.verify-banner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 18px;
  flex-wrap: wrap;
  border: 1px solid #cfdcea;
  border-left: 4px solid var(--accent);
  border-radius: var(--radius-md);
  padding: 16px 20px;
  background: #f2f6fa;
}

/* `>` ET NON UN DESCENDANT QUELCONQUE. Le titre du bandeau est un `strong`
   enfant direct ; ceux qui mettent en valeur l'adresse et le mot « spams »
   vivent DANS les paragraphes. Sans cette borne, `display: block` les passait
   tous à la ligne : l'adresse partait seule sur sa ligne et la phrase reprenait
   par un point orphelin. */
.verify-banner-text > strong {
  display: block;
  color: #24486b;
}

.verify-banner-text p strong {
  color: #24486b;
}

.verify-banner-text p {
  margin: 4px 0 0;
  color: #3d5568;
  font-size: 0.9rem;
}

/* « Ce n'est pas obligatoire pour continuer » : la phrase qui désamorce tout le
   bandeau. En italique elle passait pour une incise secondaire — c'est le
   contraire, elle porte l'information principale. */
.verify-banner-text em {
  font-style: normal;
  font-weight: 600;
  color: #24486b;
}

/* La consigne « spams » se détache de l'explication qui la précède : c'est le
   geste concret à faire, il ne doit pas se fondre dans le paragraphe. */
.verify-banner-spam {
  margin-top: 8px !important;
}

.verify-banner .actions {
  margin: 0;
}

/* ── Bouton WhatsApp ── */
.btn.whatsapp-btn {
  background: #128c50;
}

.btn.whatsapp-btn:hover {
  background: #0d6e3f;
}

.btn.whatsapp-btn svg {
  flex: none;
}


/* ── Admin : liste dense en tableau ── */
.admin-table {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  overflow: hidden;
}

.admin-table-head,
.admin-row {
  display: grid;
  grid-template-columns: 36px minmax(0, 2.2fr) 150px 80px minmax(0, 1.3fr) 84px;
  gap: 10px;
  align-items: center;
  padding: 10px 16px;
}

.admin-row-num {
  font-variant-numeric: tabular-nums;
  color: var(--muted);
  font-weight: 600;
  font-size: 0.85rem;
  text-align: right;
}

.admin-table-head {
  border-bottom: 1px solid var(--border);
  background: var(--surface-2);
  color: var(--muted);
  font-size: 0.72rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.admin-row-wrap {
  border-bottom: 1px solid var(--border);
}

.admin-row-wrap:last-child {
  border-bottom: 0;
}

.admin-row-wrap.expanded {
  background: var(--primary-soft);
}

.admin-row-identity {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
}

.admin-row-identity > div {
  min-width: 0;
}

.admin-row-identity strong {
  display: block;
  font-size: 0.95rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.admin-row-email {
  display: flex;
  align-items: center;
  gap: 6px;
  color: var(--muted);
  font-size: 0.82rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.verified-tag,
.unverified-tag {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  flex: none;
  font-style: normal;
  font-size: 0.72rem;
  font-weight: 600;
  border-radius: 999px;
  padding: 1px 8px;
}

.verified-tag {
  color: var(--primary-dark);
  background: var(--primary-soft);
}

.unverified-tag {
  color: var(--warning);
  background: #fdf0d5;
}

.admin-row-date,
.admin-row-access {
  color: var(--muted);
  font-size: 0.84rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.admin-row-manage {
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 7px 12px;
  background: var(--surface);
  color: var(--primary-dark);
  font-weight: 600;
  font-size: 0.84rem;
}

.admin-row-manage:hover {
  border-color: var(--primary);
  background: var(--primary-soft);
}

.admin-row-editor {
  padding: 16px;
  border-top: 1px dashed var(--border);
  display: grid;
  gap: 14px;
}

.admin-row-editor.full-mode .admin-access-groups {
  opacity: 0.45;
  pointer-events: none;
}

@media (max-width: 940px) {
  .admin-table-head {
    display: none;
  }

  .admin-row {
    grid-template-columns: minmax(0, 1fr) auto;
    row-gap: 6px;
  }

  .admin-row-date,
  .admin-row-num {
    display: none;
  }
}

/* ============================================================
   QCM Physique — examens à choix multiples interactifs
   ============================================================ */
.qcm-exam {
  margin-top: 8px;
}

.qcm-hint {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0 0 20px;
  padding: 10px 14px;
  background: var(--primary-soft);
  border-radius: var(--radius-md);
  color: var(--primary-dark);
  font-size: 0.9rem;
}

.qcm-hint svg {
  flex: none;
}

.qcm-exercise {
  margin-bottom: 22px;
  padding: 20px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
}

.qcm-exercise-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 8px;
}

.qcm-exercise-head h3 {
  margin: 0;
  font-family: var(--font-heading);
  font-size: 1.15rem;
  color: var(--text);
}

.qcm-count {
  flex: none;
  font-size: 0.8rem;
  color: var(--muted);
}

.qcm-preamble {
  margin-bottom: 16px;
  padding-bottom: 14px;
  border-bottom: 1px dashed var(--border);
  font-size: 0.93rem;
  line-height: 1.7;
  color: var(--text);
}

.qcm-question {
  margin-top: 18px;
}

.qcm-prompt {
  margin-bottom: 10px;
  font-size: 0.96rem;
  font-weight: 600;
  line-height: 1.6;
  color: var(--text);
}

.qcm-qlabel {
  display: inline-block;
  margin-right: 4px;
  color: var(--primary);
  font-weight: 700;
}

.qcm-options {
  display: grid;
  gap: 8px;
}

.qcm-option {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 11px 14px;
  background: var(--surface);
  border: 1.5px solid var(--border);
  border-radius: var(--radius-md);
  font-family: var(--font-body);
  font-size: 0.92rem;
  color: var(--text);
  text-align: left;
  cursor: pointer;
  transition: border-color 0.15s, background 0.15s;
}

.qcm-option:hover {
  border-color: var(--primary);
  background: var(--primary-soft);
}

.qcm-letter {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  border: 1.5px solid var(--border);
  background: var(--surface-2);
  font-weight: 700;
  font-size: 0.82rem;
  color: var(--muted);
  transition: border-color 0.15s, background 0.15s, color 0.15s;
}

.qcm-optext {
  flex: 1;
}

.qcm-mark {
  flex: none;
  width: 18px;
  text-align: center;
  font-weight: 700;
}

/* État sélectionné (avant vérification) */
.qcm-option.selected {
  border-color: var(--primary);
  background: var(--primary-soft);
}

.qcm-option.selected .qcm-letter {
  border-color: var(--primary);
  background: var(--primary);
  color: #fff;
}

/* États après vérification */
.qcm-question.checked .qcm-option {
  cursor: default;
}

.qcm-question.checked .qcm-option:hover {
  border-color: var(--border);
  background: var(--surface);
}

.qcm-option.correct {
  border-color: var(--primary);
  background: var(--primary-soft);
}

.qcm-option.correct .qcm-letter {
  border-color: var(--primary);
  background: var(--primary);
  color: #fff;
}

.qcm-option.correct:hover {
  border-color: var(--primary) !important;
  background: var(--primary-soft) !important;
}

.qcm-option.correct .qcm-mark::after {
  content: '\2713';
  color: var(--primary);
}

.qcm-option.wrong {
  border-color: var(--danger);
  background: #fbeaea;
}

.qcm-option.wrong .qcm-letter {
  border-color: var(--danger);
  background: var(--danger);
  color: #fff;
}

.qcm-option.wrong:hover {
  border-color: var(--danger) !important;
  background: #fbeaea !important;
}

.qcm-option.wrong .qcm-mark::after {
  content: '\2717';
  color: var(--danger);
}

.qcm-verdict {
  margin: 8px 0 0;
  font-size: 0.85rem;
  font-weight: 600;
}

.qcm-verdict.ok { color: var(--primary); }
.qcm-verdict.ko { color: var(--danger); }
.qcm-verdict.partial { color: var(--warning); }
.qcm-verdict.neutral { color: var(--muted); font-weight: 500; }

/* Explication propre à la question, révélée avec son verdict — permet de
   comprendre immédiatement une réponse sans aller chercher le corrigé
   détaillé en fin d'exercice. */
.qcm-explication {
  margin: 10px 0 0;
  padding: 12px 14px;
  background: var(--surface-2);
  border-left: 3px solid var(--primary);
  border-radius: var(--radius-md, 8px);
  font-size: 0.88rem;
  line-height: 1.6;
  color: var(--text);
}

.qcm-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
  margin-top: 20px;
  padding-top: 16px;
  border-top: 1px solid var(--border);
}

.qcm-check-btn {
  padding: 9px 18px;
  background: var(--primary);
  border: none;
  border-radius: var(--radius-md);
  color: #fff;
  font-family: var(--font-body);
  font-size: 0.9rem;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.15s;
}

.qcm-check-btn:hover {
  background: var(--primary-dark);
}

.qcm-check-btn:disabled {
  background: var(--surface-2);
  color: var(--muted);
  cursor: default;
}

.qcm-corr-toggle {
  padding: 9px 18px;
  background: transparent;
  border: 1.5px solid var(--border);
  border-radius: var(--radius-md);
  color: var(--primary);
  font-family: var(--font-body);
  font-size: 0.9rem;
  font-weight: 600;
  cursor: pointer;
  transition: border-color 0.15s, background 0.15s;
}

.qcm-corr-toggle:hover {
  border-color: var(--primary);
  background: var(--primary-soft);
}

.qcm-score {
  font-size: 0.9rem;
  font-weight: 700;
  color: var(--text);
}

.qcm-correction {
  margin-top: 16px;
  padding: 20px;
  background: var(--surface-2);
  border-left: 4px solid var(--primary);
  border-radius: 0 10px 10px 0;
  font-size: 0.92rem;
  line-height: 1.75;
  color: var(--text);
}

@media (max-width: 640px) {
  .qcm-exercise {
    padding: 16px;
  }
  .qcm-option {
    padding: 10px 12px;
    font-size: 0.88rem;
  }
  .qcm-actions .qcm-check-btn,
  .qcm-actions .qcm-corr-toggle {
    flex: 1 1 auto;
  }
}

/* Physique 2 : module ouvert en aperçu sous un semestre en préparation */
.module-preview-tag {
  font-style: normal;
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--primary, #1e6b47);
  background: rgba(30, 107, 71, 0.10);
  border-radius: var(--radius-sm, 4px);
  padding: 1px 6px;
  margin-left: 6px;
  vertical-align: middle;
}
.maintenance-item.available {
  border-color: rgba(30, 107, 71, 0.35);
}
.maintenance-item.available .maintenance-item-num {
  color: var(--primary, #1e6b47);
}
.btn.small {
  padding: 6px 14px;
  font-size: 0.85rem;
  margin-top: 10px;
}

/* Petit espace de paragraphe (remplace les doubles sauts de ligne) */
.md-break {
  display: block;
  height: 0.55em;
}

/* Séparateur de section (règle horizontale markdown ---) : trait discret */
.md-hr {
  border: 0;
  height: 1px;
  background: var(--border, #e2e8e5);
  margin: 1.4em 0;
}

/* Bloc de code (```lang … ```) — module Informatique pour la biologie.
   Police système monospace : pas de nouvelle police chargée. Le nom du
   langage (data-lang, ex. "python") s'affiche en petite étiquette discrète,
   dans l'esprit institutionnel du site (pas de couleurs vives ni de glow). */
.md-code {
  position: relative;
  display: block;
  margin: 14px 0;
  padding: 14px 16px;
  background: #f4f6f5;
  border: 1px solid var(--border, #e2e8e5);
  border-radius: var(--radius-md, 8px);
  overflow-x: auto;
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Consolas, "Liberation Mono", Menlo, monospace;
  font-size: 0.88rem;
  line-height: 1.55;
}
.md-code code {
  font-family: inherit;
  white-space: pre;
}
.md-code[data-lang]::before {
  content: attr(data-lang);
  position: absolute;
  top: 6px;
  right: 12px;
  font-family: var(--font-body);
  font-size: 0.68rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted, #57655d);
}

/* Code en ligne (`…`) dans la prose */
.md-icode {
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Consolas, "Liberation Mono", Menlo, monospace;
  font-size: 0.92em;
  background: #f4f6f5;
  border: 1px solid var(--border, #e2e8e5);
  border-radius: var(--radius-sm, 4px);
  padding: 0.1em 0.4em;
}
/* Insécable DANS UN TABLEAU seulement : un débutant qui lit « x == » en fin
   de ligne et « 5 » au début de la suivante ne reconnaît plus l'instruction.
   Un tableau défile dans son enveloppe (.bc-cours-table) ; un paragraphe, lui,
   ferait déborder toute la page — mesuré : 502 px pour 350 à l'écran d'un
   téléphone quand la règle s'appliquait aussi à la prose. */
table .md-icode {
  white-space: nowrap;
}

/* Figures insérées dans les contenus : flottent à côté de l'exercice (comme
   sur une copie d'examen), le texte s'écoule à gauche. */
.md-img {
  float: right;
  max-width: min(320px, 42%);
  height: auto;
  margin: 2px 0 12px 20px;
  padding: 10px;
  background: #ffffff;
  border: 1px solid var(--border, #e2e8e5);
  border-radius: var(--radius-md, 8px);
  box-shadow: var(--shadow-sm, 0 1px 2px rgba(0,0,0,0.05));
}
/* Le conteneur d'énoncé contient le flottant (pas de débordement sur la carte) */
.maths-exercise-statement,
.qcm-preamble,
.qcm-prompt {
  display: flow-root;
}
@media (max-width: 640px) {
  .md-img {
    float: none;
    max-width: 100%;
    margin: 12px auto;
  }
}

/* =========================================================================
   Animations pédagogiques (animations.js) — préfixe `.anim-`
   ========================================================================= */
.anim-player {
  margin: 20px 0;
  padding: 20px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius, 12px);
  box-shadow: var(--shadow-sm, 0 1px 2px rgba(0, 0, 0, 0.05));
}

.anim-head { margin-bottom: 14px; }

.anim-title {
  font-family: var(--font-heading);
  font-size: 1.1rem;
  color: var(--primary-dark);
  margin: 0;
}

.anim-subtitle {
  margin: 4px 0 0;
  font-size: 0.88rem;
  color: var(--muted);
}

.anim-stage {
  background: #fbfdfc;
  border: 1px solid var(--border);
  border-radius: var(--radius-md, 8px);
  padding: 8px;
  overflow-x: auto;
}

.anim-svg {
  display: block;
  width: 100%;
  min-width: 560px;
  height: auto;
}

/* ---- zones et structures ---- */
.anim-mito-outer {
  fill: #ffffff;
  stroke: var(--primary);
  stroke-width: 3;
}

.anim-zone-ims { fill: #eaf2f8; }
.anim-zone-matrice { fill: #edf5f0; }

.anim-zone-text {
  font-family: var(--font-body);
  font-size: 14px;
  font-weight: 600;
  fill: var(--muted);
}

.anim-membrane-core { fill: #f4e9d8; stroke: none; }
.anim-lipid { fill: #d8c6a6; }

.anim-complex-body {
  fill: var(--primary);
  stroke: var(--primary-dark);
  stroke-width: 2;
}

.anim-complex-label {
  font-family: var(--font-heading);
  font-size: 22px;
  font-weight: 700;
  fill: #ffffff;
  text-anchor: middle;
}

/* Le complexe II ne pompe pas : teinte volontairement distincte, l'écart
   visuel porte l'information pédagogique. */
.anim-complex-nopump .anim-complex-body {
  fill: #7f9c8c;
  stroke: #5d7a6a;
}

.anim-carrier-body {
  fill: var(--accent);
  stroke: #21486a;
  stroke-width: 2;
}

.anim-carrier-label {
  font-family: var(--font-heading);
  font-size: 15px;
  font-weight: 700;
  fill: #ffffff;
  text-anchor: middle;
}

.anim-synthase-channel {
  fill: #b8873f;
  stroke: #8e6524;
  stroke-width: 2;
}

.anim-synthase-head {
  fill: #d79a3f;
  stroke: #8e6524;
  stroke-width: 2;
}

.anim-synthase-spoke {
  stroke: #8e6524;
  stroke-width: 2;
}

.anim-synthase-label {
  font-family: var(--font-body);
  font-size: 13px;
  font-weight: 600;
  fill: var(--muted);
  text-anchor: middle;
}

.anim-spinning .anim-synthase-rotor {
  transform-box: fill-box;
  transform-origin: center;
  animation: anim-spin 2.8s linear infinite;
}

@keyframes anim-spin { to { transform: rotate(360deg); } }

/* ---- étiquettes de substrats ---- */
.anim-chip-body {
  fill: #ffffff;
  stroke: var(--border);
  stroke-width: 2;
}

.anim-chip-label {
  font-family: var(--font-body);
  font-size: 14px;
  font-weight: 700;
  fill: var(--text);
  text-anchor: middle;
}

.anim-chip-nadh .anim-chip-body { stroke: var(--primary); }
.anim-chip-fadh .anim-chip-body { stroke: #7f9c8c; }
.anim-chip-o2 .anim-chip-body { stroke: var(--accent); }

/* ADP + Pi et ATP occupent la même place : l'un remplace l'autre. */
.anim-chip-atp { display: none; }
.anim-show-atp .anim-chip-adp { display: none; }
.anim-show-atp .anim-chip-atp { display: block; }
.anim-chip-atp .anim-chip-body { fill: var(--primary); stroke: var(--primary-dark); }
.anim-chip-atp .anim-chip-label { fill: #ffffff; }

.anim-gradient-box {
  fill: #ffffff;
  stroke: var(--accent);
  stroke-width: 2;
}

.anim-gradient-title {
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 700;
  fill: var(--accent);
  text-anchor: middle;
}

.anim-gradient-value {
  font-family: var(--font-heading);
  font-size: 16px;
  font-weight: 700;
  fill: var(--text);
  text-anchor: middle;
}

/* ---- particules ---- */
.anim-particle { pointer-events: none; }

.anim-electron {
  fill: #f0c33c;
  stroke: #a8781a;
  stroke-width: 1.5;
  animation: anim-travel linear infinite;
}

.anim-proton {
  fill: #d9534f;
  stroke: #9d3733;
  stroke-width: 1.5;
  animation: anim-travel linear infinite;
}

.anim-proton-pooled {
  animation: anim-pool-in 420ms ease-out both;
  transform-box: fill-box;
  transform-origin: center;
}

.anim-particle-static { animation: none; opacity: 0.9; }

@keyframes anim-travel {
  0%   { transform: translate(var(--x0), var(--y0)); opacity: 0; }
  12%  { opacity: 1; }
  88%  { opacity: 1; }
  100% { transform: translate(var(--x1), var(--y1)); opacity: 0; }
}

@keyframes anim-pool-in {
  from { opacity: 0; transform: scale(0.4); }
  to   { opacity: 1; transform: scale(1); }
}

/* ---- animation « transports membranaires » ---- */
.anim-prot-body {
  fill: var(--accent);
  stroke: #21486a;
  stroke-width: 2;
}

.anim-prot-pore { fill: #dceaf5; }
.anim-prot-site { fill: #dceaf5; stroke: #21486a; stroke-width: 1.5; }
.anim-prot-aqua { fill: #4a8ec2; }

/* Les transporteurs actifs se distinguent des passifs par la teinte : l'écart
   visuel porte la distinction pédagogique passif / actif. */
.anim-prot-active { fill: #b8552a; stroke: #8a3d1c; }
.anim-prot-active2 { fill: #d07a3f; stroke: #a1552a; }

.anim-prot-atp {
  font-family: var(--font-body);
  font-size: 12px;
  font-weight: 700;
  fill: #8a3d1c;
  text-anchor: middle;
  opacity: 0;
  transition: opacity 240ms ease;
}

.anim-show-atp .anim-prot-atp { opacity: 1; }

.anim-station-label {
  font-family: var(--font-body);
  font-size: 12.5px;
  font-weight: 600;
  fill: var(--muted);
  text-anchor: middle;
}

.anim-station.anim-active .anim-station-label { fill: var(--primary-dark); font-weight: 700; }

.anim-solute-a { fill: #7d5ba6; stroke: #533a72; stroke-width: 1.5; animation: anim-travel linear infinite; }
.anim-solute-b { fill: #2f8f7a; stroke: #1e6455; stroke-width: 1.5; animation: anim-travel linear infinite; }
.anim-solute-c { fill: #f0c33c; stroke: #a8781a; stroke-width: 1.5; animation: anim-travel linear infinite; }
.anim-solute-eau { fill: #4a8ec2; stroke: #21486a; stroke-width: 1.5; animation: anim-travel linear infinite; }
.anim-solute-na { fill: #d9534f; stroke: #9d3733; stroke-width: 1.5; animation: anim-travel linear infinite; }
.anim-solute-k { fill: #8e6524; stroke: #5d4118; stroke-width: 1.5; animation: anim-travel linear infinite; }

/* ---- animation « flux endomembranaires » ---- */
.anim-flux-noyau { fill: #cbd9e6; stroke: #21486a; stroke-width: 2.5; }
.anim-flux-noyau-in { fill: #e6eef5; stroke: #6d90ae; stroke-width: 1.5; }
.anim-flux-re { fill: none; stroke: var(--accent); stroke-width: 5; stroke-linecap: round; }
.anim-flux-ribo { fill: #21486a; }
.anim-flux-golgi { fill: none; stroke: var(--primary); stroke-width: 7; stroke-linecap: round; }
.anim-flux-vesicule { fill: #ffffff; stroke: var(--muted); stroke-width: 2.5; }
.anim-flux-lyso .anim-flux-vesicule { fill: #f3dcc8; stroke: #b8552a; }
.anim-flux-endo .anim-flux-vesicule { fill: #dceaf5; stroke: var(--accent); }

.anim-flux-label {
  font-family: var(--font-body);
  font-size: 12.5px;
  font-weight: 600;
  fill: var(--muted);
  text-anchor: middle;
}

.anim-flux-inner {
  font-family: var(--font-body);
  font-size: 13px;
  font-weight: 700;
  fill: #21486a;
  text-anchor: middle;
}

.anim-flux-face {
  font-family: var(--font-body);
  font-size: 11.5px;
  font-style: italic;
  fill: var(--primary-dark);
  text-anchor: middle;
}

.anim-flux-part.anim-active .anim-flux-label { fill: var(--primary-dark); font-weight: 700; }

.anim-flux-bilan-val { font-size: 13.5px; }

/* Chaque flux a sa couleur : protéine sécrétée, hydrolase marquée au M6P,
   matériel entré par endocytose, et retour rétrograde. */
.anim-flux-arn { fill: #7d5ba6; stroke: #533a72; stroke-width: 1.5; animation: anim-travel linear infinite; }
.anim-flux-prot { fill: #2f8f7a; stroke: #1e6455; stroke-width: 1.5; animation: anim-travel linear infinite; }
.anim-flux-m6p { fill: #d9534f; stroke: #9d3733; stroke-width: 1.5; animation: anim-travel linear infinite; }
.anim-flux-ext { fill: #4a8ec2; stroke: #21486a; stroke-width: 1.5; animation: anim-travel linear infinite; }
.anim-flux-retro { fill: #f0c33c; stroke: #a8781a; stroke-width: 1.5; animation: anim-travel linear infinite; }

/* ---- interaction ---- */
.anim-svg [data-info] { cursor: pointer; }

.anim-svg [data-info].anim-active .anim-flux-noyau,
.anim-svg [data-info].anim-active .anim-flux-vesicule {
  stroke: #b8552a;
  stroke-width: 3.5;
}

.anim-svg [data-info].anim-active .anim-flux-re,
.anim-svg [data-info].anim-active .anim-flux-golgi {
  stroke: #b8552a;
}

.anim-svg [data-info].anim-active .anim-prot-body {
  stroke: #b8552a;
  stroke-width: 3.5;
}

.anim-svg [data-info].anim-active .anim-prot-active,
.anim-svg [data-info].anim-active .anim-prot-active2 {
  stroke: var(--primary-dark);
  stroke-width: 3.5;
}

.anim-svg [data-info].anim-active .anim-complex-body,
.anim-svg [data-info].anim-active .anim-carrier-body,
.anim-svg [data-info].anim-active .anim-chip-body,
.anim-svg [data-info].anim-active .anim-gradient-box,
.anim-svg [data-info].anim-active .anim-synthase-channel,
.anim-svg [data-info].anim-active .anim-synthase-head,
.anim-svg [data-info].anim-active.anim-zone-ims,
.anim-svg [data-info].anim-active.anim-zone-matrice {
  stroke: #b8552a;
  stroke-width: 3.5;
}

.anim-svg [data-info].anim-active .anim-membrane-core { stroke: #b8552a; stroke-width: 3; }

.anim-svg [data-info].anim-selected .anim-complex-body,
.anim-svg [data-info].anim-selected .anim-carrier-body,
.anim-svg [data-info].anim-selected .anim-chip-body,
.anim-svg [data-info].anim-selected .anim-gradient-box,
.anim-svg [data-info].anim-selected .anim-synthase-head {
  stroke: var(--accent);
  stroke-width: 4;
}

/* ---- légende d'étape ---- */
.anim-caption {
  display: flex;
  gap: 14px;
  align-items: flex-start;
  margin-top: 14px;
  padding: 14px 16px;
  background: var(--primary-soft);
  border-radius: var(--radius-md, 8px);
}

.anim-step-num {
  flex: 0 0 auto;
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--primary-dark);
  background: #ffffff;
  border-radius: var(--radius-sm, 4px);
  padding: 4px 10px;
  white-space: nowrap;
}

.anim-step-text {
  margin: 0;
  font-size: 0.94rem;
  line-height: 1.55;
  color: var(--text);
}

/* ---- progression ---- */
.anim-progress { margin-top: 14px; }

.anim-progress-bar {
  height: 6px;
  background: var(--border);
  border-radius: 999px;
  overflow: hidden;
}

.anim-progress-fill {
  height: 100%;
  width: 0;
  background: var(--primary);
  border-radius: 999px;
  transition: width 320ms ease;
}

.anim-dots {
  display: flex;
  gap: 6px;
  margin-top: 8px;
  flex-wrap: wrap;
}

.anim-dot {
  width: 22px;
  height: 6px;
  padding: 0;
  border: none;
  border-radius: 999px;
  background: var(--border);
  cursor: pointer;
  transition: background 200ms ease;
}

.anim-dot.done { background: #9dc3ad; }
.anim-dot.active { background: var(--primary); }

/* ---- commandes ---- */
.anim-controls {
  display: flex;
  gap: 8px;
  margin-top: 14px;
  flex-wrap: wrap;
}

.anim-btn {
  font-family: var(--font-body);
  font-size: 0.88rem;
  font-weight: 600;
  color: var(--primary-dark);
  background: #ffffff;
  border: 1px solid var(--border);
  border-radius: var(--radius-md, 8px);
  padding: 8px 16px;
  cursor: pointer;
  transition: background 160ms ease, border-color 160ms ease;
}

.anim-btn:hover:not(:disabled) { background: var(--primary-soft); border-color: var(--primary); }
.anim-btn:disabled { opacity: 0.45; cursor: not-allowed; }

.anim-btn-primary {
  color: #ffffff;
  background: var(--primary);
  border-color: var(--primary);
}

.anim-btn-primary:hover:not(:disabled) { background: var(--primary-dark); border-color: var(--primary-dark); }
.anim-btn-ghost { color: var(--muted); }
.anim-btn-active { background: var(--primary-soft); border-color: var(--primary); }

/* ---- panneau d'explication ---- */
.anim-info {
  margin-top: 14px;
  padding: 14px 16px;
  min-height: 76px;
  background: #fbfdfc;
  border: 1px solid var(--border);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius-md, 8px);
}

.anim-info-hint {
  margin: 0;
  font-size: 0.88rem;
  font-style: italic;
  color: var(--muted);
}

.anim-info-title {
  font-family: var(--font-heading);
  font-size: 0.98rem;
  color: var(--primary-dark);
  margin: 0 0 6px;
}

.anim-info-text {
  margin: 0;
  font-size: 0.9rem;
  line-height: 1.55;
  color: var(--text);
}

.anim-info-note {
  margin: 8px 0 0;
  font-size: 0.86rem;
  line-height: 1.5;
  color: var(--muted);
  padding-left: 10px;
  border-left: 2px solid var(--border);
}

.anim-missing {
  margin: 0;
  padding: 14px;
  font-size: 0.9rem;
  color: var(--muted);
  font-style: italic;
}

@media (max-width: 640px) {
  .anim-player { padding: 14px; }
  .anim-caption { flex-direction: column; gap: 8px; }
  .anim-controls .anim-btn { flex: 1 1 auto; }
}

@media (prefers-reduced-motion: reduce) {
  .anim-progress-fill { transition: none; }
  .anim-spinning .anim-synthase-rotor { animation: none; }
  .anim-proton-pooled { animation: none; }
}

/* ---- réglages interactifs (spec.tools) ---- */
.anim-tools {
  display: flex;
  flex-wrap: wrap;
  gap: 14px 22px;
  margin-top: 12px;
  padding: 12px 16px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-md, 8px);
}

.anim-tool {
  flex: 1 1 200px;
  min-width: 168px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.anim-tool-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
}

.anim-tool-label {
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--muted);
}

.anim-tool-out {
  font-size: 0.84rem;
  font-weight: 700;
  color: var(--primary-dark);
  font-variant-numeric: tabular-nums;
}

.anim-tool-range {
  width: 100%;
  accent-color: var(--primary);
  cursor: pointer;
}

.anim-tool-choices { display: flex; flex-wrap: wrap; gap: 6px; }

.anim-tool-choice {
  font: inherit;
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--muted);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 5px 12px;
  cursor: pointer;
}

.anim-tool-choice.is-on {
  color: #ffffff;
  background: var(--primary);
  border-color: var(--primary);
}

/* =========================================================================
   Scènes de biostatistiques (S3) — préfixe `.anim-bs-`
   =========================================================================
   Ces scènes sont des figures de raisonnement : rien n'y est décoratif. Le
   vert forêt marque toujours l'événement ou le résultat étudié, le bleu
   ardoise ce qui conditionne, l'ocre ce qui trompe (faux positifs). Aucun
   dégradé, aucune ombre — mêmes règles que le reste du design system.
   ========================================================================= */
.anim-bs-svg { min-width: 680px; }
.anim-bs-svg text { font-family: var(--font-body); }
.anim-bs-still * { transition: none !important; }

.anim-bs-title { font-size: 16px; font-weight: 700; fill: var(--primary-dark); }
.anim-bs-head { font-size: 13.5px; font-weight: 700; fill: var(--text); }
.anim-bs-label { font-size: 12px; fill: var(--muted); }
.anim-bs-note { font-size: 13px; fill: var(--muted); font-style: italic; }
.anim-bs-value { font-size: 17px; font-weight: 700; fill: var(--primary-dark); }
.anim-bs-idx { font-size: 0.72em; }
.anim-bs-axis { stroke: var(--muted); stroke-width: 1.2; fill: none; }
.anim-bs-axis-label { font-size: 12px; fill: var(--muted); }

/* ---- dénombrement : jetons, cases et matrice des quatre cas ---- */
.anim-bs-chip-body { fill: #ffffff; stroke: var(--primary); stroke-width: 2; transition: fill 220ms ease, stroke 220ms ease; }
.anim-bs-chip-text { font-size: 15px; font-weight: 700; fill: var(--primary-dark); }
.anim-bs-chip.is-used .anim-bs-chip-body { fill: var(--surface-2); stroke: var(--border); }
.anim-bs-chip.is-used .anim-bs-chip-text { fill: var(--muted); }

.anim-bs-slot-body { fill: var(--primary-soft); stroke: var(--primary); stroke-width: 2; transition: fill 220ms ease, stroke 220ms ease; }
.anim-bs-slot-letter { font-size: 26px; font-weight: 700; fill: var(--primary-dark); }
.anim-bs-slot-note { font-size: 11.5px; fill: var(--muted); }
.anim-bs-slot.is-empty .anim-bs-slot-body { fill: #ffffff; stroke: var(--border); stroke-dasharray: 5 4; }
.anim-bs-slot.is-empty .anim-bs-slot-letter { fill: #c3cec7; }
.anim-bs-slots.is-set .anim-bs-slot-body { fill: #eaf1f7; stroke: var(--accent); }
.anim-bs-slots.is-set .anim-bs-slot-letter { fill: #21486a; }

.anim-bs-cell-body { fill: #ffffff; stroke: var(--border); stroke-width: 1.5; transition: fill 220ms ease, stroke 220ms ease; }
.anim-bs-cell-title { font-size: 13px; font-weight: 700; fill: var(--text); }
.anim-bs-cell-formula { font-size: 14px; fill: var(--primary-dark); }
.anim-bs-cell-ex { font-size: 13px; fill: var(--muted); }
.anim-bs-cell.anim-active .anim-bs-cell-body { fill: var(--primary-soft); stroke: var(--primary); stroke-width: 3; }
.anim-bs-cell.anim-active .anim-bs-cell-ex { fill: var(--primary-dark); font-weight: 600; }

.anim-bs-box-body { fill: #ffffff; stroke: var(--border); stroke-width: 1.5; transition: fill 220ms ease, stroke 220ms ease; }
.anim-bs-box-title { font-size: 12.5px; fill: var(--muted); }
.anim-bs-box-value { font-size: 14px; font-weight: 700; fill: var(--primary-dark); }
.anim-bs-box.anim-active .anim-bs-box-body { fill: #eaf1f7; stroke: var(--accent); stroke-width: 3; }

/* ---- tableau des deux dés ---- */
.anim-bs-sq-body { fill: #ffffff; stroke: var(--border); stroke-width: 1; transition: fill 200ms ease, stroke 200ms ease; }
.anim-bs-sq-text { font-size: 12.5px; fill: var(--muted); }
.anim-bs-sq.is-a .anim-bs-sq-body { fill: var(--primary-soft); stroke: var(--primary); stroke-width: 1.6; }
.anim-bs-sq.is-a .anim-bs-sq-text { fill: var(--primary-dark); font-weight: 700; }
.anim-bs-sq.is-b .anim-bs-sq-body { fill: #eaf1f7; stroke: var(--accent); stroke-width: 1.6; }
.anim-bs-sq.is-b .anim-bs-sq-text { fill: #21486a; font-weight: 700; }
.anim-bs-sq.is-ab .anim-bs-sq-body { fill: var(--primary); stroke: var(--primary-dark); stroke-width: 2; }
.anim-bs-sq.is-ab .anim-bs-sq-text { fill: #ffffff; font-weight: 700; }
.anim-bs-sq.is-c .anim-bs-sq-body { fill: #f6ede2; stroke: #b8552a; stroke-width: 1.6; }
.anim-bs-sq.is-c .anim-bs-sq-text { fill: #8a3d1c; font-weight: 700; }
.anim-bs-sq.is-dim { opacity: 0.3; }
.anim-bs-sq.is-part .anim-bs-sq-body { fill: #f2f7f4; }
.anim-bs-sq.is-part-alt .anim-bs-sq-body { fill: #ffffff; }

.anim-bs-panel-title { font-size: 15px; font-weight: 700; fill: var(--primary-dark); }
.anim-bs-panel-line { font-size: 13px; fill: var(--text); }
.anim-bs-panel-box-body { fill: var(--primary-soft); stroke: var(--primary); stroke-width: 1.5; }
.anim-bs-panel-formula { font-size: 14px; font-weight: 700; fill: var(--primary-dark); }

/* ---- arbre de dépistage (Bayes) ---- */
.anim-bs-edge { stroke: var(--border); stroke-width: 2; }
.anim-bs-edge-label { font-size: 12px; fill: var(--muted); }
.anim-bs-edge-label.anim-active { fill: var(--primary-dark); font-weight: 700; }
.anim-bs-node-body { fill: #ffffff; stroke: var(--border); stroke-width: 1.5; transition: stroke 220ms ease, stroke-width 220ms ease; }
.anim-bs-node-title { font-size: 12.5px; fill: var(--muted); }
.anim-bs-node-value { font-size: 15px; font-weight: 700; fill: var(--text); }
.anim-bs-node.is-malade .anim-bs-node-body { fill: #f7ece9; stroke: #c98a72; }
.anim-bs-node.is-sain .anim-bs-node-body { fill: #eef3f0; stroke: #b9cdc1; }
.anim-bs-node.is-vp .anim-bs-node-body { fill: var(--primary-soft); stroke: var(--primary); }
.anim-bs-node.is-fp .anim-bs-node-body { fill: #f7efe2; stroke: #c8862f; }
.anim-bs-node.anim-active .anim-bs-node-body { stroke-width: 3.5; }
.anim-bs-node.anim-active .anim-bs-node-value { fill: var(--primary-dark); }

.anim-bs-posbar { opacity: 0.3; transition: opacity 260ms ease; }
.anim-bs-show-bar .anim-bs-posbar { opacity: 1; }
.anim-bs-posbar-vp { fill: var(--primary); }
.anim-bs-posbar-fp { fill: #d99a4e; }
.anim-bs-posbar-frame { fill: none; stroke: var(--border); stroke-width: 1.5; }
.anim-bs-posbar-text { font-size: 12.5px; font-weight: 700; fill: #ffffff; }

/* ---- arbre de Bernoulli et histogramme binomial ---- */
.anim-bs-tree { opacity: 0.34; transition: opacity 260ms ease; }
.anim-bs-tree-on .anim-bs-tree { opacity: 1; }
.anim-bs-branch { stroke: var(--border); stroke-width: 2; transition: stroke 200ms ease, stroke-width 200ms ease; }
.anim-bs-branch.anim-active { stroke: var(--primary); stroke-width: 3.5; }
.anim-bs-tree-node { fill: #ffffff; stroke: var(--muted); stroke-width: 1.5; }
.anim-bs-branch-label { font-size: 12.5px; fill: var(--muted); }
.anim-bs-leaf-text { font-size: 13px; fill: var(--text); }
.anim-bs-leaf.anim-active .anim-bs-leaf-text { fill: var(--primary-dark); font-weight: 700; }
.anim-bs-bar { fill: #a9c9b8; transition: fill 200ms ease; }
.anim-bs-bar.is-mode { fill: var(--primary); }
.anim-bs-bar.anim-active { fill: var(--accent); }
.anim-bs-moment { font-size: 13px; fill: var(--muted); }
.anim-bs-moments-on .anim-bs-moment { fill: var(--primary-dark); font-weight: 700; }

/* ---- densités continues et loi normale ---- */
.anim-bs-curve { fill: none; stroke: var(--primary); stroke-width: 2.5; stroke-linejoin: round; }
.anim-bs-area { fill: rgba(30, 107, 71, 0.22); stroke: none; }
.anim-bs-cdf { fill: none; stroke: var(--accent); stroke-width: 1.6; stroke-dasharray: 5 4; }
.anim-bs-bound-line { stroke: var(--accent); stroke-width: 1.6; stroke-dasharray: 4 4; }
.anim-bs-bound-text { font-size: 12.5px; font-weight: 700; fill: #21486a; }
.anim-bs-band { stroke: none; }
.anim-bs-band.is-s1 { fill: rgba(30, 107, 71, 0.30); }
.anim-bs-band.is-s2 { fill: rgba(30, 107, 71, 0.17); }
.anim-bs-band.is-s3 { fill: rgba(30, 107, 71, 0.09); }
.anim-bs-band-label { font-size: 12.5px; font-weight: 600; fill: var(--primary-dark); }
.anim-bs-zaxis .anim-bs-axis { stroke: var(--accent); }
.anim-bs-zaxis .anim-bs-axis-label { fill: #21486a; }

@media (max-width: 640px) {
  .anim-tools { padding: 10px 12px; gap: 12px; }
  .anim-tool { flex: 1 1 100%; }
}

/* =========================================================================
   Cartes mentales (Biologie cellulaire, Géologie) — préfixe .cmap-
   =========================================================================
   Une carte = un chapitre. Le nœud central porte le schéma SVG, les branches
   reprennent la numérotation du polycopié. Les couleurs de branche viennent
   des données (une teinte par branche) ; tout le reste est aux tokens.
   ========================================================================= */
.cmap-choix {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 16px;
}
/* Sélecteur GROUPÉ — utilisé par Histologie – Embryologie, dont la collection
   de cartes porte DEUX matières aux logiques de lecture différentes
   (thématique d'un côté, chronologique de l'autre). Biologie cellulaire n'a
   qu'une matière et garde son `.cmap-choix` nu, sans groupe. */
.cmap-groupe + .cmap-groupe { margin-top: 4px; }
.cmap-groupe-titre {
  margin: 0 0 7px;
  font-size: .74rem;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--muted);
}
.cmap-choix-btn {
  font: inherit;
  font-size: .88rem;
  font-weight: 600;
  color: var(--muted);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 6px 14px;
  cursor: pointer;
}
.cmap-choix-btn.is-active {
  color: #fff;
  background: var(--primary);
  border-color: var(--primary);
}

.cmap {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  overflow: hidden;
}
.cmap-head {
  padding: 18px 22px;
  border-bottom: 1px solid var(--border);
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: flex-start;
  justify-content: space-between;
}
.cmap-head h2 {
  font-size: 1.25rem;
  margin: 0;
}
.cmap-chapitre {
  font-size: .74rem;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--muted);
  font-weight: 600;
  margin: 0 0 4px;
}
.cmap-lead {
  font-size: .9rem;
  color: var(--muted);
  margin: 6px 0 0;
  max-width: 62ch;
}
.cmap-freq {
  font-size: .78rem;
  font-weight: 600;
  color: var(--primary-dark);
  background: var(--primary-soft);
  border-radius: 999px;
  padding: 4px 12px;
  white-space: nowrap;
}

/* La scène défile dans son propre cadre : la page ne déborde jamais.
   `.content-area` est un élément de grille en `min-width: auto` : sans ce
   correctif il se dilate à la largeur minimale du SVG (660px) et fait déborder
   toute la page en mobile, au lieu de laisser la scène défiler. Le `:has()`
   cible uniquement les pages qui portent une carte — les autres modules
   gardent exactement le comportement qu'ils avaient. */
.content-area:has(.cmap-stage) { min-width: 0; }

.cmap-stage {
  padding: 8px 12px 4px;
  overflow-x: auto;
}
.cmap-svg {
  display: block;
  width: 100%;
  min-width: 660px;
  height: auto;
}

.cmap-node { cursor: pointer; }
.cmap-node .cmap-box { transition: filter .15s ease; }
.cmap-node:hover .cmap-box { filter: brightness(.97); }
.cmap-node:focus-visible { outline: none; }
.cmap-node:focus-visible .cmap-box,
.cmap-node.is-active .cmap-box { stroke-width: 3; }

.cmap-link { stroke: var(--border); stroke-width: 2; fill: none; }
.cmap-centre {
  font-family: var(--font-heading);
  font-size: 15px;
  font-weight: 700;
  fill: #fff;
}
.cmap-label {
  font-family: var(--font-heading);
  font-size: 16px;
  font-weight: 700;
  fill: var(--text);
}
.cmap-num {
  font-family: var(--font-body);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .06em;
}
.cmap-sub {
  font-family: var(--font-body);
  font-size: 12.5px;
  fill: var(--muted);
}
.cmap-badge {
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 600;
}
.cmap-mini {
  font-family: var(--font-body);
  font-size: 10.5px;
  fill: var(--muted);
}
.cmap-mini-i { font-style: italic; }
/* Valeur chiffrée mise en avant dans un schéma (échelles de résolution). */
.cmap-label-s {
  font-family: var(--font-heading);
  font-size: 14px;
  font-weight: 700;
  fill: var(--primary-dark);
}

.cmap-panel {
  border-top: 1px solid var(--border);
  padding: 22px;
  background: var(--surface-2);
}
.cmap-panel-head {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 4px;
}
.cmap-panel-head h3 { font-size: 1.1rem; margin: 0; }
.cmap-chip {
  font-size: .72rem;
  font-weight: 700;
  letter-spacing: .06em;
  color: #fff;
  padding: 3px 9px;
  border-radius: var(--radius-sm);
}
.cmap-freq-line {
  font-size: .8rem;
  color: var(--muted);
  margin: 0;
}
.cmap-panel-body {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 22px;
  margin-top: 14px;
}
.cmap-panel-body h4 {
  font-family: var(--font-body);
  font-size: .8rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .07em;
  color: var(--muted);
  margin: 0 0 8px;
}
.cmap-panel-body ul { margin: 0; padding-left: 18px; }
.cmap-panel-body li { margin-bottom: 7px; }
.cmap-panel-body li:last-child { margin-bottom: 0; }
.cmap-num-val {
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  color: var(--primary-dark);
}

.cmap-piege {
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: 3px solid var(--danger);
  border-radius: var(--radius-md);
  padding: 12px 14px;
  margin-bottom: 10px;
}
.cmap-piege:last-child { margin-bottom: 0; }
.cmap-piege p { margin: 0; font-size: .92rem; }
.cmap-src {
  display: block;
  margin-top: 6px;
  font-size: .78rem;
  color: var(--muted);
}
.cmap-vide { font-size: .9rem; color: var(--muted); margin: 0; }

/* Figure d'une branche — posée par Géologie, disponible à tout module qui en
   déclare une (`branche.figure`). Elle n'emprunte pas `.md-img` : celle-ci
   flotte à droite sur 320 px, ce qui, dans une colonne de panneau, réduirait
   la figure à une vignette collée au texte. Ici elle est en tête de colonne,
   pleine largeur, avec sa légende dessous. */
.cmap-figure { margin: 0 0 14px; }
.cmap-figure img {
  display: block;
  width: 100%;
  height: auto;
  padding: 8px;
  background: #ffffff;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
}
.cmap-figure figcaption {
  font-size: .78rem;
  color: var(--muted);
  margin-top: 6px;
}

.cmap-foot {
  padding: 14px 22px;
  border-top: 1px solid var(--border);
  font-size: .8rem;
  color: var(--muted);
}

@media (max-width: 760px) {
  .cmap-panel-body { grid-template-columns: 1fr; }
}
@media (prefers-reduced-motion: reduce) {
  .cmap-node .cmap-box { transition: none; }
}

/* =========================================================================
   Cours de Biologie cellulaire — préfixe .bc-cours-
   =========================================================================
   Le lecteur lui-même réutilise .course-reader / .course-toc / .course-chapter
   (partagés avec Maths et Physique) : seuls le sélecteur de chapitre, le
   bandeau de relecture et le traitement des figures sont propres au module.
   ========================================================================= */
.bc-cours-chapitres {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 18px;
}
.bc-cours-chapitre {
  display: flex;
  align-items: baseline;
  gap: 8px;
  font: inherit;
  font-size: .86rem;
  color: var(--muted);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 7px 13px;
  cursor: pointer;
  text-align: left;
}
.bc-cours-chapitre:hover { border-color: var(--primary); }
.bc-cours-chapitre.is-active {
  color: #fff;
  background: var(--primary);
  border-color: var(--primary);
}
.bc-cours-num {
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: .82rem;
  opacity: .75;
}
.bc-cours-chapitre.is-active .bc-cours-num { opacity: .9; }
.bc-cours-titre { font-weight: 600; }

/* Bandeau des chapitres rédigés hors polycopié : le lecteur doit savoir
   d'où vient ce qu'il lit. Ne pas retirer sans validation du propriétaire. */
.bc-cours-avis {
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: 3px solid var(--warning);
  border-radius: var(--radius-md);
  padding: 12px 15px;
  margin-bottom: 18px;
  font-size: .88rem;
  color: var(--muted);
}

.bc-cours-resume {
  margin: 0 0 4px;
  font-size: .92rem;
  color: var(--muted);
  max-width: 72ch;
}

/* Les figures du cours sont larges et porteuses d'information : le flottant
   320px de `.md-img` les rendrait illisibles. Pleine largeur, centrées —
   même traitement que `.bc-statement .md-img` pour les sujets d'examen. */
.bc-cours-content .md-img {
  float: none;
  display: block;
  max-width: 100%;
  margin: 18px auto 6px;
}
/* Les schémas du résumé (SVG vectoriels, ~500px de large) n'ont pas besoin de
   toute la largeur d'une colonne large : centrés, plafonnés, jamais démesurés. */
.maths-resume-content .md-img {
  float: none;
  display: block;
  max-width: min(560px, 100%);
  margin: 18px auto 6px;
}
/* La légende suit immédiatement la figure. Attention : `parseMarkdown` ne
   produit pas de <p> — il sépare les paragraphes par <span class="md-break">.
   La légende est donc le <em> qui suit ce séparateur, pas l'image elle-même. */
.bc-cours-content .md-img + .md-break + em {
  display: block;
  text-align: center;
  font-size: .84rem;
  color: var(--muted);
  margin: 0 auto 18px;
  max-width: 60ch;
}
.bc-cours-content h3 {
  font-size: 1.02rem;
  margin: 22px 0 8px;
  color: var(--primary-dark);
}
/* Encadré d'aparté. `parseMarkdown` ne gère PAS la syntaxe blockquote `>` :
   le cours emploie les marqueurs [[note]]…[[/note]] du projet, substitués par
   injectAnimationMounts() en `.bc-aside` — comme les corrigés d'examen. La
   règle existante étant scopée à `.maths-solution` et `.qcm-correction`, il
   faut la déclarer aussi pour le cours. */
.bc-cours-content .bc-aside {
  margin: 16px 0;
  padding: 12px 15px;
  background: var(--primary-soft);
  border: 1px solid var(--border);
  border-left: 3px solid var(--primary);
  border-radius: var(--radius-md);
  font-size: .9rem;
  line-height: 1.55;
  color: var(--muted);
}

@media (max-width: 760px) {
  .bc-cours-chapitre { font-size: .8rem; padding: 6px 10px; }
}

/* Contention en largeur du lecteur de cours de Biologie cellulaire.
   Les chapitres contiennent des tableaux larges et de longs intitulés de
   navigation : leur largeur min-content remonte la chaîne des conteneurs
   (éléments de grille et de flex en `min-width: auto`) et fait déborder toute
   la page en mobile. Tout est scopé à `.bc-cours` — Maths et Physique, qui
   partagent le même lecteur, gardent exactement leur comportement. */
.content-area:has(.bc-cours) { min-width: 0; }
.bc-cours .course-reader-grid,
.bc-cours .course-chapters,
.bc-cours .course-chapter,
.bc-cours .course-chapter-body { min-width: 0; }

/* LE MEME REMEDE, POUR TOUS LES MODULES — audit de production du 4 septembre 2026.
   Le bloc ci-dessus etait scope a `.bc-cours` et disait laisser Maths et Physique
   « exactement leur comportement » : ce comportement etait un debordement
   horizontal. Mesure en ligne sur bioprep.co a 375 px de large, compte etudiant
   connecte — Physique S1 : 560 px de debordement (une page de 935 px sur un
   telephone), Biostatistiques 491, Physique 2 473, Chimie 305, Immunologie 305,
   Microbiologie 271, Biochimie structurale 255, Geologie 159, Techniques
   chimiques 152, Biologie cellulaire 138.

   Deux minimums, la meme mecanique. `.app-shell` passe en `grid-template-columns:
   1fr` sous 1020 px : une piste `1fr` a pour minimum automatique sa largeur
   min-content, donc elle refuse de descendre sous la plus large formule de la
   page — la ou la regle de bureau ecrit deja `minmax(0, 1fr)`. Et les elements du
   lecteur de cours restent en `min-width: auto`, ce qui remonte cette meme largeur
   min-content de proche en proche.

   Consequence : le `overflow-x: auto` deja pose sur `.katex-display` et
   `.bc-cours-table` n entrait JAMAIS en jeu — rien ne contraignait jamais leur
   conteneur. Les deux minimums leves, une formule trop large defile dans sa propre
   boite, comme prevu a l origine. */
@media (max-width: 1020px) {
  .app-shell { grid-template-columns: minmax(0, 1fr); }
}

.app-shell > *,
.course-reader-grid,
.course-chapters,
.course-chapter,
.course-chapter-body { min-width: 0; }

/* CENTRAGE (20 septembre 2026) : `display: flex; justify-content: center`
   centre le tableau quand il est plus étroit que son enveloppe — un tableau à
   deux colonnes ne doit pas rester collé à gauche comme du texte. Le
   défilement continue de fonctionner : un enfant flex plus large que son
   conteneur y déborde et défile, il ne le fait pas grandir. */
.bc-cours-table {
  display: flex;
  justify-content: center;
  overflow-x: auto;
  margin: 16px 0;
}
/* `display: block` est nécessaire, pas seulement `overflow-x: auto` sur
   l'enveloppe : un `<table>` reste en `table-layout: auto` par défaut, où un
   `width` (même 100 %) n'est qu'un PLANCHER — l'algorithme de colonnes peut le
   dépasser librement si le contenu des cellules le demande, et alors le
   tableau s'affiche à sa largeur intrinsèque quel que soit le défilement posé
   sur son enveloppe. Repéré sur la grille électrolytes/canaux ioniques de
   Physiologie animale (colonnes KaTeX insécables) : l'enveloppe rapportait
   fidèlement un `clientWidth` contenu, mais le tableau qu'elle contenait
   s'affichait tout de même à sa largeur pleine, et l'ancêtre remontait
   l'écart jusqu'à la page.
   `width: auto` (et non `100%`) depuis le 20 septembre 2026 : un tableau
   étroit doit pouvoir rester étroit pour que `justify-content: center`
   ci-dessus ait de l'espace à répartir. Un tableau plus large que
   l'enveloppe garde le même comportement qu'avant — `width: auto` ne
   l'empêche pas de déborder puis de défiler, seul `overflow-x: auto` sur
   l'enveloppe en décide. */
.bc-cours-table table { margin: 0; display: block; width: auto; }

/* Même contention pour un sujet de corpus (Examens/TD, `renderExamCorpus`) :
   un tableau à colonnes KaTeX insécables (grille électrolytes/canaux ioniques
   de Physiologie animale, 7 colonnes $t_1$…$t_7$) remonte la même chaîne de
   `min-width: auto` — `.maths-exam-detail` et ses descendants sont partagés
   par TOUS les modules à corpus (BC, Histologie, Chimie, TC, Géologie,
   Écologie, Microbiologie, Biochimie structurale), donc scopé large plutôt
   qu'au seul module qui l'a révélé. `overflow-x` sur `.math-table` et
   `.katex-display` (règles ci-dessus) ne suffit pas seul : sans `min-width: 0`
   sur la chaîne, c'est le CONTENEUR qui grandit avant que le défilement
   interne n'ait sa chance. */
.content-area:has(.maths-exam-detail) { min-width: 0; }
.maths-exam-detail,
.maths-exercises,
.maths-exercise,
.qcm-exam,
.qcm-exercise,
.qcm-questions,
.qcm-question { min-width: 0; }

/* Les boutons Précédent / Suivant portent le titre de la section voisine :
   ils doivent pouvoir passer à la ligne et tronquer, pas pousser la page. */
.bc-cours .course-chapter-foot { flex-wrap: wrap; gap: 8px; }
.bc-cours .course-nav-btn { min-width: 0; max-width: 100%; }
.bc-cours .course-nav-btn em {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ==========================================================================
   IMPRESSION — la feuille qui FABRIQUE le tirage
   (la seconde, en fin de fichier, NEUTRALISE l'impression du contenu payant)
   ==========================================================================

   POURQUOI ELLE EXISTE. Les résumés annoncent « à parcourir ou imprimer »
   depuis toujours, et aucune règle d'impression n'existait : un Ctrl+P tirait
   l'en-tête, la barre des semestres, les onglets, le pied de page et les fonds
   colorés de l'application. Les cartes mentales étaient pires — voir plus bas.

   CE QU'ELLE NE FAIT PAS. Elle ne touche à AUCUN rendu écran, et elle ne
   réécrit aucun contenu : même texte, même structure, mêmes images, mêmes
   couleurs. Elle retire le mobilier de l'application et rend le contenu
   imprimable, rien d'autre.

   LES COULEURS SONT DU CONTENU ICI, pas de la décoration : la couleur d'une
   branche relie sa boîte du schéma à son panneau de détail, la pastille du
   numéro et la barre de rappel se lisent l'une par l'autre. D'où
   `print-color-adjust: exact` — sans lui le navigateur tire les fonds en blanc
   « pour économiser l'encre » et la carte perd son système de repérage.

   LES CARTES S'IMPRIMENT EN PAYSAGE, et c'est une contrainte de lisibilité,
   pas un goût. Le schéma est un viewBox de 1040 unités dont les textes vont de
   10,5 px (`.cmap-mini`) à 16 px (`.cmap-label`). En A4 portrait, la largeur
   utile de 186 mm ramène le 10,5 px à 5,3 pt : illisible. En paysage, à
   245 mm, il remonte à 7 pt et le titre de branche à 10,7 pt. La largeur est
   plafonnée à 245 mm (et non à la pleine page) pour que le titre de la carte
   ET son schéma tiennent sur la MÊME feuille : 25 mm d'en-tête + 160 mm de
   schéma = 185 mm, sous les 190 mm utiles d'une A4 paysage.

   `.cmap-svg` porte `min-width: 660px` à l'écran, pour que la scène défile au
   lieu d'écraser le schéma sur mobile. En impression il n'y a pas de
   défilement : ce plancher ferait déborder la feuille, il est retiré.

   LES CONTENEURS À DÉFILEMENT SE ROUVRENT. `.bc-cours-table` et
   `.katex-display` sont des boîtes en `overflow-x: auto` : sur papier, ce qui
   dépasse n'est pas atteignable, il est COUPÉ. Ils repassent donc en
   `overflow: visible`, et `.bc-cours-table table` reprend `display: table`
   (il est en `display: block` à l'écran, sans quoi un `table-layout: auto`
   traite son `width` comme un plancher et ignore le défilement) pour que le
   tableau se replie à la largeur de la page.
   ========================================================================== */

@page {
  size: A4 portrait;
  margin: 14mm 12mm;
}

/* Page nommée pour les cartes mentales — voir la note sur la lisibilité. */
@page carte {
  size: A4 landscape;
  margin: 12mm;
}

@media print {

  /* Les couleurs portent l'information : ne pas les laisser tomber. */
  *, *::before, *::after {
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
  }

  html, body {
    background: #fff;
    font-size: 11pt;
  }

  /* ---------------------------------------------------- mobilier à retirer */
  .site-header,
  .semester-sidebar,
  .site-footer,
  .mobile-toggle,
  .access-card,
  .logout-button,
  .td-tabs,
  .cmap-groupe,
  .cmap-choix,
  .course-chapter-foot {
    display: none !important;
  }

  /* Le panneau interactif d'une carte ne montre qu'UNE branche : sur papier
     il est remplacé par `.cmap-print`, qui les porte toutes. */
  .cmap-panel { display: none !important; }
  .cmap-print { display: block !important; }

  /* ------------------------------------------------------------- la page */
  .app-shell {
    display: block;
    padding: 0;
    margin: 0;
    gap: 0;
  }
  .content-area {
    width: auto;
    max-width: none;
    min-width: 0;
    padding: 0;
    margin: 0;
  }
  .section,
  .module-card,
  .stats-module {
    border: 0;
    border-radius: 0;
    box-shadow: none;
    background: #fff;
    padding: 0;
    margin: 0;
  }

  h1 { font-size: 18pt; margin: 0 0 4pt; }
  h2 { font-size: 14pt; }
  h3 { font-size: 12pt; }
  .eyebrow { font-size: 9pt; }
  .lead { font-size: 10pt; }

  /* Un titre ne reste jamais seul en bas de feuille. */
  h1, h2, h3, h4 { break-after: avoid; page-break-after: avoid; }
  img, figure, table { break-inside: avoid; page-break-inside: avoid; }
  img { max-width: 100%; height: auto; }

  /* ------------------------------------------------- cartes mentales */
  .cmap {
    page: carte;
    border: 0;
    border-radius: 0;
    box-shadow: none;
  }
  /* L’en-tête reste SOLIDAIRE de son schéma (break-after: avoid) et se
     resserre : à sa taille d’écran, en-tête + schéma dépassaient les 186 mm
     utiles d’une A4 paysage et le schéma partait seul sur la feuille suivante,
     laissant une page presque blanche. */
  .cmap-head {
    padding: 0 0 4pt;
    border: 0;
    break-after: avoid;
    page-break-after: avoid;
  }
  .cmap-head h2 { font-size: 13pt; margin: 0; }
  .cmap-chapitre { font-size: 8pt; margin: 0 0 2pt; }
  .cmap-lead { font-size: 9pt; margin: 2pt 0 0; }
  .cmap-freq { font-size: 8.5pt; }
  .cmap-stage {
    padding: 0;
    overflow: visible;
    break-inside: avoid;
    page-break-inside: avoid;
  }
  .cmap-svg {
    min-width: 0;
    width: 100%;
    max-width: 240mm;
    height: auto;
    margin: 0 auto;
  }
  .cmap-node { cursor: auto; }

  /* Resserré pour que DEUX branches tiennent par feuille : à la densité de
     l’écran une seule y entrait, et les 63 branches du module partaient sur
     63 feuilles à moitié vides. */
  .cmap-print-branche {
    break-inside: avoid;
    page-break-inside: avoid;
    border-top: 1px solid #d6ddd6;
    padding: 6pt 0;
    font-size: 9pt;
  }
  .cmap-print .cmap-panel-head h3 { font-size: 10.5pt; }
  .cmap-print .cmap-panel-body { gap: 10pt; margin-top: 5pt; }
  .cmap-print .cmap-panel-body li { margin-bottom: 3pt; }
  .cmap-print .cmap-panel-body h4 { margin-bottom: 4pt; }
  .cmap-print .cmap-freq-line { font-size: 8pt; }
  .cmap-print .cmap-piege { margin-bottom: 5pt; }
  .cmap-print .cmap-piege p { font-size: 8.5pt; }
  .cmap-print .cmap-src { font-size: 7.5pt; }
  .cmap-print-branche:first-child { border-top: 0; }
  .cmap-print .cmap-panel-body {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 14pt;
    margin-top: 8pt;
  }
  .cmap-foot {
    break-inside: avoid;
    page-break-inside: avoid;
    font-size: 8.5pt;
  }

  /* ------------------------------------------------------------ résumés */
  .maths-resume-sheet .maths-resume-chapter {
    padding: 10pt 0;
    break-inside: auto;
  }
  .maths-resume-intro { font-size: 9.5pt; }

  /* ------------------------------- boîtes à défilement : les rouvrir */
  .bc-cours-table,
  .math-table,
  .katex-display {
    overflow: visible !important;
  }
  .bc-cours-table table {
    display: table;
    width: 100%;
    table-layout: auto;
  }
  .bc-cours-table table,
  .maths-resume-sheet table {
    font-size: 9pt;
  }

  /* Les liens de la SPA sont des ancres internes : leur URL n'apprend rien
     au lecteur d'une feuille de papier, on ne l'imprime pas. */
  a[href]::after { content: none !important; }
}


/* ==========================================================================
   PROTECTION DU CONTENU PAYANT — sélection, copie, impression
   ==========================================================================

   CE QUE CE DISPOSITIF EST, ET CE QU'IL N'EST PAS. C'est une DISSUASION, pas
   une protection : le contenu d'un module ouvert est dans le navigateur de
   l'étudiant, et qui sait ouvrir les outils de développement l'en sortira. La
   seule chose qu'on puisse viser est de rendre la copie de masse — tout
   sélectionner, copier, coller ailleurs, ou imprimer en PDF — assez pénible
   pour qu'elle cesse d'être le geste par défaut. Ne pas surestimer ce que ces
   règles achètent, et ne pas les payer trop cher côté lecture.

   ELLE NE PORTE QUE SUR LA ROUTE `module`. Le marqueur `data-protege="1"` est
   posé sur `#app` par `renderRoute()`, et par elle seule. Le reste du site —
   accueil, tarifs, règlement, contact, coordonnées bancaires — reste
   sélectionnable : un visiteur doit pouvoir copier un RIB ou un numéro, et
   bloquer la page d'accueil n'aurait rien protégé du tout.

   L'IMPRESSION DU CONTENU PAYANT EST NEUTRALISÉE. « Imprimer en PDF » est le
   moyen le plus simple d'emporter un module entier, et il contournait tout le
   reste. La page imprimée porte donc un avis à la place du contenu. C'est
   cohérent avec la décision du 3 septembre 2026 sur les PDF imprimables : ils
   sont livrés au propriétaire dans un dossier, la plateforme n'en distribue
   aucun. Les intros de résumé, qui promettaient « à parcourir ou imprimer »,
   ont été corrigées le même jour — un site ne doit pas offrir ce qu'il refuse.

   CE BLOC NE GÊNE PAS LES GÉNÉRATEURS DE PDF. `gen-pdf-cartes.js` et
   `gen-pdf-resumes.js` fabriquent leurs propres pages avec un
   `<section class="content-area">` SANS `id="app"` : la règle d'impression,
   ancrée sur `#app[data-protege="1"]`, ne les atteint pas. Si l'on déplaçait un
   jour cette ancre vers `.content-area`, les deux générateurs sortiraient des
   PDF vides — et rien ne le dirait avant d'ouvrir le fichier.
   ========================================================================== */

#app[data-protege="1"],
#app[data-protege="1"] * {
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
}

/* Les champs de saisie d'un QCM restent utilisables : `user-select: none` sur un
   ancêtre les rendrait impossibles à corriger au clavier. */
#app[data-protege="1"] input,
#app[data-protege="1"] textarea {
  -webkit-user-select: text;
  user-select: text;
}

/* Une image glissée hors de la page est une copie comme une autre. On se garde
   de `pointer-events: none` : les figures des cours et les schémas de cartes
   mentales portent des interactions, et les éteindre casserait la lecture pour
   empêcher un geste que `-webkit-user-drag` suffit à bloquer. */
#app[data-protege="1"] img {
  -webkit-user-drag: none;
  user-drag: none;
}

/* L'avis n'existe qu'à l'impression : à l'écran il ne doit rien occuper. */
.print-avis { display: none; }

@media print {
  #app[data-protege="1"] { display: none !important; }

  .print-avis {
    display: block !important;
    padding: 2em 0;
    font-family: var(--font-body, inherit);
    font-size: 12pt;
    color: #000;
  }
}

/* L'avis d'évincement, sur la page de connexion : ce compte vient d'être
   réclamé sur un autre appareil. Il n'apparaît QUE là, et seulement après un
   évincement réel (`state.evince`) — un bandeau permanent ferait passer une
   règle pour une panne. Ton d'avertissement, pas d'erreur : l'étudiant n'a rien
   cassé, il doit juste se reconnecter. */
.auth-evincement {
  margin: 0 0 18px;
  padding: 14px 16px;
  border: 1px solid var(--border);
  border-left: 3px solid var(--warning);
  border-radius: var(--radius-md);
  background: var(--surface-2);
  color: var(--text);
  font-size: 0.94rem;
  line-height: 1.55;
}
/* ==========================================================================
   DÉMARCHE DE VERSEMENT — page Paiement, section « Comment payer »

   Portage de la palette bilingue du propriétaire. Le lecteur est un bachelier
   qui n'a jamais fait de virement : la section montre ce qu'il va voir (le
   reçu-témoin), écrit ce qu'il va dire (la bulle de guichet) et lui donne le
   chiffre exact à annoncer (le récapitulatif). Rien d'ornemental — chaque bloc
   répond à une question qu'il se poserait au comptoir.

   Bilinguisme : chaque ligne en darija porte `class="ar" lang="ar" dir="rtl"`.
   La direction se pose sur l'ÉLÉMENT, jamais sur la page — le site reste en
   français, et `unicode-bidi: isolate` empêche un mot latin enchâssé (le
   « versement » de la phrase du guichet) de désordonner ce qui l'entoure.
   ========================================================================== */

.ar {
  font-family: var(--font-ar);
  direction: rtl;
  unicode-bidi: isolate;
  font-weight: 500;
  line-height: 1.8;
  /* La ligne arabe se cale sur le bord GAUCHE, comme la ligne française
     qu'elle surmonte : la direction du TEXTE reste rtl (il se lit de droite
     à gauche), seul le bloc s'aligne. Laissée à droite, chaque étape faisait
     sauter l'œil d'un bord à l'autre, et le titre en darija se retrouvait à
     l'opposé de la pastille numérotée. */
  text-align: left;
}

/* Un mot latin au milieu d'une phrase arabe : il reprend la police du corps,
   sinon il sort en glyphes de secours au milieu de la bulle. */
.ar .lat,
.guichet-bulle .lat {
  font-family: var(--font-body);
  direction: ltr;
  unicode-bidi: isolate;
  font-weight: 700;
}

.versement {
  margin-top: 56px;
}

.versement-head {
  text-align: center;
  margin-bottom: 22px;
}

.versement-head h2 {
  margin: 4px 0 10px;
}

/* Le titre de section est en darija : Source Serif 4 ne couvre pas l'arabe,
   la règle globale `h1..h4` le mettrait donc en police de secours. */
.versement-head h2 .ar {
  font-size: 1.9rem;
  font-weight: 700;
}

.versement-head p {
  margin: 0 auto;
  max-width: 620px;
  color: var(--muted);
}

/* --- Récapitulatif : l'offre choisie et le montant exact ------------------ */

.versement-recap {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 18px;
  align-items: end;
  margin: 0 auto 28px;
  max-width: 720px;
  padding: 16px 20px 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  box-shadow: var(--shadow-sm);
}

.recap-field {
  display: grid;
  gap: 2px;
  min-width: 0;
}

.recap-label {
  display: flex;
  align-items: baseline;
  gap: 8px;
  color: var(--muted);
  font-size: 0.78rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

.recap-label .ar {
  text-transform: none;
  letter-spacing: 0;
  font-size: 0.9rem;
}

.recap-value {
  font-family: var(--font-heading);
  font-size: 1.25rem;
  font-weight: 700;
  color: var(--text);
  overflow-wrap: anywhere;
}

.recap-field-montant .recap-value {
  color: var(--primary-dark);
  font-size: 1.55rem;
}

.recap-hint {
  grid-column: 1 / -1;
  margin: 4px 0 0;
  padding-top: 10px;
  border-top: 1px solid var(--border);
  color: var(--muted);
  font-size: 0.84rem;
}

/* Le rang de semestre est devenu un bouton : il hérite sinon des marges et de
   la police du navigateur, et perd l'alignement de la liste des prix. */
.sem-row {
  width: 100%;
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.sem-row.is-selected {
  border-color: var(--primary);
  background: var(--primary-soft);
  box-shadow: inset 3px 0 0 var(--primary);
}

/* --- Les quatre étapes ---------------------------------------------------- */

.versement-steps {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 18px;
}

.versement-step {
  display: grid;
  grid-template-columns: 40px minmax(0, 1fr);
  gap: 16px;
  padding: 20px 22px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  box-shadow: var(--shadow-sm);
}

.versement-num {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: 999px;
  background: var(--primary);
  color: #ffffff;
  font-weight: 700;
  font-size: 1rem;
}

.versement-body {
  min-width: 0;
}

.versement-body > h3 {
  display: grid;
  gap: 2px;
  margin: 4px 0 12px;
}

.versement-body > h3 .ar {
  font-size: 1.32rem;
  font-weight: 700;
  color: var(--text);
}

.versement-body > h3 em {
  font-family: var(--font-body);
  font-style: normal;
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--muted);
}

/* Une note bilingue : la darija en tête, le français dessous, sans puce. */
.versement-note {
  display: grid;
  gap: 1px;
  margin: 0 0 14px;
}

.versement-note .ar {
  font-size: 1.02rem;
  color: var(--text);
}

.versement-note em {
  font-style: normal;
  font-size: 0.9rem;
  color: var(--muted);
  line-height: 1.6;
}

.versement-compte em {
  color: var(--accent);
}

/* --- Étape 1 : les deux comptes ------------------------------------------ */

.rib-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 14px;
}

.rib-card {
  display: grid;
  gap: 10px;
  padding: 16px 18px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--surface-2);
}

.rib-head {
  display: flex;
  align-items: center;
  gap: 9px;
  padding-bottom: 9px;
  border-bottom: 1px solid var(--border);
}

.rib-head h4 {
  margin: 0;
  font-size: 1.02rem;
}

.rib-ico {
  display: grid;
  place-items: center;
  color: var(--primary);
}

.rib-field {
  display: grid;
  gap: 2px;
  margin: 0;
  min-width: 0;
}

.rib-key {
  display: flex;
  align-items: baseline;
  gap: 7px;
  color: var(--muted);
  font-size: 0.74rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.rib-key .ar {
  text-transform: none;
  letter-spacing: 0;
  font-size: 0.86rem;
}

/* Un numéro de compte se relit chiffre par chiffre au guichet : chasse fixe,
   chiffres tabulaires, et retour à la ligne autorisé plutôt qu'un débordement. */
.rib-number {
  font-family: 'Consolas', 'SFMono-Regular', 'Menlo', monospace;
  font-variant-numeric: tabular-nums;
  font-size: 1.02rem;
  font-weight: 700;
  color: var(--primary-dark);
  letter-spacing: 0.01em;
  overflow-wrap: anywhere;
}

.rib-copy {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  margin-top: 2px;
  padding: 8px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--surface);
  color: var(--primary-dark);
  font-size: 0.84rem;
  font-weight: 700;
  transition: border-color 0.18s ease, background 0.18s ease;
}

.rib-copy:hover {
  border-color: var(--primary);
  background: var(--primary-soft);
}

.rib-copy.is-copied {
  border-color: var(--primary);
  background: var(--primary);
  color: #ffffff;
}

/* --- Étape 2 : l'agence et la phrase à dire ------------------------------ */

.versement-carry {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin: 0 0 16px;
  padding: 0;
}

.versement-carry li {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--surface-2);
}

.carry-ico {
  display: grid;
  place-items: center;
  color: var(--primary);
}

.carry-text {
  display: grid;
  gap: 0;
  font-size: 0.88rem;
  font-weight: 700;
}

.carry-text strong {
  color: var(--primary-dark);
}

.carry-text em {
  font-style: normal;
  font-size: 0.86rem;
  font-weight: 500;
  color: var(--muted);
}

/* La bulle de guichet : c'est la pièce qui lève l'appréhension. Elle porte la
   phrase telle qu'elle se prononce, en grand, avec une pointe vers le bas pour
   se lire comme une parole et non comme un encadré de plus. */
.guichet {
  margin: 0 0 14px;
}

.guichet-intro {
  display: grid;
  gap: 1px;
  margin-bottom: 8px;
}

.guichet-intro .ar {
  font-size: 0.98rem;
  font-weight: 700;
  color: var(--primary-dark);
}

.guichet-intro em {
  font-style: normal;
  font-size: 0.86rem;
  color: var(--muted);
}

.guichet-bulle {
  position: relative;
  margin: 0 0 16px;
  padding: 16px 20px;
  border: 1px solid var(--primary);
  border-radius: var(--radius);
  background: var(--primary-soft);
  color: var(--text);
  font-family: var(--font-ar);
  font-size: 1.28rem;
  font-weight: 700;
  line-height: 1.9;
  direction: rtl;
  unicode-bidi: isolate;
  text-align: left;
}

.guichet-bulle::after {
  content: '';
  position: absolute;
  left: 32px;
  bottom: -9px;
  width: 15px;
  height: 15px;
  transform: rotate(45deg);
  border-right: 1px solid var(--primary);
  border-bottom: 1px solid var(--primary);
  background: var(--primary-soft);
}

.guichet-trad {
  margin: 0;
  color: var(--muted);
  font-size: 0.88rem;
}

/* --- Étape 3 : le reçu-témoin -------------------------------------------- */

.recu-zone {
  display: grid;
  grid-template-columns: minmax(0, 260px) minmax(0, 1fr);
  gap: 20px;
  align-items: start;
}

/* Ce n'est pas un document, c'est un schéma : il porte son étiquette
   « Exemple », des valeurs manifestement fictives, et aucune identité de
   banque. Il n'existe que pour rendre les quatre lignes reconnaissables. */
.recu {
  margin: 0;
}

/* Le papier lui-même. La légende reste en dehors : enfermée dans le cadre,
   elle se lisait comme une ligne imprimée du reçu. */
.recu-papier {
  position: relative;
  padding: 30px 16px 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  /* Teinte papier — le ticket est posé sur une carte blanche : en blanc pur,
     sa forme ne se détachait pas de son support. */
  background: #f8f8f6;
  box-shadow: var(--shadow-sm);
}


.recu-tag {
  position: absolute;
  top: 8px;
  left: 12px;
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--surface-2);
  color: var(--muted);
  font-size: 0.68rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

.recu-tag .ar {
  text-transform: none;
  letter-spacing: 0;
  font-size: 0.8rem;
}

.recu-entete {
  display: grid;
  gap: 2px;
  padding-bottom: 9px;
  margin-bottom: 9px;
  border-bottom: 1px dashed var(--border);
  text-align: center;
}

.recu-entete strong {
  font-size: 0.8rem;
  letter-spacing: 0.09em;
}

.recu-entete span {
  color: var(--muted);
  font-size: 0.72rem;
}

.recu-lignes {
  display: grid;
  gap: 3px;
  margin: 0;
  font-family: 'Consolas', 'SFMono-Regular', 'Menlo', monospace;
  font-size: 0.76rem;
}

.recu-ligne {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  padding: 4px 6px;
  border-radius: var(--radius-sm);
}

.recu-ligne dt {
  color: var(--muted);
}

.recu-ligne dd {
  margin: 0;
  font-weight: 700;
  text-align: right;
  overflow-wrap: anywhere;
}

/* Les quatre lignes que la photo doit rendre lisibles. */
.recu-ligne.is-cle {
  background: var(--primary-soft);
  box-shadow: inset 2px 0 0 var(--primary);
}

.recu-ligne.is-cle dd {
  color: var(--primary-dark);
}

.recu figcaption {
  margin-top: 14px;
  color: var(--muted);
  font-size: 0.8rem;
  line-height: 1.55;
}

.recu-aside {
  min-width: 0;
}

.recu-check {
  list-style: none;
  display: grid;
  gap: 7px;
  margin: 0 0 16px;
  padding: 0;
}

.recu-check li {
  display: flex;
  align-items: baseline;
  gap: 9px;
  font-size: 0.9rem;
  font-weight: 700;
}

.recu-check svg {
  flex: none;
  color: var(--primary);
  transform: translateY(2px);
}

.recu-check em {
  font-style: normal;
  font-weight: 500;
  color: var(--muted);
}

/* Le numéro WhatsApp est une MENTION, pas une commande : le lien wa.me a été
   retiré volontairement en juillet 2026. Ni bordure ni fond de bouton — le
   design system interdit ce qui ressemble à un bouton sans en être un. */
.wa-numero {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0;
  padding: 12px 0 0;
  border-top: 1px solid var(--border);
}

.wa-ico {
  display: grid;
  place-items: center;
  color: var(--primary);
}

.wa-texte {
  display: grid;
  gap: 0;
  min-width: 0;
}

.wa-libelle {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 7px;
  color: var(--muted);
  font-size: 0.82rem;
  font-weight: 700;
}

.wa-libelle em {
  font-weight: 500;
  font-size: 0.86rem;
}

.wa-texte strong {
  font-family: 'Consolas', 'SFMono-Regular', 'Menlo', monospace;
  font-variant-numeric: tabular-nums;
  font-size: 1.02rem;
  color: var(--primary-dark);
  letter-spacing: 0.02em;
}

/* --- Solutions de repli et avertissements -------------------------------- */

.versement-plus {
  display: grid;
  gap: 18px;
  margin-top: 18px;
}

.versement-alt h3,
.versement-garde h3 {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 10px;
  margin: 0 0 12px;
}

.versement-alt h3 .ar,
.versement-garde h3 .ar {
  font-size: 1.14rem;
  font-weight: 700;
}

.versement-alt h3 em,
.versement-garde h3 em {
  font-family: var(--font-body);
  font-style: normal;
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--muted);
}

.alt-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 14px;
}

.alt-card {
  display: grid;
  gap: 7px;
  padding: 16px 18px;
  border: 1px solid var(--border);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius-md);
  background: var(--surface);
}

.alt-ico {
  color: var(--accent);
}

.alt-card h4 {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 8px;
  margin: 0;
  font-size: 0.98rem;
}

.alt-card h4 .ar {
  font-size: 0.94rem;
  font-weight: 500;
  color: var(--muted);
}

.alt-card p {
  margin: 0;
  color: var(--muted);
  font-size: 0.88rem;
}

.versement-garde {
  padding: 18px 20px;
  border: 1px solid var(--danger);
  border-radius: var(--radius);
  background: #fdf6f6;
}

.versement-garde .garde-ico {
  display: grid;
  place-items: center;
  color: var(--danger);
  transform: translateY(3px);
}

.versement-garde ul {
  list-style: none;
  display: grid;
  gap: 12px;
  margin: 0;
  padding: 0;
}

.versement-garde li {
  display: grid;
  gap: 1px;
  padding-left: 13px;
  border-left: 2px solid var(--danger);
}

.versement-garde li .ar {
  font-size: 1rem;
  color: var(--text);
}

.versement-garde li em {
  font-style: normal;
  font-size: 0.87rem;
  color: var(--muted);
  line-height: 1.55;
}

/* --- Replis étroits ------------------------------------------------------ */

@media (max-width: 860px) {
  .rib-grid,
  .alt-grid {
    grid-template-columns: 1fr;
  }
  .recu-zone {
    grid-template-columns: 1fr;
  }
  .recu {
    max-width: 320px;
  }
}

@media (max-width: 620px) {
  .versement-recap {
    grid-template-columns: 1fr;
    align-items: start;
  }
  .versement-step {
    grid-template-columns: 1fr;
    gap: 10px;
    padding: 18px 16px;
  }
  .versement-head h2 .ar {
    font-size: 1.6rem;
  }
  .guichet-bulle {
    font-size: 1.12rem;
    padding: 14px 16px;
  }
}

/* --------------------------------------------------------------------------
   LIEN FACEBOOK — pied de page, sur toutes les pages

   Il vit dans le `.site-footer` de index.html, hors de `#app` : il suit donc le
   site partout, sans qu'aucune vue ait à le rendre et sans disparaître à chaque
   rendu. Le tracé est le « f » officiel, PLEIN : il ne peut pas passer par
   svgIcon(), dont le gabarit est en trait (`fill: none`, `stroke`).
   -------------------------------------------------------------------------- */

.fb-lien {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  margin-top: 12px;
  border-radius: var(--radius-sm);
  text-decoration: none;
}

/* `.site-footer span { display: block }` poserait le glyphe et le libellé sur
   deux lignes. On les remet en ligne ici, sans toucher à la règle générale. */
.site-footer .fb-lien span {
  display: inline-flex;
  align-items: center;
}

.fb-mark {
  flex-shrink: 0;
  /* Bleu de marque Facebook — la seule valeur du site hors palette, et posée
     sur le glyphe seul : un logo se reconnaît à sa couleur. */
  color: #1877f2;
}

.fb-libelle {
  font-size: 0.9rem;
}

.fb-lien:hover .fb-libelle,
.fb-lien:focus-visible .fb-libelle {
  text-decoration: underline;
}

.fb-lien:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 3px;
}

/* --------------------------------------------------------------------------
   LE MODULE OUVERT À TOUS

   Un module entier lisible sans compte ni paiement (voir le drapeau `free` du
   catalogue d'app.js et sa jumelle `estGratuit()` des règles Firestore). Il
   doit se voir — un échantillon qu'il faut chercher ne sert à rien —, et il
   doit se voir SANS que la page prenne le ton d'une promotion : l'étudiant
   vient lire, pas écouter une offre.

   D'où un seul écart au design system, et il est mesuré : la pastille
   « Gratuit » porte l'APLAT de `--primary` là où le site n'emploie que des
   fonds pâles. C'est l'exception — un module sur vingt-cinq —, et c'est la
   mécanique déjà retenue pour les badges de maintenance : une seule famille de
   couleur, le remplissage distingue le cas rare du cas ordinaire. Blanc sur
   `--primary` (#1e6b47) : contraste 6,4:1, au-delà du seuil AA.
   -------------------------------------------------------------------------- */

/* ---- La pastille, une seule définition pour ses trois emplacements ------- */
.module-gratuit-tag,
.access-card-tag,
.mo-pastille,
.bg-pastille {
  display: inline-block;
  padding: 2px 9px;
  border-radius: 999px;
  background: var(--primary);
  color: #fff;
  font-style: normal;
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  white-space: nowrap;
}

/* ---- Menu latéral : la ligne du module ---------------------------------- */
/* La pastille se pose EN LIGNE, derrière le titre, et non sur une ligne à
   elle : `.module-list.open` a un plafond de hauteur (voir sa règle), une
   ligne de plus qu'il ne couvre tronquerait un module en silence — vérifié
   sur pièce le 20 septembre 2026 (voir le commentaire à cette règle). */
.module-link .module-gratuit-tag {
  margin-left: 6px;
  vertical-align: 1px;
}

.module-link.gratuit {
  border-left-color: var(--primary);
}

/* ---- Carte de la barre latérale (visiteur non connecté) ----------------- */
.access-card-tag {
  /* Sur le fond `--primary-dark` de la carte, l'aplat `--primary` se
     distinguerait mal : on inverse. Vert foncé sur blanc, 8,1:1. */
  margin-bottom: 9px;
  background: #fff;
  color: var(--primary-dark);
}

/* UN LIEN PAR MODULE OUVERT, empilés : la carte est visible sur toutes les
   pages, c'est le rappel permanent, et elle doit les porter tous. Chaque lien
   nomme son semestre en seconde ligne — sans quoi « Histologie Embryologie » et
   « Ecologie » se lisent comme deux entrées sans rapport. */
.access-card-lien {
  display: block;
  margin-top: 8px;
  padding: 8px 13px;
  border-radius: var(--radius-sm);
  background: #fff;
  color: var(--primary-dark);
  font-size: 0.88rem;
  font-weight: 700;
  line-height: 1.3;
  text-decoration: none;
}

.access-card-lien em {
  display: block;
  font-style: normal;
  font-weight: 500;
  font-size: 0.76rem;
  opacity: 0.72;
}

.access-card-lien:hover,
.access-card-lien:focus-visible {
  background: var(--primary-soft);
}

/* La ligne qui parle de paiement vient APRÈS, et plus bas en contraste : elle
   informe, elle ne sollicite pas. */
.access-card .access-card-suite {
  margin-top: 11px;
  padding-top: 10px;
  border-top: 1px solid rgba(255, 255, 255, 0.18);
  color: rgba(255, 255, 255, 0.62);
  font-size: 0.82rem;
}

/* ---- Vitrine de l'accueil ----------------------------------------------- */
/* Même grille que `.learning-path`, juste au-dessus d'elle : la page garde son
   rythme, la section ne s'annonce pas par une mise en page étrangère. */
/* LA SECTION PORTE AUTANT DE CARTES QU'IL Y A DE MODULES OUVERTS.
   Elle était en deux colonnes « texte | liste », dessinée pour UN module ; à
   partir de deux (14 septembre 2026, un par semestre d'entrée) elle passe en
   en-tête commun surmontant une grille de cartes. Le auto-fit la laisse tenir à
   une carte comme à trois sans qu'aucune valeur ne soit à retoucher. */
.module-offert {
  padding: 28px;
  border: 1px solid rgba(30, 107, 71, 0.22);
  border-left: 3px solid var(--primary);
  border-radius: var(--radius);
  background: var(--primary-soft);
}

.mo-tete {
  max-width: 66ch;
  margin-bottom: 22px;
}

.module-offert .mo-pastille {
  margin-bottom: 10px;
}

.module-offert h2 {
  margin: 4px 0 10px;
}

.module-offert .lead {
  margin-bottom: 0;
}

.mo-cartes {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(290px, 1fr));
  gap: 18px;
  align-items: start;
}

/* Une carte est un bloc AUTONOME : son semestre, son titre, son contenu réel et
   son bouton. Un étudiant doit pouvoir lire la seule carte qui le concerne. */
.mo-carte {
  display: flex;
  flex-direction: column;
  padding: 18px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--surface);
  box-shadow: var(--shadow-sm);
}

.mo-carte .eyebrow {
  margin: 0 0 4px;
}

.mo-carte h3 {
  margin: 0 0 12px;
}

/* Le bouton est poussé en bas : deux cartes aux listes de longueurs
   différentes gardent leurs boutons alignés. */
.mo-carte .btn {
  margin-top: auto;
  align-self: flex-start;
}

/* La liste dit ce que le module CONTIENT — c'est elle qui convainc, pas
   l'accroche. Elle vit désormais DANS une carte, qui porte déjà le fond blanc
   et l'ombre : les lui laisser ici ferait une boîte dans une boîte. */
.mo-liste {
  display: grid;
  gap: 2px;
  margin: 0 0 16px;
  padding: 0;
  list-style: none;
}

.mo-liste li {
  display: grid;
  grid-template-columns: 26px 1fr;
  grid-template-rows: auto auto;
  align-items: baseline;
  column-gap: 8px;
  padding: 9px 0;
  border-radius: var(--radius-sm);
}

.mo-liste li + li {
  border-top: 1px solid var(--border);
}

.mo-icone {
  grid-row: 1 / span 2;
  align-self: start;
  padding-top: 2px;
  color: var(--primary);
  line-height: 0;
}

.mo-liste strong {
  font-size: 0.95rem;
}

.mo-liste em {
  grid-column: 2;
  color: var(--muted);
  font-style: normal;
  font-size: 0.85rem;
  line-height: 1.5;
}

/* ---- Bandeau en tête du module ------------------------------------------ */
/* Il dit ce qui est rare — qu'on lit sans compte — et rien d'autre. Aucun
   bouton : la page sert à lire, la suite se propose en bas. */
.bandeau-gratuit {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin: 0 0 14px;
  padding: 10px 14px;
  border: 1px solid rgba(30, 107, 71, 0.22);
  border-radius: var(--radius-md);
  background: var(--primary-soft);
  color: var(--primary-dark);
  font-size: 0.9rem;
  font-weight: 600;
}

/* ---- Pied du module : la transition vers les modules réservés ----------- */
/* Sobre par construction : elle vient APRÈS la lecture, elle rappelle ce que
   l'étudiant vient de vérifier lui-même, et elle ne se montre pas à qui a déjà
   un accès. */
.suite-gratuit {
  padding: 22px 24px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
}

.suite-gratuit h2 {
  margin: 0 0 8px;
  font-size: 1.45rem;
}

.suite-gratuit p {
  margin: 0 0 16px;
  max-width: 62ch;
  color: var(--muted);
  line-height: 1.7;
}

/* Le renvoi vers l'autre module ouvert, posé entre le texte et les boutons :
   il se lit comme une information, pas comme une troisième commande. */
.suite-autre-gratuit {
  margin: 0 0 16px;
  padding: 10px 14px;
  border-left: 2px solid var(--primary);
  background: var(--primary-soft);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  font-size: 0.9rem;
}

.suite-gratuit .suite-autre-gratuit a {
  color: var(--primary-dark);
  font-weight: 700;
}

.suite-gratuit .actions {
  margin: 0;
}

/* ---- Rappel devant un paywall ------------------------------------------- */
/* Un visiteur qui bute sur un module fermé a besoin d'une porte ouverte avant
   d'avoir besoin d'un formulaire. */
.locked .locked-gratuit {
  margin: 14px 0 0;
  padding-top: 12px;
  border-top: 1px solid var(--border);
  color: var(--muted);
  font-size: 0.9rem;
}

.locked .locked-gratuit a {
  color: var(--primary-dark);
  font-weight: 700;
}

/* ---- Page Paiement ------------------------------------------------------ */
/* Le rang d'un semestre compte ses modules PAYANTS : sans cette ligne, S3
   dirait « 5 modules » quand le catalogue en montre 6, et l'écart se lirait
   comme une erreur. */
.semester-price-note {
  margin: 10px 0 0;
  color: var(--muted);
  font-size: 0.82rem;
  line-height: 1.55;
}

.semester-price-note a {
  color: var(--primary-dark);
  font-weight: 600;
}

@media (max-width: 900px) {
  .module-offert {
    padding: 22px;
  }
  .mo-cartes {
    grid-template-columns: 1fr;
    gap: 14px;
  }
}

/* =========================================================================
   TÉLÉPHONE : desserrer les cadres imbriqués (23 septembre 2026)
   =========================================================================
   Mesuré sur un téléphone de 375 px, corrigé d'un TD ouvert : le texte ne
   disposait que de 166 px. Cinq cadres emboîtés — .app-shell (marge 16),
   .content-area (18 + bordure), .module-card (22 + bordure), .maths-exercise
   (24 + bordure), .maths-solution (20 + filet de 4) — consommaient 209 px,
   plus de la moitié de l'écran. Or la plupart des étudiants arrivent par le
   navigateur de WhatsApp, donc sur téléphone.
   Même geste que la feuille d'impression : la carte du MODULE, posée dans la
   carte de la page, est un cadre dans un cadre — on la dissout (le contenu
   garde la marge de .content-area). Les cartes d'exercice et le filet du
   corrigé restent : ce sont eux qui disent où commence et finit un exercice.
   Rien ne change au-dessus de 640 px. */
@media (max-width: 640px) {
  .app-shell {
    width: calc(100% - 16px);
    margin: 12px auto;
  }
  .content-area {
    padding: 14px 12px;
  }
  #app > .module-card {
    padding: 0;
    border: 0;
    border-radius: 0;
    box-shadow: none;
    background: transparent;
  }
  .maths-exercise {
    padding: 16px 14px;
    border-radius: 12px;
  }
  .maths-solution {
    padding: 14px 12px;
    border-left-width: 3px;
  }
}

/* ── Sommaire flottant des résumés (installerSommaireResume, app.js) ──
   Bouton « ☰ Sommaire » en bas à droite + « ↑ » ; panneau en fenêtre sur
   ordinateur, en feuille montante sur téléphone. Posé sur le <body> (voir le
   commentaire d'app.js : .content-area capture les position: fixed). */
.sommaire-flottant {
  position: fixed;
  right: 18px;
  bottom: 18px;
  z-index: 50;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 8px;
}
.sommaire-fab {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  max-width: min(320px, calc(100vw - 36px));
  border: 0;
  border-radius: 999px;
  padding: 11px 16px;
  background: var(--primary);
  color: #fff;
  font-family: inherit;
  font-size: 0.85rem;
  font-weight: 700;
  white-space: nowrap;
  box-shadow: 0 8px 22px rgba(20, 80, 50, 0.32);
  cursor: pointer;
}
.sommaire-fab small {
  overflow: hidden;
  text-overflow: ellipsis;
  font-weight: 600;
  opacity: 0.85;
}
.sommaire-fab:hover { background: var(--primary-dark); }
.sommaire-fab:focus-visible,
.sommaire-haut:focus-visible,
.sommaire-panneau [data-cible]:focus-visible {
  outline: 3px solid rgba(30, 107, 71, 0.35);
  outline-offset: 2px;
}
.sommaire-haut {
  width: 40px;
  height: 40px;
  border: 1px solid var(--border);
  border-radius: 50%;
  background: var(--surface);
  color: var(--primary-dark);
  font-size: 1.05rem;
  box-shadow: 0 4px 12px rgba(20, 50, 35, 0.14);
  cursor: pointer;
}
.sommaire-panneau {
  position: fixed;
  right: 18px;
  bottom: 76px;
  z-index: 55;
  width: 340px;
  max-height: min(70vh, 560px);
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 8px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 14px;
  box-shadow: 0 18px 40px rgba(20, 50, 35, 0.22);
}
.sommaire-panneau[hidden],
.sommaire-voile[hidden] { display: none; }
.sommaire-voile {
  position: fixed;
  inset: 0;
  z-index: 54;
  background: rgba(15, 30, 22, 0.28);
}
.sommaire-bloc + .sommaire-bloc {
  margin-top: 4px;
  padding-top: 2px;
  border-top: 1px solid var(--border);
}
/* Des boutons (voir app.js : un lien « #… » serait pris pour une route). */
.sommaire-panneau [data-cible] {
  display: flex;
  align-items: baseline;
  gap: 8px;
  width: 100%;
  padding: 5px 8px;
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--text);
  font-family: inherit;
  font-size: 0.8rem;
  font-weight: 400;
  line-height: 1.3;
  text-align: left;
  cursor: pointer;
}
.sommaire-panneau [data-cible]:hover { background: var(--primary-soft); color: var(--primary-dark); }
.sommaire-panneau [data-cible].actif { background: var(--primary-soft); color: var(--primary-dark); font-weight: 700; }
.sommaire-panneau .sommaire-chapitre {
  padding: 7px 8px 4px;
  font-family: var(--font-heading);
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--primary-dark);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.sommaire-liste { list-style: none; margin: 0; padding: 0; }
.sommaire-num {
  min-width: 18px;
  font-size: 0.68rem;
  font-weight: 700;
  color: var(--primary);
  font-variant-numeric: tabular-nums;
}
@media (max-width: 640px) {
  .sommaire-flottant { right: 14px; bottom: 14px; }
  .sommaire-panneau {
    left: 0;
    right: 0;
    bottom: 0;
    width: auto;
    max-height: 72vh;
    padding: 10px 8px 18px;
    border-radius: 16px 16px 0 0;
  }
}
@media print {
  .sommaire-flottant,
  .sommaire-panneau,
  .sommaire-voile { display: none !important; }
}
/* Résumé découpé en chapitres seulement : une liste simple, casse normale. */
.sommaire-simple .sommaire-bloc + .sommaire-bloc { margin-top: 0; padding-top: 0; border-top: 0; }
.sommaire-simple .sommaire-chapitre {
  padding: 6px 8px;
  font-family: inherit;
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--text);
  text-transform: none;
  letter-spacing: 0;
}
.sommaire-simple .sommaire-chapitre.actif { color: var(--primary-dark); font-weight: 700; }
