diff --git a/docs/superpowers/specs/2026-08-07-navigation-components-design.md b/docs/superpowers/specs/2026-08-07-navigation-components-design.md
new file mode 100644
index 00000000..7549219f
--- /dev/null
+++ b/docs/superpowers/specs/2026-08-07-navigation-components-design.md
@@ -0,0 +1,184 @@
+# Navigation component group — design
+
+Date: 2026-08-07
+Status: approved, not yet implemented
+
+## Problem
+
+The navigation group has nine components. Five of them — Nav, MegaMenu,
+Scrollspy, Pagination, Stepper — are byte-identical scaffold stubs that differ
+only in one CSS class name. Each renders `{#each items}{label}{/each}`
+and nothing else. MegaMenu has no panel, Scrollspy never observes scroll,
+Stepper has no steps or progress, Pagination has no pages.
+
+Of the remaining four, Breadcrumb is genuinely built (323 lines, own style
+block). Navbar and Sidebar render but have no keyboard handling and keep their
+styles in `ui.css`. Tabs works but is off-pattern in three ways: it is the only
+component in the library using Tailwind utility classes rather than `wire-*` +
+a local style block, it has no `outputs` block and fires raw `CustomEvent`s via
+`dispatchEvent`, and it sets a roving `tabindex` with no `@keydown` handler at
+all — which is worse than having no keyboard support, because the roving
+tabindex makes every inactive tab unreachable by Tab while arrows do nothing.
+
+## Scope
+
+All nine components, delivered in three phases.
+
+## Decisions
+
+### Styling
+
+Every navigation component gets a local `style {}` block using `wire-*`
+classes. This matches DataTable, Toaster, Modal, Drawer, ContextMenu and
+Breadcrumb — the 22 of 108 components that carry local styles are exactly the
+recently built ones. Navbar and Sidebar styles move out of `ui.css` as part of
+this work.
+
+### Dropdowns: Nav vs MegaMenu
+
+Both get dropdowns, of deliberately different kinds.
+
+- **Nav** gets multi-level cascading submenus. It is the link bar, so nested
+ submenus are its job.
+- **MegaMenu** gets a single-level rich panel: columns of grouped links with
+ headings, descriptions and icons. This is deliberate, not a shortcut. A mega
+ menu exists to show breadth flat so everything is one click away; nesting
+ inside the panel buries content behind hover-within-hover and is close to
+ unusable by keyboard and touch.
+
+Neither reuses the existing Dropdown component: Dropdown is click-triggered and
+has no nesting support.
+
+**Depth limit.** There is no recursive-component precedent in this library, so
+multi-level means fixed depth via nested `{#each}` loops — the pattern Navbar
+(4 loops) and Sidebar (2 loops) already use. Depth is **3 levels**. Unlimited
+nesting would require proving out component self-reference, which is out of
+scope here.
+
+### Roving focus lives in the runtime
+
+Arrow-key roving focus is identical logic for Tabs, Nav, MegaMenu, Sidebar and
+Stepper. It goes in the reactive runtime as a declarative attribute rather than
+five near-identical client functions:
+
+- `data-wrn-roving="horizontal|vertical|both"` on the container
+- `[data-wrn-roving-item]` on each focusable child
+
+The runtime owns arrow keys, Home/End, wrap-around, skip-disabled, and
+maintenance of the roving `tabindex`. Components declare intent only.
+
+This follows the modal-dialog focus work already in the runtime, and for the
+same reason: a client function cannot hold focus state across callbacks,
+because state written after the function returns is dropped.
+
+### Scrollspy needs runtime support too
+
+`data-wrn-scrollspy` backed by `IntersectionObserver`. It cannot be a client
+function — the observer callback fires long after the function returns, and
+that state write would be lost.
+
+### Runtime budget
+
+Roving focus is roughly 3–4k, scrollspy roughly 1.5k. The runtime is at 167k
+against the 175k ceiling raised on 2026-08-07. This fits, but leaves little
+room. The group after this one forces the decision about splitting the runtime
+into loadable chunks so pages pay only for behaviour they use.
+
+### Tabs URL mode
+
+`mode="client" | "url"`. URL mode uses a query parameter (`?tab=value`) driven
+by `history.pushState`, so content swaps with no page load and the back button
+works.
+
+Query parameter rather than hash: it is shareable, survives reload, and does
+not collide with in-page anchors or with Scrollspy, which wants the hash.
+
+Tabs also gets a panel transition on change.
+
+### Sidebar composes Drawer
+
+Sidebar does not reimplement off-canvas behaviour. Desktop renders a static
+rail; mobile renders inside Drawer. This inherits Drawer's focus trap and
+scroll lock rather than duplicating them.
+
+### Cross-cutting requirements
+
+- Icons on every menu item, tab, and step
+- Dropdown arrows that animate on open
+- Responsive behaviour per component: Nav collapses to a toggle, MegaMenu
+ stacks its panel, Tabs becomes a scrollable strip, Stepper goes vertical,
+ Pagination goes compact
+- Full ARIA Authoring Practices patterns for each role, including correct
+ `aria-current` / `aria-selected` / `aria-expanded`
+
+## Components
+
+| Component | Work |
+| ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| Nav | Build. Flat or multi-level (3 deep), horizontal/vertical, `items[{label,href,value,icon,badge,disabled,items}]`, `aria-current="page"`, roving focus, animated arrows, collapses on mobile. `outputs: select` |
+| Tabs | Rewrite off Tailwind onto `wire-*` + local styles. Real `outputs {change, select}` replacing raw `dispatchEvent`. Roving + Home/End. `mode="client"\|"url"`. Panel transition. Fix the `` that renders regardless of active tab |
+| Pagination | Build standalone. `page`/`pageSize`/`total`, compact + numbered styles, windowed page numbers. `outputs: change, previous, next` |
+| Stepper | Build. ``/`- `, status derived from `active` index, horizontal/vertical, optionally clickable, `aria-current="step"`. Indexed named slots (`data-slot="step-0"`, `step-1`, …) for custom per-step content, falling back to built-in rendering |
+| MegaMenu | Build. Trigger plus a single-level panel of link columns. Panel marked `data-wrn-anchored` so the existing clamp handles viewport containment. Hover and focus open, Escape closes, click-outside closes |
+| Scrollspy | Build. Observes section ids, moves `aria-current` to the matching link |
+| Navbar | Audit. Styles move to a local block, roving focus on the link group, keyboard for the mobile toggle |
+| Sidebar | Audit and extend. Local styles, composes Drawer for mobile, single items / labelled groups / multi-level (3 deep), vertical roving |
+| Breadcrumb | Audit only — already the strongest of the nine |
+
+Component count stays at 108; all nine files already exist.
+
+## Data flow
+
+Props in, outputs out, no global state. Every component takes its data as props
+and reports interaction through declared `outputs`.
+
+## Error handling
+
+`items` arrives as an HTML attribute and is frequently a JSON string, so:
+
+- A non-array `items` renders empty rather than throwing
+- Out-of-range `active` / `page` clamps to bounds
+
+## Testing
+
+- Per-component entries in `packages/ui/test/ui.test.ts` covering names,
+ declared outputs and props
+- Showcase profiles for each so every component gets live demos
+- Regenerate component reference, catalog, showcase, and the UI visual contract
+- Each phase ends with `bun run check:production` green
+
+## Phases
+
+Each phase ends green, committed and pushed.
+
+1. **Runtime and primitives** — roving-focus runtime, Nav, Pagination, Stepper
+2. **Composed** — Tabs (rewrite, URL sync, animation), Sidebar (on Drawer),
+ MegaMenu
+3. **Audit and polish** — Navbar, Breadcrumb, Scrollspy, responsive pass,
+ showcase generation
+
+## Risks
+
+- **Scrollspy and MegaMenu** are the only two needing new runtime behaviour.
+ MegaMenu leans on the anchored clamp, which could not be verified
+ interactively on 2026-08-07 because the browser pane was degraded
+ (screenshots timing out, `scrollIntoView` inert). Verify the pane works
+ before starting phase 2.
+- **Tabs is a breaking change.** Replacing raw `CustomEvent`s with declared
+ outputs changes its public contract; anything listening for the old events
+ breaks. 0.8.5 shipped on 2026-08-07, so this needs a migration entry in
+ `packages/cli/src/update.ts`.
+
+## Codebase constraints to respect
+
+Hazards this codebase has already hit:
+
+- No apostrophes in `.wrn` comments — the brace scanner breaks on them
+- `/* */` only inside style blocks; `//` is not a CSS comment and silently eats
+ the following rule
+- No deferred state writes in client functions; state written after the
+ function returns is dropped
+- Never call a peer function after an application callback — the wrapper
+ flushes the entry-time snapshot
+- No boolean attributes bound to loop variables
+- Package components need explicit imports