// template-pack-5-primaire.jsx
// PACK 5 · PRIMAIRE CP / CE1 / CE2 — Allo Education Books v1.2
// 12 templates imprimables, lisibles, doux mais pas bébé.
// Toutes les pages passent par <PageShell>. Aucun header/footer recréé.
// Pas d'emoji. Toutes icônes via <Icon /> ou iconKey. Pilotables par data.

/* ════════════════════════════════════════════════════════════════════════
   Helpers locaux primaire — gros caractères, lignes Seyès, cases larges.
   ════════════════════════════════════════════════════════════════════════ */

function P5BigConsigne({ children }) {
  return (
    <div style={{
      fontFamily: "var(--ae-font-title)", fontWeight: 600,
      fontSize: "0.18in", lineHeight: 1.35,
      color: "var(--ae-primary-deep)",
      padding: "0.1in 0.14in",
      background: "var(--ae-primary-soft)",
      borderLeft: "4px solid var(--ae-primary)",
      borderRadius: "0 0.08in 0.08in 0",
    }}>{children}</div>
  );
}

function P5WriteBox({ height = "0.6in", width = "100%", style }) {
  return <div style={{
    width, height,
    border: "1.5px solid var(--ae-text-soft)",
    borderRadius: "0.06in",
    background: "white",
    ...style,
  }} />;
}

// Seyès lined writing area (3-line writing rows)
function SeyesLines({ rows = 3, height = "0.45in", marginTop = "0.06in" }) {
  return (
    <div style={{
      display: "flex", flexDirection: "column", gap: marginTop,
    }}>
      {Array.from({ length: rows }).map((_, i) => (
        <svg key={i} viewBox="0 0 800 60" preserveAspectRatio="none"
          style={{ width: "100%", height, display: "block" }}>
          {/* main baseline */}
          <line x1="0" y1="44" x2="800" y2="44" stroke="var(--ae-primary)" strokeWidth="1.4" />
          {/* x-height */}
          <line x1="0" y1="28" x2="800" y2="28" stroke="var(--ae-border)" strokeWidth="1" strokeDasharray="3 3" />
          {/* ascender */}
          <line x1="0" y1="10" x2="800" y2="10" stroke="var(--ae-border)" strokeWidth="1" />
          {/* descender */}
          <line x1="0" y1="56" x2="800" y2="56" stroke="var(--ae-border)" strokeWidth="1" />
        </svg>
      ))}
    </div>
  );
}

function P5Star() {
  return <Icon k="icon-etoile" style={{ color: "var(--ae-yellow-dark)" }} />;
}

function P5LetterTile({ children, big = false, tone = "primary" }) {
  const c = tone === "orange" ? "var(--ae-orange)" : tone === "yellow" ? "var(--ae-yellow-dark)" : "var(--ae-primary)";
  return (
    <span style={{
      display: "grid", placeItems: "center",
      width: big ? "0.6in" : "0.4in",
      height: big ? "0.6in" : "0.4in",
      borderRadius: "0.1in",
      border: `2px solid ${c}`,
      background: "white",
      fontFamily: "var(--ae-font-title)", fontWeight: 700,
      fontSize: big ? "0.36in" : "0.22in",
      color: c, lineHeight: 1,
    }}>{children}</span>
  );
}

/* ════════════════════════════════════════════════════════════════════════
   1 · FICHE SON / SYLLABES (template: "phonics-syllables-sheet")
   ════════════════════════════════════════════════════════════════════════ */

function P1Phonics({ density, qrVisible, scoreVisible, scale = 1 }) {
  const son = "ou";
  const syllabes = ["chou", "fou", "mou", "tou", "bou", "dou", "lou", "rou"];
  const motsExemples = [
    { mot: "loup",  img: "loup" },
    { mot: "poule", img: "poule" },
    { mot: "roue",  img: "roue" },
    { mot: "douche",img: "douche" },
  ];
  const phrases = [
    "Le loup a une grosse bouche.",
    "La poule cache ses poussins.",
    "J'aime jouer avec ma toupie.",
  ];
  const items = ["bateau", "boule", "souris", "papa", "rouge", "table", "chouette", "lit"];

  return (
    <PageShell
      matiere="Lecture" niveau="CP" page={"Sons · Page 4"}
      density={density} qrVisible={qrVisible} scoreVisible={scoreVisible}
      qrSlug="cp-lecture-son-ou"
      qrLabel="Écouter le son" qrSubLabel="Audio Ketty"
      scale={scale}
    >
      <PageTitle
        eyebrow="Le son du jour"
        title={`Le son [ ${son} ]`}
        subtitle="Je lis, j'entoure, je dis à voix haute. Ketty m'écoute."
      />

      {/* Hero son */}
      <div style={{
        display: "grid", gridTemplateColumns: "1.5in 1fr",
        gap: "0.16in", alignItems: "center",
        padding: "0.16in 0.18in",
        background: "var(--ae-yellow-soft)",
        border: "2px solid var(--ae-yellow-dark)",
        borderRadius: "var(--ae-r-lg)",
      }}>
        <div style={{
          display: "grid", placeItems: "center",
          width: "1.5in", height: "1.5in",
          borderRadius: "999px",
          background: "white",
          border: "3px solid var(--ae-yellow-dark)",
          fontFamily: "var(--ae-font-title)", fontWeight: 700,
          fontSize: "0.85in", color: "var(--ae-primary-deep)",
          letterSpacing: "0.02em",
        }}>{son}</div>
        <div>
          <div style={{
            fontSize: "var(--ae-fs-eyebrow)", textTransform: "uppercase",
            letterSpacing: "0.08em", color: "var(--ae-orange-dark)", fontWeight: 800,
            marginBottom: "0.04in",
          }}>S'écrit</div>
          <div style={{ display: "flex", gap: "0.1in", flexWrap: "wrap" }}>
            <P5LetterTile big tone="orange">o</P5LetterTile>
            <P5LetterTile big tone="orange">u</P5LetterTile>
            <span style={{ alignSelf: "center", fontSize: "0.32in", color: "var(--ae-text-soft)" }}>=</span>
            <P5LetterTile big tone="primary">{son}</P5LetterTile>
          </div>
        </div>
      </div>

      {/* Syllabes */}
      <ExerciseCard number={1} consigne="Je lis chaque syllabe à voix haute.">
        <div style={{ display: "flex", flexWrap: "wrap", gap: "0.12in" }}>
          {syllabes.map(s => {
            const head = s.slice(0, s.length - 2);
            return (
              <span key={s} style={{
                padding: "0.12in 0.2in",
                borderRadius: "0.12in",
                background: "white",
                border: "2px solid var(--ae-primary)",
                fontFamily: "var(--ae-font-title)", fontWeight: 600,
                fontSize: "0.26in", color: "var(--ae-primary-deep)",
                minWidth: "0.9in", textAlign: "center",
              }}>
                <span>{head}</span>
                <span style={{ color: "var(--ae-orange)" }}>{son}</span>
              </span>
            );
          })}
        </div>
      </ExerciseCard>

      {/* Mots exemples + entoure */}
      <Cols ratio="1fr 1fr" gap="0.18in">
        <Box tone="primary" label="Mots-images" iconKey="icon-loupe">
          <div style={{
            display: "grid", gridTemplateColumns: "1fr 1fr",
            gap: "0.1in",
          }}>
            {motsExemples.map(m => (
              <div key={m.mot} style={{
                display: "flex", flexDirection: "column", gap: "0.06in",
                padding: "0.06in",
                background: "white",
                border: "1.5px solid var(--ae-primary)",
                borderRadius: "0.08in",
              }}>
                <div style={{
                  height: "0.7in", borderRadius: "0.06in",
                  background: "var(--ae-primary-soft)",
                  display: "grid", placeItems: "center",
                  fontSize: "var(--ae-fs-eyebrow)",
                  color: "var(--ae-primary)",
                  textTransform: "uppercase", letterSpacing: "0.06em",
                  fontFamily: "var(--ae-font-title)", fontWeight: 700,
                }}>image · {m.img}</div>
                <div style={{
                  textAlign: "center",
                  fontFamily: "var(--ae-font-title)", fontWeight: 600,
                  fontSize: "0.18in", color: "var(--ae-primary-deep)",
                }}>{m.mot}</div>
              </div>
            ))}
          </div>
        </Box>

        <ExerciseCard number={2} tone="orange" consigne="J'entoure le son [ou ] dans chaque mot.">
          <div style={{
            display: "grid", gridTemplateColumns: "1fr 1fr",
            rowGap: "0.1in", columnGap: "0.16in",
            fontSize: "0.2in",
            fontFamily: "var(--ae-font-title)", fontWeight: 600,
            color: "var(--ae-text)",
          }}>
            {items.map(w => <span key={w}>{w}</span>)}
          </div>
        </ExerciseCard>
      </Cols>

      {/* Lecture à voix haute */}
      <ExerciseCard number={3} tone="green" iconKey="icon-cible" consigne="Je lis chaque phrase à voix haute. Je coche quand c'est lu sans erreur.">
        <div style={{ display: "flex", flexDirection: "column", gap: "0.08in" }}>
          {phrases.map((p, i) => (
            <div key={i} style={{
              display: "grid", gridTemplateColumns: "0.32in 1fr 0.4in",
              alignItems: "center", gap: "0.1in",
              padding: "0.06in 0.04in",
              borderTop: i > 0 ? "1px dashed var(--ae-border)" : "none",
            }}>
              <P5Star />
              <span style={{ fontSize: "0.18in" }}>{p}</span>
              <span style={{
                width: "0.3in", height: "0.3in",
                border: "1.5px solid var(--ae-success)",
                borderRadius: "0.05in", background: "white",
              }} />
            </div>
          ))}
        </div>
      </ExerciseCard>

      <KettyBubble pose="hello" tone="primary" label="Ketty">
        Si je bloque sur un mot, je le découpe en syllabes : <b>ch-ou</b>, <b>p-ou-le</b>.
      </KettyBubble>
    </PageShell>
  );
}

