/* sandbox.jsx — The Workbench: free-build breadboard sandbox.
   No goal, no grade. Pick a bench mode (which sim engine judges the board),
   place parts, hit power, see what happens. Modes reuse the L2 engines. */

const { useState: sbUseState, useEffect: sbUseEffect } = React;

const SB_TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "theme": "paper",
  "audience": "adult"
}/*EDITMODE-END*/;

/* ── bench modes: sim engine + tool palette + generous limits ──────────── */
const SB_MODES = [
  {
    id: "lights",
    label: "Lights",
    blurb: { adult: "LEDs, resistors, series & parallel. The classic bench.", kids: "Make lights glow — one, two, or a whole row!" },
    sim: (parts) => simulateMulti(parts),
    tools: (kids) => [
      { id: "battery", label: kids ? "Battery (9V)" : "Battery 9V", hint: "+ leg first, then −" },
      { id: "resistor", label: kids ? "Resistor" : "Resistor 330Ω", hint: "either way round" },
      { id: "led", label: "LED", hint: kids ? "long leg (+) first" : "anode (+) first, then cathode" },
      { id: "pot", label: kids ? "Knob (dimmer)" : "Potentiometer", hint: kids ? "drag its knob to dim" : "variable resistor · drag the knob", part: { type: "resistor", pot: true, pos: 0.5, Rmax: 10000, R: 660, taper: "log" } },
      { id: "wire", label: kids ? "Jumper wire" : "Jumper", hint: "connects two holes" },
    ],
    limits: { battery: 1, resistor: 8, led: 8, pot: 2, wire: 24 },
  },
  {
    id: "logic",
    label: "Switches",
    blurb: { adult: "Add switches — build AND / OR gates by hand (ch. 5).", kids: "Add buttons! Make the light need one press — or two." },
    sim: (parts, sw) => simulateLogic(parts, sw),
    tools: (kids) => [
      { id: "battery", label: kids ? "Battery (9V)" : "Battery 9V", hint: "+ leg first, then −" },
      { id: "resistor", label: kids ? "Resistor" : "Resistor 330Ω", hint: "either way round" },
      { id: "led", label: "LED", hint: kids ? "long leg (+) first" : "anode (+) first, then cathode" },
      { id: "switch", label: kids ? "Switch" : "Switch", hint: "tap it on the board to flip" },
      { id: "wire", label: kids ? "Jumper wire" : "Jumper", hint: "connects two holes" },
    ],
    limits: { battery: 1, resistor: 8, led: 6, switch: 6, wire: 24 },
  },
  {
    id: "transistor",
    label: "Transistor",
    blurb: { adult: "The 3-leg valve: a base trickle gates the main flow (ch. 6).", kids: "The magic valve — a tiny stream that opens a big gate!" },
    sim: (parts, sw) => { const r = simulateTransistor(parts, sw); return r.state === "no-tx" ? simulatePower(parts) : r; },
    tools: (kids) => [
      { id: "battery", label: kids ? "Battery (9V)" : "Battery 9V", hint: "+ leg first, then −" },
      { id: "resistor", label: kids ? "Resistor" : "Resistor 330Ω", hint: "either way round" },
      { id: "led", label: "LED", hint: kids ? "long leg (+) first" : "anode (+) first, then cathode" },
      { id: "switch", label: "Switch", hint: "drives the base" },
      { id: "transistor", label: kids ? "Transistor" : "Transistor (NPN)", legs: 3, hint: "tap base, collector, emitter" },
      { id: "wire", label: kids ? "Jumper wire" : "Jumper", hint: "connects two holes" },
    ],
    limits: { battery: 1, resistor: 8, led: 6, switch: 4, transistor: 2, wire: 24 },
  },
  {
    id: "osc",
    label: "Oscillator",
    custom: true,   // renders OscCompareBench instead of the free-build board
    blurb: { adult: "The discrete blinker vs. the 555 chip — side by side, same beat (ch. 10).", kids: "Two blinkers racing — a transistor one and a chip one. Same beat!" },
  },
  {
    id: "osc555",
    label: "555 Tuner",
    custom: true, comp: "osc555",   // live tweakable 555 astable (mna-driven)
    blurb: { adult: "Turn R_A, R_B and C live — watch the 555's square wave and blink rate change (ch. 10).", kids: "Turn the knobs and change how fast your blinker blinks!" },
  },
  {
    id: "timing",
    label: "Timing",
    blurb: { adult: "Capacitors: charge through R, watch the LED fade in (ch. 4).", kids: "The bucket! Make your light turn on slooowly." },
    sim: (parts) => { const r = simulateRC(parts); return r.state === "lit-nodelay" ? { ...r, state: "lit" } : r; },
    tools: (kids) => [
      { id: "battery", label: kids ? "Battery (9V)" : "Battery 9V", hint: "+ leg first, then −" },
      { id: "resistor", label: kids ? "Resistor" : "Resistor 330Ω", hint: "either way round" },
      { id: "led", label: "LED", hint: kids ? "long leg (+) first" : "anode (+) first, then cathode" },
      { id: "capacitor", label: kids ? "Capacitor" : "Capacitor 470µF", part: { C: 2 }, hint: "the bucket" },
      { id: "wire", label: kids ? "Jumper wire" : "Jumper", hint: "connects two holes" },
    ],
    limits: { battery: 1, resistor: 8, led: 6, capacitor: 4, wire: 24 },
  },
  {
    id: "diode",
    label: "Diode",
    blurb: { adult: "One-way valves: blocking, steering, protecting (ch. 7).", kids: "One-way doors for electricity!" },
    sim: (parts, sw) => simulateRectifier(parts, sw),
    tools: (kids) => [
      { id: "battery", label: kids ? "Battery (9V)" : "Rough source 9V", hint: "+ leg first, then −" },
      { id: "resistor", label: kids ? "Resistor" : "Resistor 330Ω", hint: "either way round" },
      { id: "led", label: "LED", hint: kids ? "long leg (+) first" : "anode (+) first, then cathode" },
      { id: "diode", label: kids ? "One-way valve" : "Diode 1N4007", hint: "▷ side first (in), then |" },
      { id: "capacitor", label: kids ? "Capacitor" : "Capacitor 470µF", part: { C: 2 }, hint: "smooths the bumps" },
      { id: "wire", label: kids ? "Jumper wire" : "Jumper", hint: "connects two holes" },
    ],
    limits: { battery: 1, resistor: 8, led: 6, diode: 4, capacitor: 4, wire: 24 },
  },
];

