ScienceGrades 6-85 pages

Interactive Punnett Square Lesson for Middle School

Learn genetics by doing: breed rabbits from their alleles, fill in a Punnett square for Bb × Bb, build the baby of BB × bb, predict the white rabbits in a 12-baby litter, and take an auto-graded quiz on genotypes and phenotypes.

Interactive Punnett Square Lesson for Middle School
Live preview - answer the questions as a student would
Pages
Traits and Alleles

Live preview - click through and answer the questions just like a student would. Auto-grading is on.

What students will learn

  • Distinguish between alleles, genotype, and phenotype
  • Build a Punnett square from parent genotypes
  • Predict offspring ratios for a cross
  • Connect the 3:1 ratio to what you observe in offspring
›View the lesson source

This is the exact lesson code rendered by the interactive player above. It was generated by Glowsmith’s AI from a one-line prompt. Copy it, edit it, and generate your own.

<lesson>
  <page>
    <style>
      *{box-sizing:border-box}
      body{font-family:ui-sans-serif,system-ui,-apple-system,Segoe UI,Roboto,Arial;color:#1f2937;line-height:1.6;max-width:720px;margin:0 auto}
      h1{font-size:1.6rem;color:#0f172a;margin:0 0 4px}
      .sub{color:#64748b;font-size:0.95rem;margin:0 0 18px}
      p{font-size:0.95rem}
      .explain-demo{border:1px solid #dbe2ea;border-radius:16px;background:#f8fafc;padding:14px;margin:14px 0}
      .explain-demo .tag{display:inline-block;font-size:0.7rem;font-weight:800;letter-spacing:.08em;text-transform:uppercase;color:#059669;background:#ecfdf5;border:1px solid #a7f3d0;border-radius:999px;padding:2px 10px;margin-bottom:10px}
      .tb-demo{display:grid;gap:12px}
      .slots{display:flex;gap:12px;justify-content:center;flex-wrap:wrap}
      .slot-card{border:1px solid #ddd6fe;border-radius:14px;background:#fff;padding:14px;text-align:center;min-width:170px}
      .slot-card h3{margin:0 0 8px;font-size:0.9rem;color:#6d28d9}
      .alleles{display:flex;gap:8px;justify-content:center}
      .allele{padding:8px 16px;border:1px solid #c4b5fd;border-radius:10px;background:#faf5ff;font-weight:700;cursor:pointer;transition:transform .15s ease,background .15s ease}
      .allele:hover{transform:translateY(-1px)}
      .allele.on{background:#7c3aed;color:#fff;border-color:#7c3aed}
      .allele:disabled{opacity:.5;cursor:not-allowed}
      .opts{display:grid;grid-template-columns:1fr;gap:10px}
      .opt{border:1px solid #e2e8f0;border-radius:12px;background:#fff;padding:14px;font-size:0.95rem;color:#334155;cursor:pointer;transition:transform .15s ease,border-color .15s ease;text-align:left}
      .opt:hover{transform:translateY(-1px);border-color:#c4b5fd}
      .opt.on{border-color:#7c3aed;background:#f5f3ff;color:#5b21b6;font-weight:700}
      .opt:disabled{opacity:.55;cursor:not-allowed}
      .rab-stage{height:160px;display:grid;place-items:center;background:linear-gradient(180deg,#f5f3ff,#f8fafc);border:1px solid #e9d5ff;border-radius:14px}
      .mystery{text-align:center;color:#94a3b8}
      .mystery b{display:block;font-size:2.4rem;line-height:1;color:#c4b5fd}
      .rab-card{font-size:0.85rem;color:#6d28d9;font-weight:700}
      .tb-note{text-align:center;font-size:0.9rem;color:#334155;margin:0}
      .key{font-size:0.85rem;color:#6d28d9;text-align:center;margin-top:2px}
      .genotype-lbl{font-size:0.95rem;font-weight:800;color:#0f172a;text-align:center;margin-top:6px}
      .lead-in{margin-top:18px;padding:10px 14px;border-left:4px solid #2563eb;background:#eff6ff;border-radius:0 10px 10px 0;font-size:0.95rem;color:#1e3a8a}
      button{border:none;border-radius:999px;padding:8px 14px;font-size:0.85rem;font-weight:600;cursor:pointer;transition:transform .15s ease}
      button:hover{transform:translateY(-1px)}
      button:disabled{opacity:.5;cursor:not-allowed}
    </style>
    <h1>Traits and Alleles</h1>
    <p class="sub">Why do rabbits come in different colors? It starts with alleles.</p>
    <p>Fur color is a <strong>trait</strong>, passed down in <strong>alleles</strong> &mdash; versions of a gene. <strong>B</strong> makes brown fur (dominant) and <strong>b</strong> makes white fur (recessive). Each parent passes one allele. Try the free play below &mdash; you get the answer instantly.</p>
    <div class="explain-demo">
      <span class="tag">Explore (not graded)</span>
      <div class="tb-demo">
        <div class="slots">
          <div class="slot-card">
            <h3>Allele from Mum</h3>
            <div class="alleles">
              <button class="allele" id="dMB" type="button">B</button>
              <button class="allele" id="dMb" type="button">b</button>
            </div>
          </div>
          <div class="slot-card">
            <h3>Allele from Dad</h3>
            <div class="alleles">
              <button class="allele" id="dDB" type="button">B</button>
              <button class="allele" id="dDb" type="button">b</button>
            </div>
          </div>
        </div>
        <div class="rab-stage">
          <div id="demoRab">
            <div class="mystery"><b>?</b><div class="rab-card">Pick one allele from each parent and the baby appears instantly.</div></div>
          </div>
        </div>
        <p class="tb-note" id="dNote1">Free play: try every pairing and watch the baby.</p>
        <div class="key">Brown (B) is dominant. White (b) needs two copies.</div>
      </div>
    </div>
    <p class="lead-in">Now a real genetics question - the toy above cannot answer it. A brown rabbit that carries one hidden white allele (Bb) has babies with a white rabbit (bb). What fraction of their babies will be white?</p>
    <task-block title="Bb &times; bb - how many are white?" data-question-key="pun-t1" feedback-correct="About 1 in 2! The Bb parent passes B or b, and the bb parent always passes b. Half the babies get Bb (brown carriers), half get bb (white)." feedback-incorrect="List the combinations: Bb can pass B or b; bb can only pass b. Count how many babies end up with two b&rsquo;s." submit-label="Check my prediction">
      <div class="tb-demo">
        <div class="opts">
          <button class="opt" id="zNone" type="button">None - every baby is brown</button>
          <button class="opt" id="zQuarter" type="button">About 1 in 4</button>
          <button class="opt" id="zHalf" type="button">About 1 in 2</button>
          <button class="opt" id="zAll" type="button">All of them</button>
        </div>
        <p class="tb-note" id="n1">White fur needs two b&rsquo;s. Figure out which allele each parent can pass, then submit.</p>
      </div>
    </task-block>
    <script>
      function rabbitSvg(body, ear) {
        return "<svg viewBox=\"0 0 90 78\" width=\"92\" height=\"80\"><ellipse cx=\"46\" cy=\"58\" rx=\"30\" ry=\"18\" fill=\"" + body + "\"/><ellipse cx=\"37\" cy=\"30\" rx=\"8\" ry=\"18\" fill=\"" + ear + "\"/><ellipse cx=\"55\" cy=\"30\" rx=\"8\" ry=\"18\" fill=\"" + ear + "\"/><circle cx=\"50\" cy=\"22\" r=\"13\" fill=\"" + body + "\"/><circle cx=\"46\" cy=\"19\" r=\"2\" fill=\"#1f2937\"/><circle cx=\"56\" cy=\"19\" r=\"2\" fill=\"#1f2937\"/><path d=\"M50 26 q3 3 0 5\" stroke=\"#1f2937\" stroke-width=\"1.6\" fill=\"none\"/></svg>";
      }
      function comboOf(a, b) { return [a, b].sort().join(""); }
      function paintLive() {
        var el = document.getElementById("demoRab");
        if (!el) return;
        var d = window.__modelxDemoState;
        var combo = comboOf(d.a, d.b);
        if (!combo) return;
        var white = combo === "bb";
        el.innerHTML = rabbitSvg(white ? "#f8fafc" : "#b4835a", white ? "#e2e8f0" : "#9a6b4f") + "<div class=\"genotype-lbl\">" + combo + " = " + (white ? "White fur" : "Brown fur") + "</div>";
        var note = document.getElementById("dNote1");
        if (note) note.textContent = white ? "bb - two b&rsquo;s, so white shows." : "A B present, so the baby is brown. One B beats a b every time.";
      }
      function selectInGroup(group, sel) {
        for (var i = 0; i < group.length; i++) {
          var el = document.getElementById(group[i]);
          if (el) el.classList.toggle("on", group[i] === sel);
        }
      }
      window.__modelxDemoState = { a: "", b: "" };
      window.__modelxTaskState = { pick: "" };
      window.__modelxGetTaskState = function () { return window.__modelxTaskState; };
      window.__modelxGradeTask = function (s) { return s.pick === "half" ? 100 : 0; };
      window.__modelxOnTaskSubmitted = function (score) {
        var note = document.getElementById("n1");
        if (note) note.innerHTML = score >= 100 ? "Half. The Bb parent passes B or b, and the bb parent always passes b: the babies are Bb, Bb, bb, bb - two brown carriers and two white rabbits." : "The Bb parent can pass B or b, and the bb parent can only pass b. Of the four possible babies, two are bb (white) - so about 1 in 2.";
        ["zNone", "zQuarter", "zHalf", "zAll"].forEach(function (id) { var el = document.getElementById(id); if (el) el.disabled = true; });
      };
      document.addEventListener("click", function (e) {
        var id = e.target.id;
        if (id === "dMB" || id === "dMb") { window.__modelxDemoState.a = id === "dMB" ? "B" : "b"; selectInGroup(["dMB", "dMb"], id); paintLive(); return; }
        if (id === "dDB" || id === "dDb") { window.__modelxDemoState.b = id === "dDB" ? "B" : "b"; selectInGroup(["dDB", "dDb"], id); paintLive(); return; }
        var TASK_MAP = { zNone: "none", zQuarter: "quarter", zHalf: "half", zAll: "all" };
        if (TASK_MAP[id]) {
          window.__modelxTaskState.pick = TASK_MAP[id];
          ["zNone", "zQuarter", "zHalf", "zAll"].forEach(function (i) { var el = document.getElementById(i); if (el) el.classList.toggle("on", i === id); });
          var note = document.getElementById("n1");
          if (note) note.textContent = "Prediction picked. Submit to check.";
        }
      });
    </script>
  </page>
  <page>
    <style>
      *{box-sizing:border-box}
      body{font-family:ui-sans-serif,system-ui,-apple-system,Segoe UI,Roboto,Arial;color:#1f2937;line-height:1.6;max-width:720px;margin:0 auto}
      h1{font-size:1.6rem;color:#0f172a;margin:0 0 4px}
      .sub{color:#64748b;font-size:0.95rem;margin:0 0 18px}
      p{font-size:0.95rem}
      .explain-demo{border:1px solid #dbe2ea;border-radius:16px;background:#f8fafc;padding:14px;margin:14px 0}
      .explain-demo .tag{display:inline-block;font-size:0.7rem;font-weight:800;letter-spacing:.08em;text-transform:uppercase;color:#059669;background:#ecfdf5;border:1px solid #a7f3d0;border-radius:999px;padding:2px 10px;margin-bottom:10px}
      .tb-demo{display:grid;gap:12px;text-align:center}
      .parents{display:flex;gap:14px;justify-content:center;flex-wrap:wrap;margin-bottom:12px}
      .parent-chip{border:1px solid #ddd6fe;border-radius:12px;background:#fff;padding:6px 10px;font-size:0.8rem;color:#6d28d9;font-weight:700}
      .parent-chip .pick{display:flex;gap:6px;justify-content:center;margin-top:6px}
      .parent-chip .pick button{font-size:0.8rem}
      .parent-chip .pick button.on{background:#7c3aed;color:#fff;border-color:#7c3aed}
      table{margin:0 auto;border-collapse:separate;border-spacing:6px}
      td,th{width:74px;height:62px;text-align:center;font-weight:700;font-size:1.05rem;border-radius:12px}
      th{font-size:0.9rem;color:#6d28d9;background:#f5f3ff}
      td.cell{background:#faf5ff;border:1px solid #e9d5ff;padding:0}
      td.cell button{width:100%;height:100%;border:none;background:transparent;font-weight:700;font-size:0.95rem;color:#7c3aed;cursor:pointer;border-radius:12px}
      td.cell button:disabled{cursor:not-allowed;opacity:.8}
      td.cell.good{background:#f0fdf4;border-color:#86efac}
      td.cell.wrong{background:#fef2f2;border-color:#fca5a5}
      td.cell select{width:100%;height:100%;border:none;background:transparent;text-align:center;font-weight:700;font-size:1rem;color:#7c3aed;cursor:pointer}
      td.cell select:disabled{opacity:.75;cursor:not-allowed}
      .dot{display:inline-block;width:12px;height:12px;border-radius:50%;margin-left:6px;vertical-align:0}
      .legend{display:flex;gap:14px;justify-content:center;font-size:0.8rem;color:#334155;margin-top:8px}
      .legend span b{display:inline-block;width:14px;height:14px;border-radius:4px;margin-right:4px;vertical-align:-2px}
      .tb-note{font-size:0.9rem;color:#334155;margin:0}
      .fill-all{display:flex;gap:8px;justify-content:center;flex-wrap:wrap;margin-top:6px}
      .fill-all button{border:none;border-radius:999px;padding:8px 14px;font-size:0.85rem;font-weight:600;cursor:pointer;background:#ede9fe;color:#6d28d9;transition:transform .15s ease}
      .fill-all button:hover{transform:translateY(-1px)}
      .fill-all button:disabled{opacity:.5;cursor:not-allowed}
      .lead-in{margin-top:18px;padding:10px 14px;border-left:4px solid #2563eb;background:#eff6ff;border-radius:0 10px 10px 0;font-size:0.95rem;color:#1e3a8a}
    </style>
    <h1>Building a Punnett Square</h1>
    <p class="sub">A grid that predicts every possible baby &mdash; before they&rsquo;re born.</p>
    <p>A <strong>Punnett square</strong> shows all the ways two parents can combine their alleles. Put one parent&rsquo;s alleles across the top, the other down the side, then fill each box. Watch the ungraded demo build a square automatically as you swap the parents.</p>
    <div class="explain-demo">
      <span class="tag">Explore (not graded)</span>
      <div class="tb-demo">
        <div class="parents">
          <span class="parent-chip">Mum
            <span class="pick">
              <button class="allele on" id="dPM" type="button">BB</button>
              <button class="allele" id="dpm" type="button">bb</button>
            </span>
          </span>
          <span class="parent-chip">Dad
            <span class="pick">
              <button class="allele on" id="dPD" type="button">BB</button>
              <button class="allele" id="dpd" type="button">bb</button>
            </span>
          </span>
        </div>
        <table>
          <tr><th></th><th id="dT1">B</th><th id="dT2">B</th></tr>
          <tr><th id="dS1">B</th><td class="cell" id="dC11"><button type="button">BB<span class="dot" style="background:#b4835a"></span></button></td><td class="cell" id="dC12"><button type="button">BB<span class="dot" style="background:#b4835a"></span></button></td></tr>
          <tr><th id="dS2">B</th><td class="cell" id="dC21"><button type="button">BB<span class="dot" style="background:#b4835a"></span></button></td><td class="cell" id="dC22"><button type="button">BB<span class="dot" style="background:#b4835a"></span></button></td></tr>
        </table>
        <p class="tb-note" id="dNote2">Every box = one allele from the top plus one from the side. Swap the parents and watch every box update.</p>
        <div class="legend"><span><b style="background:#b4835a"></b>Brown</span><span><b style="background:#f3f4f6;border:1px solid #e2e8f0"></b>White</span></div>
      </div>
    </div>
    <p class="lead-in">Now fill in the square yourself: two brown rabbits that both carry Bb are breeding. Combine each top allele with each side allele in all four boxes.</p>
    <task-block title="Complete the square for Bb × Bb" data-question-key="pun-t2" feedback-correct="BB, Bb, Bb, bb. That 2:1:1 pattern is exactly the 3:1 you&rsquo;ll see in fur color." feedback-incorrect="Combine each top allele with each side allele. Check the two middle boxes carefully." submit-label="Check the square">
      <div class="tb-demo">
        <div class="parents">
          <span class="parent-chip">Parent A: Bb</span>
          <span class="parent-chip">Parent B: Bb</span>
        </div>
        <table>
          <tr><th></th><th>B</th><th>b</th></tr>
          <tr><th>B</th><td class="cell"><select id="c1"><option value="">?</option><option value="BB">BB</option><option value="Bb">Bb</option><option value="bb">bb</option></select></td><td class="cell"><select id="c2"><option value="">?</option><option value="BB">BB</option><option value="Bb">Bb</option><option value="bb">bb</option></select></td></tr>
          <tr><th>b</th><td class="cell"><select id="c3"><option value="">?</option><option value="BB">BB</option><option value="Bb">Bb</option><option value="bb">bb</option></select></td><td class="cell"><select id="c4"><option value="">?</option><option value="BB">BB</option><option value="Bb">Bb</option><option value="bb">bb</option></select></td></tr>
        </table>
        <div class="fill-all"><button id="fillBb" type="button">I think they&rsquo;re all Bb</button></div>
        <div class="legend"><span><b style="background:#b4835a"></b>Brown</span><span><b style="background:#f3f4f6;border:1px solid #e2e8f0"></b>White</span></div>
        <p class="tb-note" id="n2">Combine the top allele with the side allele in each box, then submit.</p>
      </div>
    </task-block>
    <script>
      var PUN2 = ["BB", "Bb", "Bb", "bb"];
      var dDemo2 = { m: "BB", d: "BB" };
      function paintDemo2() {
        var m = dDemo2.m, d = dDemo2.d;
        var top = document.getElementById("dT1"); if (top) top.textContent = d.charAt(0);
        var top2 = document.getElementById("dT2"); if (top2) top2.textContent = d.charAt(1);
        var s1 = document.getElementById("dS1"); if (s1) s1.textContent = m.charAt(0);
        var s2 = document.getElementById("dS2"); if (s2) s2.textContent = m.charAt(1);
        var cells = [["dC11", 0, 0], ["dC12", 0, 1], ["dC21", 1, 0], ["dC22", 1, 1]];
        cells.forEach(function (c) {
          var el = document.getElementById(c[0]);
          if (!el) return;
          var combo = m.charAt(c[1]) + d.charAt(c[2]);
          var white = combo.indexOf("B") < 0;
          var btn = el.querySelector("button");
          if (btn) btn.innerHTML = combo + "<span class=\"dot\" style=\"background:" + (white ? "#f3f4f6;border:1px solid #e2e8f0" : "#b4835a") + "\"></span>";
        });
        var note = document.getElementById("dNote2");
        if (note) note.textContent = "Boxes combine the top allele with the side allele. Any B = brown baby; only bb is white.";
      }
      window.__modelxGetTaskState = function () {
        return { c1: document.getElementById("c1").value, c2: document.getElementById("c2").value, c3: document.getElementById("c3").value, c4: document.getElementById("c4").value };
      };
      window.__modelxGradeTask = function (s) {
        var good = 0;
        ["c1", "c2", "c3", "c4"].forEach(function (k, i) { if (s[k] === PUN2[i]) good++; });
        return good === 4 ? 100 : good * 25;
      };
      window.__modelxOnTaskSubmitted = function (score) {
        ["c1", "c2", "c3", "c4"].forEach(function (k, i) {
          var sel = document.getElementById(k);
          if (!sel) return;
          var cell = sel.closest("td");
          if (cell) { cell.classList.toggle("good", sel.value === PUN2[i]); cell.classList.toggle("wrong", sel.value !== PUN2[i]); }
          sel.disabled = true;
        });
        var note = document.getElementById("n2");
        if (note) note.innerHTML = score >= 100 ? "Perfect! Two Bb (brown), one BB (brown), one bb (white) &mdash; a 3:1 brown:white ratio in fur color." : "Each box = one top allele + one side allele. The two middle boxes are both Bb.";
        var b1 = document.getElementById("fillBb"); if (b1) b1.disabled = true;
      };
      document.addEventListener("change", function (e) {
        if (e.target.closest && e.target.closest("td.cell")) {
          var filled = ["c1", "c2", "c3", "c4"].filter(function (k) { return document.getElementById(k).value !== ""; }).length;
          var note = document.getElementById("n2");
          if (note) note.textContent = filled === 4 ? "All four filled! Press Check the square." : filled + " of 4 boxes filled.";
        }
      });
      document.addEventListener("click", function (e) {
        var t = e.target;
        var id = t.id;
        if (id === "dPM" || id === "dpm") {
          dDemo2.m = id === "dPM" ? "BB" : "bb";
          selectInGroup2(["dPM", "dpm"], id);
          paintDemo2();
          return;
        }
        if (id === "dPD" || id === "dpd") {
          dDemo2.d = id === "dPD" ? "BB" : "bb";
          selectInGroup2(["dPD", "dpd"], id);
          paintDemo2();
          return;
        }
        if (id === "fillBb") {
          ["c1", "c2", "c3", "c4"].forEach(function (k) { var el = document.getElementById(k); if (el) el.value = "Bb"; });
          var note = document.getElementById("n2");
          if (note) note.textContent = "Hmm - the two middle boxes are Bb, but the corners come from B&times;B and b&times;b. Adjust, then submit.";
        }
      });
      function selectInGroup2(group, sel) {
        for (var i = 0; i < group.length; i++) {
          var el = document.getElementById(group[i]);
          if (el) el.classList.toggle("on", group[i] === sel);
        }
      }
      paintDemo2();
    </script>
  </page>
  <page>
    <style>
      *{box-sizing:border-box}
      body{font-family:ui-sans-serif,system-ui,-apple-system,Segoe UI,Roboto,Arial;color:#1f2937;line-height:1.6;max-width:720px;margin:0 auto}
      h1{font-size:1.6rem;color:#0f172a;margin:0 0 4px}
      .sub{color:#64748b;font-size:0.95rem;margin:0 0 18px}
      p{font-size:0.95rem}
      .explain-demo{border:1px solid #dbe2ea;border-radius:16px;background:#f8fafc;padding:14px;margin:14px 0}
      .explain-demo .tag{display:inline-block;font-size:0.7rem;font-weight:800;letter-spacing:.08em;text-transform:uppercase;color:#059669;background:#ecfdf5;border:1px solid #a7f3d0;border-radius:999px;padding:2px 10px;margin-bottom:10px}
      .tb-demo{display:grid;gap:12px}
      .cross{display:flex;align-items:center;justify-content:center;gap:10px;flex-wrap:wrap;font-weight:700;font-size:1.05rem;color:#0f172a}
      .geno{display:inline-block;padding:10px 16px;border:1px solid #c4b5fd;border-radius:12px;background:#fff}
      .arrow{font-size:1.2rem;color:#7c3aed}
      .kit{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:10px}
      .kit-card{border:1px solid #e9d5ff;border-radius:12px;padding:12px;background:#fff;text-align:center}
      .kit-card .al{font-size:1.5rem;font-weight:800;color:#7c3aed}
      .kit-card label{font-size:0.82rem;color:#334155}
      .kit-card select{width:100%;margin-top:6px;padding:6px 8px;border:1px solid #c4b5fd;border-radius:10px;font-weight:700;color:#7c3aed}
      .kit-card select:disabled{opacity:.7}
      .out-row{display:flex;justify-content:center;gap:12px;flex-wrap:wrap;margin-top:8px}
      .out-row .out{font-size:0.85rem;color:#334155;background:#f5f3ff;border:1px solid #e9d5ff;border-radius:10px;padding:6px 10px}
      .tb-note{text-align:center;font-size:0.9rem;color:#334155;margin:0}
      button{border:none;border-radius:999px;padding:8px 14px;font-size:0.85rem;font-weight:600;cursor:pointer;transition:transform .15s ease;background:#ede9fe;color:#6d28d9}
      button:hover{transform:translateY(-1px)}
      button:disabled{opacity:.5;cursor:not-allowed}
      .litter-line{display:flex;gap:10px;justify-content:center;flex-wrap:wrap;padding:10px 0}
      .lead-in{margin-top:18px;padding:10px 14px;border-left:4px solid #2563eb;background:#eff6ff;border-radius:0 10px 10px 0;font-size:0.95rem;color:#1e3a8a}
    </style>
    <h1>Practice: Crossing a Pure Breed</h1>
    <p class="sub">A pure brown rabbit (BB) meets a white rabbit (bb).</p>
    <p>Brown (B) is dominant. A <strong>pure</strong> brown rabbit has <strong>BB</strong> and can only pass on <strong>B</strong>. A white rabbit has <strong>bb</strong> and can only pass on <strong>b</strong>. Watch the whole litter grow first.</p>
    <div class="explain-demo">
      <span class="tag">Explore (not graded)</span>
      <div class="tb-demo">
        <div class="cross">
          <span class="geno">BB</span>
          <span class="arrow">&times;</span>
          <span class="geno">bb</span>
        </div>
        <div id="demoLitter" class="litter-line"></div>
        <p class="tb-note" id="dNote3">Press the button to grow the whole BB × bb litter instantly.</p>
        <div style="text-align:center"><button id="dGrow" type="button">Grow the litter</button></div>
      </div>
    </div>
    <p class="lead-in">Now predict it first. A pure brown rabbit (BB) has babies with a white rabbit (bb). Can ANY of their babies be white? Think about what allele the BB parent has to pass.</p>
    <task-block title="Can any baby be white?" data-question-key="pun-t3" feedback-correct="No! Every baby gets a B from the BB parent, so every baby is Bb - all brown, but each one quietly carries the white allele." feedback-incorrect="The BB parent has only B&rsquo;s to give. The bb parent gives b. So every baby gets Bb - brown every time." submit-label="Check my prediction">
      <div class="tb-demo">
        <div class="opts">
          <button class="opt" id="pwSome" type="button">Yes - about half of them</button>
          <button class="opt" id="pwNone" type="button">No - every baby gets a B from the BB parent</button>
          <button class="opt" id="pwMom" type="button">Only if a baby inherits two b&rsquo;s from its mother</button>
          <button class="opt" id="pwFirst" type="button">Only the first baby born</button>
        </div>
        <p class="tb-note" id="n3">White fur needs two b&rsquo;s. What can the BB parent pass?</p>
      </div>
    </task-block>
    <script>
      function rabbitBlocks(n) {
        var html = "";
        for (var i = 0; i < n; i++) html += "<span class=\"out\">Bb</span>";
        return html;
      }
      window.__modelxTaskState = { pick: "" };
      window.__modelxGetTaskState = function () { return window.__modelxTaskState; };
      window.__modelxGradeTask = function (s) { return s.pick === "none" ? 100 : 0; };
      window.__modelxOnTaskSubmitted = function (score) {
        var note = document.getElementById("n3");
        if (note) note.innerHTML = score >= 100 ? "Correct. The BB parent only has B to give, the bb parent only has b - so every baby is Bb. Brown, but each one carries the hidden b for a future cross." : "The BB parent can ONLY pass B. That single B blocks white fur in every baby, so none of them are white.";
        ["pwSome", "pwNone", "pwMom", "pwFirst"].forEach(function (id) { var el = document.getElementById(id); if (el) el.disabled = true; });
      };
      document.addEventListener("click", function (e) {
        if (e.target.id === "dGrow") {
          var box = document.getElementById("demoLitter");
          if (box) box.innerHTML = rabbitBlocks(4);
          var note = document.getElementById("dNote3");
          if (note) note.innerHTML = "Every baby is Bb &mdash; all brown, but each one carries the recessive b hidden inside. A later cross could let that b show.";
          return;
        }
        var TASK_MAP3 = { pwSome: "some", pwNone: "none", pwMom: "mom", pwFirst: "first" };
        if (TASK_MAP3[e.target.id]) {
          window.__modelxTaskState.pick = TASK_MAP3[e.target.id];
          ["pwSome", "pwNone", "pwMom", "pwFirst"].forEach(function (i) { var el = document.getElementById(i); if (el) el.classList.toggle("on", i === e.target.id); });
          var note3 = document.getElementById("n3");
          if (note3) note3.textContent = "Prediction picked. Submit to check.";
        }
      });
    </script>
  </page>
  <page>
    <style>
      *{box-sizing:border-box}
      body{font-family:ui-sans-serif,system-ui,-apple-system,Segoe UI,Roboto,Arial;color:#1f2937;line-height:1.6;max-width:720px;margin:0 auto}
      h1{font-size:1.6rem;color:#0f172a;margin:0 0 4px}
      .sub{color:#64748b;font-size:0.95rem;margin:0 0 18px}
      p{font-size:0.95rem}
      .explain-demo{border:1px solid #dbe2ea;border-radius:16px;background:#f8fafc;padding:14px;margin:14px 0}
      .explain-demo .tag{display:inline-block;font-size:0.7rem;font-weight:800;letter-spacing:.08em;text-transform:uppercase;color:#059669;background:#ecfdf5;border:1px solid #a7f3d0;border-radius:999px;padding:2px 10px;margin-bottom:10px}
      .tb-demo{display:grid;gap:12px}
      .row label{display:flex;justify-content:space-between;font-size:0.85rem;font-weight:600;color:#334155;margin-bottom:4px}
      input[type=range]{width:100%;accent-color:#7c3aed}
      .pred{text-align:center;font-size:2rem;font-weight:800;color:#7c3aed}
      .opts{display:grid;grid-template-columns:1fr;gap:10px}
      .opt{border:1px solid #e2e8f0;border-radius:12px;background:#fff;padding:14px;font-size:0.95rem;color:#334155;cursor:pointer;transition:transform .15s ease,border-color .15s ease;text-align:left}
      .opt:hover{transform:translateY(-1px);border-color:#c4b5fd}
      .opt.on{border-color:#7c3aed;background:#f5f3ff;color:#5b21b6;font-weight:700}
      .opt:disabled{opacity:.55;cursor:not-allowed}
      .litter-box{display:flex;flex-wrap:wrap;justify-content:center;gap:8px;padding:12px;border:1px solid #e9d5ff;border-radius:14px;background:#fff}
      .rab{position:relative;width:30px;height:24px;border-radius:50% 50% 60% 60%;display:inline-block}
      .rab::before,.rab::after{content:"";position:absolute;top:-11px;width:8px;height:15px;border-radius:4px 4px 0 0;background:inherit}
      .rab::before{left:4px;transform:rotate(-14deg)}
      .rab::after{left:18px;transform:rotate(14deg)}
      .rab.b{background:#b4835a}
      .rab.w{background:#f3f4f6;border:1px solid #e2e8f0}
      .tb-note{text-align:center;font-size:0.9rem;color:#334155;margin:0}
      button{border:none;border-radius:999px;padding:8px 14px;font-size:0.85rem;font-weight:600;cursor:pointer;transition:transform .15s ease;background:#ede9fe;color:#6d28d9}
      button:hover{transform:translateY(-1px)}
      button:disabled{opacity:.5;cursor:not-allowed}
      .lead-in{margin-top:18px;padding:10px 14px;border-left:4px solid #2563eb;background:#eff6ff;border-radius:0 10px 10px 0;font-size:0.95rem;color:#1e3a8a}
    </style>
    <h1>Genotype vs. Phenotype</h1>
    <p class="sub">The alleles you have = genotype. How they look = phenotype.</p>
    <p>Two heterozygous brown rabbits (<strong>Bb × Bb</strong>) are both brown, but their babies won&rsquo;t all be. Your square said 1 in 4 babies is bb. Grow litters for free below and watch that 1-in-4 pattern show up.</p>
    <div class="explain-demo">
      <span class="tag">Explore (not graded)</span>
      <div class="tb-demo">
        <div class="litter-box" id="dLitterBox"></div>
        <p class="tb-note" id="dCount">No litter yet.</p>
        <p class="tb-note" id="dNote4">Press the button a few times. Each litter of 12 is a fresh draw.</p>
        <div style="text-align:center"><button id="dGrow4" type="button">Grow a litter of 12</button></div>
      </div>
    </div>
    <p class="lead-in">Now predict it yourself. Out of 12 babies from Bb × Bb, how many will be white? The litter stays hidden until you submit.</p>
    <task-block title="Predict the litter of Bb × Bb" data-question-key="pun-t4" feedback-correct="3 white! The 1-in-4 pattern from your square shows up in real numbers." feedback-incorrect="Check your Punnett square - one of the four boxes was bb." submit-label="Grow the litter">
      <div class="tb-demo">
        <div class="row">
          <label>White rabbits out of 12 <span id="wv">?</span></label>
          <input id="wS" type="range" min="0" max="12" value="6">
        </div>
        <div class="pred" id="predOut">6</div>
        <div class="litter-box" id="litterBox" style="opacity:0"></div>
        <p class="tb-note" id="n4">Move the slider to predict, then submit to grow the 12 babies.</p>
      </div>
    </task-block>
    <script>
      function rabbitRow(white) {
        var html = "";
        for (var i = 0; i < 12; i++) html += "<span class=\"rab " + (i < white ? "w" : "b") + "\"></span>";
        return html;
      }
      window.__modelxGetTaskState = function () { return { white: +document.getElementById("wS").value }; };
      window.__modelxGradeTask = function (s) {
        var diff = Math.abs(s.white - 3);
        return Math.max(0, 100 - diff * 20);
      };
      window.__modelxOnTaskSubmitted = function (score) {
        var box = document.getElementById("litterBox");
        if (box) { box.style.opacity = "1"; box.innerHTML = rabbitRow(3); }
        var note = document.getElementById("n4");
        if (note) note.innerHTML = score >= 100 ? "3 white rabbits out of 12 = 1 in 4 = the 25% you predicted from the square. That&rsquo;s the 3:1 phenotype ratio!" : score > 0 ? "The Punnett square says 1 in 4 babies is bb, so 3 of 12 should be white. You predicted " + document.getElementById("wS").value + "." : "1 in 4 boxes was bb, so out of 12 babies you expect 3 white (9 brown).";
        var slider = document.getElementById("wS"); if (slider) slider.disabled = true;
      };
      document.addEventListener("input", function (e) {
        if (e.target.id === "wS") {
          var v = document.getElementById("wS").value;
          var wv = document.getElementById("wv"); if (wv) wv.textContent = v;
          var pred = document.getElementById("predOut"); if (pred) pred.textContent = v;
        }
      });
      document.addEventListener("click", function (e) {
        if (e.target.id === "dGrow4") {
          var w = 0;
          for (var i = 0; i < 12; i++) if (Math.random() < 0.25) w++;
          var box = document.getElementById("dLitterBox");
          if (box) box.innerHTML = rabbitRow(w);
          var count = document.getElementById("dCount");
          if (count) count.textContent = "This litter: " + w + " white, " + (12 - w) + " brown.";
          var note = document.getElementById("dNote4");
          if (note) note.textContent = "About 1 in 4 white, but real litters wobble. Grow more to see the pattern.";
        }
      });
    </script>
  </page>
  <page>
    <style>
      *{box-sizing:border-box}
      body{font-family:ui-sans-serif,system-ui,-apple-system,Segoe UI,Roboto,Arial;color:#1f2937;line-height:1.6;max-width:720px;margin:0 auto}
      h1{font-size:1.6rem;color:#0f172a;margin:0 0 4px}
      .sub{color:#64748b;font-size:0.95rem;margin:0 0 18px}
      p{font-size:0.95rem}
      .sum{border:1px solid #dbe2ea;border-radius:14px;background:#f8fafc;padding:16px;font-size:0.95rem;color:#334155}
      .sum b{color:#0f172a}
    </style>
    <h1>The Rabbit Ratio</h1>
    <p class="sub">The 3:1 that came out of your square.</p>
    <div class="sum">
      <p><b>Alleles</b> = versions of a gene (B or b).<br>
      <b>Genotype</b> = the allele pair (BB, Bb, bb).<br>
      <b>Phenotype</b> = what you see (brown or white).<br>
      <b>Punnett square</b> = a grid of all possible offspring combos.</p>
    </div>
    <question-block question="Which genotype produces white fur when B = brown is dominant?" answers="BB|Bb|bb|Any genotype" correct="bb" mode="single" feedback-correct="Right! White only shows when there is no B allele at all." feedback-incorrect="White requires zero dominant B alleles." data-question-key="pun-q1"></question-block>
    <question-block question="A Bb rabbit has brown fur. Its phenotype is..." answers="Brown fur|White fur|Bb|Half and half" correct="Brown fur" mode="single" feedback-correct="Yes! Phenotype = what shows up, and B wins." feedback-incorrect="Phenotype is what you see, not the letters." data-question-key="pun-q2"></question-block>
    <question-block question="Two Bb brown rabbits breed. What brown : white phenotype ratio do you expect?" answers="3 : 1|1 : 1|2 : 2|4 : 0" correct="3 : 1" mode="single" feedback-correct="Exactly! 3 brown to every 1 white - matching the square you filled." feedback-incorrect="Count the boxes: three have a B, one is bb." data-question-key="pun-q3"></question-block>
    <dropdown-question text="A Punnett square predicts the __blank__ of every possible offspring before they are born." options="genotypes|heights|colors|ages" correct="genotypes" feedback-correct="Correct - and from genotypes you can predict phenotypes." feedback-incorrect="It predicts the allele combinations, which we call...?" data-question-key="pun-q4"></dropdown-question>
    <script></script>
  </page>
</lesson>