| Area | Requirement | Current Notes |
|---|---|---|
| Performance | Keystroke latency ≤50 ms, first contentful render <2 s | Achieved on M1 + mid-tier laptops using Vite dev server; keep an eye on highlight.js bundle size. |
| Accessibility | Full keyboard navigation, visible focus states, colour contrast compliant | Menu toggles respect Escape/outside click, but additional focus outlines are on the backlog. |
| Reliability | Works offline after first load; sessions persist locally | IndexedDB stores summaries, packs are bundled with the app. |
| Security & Privacy | No telemetry, no network calls without user opt-in | Current build makes zero outbound requests. |
| Responsiveness | Maintain ≥55 fps during typing animations | Framer Motion transitions measured to stay within budget; continue profiling as we add features. |
- Bundle target: ≤1.5 MB gzipped for the web app (excluding optional WASM package). Highlight.js languages are tree-shaken; add new ones judiciously.
- Engine enforcement: Surface clear errors when the Rust WASM bundle is missing so metrics always come from the canonical engine.
- Animation budget: Keep transition durations ≤150 ms to preserve responsiveness.
- IndexedDB writes: Batch writes per completion to avoid jank during active typing.
| Milestone | Status | Notes |
|---|---|---|
| A1 — Typing core | ✅ | Typing loop, animated feedback, metrics, toast notifications in place. |
| A2 — Pack loader | ✅ | Local packs registry + language/prompt menus. Difficulty filtering deferred until packs expose metadata. |
| A3 — Persistence | ✅ | IndexedDB summaries with attempt snapshots and export helpers. |
| A4 — UI polish | ✅ | Background grid, radial blurs, lowercase header, menu animations. |
| A5 — Analytics surface | ⏳ | Dashboard/heatmap/export UI still pending; raw data exists for future views. |