@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700;800&display=swap');
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
:root{
  /* Palette assortie au logo hIAbou — Violet profond · Or · Crème */
  --v:#3D1F6E;--v2:#5B21B6;--vl:#EDE4F8;--vm:#C4B0E5;          /* Violet profond de la marque */
  --mint:#7C3AED;--mintl:#F0E9FB;                                /* Violet clair (accents) */
  --amb:#D4A017;--ambl:#FBF1D5;                                   /* Or du cercle */
  --rose:#B45309;--rosel:#FEF3E2;                                 /* Or foncé / accents */
  --sky:#6366F1;--skyl:#EEF2FF;                                   /* Violet bleuté secondaire */
  --ink:#2D1B69;--ink2:#5B3A8C;--ink3:#7d6fa0;                   /* Lectures violacées — gris remonté (était #A89DBE) pour lisibilité AA */
  --bg:#FAF8FE;--card:#FFFFFF;--bdr:rgba(91,33,182,0.13);         /* Fond violet pâle */
  --ok:#0E9488;--okl:#E6F7F4;                                     /* Vert « réalisé » (coche devoirs, Lot 2) */
  --corr:#B3261E;--corrl:#FCEBEA;--corrb:#6E6090;                 /* Corrections (v16-45). Contrastes WCAG 2.1 recalculés le 2026-09-06, seuil AA texte normal = 4,50:1. --corr = SEUL rouge du projet : --rose est en réalité de l'or foncé, --mint du violet (palette abandonnée) — ne pas les réutiliser ici. --corr donne 5,31:1 sur --vl (bulles IA), 6,20:1 sur --bg, 5,67:1 sur --corrl (le fond RÉEL du bloc, celui qui compte). Écartés : #C0392B ÉCHOUE (4,42:1 sur --vl) ; #C62828 passe de justesse (4,57:1) mais sans marge — #B3261E a été retenu pour la sienne. --corrb = gris du mot fautif Barré : --ink3 (#7d6fa0) ne donnait que 3,66:1 sur --vl et 3,91:1 sur --corrl, sous le seuil AA pour un lecteur de CP ; #6E6090 remonte à 4,56:1 et 4,87:1. */
  --r:18px;--rs:12px;--rxs:8px;
  /* GÉOMÉTRIE DU VIEWPORT VISUEL — écrite par setupViewportFix() (js/app.js).
       --vvh   = visualViewport.height    (hauteur réellement visible)
       --vvtop = visualViewport.offsetTop (décalage du viewport visuel dans le
                 viewport de MISE EN PAGE ; > 0 sur iOS clavier ouvert)
     Valeurs de repli ci-dessous = comportement d'avant si le JS ne tourne pas
     ou si visualViewport est absent. */
  --vvh:100vh;
  --vvtop:0px;
}
@supports (height:100dvh){ :root{ --vvh:100dvh } }
/* DOUBLE-TAP-ZOOM iOS (v16-37) — signalé par Ben sur le compteur d'enfants.
   Safari attend ~300 ms après un appui pour voir si un second arrive : deux
   appuis rapprochés sur un même bouton = double-tap = zoom de la page. Sur tout
   élément déclaré cliquable, ce comportement n'a aucun intérêt et gêne dès que
   l'utilisateur enchaîne les appuis (+/−, chips, boutons ronds).
   `manipulation` neutralise le double-tap-zoom SUR CES ÉLÉMENTS uniquement et
   conserve le défilement ; le pincement pour zoomer reste disponible sur toute
   la page — c'est pourquoi on ne touche PAS au meta viewport (`user-scalable=no`
   casserait l'accessibilité et serait de toute façon ignoré par iOS récent). */
button,[role="button"],.btn,.ibtn,.dv-chip,.sug-chip,.selector-card{touch-action:manipulation}
/* overflow:hidden sur html ET body : le DOCUMENT ne doit avoir AUCUN
   défilement propre (cf. #app ci-dessous). */
html,body{min-height:100%;height:100%;overflow:hidden}
body{font-family:'Poppins',system-ui,sans-serif;background:var(--bg);color:var(--ink);-webkit-font-smoothing:antialiased;overflow:hidden;overscroll-behavior:none}
/* #app ÉPOUSE LE VIEWPORT VISUEL (correctif v16-08).
   Pourquoi : position:fixed ancre au viewport de MISE EN PAGE. Or iOS, clavier
   ouvert, ne rétrécit pas ce viewport-là : il DÉCALE le viewport VISUEL vers le
   bas (visualViewport.offsetTop > 0) pour garder le champ focalisé visible. Un
   #app calé à top:0 se retrouve donc AU-DESSUS de la zone réellement visible
   (bandeau BÊTA + en-tête violet sortis par le haut) et, comme 100dvh ne
   rétrécit pas non plus, il déborde derrière le clavier (grande zone vide dans
   la conversation). C'était le symptôme constaté en prod en v16-07.
   Correctif : la géométrie suit visualViewport → top = --vvtop, height = --vvh.
   La barre de saisie se retrouve alors NATURELLEMENT au-dessus du clavier :
   plus besoin de la translater (--kbgap supprimé).
   top (et PAS transform) : deux .modal-ov (modal-freerecite, modal-create-eval-ai)
   sont DANS #app — un transform en ferait des enfants de #app au lieu du
   viewport (overlay borné à la colonne de 480px).
   margin:0 auto centre toujours (width auto bornée par max-width).
   Interdit assumé : viewport-fit=cover (en-tête sous la barre d'état iOS). */
#app{display:flex;flex-direction:column;position:fixed;top:var(--vvtop);left:0;right:0;height:var(--vvh);max-width:480px;margin:0 auto;background:var(--bg);overflow:hidden}
.screen{display:none;flex-direction:column;flex:1 1 auto;width:100%;min-height:0}
.screen.active{display:flex}

