@charset "UTF-8";
/* ═══════════════════════════════════════════════════════════════════════════
   app.css — LA FEUILLE DE LA COQUE ET DES UNITÉS 1 À 7 (06/09/2026)
   ───────────────────────────────────────────────────────────────────────────
   Extraite TELLE QUELLE du bloc <style> d'index.html (ses lignes 30 à 2558,
   BUILD version-dans-parametres-06sept) : pas une valeur n'a bougé, les
   commentaires historiques non plus — ils restent la mémoire des arbitrages.
   Le @charset en tête n'est pas décoratif : content:"·" et content:'✓' vivent
   ici, et un serveur qui ne dirait pas l'encodage les rendrait en cabalistique.

   ⚠️ TROIS CHOSES TIENNENT LE RENDU, ET AUCUN TEST DE SYNTAXE NE LES VOIT :
   ① index.html la lie EN TÊTE, juste après polices/polices.css et AVANT la
     feuille de l'unité 8 (u8.css) — c'est l'ordre de cascade. Un <link>
     déplacé change des écrans sans une erreur.
   ② sw.js la PRÉ-CACHE (liste CORE) ET la SERT depuis le cache versionné
     (branche COEUR) : l'un sans l'autre, et l'app s'ouvre nue en avion.
   ③ vite.config.mjs la MASQUE pendant le build (alaq-img:) pour qu'elle soit
     copiée telle quelle dans dist/ — sinon Vite la fondrait dans u8/u8.css et
     réécrirait son url() vers assets/.
   Garde : outils/verifier-css-externe.mjs, câblé dans le portillon.
   ═══════════════════════════════════════════════════════════════════════════ */
  :root{
    --bg:#252120; --panel:#322B28; --panel2:#3C342F; --line:#4A403A;
    --gold:#DC902E; --gold2:#E8A94F; --gold-d:#B5751F;
    --cream:#F2E9DA; --muted:#B9A99A;
    --green:#6FB08A; --green-d:#558B6E; --green-bg:#22332B;
    --coral:#E07A5F; --coral-d:#BC5B43; --coral-bg:#3A2723;
    /* ⚠️ 17/08 — LA TACHKĪL PASSE AU BLEU (décision de Myriam, preview harakat-bleu-v1
       validée). C'est LE MÊME bleu que l'unité 8 (`--info`, noyau.css) : elle y avait déjà
       mis la terminaison dhamma/dhammatayn en bleu, et Myriam veut une seule couleur pour
       les signes dans toute l'app. Le rouge des manuscrits (#F0714A) est retiré.
       Contrastes MESURÉS dans la preview : 4,52:1 sur la case, 4,34:1 dans le jeton —
       seuil 3:1 pour des glyphes de 42 px, donc large. */
    --tach:#5BA3C4;
    /* bleu « information » (02/08) : ce qu'il y a à FAIRE, pas ce qui est raté.
       Volontairement HORS de UNIT_ACCENTS — l'unité 1 est #d8463a (l'ancien rouge du point)
       et l'unité 5 est #2f74d0. Même teinte 199°, deux valeurs selon le fond :
       l'or est la complémentaire du bleu, un bleu clair y vibre (1,08:1 de contraste). */
    --info:#5BA3C4;    /* le point, sur le fond brun — 5,7:1 */
    --info-d:#1E4658;  /* la bulle, sur le bouton doré — 3,9:1 */
    --lock:#5A504A;
    /* ⚠️ LA PILE --ui EST LA RÈGLE DYNAMIQUE DU CHANTIER DU 18/08 (« pourquoi c'est
       pas dynamique ? »), ET SON ORDRE EST MESURÉ, PAS DEVINÉ (simulateur iOS, 20/08).

       ① 'Noto Naskh Arabic' attrape l'arabe CARACTÈRE PAR CARACTÈRE — le français
          reste peint par Nunito, qui le couvre. C'est ce qui règle les 12 défauts du
          balayage (_qa_police_arabe : tuiles, chiffres ١٨, toasts, arabe mêlé au
          français…). Sur iOS ces éléments étaient des CARRÉS ⍰, pas juste une
          mauvaise police : iOS ne fait AUCUN repli hors de la pile déclarée.

       🔴 ② system-ui ET -apple-system SONT DES FALLBACKS TERMINAUX SUR WEBKIT iOS.
          Une fois l'un d'eux atteint, la cascade S'ARRÊTE : tout ce qui suit est du
          CODE MORT. C'est pour ça que ⚑ U+2691 et ✕ U+2715 restaient des carrés
          même avec 'Times New Roman' en queue de pile (essayé, mesuré, faux). Ils
          sont donc RETIRÉS — et c'est le générique serif (= Times sur iOS, qui a
          ces glyphes : ⚑ 20,5 px, ✕ 25,9 px, ⌫ 20,5 px) qui les rend.
          ⚠️ Ne JAMAIS les remettre : ils reviendraient sans rien casser de visible
          au Mac, et rendraient les dingbats carrés sur iPhone.

       ③ 'Segoe UI' et Roboto restent devant serif : sur Windows et Android ils
          reprennent la main si Nunito manquait ; sur iOS ils n'existent pas, donc
          serif est atteint. Contrôlé : le français ne bouge pas d'un pixel
          (705,89 px avant, 705,89 après).
       Toute unité future héritera de cette pile sans que personne y pense. */
    --ui:'Nunito','Noto Naskh Arabic','Segoe UI',Roboto,serif,sans-serif;
    --ar:'Noto Naskh Arabic',serif;       /* vocabulaire, exercices, lecture, tracé */
    --quran:'Noto Naskh Arabic',serif;    /* Amiri RETIRÉ (Myriam 10/08) : la calligraphie
                                             perdait les primo-lecteurs — une seule police
                                             arabe partout, la calligraphie reviendra en
                                             exercice dédié un jour */
  }
  *{box-sizing:border-box;margin:0;padding:0;-webkit-tap-highlight-color:transparent}
  html,body{touch-action:manipulation;overscroll-behavior:none} /* iOS : pas de zoom au double-tap ni de rebond élastique */
  html,body{height:100%}
  body{background:var(--bg);color:var(--cream);font-family:var(--ui);line-height:1.4;overflow-x:hidden;
    background-image:radial-gradient(circle at 50% 0%, #3a302b 0, #2c2624 38%, var(--bg) 75%);
    background-attachment:fixed;}
  button{font-family:var(--ui);cursor:pointer;color:inherit}
  .gold{color:var(--gold);font-family:var(--ar);font-size:32px;font-weight:900}

  /* ====== Barre du haut ====== */
  .topbar{position:fixed;top:0;left:0;right:0;z-index:30;display:flex;align-items:center;justify-content:space-between;
    gap:10px;padding:calc(12px + env(safe-area-inset-top,0px)) 16px 12px;background:transparent;backdrop-filter:blur(10px);
    -webkit-backdrop-filter:blur(10px)}
  .blogo{width:30px;height:30px;border-radius:8px;object-fit:cover;border:1px solid var(--line)}
  .brand{display:flex;align-items:center;gap:9px;font-weight:900;letter-spacing:.14em;color:var(--gold);font-size:18px}
  .brand .dot{width:26px;height:26px;border-radius:7px;background:var(--gold);display:grid;place-items:center;
    color:var(--bg);font-family:var(--ar);font-weight:700;font-size:18px}
  .stats{display:flex;gap:10px;font-weight:800;font-size:14px;align-items:center}
  .stat{display:flex;align-items:center;gap:5px}
  .sndtog{background:none;border:none;font-size:18px;line-height:1;padding:0 2px;cursor:pointer}
    .p-foot{position:relative}
  .narr-link{position:absolute;right:14px;top:8px;width:auto;background:none;border:none;color:var(--muted);
    font-size:24px;padding:6px 8px;cursor:pointer;line-height:1;z-index:2}
  .narr-link:active{color:var(--gold2)}

  /* ====== Parcours ====== */
  .wrap{max-width:520px;margin:0 auto;padding:calc(64px + env(safe-area-inset-top,0px)) 16px 120px;min-height:100vh;min-height:100dvh}
  /* Ordinateur / tablette (≥ 540px) : l'app se centre en colonne « téléphone » — sinon tout s'étire (boutons pleine largeur). Aucun effet sur iPhone (≤ 430px). */
  @media (min-width:540px){
    body{background:#161311;background-image:radial-gradient(circle at 50% -10%, #2a2422 0, #1a1614 40%, #141110 80%)}
    .wrap{max-width:460px}
    .topbar,.botnav,.player,.finish,.onb{max-width:460px;margin-left:auto;margin-right:auto;
      box-shadow:0 0 0 1px rgba(255,255,255,.05), 0 24px 60px rgba(0,0,0,.45)}
  }
  .hero{text-align:center;padding:26px 14px 8px}
  .hero img{width:120px;height:auto;border-radius:18px;box-shadow:0 10px 30px rgba(0,0,0,.45);border:1px solid var(--line)}
  .hero h1{font-size:15px;color:var(--muted);font-weight:700;margin-top:12px}
  .unit-head{position:sticky;top:calc(54px + env(safe-area-inset-top,0px));z-index:20;--accent:var(--gold2);display:flex;align-items:center;gap:10px;
    margin:12px 0 12px;background:linear-gradient(135deg,#6f4b0f,#9a6813 55%,#c07e12);border:1px solid var(--gold2);
    border-radius:16px;padding:11px 14px;overflow:hidden;
    box-shadow:0 7px 20px rgba(0,0,0,.42),0 0 0 2px var(--accent),0 3px 10px -7px var(--accent)}
  .unit-head::after{content:'';position:absolute;top:0;left:-70%;width:45%;height:100%;pointer-events:none;
    background:linear-gradient(100deg,transparent,rgba(255,255,255,.4),transparent);transform:skewX(-18deg);animation:uhshine 5s ease-in-out infinite}
  @keyframes uhshine{0%,55%{left:-70%}100%{left:140%}}
  .unit-head .uh-main{min-width:0;flex:1}
  .unit-head .uh-top{font-size:10.5px;font-weight:900;letter-spacing:.09em;color:#fff;opacity:.85}
  .unit-head h2{font-size:13px;font-weight:900;color:#fff;line-height:1.3;margin:1px 0 0}
  /* ⚠️ `nowrap` A ÉTÉ RETIRÉ (03/09) : mesuré, « Unité 10 : L’annexion — الإِضَافَة »
     réclame 240 px pour les 196 disponibles d'un iPhone SE — il DÉBORDAIT de 44 px,
     hors du bandeau, sans un pixel de défilement pour le rattraper. Le titre se coupe
     désormais après les deux-points, un endroit qui se lit. `balance` répartit les deux
     lignes au lieu d'en laisser une orpheline, et le bandeau MESURE déjà sa hauteur au
     texte de chaque unité (voir setBanner) : rien à recalculer. */
  .unit-head .uh-l1{display:block;text-wrap:balance}
  .unit-head .uh-let{font-family:var(--ar);font-size:17px}
  .unit-head .uh-ar{font-family:var(--quran);font-size:16px}
  .unit-head .uh-sub2{display:block;font-weight:400;font-size:12px;margin-top:3px;opacity:.92}
  .unit-head .uh-sub{font-size:11px;color:#3a2a08;opacity:.82;margin-top:2px}
  .unit-head .uh-burger{margin-left:6px;flex:0 0 auto;background:rgba(0,0,0,.2);border:none;color:#fff;width:40px;height:40px;border-radius:12px;font-size:19px;font-weight:900;cursor:pointer}
  .unit-head .uh-burger:active{transform:scale(.94)}
  /* Séparateur fin et grisé entre chaque unité (façon Duolingo) */
  .unit-sec{position:relative;--accent:var(--gold2)}
  .unit-sep{display:flex;align-items:center;gap:12px;margin:30px 2px 4px;color:var(--muted);
    font-size:10.5px;font-weight:900;letter-spacing:.07em;text-transform:uppercase}
  .unit-sep::before,.unit-sep::after{content:'';flex:1;height:1px;background:var(--accent,var(--line));opacity:.6}
  .unit-sep .us-t{white-space:nowrap;opacity:.8}
  .unit-sep .us-let{font-family:var(--ar);font-size:15px;text-transform:none;color:var(--gold2);letter-spacing:0}
  .path{display:flex;flex-direction:column;align-items:center;gap:26px;margin-top:14px;position:relative}
  .unit-sec[data-u="0"] .path{margin-top:36px}
  .node{position:relative;transition:transform .12s}
  .node:active{transform:translateY(2px)}
  .bwrap{position:relative;width:74px;height:74px;margin:0 auto}
  .bubble{width:74px;height:74px;border-radius:50%;display:grid;place-items:center;border:none;font-weight:900}
  .bubble .bi{font-size:30px;line-height:1;font-family:var(--ar),'Nunito',sans-serif}
  .bimg{width:42px;height:42px;object-fit:contain;display:block;margin:auto}
  .done .bubble{background:var(--gold);color:var(--bg);box-shadow:0 6px 0 var(--accent,var(--gold-d))}
  /* Disque « courant » : pièce d'or calligraphique — dégradé bombé + reflet balayé + léger flottement */
  .current .bubble{color:var(--bg);position:relative;overflow:hidden;
    background:radial-gradient(circle at 34% 26%,#f7cd74,var(--gold) 50%,#a86a12);
    box-shadow:0 6px 0 var(--gold-d),0 0 0 5px color-mix(in srgb,var(--accent,var(--gold2)) 42%,transparent)}
  .current .bubble::after{content:'';position:absolute;top:-40%;left:-60%;width:46%;height:180%;pointer-events:none;
    background:linear-gradient(100deg,transparent,rgba(255,248,232,.62),transparent);transform:skewX(-18deg);
    animation:coinShine 4.8s ease-in-out infinite}
  @keyframes coinShine{0%,62%{left:-60%}100%{left:165%}}
  .locked .bubble{background:var(--panel2);color:var(--lock);box-shadow:0 6px 0 #2c2521;cursor:not-allowed}
  /* « AVANCER ICI ? » : 1re leçon d'une unité future — disque coloré + bulle flottante (façon Duolingo) */
  .node.jump{margin-top:46px}
  .jump .bubble{color:#fff;cursor:pointer;
    background:radial-gradient(circle at 34% 26%,color-mix(in srgb,var(--accent,var(--gold)) 60%,#fff),var(--accent,var(--gold)) 55%,color-mix(in srgb,var(--accent,var(--gold)) 58%,#000));
    box-shadow:0 6px 0 color-mix(in srgb,var(--accent,var(--gold)) 45%,#000)}
  .jump .bubble .bi{color:#fff;letter-spacing:-3px;font-family:'Nunito',sans-serif;text-shadow:0 2px 0 rgba(0,0,0,.25)}
  /* Popup de leçon façon Duolingo : titre + COMMENCER, ancrée SOUS le disque (08/08).
     Elle prend la couleur d'accent de l'unité (variable CSS héritée de .unit-sec). */
  .disc-tip{position:absolute;top:calc(100% + 14px);left:50%;transform:translateX(-50%);width:250px;
    background:var(--accent,var(--gold));border-radius:16px;padding:14px;z-index:26;text-align:center;
    box-shadow:0 12px 30px rgba(0,0,0,.5);animation:tipin .18s ease}
  @keyframes tipin{from{opacity:0;transform:translateX(-50%) translateY(-6px)}to{opacity:1;transform:translateX(-50%) translateY(0)}}
  .disc-tip::before{content:'';position:absolute;top:-6px;left:50%;transform:translateX(-50%) rotate(45deg);
    width:14px;height:14px;background:inherit;border-radius:3px}
  .disc-tip .dt-t{color:#fff;font-weight:900;font-size:15px;line-height:1.35;margin-bottom:11px}
  .disc-tip .dt-t .arw{font-family:var(--ar)}
  .disc-tip .dt-go{width:100%;background:#fff;border:none;border-radius:12px;padding:12px;font-family:var(--ui);
    font-weight:900;letter-spacing:.05em;color:var(--accent,var(--gold-d));cursor:pointer;box-shadow:0 3px 0 rgba(0,0,0,.22)}
  .jump-tip{position:absolute;bottom:calc(100% + 12px);left:50%;
    background:var(--panel2);color:var(--accent,var(--gold));border:2px solid var(--accent,var(--gold));
    font-weight:900;font-size:13px;padding:7px 13px;border-radius:12px;white-space:nowrap;z-index:3;pointer-events:none;
    animation:jbob 2.2s ease-in-out infinite}
  .jump-tip::after{content:'';position:absolute;left:50%;top:100%;transform:translateX(-50%);
    border:6px solid transparent;border-top-color:var(--accent,var(--gold))}
  @keyframes jbob{0%,100%{transform:translate(-50%,0)}50%{transform:translate(-50%,-6px)}}
  .node .ring{position:absolute;inset:-8px;border-radius:50%;pointer-events:none}
  .current .ring{inset:-9px;
    background:conic-gradient(from 0deg,transparent 0deg,var(--accent,#f4d089) 55deg,transparent 120deg,transparent 200deg,#f4d089 250deg,transparent 320deg);
    -webkit-mask:radial-gradient(farthest-side,transparent calc(100% - 4px),#000 calc(100% - 4px));
            mask:radial-gradient(farthest-side,transparent calc(100% - 4px),#000 calc(100% - 4px));
    animation:spin 6s linear infinite}
  .current .bwrap{animation:bob 2.6s ease-in-out infinite}
  @keyframes bob{0%,100%{transform:translateY(0)}50%{transform:translateY(-5px)}}
  @keyframes spin{to{transform:rotate(360deg)}}
  .start-flag{position:absolute;top:-40px;left:50%;transform:translateX(-50%);background:#fff;color:#3b342f;
    font-weight:900;font-size:12px;padding:5px 11px;border-radius:10px;box-shadow:0 4px 0 #d8ccb8;
    white-space:nowrap;pointer-events:none;z-index:2}
  .start-flag::after{content:'';position:absolute;left:50%;bottom:-6px;transform:translateX(-50%);
    border:6px solid transparent;border-top-color:#fff}
  .node .cap{margin-top:8px;text-align:center;font-size:12px;font-weight:800;color:var(--muted);max-width:130px}
  .done .cap{color:var(--gold2)}
  .check{position:absolute;right:-2px;bottom:-2px;background:#fff;color:var(--green-d);width:24px;height:24px;
    border-radius:50%;display:grid;place-items:center;font-size:14px;font-weight:900;box-shadow:0 2px 4px rgba(0,0,0,.3)}

  /* ====== Joueur ====== */
  .player{position:fixed;inset:0;z-index:50;background:var(--bg);
    background-image:radial-gradient(circle at 50% 0%, #3a302b 0, #2c2624 38%, var(--bg) 75%);
    display:none;flex-direction:column}
  .player.on{display:flex}
  .p-top{display:flex;align-items:center;gap:14px;padding:calc(14px + env(safe-area-inset-top,0px)) 16px 14px}
  .p-close{background:none;border:none;color:var(--muted);font-size:26px;font-weight:700;line-height:1;padding:0 4px}
  .pbar{flex:1;height:16px;background:var(--panel2);border-radius:10px;overflow:hidden}
  .pbar i{display:block;height:100%;width:0;background:var(--gold);border-radius:10px;transition:width .35s}
  .hearts{display:flex;align-items:center;gap:4px;color:var(--info);font-weight:900;font-size:18px} /* 05/09 : la goutte est révision, pas cœur — bleu, jamais rouge (Myriam) */
  .p-body{flex:1;overflow-y:auto;padding:8px 22px 24px;max-width:560px;width:100%;margin:0 auto}
  .p-body.p-center{display:flex;flex-direction:column;justify-content:center}
  .q-title{font-size:21px;font-weight:900;margin:14px 0 22px}
  /* la lettre nommée dans une consigne s'écrit EN ARABE, jamais en phonétique (Myriam 11/08) */
  .q-title .ar{font-family:var(--ar);font-size:32px;color:var(--gold);vertical-align:-.12em;line-height:1;font-weight:900}
  .q-note{font-size:20px;font-weight:900;color:var(--cream);line-height:1.35;margin:8px 0 22px}
  .glyph-big{font-family:var(--ar);font-size:80px;text-align:center;color:var(--gold);
    margin:4px 0 24px;line-height:1;padding:44px 0 14px;font-weight:400}
  .speak{display:block;margin:0 auto 22px;background:var(--panel);border:2px solid var(--line);
    color:var(--gold2);border-radius:14px;padding:12px 20px;font-weight:800;font-size:15px}
  .bigspeak{display:grid;place-items:center;margin:14px auto 20px;width:120px;height:120px;border-radius:28px;
    border:2px solid var(--line);background:var(--panel);font-size:52px}
  .bigspeak:active{transform:translateY(2px);border-color:var(--gold)}
  .hint{color:var(--muted);font-size:16px;font-weight:700;margin-top:16px}

  .opts{display:grid;gap:12px}
  .opts.grid2{grid-template-columns:1fr 1fr}
  .opts.grid3{grid-template-columns:1fr 1fr 1fr}
  /* ⚠️ 14/08 — Myriam : « les box contenant les mots doivent avoir un peu plus de padding
     sur le haut, parce que là les tachkīl touchent le contour de la box ». Un mot comme
     أُمٌّ empile ḍamma + chedda + tanwīn au-dessus de la ligne : à `line-height:1.2` la pile
     sort de sa boîte. Le remède est la HAUTEUR DE LIGNE de l'arabe, pas seulement le
     rembourrage — le rembourrage seul décale le mot sans lui donner de place au-dessus. */
  .opt{background:var(--panel);border:2px solid var(--line);color:var(--cream);
    border-radius:14px;padding:20px 10px 16px;font-size:18px;font-weight:700;text-align:center;transition:.08s;
    min-height:68px;display:grid;place-items:center}
  .opt .ar{font-family:var(--ar);font-size:42px;color:var(--gold);line-height:1.55;font-weight:700}
  .opt.sel{border-color:var(--gold);background:#3a312b;box-shadow:inset 0 0 0 1px var(--gold)}
  .opt.ok{border-color:var(--green);background:var(--green-bg);color:var(--green)}
  .opt.ok .ar{color:var(--green)}
  .opt.bad{border-color:var(--coral);background:var(--coral-bg);color:var(--coral)}
  .opt.bad .ar{color:var(--coral)}
  .opt[disabled]{opacity:.55}
  .opt .sopt{font-size:34px;line-height:1.2}

  .learn{background:var(--panel);border:1px solid var(--line);border-radius:18px;padding:24px;text-align:center}
  .learn .nm{font-size:22px;font-weight:900;margin-top:8px}
  .learn .son{display:inline-block;margin-top:8px;background:#3a312b;color:var(--gold2);border-radius:20px;
    padding:5px 14px;font-weight:800;font-size:14px}
  .learn .mn{color:var(--muted);font-size:15px;margin-top:14px;font-weight:600}
  .learn .demo{font-family:var(--ar);font-size:54px;color:var(--gold);margin:14px 0 4px;line-height:1.3}
  .badge-new{display:inline-block;background:var(--gold);color:var(--bg);font-weight:900;font-size:11px;
    letter-spacing:.1em;padding:4px 10px;border-radius:8px;margin-bottom:16px}
  .ar-tap{background:none;border:none;display:block;margin:0 auto;color:var(--gold);font-family:var(--ar);
    font-size:80px;line-height:1;padding:6px 22px;border-radius:18px;font-weight:400}
  .ar-tap:active{background:#3a312b}
  .pop{animation:pop .35s}
  @keyframes pop{40%{transform:scale(1.15)}}

  .explore{display:grid;grid-template-columns:repeat(3,1fr);gap:12px}
  .exp-card{background:var(--panel);border:2px solid var(--line);border-radius:16px;
    padding:18px 6px;display:flex;flex-direction:column;align-items:center;gap:8px}
  .exp-card:active{background:#3a312b;border-color:var(--gold)}
  .exp-card .ar{font-family:var(--ar);font-size:50px;color:var(--gold);line-height:1.2}
  .exp-card .enm{font-size:13px;font-weight:800;color:var(--muted)}
  .exp-card .dots{font-size:12px;color:var(--gold2);letter-spacing:2px;font-weight:900}


  /* ══ LEÇON 2 v2 (08/08) — bulles, haut-parleur dessiné, icônes du tracé ══ */
  .bulzone{position:relative;height:min(430px,52vh);margin-top:6px;overflow:hidden;border-radius:16px}
  /* pleine hauteur (Myriam 10/08) : la zone s'étire jusqu'à la ligne du bandeau bas —
     les bulles recyclées à y=BUL.H+6 semblent en sortir. La hauteur figée reste en filet. */
  .p-body.p-bulles{display:flex;flex-direction:column;overflow:hidden;padding-bottom:0}
  .p-body.p-bulles .bulzone{flex:1;height:auto;margin-bottom:42px;border-radius:16px} /* 42px : le couloir du drapeau ⚑ — les bulles ne passent plus dessous (10/08 soir) */
  /* le compteur : pastille dorée qui DÉCOMPTE les bulles restantes (Myriam 10/08) */
  /* 🔴 LE NOMBRE À 24 px, LE TEXTE À 16 (Myriam, 01/09) : « pour le nombre c'est ok,
     tu peux même le passer à 24px. Mais le texte écrit sous le nombre passe à 16px ».
     Ce sont deux rôles distincts — le chiffre est ce que l'élève suit du regard, la
     phrase en dessous n'est qu'un rappel. */
  #bul-c,#spot-c{width:max-content;margin:-6px auto 4px;background:rgba(220,144,46,.16);
    border:1.5px solid var(--gold-d);border-radius:999px;padding:4px 16px;
    font-size:24px;font-weight:900;color:var(--gold2);font-variant-numeric:tabular-nums}
  #spot-c{margin:0 auto 10px}
  #bul-c.tick,#spot-c.tick{animation:bultick .3s cubic-bezier(.3,1.8,.5,1)}
  @keyframes bultick{45%{transform:scale(1.25)}}
  .bul{position:absolute;left:0;top:0;width:64px;height:64px;border-radius:50%;
    display:grid;place-items:center;cursor:pointer;
    background:radial-gradient(circle at 32% 28%, rgba(242,233,218,.20), rgba(220,144,46,.13) 55%, rgba(220,144,46,.05));
    border:2px solid rgba(232,169,79,.55);
    box-shadow:inset -6px -8px 14px rgba(0,0,0,.22), inset 6px 8px 12px rgba(255,255,255,.10);
    font-family:var(--ar);font-size:32px;color:var(--gold2);will-change:transform;
    transform:translate(var(--x,0px),var(--y,0px))}
  .bul.frm{width:54px;height:54px;font-size:24px}
  /* 14/08 (correctifs 4) — Myriam, leçon 6 « Éclate les bulles » : « double la taille de la
     police et des bulles ». BUL.R (la physique des chocs, plus bas) double avec elle — sinon
     les bulles se chevauchent au double de leur taille visuelle sans jamais se toucher pour
     de vrai. */
  .bul.syl{width:120px;height:120px;font-size:52px} /* 18 bulles-syllabes (leçons 5/6) */
  .bul.pop{animation:bulpop .17s cubic-bezier(.3,1.8,.5,1) forwards;pointer-events:none}
  /* ⚠️ la translation DOIT être reprise dans CHAQUE étape : une @keyframes qui déclare
     `transform` remplace celui de l'élément — sans ça la bulle éclate en haut à gauche. */
  @keyframes bulpop{0%{transform:translate(var(--x),var(--y)) scale(1);opacity:1;border-width:2px}
    55%{transform:translate(var(--x),var(--y)) scale(1.22);opacity:.95;border-width:1px;filter:brightness(2.1)}
    100%{transform:translate(var(--x),var(--y)) scale(1.34);opacity:0;border-width:0}}
  .onde{position:absolute;width:64px;height:64px;margin:-32px 0 0 -32px;border-radius:50%;
    border:2px solid rgba(232,169,79,.85);pointer-events:none;
    animation:ondele .4s cubic-bezier(.15,.7,.3,1) forwards}
  @keyframes ondele{0%{transform:scale(.98);opacity:.9;border-width:2.5px}
    100%{transform:scale(1.85);opacity:0;border-width:.5px}}
  .goutte{position:absolute;border-radius:50%;pointer-events:none;background:var(--gold2);
    box-shadow:0 0 5px rgba(232,169,79,.75);animation:gouttele .5s cubic-bezier(.15,.75,.35,1) forwards}
  @keyframes gouttele{0%{transform:translate(0,0) scale(1);opacity:1}70%{opacity:.75}
    100%{transform:translate(var(--dx),var(--dy)) scale(.3);opacity:0}}
  .spkbtn{background:none;border:none;padding:0;margin:6px auto 18px;display:block;cursor:pointer;color:var(--gold)}
  .spkbtn svg{width:112px;height:78px;display:block}
  .spk .w{fill:none;stroke:currentColor;stroke-width:2.8;stroke-linecap:round;opacity:.22}
  .spk .cone{fill:currentColor}
  .spk.on .w1{animation:spkw .78s ease-out infinite}
  .spk.on .w2{animation:spkw .78s ease-out .13s infinite}
  .spk.on .w3{animation:spkw .78s ease-out .26s infinite}
  @keyframes spkw{0%{opacity:.15}38%{opacity:1}100%{opacity:.15}}
  .spkbtn.on{animation:spkbob .78s ease-out infinite}
  @keyframes spkbob{0%,100%{transform:scale(1)}38%{transform:scale(1.06)}}
  .opts.rtl3{direction:rtl}
  .opt .spk{width:56px;height:40px;color:var(--gold)}
  .opt.ok .spk{color:var(--green)} .opt.bad .spk{color:var(--coral)}
  /* la box qui parle s'illumine (Myriam 10/08) — jaune clair #f7cd74 (le reflet des disques),
     gabarit du halo calqué sur .lum.on ; le verdict vert/corail garde toujours le dernier mot */
  .opt.on:not(.ok):not(.bad){border-color:#f7cd74;background:#403727;
    box-shadow:0 0 16px rgba(247,205,116,.30),inset 0 0 12px rgba(247,205,116,.08)}
  .tico{display:flex;gap:14px;justify-content:center;margin-top:14px}
  .tico button{background:var(--panel);border:2px solid var(--line);border-radius:14px;
    width:64px;height:56px;display:grid;place-items:center;cursor:pointer;color:var(--gold2)}
  .tico button:active{transform:translateY(2px)}
.tico button:disabled{opacity:.35;pointer-events:none}
  .tico svg{width:30px;height:30px;fill:none;stroke:currentColor;stroke-width:2.1;stroke-linecap:round;stroke-linejoin:round}
  .tico .plein{fill:currentColor;stroke:none}
  /* 14/08 (correctifs 4) — Myriam : « adapte la box à la lettre, elle est trop large ». La
     case s'étirait à toute la colonne (1fr) autour d'un glyphe étroit ; `justify-items:center`
     la fait se resserrer sur son contenu au lieu d'occuper toute la largeur — c'est CE vide-là
     qui rendait la case « trop large », pas le padding (qui, lui, monte pour ne jamais laisser
     un tachkil toucher le contour). */
  .agrid{display:grid;grid-template-columns:repeat(4,1fr);gap:9px;direction:rtl;justify-items:center}
  .ag{background:var(--panel);border:2px solid var(--line);border-radius:12px;padding:12px 12px;
    min-width:58px;font-family:var(--ar);font-size:34px;color:var(--gold);line-height:1.2}
  .ag.seen{border-color:var(--gold);color:var(--gold2)}
  .ag:active{background:#3a312b}
  /* ── L'écran « 2 rôles » (14/08) ────────────────────────────────────────────
     Les trois lettres faibles sont LÉGÈREMENT dorées ; touchées, elles passent à l'or
     franc. Les 25 autres sont désactivées : elles n'ont rien à révéler, et un bouton
     désactivé sort du décompte WCAG — c'est éteint EXPRÈS, pas un défaut de contraste. */
  /* « légèrement jaune comparé aux autres » : à 14 % seule la bordure se voyait — c'est le
     FOND qui doit porter l'indice, comme pour les cartes. */
  .ag.faible{background:rgba(232,169,79,.22);border-color:var(--gold-d)}
  .ag.faible.lit{background:var(--gold);border-color:var(--gold);color:var(--on-gold,#241c10)}
  .ag[disabled]{opacity:.5;cursor:default}
  /* ⚠️ 14/08, TROUVÉ À L'ŒIL SUR LA CAPTURE ET NON AU CALCUL : les 28 lettres + le filet +
     les 5 sièges ne tenaient pas au-dessus du bouton, et la rangée des sièges était rognée —
     or c'est ELLE que l'écran fait apparaître, c'est la récompense du geste. La grille de CET
     écran se resserre donc (les cases ne sont pas là pour être lues de près, mais touchées),
     et la rangée garde le couloir de 42 px du drapeau ⚑, comme le jeu de bulles. */
  .agrid.agrid-rl{gap:6px}
  .agrid.agrid-rl .ag{padding:6px 8px;min-width:44px;font-size:28px}
  .rl-sep{position:relative;text-align:center;margin:12px 0 0}
  .rl-sep::before{content:'';position:absolute;left:0;right:0;bottom:-7px;border-top:1px dashed var(--line)}
  .rl-sep span{font-size:11.5px;font-weight:900;letter-spacing:.08em;text-transform:uppercase;color:var(--muted)}
  .lg-hamza.rl-sieges{margin-top:12px;margin-bottom:42px;border-top:none;padding-top:0}
  .lg-hamza .hz.vide{background:none;border-style:dashed;min-height:44px;cursor:default}
  .lg-hamza .hz.neuf{animation:hzpose .32s ease-out}
  @keyframes hzpose{0%{transform:scale(.6);opacity:0}60%{transform:scale(1.08)}100%{transform:scale(1);opacity:1}}

  /* l'anneau de l'objectif quotidien — SEUL, dans le Profil (preview v2 validée 10/08) */
  .obj-ring{display:grid;place-items:center;margin:14px 0}
  .obj-ring .anneau{position:relative;width:118px;height:118px;display:grid;place-items:center}
  .obj-ring svg{position:absolute;inset:0;transform:rotate(-90deg)}
  .obj-ring svg circle{fill:none;stroke-width:9}
  .obj-ring .fond{stroke:var(--panel2)}
  .obj-ring .prog{stroke:var(--gold);stroke-linecap:round;transition:stroke-dashoffset .6s cubic-bezier(.3,1,.4,1)}
  .obj-ring .mn{font-size:23px;font-weight:900;color:var(--gold2);text-align:center;line-height:1.05}
  .obj-ring .mn small{display:block;font-size:11px;color:var(--muted);font-weight:700}
  .obj-ring .mn b{display:block;font-size:26px;line-height:1}
  .obj-ring .fete .prog{stroke:var(--gold2);filter:drop-shadow(0 0 8px rgba(232,169,79,.75))}
  .obj-ring .obj-epi{position:absolute;top:-7px;right:-3px;height:30px}
  .verse{direction:rtl;font-family:var(--quran);font-size:36px;line-height:2.1;text-align:center;
    background:var(--panel);border:1px solid var(--line);border-radius:18px;padding:18px 12px;margin-bottom:6px}
  .vl{border-radius:6px;padding:0}
  /* 14/08 (correctifs 4) — l'alif poignard (le petit alif de prolongation caché, ex. sur le
     mīm de الرَّحْمَٰنِ) est minuscule même à pleine taille, zoomé — vérifié à l'œil. Il reste
     DANS sa case (jamais isolé de sa lettre porteuse : la leçon de la kasra, plus haut dans ce
     fichier, s'applique aussi ici — un span séparé casserait son rattachement). Toute la case
     grossit un peu, cible comme les autres, juste plus dure à repérer sans ce coup de pouce. */
  .vl-madd{font-size:36px;font-weight:400}
  /* leçon 4 v3 (validée 10/08) : haut-parleur dessiné + nom du récitateur SANS boîte
     (le toucher OUVRE le sélecteur) + loupe Artlist ; la loupe agrandit le verset */
  .vtools{display:flex;align-items:center;justify-content:center;gap:8px;margin:-8px 0 10px}
  .vspk{background:none;border:none;padding:2px;display:flex;align-items:center;gap:7px;color:var(--gold)}
  .vspk .spk{width:44px;height:29px}
  .qari-nom{font-size:13px;color:var(--muted);font-weight:700}
  .vloupe{background:none;border:none;padding:2px;margin-left:14px}
  .vloupe img{height:30px;width:30px;display:block;transition:transform .2s}
  .vloupe.zoomed img{transform:scale(1.18)}
  .verse.zoomed{font-size:52px;line-height:2.2}
  .vl.hit{color:var(--gold);text-shadow:0 0 14px rgba(220,144,46,.45)}
  .vl.miss{animation:vlmiss .38s ease-out}
  @keyframes vlmiss{
    0%{color:var(--coral);text-shadow:0 0 0 rgba(224,122,95,0)}
    30%{color:var(--coral);text-shadow:0 0 18px rgba(224,122,95,.95)}
    100%{color:inherit;text-shadow:0 0 0 rgba(224,122,95,0)}}
  .vw{display:inline-block;margin:0 10px;transition:color .25s ease,text-shadow .25s ease}
  /* une icône du registre posée DANS une ligne de texte (remplace les emoji, 11/08) */
  .ic-inline{height:1.15em;width:auto;vertical-align:-.18em;margin-right:.28em}
  /* la couleur de base : ce que l'élève sait déjà lire, et ce qu'elle ne sait pas encore */
  .vw.dispo{color:var(--gold)} .vw.absent{color:var(--lock)}
  /* SUIVRE LA RÉCITATION (11/08) : ces deux règles viennent APRÈS, donc elles l'emportent */
  .vw.lu{color:var(--gold2)}
  .vw.en{color:#FFE0AE;text-shadow:0 0 18px rgba(232,169,79,.6)}
  /* ═══ LA SOURATE RÉCITÉE (13/08) — le flux du mushaf, plus de boîte par verset ═══
     Les versets se suivent en continu ; chaque ayah porte son haut-parleur EN LIGNE,
     juste avant son premier mot (donc à droite : on lit de droite à gauche), et son
     numéro en fin, dans le signe ۝. */
  .mushaf{direction:rtl;font-family:var(--quran);font-size:27px;line-height:2.45;
    text-align:center;padding:2px 2px 8px}
  /* ⚠️ 17/08 — « je ne peux pas cliquer sur un mot » (Myriam, sur ordinateur). Le mot ÉTAIT
     cliquable : rien ne le DISAIT. Sur téléphone il n'y a pas de pointeur, donc l'absence de
     `cursor` ne se remarque pas ; à la souris, la flèche reste une flèche au-dessus de chaque
     mot et l'écran se lit comme une page morte. Le survol double l'indice pour la souris,
     sans rien changer au toucher. */
  .mushaf .vw{display:inline-block;margin:0 6px;padding:0 2px;border-radius:6px;cursor:pointer;
    transition:color .25s ease,text-shadow .25s ease,background .2s}
  .mushaf .vw:active{background:rgba(232,169,79,.14)}
  @media (hover:hover){ .mushaf .vw:hover{background:rgba(232,169,79,.10)} }
  .ayat .tete{white-space:nowrap}   /* le haut-parleur ne se sépare jamais du 1er mot */
  .vspk-in{background:none;border:none;padding:0;margin:0 2px 0 6px;color:var(--gold-d);
    vertical-align:-.06em;display:inline-block;cursor:pointer}
  .vspk-in .spk{width:26px;height:17px}
  .vspk-in.on{color:var(--gold2)}
  .ayano{display:inline-block;margin:0 8px;font-family:var(--quran);color:var(--gold-d);
    font-size:.92em;vertical-align:-.04em}
  .ayat.en{background:rgba(232,169,79,.06);border-radius:10px}
  .lire-tout{display:flex;align-items:center;justify-content:center;gap:10px;width:100%;
    background:var(--panel);border:2px solid var(--gold-d);border-radius:14px;padding:12px;
    color:var(--gold2);font-weight:900;font-size:15px;letter-spacing:.03em;margin:0 0 6px;cursor:pointer}
  .lire-tout.on{background:var(--gold);color:var(--bg);border-color:var(--gold)}
  .lire-tout svg{height:19px;width:19px;fill:currentColor}
  .mushaf-sous{text-align:center;font-size:12px;color:var(--muted);margin:0 0 12px}
  .spk-mini{width:20px;height:13px;vertical-align:-2px}
  .spk-mini .cone{fill:currentColor} .spk-mini .w{fill:none;stroke:currentColor;stroke-width:3.4;stroke-linecap:round;opacity:.5}
  .zoom-btn{display:block;margin:0 auto 12px;background:var(--panel);border:1px solid var(--line);
    color:var(--gold2);font-weight:800;font-size:14px;border-radius:12px;padding:8px 16px}


  .frow{display:flex;gap:10px;direction:rtl;justify-content:center;margin:10px 0 6px}
  .fcell{flex:1;max-width:86px;background:var(--panel);border:2px solid var(--line);border-radius:14px;
    padding:20px 4px 16px;min-height:108px;text-align:center}
  .fcell:active{border-color:var(--gold)}
  .fcell.done{border-color:var(--gold);background:#3a312b}
  .fcell.done .fl{color:var(--gold2)}
  .fcell .ar{font-family:var(--ar);font-size:40px;color:var(--gold);line-height:1.2;display:block;margin-bottom:16px}
  .fcell .fl{font-size:10px;font-weight:900;color:var(--muted);letter-spacing:.04em}

  .wordcard{background:var(--panel);border:1px solid var(--line);border-radius:18px;padding:26px;text-align:center}
  .wordcard .emo{font-size:56px}
  .wordcard .fr{color:var(--muted);font-weight:700;margin-top:8px}
  /* écriture "en ligne" : on désactive les ligatures verticales coraniques */
  .linear-ar{font-family:'Noto Naskh Arabic',serif;font-feature-settings:"calt" 0,"liga" 0,"dlig" 0,"rlig" 0;
    font-variant-ligatures:none;letter-spacing:0}
  .mic-btn{display:block;margin:6px auto 0;background:var(--gold);color:var(--bg);font-weight:900;
    border:none;border-radius:14px;padding:14px 26px;font-size:17px;box-shadow:0 4px 0 var(--gold-d)}
  .mic-btn.listening{background:var(--coral);box-shadow:0 4px 0 #b85c43;animation:pulse 1s ease-in-out infinite}
  @keyframes pulse{0%,100%{transform:scale(1)}50%{transform:scale(1.05)}}
  .reco-fb{margin-top:12px;min-height:20px}
  .reco-ok{color:var(--green);font-weight:900;font-size:17px}
  .reco-retry{color:var(--gold2);font-weight:800}
  .reco-warn{color:var(--muted);font-weight:700;font-size:14px;line-height:1.4}
  .slots{direction:rtl;font-family:var(--ar);font-size:64px;color:var(--cream);text-align:center;min-height:120px;
    background:var(--panel);border:2px dashed var(--line);border-radius:18px;padding:34px 12px 18px;margin-bottom:14px;line-height:1.5}
  .slots .ph{color:var(--lock)}
  .tiles{display:flex;gap:10px;justify-content:center;flex-wrap:wrap;direction:rtl}
  .tile{background:var(--panel);border:2px solid var(--line);border-radius:14px;
    width:64px;height:64px;font-family:var(--ar);font-size:36px;color:var(--gold);display:grid;place-items:center;
    position:relative;font-weight:400}
  /* La zone de TOUCHE déborde la tuile de 4 px sans rien déplacer (14/08 — « la sensibilité
     des box pourrait être améliorée au toucher »). 4 et pas 6 : les tuiles sont espacées de
     10 px, deux zones élargies de 6 se chevaucheraient et voleraient le doigt à la voisine. */
  .tile::after{content:'';position:absolute;inset:-4px;border-radius:18px}
  .tile[disabled]{opacity:.25}
  .tile[disabled]::after{display:none}
  /* ⚠️ 14/08 — Myriam : « les harakat sont trop petites. Pour les gens ayant des problèmes de
     vue comme mon mari ce sera illisible. Il faut grossir UNIQUEMENT les tachkīl dans ce type
     d'exercice et les mettre en gras. » Le signe était à 30 px ET à 55 % d'opacité : deux
     handicaps cumulés sur le seul élément qui portait l'information. Il passe à 42 px, opaque.
     Le « gras » ne peut pas venir de font-weight — Noto Naskh Arabic n'a qu'une graisse et le
     navigateur ne ferait qu'un faux gras irrégulier ; c'est le tracé qui est épaissi. */
  .tile.htile{font-family:'Noto Naskh Arabic',serif;font-size:36px;font-weight:400}
  /* 14/08 (correctifs 4) — Myriam : « les harakat sont pas centrées sur la hauteur de leur
     box, alors qu'avant c'était le cas ». `.tile` centre la BOÎTE de `.dc` (place-items:center),
     pas l'encre à l'intérieur : un signe posé sur un tatweel se dessine près du haut de sa
     ligne (métrique du signe, pas du glyphe complet d'une lettre), donc restait haut même
     boîte centrée. `line-height:1` resserre la ligne sur le signe ; le décalage qui reste
     est compensé à la main. */
  /* 🔴 42px, ET ON N'Y TOUCHE PAS (correctif du 14/08, garde par un harnais qui
     exige >= 40). Le bareme « tuile » de Myriam vaut 36 — mais CE signe-la a ete
     agrandi expres, d'un 30 juge trop petit. Une regle generale ne defait pas une
     decision particuliere anterieure : c'est le harnais qui a rattrape le coup. */
  .tile.htile .dc{font-size:42px;line-height:1;opacity:1;-webkit-text-stroke:.55px currentColor;
    display:inline-block;transform:translateY(8px);font-weight:400}
  .tile.miss{animation:tileshk .32s}
  @keyframes tileshk{25%{transform:translateX(-4px)}55%{transform:translateX(4px)}80%{transform:translateX(-2px)}}
  .tile.hint{border-color:var(--gold);color:var(--gold2);animation:tilehint .9s ease-in-out infinite}
  @keyframes tilehint{0%,100%{transform:scale(1)}50%{transform:scale(1.1);box-shadow:0 0 0 5px rgba(232,169,79,.22)}}
  .p-body.p-asm{display:flex;flex-direction:column}
  .p-body.p-asm .spkbtn{align-self:center}
  .asm-fr{flex:1;display:grid;place-items:center;font-size:22px;font-weight:700;color:var(--cream);padding:10px 0}
  /* la traduction du mcq « Lis le mot », révélée à la réussite (24/08) — CENTRÉE dans
     l'espace restant entre les choix et le bandeau du bas (retour de Myriam : elle
     collait sous les choix, loin de CONTINUER). Même patron que .p-asm/.asm-fr :
     .p-body devient une colonne flex pour CET écran, .exam-fr en occupe le reste. */
  #p-body.p-examfr{display:flex;flex-direction:column}
  .exam-fr{flex:1;display:grid;place-items:center;text-align:center;font-size:22px;font-weight:700;color:var(--cream);padding:10px 0}
  .exam-fr img{display:block;max-width:160px;max-height:160px;margin:0 auto 10px;object-fit:contain}
  .undo{display:block;margin:14px auto 0;background:none;border:none;color:var(--muted);font-weight:800;font-size:14px}

  .trow{display:flex;gap:10px;justify-content:center;margin-top:14px}
  .trow .speak{margin:0}
  .trace{display:block;margin:0 auto;width:min(300px,82vw);height:min(300px,82vw);background:var(--panel);
    border:2px solid var(--line);border-radius:18px;touch-action:none}

  .p-foot{border-top:1px solid var(--line);padding:16px 22px;max-width:560px;width:100%;margin:0 auto;transition:background .15s}
  .p-foot.ok{background:var(--green-bg);border-top-color:var(--green-d)}
  .p-foot.bad{background:var(--coral-bg);border-top-color:var(--coral-d)}
  .fb{display:flex;align-items:center;gap:10px;margin-bottom:12px;font-weight:900;font-size:16px}
  .fb.ok{color:var(--green)} .fb.bad{color:var(--coral)}
  .fb .ar{font-family:var(--ar)}
  .why{display:none;font-size:13.5px;line-height:1.55;color:var(--cream);background:var(--coral-bg);border-left:3px solid var(--coral);border-radius:10px;padding:9px 12px;margin:2px 0 12px;font-weight:600}
  .why:not(:empty){display:block}
  .why .ar{font-family:var(--ar);font-size:18px;color:var(--gold);font-weight:700}
  .cta{width:100%;border:none;border-radius:14px;padding:12px;font-size:24px;font-weight:900;letter-spacing:.04em;text-transform:uppercase;
    color:var(--bg);background:var(--gold);box-shadow:0 5px 0 var(--gold-d)}
  .cta:active{transform:translateY(3px);box-shadow:0 2px 0 var(--gold-d)}
  .cta[disabled]{background:var(--panel2);color:var(--muted);box-shadow:0 5px 0 #2c2521}
  .cta.ok{background:var(--green);box-shadow:0 5px 0 var(--green-d)}
  .cta.bad{background:var(--coral);box-shadow:0 5px 0 var(--coral-d)}

  .finish{position:fixed;inset:0;z-index:60;background:var(--bg);
    background-image:radial-gradient(circle at 50% 0%, #3a302b 0, #2c2624 38%, var(--bg) 75%);
    display:none;flex-direction:column;
    align-items:center;justify-content:center;text-align:center;padding:calc(30px + env(safe-area-inset-top,0px)) 30px 30px;
    /* Un contenu plus haut que l'écran (écran compte avec le code affiché, petit
       téléphone) débordait des DEUX côtés : le centrage flex rend alors le HAUT
       inatteignable. `safe center` recentre seulement quand ça tient ; sinon il
       aligne au début et le défilement fait le reste. Les navigateurs qui ne le
       connaissent pas gardent la déclaration précédente. */
    overflow-y:auto;justify-content:safe center}
  .finish.on{display:flex}
  .finish .big{font-family:var(--ar);font-size:80px;color:var(--gold)}
  .finish h2{font-size:26px;font-weight:900;margin:10px 0 26px}
  /* ===== Onboarding de bienvenue + série 7 épis ===== */
  .onb{position:fixed;inset:0;z-index:70;background:var(--bg);
    background-image:radial-gradient(circle at 50% 0%, #3a302b 0, #2c2624 38%, var(--bg) 75%);
    display:none;flex-direction:column;padding:calc(14px + env(safe-area-inset-top,0px)) 22px 26px}
  .onb.on{display:flex}
  .onb-top{display:flex;align-items:center;gap:10px;margin-bottom:8px;height:28px}
  .onb-back{background:none;border:none;color:var(--muted);font-size:26px;cursor:pointer;padding:0 4px;line-height:1}
  .onb-track{flex:1;height:10px;background:#3a322d;border-radius:6px;overflow:hidden}
  .onb-fill{height:100%;width:0;background:var(--gold);border-radius:6px;transition:width .3s}
  .onb-body{flex:1;display:flex;flex-direction:column;min-height:0;overflow-y:auto}
  .obs{display:none;flex:1;flex-direction:column;justify-content:center;text-align:center}
  .obs.on{display:flex}
  .obs h1{font-size:20px;font-weight:900;margin:0 0 6px}
  .ob-lead{max-width:280px;margin:12px auto 20px;color:var(--cream);font-size:16px;font-weight:700;line-height:1.45}
  .ob-sub{max-width:280px;margin:0 auto 18px;color:var(--muted);font-size:14px;line-height:1.4}
  .ob-hint{color:var(--muted);font-size:12px;margin-top:3px}
  .ob-ar{color:var(--gold2);font-size:18px;margin-top:2px}
  .ob-opts{display:flex;flex-direction:column;gap:9px;text-align:left;margin-top:6px}
  .ob-opt{display:flex;align-items:center;gap:12px;padding:12px 14px;border-radius:14px;border:2px solid var(--line);
    color:var(--cream);font-weight:700;font-size:15px;cursor:pointer;background:none;font-family:var(--ui);width:100%;text-align:left}
  .ob-opt .em{font-size:20px;width:24px;text-align:center;flex:0 0 auto}
  .ob-opt.sel{border-color:var(--gold);background:rgba(220,144,46,.16);font-weight:800}
  .ob-opt.goal{justify-content:center;gap:8px}
  .ob-opt.goal .min{color:var(--gold2)}
  .ob-opt.goal .lbl::before{content:"·";margin-right:8px;color:var(--muted)}
  .ob-list{display:flex;flex-direction:column;gap:12px;margin:6px auto 4px;width:fit-content;text-align:left}
  .ob-li{display:flex;align-items:center;gap:11px;color:var(--cream);font-size:16px;font-weight:700}
  .ob-li .ck{width:24px;height:24px;border-radius:50%;background:rgba(220,144,46,.18);border:1.5px solid var(--gold);
    color:var(--gold2);display:grid;place-items:center;font-size:13px;flex:0 0 auto}
  .ob-logo{width:150px;height:150px;object-fit:contain;border-radius:22px;margin:0 auto 10px;display:block}
  .ob-vid{width:210px;height:210px;object-fit:contain;margin:2px auto 6px;display:block;background:transparent}
  .ob-cta{margin-top:18px}
  .ob-in{width:100%;box-sizing:border-box;background:var(--panel2);border:2px solid var(--line);border-radius:14px;padding:14px;color:var(--cream);font-family:var(--ui);font-size:17px;text-align:center;margin-top:10px}
  .ob-in:focus{border-color:var(--gold);outline:none}
  /* L'écran d'assiduité (27/08) : la rangée de 7 épis (.ears/.ob-ear) est remplacée par
     l'épi animé qui pousse du tas de terre — voir .streak-plant, showStreak(). */
  .streak-plant{width:210px;height:210px;object-fit:contain;margin:6px auto 4px;display:block;background:transparent}
  /* Le verset de l'assiduité, en entier : il ne peut plus tenir en 36 px sur un iPhone. */
  #streak .verse{font-size:21px;line-height:2.05;max-width:340px;margin:6px 0 8px}
  .stk-tr{max-width:340px;color:var(--cream);font-size:13px;line-height:1.6;margin:0 0 4px}
  .stk-src{max-width:340px;color:var(--muted);font-size:11.5px;font-weight:800;margin:0 0 18px}
  .stk-spk{background:none;border:none;padding:6px;cursor:pointer;line-height:0}
  .stk-spk .spk{width:44px;height:29px}
  .rewards{display:flex;gap:14px;margin-bottom:30px}
  .reward{background:var(--panel);border:2px solid var(--line);border-radius:14px;padding:14px 22px;min-width:120px}
  .reward .lab{font-size:12px;font-weight:900;letter-spacing:.1em;color:var(--gold2)}
  .reward .val{font-size:26px;font-weight:900;margin-top:4px}
  .toast{position:fixed;left:50%;bottom:24px;transform:translateX(-50%) translateY(80px);background:var(--panel);
    border:1px solid var(--line);color:var(--cream);padding:12px 18px;border-radius:12px;font-weight:800;
    font-size:14px;z-index:80;transition:.3s;opacity:0;pointer-events:none}
  .toast.on{transform:translateX(-50%) translateY(0);opacity:1}

  /* ---- visite guidée disque 1 ---- */
  .demo .formrow,.formrow{display:flex;gap:22px;justify-content:center;margin:14px 0}
  .combine{display:flex;align-items:center;justify-content:center;gap:12px;margin:10px 0 26px;flex-wrap:wrap}
  .cmb{font-size:56px;font-weight:900;color:var(--cream);transition:.3s}
  .cmb.merge{transform:translateX(0);color:var(--gold)}
  #cmbA.merge{transform:translateX(18px)} #cmbB.merge{transform:translateX(-18px)}
  .cmb-plus,.cmb-eq{font-size:32px;color:var(--muted);font-weight:800}
  .cmb-res{color:var(--gold);min-width:60px}
  .hk3{display:flex;gap:10px;justify-content:center;margin-top:8px;flex-wrap:wrap}
  .hkcirc{position:relative;background:none;border:none;width:108px;height:150px;
    display:flex;flex-direction:column;align-items:center;justify-content:center}
  .hkcirc .circ{position:absolute;top:32px;left:50%;transform:translateX(-50%);
    width:86px;height:86px;border-radius:50%;border:3px dotted var(--gold-d)}
  .hkcirc .ctr{position:absolute;top:32px;left:50%;transform:translateX(-50%);
    width:86px;height:86px;display:grid;place-items:center;font-size:13px;font-weight:800;color:var(--muted)}
  .hkcirc .sign{position:absolute;left:50%;transform:translateX(-50%);
    font-family:var(--ar);font-size:40px;color:var(--gold);line-height:1;z-index:2}
  .hkcirc .sign.top{top:6px}
  .hkcirc .sign.bot{top:120px}  /* valeur de base — l'ajustement qui FAIT FOI est plus bas (l.~436, harakat écartées) */
  .hkcirc .hl{position:absolute;bottom:0;font-size:11px;font-weight:900;color:var(--muted);white-space:nowrap}
  .hkcirc.lit .circ{border-color:var(--gold);border-style:solid}
  .hkcirc.lit .sign{color:var(--gold2)}
  .assoc-l{font-family:var(--ar);font-size:80px;text-align:center;line-height:1.4}
  .assoc-row{display:grid;grid-template-columns:1fr 1fr 1fr;gap:10px}
  .assoc-c{background:var(--panel);border:2px solid var(--line);border-radius:14px;
    padding:14px 4px;display:flex;flex-direction:column;align-items:center;gap:6px}
  .assoc-c.lit{border-color:var(--gold);background:#3a312b}
  .assoc-c .sm{font-family:var(--ar);font-size:34px;color:var(--muted)}
  .assoc-c .res{font-family:var(--ar);font-size:40px;color:var(--gold);line-height:1.3}
  .tapset{display:grid;grid-template-columns:1fr 1fr 1fr;gap:10px;direction:rtl}
  .tapset.c3{grid-template-columns:1fr 1fr 1fr}
  /* ⚠️ 17/08 — `justify-content:center` AJOUTÉ (Myriam : « faut centrer en hauteur les
     lettres dans les box »). Une grille étire toutes les cases à la hauteur de la PLUS
     HAUTE ; sans centrage vertical, les glyphes restaient collés en haut avec du vide
     dessous — d'autant plus visible que certaines cartes portent une étiquette et d'autres
     non. C'est le même défaut que la ligne de la hamza, corrigé le 14/08 de la même façon. */
  .ts-card{background:var(--panel);border:2px solid var(--line);border-radius:14px;
    padding:14px 4px;display:flex;flex-direction:column;align-items:center;justify-content:center;
    gap:4px;direction:ltr}
  .ts-card.seen{background:var(--gold);border-color:var(--gold)}
  .ts-card.seen .ar{color:var(--bg)}
  .ts-card.seen .enm{color:var(--bg)}
  .ts-card .ar{font-family:var(--ar);font-size:42px;color:var(--gold);line-height:1.3;font-weight:500}
  .ts-card .enm{font-size:11px;font-weight:800;color:var(--muted)}
  .cmp-row{display:flex;align-items:center;justify-content:center;gap:10px;background:var(--panel);
    border:2px solid var(--line);border-radius:14px;padding:12px;margin-bottom:10px;font-family:var(--ar);font-size:38px}
  .cmp-row.lit{border-color:var(--gold)}
  .cmp-vs{color:var(--muted);font-size:20px}
  .cmp-l{font-family:var(--ui);font-size:13px;font-weight:800;color:var(--muted);margin-inline-start:auto}
  .readbox{display:flex;justify-content:center;gap:0;font-size:54px;background:var(--panel);
    border:2px solid var(--line);border-radius:18px;padding:22px 14px;touch-action:none;user-select:none}
  .readbox.ar{font-family:var(--ar);font-size:42px;font-weight:500}
  .rc{color:var(--cream);transition:color .12s}
  .rc.on{color:var(--gold);text-shadow:0 0 12px rgba(220,144,46,.55)}
  .readarrow{text-align:center;font-size:30px;color:var(--gold2);margin-top:14px;height:36px}
  .readarrow span{display:inline-block;animation:slidearrow 1.1s ease-in-out infinite}
  .readarrow.rtl span{transform:scaleX(-1)}
  @keyframes slidearrow{0%,100%{transform:translateX(-8px)}50%{transform:translateX(8px)}}
  .readarrow.rtl span{animation:slidearrowR 1.1s ease-in-out infinite}
  @keyframes slidearrowR{0%,100%{transform:scaleX(-1) translateX(-8px)}50%{transform:scaleX(-1) translateX(8px)}}
  .tapset.c4{grid-template-columns:repeat(4,1fr);gap:8px}
  .tapset.c4 .ts-card{padding:12px 2px}
  .tapset.c4 .ts-card .ar{font-size:42px;font-weight:500}
  /* ===== Leçon 1 v2 (07/08) ===== */
  .ts-card.dim{opacity:.28}                                   /* estompé mais cliquable */
  .ag.dim{opacity:.25;pointer-events:none}
  .cta.pope{animation:ctain .45s}
  @keyframes ctain{0%{transform:scale(.96)}55%{transform:scale(1.04)}100%{transform:none}}
  .elfr{font-size:12.5px;opacity:.8;font-weight:700}
  .hkcirc.gr .circ{border-color:#5a5049}
  .hkcirc.gr .sign{color:#5a5049}
  .hkcirc.gr.lit .circ{border-color:#5a5049;border-style:dotted} /* le disque RESTE gris */
  .hkcirc.gr.lit .sign{color:var(--gold2)}
  .hkcirc .sign.hi{top:-6px}                                  /* la damma ne mord plus le cercle */
  .hk3.mini{transform:scale(.6);transform-origin:top center;margin:-6px 0 -52px;flex-wrap:nowrap}
  .hk3.mini .hkcirc{pointer-events:none}
  .fuserow{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-top:16px}
  .mimC{width:84px;height:84px;border-radius:16px;background:var(--panel);border:2px dashed var(--line);
    display:grid;place-items:center;font-size:36px;color:var(--gold);flex:none;font-weight:400}
  .mimC.done{border-style:solid;border-color:var(--gold);background:#3a312b}
  .farr{font-size:24px;color:var(--muted);animation:farr 1.5s infinite;flex:none}
  @keyframes farr{0%{transform:translateX(12px);opacity:0}30%{opacity:1}100%{transform:translateX(-16px);opacity:0}}
  .fchip{width:74px;height:74px;border-radius:50%;background:var(--panel);border:2px solid var(--line);
    display:grid;place-items:center;font-size:34px;color:var(--gold);flex:none;touch-action:none;
    cursor:grab;position:relative}
  /* ═══ 17/08 — LE TRAIT DU JETON AU MILIEU DU CERCLE (preview validée) ═══════════
     Myriam : « le trait représentant la lettre doit être centré au milieu du cercle, et
     les harakat au-dessus / en dessous ne doivent pas toucher le bord ». Les deux
     demandes se règlent au même endroit : là où tombe la LIGNE DE BASE, sur laquelle le
     tatweel (ـ) repose. Une boîte de texte se centre sur sa hauteur de ligne, or
     l'ascendante d'une police arabe est bien plus grande que sa descendante — le trait
     tombait donc 10 px trop bas (20 px en grands caractères).
     ⚠️ LA POLICE EST ÉPINGLÉE, ET CE N'EST PAS COSMÉTIQUE : `.fchip` ne déclarait aucune
     `font-family` et il n'existe aucune règle `.ar` nue, donc le signe était dessiné par
     une police de SECOURS choisie par le système — autre sur iPhone que sur ce Mac. La
     correction en `em` n'était juste nulle part. Mesuré : avec Naskh épinglée, 0,22em
     centre le trait à ±1 px dans les TROIS tailles (74/34, 104/60, 85/49 × zoom 1,22).
     ⚠️ EN `em`, JAMAIS EN PIXELS : c'est un RAPPORT à la taille du glyphe, donc il suit
     tout seul le réglage « grands caractères ». En pixels il y serait faux du double.
     ⚠️ Ne vise QUE `.tach` — donc les seuls jetons qui portent un SIGNE. Sur la leçon des
     prolongations le jeton est une LETTRE (ا · و · ي) : `tachRouge` ne l'enveloppe pas,
     elle garde exactement son rendu validé.
     ⚠️ NE PAS ANCRER CES RÈGLES SUR `#fuzone`. `fantomeDe` (le fantôme qu'on traîne au doigt)
     fait `cloneNode` puis `document.body.appendChild` : le clone n'est PLUS descendant de
     `#fuzone`. Ancrées, ces règles le rataient — au moment de la prise en main le signe
     perdait sa police et son centrage (10 px de saut, 20 en grands caractères), et la 2ᵈᵉ
     couche de la kasra, privée de `position:absolute`, redevenait une CELLULE de grille :
     deux traits empilés dans le fantôme. Le geste de glisser EST la leçon : le défaut se
     verrait à chaque prise. */
  .fchip .tach{font-family:var(--ar);display:block;line-height:1;
    transform:translateY(-0.22em)}
  /* ═══ LA KASRA, UN SOUFFLE PLUS BAS (retour de Myriam : « trop près du trait ») ═════
     L'écart signe↔trait est GRAVÉ dans la police (l'ancre GPOS du couple) : impossible de
     l'agrandir sur un cluster intact, et un span autour d'une marque combinante ne la
     déplace pas plus qu'il ne la colore. D'où la règle du projet — DUPLIQUER, jamais
     découper : une couche porte le trait SEUL (c'est elle qui donne la position), l'autre
     porte le cluster ENTIER descendu de 0,09em, son propre trait retiré par un clip-path.
     ⚠️ le clip vit dans les coordonnées de la boîte, AVANT le transform : décaler la
     couche ne fait donc pas réapparaître le trait clippé.
     ⚠️ la 2ᵈᵉ couche est en `position:absolute` — c'est CE QUI LA SAUVE : `.fchip` est en
     `display:grid`, et une couche EN FLUX deviendrait une CELLULE séparée qui disloquerait
     le jeton (piège déjà vécu le 17/08 sur `.mimC`).
     ⚠️ SON ANCRAGE (`position:relative`) VIT SUR LA RÈGLE DE BASE `.fchip`, ET C'EST OBLIGÉ :
     posé sur une CLASSE il pèserait (0,2,0) et battrait `.drag-clone{position:fixed}` (0,1,0),
     qui est justement la règle qui fait suivre le fantôme au doigt — ses `left`/`top` en ligne
     deviendraient des décalages relatifs et le fantôme se figerait. Sur la règle de base il
     pèse (0,1,0) et `.drag-clone`, déclarée plus loin dans le fichier, gagne par ORDRE.
     (Même motif que `.tile`, qui porte déjà `position:relative` sur sa règle de base.) */
  .fchip .tach.fk{position:absolute;left:50%;top:50%;
    transform:translate(-50%,-50%) translateY(calc(-0.22em + 0.09em));
    clip-path:inset(0.78em 0 0 0)}
  .gone{visibility:hidden}
  .g6{display:grid;grid-template-columns:1fr 1fr 1fr;gap:10px;direction:rtl;margin-top:8px}
  .b6{background:var(--panel);border:2px solid var(--line);border-radius:14px;
    padding:12px 4px;font-size:42px;color:var(--gold);transition:opacity .3s;cursor:pointer;font-weight:700}
  .b6.sel{background:var(--gold);color:var(--bg);border-color:var(--gold)}
  .b6.dim{opacity:.28;pointer-events:none}
  .b6.wrong{border-color:var(--coral);color:var(--coral);background:var(--panel);opacity:1}
  .corr{font-size:13.5px;color:var(--coral);text-align:center;margin-top:12px;font-weight:800;min-height:18px}
  .corr .ar{font-size:1.5em;font-weight:900}
  .fourcells.ligne{grid-template-columns:repeat(4,1fr);gap:8px;direction:rtl}
  .readbox.reveal .rc{color:#57493e}
  .readbox.reveal .rc.on{color:var(--gold)}
  .readbox{position:relative}
  /* la main qui montre le geste (Artlist, Myriam 10/08) : elle balaie le MOT, du début à la
     fin — --hx0/--hx1 sont mesurés par setupRead sur les vraies lettres, pas sur le cadre */
  .readhand{position:absolute;top:44%;width:52px;height:auto;pointer-events:none;z-index:2;
    filter:drop-shadow(0 3px 5px rgba(0,0,0,.45));animation:readhand 2.6s ease-in-out infinite}
  @keyframes readhand{0%{left:var(--hx0,70%);opacity:0}14%,78%{opacity:1}100%{left:var(--hx1,6%);opacity:0}}
  .hkcirc .hbar{display:block;width:44px;height:10px;border-radius:6px;background:currentColor;transform:rotate(-18deg)}
  .hkcirc .hdam{font-family:var(--ar);font-style:normal;font-weight:700;font-size:36px;line-height:.8;display:block}
  .hkcirc .sign.top{top:5px}
  .hkcirc .sign.bot{top:130px}  /* 130 et non 122 : à 122 la kasra mordait encore le disque pointillé (Myriam 07/08) */
  .hkcirc .sign.hi{top:-4px}
  /* ⚠️ 17/08 — LE DERNIER DÉFAUT DE CONTRASTE, tranché par Myriam (« corrige le dernier
     point ») : le ✓ blanc sur la pastille verte faisait 2,54:1 en mode sombre (documenté le
     13/08, laissé alors à son arbitrage). L'encre devient SOMBRE sur les pastilles claires du
     mode nuit (vert 5,2:1 · corail 4,8:1, calculés) ; en mode clair les pastilles sont FONCÉES
     (--green #1F6B45) : le blanc y était déjà bon (5,5:1) et le sombre y serait illisible —
     d'où l'inversion plus bas, même logique que « l'allumé fonce en clair ». */
  .fb span:first-child{width:28px;height:28px;border-radius:50%;display:grid;place-items:center;
    font-size:15px;flex:none}
  .fb.ok span:first-child{background:var(--green);color:#22332B;animation:fbpop .45s cubic-bezier(.3,1.6,.5,1)}
  .fb.bad span:first-child{background:var(--coral);color:#3A2723;animation:fbpop .35s cubic-bezier(.3,1.6,.5,1),fbshake .35s ease .35s}
  @keyframes fbpop{0%{transform:scale(0)}60%{transform:scale(1.3)}100%{transform:scale(1)}}
  @keyframes fbshake{0%,100%{transform:translateX(0)}25%{transform:translateX(-4px)}55%{transform:translateX(4px)}80%{transform:translateX(-2px)}}
  /* ═══ LEÇON 7 « Lire des mots » v3 (11/08) — glisser le signe · bulles-mots · le tri ═══ */
  .sigchip{width:96px;height:96px;margin:6px auto 26px;border-radius:20px;
    background:var(--panel);border:2px solid var(--line);
    display:grid;place-items:center;font-family:var(--ar);font-size:52px;color:var(--gold);
    touch-action:none;cursor:grab;user-select:none}
  .grps{display:flex;flex-direction:column;gap:12px;align-items:center}
  .grp{min-width:150px;padding:10px 18px;border-radius:16px;background:var(--panel);
    border:2px dashed var(--line);font-family:var(--ar);font-size:44px;line-height:1.5;
    direction:rtl;text-align:center}
  .grp .gpre{color:var(--cream);opacity:.4}      /* le أَ : grisé, JAMAIS une cible */
  .grp .gcib{color:var(--gold)}
  .grp.done{border-style:solid;border-color:var(--gold);background:#3a312b}
  .grp.done .gcib{color:var(--gold2)}
  /* 14/08 — Myriam : « les mots dans les bulles sont trop petits, faut grossir les bulles
     et la taille de la police ». 96 → 112 px et 25 → 30 px. ⚠️ Le plafond n'est pas
     esthétique, il est ARITHMÉTIQUE : la mise en place range les bulles par 3 en largeur
     et le lecteur fait 346 px utiles — 3 × 116 px ne tiendrait plus. */
  .bul.mot{width:112px;height:112px;font-size:36px;font-weight:400}   /* un mot entier dans la bulle */
  .bul.shk{animation:bulshk .35s ease}
  /* ⚠️ la translation est reprise à CHAQUE étape (piège gravé de la leçon 2) */
  @keyframes bulshk{0%,100%{transform:translate(var(--x),var(--y))}
    25%{transform:translate(calc(var(--x) - 6px),var(--y))}
    60%{transform:translate(calc(var(--x) + 6px),var(--y))}}
  .trirow{display:flex;justify-content:center;gap:10px;flex-wrap:wrap;direction:rtl;margin-bottom:22px}
  /* 14/08 (correctifs 4) — Myriam, jeu de tri (écran 10 leçon 3 ET leçon 7, même moteur) :
     « augmente la taille de la police des mots à trier, et la hauteur des box pointillées ». */
  .chipmot{background:var(--panel);border:2px solid var(--line);
    border-radius:14px;padding:9px 18px;font-family:var(--ar);font-size:36px;color:var(--gold);
    touch-action:none;cursor:grab;user-select:none;font-weight:400}
  .chipmot.gone{visibility:hidden}
  .chipmot.shake{animation:penshake .35s}
  .paniers{display:flex;gap:14px}
  .panier{flex:1;min-height:210px;background:var(--panel);border:2px dashed var(--line);
    border-radius:16px;padding:8px;text-align:center}
  /* 14/08 (correctifs 4, trouvé par l'agent qa-visuel-alaq) — « le critère de tri est
     l'élément le plus petit de l'écran » : les mots agrandis (38 px) écrasent l'étiquette du
     panier, qui reste le repère à lire en premier. */
  .panier .psig{font-family:var(--ar);font-size:80px;color:var(--gold);line-height:1.3;font-weight:400}
  .panier .pmots{display:flex;flex-wrap:wrap;gap:6px;justify-content:center;direction:rtl}
  .panier .pmots span{font-family:var(--ar);font-size:23px;color:var(--gold2);background:#3a312b;
    border:1px solid var(--gold-d);border-radius:10px;padding:2px 10px;cursor:pointer}
  .panier .pmots span:active{transform:scale(.94)}

  /* ===== ⚑ Signalements (08/08) — préview validée : drapeau en haut à droite du bandeau bas ===== */
  /* top NÉGATIF : le drapeau flotte AU-DESSUS du bandeau (il recouvrait le coin de
     CONTINUER/VALIDER — Myriam 10/08, tâche leçon 4) */
  .p-flag{position:absolute;top:-42px;right:8px;background:none;border:none;color:var(--coral);
    opacity:1;font-size:29px;line-height:1;padding:4px 8px;cursor:pointer;z-index:3}
  /* DYNAMIQUE (10/08 soir) : dès que le pied porte un verdict ou l'éloge (.ok/.bad), il est
     grand — le drapeau RENTRE à son coin haut-droit (position validée le 08/08) au lieu de
     monter sur la leçon ; au repos il flotte au-dessus du bandeau (position validée le 10/08). */
  #p-foot.ok .p-flag,#p-foot.bad .p-flag{top:2px}
  /* le drapeau rentré mord sur la 1re ligne d'un verdict long : la place lui est laissée (QA 19/09) */
  #p-foot.ok .fb,#p-foot.bad .fb{padding-right:24px}
  #player.vfmode .p-flag{display:none}
  .sig-voile{position:fixed;inset:0;background:rgba(0,0,0,.55);opacity:0;pointer-events:none;transition:.25s;z-index:90}
  .sig-voile.on{opacity:1;pointer-events:auto}
  .sig-sheet{position:fixed;left:0;right:0;bottom:0;background:var(--panel);border-radius:22px 22px 0 0;
    padding:18px 16px calc(18px + env(safe-area-inset-bottom,0px));transform:translateY(105%);transition:.28s;z-index:91;
    max-width:560px;margin:0 auto}
  .sig-sheet.on{transform:none}
  .sig-sheet h3{font-size:15px;margin:0 0 12px;text-align:center;color:var(--cream)}
  .sig-opt{display:block;width:100%;text-align:left;background:var(--panel2);border:2px solid var(--line);
    border-radius:12px;color:var(--cream);font-size:14px;font-weight:700;padding:12px 14px;margin-bottom:8px;cursor:pointer}
  .sig-opt.sel{border-color:var(--gold);background:#3a312b}
  .sig-txt{width:100%;background:var(--panel2);border:2px solid var(--line);border-radius:12px;box-sizing:border-box;
    color:var(--cream);font-family:inherit;font-size:14px;padding:10px;min-height:64px;display:none;margin-bottom:8px}
  .sig-txt.on{display:block}
  .sig-env{width:100%;background:var(--gold);border:none;border-radius:14px;color:#1a1410;
    font-weight:900;font-size:15px;padding:14px;margin-top:4px;cursor:pointer}
  .sig-env:disabled{opacity:.4}
  .masc-wrap{width:170px;margin:0 auto 6px}
  /* ⚠️ 13/08 : ces règles visaient des id — donc UNE seule mascotte pouvait exister.
     Elles visent des CLASSES : l'écran de récompense peut en poser une seconde. */
  .masc{width:170px;height:200px;overflow:visible;display:block}
  .mhalo,.mcorps,.mbassin,.mjambe{transform-box:fill-box}
  .mhalo{transform-origin:50% 50%;opacity:.55}
  .mcorps{transform-origin:50% 100%}
  .mbassin{transform-origin:50% 0%;transition:transform .12s cubic-bezier(.3,1.5,.5,1)}
  .mjambe{transform-origin:50% 0%;transition:transform .13s cubic-bezier(.3,1.5,.5,1)}
  .lg-prompt{font-size:15px;font-weight:800;color:var(--cream);text-align:center;margin:0 0 10px}
  .lg-prompt.empty{color:var(--muted);font-weight:700}
  .lg-prog{margin:0 0 12px} .lg-plab{font-size:12.5px;font-weight:800;color:var(--muted);text-align:center;margin-bottom:5px}
  .lg-pbar{height:8px;background:#241f1c;border-radius:6px;overflow:hidden;border:1px solid var(--line)}
  .lg-pbar span{display:block;height:100%;background:linear-gradient(90deg,#B9770E,#E8A94F);border-radius:6px}
  .lg-qa{display:flex;gap:8px;justify-content:center;margin:12px 0 0}
  .lg-qa button{background:#2a2422;border:1.5px solid var(--line);color:var(--gold2);border-radius:10px;padding:7px 12px;font-family:var(--ui);font-weight:800;font-size:12.5px;cursor:pointer}
  .lg-top{display:flex;align-items:center;gap:10px;margin-bottom:10px}
  .lg-top .lg-rev{flex:1;width:auto;margin-top:0}
  .lg-help{flex:0 0 auto;width:44px;height:44px;border-radius:50%;background:var(--panel2);border:1.5px solid var(--line);color:var(--gold2);font-family:var(--ui);font-weight:900;font-size:19px;cursor:pointer}
  .lg-help:active{transform:scale(.94)}
  .lg-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:6px;direction:rtl}
  .lg-cell{position:relative;border-radius:12px;padding:8px 0;text-align:center;border:1.5px solid var(--line);font-family:"Noto Naskh Arabic",serif;font-size:27px;line-height:1;background:#2a2422}
  .lg-cell.locked{color:#5b524c;background:#2a2624;border-color:#332e2a;opacity:.55}
  .lg-cell.avail{color:#a9843c;background:#2b2622;cursor:pointer}
  .lg-cell.sel{color:var(--gold2);background:rgba(232,169,79,.14);border-color:var(--gold2);box-shadow:0 0 0 1px var(--gold2);cursor:pointer;font-weight:700}
  .lg-cell.nouv{animation:lgglow 1.6s ease-in-out infinite}
  /* ═══ LA HAMZA ET SES SIÈGES (13/08) ═══
     Une ligne À PART, séparée par un filet : c'est ce qui dit, sans un mot, qu'elle ne
     compte pas parmi les 28. Les cases sont plus petites que celles des lettres — elles
     ne prétendent pas au même rang. */
  .lg-hamza{display:grid;grid-template-columns:repeat(5,1fr);gap:6px;direction:rtl;
    margin-top:14px;padding-top:14px;border-top:1px dashed var(--line)}
  /* 14/08 (correctifs 4, trouvé par l'agent qa-visuel-alaq) — depuis le retrait de l'annotation
     sur les sièges, la rangée s'étire à la hauteur de la SEULE case qui gardait encore un label
     (« seule », sous ء) : les 4 autres cases suivent (grid stretch) mais leur glyphe restait
     collé en haut, avec du vide dessous. flex+centrage vertical règle ça quelle que soit la
     hauteur de la rangée, avec ou sans étiquette. ⚠️ « seule » retiré à son tour (même agent,
     seconde passe) : les 5 cases retombent alors à ~38 px de haut sans lui — sous la zone de
     touche de 44 px. min-height le garantit maintenant pour TOUTES les cases, pas seulement
     `.vide` (qui perd cette classe dès que roleTap remplit le siège). */
  .lg-hamza .hz{position:relative;display:flex;flex-direction:column;align-items:center;justify-content:center;
    min-height:44px;border-radius:12px;padding:7px 0 5px;text-align:center;
    border:1.5px solid var(--line);background:#2a2422;font-family:"Noto Naskh Arabic",serif;
    font-size:42px;line-height:1.15;color:var(--gold2);cursor:pointer;font-weight:500}
  /* L'étiquette nomme le SIÈGE. Depuis le 14/08 elle est écrite en arabe (règle absolue :
     aucune translittération sous un glyphe arabe) — sauf « seule », qui est un mot français
     descriptif, pas la transcription d'un nom de lettre. */
  .lg-hamza .hz .hzl.ar{font-family:var(--ar);font-size:16px;font-weight:700}
  .lg-hamza .hz .hzl{display:block;font-family:var(--ui);font-size:16px;font-weight:700;
    color:var(--muted);letter-spacing:.02em;margin-top:2px}
  .lg-hamza .hz.locked{color:#5b524c;background:#2a2624;border-color:#332e2a;opacity:.55;cursor:default}
  .lg-hamza .hz:not(.locked):active{border-color:var(--gold);color:var(--gold2)}
  .lg-hamza .hz.lit{border-color:var(--gold);color:var(--gold2);background:rgba(232,169,79,.12)}
  /* La même ligne, posée sous la grille d'un EXERCICE (14/08) : elle respire un peu plus,
     le compteur « 0 / 3 » vient juste après et ne doit pas lui coller. */
  .lg-hamza.ex-hamza{margin-top:12px;padding-top:12px;margin-bottom:6px}
  /* La fiche du Cours : le nom de la lettre ne s'écrit plus, le bouton dit ce qu'il joue. */
  .lcap{font-size:12px;font-weight:800;color:var(--muted)}
  @keyframes lgglow{0%,100%{box-shadow:0 0 0 0 rgba(232,169,79,0)}50%{box-shadow:0 0 0 2px rgba(232,169,79,.45)}}
  .lg-cell .lk{position:absolute;top:5px;left:7px;font-size:10px;opacity:.6}
  .lg-cell .bd{position:absolute;top:3px;right:5px;font-size:11px}
  .lg-cell .ck{position:absolute;top:4px;left:7px;font-size:11px;font-family:var(--ui);font-weight:900;color:var(--gold2)}
  /* 05/09 — déplacé en haut-DROIT (spec §2.3), possible depuis que ✨ (qui y
   vivait) est retiré. Coin bas-gauche laissé aux futurs repères, si besoin. */
.lg-cell .sm{position:absolute;top:3px;right:5px;font-size:10px;line-height:1;opacity:.9}
  .lg-rev{width:100%;margin-top:16px;padding:14px;border-radius:14px;border:none;cursor:pointer;font-family:var(--ui);font-weight:900;font-size:16px;background:var(--gold);color:#1a1410}
  .lg-rev:disabled{background:#3a332e;color:#6f665f;cursor:not-allowed}
  .lg-replay{background:transparent;border:1.5px solid var(--line);color:var(--muted);border-radius:10px;padding:8px 14px;font-family:var(--ui);font-weight:800;font-size:12.5px;cursor:pointer}
  .lg-replay:hover{border-color:var(--gold);color:var(--gold2)}
  #letterTut{position:fixed;inset:0;z-index:1200;display:none}
  #ltHole{position:fixed;border-radius:14px;box-shadow:0 0 0 9999px rgba(12,9,8,.74);border:2px solid var(--gold2);transition:top .4s cubic-bezier(.5,0,.2,1),left .4s,width .4s,height .4s;pointer-events:none}
  #ltBubble{position:fixed;max-width:290px;background:#3a322c;border:1.5px solid var(--gold2);border-radius:16px;padding:14px 16px;box-shadow:0 12px 34px rgba(0,0,0,.5);transition:top .35s,left .35s}
  #ltBubble .lt-t{font-size:15px;font-weight:900;color:var(--gold2);margin:0 0 5px}
  #ltBubble .lt-x{font-size:13.5px;line-height:1.5;color:var(--cream)}
  #ltBubble .lt-row{display:flex;justify-content:space-between;align-items:center;margin-top:12px}
  #ltBubble .lt-step{font-size:12px;font-weight:800;color:var(--muted)}
  #ltBubble .lt-btns{display:flex;gap:8px}
  #ltBubble .lt-skip{background:transparent;border:none;color:var(--muted);font-weight:800;font-size:12.5px;cursor:pointer}
  #ltBubble .lt-next{background:var(--gold);border:none;color:#1a1410;font-weight:900;font-size:13px;border-radius:10px;padding:7px 14px;cursor:pointer}
  #ltBubble .lt-arrow{position:absolute;width:16px;height:16px;background:#3a322c;border-left:1.5px solid var(--gold2);border-top:1.5px solid var(--gold2)}
  .ag.hl{background:#4a3a22;border-color:var(--gold-d)}
  .ag.hit{background:var(--gold);color:var(--bg);border-color:var(--gold)}
  .ag.miss{animation:agmiss .35s;border-color:var(--coral);color:var(--coral)}
  @keyframes agmiss{20%{transform:translateX(-5px)}60%{transform:translateX(5px)}}
  .source{text-align:center;margin-bottom:18px}
  .srcL{background:var(--panel);border:2px solid var(--gold);border-radius:18px;width:90px;height:90px;
    font-family:var(--ar);font-size:54px;color:var(--gold);line-height:90px;text-align:center;margin:0 auto;
    touch-action:none;user-select:none;-webkit-user-select:none}
  .srcL:active{background:#3a312b}
  .drag-ghost{position:fixed;transform:translate(-50%,-50%);z-index:200;pointer-events:none;
    font-family:var(--ar);font-size:60px;color:var(--gold);text-shadow:0 4px 12px rgba(0,0,0,.5)}
  /* Le fantôme-CLONE (14/08) : il garde le fond, la bordure et la police de la pastille
     d'origine ; on ne lui impose que sa position et son détachement. Les marges de la
     pastille sont neutralisées — sinon le clone se recentre à côté du doigt. */
  .drag-clone{position:fixed;left:0;top:0;transform:translate(-50%,-50%) scale(1.06);
    z-index:200;pointer-events:none;margin:0!important;opacity:1!important;
    box-shadow:0 12px 26px rgba(0,0,0,.45)}
  .fourc.hover{border-color:var(--gold2);background:#3a312b;border-style:solid}
  .fourcells{display:grid;grid-template-columns:1fr 1fr;gap:12px}
  .fourc{background:var(--panel);border:2px dashed var(--line);border-radius:16px;min-height:96px;
    display:flex;flex-direction:column;align-items:center;justify-content:center;gap:6px}
  .fourc.lit{border-style:solid;border-color:var(--gold);background:#3a312b}
  .fourc .ar{font-family:var(--ar);font-size:36px;line-height:1.4;min-height:46px;direction:rtl;font-weight:400}
  .fourc .fl{font-size:16px;font-weight:700;color:var(--muted)}
  /* l'invitation après 10 s d'inactivité (Myriam 10/08) : la source SAUTE doucement,
     les cases restantes pulsent — 3 fois, puis on se tait et on ré-arme */
  .srcL.invite{animation:penhint 1.1s ease-in-out 3, srcsaute 1.1s ease-in-out 3}
  .fourc.invite{animation:penhint 1.1s ease-in-out 3;border-color:var(--gold-d)}
  @keyframes srcsaute{0%,100%{transform:translateY(0)}45%{transform:translateY(-8px)}}
  /* Lettres vs prolongations — slides interactives */
  .lvp{display:flex;flex-direction:column;gap:12px;margin-top:8px}
  .lvp-cards{display:flex;gap:10px;justify-content:center;align-items:stretch}
  .lvp-flip{flex:1;cursor:pointer;user-select:none;position:relative}
  .lvp-flip.seen::after{content:'✓';position:absolute;top:6px;right:6px;width:20px;height:20px;border-radius:50%;
    background:var(--green);color:#fff;font-size:12px;font-weight:900;display:flex;align-items:center;justify-content:center;z-index:5}
  /* ═══ LES CARTES À DEUX VISAGES, v3 (Myriam, 14/08) ═══
     « Ce n'est pas la LETTRE qui doit être colorée, mais le FOND de la box, sinon ce n'est
     pas assez visible. » C'est la règle 5 bis du cerveau — deux natures opposées = deux
     couleurs — appliquée là où elle se voit : le RECTO porte l'or (la lettre au travail),
     le VERSO le bleu information (son second rôle). L'encre reste sombre/claire selon le
     thème, jamais une troisième couleur.
     Le terme (« consonne » / « support » / « prolongation ») est POUSSÉ EN BAS de la carte
     par un `margin-top:auto` — il ne flotte plus sous le glyphe au milieu du vide — et il
     passe de 10,5 à 13 px. Le glyphe passe de 44 à 58 px. */
  .lvp-flip-in{border-radius:16px;border:2px solid var(--gold-d);background:var(--face-or,#4a3a1e);min-height:172px;
    display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;padding:12px 8px 10px;text-align:center;
    transition:transform .24s ease,border-color .2s,background .2s}
  .lvp-flip.flipping .lvp-flip-in{transform:scaleX(.04)}
  .lvp-flip.flipped .lvp-flip-in{border-color:var(--info);background:var(--face-info,#173a49)}
  .lvp-flip .face-cons{display:flex;flex:1;flex-direction:column;align-items:center;gap:4px;width:100%}
  .lvp-flip .face-pro{display:none;flex:1;flex-direction:column;align-items:center;gap:4px;width:100%}
  .lvp-flip.flipped .face-cons{display:none}
  .lvp-flip.flipped .face-pro{display:flex}
  /* 14/08 (correctifs 4) — Myriam : « les lettres ne sont pas alignées, centre-les sur la
     hauteur ». `.ff-role` poussait le glyphe vers le haut (margin-top:auto, 14/08 matin) pour
     ne pas le laisser flotter au milieu du vide — mais chaque glyphe se retrouvait calé sur SA
     propre hauteur de trait (ا grand, و bas, ي avec hampe), donc désaligné d'une carte à
     l'autre. `.ff-slot` prend maintenant tout l'espace disponible et centre le glyphe DEDANS :
     les trois cartes centrent sur le MÊME repère, et « support »/« prolongation » reste juste
     en dessous, sans flotter (il n'a plus besoin de l'auto-margin pour ça). */
  .lvp-flip .ff-slot{flex:1;display:flex;align-items:center;justify-content:center;width:100%}
  .lvp-flip .ff-ar{font-family:var(--ar);font-size:80px;line-height:1.15;font-weight:400}
  .lvp-flip .ff-role{font-size:16px;font-weight:700;line-height:1.25;letter-spacing:.01em}
  .lvp-flip .ff-son{font-size:14px;font-weight:900}
  .lvp-flip .ff-spk{font-size:13px;opacity:.85;margin-top:2px}
  /* L'encre : la lettre et son terme prennent la couleur POSÉE SUR leur aplat, jamais
     l'aplat lui-même (piège du token à double rôle, 13/08). */
  .lvp-flip:not(.flipped) .ff-ar,.lvp-flip:not(.flipped) .ff-son,
  .lvp-flip:not(.flipped) .ff-role{color:#FFE7B8}
  .lvp-flip.flipped .ff-ar,.lvp-flip.flipped .ff-son,
  .lvp-flip.flipped .ff-role{color:#D8EEF8}
  .lvp-flip-hint{font-size:11px;color:var(--muted);font-weight:800;text-align:center;margin-top:8px}
  .lvp-exrow{display:flex;align-items:center;gap:10px;background:var(--panel);border:2px solid var(--line);border-radius:14px;padding:10px 12px}
  .lvp-exrow .ex-tag{font-weight:900;color:var(--gold2);min-width:22px;text-align:center;font-size:15px}
  .lvp-exrow .ex-chip{font-family:var(--ar);font-size:26px;color:var(--gold);background:var(--panel2);border:2px solid var(--line);
    border-radius:12px;padding:3px 14px;cursor:pointer;user-select:none;display:inline-flex;align-items:center;gap:6px;
    transition:transform .12s,border-color .2s,background .2s}
  .lvp-exrow .ex-chip:active{transform:scale(.94)}
  .lvp-exrow .ex-chip.lit{border-color:var(--gold);background:#3a312b}
  .lvp-exrow .ex-chip small{font-family:var(--ui);font-size:12px;color:var(--muted)}
  .lvp-exrow .ex-spk{margin-left:auto;font-size:16px;opacity:.55}
  /* Glisser-déposer la prolongation */
  .dm-wrap{display:flex;flex-direction:column;align-items:center;gap:14px;margin-top:4px}
  .dm-target{min-width:150px;min-height:96px;border:3px dashed var(--line);border-radius:20px;
    display:flex;align-items:center;justify-content:center;gap:4px;font-family:var(--ar);font-size:46px;color:var(--cream);
    padding:6px 20px;direction:rtl;transition:border-color .15s,background .15s}
  /* La tachkīl en rouge (14/08) — son propre token, jamais le corail de l'erreur.
     ⚠️ 14/08 (correctifs 4) — `.tach` colore maintenant le CLUSTER ENTIER (lettre + signe),
     jamais le signe seul : voir le commentaire de `tachRouge()` (trois pistes fausses avant
     celle-ci, chacune reproduite et prouvée au harnais). */
  .tach{color:var(--tach)}
  /* ══ LE CALQUE DE LA HARAKAT (17/08) ═══════════════════════════════════════════
     Myriam : « seule la harakat reste bleue, la lettre garde sa couleur initiale ».
     ⚠️ MESURÉ AU PIXEL, et c'est contre-intuitif : envelopper la marque seule dans un
     span ne change PAS sa couleur RENDUE (0 pixel bleu, 2 778 dorés sur la sonde).
     Chrome façonne lettre+marque comme UN SEUL cluster et le peint avec la couleur de
     la lettre — le style calculé dit bleu, le moteur l'ignore. C'est très exactement ce
     mur qu'annonçaient les « trois pistes fausses » du 14/08, et l'unité 8 avait fait le
     même constat (« 0 pixel bleu sur cinq sondes », previews/_u8/01-outils.js).
     LA SOLUTION : deux couches superposées. Dessous le cluster ENTIER coloré ; dessus la
     LETTRE SEULE, opaque, qui recouvre pile sa jumelle. Il ne reste que la marque colorée.
     Elles se superposent au pixel parce qu'une marque combinante ne change pas la largeur
     d'avance de sa lettre. `.hkb` prend `inherit` : la lettre garde la couleur de SA case
     (or dans .mimC, crème dans .dm-target) — ne jamais y écrire une couleur en dur. */
  .hkw{position:relative;display:inline-block}
  .hkw .hkm{position:absolute;left:0;top:0;z-index:0;color:var(--tach);white-space:pre}  /* 🔴 AUCUNE TAILLE ICI, JAMAIS (01/09). Le mot coloré vit sur DEUX couches
     exactement superposées : .hkm porte le cluster entier (en bleu), .hkb la
     lettre nue par-dessus. Elles ne coïncident que si elles ont la MÊME taille,
     donc les deux doivent HÉRITER de leur hôte. Le lot des polices a posé 80px
     ici et le mot s'est affiché EN DOUBLE — sans une erreur en console, sans
     rien de visible à la lecture du CSS. C'est le harnais du calque qui l'a vu.
     La taille d'un mot coloré se règle sur son HÔTE, jamais sur une couche. */
  .hkw .hkb{position:relative;z-index:1;color:inherit;white-space:pre}
  .dm-target.over{border-color:var(--gold2);background:#3a312b}
  .dm-target.done{border-style:solid;border-color:var(--green);background:var(--green-bg)}
  .dm-target .dm-res{color:var(--green)}
  .dm-hint{font-size:12px;color:var(--muted);font-weight:800;text-align:center;margin-top:-4px}
  .dm-tray{display:flex;gap:14px;justify-content:center;min-height:78px}
  .dm-tile{width:74px;height:74px;border-radius:16px;background:var(--panel2);border:2px solid var(--line);
    display:flex;align-items:center;justify-content:center;font-family:var(--ar);font-size:40px;color:var(--gold);
    touch-action:none;cursor:grab;user-select:none;-webkit-user-select:none;will-change:transform;
    transition:border-color .2s,background .2s,box-shadow .2s}
  .dm-tile.drag{cursor:grabbing;z-index:50;border-color:var(--gold);box-shadow:0 10px 22px rgba(0,0,0,.55)}
  .dm-tile.placed{opacity:.22;pointer-events:none}
  .dm-fb{min-height:22px;font-weight:800;font-size:15px;text-align:center}
  .dm-fb.ok{color:var(--green)} .dm-fb.bad{color:var(--coral)}
  .dm-exp{max-width:340px;margin:0 auto;line-height:1.5;font-size:15px}
  .dm-ok{margin-top:10px;background:var(--gold);color:#241c10;border:none;border-radius:12px;
    padding:8px 20px;font-family:var(--ui);font-weight:900;font-size:14px;cursor:pointer;box-shadow:0 3px 0 var(--gold-d)}
  .dm-ok:active{transform:translateY(2px);box-shadow:0 1px 0 var(--gold-d)}
  /* Association multi-cibles (prolongation) */
  .da-wrap{display:flex;flex-direction:column;align-items:center;gap:14px;margin-top:2px}
  .da-tops{display:flex;gap:10px;justify-content:center}
  .da-cell{width:92px;min-height:90px;border:3px dashed var(--line);border-radius:18px;display:flex;align-items:center;justify-content:center;
    font-family:var(--ar);font-size:36px;color:var(--cream);direction:rtl;padding:4px;transition:border-color .15s,background .15s;font-weight:400}
  .da-cell.over{border-color:var(--gold2);background:#3a312b}
  .da-cell.done{border-style:solid;border-color:var(--green);background:var(--green-bg)}
  .da-cell .da-long{color:var(--green);font-size:36px;font-weight:400}
  .da-arrowrow{font-size:12px;color:var(--muted);font-weight:800;text-align:center}
  .da-bottoms{display:flex;gap:12px;justify-content:center;min-height:72px}
  .da-tile{width:68px;height:68px;border-radius:16px;background:var(--panel2);border:2px solid var(--line);
    display:flex;align-items:center;justify-content:center;font-family:var(--ar);font-size:38px;color:var(--gold);
    touch-action:none;cursor:grab;user-select:none;-webkit-user-select:none;will-change:transform;transition:border-color .2s,box-shadow .2s}
  .da-tile.drag{cursor:grabbing;z-index:50;border-color:var(--gold);box-shadow:0 10px 22px rgba(0,0,0,.55)}
  .da-tile.placed{opacity:.18;pointer-events:none}
  .da-tile.hint,.dm-tile.hint{border-color:var(--gold);color:var(--gold2);animation:tilehint .9s ease-in-out infinite}
  .lvp-row{position:relative;display:flex;align-items:center;gap:10px;background:var(--panel);border:2px solid var(--line);
    border-radius:16px;padding:16px 20px;cursor:pointer;user-select:none;transition:transform .12s,border-color .2s,background .2s}
  .lvp-row:active{transform:scale(.98)}
  .lvp-row.lit{border-color:var(--gold);background:#3a312b}
  .lvp-row .lr-eq{font-family:var(--ar);font-size:24px;color:var(--cream);direction:rtl}
  /* 14/08 (correctifs 4) — Myriam, écran 9 « Touche chaque support » : le glyphe collait au
     bord gauche de la large box (le haut-parleur, en margin-left:auto, le poussait tout seul
     à droite). flex:1 + text-align:center l'a rapproché du centre, mais restait décalé de la
     largeur du haut-parleur (trouvé par l'agent qa-visuel-alaq) : tant que le haut-parleur
     occupe une place dans la ligne, le CENTRE de l'espace qui reste n'est pas le centre de la
     box. Le haut-parleur sort du flux (position:absolute, ancré à droite) : le glyphe seul
     dans la ligne peut enfin se centrer sur la box ENTIÈRE. */
  .lvp-row .lr-c{width:100%;text-align:center;font-family:var(--ar);font-size:52px;color:var(--gold);line-height:1.35}
  .lvp-row .lr-arrow{color:var(--muted);font-weight:900}
  .lvp-row .lr-long{font-family:var(--ar);font-size:30px;color:var(--gold);display:inline-block;transform-origin:right center}
  .lvp-row.lit .lr-long{animation:lvpStretch 1s ease}
  .lvp-row .lr-tag{font-weight:800;color:var(--gold2)}
  .lvp-row .lr-spk{position:absolute;right:20px;top:50%;transform:translateY(-50%);font-size:20px;opacity:.85}
  @keyframes lvpStretch{0%{transform:scaleX(1)}40%{transform:scaleX(1.75)}100%{transform:scaleX(1)}}
  .lvp-glotte{display:flex;justify-content:center;gap:16px;font-size:30px;font-weight:900;margin:10px 0}
  .lvp-glotte span{display:inline-block;animation:lvpBeat 1.6s ease-in-out infinite}
  .lvp-glotte span:nth-child(2){animation-delay:.18s;color:var(--gold);font-family:var(--ar)}
  @keyframes lvpBeat{0%,100%{transform:translateY(0)}30%{transform:translateY(-8px)}}
  .lvp-seat{display:flex;gap:10px;justify-content:center;margin-top:8px}
  .lvp-seat .ls{flex:1;max-width:165px;background:var(--panel);border:2px solid var(--line);border-radius:16px;
    padding:12px;text-align:center;cursor:pointer;user-select:none;transition:transform .12s,border-color .2s,background .2s}
  .lvp-seat .ls:active{transform:scale(.96)}
  .lvp-seat .ls.lit{border-color:var(--gold);background:#3a312b}
  .lvp-seat .ls-ar{font-family:var(--ar);font-size:76px;color:var(--gold);line-height:1.15}
  .lvp-seat .ls-lab{font-size:14px;font-weight:800;color:var(--muted);margin-top:6px}
  .lvp-seat .ls.lit .ls-lab{color:var(--gold2)}
/* ===== Hub Réviser + onglets icônes (validés 02/07) ===== */
.heartline{background:var(--green-bg);border:1px solid var(--green);border-radius:12px;padding:9px 12px;
  font-size:12.5px;font-weight:800;color:var(--green);margin:0 0 14px;text-align:center;font-family:var(--ui)}
.icontabs{display:flex;gap:6px;margin:0 0 36px} /* 05/09 : la .tip (infobulle, top:calc(100% + 7px)) a besoin de sa place sous les onglets, sinon elle se pose sur le contenu du dessous (Myriam) */
.itab{flex:1;position:relative;background:var(--panel);border:1px solid var(--line);border-radius:14px;
  padding:10px 0;text-align:center;cursor:pointer;font-size:21px;line-height:1}
.itab .itab-ic{height:28px;width:auto;display:block;margin:0 auto}
.itab.active .itab-ic{filter:grayscale(1) invert(1)}
.acc-ic{height:24px;width:auto;vertical-align:-7px}
.itab.active{background:var(--gold);border-color:var(--gold)}
.itab .tip{position:absolute;top:calc(100% + 7px);left:50%;transform:translateX(-50%);
  background:#181310;color:var(--cream);font-size:11.5px;font-weight:800;padding:5px 10px;border-radius:9px;
  border:1px solid var(--line);white-space:nowrap;opacity:0;pointer-events:none;transition:.15s;z-index:20;font-family:var(--ui)}
/* 🔴 L'INFOBULLE S'AFFICHAIT AU SURVOL, ET UN TAP SUR MOBILE LAISSE LE :hover
   COLLÉ — elle ne partait donc jamais (04/09, Myriam). La bascule passe par
   une CLASSE, posée par tipMontre() au changement d'onglet et retirée par un
   setTimeout de 3 s. Le survol reste pour qui a vraiment une souris. */
.itab .tip.on{opacity:1}
@media (hover:hover){ .itab:hover .tip{opacity:1} }
.tablabel{text-align:center;font-family:var(--ui);font-size:12px;font-weight:800;color:var(--gold2);margin:0 0 14px}
.spick{position:relative;margin:8px 0 10px}
.spick .sbtn{display:flex;align-items:center;gap:8px;background:var(--panel2);border:1px solid var(--gold);
  border-radius:12px;padding:9px 12px;font-weight:800;font-size:13px;cursor:pointer;color:var(--cream);font-family:var(--ui)}
.spick .pct{margin-left:auto;color:var(--gold2);font-size:12px}
.smenu{position:absolute;top:calc(100% + 6px);left:0;right:0;background:#2b2420;border:1px solid var(--gold-d);
  border-radius:14px;padding:7px;z-index:30;box-shadow:0 14px 34px rgba(0,0,0,.55);display:none}
.smenu.open{display:block}
.smenu .srow{display:flex;align-items:center;gap:9px;padding:9px 11px;border-radius:10px;
  font-weight:800;font-size:13px;font-family:var(--ui)}
.smenu .srow .sar{font-family:var(--quran);font-size:17px;color:var(--gold)}
.smenu .srow.cur{background:rgba(220,144,46,.16);color:var(--gold2)}
.smenu .srow.lock{color:var(--muted);opacity:.5}
.smenu .srow.lock .sar{color:var(--muted)}
.smenu .shint{font-size:10.5px;color:var(--muted);text-align:center;padding:5px 0 2px;font-family:var(--ui)}
.rex{display:flex;flex-direction:column;gap:7px;margin-top:12px}
.rex .re{background:var(--panel2);border:1px solid var(--line);border-radius:11px;padding:11px 12px;
  font-size:13px;font-weight:800;color:var(--cream);text-align:left;cursor:pointer;font-family:var(--ui)}
.rex .re:active{border-color:var(--gold)}

/* ===== Réviser>Qorān : la grille de 5 boîtes + la popup modale (04/09) =====
   Remplace les 5 accordéons (.racc/.ritem, retirés). Le motif visuel de la
   popup reprend .disc-tip (l. ~173, la bulle de la page d'accueil) : titre
   blanc, gros bouton blanc, fond = --accent de l'unité — MAIS centrée et
   fermable, jamais ancrée sur une boîte (une bulle de 300 px centrée sur une
   boîte de ~90 px sortirait de l'écran sur les boîtes des bords). */
.rq-grille{position:relative;display:flex;flex-wrap:wrap;gap:10px;justify-content:center;margin:14px 0 0}
.rq-boite{flex:0 0 calc((100% - 20px)/3);aspect-ratio:1/1;background:var(--panel);
  border:1px solid var(--line);border-radius:18px;display:flex;flex-direction:column;
  align-items:center;justify-content:center;gap:6px;cursor:pointer;padding:6px 4px;
  transition:border-color .15s, transform .12s}
.rq-boite:active{transform:scale(.96)}
.rq-boite.ouverte{border-color:var(--gold);background:var(--surf-hi,var(--panel2))}
.rq-boite.lock{opacity:.5;cursor:default}
.rq-boite.lock:active{transform:none}
.rq-boite img{width:40%;max-width:44px;height:auto;display:block}
.rq-lab{font-family:var(--ui);font-size:9.5px;font-weight:900;letter-spacing:.04em;
  text-transform:uppercase;color:var(--muted);text-align:center;line-height:1.15}
.rq-boite.ouverte .rq-lab{color:var(--gold2)}
/* 🔴 05/09 — Myriam, EN PRODUCTION sur son iPhone : « la hauteur de la popup
   avec les noms d'Allah est trop grande, je n'arrive plus à cliquer sur la
   croix ». Cause mesurée : `padding:20px` FIXE ne connaît pas l'encoche / l'île
   dynamique — sur `.rq-pop-full` (hauteur 100%), le haut de la popup se pose
   SOUS la zone sûre, et la croix (posée à 6px du haut de la popup) tombe dans
   la même zone. Même piège que `.qsel` (déjà corrigé le 13/08) : le haut doit
   suivre `env(safe-area-inset-top)`, jamais une valeur fixe. */
.rq-voile{position:fixed;inset:0;z-index:80;background:rgba(0,0,0,.55);
  display:flex;align-items:center;justify-content:center;
  padding:max(20px,env(safe-area-inset-top,0px)) 20px max(20px,env(safe-area-inset-bottom,0px));
  animation:rqpin .16s ease}
@keyframes rqpin{from{opacity:0}to{opacity:1}}
.rq-pop{--accent:var(--gold2);position:relative;width:100%;max-width:300px;max-height:100%;
  display:flex;flex-direction:column;overflow-y:auto;background:var(--accent,var(--gold));
  border-radius:18px;padding:18px 16px 16px;text-align:center;box-shadow:0 16px 40px rgba(0,0,0,.55)}
/* 🔴 05/09 — Myriam, correction de son propre chiffre : « je voulais dire
   diminue la hauteur de 20%, une hauteur égale à 80% de celle d'avant » —
   PAS diminuer de 80%. `height:100%` → `height:80%` : la vraie réduction
   demandée, ni le 20% littéral du premier message (mesuré : y faisait
   déborder le bouton APPRENDRE de 6px) ni le 32% choisi entre-temps pour
   compenser. Hauteur en % de `.rq-voile`, qui a une hauteur RÉSOLUE
   (`inset:0`) — pas un vh brut, donc pas le piège habituel de la barre
   d'adresse iOS. */
.rq-pop.rq-pop-full{height:80%;overflow-y:hidden}
.rq-pop .dt-x-btn{position:absolute;top:8px;right:10px;background:none;border:none;font-family:serif;
  font-size:24px;line-height:1;color:#fff;opacity:.85;cursor:pointer;padding:6px 8px;z-index:2}
/* 🔴 05/09 — « les textes sur les popup sont trop petits » ET « pas besoin de
   textes sous les titres ni de préciser la durée : trop de texte tue
   l'information, Duolingo l'a bien compris » (Myriam). `.dt-x` (la phrase
   d'explication) n'est PLUS ÉMISE par boiteTap() — le titre seul suffit,
   il est agrandi en conséquence. La règle CSS reste ici, mais rien ne la
   déclenche plus dans le HTML. */
.rq-pop .dt-t{flex:none;color:#fff;font-weight:900;font-size:20px;line-height:1.3;margin:4px 22px 14px}
.rq-pop .dt-x{flex:none;color:#fff;opacity:.9;font-weight:700;font-size:12.5px;line-height:1.45;margin-bottom:10px}
.rq-pop .dt-go{flex:none;width:100%;background:#fff;border:none;border-radius:12px;padding:14px;
  font-family:var(--ui);font-weight:900;letter-spacing:.05em;color:var(--accent,var(--gold-d));
  cursor:pointer;box-shadow:0 3px 0 rgba(0,0,0,.22);text-transform:uppercase;font-size:15px;margin-top:2px}
.rq-pop .dt-go:disabled{opacity:.5;cursor:default;box-shadow:none}
.rq-parts{display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-bottom:14px}
.rq-parts .rq-part:last-child:nth-child(odd){grid-column:1/-1}
.rq-part{background:rgba(0,0,0,.18);border:1.5px solid transparent;border-radius:10px;padding:9px 10px;
  font-family:var(--ui);font-weight:900;font-size:13.5px;color:#fff;cursor:pointer;line-height:1.3}
.rq-part.on{border-color:#fff;background:rgba(0,0,0,.34)}
.rq-part small{display:block;font-weight:700;opacity:.85;font-size:12px;margin-top:2px}
.rq-noms-compte{flex:none;color:#fff;opacity:.8;font-size:13px;font-weight:800;margin-bottom:8px}
.rq-noms{flex:1 1 auto;min-height:0;overflow-y:auto;margin-bottom:10px;
  border-top:1px solid rgba(255,255,255,.25);border-bottom:1px solid rgba(255,255,255,.25);padding:8px 0}
.rq-nom{display:flex;align-items:center;gap:10px;background:var(--panel);border:1.5px solid transparent;
  border-radius:10px;padding:8px 10px;margin-bottom:6px;cursor:pointer;min-height:40px}
.rq-nom.on{border-color:var(--gold)}
.rq-nom .ww{flex:0 0 auto;font-family:var(--ar);font-size:21px;color:var(--gold);line-height:1.5;
  direction:rtl;white-space:nowrap}
.rq-nom .wfr{flex:1 1 auto;min-width:0;font-size:13px;color:var(--muted);font-weight:700;
  text-align:left;line-height:1.3;direction:ltr}
.rq-nom .ck{flex:0 0 12px;color:var(--gold);font-weight:900;font-size:14px;text-align:center}
/* la sourate illuminée, en plein écran (ex-accordéon « ill »), gabarit .finish
   (comme #surahMenu : class="finish" + un id distinct, m.classList.toggle('on')) */
#lireSourate .fin-x{position:absolute;top:calc(14px + env(safe-area-inset-top,0px));left:14px;background:none;border:none;
  font-family:serif;font-size:24px;color:var(--muted);cursor:pointer;line-height:1;z-index:5} /* 05/09 : à gauche + sous l'encoche, comme .p-close (Myriam : injoignable en haut à droite) */
#lireSourate .lsbody{padding:calc(52px + env(safe-area-inset-top,0px)) 16px 24px;max-width:560px;margin:0 auto;overflow-y:auto;height:100%}
.stslot{display:flex;align-items:center;gap:10px;background:var(--panel);border:2px dashed var(--line);
  border-radius:12px;padding:8px 12px;margin:0 0 7px;min-height:46px}
.stslot.full{border-style:solid;border-color:var(--gold-d)}
.stslot .no{font-family:var(--ui);font-weight:900;color:var(--gold2);width:20px;flex:0 0 auto}
.stslot .txt{font-family:var(--quran);font-size:28px;color:var(--gold);direction:rtl;flex:1;text-align:right;line-height:1.7;font-weight:400}
.sttile.miss{animation:tileshk .32s}
.sttile.hint{border-color:var(--gold);animation:tilehint .9s ease-in-out infinite}
.sttile{display:block;width:100%;background:var(--panel2);border:1px solid var(--line);border-radius:11px;
  padding:9px 12px;margin:0 0 7px;font-family:var(--quran);font-size:17px;color:var(--cream);direction:rtl;
  text-align:right;cursor:pointer;line-height:1.7}
.sttile[disabled]{opacity:.25}

/* ===== Barre de navigation du bas + onglets ===== */
.botnav{position:fixed;left:0;right:0;bottom:0;z-index:40;display:flex;background:var(--panel);
  border-top:1px solid var(--line);padding:6px 4px calc(6px + env(safe-area-inset-bottom,0px))}
.botnav .bn{flex:1;background:none;border:none;cursor:pointer;color:var(--muted);display:flex;
  flex-direction:column;align-items:center;gap:3px;padding:6px 2px;font-family:var(--ui);font-size:11px;font-weight:800;border-radius:12px}
.botnav .bn .bi{font-size:22px;line-height:1;opacity:.8}
.botnav .bn.active{color:var(--gold)}
.botnav .bn.active .bi{opacity:1}
.botnav .bn{flex-direction:row;justify-content:center;gap:0;font-size:0;padding:8px 2px}
.botnav .bn .bi{font-size:30px;opacity:.5;padding:6px 12px;border-radius:14px;transition:opacity .15s,background .15s}
.bn .bni{height:27px;width:auto;display:block;filter:grayscale(1) brightness(.85)}
.bn.active .bni{filter:none}
.botnav .bn.active .bi{opacity:1;background:rgba(220,144,46,.18)}
/* menu des sourates (burger) */
.sm-box{width:min(420px,92vw);background:var(--panel);border:1px solid var(--line);border-radius:18px;padding:20px}
.sm-item{display:flex;align-items:center;gap:12px;width:100%;text-align:left;background:#2a2422;border:1.5px solid var(--line);border-radius:14px;padding:12px 14px;margin-bottom:9px;cursor:pointer;color:var(--cream)}
.sm-item.active{border-color:var(--gold2);background:rgba(232,169,79,.12)}
.sm-item:disabled{opacity:.5;cursor:not-allowed}
.sm-item .sm-ar{font-family:var(--quran);font-size:24px;color:var(--gold)}
.sm-item .sm-tx{flex:1;display:flex;flex-direction:column;min-width:0}
.sm-item .sm-tx b{font-weight:900}.sm-item .sm-tx small{color:var(--muted);font-size:12px}
.sm-item .sm-badge{font-size:16px}
.sm-box{position:relative}
.sm-close{position:absolute;top:12px;right:12px;width:34px;height:34px;border-radius:10px;background:#2a2422;border:1px solid var(--line);color:var(--cream);font-size:16px;font-weight:900;cursor:pointer;z-index:2}
.sm-close:active{transform:scale(.94)}
.sm-list{max-height:66vh;overflow-y:auto;margin-top:26px;padding-right:2px}
.sm-list::-webkit-scrollbar{width:6px}
.sm-list::-webkit-scrollbar-thumb{background:var(--line);border-radius:6px}
.sm-soon{font-size:11px;font-weight:800;color:var(--muted);background:#231e1c;border:1px solid var(--line);border-radius:8px;padding:3px 9px;white-space:nowrap}
.sm-item .sm-no{font-size:11px;font-weight:800;color:var(--muted);min-width:26px}
.view{max-width:520px;margin:0 auto;padding:calc(64px + env(safe-area-inset-top,0px)) 16px 120px;min-height:100vh;min-height:100dvh}
.view h1.vh{font-family:var(--ui);font-size:22px;font-weight:900;color:var(--cream);margin:6px 0 4px}
.view .vsub{color:var(--muted);font-size:13px;font-family:var(--ui);margin:0 0 18px}
.subnav{display:flex;gap:8px;overflow-x:auto;margin:0 -16px 18px;padding:0 16px;scrollbar-width:none}
.subnav::-webkit-scrollbar{display:none}
.subnav .pill{flex:0 0 auto;background:var(--panel);border:1px solid var(--line);color:var(--muted);
  border-radius:999px;padding:8px 16px;font-family:var(--ui);font-weight:800;font-size:13px;cursor:pointer;white-space:nowrap}
.subnav .pill.active{background:var(--gold);border-color:var(--gold);color:#1a1410}
.ccard{background:var(--panel);border:1px solid var(--line);border-radius:18px;padding:16px;margin:0 0 14px}
.ccard .ctt{display:flex;align-items:center;gap:10px;margin:0 0 10px}
.ccard .ctt .cno{width:30px;height:30px;border-radius:9px;background:var(--gold);color:#1a1410;
  font-family:var(--ui);font-weight:900;display:flex;align-items:center;justify-content:center;font-size:15px;flex:0 0 auto}
.ccard .ctt h3{font-family:var(--ui);font-size:17px;font-weight:900;color:var(--cream);margin:0}
.ccard .ctt .clet{margin-left:auto;font-family:var(--ar);font-size:26px;color:var(--gold)}
.gloss{display:flex;flex-direction:column}
.grow{display:flex;align-items:center;gap:12px;padding:9px 2px;border-top:1px dashed var(--line)}
.grow:first-child{border-top:none}
.grow .gemo{font-size:26px;width:32px;text-align:center;flex:0 0 auto}
.grow .gar{font-family:var(--ar);font-size:30px;color:var(--gold);min-width:72px;text-align:right;direction:rtl;flex:0 0 auto}
.grow .gtx{display:flex;flex-direction:column;min-width:0}
.grow .gtx .gtr{font-family:var(--ui);font-weight:800;color:var(--cream);font-size:14px}
.grow .gtx .gfr{font-family:var(--ui);color:var(--muted);font-size:12px}
.grow .gspk{margin-left:auto;background:none;border:none;cursor:pointer;font-size:20px;opacity:.85;flex:0 0 auto}
/* Liste de vocabulaire façon Duolingo : 🔊 · mot + traduction · point « à réviser » */
.wlist{display:flex;flex-direction:column;margin-top:16px}
.wrow{display:flex;align-items:center;gap:14px;padding:11px 2px;border-top:1px solid var(--line)}
.wrow:first-child{border-top:none}
.wspk{flex:0 0 auto;width:42px;height:42px;border-radius:50%;border:none;background:rgba(220,144,46,.13);color:var(--gold);font-size:19px;cursor:pointer;display:grid;place-items:center;
  transition:background .18s,box-shadow .18s,transform .18s}
.wspk:active{transform:scale(.92)}
/* ⚠️ 17/08 — « on doit le voir s'animer ET s'illuminer » (Myriam). Les ondes bougent déjà
   par `.spk.on` ; ici c'est le DISQUE qui s'allume, pour que le geste se voie de loin dans
   une longue liste. Halo doré, jamais de couleur neuve : c'est le même or que le contenu.
   `.on` est retiré par spkOff() à la fin du son. */
.wspk.on{background:rgba(220,144,46,.30);box-shadow:0 0 0 2px var(--gold-d),0 0 14px rgba(232,169,79,.45)}
  .wspk .spk{width:23px;height:16px;color:var(--gold)}
  .grow .gspk .spk{width:24px;height:17px;color:var(--gold)}
.wtx{flex:1;min-width:0}
.wtx .ww{font-family:var(--ar);font-size:24px;color:var(--gold);line-height:1.25}
.wtx .wfr{font-family:var(--ui);font-size:13px;color:var(--muted);margin-top:1px}
/* Le point passe AVANT le crayon et sa place est TOUJOURS réservée : sinon le crayon
   se décale sur les lignes sans point et la colonne des ✏️ se casse. */
.wdot{flex:0 0 auto;width:11px;height:11px;border-radius:50%;background:var(--info)}
.wdot.off{visibility:hidden}
.wpen{flex:0 0 auto;width:36px;height:36px;border-radius:50%;border:none;background:none;
  color:var(--muted);font-size:16px;display:grid;place-items:center;cursor:pointer}
.wpen:active{transform:scale(.92);color:var(--gold)}
/* ===== Vrai ou faux · 45 s (§3.2) — validé par Myriam le 02/08 (variante « dépouillé ») =====
   Ni cœurs (la révision n'en coûte jamais) ni barre de série (le jeu recycle : pas de fin à atteindre). */
#player.vfmode .pbar,#player.vfmode .hearts,#player.vfmode .p-foot{display:none}
#player.vfmode .p-body{display:flex;flex-direction:column;padding:0 0 calc(18px + env(safe-area-inset-bottom,0px));overflow:hidden}
.vf-hd{display:flex;align-items:center;gap:14px;padding:0 22px 7px}
.vf-hd .secs{flex:1;text-align:center;font-size:23px;font-weight:900;color:var(--gold2);font-variant-numeric:tabular-nums}
.vf-hd .secs small{font-size:13px;font-weight:800;color:var(--muted);margin-left:1px}
.vf-hd.low .secs{color:var(--coral)}
.vf-hd .score{font-size:19px;font-weight:900;color:var(--green);font-variant-numeric:tabular-nums;white-space:nowrap}
.vf-hd .score.rec{color:var(--gold2)}
.cbar{height:5px;margin:0 20px;background:var(--panel2);border-radius:3px;overflow:hidden}
.cbar i{display:block;height:100%;width:100%;background:var(--gold2);border-radius:3px;transition:width .25s linear}
.cbar.low i{background:var(--coral)}
.recflash{text-align:center;font-size:11.5px;font-weight:900;color:var(--gold2);letter-spacing:.08em;
  height:15px;margin-top:7px;opacity:0;transition:opacity .3s}
.recflash.on{opacity:1}
.vf-mid{flex:1;display:flex;align-items:center;justify-content:center;padding:10px 22px}
.vfbare{width:100%;text-align:center;padding:18px 0;border-radius:20px;
  border:2px solid transparent;transition:border-color .12s,background .12s}
.vfbare.ok{border-color:var(--green);background:var(--green-bg)}
.vfbare.ko{border-color:var(--coral);background:var(--coral-bg)}
.vfbare .ar{font-family:var(--ar);font-size:36px;color:var(--gold);line-height:1.5;direction:rtl;font-weight:400}
.vfbare .fr{font-size:18px;font-weight:700;color:var(--cream);margin-top:16px;line-height:1.3}
.vf-btns{display:flex;gap:12px;padding:0 22px}
.vfb{flex:1;border:none;border-radius:16px;padding:20px 8px;font-size:19px;font-weight:900;letter-spacing:.03em;
  font-family:var(--ui);cursor:pointer}
.vfb.oui{background:var(--green);box-shadow:0 4px 0 var(--green-d);color:#1b2620}
.vfb.non{background:var(--coral);box-shadow:0 4px 0 var(--coral-d);color:#2a1712}
.vfb:active{transform:translateY(3px);box-shadow:none}
/* ═══ L'ÉCRAN DE RÉCOMPENSE (13/08) — la mascotte danse, puis les 3 cases tombent ═══
   Validé par Myriam : plus de 🎉/🏆, plus d'éloge écrit (« il y a la mascotte qui danse,
   c'est suffisant »), et la monnaie apparaît enfin. */
/* .vf-fin : supprimé le 14/08 avec l'écran de récompense du vrai/faux — la fin de session
   passe désormais par #finish, qui centre déjà en hauteur (reproche de Myriam). */
.cases{display:flex;gap:10px;width:100%;max-width:400px;margin-top:6px}
.case{flex:1;border-radius:16px;padding:2px;opacity:0;transform:scale(.82) translateY(10px);
  animation:casePose .42s cubic-bezier(.28,1.5,.5,1) forwards}
.case:nth-child(1){animation-delay:.55s} .case:nth-child(2){animation-delay:.95s} .case:nth-child(3){animation-delay:1.35s}
@keyframes casePose{to{opacity:1;transform:scale(1) translateY(0)}}
.case-in{background:var(--bg);border-radius:14px;padding:11px 6px 12px;height:100%;
  display:flex;flex-direction:column;align-items:center;gap:5px}
.case .lab{font-size:10.5px;font-weight:900;letter-spacing:.6px;text-transform:uppercase;color:var(--muted)}
/* ⚠️ 14/08, vu sur la capture : « 90 % » se coupait entre le nombre et le signe — la case
   fait 1/3 de 400 px et l'espace typographique du français y devient un point de rupture. */
.case .val{font-size:26px;font-weight:900;font-variant-numeric:tabular-nums;line-height:1;white-space:nowrap}
.case .ic{height:30px;display:grid;place-items:center}
.case .ic svg{height:28px;width:auto;fill:none;stroke:currentColor}
.c-score{background:var(--info-d)} .c-score .val{color:var(--info)} .c-score .ic{color:var(--info)}
.c-reus{background:var(--green-d)} .c-reus .val{color:var(--green)} .c-reus .ic{color:var(--green)}
.c-grain{background:var(--gold-d)} .c-grain .val{color:var(--gold2)} .c-grain .ic{color:var(--gold2)}
/* L'assiduité (14/08) : l'épi, dans le bleu information — c'est un compte, pas une note. */
.c-assid{background:var(--info-d)} .c-assid .val{color:var(--info)} .c-assid .ic{color:var(--info)}
/* Les cases vivent aussi sur #finish, qui centre déjà tout : elles n'ont plus à se recentrer
   elles-mêmes (Myriam 14/08 : « il faut centrer les éléments dans le sens de la hauteur »). */
#finish .cases{margin:14px auto 4px}
.vf-rec{display:inline-flex;align-items:center;gap:8px;margin-top:16px;padding:8px 16px;border-radius:999px;
  background:var(--green-bg);border:1.5px solid var(--green-d);color:var(--green);font-size:13px;font-weight:800;
  opacity:0;animation:casePose .5s 1.75s ease-out forwards}

/* ===== Le stylo ✏️ (§3.4) : entraînement libre — aucun palier, aucun cœur =====
   Il ne juge pas, il guide : la mauvaise tuile est REFUSÉE (elle ne s'inscrit jamais, on
   n'affiche donc jamais une graphie arabe fausse), et au 2e essai raté sur la même lettre
   la bonne tuile respire en doré. Réglage « refus + indice », choisi par Myriam le 02/08. */
.pen-box{width:min(420px,92vw);background:var(--panel);border:1px solid var(--line);border-radius:18px;padding:22px 18px 18px;position:relative}
.pen-x{position:absolute;top:8px;right:12px;background:none;border:none;color:var(--muted);font-size:20px;cursor:pointer}
.pen-fr{text-align:center;font-size:19px;font-weight:800;margin:2px 0 12px;color:var(--cream)}
.pen-zone{direction:rtl;font-family:var(--ar);font-size:52px;color:var(--cream);text-align:center;min-height:96px;
  display:flex;align-items:center;justify-content:center;line-height:1.4;transition:color .15s}
.pen-zone .ph{color:var(--lock,#5A4F47)}
.pen-zone.ok{color:var(--green)}
.pen-zone.ko{color:var(--coral)}
.pen-tiles{display:flex;gap:10px;justify-content:center;flex-wrap:wrap;direction:rtl;margin-top:6px}
.pen-t{background:var(--panel2);border:2px solid var(--line);border-radius:14px;
  min-width:56px;padding:8px 12px;font-family:var(--ar);font-size:30px;color:var(--cream);line-height:1.2;cursor:pointer}
.pen-t[disabled]{opacity:.25}
/* Le clavier du stylo ✏️ suit la même règle que celui des leçons (14/08) : le signe est
   l'information, il ne peut pas être à la fois le plus petit et le plus pâle. */
.pen-t.htile{font-size:26px}
.pen-t.htile .dc{font-size:36px;opacity:1;-webkit-text-stroke:.5px currentColor;font-weight:400}
.pen-t.tdel{font-family:var(--ui);font-size:20px;color:var(--muted)}
.pen-t.shake{border-color:var(--coral);background:var(--coral-bg);color:var(--coral);animation:penshake .35s}
.pen-t.hint{animation:penhint 1.1s ease-in-out infinite;border-color:var(--gold-d)}
@keyframes penshake{0%,100%{transform:translateX(0)}25%{transform:translateX(-5px)}75%{transform:translateX(5px)}}
@keyframes penhint{0%,100%{box-shadow:0 0 0 0 rgba(232,169,79,0)}50%{box-shadow:0 0 0 7px rgba(232,169,79,.26)}}
@media (prefers-reduced-motion:reduce){.pen-t.shake,.pen-t.hint,.srcL.invite,.fourc.invite{animation:none}}
.pen-btns{display:flex;gap:9px;margin-top:16px}
.pen-btns button{flex:1;border:2px solid var(--line);background:var(--panel2);
  border-radius:13px;padding:12px 8px;font-weight:900;font-size:13.5px;font-family:var(--ui);color:var(--cream);cursor:pointer}
.pen-btns button.prim{background:var(--gold);border-color:var(--gold-d);color:#241f1d}
/* ===== Les noms d'Allah (13/07) : sélection, nom illuminé, cartes retournées, touche ⌫ ===== */
.nrow{cursor:pointer;border-radius:12px}
.nrow.nsel{background:#3d3120}
.ncoche{flex:0 0 auto;margin-left:auto;width:26px;height:26px;border-radius:50%;border:2px solid var(--line);display:grid;place-items:center;font-size:14px;color:var(--bg)}
.nrow.nsel .ncoche{background:var(--gold);border-color:var(--gold)}
.revbtn.noff{background:var(--panel2);color:var(--muted)}
.lumwrap{display:flex;flex-direction:column;gap:12px;margin-top:10px}
.lum{border:1px solid #6b5636;border-radius:18px;padding:20px 12px;text-align:center;cursor:pointer;opacity:.42;
  background:linear-gradient(180deg,#2e2620,#292019);transition:opacity .3s,box-shadow .3s,border-color .3s}
.lum .lnar{font-size:42px;display:block;line-height:1.6;font-family:var(--ar);color:var(--gold2)}
.lum .lnfr{font-size:13px;color:var(--muted);font-weight:800}
.lum.on{opacity:1;border-color:var(--gold);box-shadow:0 0 26px rgba(217,164,65,.28),inset 0 0 18px rgba(217,164,65,.07)}
.lum.on .lnar{text-shadow:0 0 18px rgba(244,208,137,.55)}
.opts.flipcol{display:flex;flex-direction:column;gap:11px}
.opt.fopt{perspective:700px;height:64px;padding:0;background:transparent;border:none;position:relative}
.opt.fopt .finner{position:absolute;inset:0;transition:transform .45s;transform-style:preserve-3d;display:block}
.opt.fopt.vu .finner{transform:rotateY(180deg)}
.opt.fopt .fface{position:absolute;inset:0;backface-visibility:hidden;border:1.5px solid var(--line);border-radius:14px;
  display:grid;place-items:center;font-weight:700;padding:4px}
.opt.fopt .fdos{background:var(--panel2);color:var(--gold);font-size:26px;font-family:var(--ar)}
.opt.fopt .fdevant{background:var(--panel);transform:rotateY(180deg)}
.opt.fopt.sel .fdevant{border-color:var(--gold);background:#3d3120}
.opt.fopt.ok .fdevant{border-color:#35a468;background:#26302a}
.opt.fopt.bad .fdevant{border-color:#d8463a}
.wtile{background:var(--panel);border:2px solid var(--line);border-radius:14px;
  /* 🔴 LA HAUTEUR SUIT LA POLICE (01/09). La boite etait calee sur 24px ;
     a 36px une ligne de Naskh mesure environ 65px et le mot chevaucherait
     son cadre. Mesure, pas devine : c'est la boite de ligne qui commande. */
  min-width:74px;padding:0 14px;height:72px;font-family:var(--quran);font-size:36px;color:var(--gold);
  display:grid;place-items:center;font-weight:400}
.wtile[disabled]{opacity:.25}
.wtile.miss{animation:tileshk .32s}
.wtile.hint{border-color:var(--gold);color:var(--gold2);animation:tilehint .9s ease-in-out infinite}
.wtile.tdel{color:#e8926d;border-color:#e8926d;background:transparent;font-size:22px;font-family:var(--ui);min-width:64px}
.tile.tdel{color:#e8926d;border-color:#e8926d;background:transparent;font-size:22px;font-family:var(--ui)}
/* ===== Profil (13/07) : compte connecté = fine bande discrète · étiquette TON RANG ===== */
.acct{display:flex;align-items:center;gap:9px;padding:9px 14px;margin:0 0 12px;
  background:var(--panel);border:1px solid var(--line);border-radius:12px;font-family:var(--ui)}
.acct-dot{flex:none;width:8px;height:8px;border-radius:50%;background:#35a468;box-shadow:0 0 6px rgba(53,164,104,.5)}
.acct-mail{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  color:var(--muted);font-size:12.5px;font-weight:700}
.acct-out{flex:none;background:none;border:none;color:var(--muted);font-family:var(--ui);text-transform:uppercase;
  font-size:12px;text-decoration:underline;text-underline-offset:2px;cursor:pointer;padding:2px}
.acct-out:active{color:var(--cream)}
/* Le nom choisi (prénom ou kunya) vit DANS la bande du compte, au-dessus du mail (Myriam 02/08) */
.acct-id{flex:1;min-width:0}
.acct-id b{display:block;font-family:var(--ui);font-size:14.5px;font-weight:900;color:var(--cream);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.acct-id .acct-todo{color:var(--gold2)}
.acct-id small{display:block;font-family:var(--ui);font-size:11.5px;font-weight:700;color:var(--muted);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.acct-pen{flex:none;background:none;border:none;color:var(--muted);font-size:15px;line-height:1;cursor:pointer;padding:2px 4px}
.acct-pen:active{transform:scale(.9)}
.rk-lbl{font-family:var(--ui);font-size:10.5px;font-weight:900;letter-spacing:.14em;color:#241a06;opacity:.72;margin:0 0 2px}/* 🔴 2,19:1 — LA DERNIÈRE DETTE DU MODE SOMBRE, TRANCHÉE PAR MYRIAM LE 17/08 (preview_carte_rang_v1, variante ② : « la carte la plus lisible »). L'encre brune #241a06 était posée sur l'extrémité SOMBRE du dégradé doré. C'est le FOND qui monte en lumière (#6f4b0f→#b07c16), pas le texte : la carte reste la plaque d'or qu'elle a validée. Mesuré au point le plus sombre du dégradé : 2,19 → 4,68:1. */
.lspk{background:none;border:none;cursor:pointer;font-size:14px;opacity:.85;padding:0 2px;vertical-align:middle;line-height:1}
.lspk:active{transform:scale(.9)}
.sgn-card{background:#2a2422;border:1px solid var(--line);border-radius:14px;padding:12px 14px;margin-top:8px}
.sgn-head{font-family:var(--ui);font-weight:800;color:var(--cream);margin-bottom:10px}
.sgn-chips{display:flex;gap:10px;flex-wrap:wrap;margin-bottom:9px}
.chip{display:flex;flex-direction:column;align-items:center;gap:2px;background:#332c28;border:1.5px solid var(--gold-d);border-radius:12px;padding:8px 15px;cursor:pointer;min-width:54px}
.chip:active{background:rgba(220,144,46,.2);border-color:var(--gold2)}
.chip-ar{font-family:var(--ar);font-size:29px;color:var(--gold);line-height:1.1;direction:rtl}
.chip-ro{font-family:var(--ui);font-size:12px;font-weight:800;color:var(--muted)}
.chip.pulse{animation:chippulse .46s ease}
@keyframes chippulse{0%{transform:scale(1)}40%{transform:scale(1.14);background:rgba(220,144,46,.28);border-color:var(--gold2)}100%{transform:scale(1)}}
.sgn-desc{font-family:var(--ui);font-size:13px;color:var(--muted);line-height:1.45}
.gsec-fl{align-self:center;font-family:var(--ui);font-size:19px;font-weight:900;color:var(--muted)}
.gsec-let{font-family:var(--ar);font-size:22px;color:var(--muted);direction:rtl;text-align:center;
  word-spacing:6px;line-height:1.75;background:var(--sunk);border:1px solid var(--line);
  border-radius:12px;padding:9px 10px;margin-bottom:9px}
.gsec-let b{color:var(--gold);font-weight:400}
.gsec-cells{display:flex;gap:6px;justify-content:center;margin-bottom:9px}
.gsec-cells .lg-cell{width:46px;padding:9px 0}
/* La pastille du numéro d'unité dans le hub de grammaire : le calque exact de
   celle des cartes du Cours (.acc .acc-h .cno), qui est ancrée sur son accordéon
   et ne peut donc pas être réemployée telle quelle. */
/* ⚠️ L’ENCRE EST UN TOKEN, JAMAIS UNE COULEUR EN DUR — mon premier jet copiait
   le #1a1410 de .cno et le balayage l’a mesuré à 3,34:1 en mode CLAIR (seuil 4,5) :
   --gold y devient un ambre FONCÉ, et une encre brune posée dessus disparaît.
   --on-gold bascule avec le thème (crème en clair) ; son repli rend le sombre
   identique au pixel près. C’est le piège du token à double rôle, gravé le 13/08. */
.gnum{flex:0 0 auto;width:30px;height:30px;border-radius:9px;background:var(--gold);color:var(--on-gold,#1a1410);
  font-family:var(--ui);font-weight:900;display:flex;align-items:center;justify-content:center;font-size:15px}
.gtt{font-family:var(--ui);font-weight:900;font-size:14.5px;color:var(--cream)}
/* ⚠️ UN SEGMENT ARABE DANS UNE PHRASE FRANÇAISE HÉRITE DES 13 px DU LATIN, et
   le Naskh y devient illisible : c'est le piège du bandeau du ciel (04/09),
   payé ici dans une carte de Cours. La pile --ui porte bien la police arabe
   depuis le 19/08 — c'est la TAILLE qui manque, pas la fonte. */
.sgn-head .ar,.sgn-desc .ar{font-family:var(--ar);font-size:1.32em;color:var(--gold2);line-height:1;vertical-align:-.08em}
.lanim{margin-top:8px}
.la-btn{background:rgba(220,144,46,.12);border:1px solid var(--gold-d);color:var(--gold2);border-radius:9px;padding:5px 12px;font-family:var(--ui);font-weight:800;font-size:12.5px;cursor:pointer}
.la-btn:active{transform:scale(.96)}
.la-stage{display:flex;align-items:center;gap:12px;margin-top:8px}
.la-word{font-family:var(--ar);font-size:40px;color:var(--gold);min-width:74px;text-align:center;direction:rtl;line-height:1}
.la-word.pop{animation:lapop .4s ease}
@keyframes lapop{0%{transform:scale(1)}45%{transform:scale(1.15)}100%{transform:scale(1)}}
.la-l2{display:inline-block;transition:transform .5s cubic-bezier(.4,0,.2,1),opacity .5s ease}
.la-l2.away{transform:translateX(-24px);opacity:.2}
.la-track{flex:1;max-width:120px;height:5px;background:#3a332e;border-radius:3px;overflow:hidden}
.la-bar{height:100%;width:0;background:var(--gold);border-radius:3px;transition:width .5s ease}
.la-ro{font-family:var(--ui);font-weight:800;font-size:15px;color:var(--gold2);min-width:38px}
.lex{font-family:var(--ui);font-size:13px;color:var(--muted);margin-top:5px}
.lex-w{font-family:var(--ar);font-size:20px;color:var(--gold2);cursor:pointer}
.lact{margin-top:7px}
.lact-b{background:rgba(220,144,46,.14);border:1px solid var(--gold-d);color:var(--gold2);border-radius:9px;padding:5px 12px;font-family:var(--ui);font-weight:800;font-size:12.5px;cursor:pointer}
.lact-b:active{transform:scale(.95)}
.revbtn{display:flex;align-items:center;justify-content:center;gap:10px}
.cbtn.revbtn{display:flex} /* 05/09 : .cbtn (défini plus bas, display:block) gagnait la cascade — le gap n'a jamais été actif (Myriam : toujours collé) */
.revcount{display:inline-flex;align-items:center;justify-content:center;width:26px;height:26px;flex:0 0 26px;
  border-radius:50% 50% 50% 4px;transform:rotate(135deg);background:var(--info-d);color:var(--cream);font-family:var(--ui);font-size:12px;font-weight:900;line-height:1} /* 05/09 : forme goutte, pointe en haut (Myriam) ; taille FIXE pour ne pas se déformer à 2 chiffres */
.revcount i{display:inline-block;transform:rotate(-135deg);font-style:normal}
.revhint{text-align:center;font-family:var(--ui);font-size:12px;color:var(--muted);margin:8px 0 0}
/* Succès : grille d'images seules (clic → popup détail) */
.sgrid{display:grid;grid-template-columns:repeat(4,1fr);gap:10px}
.scell{background:var(--panel2);border:1px solid var(--line);border-radius:14px;aspect-ratio:1;display:grid;place-items:center;cursor:pointer;padding:10px;font-size:34px;color:var(--cream);transition:transform .1s}
.scell:active{transform:scale(.93)}
.scell img{width:46px;height:46px;object-fit:contain}
.scell.locked{opacity:.34}
.scell.locked img{filter:grayscale(1)}
.succ-big{position:relative;width:112px;height:112px;margin:2px auto 0;display:grid;place-items:center;font-size:66px}
.succ-big img{width:100px;height:100px;object-fit:contain}
.succ-big.locked{opacity:.4;filter:grayscale(1)}
.succ-big.pop{animation:succpop .55s cubic-bezier(.2,1.5,.45,1)}
@keyframes succpop{0%{transform:scale(.4);opacity:0}55%{transform:scale(1.15)}100%{transform:scale(1);opacity:1}}
.succ-big.pop::after{content:'';position:absolute;inset:-8px;border-radius:50%;pointer-events:none;animation:succglow .7s ease-out forwards}
@keyframes succglow{0%{box-shadow:0 0 0 0 rgba(232,169,79,.55)}100%{box-shadow:0 0 0 42px rgba(232,169,79,0)}}
.succ-stat{font-family:var(--ui);font-weight:800;font-size:13px}
.succ-desc{font-family:var(--ui);font-size:13.5px;color:var(--muted);line-height:1.5;margin:10px 4px 0}
.pcs-top{display:flex;justify-content:space-between;align-items:baseline;font-family:var(--ui);margin-bottom:8px}
.pcs-top b{color:var(--cream);font-size:15px}
.pcs-top span{color:var(--gold2);font-weight:800;font-size:12.5px}
.arw{font-family:var(--ar)}
.rankcard{display:block;width:100%;text-align:left;background:linear-gradient(135deg,#b07c16,#c99320 60%,#d9a52a);border:1px solid var(--gold2);border-radius:16px;padding:12px 14px 14px;cursor:pointer;color:#241a06;margin:0 0 12px;box-shadow:0 6px 16px rgba(0,0,0,.35)}
.rankcard .rk-row{display:flex;align-items:center;gap:14px}
.rankcard:active{transform:scale(.99)}
.rankcard .rk-ar{font-family:var(--quran);font-size:30px;color:#241a06;flex:0 0 auto}
.rankcard .rk-mid{flex:1;min-width:0}
.rankcard .rk-tr{font-family:var(--ui);font-weight:900;font-size:14px;color:#241a06}
.rankcard .rk-next{font-family:var(--ui);font-size:11px;color:#3a2a08;opacity:.9;margin-top:3px}
.rankcard .rk-chev{font-size:24px;color:#241a06;font-weight:900;flex:0 0 auto}
.rankcard .ubar{margin-top:5px;background:rgba(0,0,0,.22)}
.rankcard .ubar i{background:#241a06}
.rankcard .rbar-track{margin:16px 4px 0;height:26px} /* pleine largeur de la box, avec de l'air sous le titre */
.rankcard .rbar-line{background:rgba(36,26,6,.32)}
.rankcard .rbar-fill{background:#241a06}
.rankcard .rbar-dots i{border:1.5px solid rgba(36,26,6,.4)}
.rbar{width:100%;max-width:300px;margin:4px auto 8px}
.rbar-head{display:flex;justify-content:space-between;font-size:11px;color:var(--muted);font-weight:800;margin-bottom:8px;letter-spacing:.03em}
.rbar-track{position:relative;height:28px;margin:0 4px}
.rbar-line{position:absolute;top:12px;left:3%;right:3%;height:3px;background:var(--line);border-radius:3px}
.rbar-fill{position:absolute;top:12px;left:3%;height:3px;background:var(--gold);border-radius:3px;transition:width .4s}
.rbar-dots{position:absolute;inset:0;display:flex;justify-content:space-between;align-items:center}
.rbar-dots i{display:grid;place-items:center;border-radius:50%;font-size:12px}
.rbar-lbl{text-align:center;margin-top:8px}
.rbar-lbl .ar{font-family:var(--quran);font-size:21px;color:var(--gold2);vertical-align:middle}
.rbar-lbl .fr{color:var(--cream);font-weight:800;font-size:13px;vertical-align:middle}
.rbar-lbl .n{color:var(--muted);font-size:12px;vertical-align:middle}
.fin-score{margin:6px 0 18px}
.fin-score .fs-v{display:block;font-size:42px;font-weight:900;color:var(--gold2);line-height:1}
.fin-score .fs-l{color:var(--muted);font-size:13px;font-weight:700}
.rbar-dots i{cursor:pointer}
.rk-big{font-family:var(--quran);font-size:64px;color:var(--gold);line-height:1.15;margin-top:6px}
.rk-stats{font-family:var(--ui);font-size:12.5px;color:var(--muted);margin-top:14px;border-top:1px solid var(--line);padding-top:10px;line-height:1.6}
.lrow{display:flex;align-items:flex-start;gap:14px;padding:12px 2px;border-top:1px dashed var(--line)}
.lrow:first-child{border-top:none}
.lrow .lbig{font-family:var(--ar);font-size:46px;color:var(--gold);line-height:1;min-width:52px;text-align:center;flex:0 0 auto}
.lrow .ltx .ln{font-family:var(--ui);font-weight:900;color:var(--cream);font-size:15px}
.lrow .ltx .ls{font-family:var(--ui);color:var(--gold2);font-size:13px;margin:2px 0}
.lrow .ltx .lm{font-family:var(--ui);color:var(--muted);font-size:12px;line-height:1.4}
.vembed{position:relative;width:100%;aspect-ratio:16/9;border-radius:14px;overflow:hidden;background:#000;border:1px solid var(--line)}
.vembed iframe{position:absolute;inset:0;width:100%;height:100%;border:0}
.vsoon{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;width:100%;
  aspect-ratio:16/9;border-radius:14px;border:1px dashed var(--line);background:var(--panel2);
  color:var(--muted);font-family:var(--ui);font-weight:800;font-size:14px;text-align:center;padding:0 18px}
.vsoon .vic{font-size:34px;opacity:.7}
.pgrid{display:flex;gap:10px;margin:0 0 18px}
/* Quatre cases au lieu de trois (14/08) : elles respirent moins, la valeur reste lisible. */
.pgrid4{gap:7px} .pgrid4 .pstat{padding:13px 3px}
.pgrid4 .pv{font-size:21px} .pgrid4 .pl{font-size:10px;letter-spacing:0}
.pstat{flex:1;background:var(--panel);border:1px solid var(--line);border-radius:16px;padding:14px 6px;text-align:center}
.pstat .pv{font-family:var(--ui);font-size:24px;font-weight:900;color:var(--gold)}
.pstat .pl{font-family:var(--ui);font-size:11px;font-weight:800;color:var(--muted);margin-top:2px;text-transform:uppercase;letter-spacing:.03em}
.ucard{background:var(--panel);border:1px solid var(--line);border-radius:16px;padding:13px 14px;margin:0 0 11px;display:flex;align-items:center;gap:12px}
.ucard .uno{width:32px;height:32px;border-radius:10px;display:flex;align-items:center;justify-content:center;font-family:var(--ui);font-weight:900;font-size:15px;flex:0 0 auto}
.ucard.ok .uno{background:var(--green);color:#0c1f16}
.ucard.cur .uno{background:var(--gold);color:#1a1410}
.ucard.lock .uno{background:var(--lock);color:#cbbfb6}
.ucard .ub{flex:1;min-width:0}
.ucard .ub .utt{font-family:var(--ui);font-weight:900;color:var(--cream);font-size:15px;display:flex;align-items:center;gap:8px}
.ucard .ub .utt .uar{font-family:var(--ar);color:var(--gold);font-size:20px}
.ucard .ub .ust{font-family:var(--ui);font-size:12px;color:var(--muted);margin-top:2px}
.ubar{height:7px;border-radius:99px;background:var(--panel2);overflow:hidden;margin-top:7px}
.ubar i{display:block;height:100%;background:var(--gold);border-radius:99px}
.prm-row{display:flex;align-items:center;justify-content:space-between;width:100%;background:none;border:none;
  border-top:1px solid var(--line);padding:13px 4px;color:var(--cream);font-family:var(--ui);font-size:14.5px;
  font-weight:700;cursor:pointer;text-align:left}
.ccard .prm-row:first-of-type{border-top:none}
/* Une ligne de LECTURE dans une carte de Paramètres (« Version de l’app », 06/09) : le gabarit
   de .prm-row, mais rien ne s'y presse — pas de main, pas de marge de <p>, la valeur en retrait
   et libre de se couper (un nom de BUILD peut être long). */
.prm-row.prm-lit{cursor:default;margin:0}
.prm-row.prm-lit span{color:var(--muted);font-weight:600;font-size:13px;text-align:right;margin-left:12px;overflow-wrap:anywhere}
.prm-sw{width:44px;height:26px;border-radius:13px;background:var(--panel2);border:1px solid var(--line);
  position:relative;transition:background .15s;flex:0 0 auto}
.prm-sw i{position:absolute;top:2px;left:2px;width:20px;height:20px;border-radius:50%;background:var(--muted);transition:left .15s,background .15s}
.prm-sw.on{background:var(--gold-d)}
.prm-sw.on i{left:20px;background:var(--cream)}
.prm-goals{display:flex;gap:8px}
.ecu{position:relative;display:inline-block;flex:0 0 auto}
.ecu img{position:absolute;inset:0;width:100%;height:100%;object-fit:contain}
.ecu i{position:absolute;left:50%;top:47%;transform:translate(-50%,-50%);font-family:var(--ar);
  font-weight:700;color:#3d2405;white-space:nowrap;font-style:normal;line-height:1}
.rk-stats{display:flex;gap:16px;justify-content:center;align-items:center;flex-wrap:wrap}
.rk-stats span{display:inline-flex;align-items:center;gap:6px}
.rk-stats img{height:22px;width:auto}
.ecu-row{display:flex;gap:12px;flex-wrap:wrap;justify-content:center;padding:4px 0 12px;
  border-bottom:1px solid var(--line);margin-bottom:12px}
.ecu-cell{display:flex;flex-direction:column;align-items:center;gap:5px;width:76px}
.ecu-cell span{font-size:9.5px;font-weight:800;color:var(--muted);text-align:center}
.ecu-cell.lk{opacity:.38;filter:grayscale(.7)}
.prm-ic{height:22px;width:auto;vertical-align:-5px;margin-right:3px}
.prm-goal{flex:1;padding:11px 0;border-radius:12px;border:2px solid var(--line);background:var(--panel);
  color:var(--cream);font-family:var(--ui);font-weight:800;font-size:14px;cursor:pointer}
.prm-goal.sel{border-color:var(--gold);background:rgba(220,144,46,.16);color:var(--gold2)}
.cbtn{display:block;width:100%;max-width:340px;margin:8px auto 0;background:var(--gold);color:#1a1410;text-transform:uppercase;
  border:none;border-radius:16px;padding:15px;font-family:var(--ui);font-weight:900;font-size:16px;cursor:pointer}
.cbtn:disabled{filter:grayscale(.85);opacity:.45;cursor:not-allowed}
/* Consentement RGPD : sans case cochée, aucun e-mail ne part (08/08) */
.rgpd-l{display:flex;gap:9px;align-items:flex-start;margin:10px 0 2px;text-align:left;
  font-family:var(--ui);font-size:12.5px;line-height:1.45;color:var(--muted);cursor:pointer}
.rgpd-l input{margin-top:2px;width:17px;height:17px;flex:0 0 auto;accent-color:var(--gold);cursor:pointer}
.rgpd-l a{color:var(--info);font-weight:700}
/* Compte déjà existant : un PANNEAU, plus un toast fugace qu'on rate (08/08) */
.known-box{border:2px solid var(--gold);background:rgba(220,144,46,.13);border-radius:14px;padding:12px 13px;
  font-family:var(--ui);font-size:13px;line-height:1.45;color:var(--cream);margin-bottom:10px;text-align:left}
.known-box b{color:var(--gold2)}
.cempty{text-align:center;color:var(--muted);font-family:var(--ui);padding:40px 20px;font-size:14px}
.cempty .ce-ic{font-size:40px;opacity:.6;margin-bottom:10px}
/* ===== Révision : association de mots (paires) ===== */
.m-done{display:flex;flex-direction:column;gap:8px;margin:0 0 14px}
.m-row{display:flex;align-items:center;gap:10px;background:var(--green-bg);border:1px solid var(--green);border-radius:12px;padding:8px 12px}
.m-row .m-ar{font-family:var(--ar);font-size:28px;color:var(--green);min-width:78px;text-align:right;direction:rtl}
.m-row .m-link{color:var(--green);font-weight:900}
.m-row .m-fr{font-family:var(--ui);font-weight:800;color:var(--cream);font-size:14px;flex:1}
.m-cols{display:flex;gap:12px}
.m-col{flex:1;display:flex;flex-direction:column;gap:10px}
.m-cell{background:var(--panel);border:2px solid var(--line);border-radius:14px;padding:10px;cursor:pointer;
  color:var(--cream);font-family:var(--ui);font-weight:800;font-size:15px;height:74px;display:flex;align-items:center;justify-content:center;text-align:center;line-height:1.2}
.m-col .m-arc{font-family:var(--ar);font-size:30px;color:var(--gold);direction:rtl}
.m-cell.sel{border-color:var(--gold);background:rgba(220,144,46,.16);transform:translateY(-1px)}
.m-cell.bad{border-color:var(--coral);background:var(--coral-bg);animation:mshake .35s}
@keyframes mshake{0%,100%{transform:translateX(0)}25%{transform:translateX(-5px)}75%{transform:translateX(5px)}}
/* ===== Cours : sections déroulantes (accordéon) ===== */
.acc .acc-h{display:flex;align-items:center;gap:10px;width:100%;background:none;border:none;cursor:pointer;padding:0;text-align:left}
.acc .acc-h .cno{width:30px;height:30px;border-radius:9px;background:var(--gold);color:#1a1410;font-family:var(--ui);font-weight:900;display:flex;align-items:center;justify-content:center;font-size:15px;flex:0 0 auto}
.acc .acc-h .acc-tt{font-family:var(--ui);font-size:16px;font-weight:900;color:var(--cream)}
.acc .acc-h .clet{margin-left:auto;font-family:var(--ar);font-size:24px;color:var(--gold)}
/* 17/08 (Myriam : « c'est quoi la police attribuée à Article ? ») — le sujet d'une unité
   sans lettres est un texte MIXTE : « L'article » composait en police ARABE. Le conteneur
   passe en police d'interface, chaque segment arabe garde la sienne. */
.acc .acc-h .clet.csujet,.ccard .ctt .clet.csujet{font-family:var(--ui);font-size:14px;font-weight:800}
.clet .csar{font-family:var(--ar);font-size:20px;vertical-align:-1px}
.acc .acc-h .acc-chev{margin-left:12px;color:var(--muted);font-size:13px;width:14px;text-align:center;flex:0 0 auto}
.acc .acc-b{display:none;margin-top:12px}
.acc.open .acc-b{display:block}
.acc-all{display:block;margin:0 0 12px auto;background:none;border:1px solid var(--line);color:var(--gold2);border-radius:999px;
  padding:7px 15px;font-family:var(--ui);font-weight:800;font-size:12px;cursor:pointer}
/* ============================================================
   MODE ORDINATEUR ET TABLETTE — 3 colonnes plein écran
   Le basculement se lit en LARGEUR DE FENÊTRE, jamais en type d'appareil :
   dès 700px de large, on passe en 3 colonnes. Cela couvre l'iPad en portrait
   (744 à 834px), l'iPad en paysage, la fenêtre d'ordinateur non maximisée,
   et le téléphone COUCHÉ (iPhone paysage = 844 à 932px de large) — choix de
   Myriam le 02/08 : couché, le téléphone est plus large qu'un iPad debout.
   Deux paliers de largeur : rails compacts sur tablette, larges sur ordinateur.
   Un troisième palier allège les marges quand la fenêtre est BASSE (< 520px).
   N'altère pas le téléphone debout : tout est sous min-width:700px.
   ============================================================ */
.deskbrand, .botnav .bn-lab, .deskrail{ display:none; }

@media (min-width:700px){
  /* Palier TABLETTE (valeurs par défaut) — l'ordinateur les élargit plus bas. */
  :root{
    --rail-l:170px; --rail-r:228px; --nav-gap:10px; --nav-pad:12px;
    --brand-fs:18px; --lab-fs:10.5px; --dr-pad:14px; --nom-fs:30px;
    --view-pad:24px 18px 56px;
  }
  body{ background:var(--bg); }
  .topbar{ display:none; }

  /* ---------- MENU GAUCHE (la botnav devient verticale) ---------- */
  .botnav{
    top:0; bottom:0; left:0; right:auto; width:var(--rail-l); max-width:none; margin:0; overflow-y:auto;
    flex-direction:column; justify-content:flex-start; align-items:stretch; gap:4px;
    padding:20px 14px; background:var(--bg); box-shadow:inset -1px 0 0 var(--line);
  }
  .deskbrand{
    display:flex; align-items:center; gap:10px; font-weight:900; font-size:var(--brand-fs);
    color:var(--gold2); padding:4px 12px 20px; letter-spacing:.02em;
  }
  .deskbrand .dl{ font-size:26px; line-height:1; }
  .deskbrand .dlg{ width:26px; height:26px; border-radius:7px; object-fit:cover; border:1px solid var(--line); }
  .botnav .bn{
    flex:0 0 auto; font-size:15px; color:var(--muted); font-weight:800;
    display:flex; flex-direction:row; align-items:center; justify-content:flex-start;
    gap:var(--nav-gap); padding:12px var(--nav-pad); border-radius:14px; transition:background .15s,color .15s;
  }
  .botnav .bn .bi{ font-size:21px; line-height:1; }
  .botnav .bn-lab{ display:inline; font-size:var(--lab-fs); letter-spacing:.05em; text-transform:uppercase; white-space:nowrap; }
  .botnav .bn:hover{ background:var(--panel); color:var(--cream); }
  .botnav .bn.active{ background:var(--panel); color:var(--gold2); }

  /* ---------- CENTRE : la vue active, entre les deux rails ---------- */
  .wrap, .view{ max-width:none; margin:0; padding:var(--view-pad); }
  #home, #view-cours, #view-reviser, #view-prog, #view-params{ margin-left:var(--rail-l); margin-right:var(--rail-r); }
  #home > *, #view-cours > *, #view-reviser > *, #view-prog > *, #view-params > *{
    max-width:560px; margin-left:auto; margin-right:auto;
  }
  .unit-head{ top:16px; }

  /* overlays plein écran : on retire la contrainte « colonne téléphone » (460px) */
  .player, .finish, .onb{ max-width:none; margin:0; left:0; right:0; box-shadow:none; }
  /* …mais le CONTENU reste dans une colonne lisible et centrée : sans cela, la barre
     de progression, les champs, « CONTINUER » et les .ob-opt s'étirent sur toute la
     largeur de l'écran (retour de Myriam le 02/08). Le fond, lui, reste plein écran. */
  .onb-top, .onb-body > .obs{ width:100%; max-width:440px; margin-left:auto; margin-right:auto; }

  /* ---------- COLONNE DROITE ---------- */
  .deskrail{
    display:block; position:fixed; top:0; right:0; bottom:0; width:var(--rail-r); z-index:25;
    overflow-y:auto; padding:var(--dr-pad) calc(var(--dr-pad) + 2px) 44px; background:var(--bg);
    box-shadow:inset 1px 0 0 var(--line);
  }
  .dr-card{ background:var(--panel); border:1px solid var(--line); border-radius:18px; padding:var(--dr-pad); margin-bottom:13px; }
  .dr-h{ font-size:11px; font-weight:900; letter-spacing:.16em; text-transform:uppercase; color:var(--gold-d); margin-bottom:11px; }
  .dr-rank{ display:flex; align-items:center; gap:14px; cursor:pointer; }
  .dr-rank .lamp{ flex:none; display:flex; }
  .dr-rank-ar{ font-family:var(--ar); direction:rtl; font-size:24px; color:var(--gold2); line-height:1.3; }
  .dr-rank-fr{ font-size:12.5px; color:var(--muted); font-weight:700; margin-top:2px; }
  .dr-prog{ height:6px; border-radius:3px; background:var(--panel2); overflow:hidden; margin-top:12px; width:100%; }
  .dr-prog i{ display:block; height:100%; background:var(--gold); border-radius:3px; }
  .dr-stats{ display:flex; gap:12px; margin-bottom:15px; }
  .dr-stats > div{ flex:1; background:var(--panel); border:1px solid var(--line); border-radius:14px; padding:12px 8px; text-align:center; font-weight:900; font-size:17px; color:var(--cream); }
  .dr-stats small{ display:block; font-size:9.5px; font-weight:800; letter-spacing:.14em; text-transform:uppercase; color:var(--muted); margin-top:3px; }
  .dr-nom-ar{ font-family:var(--ar); direction:rtl; font-size:var(--nom-fs); color:var(--gold2); text-align:center; line-height:1.6; text-shadow:0 2px 14px rgba(232,169,79,.25); }
  .dr-nom-fr{ text-align:center; color:var(--muted); font-size:14px; margin-top:6px; }
  .dr-parole-ar{ font-family:var(--ar); direction:rtl; font-size:19px; color:var(--cream); line-height:2.1; text-align:center; }
  .dr-parole-fr{ color:var(--muted); font-size:12.5px; font-style:italic; text-align:center; margin-top:8px; line-height:1.5; }
  .dr-rev-n{ font-size:22px; font-weight:900; color:var(--gold2); }
  .dr-rev-btn{ margin-top:12px; width:100%; background:var(--gold); color:#2a1c08; border:none; border-radius:12px; padding:12px; font-weight:900; font-size:13.5px; letter-spacing:.05em; text-transform:uppercase; cursor:pointer; transition:background .15s; }
  .dr-rev-btn:hover{ background:var(--gold2); }
  /* les stats du panneau droit portent les MÊMES icônes que la barre mobile (10/08) */
  .dr-rank .lant-wrap{ width:46px; height:46px; }
  .dr-rank .lant-wrap .lant{ width:32px; }
  .dr-stx{ display:flex; align-items:center; justify-content:center; gap:6px; }
}

/* Palier ORDINATEUR (≥1024px) : mêmes règles, rails et typographie au large. */
@media (min-width:1024px){
  :root{
    --rail-l:210px; --rail-r:300px; --nav-gap:13px; --nav-pad:15px;
    --brand-fs:22px; --lab-fs:13px; --dr-pad:18px; --nom-fs:36px;
    --view-pad:34px 24px 64px;
  }
}

/* Palier FENÊTRE BASSE : téléphone couché (430px de haut). Trois colonnes aussi,
   mais on récupère la hauteur perdue en marges — le menu de gauche défile au besoin. */
@media (min-width:700px) and (max-height:520px){
  :root{ --view-pad:14px 18px 34px; }
  .botnav{ padding:12px 10px; }
  .deskbrand{ font-size:16px; padding:2px 10px 10px; }
  .botnav .bn{ padding:9px var(--nav-pad); }
  .onb{ padding-top:calc(8px + env(safe-area-inset-top,0px)); padding-bottom:14px; }
}
  /* ── Récitateur : le sélecteur plein écran (le bouton d'accès vit désormais
     UNIQUEMENT dans Paramètres, .prm-row — retiré d'ici le 04/09, il faisait
     doublon) ── */
  .qsel{position:fixed;inset:0;z-index:60;background:var(--bg);display:none;flex-direction:column;
    padding-top:env(safe-area-inset-top,0px)}
  .qsel.on{display:flex}
  .qsel-top{display:flex;align-items:center;gap:12px;padding:16px 20px 10px;flex:none}
  .qsel-top .qx{background:none;border:none;font-size:20px;color:var(--muted);cursor:pointer;line-height:1}
  .qsel-top h3{font-size:17px;font-weight:900}
  .qsel-top .qi{width:22px;height:22px;border-radius:50%;border:1.5px solid var(--info);background:none;
    color:var(--info);font-size:12px;font-weight:900;display:grid;place-items:center;line-height:1;cursor:pointer}
  .qsel-top .qi.on{background:var(--info);color:#1b2529}
  .qbulle{position:absolute;top:calc(46px + env(safe-area-inset-top,0px));left:20px;right:20px;z-index:70;
    padding:11px 13px;border-radius:12px;background:#22323A;border:1px solid #33505E;
    font-size:12.5px;color:#C6D9E2;font-weight:600;box-shadow:0 12px 30px rgba(0,0,0,.5);display:none}
  .qbulle.on{display:block}
  .qbulle:before{content:'';position:absolute;top:-6px;left:118px;width:10px;height:10px;
    background:#22323A;border-left:1px solid #33505E;border-top:1px solid #33505E;transform:rotate(45deg)}
  .qpin{margin:0 14px 4px;padding:9px 12px 11px;border-radius:14px;background:#3A2F26;
    border:2px solid var(--gold-d);display:flex;flex-direction:column;gap:4px;flex:none}
  .qpin .cap{font-size:10px;font-weight:900;letter-spacing:.09em;text-transform:uppercase;color:var(--gold2)}
  .qrow .qhoro{display:block;font-size:10.5px;font-weight:800;color:var(--gold);margin-top:1px}
  .qlist{flex:1;overflow-y:auto;padding:0 14px calc(14px + env(safe-area-inset-bottom,0px))}
  .qgrp{font-size:11px;font-weight:900;letter-spacing:.1em;text-transform:uppercase;color:var(--muted);padding:14px 6px 8px}
  .qgrp em{font-style:normal;color:var(--muted);letter-spacing:0;text-transform:none;font-weight:700}
  .qrow{display:flex;align-items:center;gap:10px;width:100%;text-align:left;background:var(--panel);
    border:2px solid transparent;border-radius:14px;padding:9px 10px 9px 12px;margin-bottom:7px;
    color:var(--cream);font-family:var(--ui);cursor:pointer}
  .qrow.on{border-color:var(--gold-d);background:#3A2F26}
  .qrow .tick{flex:none;width:20px;height:20px;border-radius:50%;border:2px solid var(--line);
    display:grid;place-items:center;font-size:11px;color:#241f1d}
  .qrow.on .tick{background:var(--gold);border-color:var(--gold)}
  .qnm{flex:1;min-width:0}
  .qnm .fr{display:block;font-size:14px;font-weight:800;line-height:1.25;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .qnm .arb{display:block;font-family:var(--ar);direction:rtl;text-align:right;font-size:13.5px;color:var(--muted);line-height:1.7}
  .qsec{flex:none;font-size:12.5px;font-weight:900;color:var(--muted);font-variant-numeric:tabular-nums}
  .qsec em{font-style:normal;font-size:9.5px;font-weight:800;margin-left:1px;color:var(--muted)}
  .qrow.on .qsec{color:var(--gold2)}
  /* 05/09 (retour de Myriam) : la box bordée (émoji ▶ + texte « écouter ») cède la
     place au haut-parleur dessiné, comme partout ailleurs dans l'app (spkSVG) — les
     ondes s'animent pendant la lecture au lieu d'un simple changement de texte. */
  .qhear{flex:none;display:flex;align-items:center;justify-content:center;width:38px;height:36px}
  .qhear .spk{width:26px;height:17px;color:var(--muted)}
  .qrow.play .qhear .spk{color:var(--gold2)}
  .qrow.load .qhear .spk{color:var(--info)}
  .qpin .qrow{background:transparent;border:none;padding:0;margin:0}
  /* la voix choisie est épinglée en haut : elle ne se répète pas dans la liste */
  .qlist .qrow.on{display:none}

/* ══════════════════════════════════════════════════════════════════════════
   CIEL-V1 — la journée de marche.  Tout ce bloc est ajouté EN FIN de feuille :
   il surcharge sans rien réécrire, donc il se retire d'un seul coup si besoin.
   ══════════════════════════════════════════════════════════════════════════ */

/* ---- le décor, fixe derrière l'app, visible sur le seul accueil ---- */
#skyWrap{position:fixed;inset:0;z-index:0;pointer-events:none;opacity:0;transition:opacity .45s ease;overflow:hidden}
body.ciel #skyWrap{opacity:1}
#skyBg{position:absolute;inset:0}
#skyStars{position:absolute;left:0;right:0;top:0;bottom:24%;transition:opacity .8s}
#skyStars i{position:absolute;border-radius:50%;background:#EFE6D2;animation:ctw 3.4s ease-in-out infinite}
@keyframes ctw{0%,100%{opacity:.95}50%{opacity:.25}}
#skySun{position:absolute;transform:translate(-50%,-50%);border-radius:50%}
#skyMoon{position:absolute;top:104px;right:26px;width:26px;height:26px;opacity:0;transition:opacity .8s;
  filter:drop-shadow(0 0 10px rgba(239,230,207,.35))}
/* les collines se peignent APRÈS le soleil : il se lève derrière elles et s'y couche */
/* ⚠️ à bottom:0 la crête des dunes tombait DERRIÈRE la barre du bas (62 px +
   safe-area) : sur iPhone on ne voyait plus que le ciel, et la caravane posée
   à une hauteur fixe semblait flotter. Les dunes remontent, et la caravane
   n'est plus posée « à peu près » mais SUR la crête, mesurée. */
#skyDunes{position:absolute;left:0;right:0;bottom:56px;width:100%;
  height:min(240px,30vh);display:block}
#skyDunes path{transition:none}
#skyCarav{position:absolute;width:46px;height:auto;z-index:1;animation:cmarche 1.9s ease-in-out infinite} /* z-index:1 : il passe DEVANT dunes et feu pendant la traversée */
#skyCarav,#skyCamp,#skyFire{bottom:auto}
#skyCarav.arrive{animation:none}
#skyCarav{transform:scaleX(-1)} /* il marche vers la gauche */
@keyframes cmarche{0%,100%{transform:translateY(0) scaleX(-1)}50%{transform:translateY(-2.5px) scaleX(-1)}}
/* la lueur était plus large que la marge droite : son halo se coupait net
   sur le bord de l'écran. Elle rentre, et le campement recule avec elle.
   ⚠️ centré sur le bord BAS (at 50% 100%), le dégradé était à son maximum là où
   la boîte s'arrête : ligne horizontale dure au ras des flammes. Le centre rentre
   au milieu et les rayons s'éteignent (72 % de 46 %) AVANT chaque bord. */
#skyFire{position:absolute;right:10px;width:150px;height:104px;opacity:0;
  background:radial-gradient(52% 46% at 50% 50%,rgba(235,140,66,.5),rgba(235,140,66,0) 72%)}
#skyCamp{position:absolute;right:56px;width:58px;height:49px;opacity:0}
#skyCamp .fl{transform-origin:60px 86px}
#skyCamp .f1{animation:cfl1 1.15s ease-in-out infinite}
#skyCamp .f2{animation:cfl2 .78s ease-in-out infinite}
#skyCamp .f3{animation:cfl3 .52s ease-in-out infinite}
@keyframes cfl1{0%,100%{transform:scale(1,1) rotate(0)}30%{transform:scale(.93,1.09) rotate(-2.5deg)}
  65%{transform:scale(1.07,.94) rotate(2deg)}}
@keyframes cfl2{0%,100%{transform:scale(1,1) rotate(1.2deg)}45%{transform:scale(1.09,.9) rotate(-3deg)}}
@keyframes cfl3{0%,100%{transform:scale(1,.95)}50%{transform:scale(.88,1.12)}}
#skyCamp .braise{animation:cbraise 1.6s ease-in-out infinite}
@keyframes cbraise{0%,100%{opacity:.45}50%{opacity:.9}}
/* le contenu passe DEVANT le décor */
body.ciel .wrap{position:relative;z-index:1}
/* la barre du haut est transparente : sans ce voile aux couleurs de l'heure,
   les chiffres deviennent illisibles sur le ciel clair de midi */
body.ciel .topbar{background:linear-gradient(180deg,var(--ciel-scrim) 0%,var(--ciel-scrim) 64%,transparent 100%)}
body.ciel .topbar .stats,body.ciel .topbar .stat{color:var(--ciel-ink)}
/* ⚠️ renderHome() pose --accent en style INLINE (sec.style.setProperty) : seul
   !important peut le couvrir. Les 7 accents arc-en-ciel cèdent la place à la
   lumière de l'heure — à 12 unités, le modulo 7 les ferait de toute façon se répéter. */
body.ciel .unit-sec{--accent:var(--gold2) !important}
body.ciel .unit-head{--accent:var(--gold2) !important}
body.ciel .unit-sep{color:var(--ciel-soft)}
body.ciel .unit-sep::before,body.ciel .unit-sep::after{background:var(--ciel-soft);opacity:.5}
.tbic{height:19px;width:auto;display:block;object-fit:contain}

/* ---- les pièces : une ELLIPSE de rapport 1,23, comme celles de Duolingo ---- */
.bwrap{width:80px;height:65px}
.bubble{width:80px;height:65px;position:relative;overflow:hidden;
  transition:box-shadow .16s linear}
/* le reflet du dessus : c'est lui, plus que la forme, qui fait lire le volume */
.bubble::before{content:'';position:absolute;left:10%;right:10%;top:5%;height:44%;border-radius:50%;
  background:linear-gradient(180deg,rgba(255,255,255,.5),rgba(255,255,255,.06) 62%,rgba(255,255,255,0));
  pointer-events:none;z-index:2}
.locked .bubble::before{background:linear-gradient(180deg,rgba(255,255,255,.18),rgba(255,255,255,0) 70%)}
.bimg{width:40px;height:40px;position:relative;z-index:1}
.path{gap:30px}
/* deux ombres distinctes : l'ÉPAISSEUR de la pièce (fixe) et l'OMBRE PORTÉE par
   le soleil (mobile). Les confondre ferait basculer la pièce. */
.done .bubble{box-shadow:0 8px 0 var(--accent,var(--gold-d)),
  var(--ciel-shx,0px) var(--ciel-shy,4px) var(--ciel-shb,10px) rgba(0,0,0,var(--ciel-sha,.22))}
.current .bubble{box-shadow:0 8px 0 var(--gold-d),0 0 0 5px color-mix(in srgb,var(--accent,var(--gold2)) 42%,transparent),
  var(--ciel-shx,0px) var(--ciel-shy,4px) var(--ciel-shb,10px) rgba(0,0,0,var(--ciel-sha,.22))}
.locked .bubble{box-shadow:0 8px 0 #2c2521,
  var(--ciel-shx,0px) var(--ciel-shy,4px) var(--ciel-shb,10px) rgba(0,0,0,var(--ciel-sha,.22))}
.jump .bubble{box-shadow:0 8px 0 color-mix(in srgb,var(--accent,var(--gold)) 45%,#000),
  var(--ciel-shx,0px) var(--ciel-shy,4px) var(--ciel-shb,10px) rgba(0,0,0,var(--ciel-sha,.22))}
/* ═══ 14/08 — LE RELIEF DU DISQUE TERMINÉ ÉTAIT À L'ENVERS (Myriam) ═══
   « Il faut inverser les couleurs : le dessus doit être plus clair que le rebord pour donner
   une impression d'ombre, comme tu l'as justement fait pour les disques grisés. »
   Mesuré, elle a raison, et sur CE disque-là seulement :
     terminé    dessus L=0,354  rebord L=0,461  ← le rebord était le plus CLAIR
     courant    dessus L=0,647  rebord L=0,226  ✓
     verrouillé dessus L=0,036  rebord L=0,020  ✓  (sa référence)
   La cause : le dessus prend `--gold` (#DC902E, l'or SOMBRE) et le rebord prend `--accent`,
   que le ciel force à `--gold2` (#E8A94F, l'or CLAIR). La lumière semblait venir d'en bas.
   ⚠️ On ne touche PAS à `--accent` : il porte aussi l'auréole du disque courant et le disque
   « AVANCER ICI ? », pour lesquels l'or clair a été choisi exprès le 13/08 (repérabilité sur
   la nuit). On écrit donc le relief du disque terminé en toutes lettres — dessus l'or clair,
   rebord l'or foncé. Rapport final 0,461 / 0,226 = 2,0× : une vraie ombre, pas un dégradé. */
body.ciel .done .bubble{background:var(--gold2)}
body.ciel .done .bubble{box-shadow:0 8px 0 var(--gold-d),
  var(--ciel-shx,0px) var(--ciel-shy,4px) var(--ciel-shb,10px) rgba(0,0,0,var(--ciel-sha,.22))}

/* un halo CONIQUE tourne mal sur une ellipse : il y accélère dans les petits
   rayons. On pulse — l'onde épouse n'importe quelle forme. */
.current .ring{inset:-7px;border:2.5px solid var(--accent,#f4d089);border-radius:50%;
  background:none;-webkit-mask:none;mask:none;animation:cpulse 2.3s cubic-bezier(.2,.6,.3,1) infinite}
@keyframes cpulse{0%{transform:scale(.96);opacity:.9}65%{transform:scale(1.26);opacity:0}
  100%{transform:scale(1.26);opacity:0}}

/* ---- la barre du bas : les icônes gardent LEUR couleur ---- */
/* l'onglet actif est désigné par une pastille et un trait — des repères de forme,
   qui survivent au daltonisme et au plein soleil, contrairement à une désaturation */
.bn .bni{filter:none;opacity:.72;transition:opacity .18s ease,transform .18s ease}
.bn.active .bni{opacity:1;transform:translateY(-1px) scale(1.06)}
.botnav .bn .bi{position:relative;opacity:1}
.botnav .bn.active .bi{background:rgba(220,144,46,.20);box-shadow:inset 0 0 0 1.5px rgba(232,169,79,.65)}
.botnav .bn.active .bi::after{content:'';position:absolute;left:50%;bottom:1px;transform:translateX(-50%);
  width:16px;height:2.5px;border-radius:2px;background:var(--gold2)}

@media (prefers-reduced-motion: reduce){
  #skyStars i,#skyCamp .fl,#skyCamp .braise,#skyCarav,.current .ring{animation:none}
  #skyWrap,#skyStars,#skyMoon,.bubble{transition:none}
}

/* ---- ordinateur/tablette (10/08) : le décor vit ENTRE les rails, pas sous eux ----
   #skyWrap couvrait tout l'écran : les rails opaques recouvraient le feu (right:10px),
   la lune (right:26px) et le soleil couchant (x en % de la largeur TOTALE) — et la dune
   gardait les 56 px réservés à une barre du bas qui n'existe pas en trois colonnes.
   Recadré entre les rails, tous les % redeviennent justes d'un coup. */
@media (min-width:700px){
  #skyWrap{left:var(--rail-l);right:var(--rail-r)}
  #skyDunes{bottom:0}
  /* 10/08, retours de Myriam : à 58 px dans une colonne de ~1400, le crépitement des
     flammes était invisible, et le halo mourait contre le rail droit opaque. Le campement
     grandit et s'éloigne du bord — le halo entier respire dans la colonne. */
  #skyCamp{right:96px;width:88px;height:74px}
  #skyFire{right:36px;width:230px;height:158px}
}


/* ══════════════════════════════════════════════════════════════════════════
   CIEL-V2 — le bandeau à deux lignes, le sommaire, la lanterne, le portail.
   Ajouté en fin de feuille comme le lot 1 : rien n'est réécrit.
   ══════════════════════════════════════════════════════════════════════════ */

/* ---- la lanterne du rang : l'icône est fixe, le HALO porte la couleur ---- */
.lant-wrap{position:relative;display:flex;align-items:center;justify-content:center;
  width:26px;height:26px}
.lant-wrap::before{content:'';position:absolute;inset:-7px;border-radius:50%;
  background:radial-gradient(circle,var(--rangc,#DC902E) 0%,rgba(0,0,0,0) 68%);opacity:.6}
.lant-wrap .lant{width:21px;height:auto;display:block;position:relative;z-index:1}

/* ---- le bandeau : deux lignes, plus haut, police x1,2 ---- */
body.ciel .unit-head{padding:15px 15px;border-radius:18px}
body.ciel .unit-head .uh-top{font-size:12.6px;letter-spacing:.07em;opacity:.9}
body.ciel .unit-head h2{font-size:15.6px;line-height:1.35;margin-top:5px}
body.ciel .unit-head .uh-let{font-size:20.4px}
body.ciel .unit-head .uh-sub2{display:none}   /* la 3e ligne tombe : deux lignes suffisent */
/* le parchemin remplace le burger : c'est un sommaire, pas un menu système */
body.ciel .unit-head .uh-burger{width:44px;height:44px;border-radius:13px;padding:0;
  display:grid;place-items:center;background:rgba(0,0,0,.22);font-size:0}
body.ciel .unit-head .uh-burger img{width:26px;height:26px;object-fit:contain;display:block}

/* ---- le sommaire de la journée ---- */
#sommCiel{position:fixed;inset:0;z-index:70;display:none}
#sommCiel.on{display:block}
#sommCiel .sc-bg{position:absolute;inset:0;background:rgba(8,6,4,.62);
  -webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px)}
#sommCiel .sc-in{position:absolute;left:50%;transform:translateX(-50%);bottom:0;width:min(520px,100%);
  max-height:82%;overflow-y:auto;background:#1B1510;border-radius:22px 22px 0 0;
  border-top:1px solid rgba(220,144,46,.4);padding:14px 12px calc(24px + env(safe-area-inset-bottom,0px));
  animation:scup .26s ease}
@keyframes scup{from{transform:translate(-50%,30px);opacity:0}to{transform:translate(-50%,0);opacity:1}}
#sommCiel .sc-h{display:flex;align-items:center;justify-content:space-between;margin:0 6px 8px}
/* le triangle est À GAUCHE du nom : c'est lui qui dit « ceci se déplie ».
   Un chevron à droite se lit « on va ailleurs », pas « menu ». */
#sommCiel .sc-t{background:none;border:none;font-family:var(--ui);font-size:10.5px;letter-spacing:.24em;
  font-weight:900;color:var(--gold2);cursor:pointer;padding:5px 2px;display:flex;align-items:center;gap:8px}
#sommCiel .sc-t .tri{font-size:12px;letter-spacing:0}
#sommCiel .sc-x{background:none;border:none;color:#9C8E76;font-size:19px;cursor:pointer;padding:2px 8px}
#sommCiel .srow{display:flex;align-items:center;gap:12px;width:100%;background:none;border:none;
  cursor:pointer;padding:10px 8px;border-radius:13px;text-align:left;font-family:var(--ui)}
#sommCiel .srow .sc-m{position:relative;width:38px;height:38px;flex:none;display:grid;place-items:center}
#sommCiel .srow .sc-m svg{position:absolute;inset:0;width:100%;height:100%}
#sommCiel .srow .sc-m b{position:relative;font-size:12px;font-weight:900;color:var(--gold2);line-height:1}
#sommCiel .srow.fait .sc-m b{color:#241703}
#sommCiel .srow.off .sc-m b{color:#6E6455}
#sommCiel .srow .sc-x1{flex:1;min-width:0;font-size:12.5px;font-weight:900;color:var(--cream)}
#sommCiel .srow .sc-x1 .ar{font-family:var(--ar);font-size:14.5px;color:var(--gold2)}
#sommCiel .srow .sc-e{flex:none;font-size:10px;font-weight:900;letter-spacing:.06em;color:var(--muted)}
#sommCiel .srow.fait .sc-e{color:var(--gold2)}
#sommCiel .srow.ici{background:rgba(220,144,46,.15);box-shadow:inset 0 0 0 1px rgba(220,144,46,.5)}
#sommCiel .sc-sep{margin:10px 8px 4px;font-size:8.5px;letter-spacing:.26em;font-weight:900;color:var(--muted)}
#sommCiel .cnum{flex:none;width:38px;height:38px;border-radius:12px;display:grid;place-items:center;
  background:rgba(220,144,46,.13);color:var(--gold2);font-size:12px;font-weight:900}
#sommCiel .srow.ici .cnum{background:var(--gold);color:#241703}

/* ---- le portail de fin de sourate ---- */
#portail{margin:20px auto 32px;text-align:center;cursor:pointer;-webkit-user-select:none;user-select:none;
  filter:drop-shadow(0 14px 24px rgba(0,0,0,.5))}
#portail .pt-cadre{position:relative;width:88px;margin:0 auto;padding:8px 7px 7px;
  border-radius:60px 60px 13px 13px;
  background:linear-gradient(178deg,#4A3416 0%,#2E1F0C 58%,#1E1408 100%);
  box-shadow:inset 0 0 0 2.4px var(--gold),inset 0 0 0 6px rgba(20,12,4,.9),
             inset 0 0 0 7.4px rgba(220,144,46,.45)}
#portail .pt-jour{position:relative;width:74px;height:99px;margin:0 auto;overflow:hidden;
  border-radius:37px 37px 5px 5px;background:#0E0904;perspective:420px}
#portail .pt-clarte{position:absolute;inset:0;opacity:0;transition:opacity 1s .3s;
  background:radial-gradient(74% 62% at 50% 80%,#FFF3D2 0%,#F0B75A 36%,rgba(220,144,46,0) 80%)}
#portail .pt-v{position:absolute;top:0;bottom:0;width:50%;background-color:#C07E12;
  background-image:var(--im-porte,url('images-app-alaq/icone-porte-v1.png'));background-size:74px auto;
  background-repeat:no-repeat;transition:transform .9s cubic-bezier(.35,.02,.2,1)}
#portail .pt-v.g{left:0;transform-origin:left center;background-position:left top}
#portail .pt-v.d{right:0;transform-origin:right center;background-position:right top}
#portail.ouvert .pt-v.g{transform:rotateY(-102deg)}
#portail.ouvert .pt-v.d{transform:rotateY(102deg)}
#portail.ouvert .pt-clarte{opacity:1}
#portail .pt-seuil{width:71px;height:5px;margin:0 auto;border-radius:0 0 4px 4px;
  background:linear-gradient(180deg,#8A5A16,#3A2610)}
/* verrouillé : la porte est là, on voit qu'elle attend, on ne peut pas l'ouvrir */
#portail.verrouille{filter:grayscale(.9) brightness(.5);cursor:default;opacity:.85;pointer-events:none}
/* l'entrée dans l'histoire : la lumière de la porte envahit l'écran */
#entreeHalte{position:fixed;inset:0;z-index:80;display:none;flex-direction:column;
  align-items:center;justify-content:center;text-align:center;padding:0 28px;
  background:radial-gradient(90% 70% at 50% 62%,#FFF3D2 0%,#F4D89C 30%,#EDBE72 62%,#C98F2E 100%)}
#entreeHalte.on{display:flex;animation:enthalte 1.15s cubic-bezier(.4,0,.2,1) forwards}
@keyframes enthalte{from{clip-path:circle(7% at 50% 76%);opacity:.35}
  to{clip-path:circle(140% at 50% 50%);opacity:1}}
#entreeHalte .eh-k{font-size:9.5px;letter-spacing:.34em;font-weight:900;color:#7A5514}
#entreeHalte .eh-t{font-family:var(--ui);font-weight:900;font-size:23px;color:#2E2314;margin-top:10px}
#entreeHalte .eh-s{font-size:11.5px;color:#6E5A33;margin-top:9px;font-weight:700}
#entreeHalte .eh-n{font-size:11px;color:#7A6540;margin-top:22px;font-style:italic;max-width:280px;line-height:1.6}
#entreeHalte .eh-x{position:absolute;top:calc(16px + env(safe-area-inset-top,0px));right:16px;
  background:rgba(46,35,20,.14);border:none;width:38px;height:38px;border-radius:50%;
  color:#2E2314;font-size:17px;cursor:pointer}
@media (prefers-reduced-motion: reduce){
  #sommCiel .sc-in,#entreeHalte.on{animation:none}
  #portail .pt-v,#portail .pt-clarte{transition:none}
}


/* ══════════════════════════════════════════════════════════════════════════
   ACCESSIBILITÉ (13/08/2026) — demandé par Myriam pour son mari.
   Trois feuilles, posées par les classes `clair`, `gros` et `gtexte` sur <html>
   (jamais sur l'élément body : le réglage doit s'appliquer AVANT le premier affichage,
   sinon l'app clignote en sombre au lancement).
   ══════════════════════════════════════════════════════════════════════════ */
/* ═══════════════════════════════════════════════════════════════════════════
   ALAQ — MODE CLAIR (13/08/2026)
   Demandé par Myriam pour son mari : déchirure de la rétine, taches sombres,
   vision réduite. Tout est calculé pour le CONTRASTE, pas pour l'esthétique.

   L'app est tokenisée à 83 % (977 `var(--…)` contre 154 règles en dur) : le
   thème redéfinit les tokens, puis rattrape les 154 règles restantes, groupées
   en familles. Rien n'est déplacé, aucune taille ne change : seules les
   couleurs basculent.

   ⚠️ Le CIEL de l'accueil (dunes, feu, portail, sommaire) N'EST PAS retouché :
   c'est une illustration qui suit déjà l'heure du jour, pas de la chrome.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── LES TOKENS ─────────────────────────────────────────────────────────────
   Contrastes mesurés (WCAG) : texte/fond 14,8:1 · discret/fond 6,5:1 ·
   or/fond 4,9:1 · encre sur bouton doré 5,2:1 · bordures 3,1:1.
   Le SOMBRE actuel donne 13,2 / 7,0 / 6,1 — le clair est donc au moins aussi
   lisible, et sans halo lumineux autour des lettres claires sur fond sombre
   (l'« irradiation », qui gêne beaucoup une rétine abîmée). */
html.clair{
  --bg:#F7F1E4;         /* parchemin : moins éblouissant qu'un blanc pur */
  --panel:#FFFFFF;
  --panel2:#F0E7D6;
  --line:#8A7A5E;       /* 3,1:1 sur blanc — une bordure doit se VOIR */
  --gold:#9A5A0B; --gold2:#7E4808; --gold-d:#653A06;
  --cream:#241D14;      /* le texte principal */
  --muted:#63543F;
  --green:#1F6B45; --green-d:#145233; --green-bg:#DCEFE3;
  --coral:#B3411F; --coral-d:#8C3117; --coral-bg:#FAE2DA;
  --info:#12607F; --info-d:#D6EAF3;
  --lock:#8E8071;
  --tach:#12607F;       /* 17/08 : le bleu de la tachkīl, version claire (le `--info` du mode
                           clair) — 6,93:1 sur blanc, MESURÉ. Remplace le rouge #A8300B. */
  --ar:'Noto Naskh Arabic',serif;
  /* tokens NEUFS, créés pour ce thème (les 154 règles en dur s'y branchent) */
  --surf-hi:#F3E4CB;    /* la surface « allumée / choisie » (ex-#3a312b) */
  --sunk:#EFE9DC;       /* les creux : pastilles, pistes, tuiles éteintes */
  --on-gold:#FFF8EA;    /* l'encre POSÉE sur un aplat doré/vert/corail */
  --tip:#2A2117;        /* les bulles d'aide gardent un fond sombre (elles
                           flottent : un fond clair sur clair disparaîtrait) */
  --tip-txt:#FBF5E8;
  color-scheme:light;
}

/* ── LE FOND ────────────────────────────────────────────────────────────── */
html.clair body,
html.clair .player,
html.clair .finish,
html.clair .onb{
  background:var(--bg);
  background-image:radial-gradient(circle at 50% 0%, #FFFDF7 0, #FBF6EB 38%, var(--bg) 75%);
}
/* ── LA MASCOTTE SE DÉTACHE DU PARCHEMIN (Myriam, 14/08 : « la mascotte ne se distingue
   pas très bien à cause des couleurs similaires ») ───────────────────────────
   Sa lanterne est crème (#F7EBC0) et le fond de l'écran de fin l'est aussi (#FBF6EB) :
   1,08:1, elle flotte sans contour. Le DESSIN n'est pas touché (il est validé) — c'est son
   HALO, déjà présent dans le dessin, qui devient un vrai coussin ambré en mode clair, plus
   une ombre portée qui suit exactement la silhouette.
   ⚠️ On ne peut PAS passer par `opacity` : `mascotteDanse` la repose en style INLINE à la
   fin de la danse, et un style inline bat toute règle de thème (piège du 13/08). On teinte
   donc les ARRÊTS du dégradé, que la danse ne touche jamais. */
html.clair .masc{filter:drop-shadow(0 4px 12px rgba(101,58,6,.30))}
html.clair .masc stop:first-child{stop-color:#F0BE63;stop-opacity:.98}
html.clair .masc stop:nth-child(2){stop-color:#DE9A31;stop-opacity:.62}
html.clair .masc stop:last-child{stop-color:#DE9A31;stop-opacity:0}

html.clair .itab .tip,
html.clair #ltBubble,
html.clair #ltBubble .lt-arrow{ background:var(--tip); color:var(--tip-txt) }
html.clair #ltBubble .lt-next{ color:var(--on-gold) }
/* ⚠️ La bulle garde son fond sombre, mais chacun de ses enfants déclare SA couleur :
   `color` posé sur #ltBubble ne les atteint jamais. En clair, --cream/--muted/--gold2
   deviennent des encres foncées → texte noir sur bulle noire (1,05:1, INVISIBLE).
   Règle : une règle de thème qui reteint un CONTENEUR doit reteindre ses enfants
   qui portent une couleur propre. */
html.clair #ltBubble .lt-t{ color:#F0C46A }
html.clair #ltBubble .lt-x{ color:var(--tip-txt) }
html.clair #ltBubble .lt-step,
html.clair #ltBubble .lt-skip{ color:#BCAF9C }

/* ── FAMILLE A · la surface « allumée » (19 règles, ex-#3a312b) ─────────── */
html.clair .opt.sel,
html.clair .learn .son,
html.clair .ar-tap:active,
html.clair .exp-card:active,
html.clair .ag:active,
html.clair .fcell.done,
html.clair .assoc-c.lit,
html.clair .mimC.done,
html.clair .grp.done,
html.clair .panier .pmots span,
html.clair .sig-opt.sel,
html.clair .srcL:active,
html.clair .fourc.hover,
html.clair .fourc.lit,
html.clair .lvp-exrow .ex-chip.lit,
html.clair .dm-target.over,
html.clair .da-cell.over,
html.clair .lvp-row.lit,
html.clair .lvp-seat .ls.lit,
html.clair .ag.hl{ background:var(--surf-hi) }
html.clair .opt.on:not(.ok):not(.bad){ background:#FBE9C4; border-color:var(--gold) }

/* ── FAMILLE B · l'encre posée SUR un aplat coloré ──────────────────────── */
html.clair .sig-env,
html.clair .lg-rev,
html.clair .dm-ok,
html.clair .subnav .pill.active,
html.clair .ccard .ctt .cno,
html.clair .vfb.oui,
html.clair .vfb.non,
html.clair .pen-btns button.prim,
html.clair .cbtn,
html.clair .acc .acc-h .cno,
html.clair .dr-rev-btn,
html.clair .qsel-top .qi.on,
html.clair .qrow .tick,
html.clair .rk-lbl,
html.clair .ecu i,
html.clair .ucard.ok .uno,
html.clair .ucard.cur .uno,
html.clair .unit-head .uh-sub,
html.clair .rankcard,
html.clair .rankcard .rk-ar,
html.clair .rankcard .rk-tr,
html.clair .rankcard .rk-next,
html.clair .rankcard .rk-chev{ color:var(--on-gold) }
/* 🔴 LE CLAIR GARDE L'OR FONCÉ. En éclaircissant le dégradé pour le mode SOMBRE
   (2,19 → 4,68), j'allais casser le clair sans le voir : son encre est CRÈME
   (--on-gold #FFF8EA), pas brune — sur l'or clair elle tombe à 3,46:1 alors
   qu'elle était à 7,39:1. Les deux thèmes n'ont pas la même encre sur cette carte,
   ils ne peuvent donc pas partager le même fond. Piège de la règle du 13/08 :
   « toute règle de thème qui vise un état au repos doit redéclarer l'état allumé »
   — ici, corriger une couleur COMMUNE oblige à revérifier les deux thèmes. */
html.clair .rankcard{ background:linear-gradient(135deg,#6f4b0f,#9a6813 60%,#b8770f) }
html.clair .rankcard .ubar i,
html.clair .rankcard .rbar-fill{ background:var(--on-gold) }
html.clair .cta{ color:var(--on-gold) }          /* bouton doré foncé, encre claire */
html.clair .cta[disabled]{ background:var(--sunk);color:var(--muted);box-shadow:0 5px 0 #D8CDB6 }
html.clair .fb > span:first-child{ color:#fff }

/* ── FAMILLE C · les surfaces creuses ───────────────────────────────────── */
html.clair .lg-pbar,
html.clair .lg-qa button,
html.clair .lg-cell,
html.clair .sgn-card,
html.clair .chip,
html.clair .la-track,
html.clair .onb-track,
html.clair .smenu,
html.clair .sm-item,
html.clair .sm-close,
html.clair .sm-soon,
html.clair .qpin,
html.clair .qrow.on,
html.clair .nrow.nsel,
html.clair .opt.fopt.sel .fdevant,
html.clair .lg-rev:disabled{ background:var(--sunk) }
html.clair .lg-cell.locked{ background:var(--sunk);color:var(--lock);border-color:#DCD2C0 }
/* Les cartes à deux visages en mode clair : les MÊMES deux natures, en aplats pâles et
   encre sombre. ⚠️ Une règle de thème qui vise l'état au repos doit redéclarer l'état
   allumé (règle du 13/08) — ici l'état « retournée » a donc sa propre ligne. */
/* 🔴 L'ARABE DANS UNE BOÎTE S'ÉCRIT EN MARRON, PAS EN NOIR (Myriam, 01/09,
   repéré sur la preview des polices : « en mode clair, tu ne peux pas m'écrire
   dans boîte des mots en noir mais en marron comme l'écriture des versets »).
   En mode clair `--cream` vaut #241D14 — quasi noir : c'est l'encre du FRANÇAIS.
   L'arabe s'écrit en `--gold` (#9A5A0B) partout ailleurs : un verset, un mot
   révélé, une tuile. Une boîte n'avait aucune raison de faire exception, c'est
   le même texte arabe.
   ⚠️ C'EST UNE RÈGLE DE THÈME, PAS UN CHANGEMENT DE BASE : le mode sombre ne
   bouge pas d'un pixel. Le fichier fait déjà exactement ça juste en dessous,
   pour les cartes qui se retournent — on suit le modèle qui existe. */
html.clair .slots,
html.clair .da-cell,
html.clair .dm-target,
html.clair .fourc .ar{color:var(--gold)}
/* ⚠️ DEUX D'ENTRE ELLES SONT SUR UN FOND CRÈME, PAS SUR DU BLANC — donc --gold2,
   le brun plus foncé. Mesuré par le balayage : --gold (#9A5A0B) sur --panel2
   (#F0E7D6) donne 4,45:1 pour un seuil de 4,50 — cinq centièmes en dessous, sur
   DEUX éléments. La même encre passe largement sur le blanc (6,7:1).
   C'est la leçon de la « couleur partagée par deux thèmes », re-payée : une encre
   ne se choisit pas dans l'absolu, elle se choisit CONTRE SON FOND. */
html.clair .sttile,
html.clair .pen-zone,
html.clair .pen-t{color:var(--gold2)}
html.clair .lvp-flip-in{ background:#F6E3BE;border-color:var(--gold-d) }
html.clair .lvp-flip.flipped .lvp-flip-in{ background:#D6EAF3;border-color:var(--info) }
html.clair .lvp-flip:not(.flipped) .ff-ar,
html.clair .lvp-flip:not(.flipped) .ff-son,
html.clair .lvp-flip:not(.flipped) .ff-role{ color:#4A2E05 }
html.clair .lvp-flip.flipped .ff-ar,
html.clair .lvp-flip.flipped .ff-son,
html.clair .lvp-flip.flipped .ff-role{ color:#0C3D52 }

html.clair .lg-hamza .hz{ background:var(--sunk);color:var(--gold2) }
html.clair .lg-hamza .hz.locked{ background:var(--sunk);color:var(--lock);border-color:#DCD2C0 }
/* ⚠️ Un style INLINE bat toute règle de thème : l’encre de ce bouton devait quitter
   l’attribut style pour pouvoir basculer. En clair, --coral fonce — l’encre s’éclaircit. */
.cta-danger{ background:var(--coral);color:#1a1410 }
html.clair .cta-danger{ color:var(--on-gold) }
html.clair .lg-hamza .hz.lit{ background:#FBE9C4;border-color:var(--gold);color:#8A4A00 }
html.clair .lg-cell.avail{ background:#FBEFD8;color:var(--gold2) }
html.clair .lum{ background:linear-gradient(180deg,#FFFDF8,#F4EBDA);border:1px solid #C9AF7C }
html.clair .opt.fopt.ok .fdevant{ background:var(--green-bg);border-color:var(--green) }
html.clair .opt.fopt.bad .fdevant{ border-color:var(--coral) }
/* 14/08 (correctifs 4, trouvé par l'agent qa-visuel-alaq) — DEUX règles concurrentes pour la
   même carte : celle-ci (sans commentaire, tons #BBD0C2/#D6C39A qui n'appartiennent à AUCUN
   token du thème) écrasait border-color APRÈS la règle juste de la ligne ~1953, en clair
   seulement. Chaque face affichait donc la bordure pensée pour l'AUTRE — le recto (or) cerclé
   d'un vert-de-gris froid, le verso (bleu) cerclé d'un sable chaud. Supprimée : la ligne ~1953
   suffit et reste la seule source de vérité. */
html.clair .locked .bubble{ box-shadow:0 6px 0 #CFC3AC }
html.clair .vembed{ background:#111 }

/* ── FAMILLE D · les gris de texte ──────────────────────────────────────── */
html.clair .hkcirc.gr .circ,
html.clair .hkcirc.gr.lit .circ{ border-color:var(--lock) }
html.clair .hkcirc.gr .sign{ color:var(--lock) }
/* ⚠️ PIÈGE DE SPÉCIFICITÉ (13/08) : `html.clair .readbox.reveal .rc` pèse plus lourd
   que `.readbox.reveal .rc.on` — ma règle de thème écrasait donc l'état RÉVÉLÉ, et le
   mot restait de la couleur du mot caché. Toute règle de thème qui vise un état « au
   repos » doit redéclarer l'état « allumé » juste après. */
html.clair .readbox.reveal .rc{ color:#C6B8A6 }
html.clair .rc.on,
html.clair .readbox.reveal .rc.on{ color:#8A4A00;text-shadow:0 0 14px rgba(154,90,11,.4) }
/* Les harakat révélées : en sombre, « allumé » = plus CLAIR que le fond. En clair il faut
   l'inverse — l'éteint pâlit, l'allumé fonce et s'auréole. Sans ça les deux états se
   ressemblaient (Myriam : « la sélection en surbrillance n'existe plus »). */
html.clair .hkcirc.gr .circ,
html.clair .hkcirc.gr.lit .circ{ border-color:#C6B8A6 }
html.clair .hkcirc.gr .sign{ color:#C6B8A6 }
html.clair .hkcirc.gr.lit .sign,
html.clair .hkcirc.lit .sign{ color:#8A4A00;text-shadow:0 0 14px rgba(154,90,11,.4) }
html.clair .hkcirc.lit .circ{ border-color:var(--gold) }
/* Les mêmes états « allumé » ailleurs, redéclarés pour la même raison */
html.clair .vl.hit{ color:#8A4A00;text-shadow:0 0 14px rgba(154,90,11,.4) }
html.clair .lum.on,html.clair .ex-chip.lit,html.clair .fourc.lit,
html.clair .assoc-c.lit,html.clair .lvp-row.lit{ border-color:var(--gold) }
html.clair .lg-rev:disabled{ color:var(--muted) }
html.clair .ucard.lock .uno{ color:var(--lock) }
/* 14/08 (correctifs 4) — Myriam : « la box Assiduité n'a plus son contour bleu foncé ». Cause :
   `.c-assid`/`.c-score` peignent leur anneau avec `--info-d`, qui en clair vaut #D6EAF3 — un
   bleu pâle pensé pour UN AUTRE usage (le fond d'une pastille pleine, .qbulle, où le texte
   sombre lu PAR-DESSUS a besoin de rester clair). Sur le parchemin de `.case-in`, ce même pâle
   ne fait plus un anneau visible. On ne touche pas le token partagé (`.qbulle` reste juste) :
   ces deux cases reprennent la teinte foncée déjà validée en sombre. */
html.clair .c-assid,html.clair .c-score{ background:#1E4658 }
html.clair .vw.en{ color:#7A3F00;text-shadow:0 0 14px rgba(154,90,11,.28) }
html.clair .mushaf .vw.en,
html.clair .mushaf .vw.solo{ color:#7A3F00;text-shadow:none;background:#FBE9C4;border-radius:6px }
html.clair .mushaf .vw.lu{ color:var(--gold2) }
html.clair .ayat.en{ background:rgba(154,90,11,.07) }

/* ── FAMILLE E · le bleu du récitateur ──────────────────────────────────── */
html.clair .qbulle,
html.clair .qbulle:before{ background:var(--info-d);border-color:var(--info);color:#0C3A4C }

/* ── Les images : les icônes crème deviennent illisibles sur du blanc ────
   Le registre ICONES sert des PNG pensés pour un fond sombre. On ne fabrique
   pas de seconde famille de fichiers : un filtre les fonce, ce qui préserve
   leur dessin et coûte zéro octet. ⚠️ à revoir si Myriam veut des originaux
   clairs (ce serait plus propre, mais c'est un lot Artlist entier). */
/* ⚠️ `brightness()` seul DÉSATURE en même temps qu'il assombrit : le crème des icônes
   virait au gris (Myriam : « le blanc des icônes est plutôt gris, il devrait être
   beige »). On les fait passer par le sépia AVANT de les assombrir — le crème devient
   un beige chaud, le brun un brun profond, et le dessin garde son relief. */
html.clair .itab-ic,
html.clair .acc-ic,
html.clair .rq-boite img,
html.clair .bn .bi img,
html.clair .ic-inline,
html.clair .case .ic img{ filter:sepia(.85) saturate(2.6) hue-rotate(-12deg) brightness(.62) }
html.clair .itab.active .itab-ic{ filter:none }

/* ── L'ombre portée : sur clair, une ombre noire salit ──────────────────── */
/* ⚠️ La pastille de l'interrupteur ALLUMÉ est `--cream` : en clair, --cream devient
   presque noir et la pastille disparaissait sur la piste dorée foncée. Elle prend
   l'encre des aplats. (Trouvé au harnais, pas à l'œil.) */
/* ⚠️ LES DISQUES DE L'ACCUEIL GARDENT LEUR OR (Myriam, 13/08 : « tu as assombri le
   jaune des disques »). Ils sont posés sur le CIEL, qui reste sombre par sa décision :
   un or foncé y perd exactement ce qui les rend repérables. Ils ne suivent donc pas le
   thème — les valeurs sont celles du sombre, écrites en clair. */
html.clair .done .bubble{ background:#E8A94F;color:#252120 }   /* inversé le 14/08, comme en sombre */
html.clair .current .bubble{ background:radial-gradient(circle at 34% 26%,#f7cd74,#DC902E 50%,#a86a12);color:#252120 }
/* ⚠️ MAIS LES VERROUILLÉS, SI (Myriam, 13/08 : « les disques sombres étaient au
   début passés en clair et ce n’est plus le cas »). Ils n’ont pas d’or à
   protéger : un galet de parchemin se repère MIEUX sur la nuit qu’un galet sombre.
   ⚠️ Leur icône est un dessin SABLE, dessiné pour un fond sombre : sur le parchemin
   elle s’évanouirait. Elle est assombrie ici, sinon le disque devient un galet nu. */
html.clair .locked .bubble{ box-shadow:0 8px 0 #CFC3AC,
  var(--ciel-shx,0px) var(--ciel-shy,4px) var(--ciel-shb,10px) rgba(0,0,0,var(--ciel-sha,.22)) }
html.clair .locked .bimg{ filter:sepia(.55) saturate(1.5) brightness(.5) }
  /* 🔴 LES QUATRE GRANDES ICÔNES D'ÉCRAN N'AVAIENT AUCUNE RÈGLE EN MODE CLAIR
     (Myriam, 15/08 : « problème de couleur avec le crayon qui n'est pas visible »).
     `ecran-corriger` (On corrige tes erreurs), `ecran-pousse` (la série repart à
     zéro), `ecran-ghufran` (×3) et `ecran-compte` sont des dessins CRÈME, pensés
     pour la nuit : posés sur le parchemin ils s'effacent. Ça ne concerne pas
     l'unité 8 — c'est TOUTE l'app, dans toutes les unités, depuis le mode clair.
     ⚠️ Ciblées par leur SOURCE et non par une classe : les cinq appels sont des
     <img> nus écrits à cinq endroits, et une cinquième icône ajoutée demain
     hériterait de la règle sans que personne y pense.
     Recette des disques verrouillés (13/08) : le sépia AVANT l'assombrissement,
     sinon `brightness` désature et le crème vire au gris. */
  /* la bascule par THÈME, comme les illustrations de l'unité 8 : deux fichiers, on
     montre celui qui va avec le fond. Le filtre qui les rendait olive est retiré.
     ⚠️ `!important` OBLIGATOIRE sur les deux display:none (Myriam, 23/08 : les DEUX
     stylos empilés sur « On corrige tes erreurs ») : l'appelant passe
     `display:block` en style INLINE aux deux <img>, et un style inline bat toute
     règle de feuille — le piège documenté de RÉINITIALISER (13/08). Sans !important,
     la variante masquée redevient visible partout où icoEcran reçoit un display. */
  .ic2 .o-jour{display:none!important} .ic2 .o-nuit{display:inline-block}
  html.clair .ic2 .o-nuit{display:none!important} html.clair .ic2 .o-jour{display:inline-block!important}
/* ⚠️ MÊME CAUSE, TROUVÉE À L'ŒIL ET NON AU CALCUL : sur le ciel, `--accent` est forcé
   à --gold2, qui devient un brun en clair. Le disque « AVANCER ICI ? » et l'auréole du
   disque courant viraient donc au brun sur la nuit — un contraste correct (l'encre est
   blanche), mais la repérabilité perdue, exactement ce que Myriam avait refusé pour les
   disques. Sur le ciel, l'accent garde l'or du sombre. */
html.clair body.ciel .unit-sec,
html.clair body.ciel .unit-head{ --accent:#DC902E !important }
html.clair .unit-head{ background:linear-gradient(135deg,#6f4b0f,#9a6813 55%,#c08b1e) }
html.clair .unit-head .uh-top,html.clair .unit-head h2,html.clair .unit-head .uh-burger{ color:#fff }
html.clair .unit-head .uh-sub{ color:#3a2a08 }

/* ── LE SOMMAIRE DU CIEL ────────────────────────────────────────────────── */
/* Sa feuille portait `background:#1B1510` EN DUR : elle est restée sombre pendant
   que ses onze textes suivaient le thème. Neuf défauts d'un coup, dont le nom de
   chaque leçon à 1,09:1. C'est une FEUILLE, pas le décor : elle s'éclaircit comme
   celles du récitateur et du signalement. Le ciel derrière, lui, reste la nuit. */
html.clair #sommCiel .sc-in{ background:var(--panel);border-top-color:var(--gold-d) }
html.clair #sommCiel .sc-x{ color:var(--muted) }
html.clair #sommCiel .srow .sc-x1{ color:var(--cream) }
html.clair #sommCiel .srow .sc-e,
html.clair #sommCiel .sc-sep,
html.clair #sommCiel .srow.off .sc-m b{ color:var(--muted) }

/* ── LES DERNIÈRES ENCRES TROP PÂLES ────────────────────────────────────── */
/* le ⌫ du clavier : un corail clair pensé pour un fond sombre (2,13:1) */
html.clair .tile.tdel,
html.clair .wtile.tdel{ color:var(--coral);border-color:var(--coral) }
/* les petites italiques du récitateur, posées sur du blanc : --lock n'y vaut que 3,8:1 */
html.clair .qsec em,
html.clair .qgrp em{ color:var(--muted) }
html.clair .prm-sw.on i{ background:var(--on-gold) }
html.clair .dm-tile.drag,
html.clair .da-tile.drag{ box-shadow:0 10px 22px rgba(90,70,40,.28) }
html.clair .drag-ghost{ box-shadow:0 8px 20px rgba(90,70,40,.3) }

/* ═══════════════════════════════════════════════════════════════════════════
   ALAQ — LES ÉCRANS QUI GLISSENT, EN GRAND (13/08/2026)
   Demande de Myriam : « grossir au maximum les exercices où on fait glisser
   les harakat ou les prolongations sur les lettres ».

   Cinq écrans sont concernés, dans quatre leçons :
     · fuse      — leçon 1 (les harakat sur le م) et leçons 5/6 (7 unités)
     · place     — leçon 7 (soukoun · chedda · dhammatayn sur أَم أَن أَل)
     · dragmad   — unité 2, « glisse la bonne prolongation »
     · dragassoc — unité 2, « forme la prolongation »

   ⚠️ CONTRAINTE MESURÉE : le lecteur fait 390 px de large moins 44 px de
   marges = 346 px utiles. Trois cibles côte à côte ne peuvent donc pas
   dépasser 108 px avec 10 px d'écart (3×108 + 2×10 = 344). Tout ce qui est
   sur UNE ligne est calé sur ce plafond ; ce qui est empilé peut aller plus
   loin. On ne « grossit » pas au hasard : on grossit jusqu'au bord.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── fuse : la lettre-cible et le jeton qu'on lui apporte ───────────────── */
html.gros .fuserow{ gap:10px;margin-top:22px }
html.gros .mimC{ width:124px;height:124px;border-radius:22px;font-size:74px;border-width:3px }
html.gros .fchip{ width:104px;height:104px;font-size:60px;border-width:3px }
html.gros .farr{ font-size:34px }

/* ── place : le signe qu'on traîne, et les groupes أَم أَن أَل ──────────── */
html.gros .sigchip{ width:132px;height:132px;margin:10px auto 30px;border-radius:26px;font-size:78px;border-width:3px }
html.gros .grps{ gap:14px }
/* ⚠️ mesuré : trois groupes EMPILÉS + le signe à traîner + le titre sur deux lignes
   ne tiennent dans 800 px de haut qu'en dessous de ~110 px par groupe. À 64 px de
   police le 3ᵉ passait sous le pli — et un exercice où il faut faire défiler pour
   voir sa dernière cible n'est pas « plus grand », il est plus difficile. */
html.gros .grp{ min-width:250px;padding:11px 24px;font-size:52px;border-radius:20px;border-width:3px }

/* ── dragmad : la lettre porteuse et les 3 prolongations ────────────────── */
html.gros .dm-wrap{ gap:20px }
html.gros .dm-target{ min-width:230px;min-height:150px;font-size:82px;border-width:4px;border-radius:26px }
html.gros .dm-tray{ gap:12px;min-height:106px }
html.gros .dm-tile{ width:106px;height:106px;font-size:62px;border-radius:22px;border-width:3px }

/* ── dragassoc : 3 cellules en ligne — le plafond des 108 px s'applique ─── */
html.gros .da-wrap{ gap:20px }
html.gros .da-tops{ gap:10px }
html.gros .da-cell{ width:108px;min-height:126px;font-size:52px;border-width:4px;border-radius:22px }
html.gros .da-cell .da-long{ font-size:52px }
html.gros .da-bottoms{ gap:10px;min-height:104px }
html.gros .da-tile{ width:100px;height:100px;font-size:58px;border-radius:22px;border-width:3px }

/* ══ QUAND LES DEUX GROSSISSEMENTS SE RENCONTRENT ══
   Les écrans qui glissent sont DÉJÀ calés sur le bord de l'écran : les « grands
   caractères » (zoom 1,22) les faisaient déborder, et le 3ᵉ groupe de la leçon 7
   passait sous le pli (mesuré : 800 px pour 683 disponibles).
   On divise donc les tailles par 1,22 quand le zoom est actif : le rendu FINAL est
   identique, et tout retient dans l'écran. C'est une limite physique, pas un choix —
   on ne peut pas être plus grand que large. */
html.gtexte.gros .mimC{ width:102px;height:102px;font-size:61px }
html.gtexte.gros .fchip{ width:85px;height:85px;font-size:49px }
html.gtexte.gros .sigchip{ width:108px;height:108px;font-size:64px;margin:6px auto 14px }
html.gtexte.gros .grps{ gap:10px }
html.gtexte.gros .grp{ min-width:205px;padding:8px 20px;font-size:43px }
html.gtexte.gros .dm-target{ min-width:189px;min-height:123px;font-size:67px }
html.gtexte.gros .dm-tile{ width:87px;height:87px;font-size:51px }
html.gtexte.gros .da-cell{ width:88px;min-height:103px;font-size:43px }
html.gtexte.gros .da-cell .da-long{ font-size:43px }
html.gtexte.gros .da-tile{ width:82px;height:82px;font-size:48px }

/* ── le fantôme qui suit le doigt suit la même échelle ──────────────────── */
html.gros .drag-ghost{ font-size:64px }

/* ⚠️ Pas de règle sur `.q-title` ici : c'est le titre de TOUS les écrans, pas seulement
   de ceux qui glissent — le grossir depuis cette feuille toucherait toute l'app, et le
   compenser ensuite annulerait les « grands caractères ». La taille des titres est le
   travail du réglage d'affichage, pas celui de cette feuille. */

/* ══ GRANDS CARACTÈRES ══
   Le CSS de l'app est en PIXELS : le seul levier qui grossit vraiment tout — l'arabe,
   les boutons ET les zones de touche — est `zoom`. Le doute portait sur le
   glisser-déposer, qui compare partout un `getBoundingClientRect()` à la position du
   doigt : si les deux repères divergeaient, l'élève viserait juste sans rien poser.
   ⚠️ MESURÉ avant d'être adopté (`previews/_verif_zoom_glisser.html`, 8/8) : le signe
   se pose exactement là où on vise, à 1,0 comme à 1,22, et rien ne déborde de l'écran.
   On zoome les conteneurs de CONTENU, pas la mise en page globale. */
html.gtexte .p-body,
html.gtexte .p-foot,
html.gtexte .view,
html.gtexte .finish,
html.gtexte .botnav,
html.gtexte .onb-body{ zoom:1.22 }

/* ══ LA TRADUCTION AU TOUCHER ══
   Un bandeau BAS plutôt qu'une bulle ancrée au mot : une bulle couvrirait le verset
   qu'on est en train de lire, et il faut de la place pour écrire gros. Posé AU-DESSUS
   de la barre de navigation, pas dessus. */
/* ⚠️ 17/08 — LE « POP-UP FANTÔME » DE MYRIAM (capture du 15/08, écran d'ordinateur).
   L'état fermé se cachait par le SEUL `translateY(140%)`. Or 140 % ne sort de l'écran que
   si la bulle est plus haute que 165 px (il faut 0,4 × hauteur ≥ 66 px de `bottom`) : vide,
   elle ne l'est pas, et un liseré avec sa croix restait posé en bas. Sur TÉLÉPHONE personne
   ne l'a jamais vu — la barre du bas (`z-index:40`) recouvrait ce liseré (`z-index:38`).
   Sur ORDINATEUR la barre part en rail vertical à gauche : plus rien ne couvre, le liseré
   apparaît. Et il était « infermable » parce qu'il était DÉJÀ fermé : `pointer-events:none`
   rendait sa croix inerte. `visibility` ferme pour de bon, quelle que soit la hauteur —
   décalée de .22s pour ne pas escamoter l'animation de sortie. */
.motbulle{position:fixed;left:0;right:0;bottom:66px;   /* recalculé à l'ouverture */
  z-index:38;background:var(--panel);border-top:2px solid var(--gold-d);
  box-shadow:0 -10px 30px rgba(0,0,0,.28);padding:14px 18px 16px;
  max-width:560px;margin:0 auto;transform:translateY(140%);
  transition:transform .22s ease-out,visibility 0s linear .22s;
  visibility:hidden;pointer-events:none}
.motbulle.on{transform:none;pointer-events:auto;visibility:visible;
  transition:transform .22s ease-out,visibility 0s}
/* Sur ordinateur elle se centre entre les DEUX RAILS, pas dans la fenêtre : `left:0;right:0`
   la centrait sur toute la largeur, donc décalée par rapport à la colonne qu'on est en train
   de lire. Mêmes variables que la mise en page bureau — elles suivent les deux paliers. */
@media (min-width:700px){
  .motbulle{left:var(--rail-l);right:var(--rail-r)}
}
.motbulle .mb-h{display:flex;align-items:center;gap:12px}
.motbulle .mb-ar{font-family:var(--quran);font-size:40px;color:var(--gold);line-height:1.5;flex:1;
  direction:rtl;text-align:right}
.motbulle .mb-spk{background:none;border:none;padding:2px;color:var(--gold)}
.motbulle .mb-spk .spk{width:40px;height:26px}
.motbulle .mb-x{background:none;border:none;font-size:24px;color:var(--muted);padding:0 2px;line-height:1}
.motbulle .mb-lab{font-size:11px;font-weight:900;letter-spacing:.6px;text-transform:uppercase;
  color:var(--muted);margin:6px 0 2px}
.motbulle .mb-fr{font-size:22px;font-weight:800;color:var(--cream);line-height:1.35}
.motbulle .mb-src{font-size:11.5px;color:var(--muted);margin-top:7px}
/* @U8-CSS — LE CSS DE L'UNITÉ 8 A DÉMÉNAGÉ (POC-1, 18/08/2026).
   Il vit dans src/units/unit-8/styles/ et arrive par le lien posé JUSTE APRÈS
   la fin de ce bloc. La position est la règle : en CSS, deux règles de même poids se
   départagent par leur ORDRE, et ce bloc était le dernier de la feuille de
   l'app. Un <link> placé ailleurs changerait le rendu sans qu'aucun test de
   syntaxe ne bronche.
   ⚠️ Tout y est scopé `#player.u8` — 31 règles du noyau portent le nom d'une
   règle de l'app avec d'autres valeurs. Sans la cloche, ouvrir l'unité 8
   redessinerait les unités 1 à 7.
   ⚠️ ON N'ÉCRIT JAMAIS « </ style > » NI « < script > » EN TOUTES LETTRES dans un
   commentaire : l'analyseur HTML ne connaît pas les commentaires CSS ni JS, et il
   FERME l'élément à cette chaîne. Le reste du commentaire devient alors du texte
   dans la page — et les harnais qui mesurent le rendu ne le voient pas forcément. */

/* ═══ LA FEUILLE DE LECTURE DE LA FILE (09/09, POC-5 — PROVISOIRE) ═══════════
   Ouverte par sept tapotements sur le numéro de version. Rien ici ne se voit tant
   que le geste n'est pas fait : la carte « Version de l'app » reste identique.
   ⚠️ Ce bloc et la fonction _ouvrirLectureFile d'index.html sont les DEUX SEULS
   endroits touchés : le retrait, le jour venu, ne laisse aucune trace ailleurs. */
.filevoile{position:fixed;inset:0;background:rgba(0,0,0,.55);opacity:0;pointer-events:none;
  transition:opacity .26s;z-index:9998}
.filevoile.on{opacity:1;pointer-events:auto}
.filesheet{position:fixed;left:0;right:0;bottom:0;background:var(--panel);
  border-top:2px solid var(--gold);border-radius:18px 18px 0 0;padding:16px 18px 24px;
  transform:translateY(105%);transition:transform .26s cubic-bezier(.3,1.2,.5,1);
  z-index:9999;max-height:78vh;overflow:auto;box-shadow:0 -8px 30px rgba(0,0,0,.5)}
.filesheet.on{transform:translateY(0)}
.filesheet h3{font-family:var(--ui);font-size:16px;font-weight:900;color:var(--gold);margin:0 0 2px}
.filesheet .fs-q{font-size:11.5px;color:var(--muted);margin:0 0 14px}
.filesheet .fs-l{display:flex;justify-content:space-between;align-items:baseline;gap:12px;
  padding:8px 0;border-bottom:1px solid var(--line);font-size:13.5px;color:var(--cream);
  font-family:var(--ui);font-weight:700}
.filesheet .fs-l:last-of-type{border-bottom:none}
.filesheet .fs-l .v{font-variant-numeric:tabular-nums;font-weight:900;font-size:16px;text-align:right}
.filesheet .fs-l .v.ok{color:#8fd6a0}
.filesheet .fs-l .v.att{color:var(--gold)}
.filesheet .fs-l .v.nul{color:var(--muted)}
.filesheet .fs-x{margin-top:16px;width:100%;padding:12px;border-radius:12px;
  border:1px solid var(--line);background:transparent;color:var(--cream);
  font-family:var(--ui);font-size:14.5px;font-weight:800}
