// stress-pages.jsx
// 10 stress-test templates. Every page composes ONLY locked blocks
// (PageShell + PageTitle + Box variants + Cols + Ketty + QR).
// No header/footer, no margins, no spacing, no typo redefined locally.

const { Fragment: SF } = React;

/* helpers used in several pages */
function CheckLine({ children }) {
  return (
    <div className="bk-q" style={{ alignItems: "center" }}>
      <span className="bk-check" style={{ marginRight: "0.06in" }}></span>
      <span className="bk-q-content">{children}</span>
    </div>
  );
}
function NumPill({ n }) {
  return (
    <span style={{
      display: "inline-grid", placeItems: "center",
      width: "0.22in", height: "0.22in", borderRadius: "999px",
      background: "var(--ae-primary)", color: "white",
      fontFamily: "var(--ae-font-title)", fontWeight: 600,
      fontSize: "0.12in", flex: "0 0 auto",
    }}>{n}</span>
  );
}

/* ========================================================================
   1 · DIAGNOSTIC DE DÉPART
   ======================================================================== */
function StressDiagnostic({ density, qrVisible, scoreVisible, scale = 1 }) {
  return (
    <PageShell
      matiere="Maths" niveau="6ᵉ" page={"Diagnostic · Page 4"}
      density={density} qrVisible={qrVisible} scoreVisible={scoreVisible}
      qrLabel="Auto-correction"
      scale={scale}
    >
      <PageTitle
        eyebrow="Diagnostic de départ · 15 min"
        title="Où en es-tu en début d'année ?"
        subtitle="10 questions courtes pour faire le point. Pas de stress, on regarde simplement."
      />

      <ObjectiveBox
        title="Comment ça marche"
        items={[
          "Lis chaque question puis coche ou écris ta réponse.",
          "Si tu hésites, passe à la suivante : tu reviendras à la fin.",
          "À la fin, on fait le bilan ensemble avec Ketty.",
        ]}
      />

      <Cols ratio="1fr 1fr">
        <ExerciseCard number={1} title="Partie A" consigne="Calcul mental — coche la bonne réponse.">
          <QInput n={1}>17 + 8 = <QCMRow options={[["A","23"],["B","25"],["C","26"]]} /></QInput>
          <QInput n={2}>9 × 7 = <QCMRow options={[["A","56"],["B","63"],["C","72"]]} /></QInput>
          <QInput n={3}>100 − 47 = <QCMRow options={[["A","53"],["B","57"],["C","63"]]} /></QInput>
          <QInput n={4}>Moitié de 86 = <QCMRow options={[["A","42"],["B","43"],["C","44"]]} /></QInput>
          <QInput n={5}>Double de 35 = <QCMRow options={[["A","65"],["B","70"],["C","75"]]} /></QInput>
        </ExerciseCard>
        <ExerciseCard number={2} tone="orange" title="Partie B" consigne="Réponds par un nombre.">
          <QInput n={6}>Écris en chiffres : « trois mille douze » <AnswerLine width="1in" /></QInput>
          <QInput n={7}>Combien de minutes dans ¾ d'heure ? <AnswerLine width="0.7in" /></QInput>
          <QInput n={8}>Le tiers de 27 ? <AnswerLine width="0.7in" /></QInput>
          <QInput n={9}>Périmètre d'un carré de côté 5 cm ? <AnswerLine width="0.9in" /></QInput>
          <QInput n={10}>Quel est le nombre pair entre 38 et 41 ? <AnswerLine width="0.7in" /></QInput>
        </ExerciseCard>
      </Cols>

      <Cols ratio="1.2fr 1fr">
        <KettyBubble pose="thinking" tone="primary" label="Ketty te rassure">
          Ce diagnostic ne compte pas. Il sert à savoir où tu es <b>avant</b> de
          commencer le cahier — comme une photo de départ pour mesurer tes progrès.
        </KettyBubble>
        <ScoreBox label="Mon score de départ" message="Je note mon résultat ici, on le comparera plus tard." />
      </Cols>
    </PageShell>
  );
}

/* ========================================================================
   2 · MINI-LEÇON + EXERCICES
   ======================================================================== */
