diff --git a/docs/superpowers/specs/2026-04-30-relicario-fullscreen-ux-redesign-design.md b/docs/superpowers/specs/2026-04-30-relicario-fullscreen-ux-redesign-design.md
new file mode 100644
index 0000000..0dd9756
--- /dev/null
+++ b/docs/superpowers/specs/2026-04-30-relicario-fullscreen-ux-redesign-design.md
@@ -0,0 +1,455 @@
+# Relicario fullscreen UX redesign
+
+**Date:** 2026-04-30
+**Status:** Spec, awaiting review
+**Surface:** Browser extension fullscreen vault UI (`extension/src/vault/`)
+
+## Goals
+
+- Make the fullscreen vault tab (`vault.html`) feel like a first-class app, not a popup form stretched across a wide monitor.
+- Add structural affordances (keyboard nav, command palette, multi-select) that the popup cannot fit and that match the project's monospace/terminal aesthetic.
+- Improve form-level affordances (smart inputs) in a way the popup can also adopt where space allows.
+- Establish a consistent visual language — typography, glyphs, focus states, button conventions — shared between popup and fullscreen.
+
+## Non-goals
+
+- Sidebar/empty-state rework (deliberately out of scope; current sidebar layout stays as-is).
+- Mobile responsive design (fullscreen is desktop-only; popup handles narrow widths).
+- New item types, schema changes, or sync-protocol changes.
+- Theme system / light mode (single dark theme stays).
+
+## Scope summary
+
+| Theme | Where it applies |
+|---|---|
+| **A.** Two-column form layout, sticky save bar | Fullscreen only |
+| **B.** Visual polish: glyphs, focus rings, required pill, "esc to cancel" subtitle | Both (popup adopts what fits) |
+| **C.** Smart inputs (8 affordances) | Both — same code path in `popup/components/types/login.ts` |
+| **E.** Keyboard nav, ⌘K palette, three-pane shell, multi-select, drag-drop attach, unsaved-changes guard, recent items | Fullscreen only |
+| **Glyph button convention** | Both (icons-only, native tooltips) |
+
+---
+
+## Architecture
+
+### Component map (after redesign)
+
+```
+extension/src/vault/
+├── vault.ts # entry point — restructured for 3-pane shell
+├── vault.html # split panes: nav | list | detail
+├── vault.css # restyled — see "visual language" below
+├── shell/
+│ ├── three-pane.ts # NEW — pane sizing, divider drag
+│ ├── keymap.ts # NEW — global keyboard handler
+│ ├── command-palette.ts # NEW — ⌘K overlay
+│ └── unsaved-guard.ts # NEW — beforeunload + in-app intercept
+├── selection.ts # NEW — multi-select state
+└── components/ # existing — backup-panel, import-panel
+
+extension/src/popup/components/types/
+├── login.ts # restructured form, 8 smart-input affordances
+├── secure-note.ts # adopts shared visual language
+├── identity.ts # ditto (later phase)
+├── card.ts # ditto (later phase)
+├── key.ts # ditto (later phase)
+├── totp.ts # ditto (later phase)
+└── document.ts # ditto (later phase)
+
+extension/src/shared/
+├── glyphs.ts # NEW — icon glyph constants & button helper
+├── shortcuts.ts # NEW — keymap registry consumed by vault
+└── form-affordances/ # NEW — reusable smart-input mixins
+ ├── url-affordances.ts # fill-from-tab, hostname chip
+ ├── group-autocomplete.ts # datalist
+ ├── password-tools.ts # reveal toggle, strength bar
+ └── totp-tools.ts # live preview, QR decode
+```
+
+### Data flow
+
+No changes to the message-bus contract. New SW handlers needed:
+
+- `get_active_tab_url` — popup-only message; SW reads `chrome.tabs.query({active:true, lastFocusedWindow:true})`, returns `{ url, title }`. Used by URL fill-from-tab affordance.
+- `list_groups` — popup-only; reads manifest, returns deduplicated set of all group strings (for datalist autocomplete).
+- `list_recently_viewed` — popup-only; returns last N item IDs from a per-device LRU stored in `chrome.storage.local`.
+
+Existing handlers (`rate_passphrase`, `get_totp`, `add_item`, etc.) are reused as-is.
+
+### Dependencies
+
+- **`jsqr`** — `~50KB` minified. QR-image → otpauth-URI decoder for TOTP-from-QR. Loaded lazily (only when the user clicks the `◫` button).
+- No other new runtime deps. `zxcvbn` already integrated via `rate_passphrase`.
+
+---
+
+## Visual language
+
+The single source of truth for shared style is `extension/src/shared/glyphs.ts` (constants) and `vault.css` / `popup.css` (CSS tokens).
+
+### Typography
+
+- Body: `ui-monospace, "JetBrains Mono", "SF Mono", monospace` (already present).
+- Numerals: `font-variant-numeric: tabular-nums` on TOTP code, countdowns, item counts.
+- Labels: lowercase, weight 400, color `var(--text-muted)`.
+- Section headers (form sub-sections): uppercase, letter-spacing 1px, weight 500, with a 1px bottom border.
+
+### Color tokens (additive — no existing colors removed)
+
+```css
+:root {
+ --accent: #d49b3a; /* amber, brand */
+ --accent-soft: rgba(212, 155, 58, 0.18);
+ --focus-ring: 0 0 0 2px rgba(212, 155, 58, 0.35);
+ --bg-input: #0e1620;
+ --bg-pane: #1a2230;
+ --border-subtle: #2a3848;
+ --text: #cdd6e0;
+ --text-muted: #8b97a8;
+ --text-dim: #6b7888;
+ --danger: #c75a4f;
+ --success: #6cb37a;
+}
+```
+
+### Glyph convention
+
+All action glyphs are unicode (no emoji), monochrome, with `title=` tooltips. Defined as constants in `shared/glyphs.ts`:
+
+| Glyph | Constant | Use |
+|---|---|---|
+| `⊙` / `⊘` | `GLYPH_REVEAL` / `GLYPH_HIDE` | Password reveal toggle |
+| `↻` | `GLYPH_GENERATE` | Password / passphrase generate |
+| `⤓` | `GLYPH_FILL_FROM_TAB` | Fill URL from active tab |
+| `◫` | `GLYPH_QR` | Paste/upload QR image |
+| `≡` | `GLYPH_MONO` | Toggle notes monospace |
+| `▦` | `GLYPH_TRASH` | Trash nav (replaces 🗑) |
+| `⌬` | `GLYPH_DEVICES` | Devices nav (replaces 📺) |
+| `⚙` | `GLYPH_SETTINGS` | Settings nav (kept) |
+| `⏻` | `GLYPH_LOCK` | Lock nav (replaces 🔒) |
+| `⌘ K` | (literal) | Command palette label |
+
+Buttons use a shared `.glyph-btn` class: 28px min-width, monospace, neutral background, hover lift.
+
+### Focus state
+
+Single token `--focus-ring` applied to all focusable form elements via `:focus-visible`. Browser default outline is suppressed. Combined with a 1px amber border on the focused input.
+
+### Required-field pill
+
+Replaces the trailing `*` marker. A `required` after the label text:
+
+```css
+.req-pill {
+ display: inline-block; font-size: 9px; padding: 1px 5px;
+ background: var(--accent-soft); color: var(--accent);
+ border-radius: 2px; margin-left: 6px; vertical-align: middle;
+ text-transform: uppercase; letter-spacing: 0.5px;
+}
+```
+
+---
+
+## A. Form layout (fullscreen only)
+
+The fullscreen `vault.html` form pane gets a two-column layout for login items. Other types stay single-column for now.
+
+### Layout rules
+
+```
+┌────────────────────────────────────────────────────────────┐
+│ ◀ new login ⌘+S to save │
+│ unsaved · esc to cancel │
+├──────────────────────────┬─────────────────────────────────┤
+│ IDENTITY │ CREDENTIALS │
+│ ┌──────────────────────┐ │ ┌─────────────────────────────┐ │
+│ │ title [required] │ │ │ username │ │
+│ │ url + ⤓ │ │ │ password ⊙ ↻ │ │
+│ │ group (autocomplete) │ │ │ strength: ████░ │ │
+│ └──────────────────────┘ │ │ totp secret ◫ │ │
+│ │ │ live: 492 837 · 23s │ │
+│ │ └─────────────────────────────┘ │
+├──────────────────────────┴─────────────────────────────────┤
+│ NOTES │
+│ ┌────────────────────────────────────────────────────────┐ │
+│ │ ... │ │
+│ └────────────────────────────────────────────────────────┘ │
+│ │
+│ ▾ custom sections & fields ▸ attachments │
+├────────────────────────────────────────────────────────────┤
+│ STICKY SAVE BAR [cancel] [save] │
+└────────────────────────────────────────────────────────────┘
+```
+
+- Pane content max-width: `960px`, centered horizontally in the pane.
+- Two columns: equal width, 24px gap. Stack to single column under 720px viewport (degrades gracefully for narrow windows).
+- Notes / custom sections / attachments are full-width below the columns.
+- **Sticky save bar:** position `sticky` at the bottom of the form pane, with a fade gradient above so content scrolls under it. Always reachable, even on long forms.
+
+### Header treatment
+
+- Heading "new login" / "edit login" left-aligned.
+- Subtitle below: "unsaved · esc to cancel" (when dirty) or "no changes" (when pristine).
+- Right side: keyboard hint "⌘+S to save" (visual only — not a button).
+- The popout-to-tab `⤴` button is **removed** from the fullscreen form (it's a no-op in this context). It stays in the popup form.
+
+### Fields per item type (column assignment)
+
+Only `login` is two-column. Other types (`secure_note`, `identity`, `card`, `key`, `totp`, `document`) remain single-column with the polish/visual-language updates applied.
+
+---
+
+## B. Visual polish (both surfaces, popup adopts what fits)
+
+Six tweaks, applied via `vault.css` / `popup.css`:
+
+1. **Popout button:** removed from fullscreen forms. Stays in popup forms.
+2. **Sidebar glyphs:** emoji → unicode constants from `shared/glyphs.ts`.
+3. **Required pill:** `required` replaces trailing `*`.
+4. **Focus ring:** `--focus-ring` token on `:focus-visible`.
+5. **Form header subtitle:** "unsaved · esc to cancel" / "no changes" status line.
+6. **Rhythm:** input padding raised from 5px → 6px, line-height 1.4 → 1.5, label margin tweaks for breathing room.
+
+The popup adopts (3), (4), (5 — minus "esc to cancel" since popup escape closes the popup). Popup keeps (2) sidebar glyphs. Layout (sticky bar / two-column) does not apply to popup.
+
+---
+
+## C. Smart inputs (both surfaces)
+
+Each affordance lives in `shared/form-affordances/` so the popup and fullscreen forms call the same module.
+
+### C1. Fill URL from current tab
+
+- New SW message: `get_active_tab_url` → `{ url: string, title: string } | null`. Uses `chrome.tabs.query({active:true, lastFocusedWindow:true})`, filters out `chrome://` / extension URLs.
+- Glyph button `⤓` next to the URL input. Click → fetch → set URL field; if title field is empty, set title too.
+- No-op (button disabled) if no usable active tab (e.g., user opened vault.html and no other tab).
+
+### C2. Hostname chip next to URL
+
+- Live: parse the URL with `URL` constructor on each input event (debounced 200ms).
+- If it parses, show a chip with the first letter of the hostname on a colored background + the bare hostname underneath the input.
+- No network fetch. No favicon download. Pure visual confirmation.
+
+### C3. Group autocomplete (datalist)
+
+- New SW message: `list_groups` → `{ groups: string[] }`. Reads `state.manifest.items`, collects unique non-empty `group` values, sorts.
+- Form's group input gets `