diff --git a/.gitignore b/.gitignore
index b523c6d7..d9c8ee36 100644
--- a/.gitignore
+++ b/.gitignore
@@ -15,3 +15,4 @@ frontend/node_modules/
# permission-neutral so devs can `claude` interactively here without
# inheriting production-agent restrictions.
.claude/
+.superpowers/
diff --git a/docs/superpowers/specs/2026-07-15-inventory-search-redesign-design.md b/docs/superpowers/specs/2026-07-15-inventory-search-redesign-design.md
new file mode 100644
index 00000000..c5ef6caa
--- /dev/null
+++ b/docs/superpowers/specs/2026-07-15-inventory-search-redesign-design.md
@@ -0,0 +1,115 @@
+# Inventory Search redesign — React full-page view
+
+**Date:** 2026-07-15
+**Status:** Approved (layout + behaviors validated interactively in visual-companion mockup)
+**Mockup:** `2026-07-15-inventory-search-redesign-mockup.html` (same directory — the approved clickable reference)
+
+## Problem
+
+The inventory search UI (`static/inventory.html` + `inventory.js`, ~2100 lines of
+2010s-era dense gray vanilla HTML) is functionally complete (all filters work
+against the Go `inventory-go` service, including the July 2026 spell filters)
+but visually dated and inconsistent with the React dashboard. Full redesign
+requested.
+
+## Decisions (user-validated)
+
+1. **Platform:** new full-page view in the existing React app (`frontend/`),
+ reached via `/?view=inventory` — same routing pattern as `?view=dashboard`
+ in `App.tsx`.
+2. **Layout:** facet sidebar (direction A of three mocked options) + active-
+ filter chips row borrowed from direction B.
+3. **Search trigger:** instant auto-search, debounced ~400 ms, no Search
+ button; in-flight requests aborted via `AbortController`.
+4. **Item details:** right-side detail panel opened by row click; ↑/↓ moves
+ selection, Esc closes.
+5. **Set analysis:** dropped entirely. The new page fully replaces
+ `inventory.html`/`inventory.js` — both deleted at cutover; the "Analyze
+ Sets" feature ceases to exist.
+6. **Shareable URLs:** filter state serialized to the query string.
+
+## Layout (per approved mockup)
+
+- **Top bar:** title, name/material search box (`text` param), Reset (clears
+ all filters), column picker (⚙), result count + query time.
+- **Chips row:** one removable chip per active filter; legendary-cantrip chips
+ styled gold (#fc6 on #2a2418).
+- **Facet sidebar** (~210 px, collapsible groups with active-count badges):
+ - **Characters** — searchable checkbox list, All/None/Online links, green
+ online dots (from the `/live` data the app already polls).
+ - **Item type** — radios: All / Armor / Jewelry / Weapons (+subtype) /
+ Clothing (maps to `armor_only`/`jewelry_only`/`weapon_only`+`weapon_type`/
+ `clothing_only`; shirts/pants reachable as clothing subtypes).
+ - **Slots** — jewelry slots (Ring/Bracelet/Neck/Trinket/Cloak) up front,
+ armor slots behind a "show armor slots" expander (`slot_names` CSV).
+ - **Cantrips** — find-as-you-type filter over the legendary cantrip list,
+ grouped (Attributes / Skills / Defense / Banes / Other); checked items pin
+ to a "Selected" section on top; gold styling; plus an "any-tier spell
+ search" text input (`spell_contains`). Checkbox values = the same display
+ names the old page sent (`legendary_cantrips` CSV, AND semantics).
+ - **Ratings** (collapsed) — min inputs for the 4 common ratings, "all 20
+ ratings" expander for the rest (`min_*` params).
+ - **Equipment sets** (collapsed) — searchable set list (`item_set`/`item_sets`).
+ - **Item state** (collapsed) — equipped-only, bonded, attuned, rare
+ (`equipment_status`, `bonded`, `attuned`, `is_rare`).
+ - **Reqs & value** (collapsed) — wield level ≤, value ≥, workmanship ≥,
+ burden ≤ (`max_level`, `min_value`, `min_workmanship`, `max_burden`).
+- **Results table:** server-side sort via `sort_by`/`sort_dir` (click headers);
+ sticky header; equipped marker (green ⚔); Spells column with legendary names
+ gold; pagination footer (200/page default, `page`/`limit`). Column set
+ togglable via the ⚙ picker, persisted to `localStorage`.
+- **Detail panel** (~250 px): item name, slot, equipped state, character,
+ value/burden/wield/workmanship/mana, full ordered spell list (legendary
+ gold). Keyboard: ↑/↓/Esc.
+
+## Implementation shape
+
+- **No backend changes.** The existing `GET /api/inv/search/items` supports
+ every filter above (validated; the spell filters shipped 2026-07-14).
+- New directory `frontend/src/components/inventory/`:
+ - `InventorySearchPage.tsx` — page layout, keyboard handling.
+ - `FilterSidebar.tsx` + one small component per filter group.
+ - `ActiveChips.tsx`, `ResultsTable.tsx`, `DetailPanel.tsx`.
+ - `useInventorySearch.ts` — single-reducer filter state, debounce,
+ AbortController fetch, URL (de)serialization.
+- Filter state ↔ URL: serialize non-default filters into query params on
+ change (replaceState), parse on mount — bookmarkable searches.
+- Styling: `frontend/src/styles/inventory.css`, `.inv-*` class prefix,
+ dashboard dark tokens (#111 bg, #1a1a1a panels, #333 borders, #88f accent,
+ #fc6 legendary gold, Segoe UI) — mirrors `map-layout.css` conventions.
+- **No new npm dependencies.**
+- Cantrip list + grouping: lift the value strings from the old
+ `inventory.html` checkbox grid (they are the strings the backend matches);
+ store as a typed constant module.
+- Character list: reuse the app's existing live-players data source for names
+ + online status; fall back to `/api/inv/characters/list` for characters that
+ are offline/never online.
+
+## Cutover
+
+Same commit series: add the new view → repoint the dashboard tool-link that
+currently opens `/inventory.html` to `/?view=inventory` → delete
+`static/inventory.html` and `static/inventory.js`. `/inventory.html` then 404s
+to the SPA fallback; acceptable (single-user tool, no external links).
+
+## Testing & verification
+
+The frontend has no test framework (build = `tsc -b && vite build`).
+Verification per task: TypeScript build green + live checks in the Vite dev
+server against the production API, then post-deploy spot checks of the same
+scenarios used for the spell-filter validation (Invuln+Summon → 2 items;
+Ring+Invuln → 56; filterless jewelry → ~4.8k). Adding a test harness is out
+of scope.
+
+## Deploy
+
+`bash deploy-frontend.sh` (builds + copies into `static/`), commit `static/`
++ `frontend/` + deletions, push; server picks it up via bind mount, no
+restart.
+
+## Out of scope
+
+- Set analysis (dropped per decision 5).
+- Suitbuilder page (untouched).
+- React-window (`InventoryWindow.tsx`) per-character inventory — unrelated.
+- Mobile layout (desktop tool); no test framework introduction.
diff --git a/docs/superpowers/specs/2026-07-15-inventory-search-redesign-mockup.html b/docs/superpowers/specs/2026-07-15-inventory-search-redesign-mockup.html
new file mode 100644
index 00000000..f019183c
--- /dev/null
+++ b/docs/superpowers/specs/2026-07-15-inventory-search-redesign-mockup.html
@@ -0,0 +1,294 @@
+
+
+
+
+Inventory Search — mockup
+
+
+
+
+
+ ⚔ Inventory Search
+
+
+
+ 56 items · 24 ms
+
+
+
+ ACTIVE
+ Jewelry ×
+ Slot: Ring ×
+ Legendary Invulnerability ×
+ Legendary Summoning ×
+
+
+
+
+
+
+
+
+
+ | Item | Character | Slot | Value | Wield | Spells / Cantrips |
+
+
+
+
+
+
+
+
+
+
+
+
+