Decision-based tabs, always-visible counts, inline per-item editing, plain-language can't-swap.
| Component | Spec |
|---|---|
| Summary / tab bar | 3 segments. Replace & Don't-replace are interactive tabs; Can't-swap is read-only. Each shows live count (num, 18px/800) + label (11px). Active: 2px bottom border #111; number tints to the category color. |
| Find field | Full-width input, border-radius 10px, leading search icon, placeholder "Find an item". Filters rows by name (case-insensitive, substring) across all tabs; clears back to the active tab when empty. |
| Item row | Thumb 40×40 (radius 10) · name 14/600 · size 12/sub. Trailing control: seg2 Replace/Keep toggle (min tap target 32px height, 44px row) OR lock chip for can't-swap. |
| Toast | Appears on toggle for 3s. "Moved to {tab} · Undo". Undo reverts state + count. Auto-dismiss. |
| Trigger | Result |
|---|---|
| Tap segment (Replace / Keep) | Filter list to that category; segment → active. |
| Tap segment (Can't swap) | Show the 2 read-only locked rows + an explanatory note. No toggles. |
| Toggle Replace ⇄ Keep | Update row state, recount both segments live, show Moved/Undo toast. Item leaves the current tab. |
| Type in Find | Show matching rows regardless of tab; segments dim while searching. |
| Empty tab | Empty state: "Nothing here yet." |
aria-live="polite" so screen readers hear the total change on toggle.role="tab" / list is role="tabpanel"; Find is a labeled search input.Counts are derived, never hardcoded. Can't-swap set comes from the catalog's non-substitutable flag (alcohol, medication, etc.) — copy pulled from a single source so legal/CS can edit it in one place.