/* ════════════════════════════════════════════════════════════════════════
   2 · LECTURE DE MOTS (template: "word-reading-sheet")
   ════════════════════════════════════════════════════════════════════════ */

function ColoredSyllableWord({ parts }) {
  // parts = [["ch", "p"], ["a", "o"]…] — alternating colored syllables
  const colors = ["var(--ae-primary)", "var(--ae-orange)"];
  return (
    <span style={{
      fontFamily: "var(--ae-font-title)", fontWeight: 600,
      fontSize: "0.22in", letterSpacing: "0.01em",
      whiteSpace: "nowrap",
    }}>
      {parts.map((p, i) => (
        <span key={i} style={{ color: colors[i % 2] }}>{p}</span>
      ))}
    </span>
  );
}

function P2WordReading({ density, qrVisible, scoreVisible, scale = 1 }) {
  const niveaux = [
    {
      lab: "Niveau 1 — mots de 2 syllabes", tone: "primary",
      mots: [
        ["ma", "ma"], ["pa", "pi"], ["pi", "pa"],
        ["ba", "teau"], ["ca", "deau"], ["pou", "le"],
      ],
    },
    {
      lab: "Niveau 2 — mots de 3 syllabes", tone: "orange",
      mots: [
        ["pa", "pil", "lon"], ["cho", "co", "lat"], ["te", "lé", "phone"],
        ["a", "ni", "mal"], ["mu", "si", "que"], ["bi", "ci", "clette"],
      ],
    },
    {
      lab: "Niveau 3 — mots plus longs", tone: "yellow",
      mots: [
        ["or", "di", "na", "teur"], ["pa", "ra", "pluie"],
        ["di", "no", "saure"], ["é", "lec", "tri", "que"],
      ],
    },
  ];
  const phrase = ["Le", "petit", "papillon", "vole", "vers", "le", "soleil."];

  return (
    <PageShell
      matiere="Lecture" niveau="CP — CE1" page={"Lecture · Page 8"}
      density={density} qrVisible={qrVisible} scoreVisible={scoreVisible}
      qrSlug="cp-ce1-lecture-mots"
      qrLabel="Écouter et corriger"
      scale={scale}
    >
      <PageTitle
        eyebrow="Lecture de mots · 3 niveaux"
        title="Je lis de plus en plus loin"
        subtitle="Les syllabes sont colorées pour m'aider. Je lis lentement, puis de plus en plus vite."
      />

      <div style={{ display: "flex", flexDirection: "column", gap: "0.16in" }}>
        {niveaux.map((n, i) => (
          <Box key={i} tone={n.tone} label={n.lab} iconKey="icon-cible">
            <div style={{
              display: "grid", gridTemplateColumns: "1fr 1fr 1fr",
              rowGap: "0.12in", columnGap: "0.16in",
              padding: "0.04in 0",
            }}>
              {n.mots.map((parts, j) => (
                <div key={j} style={{ display: "flex", alignItems: "center", gap: "0.1in" }}>
                  <ColoredSyllableWord parts={parts} />
                </div>
              ))}
            </div>
          </Box>
        ))}
      </div>

      <ExerciseCard number={1} tone="green" consigne="Je lis chaque mot et je coche selon ma confiance.">
        <div style={{
          display: "grid",
          gridTemplateColumns: "1fr 1in 1in 1in",
          rowGap: "0.06in", columnGap: "0.1in",
          alignItems: "center", fontSize: "0.16in",
        }}>
          <div className="bk-col-head">Mot</div>
          <div className="bk-col-head" style={{ textAlign: "center" }}>Lu seul</div>
          <div className="bk-col-head" style={{ textAlign: "center" }}>Avec aide</div>
          <div className="bk-col-head" style={{ textAlign: "center" }}>À retravailler</div>
          {["papillon", "ordinateur", "bicyclette", "dinosaure"].map(w => (
            <div key={w} style={{ display: "contents" }}>
              <span style={{ fontFamily: "var(--ae-font-title)", fontWeight: 600, fontSize: "0.2in" }}>{w}</span>
              {[0, 1, 2].map(i => (
                <div key={i} style={{ display: "grid", placeItems: "center" }}>
                  <span style={{
                    width: "0.34in", height: "0.34in", borderRadius: "0.06in",
                    border: "1.5px solid var(--ae-primary)",
                    background: "white",
                  }} />
                </div>
              ))}
            </div>
          ))}
        </div>
      </ExerciseCard>

      <Box tone="primary" label="Phrase mystère" iconKey="icon-loupe">
        <div style={{
          display: "flex", flexWrap: "wrap", gap: "0.1in", padding: "0.06in 0",
        }}>
          {phrase.map((w, i) => (
            <span key={i} style={{
              padding: "0.06in 0.14in",
              background: i % 2 ? "var(--ae-orange-soft)" : "var(--ae-primary-soft)",
              border: `1.5px solid ${i % 2 ? "var(--ae-orange)" : "var(--ae-primary)"}`,
              borderRadius: "0.08in",
              fontFamily: "var(--ae-font-title)", fontWeight: 600,
              fontSize: "0.22in",
              color: i % 2 ? "var(--ae-orange-dark)" : "var(--ae-primary-deep)",
            }}>{w}</span>
          ))}
        </div>
      </Box>

      <ScoreBox label="Confiance globale" message="Je colorie 1, 2 ou 3 étoiles selon ma lecture." />
    </PageShell>
  );
}

/* ════════════════════════════════════════════════════════════════════════
   3 · LECTURE COMPRÉHENSION COURTE (template: "primary-reading-comprehension")
   ════════════════════════════════════════════════════════════════════════ */

