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.
Live preview - click through and answer the questions just like a student would. Auto-grading is on.
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> — 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 — 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 × 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’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’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’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 — before they’re born.</p>
<p>A <strong>Punnett square</strong> shows all the ways two parents can combine their alleles. Put one parent’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’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’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) — 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×B and b×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">×</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’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’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’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 — 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’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’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>