/* MODE BANNER */
.mode-banner{display:flex;align-items:center;gap:10px;padding:8px 14px;flex-shrink:0;font-size:11px;font-weight:700}
.mode-banner.dev{background:#1A1033;color:#F5A623}
.mode-banner.beta{background:#0F6E56;color:#D6F7F1}
.mode-banner.prod{background:#185FA5;color:#E0F3FC}
/* MODE DÉCOUVERTE (v16-37) — on RÉUTILISE #mode-banner, on n'ajoute aucun
   élément : c'est le seul emplacement déjà géré par les media queries clavier
   (lignes ~149/158/172), donc le seul sans risque de casser la mise en page de
   l'écran « Aider » clavier ouvert (incident v16-02). */
.mode-banner.demo{background:#3D1F6E;color:#EDE9FD}
.mode-dot{width:7px;height:7px;border-radius:50%;background:currentColor;animation:pulse2 1.5s infinite}
@keyframes pulse2{0%,100%{opacity:1}50%{opacity:0.4}}
.mode-label{flex:1}
.mode-btn{padding:3px 8px;border:1px solid currentColor;border-radius:10px;cursor:pointer;background:transparent;color:inherit;font-family:'Poppins',system-ui,sans-serif;font-size:10px;font-weight:700}

/* HEADER — collé en haut */
.hdr{
  background:var(--v);padding:14px 16px 18px;
  border-radius:0 0 24px 24px;
  display:flex;align-items:center;gap:12px;
  flex-shrink:0;
  position:sticky;top:0;
  overflow:hidden;z-index:5;
  padding-top:calc(14px + env(safe-area-inset-top));
}
.hdr::before{content:'';position:absolute;top:-40px;right:-30px;width:130px;height:130px;border-radius:50%;background:rgba(255,255,255,0.07)}
.hdr-logo{flex-shrink:0;z-index:1;background:transparent;border-radius:26%;padding:0;box-shadow:0 0 0 3px rgba(167,139,250,0.4),0 4px 12px rgba(0,0,0,0.25);display:flex;align-items:center;justify-content:center}
.hdr-logo img{border-radius:24%;display:block}
.hdr-brand{flex:1;z-index:1}
.hdr-brand h1{font-size:22px;font-weight:800;color:#fff;letter-spacing:-0.5px;line-height:1}
.hdr-brand p{font-size:10px;color:rgba(255,255,255,0.6);margin-top:2px}
.hdr-right{z-index:1;display:flex;flex-direction:column;align-items:flex-end;gap:6px}
.plan-pill{font-size:9px;font-weight:800;padding:3px 9px;border-radius:14px}
.plan-dev{background:#F5A623;color:#412402}
.plan-beta{background:#00C9A7;color:#04342C}
.plan-family{background:#F5A623;color:#412402}
.grade-pill{display:flex;align-items:center;gap:5px;background:rgba(255,255,255,0.18);border:1px solid rgba(255,255,255,0.25);border-radius:20px;padding:2px 10px 2px 8px}
.grade-dot{width:7px;height:7px;border-radius:50%;background:var(--mint);flex-shrink:0}
/* font-size:16px obligatoire (zoom auto iOS sous 16px) — compacité via le padding de .grade-pill */
.grade-pill select{background:transparent;border:none;color:white;font-family:'Poppins',system-ui,sans-serif;font-size:16px;font-weight:700;cursor:pointer;outline:none;-webkit-appearance:none;padding:0;line-height:1.1}
.grade-pill select option{color:var(--ink);background:white}
.xp-val{font-size:14px;font-weight:800;color:var(--amb)}
/* Bouton ↻ « nouveau chat » de l'en-tête enfant (styles ici et pas en inline :
   l'écran Aider les resserre, cf. body.aide-min plus bas). */
.hdr-refresh{background:#0E9488;border:none;border-radius:50%;width:28px;height:28px;display:flex;align-items:center;justify-content:center;cursor:pointer;padding:0}

/* HEADER ENFANT — v17-10 (POINT 6a) : ne loge plus que la ligne logo+prénom
   (le sélecteur de classe est passé dans « Mes progrès »). Le prénom est
   agrandi et tenu sur 1 ligne. Le .hdr de base (parent) reste en ligne, intact. */
.hdr-child{flex-direction:column;align-items:stretch;gap:12px}
.hdr-row{display:flex;align-items:center;gap:12px}
/* Prénom enfant agrandi, 1 seule ligne (ellipse si trop long). */
#s-child .hdr-child .hdr-brand h1{font-size:26px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* OBJECTIF DU JOUR + STREAK (Phase 3) — dérivés côté client (dans « Aller plus loin ») */
.goal-top{display:flex;justify-content:space-between;align-items:center;color:#fff;font-size:12.5px;margin-bottom:7px}
.goal-top b{color:#ffe9a8;font-weight:800}
.goal-bar{height:9px;background:rgba(255,255,255,0.22);border-radius:99px;overflow:hidden}
.goal-bar i{display:block;height:100%;width:0;background:linear-gradient(90deg,var(--amb),#ffd451);border-radius:99px;transition:width 0.5s}
.streak-chip{display:inline-flex;align-items:center;gap:5px;margin-top:9px;background:rgba(255,255,255,0.16);border-radius:99px;padding:4px 11px;color:#fff;font-size:12px;font-weight:700}
.num{font-variant-numeric:tabular-nums}

/* SCROLL — chaque panel se comporte comme une page normale */
.scroll{
  flex:1 1 auto;
  width:100%;
  padding:12px 14px;
  /* Plus de compensation clavier ici : #app épouse le viewport visuel, ce
     panneau est donc déjà entièrement dans la zone visible. */
  overflow-y:auto;
  -webkit-overflow-scrolling:touch;
  min-height:0;
}
/* Pas de scroll forcé sur .scroll — c'est la page entière qui scrolle */
/* v16-18 : la pilule flottante enfant (.child-nav, position:fixed) recouvre le
   bas du viewport. Réserve d'espace UNIQUEMENT sur les zones scrollables de
   l'espace enfant pour que la fin de liste ne passe pas dessous. Parent/admin
   (barre plate .nav-bar dans le flux) NON concernés. */
#s-child .scroll{padding-bottom:calc(96px + env(safe-area-inset-bottom))}
/* v16-20 : idem parent/admin (pilule flottante par-dessus le contenu) */
#s-parent .scroll,#s-admin .scroll{padding-bottom:calc(96px + env(safe-area-inset-bottom))}
body.modal-open{overflow:hidden;position:fixed;width:100%}

/* CLAVIER OUVERT (classe posée par setupViewportFix) — on rend au fil de
   discussion la place prise par la barre de nav et la barre de suggestions, et
   on resserre le bandeau + l'en-tête. On ne masque JAMAIS l'en-tête ni la
   barre de saisie (demande de Ben).
   Note : aucune règle sur .chat-msgs ici — #chat-msgs porte min-height:0 en
   style INLINE (index.html), qui gagne sur toute règle de feuille. Les deux
   anciennes règles .chat-msgs (min-height 60px / 0) étaient donc MORTES :
   retirées pour ne pas laisser croire à une sécurité qui n'existait pas. */
body.kb-open .nav-bar{display:none}
/* v16-18 : la pilule flottante enfant hérite du masquage clavier iOS (calqué sur
   .nav-bar) ET disparaît sur l'écran Aider (chat plein écran, body.aide-min).
   La bulle Aider suit les deux mêmes états. */
body.kb-open .child-nav{display:none}
body.aide-min .child-nav{display:none}
body.kb-open .aide-bubble{display:none}
body.aide-min .aide-bubble{display:none}
/* v16-41 (lot 3) : `body.kb-open #chat-suggestions{display:none!important}` a été
   RETIRÉE ici, en même temps que le nœud #chat-suggestions (index.html). Les
   propositions vivent maintenant DANS #chat-msgs (.chat-props, cf. plus bas) :
   elles défilent avec la conversation et n'ont plus à être masquées au clavier —
   ce masquage les rendait invisibles depuis que le clavier s'ouvre tout seul à
   l'arrivée sur le tchat (ouvrirTchatDepuisGeste, js/child.js). */
body.kb-open .mode-banner{padding-top:4px;padding-bottom:4px}
body.kb-open .hdr{padding-top:calc(8px + env(safe-area-inset-top));padding-bottom:10px;border-radius:0 0 16px 16px}
/* Écran très bas (téléphone en PAYSAGE) : #app épousant désormais la zone
   visible, celle-ci peut tomber à ~170 px clavier ouvert. On sacrifie alors le
   bandeau pour garder l'en-tête ET la barre de saisie à l'écran (sans quoi
   #app, en overflow:hidden, rognerait la saisie).
   La media query lit la hauteur de MISE EN PAGE (qui ne bouge pas au clavier) :
   elle ne se déclenche donc qu'en paysage, jamais en portrait. */
@media (max-height:430px){
  body.kb-open .mode-banner{display:none}
}

/* ÉCRAN AIDER — EN-TÊTE MINIMAL (option C, classe posée par switchChildTab)
   L'en-tête complet + le bandeau BÊTA mangeaient ~300 px pour ~350 px de chat.
   Sur CET écran seulement : bandeau BÊTA masqué (il s'adresse aux testeurs, pas
   à l'enfant) et en-tête réduit à une barre fine retour + petit logo + prénom,
   avec le ↻ (nouveau chat) conservé en discret à droite — la fonction existe
   toujours, elle change juste de taille.
   UN SEUL ÉTAT : ces règles ne dépendent PAS de kb-open, l'interface ne saute
   donc pas à l'ouverture du clavier (choix de Ben, c'est ce qui a fait préférer
   C à A). Leur spécificité (1,2,1) passe devant `body.kb-open .hdr` (0,2,1) :
   la compaction clavier de l'en-tête n'a plus prise ici.
   Tous les autres écrans (Leçons, Devoirs, espace parent…) sont inchangés. */
body.aide-min .mode-banner{display:none}
/* EXCEPTION MODE DÉCOUVERTE (v16-39). La règle ci-dessus masque le bandeau sur
   l'écran « Aider » pour rendre la hauteur au tchat — parfait pour le bandeau
   BÊTA, qui n'est qu'informatif. Mais en découverte, ce bandeau porte le SEUL
   bouton « Créer mon compte » visible en permanence : le masquer supprime la
   sortie précisément sur l'écran où un visiteur passe le plus de temps. C'est
   ce qui a fait dire à Ben qu'il n'y avait « pas de retour ».
   Volontairement limité à `aide-min` : on ne touche PAS à `body.kb-open`
   (ligne ~163). Clavier ouvert, l'enfant écrit, il ne cherche pas la sortie, et
   chaque pixel compte — c'est l'écran qui a causé l'incident v16-02. */
body.demo.aide-min .mode-banner{display:flex}
body.aide-min #s-child .hdr{padding:5px 12px 7px;padding-top:calc(5px + env(safe-area-inset-top));border-radius:0 0 14px 14px;gap:8px}
body.aide-min #s-child .hdr-row{gap:8px}
body.aide-min #s-child .hdr-logo{padding:2px;box-shadow:0 0 0 2px rgba(167,139,250,0.4),0 2px 6px rgba(0,0,0,0.2)}
body.aide-min #s-child .hdr-logo img{width:28px;height:28px}
body.aide-min #s-child .hdr-brand h1{font-size:16px}
/* Pastille de classe et XP : hors sujet pendant une conversation. */
body.aide-min #s-child .grade-pill,
body.aide-min #s-child .xp-val{display:none}
body.aide-min #s-child .hdr-right{flex-direction:row;align-items:center}
body.aide-min #s-child .hdr-refresh{width:26px;height:26px;background:#0E9488}

/* NAV parent/admin — v16-20 : MÊME pilule flottante translucide que l'enfant
   (Ben veut le même effet). Verre dépoli, détachée des bords. Masquage clavier
   body.kb-open .nav-bar déjà défini plus haut. */
.nav-bar{
  position:fixed;
  left:50%;
  transform:translateX(-50%);
  bottom:calc(12px + env(safe-area-inset-bottom));
  max-width:min(440px, calc(100% - 24px));
  width:calc(100% - 24px);
  display:flex;padding:8px 6px;
  border-radius:26px;
  background:rgba(255,255,255,.60);
  -webkit-backdrop-filter:blur(16px) saturate(1.4);
  backdrop-filter:blur(16px) saturate(1.4);
  border:1px solid rgba(255,255,255,.6);
  box-shadow:0 8px 28px rgba(45,27,105,.18);
  z-index:10;
}
.ni{flex:1;display:flex;flex-direction:column;align-items:center;gap:4px;padding:5px 2px;border-radius:var(--rxs);cursor:pointer;border:none;background:transparent;font-family:'Poppins',system-ui,sans-serif;transition:all 0.15s}
/* rond actif violet placé derrière l'icône (au lieu d'un fond plein sur tout le bouton) */
.ni.active{background:transparent}
.ni svg{width:19px;height:19px;stroke:#A08060;fill:none;stroke-width:2;stroke-linecap:round;box-sizing:content-box;padding:7px;border-radius:14px;transition:background 0.15s}
.ni.active svg{stroke:var(--v2);background:var(--vl)}
.ni span{font-size:9px;font-weight:700;color:#A08060}
.ni.active span{color:var(--v2)}

/* v17-8 (C1) — barre enfant à EMOJI (Mes progrès / M'aider / Mon historique).
   L'emoji joue le rôle de l'ancienne icône SVG : même pastille violette au clic
   sur l'onglet actif. Le libellé garde la taille .ni span (9px), l'emoji est
   agrandi et reçoit le fond actif (calqué sur .ni.active svg). */
.child-nav .child-nav-emo{font-size:16px;line-height:1;padding:6px;border-radius:14px;transition:background 0.15s;font-weight:400}
.child-nav .ni.active .child-nav-emo{background:var(--vl)}
/* v17-11 (POINT 5) — onglet « M'aider » : logo rond (chouette) à la place de
   l'emoji. Taille ~25px, rond plein, image recadrée. Le fond violet actif
   (.ni.active) est porté par un padding/rayon cohérent avec .child-nav-emo. */
.child-nav .cn-logo{width:25px;height:25px;border-radius:50%;object-fit:cover;display:block;padding:0;transition:box-shadow 0.15s}
.child-nav .ni.active .cn-logo{box-shadow:0 0 0 3px var(--vl)}
.child-nav .child-nav-lbl{font-size:9px;font-weight:700;color:#A08060}
.child-nav .ni.active .child-nav-lbl{color:var(--v2)}

/* v16-18 — PILULE FLOTTANTE ENFANT (.child-nav) : verre dépoli (blanc ~60% +
   flou 16px), détachée des bords, le contenu défile visible à travers. Classe
   DÉDIÉE : parent/admin gardent .nav-bar. Réutilise les styles .ni / .ni.active
   déjà définis ci-dessus (ils s'appliquent aux boutons enfants de cette nav). */
.child-nav{
  position:fixed;
  left:50%;
  transform:translateX(-50%);
  bottom:calc(12px + env(safe-area-inset-bottom));
  max-width:min(440px, calc(100% - 24px));
  width:calc(100% - 24px);
  display:flex;
  border-radius:26px;
  padding:8px 6px;
  background:rgba(255,255,255,.60);
  -webkit-backdrop-filter:blur(16px) saturate(1.4);
  backdrop-filter:blur(16px) saturate(1.4);
  border:1px solid rgba(255,255,255,.6);
  box-shadow:0 8px 28px rgba(45,27,105,.18);
  z-index:10;
}

/* v17-10 (POINT 3) — bouton flottant rond « retour M'aider » (🦉). Unique pour
   tous les sous-écrans enfant. En haut à droite, au-dessus de la piste (z-index
   10) mais SOUS les modales (200) et la caméra (300). switchChildTab pilote
   l'affichage (visible hors 'home', masqué sur 'home'). */
/* v17-11 (POINT 2) — bulle logo flottante « retour M'aider ». Repositionnée en
   BAS À DROITE, AU-DESSUS de la pilule .child-nav (bottom:86px). Le logo rond
   REMPLIT la bulle (56px). Le contenu de la page passe DESSOUS (position:fixed).
   z-index au-dessus du contenu, SOUS les modales/caméra (.modal-ov ~1000). */
.owl-back-btn{
  position:fixed;
  bottom:calc(86px + env(safe-area-inset-bottom));
  right:calc(16px + env(safe-area-inset-right));
  width:56px;height:56px;
  border:none;border-radius:50%;
  background:#fff;
  box-shadow:0 6px 18px rgba(45,27,105,.35);
  line-height:0;overflow:hidden;
  display:flex;align-items:center;justify-content:center;
  cursor:pointer;padding:0;
  z-index:50;
}
.owl-back-btn img{width:100%;height:100%;border-radius:50%;object-fit:cover;display:block}
/* Pendant la frappe/conversation, ne pas flotter par-dessus le clavier. */
body.kb-open .owl-back-btn{display:none !important}

/* v16-18 — BULLE « Aider » flottante (avatar hibou, bas-droite, au-dessus de la
   pilule). Dans #s-child → absente en parent/admin. Masquages kb-open/aide-min
   déclarés plus haut avec .child-nav. */
.aide-bubble{
  position:fixed;
  right:16px;
  bottom:calc(84px + env(safe-area-inset-bottom));
  width:56px;
  height:56px;
  border-radius:50%;
  box-shadow:0 8px 22px rgba(61,31,110,.4);
  z-index:11;
  border:3px solid #fff;
  background:#fff;
  overflow:hidden;
  cursor:pointer;
  padding:0;
}
.aide-bubble img{width:100%;height:100%;object-fit:cover;display:block}
.aide-bubble:active{transform:scale(0.94)}

/* v16-19 — FEUILLE D'ACTIONS (bottom-sheet) générique. Voile + panneau blanc
   qui slide du bas. z-index > .child-nav(10)/.aide-bubble(11) : passe au-dessus
   de la nav flottante. prefers-reduced-motion respecté (transitions coupées). */
.act-sheet-ov{position:fixed;inset:0;z-index:120;background:rgba(30,18,60,.42);
  display:flex;align-items:flex-end;justify-content:center;
  opacity:0;transition:opacity .22s ease}
.act-sheet-ov.open{opacity:1}
.act-sheet{width:100%;max-width:440px;background:var(--card);
  border-radius:20px 20px 0 0;padding:8px 14px calc(16px + env(safe-area-inset-bottom));
  box-shadow:0 -8px 30px rgba(45,27,105,.25);
  transform:translateY(100%);transition:transform .26s cubic-bezier(.32,.72,0,1)}
.act-sheet-ov.open .act-sheet{transform:translateY(0)}
.act-sheet-grip{width:38px;height:4px;border-radius:3px;background:var(--bdr);
  margin:6px auto 10px}
.act-sheet-hd{padding:0 4px 10px;border-bottom:1px solid var(--bdr);margin-bottom:8px}
.act-sheet-ttl{font-size:15px;font-weight:800;color:var(--ink);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.act-sheet-sub{font-size:11px;color:var(--ink3);margin-top:2px}
/* v16-57 Phase 2 : slot de contenu riche (feuille d'aide) entre l'en-tête et
   la liste de boutons. Défile si le pitch dépasse la hauteur disponible. */
.act-sheet-body{padding:2px 4px 8px;max-height:62vh;overflow-y:auto}
.act-sheet-list{display:flex;flex-direction:column;gap:4px}
.act-sheet-btn{display:flex;align-items:center;gap:12px;width:100%;
  padding:13px 12px;border:none;background:transparent;border-radius:12px;
  font-size:15px;font-weight:600;color:var(--ink);text-align:left;cursor:pointer}
.act-sheet-btn:active{background:var(--bg)}
.act-sheet-ic{font-size:18px;width:24px;text-align:center;flex-shrink:0}
.act-sheet-primary{color:var(--v2)}
.act-sheet-danger{color:var(--rose)}
@media (prefers-reduced-motion: reduce){
  .act-sheet-ov,.act-sheet{transition:none}
}

/* Menu de l'écran Admin (#s-admin) : nav EN BAS, mêmes règles que la nav
   enfant/parent (.nav-bar + .ni). 6 entrées à libellés courts pour tenir sur
   mobile sans débordement horizontal (flex:1 réparti à parts égales). */

/* CARDS */
.card{background:var(--card);border-radius:var(--r);border:1.5px solid var(--bdr);padding:15px;margin-bottom:10px}
.card-title{font-size:13px;font-weight:800;color:var(--ink);margin-bottom:10px}
.sec-lbl{font-size:10px;font-weight:700;color:var(--ink3);text-transform:uppercase;letter-spacing:0.9px;margin-bottom:9px;display:block}

/* v16-19 — barre de recherche des listes épurées (leçons / corrections) */
.list-search{width:100%;box-sizing:border-box;margin-bottom:10px;padding:9px 12px;
  font-size:14px;border:1.5px solid var(--bdr);border-radius:12px;
  background:var(--card);color:var(--ink);-webkit-appearance:none;appearance:none}
.list-search:focus{outline:none;border-color:var(--v2)}
.list-search::placeholder{color:var(--ink3)}

/* BUTTONS */
.btn{padding:11px 16px;border-radius:var(--rs);font-family:'Poppins',system-ui,sans-serif;font-size:13px;font-weight:700;cursor:pointer;border:none;transition:all 0.18s;display:inline-flex;align-items:center;gap:7px;justify-content:center;width:100%}
.btn-v{background:var(--v2);color:#fff}
.btn-v:hover{background:#3A2282}
.btn-ghost{background:transparent;color:var(--ink2);border:1.5px solid var(--bdr)}
.btn-mint{background:#00896F;color:#fff}
.btn-mint:hover{background:#006B57}
.btn-new{background:#12B5A5;color:#fff}
.btn-new:hover{background:#0E9488}
.btn-sm{padding:6px 12px;font-size:11px;border-radius:20px;width:auto}

/* FORM */
.field{margin-bottom:12px}
.field label{font-size:11px;font-weight:700;color:var(--ink2);display:block;margin-bottom:5px}
/* font-size:16px obligatoire (zoom auto iOS sous 16px) — compacité via le padding */
.field input,.field select,.field textarea{width:100%;padding:9px 12px;border:1.5px solid var(--bdr);border-radius:var(--rxs);font-family:'Poppins',system-ui,sans-serif;font-size:16px;color:var(--ink);background:var(--bg);outline:none;transition:border-color 0.18s}
.field input:focus,.field select:focus{border-color:var(--v2)}
.field input::placeholder{color:var(--ink3)}
.field textarea{resize:none;height:76px}
/* Case à cocher + libellé sur plusieurs lignes (formulaire support).
   Classe dédiée : NE PAS hériter du width:100%/padding de .field input. */
.field label.field-check{display:flex;align-items:flex-start;gap:8px;font-size:11px;font-weight:400;width:100%;margin-bottom:0;cursor:pointer}
.field label.field-check input[type=checkbox]{flex:0 0 auto;width:17px;height:17px;margin:1px 0 0;padding:0;accent-color:var(--v2);cursor:pointer}
.field label.field-check span{flex:1 1 auto;min-width:0;overflow-wrap:break-word;line-height:1.4;color:var(--ink2)}

/* CHAT */
.chat-wrap{display:flex;flex-direction:column;flex:1 1 auto;overflow:hidden;background:var(--bg);min-height:0}
/* Le message d'accueil est une bulle ordinaire de .chat-msgs (plus d'en-tête
   figé #chat-intro : clavier ouvert, il mangeait la moitié de l'écran).
   Plus de padding-bottom variable : la barre de saisie ne se déplace plus. */
.chat-msgs{flex:1 1 0;overflow-y:auto;padding:12px;display:flex;flex-direction:column;gap:9px;-webkit-overflow-scrolling:touch;min-height:120px}
.chat-msgs::-webkit-scrollbar{display:none}
/* Le wrapper s-child doit s'assurer que tout colle correctement */
#s-child{display:none;flex-direction:column}
#s-child.active{display:flex}
/* v17-8 (C3, POINT 1) : ce conteneur (#child-stage) est le STAGE du swipe
   interactif. Il masque le débordement horizontal de la piste (#child-track
   fait 300% de large) tout en laissant chaque écran gérer son scroll VERTICAL
   interne. Ciblé par id dédié : l'ancien `#s-child > div:nth-child(2)` tombait
   sur la bannière #grade-consult-banner (masquée), pas sur le vrai stage.
   v17-11 (POINT 1) : mêmes règles pour les stages parent (#parent-stage,
   piste 4 onglets) et admin (#admin-stage, piste 6 onglets). */
#child-stage,#parent-stage,#admin-stage{display:flex;flex-direction:column;flex:1 1 auto;min-height:0;position:relative;overflow-x:hidden}
/* v17-15 — SWIPE « BACK » INTERACTIF : pendant le drag, le sous-écran enfant
   (cp-lessons / cp-evals) devient un OVERLAY absolu au-dessus de la piste (qui
   affiche « Mes progrès » derrière) et suit le doigt. Fond opaque (var(--bg))
   pour ne pas laisser transparaître la piste sous les zones vides. Ombre gauche
   discrète = effet « feuille qui se soulève » (comme un retour iOS). z-index
   au-dessus de la piste, sous la nav flottante et les modales. */
#child-stage .sw-back-drag{position:absolute;inset:0;z-index:4;background:var(--bg);
  overflow-y:auto;-webkit-overflow-scrolling:touch;box-shadow:-8px 0 20px rgba(24,16,48,.10);
  will-change:transform}

/* ═══════════════════════════════════════════════════════════════════════════
   v17-8 (C3, POINT 1) — SWIPE INTERACTIF entre les 3 écrans d'onglets.
   Piste horizontale calquée sur le prototype validé (proto-swipe-v17-8.html).
   #child-track : 3 écrans côte à côte (largeur 300% = 3 × la largeur du stage),
   translateX piloté par js/app.js (setSwipeX/placeSwipe). La transition n'est
   posée qu'au SNAP (classe .swiping la retire pendant le drag pour suivre le
   doigt sans latence). touch-action:pan-y = on laisse le scroll VERTICAL natif,
   le JS ne prend QUE l'horizontal (preventDefault au franchissement du seuil).
   ═══════════════════════════════════════════════════════════════════════════ */
/* v17-11 (POINT 1) — PISTE SWIPE GÉNÉRIQUE. .child-track (3 slides, 300%) reste
   l'alias historique de l'espace enfant ; .swipe-track est la base commune,
   utilisée par les pistes parent (#parent-track, .track-4) et admin
   (#admin-track, .track-6). La LARGEUR de la piste est posée inline
   (width:400%/600%) ; la largeur de chaque slide vient de .track-4/.track-6. */
.child-track,.swipe-track{
  display:flex;            /* rangée : les écrans côte à côte */
  flex:1 1 auto;
  min-height:0;
  will-change:transform;
  transform:translateX(0);
  transition:transform .28s cubic-bezier(.22,.61,.36,1);
  touch-action:pan-y;
}
.child-track{width:300%}   /* enfant : 3 slides */
/* Pendant le drag on suit le doigt : pas de transition (posée/retirée en JS). */
.child-track.swiping,.swipe-track.swiping{transition:none}
/* Chaque écran de la piste occupe une fraction fixe = 100% du stage. Écrase le
   flex:1 1 auto / width:100% hérité de .scroll : ici c'est un rail fixe. .scroll
   fournit déjà overflow-y:auto + padding : on ne touche PAS au scroll VERTICAL,
   seul l'horizontal est géré par le stage. */
.child-track .cp-slide,.swipe-track .cp-slide{
  flex:0 0 auto;
  min-width:0;
  height:100%;
}
.child-track .cp-slide{flex-basis:33.3333%;width:33.3333%}   /* 3 onglets enfant */
.track-4 .cp-slide{flex-basis:25%;width:25%}                 /* 4 onglets parent */
.track-6 .cp-slide{flex-basis:16.6667%;width:16.6667%}       /* 6 onglets admin */
.brow{display:flex;gap:7px;align-items:flex-end}
.brow.me{flex-direction:row-reverse}
.bav{width:28px;height:28px;border-radius:24%;background:var(--vl);overflow:hidden;flex-shrink:0;display:flex;align-items:center;justify-content:center}
.bbl{max-width:78%;padding:11px 15px;font-size:15px;line-height:1.55;border-radius:16px}
.brow.ia .bbl{background:var(--vl);color:var(--ink);border-radius:3px 16px 16px 16px}
.brow.me .bbl{background:var(--v2);color:#fff;border-radius:16px 3px 16px 16px}
/* MINI-MARKDOWN (mdToHtml, js/app.js) — rendu des réponses de la mascotte.
   Le reset global met margin/padding à 0 : les listes ont besoin d'un
   padding-left explicite pour afficher leurs puces. */
.md-h{font-weight:800;margin:7px 0 3px;line-height:1.3}
.md-h:first-child{margin-top:0}
.md-hr{border:none;border-top:1px solid rgba(91,33,182,0.22);margin:9px 0}
ul.md-l,ol.md-l{margin:5px 0;padding-left:20px}
ul.md-l{list-style:disc outside}
ol.md-l{list-style:decimal outside}
ul.md-l li,ol.md-l li{margin:3px 0}
.bbl code,#cor-msgs code{background:rgba(45,27,105,0.09);border-radius:5px;padding:1px 5px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:0.9em}
.brow.me .bbl code{background:rgba(255,255,255,0.22)}
/* CORRECTIONS EN ROUGE (corrHtml / mdToHtml, js/app.js) — v16-45.
   Deux surfaces seulement : les bulles du tchat (.bbl) et l'écran Corrections
   (#cor-msgs), qui n'utilise PAS .bbl.
   Le couple « barré → corrigé » reste sur la MÊME ligne (tout est inline) : la
   relation se lit d'un coup d'œil ou pas du tout. Pas de font-size réduite. */
.bbl .corr-bloc,#cor-msgs .corr-bloc,#assist-result .corr-bloc{border-left:3px solid var(--corr);background:var(--corrl);border-radius:0 10px 10px 0;padding:8px 10px;margin-top:9px;overflow-wrap:break-word}
.bbl .corr-old,#cor-msgs .corr-old,#assist-result .corr-old{text-decoration:line-through;color:var(--corrb);font-weight:400;background:none}
.bbl .corr-new,#cor-msgs .corr-new,#assist-result .corr-new{color:var(--corr);font-weight:800}
/* v17-5 : fond rouge léger PERSISTANT sur les corrections (le mot corrigé et le
   couple barré→corrigé), pour qu'elles sautent aux yeux EN PERMANENCE — plus de
   pulsation qui s'efface. Le bouton « 🔴 Corriger » ne fait plus que défiler
   jusqu'au bloc ; il n'ajoute plus de surbrillance temporaire. box-decoration-break
   garde le fond continu si le couple passe à la ligne. Surfaces couvertes :
   bulles du fil (.bbl), écran Corrections (#cor-msgs) et accueil (#assist-result). */
.bbl .corr-new,#cor-msgs .corr-new,#assist-result .corr-new,
.bbl .corr,#cor-msgs .corr,#assist-result .corr{
  background:var(--corrl);border-radius:4px;padding:1px 4px;
  -webkit-box-decoration-break:clone;box-decoration-break:clone}
/* dans le couple barré→corrigé, le fond est déjà porté par .corr : le .corr-new
   interne ne le redouble pas (sinon le mot corrigé aurait un liseré plus foncé). */
.bbl .corr .corr-new,#cor-msgs .corr .corr-new,#assist-result .corr .corr-new{
  background:none;padding:0}
/* La barre de saisie ne se déplace PLUS : elle est le dernier élément du flux
   de #app, et #app se termine exactement au bas de la zone visible (--vvh),
   donc juste au-dessus du clavier. */
/* .chat-foot est désormais une COLONNE : aperçu photo (facultatif) au-dessus,
   ligne de saisie (.chat-row) en dessous. Le flex horizontal des boutons/champ
   vit maintenant dans .chat-row (v16-34). */
.chat-foot{padding:9px 11px 11px;border-top:1px solid var(--bdr);display:flex;flex-direction:column;gap:7px;flex:0 0 auto;background:var(--card);position:relative;z-index:6}
.chat-row{display:flex;gap:7px;align-items:center}
/* Photo choisie, en attente d'envoi : miniature 76px + croix violette + libellé (v16-34) */
.chat-pending{display:flex;align-items:flex-start;gap:10px;padding:2px 2px 4px}
/* v17-7 (POINT 1) : file multi-photos. La grille des miniatures s'enroule ; la
   légende passe en dessous (conteneur en colonne dès qu'il y a une grille). */
.chat-pending:has(.chat-pending-grid){flex-direction:column;align-items:stretch}
.chat-pending-grid{display:flex;flex-wrap:wrap;gap:8px}
.chat-pending .chat-pending-thumb{position:relative;flex-shrink:0}
.chat-pending img{width:76px;height:76px;object-fit:cover;border-radius:12px;border:1.5px solid var(--bdr);display:block}
.chat-pending .chat-pending-rm{position:absolute;top:-7px;right:-7px;width:22px;height:22px;border-radius:50%;background:var(--v2);color:#fff;border:2px solid #fff;font-size:12px;font-weight:800;cursor:pointer;display:flex;align-items:center;justify-content:center;line-height:1;padding:0}
.chat-pending .chat-pending-cap{flex:1;min-width:0;font-size:11px;color:var(--ink3);line-height:1.5;padding-top:4px}
.chat-pending .chat-pending-cap b{color:var(--ink2)}
.chat-pending-tag{display:inline-block;font-size:9px;font-weight:800;background:var(--skyl);color:#185FA5;border-radius:99px;padding:2px 7px;margin-bottom:3px}
/* v17-9 (POINT 2) : rappel bienveillant « 4 photos maximum » sous les vignettes,
   affiché seulement quand la borne CHAT_PENDING_MAX est atteinte. */
.chat-pending-capmax{width:100%;margin-top:6px;font-size:11px;font-weight:700;color:var(--v2);background:var(--vl);border-radius:12px;padding:7px 10px;line-height:1.4}
/* v17-8 (POINT 3a) : bouton « valider » quand ≥1 photo est empilée sur l'accueil */
.chat-pending-go{align-self:flex-start;margin-top:6px;background:#0E9488;color:#fff;border:none;border-radius:22px;padding:8px 16px;font-family:'Poppins',system-ui,sans-serif;font-size:13px;font-weight:800;cursor:pointer}
/* font-size:16px obligatoire (zoom auto iOS sous 16px) — compacité via le padding */
.cin{flex:1;min-width:0;background:var(--bg);border:1.5px solid transparent;border-radius:22px;padding:7px 13px;font-family:'Poppins',system-ui,sans-serif;font-size:16px;color:var(--ink);outline:none;transition:border-color 0.18s}
.cin:focus{border-color:var(--v2)}
.cin::placeholder{color:var(--ink3)}
.ibtn{width:34px;height:34px;border-radius:50%;border:none;cursor:pointer;display:flex;align-items:center;justify-content:center;flex-shrink:0}
/* ⚠️ .send-btn, .mic-btn, .mic-btn.rec et @keyframes micp SERVENT AILLEURS et
   restent en place, même si le tchat ne les utilise plus depuis la v16-41 :
   .send-btn → corrections (index.html) + récitation (js/lessons.js) ;
   .mic-btn(.rec) → récitation ; micp → .mic-btn.rec ET .dv-rec-dot (devoirs). */
.send-btn{background:var(--v2)}
.mic-btn{background:var(--mintl)}
.mic-btn.rec{background:var(--rosel);animation:micp 1s infinite}
@keyframes micp{0%,100%{box-shadow:0 0 0 0 rgba(255,107,138,0.3)}50%{box-shadow:0 0 0 7px rgba(255,107,138,0)}}

/* ── v16-41 (lot 2) : BARRE DE SAISIE DU TCHAT, MODÈLE iMESSAGE ────────────
   Demande de Ben (capture iMessage) : la ligne était tassée (micro + photo +
   champ + envoyer se partageaient la largeur, la phrase d'invite était coupée).
   Restent : le bouton « + » (menu des propositions, photo comprise) et le champ,
   qui récupère ~41 px de large. Le bouton d'envoi passe DANS le champ et ne
   s'affiche que s'il y a quelque chose à envoyer.

   ⚠️ ON NE TOUCHE PAS À .cin : cette classe habille ~20 champs ailleurs (PIN,
   mot de passe, code promo, support, évals). D'où ce wrapper dédié.
   `flex:1;min-width:0` reprend exactement ce que .cin faisait dans .chat-row —
   le flex:1 de .cin devient inerte à l'intérieur du wrapper (qui n'est pas un
   conteneur flex), d'où le width:100% sur le champ.

   UNE SEULE classe .a-envoyer, posée sur le wrapper par majBoutonEnvoyer()
   (js/child.js), pilote À LA FOIS l'affichage du bouton et la réserve de place
   dans le champ : impossible d'avoir l'un sans l'autre. */
.cin-wrap{position:relative;flex:1;min-width:0}
.cin-wrap #chat-input{width:100%}
.cin-wrap.a-envoyer #chat-input{padding-right:42px}
/* Bouton d'envoi intégré — classe/sélecteur À PART, .send-btn n'est pas retouchée. */
.cin-wrap #chat-send{position:absolute;right:4px;top:50%;transform:translateY(-50%);width:34px;height:34px;border-radius:50%;border:none;padding:0;background:var(--v2);cursor:pointer;display:none;align-items:center;justify-content:center}
.cin-wrap.a-envoyer #chat-send{display:flex}
/* Cible tactile portée à 44×44 sans agrandir le dessin — même motif que
   .sel-quit-demo (v16-39) : un ::before transparent en débord de 5 px. */
.cin-wrap #chat-send::before{content:'';position:absolute;top:-5px;right:-5px;bottom:-5px;left:-5px}
/* Bouton « + » : même gabarit 34 px que les anciens boutons de la ligne. */
.chat-plus{background:var(--vl)}
.chip-row{display:flex;gap:6px;flex-wrap:wrap;padding:6px 10px 8px}
.cb{padding:5px 10px;border:none;border-radius:16px;font-family:'Poppins',system-ui,sans-serif;font-size:11px;font-weight:700;cursor:pointer}
.tdots{display:flex;gap:4px;padding:5px 2px}
.tdot{width:6px;height:6px;border-radius:50%;background:var(--v2);opacity:0.5;animation:bop 1.1s infinite}
.tdot:nth-child(2){animation-delay:.2s}
.tdot:nth-child(3){animation-delay:.4s}
@keyframes bop{0%,60%,100%{transform:translateY(0);opacity:0.5}30%{transform:translateY(-5px);opacity:1}}

/* QUICK GRID */
.quick-grid{display:grid;grid-template-columns:1fr 1fr;gap:9px;margin-bottom:10px}
.qcard{background:var(--card);border-radius:var(--r);border:1.5px solid var(--bdr);padding:13px;cursor:pointer;transition:all 0.15s}
.qcard:hover{border-color:var(--v2);transform:translateY(-2px)}
.qi{width:36px;height:36px;border-radius:11px;display:flex;align-items:center;justify-content:center;margin-bottom:7px}
.ql{font-size:12px;font-weight:800;color:var(--ink)}
.qd{font-size:10px;color:var(--ink3);margin-top:1px}

/* LESSONS */
.lscroll{display:flex;gap:9px;overflow-x:auto;padding-bottom:4px;scrollbar-width:none}
.lscroll::-webkit-scrollbar{display:none}
.lchip{flex-shrink:0;min-width:118px;background:var(--card);border:1.5px solid var(--bdr);border-radius:var(--rs);padding:11px 13px;cursor:pointer;transition:all 0.13s}
.lchip:hover{border-color:var(--v2)}
.ls{font-size:9px;font-weight:700;text-transform:uppercase;letter-spacing:0.6px;margin-bottom:4px}
.lt{font-size:11px;font-weight:700;color:var(--ink);line-height:1.3}
.lb{height:3px;border-radius:2px;background:rgba(0,0,0,0.07);margin-top:7px}
.lf{height:100%;border-radius:2px}
.lr{display:flex;align-items:center;gap:10px;padding:10px 12px;background:var(--card);border-radius:var(--rs);border:1.5px solid var(--bdr);margin-bottom:7px;cursor:pointer;transition:all 0.13s}
.lr:hover{border-color:var(--v2)}
.lr-ic{width:34px;height:34px;border-radius:9px;display:flex;align-items:center;justify-content:center;flex-shrink:0}

/* UPLOAD */
.upload-z{border:2px dashed var(--vm);border-radius:var(--r);padding:26px 16px;text-align:center;cursor:pointer;transition:all 0.18s;background:var(--vl);margin-bottom:11px}
.upload-z:hover{border-color:var(--v2);background:rgba(74,45,156,0.1)}
.upload-z p{font-size:12px;color:var(--v2);font-weight:700;margin-top:7px}
.upload-z span{font-size:10px;color:var(--ink3)}

/* RECITE */
.prog-row{display:flex;align-items:center;gap:9px;margin-bottom:10px}
.prog-t{flex:1;height:7px;background:var(--bg);border-radius:4px;overflow:hidden}
.prog-f{height:100%;background:var(--mint);border-radius:4px;transition:width 0.4s}
.prog-p{font-size:12px;font-weight:800;color:var(--mint)}
.qbox{background:var(--vl);border-radius:13px;padding:13px;margin-bottom:10px;font-size:12px;color:var(--ink);line-height:1.6;min-height:54px}
.kchips{display:flex;flex-wrap:wrap;gap:5px}
.kc{padding:4px 9px;border-radius:16px;font-size:10px;font-weight:700}
.kc-ok{background:var(--mintl);color:#085041}
.kc-w{background:var(--ambl);color:#633806}
.kc-f{background:var(--rosel);color:#72243E}

/* STATS */
.stat-g{display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-bottom:10px}
.stat-b{background:var(--card);border-radius:var(--rs);border:1.5px solid var(--bdr);padding:12px;text-align:center}
.stat-n{font-size:20px;font-weight:800;color:var(--v2)}
.stat-l{font-size:10px;color:var(--ink3);margin-top:2px}
.bar-c{display:flex;flex-direction:column;gap:7px}
.bar-r{display:flex;align-items:center;gap:8px}
.bar-lb{font-size:10px;color:var(--ink3);width:54px;flex-shrink:0;text-align:right}
.bar-tr{flex:1;height:7px;background:rgba(45,27,105,0.08);border-radius:4px;overflow:hidden}
.bar-fl{height:100%;border-radius:4px;background:var(--v2);transition:width 0.5s}
.bar-vl{font-size:10px;font-weight:700;color:var(--ink2);width:34px;flex-shrink:0}

/* PLANS */
.pc{background:var(--card);border-radius:var(--r);border:1.5px solid var(--bdr);padding:14px;margin-bottom:9px;position:relative;cursor:pointer;transition:all 0.15s}
.pc:hover{border-color:var(--v2)}
.pc.feat{border:2px solid var(--v2)}
.pbdg{position:absolute;top:-1px;right:13px;background:var(--v2);color:#fff;font-size:9px;font-weight:800;padding:3px 8px;border-radius:0 0 7px 7px}
.pn{font-size:13px;font-weight:800;color:var(--ink);margin-bottom:3px}
.pa{display:flex;align-items:baseline;gap:3px;margin-bottom:3px}
.pe{font-size:22px;font-weight:800;color:var(--ink)}
.pp{font-size:11px;color:var(--ink3)}
.pd{font-size:11px;color:var(--ink3);margin-bottom:10px}
.pf{display:flex;flex-direction:column;gap:5px;margin-bottom:12px}
.pfi{display:flex;align-items:center;gap:6px;font-size:11px;color:var(--ink2)}
.pfck{width:14px;height:14px;border-radius:50%;background:var(--mintl);display:flex;align-items:center;justify-content:center;flex-shrink:0}
/* Vitrine tarifaire (v16 Phase 1) */
.cycle-tog{display:flex;gap:3px;background:var(--bg);border-radius:var(--rxs);padding:3px;margin-bottom:8px}
.cyb{flex:1;padding:9px;border:none;border-radius:6px;font-family:'Poppins',system-ui,sans-serif;font-size:12px;font-weight:800;cursor:pointer;background:transparent;color:var(--ink3);transition:all 0.15s}
.cyb.on{background:var(--v2);color:#fff}
.cycle-badge{display:block;text-align:center;background:var(--ambl);color:#7a5c0d;font-size:11px;font-weight:700;padding:6px 10px;border-radius:99px;margin-bottom:12px}
.cycle-badge b{color:var(--v2)}
.plan-annual{font-size:11px;color:var(--ink3);margin-bottom:3px;min-height:14px}
.plan-annual .eco{color:#00896F;font-weight:800}
.plan-perday{font-size:11px;color:var(--ink3);font-style:italic;margin-bottom:10px;opacity:.92}
/* Échéancier d'un code promo, sous le prix d'une carte forfait (v16 — mois
   offerts). Discret et sur une seule colonne : sur un téléphone la phrase
   passe en 2 lignes sans casser la carte. Vide → masqué (pas de trou). */
.promo-sched{font-size:11px;font-weight:700;color:#085041;background:var(--mintl);border-left:3px solid var(--v2);border-radius:var(--rxs);padding:7px 9px;margin:2px 0 9px;line-height:1.45}
.promo-sched:empty{display:none}
.promo-box{background:var(--card);border:1.5px dashed var(--vm);border-radius:var(--rs);padding:12px;margin:4px 0 10px}
.promo-box label{display:block;font-size:11px;font-weight:800;color:var(--ink2);margin-bottom:8px}
.promo-row{display:flex;gap:7px}
.promo-row .cin{flex:1;min-width:0;text-transform:uppercase}
.promo-row .btn{width:auto;padding:0 16px;white-space:nowrap}
.promo-msg{font-size:11px;font-weight:700;margin-top:8px;min-height:14px}
.promo-msg.ok{color:#085041}
.promo-msg.err{color:var(--rose)}
/* Choix du forfait À L'INSCRIPTION (v16 — le forfait s'applique dès la création
   du compte). Volontairement plus compact que les cartes `.pc` de l'espace
   Compte : le formulaire d'inscription porte déjà 6 champs, 3 cartes pleine
   hauteur de plus le rendraient interminable sur un téléphone. Une ligne =
   un forfait = un tap ; le prix reste l'information la plus lisible. */
.pp-trial{font-size:10px;color:var(--ink3);line-height:1.5;margin:-1px 0 7px}
.pp-list{display:flex;flex-direction:column;gap:7px}
.pp-card{display:block;width:100%;position:relative;text-align:left;background:var(--card);border:1.5px solid var(--bdr);border-radius:var(--rs);padding:10px 40px 10px 12px;font-family:'Poppins',system-ui,sans-serif;cursor:pointer;transition:border-color .15s,background .15s}
.pp-card.sel{border-color:var(--v2);background:var(--vl)}
.pp-head{display:flex;align-items:baseline;justify-content:space-between;gap:8px}
.pp-name{font-size:13px;font-weight:800;color:var(--ink)}
.pp-price{font-size:15px;font-weight:800;color:var(--v2);white-space:nowrap}
.pp-per{font-size:10px;font-weight:700;color:var(--ink3);margin-left:1px}
.pp-inc{font-size:11px;color:var(--ink3);margin-top:3px}
.pp-annual{display:block;font-size:10px;font-weight:800;color:var(--v2);margin-top:3px}
.pp-badge{display:inline-block;background:var(--v2);color:#fff;font-size:9px;font-weight:800;padding:2px 6px;border-radius:99px;margin-left:6px;vertical-align:1px}
.pp-tick{position:absolute;top:50%;right:12px;transform:translateY(-50%);width:19px;height:19px;border-radius:50%;border:1.5px solid var(--bdr);background:var(--card)}
.pp-card.sel .pp-tick{border-color:var(--v2);background:var(--v2)}
.pp-card.sel .pp-tick::after{content:'';position:absolute;left:5px;top:6px;width:8px;height:4px;border-left:2px solid #fff;border-bottom:2px solid #fff;transform:rotate(-45deg)}

/* ══ BLOC OFFRE À COMPTEUR (v16-36) ═══════════════════════════════════════
   UN SEUL bloc remplace les 5 cartes tarifaires, sur les DEUX écrans qui
   vendaient l'offre : l'inscription (préfixe `reg-offer`) et « Mon compte →
   Changer d'offre » (préfixe `acc-offer`). Markup généré par
   offerBlockHTML() / offerBlockUpdate() (js/app.js).
   ⚠️ Les styles `.pc` et `.pp-card` ci-dessus sont VOLONTAIREMENT CONSERVÉS :
   plus personne ne les instancie, mais `.plan-annual`, `.promo-sched`,
   `.cycle-tog`, `.cyb` et `.cycle-badge` du même bloc servent encore (promo,
   toggle Mensuel/Annuel). Leur retrait est un nettoyage à faire dans un lot
   dédié, pas au milieu d'un changement d'écran. */
.offer{background:var(--card);border:2px solid var(--v2);border-radius:var(--r);padding:16px;text-align:center}
.offer-q{font-size:12px;font-weight:700;color:var(--ink2);margin-bottom:10px}
/* Compteur − / +
   `touch-action:manipulation` (v16-37) : sur iOS, deux appuis rapprochés sur un
   même bouton sont interprétés comme un double-tap et déclenchent le zoom de la
   page — très gênant ici, où l'on tape justement plusieurs fois de suite sur +.
   Cette déclaration supprime UNIQUEMENT le double-tap-zoom sur ces boutons ; le
   pincement pour zoomer et le défilement restent intacts partout (on ne touche
   donc pas au meta viewport, qui doit rester zoomable pour l'accessibilité).
   `user-select:none` évite la sélection de texte parasite sur appui maintenu. */
.stepper{display:flex;align-items:center;justify-content:center;gap:16px}
.stp{width:44px;height:44px;border-radius:50%;border:1.5px solid var(--bdr);background:var(--bg);color:var(--v2);font-family:'Poppins',system-ui,sans-serif;font-size:23px;font-weight:700;cursor:pointer;display:flex;align-items:center;justify-content:center;line-height:1;flex-shrink:0;transition:all 0.15s;-webkit-tap-highlight-color:transparent;touch-action:manipulation;-webkit-user-select:none;user-select:none}
.stp:hover:not(:disabled){border-color:var(--v2);background:var(--vl)}
.stp:disabled{opacity:.3;cursor:not-allowed}
.stp:focus-visible{outline:2px solid var(--v2);outline-offset:2px}
.stp-cnt{min-width:66px}
.stp-n{font-size:40px;font-weight:800;color:var(--v2);line-height:1}
.stp-l{font-size:11px;color:var(--ink3);font-weight:700}
/* Prix + lignes secondaires */
.offer-price{margin:12px 0 1px;display:flex;align-items:baseline;justify-content:center;gap:3px;flex-wrap:wrap}
.offer-p{font-size:32px;font-weight:800;color:var(--ink);line-height:1.1}
.offer-u{font-size:12px;color:var(--ink3);font-weight:700}
.offer-strike{text-decoration:line-through;opacity:.5;font-weight:600}
.offer-promo{color:var(--v2)}
.offer-after{font-size:11.5px;color:#0E9488;font-weight:800;min-height:16px;line-height:1.4}
.offer-alt{font-size:11px;color:var(--ink3);min-height:15px;margin-top:2px;line-height:1.4}
.offer-alt b{color:var(--ink2)}
/* Puces incluses */
.offer-feats{display:flex;flex-direction:column;gap:6px;margin-top:13px;text-align:left}
.offer-fi{display:flex;align-items:center;gap:8px;font-size:11.5px;color:var(--ink2)}
.offer-fck{width:15px;height:15px;border-radius:50%;background:var(--mintl);display:flex;align-items:center;justify-content:center;flex-shrink:0;font-size:8px;color:#00896F;font-weight:800}
.offer-perday{font-size:11px;color:var(--ink3);font-style:italic;margin-top:10px;opacity:.92}
.offer-cta{margin-top:12px}
.offer-cta:disabled{background:var(--vl);color:var(--ink3);cursor:not-allowed}
/* L'échéancier promo réutilise `.promo-sched` (défini plus haut) : même
   phrase, même style, qu'on soit sur une carte ou sur le bloc compteur. */
.offer .promo-sched{text-align:left;margin:9px 0 0}

/* ══ BANDEAU DE RÉASSURANCE — inscription (v16-36) ════════════════════════
   ⚠️ Contenu sous contrainte produit : ne JAMAIS y écrire « sans carte
   bancaire » ni « résiliable en 1 clic » (achats in-app → intenable). */
.trust{background:linear-gradient(135deg,#0E9488,#12B5A5);color:#fff;border-radius:14px;padding:13px 14px;margin-bottom:16px;box-shadow:0 4px 14px rgba(14,148,136,0.25)}
.trust-t1{font-size:15px;font-weight:800;display:flex;align-items:center;gap:7px;line-height:1.3}
.trust-t2{font-size:11.5px;opacity:.95;margin-top:5px;line-height:1.5}
.trust-pills{display:flex;gap:6px;margin-top:9px;flex-wrap:wrap}
.trust-pill{background:rgba(255,255,255,0.2);border-radius:99px;padding:3px 9px;font-size:10px;font-weight:800}
/* Sous-texte sous le bouton de création de compte */
.reassure{font-size:11px;color:var(--ink3);text-align:center;margin-top:9px;line-height:1.5}
.reassure b{color:#0E9488}

/* ══ « GÉRER MON ABONNEMENT » — Mon compte (v16-36) ═══════════════════════ */
.manage-sub{display:flex;align-items:center;gap:10px;width:100%;background:var(--bg);border:1.5px solid var(--bdr);border-radius:12px;padding:12px;cursor:pointer;text-align:left;margin-top:12px;font-family:'Poppins',system-ui,sans-serif;transition:border-color 0.15s,background 0.15s}
.manage-sub:hover{border-color:var(--v2);background:var(--vl)}
.manage-sub:focus-visible{outline:2px solid var(--v2);outline-offset:2px}
.ms-ico{font-size:19px;flex-shrink:0}
.ms-txt{flex:1;min-width:0}
.ms-txt b{display:block;font-size:12.5px;color:var(--ink);font-weight:800}
.ms-txt span{font-size:10.5px;color:var(--ink3);line-height:1.4}
.ms-arw{color:var(--ink3);font-size:16px;flex-shrink:0}
.legal-hint{font-size:10px;color:var(--ink3);line-height:1.5;margin-top:8px;background:var(--skyl);border-radius:var(--rxs);padding:8px 10px}

/* Texte réservé aux lecteurs d'écran (zone aria-live du compteur). */
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}

/* REPORT */
.freq-tog{display:flex;gap:3px;background:var(--bg);border-radius:var(--rxs);padding:3px;margin-bottom:11px}
.fb{flex:1;padding:7px;border:none;border-radius:6px;font-family:'Poppins',system-ui,sans-serif;font-size:11px;font-weight:700;cursor:pointer;background:transparent;color:var(--ink3)}
.fb.on{background:var(--v2);color:#fff}
.rp{background:var(--vl);border-radius:var(--rs);padding:11px;margin-bottom:10px}
.rprow{display:flex;justify-content:space-between;padding:5px 0;border-bottom:1px solid rgba(45,27,105,0.1);font-size:11px}
.rprow:last-child{border:none}
.rpk{color:var(--ink2)}
.rpv{font-weight:700;color:var(--v2)}

/* CHILDREN */
.child-c{display:flex;align-items:center;gap:10px;padding:10px 12px;background:var(--card);border-radius:var(--rs);border:1.5px solid var(--bdr);margin-bottom:7px;cursor:pointer;transition:all 0.13s}
.child-c:hover{border-color:var(--v2)}
.av{width:38px;height:38px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:14px;font-weight:800;flex-shrink:0}
.add-c{display:flex;align-items:center;gap:8px;padding:10px 12px;border:2px dashed var(--vm);border-radius:var(--rs);cursor:pointer;color:var(--v2);font-size:12px;font-weight:700;background:transparent;font-family:'Poppins',system-ui,sans-serif;width:100%;transition:all 0.13s;margin-bottom:7px}
.add-c:hover{background:var(--vl)}
.online-dot{width:6px;height:6px;border-radius:50%;background:var(--mint);display:inline-block;margin-right:3px}

/* AUTH */
/* L'écran d'authentification est le SEUL .screen qui n'avait pas de conteneur
   scrollable interne (son contenu est un simple <div> de padding). Tant que le
   document pouvait défiler, iOS rattrapait le coup ; #app étant désormais en
   position:fixed, l'inscription (8 champs + mentions) serait tronquée et le PIN
   inatteignable. Il devient donc lui-même la zone qui défile. */
#s-auth{overflow-y:auto;-webkit-overflow-scrolling:touch}
.auth-wrap{padding:28px 20px;overflow-y:auto;flex:1}
.auth-logo{display:flex;align-items:center;gap:13px;margin-bottom:28px}
.auth-logo h2{font-size:24px;font-weight:800;color:var(--ink)}
.auth-logo p{font-size:11px;color:var(--ink3)}
.auth-title{font-size:18px;font-weight:800;color:var(--ink);margin-bottom:16px}
/* Titre avec flèche de retour (v16-37 connexion, v16-38 inscription → accueil).
   La flèche fait 20 px de glyphe mais doit rester attrapable au pouce : on lui
   donne une zone d'appui de 44×44 (cible tactile minimale du projet), tirée
   vers la gauche par une marge négative pour que le TEXTE du titre reste aligné
   sur les autres écrans — sans ça, tous les titres se décaleraient de 12 px. */
.auth-title-row{display:flex;align-items:center;gap:2px}
.auth-back{display:flex;align-items:center;justify-content:center;width:44px;height:44px;margin-left:-12px;background:none;border:none;padding:0;font-family:'Poppins',system-ui,sans-serif;font-size:20px;font-weight:800;line-height:1;color:var(--v2);cursor:pointer}
.auth-sw{text-align:center;font-size:12px;color:var(--ink3);margin-top:13px}
.auth-sw a{color:var(--v2);font-weight:700;cursor:pointer}

/* ══ ÉCRAN D'ACCUEIL VISITEUR (v16-37) ═══════════════════════════════════
   Première impression : avant, un visiteur tombait sur le formulaire de
   connexion (« Espace parent ») sans savoir ce que fait l'application.
   Structure = maquette validée par Ben : bandeau violet (le MÊME dégradé que
   l'écran sélecteur : une seule identité visuelle) → 3 bénéfices → 2 boutons
   → réassurance → lien démo discret.
   Aucune couleur nouvelle : tout vient de :root (--v2, --vl, --ink*, --ok…).
   ⚠️ Les textes de cet écran sont sous la même contrainte que le bandeau
   d'inscription : jamais « sans carte bancaire » ni « résiliable en 1 clic »
   (achats in-app → paiement et résiliation vivent chez Apple/Google). */
#auth-accueil{width:100%;max-width:480px;margin:0 auto}
.home-hero{position:relative;overflow:hidden;padding:30px 20px 26px;text-align:center;background:linear-gradient(165deg,#3D1F6E 0%,#1A0A40 100%)}
/* Filigrane : même image et même traitement que le fond du sélecteur
   (mix-blend-mode:screen fait disparaître le noir du PNG sur le violet), en
   plus discret. Dimensionné en HAUTEUR (150 % du bandeau) et centré : le
   bandeau d'accueil est bien moins haut que l'écran sélecteur, une largeur en
   % y couperait le logo au ras du titre. Il déborde volontairement en haut et
   en bas, `overflow:hidden` du bandeau le recadre. */
.home-hero-bg{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);height:150%;width:auto;opacity:.30;mix-blend-mode:screen;pointer-events:none;z-index:0}
.home-hero-in{position:relative;z-index:2}
.home-hero h2{font-size:27px;font-weight:800;letter-spacing:-.6px;color:#fff}
.home-tag{margin:8px 14px 0;font-size:13px;line-height:1.55;color:rgba(255,255,255,0.78)}
.home-tag b{color:#fff}
.home-gift{display:inline-flex;align-items:center;gap:6px;margin-top:14px;padding:6px 14px;border-radius:99px;font-size:11.5px;font-weight:800;color:#fff;background:rgba(255,255,255,0.16);border:1px solid rgba(255,255,255,0.26)}
.home-benefits{display:flex;flex-direction:column;gap:11px;padding:18px 20px 4px}
.home-bi{display:flex;align-items:flex-start;gap:11px}
.home-ic{width:34px;height:34px;border-radius:11px;background:var(--vl);display:flex;align-items:center;justify-content:center;font-size:16px;flex-shrink:0}
.home-tx{font-size:12px;line-height:1.5;color:var(--ink2)}
.home-tx b{display:block;font-size:12.5px;font-weight:800;color:var(--ink);margin-bottom:1px}
.home-ctas{display:flex;flex-direction:column;gap:9px;padding:16px 20px 6px}
/* Boutons un cran plus généreux que le .btn standard (cible tactile confortable,
   cf. maquette). v16-52 : les 3 CTA (créer / essayer / déjà un compte) vivent
   désormais dans ce bloc, tous à la même hauteur. */
.home-ctas .btn{padding:13px 16px;font-size:14px;font-weight:800}
/* .btn-ghost est transparent partout ailleurs ; ici il se détache sur le fond
   --bg (le blanc de la carte le rend cliquable au premier coup d'œil). */
.home-ctas .btn-ghost{background:var(--card);color:var(--v2)}
/* v16-52 — accordéon « Comment ça marche ? » : motif natif .fold (v16-46) posé
   sur le fond CLAIR de l'accueil. On ne recrée pas de variante « landing violet »
   car le violet ne couvre QUE .home-hero ; sous le hero, l'accueil est déjà sur
   --bg, exactement le terrain pour lequel .fold a été pensé. Seule retouche : la
   marge latérale de l'accueil (le .fold standard n'en a pas) et le retrait du
   padding vertical du .home-benefits une fois imbriqué dans le .fold-body. */
.home-fold{margin:14px 20px 0}
.home-fold .home-benefits{padding:8px 0 6px}
.home-trust{padding:8px 20px 18px;text-align:center;font-size:10.5px;line-height:1.6;color:var(--ink3)}
.home-trust b{color:var(--ok)}
/* MODE DÉCOUVERTE — .btn-demo est le bouton « ✨ Essayer sans compte » de
   l'accueil. v16-52 : il a rejoint .home-ctas (2ᵉ des 3 CTA), les anciens blocs
   dédiés .home-demo et .home-share (bouton Partager retiré) ont été supprimés.
   Hiérarchie voulue sur l'accueil, du plus fort au plus discret :
     1. « Créer mon compte — 1 mois gratuit » → .btn-v    violet PLEIN  (principale)
     2. « ✨ Essayer sans compte »            → .btn-demo violet PÂLE   (2ᵉ option)
     3. « J'ai déjà un compte »               → .btn-ghost carte blanche (discret)
   Aucune couleur nouvelle : --vl (fond) et --v2 (encre) viennent de :root et
   servent déjà ailleurs (.home-ic, .parent-av, .ibox).
   La BORDURE n'est pas décorative : --vl (#EDE4F8) sur le fond de page --bg
   (#FAF8FE) ne donne qu'un contraste de 1,17:1, très en dessous des 3:1 exigés
   pour délimiter un composant (WCAG 1.4.11). Sans elle, la forme du bouton
   disparaît en plein soleil. L'encre reste à 7,29:1, largement conforme. */
.btn-demo{background:var(--vl);color:var(--v2);border:1.5px solid var(--vm)}
.btn-demo:hover{background:var(--vm)}
.ibox{border-radius:var(--rxs);padding:9px 11px;font-size:11px;margin-bottom:12px}
.ibox-b{background:var(--skyl);color:#0C447C}
.ibox-a{background:var(--ambl);color:#633806}
.ibox-g{background:var(--mintl);color:#085041}
.ibox-r{background:var(--rosel);color:#72243E}                    /* action irréversible */

/* PARENTS DU FOYER (v16) */
.parent-card{display:flex;align-items:center;gap:11px;background:var(--card);border:1px solid var(--bdr);border-radius:var(--rs);padding:10px 12px;margin-bottom:8px}
.parent-av{width:34px;height:34px;border-radius:50%;background:var(--vl);display:flex;align-items:center;justify-content:center;font-size:12px;font-weight:800;color:var(--v2);flex-shrink:0}
.parent-tag{font-size:9px;font-weight:800;padding:2px 7px;border-radius:12px;background:var(--mintl);color:#085041;flex-shrink:0}

/* ZONE DANGEREUSE (suppression de compte) */
.danger-zone{border:1px solid var(--rosel);border-radius:var(--rs);padding:12px;margin:18px 0 10px}
.danger-zone .dz-t{font-size:12px;font-weight:800;color:var(--rose);margin-bottom:5px}
.danger-zone .dz-d{font-size:11px;color:var(--ink3);line-height:1.5;margin-bottom:10px}
.btn-danger{background:transparent;border:1.5px solid var(--rose);color:var(--rose);border-radius:var(--rxs);padding:8px 14px;font-family:'Poppins',system-ui,sans-serif;font-size:12px;font-weight:700;cursor:pointer}

/* SHARE */
.share-url{background:var(--bg);border-radius:var(--rxs);padding:8px 10px;font-size:10px;color:var(--ink2);font-family:monospace;word-break:break-all;margin-bottom:10px;border:1px solid var(--bdr)}

/* MODAL — scroll iOS fix */
.modal-ov{
  display:none;
  /* Même géométrie que #app : la modale couvre la zone VISIBLE, pas le viewport
     de mise en page. Sans ça, clavier ouvert sur iOS, le haut de la modale sort
     par le haut et son bas passe derrière le clavier. */
  position:fixed;left:0;right:0;top:var(--vvtop);height:var(--vvh);
  background:rgba(26,10,0,0.62);
  z-index:200;
  overflow-y:auto;                  /* scroll de la modale elle-même */
  -webkit-overflow-scrolling:touch;
  padding:24px 14px 40px;           /* espace en bas pour le safe area */
  align-items:flex-start;           /* ne pas coller en bas — permet le scroll */
  justify-content:center;
}
.modal-ov.open{display:flex}
.modal-box{
  background:var(--card);
  border-radius:22px;
  /* padding-top élargi : il réserve la place de la croix de fermeture, qui est
     positionnée en absolu et dont la zone de tap fait 44×44 (doigt d'enfant).
     Sans cette réserve, la croix recouvrirait le titre ou les boutons d'action
     de la première ligne (cas de modal-eval-result). */
  padding:44px 18px 18px;
  width:100%;
  max-width:460px;
  position:relative;
  /* PAS de max-height ici — on laisse le contenu dicter la taille */
}
/* CROIX DE FERMETURE — injectée dans chaque .modal-box par setupModalDismiss()
   (js/app.js). Pastille claire opaque + trait foncé : lisible quel que soit le
   contenu qui passe dessous (fond clair comme sombre). */
.modal-x{
  position:absolute;top:3px;right:3px;
  width:44px;height:44px;               /* zone de tap ≥ 44×44 */
  display:flex;align-items:center;justify-content:center;
  padding:0;border:none;background:transparent;cursor:pointer;
  z-index:3;-webkit-tap-highlight-color:transparent;
}
.modal-x::before{
  content:'';position:absolute;inset:6px;border-radius:50%;
  background:var(--bg);border:1.5px solid var(--bdr);
  box-shadow:0 1px 3px rgba(45,27,105,0.12);
}
.modal-x svg{position:relative;width:15px;height:15px;stroke:var(--ink);stroke-width:2.6;stroke-linecap:round}
.modal-x:hover::before{background:var(--vl);border-color:var(--v2)}
.modal-x:active{transform:scale(0.92)}
/* .busy = une tâche IA/upload tourne : la croix reste cliquable, elle demande
   simplement confirmation avant d'abandonner (voir dismissModal). */
.modal-ov.busy .modal-x::before{border-color:var(--amb);background:var(--ambl)}
.modal-box h3{font-size:14px;font-weight:800;color:var(--ink);margin-bottom:13px}
.modal-btns{display:flex;gap:7px;margin-top:12px}
.mbc{flex:1;padding:10px;border-radius:var(--rxs);border:1.5px solid var(--bdr);background:var(--bg);font-family:'Poppins',system-ui,sans-serif;font-size:12px;font-weight:600;color:var(--ink3);cursor:pointer}
.mbo{flex:2;padding:10px;border-radius:var(--rxs);border:none;background:var(--v2);color:#fff;font-family:'Poppins',system-ui,sans-serif;font-size:12px;font-weight:700;cursor:pointer}

/* BANDEAU « CONSULTATION SEULE » (espace enfant)
   Affiché quand la pastille de classe pointe une classe ANTÉRIEURE : l'enfant
   peut relire, mais toute nouvelle leçon ira dans la classe de son profil.
   Ton doux (or), pas d'alerte rouge : ce n'est pas une erreur, c'est de la
   révision. Le bouton ramène en un geste à sa classe. */
.grade-consult-banner{display:flex;align-items:center;gap:8px;flex-shrink:0;padding:8px 12px;background:var(--ambl);border-bottom:1.5px solid rgba(212,160,23,0.35)}
.gcb-emo{font-size:15px;line-height:1}
.gcb-txt{flex:1;font-size:11px;line-height:1.35;color:#6B4E00}
.gcb-txt strong{font-weight:800;color:#4A3600}
.gcb-btn{flex-shrink:0;padding:5px 9px;border:none;border-radius:var(--rxs);background:var(--v2);color:#fff;font-family:'Poppins',system-ui,sans-serif;font-size:10px;font-weight:700;cursor:pointer}

/* SAFETY */
.safety{display:flex;align-items:center;gap:6px;background:var(--mintl);border-radius:var(--rxs);padding:7px 10px;font-size:10px;color:#085041;margin-bottom:10px}
/* Cartes de l'accueil (v15 → v15-7 : plus visuelles, rond coloré + mini-barre) */
.home-card{background:var(--card);border:1.5px solid var(--bdr);border-radius:16px;padding:15px 12px;text-align:center;cursor:pointer;min-height:120px;display:flex;flex-direction:column;align-items:center;justify-content:center;transition:all 0.15s}
.home-card:hover{border-color:var(--v2);transform:translateY(-1px);box-shadow:0 4px 12px rgba(91,33,182,0.08)}
.home-card:active{transform:scale(0.97)}
/* icône dans un rond coloré (accents violet par défaut, or via .hc-a) */
.home-card-icon{width:52px;height:52px;border-radius:15px;display:flex;align-items:center;justify-content:center;font-size:27px;line-height:1;margin-bottom:8px;background:var(--vl);color:var(--v2)}
.hc-a .home-card-icon{background:var(--ambl)}
.home-card-label{font-size:13px;font-weight:800;color:var(--ink);margin-bottom:2px}
.home-card-desc{font-size:10px;color:var(--ink3);line-height:1.3}
/* (v15-10 : les mini-barres de progression décoratives .home-card-pg ont été
   retirées des cartes d'accueil — valeurs arbitraires, aucune information) */
/* carte « Mes corrections » = ton atout (format carte standard, badge conservé) */
.tag-atout{display:inline-block;background:var(--amb);color:#412402;font-size:9px;font-weight:800;border-radius:99px;padding:1px 6px;margin-left:4px;vertical-align:middle}

/* ══════════════════════════════════════════════════════════════════════════
   v16-57 — REFONTE ESPACE ENFANT « ASSISTANT » (Phase 1, coquille UI pure).
   Aucune couleur nouvelle : tout vient de :root (--v2, --vl, --ink*, --bg…) ou
   de la palette SUBJ (injectée inline par renderChildHistory).
   ────────────────────────────────────────────────────────────────────────── */

/* ── Accueil : en-tête « assistant » ── */
.assist-hero{margin-bottom:14px}
.assist-title{font-size:21px;line-height:1.25;font-weight:800;color:var(--ink);margin:0 0 6px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.assist-sub{font-size:12px;line-height:1.4;color:var(--ink3);margin:0}

/* ── Accueil : en-tête « assistant », ligne titre + aide (v16-57 Phase 2) ──
   La ligne .assist-hero-row aligne le titre et l'icône « ? » ; l'icône est
   poussée à droite (margin-left:auto). Au clic elle ouvre la feuille d'aide
   (pitch) via le mécanisme de feuille du bas existant (openActionSheet). */
.assist-hero-row{display:flex;align-items:flex-start;gap:10px}
.assist-hero-row .assist-title{flex:1}
.assist-help{flex:0 0 auto;margin-left:auto;width:32px;height:32px;border-radius:50%;
  background:var(--vl);color:var(--v2);border:none;font-size:15px;font-weight:800;
  display:grid;place-items:center;cursor:pointer}
.assist-help:active{transform:scale(.94)}
/* v17-9 (POINT 4) : bouton refresh déplacé du header vers cp-home, à côté du
   titre. Rond turquoise #0E9488, icône ↺ blanche. flex:0 0 auto pour ne pas
   s'étirer ; aligné avec le titre (la ligne .assist-hero-row aligne en haut). */
.assist-refresh{flex:0 0 auto;width:32px;height:32px;border-radius:50%;
  background:#0E9488;border:none;display:grid;place-items:center;cursor:pointer;
  padding:0;box-shadow:0 3px 10px rgba(14,148,136,.30)}
.assist-refresh:active{transform:scale(.94)}

/* ── Accueil : barre de recherche (porte d'entrée unique). Réutilise le tchat
   existant au clic ; le champ lui-même est readonly (leurre). v16-57 Phase 2 :
   AGRANDIE sur 2 lignes (colonne) — la question sur .assist-qtext, la barre
   d'outils (+ à gauche, loupe à droite) sur .assist-bar dessous. ── */
.assist-search{display:flex;flex-direction:column;align-items:stretch;gap:10px;
  background:var(--card);border:1.5px solid var(--bdr);border-radius:22px;
  padding:14px 15px 11px;box-shadow:0 4px 16px rgba(91,33,182,.08);margin-bottom:18px}
.assist-search:focus-within{border-color:var(--v2)}
/* v17-8 (point 2b) — BARRE DE SAISIE FIGÉE (sticky) : la barre reste visible au
   scroll de cp-home (elle est en HAUT du flux → top:0). #cp-home.scroll est le
   conteneur de défilement (aucun rapport avec l'appareillage viewport/clavier du
   tchat, zone v16-02 : on ne touche NI viewport-fit, NI interactive-widget, NI
   --vvh/--vvtop). Le fond de la carte (var(--card)) est opaque ; un ::before
   opaque (var(--bg)) déborde derrière pour masquer le contenu qui défile sous
   les coins arrondis + la marge. z-index au-dessus du résultat/onglets. */
/* v17-9 (POINT 3) — RÉGRESSION v17-8 corrigée : en sticky, le ::before opaque
   (mask de scroll, z-index:-1) se peint AU-DESSUS du fond/bordure/ombre PROPRES
   de l'élément (ordre de peinture : fond+bordure+ombre du bloc établissant le
   contexte AVANT ses descendants à z-index négatif). Il masquait donc tout
   l'encadré. On sépare les deux rôles :
     • ::before = MASK opaque (var(--bg)) qui déborde pour cacher le contenu qui
       défile derrière les coins arrondis + la marge (peint en premier) ;
     • ::after  = la CARTE VISIBLE (blanc + bordure 1.5px + radius 22px + ombre),
       calée sur le box de la barre (inset:0), peinte APRÈS ::before (même
       z-index:-1, ::after > ::before en ordre d'arbre) donc PAR-DESSUS le mask.
   La saisie/les boutons (enfants réels, z-index auto ≥ 0) restent au-dessus des
   deux pseudos → tout est lisible, l'ombre réapparaît, le sticky continue. On
   neutralise le fond/bordure/ombre du bloc lui-même sur cp-home (ils seraient
   cachés par ::before de toute façon) : c'est ::after qui porte l'encadré. */
#cp-home .assist-search{position:sticky;top:0;z-index:6;
  background:transparent;border-color:transparent;box-shadow:none}
#cp-home .assist-search::before{content:"";position:absolute;left:-14px;right:-14px;
  top:-12px;bottom:-18px;background:var(--bg);z-index:-1}
#cp-home .assist-search::after{content:"";position:absolute;inset:0;z-index:-1;
  background:var(--card);border:1.5px solid var(--bdr);border-radius:22px;
  box-shadow:0 4px 16px rgba(91,33,182,.08);pointer-events:none}
/* Le focus met la bordure de l'encadré (portée par ::after) en violet. */
#cp-home .assist-search:focus-within::after{border-color:var(--v2)}
/* Zone de saisie (leurre readonly) : haute, texte d'invite sur 2 lignes. */
.assist-qtext{font-size:16px;line-height:1.45;color:var(--ink3);min-height:46px;
  background:transparent;border:none;outline:none;width:100%;resize:none;
  font-family:'Poppins',system-ui,sans-serif;cursor:pointer;padding:0}
.assist-qtext::placeholder{color:var(--ink3)}
.assist-bar{display:flex;align-items:center;gap:8px}
.assist-plus{flex:0 0 auto;width:34px;height:34px;border-radius:50%;
  background:var(--vl);display:flex;align-items:center;justify-content:center;
  border:none;cursor:pointer;padding:0}
.assist-plus:active{transform:scale(.94)}
.assist-go{flex:0 0 auto;min-width:52px;height:38px;border-radius:19px;
  padding:9px 18px;background:#0E9488;color:#fff;display:flex;align-items:center;
  justify-content:center;border:none;cursor:pointer;
  box-shadow:0 3px 10px rgba(14,148,136,.30)}
.assist-go:active{transform:scale(.94)}
/* v17-2 (anti-double) : bouton d'envoi désactivé pendant tout le flux recherche
   accueil (réponse + production auto) → visuellement grisé, non cliquable. */
.assist-go.is-busy,.assist-go:disabled{opacity:.5;cursor:default;pointer-events:none;transform:none}

/* ── v17-15 — TCHAT « façon texto » PLAQUÉ EN BAS ────────────────────────────
   #cp-home est une COLONNE FLEX qui remplit le stage (height:100% héritée de
   .child-track .cp-slide). Elle ne scrolle PAS elle-même : le scroll est dans
   #cp-home-scroll (zone haute), et la barre .assist-search-bottom est PLAQUÉE en
   bas (flex, hors scroll), juste au-dessus de .child-nav. Ainsi, conversation
   courte = barre quand même en bas (plus de grand vide). On NE touche PAS au
   viewport/clavier (zone v16-02) : #app garde --vvh ; au clavier, #app rétrécit,
   la colonne #cp-home rétrécit, la barre reste plaquée au-dessus du clavier. */
#cp-home{display:flex;flex-direction:column;min-height:0;overflow:hidden;padding:0}
/* Zone scrollable = tout SAUF la barre. Reprend le padding de .scroll ; réserve
   d'espace bas retirée (la barre + son margin gèrent le dégagement .child-nav). */
#cp-home-scroll{flex:1 1 auto;min-height:0;width:100%;overflow-y:auto;
  -webkit-overflow-scrolling:touch;padding:12px 14px}
/* Quand la barre est MASQUÉE (module ≠ Tchat), le scroll va jusqu'en bas du
   stage : on réserve la hauteur de la pilule .child-nav (flottante) pour ne pas
   cacher la fin du contenu. Quand la barre est visible, elle porte déjà ce
   dégagement → on l'annule ici pour éviter un double vide. */
#cp-home:has(.assist-search-bottom.hide-bar) #cp-home-scroll{padding-bottom:calc(96px + env(safe-area-inset-bottom))}

/* ── v17-14 (T2) — SAISIE « FAÇON TEXTO » : barre UNIQUE, une seule ligne
   (＋ | champ pill | ➤). v17-15 : EN BAS de #cp-home (flex, hors scroll), avec un
   dégagement bas = hauteur de .child-nav pour se poser JUSTE au-dessus du menu. ── */
#cp-home .assist-search-bottom{position:relative;flex:0 0 auto;z-index:6;
  flex-direction:column;align-items:stretch;gap:8px;
  /* v17-17 : dégagement bas CALCULÉ à partir de la vraie taille du menu. La
     variable --assist-bar-clearance (posée par majAssistBarClearance, js/app.js)
     = hauteurRéelleMenu + 12px (offset bottom du menu) + ASSIST_BAR_GAP (espace
     CONFORTABLE voulu, ~24px, réglable en JS). On y ajoute env(safe-area) ici (le
     menu est à bottom:12px+safe → sa hauteur mesurée ne l'inclut pas). Fallback
     94px si la mesure échoue (menu non peint). Résultat : espace généreux au-dessus
     de la pilule, jamais de chevauchement, sur tous les appareils. */
  margin:0;padding:8px 14px calc(var(--assist-bar-clearance, 94px) + env(safe-area-inset-bottom));
  background:transparent;border:none;box-shadow:none}
/* Mask opaque derrière la barre (fond app) pour masquer le fil qui défilerait. */
#cp-home .assist-search-bottom::before{content:"";position:absolute;left:0;right:0;
  top:0;bottom:0;background:var(--bg);z-index:-1}
/* Pas de « carte » englobante (::after) ici : c'est .assist-bar qui porte la pill. */
#cp-home .assist-search-bottom::after{content:none;display:none}
/* La ligne = pill blanche englobant ＋ | champ | ➤. */
#cp-home .assist-search-bottom .assist-bar{background:var(--card);border:1.5px solid var(--bdr);
  border-radius:26px;box-shadow:0 4px 16px rgba(91,33,182,.10);padding:6px 8px;gap:8px}
#cp-home .assist-search-bottom:focus-within .assist-bar{border-color:var(--v2)}
/* Le champ prend toute la largeur, une seule ligne (plus de min-height à 46px). */
#cp-home .assist-search-bottom .assist-qtext{flex:1;min-width:0;min-height:0;height:38px;
  color:var(--ink);cursor:text;padding:0 2px}
/* Clavier ouvert : .child-nav est masquée (body.kb-open .child-nav{display:none})
   → on RETIRE le dégagement bas pour que la barre soit collée au-dessus du
   clavier, sans espace mort. */
body.kb-open #cp-home .assist-search-bottom{padding-bottom:calc(8px + env(safe-area-inset-bottom))}
/* Masquée quand un module ≠ Tchat est actif (posé par assistTabsActiver) → le
   contenu du module occupe alors toute la hauteur. */
#cp-home .assist-search-bottom.hide-bar{display:none}

/* ── Feuille d'aide (pitch « Comment ça marche ? ») — v16-57 Phase 2.
   Rendue DANS la feuille du bas existante (.act-sheet, via le slot bodyHtml
   ajouté à openActionSheet) : pas de nouveau système modal. Ces classes ne
   stylent QUE le contenu du pitch (le chrome ouvrant/fermant reste .act-sheet). */
.help-sheet h3{font-size:16px;margin:0 0 4px;color:var(--ink)}
.help-sheet .lead{font-size:12.5px;color:var(--ink2);line-height:1.5;margin:0 0 12px}
.help-li{display:flex;gap:9px;font-size:12.5px;color:var(--ink2);line-height:1.45;margin-bottom:9px}
.help-li .hic{font-size:15px;flex:0 0 auto}
.help-note{font-size:11.5px;color:var(--amb);background:var(--ambl);border-radius:10px;
  padding:8px 11px;line-height:1.45;margin:4px 0 12px;font-weight:600}
.help-ex{font-size:11.5px;color:var(--ink3);background:var(--bg);border:1px solid var(--bdr);
  border-radius:10px;padding:9px 11px;line-height:1.6}
.help-ex b{color:var(--v2)}
.help-skills{display:flex;gap:6px;flex-wrap:wrap;margin-top:11px}
.help-skill{font-size:11px;font-weight:700;border-radius:99px;padding:3px 10px}

/* ── Accueil : rangée de boutons d'action INACTIFS (Phase 1). .act-off = grisé,
   pointillés, non cliquable. Les styles « actif » sont posés dès maintenant :
   en Phase 2 il suffira de retirer .act-off pour les allumer. ── */
.assist-actions{display:flex;gap:8px;overflow-x:auto;padding:2px 0 4px;
  scrollbar-width:none}
.assist-actions::-webkit-scrollbar{display:none}
.assist-act{position:relative;flex:0 0 auto;display:flex;flex-direction:column;
  align-items:center;gap:5px;min-width:64px;padding:11px 8px;border-radius:16px;
  background:var(--card);border:1.5px solid var(--bdr);cursor:pointer;transition:all .15s}
.assist-act:active{transform:scale(.96)}
.assist-act-ic{font-size:22px;line-height:1}
.assist-act-lb{font-size:10px;font-weight:700;color:var(--ink2);
  white-space:nowrap}
/* état inactif (Phase 1) : estompé + pointillés + neutralisé */
.assist-act.act-off{opacity:.5;border-style:dashed;background:transparent;
  cursor:default;pointer-events:none}
.assist-act.act-off .assist-act-lb{color:var(--ink3)}

/* ── Rangée d'actions SOUS une réponse de hIAbou (v16-57 Phase 2). Réutilise
   les cartes .assist-act (actives), dans une rangée défilante insérée sous la
   bulle IA. Marge haute pour la détacher de la bulle. ── */
.reply-actions{display:flex;gap:8px;overflow-x:auto;padding:8px 0 6px;
  scrollbar-width:none;margin:2px 0 4px 44px}
.reply-actions::-webkit-scrollbar{display:none}
/* Sur l'accueil (v17-2) : pas d'avatar → pas de retrait à gauche. */
.assist-result .reply-actions{margin-left:0}
/* variante « Corriger » : liseré + libellé en rouge (--corr), pastille du nombre
   de corrections détectées. Purement cosmétique : c'est un .assist-act normal. */
.assist-act.act-corr{border-color:var(--corr)}
.assist-act.act-corr .assist-act-lb{color:var(--corr)}
.assist-act .act-badge{position:absolute;top:-5px;right:-5px;min-width:16px;height:16px;
  padding:0 4px;border-radius:99px;background:var(--corr);color:#fff;font-size:9px;
  font-weight:800;display:flex;align-items:center;justify-content:center;line-height:1}

/* ── RÉSULTAT de la recherche RENDU SUR L'ACCUEIL (v17-2). On reste sur cp-home :
   la question + la réponse de hIAbou + les boutons d'action s'affichent ici, sans
   chrome de messagerie. Style volontairement sobre, aligné sur les cartes. ── */
.assist-result{margin-top:14px;display:flex;flex-direction:column;gap:10px}
.assist-result .ar-q{align-self:flex-end;max-width:88%;background:var(--v);color:#fff;
  padding:9px 13px;border-radius:16px 16px 4px 16px;font-size:14px;line-height:1.35;
  white-space:pre-wrap;word-break:break-word}
/* v17-14 (T3) — rangée Léa : avatar rond logo hIAbou à GAUCHE + bulle. */
.assist-result .ar-row.ia{display:flex;align-items:flex-start;gap:8px;max-width:92%;align-self:flex-start}
.assist-result .ar-av{width:30px;height:30px;border-radius:50%;flex:0 0 auto;object-fit:cover;
  background:var(--vl);margin-top:2px}
.assist-result .ar-row.ia .ar-a{flex:1;min-width:0}
.assist-result .ar-a{background:var(--card);border:1.5px solid var(--bdr);border-radius:4px 16px 16px 16px;
  padding:12px 14px;font-size:14px;line-height:1.5;color:var(--ink);word-break:break-word}
.assist-result .ar-a h2{font-size:16px;margin:10px 0 6px}
.assist-result .ar-a h3{font-size:14px;margin:8px 0 4px}
.assist-result .ar-a ul,.assist-result .ar-a ol{padding-left:20px;margin:6px 0}
/* Carte de confirmation « ✅ … créé — Ouvrir/Jouer ». */
.assist-result .ar-card{display:flex;align-items:center;gap:10px;background:var(--mintl);
  border:1.5px solid var(--mint);border-radius:14px;padding:11px 13px;font-size:13px;color:#085041}
.assist-result .ar-card .ar-card-txt{flex:1;font-weight:700}
.assist-result .ar-card .ar-card-sub{font-weight:500;color:#0F6E56;font-size:11px}
/* v17-8 (point 2a) — Carte « changé de sujet ? » : ton neutre (violet), en
   colonne, 2 choix pleine largeur. Distincte des cartes mint « créé ». */
.assist-result .ar-card-switch{flex-direction:column;align-items:stretch;gap:9px;
  background:var(--vl);border-color:var(--v2);color:var(--ink)}
.assist-result .ar-card-switch .ar-card-txt{font-weight:800;color:var(--v2)}
.assist-result .ar-card-switch .ar-card-sub{color:var(--ink2);margin-top:3px;line-height:1.4}
.assist-result .ar-card-switch .ar-card-choices{display:flex;flex-direction:column;gap:7px}
.assist-result .ar-card-switch .ar-card-choices .btn{width:100%;justify-content:center}
/* v17-2 (séquence auto) — carte « en attente » (spinner) puis « échec » discret. */
.assist-result .ar-card-pending{background:var(--card);border-color:var(--bdr);color:var(--ink2)}
.assist-result .ar-card-pending .ar-card-txt{font-weight:600}
.assist-result .ar-card-pending .ar-spin{width:15px;height:15px;flex:0 0 auto;border:2px solid var(--bdr);
  border-top-color:var(--v);border-radius:50%;animation:ar-spin .7s linear infinite}
.assist-result .ar-card-fail{background:var(--bg);border-color:var(--bdr);color:var(--ink3)}
.assist-result .ar-card-fail .ar-card-txt{font-weight:600;font-size:12px}
/* v17-3 — carte « ✅ Exercice prêt » : titre + énoncé multi-lignes (colonne),
   distincte des cartes Leçon/Fiche/Éval (qui sont sur une seule ligne). */
.assist-result .ar-card-exo{display:flex;flex-direction:column;align-items:stretch;gap:8px}
.assist-result .ar-card-exo .ar-exo-body{font-weight:500;color:#085041;font-size:13px;line-height:1.5}
.assist-result .ar-card-exo .ar-exo-body h2,
.assist-result .ar-card-exo .ar-exo-body h3{font-size:14px;font-weight:800;margin:4px 0}
.assist-result .ar-card-exo .ar-exo-body ul,
.assist-result .ar-card-exo .ar-exo-body ol{padding-left:20px;margin:6px 0}
.assist-result .ar-card-exo .ar-exo-body p{margin:5px 0}
.assist-result .ar-busy{display:flex;align-items:center;gap:9px;color:var(--ink2);
  font-size:13px;padding:6px 2px}
.assist-result .ar-busy .ar-spin{width:15px;height:15px;border:2px solid var(--bdr);
  border-top-color:var(--v);border-radius:50%;animation:ar-spin .7s linear infinite}
@keyframes ar-spin{to{transform:rotate(360deg)}}

/* ── ONGLETS COMPACTS DU RÉSULTAT (v17-7, points 5+7) ─────────────────────────
   Rangée horizontale scrollable sous la barre de recherche. Remplace la rangée
   de boutons producteurs. Onglet actif = plein violet ; onglet « prêt » = pastille
   turquoise ; onglet dynamique neuf (Rédaction/Exercice) = liseré pointillé. */
.assist-tabs{display:flex;gap:7px;overflow-x:auto;margin:12px 0 2px;padding-bottom:2px;
  scrollbar-width:none;-ms-overflow-style:none}
.assist-tabs::-webkit-scrollbar{display:none;width:0;height:0}
/* v17-8 (point 2c) — RANGÉE D'ONGLETS FIGÉE (sticky) : reste sous la main au
   scroll pour ne pas « refaire » une leçon par erreur. Calée SOUS la barre
   sticky (2b) : top = hauteur mesurée de la barre (--assist-bar-h, posée par
   assistTabsRender) pour NE PAS chevaucher. z-index sous la barre, au-dessus du
   contenu. Fond opaque (var(--bg)) + petit padding pour masquer le défilé. */
/* v17-14 (T2/T4) : la barre de saisie est passée EN BAS → la rangée de modules
   se cale en HAUT (top:0), juste sous le hero. */
#cp-home .assist-tabs{position:sticky;top:0;z-index:5;
  background:var(--bg);padding-top:6px;margin-top:0}
#cp-home .assist-tabs::before{content:"";position:absolute;left:-14px;right:-14px;
  top:0;bottom:0;background:var(--bg);z-index:-1}
/* v17-14 (T4) — MODULES = petits CARRÉS arrondis, ICÔNE SEULE. Le nom apparaît
   seulement sur l'onglet actif (.has-lb → le carré s'allonge en pilule). */
.assist-tab{flex:0 0 auto;display:flex;align-items:center;justify-content:center;gap:6px;
  width:44px;height:44px;padding:0;border-radius:14px;background:#fff;border:1.5px solid var(--bdr);
  font-size:12px;font-weight:800;color:var(--ink2);white-space:nowrap;cursor:pointer;
  font-family:inherit;position:relative;transition:width .15s ease}
.assist-tab.has-lb{width:auto;padding:0 14px}
.assist-tab .assist-tab-ic{font-size:20px;line-height:1}
.assist-tab .assist-tab-logo{width:24px;height:24px;border-radius:50%;object-fit:cover;display:block}
.assist-tab .assist-tab-lb{font-size:12px;font-weight:800}
.assist-tab.on{background:var(--v);border-color:var(--v);color:#fff}
.assist-tab.on .assist-tab-logo{box-shadow:0 0 0 2px rgba(255,255,255,.5)}
.assist-tab.neuf{border-style:dashed;border-color:var(--mint);color:#0F6E56;background:var(--mintl)}
/* Pastille « prêt » (le livrable existe) ; spinner « en cours » (pending). Placés
   en pastille flottante en haut-droite du carré (plus de place pour un libellé). */
.assist-tab .assist-tab-dot{position:absolute;top:5px;right:5px;width:7px;height:7px;
  border-radius:50%;background:var(--mint);flex:0 0 auto}
.assist-tab .assist-tab-spin{position:absolute;top:4px;right:4px;width:11px;height:11px;flex:0 0 auto;
  border:2px solid var(--bdr);border-top-color:var(--v);border-radius:50%;animation:ar-spin .7s linear infinite}
.assist-tab.on .assist-tab-spin{border-color:rgba(255,255,255,.4);border-top-color:#fff}

/* ── PANNEAU DE CONTENU D'UN ONGLET (rendu EN PLACE, pas de modale) ────────── */
.assist-tabpanel{margin-top:10px;display:flex;flex-direction:column;gap:9px}
/* Bloc « document » (Leçon / Fiche / Éval) inline, aligné sur la maquette. */
.assist-tabpanel .at-doc{background:#fff;border:1.5px solid var(--bdr);border-radius:14px;
  padding:13px 14px}
.assist-tabpanel .at-doc h3{font-size:15px;color:var(--v);margin:0 0 8px;
  display:flex;align-items:center;gap:7px;flex-wrap:wrap}
.assist-tabpanel .at-doc-body{font-size:14px;color:var(--ink);line-height:1.6;word-break:break-word}
.assist-tabpanel .at-doc-body h2{font-size:16px;color:var(--v2);margin:10px 0 6px}
.assist-tabpanel .at-doc-body h3,.assist-tabpanel .at-doc-body h4{font-size:14px;color:var(--v2);margin:8px 0 4px}
.assist-tabpanel .at-doc-body strong{color:var(--v2)}
.assist-tabpanel .at-doc-body ul,.assist-tabpanel .at-doc-body ol{padding-left:20px;margin:6px 0}
.assist-tabpanel .at-doc-body p{margin:6px 0}
/* Photos rattachées (rendu identique à viewLessonDetails, mais inline). */
.assist-tabpanel .at-photo{margin-top:12px}
.assist-tabpanel .at-photo-lb{font-size:11px;font-weight:700;color:var(--ink3);margin-bottom:6px}
.assist-tabpanel .at-photo img{width:100%;border-radius:10px;border:1.5px solid var(--bdr);
  display:block;cursor:zoom-in;background:var(--card);min-height:80px}
/* Point clé (importance) — même code couleur que viewLessonDetails. */
.assist-tabpanel .at-kp{border-radius:10px;padding:12px;margin-bottom:8px;border-left:4px solid #A08060;background:var(--bg)}
.assist-tabpanel .at-kp-lb{font-size:11px;font-weight:800;margin-bottom:4px}
.assist-tabpanel .at-kp-tx{font-size:14px;color:var(--ink);line-height:1.5}
/* v17-13 (T2) — Encart « Ce qu'on attend de toi » : VERT clair (pas jaune),
   objectif d'apprentissage en tête de l'onglet Leçon. Vert = #E3F5EF / #085041
   (mêmes tons que .safety avant le rebrand). Scopé sur .at-doc → vaut aussi dans
   la modale « Mes leçons » (rendu partagé renderLessonBody). */
.at-doc .at-attendu{background:#E3F5EF;border:1.5px solid #B7E4D6;border-left:4px solid #00896F;
  border-radius:12px;padding:11px 13px;margin:0 0 12px}
.at-doc .at-attendu-lb{font-size:11px;font-weight:800;color:#085041;margin-bottom:4px;text-transform:uppercase;letter-spacing:.3px}
.at-doc .at-attendu-tx{font-size:14px;color:#0A3D30;line-height:1.55}
.at-doc .at-attendu-tx strong{color:#064030}
/* v17-13 (T3) — « L'essentiel » dans l'onglet À retenir (quand pas de fiche). */
.at-doc .at-essentiel{background:var(--ambl);border-left:4px solid #A06000;border-radius:12px;
  padding:11px 13px;margin:0 0 10px}
.at-doc .at-essentiel-lb{font-size:11px;font-weight:800;color:#A06000;margin-bottom:4px}
.at-doc .at-essentiel-tx{font-size:14px;color:var(--ink);line-height:1.55}
/* v17-13 (T3) — bouton « Retirer » sur une photo de l'onglet Photos. */
.at-doc .at-photo-lb{display:flex;align-items:center;justify-content:space-between;gap:8px}
.at-doc .at-photo-del{color:var(--rose);font-size:10px;padding:3px 8px}
/* État « en cours de création » (spinner) — repris de la maquette .pending. */
.assist-tabpanel .at-pending{display:flex;align-items:center;gap:9px;background:var(--vl);
  border:1.5px dashed var(--v2);border-radius:12px;padding:12px 14px;color:var(--v2);
  font-weight:800;font-size:13px}
.assist-tabpanel .at-pending .ar-spin{width:16px;height:16px;flex:0 0 auto;border:2.5px solid var(--bdr);
  border-top-color:var(--v2);border-radius:50%;animation:ar-spin .7s linear infinite}
/* État « rien encore » (onglet touché avant génération) + bouton de génération. */
.assist-tabpanel .at-empty{text-align:center;padding:16px 12px;color:var(--ink3);font-size:13px;line-height:1.5}
.assist-tabpanel .at-actions{display:flex;gap:8px;flex-wrap:wrap;margin-top:12px}
.assist-tabpanel .at-actions .btn{flex:1;min-width:130px}
/* Éval inline : compteur + bouton « Jouer » (le moteur eval.js reste en modale). */
.assist-tabpanel .at-eval-count{font-size:10.5px;font-weight:800;color:#0F6E56;background:var(--mintl);
  border-radius:20px;padding:2px 8px}
.assist-tabpanel .at-eval-score{font-size:13px;font-weight:800;color:var(--ink2);margin-top:6px}
/* v17-8 (point 2d) — Info « change de type d'éval dans le tchat ». */
.assist-tabpanel .at-eval-info{font-size:12px;color:var(--ink2);background:var(--vl);
  border-radius:10px;padding:9px 11px;margin-top:10px;line-height:1.45}
/* v17-8 (point 2d) — Bloc « Je t'aide à l'apprendre » (Leçon + À retenir). Le
   bouton déplie 3 sous-boutons vers les mécaniques existantes (répète/récite/
   écris). Réutilise .btn ; mise en page en colonne pour tenir sur mobile. */
.assist-tabpanel .at-apprendre{margin-top:12px}
.assist-tabpanel .at-apprendre-toggle{width:100%}
.assist-tabpanel .at-apprendre-subs{display:flex;flex-direction:column;gap:7px;margin-top:8px}
.assist-tabpanel .at-apprendre-sub{width:100%;justify-content:center}

/* ── Historique (onglet history) ── */
.assist-hist-search{display:flex;align-items:center;gap:8px;background:var(--card);
  border:1.5px solid var(--bdr);border-radius:22px;padding:8px 12px;
  margin-bottom:12px}
.assist-hist-search:focus-within{border-color:var(--v2)}
.assist-hist-ic{flex:0 0 auto}
.assist-hist-input{flex:1;min-width:0;background:transparent;border:none;
  outline:none;font-family:'Poppins',system-ui,sans-serif;font-size:16px;
  color:var(--ink)}
.assist-hist-input::placeholder{color:var(--ink3)}

/* filtres matière : couleurs pilotées par --chip-c / --chip-bg (SUBJ, inline) */
.assist-hist-filters{display:flex;gap:7px;overflow-x:auto;padding:1px 0 10px;
  scrollbar-width:none}
.assist-hist-filters::-webkit-scrollbar{display:none}
.hist-chip{flex:0 0 auto;font-family:'Poppins',system-ui,sans-serif;font-size:12px;
  font-weight:700;padding:6px 13px;border-radius:99px;cursor:pointer;
  border:1.5px solid var(--chip-c);color:var(--chip-c);background:transparent;
  transition:all .15s}
.hist-chip.active{background:var(--chip-bg);border-color:var(--chip-bg)}

/* cartes historique : liseré matière (bord gauche) + pastille + badges.
   Couleurs par --card-c / --card-bg (SUBJ, inline). */
/* Titre de section de date (Aujourd'hui / Cette semaine / Avant). */
.hist-groupe{font-size:11px;font-weight:800;color:var(--ink3);
  text-transform:uppercase;letter-spacing:.04em;margin:14px 2px 8px}
.hist-groupe:first-child{margin-top:2px}
.hist-card{background:var(--card);border:1.5px solid var(--bdr);
  border-left:5px solid var(--card-c);border-radius:14px;padding:12px 14px;
  margin-bottom:10px;cursor:pointer;transition:box-shadow .15s,transform .05s}
.hist-card:active{transform:scale(.99)}
.hist-card:focus-visible{outline:2px solid var(--v2);outline-offset:2px}
.hist-card-top{display:flex;align-items:center;justify-content:space-between;
  gap:8px;margin-bottom:6px}
.hist-pill{font-size:10px;font-weight:800;padding:2px 9px;border-radius:99px;
  color:var(--card-c);background:var(--card-bg)}
.hist-when{font-size:10px;color:var(--ink3);font-weight:600;margin-left:auto}
.hist-del{border:none;background:transparent;font-size:14px;line-height:1;padding:2px 4px;
  cursor:pointer;border-radius:8px;opacity:.6}
.hist-del:hover,.hist-del:active{opacity:1;background:var(--bg)}
.hist-card-title{font-size:14px;font-weight:800;color:var(--ink);
  margin-bottom:8px}
.hist-badges{display:flex;flex-wrap:wrap;gap:6px}
.hist-badge{font-size:10px;font-weight:700;color:var(--ink2);background:var(--bg);
  border:1px solid var(--bdr);border-radius:99px;padding:2px 9px}
.hist-empty{text-align:center;font-size:12px;color:var(--ink3);line-height:1.5;
  padding:22px 16px;background:var(--bg);border:1.5px dashed var(--bdr);
  border-radius:14px;margin-top:4px}

/* MES TROPHÉES (Phase 3 — badges calculés côté client) */
.trophees{display:flex;gap:10px;overflow-x:auto;padding:2px 2px 6px;scrollbar-width:none}
.trophees::-webkit-scrollbar{display:none}
.tr{flex:none;width:66px;text-align:center}
.tr .medal{width:56px;height:56px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:26px;background:var(--card);border:1.5px solid var(--bdr);box-shadow:0 3px 10px rgba(45,27,105,0.08);margin:0 auto 5px}
.tr.win .medal{background:var(--ambl);border-color:var(--amb)}
.tr.locked .medal{opacity:0.45;filter:grayscale(1)}
.tr small{font-size:10.5px;color:var(--ink3);line-height:1.2;display:block}

/* PROGRESSION (dans « Aller plus loin ») — réutilise .goal-bar/.trophees, texte sombre sur carte claire */
.prog-goal{margin-bottom:12px}
.prog-goal .goal-top{color:var(--ink)}
.prog-goal .goal-top b{color:var(--amb2,#b8790a)}
.prog-goal .goal-bar{background:var(--vl)}
.streak-chip.prog-streak{background:var(--ambl);color:#7a4d02;margin-top:9px}
.prog-xp-row{font-size:13px;color:var(--ink2);margin-bottom:14px}
.prog-xp-row b{color:var(--ink);font-weight:800}
.prog-tr-lbl{font-size:12px;font-weight:800;color:var(--ink2);text-transform:uppercase;letter-spacing:0.05em;margin:0 2px 11px}
.prog-help{margin-top:14px;border-top:1.5px solid var(--bdr);padding-top:4px}
.prog-help summary{cursor:pointer;list-style:none;padding:11px 2px;font-size:13px;font-weight:700;color:var(--v2);display:flex;align-items:center;gap:8px}
.prog-help summary::-webkit-details-marker{display:none}
.prog-help summary::before{content:'▸';font-size:12px;transition:transform 0.15s;color:var(--ink3)}
.prog-help[open] summary::before{transform:rotate(90deg)}
.prog-help-body{font-size:12px;color:var(--ink2);line-height:1.5;padding:2px 2px 6px}
.prog-help-body b{color:var(--ink)}
.prog-help-body ul{margin:5px 0 12px;padding-left:18px}
.prog-help-body li{margin-bottom:4px}

/* ════════════════════════════════════════════════════════════════════════
   v17-8 (C1) — PAGE DE GARDE « MES PROGRÈS » (#cp-more). Voir maquette validée.
   Palette du projet (violet --v/--v2), vert LOCAL pour les trophées acquis
   (le projet n'a pas de vert de marque : --mint est en réalité du violet).
   ════════════════════════════════════════════════════════════════════════ */
#cp-more{--mp-gr:#0E9466;--mp-grbg:#E3F5EC}
/* HERO : dégradé violet, points en grand + prochain palier */
.mp-hero{background:linear-gradient(135deg,var(--v),var(--v2));border-radius:18px;padding:16px;color:#fff;text-align:center;margin-bottom:12px}
/* v17-11 (POINT 6) : valeur + « points ✨ » sur UNE ligne (baseline alignée). */
.mp-hero .mp-xp-line{display:flex;align-items:baseline;justify-content:center;gap:7px;flex-wrap:wrap}
.mp-hero .mp-xp{font-size:32px;font-weight:900;letter-spacing:-1px;line-height:1}
.mp-hero .mp-xpl{font-size:15px;opacity:.9;font-weight:800;line-height:1}
.mp-hero .mp-goal{margin-top:9px;background:rgba(255,255,255,.15);border-radius:10px;padding:7px 10px;font-size:11.5px;font-weight:700}
/* v17-10 (POINT 6a) : pastille « Classe : X » dans le hero de Mes progrès.
   Réutilise .grade-pill (select transparent, font-size:16px anti-zoom iOS). */
.mp-hero .mp-grade{display:inline-flex;align-items:center;gap:5px;margin-top:11px;justify-content:center}
.mp-hero .mp-grade .mp-grade-lbl{font-size:12px;font-weight:700;opacity:.9}
/* 2 TUILES cliquables (Mes leçons / Mes évals) + chevron */
.mp-stats{display:flex;gap:10px;margin-bottom:16px}
.mp-stat{flex:1;background:#fff;border:1.5px solid var(--v2);border-radius:14px;padding:13px 8px;text-align:center;position:relative;box-shadow:0 2px 8px rgba(91,33,182,.10);cursor:pointer;font-family:'Poppins',system-ui,sans-serif}
.mp-stat::after{content:"›";position:absolute;top:8px;right:11px;color:var(--v2);font-weight:900;font-size:16px;line-height:1}
.mp-stat:active{transform:scale(.98)}
.mp-stat .mp-stat-n{font-size:23px;font-weight:900;color:var(--v2);line-height:1}
.mp-stat .mp-stat-l{font-size:11px;font-weight:800;color:var(--ink2);margin-top:3px}
/* v17-10 (POINT 12) — bandeau « S'entraîner » (turquoise), cf. maquette */
/* v17-11 (POINT 7) : bandeau plus BAS (padding vertical réduit ~11px), reste
   sur une ligne compacte (icône + « S'entraîner » + sous-texte + Go). */
.mp-train-cta{display:flex;align-items:center;gap:12px;width:100%;text-align:left;
  background:linear-gradient(135deg,#0E9488,#12b3a3);color:#fff;border:none;
  border-radius:16px;padding:11px 16px;margin-bottom:16px;cursor:pointer;
  box-shadow:0 6px 18px rgba(14,148,136,.32);font-family:'Poppins',system-ui,sans-serif}
.mp-train-cta:active{transform:scale(.99)}
.mp-train-cta .mp-train-ic{font-size:26px;line-height:1}
.mp-train-cta .mp-train-tt{flex:1;min-width:0}
.mp-train-cta .mp-train-tt b{font-size:16px;font-weight:900;display:block}
.mp-train-cta .mp-train-tt span{font-size:11.5px;opacity:.92;display:block;margin-top:1px}
.mp-train-cta .mp-train-go{background:rgba(255,255,255,.22);border-radius:12px;
  padding:7px 12px;font-size:12.5px;font-weight:800;white-space:nowrap;flex-shrink:0}
/* SECTION trophées — v17-11 (POINT 4) : titre + pastille info EN FACE (<details>).
   Le <summary> porte la ligne de titre (« 🏆 Trophées » + pastille ⓘ à droite) ;
   cliquer révèle l'explication (.mp-troph-exp). La grille reste sous ce bloc. */
.mp-troph-acc{margin:4px 2px 9px}
.mp-troph-acc summary.mp-troph-h{list-style:none;cursor:pointer;display:flex;align-items:center;gap:8px}
.mp-troph-acc summary.mp-troph-h::-webkit-details-marker{display:none}
.mp-troph-acc .mp-troph-t{font-size:14px;font-weight:800;color:var(--ink)}
.mp-troph-acc .mp-troph-info{margin-left:auto;font-size:11px;font-weight:800;color:var(--v2);background:var(--vl);border-radius:20px;padding:4px 11px;display:inline-flex;align-items:center;gap:5px;white-space:nowrap}
.mp-troph-acc[open] .mp-troph-info{background:var(--v2);color:#fff}
.mp-troph-acc .mp-troph-exp{margin-top:9px;background:#fff;border:1.5px solid var(--bdr);border-radius:13px;padding:12px 14px;font-size:12px;color:var(--ink2);line-height:1.55}
.mp-troph-acc .mp-troph-exp b{color:var(--v2)}
.mp-troph{display:grid;grid-template-columns:1fr 1fr 1fr;gap:9px;margin-bottom:14px}
.mp-tr{border-radius:13px;padding:11px 5px;text-align:center;border:1.5px solid var(--bdr)}
.mp-tr .mp-tr-ic{font-size:26px;line-height:1}
.mp-tr .mp-tr-tl{font-size:9.5px;font-weight:800;margin-top:3px;line-height:1.15}
.mp-tr .mp-tr-cond,.mp-tr .mp-tr-prog{font-size:8.5px;margin-top:2px}
.mp-tr.done{background:var(--mp-grbg);border-color:var(--mp-gr)}
.mp-tr.done .mp-tr-tl{color:#0a6d4c}
.mp-tr.done .mp-tr-cond{color:var(--mp-gr);font-weight:700}
.mp-tr.next{background:#f3f1f7;border-color:#e0dcea}
.mp-tr.next .mp-tr-ic{filter:grayscale(1);opacity:.45}
.mp-tr.next .mp-tr-tl{color:#9a92ac}
.mp-tr.next .mp-tr-prog{color:#8a82a0;font-weight:800}

/* v17-8 (C1) — EN-TÊTE des listes « Mes leçons » / « Mes évals » + regroupement
   par matière. Le turquoise de la maquette n'existe pas dans la palette du
   projet → bouton « + » en violet de marque (--v2). Les couleurs des en-têtes
   de matière viennent de SUBJ (inline, source unique de vérité). */
.mp-list-top{display:flex;align-items:center;gap:8px;margin-bottom:10px}
.mp-list-top .mp-list-h{font-size:18px;font-weight:800;flex:1;color:var(--ink);margin:0}
.mp-add{background:var(--v2);color:#fff;border:none;border-radius:12px;padding:8px 13px;font-size:12.5px;font-weight:800;white-space:nowrap;cursor:pointer;font-family:'Poppins',system-ui,sans-serif}
.mp-add:active{transform:scale(.97)}
.mp-mat-h{font-size:11px;font-weight:800;text-transform:uppercase;letter-spacing:.4px;margin:12px 2px 7px;display:flex;align-items:center;gap:7px}
.mp-mat-h .mp-mat-dot{width:9px;height:9px;border-radius:50%;flex-shrink:0}

/* ── Blocs repliables « fold » (Lot 2 espace parent) ──
   Réutilise le mécanisme natif <details>/<summary> déjà éprouvé sur
   .prog-help. Fermé par défaut, sans animation lourde, focus visible.
   Rien n'est caché fonctionnellement : le contenu reste dans le DOM et
   tous les id/handlers déplacés y restent joignables. */
.fold{margin-bottom:12px;border:1.5px solid var(--bdr);border-radius:14px;background:var(--card,#fff);overflow:hidden}
.fold>summary{cursor:pointer;list-style:none;padding:13px 14px;font-size:13px;font-weight:800;color:var(--ink);display:flex;align-items:center;gap:9px}
.fold>summary::-webkit-details-marker{display:none}
.fold>summary::before{content:'▸';font-size:12px;color:var(--v2);transition:transform 0.15s;flex-shrink:0}
.fold[open]>summary::before{transform:rotate(90deg)}
.fold>summary:focus-visible{outline:2px solid var(--v2);outline-offset:-2px}
.fold-body{padding:0 14px 8px}
.fold-body>.card:first-child,.fold-body>.card-title:first-child{margin-top:0}
/* Badge à droite du résumé d'un accordéon (Lot 2 « Mon abonnement ») */
.fold-right{margin-left:auto;font-size:11px;font-weight:700;color:var(--ink3)}

/* ── Mon compte : bloc statut + quota fair-use (Lot 2 v16-31) ── */
.quota-box{border:none;padding:0;margin-bottom:10px}
.badge-beta{display:inline-block;background:#0F6E56;color:#D6F7F1;font-size:10px;font-weight:800;padding:3px 9px;border-radius:99px}
.badge-plan{display:inline-block;background:var(--vl);color:var(--v2);font-size:10px;font-weight:800;padding:3px 9px;border-radius:99px}
.badge-ok{display:inline-block;background:var(--mintl);color:#085041;font-size:10px;font-weight:800;padding:3px 9px;border-radius:99px}
/* Barre de quota : réutilise .bar-tr/.bar-fl ; variante « chaude » proche du plafond */
.bar-fl-hot{background:var(--rose)}

/* TOAST
   `white-space:nowrap` débordait des DEUX côtés de l'écran dès qu'un message
   dépassait ~45 caractères (translateX(-50%) sur une bulle plus large que le
   téléphone) : le message de refus « 2 classes » était illisible. On borne la
   largeur et on autorise le retour à la ligne ; un toast court reste sur une
   seule ligne, l'aspect ne change pas pour les messages existants. */
#toast{position:fixed;top:calc(14px + var(--vvtop));left:50%;transform:translateX(-50%) translateY(-70px);background:var(--ink);color:#fff;padding:9px 18px;border-radius:18px;font-size:12px;font-weight:700;max-width:min(92vw,440px);white-space:normal;text-align:center;line-height:1.35;z-index:9999;transition:transform 0.28s;pointer-events:none}
#toast.show{transform:translateX(-50%) translateY(0)}

/* INSTALL BANNER */
#install-banner{display:none;background:var(--v);color:#fff;padding:11px 14px;align-items:center;gap:10px;flex-shrink:0}
#install-banner.show{display:flex}
#install-banner p{flex:1;font-size:12px;font-weight:600}
#install-banner button{background:white;color:var(--v2);border:none;border-radius:var(--rxs);padding:6px 13px;font-family:'Poppins',system-ui,sans-serif;font-size:11px;font-weight:800;cursor:pointer}
#install-dismiss{background:transparent!important;color:rgba(255,255,255,0.6)!important;font-size:15px!important}

@media(min-width:480px){#app{box-shadow:0 0 40px rgba(45,27,105,0.15)}}
.screen.active{animation:fadein 0.2s ease}
@keyframes fadein{from{opacity:0;transform:translateY(5px)}to{opacity:1;transform:translateY(0)}}
::-webkit-scrollbar{display:none}

/* ── SELECTOR SCREEN (qui veut travailler ?) ── */
.selector-wrap{padding:20px 16px;flex:1;width:100%}
.selector-bg-wrap{flex:1 1 auto;width:100%;position:relative;min-height:0}
.selector-header{text-align:center;margin-bottom:24px;margin-top:14px}
.selector-header h2{font-size:20px;font-weight:800;color:var(--ink);margin-bottom:4px}
.selector-header p{font-size:13px;color:var(--ink3)}
.selector-grid{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-bottom:20px}
/* Cartes en verre dépoli sur le fond violet (v15.4) */
.selector-card{background:rgba(255,255,255,0.12);border-radius:18px;padding:16px;cursor:pointer;transition:all 0.18s;text-align:center;border:1.5px solid rgba(255,255,255,0.18);backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px)}
.selector-card:hover{transform:translateY(-2px);border-color:rgba(167,139,250,0.6);background:rgba(255,255,255,0.18);box-shadow:0 6px 18px rgba(0,0,0,0.25)}
.selector-card:active{transform:scale(0.97)}
.selector-avatar{width:80px;height:80px;border-radius:50%;display:flex;align-items:center;justify-content:center;margin:0 auto 10px}
.selector-name{font-size:14px;font-weight:800;color:#fff}
.selector-grade{font-size:11px;color:rgba(255,255,255,0.6);margin-top:2px}
.selector-parent{background:rgba(212,160,23,0.18);border-color:rgba(212,160,23,0.4)}
.selector-parent .selector-name{color:#FDCB6E}
.selector-parent .selector-grade{color:rgba(253,203,110,0.7)}
.selector-add{background:rgba(255,255,255,0.06);border:1.5px dashed rgba(255,255,255,0.3)}
.selector-add .selector-name{color:#fff}
.selector-add .selector-grade{color:rgba(255,255,255,0.5)}

.selector-footer{text-align:center;padding-top:14px;border-top:1px solid var(--bdr);margin-top:14px}
.btn-logout{background:transparent;border:none;color:var(--ink3);font-size:11px;cursor:pointer;font-family:inherit}

/* ── AVATAR PICKER (modal) ── */
.avatar-grid{display:flex;flex-direction:column;gap:8px;max-height:280px;overflow-y:auto;padding:4px;margin-bottom:12px}
.av-pick{padding:8px;border-radius:10px;border:1.5px solid var(--bdr);cursor:pointer;display:flex;flex-direction:column;align-items:center;justify-content:center;transition:all 0.15s;background:var(--bg);min-height:50px}
.av-pick:hover{transform:scale(1.08)}
.av-pick.selected{border:2.5px solid var(--v2);transform:scale(1.05)}

/* ── BACK BUTTON child header ── */
.back-btn{background:rgba(255,255,255,0.18);border:1px solid rgba(255,255,255,0.25);color:white;border-radius:50%;width:34px;height:34px;display:flex;align-items:center;justify-content:center;cursor:pointer;flex-shrink:0;z-index:1}
.back-btn:hover{background:rgba(255,255,255,0.28)}

/* ── PIN MODAL ── */
.pin-input{-webkit-text-security:disc;width:100%;padding:14px;font-size:24px;font-weight:800;text-align:center;letter-spacing:14px;border:2px solid var(--bdr);border-radius:12px;background:var(--bg);color:var(--v2);outline:none;font-family:'Poppins',system-ui,sans-serif}
.pin-input:focus{border-color:var(--v2)}

/* ── CHILD CARD with avatar in selector context ── */
.child-card-v6{display:flex;align-items:center;gap:12px;padding:12px 14px;background:var(--card);border-radius:var(--rs);border:1.5px solid var(--bdr);margin-bottom:8px;transition:all 0.15s}
.child-card-v6 .av-emoji{width:42px;height:42px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:24px;flex-shrink:0}

/* ── v10 : POLICES PLUS GRANDES POUR LES ENFANTS ── */
/* Texte de récitation/mémorisation : plus gros */
#rec-question-area > div:last-child{font-size:16px !important;line-height:1.6 !important}
#memo-text-display div{font-size:16px}
/* Texte du modal de détail leçon */
.lv-content{font-size:14px;line-height:1.6;color:var(--ink)}
/* Phrase courante surlignée plus visible en mémorisation */
#memo-text-display [id^="memo-sent-"][style*="background:#FFF7CC"]{font-size:17px !important;font-weight:600}
/* Modal training */
#training-running-question{font-size:18px !important;line-height:1.5 !important}

/* ── v14 : SUGGESTION CHIPS ── */
.sug-chip {
  display:inline-flex;align-items:center;gap:5px;
  background:var(--vl);border:1.5px solid var(--v2);
  color:var(--v2);border-radius:20px;
  padding:6px 12px;font-size:12px;font-weight:700;
  font-family:'Poppins',system-ui,sans-serif;
  cursor:pointer;transition:background 0.15s,transform 0.1s;
  white-space:nowrap;
}
.sug-chip:hover{background:var(--v2);color:white;transform:scale(1.03)}
.sug-chip:active{transform:scale(0.97)}

/* ── v16-41 (lot 3) : LES PROPOSITIONS DANS LA CONVERSATION ────────────────
   Les puces ci-dessus vivaient dans un bandeau fixe (#chat-suggestions) entre
   le fil et la barre de saisie. Elles sont maintenant insérées DANS #chat-msgs,
   juste après la bulle d'accueil, par renderChatSuggestions() (js/child.js).
   · flex-wrap:wrap — dans un bandeau d'une ligne il fallait défiler
     horizontalement pour découvrir les 4 dernières (personne ne le devinait) ;
     dans le fil, la place est verticale : les 7 sont visibles d'un coup.
   · padding-left 35px = .bav (28px) + gap de .brow (7px) : les puces s'alignent
     sur le bord gauche des bulles de la mascotte, elles se lisent comme la
     suite de son message d'accueil.
   · #chat-msgs est déjà `display:flex;flex-direction:column;gap:9px` : ce bloc
     est un élément de cette colonne, il n'a besoin d'aucune marge verticale.
   Aucune règle liée au clavier : ce bloc défile, il n'a plus à disparaître. */
.chat-props{display:flex;flex-wrap:wrap;gap:6px;padding-left:35px}

/* ── v14 : CORBEILLE ── */
.trash-item{display:flex;align-items:center;gap:10px;padding:10px 0;border-bottom:1px solid var(--bdr)}
.trash-item-ico{width:36px;height:36px;border-radius:10px;background:var(--rosel);display:flex;align-items:center;justify-content:center;font-size:16px;flex-shrink:0}

/* ══════════════════════════════════════════════════════════
   v15.9 — DEVOIRS (espace enfant, BRIQUE 3)
   Palette et rayons repris des cartes existantes : rien de nouveau,
   juste la mise en page des 3 sous-onglets.
══════════════════════════════════════════════════════════ */

/* Sous-onglets À faire / Planning / Faits */
.dv-tabs{display:flex;gap:6px;margin-bottom:12px}
.dv-tab{flex:1;padding:8px 6px;border-radius:20px;border:1.5px solid var(--bdr);background:var(--card);color:var(--ink3);font-family:'Poppins',system-ui,sans-serif;font-size:11px;font-weight:700;cursor:pointer;transition:all 0.15s;white-space:nowrap}
.dv-tab.on{background:var(--v2);border-color:var(--v2);color:#fff}

/* ══ DEVOIRS Lot 2 v16-31 : toggle Liste/Agenda + filtre + coche ══ */
/* Toggle Liste / Agenda (façon cycle-tog) */
.vtog{display:flex;gap:3px;background:var(--bg);border:1px solid var(--bdr);border-radius:var(--rxs);padding:3px;margin-bottom:9px}
.vtog button{flex:1;padding:8px;border:none;border-radius:6px;font-family:'Poppins',system-ui,sans-serif;font-size:12px;font-weight:800;background:transparent;color:var(--ink3);cursor:pointer}
.vtog button.on{background:var(--v2);color:#fff}
/* v16-33 : filtres ADDITIFS « À faire » / « Réalisés » (les 2 actifs = tout
   visible ; pastille = état ; « Réalisés » actif prend la teinte verte). */
.dv-filt{display:flex;gap:8px;margin-bottom:11px}
.dv-filt-btn{flex:1;padding:8px 10px;border-radius:99px;border:1.5px solid var(--bdr);background:var(--card);font-family:'Poppins',system-ui,sans-serif;font-size:11.5px;font-weight:800;color:var(--ink3);cursor:pointer;display:flex;align-items:center;justify-content:center;gap:7px}
.dv-filt-btn.on{background:var(--v2);border-color:var(--v2);color:#fff}
.dv-filt-btn.on.done{background:var(--ok);border-color:var(--ok)}
.dv-filt-btn .dot{width:9px;height:9px;border-radius:50%;background:currentColor;opacity:.9;flex-shrink:0}
.dv-filt .cnt{font-size:10px;font-weight:800;padding:0 6px;border-radius:99px;background:rgba(45,27,105,.12);color:inherit}
.dv-filt-btn.on .cnt{background:rgba(255,255,255,.25)}
/* Bandeau « semaines suivantes » — incite à changer de semaine (cliquable). */
.dv-next-banner{display:flex;align-items:center;gap:9px;background:var(--ambl);color:#7a5c0d;border-radius:12px;padding:9px 11px;font-size:11.5px;line-height:1.35;margin-bottom:11px;cursor:pointer}
.dv-next-banner b{color:var(--v2)}
.dv-next-banner .go{margin-left:auto;font-weight:800;color:var(--v2);white-space:nowrap}
.dv-next-banner:focus-visible{outline:2px solid var(--v2);outline-offset:2px}
/* Nudge d'anticipation (ancienne vue liste — conservé, inoffensif) */
.nudge{background:var(--ambl);color:#7a5c0d;border-radius:12px;padding:10px 12px;font-size:11.5px;line-height:1.45;margin-bottom:8px}
/* En-tête de groupe par échéance (« Pour demain… ») */
.dv-day-h{font-size:12px;font-weight:800;color:var(--ink2);margin:14px 2px 7px}
.dv-day-h:first-child{margin-top:0}

/* Une ligne = un devoir. Toute la ligne est cliquable (action-sheet). */
.dv-item{display:flex;align-items:center;gap:11px;padding:11px 12px;background:var(--card);border:1.5px solid var(--bdr);border-radius:12px;margin-bottom:7px;cursor:pointer}
.dv-item:active{background:var(--bg)}
.dv-item:focus-visible{outline:2px solid var(--v2);outline-offset:2px}
.dv-item.done{background:var(--okl);border-color:rgba(14,148,136,.3);cursor:default}
.dv-item.done .dv-desc{color:var(--ink2)}
.dv-ico{width:36px;height:36px;border-radius:11px;background:var(--vl);display:flex;align-items:center;justify-content:center;font-size:18px;flex-shrink:0}
/* Coche verte CLAIRE — indicateur d'état sur les réalisés uniquement */
.dv-check{width:26px;height:26px;border-radius:50%;background:var(--ok);display:flex;align-items:center;justify-content:center;flex-shrink:0}
.dv-check svg{width:13px;height:13px}
.dv-body{flex:1;min-width:0}
.dv-desc{font-size:12.5px;font-weight:700;color:var(--ink);line-height:1.35;word-break:break-word}
.dv-meta{font-size:10.5px;color:var(--ink3);margin-top:3px;display:flex;flex-wrap:wrap;gap:5px;align-items:center}
.dv-chev{color:var(--ink3);font-size:16px;flex-shrink:0}
/* Badge « auto » (passé en réalisé par la règle J+2) */
.dv-auto{font-size:9px;font-weight:800;color:var(--ok);background:#fff;border:1px solid rgba(14,148,136,.3);border-radius:99px;padding:1px 6px;margin-left:6px;white-space:nowrap}
/* Badge de source (photo / EcoleDirecte / saisi) */
.src{font-size:9px;font-weight:800;padding:1px 6px;border-radius:99px}
.src-photo{background:var(--skyl);color:#0C447C}
.src-ed{background:var(--mintl);color:#085041}
.src-man{background:var(--ambl);color:#633806}

/* Vue AGENDA — semaine Lun→Dim */
.dv-wk-head{display:flex;justify-content:space-between;align-items:center;margin-bottom:8px}
.dv-wk-nav{width:30px;height:30px;border-radius:9px;border:1px solid var(--bdr);background:var(--card);color:var(--v2);font-size:15px;cursor:pointer}
.dv-wk-title{font-size:12px;font-weight:800;color:var(--ink)}
.dv-day-row{display:flex;gap:10px;padding:9px 0;border-top:1px solid var(--bdr)}
.dv-day-row:first-of-type{border-top:none}
.dv-day-row.past{opacity:.5}
.dv-day-row.vac .dv-chips{opacity:.85}
.dv-dcol{width:44px;flex-shrink:0;text-align:center}
.dv-dname{font-size:10px;font-weight:700;color:var(--ink3);text-transform:uppercase}
.dv-dnum{font-size:17px;font-weight:800;color:var(--ink);line-height:1.1}
.dv-day-row.today .dv-dnum{background:var(--v2);color:#fff;border-radius:9px;padding:1px 0;display:block}
.dv-day-row.today .dv-dname{color:var(--v2)}
.dv-chips{flex:1;display:flex;flex-direction:column;gap:5px;min-width:0;padding-top:2px}
.dv-chip{display:flex;align-items:center;gap:7px;background:var(--card);border:1.5px solid var(--bdr);border-left:3px solid var(--v2);border-radius:9px;padding:6px 9px;font-size:11px;font-weight:600;color:var(--ink);cursor:pointer;min-width:0}
.dv-chip:active{background:var(--bg)}
.dv-chip:focus-visible{outline:2px solid var(--v2);outline-offset:2px}
.dv-chip-t{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.dv-chip-em{font-size:14px;flex-shrink:0}
.dv-chip-ck{flex-shrink:0}
/* v16-33 : FAIT = fond vert + coche verte, texte LISIBLE (jamais barré). */
.dv-chip.done{background:var(--okl);border-color:var(--ok);border-left-color:var(--ok);color:var(--ink)}
.dv-chip.done .dv-chip-ck{color:var(--ok)}
/* Barre de couleur = matière (aligné sur MATIERE_EMOJI / matiereSlug) */
.dv-chip-francais{border-left-color:#B45309}
.dv-chip-sciences{border-left-color:#0E9488}
.dv-chip-histoire-geo{border-left-color:#6366F1}
.dv-chip-anglais{border-left-color:#0F6E56}
.dv-chip-maths{border-left-color:#5B21B6}
.dv-empty-day{font-size:10.5px;color:var(--ink3);font-style:italic;padding-top:6px;opacity:.7}
.dv-leg{font-size:10px;color:var(--ink3);text-align:center;margin-top:10px;line-height:1.5}

/* Planning — 7 colonnes, scroll horizontal sur téléphone */
.dv-week-wrap{overflow-x:auto;-webkit-overflow-scrolling:touch;scrollbar-width:none;margin:0 -2px}
.dv-week-wrap::-webkit-scrollbar{display:none}
.dv-week{display:grid;grid-template-columns:repeat(7,minmax(104px,1fr));gap:6px;padding:2px}
.dv-day{background:var(--card);border:1.5px solid var(--bdr);border-radius:12px;padding:8px 7px;min-height:120px}
.dv-day.today{border-color:var(--v2);box-shadow:0 0 0 2px var(--vl)}
.dv-day.vac{background:var(--bg);opacity:0.75}
.dv-day-lbl{font-size:10px;font-weight:800;color:var(--ink2);text-align:center;margin-bottom:6px;text-transform:capitalize}
.dv-day.today .dv-day-lbl{color:var(--v2)}
.dv-day-vac{font-size:9px;color:var(--ink3);text-align:center;font-style:italic}
.dv-slot{background:var(--vl);border-radius:9px;padding:6px;margin-bottom:5px;font-size:10px;color:var(--ink);line-height:1.3;cursor:pointer}
.dv-slot b{display:block;font-size:10px;font-weight:800;margin-bottom:1px}
.dv-slot.done{background:var(--okl);opacity:0.9}

/* Bouton flottant « + Ajouter un devoir », au-dessus de la barre de nav.
   position:absolute (et non fixed) : l'ancêtre positionné est #app, qui est
   limité à 480px et centré — le bouton reste donc dans la colonne de l'app,
   y compris sur grand écran, et ne défile pas avec la liste. */
/* v16-18 : FAB « + Ajouter un devoir » déplacé en bas à GAUCHE (décision Ben) —
   la bulle Aider occupe désormais le bas-droite. Position remontée pour ne pas
   passer sous la pilule flottante. Handler inchangé (openDevoirModal). */
.dv-fab{position:absolute;left:16px;bottom:calc(84px + env(safe-area-inset-bottom));z-index:20;background:var(--v2);color:#fff;border:none;border-radius:26px;padding:12px 18px;font-family:'Poppins',system-ui,sans-serif;font-size:13px;font-weight:800;cursor:pointer;box-shadow:0 6px 18px rgba(91,33,182,0.32)}
.dv-fab:active{transform:scale(0.96)}

/* Modale d'ajout — choix du mode */
.dv-modes{display:flex;flex-direction:column;gap:8px}
.dv-mode{display:flex;align-items:center;gap:12px;padding:14px;border-radius:14px;border:1.5px solid var(--bdr);background:var(--card);cursor:pointer;text-align:left;width:100%;font-family:'Poppins',system-ui,sans-serif}
.dv-mode:hover{border-color:var(--v2)}
.dv-mode-ico{width:42px;height:42px;border-radius:13px;background:var(--vl);display:flex;align-items:center;justify-content:center;font-size:21px;flex-shrink:0}
.dv-mode-t{font-size:13px;font-weight:800;color:var(--ink)}
.dv-mode-d{font-size:10px;color:var(--ink3);margin-top:1px}

/* Écran de confirmation des devoirs extraits */
.dv-confirm{border:1.5px solid var(--bdr);border-radius:13px;padding:10px;margin-bottom:8px;background:var(--card)}
.dv-confirm.off{opacity:0.5}
.dv-confirm-top{display:flex;align-items:center;gap:8px;margin-bottom:7px}
.dv-confirm-top input[type=checkbox]{width:18px;height:18px;accent-color:var(--v2);flex-shrink:0}
.dv-grid2{display:grid;grid-template-columns:1fr 1fr;gap:7px}
/* font-size:16px obligatoire (zoom auto iOS sous 16px) — compacité via le padding */
.dv-in{width:100%;padding:6px 10px;border:1.5px solid var(--bdr);border-radius:10px;font-family:'Poppins',system-ui,sans-serif;font-size:16px;color:var(--ink);background:var(--bg);outline:none}
.dv-in:focus{border-color:var(--v2)}
.dv-lbl{font-size:10px;font-weight:700;color:var(--ink2);display:block;margin-bottom:3px}
.dv-diffs{display:flex;gap:6px}
.dv-diff-btn{flex:1;padding:9px 4px;border-radius:10px;border:1.5px solid var(--bdr);background:var(--bg);font-family:'Poppins',system-ui,sans-serif;font-size:11px;font-weight:700;color:var(--ink2);cursor:pointer}
.dv-diff-btn.on{background:var(--v2);border-color:var(--v2);color:#fff}

/* Transcription vocale live */
.dv-live{min-height:76px;background:var(--vl);border-radius:13px;padding:12px;font-size:13px;color:var(--ink);line-height:1.5;margin-bottom:10px}
.dv-live-hint{font-size:10px;color:var(--ink3);text-align:center;margin-bottom:8px}
.dv-rec-dot{display:inline-block;width:8px;height:8px;border-radius:50%;background:var(--rose);margin-right:6px;animation:micp 1s infinite}

/* Stats de l'onglet Faits */
.dv-stats{display:flex;gap:8px;margin-bottom:12px}
.dv-stat{flex:1;background:var(--card);border:1.5px solid var(--bdr);border-radius:13px;padding:11px;text-align:center}
.dv-stat b{display:block;font-size:19px;font-weight:800;color:var(--v2)}
.dv-stat span{font-size:10px;color:var(--ink3)}

/* ══════════════════════════════════════════════════════════
   v15-10 — ZOOM iOS : filet de sécurité sur TOUS les champs
   Safari iOS zoome brutalement la page dès qu'un champ prend le
   focus avec une taille de police < 16px. Les classes de base
   (.cin, .field input, .dv-in, .grade-pill select) sont déjà à
   16px ; cette règle couvre en plus les champs stylés en inline
   dans index.html et dans les templates JS — d'où le !important.
   RÈGLE : pour rester compact, on réduit le padding, JAMAIS la
   taille de police. Les champs volontairement plus gros (PIN,
   codes à saisir) sont réaffirmés juste en dessous.
   NB : la balise <meta viewport> ne contient volontairement ni
   maximum-scale ni user-scalable=no (accessibilité).
══════════════════════════════════════════════════════════ */
input,textarea,select{font-size:16px!important}
.pin-input{font-size:24px!important}
#reg-pin,#reset-code,#beta-code-input{font-size:18px!important}

/* ── Voile d'attente des modales (v15-21) ─────────────────────────────
   Pendant un traitement hIAbou, la modale est verrouillée : plus aucun
   bouton n'est cliquable, seule la croix (z-index supérieur) reste
   accessible. Évite qu'un enfant enchaîne « Suivant » pendant l'analyse. */
.modal-box { position: relative; }
.modal-attente {
  position: absolute; inset: 0; z-index: 5;
  background: rgba(255,255,255,.94);
  backdrop-filter: blur(2px);
  border-radius: inherit;
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  gap: 12px; padding: 24px; text-align: center;
}
.modal-attente .ma-mascotte { display: block; border-radius: 24%; animation: ma-flotte 1.6s ease-in-out infinite; }
.modal-attente .ma-txt   { font-size: 14px; font-weight: 800; color: var(--ink); line-height: 1.4; max-width: 300px; }
.modal-attente .ma-note  { font-size: 11px; color: var(--ink3); }
.modal-attente .ma-barre { width: 170px; height: 6px; border-radius: 99px; background: var(--vl); overflow: hidden; }
.modal-attente .ma-barre i {
  display: block; height: 100%; width: 40%; border-radius: 99px;
  background: var(--v2); animation: ma-glisse 1.2s ease-in-out infinite;
}
/* Progression connue (ex : « 2 questions sur 5 ») : la barre cesse de glisser
   et se remplit vraiment — l'enfant voit que hIAbou avance et n'appuie pas
   une 2e fois sur « Générer ». */
.modal-attente.ma-determine .ma-barre i {
  animation: none; margin-left: 0; transition: width .35s ease;
}
@keyframes ma-flotte { 0%,100% { transform: translateY(0) }   50% { transform: translateY(-7px) } }
@keyframes ma-glisse { 0% { margin-left: -40% }  100% { margin-left: 100% } }
/* La croix passe AU-DESSUS du voile : c'est la seule sortie. */
.modal-box .modal-x { z-index: 6; }

/* ── v17-9 (POINT 1) — APPAREIL PHOTO INTÉGRÉ ─────────────────────────────
   Overlay plein écran, fond sombre, boutons GROS et tactiles (doigt d'enfant).
   inset:0 pur (PAS de --vvh/--vvtop : ces variables sont interdites hors du
   layout principal, cf. incidents v16-02). z-index 300 : au-dessus des modales
   (.modal-ov=200) mais SOUS le toast (#toast=9999) pour que les messages
   « 4 photos maximum » restent visibles par-dessus la caméra. */
.cam-ov { display:none; position:fixed; inset:0; z-index:300; background:#0b0710;
  overflow:hidden; }
.cam-ov.open { display:block; }
.cam-video { position:absolute; inset:0; width:100%; height:100%;
  object-fit:cover; background:#000; }
.cam-close { position:absolute; top:calc(12px + env(safe-area-inset-top));
  right:14px; width:46px; height:46px; border-radius:50%; border:none;
  background:rgba(0,0,0,.5); color:#fff; font-size:22px; line-height:46px;
  cursor:pointer; z-index:2; }
.cam-bottom { position:absolute; left:0; right:0;
  bottom:0; padding:14px 14px calc(18px + env(safe-area-inset-bottom));
  background:linear-gradient(to top, rgba(0,0,0,.72), rgba(0,0,0,0));
  display:flex; flex-direction:column; gap:12px; z-index:2; }
.cam-thumbs { display:flex; gap:8px; overflow-x:auto; -webkit-overflow-scrolling:touch;
  min-height:0; padding:2px; }
.cam-thumbs:empty { display:none; }
.cam-thumb { position:relative; flex:0 0 auto; width:60px; height:60px;
  border-radius:12px; overflow:hidden; box-shadow:0 2px 8px rgba(0,0,0,.45); }
.cam-thumb img { width:100%; height:100%; object-fit:cover; display:block; }
.cam-thumb .cam-thumb-rm { position:absolute; top:-2px; right:-2px; width:22px;
  height:22px; border-radius:50%; border:2px solid #fff; background:#E11D48;
  color:#fff; font-size:12px; line-height:18px; padding:0; cursor:pointer; }
.cam-controls { display:flex; align-items:center; justify-content:space-between;
  gap:12px; }
.cam-side { flex:0 0 96px; }
.cam-shutter { flex:0 0 auto; width:74px; height:74px; border-radius:50%;
  border:4px solid #fff; background:rgba(255,255,255,.18); cursor:pointer;
  display:flex; align-items:center; justify-content:center; padding:0;
  margin:0 auto; }
.cam-shutter .cam-shutter-in { width:58px; height:58px; border-radius:50%;
  background:#fff; transition:transform .1s; }
.cam-shutter:active .cam-shutter-in { transform:scale(.88); }
.cam-shutter:disabled { opacity:.4; cursor:not-allowed; }
.cam-valider { flex:0 0 96px; min-height:52px; border-radius:26px; border:none;
  background:var(--v2); color:#fff; font-family:'Poppins',system-ui,sans-serif;
  font-size:14px; font-weight:800; cursor:pointer; padding:0 10px;
  box-shadow:0 4px 14px rgba(91,33,182,.5); }
.cam-valider:disabled { opacity:.4; cursor:not-allowed; }

/* ── Écran « Mes évals » : 3 sections (v16.1) ─────────────────────────────
   À faire / Réalisées / En pause (génération interrompue, reprenable).
   Sobre et lisible sur mobile : de simples titres, sections vides masquées. */
.ev-sec { display: flex; align-items: center; gap: 6px; margin: 14px 0 9px; }
.ev-sec:first-child { margin-top: 0; }
.ev-cnt {
  font-size: 10px; font-weight: 800; color: var(--v2); background: var(--vl);
  border-radius: 99px; padding: 1px 7px; line-height: 1.6;
}
.ev-bloc { margin-bottom: 7px; }
.ev-actions {
  display: flex; gap: 6px; padding: 8px 10px;
  background: var(--card); border: 1.5px solid var(--bdr); border-top: none;
  border-radius: 0 0 var(--rs) var(--rs);
}
.ev-gen { font-size: 10px; color: var(--ink3); padding: 0 12px; }
.ev-gen:not(:empty) { padding: 5px 12px 0; }
.ev-err {
  background: var(--rosel); border: 1.5px solid var(--rose); border-radius: var(--rs);
  padding: 12px; margin-bottom: 10px; color: #72243E; text-align: center;
}

/* ── Choix du format d'éval (v16.2) : sur écran ou à imprimer ─────────────
   2 options, pas plus, présentées au moment de créer l'éval — mêmes libellés
   et même rendu dans les deux points d'entrée (« Mes leçons » et « Mes évals »).
   L'option retenue est visible d'un coup d'œil (cadre coloré + pastille ✓). */
.ev-fmt { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-bottom: 12px; }
.ev-fmt-opt {
  position: relative; display: flex; flex-direction: column; gap: 3px;
  text-align: left; padding: 11px 10px; cursor: pointer;
  background: var(--bg); border: 1.5px solid var(--bdr); border-radius: var(--rs);
  font-family: 'Poppins', system-ui, sans-serif; color: var(--ink);
  transition: border-color .15s, background .15s;
}
.ev-fmt-opt.on { background: var(--vl); border-color: var(--v2); }
.ev-fmt-opt.on::after {
  content: '✓'; position: absolute; top: 6px; right: 8px;
  font-size: 11px; font-weight: 800; color: var(--v2);
}
.ev-fmt-t { font-size: 12.5px; font-weight: 800; line-height: 1.25; }
.ev-fmt-s { font-size: 10px; font-weight: 500; color: var(--ink3); line-height: 1.3; }
.ev-fmt-opt.on .ev-fmt-s { color: var(--v2); }

/* ── À qui est cette éval ? (v16.2, espace parent uniquement) ─────────────
   Les évals sont séparées par enfant : dans l'espace parent, la liste couvre
   tout le foyer, donc chaque carte dit à QUI elle appartient. Les évals
   d'avant la séparation (child_id NULL) sont marquées « Toute la famille ».
   Pastille discrète : elle ne doit pas voler la vedette au titre de l'éval. */
.ev-who {
  display: inline-flex; align-items: center; gap: 3px;
  font-size: 9.5px; font-weight: 800; line-height: 1.6;
  color: var(--v2); background: var(--vl);
  border-radius: 99px; padding: 1px 7px; margin-bottom: 3px;
  max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ev-who.tous { color: var(--ink2); background: var(--bg); }

/* Filtre par enfant de l'écran « Évaluations » de l'espace parent.
   Même grammaire que le filtre des statistiques (barre de pastilles
   défilante) : un seul geste, aucun menu déroulant sur mobile. */
.ev-filtre { display: flex; gap: 5px; overflow-x: auto; padding: 2px 0 8px; }
.ev-filtre button {
  flex-shrink: 0; padding: 6px 12px; border-radius: 8px; border: none;
  font-family: inherit; font-size: 11px; font-weight: 700; cursor: pointer;
  background: var(--bg); color: var(--ink2);
}
.ev-filtre button.on { background: var(--v2); color: #fff; }
/* Le filtre prend la place du « premier enfant » : sans ça, la 1re section
   récupérait sa marge haute de 14px et l'écran respirait trop. */
.ev-filtre + .ev-sec { margin-top: 2px; }

/* Bouton « Imprimer » d'une éval de la liste (à côté de Démarrer / du score). */
.ev-print {
  background: var(--card); border: 1.5px solid var(--bdr); border-radius: 8px;
  padding: 4px 7px; font-size: 13px; line-height: 1; cursor: pointer;
}
.ev-print:active { background: var(--vl); border-color: var(--v2); }

/* Éval en cours : l'enfant a rattrapé la génération en arrière-plan. */
.ev-wait {
  display: flex; flex-direction: column; align-items: center; gap: 7px;
  text-align: center; padding: 20px 12px; margin-bottom: 12px;
  background: var(--vl); border-radius: 12px;
}
.ev-wait-mascotte { display: block; border-radius: 24%; animation: ma-flotte 1.6s ease-in-out infinite; }
.ev-wait-barre {
  width: 150px; height: 6px; border-radius: 99px; background: #fff;
  overflow: hidden; margin: 2px 0 4px;
}
.ev-wait-barre i {
  display: block; height: 100%; width: 40%; border-radius: 99px;
  background: var(--v2); animation: ma-glisse 1.2s ease-in-out infinite;
}
@media (prefers-reduced-motion: reduce) {
  .ev-wait-mascotte, .ev-wait-barre i { animation: none; }
}
@media (prefers-reduced-motion: reduce) {
  .modal-attente .ma-mascotte, .modal-attente .ma-barre i { animation: none; }
}

/* ── Correction anticipée (v16.3) : retour sur la question précédente ──────
   Une seule ligne, au-dessus de la question en cours. Elle change d'état sans
   rien interrompre : « hIAbou corrige… » pendant l'appel, puis le verdict.
   C'est le temps de LECTURE de la question suivante qui masque la latence. */
.ev-prev {
  font-size: 11px; font-weight: 700; line-height: 1.35;
  border-radius: 9px; padding: 7px 10px; margin-bottom: 8px;
}
.ev-prev.att { background: var(--bg);    color: var(--ink3); font-weight: 600; }
.ev-prev.ok  { background: var(--mintl); color: #085041; }
.ev-prev.ko  { background: var(--rosel); color: #72243E; }

/* ── Écran de correction d'une éval (v16.3) ───────────────────────────────
   Un bloc repliable par question + LE bouton « Tout afficher » demandé par
   Ben (le dernier choix est mémorisé, cf. EVAL_CORR_OUVERT_CLE côté JS). */
.ev-corr-head { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; }
.ev-corr-sub  { flex: 1; min-width: 0; font-size: 11px; color: var(--ink3); line-height: 1.35; }
.ev-corr-it {
  background: var(--card); border: 1.5px solid var(--bdr);
  border-radius: var(--rs); margin-bottom: 6px; overflow: hidden;
}
.ev-corr-q {
  display: flex; align-items: flex-start; gap: 8px; width: 100%; text-align: left;
  padding: 10px; background: none; border: none; cursor: pointer;
  font-family: inherit; font-size: 12px; font-weight: 700; color: var(--ink); line-height: 1.35;
}
.ev-corr-n {
  flex-shrink: 0; width: 18px; height: 18px; border-radius: 99px;
  background: var(--vl); color: var(--v2);
  font-size: 10px; font-weight: 800;
  display: flex; align-items: center; justify-content: center;
}
.ev-corr-txt { flex: 1; min-width: 0; overflow-wrap: break-word; }
.ev-corr-p  { flex-shrink: 0; font-size: 12px; }
.ev-corr-ca { flex-shrink: 0; font-size: 11px; color: var(--ink3); transition: transform .15s; }
.ev-corr-it.ouvert .ev-corr-ca { transform: rotate(180deg); }
.ev-corr-body { display: none; padding: 0 10px 10px 36px; }
.ev-corr-it.ouvert .ev-corr-body { display: block; }
.ev-corr-l {
  font-size: 11.5px; color: var(--ink2); line-height: 1.4;
  margin-top: 5px; overflow-wrap: break-word;
}
.ev-corr-l b {
  display: block; font-size: 9.5px; font-weight: 800; letter-spacing: .03em;
  text-transform: uppercase; color: var(--ink3); margin-bottom: 1px;
}
.ev-corr-l.bonne { background: var(--mintl); color: #085041; border-radius: 8px; padding: 6px 8px; }
.ev-corr-l.bonne b { color: #0A6B57; }
.ev-corr-note {
  font-size: 10px; color: #72243E; background: var(--rosel);
  border-radius: 8px; padding: 5px 8px; margin-top: 6px;
}
@media (prefers-reduced-motion: reduce) { .ev-corr-ca { transition: none; } }

/* ═══ Lot 2 · Chantier A — CARTE LIÉE DANS LE TCHAT ═══
   Insérée dans une bulle IA à la place d'un marqueur [[type:id]]. Style repris
   de la maquette validée (maquette-tchat-liens.html). Couleur = matière :
   variante .fr (français / histoire) passe l'accent en ambre foncé. La carte
   fonctionne seule sur sa ligne (largeur pleine dans la bulle) ou après du
   texte (margin-top de séparation). */
.link-card {
  display: flex; align-items: center; gap: 11px;
  background: var(--bg); border: 1.5px solid var(--bdr);
  border-left: 3px solid var(--v2); border-radius: 12px;
  padding: 10px 11px; margin-top: 9px; cursor: pointer;
  width: 100%; text-align: left; -webkit-tap-highlight-color: transparent;
}
.link-card:active { background: var(--vl); }
.link-card.fr { border-left-color: #B45309; }
.link-card .lc-em { font-size: 20px; flex-shrink: 0; }
.link-card .lc-mid { flex: 1; min-width: 0; }
.link-card .lc-k {
  font-size: 9px; font-weight: 800; text-transform: uppercase;
  letter-spacing: .4px; color: var(--v2);
}
.link-card.fr .lc-k { color: #B45309; }
.link-card .lc-t {
  font-size: 12.5px; font-weight: 700; color: var(--ink); margin-top: 1px;
  overflow-wrap: break-word;
}
.link-card .lc-s { font-size: 10.5px; color: var(--ink3); margin-top: 1px; }
.link-card .lc-go {
  background: var(--v2); color: #fff; font-size: 11px; font-weight: 800;
  border: none; border-radius: 99px; padding: 7px 13px; flex-shrink: 0;
  cursor: pointer;
}
.link-card.fr .lc-go { background: #B45309; }

/* ═══════════════════════════════════════════════════════════════════════════
   MODE DÉCOUVERTE (v16-37) — 2 règles, strictement additives.

   `body.demo` est posé par demarrerDemo() et retiré par quitterDemo()
   (js/demo.js). Hors démo, aucune de ces règles ne s'applique : le CSS des
   vrais utilisateurs n'est pas touché d'un pixel.

   .demo-hide → blocs STATIQUES d'index.html qui n'ont pas de sens sans compte
                réel (changer le code PIN, Face ID, supprimer le compte,
                EcoleDirecte). Ils ne sont pas rendus par du JS : c'est donc
                ici, et nulle part ailleurs, qu'on les retire.
   .demo-only → l'inverse : le rappel « créez votre compte » en bas de
                « Mon compte », invisible pour un vrai utilisateur.
   ═══════════════════════════════════════════════════════════════════════════ */
body.demo .demo-hide{display:none!important}
.demo-only{display:none}
body.demo .demo-only{display:block}

/* ── SORTIE DE DÉCOUVERTE SUR LE SÉLECTEUR (v16-39) ───────────────────────
   Ben, sur iPhone : « fais-moi une flèche pour revenir de la démo quand tu
   choisis enfant ou parent, vers la page d'inscription, car il n'y en a pas ».
   Deux sorties existaient déjà (bouton du bandeau violet, bouton de
   déconnexion en haut à droite) mais aucune ne SE LIT comme un retour : la
   première ressemble à une publicité, la seconde à une déconnexion — or on
   n'est pas connecté. On ajoute donc le geste attendu : une flèche ←, à
   l'emplacement où l'œil la cherche (haut à GAUCHE), symétrique du bouton de
   déconnexion. Les deux autres sorties sont conservées.

   ⚠️ Le déclencheur est `.demo-only` (donc `body.demo`, posé par
   demarrerDemo() et retiré par quitterDemo(), js/demo.js) : ZÉRO ligne de JS,
   donc zéro risque qu'un vrai parent voie cette flèche — il n'a rien à
   quitter, et son sélecteur est rendu par le même index.html.

   `display:flex` : `.demo-only` affiche en `block`, ce qui laisserait le SVG
   collé en haut à gauche du cercle. Cette règle vient APRÈS et à specificité
   égale, elle l'emporte donc dans la cascade — ne pas la remonter au-dessus.

   Cercle de 36 px pour rester à l'identique du bouton de déconnexion voisin
   (fond blanc translucide, bordure claire) ; la CIBLE TACTILE, elle, est
   portée à 44×44 par le ::before (inset -4px de chaque côté), conformément à
   la règle du projet resserrée en v16-38. On agrandit la zone d'appui sans
   agrandir le dessin, sinon les deux boutons du haut seraient dissemblables.

   `env(safe-area-inset-top)` : recopié du bouton de déconnexion — sans lui,
   la flèche passe sous l'encoche / la barre d'état iOS en PWA installée. */
.sel-quit-demo{
  position:absolute;
  top:calc(14px + env(safe-area-inset-top));
  left:16px;
  z-index:5;
  align-items:center;
  justify-content:center;
  width:36px;height:36px;
  padding:0;
  background:rgba(255,255,255,0.15);
  border:1px solid rgba(255,255,255,0.22);
  border-radius:50%;
  cursor:pointer;
}
body.demo .sel-quit-demo{display:flex}
.sel-quit-demo::before{content:'';position:absolute;top:-4px;right:-4px;bottom:-4px;left:-4px}

/* ── SIGNALER / COPIER une réponse IA (lot F ; APPUI LONG depuis v16-50) ─────
   Bloquant stores (politique GenAI Google/Apple) : signaler chaque réponse de
   hIAbou sans quitter l'app. v16-50 (décision Ben) : abandon du bouton ⚑
   visible → geste iMessage/WhatsApp. Un appui long (~500 ms) sur une bulle de
   réponse hIAbou ouvre la feuille du bas générique (.act-sheet) avec Copier /
   Signaler (câblage : ouvrirMenuBulleIA, js/child.js). Aucun composant CSS
   propre à écrire — la feuille du bas existe déjà (.act-sheet, plus haut).

   Seul réglage utile : sur les bulles signalables, on coupe le menu de
   sélection/callout natif d'iOS pour qu'il ne se superpose pas au nôtre pendant
   l'appui long. On garde la sélection de texte possible au survol souris/desktop
   (le callout ne concerne que le tactile). */
#chat-msgs .bbl[data-signal-idx],
#cor-msgs  .bbl[data-signal-idx]{
  -webkit-touch-callout:none;   /* pas de menu iOS natif sur appui long */
}

/* Indice de découvrabilité de l'appui long (v16-50). Discret (décision Ben) :
   petite ligne grise sous la 1re réponse, qui s'estompe seule. Pas d'encadré,
   pas de bouton. .chat-astuce-out déclenche le fondu de sortie. */
.chat-astuce{
  margin:2px 2px 6px 40px;   /* aligné sous la bulle IA (après l'avatar) */
  font-size:10.5px;color:var(--ink3);opacity:.75;line-height:1.4;
  transition:opacity .5s ease;
}
.chat-astuce-out{opacity:0}
