Explore mitosis and the cell cycle with an interactive biology lesson. Grow a cell until it divides, orbit through G1, S, G2, and M phases, step through prophase to telophase, and order the phases in an auto-graded challenge.
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}
.dish{position:relative;height:230px;border:1px solid #dbe2ea;border-radius:50%;background:radial-gradient(circle,#f8fafc 55%,#eef2f7 75%,#e2e8f0);display:flex;align-items:center;justify-content:center;overflow:hidden}
.cell{width:40px;height:40px;border-radius:50%;background:radial-gradient(circle at 35% 30%,#a7f3d0,#059669);box-shadow:0 6px 16px rgba(5,150,105,.4);transition:width .25s ease,height .25s ease}
.daughters{position:absolute;display:flex;gap:26px;opacity:0;transition:opacity .5s ease}
.daughters .d{width:36px;height:36px;border-radius:50%;background:radial-gradient(circle at 35% 30%,#a7f3d0,#059669)}
.readout{display:flex;gap:18px;justify-content:center;font-size:0.95rem;color:#334155}
.readout b{color:#059669}
.btn-row{display:flex;gap:10px;justify-content:center;flex-wrap:wrap}
button{border:none;border-radius:999px;padding:10px 18px;font-size:0.9rem;font-weight:600;cursor:pointer;transition:transform .15s ease}
button:hover{transform:translateY(-1px)}
button:disabled{opacity:.5;cursor:not-allowed}
#feedBtn,#dFeed{background:#059669;color:#fff}
.tb-note{text-align:center;font-size:0.9rem;color:#334155;margin: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}
.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:#6ee7b7}
.opt.on{border-color:#059669;background:#ecfdf5;color:#064e3b;font-weight:700}
.opt:disabled{opacity:.55;cursor:not-allowed}
</style>
<h1>Grow Before You Split</h1>
<p class="sub">A cell must double its contents before it can divide into two working cells.</p>
<p>This little cell starts at 40 units across. Try the free demo first — split it at different sizes and see what happens. It is not graded.</p>
<div class="explain-demo">
<span class="tag">Explore (not graded)</span>
<div class="tb-demo">
<div class="dish">
<div class="cell" id="dCell"></div>
<div class="daughters" id="dDaugh">
<div class="d"></div>
<div class="d"></div>
</div>
</div>
<div class="readout">
<span>Cell size <b id="dSize">40</b> units</span>
</div>
<div class="btn-row">
<button id="dFeed" type="button">Feed (grow 5)</button>
<button id="dSplit" type="button">Demo split</button>
<button id="dReset" type="button">Reset</button>
</div>
<p class="tb-note" id="dNote1">Free play: feed, then split at different sizes to watch what happens.</p>
</div>
</div>
<p class="lead-in">Watch the free demo above, then predict: roughly how big must this cell get before it can split into two healthy daughters?</p>
<task-block title="How big before it splits?" data-question-key="cell-t1" feedback-correct="Grow to about 80 units - roughly double the 40-unit start. Each daughter then gets a complete set of contents and can live on." feedback-incorrect="Two healthy daughters need each one to get a full working set. That means the mother cell must roughly double its contents before dividing." submit-label="Check my prediction">
<div class="tb-demo">
<div class="opts">
<button class="opt" id="gStay" type="button">Any size works - size does not matter</button>
<button class="opt" id="gSix" type="button">Grow a little - to about 60 units</button>
<button class="opt" id="gEight" type="button">Roughly double - to about 80 units</button>
<button class="opt" id="gOver" type="button">Grow way past double - to about 110 units</button>
</div>
<p class="tb-note" id="n1">The cell starts at 40 units. Think about what each daughter needs, then submit.</p>
</div>
</task-block>
<script>
var demo1 = { size: 40, done: false };
function paintDemo1() {
var cell = document.getElementById("dCell");
var daugh = document.getElementById("dDaugh");
var size = document.getElementById("dSize");
if (cell) { cell.style.width = demo1.size + "px"; cell.style.height = demo1.size + "px"; }
if (size) size.textContent = demo1.size;
if (daugh) daugh.style.opacity = demo1.done ? "1" : "0";
if (cell) cell.style.opacity = demo1.done ? "0" : "1";
}
function demo1Note() {
var note = document.getElementById("dNote1");
if (!note) return;
if (demo1.done) {
if (demo1.size < 78) note.innerHTML = "Split at " + demo1.size + " units: the daughters are too small to survive. Cells must finish growing before they split.";
else if (demo1.size <= 92) note.innerHTML = "Split at " + demo1.size + " units: two healthy daughters survived.";
else note.innerHTML = "Split at " + demo1.size + " units: the cell wasted energy it needed later.";
} else {
note.textContent = "Fed to " + demo1.size + " units. Split it to see the outcome.";
}
}
window.__modelxTaskState = { pick: "" };
window.__modelxGetTaskState = function () { return window.__modelxTaskState; };
window.__modelxGradeTask = function (s) { return s.pick === "eight" ? 100 : 0; };
window.__modelxOnTaskSubmitted = function (score) {
var note = document.getElementById("n1");
if (note) note.innerHTML = score >= 100 ? "Correct. From a 40-unit start, about 80 units - roughly a doubling - gives each daughter a complete set of contents so both survive." : "Split too early and the daughters are missing supplies; split too late and the cell wastes energy. The healthy target is roughly double the starting size.";
["gStay", "gSix", "gEight", "gOver"].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 === "dFeed") {
if (demo1.done) return;
demo1.size = Math.min(120, demo1.size + 5);
paintDemo1();
demo1Note();
return;
}
if (id === "dSplit") {
if (demo1.done) return;
demo1.done = true;
paintDemo1();
demo1Note();
var fb = document.getElementById("dFeed"); if (fb) fb.disabled = true;
var sp = document.getElementById("dSplit"); if (sp) sp.disabled = true;
return;
}
if (id === "dReset") {
demo1.size = 40;
demo1.done = false;
var fb2 = document.getElementById("dFeed"); if (fb2) fb2.disabled = false;
var sp2 = document.getElementById("dSplit"); if (sp2) sp2.disabled = false;
paintDemo1();
var note = document.getElementById("dNote1");
if (note) note.textContent = "Reset. Feed, split, and compare outcomes at different sizes.";
return;
}
var TASK_MAP1 = { gStay: "stay", gSix: "six", gEight: "eight", gOver: "over" };
if (TASK_MAP1[id]) {
window.__modelxTaskState.pick = TASK_MAP1[id];
["gStay", "gSix", "gEight", "gOver"].forEach(function (i) { var el = document.getElementById(i); if (el) el.classList.toggle("on", i === id); });
var n1 = document.getElementById("n1");
if (n1) n1.textContent = "Prediction picked. Submit to check.";
}
});
paintDemo1();
</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}
.dish{position:relative;height:200px;border:1px solid #dbe2ea;border-radius:50%;background:radial-gradient(circle,#f8fafc 55%,#eef2f7 75%,#e2e8f0);display:flex;align-items:center;justify-content:center;overflow:hidden}
.cell{position:absolute;border-radius:50%;background:radial-gradient(circle at 35% 30%,#a7f3d0,#059669);box-shadow:0 6px 16px rgba(5,150,105,.4);transition:width .3s ease,height .3s ease}
.dna{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);font-size:0.8rem;font-weight:800;color:#064e3b;background:#ecfdf5;border:1px solid #a7f3d0;border-radius:999px;padding:2px 8px;white-space:nowrap;opacity:0;transition:opacity .3s ease}
.daughters{position:absolute;display:flex;gap:26px;opacity:0;transition:opacity .5s ease}
.daughters .d{width:36px;height:36px;border-radius:50%;background:radial-gradient(circle at 35% 30%,#a7f3d0,#059669)}
.stage-lbl{text-align:center;font-size:1.05rem;font-weight:800;color:#059669}
.btn-row{display:flex;gap:10px;justify-content:center;flex-wrap:wrap}
button{border:none;border-radius:999px;padding:10px 18px;font-size:0.9rem;font-weight:600;cursor:pointer;transition:transform .15s ease}
button:hover{transform:translateY(-1px)}
button: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:1rem;font-weight:600;color:#334155;cursor:pointer;transition:transform .15s ease,border-color .15s ease;text-align:left;display:flex;align-items:center;gap:10px}
.opt:hover{transform:translateY(-1px);border-color:#fcd34d}
.opt.on{border-color:#d97706;background:#fffbeb;color:#92400e}
.opt .n{width:26px;height:26px;border-radius:50%;background:#fef3c7;color:#92400e;display:flex;align-items:center;justify-content:center;font-size:0.85rem;font-weight:800;flex:none}
.opt:disabled{opacity:.55;cursor:not-allowed}
.tb-note{text-align:center;font-size:0.9rem;color:#334155;margin:0}
.cycle{display:flex;justify-content:center;gap:8px;font-size:0.8rem;color:#475569;font-weight:700;margin-bottom:6px}
.cycle span{padding:4px 8px;border-radius:999px;background:#ecfdf5}
.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>The Cell Cycle in Order</h1>
<p class="sub">Growth, copying, more growth, then the big split - always in this order.</p>
<p>Step through the free animation below — it is not graded. Watch the cell grow, copy its DNA, prepare, then split.</p>
<div class="explain-demo">
<span class="tag">Explore (not graded)</span>
<div class="tb-demo">
<div class="dish">
<div class="cell" id="dCell2"></div>
<div class="dna" id="dDna2">DNA copied</div>
<div class="daughters" id="dDaugh2">
<div class="d"></div>
<div class="d"></div>
</div>
</div>
<div class="stage-lbl" id="dStageLbl">G1 - the cell grows</div>
<div class="btn-row">
<button id="dStep2" type="button">Step forward</button>
<button id="dPlay2" type="button">Play through</button>
</div>
<p class="tb-note" id="dNote2">Step or play to see the order of the cell cycle.</p>
</div>
</div>
<p class="lead-in">The demo shows the order: G1 grows, S copies DNA, G2 preps, M splits. Now think about WHY. Why must DNA be copied in S phase BEFORE the cell splits in M phase?</p>
<task-block title="Why must S come before M?" data-question-key="cell-t2" feedback-correct="So each daughter gets a complete copy of the instructions. The split just cuts the cell in two - if the DNA was not copied first, one daughter would lose half its instructions." feedback-incorrect="S is the copying step. If M happened first, the cell would split before the DNA was duplicated - so each daughter would only get half the instructions." submit-label="Check my prediction">
<div class="tb-demo">
<div class="opts">
<button class="opt" id="c2copy" type="button">So each daughter cell gets a complete copy of the DNA</button>
<button class="opt" id="c2size" type="button">So the cell can grow larger before splitting</button>
<button class="opt" id="c2wall" type="button">So the cell wall has time to form</button>
<button class="opt" id="c2half" type="button">So the DNA can be cut in half before splitting</button>
</div>
<p class="tb-note" id="n2">The split divides the cell. What does the copy in S give each daughter?</p>
</div>
</task-block>
<script>
var demo2Stages = [
{ label: "G1 - the cell grows", size: 46, desc: "The cell grows and builds what it needs." },
{ label: "S - DNA is copied", size: 62, desc: "Every chromosome is duplicated - two full sets now." },
{ label: "G2 - the cell preps", size: 76, desc: "Last checks before the big split." },
{ label: "M - mitosis splits the cell", size: 92, desc: "The cell divides into two daughter cells." }
];
var demoStage = 0;
var playing = false;
var playTimer = null;
function renderDemo2() {
var st = demo2Stages[demoStage];
var cell = document.getElementById("dCell2");
var dna = document.getElementById("dDna2");
var daugh = document.getElementById("dDaugh2");
var lbl = document.getElementById("dStageLbl");
var note = document.getElementById("dNote2");
if (cell) { cell.style.width = st.size + "px"; cell.style.height = st.size + "px"; }
if (cell) cell.style.opacity = demoStage === 3 ? "0" : "1";
if (daugh) daugh.style.opacity = demoStage === 3 ? "1" : "0";
if (dna) dna.style.opacity = demoStage === 1 || demoStage === 2 || demoStage === 3 ? "1" : "0";
if (lbl) lbl.textContent = st.label;
if (note) note.textContent = "Stage " + (demoStage + 1) + " of 4: " + st.desc;
}
function stepDemo2() {
demoStage = (demoStage + 1) % 4;
renderDemo2();
}
function setPlaying(on) {
playing = on;
var pb = document.getElementById("dPlay2");
if (pb) pb.textContent = playing ? "Pause" : "Play through";
if (playTimer) { clearInterval(playTimer); playTimer = null; }
if (playing) playTimer = setInterval(function () { stepDemo2(); }, 1300);
}
window.__modelxTaskState = { pick: "" };
window.__modelxGetTaskState = function () { return window.__modelxTaskState; };
window.__modelxGradeTask = function (s) { return s.pick === "copy" ? 100 : 0; };
window.__modelxOnTaskSubmitted = function (score) {
var note = document.getElementById("n2");
if (note) note.innerHTML = score >= 100 ? "Right. The copy in S phase is what lets the split give both daughters a complete set of instructions - one full set for each." : "The split divides the cell in two. If the DNA was copied first (S), both halves get a full set; if not, they each get half.";
["c2copy", "c2size", "c2wall", "c2half"].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 === "dStep2") { setPlaying(false); stepDemo2(); return; }
if (id === "dPlay2") { setPlaying(!playing); return; }
var TASK_MAP2 = { c2copy: "copy", c2size: "size", c2wall: "wall", c2half: "half" };
if (TASK_MAP2[id]) {
window.__modelxTaskState.pick = TASK_MAP2[id];
["c2copy", "c2size", "c2wall", "c2half"].forEach(function (i) { var el = document.getElementById(i); if (el) el.classList.toggle("on", i === id); });
var note = document.getElementById("n2");
if (note) note.textContent = "Prediction picked. Submit to check.";
}
});
renderDemo2();
</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}
.mito-wrap{text-align:center}
.stage-lbl{text-align:center;font-size:1rem;font-weight:800;color:#7c3aed}
.btn-row{display:flex;gap:10px;justify-content:center;flex-wrap:wrap}
button{border:none;border-radius:999px;padding:10px 18px;font-size:0.9rem;font-weight:600;cursor:pointer;transition:transform .15s ease}
button:hover{transform:translateY(-1px)}
button:disabled{opacity:.5;cursor:not-allowed}
.slots{display:grid;grid-template-columns:repeat(5,1fr);gap:8px}
.slot{border:2px dashed #cbd5e1;border-radius:12px;min-height:84px;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;font-size:0.75rem;font-weight:800;color:#94a3b8;cursor:pointer;transition:border-color .15s ease}
.slot.filled{border-style:solid;border-color:#7c3aed;background:#f5f3ff;color:#5b21b6}
.chips{display:grid;grid-template-columns:1fr;gap:8px}
.chip{border:1px solid #e2e8f0;border-radius:12px;background:#fff;padding:10px 12px;font-size:0.9rem;font-weight:600;color:#334155;cursor:pointer;transition:transform .15s ease,border-color .15s ease}
.chip:hover{transform:translateY(-1px);border-color:#c4b5fd}
.chip.sel{border-color:#7c3aed;background:#ede9fe;color:#5b21b6}
.chip: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:#ede9fe;color:#5b21b6;font-weight:700}
.opt:disabled{opacity:.55;cursor:not-allowed}
.tb-note{text-align:center;font-size:0.9rem;color:#334155;margin:0}
.hint{text-align:center;font-size:0.8rem;color:#64748b;margin: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>Put Mitosis in Order</h1>
<p class="sub">Mitosis has a strict five-step choreography.</p>
<p>Watch the free animation below — step through the five phases to see how the chromosomes move. Not graded.</p>
<div class="explain-demo">
<span class="tag">Explore (not graded)</span>
<div class="tb-demo">
<div class="mito-wrap" id="dMitoBox"></div>
<div class="stage-lbl" id="dMitoLbl">Prophase - chromosomes condense</div>
<div class="btn-row">
<button id="dStep3" type="button">Step forward</button>
<button id="dPlay3" type="button">Play through</button>
</div>
<p class="tb-note" id="dNote3">Step or play to see the mitosis sequence.</p>
</div>
</div>
<p class="lead-in">Now apply it. The demo showed anaphase: the copied chromosomes get pulled apart, one set to each side. Imagine anaphase FAILS - the copies are never separated. What would happen when the cell splits?</p>
<task-block title="What if anaphase fails?" data-question-key="cell-t3" feedback-correct="One daughter would get all the chromosomes, the other almost none. Anaphase is what divides the copies evenly - without it, the split hands the whole set to one side." feedback-incorrect="Anaphase is the step that pulls the copies apart so each side gets one set. Skip it, and one side gets everything while the other gets nothing." submit-label="Check my prediction">
<div class="tb-demo">
<div class="opts">
<button class="opt" id="c3one" type="button">One daughter would get all the chromosomes, the other almost none</button>
<button class="opt" id="c3norm" type="button">Nothing - both daughters would still turn out normal</button>
<button class="opt" id="c3half" type="button">Both daughters would get a half set and be fine</button>
<button class="opt" id="c3sames" type="button">Both daughters would get an identical full set anyway</button>
</div>
<p class="tb-note" id="n3">Anaphase is the step that separates the copies. What depends on that separation?</p>
</div>
</task-block>
<script>
var mitoStages = [
{ label: "Prophase - chromosomes condense", desc: "The DNA coils up into tight X-shaped chromosomes." },
{ label: "Metaphase - chromosomes line up", desc: "The chromosomes line up across the middle of the cell." },
{ label: "Anaphase - copies split apart", desc: "Each chromosome’s copies get pulled to opposite sides." },
{ label: "Telophase - nuclei reform", desc: "Two new nuclei form around each set of chromosomes." },
{ label: "Cytokinesis - cell pinches in two", desc: "The cell pinches down the middle into two daughter cells." }
];
function mitoSvg(idx) {
var s = "<svg viewBox=\"0 0 240 150\" width=\"100%\" style=\"max-width:300px;display:block;margin:0 auto\"><ellipse cx=\"120\" cy=\"75\" rx=\"90\" ry=\"55\" fill=\"#faf5ff\" stroke=\"#7c3aed\" stroke-width=\"2\"/>";
if (idx === 0) {
s += "<circle cx=\"120\" cy=\"75\" r=\"20\" fill=\"#f5f3ff\" stroke=\"#7c3aed\" stroke-width=\"1.5\"/>";
s += "<circle cx=\"112\" cy=\"68\" r=\"6\" fill=\"#7c3aed\"/>";
s += "<circle cx=\"128\" cy=\"70\" r=\"6\" fill=\"#7c3aed\"/>";
s += "<circle cx=\"115\" cy=\"84\" r=\"6\" fill=\"#7c3aed\"/>";
s += "<circle cx=\"126\" cy=\"80\" r=\"6\" fill=\"#7c3aed\"/>";
}
if (idx === 1) {
s += "<circle cx=\"70\" cy=\"75\" r=\"6\" fill=\"#7c3aed\"/>";
s += "<circle cx=\"105\" cy=\"75\" r=\"6\" fill=\"#7c3aed\"/>";
s += "<circle cx=\"135\" cy=\"75\" r=\"6\" fill=\"#7c3aed\"/>";
s += "<circle cx=\"170\" cy=\"75\" r=\"6\" fill=\"#7c3aed\"/>";
}
if (idx === 2) {
s += "<circle cx=\"85\" cy=\"75\" r=\"6\" fill=\"#7c3aed\"/>";
s += "<circle cx=\"102\" cy=\"70\" r=\"6\" fill=\"#7c3aed\"/>";
s += "<circle cx=\"155\" cy=\"80\" r=\"6\" fill=\"#7c3aed\"/>";
s += "<circle cx=\"172\" cy=\"72\" r=\"6\" fill=\"#7c3aed\"/>";
}
if (idx === 3) {
s += "<circle cx=\"85\" cy=\"75\" r=\"18\" fill=\"#f5f3ff\" stroke=\"#7c3aed\" stroke-width=\"1.5\"/>";
s += "<circle cx=\"80\" cy=\"72\" r=\"5\" fill=\"#7c3aed\"/>";
s += "<circle cx=\"90\" cy=\"80\" r=\"5\" fill=\"#7c3aed\"/>";
s += "<circle cx=\"155\" cy=\"75\" r=\"18\" fill=\"#f5f3ff\" stroke=\"#7c3aed\" stroke-width=\"1.5\"/>";
s += "<circle cx=\"150\" cy=\"72\" r=\"5\" fill=\"#7c3aed\"/>";
s += "<circle cx=\"160\" cy=\"80\" r=\"5\" fill=\"#7c3aed\"/>";
}
if (idx === 4) {
s += "<path d=\"M120 20 C70 20 40 45 40 75 C40 105 70 130 120 130\" fill=\"#faf5ff\" stroke=\"#7c3aed\" stroke-width=\"2\"/>";
s += "<path d=\"M120 20 C170 20 200 45 200 75 C200 105 170 130 120 130\" fill=\"#faf5ff\" stroke=\"#7c3aed\" stroke-width=\"2\"/>";
s += "<line x1=\"120\" y1=\"20\" x2=\"120\" y2=\"130\" stroke=\"#7c3aed\" stroke-width=\"2\" stroke-dasharray=\"4 4\"/>";
s += "<circle cx=\"85\" cy=\"75\" r=\"15\" fill=\"#f5f3ff\" stroke=\"#7c3aed\" stroke-width=\"1.5\"/>";
s += "<circle cx=\"80\" cy=\"72\" r=\"5\" fill=\"#7c3aed\"/>";
s += "<circle cx=\"90\" cy=\"80\" r=\"5\" fill=\"#7c3aed\"/>";
s += "<circle cx=\"155\" cy=\"75\" r=\"15\" fill=\"#f5f3ff\" stroke=\"#7c3aed\" stroke-width=\"1.5\"/>";
s += "<circle cx=\"150\" cy=\"72\" r=\"5\" fill=\"#7c3aed\"/>";
s += "<circle cx=\"160\" cy=\"80\" r=\"5\" fill=\"#7c3aed\"/>";
}
s += "</svg>";
return s;
}
var mitoIdx = 0;
var mPlaying = false;
var mTimer = null;
function renderMito() {
var box = document.getElementById("dMitoBox");
if (box) box.innerHTML = mitoSvg(mitoIdx);
var lbl = document.getElementById("dMitoLbl");
if (lbl) lbl.textContent = mitoStages[mitoIdx].label;
var note = document.getElementById("dNote3");
if (note) note.textContent = "Phase " + (mitoIdx + 1) + " of 5: " + mitoStages[mitoIdx].desc;
}
function stepMito() {
mitoIdx = (mitoIdx + 1) % 5;
renderMito();
}
function setMitoPlaying(on) {
mPlaying = on;
var pb = document.getElementById("dPlay3");
if (pb) pb.textContent = mPlaying ? "Pause" : "Play through";
if (mTimer) { clearInterval(mTimer); mTimer = null; }
if (mPlaying) mTimer = setInterval(function () { stepMito(); }, 1400);
}
window.__modelxTaskState = { pick: "" };
window.__modelxGetTaskState = function () { return window.__modelxTaskState; };
window.__modelxGradeTask = function (s) { return s.pick === "one" ? 100 : 0; };
window.__modelxOnTaskSubmitted = function (score) {
var note = document.getElementById("n3");
if (note) note.innerHTML = score >= 100 ? "Right. Anaphase is what splits the copies evenly between the two sides - without it, the split gives one daughter the whole set and the other next to nothing." : "Anaphase separates the copies so each side gets one full set. If it never happens, the separation is missing and one daughter ends up with everything.";
["c3one", "c3norm", "c3half", "c3sames"].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 === "dStep3") { setMitoPlaying(false); stepMito(); return; }
if (id === "dPlay3") { setMitoPlaying(!mPlaying); return; }
var TASK_MAP3 = { c3one: "one", c3norm: "norm", c3half: "half", c3sames: "sames" };
if (TASK_MAP3[id]) {
window.__modelxTaskState.pick = TASK_MAP3[id];
["c3one", "c3norm", "c3half", "c3sames"].forEach(function (i) { var el = document.getElementById(i); if (el) el.classList.toggle("on", i === id); });
var note = document.getElementById("n3");
if (note) note.textContent = "Prediction picked. Submit to check.";
}
});
renderMito();
</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}
.dish{position:relative;height:200px;border:1px solid #dbe2ea;border-radius:50%;background:radial-gradient(circle,#f8fafc 55%,#eef2f7 75%,#e2e8f0);display:flex;align-items:center;justify-content:center;overflow:hidden}
.cell{width:60px;height:60px;border-radius:50%;background:radial-gradient(circle at 35% 30%,#bae6fd,#0284c7);box-shadow:0 6px 16px rgba(2,132,199,.4)}
.daughters{position:absolute;display:flex;gap:30px;opacity:0;transition:opacity .5s ease}
.daughters .d{width:40px;height:40px;border-radius:50%;background:radial-gradient(circle at 35% 30%,#bae6fd,#0284c7)}
.check{display:grid;grid-template-columns:1fr;gap:6px;margin-top:4px}
.check .row{border:1px solid #e2e8f0;border-radius:10px;padding:8px 12px;font-size:0.9rem;color:#334155;background:#fff}
.check .row b{float:right;font-weight:800}
.check .row.good{border-color:#86efac;background:#f0fdf4}
.check .row.good b{color:#15803d}
.check .row.bad{color:#94a3b8}
.btn-row{display:flex;gap:10px;justify-content:center;flex-wrap:wrap}
button{border:none;border-radius:999px;padding:10px 18px;font-size:0.9rem;font-weight:600;cursor:pointer;transition:transform .15s ease;background:#0ea5e9;color:#fff}
button:hover{transform:translateY(-1px)}
button:disabled{opacity:.5;cursor:not-allowed}
.kit{display:grid;grid-template-columns:1fr;gap:10px}
.part{border:1px solid #e2e8f0;border-radius:12px;background:#fff;padding:12px 14px;font-size:0.95rem;font-weight:600;color:#334155;cursor:pointer;transition:transform .15s ease,border-color .15s ease;text-align:left}
.part:hover{transform:translateY(-1px)}
.part.on{border-color:#0ea5e9;background:#f0f9ff;color:#075985}
.part:disabled{opacity:.55;cursor:not-allowed}
.readout{text-align:center;font-size:0.9rem;color:#334155}
.readout b{color:#0ea5e9}
.tb-note{text-align:center;font-size:0.9rem;color:#334155;margin: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>Pack a Daughter Cell Kit</h1>
<p class="sub">What exactly does a daughter cell get? Choose the right supplies.</p>
<p>Watch the free split below - just watch what happens. It is not graded.</p>
<div class="explain-demo">
<span class="tag">Explore (not graded)</span>
<div class="tb-demo">
<div class="dish">
<div class="cell" id="dCell4"></div>
<div class="daughters" id="dDaugh4">
<div class="d"></div>
<div class="d"></div>
</div>
</div>
<div class="btn-row">
<button id="dSplit4" type="button">Split the demo cell</button>
</div>
<p class="tb-note" id="dNote4">Free play: split the cell and watch it become two daughters.</p>
</div>
</div>
<p class="lead-in">Now pick the two essential supplies each daughter needs - exactly two.</p>
<task-block title="Pick the two essential supplies" data-question-key="cell-t4" feedback-correct="Exactly! A full DNA copy (from S phase) plus half the cytoplasm - a complete starter kit." feedback-incorrect="A daughter needs ALL the DNA instructions, not a random slice, and only part of the cytoplasm." submit-label="Grade my kit">
<div class="tb-demo">
<div class="kit">
<button class="part" id="itDNA" type="button">A complete copy of every chromosome</button>
<button class="part" id="itHalf" type="button">A random half of the chromosomes</button>
<button class="part" id="itNuc" type="button">The mother cell’s original nucleus</button>
<button class="part" id="itCyto" type="button">About half of the cytoplasm</button>
<button class="part" id="itWall" type="button">The mother cell’s cell wall</button>
<button class="part" id="itAll" type="button">All of the cytoplasm</button>
</div>
<div class="readout">Selected <b id="pickOut">0</b> of 2</div>
<p class="tb-note" id="n4">Choose exactly two supplies, then submit.</p>
</div>
</task-block>
<script>
var CORRECT_SET = { itDNA: 1, itCyto: 1 };
window.__modelxTaskState = { pick: [] };
window.__modelxGetTaskState = function () { return window.__modelxTaskState; };
window.__modelxGradeTask = function (s) {
if (s.pick.length !== 2) return 0;
var good = 0, wrong = 0;
for (var i = 0; i < s.pick.length; i++) {
if (CORRECT_SET[s.pick[i]]) good++; else wrong++;
}
return good === 2 ? 100 : 50;
};
window.__modelxOnTaskSubmitted = function (score) {
var s = window.__modelxTaskState;
var note = document.getElementById("n4");
if (note) note.innerHTML = score >= 100 ? "Each daughter gets a complete copy of the chromosomes (made during S phase) and about half the cytoplasm. That is a full working cell." : s.pick.indexOf("itHalf") >= 0 ? "A random half of the chromosomes would leave the daughter missing genes. Mitosis copies ALL of them first." : "Check again: both daughters need the full set of DNA instructions and roughly half the cytoplasm.";
var keys = Object.keys(CORRECT_SET).concat(["itHalf", "itNuc", "itWall", "itAll"]);
for (var i = 0; i < keys.length; i++) { var el = document.getElementById(keys[i]); if (el) el.disabled = true; }
};
document.addEventListener("click", function (e) {
var id = e.target.id;
if (id === "dSplit4") {
var cell = document.getElementById("dCell4");
var daugh = document.getElementById("dDaugh4");
if (cell) cell.style.opacity = "0";
if (daugh) daugh.style.opacity = "1";
var note = document.getElementById("dNote4");
if (note) note.innerHTML = "The mother cell split into two daughters.";
var sp = document.getElementById("dSplit4"); if (sp) sp.disabled = true;
return;
}
var ids = ["itDNA", "itHalf", "itNuc", "itCyto", "itWall", "itAll"];
if (ids.indexOf(id) < 0) return;
var s = window.__modelxTaskState;
var idx = s.pick.indexOf(id);
if (idx >= 0) s.pick.splice(idx, 1);
else if (s.pick.length < 2) s.pick.push(id);
for (var i = 0; i < ids.length; i++) {
var el = document.getElementById(ids[i]);
if (el) el.classList.toggle("on", s.pick.indexOf(ids[i]) >= 0);
}
var po = document.getElementById("pickOut"); if (po) po.textContent = s.pick.length;
var note2 = document.getElementById("n4");
if (note2) note2.textContent = s.pick.length === 2 ? "Kit selected - submit to grade!" : "Pick one more supply.";
});
</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 Split Decision</h1>
<p class="sub">Four questions to lock in the cell cycle.</p>
<div class="sum">
<p><b>Cell cycle</b>: G1 → S → G2 → M.<br>
<b>Mitosis</b>: prophase → metaphase → anaphase → telophase → cytokinesis.<br>
<b>Daughter cells</b>: identical DNA, half the cytoplasm.</p>
</div>
<question-block question="During which stage of the cell cycle is DNA copied?" answers="G1|S|G2|M" correct="S" mode="single" feedback-correct="Correct! S stands for synthesis - the DNA is copied." feedback-incorrect="Which stage is named for synthesis (copying)?" data-question-key="cell-q1"></question-block>
<question-block question="In which phase do copied chromosomes get pulled apart to opposite sides?" answers="Prophase|Metaphase|Anaphase|Telophase" correct="Anaphase" mode="single" feedback-correct="Right! Anaphase is when the copies separate." feedback-incorrect="Which phase means ‘apart’ - the split of the copies?" data-question-key="cell-q2"></question-block>
<question-block question="How many cells come out of one cell division?" answers="One|Two|Three|Four" correct="Two" mode="single" feedback-correct="Correct! One mother cell makes two daughter cells." feedback-incorrect="One parent, how many children?" data-question-key="cell-q3"></question-block>
<dropdown-question text="The chromosomes line up in the middle of the cell during __blank__." options="prophase|metaphase|anaphase|telophase" correct="metaphase" feedback-correct="Correct! Meta means middle - they line up in the center." feedback-incorrect="Which phase name means ‘middle’?" data-question-key="cell-q4"></dropdown-question>
<script></script>
</page>
</lesson>