/* Friendly, non-judgy verdicts — the sandbox never says "wrong". */
function sbDescribe(result, kids) {
  const r = result;
  switch (r.state) {
    case "no-batt": return ["warn", kids ? "Add a battery — it's the push that makes everything go." : "No source yet — place the battery to power the board."];
    case "switch-open": return ["warn", kids ? "A switch is open, so the path is broken — nothing flows. Close it to light up!" : "Switch open — the loop is broken, no current. Close a switch to complete the path."];
    case "open": return ["warn", kids ? "No complete loop yet. Follow the path from + all the way back to −." : "Open circuit — no complete path from + back to −. Not wrong, just not finished."];
    case "backwards": return ["warn", kids ? "An LED is in backwards — flip it and see!" : "An LED is reversed — it blocks in that direction. Flip it (or keep it; that's a lesson too)."];
    case "cap-series": return ["warn", kids ? "Your capacitor is in the way like a closed door — it fills up then stops the flow. Put it BESIDE the LED (both legs on the LED's two rows), not in the line." : "A capacitor in series blocks steady current — it charges, then DC stops. For the RC fade, wire the cap in PARALLEL with the LED (across its two nodes), with the resistor feeding that node."];
    case "diode-backwards": return ["warn", kids ? "The one-way door is facing backwards — it blocks the flow. Flip the diode around!" : "Diode is reverse-biased — it blocks current that way. Flip it so the ▷ points with the flow (anode to +)."];
    case "short":
      return ["fail", kids ? "+ is connected straight to − — a short circuit! Real batteries get HOT doing this." : "Short circuit: + tied to − without a load. On a real bench this cooks the battery. Add something useful in the path."];
    case "pop":
      return ["fail", kids ? "Pop! 💥 Too much flow for the LED. Add a resistor to calm it down." : "LED popped — too much current. This is why every LED gets a series resistor. Undo and try one."];
    case "lit": {
      if (r.timed) return ["pass", kids ? "It works — watch it fade in! The bucket is filling." : `Works — RC ramp of ~${(r.delay || 1).toFixed(1)}s. The cap charges through the resistor.`];
      const i = r.I ? ` at ${r.I.toFixed(0)} mA` : "";
      return ["pass", kids ? "It glows! You built that. Now change something and see what happens." : `Lit${i}. Now perturb it — add a branch, double the resistance, see what moves.`];
    }
    case "lit-nodelay": {
      const i = r.I ? ` at ${r.I.toFixed(0)} mA` : "";
      return ["pass", kids ? "It glows! Add a capacitor across it to make it fade in slowly." : `Lit${i} — no timing element, so it's instant. Add a cap across the LED for an RC fade.`];
    }
    default:
      return ["warn", kids ? "Hmm — try the power button and see." : "Indeterminate state — power it and probe."];
  }
}