function P3PrimaryReading({ density, qrVisible, scoreVisible, scale = 1 }) {
  const text = [
    "Lila a un petit chat qui s'appelle Mistou.",
    "Il est gris et blanc, avec une tache noire sur le museau.",
    "Chaque matin, Mistou suit Lila jusqu'à la porte de l'école.",
    "Il l'attend ensuite sur le mur du jardin, près du grand cerisier.",
    "Quand Lila revient à 17 heures, Mistou saute pour lui dire bonjour.",
    "Le soir, ils regardent ensemble la lune par la fenêtre du salon.",
  ];
  const questions = [
    ["Comment s'appelle le chat de Lila ?", true],
    ["De quelle couleur est Mistou ?", true],
    ["Où Mistou attend-il Lila pendant l'école ?", true],
    ["À quelle heure Lila rentre-t-elle ?", true],
  ];
  const colorChoices = [
    "Mistou est un chien.",
    "Mistou est un chat.",
    "Mistou est un oiseau.",
  ];

  return (
    <PageShell
      matiere="Français" niveau="CE1" page={"Lecture · Page 12"}
      density={density} qrVisible={qrVisible} scoreVisible={scoreVisible}
      qrSlug="ce1-comprehension-mistou"
      qrLabel="Écouter le texte" qrSubLabel="Audio Ketty"
      scale={scale}
    >
      <PageTitle
        eyebrow="Lecture &amp; compréhension"
        title="Mistou, le chat de Lila"
        subtitle="Je lis le texte deux fois, puis je réponds aux questions."
      />

      <Box tone="cream" label="Mon texte du jour" iconKey="icon-livre">
        <div style={{
          fontSize: "0.2in", lineHeight: 1.6,
          fontFamily: "var(--ae-font-body)",
          color: "var(--ae-text)",
          padding: "0.06in 0",
        }}>
          {text.map((l, i) => <div key={i}>{l}</div>)}
        </div>
      </Box>

      <ExerciseCard number={1} consigne="Je réponds aux questions par une phrase complète.">
        <div style={{ display: "flex", flexDirection: "column", gap: "0.1in" }}>
          {questions.map(([q], i) => (
            <div key={i} style={{
              display: "flex", flexDirection: "column", gap: "0.04in",
              paddingTop: i > 0 ? "0.06in" : 0,
              borderTop: i > 0 ? "1px dashed var(--ae-border)" : "none",
            }}>
              <div style={{
                display: "flex", gap: "0.08in", alignItems: "baseline",
                fontSize: "0.17in",
              }}>
                <span style={{
                  fontFamily: "var(--ae-font-title)", fontWeight: 700,
                  color: "var(--ae-primary)", minWidth: "0.3in",
                }}>{i + 1}.</span>
                <span>{q}</span>
              </div>
              <SeyesLines rows={1} height="0.42in" />
            </div>
          ))}
        </div>
      </ExerciseCard>

      <Cols ratio="1fr 1fr" gap="0.16in">
        <ExerciseCard number={2} tone="orange" consigne="Je colorie la bonne réponse.">
          <div style={{ display: "flex", flexDirection: "column", gap: "0.08in" }}>
            {colorChoices.map((c, i) => (
              <div key={i} style={{
                display: "flex", alignItems: "center", gap: "0.1in",
                padding: "0.08in 0.12in",
                background: "white",
                border: "1.5px solid var(--ae-orange)",
                borderRadius: "0.1in",
                fontSize: "0.16in",
              }}>
                <span style={{
                  width: "0.26in", height: "0.26in", borderRadius: "999px",
                  border: "1.5px solid var(--ae-orange)", background: "white",
                  flex: "0 0 auto",
                }} />
                {c}
              </div>
            ))}
          </div>
        </ExerciseCard>

        <ExerciseCard number={3} tone="green" iconKey="icon-crayon" consigne="Je recopie la phrase ci-dessous en soignant mon écriture.">
          <div style={{
            fontFamily: "var(--ae-font-title)", fontWeight: 600,
            fontSize: "0.18in", color: "var(--ae-primary-deep)",
            marginBottom: "0.08in",
          }}>« Mistou attend Lila sur le mur du jardin. »</div>
          <SeyesLines rows={2} height="0.42in" />
        </ExerciseCard>
      </Cols>
    </PageShell>
  );
}

/* ════════════════════════════════════════════════════════════════════════
   4 · ÉCRITURE / GRAPHISME (template: "handwriting-practice")
   ════════════════════════════════════════════════════════════════════════ */

function P4Handwriting({ density, qrVisible, scoreVisible, scale = 1 }) {
  const lettre = "a";
  return (
    <PageShell
      matiere="Écriture" niveau="CP" page={"Écriture · Page 6"}
      density={density} qrVisible={qrVisible} scoreVisible={scoreVisible}
      qrSlug="cp-ecriture-lettre-a"
      qrLabel="Voir le tracé animé"
      scale={scale}
    >
      <PageTitle
        eyebrow="Écriture cursive"
        title={`La lettre ${lettre}`}
        subtitle="Je trace, je copie, je soigne. Mon crayon ne quitte pas la ligne avant la fin."
      />

      <Cols ratio="1fr 1fr 1fr" gap="0.12in">
        <Box tone="primary" label="Cursive" iconKey="icon-crayon">
          <div style={{
            display: "grid", placeItems: "center",
            height: "1in",
            fontFamily: "Lora, serif", fontStyle: "italic",
            fontSize: "0.7in", color: "var(--ae-primary-deep)",
            fontWeight: 500,
          }}>{lettre}</div>
        </Box>
        <Box tone="orange" label="Script" iconKey="icon-crayon">
          <div style={{
            display: "grid", placeItems: "center",
            height: "1in",
            fontFamily: "var(--ae-font-body)",
            fontSize: "0.7in", color: "var(--ae-orange-dark)",
            fontWeight: 700,
          }}>{lettre}</div>
        </Box>
        <Box tone="yellow" label="Majuscule" iconKey="icon-crayon">
          <div style={{
            display: "grid", placeItems: "center",
            height: "1in",
            fontFamily: "var(--ae-font-title)",
            fontSize: "0.7in", color: "var(--ae-primary-deep)",
            fontWeight: 700,
          }}>{lettre.toUpperCase()}</div>
        </Box>
      </Cols>

      <ExerciseCard number={1} consigne="Je repasse sur le modèle, puis je continue tout seul jusqu'au bout de la ligne.">
        <div style={{
          fontFamily: "Lora, serif", fontStyle: "italic",
          fontSize: "0.4in", color: "var(--ae-text-soft)",
          letterSpacing: "0.3in",
          paddingLeft: "0.06in",
          marginBottom: "0.04in",
        }}>{`${lettre} ${lettre} ${lettre}`}</div>
        <SeyesLines rows={3} height="0.5in" />
      </ExerciseCard>

      <ExerciseCard number={2} tone="orange" consigne="Je copie ces mots en cursive, en respectant la taille des lettres.">
        <div style={{
          display: "flex", gap: "0.16in", flexWrap: "wrap",
          fontFamily: "Lora, serif", fontStyle: "italic",
          fontSize: "0.26in", color: "var(--ae-primary-deep)",
          marginBottom: "0.06in",
        }}>
          <span>ami</span><span>papa</span><span>maman</span><span>arbre</span>
        </div>
        <SeyesLines rows={3} height="0.5in" />
      </ExerciseCard>

      <ExerciseCard number={3} tone="green" iconKey="icon-cible" consigne="Je copie cette phrase en faisant ma plus belle écriture.">
        <div style={{
          fontFamily: "Lora, serif", fontStyle: "italic", fontWeight: 500,
          fontSize: "0.22in", color: "var(--ae-primary-deep)",
          marginBottom: "0.08in",
        }}>« Anna et Adam jouent dans le jardin. »</div>
        <SeyesLines rows={2} height="0.5in" />
      </ExerciseCard>

      <Cols ratio="1.4fr 1fr">
        <Box tone="cool" label="Auto-check" iconKey="icon-trophee">
          <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", rowGap: "0.06in", columnGap: "0.16in", fontSize: "0.16in" }}>
            {[
              "Je tiens bien mon crayon.",
              "Mes lettres touchent la ligne.",
              "Je laisse une espace entre chaque mot.",
              "Mon cahier est propre.",
            ].map((c, i) => (
              <span key={i} style={{ display: "flex", alignItems: "center", gap: "0.08in" }}>
                <span style={{ width: "0.22in", height: "0.22in", border: "1.5px solid var(--ae-primary)", borderRadius: "0.04in", background: "white", flex: "0 0 auto" }} />
                {c}
              </span>
            ))}
          </div>
        </Box>
        <KettyBubble pose="thumbsup" tone="yellow" label="Astuce">
          Je m'arrête, je souffle, je regarde le modèle, puis je trace.
        </KettyBubble>
      </Cols>
    </PageShell>
  );
}