function StressLessonExercise({ density, qrVisible, scoreVisible, scale = 1 }) {
  return (
    <PageShell
      matiere="Français" niveau="CM2" page={18}
      density={density} qrVisible={qrVisible} scoreVisible={scoreVisible}
      scale={scale}
    >
      <PageTitle
        eyebrow="Conjugaison · Leçon 4"
        title="L'imparfait des verbes en -er"
        subtitle="Une terminaison régulière, un radical à repérer."
      />

      <Cols ratio="1fr 1fr">
        <LessonBox title="Je retiens" formula="radical + ais / ais / ait / ions / iez / aient">
          À l'imparfait, tous les verbes en <b>-er</b> prennent les mêmes terminaisons.
          On les ajoute au <b>radical</b> (le verbe sans son <i>-er</i>).
        </LessonBox>
        <MethodSteps
          title="Méthode"
          steps={[
            "Trouve l'infinitif (chant-er, march-er…).",
            "Repère le radical (chant-, march-…).",
            "Ajoute la terminaison qui correspond au sujet.",
          ]}
        />
      </Cols>

      <Box tone="neutral" label="Exemple guidé" iconKey="icon-loupe">
        <div className="bk-text">
          <b>Verbe :</b> chanter — <b>Sujet :</b> nous → radical <b>chant-</b> + terminaison <b>-ions</b> →
          <span style={{ background: "var(--ae-yellow-soft)", padding: "0 0.06in", borderRadius: "0.04in", marginLeft: "0.06in" }}>
            nous chant<b>ions</b>
          </span>
        </div>
      </Box>

      <ExerciseCard number={1} consigne="Conjugue à l'imparfait.">
        <QInput n={1}>(jouer) — Je <AnswerLine width="1.2in" /> dans le jardin.</QInput>
        <QInput n={2}>(regarder) — Tu <AnswerLine width="1.2in" /> les nuages.</QInput>
        <QInput n={3}>(parler) — Vous <AnswerLine width="1.2in" /> trop fort.</QInput>
        <QInput n={4}>(chanter) — Elles <AnswerLine width="1.2in" /> en chœur.</QInput>
      </ExerciseCard>

      <Cols ratio="1fr 1fr">
        <WarningBox title="Attention !">
          Pour les verbes en <b>-cer</b> et <b>-ger</b>, on adapte le radical
          devant <b>-ait, -ais, -aient</b> : <i>nous mang<b>e</b>ions</i>, <i>il lan<b>ç</b>ait</i>.
        </WarningBox>
        <ChallengeBox title="Mini-défi">
          Écris une phrase à l'imparfait avec le verbe <b>« rêver »</b> et le sujet <b>« nous »</b>.
          <div style={{ marginTop: "0.08in" }}><AnswerBox height="0.5in" ruled /></div>
        </ChallengeBox>
      </Cols>
    </PageShell>
  );
}

/* ========================================================================
   3 · EXERCICE PROBLÈME
   ======================================================================== */
function StressProblem({ density, qrVisible, scoreVisible, scale = 1 }) {
  return (
    <PageShell
      matiere="Maths" niveau="5ᵉ" page={"Bloc 2 · Page 31"}
      density={density} qrVisible={qrVisible} scoreVisible={scoreVisible}
      scale={scale}
    >
      <PageTitle
        eyebrow="Problème ouvert · Proportionnalité"
        title="La sortie au stade"
        subtitle="Lis attentivement, organise-toi, puis rédige ta réponse."
      />

      <Box tone="neutral" label="Énoncé" iconKey="icon-section">
        <p style={{ fontSize: "var(--ae-fs-body)", lineHeight: "var(--ae-line-h)" }}>
          La classe de 5ᵉ B prépare une sortie au stade. Le car coûte
          <b> 240 €</b> pour le trajet aller-retour, et chaque billet d'entrée
          coûte <b>6 €</b>. Le collège participe à hauteur de <b>90 €</b> par
          classe. Il y a <b>24 élèves</b>, et chacun doit payer la même somme.
          La professeure souhaite savoir <b>combien chaque élève doit verser</b>.
        </p>
      </Box>

      <Cols ratio="1fr 1fr">
        <Box tone="cool" label="Données utiles" iconKey="icon-info">
          <ul className="bk-bullets">
            <li><span className="dot"></span>Car aller-retour : 240 €</li>
            <li><span className="dot"></span>Billet par élève : 6 €</li>
            <li><span className="dot"></span>Aide du collège : 90 €</li>
            <li><span className="dot"></span>Effectif : 24 élèves</li>
          </ul>
        </Box>
        <MethodSteps
          title="Étapes guidées"
          steps={[
            "Calcule le coût total des billets (24 × 6 €).",
            "Ajoute le car. Soustrais l'aide du collège.",
            "Divise la dépense restante par 24.",
          ]}
        />
      </Cols>

      <ExerciseCard number={1} consigne="Rédige ta démarche puis ta réponse en phrase complète.">
        <div className="bk-text" style={{ marginBottom: "0.08in" }}>
          <b>Mes calculs :</b>
        </div>
        <AnswerBox height="1.4in" ruled />
        <div className="bk-text" style={{ margin: "0.1in 0 0.06in" }}>
          <b>Ma réponse :</b>
        </div>
        <AnswerBox height="0.5in" ruled />
      </ExerciseCard>

      <KettyBubble pose="pointing" tone="yellow" label="Indice de Ketty">
        Si une étape te bloque, écris en mots ce que tu cherches avant
        d'écrire les calculs. Souvent ça suffit à débloquer.
      </KettyBubble>
    </PageShell>
  );
}