/* ── things to try — gentle prompts, not assignments ───────────────────── */
const SB_IDEAS = {
  lights: {
    adult: ["Two LEDs in series — why are both dimmer?", "Two LEDs in parallel — independent, both bright", "One resistor shared vs. one each — spot the difference", "Pull a wire out of a lit circuit and watch the loop die"],
    kids: ["Can you light TWO lights at once?", "Make one bright and one dim!", "What happens if you pull a wire out?"],
  },
  logic: {
    adult: ["Two switches in series — an AND gate", "Two in parallel — an OR", "AND of an OR: (A or B) and C", "A switch that shorts past the LED — why does it go dark?"],
    kids: ["Make a light that needs BOTH buttons", "Make a light that works with EITHER button", "Can you make a button that turns the light OFF?"],
  },
  transistor: {
    adult: ["Switch → base: the classic driver", "No base connection — why does the main loop stay dead?", "Base straight to + (no switch) — always on"],
    kids: ["Make the tiny switch boss the big light around!", "Take away the trickle — does the gate close?"],
  },
  timing: {
    adult: ["R → C → LED: a slow fade-in", "Double the capacitance — slower ramp", "Two caps in parallel = one bigger bucket"],
    kids: ["Make the slowest light ever!", "Two buckets — even slower?"],
  },
  diode: {
    adult: ["Diode forward: passes. Reverse: blocks", "Diode + cap: the half-wave rectifier topology", "Backwards-battery protection — diode in series"],
    kids: ["Put the one-way door in backwards — what happens?", "Can the door protect the light from a backwards battery?"],
  },
};

/* ready-made working examples — one per mode ("fill it in for me"). All five
   verified to light/animate with their bench engine. */