/* ════════════════════════════════════════════════════════════════════════
   5 · DICTÉE PRÉPARÉE (template: "primary-spelling-dictation")
   ════════════════════════════════════════════════════════════════════════ */

function P5Dictation({ density, qrVisible, scoreVisible, scale = 1 }) {
  const mots = [
    { mot: "écureuil", piege: "il finit par -euil" },
    { mot: "feuille",  piege: "le e après f, et le 2 l" },
    { mot: "automne",  piege: "le m muet" },
    { mot: "branche",  piege: "le n avant le ch" },
    { mot: "grimper",  piege: "i avant m" },
    { mot: "champignon", piege: "ch + gn" },
  ];
  return (
    <PageShell
      matiere="Français" niveau="CE2" page={"Dictée · Page 9"}
      density={density} qrVisible={qrVisible} scoreVisible={scoreVisible}
      qrSlug="ce2-dictee-foret"
      qrLabel="Écouter la dictée" qrSubLabel="Audio Ketty"
      scale={scale}
    >
      <PageTitle
        eyebrow="Dictée préparée · La forêt en automne"
        title="J'observe, je m'entraîne, j'écris"
        subtitle="6 mots à observer avant la dictée. Je repère les pièges, puis j'écoute et j'écris."
      />

      <Box tone="primary" label="Mots à observer" iconKey="icon-loupe">
        <div style={{
          display: "grid", gridTemplateColumns: "1fr 1fr",
          rowGap: "0.08in", columnGap: "0.18in",
        }}>
          {mots.map((m, i) => (
            <div key={i} style={{ display: "flex", alignItems: "baseline", gap: "0.1in" }}>
              <span style={{
                fontFamily: "var(--ae-font-title)", fontWeight: 700,
                fontSize: "0.22in", color: "var(--ae-primary-deep)",
                minWidth: "1.4in",
              }}>{m.mot}</span>
              <span style={{
                fontSize: "0.13in", color: "var(--ae-orange-dark)",
                fontStyle: "italic",
              }}>piège : {m.piege}</span>
            </div>
          ))}
        </div>
      </Box>

      <ExerciseCard number={1} tone="orange" iconKey="icon-crayon" consigne="Je recopie chaque mot 2 fois pour bien le mémoriser.">
        <div style={{ display: "flex", flexDirection: "column", gap: "0.06in" }}>
          {mots.slice(0, 4).map((m, i) => (
            <div key={i} style={{
              display: "grid", gridTemplateColumns: "1.6in 1fr 1fr",
              alignItems: "center", gap: "0.1in",
              padding: "0.04in 0",
              borderTop: i > 0 ? "1px dashed var(--ae-border)" : "none",
            }}>
              <span style={{
                fontFamily: "var(--ae-font-title)", fontWeight: 700,
                fontSize: "0.19in", color: "var(--ae-primary)",
              }}>{m.mot}</span>
              <P5WriteBox height="0.4in" />
              <P5WriteBox height="0.4in" />
            </div>
          ))}
        </div>
      </ExerciseCard>

      <ExerciseCard number={2} tone="green" iconKey="icon-cible" consigne="J'écoute la dictée, je l'écris ligne par ligne.">
        <SeyesLines rows={5} height="0.46in" />
      </ExerciseCard>

      <Cols ratio="1fr 1.2fr">
        <Box tone="green" label="Auto-correction" iconKey="icon-trophee">
          <div style={{ fontSize: "0.16in" }}>Je relis avec une couleur :</div>
          <ul className="bk-bullets" style={{ marginTop: "0.06in", fontSize: "0.15in" }}>
            <li>les majuscules · les points</li>
            <li>les pluriels (s, x)</li>
            <li>les mots de la liste</li>
            <li>les accords sujet-verbe</li>
          </ul>
        </Box>
        <KettyBubble pose="pointing" tone="primary" label="Méthode Ketty">
          Avant la dictée, je ferme les yeux, je vois le mot dans ma tête,
          puis je l'écris en l'air avec mon doigt.
        </KettyBubble>
      </Cols>
    </PageShell>
  );
}

/* ════════════════════════════════════════════════════════════════════════
   6 · CALCUL MENTAL PRIMAIRE (template: "primary-mental-math")
   ════════════════════════════════════════════════════════════════════════ */

function P6MentalMath({ density, qrVisible, scoreVisible, scale = 1 }) {
  const blocks = [
    {
      lab: "Additions", tone: "primary",
      ops: ["7 + 5", "8 + 6", "9 + 4", "6 + 7", "8 + 8", "9 + 7", "7 + 6", "9 + 5"],
    },
    {
      lab: "Doubles &amp; moitiés", tone: "orange",
      ops: ["double de 7", "double de 9", "moitié de 12", "moitié de 18",
            "double de 12", "double de 15", "moitié de 20", "moitié de 24"],
    },
    {
      lab: "Tables × 2 et × 5", tone: "yellow",
      ops: ["3 × 2", "5 × 2", "8 × 2", "9 × 2",
            "4 × 5", "6 × 5", "7 × 5", "9 × 5"],
    },
  ];
  return (
    <PageShell
      matiere="Maths" niveau="CE1 — CE2" page={"Calcul · Page 11"}
      density={density} qrVisible={qrVisible} scoreVisible={scoreVisible}
      qrSlug="ce1-calculmental-bloc11"
      qrLabel="Réponses commentées"
      scale={scale}
    >
      <PageTitle
        eyebrow="Calcul mental express"
        title="3 séries · 8 calculs"
        subtitle="J'ai 4 minutes par série. Je note vite, je vérifie ensuite."
      />

      <div style={{
        display: "flex", gap: "0.16in", alignItems: "center",
        padding: "0.08in 0.12in",
        background: "var(--ae-yellow-soft)",
        border: "1.5px solid var(--ae-yellow-dark)",
        borderRadius: "0.1in",
        fontFamily: "var(--ae-font-title)", fontWeight: 600,
        fontSize: "0.17in", color: "var(--ae-primary-deep)",
      }}>
        <Icon k="icon-horloge" /> Temps conseillé : <b>4 min</b> par série
        <Sep />
        <Icon k="icon-trophee" /> Score visé : <b>6/8 minimum</b>
      </div>

      <div style={{ display: "flex", flexDirection: "column", gap: "0.14in" }}>
        {blocks.map((b, i) => (
          <Box key={i} tone={b.tone} label={b.lab}>
            <div style={{
              display: "grid", gridTemplateColumns: "1fr 1fr 1fr 1fr",
              rowGap: "0.1in", columnGap: "0.16in",
            }}>
              {b.ops.map((op, j) => (
                <div key={j} style={{
                  display: "grid", gridTemplateColumns: "0.32in 1fr 0.6in",
                  alignItems: "center", gap: "0.06in",
                }}>
                  <NumChip n={j + 1} tone={i === 0 ? "primary" : i === 1 ? "orange" : "yellow"} size="0.26in" />
                  <span style={{
                    fontFamily: "var(--ae-font-mono)", fontWeight: 600,
                    fontSize: "0.17in", color: "var(--ae-text)",
                  }}>{op} =</span>
                  <P5WriteBox height="0.32in" />
                </div>
              ))}
            </div>
          </Box>
        ))}
      </div>

      <Cols ratio="1fr 1.3fr">
        <ScoreBox label="Mon score" message="1 point par bonne réponse · Total /24." />
        <KettyBubble pose="thinking" tone="primary" label="Conseil Ketty">
          Je commence par les calculs <b>faciles</b> pour mettre des points
          dans mon panier, puis je reviens sur ceux qui me bloquent.
        </KettyBubble>
      </Cols>
    </PageShell>
  );
}

