// template-pack-maths-brevet.jsx
// PACK MATHS BREVET 3e — Allo Education Books v1.2
// 15 templates pour générer le livre « Objectif Brevet Maths 3e ».
// Strictement composés à partir des blocs verrouillés (PageShell, PageTitle,
// Box, Cols, KettyBubble, QRBlock, TableBlock, FigureBlock, etc.) + helpers
// math (MathExpr, Frac, StepBlock, GridCalc, AxisGrid, BarChart, TriangleFigure).
// Aucun emoji. Tous pictos via iconKey.

const MB_FR = React.Fragment;

/* ════════════════════════════════════════════════════════════════════════
   01 · math-lesson-exercise — Leçon maths avec exemple guidé
   ════════════════════════════════════════════════════════════════════════ */
function MBLessonExercise({ density, qrVisible, scoreVisible, scale = 1 }) {
  return (
    <PageShell
      matiere="Mathématiques" niveau="3ᵉ" page={"Chapitre 4 · Page 21"}
      density={density} qrVisible={qrVisible} scoreVisible={scoreVisible}
      qrSlug="AE-3E-MATH-001-2026-V1-P021"
      qrLabel="Vidéo de la leçon"
      scale={scale}
    >
      <PageTitle
        eyebrow="Calcul littéral · Leçon"
        title="Développer une expression"
        subtitle="Distribuer le facteur à chaque terme — sans erreur de signe."
      />

      <Cols ratio="1fr 1fr">
        <ObjectiveBox
          title="Objectif de la page"
          items={[
            "Reconnaître une expression à développer",
            "Distribuer le facteur à chaque terme",
            "Réduire et ordonner le résultat",
          ]}
        />
        <LessonBox title="À retenir" formula="k × (a + b) = k × a + k × b">
          On multiplie le facteur <b>k</b> par chaque terme dans la parenthèse,
          <b> sans oublier les signes</b>, puis on regroupe les termes semblables.
        </LessonBox>
      </Cols>

      <Box tone="primary" label="Exemple guidé" iconKey="icon-loupe">
        Développer et réduire <MathExpr>A = 4(2x − 3) + 5</MathExpr>.
        <div style={{ marginTop: "0.06in" }}>
          <StepBlock
            steps={[
              { expr: <span>A = 4 · 2x + 4 · (−3) + 5</span>, note: "je distribue" },
              { expr: <span>A = 8x − 12 + 5</span> },
              { expr: <span>A = 8x − 7</span>, note: "réduit" },
            ]}
          />
        </div>
      </Box>

      <ExerciseCard number={1} consigne="Développe et réduis chaque expression.">
        <GridCalc cols={2} items={[
          <span>3(x + 5)</span>,
          <span>2(4x − 1) + 3</span>,
          <span>5(2x + 3) − 4x</span>,
          <span>−2(x − 7)</span>,
        ]} />
      </ExerciseCard>

      <SelfCheck
        title="Réflexes à cocher"
        items={[
          "J'ai distribué chaque terme à chaque terme.",
          "J'ai vérifié les signes (− × − = +).",
          "J'ai bien regroupé les termes en x², en x, et les constantes.",
        ]}
      />
    </PageShell>
  );
}

/* ════════════════════════════════════════════════════════════════════════
   02 · math-progressive-exercise — Exercices progressifs
   ════════════════════════════════════════════════════════════════════════ */
function MBProgressive({ density, qrVisible, scoreVisible, scale = 1 }) {
  return (
    <PageShell
      matiere="Mathématiques" niveau="3ᵉ" page={"Chapitre 5 · Page 28"}
      density={density} qrVisible={qrVisible} scoreVisible={scoreVisible}
      qrSlug="AE-3E-MATH-001-2026-V1-P028"
      qrLabel="Correction détaillée"
      scale={scale}
    >
      <PageTitle
        eyebrow="Équations · Entraînement progressif"
        title="Résoudre une équation du 1er degré"
        subtitle="Trois exercices, trois niveaux. Tu montes en difficulté à ton rythme."
      />

      <Box tone="cool" label="Méthode express" iconKey="icon-fleche">
        <b>1.</b> Je regroupe les <i>x</i> à gauche, les nombres à droite.
        <b> 2.</b> Je réduis. <b>3.</b> Je divise par le coefficient de <i>x</i>.
      </Box>

      <ExerciseCard number={1} tone="green" consigne="Niveau facile — résous.">
        <StepBlock steps={[{ expr: <span>3x + 5 = 17</span> }]} />
        <AnswerLine width="100%" />
      </ExerciseCard>

      <ExerciseCard number={2} consigne="Niveau moyen — résous.">
        <StepBlock steps={[{ expr: <span>5x − 7 = 2x + 8</span> }]} />
        <AnswerBox height="0.55in" ruled />
      </ExerciseCard>

      <Cols ratio="1.4fr 1fr">
        <ExerciseCard number={3} tone="orange" consigne="Défi — attention au piège.">
          <StepBlock steps={[{ expr: <span>2(3x − 4) = 5x + 1</span>, note: "distribue d'abord" }]} />
          <AnswerBox height="0.5in" ruled />
        </ExerciseCard>
        <SelfCheck
          title="Auto-évaluation"
          items={[
            "Exo 1 réussi sans aide.",
            "Exo 2 réussi en 1 essai.",
            "J'ai distribué avant de regrouper.",
          ]}
        />
      </Cols>
    </PageShell>
  );
}

/* ════════════════════════════════════════════════════════════════════════
   03 · math-guided-problem — Problème guidé
   ════════════════════════════════════════════════════════════════════════ */
function MBGuidedProblem({ density, qrVisible, scoreVisible, scale = 1 }) {
  return (
    <PageShell
      matiere="Mathématiques" niveau="3ᵉ" page={"Chapitre 7 · Page 38"}
      density={density} qrVisible={qrVisible} scoreVisible={scoreVisible}
      qrSlug="AE-3E-MATH-001-2026-V1-P038"
      qrLabel="Correction enrichie"
      scale={scale}
    >
      <PageTitle
        eyebrow="Problème guidé · Mise en équation"
        title="Le concert de fin d'année"
        subtitle="Pour réussir : lis bien, pose ton inconnue, traduis l'énoncé."
      />

      <Box tone="neutral" label="Situation" iconKey="icon-livre">
        Pour son concert, le club organise <b>180</b> places. Le tarif adulte
        est de <b>12&nbsp;€</b> et le tarif jeune de <b>7&nbsp;€</b>. La recette
        totale s'élève à <b>1 660&nbsp;€</b>.
        <div style={{ marginTop: "0.04in" }}><b>Question :</b> combien de places adultes ont été vendues ?</div>
      </Box>

      <Cols ratio="1fr 1.2fr">
        <Box tone="cool" label="Données utiles" iconKey="icon-section">
          <ul className="bk-bullets" style={{ marginBottom: 0 }}>
            <li><span className="dot"></span>Total places : 180</li>
            <li><span className="dot"></span>Tarif adulte : 12 €</li>
            <li><span className="dot"></span>Tarif jeune : 7 €</li>
            <li><span className="dot"></span>Recette : 1 660 €</li>
          </ul>
        </Box>
        <MethodSteps
          title="Étapes guidées"
          steps={[
            "Je note x le nombre de places adultes.",
            "J'exprime le nombre de places jeunes (180 − x).",
            "Je traduis la recette : 12x + 7(180 − x) = 1 660.",
            "Je résous, je conclus en phrase.",
          ]}
        />
      </Cols>

      <ExerciseCard number={1} consigne="Mes calculs.">
        <AnswerBox height="0.7in" ruled />
      </ExerciseCard>

      <Cols ratio="1.3fr 1fr">
        <Box tone="green" label="Phrase réponse" iconKey="icon-check">
          <AnswerLine width="100%" />
        </Box>
        <WarningBox title="Erreur à éviter">
          Ne pas oublier <b>(180 − x)</b> dans l'équation : c'est le nombre de
          places jeunes, pas une seule place !
        </WarningBox>
      </Cols>
    </PageShell>
  );
}

