/* Direction graphique "Masterio" — sous-marque My Sherpa (voir Claude Design, projet
   "Plateforme éducative belgique française", fichier Masterio.dc.html, importé le 2026-08-23).
   DM Sans, bleu My Sherpa #005293 comme identité, accent ambre pour la gamification, cartes à
   bordure fine plutôt qu'à ombre, rayons généreux (univers enfant). Remplace la direction
   provisoire "Baloo 2 / sable" précédente — voir AGENTS.md, section "Direction visuelle".
   Les noms des variables historiques (--ink, --blue, --green…) sont conservés pour ne pas
   toucher aux templates ; seules leurs valeurs changent. */
@import url("https://fonts.googleapis.com/css2?family=DM+Sans:ital,opsz,wght@0,9..40,100..1000;1,9..40,100..1000&display=swap");

:root{
  --font-sans:"DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;

  /* --- Surfaces --- */
  --sand:#EEF3F8;            /* fond de la page, hors carte */
  --cream:#FFFFFF;           /* conteneur .page */
  --white:#fff;

  /* --- Encre --- */
  --ink:#10243A;
  --ink-soft:#41586E;
  --muted:#7D8FA0;
  --line:#E2EBF3;
  --line-strong:#CFDDE9;
  --dot:#E2EBF3;
  --track:#E2EBF3;

  /* --- Bleu (identité) --- */
  --blue:#005293;
  --blue-dark:#004178;
  --blue-bg:#E8F1F8;
  --blue-line:#CFE1EF;

  /* --- Vert (réussite) --- */
  --green:#3FB878;
  --green-bg:#E9F9F0;
  --green-line:#BFE9D3;
  --green-dark:#0F5C3C;

  /* --- Rouge (erreur) --- */
  --red:#FF6B4A;
  --red-bg:#FFEDE8;
  --red-line:#FFD3C6;
  --red-dark:#B23A1E;

  /* --- Ambre (gamification / action) --- */
  --amber:#FFB020;
  --amber-bg:#FFF3DE;
  --amber-line:#FFE1AA;
  --amber-dark:#B26E00;

  /* --- Rayons --- */
  --radius-xs:4px;
  --radius-sm:12px;
  --radius:20px;
  --radius-lg:28px;
  --radius-xl:32px;
  --radius-pill:999px;

  /* --- Élévation --- */
  --shadow-card:0 1px 2px rgba(16,36,58,.04), 0 8px 20px rgba(16,36,58,.06);
  --shadow-lift:0 2px 4px rgba(16,36,58,.06), 0 14px 32px rgba(16,36,58,.10);
  --shadow-press:inset 0 -3px 0 rgba(16,36,58,.12);
  --shadow-page:0 24px 60px rgba(16,36,58,.10);

  /* --- Mouvement --- */
  --ease:ease-in-out;
  --dur-fast:.2s;
  --dur-base:.3s;
  --focus-ring:rgba(0,82,147,.25);
}
*{box-sizing:border-box;}
html,body{margin:0;padding:0;}
img{max-width:100%; height:auto;}
body{
  background:var(--white);
  font-family:var(--font-sans);
  color:var(--ink);
  min-height:100vh;
  -webkit-font-smoothing:antialiased;
  /* Coupe le pull-to-refresh : en plein milieu d'un quiz il rechargerait la page, et l'état d'un
     essai en cours (state.answers, série piochée, chrono de lecture) n'est QUE de la mémoire JS,
     jamais persistée côté serveur (voir AGENTS.md) — l'essai serait perdu sans prévenir. Coupe
     aussi le rebond élastique en bas de page, qui trahit la page web dans une PWA installée. */
  overscroll-behavior:none;
  /* Retire le flash gris au tap sur iOS/Android : le retour visuel est déjà géré par nos propres
     états :active/.selected, celui du navigateur en plus fait "lien hypertexte", pas "bouton d'app". */
  -webkit-tap-highlight-color:transparent;
}
/* Empêche iOS de gonfler tout seul la taille du texte (rotation paysage notamment) : la mise en page
   du quiz est calibrée au pixel près en hauteur (voir body.quiz-mode plus bas), un texte réajusté
   par le navigateur fait déborder la dernière option hors de l'écran. */
html{-webkit-text-size-adjust:100%; text-size-adjust:100%;}
/* Supprime le double-tap-to-zoom. C'est le vrai coupable au quotidien sur ce site : dans un quiz où
   l'enfant tape vite, deux taps rapprochés (deux réponses, ou un tap répété sur un bouton qui n'a
   pas encore réagi) sont interprétés comme un double-tap et zooment la page. `manipulation` laisse
   le scroll ET le pinch intacts — c'est le geste involontaire qu'on retire, pas la capacité de
   zoomer, qui reste gérée par le viewport (voir base.html). Sélecteur universel volontaire :
   touch-action ne s'hérite pas, le poser sur html/body ne couvrirait pas les boutons eux-mêmes,
   qui sont précisément les éléments qu'on tape. */
*{touch-action:manipulation;}
a{color:var(--blue); text-decoration:none;}
a:hover{color:var(--green-dark);}
h1,h2{font-family:var(--font-sans); color:var(--ink); font-weight:500; margin:0 0 8px; letter-spacing:-.01em;}
h1{font-size:38px; line-height:1.12;}
h2{font-size:24px; line-height:1.2;}

.utility-bar{
  display:flex; justify-content:space-between; gap:12px; flex-wrap:wrap;
  background:var(--blue-bg); color:var(--ink-soft); font-size:13px; font-weight:500;
  padding:8px calc(28px + env(safe-area-inset-right, 0px)) 8px calc(28px + env(safe-area-inset-left, 0px));
}
.utility-bar-accent{color:var(--blue); font-weight:700;}

.topbar{
  display:flex; align-items:center; gap:16px; flex-wrap:wrap; justify-content:space-between;
  background:var(--white); border-bottom:1px solid var(--line);
  /* env(safe-area-inset-*) : évite que le contenu ne passe sous l'encoche/coins arrondis en mode
     PWA installée plein écran (viewport-fit=cover, voir base.html) ; no-op ailleurs (vaut 0). */
  padding:calc(16px + env(safe-area-inset-top, 0px)) calc(28px + env(safe-area-inset-right, 0px)) 16px calc(28px + env(safe-area-inset-left, 0px));
}
.brand{display:flex; align-items:center;}
.brand-logo{height:30px; width:auto; display:block;}

/* Un seul bandeau (base.html) : à droite du logo, soit la nav compte (connecté à une classe), soit
   la nav marketing (visiteur anonyme) — jamais les deux, jamais de second bandeau en dessous. */
.topbar-account{display:flex; align-items:center; gap:10px; flex-wrap:wrap;}
.topbar-pseudo{font-size:14px; font-weight:700; color:var(--ink-soft);}
.topbar-account-links{display:flex; gap:16px; font-size:13px; font-weight:700; margin-left:8px;}
.topbar-account-links a{color:var(--ink-soft);}
.topbar-account-links a:hover{color:var(--blue);}
.topbar-marketing{display:flex; align-items:center; gap:22px;}
.topbar-marketing a:not(.btn){font-weight:600; font-size:15px; color:var(--ink-soft);}
.topbar-marketing a:not(.btn):hover{color:var(--blue);}
/* "Se connecter" reste un lien texte, pas un bouton — seul "Créer un compte gratuit" est un vrai
   CTA (écho fidèle de la maquette : un seul bouton plein dans la nav, jamais deux). */
.topbar-link{font-weight:700 !important; color:var(--blue) !important;}
.btn-sm{min-height:auto; padding:9px 18px; font-size:14px;}
.cta-short{display:none;}

/* Menu bas mobile (espace classe connecté) : remplace la nav de compte du header sous 900px, voir
   media query plus bas. Masqué par défaut (desktop) — .bottom-nav n'existe que si nav_account. */
.bottom-nav{display:none;}

/* Plein écran, bord à bord (header/footer) — .page centre juste le contenu à une largeur de lecture
   confortable, sans carte/bordure/ombre autour (voir base.html). */
.page{
  max-width:1180px; margin:0 auto; padding:36px 40px 48px;
}

.footer{
  text-align:center; font-size:13px; color:var(--muted); font-weight:600;
  padding:20px calc(18px + env(safe-area-inset-right, 0px)) calc(28px + env(safe-area-inset-bottom, 0px)) calc(18px + env(safe-area-inset-left, 0px));
}
.lead{color:var(--ink-soft); font-weight:400; margin:0 0 18px; font-size:17px; line-height:1.6;}
.empty{color:var(--muted); font-weight:600;}
.tiny{font-size:13px; color:var(--muted); margin-top:24px;}
.hint{font-size:14px; color:var(--muted); font-weight:500; margin:0 0 12px;}
.hint-inline{font-weight:500; color:var(--muted); font-size:12px;}
.back-link{display:inline-block; margin-bottom:14px; font-weight:700; font-size:14px;}
/* Fil d'Ariane (matiere.html) : un seul "←" au début, puis un ou plusieurs crumbs séparés par "›".
   engine.js étend ce nav en ajoutant un crumb (ex. le nom de la matière) sur le hub d'un thème plutôt
   que d'afficher un 2e "← Retour" séparé — retour utilisateur : deux "←" empilés avec des styles
   différents (l'un <a>, l'autre <button> sans reset) étaient indiscernables et incohérents visuellement.
   .crumb-btn reprend exactement le rendu d'un <a> du nav (un <button> n'hérite pas de la couleur/police
   des liens par défaut) pour que tous les crumbs soient visuellement identiques, cliquable ou non. */