/* ════════════════════════════════════════════════════════════════════════
   7 · CALCUL POSÉ (template: "written-calculation")
   ════════════════════════════════════════════════════════════════════════ */

function P7WrittenCalc({ density, qrVisible, scoreVisible, scale = 1 }) {
  // Each calculation as digit array, padded so columns line up
  const adds = [
    { a: "247", b: "138" },
    { a: "356", b: "419" },
    { a: " 89", b: "127" },
  ];
  const subs = [
    { a: "532", b: "146" },
    { a: "401", b: "238" },
  ];
  const muls = [
    { a: "47", b: " 6" },
    { a: "83", b: " 4" },
  ];

  function ColumnCalc({ a, b, op, retenue = true }) {
    const w = Math.max(a.length, b.length);
    const pad = (s) => s.padStart(w, " ").split("");
    return (
      <div style={{
        display: "inline-flex", flexDirection: "column", alignItems: "flex-end",
        padding: "0.08in 0.1in", background: "white",
        border: "1.5px solid var(--ae-border)",
        borderRadius: "0.08in", fontFamily: "var(--ae-font-mono)",
        fontWeight: 600, fontSize: "0.22in", lineHeight: 1.4,
      }}>
        {retenue && (
          <div style={{
            display: "flex", gap: "0.04in",
            fontSize: "0.12in", color: "var(--ae-orange-dark)",
            height: "0.18in", alignItems: "center",
          }}>
            {pad("").map((_, i) => (
              <span key={i} style={{ width: "0.22in", textAlign: "center" }}>·</span>
            ))}
          </div>
        )}
        <div style={{ display: "flex", gap: "0.04in" }}>
          {pad(a).map((c, i) => <span key={i} style={{ width: "0.22in", textAlign: "right" }}>{c}</span>)}
        </div>
        <div style={{ display: "flex", gap: "0.04in", borderBottom: "1.5px solid var(--ae-text)", paddingBottom: "0.02in" }}>
          <span style={{ marginRight: "0.04in", color: "var(--ae-primary)" }}>{op}</span>
          {pad(b).map((c, i) => <span key={i} style={{ width: "0.22in", textAlign: "right" }}>{c}</span>)}
        </div>
        <div style={{ display: "flex", gap: "0.04in", marginTop: "0.04in" }}>
          {pad("").map((_, i) => (
            <span key={i} style={{
              width: "0.22in", height: "0.3in",
              borderBottom: "1.5px dotted var(--ae-text-soft)",
            }} />
          ))}
        </div>
      </div>
    );
  }

  return (
    <PageShell
      matiere="Maths" niveau="CE2" page={"Calcul posé · Page 14"}
      density={density} qrVisible={qrVisible} scoreVisible={scoreVisible}
      qrSlug="ce2-calculpose-bloc14"
      qrLabel="Voir les retenues"
      scale={scale}
    >
      <PageTitle
        eyebrow="Calcul posé · Avec retenue"
        title="Je pose, j'aligne, je calcule"
        subtitle="Je commence toujours par les unités, à droite. Je note les retenues en haut, en orange."
      />

      <Box tone="green" label="Exemple guidé" iconKey="icon-info">
        <div style={{ display: "flex", alignItems: "center", gap: "0.2in", flexWrap: "wrap" }}>
          <ColumnCalc a="356" b="178" op="+" />
          <div style={{ flex: 1, fontSize: "0.16in", lineHeight: 1.5, minWidth: "2.5in" }}>
            <b>1.</b> J'aligne les unités à droite.<br/>
            <b>2.</b> 6 + 8 = 14 → j'écris 4, je retiens 1.<br/>
            <b>3.</b> 1 + 5 + 7 = 13 → j'écris 3, je retiens 1.<br/>
            <b>4.</b> 1 + 3 + 1 = 5 → j'écris 5. Total : <b>534</b>.
          </div>
        </div>
      </Box>

      <ExerciseCard number={1} consigne="Additions à trous : je pose et je calcule.">
        <div style={{ display: "flex", gap: "0.18in", flexWrap: "wrap" }}>
          {adds.map((c, i) => <ColumnCalc key={i} {...c} op="+" />)}
        </div>
      </ExerciseCard>

      <Cols ratio="1fr 1fr">
        <ExerciseCard number={2} tone="orange" consigne="Soustractions posées.">
          <div style={{ display: "flex", gap: "0.16in", flexWrap: "wrap" }}>
            {subs.map((c, i) => <ColumnCalc key={i} {...c} op="−" />)}
          </div>
        </ExerciseCard>
        <ExerciseCard number={3} tone="yellow" consigne="Multiplications par un chiffre.">
          <div style={{ display: "flex", gap: "0.16in", flexWrap: "wrap" }}>
            {muls.map((c, i) => <ColumnCalc key={i} {...c} op="×" />)}
          </div>
        </ExerciseCard>
      </Cols>

      <KettyBubble pose="pointing" tone="primary" label="Astuce">
        Si je n'ai pas de retenue, je laisse l'espace vide en haut — mais je
        garde toujours mes colonnes bien alignées, sinon je me trompe.
      </KettyBubble>
    </PageShell>
  );
}

/* ════════════════════════════════════════════════════════════════════════
   8 · PETITS PROBLÈMES (template: "primary-word-problems")
   ════════════════════════════════════════════════════════════════════════ */

function P8WordProblems({ density, qrVisible, scoreVisible, scale = 1 }) {
  const problemes = [
    {
      n: 1,
      enonce: "Léa a 24 billes. Sa grande sœur lui en donne 18. Combien de billes Léa a-t-elle maintenant ?",
      donnees: ["24 billes au départ", "18 billes données"],
      ops: ["+", "−", "×"],
    },
    {
      n: 2,
      enonce: "Dans la classe, il y a 27 élèves. 9 sont absents aujourd'hui. Combien d'élèves sont en classe ?",
      donnees: ["27 élèves au total", "9 élèves absents"],
      ops: ["+", "−", "×"],
    },
    {
      n: 3,
      enonce: "Maman achète 6 paquets de 5 cookies. Combien de cookies a-t-elle en tout ?",
      donnees: ["6 paquets", "5 cookies par paquet"],
      ops: ["+", "−", "×"],
    },
  ];

  return (
    <PageShell
      matiere="Maths" niveau="CE2" page={"Problèmes · Page 7"}
      density={density} qrVisible={qrVisible} scoreVisible={scoreVisible}
      qrSlug="ce2-problemes-bloc7"
      qrLabel="Solutions détaillées"
      scale={scale}
    >
      <PageTitle
        eyebrow="Petits problèmes"
        title="Je lis, je choisis, je calcule, je rédige"
        subtitle="Pour chaque problème : je relève les données, je choisis la bonne opération, je calcule, j'écris une phrase de réponse."
      />

      <Box tone="cool" label="Méthode en 4 étapes" iconKey="icon-info">
        <ol className="bk-steps">
          <li><span className="n">1</span><span className="t">Je lis 2 fois l'énoncé en entier.</span></li>
          <li><span className="n">2</span><span className="t">J'entoure les nombres et la question.</span></li>
          <li><span className="n">3</span><span className="t">Je choisis l'opération.</span></li>
          <li><span className="n">4</span><span className="t">Je calcule, puis je rédige une phrase de réponse.</span></li>
        </ol>
      </Box>

      <div style={{ display: "flex", flexDirection: "column", gap: "0.14in" }}>
        {problemes.map(p => (
          <ExerciseCard key={p.n} number={p.n} consigne={p.enonce}>
            <div style={{
              display: "grid", gridTemplateColumns: "1fr 1fr",
              gap: "0.14in",
            }}>
              <Box tone="primary" label="Données utiles" iconKey="icon-loupe">
                <ul className="bk-bullets" style={{ fontSize: "0.16in", margin: 0, paddingLeft: "0.18in" }}>
                  {p.donnees.map((d, i) => <li key={i}>{d}</li>)}
                </ul>
              </Box>
              <div>
                <div className="bk-col-head" style={{ marginBottom: "0.04in" }}>Opération choisie</div>
                <div style={{ display: "flex", gap: "0.1in", marginBottom: "0.08in" }}>
                  {p.ops.map(o => (
                    <span key={o} style={{
                      width: "0.4in", height: "0.4in",
                      display: "grid", placeItems: "center",
                      border: "1.5px solid var(--ae-orange)",
                      borderRadius: "0.06in", background: "white",
                      fontFamily: "var(--ae-font-title)", fontWeight: 700,
                      fontSize: "0.22in", color: "var(--ae-orange-dark)",
                    }}>{o}</span>
                  ))}
                </div>
                <div className="bk-col-head" style={{ marginBottom: "0.04in" }}>Mon calcul</div>
                <P5WriteBox height="0.4in" />
              </div>
            </div>
            <div style={{ marginTop: "0.1in" }}>
              <div className="bk-col-head" style={{ marginBottom: "0.04in" }}>Phrase de réponse</div>
              <SeyesLines rows={1} height="0.42in" />
            </div>
          </ExerciseCard>
        ))}
      </div>

      <KettyBubble pose="thumbsup" tone="green" label="Méthode Ketty">
        Une <b>phrase de réponse</b> reprend les mots de la question. C'est elle
        qui me fait gagner les points, pas seulement le calcul.
      </KettyBubble>
    </PageShell>
  );
}