/* ========================================================================
   4 · TABLEAU À COMPLÉTER
   ======================================================================== */
function StressTable({ density, qrVisible, scoreVisible, scale = 1 }) {
  return (
    <PageShell
      matiere="Maths" niveau="6ᵉ" page={"Bloc 3 · Page 22"}
      density={density} qrVisible={qrVisible} scoreVisible={scoreVisible}
      scale={scale}
    >
      <PageTitle
        eyebrow="Proportionnalité · Application"
        title="Le tableau du marchand de fruits"
        subtitle="Complète les cases manquantes en utilisant la règle du coefficient."
      />

      <LessonBox title="Rappel">
        Dans un tableau de proportionnalité, on passe d'une ligne à l'autre en
        <b> multipliant par un même nombre </b>: le <b>coefficient</b>.
      </LessonBox>

      <ExerciseCard number={1} consigne="Complète le tableau. Le prix de 1 kg te donne le coefficient.">
        <TableBlock
          columns={["Quantité (kg)", "1", "2", "3", "5", "8", "10"]}
          rows={[
            ["Pommes (€)",   "2,40", "…",   "…",   "12,00", "…",    "…"],
            ["Poires (€)",   "…",    "5,80","…",   "…",    "23,20","…"],
            ["Bananes (€)",  "1,80", "…",   "5,40","…",    "…",    "18,00"],
          ]}
        />
      </ExerciseCard>

      <Cols ratio="1fr 1fr">
        <ExerciseCard number={2} tone="orange" title="Conjugaison" consigne="Complète le tableau au présent.">
          <TableBlock
            columns={["Personne", "être", "avoir", "aller"]}
            rows={[
              ["je / j'", "suis",   "…",   "…"],
              ["tu",      "…",      "as",  "vas"],
              ["il / elle","est",   "a",   "…"],
              ["nous",    "…",      "…",   "allons"],
              ["vous",    "êtes",   "…",   "…"],
              ["ils",     "…",      "ont", "vont"],
            ]}
          />
        </ExerciseCard>

        <SelfCheck
          title="Je vérifie"
          items={[
            "Tous les coefficients sont identiques sur une ligne.",
            "J'ai gardé deux décimales pour les prix en €.",
            "Mes terminaisons sont au bon temps.",
          ]}
        />
      </Cols>
    </PageShell>
  );
}

/* ========================================================================
   5 · GRAPHIQUE / FIGURE
   ======================================================================== */
function FigureFunc() {
  return (
    <svg viewBox="0 0 320 180" style={{ width: "100%", height: "100%" }}>
      <rect x="0" y="0" width="320" height="180" fill="white" />
      {/* grid */}
      {Array.from({ length: 9 }).map((_, i) => (
        <line key={"v"+i} x1={20 + i*36} y1="10" x2={20 + i*36} y2="170" stroke="#E6EAF5" strokeWidth="0.8"/>
      ))}
      {Array.from({ length: 5 }).map((_, i) => (
        <line key={"h"+i} x1="20" y1={10 + i*40} x2="308" y2={10 + i*40} stroke="#E6EAF5" strokeWidth="0.8"/>
      ))}
      {/* axes */}
      <line x1="20" y1="170" x2="308" y2="170" stroke="#0F1A3D" strokeWidth="1.4"/>
      <line x1="20" y1="10"  x2="20"  y2="170" stroke="#0F1A3D" strokeWidth="1.4"/>
      {/* ticks labels */}
      {[0,1,2,3,4,5,6,7].map(i => (
        <text key={"x"+i} x={20 + i*36} y="180" textAnchor="middle" fontSize="9" fill="#2B3656" fontFamily="Nunito Sans">{i}</text>
      ))}
      {[0,1,2,3,4].map(i => (
        <text key={"y"+i} x="14" y={174 - i*40} textAnchor="end" fontSize="9" fill="#2B3656" fontFamily="Nunito Sans">{i}</text>
      ))}
      {/* line y = 0.5x + 0.5 */}
      <line x1="20" y1={170 - 20} x2="308" y2={170 - (20 + 8*18)} stroke="#1B3FB8" strokeWidth="2"/>
      {/* points */}
      {[[1,1],[3,2],[5,3]].map(([x,y],i) => (
        <circle key={i} cx={20 + x*36} cy={170 - y*40} r="3.4" fill="#F5781C" stroke="white" strokeWidth="1.2"/>
      ))}
      <text x="240" y="40" fontSize="10" fill="#1B3FB8" fontFamily="Fredoka" fontWeight="600">y = 0,5 x + 0,5</text>
    </svg>
  );
}
function FigureGeom() {
  return (
    <svg viewBox="0 0 320 180" style={{ width: "100%", height: "100%" }}>
      <rect x="0" y="0" width="320" height="180" fill="white" />
      {/* triangle ABC */}
      <polygon points="60,150 250,150 60,40" fill="#E8EEFB" stroke="#1B3FB8" strokeWidth="1.6"/>
      {/* right angle marker */}
      <polyline points="60,140 70,140 70,150" fill="none" stroke="#1B3FB8" strokeWidth="1.4"/>
      {/* labels */}
      <text x="52" y="158" fontSize="11" fontFamily="Fredoka" fontWeight="600" fill="#0F1A3D">A</text>
      <text x="256" y="158" fontSize="11" fontFamily="Fredoka" fontWeight="600" fill="#0F1A3D">B</text>
      <text x="52" y="36" fontSize="11" fontFamily="Fredoka" fontWeight="600" fill="#0F1A3D">C</text>
      <text x="155" y="166" fontSize="9" fill="#2B3656">8 cm</text>
      <text x="30" y="100" fontSize="9" fill="#2B3656">6 cm</text>
      <text x="170" y="92" fontSize="9" fill="#F5781C" fontWeight="700">? cm</text>
    </svg>
  );
}

