diff --git a/src/ui/tutorial.ts b/src/ui/tutorial.ts
new file mode 100644
index 0000000..5110a5b
--- /dev/null
+++ b/src/ui/tutorial.ts
@@ -0,0 +1,149 @@
+// Goal-driven tutorial: a quest card that watches sim state and advances
+// itself. Optional (chip toggle), persisted, auto-skips already-done steps.
+import { SimState } from "../sim/state";
+import { sfx } from "./sfx";
+
+interface Step {
+ id: string;
+ title: string;
+ body: string;
+ done: (s: SimState) => boolean;
+}
+
+const STEPS: Step[] = [
+ {
+ id: "wire",
+ title: "Plug in the slop pipe",
+ body: "Your PC can't sell garbage without internet. Press W (or the ๐ Wire chip), click the PC, then the router.",
+ done: (s) => s.devices.some((d) => d.wiredTo !== null),
+ },
+ {
+ id: "first_video",
+ title: "Watch the slop flow",
+ body: "You're live. Tokens accumulate and videos publish themselves โ watch SLOPTUBE STUDIO (bottom-left) and NET/S up top. Views = ad money.",
+ done: (s) => s.videos.length >= 1,
+ },
+ {
+ id: "fan",
+ title: "Your room is cooking",
+ body: "Computers make heat; above 85ยฐC they throttle. Buy a Desk Fan ($18) from the store and drop it next to the PC. Right-click sells stuff.",
+ done: (s) => s.devices.some((d) => d.defId === "desk_fan" || d.defId === "window_ac"),
+ },
+ {
+ id: "train",
+ title: "The platforms are learning",
+ body: "Every publish raises ALGO HEAT โ spam filters adapt and views shrink. Push the TRAIN slider up to bank training tokens for a fresh model.",
+ done: (s) => s.allocTraining >= 0.4 || s.trainTokens > 800,
+ },
+ {
+ id: "release",
+ title: "Release the next version",
+ body: "Open the ๐งช Model Lab (L). When the bank covers it, train the next version โ new models slip right past the filters and earn more per view.",
+ done: (s) => s.tier >= 1,
+ },
+ {
+ id: "raise",
+ title: "Take the devil's money",
+ body: "Hit ๐ฐ Raise Seed: instant cash, but the board sets a views target with a deadline. Miss it and they take equity forever. Spend the money on compute immediately.",
+ done: (s) => s.round >= 1 || s.mandate !== null,
+ },
+ {
+ id: "scale",
+ title: "Build a real rig",
+ body: "Buy a Rig Frame, click it, and install GPU cards in its slots. Watch the POWER bar โ trip the breaker and your training checkpoint corrupts. Sub-panels add capacity.",
+ done: (s) => s.devices.some((d) => d.gpus.length >= 2),
+ },
+ {
+ id: "ship",
+ title: "Ship it and sell the excess",
+ body: "In the Lab, ship a grade of your model (mini/pro/MAX). Then open the ๐ก Market (M) and use the HOST slider to sell spare compute. Hosting your own weights invites distillation โ that's the fun part.",
+ done: (s) => s.shippedGrades.length >= 1,
+ },
+ {
+ id: "grad",
+ title: "You are now the problem",
+ body: "The rest you learn by fire โ literally, hardware over 95ยฐC ignites. Subscribers hate downtime, rivals hate you, and the furnace takes cash. Good luck. ๐ซก