# Wave D1 — and why E1/E9 were not it ## PHASE 0 — the audit's actual wave order The order proposed E1 + E9 as Wave-1 primitives and instructed me to follow the audit if it disagreed. **It disagrees.** | item | the audit's placement | |---|---| | **E9 calibration curve** | **WAVE D3 — gated on MODEL work**: *"resolve n≥20 vs N30, accrue buckets"* | | **E1 movement strip** | **WAVE D6 — large surface builds**, alongside crown / disagreement axis / SPLIT | **Neither is Wave 1.** And E9's gate is live right now: calibration is **withdrawn** (`CALIBRATION_DEPLOYED = []`) at **0 eligible dates**, so a calibration curve today could only render its empty state. Building it now would produce a component whose entire purpose is unavailable. **WAVE D1, per the audit:** glyph library · card token + `vy-glitch` naming · `nudge()`/boot-stagger/row-hover/IntersectionObserver · boundary-channel blue · team-gradient chips + READ-FAB. ## PHASE 1 — three of the five Wave D1 items were already done Checked rather than assumed, and the audit (2026-07-31) has aged: | item | audit said | measured now | |---|---|---| | **D1 glyph library** | PARTIAL — 38 of 83 wired (46%) | **COMPLETE for everything wireable.** 83 designed glyphs, 41 registry archetypes, **39 map — and all 39 are wired, with colours matching the registry exactly (0 disagreements).** | | **A1 card token `#0E0E14`** | BUILT-BUT-DRIFTED — "in only 1 file" | **BUILT-TO-SPEC.** It is the `--bg-1` token in `globals.css`, consumed by **32 files** via `var(--bg-1)`. The audit counted literal hex occurrences, which is what a *correctly tokenised* value looks like. | | **B1 boundary channel** | PARTIAL — hex in 2 files | **BUILT.** `--priced-out: #8fb2de` + `--priced-out-dim` are tokens with a documented colour law in `globals.css`, consumed by 4 files. | **The 44 unwired glyphs are not a wiring gap.** They have no backend archetype — wiring them would mean **inventing 44 archetypes to consume artwork**, which is the fabrication this programme refuses. That is the 41-vs-74 scope question, and it is Kev's call, not a build task. Separately, **2 registry archetypes have no designed glyph** (`DUAL THREAT`, `PAINT BOSS`) — a design gap, not a code one. ## PHASE 2 — what was genuinely absent, and is now built `web/src/lib/motion.js` — the four primitives, all previously 0 files: | primitive | the rule it enforces | |---|---| | **E17 `nudge()`** | ≤180ms. Confirms an action *registered* without claiming it finished — a long pulse reads as latency, the opposite of a perceived-speed primitive. | | **E18 `bootStagger()`** | **capped at 240ms.** Uncapped, row 40 waits 1.1s and the stagger *becomes* the latency it exists to disguise. | | **E27 `rowHover()`** | returns handlers, not CSS — so a tap on touch cannot stick a hover state that never clears. | | **E28 `revealOnIntersect()`** | returns an unobserve fn in every path, and **reveals IMMEDIATELY** without IntersectionObserver or under reduced motion. Content is never hidden behind a capability check. | **Reduced motion is honoured, not softened** — every primitive skips outright, and server-side assumes reduced. 10 tests, the sharpest being that `bootStagger` under reduced motion returns `opacity: 1` and not merely `delay: 0`: if the CSS animation supplies the opacity, skipping the animation without forcing it leaves the row invisible forever. ## PHASE 3 — guard registration and Wave-2 readiness The reachability guard now carries a **PRIMITIVES** section: a module built to be embedded must declare its exports *and name its intended consumers*. A primitive imported by nothing is the same built-but-unread class as an unmounted component. 24 checks green. ### Wave-2 readiness **Ungated — design complete, no blocker:** - **F9/F10/F11 offseason hub** (Wave D6) — the largest, fully spec'd - **F5 article media** (Wave D6) — hero + figure system fully spec'd - **E10/E12 The Report email + `/report` archive** — design exists - **E1 movement strip** (Wave D6) — spec'd, absent, now has its motion primitives **Gated, and by what:** | item | gate | |---|---| | E9 calibration curve | **model** — calibration withdrawn, 0 eligible dates | | E15 Price Triplet MODEL leg | **model** — EV layer | | E16 share cards + F8 crops | **resolution tail** *and* the card-system reconciliation | | E2 BookChip tiles / E6 push-to-book | **licensing / affiliate approval** | | E13 Scanner S6 | another build order | **The card-system reconciliation** (content-engine 1080×1350 vs E16's five masters) gates E16/F8 and should be settled with the social chat, since off-site posts and on-site share cards are one system. Isolated throughout: read-only, no serving or model change, **accrual clock unchanged at 0 eligible dates**.