function StressFigure({ density, qrVisible, scoreVisible, scale = 1 }) {
  return (
    <PageShell
      matiere="Maths" niveau="3ᵉ" page={"Bloc 1 · Page 12"}
      density={density} qrVisible={qrVisible} scoreVisible={scoreVisible}
      scale={scale}
    >
      <PageTitle
        eyebrow="Fonctions affines · Lecture graphique"
        title="Lire et interpréter une droite"
        subtitle="Observe le graphique, puis la figure géométrique."
      />

      <Cols ratio="1fr 1fr">
        <FigureBlock label="Document 1" caption="Représentation graphique de f.">
          <FigureFunc />
        </FigureBlock>
        <FigureBlock label="Document 2" caption="Triangle rectangle ABC en A.">
          <FigureGeom />
        </FigureBlock>
      </Cols>

      <ExerciseCard number={1} consigne="À partir du document 1, réponds.">
        <QInput n={1}>L'image de 4 par f est : <AnswerLine width="0.8in" /></QInput>
        <QInput n={2}>L'antécédent de 2 par f est : <AnswerLine width="0.8in" /></QInput>
        <QInput n={3}>Donne l'équation de la droite : <AnswerLine width="1.6in" /></QInput>
      </ExerciseCard>

      <ExerciseCard number={2} tone="orange" consigne="À partir du document 2.">
        <QInput n={1}>Identifie l'hypoténuse : <AnswerLine width="1in" /></QInput>
        <QInput n={2}>Calcule BC. Donne la valeur arrondie au mm.</QInput>
        <AnswerBox height="0.7in" ruled />
      </ExerciseCard>

      <SelfCheck
        title="Je vérifie"
        items={[
          "J'ai lu les valeurs sur les axes au bon endroit.",
          "J'ai justifié l'angle droit avant Pythagore.",
          "Mes unités sont cohérentes (cm partout).",
        ]}
      />
    </PageShell>
  );
}

/* ========================================================================
   6 · CORRECTION COMPACTE
   ======================================================================== */
function CorrigeBlock({ n, title, children, color = "primary" }) {
  return (
    <div style={{
      borderLeft: `0.04in solid var(--ae-${color === "orange" ? "orange" : "primary"})`,
      paddingLeft: "0.12in",
    }}>
      <div style={{
        display: "flex", alignItems: "center", gap: "0.08in",
        marginBottom: "0.04in",
      }}>
        <span style={{
          fontFamily: "var(--ae-font-title)", fontWeight: 700,
          fontSize: "0.13in", color: "var(--ae-primary-deep)",
        }}>Exercice {n}</span>
        <span style={{ fontSize: "0.11in", color: "var(--ae-muted)" }}>· {title}</span>
      </div>
      <div style={{ fontSize: "var(--ae-fs-body-min)", lineHeight: 1.4, color: "var(--ae-text)" }}>
        {children}
      </div>
    </div>
  );
}

