/* project-lamp-data.jsx — "The Mood Lamp" build descriptor.
   Smooth a 555's PWM into a steady glow, dial it with a pot, drive a bright LED.
   Sets window.PROJECT_BUILD for projectkit.jsx. Names pk-prefixed (ML_ for build data). */

const pkOhm = (r) => r >= 1000 ? `${(r / 1000).toFixed(r % 1000 ? 1 : 0)} kΩ` : `${r} Ω`;
const pkFar = (c) => c >= 1e-6 ? `${(c * 1e6).toFixed(c * 1e6 % 1 ? 1 : 0)} µF` : `${(c * 1e9).toFixed(0)} nF`;
const pkMA  = (a) => `${a.toFixed(a < 10 ? 1 : 0)} mA`;
const pkSec = (s) => s >= 1 ? `${s.toFixed(2)} s` : `${(s * 1000).toFixed(0)} ms`;

const ML_VB = 9, ML_VF = 2, ML_PWM_T = 0.004; // 250 Hz PWM source

const ML_STAGES = [
  {
    id: "smooth", n: 1, schem: "smooth", part: "cap",
    title: "Smooth the Blink", teaches: "RC smoothing",
    tagline: "Turn a fast on/off square wave into a steady glow.",
    intro: {
      adult: "The 555 only knows on and off — a 250 Hz PWM square wave. A resistor feeding a capacitor averages that into a smooth DC level: the bigger the time constant τ = R·C versus the PWM period, the less ripple is left. With R = 10 kΩ, pick a capacitor that smooths well but still follows the knob.",
      kids: "The chip can only flash fully on or off, really fast. A bucket (capacitor) filled through a pipe (resistor) averages all that flashing into a smooth, steady glow. Pick a bucket big enough to hide the flicker.",
    },
    spec: "Smoothing τ = R·C at least 10× the PWM period (≈ 40 ms), but under ~0.5 s so the knob stays responsive.",
    givens: ["PWM period ≈ 4 ms (250 Hz)", "R = 10 kΩ", "τ = R · C", "Want τ ≈ 40 ms – 0.5 s"],
    explain: "An RC low-pass filter charges and discharges slowly compared to the fast PWM, so the capacitor holds a steady average. τ = R × C; making τ many times the PWM period flattens the ripple — but too large and the lamp lags behind the dimmer knob.",
    picks: [{
      id: "C", label: "Smoothing capacitor", unit: "F",
      hint: "τ = 10 kΩ × C. Aim well past 4 ms, under ~0.5 s.",
      options: [1e-6, 4.7e-6, 1e-5, 4.7e-5, 1e-4].map(c => ({ label: pkFar(c), value: c })),
    }],
    check: (v) => {
      const tau = 10000 * v.C;
      const ratio = tau / ML_PWM_T;
      const ok = tau >= 0.04 && tau <= 0.5;
      return {
        ok,
        headline: `τ ≈ ${pkSec(tau)} · ${ratio.toFixed(0)}× the PWM period`,
        formula: `τ = R·C = 10 kΩ × ${pkFar(v.C)} = ${pkSec(tau)}  (PWM period ≈ 4 ms)`,
        lines: [
          { k: "Target τ", v: "40 ms – 0.5 s" },
          { k: "Your τ", v: pkSec(tau), ok },
          { k: "× PWM period", v: `${ratio.toFixed(0)}×` },
        ],
        note: {
          adult: ok ? "Smooth and responsive — the ripple's gone but the lamp still tracks the knob the instant you turn it." : tau < 0.04 ? "Too little smoothing — you'll see the 250 Hz flicker. Use a bigger capacitor." : "Over-smoothed — the lamp lags noticeably behind the knob. Ease back to a smaller capacitor.",
          kids: ok ? "A perfectly smooth glow that still answers the knob!" : tau < 0.04 ? "Still flickery — use a bigger bucket." : "Too sluggish — the lamp lags the knob. Smaller bucket.",
        },
      };
    },
  },
  {
    id: "dimmer", n: 2, schem: "dimmer", part: "pot",
    title: "The Dimmer Knob", teaches: "Potentiometer control",
    tagline: "A knob sets the level — sized to reach full brightness.",
    intro: {
      adult: "A potentiometer is an adjustable divider: turn it and the control voltage into the driver rises from zero to full. The base resistor between the knob and the transistor sets the top end — at the knob's max it must still deliver enough base current to fully light the 50 mA lamp (≥ 1 mA, with β ≈ 100), without wasting drive.",
      kids: "A knob (potentiometer) lets you set how bright — from off all the way to full. The resistor after the knob decides the brightest setting. Pick it so that turning the knob all the way really does reach full brightness.",
    },
    spec: "At full knob, base current ≥ 1 mA (to saturate the 50 mA lamp) and ≤ 10 mA.",
    givens: ["Lamp target ≈ 50 mA", "β ≈ 100 → just-on at 0.5 mA", "Full-knob I_b ≥ 1 mA", "I_b = (9 − 0.7) ÷ R_b"],
    explain: "At full brightness the knob passes nearly the whole supply to the base resistor, so I_b = (9 − 0.7) ÷ R_b. To saturate a 50 mA lamp you need I_b past I_c/β = 0.5 mA — design for at least double, but don't drown the base.",
    picks: [{
      id: "Rb", label: "Base resistor (after the knob)", unit: "Ω",
      hint: "Smaller R_b → more drive at full knob. Want 1–10 mA.",
      options: [1000, 4700, 10000, 47000].map(r => ({ label: pkOhm(r), value: r })),
    }],
    check: (v) => {
      const Ib = (ML_VB - 0.7) / v.Rb * 1000;
      const ok = Ib >= 1 && Ib <= 10;
      return {
        ok,
        headline: `Full-knob base current ≈ ${pkMA(Ib)}`,
        formula: `I_b = (9 V − 0.7 V) ÷ ${pkOhm(v.Rb)} = ${pkMA(Ib)}   (need ≥ 1 mA)`,
        lines: [
          { k: "Just-saturate (I_c/β)", v: "0.5 mA" },
          { k: "Target at full knob", v: "1 – 10 mA" },
          { k: "Your I_b", v: pkMA(Ib), ok },
        ],
        note: {
          adult: ok ? "The knob now spans dark to full bright — 4.7 kΩ reaches ~1.8 mA at the top, comfortably saturating the lamp." : Ib < 1 ? "At full knob it still can't quite light the lamp fully — the top of the range is dim. Use a smaller base resistor." : "More base drive than the lamp needs — wasteful and it loses fine control near the top. Use a larger base resistor.",
          kids: ok ? "The knob goes from off to full bright — perfect range!" : Ib < 1 ? "Even at full it stays dim. Smaller resistor." : "Too much push — you lose the gentle top end. Bigger resistor.",
        },
      };
    },
  },
  {
    id: "lamp", n: 3, schem: "lamp-driver", part: "led", final: true,
    title: "Drive the Glow", teaches: "Transistor driver",
    tagline: "A bright lamp at full tilt — current-limited safely.",
    intro: {
      adult: "Behind the transistor the lamp can pull far more than a control pin ever could. A high-brightness LED is happy around 40–60 mA — pick the series resistor that sets its full-on current via I = (9 − 2) ÷ R. This is the finale: hit it and your mood lamp glows.",
      kids: "Because the transistor does the muscle work, the lamp can be really bright. Pick the resistor that sets how much flows when it's full on — bright, but not so much it burns out.",
    },
    spec: "Full-on lamp current 40–60 mA. This is the finale — hit it and the Mood Lamp is complete.",
    givens: ["Supply = 9 V", "Bright LED drops 2 V", "Driven by the transistor", "I = (9 − 2) ÷ R, target 40–60 mA"],
    explain: "The transistor carries the lamp current, so the lamp isn't limited by the control side. The series resistor sets full brightness by Ohm's law: I = (9 − 2) ÷ R. A high-brightness LED tolerates more current than the gentle 15 mA of an indicator.",
    picks: [{
      id: "R", label: "Lamp resistor", unit: "Ω",
      hint: "I = (9 − 2) ÷ R. Aim 40–60 mA for a bright glow.",
      options: [100, 120, 150, 220].map(r => ({ label: pkOhm(r), value: r })),
    }],
    check: (v) => {
      const I = (ML_VB - ML_VF) / v.R * 1000;
      const ok = I >= 40 && I <= 60;
      return {
        ok,
        headline: `Full-on lamp current ≈ ${pkMA(I)}`,
        formula: `I = (9 V − 2 V) ÷ ${pkOhm(v.R)} = ${pkMA(I)}`,
        lines: [{ k: "Target", v: "40 – 60 mA" }, { k: "Your current", v: pkMA(I), ok }],
        note: {
          adult: ok ? "A rich, bright glow at full knob — and safely within a high-brightness LED's rating. The Mood Lamp is complete." : I > 60 ? "Too much — even a bright LED runs hot and ages fast here. Use a bigger resistor." : "Dimmer than it could be at full — drop the resistor a little for more punch.",
          kids: ok ? "A warm, bright glow you can dial up and down — the Mood Lamp is ALIVE! 🎉" : I > 60 ? "Too much — it'll run hot. Bigger resistor." : "A bit dim at full. Smaller resistor.",
        },
      };
    },
  },
];

