# Visual Grammar — Concept Shape → Medium (implementation recipes)

Everything is vanilla JS + SVG/Canvas + CSS unless noted. CDN-allowed libs: Chart.js, rough.js, d3 (only when data structure genuinely needs it). One HTML file, opens from disk, no build.

Global rules that apply to every recipe:
- Every animation gets: a scrubber or step buttons, a replay button, and a static-with-steps fallback under `prefers-reduced-motion`.
- Signaling: when explaining part N, dim everything else to ~30% opacity (spotlight pattern). Never rely on the reader finding the right region.
- Consistent cast identity: each named part keeps its color/shape/icon across every chunk.
- Labels live ON the graphic. Arrows/leader-lines over legends. Legends are a spatial-contiguity failure.

---

## FLOW (sequence, pipeline, protocol, algorithm)

**Recipe: step-sequencer.** SVG scene of the stations; a token (dot/packet/document glyph) travels the path. Controls: ⏮ prev-step, ▶ play, ⏭ next-step, plus a scrub range input mapped to step index. Each step advance updates a one-line caption *synchronized* with the motion (temporal contiguity) and highlights the active station.
- Implementation: define `steps = [{highlight, tokenPos, caption}, ...]`; a single `render(i)` function; play = interval over `render`. Animate token via CSS transform transitions between positions (transform/opacity only).
- Branching flows: show the happy path first, then replay with the branch ("now watch what happens when the cache misses").
- Algorithms over data: render the data structure's state per step (array as boxes, values morph with FLIP animations). Show the SAME algorithm on a second input after the first run.

## SYSTEM (interacting parts, feedback loops)

**Recipe: knob-simulation.** Canvas or SVG live model with 1–3 sliders max (each additional knob multiplies confusion). The loop runs visibly slow enough to follow (or has a speed control). Pair with suggested experiments: "set birth rate to max — watch the crash."
- Feedback loops get an explicit loop-arrow overlay toggle: "show me the loop" draws the causal circle with +/− signs on each edge.
- Equilibrium/oscillation topics: plot the live time-series of one variable *next to* the simulation so the reader connects animation ↔ chart.

**Above ~5 boxes this becomes a graph, not a drawing.** Switch to `system-diagrams.md`: declare nodes and edges, compute the layout, emit static SVG, then offer lenses (structure, traffic, ownership, failure) over that one layout.

## HIERARCHY (containment, taxonomy, scale of organization)

**Recipe: zoom-descent.** Nested rounded rects; clicking a node smooth-zooms into it (scale+translate transform on a group), breadcrumb trail appears top-left (working-memory offload: always show the path from root). Collapse everything not on the current path.
- Alternative for wide taxonomies: indented collapsible tree, but pre-collapsed to depth 1 — never dump the full tree.

## CHANGE (over time: growth, decay, training curves, history)

**Recipe: scrub-chart.** Chart.js line/area with a time scrubber; a vertical "now" cursor with a callout showing the value + a one-line "what's happening here" annotation for pre-marked epochs. Key events are dots on the line that pulse when the cursor crosses them.
- Exponential growth: linear axis FIRST (the hockey stick shock is the lesson), then offer the log toggle and explain what log-scale does in one line.
- History timelines: horizontal scroll-linked band, era-colored; keep it to ≤12 marked events.

## COMPARISON (X vs Y, tradeoffs)

**Recipe: synced-panels.** Two side-by-side panels (stack at mobile width), ONE set of controls drives both simultaneously — the reader changes the input once and watches both react differently. Difference callouts appear at divergence moments.
- Tradeoff matrices: never a raw table dump; a 2-axis scatter ("fast↔cheap vs simple↔powerful") with the options as labeled dots, hover for the one-line story of each.
- "Old way vs new way": before/after slider (drag divider) when visual, sequential reveal when procedural.

## SCALE (orders of magnitude)

**Recipe: zoom-ladder.** Scroll-driven (or button-stepped) zoom where each step is exactly one order of magnitude and each rung has a familiar anchor object drawn to relative size. Show the ratio explicitly at each step ("×10"). Scroll-jacking is acceptable HERE only — it's the one pattern where hijacked scroll = the meaning.
- Alternative: fixed viewport, shrinking reference object with ghost outline of previous size (persistence of the previous rung is what makes the ratio legible).

## MECHANISM (hidden machinery)

**Recipe: cutaway + fire-one-cycle.** Layered SVG: skin layer, mechanism layer, annotation layer. An x-ray slider (drag a divider, or layer-toggle chips) reveals internals. A "fire one cycle" button runs exactly one operation slowly with each phase captioned.
- For invisible/abstract machinery (transformer attention, GC, event loop): invent a spatial metaphor and keep it rigorously consistent; the metaphor IS the interface. Show real values flowing (actual tiny numbers, actual tokens) — abstract flow arrows teach less than watching "0.73" move.

## PROBABILITY (uncertainty, risk, distributions)

**Recipe: dot-swarm.** Populations as individual animated dots (100 or 1000). Conditional probability = natural-frequency tree where the dots physically flow into branches. A "run it again" button re-samples — variance across runs teaches noise better than any sentence.
- Distributions: build the histogram by raining dots into bins, not by revealing a curve. The curve appears at the end as the shadow of the accumulated dots.
- Never: pie charts, standalone percentages for conditionals, error bars without explanation.

---

## Sketch / artistic register

When the domain is human, organic, historical, or emotional (not precision-technical), a hand-drawn register lowers intimidation and raises warmth:
- rough.js (CDN) for wobbly rects/arrows/underlines; or SVG `filter: url(#roughen)` with `feTurbulence + feDisplacementMap` for a cheap hand-drawn feel on standard shapes.
- Hand-drawn register pairs with a humanist type and paper-tinted background; do NOT mix it with machine-precise Chart.js axes in the same chunk — commit per chunk.
- Marginalia style callouts (small rotated notes with a connector line) work well here for the "sharp friend" voice.

## Composition rules across chunks

- Max 2 media formats per chunk; the chunk's ONE idea gets ONE primary visual.
- Alternate visual weight: heavy interactive chunk → light diagram chunk → text-forward breather with a single strong pull-quote fact. Density waves keep the scroll alive without exhausting.
- Full-bleed moments: 1–2 per explainer max (the hook and possibly the recap). Everything else within a comfortable ~720–880px column with visuals allowed to break out wider.