/* ════════════════════════════════════════════════════════════════════════
   04 · math-grid-practice — Calculs en grille
   ════════════════════════════════════════════════════════════════════════ */
function MBGridPractice({ density, qrVisible, scoreVisible, scale = 1 }) {
  return (
    <PageShell
      matiere="Mathématiques" niveau="3ᵉ" page={"Chapitre 1 · Page 12"}
      density={density} qrVisible={qrVisible} scoreVisible={scoreVisible}
      qrSlug="AE-3E-MATH-001-2026-V1-P012"
      scale={scale}
    >
      <PageTitle
        eyebrow="Automatismes · Priorités &amp; relatifs"
        title="20 calculs en 10 minutes"
        subtitle="Vitesse + précision. Pose le moins possible, vérifie le signe."
      />

      <Cols ratio="1.3fr 1fr">
        <Box tone="primary" label="Consigne" iconKey="icon-horloge">
          Effectue les calculs sans calculatrice. Tu disposes de
          <b> 10 minutes </b>. Si tu hésites, passe au suivant.
        </Box>
        <ScoreBox barRatio={0.5} />
      </Cols>

      <ExerciseCard number={1} tone="green" consigne="Priorités opératoires.">
        <GridCalc cols={3} items={[
          "8 + 3 × 4", "(7 − 2) × 3", "12 ÷ 4 + 5",
          "5² − 4 × 3", "−6 + 2 × 7", "20 − (3 + 4) × 2",
        ]} />
      </ExerciseCard>

      <ExerciseCard number={2} consigne="Nombres relatifs.">
        <GridCalc cols={3} items={[
          "−4 + 9", "−7 − 3", "8 − (−5)",
          "(−6) × (−4)", "−15 ÷ 3", "(−2)³",
        ]} />
      </ExerciseCard>

      <ExerciseCard number={3} tone="orange" consigne="Fractions — donne le résultat irréductible.">
        <GridCalc cols={3} items={[
          <span><Frac num="2" den="3" /> + <Frac num="1" den="4" /></span>,
          <span><Frac num="5" den="6" /> − <Frac num="1" den="3" /></span>,
          <span><Frac num="3" den="4" /> × <Frac num="8" den="9" /></span>,
        ]} />
      </ExerciseCard>
    </PageShell>
  );
}

/* ════════════════════════════════════════════════════════════════════════
   05 · math-qcm — QCM maths
   ════════════════════════════════════════════════════════════════════════ */