const SB_EXAMPLES = {
  lights: [
    { name: "Single LED", switches: {}, parts: [
      { type: "battery", a: "P6", b: "N6" },
      { type: "wire", a: "P0", b: "T1a" },
      { type: "resistor", a: "T1a", b: "T2a", R: 330 },
      { type: "led", a: "T2a", b: "T3a" },
      { type: "wire", a: "T3a", b: "N2" },
    ] },
    { name: "Two LEDs · parallel", switches: {}, parts: [
      { type: "battery", a: "P6", b: "N6" },
      { type: "wire", a: "P0", b: "T1a" },
      { type: "resistor", a: "T1a", b: "T2a", R: 330 },
      { type: "led", a: "T2a", b: "T3a" },
      { type: "led", a: "T2b", b: "T3b" },
      { type: "wire", a: "T3c", b: "N2" },
    ] },
    { name: "Two LEDs · series", switches: {}, parts: [
      { type: "battery", a: "P6", b: "N6" },
      { type: "wire", a: "P0", b: "T1a" },
      { type: "resistor", a: "T1a", b: "T2a", R: 330 },
      { type: "led", a: "T2a", b: "T3a" },
      { type: "led", a: "T3a", b: "T4a" },
      { type: "wire", a: "T4a", b: "N3" },
    ] },
    { name: "Dimmer (turn the knob)", switches: {}, parts: [
      { type: "battery", a: "P6", b: "N6" },
      { type: "wire", a: "P0", b: "T1a" },
      { type: "resistor", a: "T1a", b: "T2a", R: 330 },
      { type: "resistor", a: "T2a", b: "T3a", pot: true, pos: 0.5, Rmax: 10000, R: 660, taper: "log" },
      { type: "led", a: "T3a", b: "T4a" },
      { type: "wire", a: "T4a", b: "N3" },
    ] },
    { name: "Dimmer · NO safety resistor ⚠", switches: {}, parts: [
      { type: "battery", a: "P6", b: "N6" },
      { type: "wire", a: "P0", b: "T1a" },
      { type: "resistor", a: "T1a", b: "T2a", pot: true, pos: 0.55, Rmax: 10000, R: 874, taper: "log" },
      { type: "led", a: "T2a", b: "T3a" },
      { type: "wire", a: "T3a", b: "N2" },
    ] },
    { name: "Voltage divider (probe the tap)", switches: {}, parts: [
      { type: "battery", a: "P6", b: "N6" },
      { type: "wire", a: "P0", b: "T1a" },
      { type: "resistor", a: "T1a", b: "T2a", R: 1000 },
      { type: "resistor", a: "T2a", b: "N2", R: 1000 },
      { type: "resistor", a: "T2b", b: "T3a", R: 330 },
      { type: "led", a: "T3a", b: "T4a" },
      { type: "wire", a: "T4a", b: "N3" },
    ] },
  ],
  logic: [
    { name: "One switch, one light", switches: { 3: true }, parts: [
      { type: "battery", a: "P6", b: "N6" },
      { type: "wire", a: "P0", b: "T1a" },
      { type: "resistor", a: "T1a", b: "T2a", R: 330 },
      { type: "switch", a: "T2a", b: "T3a" },
      { type: "led", a: "T3a", b: "T4a" },
      { type: "wire", a: "T4a", b: "N3" },
    ] },
    { name: "AND gate · two in series", switches: { 3: true, 4: true }, parts: [
      { type: "battery", a: "P6", b: "N6" },
      { type: "wire", a: "P0", b: "T1a" },
      { type: "resistor", a: "T1a", b: "T2a", R: 330 },
      { type: "switch", a: "T2a", b: "T3a" },
      { type: "switch", a: "T3a", b: "T4a" },
      { type: "led", a: "T4a", b: "T5a" },
      { type: "wire", a: "T5a", b: "N4" },
    ] },
    { name: "OR gate · two in parallel", switches: { 3: true, 4: true }, parts: [
      { type: "battery", a: "P6", b: "N6" },
      { type: "wire", a: "P0", b: "T1a" },
      { type: "resistor", a: "T1a", b: "T2a", R: 330 },
      { type: "switch", a: "T2a", b: "T3a" },
      { type: "switch", a: "T2b", b: "T3b" },
      { type: "led", a: "T3a", b: "T4a" },
      { type: "wire", a: "T4a", b: "N3" },
    ] },
  ],
  transistor: [
    { name: "Transistor switch", switches: {}, parts: [
      { type: "battery", a: "P6", b: "N6" },
      { type: "wire", a: "P0", b: "T1a" },
      { type: "resistor", a: "T1a", b: "T2a", R: 330 },
      { type: "led", a: "T2a", b: "T3a" },
      { type: "transistor", a: "T4a", b: "T3b", c: "T5a" },
      { type: "wire", a: "T5a", b: "N4" },
      { type: "resistor", a: "P3", b: "T4a", R: 10000 },
    ] },
  ],
  timing: [
    { name: "Instant LED (no cap)", switches: {}, parts: [
      { type: "battery", a: "P6", b: "N6" },
      { type: "wire", a: "P0", b: "T1a" },
      { type: "resistor", a: "T1a", b: "T2a", R: 330 },
      { type: "led", a: "T2a", b: "T3a" },
      { type: "wire", a: "T3a", b: "N2" },
    ] },
    { name: "Slow fade-in (RC)", switches: {}, parts: [
      { type: "battery", a: "P6", b: "N6" },
      { type: "wire", a: "P0", b: "T1a" },
      { type: "resistor", a: "T1a", b: "T2a", R: 1000 },
      { type: "led", a: "T2a", b: "T3a" },
      { type: "capacitor", a: "T2b", b: "T3b", C: 2 },
      { type: "wire", a: "T3c", b: "N2" },
    ] },
  ],
  diode: [
    { name: "Diode forward (passes)", switches: {}, parts: [
      { type: "battery", a: "P6", b: "N6" },
      { type: "diode", a: "P0", b: "T1a" },
      { type: "resistor", a: "T1a", b: "T2a", R: 330 },
      { type: "led", a: "T2a", b: "T3a" },
      { type: "wire", a: "T3a", b: "N2" },
    ] },
    { name: "Diode reversed (blocks)", switches: {}, parts: [
      { type: "battery", a: "P6", b: "N6" },
      { type: "diode", a: "T1a", b: "P0" },
      { type: "resistor", a: "T1a", b: "T2a", R: 330 },
      { type: "led", a: "T2a", b: "T3a" },
      { type: "wire", a: "T3a", b: "N2" },
    ] },
    { name: "Rectifier + smoothing cap", switches: {}, parts: [
      { type: "battery", a: "P6", b: "N6" },
      { type: "diode", a: "P0", b: "T1a" },
      { type: "capacitor", a: "T1a", b: "N2", C: 2 },
      { type: "resistor", a: "T1a", b: "T2a", R: 330 },
      { type: "led", a: "T2a", b: "T3a" },
      { type: "wire", a: "T3a", b: "N3" },
    ] },
  ],
};