/* ════════════════════════════════════════════════════════════════════════
   9 · NUMÉRATION (template: "number-sense-sheet")
   ════════════════════════════════════════════════════════════════════════ */

function NumberLine({ from = 0, to = 100, step = 10, mark }) {
  const ticks = [];
  for (let v = from; v <= to; v += step) ticks.push(v);
  return (
    <svg viewBox="0 0 800 80" style={{ width: "100%", height: "0.6in", display: "block" }}>
      <line x1="20" y1="50" x2="780" y2="50" stroke="var(--ae-text)" strokeWidth="2" />
      {/* arrow */}
      <polygon points="780,42 794,50 780,58" fill="var(--ae-text)" />
      {ticks.map((v, i) => {
        const x = 20 + (760 * i) / (ticks.length - 1);
        const isMark = v === mark;
        return (
          <g key={v}>
            <line x1={x} y1="40" x2={x} y2="60" stroke="var(--ae-text)" strokeWidth="1.5" />
            <text x={x} y="74" textAnchor="middle"
              fontFamily="var(--ae-font-mono)" fontSize="13"
              fill={isMark ? "var(--ae-orange-dark)" : "var(--ae-text-soft)"}
              fontWeight={isMark ? 700 : 500}>{v}</text>
            {isMark && <circle cx={x} cy="50" r="8" fill="var(--ae-orange)" />}
          </g>
        );
      })}
    </svg>
  );
}

function P9NumberSense({ density, qrVisible, scoreVisible, scale = 1 }) {
  const nombre = 348;
  const compares = [
    ["348", "?", "843"],
    ["348", "?", "248"],
    ["348", "?", "350"],
  ];

  return (
    <PageShell
      matiere="Maths" niveau="CE1 — CE2" page={"Numération · Page 5"}
      density={density} qrVisible={qrVisible} scoreVisible={scoreVisible}
      qrSlug="ce1-numeration-bloc5"
      qrLabel="Vérifier les écritures"
      scale={scale}
    >
      <PageTitle
        eyebrow="Numération · Le nombre du jour"
        title={`Le nombre ${nombre}`}
        subtitle="Je l'écris, je le décompose, je le compare, je le place."
      />

      <Cols ratio="1fr 1fr" gap="0.16in">
        <ExerciseCard number={1} consigne="Je l'écris en chiffres et en lettres.">
          <div style={{
            display: "grid", gridTemplateColumns: "1.4in 1fr",
            rowGap: "0.1in", alignItems: "center",
            fontSize: "0.16in",
          }}>
            <span style={{ fontWeight: 700 }}>En chiffres</span>
            <P5WriteBox height="0.46in" />
            <span style={{ fontWeight: 700 }}>En lettres</span>
            <P5WriteBox height="0.46in" />
          </div>
        </ExerciseCard>

        <ExerciseCard number={2} tone="orange" consigne="Je décompose en centaines, dizaines, unités.">
          <div style={{
            display: "grid", gridTemplateColumns: "0.6in 1fr 0.6in 1fr 0.6in 1fr",
            alignItems: "center", gap: "0.08in",
            fontFamily: "var(--ae-font-mono)", fontSize: "0.2in",
            color: "var(--ae-primary-deep)",
          }}>
            <span style={{ fontFamily: "var(--ae-font-title)", fontWeight: 700, color: "var(--ae-orange-dark)", fontSize: "0.13in", textTransform: "uppercase", letterSpacing: "0.06em" }}>C</span>
            <P5WriteBox height="0.4in" />
            <span style={{ fontFamily: "var(--ae-font-title)", fontWeight: 700, color: "var(--ae-orange-dark)", fontSize: "0.13in", textTransform: "uppercase", letterSpacing: "0.06em" }}>D</span>
            <P5WriteBox height="0.4in" />
            <span style={{ fontFamily: "var(--ae-font-title)", fontWeight: 700, color: "var(--ae-orange-dark)", fontSize: "0.13in", textTransform: "uppercase", letterSpacing: "0.06em" }}>U</span>
            <P5WriteBox height="0.4in" />
          </div>
          <div style={{
            marginTop: "0.1in",
            fontFamily: "var(--ae-font-mono)",
            fontSize: "0.18in",
            color: "var(--ae-text-soft)",
          }}>
            348 = … × 100 + … × 10 + … × 1
          </div>
        </ExerciseCard>
      </Cols>

      <ExerciseCard number={3} tone="green" consigne="Je compare avec &lt;, &gt; ou =.">
        <div style={{ display: "flex", gap: "0.18in", flexWrap: "wrap", justifyContent: "center" }}>
          {compares.map(([a, , b], i) => (
            <div key={i} style={{
              display: "flex", alignItems: "center", gap: "0.1in",
              padding: "0.08in 0.14in",
              background: "white",
              border: "1.5px solid var(--ae-success)",
              borderRadius: "0.1in",
              fontFamily: "var(--ae-font-mono)", fontWeight: 600,
              fontSize: "0.22in",
            }}>
              <span>{a}</span>
              <span style={{
                width: "0.46in", height: "0.46in",
                border: "1.5px solid var(--ae-success)",
                borderRadius: "0.06in", background: "var(--ae-success-soft)",
              }} />
              <span>{b}</span>
            </div>
          ))}
        </div>
      </ExerciseCard>

      <ExerciseCard number={4} tone="yellow" consigne="Je place 348 sur la droite graduée.">
        <NumberLine from={0} to={1000} step={100} mark={undefined} />
      </ExerciseCard>
    </PageShell>
  );
}

/* ════════════════════════════════════════════════════════════════════════
   10 · GÉOMÉTRIE PRIMAIRE (template: "primary-geometry-sheet")
   ════════════════════════════════════════════════════════════════════════ */