window.PROJECT_BUILD = {
  id: "lamp", name: "The Mood Lamp", em: "Mood Lamp", kicker: "Project 04 · light",
  hero: {
    adult: "Trade the blink for a breath. A capacitor smooths the 555's PWM into a steady level, a potentiometer sets it by hand, and a transistor drives a bright LED — your first analog-feeling control, where a turn of the knob glides from dark to full glow.",
    kids: "A lamp you can fade up and down with a knob. You'll turn the chip's fast flashing into a smooth glow, add a dial to set the brightness, and drive a nice bright light.",
  },
  stages: ML_STAGES,
  learned: {
    smooth: ["An RC filter averages a fast PWM square wave into a smooth voltage.", "Make τ = R·C much larger than the PWM period to kill ripple."],
    dimmer: ["A potentiometer is an adjustable divider — it sets the level by hand.", "Size the base resistor so the knob's top end still saturates the driver."],
    lamp:   ["A transistor driver lets the lamp pull far more current than the control side.", "A series resistor sets full-on current: I = (V − V_LED) ÷ R."],
  },
  finale: {
    adult: "Three stages — a smoothing capacitor, a dimmer knob sized to reach full, and a transistor-driven lamp — and you've turned a hard on-off blink into a glow you sweep by hand. That's analog control.",
    kids: "You turned fast flashing into a smooth, dial-able glow! From a sharp blink to a soft light you control — that's how dimmers and displays feel alive.",
  },
  bench: {
    adult: "You've specified every value. Wire it on the breadboard in this order — the smoothing capacitor on the 555's output, then the pot and base resistor, then the transistor and bright lamp:",
    kids: "You have the plan. Build it for real — the smoothing bucket first, then the knob, then the bright lamp and its driver.",
  },
  specFoot: "Supply 9 V · bright LED Vf 2 V · β ≈ 100 · 250 Hz PWM source · every value meets its target spec.",
};