function StressCorrection({ density, qrVisible, scoreVisible, scale = 1 }) {
  return (
    <PageShell
      matiere="Maths" niveau="4ᵉ" page={"Corrigé · Page 84"}
      density="dense"
      qrVisible={qrVisible} scoreVisible={false}
      qrLabel="Détails en vidéo"
      scale={scale}
    >
      <PageTitle
        eyebrow="Corrections — Bloc 3"
        title="Les solutions, exercice par exercice"
        subtitle="Compare avec ta démarche. Ce qui compte, c'est de comprendre l'étape qui t'a posé souci."
      />

      <Box tone="cool" label="Pour t'auto-corriger" iconKey="icon-check">
        <ul className="bk-bullets" style={{ gridTemplateColumns: "1fr 1fr", display: "grid" }}>
          <li><span className="dot"></span>Coche d'abord ce que tu avais juste.</li>
          <li><span className="dot"></span>Note en marge l'étape qui a manqué.</li>
        </ul>
      </Box>

      <div style={{
        display: "grid", gridTemplateColumns: "1fr 1fr",
        gap: "0.18in 0.24in",
      }}>
        <CorrigeBlock n="1" title="Calcul de fractions">
          <b>a)</b> 3/4 + 1/2 = 3/4 + 2/4 = <b>5/4</b>.<br/>
          <b>b)</b> 5/6 − 1/3 = 5/6 − 2/6 = <b>3/6 = 1/2</b>.<br/>
          <b>c)</b> 2/5 × 10 = 20/5 = <b>4</b>.
        </CorrigeBlock>
        <CorrigeBlock n="2" title="Pythagore">
          BC² = AB² + AC² = 36 + 64 = 100<br/>
          BC = √100 = <b>10 cm</b>.<br/>
          <i>Erreur fréquente :</i> oublier la racine carrée.
        </CorrigeBlock>
        <CorrigeBlock n="3" title="Proportionnalité" color="orange">
          Coefficient = 2,40 / 1 = <b>2,40 €/kg</b>.<br/>
          5 kg → 5 × 2,40 = <b>12,00 €</b>.<br/>
          8 kg → 8 × 2,40 = <b>19,20 €</b>.
        </CorrigeBlock>
        <CorrigeBlock n="4" title="Équation du 1er degré" color="orange">
          3x − 5 = 16 ⟶ 3x = 21 ⟶ <b>x = 7</b>.<br/>
          Vérification : 3 × 7 − 5 = 16 <Icon k="icon-check" style={{ color: "var(--ae-success)" }} />
        </CorrigeBlock>
        <CorrigeBlock n="5" title="Pourcentages">
          25 % de 80 = 0,25 × 80 = <b>20</b>.<br/>
          Augmenter de 10 % : ×1,10. 60 ⟶ <b>66</b>.
        </CorrigeBlock>
        <CorrigeBlock n="6" title="Statistiques" color="orange">
          Moyenne = (12+14+15+13+16)/5 = <b>14</b>.<br/>
          Médiane (série triée) = <b>14</b>.
        </CorrigeBlock>
      </div>

      <Cols ratio="1.4fr 1fr">
        <KettyBubble pose="thumbsup" tone="primary" label="Le mot de Ketty">
          Si tu as raté un exercice, recopie l'étape clé sur une fiche.
          C'est la meilleure manière de retenir <b>pourquoi</b> ça marche.
        </KettyBubble>
        <QRBlock title="Voir les corrections en vidéo" url="alloeducation.fr/maths/4e/corr3" seed={203} size="0.85in" />
      </Cols>
    </PageShell>
  );
}

/* ========================================================================
   7 · MINI-SUJET D'EXAMEN
   ======================================================================== */
function StressExam({ density, qrVisible, scoreVisible, scale = 1 }) {
  return (
    <PageShell
      matiere="Maths" niveau="3ᵉ" page={"Évaluation · Page 60"}
      density={density} qrVisible={qrVisible} scoreVisible={scoreVisible}
      qrLabel="Barème détaillé"
      scale={scale}
    >
      <PageTitle
        eyebrow="Évaluation type Brevet"
        title="Mini-sujet · 45 minutes"
        subtitle="3 exercices indépendants. Calculatrice autorisée. Soigne la rédaction."
      />

      <Cols ratio="1fr 1fr 1fr">
        <Box tone="primary" label="Durée" iconKey="icon-horloge">
          <div style={{ fontFamily: "var(--ae-font-title)", fontWeight: 700, fontSize: "0.32in", color: "var(--ae-primary-deep)" }}>45 min</div>
          <div style={{ fontSize: "var(--ae-fs-body-min)", color: "var(--ae-text-soft)" }}>Lecture du sujet incluse.</div>
        </Box>
        <Box tone="yellow" label="Barème total" iconKey="icon-sigma">
          <div style={{ fontFamily: "var(--ae-font-title)", fontWeight: 700, fontSize: "0.32in", color: "var(--ae-primary-deep)" }}>20 pts</div>
          <div style={{ fontSize: "var(--ae-fs-body-min)", color: "var(--ae-text-soft)" }}>Ex 1 : 6 · Ex 2 : 7 · Ex 3 : 7</div>
        </Box>
        <Box tone="cool" label="Conditions" iconKey="icon-info">
          <ul className="bk-bullets" style={{ gap: "0.04in" }}>
            <li><span className="dot"></span>Calculatrice autorisée</li>
            <li><span className="dot"></span>Téléphone éteint</li>
            <li><span className="dot"></span>Brouillon non noté</li>
          </ul>
        </Box>
      </Cols>

      <ExerciseCard number={1} consigne="Calcul littéral · 6 points">
        <QInput n={1}>Développe et réduis : A = (2x + 3)(x − 5)</QInput>
        <AnswerBox height="0.55in" ruled />
        <QInput n={2}>Factorise : B = 4x² − 9</QInput>
        <AnswerBox height="0.4in" ruled />
      </ExerciseCard>

      <ExerciseCard number={2} tone="orange" consigne="Géométrie · 7 points">
        <QInput n={1}>Dans un triangle ABC rectangle en A : AB = 5 cm, AC = 12 cm.
          Calcule BC en justifiant.</QInput>
        <AnswerBox height="0.7in" ruled />
        <QInput n={2}>Calcule la mesure de l'angle <span style={{ fontFamily: "var(--ae-font-mono)" }}>ABC</span> arrondie au degré.</QInput>
        <AnswerBox height="0.55in" ruled />
      </ExerciseCard>

      <ExerciseCard number={3} consigne="Problème · 7 points">
        <QInput n={1}>Un compte d'épargne de 1 200 € rapporte 2,5 % d'intérêts par an.
          Quel est son montant après 1 an ? après 3 ans ?</QInput>
        <AnswerBox height="0.85in" ruled />
      </ExerciseCard>
    </PageShell>
  );
}

