ScienceGrade 75 pages

Interactive Photosynthesis Lesson for 7th Grade

A free, interactive photosynthesis lesson for middle school. Students explore the reactants, the role of chlorophyll, and the photosynthesis equation by dragging ingredients, adjusting sliders, and answering auto-graded questions.

Interactive Photosynthesis Lesson for 7th Grade
Live preview - answer the questions as a student would
Pages
Power Up the Plant Factory

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

What students will learn

  • Identify the inputs and outputs of photosynthesis
  • Explain the role of chlorophyll and light in the reaction
  • Write and balance the photosynthesis equation
  • Describe how plants make glucose and oxygen from water and carbon dioxide
›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}
      .stage{position:relative;height:170px;border-radius:14px;background:linear-gradient(180deg,#e0f2fe,#f0fdf4);border:1px solid #dbe2ea;overflow:hidden;display:flex;align-items:flex-end;justify-content:center;padding-bottom:18px}
      .sun-badge{position:absolute;top:12px;right:14px;font-size:0.8rem;font-weight:700;color:#b45309}
      .plant{position:relative}
      .stem{width:10px;height:58px;background:#15803d;border-radius:3px 3px 0 0;margin:0 auto}
      .leaves{display:flex;justify-content:center;gap:6px;margin-bottom:-4px}
      .leaf{width:46px;height:46px;background:#a3e635;border-radius:50% 0 50% 50%;transition:background .3s ease,transform .3s ease}
      .leaf.r{transform:scaleX(-1)}
      .stage.off .leaf{filter:grayscale(1) opacity(.45)}
      .stage.on .leaf{animation:breathe 1.6s ease-in-out infinite}
      @keyframes breathe{0%,100%{transform:scale(1)}50%{transform:scale(1.08)}}
      .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 .15s ease}
      button:hover{transform:translateY(-1px)}
      button:disabled{opacity:.5;cursor:not-allowed}
      .toggle{background:#fff;border:2px solid #e2e8f0;color:#334155}
      .toggle.on{background:#2563eb;border-color:#2563eb;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}
      .scenario{font-size:0.92rem;color:#1e3a8a;background:#eff6ff;border:1px solid #dbeafe;border-radius:12px;padding:10px 14px;font-weight:600}
    </style>
    <h1>Power Up the Plant Factory</h1>
    <p class="sub">Photosynthesis is how a leaf turns simple stuff into food.</p>
    <p>A leaf is a tiny factory. Before it can make food it needs two raw ingredients switched on: <strong>sunlight</strong> and <strong>water</strong>. Play with the demo below &mdash; it is not graded &mdash; then do the challenge under it.</p>
    <div class="explain-demo">
      <span class="tag">Explore (not graded)</span>
      <div class="tb-demo">
        <div class="stage off" id="demoStage">
          <div class="sun-badge" id="demoSunLbl">Sun off</div>
          <div class="plant">
            <div class="leaves"><div class="leaf"></div><div class="leaf r"></div></div>
            <div class="stem"></div>
          </div>
        </div>
        <div class="btn-row">
          <button id="demoSun" class="toggle" type="button">Toggle sunlight</button>
          <button id="demoWater" class="toggle" type="button">Toggle water</button>
        </div>
        <p class="tb-note" id="demoNote">Tap the toggles and watch the leaf. Water arrives through the roots; sunlight arrives as energy.</p>
      </div>
    </div>
    <p class="lead-in">Now for the real question. A tomato plant has sat in a bright sunny window all day, but nobody watered it for two weeks &mdash; the soil is bone dry. Model this plant&rsquo;s situation with the toggles, then predict what happens to it.</p>
    <task-block title="Diagnose the thirsty plant" data-question-key="pho-t1" feedback-correct="Right diagnosis! The window gives sunlight, but dry soil means the roots pull up no water. No water, no food &mdash; the plant cannot run photosynthesis." feedback-incorrect="Read the scenario again: the window supplies sunlight, but the bone-dry soil means water is NOT reaching the roots. Model both correctly, then predict whether it can make food." submit-label="Submit diagnosis">
      <div class="tb-demo">
        <div class="scenario">A tomato plant: bright sunny window all day, but the soil is bone dry for two weeks.</div>
        <div class="btn-row">
          <button id="t1sun" class="toggle" type="button">Sunlight: ?</button>
          <button id="t1water" class="toggle" type="button">Water: ?</button>
        </div>
        <div class="btn-row">
          <button id="t1yes" class="toggle" type="button">Making food? Yes</button>
          <button id="t1no" class="toggle" type="button">Making food? No</button>
        </div>
        <p class="tb-note" id="t1note">Is sunlight available for this plant? Is water available? Then predict: is it making food?</p>
      </div>
    </task-block>
    <script>
      function paintStage(stageId, sunLblId, sun, water) {
        var stage = document.getElementById(stageId);
        if (!stage) return;
        stage.classList.toggle("on", sun && water);
        stage.classList.toggle("off", !(sun && water));
        var lbl = document.getElementById(sunLblId);
        if (lbl) lbl.textContent = sun ? "Sun on" : "Sun off";
      }
      var demo = { sun: false, water: false };
      window.__modelxTaskState = { sun: false, water: false, pred: "" };
      window.__modelxGetTaskState = function () { return window.__modelxTaskState; };
      window.__modelxGradeTask = function (s) {
        var stateOK = s.sun === true && s.water === false;
        var predOK = s.pred === "no";
        if (stateOK && predOK) return 100;
        if (stateOK || predOK) return 50;
        return 0;
      };
      function paintTask() {
        var s = window.__modelxTaskState;
        var bSun = document.getElementById("t1sun");
        var bWat = document.getElementById("t1water");
        if (bSun) { bSun.classList.toggle("on", s.sun); bSun.textContent = s.sun ? "Sunlight: available" : "Sunlight: missing"; }
        if (bWat) { bWat.classList.toggle("on", s.water); bWat.textContent = s.water ? "Water: available" : "Water: missing"; }
        var bYes = document.getElementById("t1yes");
        var bNo = document.getElementById("t1no");
        if (bYes) bYes.classList.toggle("on", s.pred === "yes");
        if (bNo) bNo.classList.toggle("on", s.pred === "no");
        var note = document.getElementById("t1note");
        if (note) note.textContent = s.pred ? "Model built. Submit your diagnosis." : "Sunlight " + (s.sun ? "on" : "off") + ", water " + (s.water ? "on" : "off") + ". Now predict: is it making food?";
      }
      window.__modelxOnTaskSubmitted = function (score) {
        var note = document.getElementById("t1note");
        if (note) note.innerHTML = score >= 100 ? "Correct! Sunlight yes, water no. Without water the factory has no ingredient to run on, so this plant is NOT making food - it will wilt and starve." : "The window supplies sunlight, but the bone-dry soil means no water reaches the roots. Photosynthesis needs BOTH - so this plant is not making food.";
        ["t1sun", "t1water", "t1yes", "t1no"].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 === "demoSun" || id === "demoWater") {
          if (id === "demoSun") demo.sun = !demo.sun;
          else demo.water = !demo.water;
          paintStage("demoStage", "demoSunLbl", demo.sun, demo.water);
          var note = document.getElementById("demoNote");
          if (note) note.textContent = demo.sun && demo.water ? "Both on - the leaf is running photosynthesis!" : "Experiment: flip one or both toggles and watch the leaf.";
          return;
        }
        if (id === "t1sun" || id === "t1water") {
          if (id === "t1sun") window.__modelxTaskState.sun = !window.__modelxTaskState.sun;
          else window.__modelxTaskState.water = !window.__modelxTaskState.water;
          paintTask();
          return;
        }
        if (id === "t1yes" || id === "t1no") {
          window.__modelxTaskState.pred = id === "t1yes" ? "yes" : "no";
          paintTask();
          return;
        }
      });
      paintTask();
    </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:#16a34a}
      .plant-wrap{display:flex;align-items:flex-end;justify-content:center;gap:8px;height:150px;margin:6px 0}
      .leaf-demo{width:50px;height:50px;background:#d9f99d;border-radius:50% 0 50% 50%;transition:background .3s ease,transform .3s ease}
      .leaf-demo.r{transform:scaleX(-1)}
      .stem-demo{width:10px;height:60px;background:#15803d;border-radius:3px 3px 0 0}
      .meter{height:12px;border-radius:999px;background:#e2e8f0;overflow:hidden}
      .meter > div{height:100%;width:0%;background:linear-gradient(90deg,#a7f3d0,#059669);transition:width .2s ease}
      .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}
      .scenario{font-size:0.92rem;color:#1e3a8a;background:#eff6ff;border:1px solid #dbeafe;border-radius:12px;padding:10px 14px;font-weight:600}
      .bank{display:flex;flex-wrap:wrap;gap:10px;justify-content:center}
      .chip{border:1px solid #dbe2ea;border-radius:999px;background:#fff;padding:10px 16px;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:#86efac}
      .chip.on{border-color:#16a34a;background:#f0fdf4;color:#166534;box-shadow:0 0 0 2px rgba(22,163,74,.25)}
      .chip:disabled{opacity:.5;cursor:not-allowed}
    </style>
    <h1>Three Ingredients, One Recipe</h1>
    <p class="sub">Photosynthesis needs exactly three inputs, and all three must be present.</p>
    <p>Try the ungraded sliders first. Watch how the &ldquo;recipe rate&rdquo; meter only climbs when <strong>all three</strong> inputs rise together.</p>
    <div class="explain-demo">
      <span class="tag">Explore (not graded)</span>
      <div class="tb-demo">
        <div class="row"><label>Sunlight <span id="dS2v">0</span></label><input id="dS2" type="range" min="0" max="100" value="0"></div>
        <div class="row"><label>Water <span id="dW2v">0</span></label><input id="dW2" type="range" min="0" max="100" value="0"></div>
        <div class="row"><label>Carbon dioxide <span id="dC2v">0</span></label><input id="dC2" type="range" min="0" max="100" value="0"></div>
        <div class="meter"><div id="dMeter"></div></div>
        <p class="tb-note" id="dNote2">Raise all three sliders and watch the rate meter fill.</p>
      </div>
    </div>
    <p class="lead-in">Now the real challenge. This leaf gets a blazing sun (100 units of sunlight) and plenty of water (100 units), but the air is poor in carbon dioxide &mdash; only 30 units reach the leaves. Predict the recipe rate, and name the ingredient that caps it.</p>
    <task-block title="Find the bottleneck" data-question-key="pho-t2" feedback-correct="Rate = 30! The recipe only runs as fast as its slowest ingredient. Sunlight and water are maxed, so carbon dioxide at 30 caps the whole reaction." feedback-incorrect="The recipe runs at the speed of the LOWEST ingredient. Sunlight and water are maxed out, so the 30-unit carbon dioxide is what holds the rate back." submit-label="Submit prediction">
      <div class="tb-demo">
        <div class="scenario">Sunlight = 100&nbsp;&nbsp;|&nbsp;&nbsp;Water = 100&nbsp;&nbsp;|&nbsp;&nbsp;Carbon dioxide = 30</div>
        <div class="row"><label>Your predicted recipe rate <span id="rateGuessV">0</span>%</label><input id="rateGuess" type="range" min="0" max="100" value="0"></div>
        <div class="bank" id="t2Bank">
          <button class="chip" data-b="sun" type="button">Sunlight</button>
          <button class="chip" data-b="water" type="button">Water</button>
          <button class="chip" data-b="co2" type="button">Carbon dioxide</button>
          <button class="chip" data-b="none" type="button">Nothing is holding it back</button>
        </div>
        <p class="tb-note" id="n2">Set your prediction for the recipe rate, then pick the ingredient that caps it. Submit when done.</p>
      </div>
    </task-block>
    <script>
      window.__modelxTaskState = { rate: 0, bottleneck: "" };
      window.__modelxGetTaskState = function () { return window.__modelxTaskState; };
      window.__modelxGradeTask = function (s) {
        var rateScore = Math.max(0, 100 - Math.abs((s.rate || 0) - 30) * 2);
        var bottleScore = s.bottleneck === "co2" ? 100 : 0;
        return Math.round(0.6 * bottleScore + 0.4 * rateScore);
      };
      window.__modelxOnTaskSubmitted = function (score) {
        var note = document.getElementById("n2");
        if (note) note.innerHTML = "The recipe runs at the speed of its slowest ingredient. min(100, 100, 30) = 30, capped by the carbon dioxide. Raise CO&#8322; and the rate climbs.";
        var chips = document.querySelectorAll("#t2Bank .chip");
        for (var i = 0; i < chips.length; i++) chips[i].disabled = true;
        var slider = document.getElementById("rateGuess");
        if (slider) slider.disabled = true;
      };
      function paintRate() {
        var slider = document.getElementById("rateGuess");
        var label = document.getElementById("rateGuessV");
        if (slider && label) label.textContent = slider.value;
      }
      document.addEventListener("input", function (e) {
        if (e.target.id === "rateGuess") {
          window.__modelxTaskState.rate = +e.target.value;
          paintRate();
        }
        if (e.target.id === "dS2" || e.target.id === "dW2" || e.target.id === "dC2") updateDemo();
      });
      document.addEventListener("click", function (e) {
        var t = e.target;
        if (t && t.classList && t.classList.contains("chip")) {
          window.__modelxTaskState.bottleneck = t.getAttribute("data-b");
          var chips = document.querySelectorAll("#t2Bank .chip");
          for (var i = 0; i < chips.length; i++) chips[i].classList.toggle("on", chips[i] === t);
          var note = document.getElementById("n2");
          if (note) note.textContent = "Bottleneck picked: " + t.textContent + ". Submit to check your prediction.";
        }
      });
      function updateDemo() {
        var s = +document.getElementById("dS2").value, w = +document.getElementById("dW2").value, c = +document.getElementById("dC2").value;
        var r = Math.min(s, w, c);
        document.getElementById("dS2v").textContent = s;
        document.getElementById("dW2v").textContent = w;
        document.getElementById("dC2v").textContent = c;
        var meter = document.getElementById("dMeter");
        if (meter) meter.style.width = r + "%";
      }
      updateDemo();
    </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}
      .leaf-cut{position:relative;height:210px;border-radius:14px;background:#f8fafc;border:1px solid #e2e8f0;overflow:hidden;display:grid;place-items:center}
      .leaf-cut svg{width:100%;max-width:300px}
      .opts{display:grid;grid-template-columns:1fr;gap:10px}
      .opt{border:1px solid #e2e8f0;border-radius:12px;background:#fff;padding:12px 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:#16a34a;background:#f0fdf4;font-weight:700;color:#166534}
      .opt:disabled{opacity:.55;cursor:not-allowed}
      .tb-note{text-align:center;font-size:0.9rem;color:#334155;margin:0}
      .beam{fill:#fde68a;opacity:0;transition:opacity .4s ease}
      .chl{fill:#dcfce7;transition:fill .3s ease}
      .explain-demo .beam-on .beam{opacity:.9}
      .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 Solar Panel Inside the Leaf</h1>
    <p class="sub">Chlorophyll is the molecule that catches sunlight.</p>
    <p>Inside every green leaf, <strong>chlorophyll</strong> (the green pigment) acts like a solar panel. It soaks up light energy so the factory can use it. Click the leaf below to watch a light beam hit the chlorophyll.</p>
    <div class="explain-demo">
      <span class="tag">Explore (not graded)</span>
      <div class="leaf-cut" id="demoLeaf">
        <svg viewBox="0 0 300 170">
          <rect x="0" y="0" width="300" height="170" rx="14" fill="#ffffff"></rect>
          <path d="M150 10 L150 60" stroke="#166534" stroke-width="6" stroke-linecap="round"></path>
          <path d="M150 40 C150 40 90 30 60 60 M150 40 C150 40 210 30 240 60 M150 55 C150 55 95 50 70 80 M150 55 C150 55 205 50 230 80" fill="none" stroke="#65a30d" stroke-width="14" stroke-linecap="round"></path>
          <ellipse cx="150" cy="62" rx="95" ry="52" fill="#dcfce7" stroke="#65a30d" stroke-width="3"></ellipse>
          <circle cx="90" cy="50" r="8" class="chl"></circle>
          <circle cx="150" cy="45" r="8" class="chl"></circle>
          <circle cx="205" cy="55" r="8" class="chl"></circle>
          <circle cx="120" cy="80" r="8" class="chl"></circle>
          <circle cx="185" cy="82" r="8" class="chl"></circle>
          <rect x="40" y="8" width="90" height="12" class="beam"></rect>
        </svg>
      </div>
      <p class="tb-note" id="demoNote3">Click the leaf to shine light onto the chlorophyll dots.</p>
    </div>
    <p class="lead-in">Now apply what the demo showed. A variegated plant has leaves with white patches. The white patches contain NO chlorophyll. What can those white patches do?</p>
    <task-block title="Can the white patches make food?" data-question-key="pho-t3" feedback-correct="They cannot make food! No chlorophyll means nothing to catch the light - the white patch is cut off from photosynthesis." feedback-incorrect="Chlorophyll is what captures the light. No chlorophyll, no captured light, no food." submit-label="Check my prediction">
      <div class="tb-demo">
        <div class="opts">
          <button class="opt" id="t3fine" type="button">They make food fine - every part of the leaf works the same</button>
          <button class="opt" id="t3none" type="button">They cannot make food - no chlorophyll to catch light</button>
          <button class="opt" id="t3green" type="button">They make food, just a little less than the green parts</button>
          <button class="opt" id="t3fast" type="button">They make food even faster than the green parts</button>
        </div>
        <p class="tb-note" id="n3">The white patches have no chlorophyll. What does that mean for catching light?</p>
      </div>
    </task-block>
    <script>
      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 ? "Right. The white patch has no chlorophyll, so it captures no light - and with no light captured, it cannot run photosynthesis or make its own food." : "The green part works because of chlorophyll. White patches have none, so they cannot catch light and cannot make food.";
        ["t3fine", "t3none", "t3green", "t3fast"].forEach(function (id) { var el = document.getElementById(id); if (el) el.disabled = true; });
      };
      document.addEventListener("click", function (e) {
        var map = { t3fine: "fine", t3none: "none", t3green: "green", t3fast: "fast" };
        if (e.target.id === "demoLeaf") {
          var dl = document.getElementById("demoLeaf");
          dl.classList.toggle("beam-on");
          var dn = document.getElementById("demoNote3");
          if (dn) dn.textContent = dl.classList.contains("beam-on") ? "Sunlight is hitting the chlorophyll dots - this is where light energy gets caught." : "Click the leaf to shine light on the chlorophyll.";
          return;
        }
        if (map[e.target.id]) {
          window.__modelxTaskState.pick = map[e.target.id];
          ["t3fine", "t3none", "t3green", "t3fast"].forEach(function (id) {
            var el = document.getElementById(id);
            if (el) el.classList.toggle("on", id === e.target.id);
          });
          var n3 = document.getElementById("n3");
          if (n3) n3.textContent = "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}
      .equation{display:flex;flex-wrap:wrap;align-items:center;justify-content:center;gap:10px;font-size:1.05rem;font-weight:700;color:#0f172a;padding:14px;border:1px solid #e2e8f0;border-radius:14px;background:#fff}
      .eq-chip{display:inline-block;padding:6px 12px;border-radius:999px;background:#f1f5f9;color:#475569}
      .eq-chip.ing{background:#f0fdf4;color:#15803d}
      .eq-chip.prod{background:#eff6ff;color:#1d4ed8}
      .eq-chip.hidden{opacity:0;transition:opacity .5s ease}
      .slot{border:2px dashed #cbd5e1;border-radius:12px;padding:8px 14px;min-width:120px;text-align:center;color:#94a3b8;font-size:0.9rem;font-weight:600}
      .slot.filled{border-style:solid;border-color:#16a34a;background:#f0fdf4;color:#166534}
      .bank{display:flex;flex-wrap:wrap;gap:10px;justify-content:center}
      .chip{border:1px solid #dbe2ea;border-radius:999px;background:#fff;padding:10px 16px;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:#86efac}
      .chip.used{opacity:.45;pointer-events:none}
      .chip:disabled{opacity:.45;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:#a7f3d0}
      .opt.on{border-color:#16a34a;background:#f0fdf4;color:#14532d;font-weight:700}
      .opt:disabled{opacity:.55;cursor:not-allowed}
      .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>The Recipe: Inputs In, Products Out</h1>
    <p class="sub">Water + carbon dioxide + light become glucose + oxygen.</p>
    <p>Watch the ungraded animation: ingredients flow <em>in</em> on the left, and the leaf puts <em>out</em> glucose (its food) and oxygen.</p>
    <div class="explain-demo">
      <span class="tag">Explore (not graded)</span>
      <div class="tb-demo">
        <div class="equation" id="demoEq">
          <span class="eq-chip ing hidden" id="dEq1">water</span>
          <span>+</span>
          <span class="eq-chip ing hidden" id="dEq2">carbon dioxide</span>
          <span>+</span>
          <span class="eq-chip ing" id="dEqLight">light</span>
          <span>&rarr;</span>
          <span class="eq-chip prod hidden" id="dEq3">glucose</span>
          <span>+</span>
          <span class="eq-chip prod hidden" id="dEq4">oxygen</span>
        </div>
        <div class="btn-row" style="text-align:center">
          <button id="demoPlay" class="toggle" type="button">Play the reaction</button>
        </div>
        <p class="tb-note" id="demoNote4">Hit play to watch ingredients flow in and products flow out.</p>
      </div>
    </div>
    <p class="lead-in">Now predict it first. The demo showed you the recipe &mdash; light is one of the inputs. A healthy green plant sits in a completely dark closet. Can it make glucose in the dark?</p>
    <task-block title="Can it make glucose in the dark?" data-question-key="pho-t4" feedback-correct="No - light is one of the required inputs. Without light, the chlorophyll has nothing to capture, so the recipe never runs." feedback-incorrect="Look at the recipe inputs: water + carbon dioxide + LIGHT. The demo needs all three to run." submit-label="Check my prediction">
      <div class="tb-demo">
        <div class="opts">
          <button class="opt" id="p4no" type="button">No - light is one of the required inputs</button>
          <button class="opt" id="p4yes" type="button">Yes - it can make glucose in the dark</button>
          <button class="opt" id="p4half" type="button">Yes, but only at half the rate</button>
          <button class="opt" id="p4soil" type="button">No - it needs soil, not light</button>
        </div>
        <p class="tb-note" id="n4">The recipe needs water + carbon dioxide + light. What is missing in a dark closet?</p>
      </div>
    </task-block>
    <script>
      window.__modelxTaskState = { pick: "" };
      window.__modelxGetTaskState = function () { return window.__modelxTaskState; };
      window.__modelxGradeTask = function (s) { return s.pick === "no" ? 100 : 0; };
      window.__modelxOnTaskSubmitted = function (score) {
        var note = document.getElementById("n4");
        if (note) note.innerHTML = score >= 100 ? "No. Without light, the chlorophyll captures nothing and the recipe cannot run - water and carbon dioxide just sit unused." : "Light is one of the three inputs. No light means the recipe never starts, so no glucose gets made.";
        ["p4no", "p4yes", "p4half", "p4soil"].forEach(function (id) { var el = document.getElementById(id); if (el) el.disabled = true; });
      };
      document.addEventListener("click", function (e) {
        if (e.target.id === "demoPlay") {
          var seq = ["dEq1", "dEq2", "dEq3", "dEq4"];
          var labels = ["water", "carbon dioxide", "glucose", "oxygen"];
          for (var i = 0; i < seq.length; i++) {
            (function (idx) {
              setTimeout(function () {
                var el = document.getElementById(seq[idx]);
                if (el) el.classList.remove("hidden");
                var note = document.getElementById("demoNote4");
                if (note) note.textContent = labels[idx];
              }, 600 * idx);
            })(i);
          }
          return;
        }
        var TASK_MAP4 = { p4no: "no", p4yes: "yes", p4half: "half", p4soil: "soil" };
        if (TASK_MAP4[e.target.id]) {
          window.__modelxTaskState.pick = TASK_MAP4[e.target.id];
          ["p4no", "p4yes", "p4half", "p4soil"].forEach(function (id) {
            var el = document.getElementById(id);
            if (el) el.classList.toggle("on", id === e.target.id);
          });
          var n4 = document.getElementById("n4");
          if (n4) n4.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}
      .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 Plant Factory Report</h1>
    <p class="sub">Everything the factory takes in and puts out.</p>
    <div class="sum">
      <p><b>Inputs</b>: water + carbon dioxide + light.<br>
      <b>Captured by</b>: chlorophyll in the chloroplasts.<br>
      <b>Outputs</b>: glucose (food) + oxygen.</p>
    </div>
    <question-block question="Which three things does a plant need for photosynthesis?" answers="Water, carbon dioxide, sunlight|Water, soil, sunlight|Carbon dioxide, soil, oxygen|Sunlight, oxygen, glucose" correct="Water, carbon dioxide, sunlight" mode="single" feedback-correct="Correct! Those are the three inputs." feedback-incorrect="Think about what flows IN: water, CO₂, and light." data-question-key="pho-q1"></question-block>
    <question-block question="Which part of the leaf captures sunlight?" answers="The cell wall|The roots|Chlorophyll|The stomata" correct="Chlorophyll" mode="single" feedback-correct="Right! Chlorophyll is the green pigment that catches light." feedback-incorrect="It is the green pigment inside chloroplasts." data-question-key="pho-q2"></question-block>
    <question-block question="What does the plant make as food?" answers="Oxygen|Glucose|Carbon dioxide|Nitrogen" correct="Glucose" mode="single" feedback-correct="Yes! Glucose is the sugar the plant uses for energy." feedback-incorrect="The plant makes a sugar." data-question-key="pho-q3"></question-block>
    <dropdown-question text="The photosynthesis equation makes glucose and releases __blank__ into the air." options="carbon dioxide|oxygen|nitrogen|water" correct="oxygen" feedback-correct="Correct! Oxygen is the byproduct we breathe." feedback-incorrect="The gas we breathe out of the reaction." data-question-key="pho-q4"></dropdown-question>
    <script></script>
  </page>
</lesson>