M9 section S1, commit 4 (frontend). Introduce the shared UI primitives the 7 data views + 5 editor hosts were hand-rolling: - components/AsyncState.vue: the loading / error(+Retry) wrapper (emits `retry`). - components/EmptyState.vue: the centered title/subtitle "nothing here" block. - composables/useNoteEditor.ts: the editing/open/close/navigate glue every editor host duplicated, as one controller (onClose hook + local-list resolution for [[wiki-link]] navigation). BoardView adopts all three: its three hand-rolled loading/error/empty blocks collapse into <AsyncState> + <EmptyState>, and its editor glue into useNoteEditor. The other views + editor hosts adopt these in the Organize (S3) and Auth (S5) sections. Behavior-preserving. Frontend has no local typecheck (rule 10); CI's vue-tsc is the gate. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FRgehjoz7Yv8LkUfADxACm