diff --git a/docs/challenge-explainers.md b/docs/challenge-explainers.md
index 95567ad..4f156d8 100644
--- a/docs/challenge-explainers.md
+++ b/docs/challenge-explainers.md
@@ -83,3 +83,21 @@ windows: [0,10) | [10,20) watermark = 10
The axes are conceptual but use the exact published numbers. Do not interpolate
a fake performance result. In an editor split, keep critical labels legible
without relying on viewport breakpoints.
+
+## Work and resources batch
+
+These four diagrams share ink typography but not a layout metaphor. Each one
+answers a single question with the exact numbers in its public example. A
+labelled final frame must remain useful without motion or color perception.
+
+| Story | Surface | Single visual transition |
+| --- | --- | --- |
+| Chunk Store | Cool cyan paper with a dark frame boundary | A two-byte selection lights up `CD` in block 1; block 0 remains untouched. |
+| Deadline Scheduler | Ink paper with coral worker lane | C arrives at tick 1 while A continues until tick 6; only then is another dispatch possible. |
+| Durable Queue | Mint field with orange leased state | Nack returns A behind B without releasing resident capacity; B is next. |
+| Fair Gate | Butter field with cobalt token cells | Spend three of four, reject cost three, refill two at tick 3, then admit. |
+
+The typography remains Bricolage for the question and JetBrains Mono for
+bytes, ticks, and tokens. Motion is a finite reveal, never a loop. The queue
+example chooses `Nack` rather than expiry because it matches the published
+worked example; the caption explains that expiry follows the same tail rule.
diff --git a/src/lib/arena/statement.ts b/src/lib/arena/statement.ts
index 2fd471f..113f6ac 100644
--- a/src/lib/arena/statement.ts
+++ b/src/lib/arena/statement.ts
@@ -77,6 +77,10 @@ const conceptFigureProps = {
"systems.journal-story": z.object({}).strict(),
"systems.lsm-story": z.object({}).strict(),
"systems.window-story": z.object({}).strict(),
+ "systems.chunk-story": z.object({}).strict(),
+ "systems.scheduler-story": z.object({}).strict(),
+ "systems.queue-story": z.object({}).strict(),
+ "systems.gate-story": z.object({}).strict(),
} as const;
const figureBlock = z.object({
@@ -88,6 +92,7 @@ const figureBlock = z.object({
"systems.ranges", "systems.exchange",
"systems.cache-story", "systems.lost-ack-story",
"systems.journal-story", "systems.lsm-story", "systems.window-story",
+ "systems.chunk-story", "systems.scheduler-story", "systems.queue-story", "systems.gate-story",
]),
props: z.record(z.string(), z.unknown()).optional(),
}).strict(),
diff --git a/src/packs/systems/index.ts b/src/packs/systems/index.ts
index d659702..85904fc 100644
--- a/src/packs/systems/index.ts
+++ b/src/packs/systems/index.ts
@@ -5,6 +5,7 @@ import { BudgetDiagram, ExchangeDiagram, FrameDiagram, RangeDiagram, SnapshotDia
import { FlowDiagram, StateDiagram, TimelineDiagram } from "./illustrations";
import { JournalRecoveryStory, LsmOverlapStory, StreamWatermarkStory } from "./recovery-time-stories";
import { CacheStory, LostAckStory } from "./story-illustrations";
+import { ChunkReadStory, SchedulerStory, QueueLeaseStory, TokenGateStory } from "./work-stories";
registerIllustration("systems.flow", FlowDiagram);
registerIllustration("systems.state", StateDiagram);
@@ -19,3 +20,7 @@ registerIllustration("systems.lost-ack-story", LostAckStory);
registerIllustration("systems.journal-story", JournalRecoveryStory);
registerIllustration("systems.lsm-story", LsmOverlapStory);
registerIllustration("systems.window-story", StreamWatermarkStory);
+registerIllustration("systems.chunk-story", ChunkReadStory);
+registerIllustration("systems.scheduler-story", SchedulerStory);
+registerIllustration("systems.queue-story", QueueLeaseStory);
+registerIllustration("systems.gate-story", TokenGateStory);
diff --git a/src/packs/systems/work-stories.tsx b/src/packs/systems/work-stories.tsx
new file mode 100644
index 0000000..7089022
--- /dev/null
+++ b/src/packs/systems/work-stories.tsx
@@ -0,0 +1,173 @@
+"use client";
+
+import { cn } from "@/lib/utils";
+
+import { Replay, useVisibleStory } from "./story-illustrations";
+
+function StoryFooter({ copy, finished, reducedMotion, replay }: {
+ copy: string;
+ finished: boolean;
+ reducedMotion: boolean;
+ replay: () => void;
+}) {
+ return (
+
+
{copy}
+ {finished && !reducedMotion &&
}
+
+ );
+}
+
+const CHUNK_STEPS = [
+ "ReadAt(5, 2) asks for bytes C and D.",
+ "The index points to block 1. Block 0 is not read.",
+ "Verify and decode block 1, then return CD.",
+] as const;
+
+export function ChunkReadStory() {
+ const { ref, stage, reducedMotion, replay } = useVisibleStory(2, 1250);
+ return (
+
+
+
+
Read only what you need.
+ ReadAt(5, 2)
+
+
+ {[
+ { name: "BLOCK 0", bytes: "AAAA", touched: false },
+ { name: "BLOCK 1", bytes: "BCDE", touched: true },
+ ].map((block) => (
+
= 1 ? "border-[#2141b4] bg-white" : "border-[#282334]/20 bg-white/45")}>
+
+ {block.name}{block.touched && stage >= 1 ? "SELECTED" : "NO READ"}
+
+
+ {block.bytes.split("").map((byte, index) => (
+ = 2 && (index === 1 || index === 2) ? "bg-[#ff784f]" : "bg-[#282334]/10")}>{byte}
+ ))}
+
+
{block.touched && stage >= 2 ? "CRC verified · CD copied" : block.touched ? "frame + CRC" : "untouched"}
+
+ ))}
+
+
+ logical bytes 0–7{stage === 2 ? "result: CD" : "one indexed frame"}
+
+
+
+
+ );
+}
+
+const SCHEDULER_STEPS = [
+ "A takes the only worker at tick 0.",
+ "C arrives at tick 1, but cannot interrupt A.",
+ "A finishes at tick 6. The next choice happens now.",
+] as const;
+
+export function SchedulerStory() {
+ const { ref, stage, reducedMotion, replay } = useVisibleStory(2, 1400);
+ return (
+
+
+
+
Arrival isn’t interruption.
+ 1 worker
+
+
+
WORKER / TICK
+
+
06811
+
+
+ A running
+ {stage >= 1 && C arrives @ 1 · waits}
+ {stage >= 2 && next dispatch @ 6}
+
+
+
+
+ );
+}
+
+const QUEUE_STEPS = [
+ "A and B are ready; both occupy capacity.",
+ "Lease A. It is still resident while B waits.",
+ "Nack A. Its old token is stale; B is now next.",
+] as const;
+
+export function QueueLeaseStory() {
+ const { ref, stage, reducedMotion, replay } = useVisibleStory(2, 1350);
+ return (
+
+
+
+
Returned means last.
+ FIFO by availability
+
+
+
+
READY / NEXT →
+
+ {(stage === 0 ? ["A", "B"] : stage === 1 ? ["B"] : ["B", "A"]).map((job, index) => (
+ {job}
+ ))}
+ {stage === 1 && A is with worker}
+
+
+
+ WORKER
+ {stage === 1 ? "A · lease to 10" : stage === 2 ? "A returned" : "idle"}
+
+
+
+ resident: A + B{stage === 2 ? "old A token: stale" : "capacity held"}
+
+
+
+
+ );
+}
+
+const GATE_STEPS = [
+ "At tick 0, the burst budget contains four tokens.",
+ "Cost 3 is allowed; one token remains.",
+ "Another cost 3 is rejected. Earliest retry is tick 3.",
+ "At tick 3, two tokens have accrued. Three are available.",
+ "The retry spends all three. Zero remain.",
+] as const;
+
+export function TokenGateStory() {
+ const { ref, stage, reducedMotion, replay } = useVisibleStory(4, 1150);
+ const tokens = [4, 1, 1, 3, 0][stage];
+ return (
+
+
+
+
Wait for the exact tick.
+ 2 tokens / 3 ticks
+
+
+
BURST / 4tick {stage >= 3 ? "3" : "0"}
+
+ {[0, 1, 2, 3].map((i) => (
+
+ ))}
+
+
+ {stage === 0 ? "4 available" : stage === 1 ? "3 spent · 1 available" : stage === 2 ? "3 needed · retry @ 3" : stage === 3 ? "+2 accrued · 3 available" : "3 spent · 0 left"}
+
+
+
+ cost 3{stage === 2 ? "DENIED" : stage === 4 ? "ALLOWED" : "lazy refill"}
+
+
+
+
+ );
+}
diff --git a/tests/e2e/challenge-explainers.spec.ts b/tests/e2e/challenge-explainers.spec.ts
index dd4c69f..699583e 100644
--- a/tests/e2e/challenge-explainers.spec.ts
+++ b/tests/e2e/challenge-explainers.spec.ts
@@ -48,6 +48,33 @@ test.describe("challenge explainers", () => {
await expect(page.getByText("count 1 · sum 7")).toBeVisible();
});
+ test("chunk read decodes only the indexed block", async ({ page }) => {
+ await page.goto("/challenges/chunk-store-easy");
+ await expect(page.getByRole("img", { name: /Only block 1 is verified and decoded/ })).toBeVisible();
+ await expect(page.getByText("CRC verified · CD copied")).toBeVisible();
+ await expect(page.getByText("result: CD")).toBeVisible();
+ });
+
+ test("non-preemptive worker makes its next choice at tick six", async ({ page }) => {
+ await page.goto("/challenges/deadline-scheduler-easy");
+ await expect(page.getByRole("img", { name: /C arrives at tick 1 and waits/ })).toBeVisible();
+ await expect(page.getByText("next dispatch @ 6")).toBeVisible();
+ });
+
+ test("nack returns A behind B and keeps capacity occupied", async ({ page }) => {
+ await page.goto("/challenges/durable-queue-easy");
+ await expect(page.getByRole("img", { name: /ready order B then A/ })).toBeVisible();
+ await expect(page.getByText("resident: A + B")).toBeVisible();
+ await expect(page.getByText("old A token: stale")).toBeVisible();
+ });
+
+ test("the token gate admits the retry at the exact refill tick", async ({ page }) => {
+ await page.goto("/challenges/fair-gate-easy");
+ await expect(page.getByRole("img", { name: /earliest RetryAt tick three/ })).toBeVisible();
+ await expect(page.getByText("3 spent · 0 left")).toBeVisible();
+ await expect(page.getByText("ALLOWED", { exact: true })).toBeVisible();
+ });
+
test("the finite story settles and can be replayed", async ({ page }) => {
await page.emulateMedia({ reducedMotion: "no-preference" });
await page.goto("/challenges/cache-pressure-easy");