function SbApp() {
  const [t, setTweak] = useTweaks(SB_TWEAK_DEFAULTS);
  useCrossChapterPersistence(t, setTweak);
  sbUseEffect(() => { document.body.setAttribute("data-theme", t.theme); }, [t.theme]);
  const kids = t.audience === "kids";
  const [modeId, setModeId] = sbUseState("lights");
  const [showCharges, setShowCharges] = sbUseState(true);
  const [liveMode, setLiveMode] = sbUseState(true);   // M3: transient sim on the board
  const [preset, setPreset] = sbUseState(null);
  const loadExample = (idx) => setPreset({ ...SB_EXAMPLES[modeId][idx], mode: modeId, idx, nonce: Date.now() });
  const mode = SB_MODES.find(m => m.id === modeId);

  // ── the parts bin: pick the VALUE the next resistor / capacitor will have ──
  const [rOhm, setROhm] = sbUseState(330);
  const [cUf, setCUf] = sbUseState(470);
  const fmtOhm = (r) => (r >= 1000 ? (r / 1000).toString().replace(".0", "") + " kΩ" : r + " Ω");
  const tools = mode.tools ? mode.tools(kids).map(tl =>
    tl.id === "resistor"
      ? { ...tl, label: (kids ? "Resistor " : "Resistor ") + fmtOhm(rOhm), part: { ...(tl.part || {}), R: rOhm } }
      : tl.id === "capacitor"
      ? { ...tl, label: (kids ? "Capacitor " : "Capacitor ") + cUf + " µF", part: { ...(tl.part || {}), C: cUf / 235, uF: cUf } }
      : tl) : [];
  const hasCapTool = tools.some(tl => tl.id === "capacitor");
  const binChip = (on) => ({
    cursor: "pointer", fontSize: 12, padding: "6px 12px", flexShrink: 0, whiteSpace: "nowrap",
    background: on ? "var(--ink)" : "transparent",
    color: on ? "var(--bg-card)" : "var(--ink-soft)",
    border: `1.5px solid ${on ? "var(--ink)" : "var(--rule-strong)"}`,
    borderRadius: 7, fontFamily: "IBM Plex Mono, monospace", letterSpacing: "0.04em",
  });
  // horizontal scroll strip for the value buttons (so the full E-series fits)
  const binStrip = { display: "flex", gap: 8, overflowX: "auto", padding: "2px 2px 7px", WebkitOverflowScrolling: "touch", scrollbarWidth: "thin", flex: "1 1 auto", minWidth: 0 };
  const binLabel = { fontFamily: "IBM Plex Mono, monospace", fontSize: 12, color: "var(--ink-faint)", width: 86, flexShrink: 0 };

  // The value selectors now live WITH the parts palette (passed into the builder),
  // so "pick a value" and "pick a part to place" read as one combined parts area.
  const valueBin = (
    <div style={{ marginBottom: 12 }}>
      <div className="eyebrow" style={{ marginBottom: 9 }}>{kids ? "pick a size for the next part" : "value for the NEXT part placed"}</div>
      <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
        <span style={binLabel}>{kids ? "squeeze:" : "resistor:"}</span>
        <div style={binStrip}>
          {[100, 220, 330, 470, 680, 1000, 2200, 4700, 10000, 22000, 47000, 100000].map(r => (
            <button key={r} style={binChip(r === rOhm)} onClick={() => setROhm(r)}>{fmtOhm(r)}</button>
          ))}
        </div>
      </div>
      {hasCapTool && (
        <div style={{ display: "flex", alignItems: "center", gap: 8, marginTop: 8 }}>
          <span style={binLabel}>{kids ? "bucket:" : "capacitor:"}</span>
          <div style={binStrip}>
            {[1, 10, 47, 100, 220, 470, 1000].map(c => (
              <button key={c} style={binChip(c === cUf)} onClick={() => setCUf(c)}>{c} µF</button>
            ))}
          </div>
        </div>
      )}
    </div>
  );

  return (
    <>
      <ProgressBar />
      <TopBar chapterLabel="The Workbench" audience={t.audience}
              setAudience={(a) => setTweak("audience", a)} />

      <main>
        <section className="section" id="workbench" data-screen-label="Workbench" style={{ paddingTop: "13vh" }}>
          <div className="section-inner">
            <div className="eyebrow" style={{ marginBottom: 10 }}>the workbench · free build</div>
            <h1 className="serif" style={{ fontSize: "clamp(34px, 5vw, 54px)", margin: "0 0 10px" }}>
              No goal. No grade.<br/><em>Just wire things.</em>
            </h1>
            <p className="lede" style={{ maxWidth: 640 }}>
              {kids
                ? <>This is YOUR bench. Pick your parts, tap two holes to place each one, and hit power. Nothing here counts for anything — which means you can't mess up.</>
                : <>Everything the course taught, with the training wheels off. Pick a bench, place parts, power it, and find out. Shorts, pops, and dead loops are all honest answers here — the sandbox judges nothing.</>}
            </p>

            <div style={{ display: "flex", gap: 8, alignItems: "center", flexWrap: "wrap", marginTop: 14, fontFamily: "var(--mono, 'IBM Plex Mono', monospace)", fontSize: 12.5 }}>
              <span style={{ background: "var(--bg-deeper)", border: "1px solid var(--rule)", borderRadius: 6, padding: "3px 9px", color: "var(--ink-soft)" }}>use this to <b style={{ color: "var(--ink)" }}>build</b> on a real breadboard</span>
              <span style={{ color: "var(--ink-faint)" }}>— want to see how a circuit actually works first?</span>
              <a href="flow-sandbox.html" style={{ color: "var(--water)", textDecoration: "none" }}>Go to The Sandbox →</a>
              <a href="circuit-lab.html" style={{ color: "var(--water)", textDecoration: "none" }}>Circuit Lab →</a>
            </div>

            {/* bench mode chips */}
            <div style={{ display: "flex", gap: 8, flexWrap: "wrap", margin: "22px 0 8px" }}>
              {SB_MODES.map(m => (
                <button key={m.id} className="chip" onClick={() => setModeId(m.id)}
                        style={{
                          cursor: "pointer", fontSize: 13, padding: "9px 18px",
                          background: m.id === modeId ? "var(--ink)" : "transparent",
                          color: m.id === modeId ? "var(--bg-card)" : "var(--ink-soft)",
                          border: `1.5px solid ${m.id === modeId ? "var(--ink)" : "var(--rule-strong)"}`,
                          borderRadius: 8, fontFamily: "IBM Plex Mono, monospace", letterSpacing: "0.06em",
                        }}>
                  {m.label}
                </button>
              ))}
            </div>
            <p className="marg" style={{ marginBottom: 18 }}>{kids ? mode.blurb.kids : mode.blurb.adult}</p>

            {mode.custom ? (mode.comp === "osc555" ? <Osc555Free kids={kids} /> : <OscMode kids={kids} />) : (<>
            {/* example gallery — named circuits, simple → complex */}
            <div style={{ marginBottom: 14 }}>
              <div className="eyebrow" style={{ marginBottom: 8 }}>{kids ? "\u2728 load an example · simple → tricky" : "\u2728 load an example · simple → complex"}</div>
              <div style={{ display: "flex", gap: 8, flexWrap: "wrap" }}>
                {SB_EXAMPLES[modeId].map((ex, i) => {
                  const on = preset && preset.mode === modeId && preset.idx === i;
                  return (
                  <button key={ex.name} onClick={() => loadExample(i)}
                          style={{
                            cursor: "pointer", fontSize: 12.5, padding: "8px 14px",
                            background: on ? "var(--current)" : "transparent",
                            color: on ? "#fff" : "var(--current)",
                            border: "1.5px solid var(--current)",
                            borderRadius: 8, fontFamily: "IBM Plex Mono, monospace", letterSpacing: "0.03em",
                            display: "flex", alignItems: "center", gap: 7,
                            boxShadow: on ? "0 4px 14px -6px var(--current)" : "none",
                          }}>
                    <span style={{ opacity: on ? 0.95 : 0.6, fontWeight: 600 }}>{on ? "\u2713" : i + 1}</span>{ex.name}
                  </button>
                  );
                })}
              </div>
            </div>

            {/* live-sim toggle — the board runs the real transient engine */}
            <div style={{ display: "flex", alignItems: "center", gap: 12, marginBottom: 14, flexWrap: "wrap" }}>
              <button onClick={() => setLiveMode(v => !v)}
                      style={{
                        cursor: "pointer", fontSize: 13, padding: "9px 18px",
                        background: liveMode ? "var(--current)" : "transparent",
                        color: liveMode ? "#fff" : "var(--ink-soft)",
                        border: `1.5px solid ${liveMode ? "var(--current)" : "var(--rule-strong)"}`,
                        borderRadius: 8, fontFamily: "IBM Plex Mono, monospace", letterSpacing: "0.05em",
                      }}>
                {liveMode ? "\u25cf live sim: ON" : "\u25cb live sim: OFF"}
              </button>
              <span className="marg" style={{ fontSize: 13, color: "var(--ink-faint)" }}>
                {kids
                  ? <>The light’s brightness is the REAL flow through it — turn a knob and watch it dim for real.</>
                  : <>LED brightness is solved live by the transient circuit engine (Ohm + Kirchhoff each frame), not a lookup. Dimmers, RC fades and switch flips animate continuously.</>}
              </span>
            </div>

            {/* watch-the-charges toggle */}
            <div style={{ display: "flex", alignItems: "center", gap: 12, marginBottom: 14, flexWrap: "wrap" }}>
              <button onClick={() => setShowCharges(v => !v)}
                      style={{
                        cursor: "pointer", fontSize: 13, padding: "9px 18px",
                        background: showCharges ? "var(--water)" : "transparent",
                        color: showCharges ? "#fff" : "var(--ink-soft)",
                        border: `1.5px solid ${showCharges ? "var(--water)" : "var(--rule-strong)"}`,
                        borderRadius: 8, fontFamily: "IBM Plex Mono, monospace", letterSpacing: "0.05em",
                      }}>
                {showCharges ? "\u25cf charges: ON" : "\u25cb charges: OFF"}
              </button>
              <span className="marg" style={{ fontSize: 13, color: "var(--ink-faint)" }}>
                {kids
                  ? <>Watch the dots flow through whatever you build — flip a switch and see them stop!</>
                  : <>Spectrum charges flow along the path you wired (blue = full → red = spent). Open a switch and the whole loop freezes.</>}
              </span>
            </div>

            {/* key forces remount on mode switch so parts don't carry across engines */}
            <BreadboardBuilder key={modeId} kids={kids}
                               sim={mode.sim} tools={tools} limits={mode.limits}
                               describe={sbDescribe}
                               showCharges={showCharges}
                               live={liveMode}
                               valueBin={valueBin}
                               preset={preset && preset.mode === modeId ? preset : null}
                               goalAdult="Free build — anything goes."
                               goalKids="Free build — anything goes!" />
            </>)}

            {!mode.custom && (
            <div className="card" style={{ marginTop: 26, background: "transparent", maxWidth: 720 }}>
              <div className="eyebrow" style={{ marginBottom: 10 }}>{kids ? "fun things to try" : "things worth trying"}</div>
              <ul style={{ margin: 0, paddingLeft: 22, display: "grid", gap: 7 }}>
                {(kids ? SB_IDEAS[modeId].kids : SB_IDEAS[modeId].adult).map((idea, i) => (
                  <li key={i} style={{ fontSize: 15.5, lineHeight: 1.5 }}>{idea}</li>
                ))}
              </ul>
            </div>
            )}

            <div style={{ display: "flex", gap: 12, marginTop: 30, flexWrap: "wrap" }}>
              <PrevChapterButton href="map.html" label="Course map" />
              <NextChapterButton href="scope.html" label="Learn the oscilloscope" />
            </div>
          </div>
        </section>
      </main>

      <TweaksPanel title="Tweaks">
        <CommonTweaks t={t} setTweak={setTweak} />
      </TweaksPanel>
      <GlossaryFab />
    </>
  );
}

ReactDOM.createRoot(document.getElementById("root")).render(<SbApp />);