/* ========================================================================
   8 · CARTE MENTALE
   ======================================================================== */
function MindMap() {
  // 5 branches around a centre node — pure SVG so it scales with the figure
  const branches = [
    { label: "Lieu", sub: "noyau",       angle: -150, color: "#1B3FB8" },
    { label: "Acteur", sub: "ARN polym.", angle: -90,  color: "#F5781C" },
    { label: "Étape 1", sub: "transcription", angle: -30,  color: "#1F9E5A" },
    { label: "Produit", sub: "ARNm",      angle: 30,   color: "#FFC533" },
    { label: "Étape 2", sub: "traduction",angle: 90,   color: "#9F1239" },
    { label: "Code",  sub: "universel",  angle: 150,  color: "#5B21B6" },
  ];
  const cx = 200, cy = 130, r = 105;
  return (
    <svg viewBox="0 0 400 260" style={{ width: "100%", height: "100%" }}>
      {/* connectors */}
      {branches.map((b, i) => {
        const rad = (b.angle * Math.PI) / 180;
        const x = cx + Math.cos(rad) * r;
        const y = cy + Math.sin(rad) * r;
        return (
          <g key={i}>
            <path d={`M${cx},${cy} Q${(cx+x)/2 + (i%2?12:-12)},${(cy+y)/2} ${x},${y}`}
                  fill="none" stroke={b.color} strokeWidth="1.6" />
          </g>
        );
      })}
      {/* central node */}
      <ellipse cx={cx} cy={cy} rx="56" ry="32" fill="#1B3FB8" />
      <text x={cx} y={cy - 4} textAnchor="middle" fill="white" fontFamily="Fredoka" fontWeight="700" fontSize="14">
        Synthèse des
      </text>
      <text x={cx} y={cy + 12} textAnchor="middle" fill="white" fontFamily="Fredoka" fontWeight="700" fontSize="14">
        protéines
      </text>
      {/* branch nodes */}
      {branches.map((b, i) => {
        const rad = (b.angle * Math.PI) / 180;
        const x = cx + Math.cos(rad) * r;
        const y = cy + Math.sin(rad) * r;
        return (
          <g key={i}>
            <rect x={x - 38} y={y - 16} width="76" height="32" rx="6" fill="white" stroke={b.color} strokeWidth="1.4"/>
            <text x={x} y={y - 2} textAnchor="middle" fontFamily="Fredoka" fontWeight="600" fontSize="10" fill={b.color}>{b.label}</text>
            <text x={x} y={y + 11} textAnchor="middle" fontFamily="Nunito Sans" fontSize="9" fill="#2B3656">{b.sub}</text>
          </g>
        );
      })}
    </svg>
  );
}

function StressMindmap({ density, qrVisible, scoreVisible, scale = 1 }) {
  return (
    <PageShell
      matiere="SVT" niveau="Première" page={"Synthèse · Page 52"}
      density={density} qrVisible={qrVisible} scoreVisible={scoreVisible}
      scale={scale}
    >
      <PageTitle
        eyebrow="Carte mentale · Chapitre 3"
        title="Tout retenir d'un coup d'œil"
        subtitle="Six branches pour relier les notions du chapitre."
      />

      <FigureBlock label="Carte mentale" caption="À recopier sur ton cahier en couleur." height="2.4in">
        <MindMap />
      </FigureBlock>

      <Cols ratio="1fr 1fr">
        <Box tone="yellow" label="Comment l'utiliser" iconKey="icon-loupe">
          <ol className="bk-steps">
            <li><span className="n">1</span><span className="t">Recopie la carte sans regarder.</span></li>
            <li><span className="n">2</span><span className="t">Vérifie chaque branche avec ton cours.</span></li>
            <li><span className="n">3</span><span className="t">Ajoute une branche personnelle.</span></li>
          </ol>
        </Box>
        <ChallengeBox title="Ma branche perso">
          Choisis un mot du chapitre qui n'est pas sur la carte et ajoute-le ici en
          le reliant à une branche existante.
          <div style={{ marginTop: "0.08in" }}><AnswerBox height="0.7in" ruled /></div>
        </ChallengeBox>
      </Cols>
    </PageShell>
  );
}