.breadcrumb{
  display:flex; align-items:center; flex-wrap:wrap; gap:6px; margin-bottom:14px;
  font-weight:700; font-size:14px; color:var(--blue);
}
.breadcrumb a, .breadcrumb .crumb-btn{
  color:var(--blue); text-decoration:none; font:inherit; background:none; border:none; padding:0;
  cursor:pointer;
}
.breadcrumb a:hover, .breadcrumb .crumb-btn:hover{text-decoration:underline;}
.breadcrumb .crumb-sep{color:var(--muted); font-weight:500;}
/* Bouton retour rond (écrans auth, hide_topbar) — écho du bouton "‹" de la maquette (écrans isAuth
   mobile), à côté du logo dans le header compact plutôt qu'un lien texte "← Accueil". */
.back-link-icon{
  display:inline-flex; align-items:center; justify-content:center; width:40px; height:40px; flex:none;
  border-radius:var(--radius-pill); border:1px solid var(--line); background:var(--white);
  color:var(--ink); font-size:18px; text-decoration:none; box-shadow:var(--shadow-card);
}
.back-link-icon:hover{background:var(--blue-bg); color:var(--blue);}
/* Bouton retour + logo, écrans auth (connexion/inscription/parent_connexion) — sur desktop le logo
   normal est caché ici (déjà affiché dans .auth-side, voir plus bas) ; sur mobile .auth-side disparaît
   entièrement (la maquette ne montre jamais le panneau bleu hors desktop) et c'est ce bandeau qui porte
   le logo à la place, en couleurs normales sur fond clair — pas besoin de pastille blanche ici. */
.auth-top-row{display:flex; align-items:center; margin-bottom:14px;}
.auth-top-row-logo{display:none;}
/* Ligne unique "Étape N sur 3 · Libellé" (mobile seulement — voir .wizard-labels caché sous 480px
   dans la media query plus bas ; miroir de signupStepLabel vs signupSteps dans Masterio.dc.html). */
.wizard-step-mobile{display:none; font-size:13px; font-weight:700; color:var(--blue);}
.loading{color:var(--muted); font-weight:600;}

/* Bandeau « géré par un parent » (voir base.html, nav_parent.siblings) : switch fratrie + retour
   gestion, sans jamais redemander de mot de passe. Toujours visible (desktop ET mobile) — c'est
   la seule voie retour vers /parent une fois topbar-account-links caché sous 900px. Volontairement
   compact et sur une seule ligne (jamais de wrap, le libellé se tronque plutôt que de repasser à la
   ligne) : ce bandeau s'affiche sur la quasi-totalité des sessions élève dès qu'un parent est
   « entré » dans un profil, donc jamais aussi lourd visuellement qu'une alerte ponctuelle. */
.child-switch-bar{
  display:flex; align-items:center; gap:8px; flex-wrap:nowrap;
  background:var(--blue-bg); border-radius:var(--radius-sm);
  padding:5px 10px; margin-bottom:14px; font-size:12px;
}
.child-switch-label{
  color:var(--blue-dark); font-weight:600; margin-right:auto;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; min-width:0;
}
.child-switch-avatars{display:flex; align-items:center; gap:4px; flex-shrink:0;}
.child-switch-form{display:contents;}
.child-switch-avatar{
  display:flex; align-items:center; justify-content:center; width:22px; height:22px;
  font-size:12px; line-height:1; border-radius:var(--radius-pill); border:1px solid var(--blue-line);
  background:var(--white); cursor:pointer; padding:0;
}
.child-switch-avatar.is-current{border-color:var(--blue); box-shadow:0 0 0 2px var(--blue-bg), 0 0 0 2px var(--blue);}
.child-switch-avatar:not(.is-current):hover{border-color:var(--blue);}
.child-switch-manage{color:var(--blue-dark); font-weight:600; white-space:nowrap; flex-shrink:0;}
.child-switch-manage:hover{color:var(--blue);}

.flashes{margin-bottom:16px;}
.flash{border-radius:var(--radius-sm); padding:14px 18px; font-weight:600; margin-bottom:8px; border:1px solid transparent;}
.flash-error{background:var(--red-bg); border-color:var(--red-line); color:var(--red-dark);}
.flash-success{background:var(--green-bg); border-color:var(--green-line); color:var(--green-dark);}
.flash-info{background:var(--blue-bg); border-color:var(--blue-line); color:var(--blue-dark);}

.card{
  background:var(--white); border:1px solid var(--line); border-radius:var(--radius);
  padding:20px 22px; margin-bottom:18px; box-shadow:var(--shadow-card);
}
.school-list + .card{margin-top:24px;}
/* Classe utilitaire : elle doit gagner sur le display de N'IMPORTE quel composant, sinon elle ne
   masque rien. Sans !important, `.btn{display:inline-flex}` (déclaré plus bas, même spécificité,
   donc règle la plus tardive gagnante) l'emportait — et le bouton « Suivant → » du quiz, rendu avec
   la classe `hidden` par engine.js::renderQuestion(), restait visible avant même que l'enfant ait
   répondu. Ne pas retirer ce !important sans revérifier tous les usages de .hidden dans engine.js. */
.hidden{display:none !important;}

/* ---------- Badges pilule ---------- */
.pill{
  display:inline-flex; align-items:center; font-size:12px; font-weight:700; letter-spacing:.04em;
  text-transform:uppercase; border-radius:var(--radius-pill); padding:7px 14px;
}
.pill-amber{color:var(--amber-dark); background:var(--amber-bg);}
.pill-green{color:var(--green-dark); background:var(--green-bg);}
.pill-blue{color:var(--blue); background:var(--blue-bg);}
.pill-red{color:var(--red-dark); background:var(--red-bg);}
.pill-row{display:flex; gap:8px; flex-wrap:wrap; margin-bottom:18px;}

/* ---------- Accueil : hero + code de classe ---------- */
/* Bandeau teinté + décor "carré arrondi pivoté" derrière le hero — le seul motif décoratif de la
   charte (voir AGENTS.md / le design system Masterio), repris ici et sur .cta-banner/.auth-side. */
.hero-band{
  position:relative; overflow:hidden; background:var(--blue-bg);
  border-radius:var(--radius-xl); padding:44px 40px; margin-bottom:40px;
}
.hero-band::before{
  content:""; position:absolute; right:-6rem; top:-6rem; width:18rem; height:18rem;
  border-radius:4rem; transform:rotate(15deg); background:rgba(0,82,147,.07); pointer-events:none;
}
.hero{position:relative; display:grid; grid-template-columns:1.05fr .95fr; gap:44px; align-items:center;}
.hero-copy{display:flex; flex-direction:column; gap:18px;}
.code-form{display:flex; flex-direction:column; gap:10px; margin-top:6px; max-width:440px;}
.code-form label{font-size:15px; font-weight:600; color:var(--ink);}
.code-row{display:flex; gap:10px; flex-wrap:wrap;}
.code-row input{
  flex:1; font-family:var(--font-sans); font-size:16px; font-weight:600; color:var(--ink);
  min-height:52px; padding:14px 18px; background:var(--white); border:1.5px solid var(--line-strong);
  border-radius:var(--radius-sm); outline:none; transition:border-color var(--dur-fast) var(--ease);
}
.code-row input:focus{border-color:var(--blue); box-shadow:0 0 0 4px var(--focus-ring);}

/* ---------- Bulle Tenzing (mascotte) — composant générique, écho de TenzingBubble.jsx dans
   Masterio.dc.html : avatar rond + bulle de texte teintée, 3 tons. Remplace l'ancien
   .mascotte-intro (accueil uniquement) — réutilisé aussi sur mon_espace.html et matiere.html
   (rappel avant quiz / message de résultat, voir engine.js). */
.tenzing-bubble{
  display:flex; align-items:center; gap:14px; border-radius:var(--radius);
  padding:16px 20px; margin-bottom:14px;
}
.tenzing-bubble img{width:56px; height:56px; flex:none; border-radius:var(--radius-pill); background:var(--white); object-fit:contain;}
.tenzing-bubble-text{font-size:14.5px; line-height:1.5; font-weight:600;}
.tenzing-blue{background:var(--blue-bg);} .tenzing-blue .tenzing-bubble-text{color:var(--ink-soft);}
.tenzing-amber{background:var(--amber-bg);} .tenzing-amber .tenzing-bubble-text{color:var(--amber-dark);}
.tenzing-green{background:var(--green-bg);} .tenzing-green .tenzing-bubble-text{color:var(--green-dark);}
/* Variante "intro" (accueil) : plus grande, avec un titre au-dessus du texte. */
.tenzing-bubble.tenzing-intro img{width:74px; height:74px;}
.tenzing-intro-title{font-family:var(--font-sans); font-size:18px; font-weight:700; color:var(--blue); display:block;}

/* ---------- Étoiles de maîtrise (0 à 3) — écho de MasteryStars.jsx : pleine = ambre, vide = ligne. */
.mastery-stars{display:inline-flex; align-items:center; gap:3px; vertical-align:middle;}
.mastery-stars svg{display:block;}
.mastery-stars.sm svg{width:14px; height:14px;}
.mastery-stars.md svg{width:18px; height:18px;}

.preview-card{
  background:var(--white); border:1px solid var(--line); border-radius:var(--radius);
  padding:20px 22px; box-shadow:var(--shadow-card); margin-bottom:14px;
}
.preview-row{display:flex; gap:14px;}
.preview-row .preview-card{flex:1; margin-bottom:0;}
.preview-chip{width:44px; height:44px; border-radius:var(--radius-sm); display:grid; place-items:center; font-size:21px; margin-bottom:8px;}
.preview-name{font-family:var(--font-sans); font-size:17px; font-weight:700; display:block;}
.preview-meta{font-size:13px; color:var(--muted);}