function P10Geometry({ density, qrVisible, scoreVisible, scale = 1 }) {
  return (
    <PageShell
      matiere="Maths" niveau="CE1" page={"Géométrie · Page 8"}
      density={density} qrVisible={qrVisible} scoreVisible={scoreVisible}
      qrSlug="ce1-geometrie-bloc8"
      qrLabel="Solutions des tracés"
      scale={scale}
    >
      <PageTitle
        eyebrow="Géométrie · Les figures planes"
        title="Je reconnais, je trace, je colorie"
        subtitle="J'utilise toujours ma règle pour tracer les côtés."
      />

      <ExerciseCard number={1} consigne="Je relie chaque figure à son nom.">
        <div style={{
          display: "grid", gridTemplateColumns: "repeat(4, 1fr)",
          gap: "0.14in",
        }}>
          {[
            { svg: <rect x="20" y="20" width="60" height="60" fill="white" stroke="var(--ae-primary)" strokeWidth="2.5" />, n: "Carré" },
            { svg: <rect x="10" y="25" width="80" height="50" fill="white" stroke="var(--ae-primary)" strokeWidth="2.5" />, n: "Rectangle" },
            { svg: <circle cx="50" cy="50" r="32" fill="white" stroke="var(--ae-primary)" strokeWidth="2.5" />, n: "Cercle" },
            { svg: <polygon points="50,15 85,80 15,80" fill="white" stroke="var(--ae-primary)" strokeWidth="2.5" />, n: "Triangle" },
          ].map((f, i) => (
            <div key={i} style={{
              display: "flex", flexDirection: "column", alignItems: "center", gap: "0.06in",
              padding: "0.08in",
              background: "white",
              border: "1.5px solid var(--ae-border)",
              borderRadius: "0.1in",
            }}>
              <svg viewBox="0 0 100 100" style={{ width: "1in", height: "1in" }}>{f.svg}</svg>
              <div style={{
                fontFamily: "var(--ae-font-title)", fontWeight: 600,
                fontSize: "0.15in", color: "var(--ae-primary-deep)",
              }}>{f.n}</div>
              <P5WriteBox height="0.32in" width="80%" />
            </div>
          ))}
        </div>
      </ExerciseCard>

      <Cols ratio="1fr 1fr">
        <ExerciseCard number={2} tone="orange" consigne="Je trace un carré de 4 cm de côté avec ma règle.">
          <div style={{
            height: "1.8in",
            background: "repeating-linear-gradient(0deg, var(--ae-bg-cool) 0 20px, white 20px 21px), repeating-linear-gradient(90deg, var(--ae-bg-cool) 0 20px, white 20px 21px)",
            border: "1.5px solid var(--ae-border)",
            borderRadius: "0.06in",
          }} />
        </ExerciseCard>

        <ExerciseCard number={3} tone="yellow" consigne="Je complète la figure pour faire un rectangle.">
          <svg viewBox="0 0 200 140" style={{ width: "100%", height: "1.8in", background: "white", border: "1.5px solid var(--ae-border)", borderRadius: "0.06in" }}>
            <line x1="40" y1="30" x2="160" y2="30" stroke="var(--ae-primary)" strokeWidth="2.5" />
            <line x1="40" y1="30" x2="40" y2="100" stroke="var(--ae-primary)" strokeWidth="2.5" />
            <line x1="160" y1="30" x2="160" y2="100" strokeDasharray="4 4" stroke="var(--ae-orange)" strokeWidth="2" />
            <line x1="40" y1="100" x2="160" y2="100" strokeDasharray="4 4" stroke="var(--ae-orange)" strokeWidth="2" />
            <text x="100" y="22" textAnchor="middle" fontSize="11" fill="var(--ae-primary)" fontFamily="var(--ae-font-title)" fontWeight="700">12 cm</text>
            <text x="28" y="68" textAnchor="middle" fontSize="11" fill="var(--ae-primary)" fontFamily="var(--ae-font-title)" fontWeight="700">7 cm</text>
          </svg>
        </ExerciseCard>
      </Cols>

      <ExerciseCard number={4} tone="green" consigne="Je colorie selon la consigne · côtés en bleu, sommets en orange.">
        <div style={{ display: "flex", gap: "0.16in", alignItems: "center", flexWrap: "wrap" }}>
          <svg viewBox="0 0 200 140" style={{ width: "2.4in", height: "1.6in" }}>
            <polygon points="40,110 100,30 160,110" fill="white" stroke="var(--ae-text)" strokeWidth="2" />
            <circle cx="40" cy="110" r="6" fill="white" stroke="var(--ae-text)" strokeWidth="1.5" />
            <circle cx="100" cy="30" r="6" fill="white" stroke="var(--ae-text)" strokeWidth="1.5" />
            <circle cx="160" cy="110" r="6" fill="white" stroke="var(--ae-text)" strokeWidth="1.5" />
          </svg>
          <div style={{
            display: "grid", gridTemplateColumns: "0.5in 1fr",
            rowGap: "0.06in", alignItems: "center",
            fontSize: "0.16in",
          }}>
            <span style={{ width: "0.5in", height: "0.18in", background: "var(--ae-primary)", borderRadius: "999px" }} />
            <span>Côtés du triangle</span>
            <span style={{ width: "0.3in", height: "0.3in", borderRadius: "999px", border: "2px solid var(--ae-orange)" }} />
            <span>Sommets du triangle</span>
          </div>
        </div>
      </ExerciseCard>
    </PageShell>
  );
}

/* ════════════════════════════════════════════════════════════════════════
   11 · FICHE "JE RÉVISE" (template: "primary-revision-sheet")
   ════════════════════════════════════════════════════════════════════════ */

function P11RevisionSheet({ density, qrVisible, scoreVisible, scale = 1 }) {
  return (
    <PageShell
      matiere="Je révise" niveau="CE1" page={"Quotidien · Page 18"}
      density={density} qrVisible={qrVisible} scoreVisible={scoreVisible}
      qrSlug="ce1-jerevise-jour18"
      qrLabel="Corrigé du jour"
      scale={scale}
    >
      <PageTitle
        eyebrow="Ma fiche du jour · 4 mini-blocs"
        title="Je révise en 15 minutes"
        subtitle="Une lecture, une écriture, un calcul, un problème. Je colorie une étoile par bloc réussi."
      />

      <div style={{
        display: "grid", gridTemplateColumns: "1fr 1fr",
        gap: "0.16in",
      }}>
        {/* Lecture */}
        <Box tone="primary" label="1 · Lecture" iconKey="icon-livre">
          <div style={{
            fontSize: "0.16in", lineHeight: 1.5, padding: "0.04in 0",
          }}>
            « En automne, les feuilles changent de couleur. Le vent les fait
            tomber. Les écureuils ramassent des noisettes. »
          </div>
          <div style={{
            marginTop: "0.08in",
            display: "flex", flexDirection: "column", gap: "0.06in",
            fontSize: "0.15in",
          }}>
            <span><b>Q.</b> Que ramassent les écureuils ?</span>
            <P5WriteBox height="0.34in" />
          </div>
        </Box>

        {/* Écriture */}
        <Box tone="orange" label="2 · Écriture" iconKey="icon-crayon">
          <div style={{
            fontFamily: "Lora, serif", fontStyle: "italic", fontWeight: 500,
            fontSize: "0.2in", color: "var(--ae-primary-deep)",
            marginBottom: "0.06in",
          }}>« L'automne arrive. »</div>
          <SeyesLines rows={2} height="0.4in" />
        </Box>

        {/* Calcul */}
        <Box tone="yellow" label="3 · Calcul" iconKey="icon-cible">
          <div style={{
            display: "grid", gridTemplateColumns: "1fr 1fr",
            rowGap: "0.08in", columnGap: "0.12in",
            fontFamily: "var(--ae-font-mono)", fontWeight: 600,
            fontSize: "0.18in",
          }}>
            {["12 + 8", "20 − 7", "5 × 4", "30 − 12", "9 + 9", "7 × 2"].map(op => (
              <div key={op} style={{ display: "flex", alignItems: "center", gap: "0.08in" }}>
                <span>{op} =</span>
                <P5WriteBox height="0.3in" width="0.7in" />
              </div>
            ))}
          </div>
        </Box>

        {/* Problème */}
        <Box tone="green" label="4 · Problème" iconKey="icon-info">
          <div style={{ fontSize: "0.16in", lineHeight: 1.45 }}>
            <b>Énoncé.</b> Tom a 35 € dans sa tirelire. Il achète un livre à 14 €.
            Combien lui reste-t-il ?
          </div>
          <div style={{
            marginTop: "0.06in", fontSize: "0.14in",
            color: "var(--ae-muted)", textTransform: "uppercase",
            letterSpacing: "0.06em", fontWeight: 700,
          }}>Mon calcul</div>
          <P5WriteBox height="0.36in" />
          <div style={{
            marginTop: "0.06in", fontSize: "0.14in",
            color: "var(--ae-muted)", textTransform: "uppercase",
            letterSpacing: "0.06em", fontWeight: 700,
          }}>Phrase réponse</div>
          <SeyesLines rows={1} height="0.4in" />
        </Box>
      </div>

      <Cols ratio="1fr 1.4fr">
        <Box tone="cool" label="Mes étoiles" iconKey="icon-trophee">
          <div style={{ display: "flex", gap: "0.1in", justifyContent: "space-around" }}>
            {["Lecture", "Écriture", "Calcul", "Problème"].map(l => (
              <div key={l} style={{ display: "flex", flexDirection: "column", alignItems: "center", gap: "0.04in" }}>
                <span style={{
                  width: "0.5in", height: "0.5in", borderRadius: "999px",
                  border: "2px solid var(--ae-yellow-dark)",
                  background: "white",
                  display: "grid", placeItems: "center",
                }}>
                  <Icon k="icon-etoile" style={{ color: "var(--ae-yellow-dark)", fontSize: "0.26in" }} />
                </span>
                <span style={{ fontSize: "0.12in", textTransform: "uppercase", letterSpacing: "0.06em", fontWeight: 700, color: "var(--ae-text-soft)" }}>{l}</span>
              </div>
            ))}
          </div>
        </Box>
        <KettyBubble pose="celebrating" tone="yellow" label="Bravo">
          Tu as fait ta fiche du jour ! Demain, on continue avec un nouveau bloc.
          La régularité, c'est ton meilleur allié.
        </KettyBubble>
      </Cols>
    </PageShell>
  );
}