/* ========================================================================
   9 · RESSOURCES QR
   ======================================================================== */
function ResourceCard({ kind, title, subtitle, duration, seed }) {
  return (
    <div style={{
      display: "flex", gap: "0.14in", alignItems: "center",
      padding: "0.14in", borderRadius: "0.12in",
      border: "1.5px solid var(--ae-border)",
      background: "white",
    }}>
      <div style={{
        width: "0.7in", height: "0.7in", flex: "0 0 auto",
        borderRadius: "0.08in",
        background: "var(--ae-primary)",
        display: "grid", placeItems: "center",
        color: "white",
        fontFamily: "var(--ae-font-title)", fontWeight: 700,
        fontSize: "0.16in",
      }}>{kind}</div>
      <div style={{ flex: 1, minWidth: 0 }}>
        <div style={{
          fontFamily: "var(--ae-font-title)", fontWeight: 600,
          fontSize: "0.15in", color: "var(--ae-primary-deep)",
          lineHeight: 1.2,
        }}>{title}</div>
        <div style={{
          fontSize: "var(--ae-fs-body-min)", color: "var(--ae-text-soft)",
          lineHeight: 1.3, marginTop: "0.03in",
        }}>{subtitle}</div>
        <div style={{
          marginTop: "0.05in",
          display: "inline-flex", alignItems: "center", gap: "0.05in",
          background: "var(--ae-yellow-soft)", border: "1px solid var(--ae-yellow-dark)",
          padding: "0.02in 0.08in", borderRadius: "999px",
          fontSize: "0.1in", color: "var(--ae-primary-deep)", fontWeight: 700,
        }}>⏱ {duration}</div>
      </div>
      <div style={{ flex: "0 0 auto" }}>
        <QRPlaceholder size="0.65in" seed={seed} />
      </div>
    </div>
  );
}

function StressQrResources({ density, qrVisible, scoreVisible, scale = 1 }) {
  return (
    <PageShell
      matiere="Histoire" niveau="4ᵉ" page={"Bloc 4 · Page 71"}
      density={density} qrVisible={qrVisible} scoreVisible={false}
      qrLabel="Page ressources"
      scale={scale}
    >
      <PageTitle
        eyebrow="Ressources numériques"
        title="Aller plus loin sur la Révolution"
        subtitle="Scanne les QR avec ton téléphone. Les contenus sont gratuits, sans pub."
      />

      <Cols ratio="1fr 1fr">
        <ResourceCard kind="VID" title="14 juillet 1789, expliqué"
          subtitle="Vidéo animée — la chute de la Bastille en images."
          duration="6 min" seed={11} />
        <ResourceCard kind="AUD" title="Podcast : Olympe de Gouges"
          subtitle="Voix posée, niveau 4ᵉ, transcription incluse."
          duration="11 min" seed={29} />
        <ResourceCard kind="DOC" title="Frise interactive"
          subtitle="Glisser-déposer les événements clés 1789–1799."
          duration="10 min" seed={47} />
        <ResourceCard kind="QCM" title="Quiz d'auto-évaluation"
          subtitle="20 questions, score immédiat, conseils Ketty."
          duration="8 min" seed={61} />
      </Cols>

      <Box tone="primary" label="QR principal · toute la page" iconKey="icon-cible">
        <div style={{ display: "flex", alignItems: "center", gap: "0.2in" }}>
          <QRPlaceholder size="1.3in" seed={101} />
          <div style={{ flex: 1 }}>
            <div style={{ fontFamily: "var(--ae-font-title)", fontWeight: 600, fontSize: "0.18in", color: "var(--ae-primary-deep)" }}>
              Toutes les ressources de la page
            </div>
            <div style={{ fontSize: "var(--ae-fs-body)", color: "var(--ae-text-soft)", marginTop: "0.05in" }}>
              Un seul scan pour ouvrir le hub. Mises à jour gratuites pendant
              toute l'année scolaire.
            </div>
            <div style={{
              display: "inline-block", marginTop: "0.1in",
              fontFamily: "var(--ae-font-mono)", fontSize: "0.11in",
              color: "var(--ae-primary)", background: "white",
              border: "1px solid var(--ae-border)",
              padding: "0.04in 0.1in", borderRadius: "999px",
            }}>alloeducation.fr/h4/p71</div>
          </div>
        </div>
      </Box>
    </PageShell>
  );
}