function MBQCM({ density, qrVisible, scoreVisible, scale = 1 }) {
  return (
    <PageShell
      matiere="Mathématiques" niveau="3ᵉ" page={"Bilan · Page 75"}
      density={density} qrVisible={qrVisible} scoreVisible={scoreVisible}
      qrSlug="AE-3E-MATH-001-2026-V1-P075"
      qrLabel="Réponses commentées"
      scale={scale}
    >
      <PageTitle
        eyebrow="QCM bilan · 8 questions"
        title="Vérifie tes acquis"
        subtitle="Une seule réponse correcte par question. Coche la bonne lettre."
      />

      <Box tone="neutral" label="Choisis la bonne réponse" iconKey="icon-question">
        <QCMRow n="1" q={<span>Le nombre <MathExpr>(−3)²</MathExpr> est égal à :</span>}
          options={["−6", "9", "−9"]} />
        <QCMRow n="2" q={<span>L'écriture scientifique de 0,000 42 est :</span>}
          options={[<span>4,2 × 10<sup>−4</sup></span>, <span>42 × 10<sup>−5</sup></span>, <span>4,2 × 10<sup>4</sup></span>]} />
        <QCMRow n="3" q={<span>Une augmentation de 20 % puis une baisse de 20 % donne :</span>}
          options={["aucun changement", "une baisse de 4 %", "une baisse de 20 %"]} />
        <QCMRow n="4" q={<span>L'image de 3 par f tel que f(x) = 2x − 5 est :</span>}
          options={["1", "−1", "11"]} />
        <QCMRow n="5" q={<span>Si ABC est rectangle en A avec AB = 3, AC = 4, alors BC =</span>}
          options={["5", "7", "√7"]} />
        <QCMRow n="6" q={<span>La médiane de la série 4 ; 7 ; 9 ; 12 ; 15 est :</span>}
          options={["7", "9", "9,4"]} />
      </Box>

      <Cols ratio="1.4fr 1fr">
        <Box tone="cool" label="Justifie une de tes réponses au choix" iconKey="icon-crayon">
          <AnswerBox height="0.5in" ruled />
        </Box>
        <ScoreBox barRatio={0.5} />
      </Cols>
    </PageShell>
  );
}

/* ════════════════════════════════════════════════════════════════════════
   06 · algebra-equation-page — Équations / calcul littéral
   ════════════════════════════════════════════════════════════════════════ */
function MBAlgebra({ density, qrVisible, scoreVisible, scale = 1 }) {
  return (
    <PageShell
      matiere="Mathématiques" niveau="3ᵉ" page={"Chapitre 4 · Page 25"}
      density={density} qrVisible={qrVisible} scoreVisible={scoreVisible}
      qrSlug="AE-3E-MATH-001-2026-V1-P025"
      scale={scale}
    >
      <PageTitle
        eyebrow="Calcul littéral · Application"
        title="Développer, réduire, factoriser"
        subtitle="Trois gestes essentiels — un par bloc."
      />

      <Cols ratio="1fr 1fr 1fr">
        <ExerciseCard number={1} tone="green" consigne="Je développe.">
          <MathExpr display>A = 3(2x − 5)</MathExpr>
          <StepBlock steps={[{ expr: <span>A = 3 · 2x + 3 · (−5)</span> }, { expr: <span>A = …</span> }]} />
        </ExerciseCard>
        <ExerciseCard number={2} consigne="Je réduis.">
          <MathExpr display>B = 4x + 7 − 2x + 3</MathExpr>
          <StepBlock steps={[{ expr: <span>B = (4x − 2x) + (7 + 3)</span> }, { expr: <span>B = …</span> }]} />
        </ExerciseCard>
        <ExerciseCard number={3} tone="orange" consigne="Je factorise.">
          <MathExpr display>C = 6x + 9</MathExpr>
          <StepBlock steps={[{ expr: <span>C = 3 · 2x + 3 · 3</span>, note: "facteur 3" }, { expr: <span>C = 3 · (…)</span> }]} />
        </ExerciseCard>
      </Cols>

      <ExerciseCard number={4} consigne="Résous l'équation.">
        <MathExpr display>5(x − 2) = 3x + 4</MathExpr>
        <AnswerBox height="0.7in" ruled />
      </ExerciseCard>

      <SelfCheck
        title="Auto-check"
        items={[
          "J'ai distribué AVANT de regrouper.",
          "Mes signes sont corrects (−×− = +).",
          "J'ai vérifié ma solution en remplaçant x dans l'équation de départ.",
        ]}
      />
    </PageShell>
  );
}

/* ════════════════════════════════════════════════════════════════════════
   07 · proportionality-table — Tableau de proportionnalité
   ════════════════════════════════════════════════════════════════════════ */
function MBProportionality({ density, qrVisible, scoreVisible, scale = 1 }) {
  return (
    <PageShell
      matiere="Mathématiques" niveau="3ᵉ" page={"Chapitre 6 · Page 36"}
      density={density} qrVisible={qrVisible} scoreVisible={scoreVisible}
      qrSlug="AE-3E-MATH-001-2026-V1-P036"
      scale={scale}
    >
      <PageTitle
        eyebrow="Proportionnalité · Tableaux"
        title="Trouver le coefficient, compléter le tableau"
        subtitle="Une multiplication suffit — encore faut-il la repérer."
      />

      <LessonBox title="Méthode" iconKey="icon-fleche" formula="y = k × x">
        Dans un tableau de proportionnalité, on passe d'une ligne à l'autre
        en multipliant par un même nombre <b>k</b> appelé <b>coefficient</b>.
      </LessonBox>

      <ExerciseCard number={1} consigne="Au supermarché — complète le tableau et donne le coefficient.">
        <ProportionalityTable
          headers={["Quantité (kg)", "Prix (€)"]}
          cols={[{ x: 2, y: 5 }, { x: 5, y: null }, { x: 8, y: null }, { x: 12, y: null }]}
          coef={null}
        />
      </ExerciseCard>

      <Cols ratio="1.2fr 1fr">
        <Box tone="cool" label="Méthode : passer par l'unité" iconKey="icon-loupe">
          Je calcule le prix de <b>1 kg</b> (ici : 5 ÷ 2 = 2,50 €), puis je
          multiplie par la quantité voulue. C'est souvent le chemin le plus rapide.
        </Box>
        <Box tone="green" label="Phrase réponse" iconKey="icon-check">
          12 kg coûtent <AnswerLine width="0.7in" /> €.
        </Box>
      </Cols>

      <ExerciseCard number={2} tone="orange" consigne="Cette situation est-elle proportionnelle ? Justifie.">
        <TableBlock
          columns={["Durée (min)", "Distance (km)"]}
          rows={[["10", "8"], ["20", "15"], ["30", "24"]]}
        />
        <AnswerBox height="0.45in" ruled />
      </ExerciseCard>
    </PageShell>
  );
}

/* ════════════════════════════════════════════════════════════════════════
   08 · percentage-scale-page — Pourcentages / échelles
   ════════════════════════════════════════════════════════════════════════ */
function MBPercentage({ density, qrVisible, scoreVisible, scale = 1 }) {
  return (
    <PageShell
      matiere="Mathématiques" niveau="3ᵉ" page={"Chapitre 6 · Page 42"}
      density={density} qrVisible={qrVisible} scoreVisible={scoreVisible}
      qrSlug="AE-3E-MATH-001-2026-V1-P042"
      scale={scale}
    >
      <PageTitle
        eyebrow="Pourcentages &amp; échelles"
        title="Calculer une variation, lire une carte"
        subtitle="Multiplie, divise, raisonne — n'oublie jamais l'unité."
      />

      <Cols ratio="1fr 1fr">
        <LessonBox title="Augmentation / réduction" formula="prix × (1 + t/100)  ou  prix × (1 − t/100)">
          Pour une <b>hausse de t %</b>, on multiplie par <b>1 + t/100</b>.
          Pour une <b>baisse de t %</b>, on multiplie par <b>1 − t/100</b>.
        </LessonBox>
        <LessonBox title="Échelle" formula="échelle = distance carte ÷ distance réelle">
          Une échelle <MathExpr>1/25 000</MathExpr> signifie que <b>1 cm</b> sur
          la carte représente <b>25 000 cm = 250 m</b> dans la réalité.
        </LessonBox>
      </Cols>

      <ExerciseCard number={1} tone="green" consigne="Soldes — calcule le nouveau prix.">
        <GridCalc cols={2} items={[
          "Veste 80 € − 25 %", "Livre 14 € + 5 %",
          "Jeans 65 € − 30 %", "Abonnement 24 € + 8 %",
        ]} />
      </ExerciseCard>

      <ExerciseCard number={2} consigne="Échelle — sur une carte au 1/50 000.">
        <div style={{ fontSize: "var(--ae-fs-body)", lineHeight: 1.5 }}>
          <b>a.</b> 1 cm sur la carte = combien de m en vrai ? <AnswerLine width="1in" />
          <br/>
          <b>b.</b> Une rivière mesure 4,5 cm sur la carte. Sa longueur réelle est de <AnswerLine width="1in" />.
        </div>
      </ExerciseCard>

      <WarningBox title="Conversions">
        Toujours convertir avant de comparer : <b>1 m = 100 cm</b>, <b>1 km = 1 000 m</b>.
        Une réponse en cm ou en km change la note !
      </WarningBox>
    </PageShell>
  );
}

/* ════════════════════════════════════════════════════════════════════════
   09 · function-table-graph — Fonctions
   ════════════════════════════════════════════════════════════════════════ */
function MBFunctions({ density, qrVisible, scoreVisible, scale = 1 }) {
  return (
    <PageShell
      matiere="Mathématiques" niveau="3ᵉ" page={"Chapitre 8 · Page 48"}
      density={density} qrVisible={qrVisible} scoreVisible={scoreVisible}
      qrSlug="AE-3E-MATH-001-2026-V1-P048"
      qrLabel="Graphique interactif"
      scale={scale}
    >
      <PageTitle
        eyebrow="Fonctions · Lecture &amp; graphique"
        title="De la formule au repère"
        subtitle="Une fonction, c'est une machine : tu donnes x, elle te rend f(x)."
      />

      <Cols ratio="1fr 1.1fr">
        <LessonBox title="La fonction de l'exercice" formula="f(x) = 2x − 1">
          <b>Image</b> : on calcule f(x) en remplaçant.
          <br/><b>Antécédent</b> : on cherche x tel que f(x) = … (équation).
        </LessonBox>
        <Box tone="cool" label="Tableau de valeurs" iconKey="icon-section">
          <TableBlock
            columns={["x", "−2", "−1", "0", "1", "2", "3"]}
            rows={[["f(x)", "−5", "−3", "−1", "…", "…", "…"]]}
          />
        </Box>
      </Cols>

      <Cols ratio="1.1fr 1fr">
        <FigureBlock label="Repère orthonormé" caption="Place les points et trace la droite." height="2.4in">
          <div style={{ display: "grid", placeItems: "center", padding: "0.1in", height: "100%" }}>
            <AxisGrid
              points={[{ x: -2, y: -5, label: "A" }, { x: 0, y: -1, label: "B" }, { x: 2, y: 3, label: "C" }]}
              plotF={x => 2 * x - 1}
              xMin={-3} xMax={4} yMin={-5} yMax={5}
            />
          </div>
        </FigureBlock>
        <ExerciseCard number={1} consigne="Réponds.">
          <QInput n={1}>Image de 4 par f : <AnswerLine width="0.8in" /></QInput>
          <QInput n={2}>Antécédent de 7 : <AnswerLine width="0.8in" /></QInput>
          <QInput n={3}>f(x) = 0 pour x = <AnswerLine width="0.8in" /></QInput>
        </ExerciseCard>
      </Cols>
    </PageShell>
  );
}

/* ════════════════════════════════════════════════════════════════════════
   10 · stats-probability-page — Statistiques / probabilités
   ════════════════════════════════════════════════════════════════════════ */
function MBStatsProba({ density, qrVisible, scoreVisible, scale = 1 }) {
  return (
    <PageShell
      matiere="Mathématiques" niveau="3ᵉ" page={"Chapitre 9 · Page 53"}
      density={density} qrVisible={qrVisible} scoreVisible={scoreVisible}
      qrSlug="AE-3E-MATH-001-2026-V1-P053"
      scale={scale}
    >
      <PageTitle
        eyebrow="Statistiques &amp; probabilités"
        title="Lire, calculer, interpréter"
        subtitle="Moyenne, médiane, étendue — et un peu de hasard pour finir."
      />

      <Cols ratio="1fr 1.2fr">
        <Box tone="cool" label="Notes en français · 12 élèves" iconKey="icon-section">
          <TableBlock
            columns={["Note", "8", "10", "12", "14", "16"]}
            rows={[["Effectif", "1", "3", "4", "3", "1"]]}
          />
        </Box>
        <FigureBlock label="Diagramme en barres" height="1.7in">
          <div style={{ display: "grid", placeItems: "center", height: "100%", padding: "0.06in" }}>
            <BarChart data={[
              { label: "8", v: 1 }, { label: "10", v: 3 }, { label: "12", v: 4 },
              { label: "14", v: 3 }, { label: "16", v: 1 },
            ]} yMax={5} />
          </div>
        </FigureBlock>
      </Cols>

      <ExerciseCard number={1} consigne="Calcule.">
        <Cols ratio="1fr 1fr 1fr">
          <span><b>Moyenne :</b> <AnswerLine width="1in" /></span>
          <span><b>Médiane :</b> <AnswerLine width="1in" /></span>
          <span><b>Étendue :</b> <AnswerLine width="1in" /></span>
        </Cols>
      </ExerciseCard>

      <ExerciseCard number={2} tone="orange" consigne="Probabilité — une urne contient 5 boules rouges, 3 bleues, 2 vertes. On tire au hasard.">
        <QInput n={1}>P(rouge) = <AnswerLine width="1in" /></QInput>
        <QInput n={2}>P(non bleue) = <AnswerLine width="1in" /></QInput>
        <QInput n={3}>P(verte ou rouge) = <AnswerLine width="1in" /></QInput>
      </ExerciseCard>
    </PageShell>
  );
}

/* ════════════════════════════════════════════════════════════════════════
   11 · geometry-figure-page — Géométrie générique avec figure
   ════════════════════════════════════════════════════════════════════════ */
function MBGeometry({ density, qrVisible, scoreVisible, scale = 1 }) {
  return (
    <PageShell
      matiere="Mathématiques" niveau="3ᵉ" page={"Chapitre 10 · Page 58"}
      density={density} qrVisible={qrVisible} scoreVisible={scoreVisible}
      qrSlug="AE-3E-MATH-001-2026-V1-P058"
      qrLabel="Correction enrichie"
      scale={scale}
    >
      <PageTitle
        eyebrow="Géométrie · Calcul de longueur"
        title="Le triangle ABC"
        subtitle="Lis l'énoncé deux fois, puis identifie la bonne configuration."
      />

      <Cols ratio="1fr 1fr">
        <FigureBlock label="Figure 1" caption="Triangle ABC rectangle en C." height="2in">
          <div style={{ display: "grid", placeItems: "center", height: "100%", padding: "0.06in" }}>
            <TriangleFigure variant="pythagoras" labels={{ AB: "?", AC: "3 cm", BC: "4 cm" }} />
          </div>
        </FigureBlock>
        <Box tone="cool" label="Données &amp; questions" iconKey="icon-info">
          <ul className="bk-bullets" style={{ marginBottom: "0.06in" }}>
            <li><span className="dot"></span>ABC est rectangle en C</li>
            <li><span className="dot"></span>AC = 3 cm, BC = 4 cm</li>
          </ul>
          <QInput n={1}>Calcule AB.</QInput>
          <QInput n={2}>Le triangle ABC est-il isocèle ? Justifie.</QInput>
        </Box>
      </Cols>

      <ExerciseCard number={1} consigne="Mes calculs.">
        <AnswerBox height="0.7in" ruled />
      </ExerciseCard>

      <Box tone="green" label="Phrase réponse" iconKey="icon-check">
        AB = <AnswerLine width="1in" />, donc <AnswerLine width="2.6in" />.
      </Box>
    </PageShell>
  );
}

/* ════════════════════════════════════════════════════════════════════════
   12 · geometry-theorem-page — Pythagore / Thalès / Trigo (variants)
   ════════════════════════════════════════════════════════════════════════ */
function MBTheorem({ variant = "pythagoras", density, qrVisible, scoreVisible, scale = 1 }) {
  const cfg = {
    "pythagoras": {
      eyebrow: "Théorème de Pythagore",
      title: "Calculer une longueur dans un triangle rectangle",
      page: "Page 60",
      condition: "Si le triangle ABC est rectangle en C…",
      formula: "AB² = AC² + BC²",
      hyp: "AB est l'hypoténuse (opposée à l'angle droit).",
      figLabels: { AB: "?", AC: "5 cm", BC: "12 cm" },
      pitfall: "L'hypoténuse est le côté OPPOSÉ à l'angle droit. Ne jamais confondre.",
      qrSlug: "AE-3E-MATH-001-2026-V1-P060",
    },
    "pythagoras-converse": {
      eyebrow: "Réciproque de Pythagore",
      title: "Démontrer qu'un triangle est rectangle",
      page: "Page 62",
      condition: "Si AB² = AC² + BC², alors le triangle est rectangle en C.",
      formula: "comparer AB²  et  AC² + BC²",
      hyp: "On prend toujours le plus grand côté comme « hypoténuse » candidate.",
      figLabels: { AB: "13 cm", AC: "5 cm", BC: "12 cm" },
      pitfall: "Toujours calculer AB² ET AC² + BC² séparément, puis comparer.",
      qrSlug: "AE-3E-MATH-001-2026-V1-P062",
    },
    "thales": {
      eyebrow: "Théorème de Thalès",
      title: "Reporter des rapports égaux",
      page: "Page 65",
      condition: "Si (MN) // (AB) et O, M, A alignés, O, N, B alignés…",
      formula: "OM/OA = ON/OB = MN/AB",
      hyp: "Trois rapports égaux. On utilise les deux qu'il nous faut.",
      figLabels: {},
      pitfall: "Vérifier l'alignement et le parallélisme avant de poser les rapports.",
      qrSlug: "AE-3E-MATH-001-2026-V1-P065",
    },
    "trigonometry": {
      eyebrow: "Trigonométrie",
      title: "SOH · CAH · TOA",
      page: "Page 68",
      condition: "Dans un triangle rectangle, à partir d'un angle aigu α…",
      formula: "sin α = opp/hyp · cos α = adj/hyp · tan α = opp/adj",
      hyp: "Le côté opposé est en face de l'angle, l'adjacent est à côté de l'angle.",
      figLabels: { AB: "hyp", AC: "adj", BC: "opp", angle: "α" },
      pitfall: "Toujours identifier l'angle de référence avant de nommer les côtés.",
      qrSlug: "AE-3E-MATH-001-2026-V1-P068",
    },
  }[variant];

  const figVariant = variant === "thales" ? "thales" : (variant === "trigonometry" ? "trigonometry" : "pythagoras");

  return (
    <PageShell
      matiere="Mathématiques" niveau="3ᵉ" page={`Chapitre 11 · ${cfg.page}`}
      density={density} qrVisible={qrVisible} scoreVisible={scoreVisible}
      qrSlug={cfg.qrSlug}
      scale={scale}
    >
      <PageTitle
        eyebrow={cfg.eyebrow}
        title={cfg.title}
        subtitle={cfg.hyp}
      />

      <Cols ratio="1fr 1fr">
        <LessonBox title="Condition d'utilisation" iconKey="icon-info">
          {cfg.condition}
        </LessonBox>
        <Box tone="primary" label="Formule" iconKey="icon-sigma">
          <MathExpr display size="0.18in">{cfg.formula}</MathExpr>
        </Box>
      </Cols>

      <Cols ratio="1fr 1.1fr">
        <FigureBlock label="Figure" height="1.8in">
          <div style={{ display: "grid", placeItems: "center", height: "100%", padding: "0.06in" }}>
            <TriangleFigure variant={figVariant} labels={cfg.figLabels} />
          </div>
        </FigureBlock>
        <ExerciseCard number={1} consigne="Exemple guidé — applique la formule.">
          <AnswerBox height="0.85in" ruled />
        </ExerciseCard>
      </Cols>

      <WarningBox title="Erreur à éviter">{cfg.pitfall}</WarningBox>
    </PageShell>
  );
}

/* ════════════════════════════════════════════════════════════════════════
   13 · math-formula-sheet — Formulaire express
   ════════════════════════════════════════════════════════════════════════ */
function MBFormulaSheet({ density, qrVisible, scoreVisible, scale = 1 }) {
  const Row = ({ label, expr, note }) => (
    <div style={{
      display: "grid", gridTemplateColumns: "1.1in 1fr",
      gap: "0.06in", alignItems: "baseline",
      padding: "0.05in 0", borderBottom: "1px dashed var(--ae-border)",
    }}>
      <span style={{ fontSize: "0.105in", color: "var(--ae-text-soft)", fontFamily: "var(--ae-font-title)", fontWeight: 600, textTransform: "uppercase", letterSpacing: "0.04em" }}>{label}</span>
      <span style={{ fontFamily: '"Cambria Math", Georgia, serif', fontSize: "0.135in", fontStyle: "italic" }}>
        {expr}
        {note && <span style={{ marginLeft: "0.08in", color: "var(--ae-text-soft)", fontFamily: "var(--ae-font-body)", fontStyle: "normal", fontSize: "0.1in" }}>· {note}</span>}
      </span>
    </div>
  );
  return (
    <PageShell
      matiere="Mathématiques" niveau="3ᵉ" page={"Formulaire express · Page 79"}
      density={density} qrVisible={qrVisible} scoreVisible={scoreVisible}
      qrSlug="AE-3E-MATH-001-2026-V1-P079"
      qrLabel="Formulaire imprimable"
      scale={scale}
    >
      <PageTitle
        eyebrow="Formulaire express · à connaître par cœur"
        title="Toutes les formules du Brevet"
        subtitle="Affiche-le près de ton bureau. Relis-le 3 fois par semaine."
      />

      <Cols ratio="1fr 1fr">
        <Box tone="cool" label="Calculs &amp; algèbre" iconKey="icon-sigma">
          <Row label="Distrib." expr={<span>k(a + b) = ka + kb</span>} />
          <Row label="Identité" expr={<span>(a + b)² = a² + 2ab + b²</span>} />
          <Row label="Identité" expr={<span>(a + b)(a − b) = a² − b²</span>} />
          <Row label="Puissances" expr={<span>aᵐ × aⁿ = aᵐ⁺ⁿ</span>} />
          <Row label="Puissances" expr={<span>(aᵐ)ⁿ = aᵐⁿ</span>} />
          <Row label="Notation sci." expr={<span>a × 10ⁿ avec 1 ≤ |a| &lt; 10</span>} />
        </Box>
        <Box tone="primary" label="Géométrie" iconKey="icon-section">
          <Row label="Pythagore" expr={<span>BC² = AB² + AC²</span>} note="rectangle en A" />
          <Row label="Thalès" expr={<span>OM/OA = ON/OB = MN/AB</span>} />
          <Row label="Trigo · sin" expr={<span>sin α = opp / hyp</span>} />
          <Row label="Trigo · cos" expr={<span>cos α = adj / hyp</span>} />
          <Row label="Trigo · tan" expr={<span>tan α = opp / adj</span>} />
          <Row label="Aire disque" expr={<span>π × r²</span>} />
        </Box>
      </Cols>

      <Cols ratio="1fr 1fr">
        <Box tone="green" label="Volumes &amp; conversions" iconKey="icon-sigma">
          <Row label="Cube" expr={<span>V = c³</span>} />
          <Row label="Pavé droit" expr={<span>V = L × ℓ × h</span>} />
          <Row label="Cylindre" expr={<span>V = π × r² × h</span>} />
          <Row label="Conversion" expr={<span>1 L = 1 dm³ = 1 000 cm³</span>} />
          <Row label="Conversion" expr={<span>1 m³ = 1 000 dm³ = 1 000 L</span>} />
        </Box>
        <Box tone="neutral" label="Stats / probas + méthode" iconKey="icon-ampoule">
          <Row label="Moyenne" expr={<span>(somme) / (effectif)</span>} />
          <Row label="Médiane" expr={<span>valeur centrale (série rangée)</span>} />
          <Row label="Étendue" expr={<span>max − min</span>} />
          <Row label="Probabilité" expr={<span>P(A) = favorables / possibles</span>} />
          <div style={{ marginTop: "0.06in", fontSize: "0.105in", color: "var(--ae-text-soft)" }}>
            Méthode · lire 2× · vérifier l'unité · faire un schéma · conclure par une phrase.
          </div>
        </Box>
      </Cols>
    </PageShell>
  );
}

/* ════════════════════════════════════════════════════════════════════════
   14 · brevet-mini-exam — Mini-sujet brevet
   ════════════════════════════════════════════════════════════════════════ */
function MBMiniExam({ density, qrVisible, scoreVisible, scale = 1 }) {
  return (
    <PageShell
      matiere="Mathématiques" niveau="3ᵉ" page={"Brevet blanc · Page 84"}
      density={density} qrVisible={qrVisible} scoreVisible={scoreVisible}
      qrSlug="AE-3E-MATH-001-2026-V1-P084"
      qrLabel="Corrigé du sujet"
      qrSubLabel="Barème détaillé"
      scale={scale}
    >
      <PageTitle
        eyebrow="Brevet blanc · Sujet 2"
        title="3 exercices · 45 minutes"
        subtitle="Travaille comme le jour J : lis tout, choisis l'ordre, surveille le temps."
      />

      <Cols ratio="1fr 1fr 1fr">
        <Box tone="primary" label="Temps conseillé" iconKey="icon-horloge">
          <b>45 min.</b> · 15 min par exercice maximum.
        </Box>
        <Box tone="cool" label="Barème" iconKey="icon-section">
          Exo 1 · 5 pts<br/>Exo 2 · 7 pts<br/>Exo 3 · 8 pts<br/><b>Total · 20 pts</b>
        </Box>
        <Box tone="green" label="Stratégie" iconKey="icon-fleche">
          Commence par ce qui te paraît le plus simple. Garde 5 min pour relire.
        </Box>
      </Cols>

      <ExerciseCard number={1} consigne="Calcul · résous l'équation 4(2x − 3) = x + 9.">
        <AnswerBox height="0.55in" ruled />
      </ExerciseCard>

      <ExerciseCard number={2} tone="orange" consigne="Géométrie · ABC rectangle en A, AB = 6 cm, AC = 8 cm. Calcule BC, puis cos B.">
        <AnswerBox height="0.65in" ruled />
      </ExerciseCard>

      <ExerciseCard number={3} consigne="Problème · un commerçant baisse un prix de 15 % puis l'augmente de 15 %. Le prix final est-il le prix initial ? Justifie.">
        <AnswerBox height="0.7in" ruled />
      </ExerciseCard>
    </PageShell>
  );
}

/* ════════════════════════════════════════════════════════════════════════
   15 · math-compact-correction — Correction compacte
   ════════════════════════════════════════════════════════════════════════ */
function MBCompactCorrection({ density, qrVisible, scoreVisible, scale = 1 }) {
  const CorrectionRow = ({ refId, title, steps, answer }) => (
    <div style={{
      padding: "0.08in 0.12in", borderRadius: "0.06in",
      border: "1px solid var(--ae-border)", background: "white",
      display: "grid", gridTemplateColumns: "0.6in 1fr 1fr", gap: "0.1in",
      alignItems: "start",
    }}>
      <div style={{
        fontFamily: "var(--ae-font-title)", fontWeight: 600,
        color: "var(--ae-primary-deep)", fontSize: "0.115in",
        background: "var(--ae-primary-soft)", padding: "0.04in 0.06in",
        borderRadius: "0.04in", textAlign: "center",
      }}>{refId}</div>
      <div>
        <div style={{ fontFamily: "var(--ae-font-title)", fontWeight: 600, fontSize: "0.12in" }}>{title}</div>
        <div style={{ fontFamily: '"Cambria Math", Georgia, serif', fontStyle: "italic", fontSize: "0.115in", color: "var(--ae-text)", lineHeight: 1.5 }}>
          {steps}
        </div>
      </div>
      <div style={{
        fontFamily: '"Cambria Math", Georgia, serif', fontStyle: "italic",
        fontSize: "0.13in", color: "var(--ae-primary-deep)",
        background: "var(--ae-yellow)", padding: "0.06in 0.1in",
        borderRadius: "0.05in",
        display: "flex", alignItems: "center", justifyContent: "flex-start",
      }}>
        <b style={{ fontStyle: "normal", fontFamily: "var(--ae-font-body)", fontSize: "0.1in", marginRight: "0.06in", color: "var(--ae-text)" }}>Réponse</b>
        {answer}
      </div>
    </div>
  );
  return (
    <PageShell
      matiere="Mathématiques" niveau="3ᵉ" page={"Corrections · Page 92"}
      density="dense" qrVisible={qrVisible} scoreVisible={false}
      qrSlug="AE-3E-MATH-001-2026-V1-P092"
      qrLabel="Corrections enrichies en vidéo"
      scale={scale}
    >
      <PageTitle
        eyebrow="Corrections compactes · pages 21 à 28"
        title="Tu vérifies, tu repars."
        subtitle="Étapes essentielles uniquement. Pour les détails, scanne le QR."
      />

      <div style={{ display: "grid", gap: "0.1in" }}>
        <CorrectionRow
          refId="P021"
          title="Calculer 3x + 5 pour x = 4"
          steps="= 3 × 4 + 5 = 12 + 5"
          answer="17"
        />
        <CorrectionRow
          refId="P022"
          title="Réduire 4x + 7 − 2x + 3"
          steps="= (4x − 2x) + (7 + 3) = 2x + 10"
          answer="2x + 10"
        />
        <CorrectionRow
          refId="P024"
          title="Développer 4(2x − 3)"
          steps="= 4 · 2x + 4 · (−3) = 8x − 12"
          answer="8x − 12"
        />
        <CorrectionRow
          refId="P025"
          title="Résoudre 3x + 5 = 17"
          steps="3x = 12  →  x = 4"
          answer="x = 4"
        />
        <CorrectionRow
          refId="P027"
          title="Pythagore · AC = 3, BC = 4"
          steps="AB² = 9 + 16 = 25  →  AB = 5"
          answer="AB = 5 cm"
        />
        <CorrectionRow
          refId="P028"
          title="Probabilité tirage P(rouge)"
          steps="favorables/total = 5/10"
          answer="P = 1/2 = 0,5"
        />
      </div>
    </PageShell>
  );
}

/* ════════════════════════════════════════════════════════════════════════
   16 · solids-volume-page — Solides &amp; volumes (P071-P074)
   ════════════════════════════════════════════════════════════════════════ */
function MBSolidsVolume({ density, qrVisible, scoreVisible, scale = 1 }) {
  const SolidIcon = ({ kind }) => {
    if (kind === "cube") return (
      <svg viewBox="0 0 80 80" width="0.7in" height="0.7in"><polygon points="15,30 50,15 75,30 75,65 40,80 15,65" fill="var(--ae-primary-soft)" stroke="var(--ae-primary-deep)" strokeWidth="1.6"/><polyline points="15,30 40,45 75,30" fill="none" stroke="var(--ae-primary-deep)" strokeWidth="1.4"/><line x1="40" y1="45" x2="40" y2="80" stroke="var(--ae-primary-deep)" strokeWidth="1.4"/></svg>
    );
    if (kind === "pave") return (
      <svg viewBox="0 0 90 80" width="0.8in" height="0.7in"><polygon points="10,30 55,15 85,30 85,60 40,75 10,60" fill="var(--ae-primary-soft)" stroke="var(--ae-primary-deep)" strokeWidth="1.6"/><polyline points="10,30 40,45 85,30" fill="none" stroke="var(--ae-primary-deep)" strokeWidth="1.4"/><line x1="40" y1="45" x2="40" y2="75" stroke="var(--ae-primary-deep)" strokeWidth="1.4"/></svg>
    );
    return (
      <svg viewBox="0 0 80 80" width="0.7in" height="0.7in"><ellipse cx="40" cy="20" rx="25" ry="8" fill="var(--ae-primary-soft)" stroke="var(--ae-primary-deep)" strokeWidth="1.6"/><line x1="15" y1="20" x2="15" y2="60" stroke="var(--ae-primary-deep)" strokeWidth="1.6"/><line x1="65" y1="20" x2="65" y2="60" stroke="var(--ae-primary-deep)" strokeWidth="1.6"/><path d="M 15 60 A 25 8 0 0 0 65 60" fill="var(--ae-primary-soft)" stroke="var(--ae-primary-deep)" strokeWidth="1.6"/><path d="M 15 60 A 25 8 0 0 1 65 60" fill="none" stroke="var(--ae-primary-deep)" strokeWidth="1.4" strokeDasharray="3 3"/></svg>
    );
  };
  const SolidCard = ({ kind, name, formula }) => (
    <div style={{ display: "grid", gridTemplateColumns: "0.9in 1fr", gap: "0.1in", alignItems: "center", padding: "0.08in 0.12in", background: "white", border: "1px solid var(--ae-border)", borderRadius: "0.06in" }}>
      <div style={{ display: "grid", placeItems: "center" }}><SolidIcon kind={kind} /></div>
      <div>
        <div style={{ fontFamily: "var(--ae-font-title)", fontWeight: 600, fontSize: "0.13in", color: "var(--ae-primary-deep)" }}>{name}</div>
        <div style={{ fontFamily: '"Cambria Math", Georgia, serif', fontStyle: "italic", fontSize: "0.13in", marginTop: "0.04in" }}>V = {formula}</div>
      </div>
    </div>
  );
  return (
    <PageShell
      matiere="Mathématiques" niveau="3ᵉ" page={"Chapitre 12 · Page 71"}
      density={density} qrVisible={qrVisible} scoreVisible={scoreVisible}
      qrSlug="AE-3E-MATH-001-2026-V1-P071"
      scale={scale}
    >
      <PageTitle
        eyebrow="Solides &amp; volumes"
        title="Reconnaître un solide, calculer son volume"
        subtitle="Trois solides à connaître pour le brevet — formule + application."
      />

      <Cols ratio="1fr 1fr 1fr">
        <SolidCard kind="cube" name="Cube" formula={<span>c³</span>} />
        <SolidCard kind="pave" name="Pavé droit" formula={<span>L × ℓ × h</span>} />
        <SolidCard kind="cyl"  name="Cylindre"   formula={<span>π × r² × h</span>} />
      </Cols>

      <ExerciseCard number={1} consigne="Calcule le volume — donne le résultat avec l'unité.">
        <QInput n={1}>Cube de côté <b>5 cm</b> : V = <AnswerLine width="1in" /> cm³</QInput>
        <QInput n={2}>Pavé droit <b>4 × 3 × 6 cm</b> : V = <AnswerLine width="1in" /> cm³</QInput>
        <QInput n={3}>Cylindre <b>r = 2 cm, h = 10 cm</b> : V = <AnswerLine width="1.2in" /> cm³</QInput>
      </ExerciseCard>

      <Cols ratio="1fr 1fr">
        <ExerciseCard number={2} tone="orange" consigne="Une boîte cubique a un volume de 64 cm³. Quelle est la longueur de son côté ?">
          <AnswerBox height="0.5in" ruled />
        </ExerciseCard>
        <WarningBox title="Erreur à éviter">
          Le volume d'un cylindre s'écrit <b>π × r² × h</b>, pas <b>π × r × h</b>.
          Pense à <b>élever r au carré</b> avant de multiplier par h.
        </WarningBox>
      </Cols>
    </PageShell>
  );
}

/* ════════════════════════════════════════════════════════════════════════
   17 · volume-units-page — Conversions L / cm³ / dm³ / m³ (P073-P075)
   ════════════════════════════════════════════════════════════════════════ */
function MBVolumeUnits({ density, qrVisible, scoreVisible, scale = 1 }) {
  return (
    <PageShell
      matiere="Mathématiques" niveau="3ᵉ" page={"Chapitre 12 · Page 73"}
      density={density} qrVisible={qrVisible} scoreVisible={scoreVisible}
      qrSlug="AE-3E-MATH-001-2026-V1-P073"
      scale={scale}
    >
      <PageTitle
        eyebrow="Volumes · Unités"
        title="Convertir L, cm³, dm³, m³"
        subtitle="Une seule règle à connaître — et plus aucune erreur."
      />

      <LessonBox title="Les deux égalités à savoir par cœur" iconKey="icon-info" formula="1 L = 1 dm³ = 1 000 cm³   ·   1 m³ = 1 000 dm³ = 1 000 L">
        Le <b>litre</b> est une unité de capacité. Il correspond exactement à
        <b> un dm³ </b>. Pour passer du m³ au cm³, on traverse <b>3 zéros par étage</b>.
      </LessonBox>

      <Box tone="cool" label="Tableau de conversion" iconKey="icon-section">
        <TableBlock
          columns={["m³", "dm³ (= L)", "cm³"]}
          rows={[
            ["1",     "1 000",   "1 000 000"],
            ["0,1",   "100",     "100 000"],
            ["0,001", "1",       "1 000"],
          ]}
        />
      </Box>

      <ExerciseCard number={1} consigne="Convertis.">
        <Cols ratio="1fr 1fr">
          <span><b>2,5 L</b> = <AnswerLine width="0.9in" /> cm³</span>
          <span><b>1 500 cm³</b> = <AnswerLine width="0.9in" /> L</span>
          <span><b>0,75 m³</b> = <AnswerLine width="0.9in" /> L</span>
          <span><b>4 200 mL</b> = <AnswerLine width="0.9in" /> dm³</span>
        </Cols>
      </ExerciseCard>

      <ExerciseCard number={2} tone="orange" consigne="Un aquarium mesure 60 × 30 × 40 cm. Quel est son volume en litres ?">
        <AnswerBox height="0.55in" ruled />
      </ExerciseCard>
    </PageShell>
  );
}

/* ════════════════════════════════════════════════════════════════════════
   18 · geometry-transformations-page — Translation, rotation, sym., agrand. (P076-P078)
   ════════════════════════════════════════════════════════════════════════ */
function MBTransformations({ density, qrVisible, scoreVisible, scale = 1 }) {
  const TransformIcon = ({ kind }) => {
    if (kind === "translation") return (
      <svg viewBox="0 0 90 60" width="1.2in" height="0.8in"><polygon points="10,40 25,40 17,25" fill="var(--ae-primary-soft)" stroke="var(--ae-primary-deep)" strokeWidth="1.5"/><polygon points="55,40 70,40 62,25" fill="none" stroke="var(--ae-primary-deep)" strokeWidth="1.5" strokeDasharray="3 2"/><line x1="20" y1="48" x2="60" y2="48" stroke="var(--ae-orange)" strokeWidth="1.6" markerEnd="url(#arrA)"/><defs><marker id="arrA" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="6" markerHeight="6" orient="auto"><path d="M0,0 L10,5 L0,10 z" fill="var(--ae-orange)"/></marker></defs></svg>
    );
    if (kind === "rotation") return (
      <svg viewBox="0 0 90 60" width="1.2in" height="0.8in"><circle cx="45" cy="30" r="2.5" fill="var(--ae-orange)"/><polygon points="20,15 35,15 27,5" fill="var(--ae-primary-soft)" stroke="var(--ae-primary-deep)" strokeWidth="1.5"/><polygon points="55,45 70,45 62,55" fill="none" stroke="var(--ae-primary-deep)" strokeWidth="1.5" strokeDasharray="3 2"/><path d="M 30 20 A 20 20 0 0 1 60 40" fill="none" stroke="var(--ae-orange)" strokeWidth="1.4" markerEnd="url(#arrB)"/><defs><marker id="arrB" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="6" markerHeight="6" orient="auto"><path d="M0,0 L10,5 L0,10 z" fill="var(--ae-orange)"/></marker></defs></svg>
    );
    if (kind === "symmetry") return (
      <svg viewBox="0 0 90 60" width="1.2in" height="0.8in"><line x1="45" y1="5" x2="45" y2="55" stroke="var(--ae-orange)" strokeWidth="1.6" strokeDasharray="3 2"/><polygon points="15,40 35,40 25,18" fill="var(--ae-primary-soft)" stroke="var(--ae-primary-deep)" strokeWidth="1.5"/><polygon points="55,40 75,40 65,18" fill="none" stroke="var(--ae-primary-deep)" strokeWidth="1.5"/></svg>
    );
    return (
      <svg viewBox="0 0 90 60" width="1.2in" height="0.8in"><polygon points="15,40 28,40 21,28" fill="var(--ae-primary-soft)" stroke="var(--ae-primary-deep)" strokeWidth="1.5"/><polygon points="50,50 80,50 65,18" fill="none" stroke="var(--ae-primary-deep)" strokeWidth="1.5"/><line x1="35" y1="38" x2="50" y2="42" stroke="var(--ae-orange)" strokeWidth="1.4" strokeDasharray="2 2"/></svg>
    );
  };
  const TCard = ({ kind, name, def }) => (
    <div style={{ padding: "0.08in 0.1in", border: "1px solid var(--ae-border)", borderRadius: "0.06in", background: "white" }}>
      <div style={{ display: "grid", placeItems: "center", marginBottom: "0.05in" }}><TransformIcon kind={kind} /></div>
      <div style={{ fontFamily: "var(--ae-font-title)", fontWeight: 600, fontSize: "0.115in", color: "var(--ae-primary-deep)", textAlign: "center" }}>{name}</div>
      <div style={{ fontSize: "0.105in", color: "var(--ae-text-soft)", marginTop: "0.04in", lineHeight: 1.4 }}>{def}</div>
    </div>
  );
  return (
    <PageShell
      matiere="Mathématiques" niveau="3ᵉ" page={"Chapitre 13 · Page 76"}
      density={density} qrVisible={qrVisible} scoreVisible={scoreVisible}
      qrSlug="AE-3E-MATH-001-2026-V1-P076"
      scale={scale}
    >
      <PageTitle
        eyebrow="Transformations géométriques"
        title="Translation, rotation, symétries, homothétie"
        subtitle="Quatre transformations à savoir reconnaître et appliquer."
      />

      <Cols ratio="1fr 1fr 1fr 1fr">
        <TCard kind="translation" name="Translation" def="Déplace la figure dans une direction, sans la tourner." />
        <TCard kind="rotation"    name="Rotation"    def="Tourne la figure autour d'un centre selon un angle." />
        <TCard kind="symmetry"    name="Symétrie axiale" def="Réfléchit la figure par rapport à un axe (effet miroir)." />
        <TCard kind="homothety"   name="Homothétie"  def="Agrandit ou réduit la figure d'un rapport k." />
      </Cols>

      <Box tone="primary" label="Effets sur les longueurs et les angles" iconKey="icon-info">
        Translation, rotation et symétrie <b>conservent</b> longueurs et angles.
        L'<b>homothétie de rapport k</b> multiplie les longueurs par |k| et conserve les angles.
      </Box>

      <ExerciseCard number={1} consigne="Pour chaque énoncé, identifie la transformation utilisée.">
        <QInput n={1}>Le triangle A'B'C' est l'image de ABC après un glissement de 3 cm vers la droite. → <AnswerLine width="1.5in" /></QInput>
        <QInput n={2}>Une figure est réfléchie par rapport à une droite. → <AnswerLine width="1.5in" /></QInput>
        <QInput n={3}>Une photo est agrandie 2 fois. → <AnswerLine width="1.5in" /></QInput>
        <QInput n={4}>Une horloge tourne autour de son axe central. → <AnswerLine width="1.5in" /></QInput>
      </ExerciseCard>

      <ExerciseCard number={2} tone="orange" consigne="ABC a une aire de 12 cm². Une homothétie de rapport k = 3 donne A'B'C'. Quelle est l'aire de A'B'C' ?">
        <AnswerBox height="0.45in" ruled />
      </ExerciseCard>
    </PageShell>
  );
}

/* ════════════════════════════════════════════════════════════════════════
   19 · algorithm-tableur-page — Scratch / programmes de calcul / tableur (P078-P080)
   ════════════════════════════════════════════════════════════════════════ */
function MBAlgoTableur({ density, qrVisible, scoreVisible, scale = 1 }) {
  const propCellHead = { padding: "0.07in 0.1in", fontFamily: "var(--ae-font-title)", fontWeight: 600, textAlign: "center", color: "var(--ae-primary-deep)" };
  const propCell = { padding: "0.08in 0.1in", textAlign: "center", fontFamily: '"Cambria Math", Georgia, serif', fontStyle: "italic" };
  const ScratchBlock = ({ kind, children }) => {
    const colors = {
      event: { bg: "#FFB22A", fg: "#3A2700" },
      ctrl:  { bg: "#FFA13F", fg: "#3A2700" },
      op:    { bg: "#59C059", fg: "#0F2E0F" },
      var:   { bg: "#FF8C1A", fg: "#3A2700" },
    }[kind] || { bg: "#4C97FF", fg: "white" };
    return (
      <div style={{
        background: colors.bg, color: colors.fg,
        padding: "0.05in 0.12in", borderRadius: "0.05in",
        fontFamily: "var(--ae-font-title)", fontWeight: 600,
        fontSize: "0.105in", marginBottom: "0.04in",
        display: "inline-block", boxShadow: "0 1px 0 rgba(0,0,0,.15)",
      }}>{children}</div>
    );
  };
  return (
    <PageShell
      matiere="Mathématiques" niveau="3ᵉ" page={"Chapitre 14 · Page 78"}
      density={density} qrVisible={qrVisible} scoreVisible={scoreVisible}
      qrSlug="AE-3E-MATH-001-2026-V1-P078"
      qrLabel="Programme Scratch en ligne"
      scale={scale}
    >
      <PageTitle
        eyebrow="Algorithmique &amp; tableur"
        title="Programmes de calcul, Scratch, formules"
        subtitle="Lire un programme, prévoir le résultat, traduire en formule tableur."
      />

      <Cols ratio="1fr 1.2fr">
        <Box tone="cool" label="Programme de calcul" iconKey="icon-section">
          <ol style={{ margin: 0, paddingLeft: "0.2in", fontSize: "var(--ae-fs-body)", lineHeight: 1.55 }}>
            <li>Choisir un nombre.</li>
            <li>Le multiplier par <b>3</b>.</li>
            <li>Ajouter <b>5</b>.</li>
            <li>Soustraire le nombre choisi.</li>
            <li>Annoncer le résultat.</li>
          </ol>
          <div style={{ marginTop: "0.06in", fontSize: "var(--ae-fs-body)" }}>
            <b>Q1.</b> Avec <b>4</b>, on obtient : <AnswerLine width="0.8in" /><br/>
            <b>Q2.</b> Avec <b>x</b>, on obtient : <AnswerLine width="1.5in" />
          </div>
        </Box>
        <Box tone="primary" label="Le même programme en Scratch" iconKey="icon-info">
          <ScratchBlock kind="event">quand drapeau cliqué</ScratchBlock>
          <ScratchBlock kind="var">demander &laquo;&nbsp;Choisis un nombre&nbsp;&raquo; et attendre</ScratchBlock>
          <ScratchBlock kind="var">mettre n à : réponse</ScratchBlock>
          <ScratchBlock kind="op">mettre résultat à : (n × 3) + 5 − n</ScratchBlock>
          <ScratchBlock kind="event">dire (résultat)</ScratchBlock>
        </Box>
      </Cols>

      <Box tone="green" label="Tableur — formule à saisir en B2" iconKey="icon-fleche">
        <div style={{ display: "grid", gridTemplateColumns: "1fr 1.4fr 1fr", gap: 0, border: "1.5px solid var(--ae-text)", borderRadius: "0.05in", overflow: "hidden", fontFamily: '"Cambria Math", Georgia, serif', fontSize: "0.13in" }}>
          <div style={{ ...propCellHead, background: "var(--ae-primary-soft)", borderRight: "1px solid var(--ae-text-soft)" }}>A</div>
          <div style={{ ...propCellHead, background: "var(--ae-primary-soft)", borderRight: "1px solid var(--ae-text-soft)" }}>B</div>
          <div style={{ ...propCellHead, background: "var(--ae-primary-soft)" }}>C</div>
          <div style={{ ...propCell, borderTop: "1px solid var(--ae-text-soft)", borderRight: "1px solid var(--ae-text-soft)" }}>n</div>
          <div style={{ ...propCell, borderTop: "1px solid var(--ae-text-soft)", borderRight: "1px solid var(--ae-text-soft)" }}>résultat</div>
          <div style={{ ...propCell, borderTop: "1px solid var(--ae-text-soft)" }}>vérif.</div>
          <div style={{ ...propCell, borderTop: "1px solid var(--ae-text-soft)", borderRight: "1px solid var(--ae-text-soft)" }}>4</div>
          <div style={{ ...propCell, borderTop: "1px solid var(--ae-text-soft)", borderRight: "1px solid var(--ae-text-soft)", color: "var(--ae-primary-deep)" }}>= A2 * 3 + 5 − A2</div>
          <div style={{ ...propCell, borderTop: "1px solid var(--ae-text-soft)" }}><AnswerLine width="0.6in" /></div>
        </div>
      </Box>

      <ExerciseCard number={1} tone="orange" consigne="Démontre que ce programme produit toujours 2n + 5.">
        <AnswerBox height="0.5in" ruled />
      </ExerciseCard>
    </PageShell>
  );
}

// Variant exports — for the 4 theorem variants, build small wrappers
function MBPythagoras(p)        { return <MBTheorem {...p} variant="pythagoras" />; }
function MBPythagorasConverse(p){ return <MBTheorem {...p} variant="pythagoras-converse" />; }
function MBThales(p)            { return <MBTheorem {...p} variant="thales" />; }
function MBTrigonometry(p)      { return <MBTheorem {...p} variant="trigonometry" />; }

Object.assign(window, {
  MBLessonExercise, MBProgressive, MBGuidedProblem, MBGridPractice, MBQCM,
  MBAlgebra, MBProportionality, MBPercentage, MBFunctions, MBStatsProba,
  MBGeometry, MBTheorem, MBPythagoras, MBPythagorasConverse, MBThales, MBTrigonometry,
  MBSolidsVolume, MBVolumeUnits, MBTransformations, MBAlgoTableur,
  MBFormulaSheet, MBMiniExam, MBCompactCorrection,
});