/* ════════════════════════════════════════════════════════════════════════
   12 · FICHE GÉNÉRATEUR PROF/PARENT (template: "teacher-printable-worksheet")
   ════════════════════════════════════════════════════════════════════════ */

function P12TeacherPrintable({ density, qrVisible, scoreVisible, scale = 1 }) {
  return (
    <PageShell
      matiere="Fiche imprimable" niveau="CP — CE2" page={"Fiches · Modèle"}
      density={density} qrVisible={qrVisible} scoreVisible={scoreVisible}
      qrSlug="primaire-fiche-generateur"
      qrLabel="Plus de fiches gratuites" qrSubLabel="alloeducation.fr/fiches"
      scale={scale}
    >
      <PageTitle
        eyebrow="Fiche imprimable · Modèle prof / parent"
        title="Mon entraînement du jour"
        subtitle="Une fiche claire, prête à imprimer, personnalisable en 30 secondes."
      />

      {/* Bandeau identité */}
      <div style={{
        display: "grid", gridTemplateColumns: "1.6fr 1fr 1fr",
        gap: "0.12in",
      }}>
        {[
          { lab: "Prénom", val: "" },
          { lab: "Niveau", val: "CE1" },
          { lab: "Date", val: "" },
        ].map((f, i) => (
          <div key={i} style={{
            border: "1.5px solid var(--ae-primary)",
            borderRadius: "0.1in",
            padding: "0.08in 0.12in",
            background: "white",
          }}>
            <div style={{
              fontSize: "var(--ae-fs-eyebrow)", textTransform: "uppercase",
              letterSpacing: "0.08em", color: "var(--ae-primary)",
              fontWeight: 800, marginBottom: "0.04in",
            }}>{f.lab}</div>
            <div style={{ fontFamily: "var(--ae-font-title)", fontWeight: 600, fontSize: "0.2in", color: "var(--ae-primary-deep)", minHeight: "0.32in" }}>{f.val || "_____________"}</div>
          </div>
        ))}
      </div>

      <Box tone="yellow" label="Objectif du jour" iconKey="icon-cible">
        <div style={{ fontFamily: "var(--ae-font-title)", fontWeight: 600, fontSize: "0.2in", color: "var(--ae-primary-deep)" }}>
          Réviser les additions à retenue jusqu'à 100.
        </div>
      </Box>

      {/* Exercices courts */}
      <div style={{ display: "flex", flexDirection: "column", gap: "0.12in" }}>
        <ExerciseCard number={1} consigne="Je calcule en ligne.">
          <div style={{
            display: "grid", gridTemplateColumns: "1fr 1fr 1fr",
            rowGap: "0.08in", columnGap: "0.16in",
            fontFamily: "var(--ae-font-mono)", fontWeight: 600,
            fontSize: "0.2in",
          }}>
            {["35 + 18", "47 + 26", "58 + 19", "29 + 35", "44 + 27", "63 + 28"].map(op => (
              <div key={op} style={{ display: "flex", alignItems: "center", gap: "0.08in" }}>
                <span>{op} =</span>
                <P5WriteBox height="0.34in" width="0.9in" />
              </div>
            ))}
          </div>
        </ExerciseCard>

        <ExerciseCard number={2} tone="orange" consigne="Je complète chaque égalité.">
          <div style={{
            display: "grid", gridTemplateColumns: "1fr 1fr 1fr 1fr",
            rowGap: "0.08in", columnGap: "0.12in",
            fontFamily: "var(--ae-font-mono)", fontWeight: 600,
            fontSize: "0.18in",
          }}>
            {[["28 + …", "= 50"], ["45 + …", "= 60"], ["… + 17", "= 30"], ["… + 35", "= 70"]].map(([a, b], i) => (
              <div key={i} style={{ display: "flex", alignItems: "center", gap: "0.04in" }}>
                <span>{a}</span><span>{b}</span>
              </div>
            ))}
          </div>
        </ExerciseCard>

        <ExerciseCard number={3} tone="green" consigne="Je résous le mini-problème.">
          <div style={{ fontSize: "0.16in", lineHeight: 1.45, marginBottom: "0.06in" }}>
            Camille a 47 autocollants. Sa tante lui en offre 25. Combien
            d'autocollants Camille possède-t-elle maintenant ?
          </div>
          <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: "0.1in" }}>
            <div>
              <div className="bk-col-head" style={{ marginBottom: "0.04in" }}>Mon calcul</div>
              <P5WriteBox height="0.4in" />
            </div>
            <div>
              <div className="bk-col-head" style={{ marginBottom: "0.04in" }}>Phrase réponse</div>
              <SeyesLines rows={1} height="0.4in" />
            </div>
          </div>
        </ExerciseCard>
      </div>

      {/* Bandeau fin */}
      <div style={{
        display: "grid", gridTemplateColumns: "1fr 1.6fr",
        gap: "0.12in", alignItems: "center",
      }}>
        <ScoreBox label="Score du jour" message="3 exercices · 1 point par bonne réponse." />
        <div style={{
          padding: "0.1in 0.14in",
          background: "var(--ae-bg-cream)",
          border: "1px solid var(--ae-border)",
          borderRadius: "0.1in",
          fontSize: "0.13in",
          color: "var(--ae-muted)",
          fontStyle: "italic",
          textAlign: "right",
        }}>
          Fiche d'entraînement gratuite · <b style={{ color: "var(--ae-primary)" }}>Allo Education</b> ·
          Plus de fiches sur <b>alloeducation.fr/fiches</b>.
        </div>
      </div>
    </PageShell>
  );
}

/* ────────────────────────────────────────────────────────────────────────
   Export
   ──────────────────────────────────────────────────────────────────────── */
Object.assign(window, {
  P1Phonics, P2WordReading, P3PrimaryReading, P4Handwriting,
  P5Dictation, P6MentalMath, P7WrittenCalc, P8WordProblems,
  P9NumberSense, P10Geometry, P11RevisionSheet, P12TeacherPrintable,
});