/* ========================================================================
   10 · DIPLÔME / CERTIFICAT
   ======================================================================== */
function DiplomaSeal() {
  return (
    <svg viewBox="0 0 200 200" style={{ width: "1.6in", height: "1.6in" }}>
      {/* outer star burst */}
      <g transform="translate(100,100)">
        {Array.from({ length: 24 }).map((_, i) => {
          const a = (i * 360) / 24;
          return (
            <rect key={i} x="-2" y="-90" width="4" height="14"
              fill="#FFC533" transform={`rotate(${a})`} />
          );
        })}
        <circle r="74" fill="#1B3FB8" />
        <circle r="62" fill="none" stroke="#FFC533" strokeWidth="2" strokeDasharray="3 4"/>
        <text y="-12" textAnchor="middle" fontFamily="Fredoka" fontWeight="700" fontSize="14" fill="white">BRAVO !</text>
        <text y="8"  textAnchor="middle" fontFamily="Fredoka" fontWeight="600" fontSize="11" fill="white">Cahier</text>
        <text y="22" textAnchor="middle" fontFamily="Fredoka" fontWeight="600" fontSize="11" fill="white">terminé</text>
        <path d="M-22 36 L0 50 L22 36" fill="none" stroke="#FFC533" strokeWidth="2" strokeLinecap="round"/>
      </g>
    </svg>
  );
}

function StressDiploma({ density, qrVisible, scoreVisible, scale = 1 }) {
  return (
    <PageShell
      matiere="Diplôme" niveau="Tous niveaux" page={"Page finale"}
      density="light"
      qrVisible={qrVisible} scoreVisible={false}
      qrLabel="Partage ta réussite"
      scale={scale}
    >
      <PageTitle
        eyebrow="Tu y es arrivé·e !"
        title="Diplôme Allo Education"
        subtitle="La preuve officielle de ton parcours dans ce cahier."
      />

      <div style={{
        position: "relative",
        borderRadius: "0.18in",
        border: "0.04in double var(--ae-primary)",
        background: "linear-gradient(180deg, var(--ae-bg) 0%, var(--ae-yellow-soft) 100%)",
        padding: "0.28in 0.3in",
        textAlign: "center",
      }}>
        <div style={{
          fontFamily: "var(--ae-font-title)",
          fontWeight: 500, color: "var(--ae-orange-dark)",
          fontSize: "0.14in", letterSpacing: "0.16em", textTransform: "uppercase",
        }}>Ce diplôme est décerné à</div>

        <div style={{
          fontFamily: "var(--ae-font-title)",
          fontWeight: 600, fontSize: "0.42in",
          color: "var(--ae-primary-deep)",
          margin: "0.08in 0 0.04in",
          borderBottom: "2px dashed var(--ae-primary)",
          paddingBottom: "0.08in",
          width: "70%", marginLeft: "auto", marginRight: "auto",
        }}>Prénom Nom</div>

        <div style={{
          margin: "0.16in auto 0", maxWidth: "5in",
          fontSize: "var(--ae-fs-body)", lineHeight: 1.5, color: "var(--ae-text-soft)",
        }}>
          pour avoir terminé avec sérieux et persévérance le cahier
          <b> Allo Education </b>— et avoir transformé chaque page
          en un pas de plus vers ses objectifs.
        </div>

        <div style={{ display: "flex", justifyContent: "center", margin: "0.14in 0" }}>
          <DiplomaSeal />
        </div>

        <Cols ratio="1fr 1fr">
          <div style={{ textAlign: "left" }}>
            <div style={{ fontSize: "0.1in", color: "var(--ae-muted)", textTransform: "uppercase", letterSpacing: "0.12em" }}>Date</div>
            <div style={{ borderBottom: "1.5px solid var(--ae-primary-deep)", height: "0.34in" }}></div>
          </div>
          <div style={{ textAlign: "left" }}>
            <div style={{ fontSize: "0.1in", color: "var(--ae-muted)", textTransform: "uppercase", letterSpacing: "0.12em" }}>Signature</div>
            <div style={{ borderBottom: "1.5px solid var(--ae-primary-deep)", height: "0.34in" }}></div>
          </div>
        </Cols>
      </div>

      <KettyBubble pose="celebrating" tone="orange" label="Ketty te félicite">
        Tu as tenu jusqu'au bout, page après page. C'est exactement
        comme ça qu'on devient meilleur·e — par petites victoires régulières.
        Garde ce cahier, tu seras fier·e d'y revenir plus tard !
      </KettyBubble>
    </PageShell>
  );
}

Object.assign(window, {
  StressDiagnostic, StressLessonExercise, StressProblem,
  StressTable, StressFigure, StressCorrection, StressExam,
  StressMindmap, StressQrResources, StressDiploma,
});