/* ---------- Démo de quiz jouable sur l'accueil (voir index.html, #demoQuiz)
   Réutilise les vraies classes du quiz (.opt-btn/.opt-key/.correct/.wrong/.dim) plutôt que d'en
   inventer d'autres — l'aperçu montre alors exactement ce que l'enfant verra. Seule la mise en
   page change : 2 colonnes compactes pour tenir dans une carte du hero, contre une colonne pleine
   largeur dans le vrai quiz. */
.demo-quiz-options{display:grid; grid-template-columns:1fr 1fr; gap:8px; margin-top:12px;}
.demo-quiz-options .opt-btn{padding:12px 14px; gap:10px; font-size:15px; box-shadow:none;}
.demo-quiz-options .opt-key{width:26px; height:26px; font-size:13px;}
.demo-quiz-options .opt-btn:disabled{cursor:default;}
.demo-quiz-feedback{
  font-size:14px; line-height:1.5; font-weight:600; margin:12px 0 0;
  padding:10px 12px; border-radius:var(--radius-sm);
  /* Place réservée en permanence (2 lignes + padding) : sans ça, la carte grandit au clic et pousse
     la bulle de Tenzing vers le bas à chaque essai, puis remonte 5 s plus tard. */
  min-height:62px;
}
.demo-quiz-feedback.idle{background:transparent; color:var(--muted); font-weight:500;}
.demo-quiz-feedback.good{background:var(--green-bg); color:var(--green-dark);}
.demo-quiz-feedback.bad{background:var(--red-bg); color:var(--red-dark);}

.steps{display:grid; grid-template-columns:repeat(3,1fr); gap:20px; margin:36px 0;}
.step-num{font-family:var(--font-sans); font-size:28px; font-weight:800; color:var(--blue); display:block; margin-bottom:6px; line-height:1;}
.step-title{font-family:var(--font-sans); font-size:19px; font-weight:700; color:var(--ink); display:block; margin-bottom:6px;}
.step-text{font-size:15px; line-height:1.6; color:var(--ink-soft);}

.info-grid{display:grid; grid-template-columns:repeat(2,1fr); gap:16px; margin-bottom:32px;}
.info-card{border-radius:var(--radius); padding:22px 24px; font-size:16px; line-height:1.6; color:var(--ink);}
.info-card.plain{background:var(--sand); border:1px solid var(--line);}
.info-card.accent{background:var(--blue-bg); border:1px solid var(--blue-line);}

.warn-box{
  background:var(--sand); border:1px solid var(--line); border-radius:var(--radius);
  padding:24px 26px; margin-bottom:24px;
}
.warn-title{display:flex; align-items:center; gap:10px; font-family:var(--font-sans); font-size:19px; font-weight:700; margin-bottom:14px; color:var(--ink);}
.warn-grid{display:grid; grid-template-columns:repeat(3,1fr); gap:20px;}
.warn-item-title{font-size:15px; font-weight:700; color:var(--amber-dark); display:block; margin-bottom:4px;}
.warn-item-text{font-size:14px; line-height:1.6; color:var(--ink-soft);}

.about-line{
  margin-top:8px; padding-top:18px; border-top:1px solid var(--line);
  font-size:14px; color:var(--ink-soft); line-height:1.6;
}

.browse-classes{margin-top:8px;}
.browse-classes summary{cursor:pointer; font-weight:700; font-size:14px; color:var(--blue); margin-bottom:14px;}

/* ---------- Grilles de cartes (classes / matières / thèmes) ---------- */
.school-list, .themes-grid, .matiere-grid{
  display:grid; grid-template-columns:repeat(auto-fill, minmax(220px, 1fr)); gap:16px;
}
.class-card{
  display:block; background:var(--white); border:1px solid var(--line); border-radius:var(--radius);
  padding:18px 20px; box-shadow:var(--shadow-card); transition:box-shadow var(--dur-base) var(--ease), transform var(--dur-base) var(--ease);
}
.class-card:hover{box-shadow:var(--shadow-lift); transform:scale(1.015);}
.class-card-wrap{position:relative;}
.class-card-edit{
  position:absolute; top:10px; right:10px; width:30px; height:30px; display:flex;
  align-items:center; justify-content:center; font-size:14px; text-decoration:none;
  background:var(--white); border:1px solid var(--line); border-radius:var(--radius-pill);
  box-shadow:var(--shadow-card);
}
.class-card-edit:hover{background:var(--blue-bg);}
.class-card-school{font-size:12px; font-weight:700; color:var(--muted); text-transform:uppercase; letter-spacing:.05em;}
.class-card-name{font-weight:700; font-family:var(--font-sans); font-size:18px; margin:4px 0 2px; color:var(--ink);}
.class-card-year{font-size:13px; color:var(--blue); font-weight:600;}

form label{display:block; font-weight:600; font-size:14px; margin-bottom:14px; color:var(--ink-soft);}
form input[type=text], form input[type=password], form input[type=email]{
  display:block; width:100%; margin-top:6px; min-height:52px; padding:14px 18px; font-size:16px;
  border:1.5px solid var(--line-strong); border-radius:var(--radius-sm); font-family:inherit; outline:none;
  color:var(--ink); background:var(--white); transition:border-color var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease);
}
form input[type=text]:focus, form input[type=password]:focus, form input[type=email]:focus{
  border-color:var(--blue); box-shadow:0 0 0 4px var(--focus-ring);
}
form select{
  display:block; width:100%; margin-top:6px; min-height:52px; padding:14px 18px; font-size:16px;
  border:1.5px solid var(--line-strong); border-radius:var(--radius-sm); font-family:inherit; outline:none;
  background:var(--white); color:inherit;
}
form select:focus{border-color:var(--blue); box-shadow:0 0 0 4px var(--focus-ring);}
textarea.code-editor{
  display:block; width:100%; margin-top:4px; padding:14px; font-size:13px; line-height:1.5;
  border:1.5px solid var(--line-strong); border-radius:var(--radius-sm); font-family:'SF Mono', Menlo, Consolas, monospace;
  resize:vertical; box-sizing:border-box; background:var(--white);
}
form input[type=file]{display:block; width:100%; margin-top:4px; font-size:13px;}
.inline-form{display:flex; gap:8px; align-items:center; flex-wrap:wrap;}
.inline-form input[type=text]{width:auto; display:inline-block; margin-top:0;}
fieldset.avatar-choice{border:none; padding:0; margin:0 0 16px;}
fieldset.avatar-choice legend{font-weight:600; font-size:14px; margin-bottom:8px; padding:0; color:var(--ink-soft);}
.avatar-option{display:inline-flex; align-items:center; gap:4px; margin:0 8px 8px 0; font-size:24px; cursor:pointer;}
.avatar-option input{margin:0;}

.btn{
  border:none; border-radius:var(--radius-pill); min-height:52px; padding:14px 26px;
  font-family:var(--font-sans); font-weight:700; font-size:16px; cursor:pointer; white-space:nowrap;
  display:inline-flex; align-items:center; justify-content:center; gap:8px;
  transition:transform var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.btn:hover{transform:scale(1.025);}
.btn:active{transform:scale(.98);}
.btn-primary{background:var(--blue); color:#fff; box-shadow:var(--shadow-press);}
.btn-primary:hover{background:var(--green-dark);}
.btn-accent{background:var(--amber); color:#3D2600; box-shadow:var(--shadow-press);}
.btn-accent:hover{background:var(--amber-dark); color:#fff;}
.btn-secondary{background:var(--white); color:var(--blue); border:1.5px solid var(--line-strong); box-shadow:none;}
.btn-secondary:hover{border-color:var(--blue);}
.btn-danger{background:var(--white); color:var(--red-dark); border:1.5px solid var(--red-line); box-shadow:none;}
.btn-danger:hover{background:var(--red-bg);}

/* Bouton stylé comme un simple lien texte (ex. "renvoyer un email" sur parent_verifier.html) — une
   action réelle (POST, donc pas un <a>) mais qui ne doit pas peser visuellement comme un .btn plein. */
.btn-link{
  background:none; border:none; padding:0; margin:0; font-family:var(--font-sans); font-weight:700;
  font-size:14px; color:var(--blue); cursor:pointer; text-decoration:underline;
}
.btn-link:hover{color:var(--blue-dark);}

/* Saisie du code de connexion à 6 chiffres (parent_verifier.html) : grand, espacé, centré — pensé
   pour se lire d'un coup d'œil en recopiant depuis l'email. */
.code-input{
  font-size:28px; font-weight:700; letter-spacing:10px; text-align:center;
  font-family:var(--font-sans);
}

/* Modal de confirmation avant déconnexion (base.html, <dialog> natif). */
.logout-modal{
  border:none; border-radius:var(--radius-lg); padding:0; max-width:360px; width:calc(100% - 40px);
  box-shadow:var(--shadow-lift);
}
.logout-modal::backdrop{background:rgba(16,36,58,.45);}
.logout-modal-body{padding:30px 28px 26px; text-align:center;}
.logout-modal-emoji{font-size:40px; display:block; margin-bottom:8px;}
.logout-modal-body h2{font-size:21px; margin-bottom:6px;}
.logout-modal-body p{color:var(--ink-soft); font-weight:400; font-size:14px; line-height:1.5; margin:0 0 22px;}
.logout-modal-actions{display:flex; gap:10px; justify-content:center;}
.logout-modal-actions .btn{flex:1; text-align:center;}

.streak-badge{
  display:flex; align-items:center; gap:6px; background:var(--amber-bg); color:var(--amber-dark);
  border-radius:var(--radius-pill); padding:8px 14px; font-size:14px; font-weight:700;
}
.avatar-badge{
  font-size:20px; width:36px; height:36px; border-radius:var(--radius-pill); background:var(--blue-bg);
  display:grid; place-items:center; flex:none;
}
.greeting-card{
  display:flex; align-items:center; gap:18px; margin-bottom:22px; flex-wrap:wrap;
}
.greeting-card img{width:82px; height:82px; flex:none; object-fit:contain;}
.greeting-bubble{
  position:relative; background:var(--blue-bg); border-radius:var(--radius);
  padding:16px 20px;
}
.greeting-bubble h2{font-size:24px; margin:0 0 4px; font-weight:700;}
.greeting-bubble span{font-size:16px; color:var(--ink-soft);}

.matiere-card{
  --accent:#005293;
  display:flex; flex-direction:column; gap:14px;
  background:var(--white); color:var(--ink); border:1px solid var(--line); border-radius:var(--radius);
  padding:20px; box-shadow:var(--shadow-card); transition:box-shadow var(--dur-base) var(--ease), transform var(--dur-base) var(--ease);
}
.matiere-card:hover{box-shadow:var(--shadow-lift); transform:scale(1.015);}
/* Matière `status: a_venir` (voir AGENTS.md « Matières annoncées à l'avance ») — reste cliquable
   (contrairement à .theme-card-soon, voir plus bas) : elle mène à une page d'explication, pas à un
   thème vide. Juste plus discrète pour ne pas se confondre avec une matière réellement jouable. */
.matiere-card-soon{opacity:.7;}
.matiere-card-top{display:flex; align-items:center; gap:14px;}
.matiere-emoji{
  font-size:24px; width:52px; height:52px; border-radius:var(--radius-sm); display:grid; place-items:center; flex:none;
  background:color-mix(in srgb, var(--accent) 14%, white);
}
.matiere-name{font-weight:700; font-family:var(--font-sans); font-size:18px; display:block;}
.matiere-desc{font-size:13px; color:var(--muted); display:block; margin-top:2px;}
/* Piste + barre de progression : mécanique partagée par .progress (quiz), .subject-progress
   (accueil/mon espace) et .wizard-progress (inscription) — seuls hauteur/marge/couleur varient
   d'un usage à l'autre, factorisés ici plutôt que dupliqués dans chaque bloc. */
.progress, .subject-progress, .wizard-progress{background:var(--track); border-radius:var(--radius-pill); overflow:hidden;}
.progress-bar, .subject-progress-bar, .wizard-progress-bar{height:100%; border-radius:var(--radius-pill); transition:width var(--dur-base) var(--ease);}
.subject-progress{height:8px;}
/* var(--accent) n'est défini que sur .matiere-card/.theme-card (voir plus bas) ; repli sur --blue
   pour l'usage "nu" de renderHome() dans engine.js, hors de ces deux contextes — sans ce repli la
   barre n'a aucune couleur de fond et reste invisible quel que soit son avancement réel (bug observé
   sur /programme/.../<matiere> : "la barre ne bouge pas"). */
.subject-progress-bar{background:var(--accent, var(--blue));}
.subject-progress-wrap{display:flex; flex-direction:column; gap:6px;}
.subject-progress-label{display:flex; align-items:center; gap:6px; font-size:13px; font-weight:600; color:var(--ink-soft);}

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

/* Tableau plus large que l'écran (mobile) : scroll cantonné au tableau plutôt que toute la page. */
.table-scroll{overflow-x:auto; -webkit-overflow-scrolling:touch;}
.results-table{width:100%; border-collapse:collapse; margin-top:8px;}
.results-table th, .results-table td{text-align:left; padding:10px 8px; border-bottom:1px solid var(--line); font-size:14px;}
.results-table th{color:var(--muted); font-weight:700;}

.login-grid{display:grid; grid-template-columns:1fr 1fr; gap:18px;}
@media (max-width:640px){ .login-grid{grid-template-columns:1fr;} }

/* ---------- Micro-label (eyebrow) ---------- */
.eyebrow{
  display:block; font-size:12px; font-weight:700; letter-spacing:.06em; text-transform:uppercase;
  color:var(--blue);
}

/* ---------- Sections marketing (accueil) ---------- */
.reassurance-row{display:flex; gap:8px 22px; flex-wrap:wrap; font-size:14px; color:var(--ink-soft); margin-top:2px;}
.split-section{display:grid; grid-template-columns:1fr 1fr; gap:40px; align-items:center; margin:56px 0;}
.programme-grid{display:grid; grid-template-columns:repeat(auto-fill, minmax(200px, 1fr)); gap:16px; margin-bottom:16px;}
.programme-card{
  display:flex; align-items:center; gap:16px; background:var(--white); border:1px solid var(--line);
  border-radius:var(--radius); padding:20px; box-shadow:var(--shadow-card); text-decoration:none;
  transition:box-shadow var(--dur-base) var(--ease), transform var(--dur-base) var(--ease);
}
.programme-card:hover{box-shadow:var(--shadow-lift); transform:scale(1.015);}

.cta-banner{
  position:relative; overflow:hidden; margin:0 0 56px; border-radius:var(--radius-xl);
  background:var(--blue); color:#fff; padding:48px 44px;
}
.cta-banner::before{
  content:""; position:absolute; left:-6rem; bottom:-8rem; width:20rem; height:20rem;
  border-radius:4rem; transform:rotate(-15deg); background:rgba(255,255,255,.06); pointer-events:none;
}
.cta-banner-inner{position:relative; display:flex; flex-direction:column; gap:14px; max-width:560px;}
.cta-banner .eyebrow{color:rgba(255,255,255,.75);}
.cta-banner h2{color:#fff;}
.cta-banner p{margin:0; font-size:17px; line-height:1.6; color:rgba(255,255,255,.85);}
.cta-banner .btn-row{display:flex; gap:12px; flex-wrap:wrap; margin-top:6px;}
.cta-banner .btn-secondary{background:rgba(255,255,255,.1); color:#fff; border-color:rgba(255,255,255,.35);}
.cta-banner .btn-secondary:hover{background:rgba(255,255,255,.18);}

/* ---------- Connexion / inscription : panneau fractionné ---------- */
.auth-tabs{display:inline-flex; gap:6px; padding:5px; border-radius:var(--radius-pill); background:var(--blue-bg); margin-bottom:22px;}
.auth-tab{
  padding:10px 20px; border-radius:var(--radius-pill); border:none; cursor:pointer; font-family:var(--font-sans);
  font-size:15px; font-weight:700; min-height:44px; background:transparent; color:var(--ink-soft); text-decoration:none;
  display:inline-flex; align-items:center; justify-content:center; white-space:nowrap;
  transition:background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.auth-tab:hover{color:var(--blue);}
.auth-tab.active{background:var(--blue); color:#fff;}
.auth-tab.active:hover{color:#fff;}

.auth-shell{
  display:grid; grid-template-columns:.85fr 1.15fr; background:var(--white); border:1px solid var(--line);
  border-radius:var(--radius-lg); overflow:hidden; box-shadow:var(--shadow-page); margin-bottom:24px;
}
.auth-side{
  position:relative; overflow:hidden; background:var(--blue); color:#fff; padding:48px 40px;
  display:flex; flex-direction:column; gap:22px;
}
.auth-side::before{
  content:""; position:absolute; left:-7rem; bottom:-8rem; width:20rem; height:20rem;
  border-radius:4rem; transform:rotate(-15deg); background:rgba(255,255,255,.06); pointer-events:none;
}
.auth-side > *{position:relative;}
/* Pas de filter:invert ici : le logo a une icône à deux tons (dégradé bleu + silhouettes blanches) —
   brightness(0) invert(1) aplatit tout en blanc uni et l'icône devient un blob illisible (vérifié :
   le mot "Masterio" s'inverse proprement, mais pas l'icône). On garde donc le logo en couleurs
   d'origine, posé sur une pastille blanche pour rester lisible sur le bleu du panneau. */
.auth-side .brand-logo{
  height:24px; background:var(--white); padding:8px 14px; border-radius:var(--radius-pill);
  /* .auth-side est une colonne flex (align-items:stretch par défaut) : sans ça, la pastille blanche
     s'étire sur toute la largeur du panneau au lieu de rester ajustée au logo. */
  align-self:flex-start;
}
.auth-side h2{color:#fff; font-size:27px; font-weight:500; margin:0; line-height:1.2;}
.auth-points{display:flex; flex-direction:column; gap:12px; margin:0; padding:0; list-style:none;}
.auth-points li{font-size:15px; line-height:1.5; color:rgba(255,255,255,.85);}
.auth-note{margin-top:auto; padding:18px; border-radius:var(--radius); background:rgba(255,255,255,.1); font-size:14px; line-height:1.55; color:rgba(255,255,255,.85);}
.auth-form-side{padding:44px; display:flex; flex-direction:column; gap:20px; min-width:0;}

/* Étapes de l'inscription */
.wizard-top-row{display:flex; align-items:baseline; justify-content:space-between; gap:12px;}
.wizard-labels{display:flex; gap:16px; flex-wrap:wrap; margin-bottom:8px;}
.wizard-label{font-size:13px; font-weight:600; color:var(--muted);}
.wizard-label.active{color:var(--blue); font-weight:700;}
/* Pourcentage à droite du libellé d'étape — écho de NotionProgress (showValue=true par défaut). */
.wizard-pct{font-size:13px; font-weight:800; color:var(--amber-dark); flex:none; white-space:nowrap;}
.wizard-progress{height:8px; margin-bottom:6px;}
.wizard-progress-bar{background:var(--amber);}
.form-step{display:flex; flex-direction:column; gap:18px;}
.step-hidden{display:none;}
.step-actions{display:flex; gap:12px; flex-wrap:wrap; align-items:center; margin-top:4px;}
.step-back{border:none; background:none; color:var(--muted); font-family:var(--font-sans); font-weight:600; font-size:15px; cursor:pointer; padding:14px 8px;}
.step-back:hover{color:var(--ink);}
.year-pills{display:flex; gap:8px; flex-wrap:wrap; margin-top:8px;}
.year-pill{
  padding:10px 18px; border-radius:var(--radius-pill); border:1.5px solid var(--line-strong); background:var(--white);
  color:var(--ink-soft); font-family:var(--font-sans); font-size:15px; font-weight:600; min-height:44px; cursor:pointer;
}
.year-pill.active{background:var(--blue); border-color:var(--blue); color:#fff;}
.js-enhanced-hide{position:absolute !important; width:1px; height:1px; padding:0; margin:-1px; overflow:hidden; clip:rect(0,0,0,0); border:0;}
.school-suggestion{
  display:flex; flex-direction:column; gap:2px; padding:14px 16px; border-radius:var(--radius-sm);
  border:1px solid var(--line); background:var(--white); cursor:pointer;
}
.school-suggestion strong{font-size:15px; color:var(--ink); font-weight:600;}
.school-suggestion span{font-size:13px; color:var(--muted);}

/* ---------- Moteur fiche/quiz (engine.js) ---------- */
.theme-card{
  --accent:#005293;
  position:relative;
  display:block; background:var(--white); color:var(--ink); border:1px solid var(--line);
  border-radius:var(--radius); padding:18px 20px; box-shadow:var(--shadow-card);
  cursor:pointer; text-align:left; width:100%; transition:box-shadow var(--dur-base) var(--ease), transform var(--dur-base) var(--ease);
}
.theme-card:hover{box-shadow:var(--shadow-lift); transform:scale(1.015);}
/* :active seul, hover ne sert à rien au doigt sur mobile/tactile — c'est ce petit "clic" visuel qui
   remplace la vibration là où elle n'existe pas (iOS Safari, PWA installée y compris). */
.theme-card:active{transform:scale(.97); transition:transform .07s ease;}
/* Thème déjà essayé (voir engine.js renderHome) : bordure verte discrète + badge coché en coin,
   pour repérer "c'est fait" d'un coup d'œil sans devoir lire les petites étoiles. */
.theme-card-done{border-color:var(--green-line);}
/* Thème "à venir" (status: a_venir) ou moitié manquante d'un thème partiel (sheet seul ou quiz seul
   — voir engine.js renderHome/openSheet) : carte visible mais non cliquable (attribut `disabled`,
   natif à un <button>, suffit à bloquer le clic sans logique JS dédiée), pour montrer le programme
   complet dès le départ sans faire croire que c'est déjà disponible. */
.theme-card-soon{opacity:.55; cursor:default; box-shadow:none;}
.theme-card-soon:hover{box-shadow:none; transform:none;}
.theme-card-soon .theme-emoji{background:color-mix(in srgb, var(--ink) 8%, white);}
.theme-done-badge{
  position:absolute; top:-8px; right:-8px; width:26px; height:26px; border-radius:50%;
  background:var(--green); color:#fff; font-size:13px; font-weight:800; line-height:1;
  display:flex; align-items:center; justify-content:center; box-shadow:var(--shadow-card);
}
.theme-emoji{
  font-size:22px; display:inline-flex; width:48px; height:48px; border-radius:var(--radius-sm); align-items:center;
  justify-content:center; margin-bottom:8px; background:color-mix(in srgb, var(--accent) 14%, white);
}
.theme-title{font-weight:700; font-family:var(--font-sans); font-size:16px; display:block;}
.theme-time{font-size:12px; color:var(--muted); font-weight:600; display:block; margin-top:4px;}
.theme-status{margin-top:10px; gap:5px;}
.theme-status .mastery-stars{gap:2px;}

.sheet-title{font-family:var(--font-sans); font-size:30px; font-weight:500; margin:8px 0 6px; color:var(--ink);}
.sheet-intro{color:var(--ink-soft); font-weight:400; font-size:16px; margin-bottom:16px; line-height:1.6;}
.sheet-row{display:flex; justify-content:space-between; gap:10px; padding:12px 0; border-bottom:1px solid var(--line);}
.sheet-nl{font-weight:700; font-family:var(--font-sans); color:var(--blue);}
.sheet-fr{font-weight:500; color:var(--ink-soft); text-align:right;}
.sheet-table{width:100%; border-collapse:collapse; margin-bottom:10px;}
.sheet-table td, .sheet-table th{padding:10px 6px; border-bottom:1px solid var(--line); font-weight:600; font-size:14px;}
.sheet-box{background:var(--amber-bg); border-radius:var(--radius); padding:16px 20px; font-weight:500; color:var(--amber-dark); font-size:15px; line-height:1.6;}
.sheet-examples{list-style:none; margin:10px 0 0; padding:0;}
.sheet-examples li{padding:10px 0; border-bottom:1px solid var(--line); font-weight:500; font-size:14px;}

/* ---------- Hub d'un thème : 2 choix clairs, synthèse ou quiz (voir engine.js::openSheet) ---------- */
.theme-hub-choices{display:flex; flex-direction:column; gap:14px; margin-top:18px;}
.theme-hub-choices .theme-card{padding:22px 20px;}

/* ---------- Synthèse plein écran en petites cartes (une par concept, voir engine.js::sheetToCards) —
   rejoue l'habillage .quiz-screen/.quiz-header/.quiz-body/.quiz-footer du quiz (setQuizMode). ---------- */
/* min-height en dur (pas juste flex:1) pour que ça marche aussi hors du mode plein écran mobile
   (.quiz-mode ne stretch #app/.quiz-body qu'en dessous de 900px, voir plus bas). */
.synthese-body{display:flex; flex-direction:column; min-height:50vh;}
.sheet-card{margin-bottom:14px; width:100%;}
.sheet-card .card{margin-bottom:0;}
/* Cartes courtes (intro/concept) : occupent tout l'espace vertical restant sous le "Carte X/Y" et
   centrent leur contenu dedans — vraie présence de flashcard plutôt qu'une petite boîte perdue en haut
   d'un grand vide (retour utilisateur). Volontairement PAS appliqué à la récap : elle réutilise le
   rendu complet en une page, potentiellement long — flex+justify-content:center sur un contenu qui
   déborde couperait son début, elle doit rester ancrée en haut et défiler normalement. */
.sheet-card-intro, .sheet-card-concept{flex:1; display:flex; flex-direction:column; justify-content:center;}
.sheet-card-intro .card, .sheet-card-concept .card{padding:30px 26px;}
.sheet-card-intro .sheet-intro{font-size:21px; line-height:1.7; font-weight:500; color:var(--ink);}
.sheet-card-concept .sheet-row{padding:18px 0; font-size:18px;}
.sheet-card-concept .sheet-nl{font-size:19px;}
.sheet-card-concept .sheet-box{font-size:18px; line-height:1.75; padding:26px 24px;}
.sheet-card-concept .sheet-table td, .sheet-card-concept .sheet-table th{font-size:16px; padding:14px 8px;}
/* --- Illustrations de fiche/question (`visual:` dans le YAML, voir engine.js::renderVisual) ---
   Deux formes seulement : un tableau dessiné par le moteur (.visual-table) et un SVG écrit dans le
   contenu. Le SVG n'a jamais de couleur en dur (validé côté content.py) — il hérite d'ici via
   currentColor, donc une illustration suit la charte sans que l'auteur du contenu ait à la connaître. */
.sheet-visual{margin:16px 0 0; display:flex; flex-direction:column; align-items:center; gap:8px; color:var(--blue);}
/* Le wrapper role="img" (voir renderVisual) doit occuper toute la largeur, et le SVG avoir une
   largeur DÉFINIE : un SVG déclaré avec viewBox seul, sans width/height (c'est la règle imposée au
   contenu), n'a aucune largeur intrinsèque — dans un conteneur en shrink-to-fit il s'effondre à
   zéro et l'illustration disparaît en laissant son espace vide. D'où width:100% + max-width plutôt
   qu'un max-height : la hauteur se déduit du ratio du viewBox. */
.sheet-visual > div{width:100%;}
.sheet-visual svg{display:block; width:100%; max-width:300px; height:auto; margin:0 auto;}
.sheet-visual-caption{font-size:13px; color:var(--muted); text-align:center; line-height:1.5;}
.visual-table{border-collapse:collapse; font-size:14px; max-width:100%; margin:0 auto;}
.visual-table th, .visual-table td{
  border:1px solid var(--line-strong); padding:8px 12px; text-align:center; font-weight:600; color:var(--ink-soft);
}
.visual-table thead th{background:var(--blue-bg); color:var(--blue); font-weight:700;}
.visual-table tbody th{background:var(--blue-bg); color:var(--blue); font-weight:700; text-align:left;}
.visual-table .is-highlight{background:var(--amber-bg); color:var(--amber-dark); font-weight:800; box-shadow:inset 0 0 0 2px var(--amber);}
/* En carte de synthèse plein écran, la place ne manque pas : l'illustration peut respirer. */
.sheet-card-concept .sheet-visual svg, .sheet-card-intro .sheet-visual svg{max-width:340px;}
.sheet-card-concept .visual-table th, .sheet-card-concept .visual-table td{padding:10px 14px; font-size:15px;}
/* Dans un quiz (question ou récap), l'illustration reste compacte pour laisser les réponses visibles. */
.quiz-body .sheet-visual{margin:0 0 18px;}
.quiz-body .sheet-visual svg{max-width:260px;}
.recap-item .sheet-visual{margin:8px 0;}
.recap-item .sheet-visual svg{max-width:200px;}

/* --- Note "ce qui n'est pas encore couvert" (`competences_non_couvertes:`, engine.js::coverageNote) ---
   Volontairement une note repliable discrète, pas un bandeau d'alerte : le projet est explicitement
   non exhaustif (voir AGENTS.md), le dire ne doit pas dramatiser. */
.coverage-note{margin:0 0 18px; font-size:14px; color:var(--ink-soft);}
.coverage-note summary{cursor:pointer; color:var(--muted); font-weight:600; list-style:none;}
.coverage-note summary::-webkit-details-marker{display:none;}
/* Le marqueur natif est masqué (rendu incohérent d'un navigateur à l'autre) — ce chevron le
   remplace, sinon rien n'indique que la note se déplie. */
.coverage-note summary::after{content:" ▸";}
.coverage-note[open] summary::after{content:" ▾";}
.coverage-note ul{margin:8px 0 0; padding:12px 16px 12px 32px; background:var(--sand); border-radius:var(--radius); line-height:1.6;}

/* --- Page "matière à venir" (matiere_a_venir.html, voir AGENTS.md « Matières annoncées à l'avance »)
   Même esprit que .coverage-note (une note, pas une alerte) mais en page entière plutôt qu'en note
   repliable : ici c'est tout le contenu de la page, pas une précision en footnote. */
.a-venir-hero{display:flex; align-items:center; gap:16px; margin:8px 0 20px;}
.a-venir-hero .matiere-emoji{font-size:32px; width:64px; height:64px;}
.a-venir-box{background:var(--sand); border-radius:var(--radius); padding:18px 20px; line-height:1.6;}
.a-venir-box h2{margin:0 0 10px; font-size:16px;}
.a-venir-box ul{margin:0; padding-left:22px;}
.a-venir-box li{margin:4px 0;}

.sheet-recap-label{font-family:var(--font-sans); font-weight:700; font-size:15px; color:var(--blue); margin-bottom:10px;}
.sheet-nav{display:flex; gap:10px;}
.sheet-nav .btn{flex:1;}
.sheet-nav .btn:disabled{opacity:.35; cursor:default; pointer-events:none;}

#questionText{font-family:var(--font-sans); font-size:30px; font-weight:500; margin:14px 0 20px; color:var(--ink);}
.options{display:flex; flex-direction:column; gap:12px;}
.opt-btn{
  display:flex; align-items:center; gap:16px; text-align:left; background:var(--white);
  border:1.5px solid var(--line-strong); border-radius:var(--radius); padding:18px 20px;
  font-family:var(--font-sans); font-weight:600; font-size:17px; cursor:pointer; color:var(--ink);
  box-shadow:var(--shadow-card); transition:transform .07s ease, box-shadow .07s ease, border-color var(--dur-fast) var(--ease);
}
.opt-btn:hover:not(:disabled){border-color:var(--blue);}
/* Retour tactile immédiat au tap, avant même que correct/wrong ne s'affiche (voir FX.tap() dans
   engine.js pour le son/la vibration) — :disabled une fois la réponse validée, donc ne rejoue pas. */
.opt-btn:active:not(:disabled){transform:scale(.98);}
.opt-key{
  width:34px; height:34px; flex:none; border-radius:var(--radius-sm); display:grid; place-items:center;
  font-family:var(--font-sans); font-size:15px; font-weight:700; background:var(--blue-bg); color:var(--blue);
}
.opt-btn.correct{border-color:var(--green); background:var(--green-bg);}
.opt-btn.correct .opt-key{background:var(--green); color:#fff;}
.opt-btn.wrong{border-color:var(--red); background:var(--red-bg);}
.opt-btn.wrong .opt-key{background:var(--red); color:#fff;}
.opt-btn.dim{opacity:.5; box-shadow:none;}
.feedback{
  min-height:0; display:flex; flex-wrap:wrap; align-items:center; gap:16px; margin-top:16px; padding:0 2px;
  font-weight:600; border-radius:var(--radius); position:relative;
}
.feedback:not(:empty){padding:20px 22px;}
.feedback.good{background:var(--green-bg); color:var(--green-dark);}
.feedback.bad{background:var(--red-bg); color:var(--red-dark);}
/* Explication de la bonne réponse (theme.quiz.questions[].explanation, optionnel) — sur sa propre
   ligne sous le message bonne/mauvaise réponse, alignée sous le texte (pas sous la mascotte). */
.feedback-explanation{flex-basis:100%; margin:8px 0 0; padding-left:72px; font-weight:500; font-size:14px; line-height:1.5; opacity:.85;}
.progress{height:10px; margin-bottom:10px;}
.progress-bar{width:0%; background:var(--amber);}
/* Texte d'un passage de lecture (quiz.passages) — écran de lecture dédié (renderPassageIntro) et
   référence repliable pendant ses questions (renderQuestion, voir .quiz-passage-ref). Jamais de
   minuteur visible ici, volontairement (voir AGENTS.md/engine.js::readingPaceNote). */
.quiz-passage{
  background:var(--sand); border:1px solid var(--line); border-radius:var(--radius);
  padding:20px 22px; margin:16px 0; font-size:17px; line-height:1.7; color:var(--ink);
}
.quiz-passage p{margin:0 0 12px;}
.quiz-passage p:last-child{margin-bottom:0;}
.quiz-passage-ref{margin-bottom:16px;}
.quiz-passage-ref summary{
  cursor:pointer; font-weight:700; color:var(--blue); padding:4px 0; list-style:none;
}
.quiz-passage-ref summary::-webkit-details-marker{display:none;}
.quiz-passage-ref .quiz-passage{margin-top:8px;}
/* Note discrète de vitesse de lecture (state.passageTimings) — jamais de couleur bonne/mauvaise ici,
   juste une info neutre, en petit, sous le message de résultat. */
.reading-pace-note{font-size:14px; color:var(--muted); margin:4px 0 20px;}
.result-box{text-align:center; padding-top:24px; position:relative;}
.grade-num{font-family:var(--font-sans); font-weight:800; font-size:52px; color:var(--green);}

/* ---------- Question "texte_libre" (réponse tapée) ---------- */
.text-answer{display:flex; gap:12px; align-items:center; flex-wrap:wrap;}
.text-answer-input{
  flex:1; min-width:160px; border:1.5px solid var(--line-strong); border-radius:var(--radius);
  padding:16px 18px; font-family:var(--font-sans); font-weight:600; font-size:17px; color:var(--ink);
  background:var(--white);
}
.text-answer-input:focus{outline:none; border-color:var(--blue);}
.text-answer-input:disabled{opacity:.6;}
/* Bouton ± (réponse numérique du secondaire) : le pavé numérique mobile n'a pas de touche moins,
   voir engine.js::signeMoinsBtn. Taille de cible tactile alignée sur la hauteur du champ. */
.text-answer-sign{
  flex:0 0 auto; min-width:56px; align-self:stretch; border:1.5px solid var(--line-strong);
  border-radius:var(--radius); background:var(--white); color:var(--ink);
  font-family:var(--font-sans); font-weight:800; font-size:20px; line-height:1; cursor:pointer;
}
.text-answer-sign:active{background:var(--blue-bg); border-color:var(--blue);}
.text-answer-sign:disabled{opacity:.6;}

/* ---------- Question "ordre" (remise en ordre par tap, voir engine.js::renderOrdre) ---------- */
.order-slots{display:flex; flex-wrap:wrap; gap:10px; min-height:52px; margin-bottom:14px;}
.order-slot{display:flex; align-items:center; gap:8px;}
.order-slot-badge{
  width:24px; height:24px; flex:none; border-radius:50%; display:grid; place-items:center;
  background:var(--blue-bg); color:var(--blue); font-size:12px; font-weight:700;
}
.order-bank{display:flex; flex-wrap:wrap; gap:10px; margin-bottom:14px;}
.order-chip{
  background:var(--white); border:1.5px solid var(--line-strong); border-radius:var(--radius-pill);
  padding:10px 18px; font-family:var(--font-sans); font-weight:600; font-size:15px; color:var(--ink);
  cursor:pointer; box-shadow:var(--shadow-card);
}
.order-chip:hover{border-color:var(--blue);}

/* ---------- Question "association" (relier deux colonnes, voir engine.js::renderAssociation) ---------- */
.match-columns{display:flex; gap:16px;}
.match-col{flex:1; display:flex; flex-direction:column; gap:10px; min-width:0;}
.match-item{
  background:var(--white); border:1.5px solid var(--line-strong); border-radius:var(--radius);
  padding:14px 16px; font-family:var(--font-sans); font-weight:600; font-size:15px; color:var(--ink);
  cursor:pointer; text-align:left; box-shadow:var(--shadow-card);
}
.match-item:hover:not(:disabled){border-color:var(--blue);}
.match-item.selected{border-color:var(--blue); background:var(--blue-bg);}
.match-item.correct{border-color:var(--green); background:var(--green-bg);}
.match-item.wrong{border-color:var(--red); background:var(--red-bg);}
.match-item:disabled{cursor:default;}
/* Association mot/image (depuis le 2026-08-26) : le bouton porte une illustration (renderVisual,
   toujours enveloppée dans une <figure class="sheet-visual">) plutôt qu'un texte 'fr' — on annule sa
   marge/largeur pensées pour une fiche pleine page et on la réduit à la taille d'une puce. */
.match-item-visual{display:flex; align-items:center; justify-content:center; padding:10px;}
.match-item-visual .sheet-visual{margin:0; width:100%;}
.match-item-visual .sheet-visual svg{max-width:64px;}
.match-item-visual .sheet-visual-caption{display:none;}

/* ---------- Récap de fin de quiz (state.answers, voir engine.js::renderRecap) ---------- */
.recap{margin-top:22px; text-align:left;}
.recap-toggle{
  display:block; margin:0 auto; background:none; border:none; color:var(--blue); font-weight:700;
  font-size:15px; cursor:pointer; padding:10px;
}
.recap-item{border:1.5px solid var(--line); border-radius:var(--radius); padding:14px 16px; margin-bottom:10px;}
.recap-item.correct{border-left:4px solid var(--green);}
.recap-item.wrong{border-left:4px solid var(--red);}
.recap-question{font-weight:700; margin:0 0 6px;}
.recap-your-answer, .recap-correct-answer{font-size:14px; margin:2px 0; color:var(--muted);}
.recap-correct-answer{color:var(--green-dark); font-weight:600;}
.recap-explanation{font-size:14px; margin:6px 0 0; opacity:.85;}

/* ---------- Mascotte animée (clin d'œil / expressions) ---------- */
/* Un seul fichier mascotte.png (pas de sprite à maintenir) : "fermer un œil" = un petit ovale couleur
   peau posé sur la pupille + un trait fin dessous façon paupière souriante, positionnés en % des
   coordonnées mesurées sur l'image d'origine — ça reste juste quelle que soit la taille affichée
   (56px dans .feedback, 38px en mode quiz mobile, cf. media query plus bas). Ces teintes suivent
   l'illustration elle-même, pas la charte de couleurs — inchangées par la refonte visuelle. */
.mascotte-wrap{position:relative; display:inline-block; flex:none; height:56px;}
.mascotte-wrap .mascotte-img{display:block; height:100%; width:auto;}
.mascotte-eyelid{
  position:absolute; width:7%; height:6.6%; border-radius:50%; background:#f8ce9b;
  transform:scaleY(0); transform-origin:center; pointer-events:none;
}
.mascotte-eyelid::after{
  content:""; position:absolute; left:8%; right:8%; top:36%; height:16%;
  border-bottom:3px solid #052041; border-radius:0 0 60% 60% / 0 0 100% 100%;
}
.mascotte-eyelid-l{left:37%; top:48.4%;}
.mascotte-eyelid-r{left:54.6%; top:48.4%;}
.mascotte-eyelid.mascotte-blink{animation:mascotte-blink .5s ease;}
@keyframes mascotte-blink{
  0%{transform:scaleY(0);} 35%{transform:scaleY(1);} 70%{transform:scaleY(1);} 100%{transform:scaleY(0);}
}
.mascotte-happy .mascotte-img{animation:mascotte-bounce .5s ease;}
.mascotte-oops .mascotte-img{animation:mascotte-shake .45s ease;}
@keyframes mascotte-bounce{
  0%,100%{transform:translateY(0) rotate(0);}
  30%{transform:translateY(-6px) rotate(-4deg);}
  60%{transform:translateY(0) rotate(3deg);}
}
@keyframes mascotte-shake{
  0%,100%{transform:translateX(0);}
  20%{transform:translateX(-4px);} 40%{transform:translateX(4px);}
  60%{transform:translateX(-3px);} 80%{transform:translateX(2px);}
}

/* Petit "+1" qui s'envole au-dessus du score à chaque bonne réponse (voir spawnScorePop() dans
   engine.js) — purement décoratif, se retire lui-même après l'animation. */
.score-pop{
  position:absolute; right:22px; top:8px; font-family:var(--font-sans); font-weight:800; font-size:20px;
  color:var(--green-dark); pointer-events:none; animation:score-pop .8s ease forwards;
}
@keyframes score-pop{
  0%{opacity:0; transform:translateY(0) scale(.8);}
  20%{opacity:1; transform:translateY(-6px) scale(1.1);}
  100%{opacity:0; transform:translateY(-34px) scale(1);}
}

/* Flash coloré plein écran à la validation d'une réponse — un halo qui pulse puis s'efface,
   pour renforcer bonne/mauvaise réponse là où la vibration n'existe pas (iOS). Sur <body>::before en
   position fixed pour ne jamais pousser le contenu ni gêner le scroll. */
body::before{content:""; position:fixed; inset:0; pointer-events:none; z-index:9999; opacity:0;}
body.fx-glow-good::before{background:radial-gradient(circle at 50% 30%, rgba(63,184,120,.28), transparent 65%); animation:fx-glow .5s ease;}
body.fx-glow-bad::before{background:radial-gradient(circle at 50% 30%, rgba(255,107,74,.24), transparent 65%); animation:fx-glow .5s ease;}
@keyframes fx-glow{0%{opacity:1;} 100%{opacity:0;}}

/* Confettis (résultat parfait ⭐⭐⭐) — voir burstConfetti() dans engine.js, morceaux générés en JS,
   juste le rendu/l'animation de chute ici. */
.confetti-piece{
  position:absolute; top:-12px; width:8px; height:14px; opacity:0; border-radius:2px;
  animation:confetti-fall 1.5s ease-in forwards;
}
@keyframes confetti-fall{
  0%{opacity:1; transform:translateY(0) rotate(0deg);}
  100%{opacity:0; transform:translateY(220px) rotate(540deg);}
}

/* ---------- Mode quiz plein écran (façon appli mobile, ex. Duolingo) ---------- */
/* Actif seulement pendant une question (voir setQuizMode() dans engine.js) — le reste (accueil
   matière, fiche, résultat) reste une page normale qui scrolle. */
.quiz-screen{display:flex; flex-direction:column;}
.quiz-header{display:flex; align-items:center; gap:14px; margin-bottom:6px;}
.quiz-header .progress{flex:1; margin-bottom:0;}
.quiz-close{
  flex:none; width:34px; height:34px; padding:0; border:none; background:none;
  font-size:20px; line-height:1; color:var(--muted); cursor:pointer;
}
.quiz-close:hover{color:var(--ink);}
.fx-toggle{
  flex:none; width:34px; height:34px; padding:0; border:none; background:none;
  font-size:18px; line-height:1; color:var(--muted); cursor:pointer;
}
.fx-toggle:hover{color:var(--ink);}
.quiz-footer{margin-top:auto;}
/* :not(.hidden), pas #nextBtn seul : un id l'emporterait sur .hidden pendant que le bouton doit
   rester masqué avant la réponse. Redondant depuis que .hidden est en !important, mais gardé — la
   règle reste correcte en soi et documente l'intention. */
#nextBtn:not(.hidden){display:flex; margin:14px auto 0;}

/* ---------- Espace parent : avancement enfant (/parent, /parent/enfants/<id>...) ----------
   Écho des écrans Claude Design importés le 2026-08-26 (Masterio.dc.html, "Espace parent") — voir
   AGENTS.md « Direction visuelle ». Réutilise .card/.pill/.subject-progress/.admin-actions/
   .auth-tabs/.auth-tab tels quels plutôt que d'inventer des équivalents, même esprit que le reste
   de la charte (facteurs communs, voir plus haut). */
.child-card{display:flex; flex-direction:column; gap:20px; padding:26px;}
.child-header{display:flex; align-items:center; gap:20px; flex-wrap:wrap;}
/* Anneau de progression : conic-gradient posé en style inline (couleur + %, calculés côté serveur),
   cette règle ne fixe que la forme/taille — cercle blanc intérieur pour découper l'anneau en tube
   plutôt qu'un disque plein. */
.child-ring{width:120px; height:120px; border-radius:50%; flex:none; display:flex; align-items:center; justify-content:center;}
.child-ring-inner{
  width:96px; height:96px; border-radius:50%; background:var(--white);
  display:flex; flex-direction:column; align-items:center; justify-content:center; gap:1px;
}
.child-ring-pct{font-size:24px; font-weight:800; font-family:var(--font-sans); color:var(--ink);}
.child-ring-label{font-size:10px; font-weight:700; letter-spacing:.04em; text-transform:uppercase; color:var(--muted); text-align:center;}
.child-identity{flex:1; min-width:220px; display:flex; flex-direction:column; gap:6px;}
.child-name-row{display:flex; align-items:center; gap:10px; flex-wrap:wrap;}
.child-name{font-size:21px; font-weight:700; font-family:var(--font-sans); color:var(--ink);}
.child-meta{font-size:14px; color:var(--ink-soft);}
.child-badges{display:flex; gap:8px; flex-wrap:wrap; margin-top:2px;}
.child-stats{display:grid; grid-template-columns:repeat(3, minmax(84px,1fr)); gap:10px; min-width:280px;}
.child-stat{display:flex; flex-direction:column; align-items:center; justify-content:center; gap:2px; padding:10px 6px; border-radius:var(--radius-sm); text-align:center;}
.child-stat-num{font-size:19px; font-weight:800; font-family:var(--font-sans);}
.child-stat-label{font-size:11px; line-height:1.3; color:var(--ink-soft); font-weight:600;}
.child-stat-green{background:var(--green-bg);} .child-stat-green .child-stat-num{color:var(--green-dark);}
.child-stat-blue{background:var(--blue-bg);} .child-stat-blue .child-stat-num{color:var(--blue-dark);}
.child-stat-amber{background:var(--amber-bg);} .child-stat-amber .child-stat-num{color:var(--amber-dark);}
.child-subjects{display:grid; grid-template-columns:repeat(2,1fr); gap:14px 28px; padding-top:18px; border-top:1px solid var(--line);}
.child-alert{
  display:flex; gap:12px; align-items:flex-start; padding:14px 18px; border-radius:var(--radius);
  background:var(--amber-bg); color:var(--amber-dark); font-size:14.5px; line-height:1.55; font-weight:600;
}
.child-alert svg{flex:none; margin-top:1px;}
.pill-muted{color:var(--muted); background:var(--sand);}

/* ---------- Détail de l'avancement (/parent/enfants/<id>) ---------- */
.subject-detail-card{display:flex; flex-direction:column; gap:4px;}
.subject-detail-header{display:flex; align-items:center; gap:16px; flex-wrap:wrap; margin-bottom:10px;}
.subject-detail-emoji{
  font-size:22px; width:52px; height:52px; border-radius:var(--radius-sm); flex:none;
  display:flex; align-items:center; justify-content:center;
  background:color-mix(in srgb, var(--accent, var(--blue)) 14%, white);
}
.subject-detail-name{font-size:18px; font-weight:700; font-family:var(--font-sans); color:var(--ink); display:block;}
.subject-detail-summary{font-size:14px; color:var(--muted); display:block;}
.subject-detail-progress{width:200px; flex:none;}
.chapter-row{display:flex; align-items:center; gap:14px; padding:12px 0; border-bottom:1px solid var(--line); flex-wrap:wrap;}
.chapter-row:last-child{border-bottom:none;}
.chapter-title{flex:1; min-width:140px; font-size:15px; color:var(--ink); font-weight:600;}
.chapter-when{font-size:13px; color:var(--muted); min-width:96px; text-align:right;}
.review-card{display:flex; align-items:center; gap:18px; flex-wrap:wrap;}
.review-body{flex:1; min-width:180px; display:flex; flex-direction:column; gap:3px;}
.review-title{font-size:16px; font-weight:700; color:var(--ink);}
.review-reason{font-size:14px; color:var(--ink-soft);}
.activity-row{display:flex; align-items:center; gap:16px; padding:12px 0; border-bottom:1px solid var(--line); flex-wrap:wrap;}
.activity-row:last-child{border-bottom:none;}
.activity-when{font-size:13px; color:var(--muted); min-width:100px;}
.activity-label{flex:1; min-width:160px; font-size:15px; color:var(--ink);}

@media (max-width:640px){
  .child-subjects{grid-template-columns:1fr;}
  .subject-detail-progress{width:100%;}
}

/* ---------- Responsive ---------- */
@media (max-width:900px){
  .page{padding:26px 20px 40px;}
  /* La maquette n'a jamais de bandeau utilitaire sur mobile (juste le header compact logo + 1 CTA) —
     masqué entièrement plutôt que juste réduit (auparavant seul .utility-bar-accent disparaissait,
     la ligne de texte restait et mangeait de la hauteur utile). */
  .utility-bar{display:none;}
  .hero, .steps, .info-grid, .warn-grid, .login-grid, .split-section{grid-template-columns:1fr;}
  /* Header : "Créer un compte gratuit" ne tient pas à côté du logo sur un écran étroit — la maquette
     raccourcit spécifiquement ce bouton en "Créer un compte" sur mobile plutôt que de le laisser
     passer à la ligne (voir .cta-full/.cta-short et base.html). */
  .cta-full{display:none;}
  .cta-short{display:inline;}
  .topbar{flex-wrap:nowrap;}
  /* Bord à bord (pas de marge blanche de chaque côté) : la maquette ne met JAMAIS .hero-band dans le
     padding de .page sur mobile, contrairement au reste du contenu — seule cette bande "en-tête de
     page" est un rectangle plein qui touche les bords de l'écran, avec juste son padding interne.
     Marges négatives pour "sortir" du padding de .page (26px 20px) tout en gardant le même rythme
     vertical en dessous. */
  .hero-band{
    margin:-26px -20px 24px; padding:24px 20px 28px; border-radius:0;
  }
  .preview-row{flex-direction:column;}
  .cta-banner{padding:32px 24px; border-radius:var(--radius-lg);}
  .cta-banner h2{font-size:26px;}
  /* Boutons d'action en pleine largeur, empilés, sur mobile — la maquette ne les laisse jamais en
     pilules "shrink-to-fit" flottant avec du vide à côté (ex. hero, bandeau CTA, étapes du wizard,
     bas de fiche/quiz/résultat dans engine.js) : chaque bouton d'un groupe prend toute la largeur. */
  .code-row, .cta-banner .btn-row, .step-actions{flex-direction:column; align-items:stretch;}
  .code-row .btn, .cta-banner .btn-row .btn, .step-actions .btn, .step-actions .step-back,
  #app .btn{width:100%;}
  /* .result-box (engine.js) n'est pas un conteneur flex — ses 2 boutons restent des inline-flex
     larg. 100%, ce qui suffit à les faire passer à la ligne l'un sous l'autre (plus de place à côté). */
  #app .result-box .btn + .btn{margin-top:10px;}
  .auth-shell{grid-template-columns:1fr; border-radius:var(--radius);}
  /* Le panneau bleu (.auth-side) n'existe pas du tout sur mobile dans la maquette — juste le bandeau
     retour + logo (.auth-top-row) au-dessus des onglets, voir plus haut. Auparavant réduit à une
     bande fine plutôt que masqué : ça restait un panneau bleu chiche à côté d'un logo minuscule, pas
     ce que montre la maquette. */
  .auth-side{display:none;}
  .auth-top-row-logo{display:block; height:22px; margin-left:auto;}
  .auth-form-side{padding:20px 22px 28px;}
  .wizard-labels{display:none;}
  .wizard-step-mobile{display:block;}
  /* La maquette elle-même met les 2 onglets à largeur égale sur mobile (flex:1 1 0, police réduite à
     14px) plutôt que shrink-to-fit — sans ça le texte peut se remettre à la ligne sur un écran étroit
     ou avec une police système agrandie (accessibilité). */
  .auth-tabs{display:flex; width:100%;}
  .auth-tab{flex:1 1 0; font-size:14px; padding:10px 12px;}
  h1{font-size:30px;}
  .sheet-title{font-size:26px;}
  #questionText{font-size:24px;}
  .topbar{padding:calc(10px + env(safe-area-inset-top, 0px)) calc(16px + env(safe-area-inset-right, 0px)) 10px calc(16px + env(safe-area-inset-left, 0px));}
  .brand-logo{height:24px;}
  /* Sous 900px, la nav de compte (Mes résultats/Mon compte/Se déconnecter) et le pseudo en toutes
     lettres quittent le header pour le menu du bas façon appli (.bottom-nav) — ne reste dans le
     bandeau que la marque + badge streak/avatar, pour éviter un header qui déborde sur deux lignes. */
  .topbar-pseudo, .topbar-account-links{display:none;}
  /* Idem pour la nav marketing (visiteur anonyme) : ne garder que le bouton "Se connecter", les liens
     texte ("Comment ça marche"/"Contribuer") ont trop peu de place pour rester lisibles ici. */
  .topbar-marketing a:not(.btn){display:none;}

  .bottom-nav{
    position:fixed; left:0; right:0; bottom:0; z-index:40; display:flex;
    background:var(--white); border-top:1px solid var(--line);
    box-shadow:0 -6px 18px rgba(16,36,58,.08);
    padding:6px calc(8px + env(safe-area-inset-right, 0px)) calc(6px + env(safe-area-inset-bottom, 0px)) calc(8px + env(safe-area-inset-left, 0px));
  }
  .bottom-nav a{
    flex:1; display:flex; flex-direction:column; align-items:center; gap:2px;
    padding:6px 0; font-size:19px; color:var(--muted); text-decoration:none;
  }
  .bottom-nav a span{font-size:11px; font-weight:700;}
  .bottom-nav a.active{color:var(--blue);}
  /* Place pour le menu du bas fixe, pour qu'il ne recouvre pas la fin du contenu de page. */
  body.has-bottom-nav .page{padding-bottom:calc(78px + env(safe-area-inset-bottom, 0px));}

  body.quiz-mode{overflow:hidden; height:100%;}
  body.quiz-mode .topbar, body.quiz-mode .utility-bar, body.quiz-mode .footer, body.quiz-mode .bottom-nav,
  body.quiz-mode .back-link, body.quiz-mode .breadcrumb, body.quiz-mode .flashes, body.quiz-mode .flash,
  body.quiz-mode .child-switch-bar{display:none;}
  body.quiz-mode .page{
    position:fixed; inset:0; margin:0;
    padding:calc(14px + env(safe-area-inset-top, 0px)) calc(20px + env(safe-area-inset-right, 0px))
            calc(28px + env(safe-area-inset-bottom, 12px)) calc(20px + env(safe-area-inset-left, 0px));
    border-radius:0; box-shadow:none; display:flex; flex-direction:column;
  }
  body.quiz-mode #app{flex:1; min-height:0; display:flex; flex-direction:column;}
  body.quiz-mode .quiz-screen{flex:1; min-height:0;}
  body.quiz-mode .quiz-body{flex:1; min-height:0; overflow-y:auto; padding-top:4px;}
  /* Resserré au maximum : sur un vrai téléphone (barre d'adresse visible, pas de scroll de page pour
     la faire disparaître — voir body.quiz-mode plus haut), la hauteur utile est plus proche de 660px
     que des 844px du plein écran. Une question longue à 4 options doit quand même tenir sans que le
     dernier bouton ne touche la zone de feedback. */
  body.quiz-mode .hint{margin-bottom:6px;}
  body.quiz-mode #questionText{font-size:21px; margin:8px 0 12px;}
  body.quiz-mode .options{gap:8px;}
  body.quiz-mode .opt-btn{padding:12px 14px;}
  body.quiz-mode .feedback:not(:empty){padding:12px 14px;}
  body.quiz-mode .mascotte-wrap{height:38px;}
  body.quiz-mode #nextBtn:not(.hidden){margin-top:10px;}
  /* Aligné sous le texte du feedback, pas sous la mascotte réduite à 38px+gap sur mobile. */
  body.quiz-mode .feedback-explanation{padding-left:54px;}
  body.quiz-mode .match-columns{gap:10px;}
  body.quiz-mode .match-item{padding:10px 12px; font-size:14px;}
  body.quiz-mode .order-chip{padding:8px 14px; font-size:14px;}
}
