Restructures the unlock screen so the form sits in a glass card with
a primary 'unlock vault' button. Logo, brand, and tagline are grouped
as a lockup. Open-vault and settings are demoted to secondary buttons.
Body gets the .surface-backdrop wrapper.
Two-tier button hierarchy. .btn-primary uses patina gold fill; .btn-secondary
is a ghost button with muted border. Existing .btn class kept for
backwards compatibility.
Replaces bright amber #d2ab43 with patina gold #a88a4a as the new base.
Keeps --accent as alias for backwards compatibility. Adds --bg-card
and --border-soft for upcoming glass card class.
Brand name uses capital R in user-facing text — extension UI strings,
CLI clap help / descriptions / error prose, markdown docs. Lowercase
preserved for the binary command, crate names, npm package, file
paths, env vars, and code identifiers.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Code-review feedback on Task 8: the conditional empty
<div style="margin-bottom:16px;"> spacer was an inline-styled magic
number and the 6-line header pattern was duplicated across all 7 typed
forms.
Now:
- .form-header class owns the bottom margin in both stylesheets.
- :has(+ .form-subtitle) selector drops the margin when a subtitle
follows, so spacing tokens stay in CSS instead of inline styles.
- renderFormHeader(titleText) shared helper collapses the 6-line
duplication to a one-liner per form. item-form.ts (type-selection
screen) is unaffected — it uses a different header structure.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
All seven type forms plus the type-selection screen now show a small
'esc to cancel' subtitle under the heading when rendered in the
fullscreen vault tab (isInTab() === true). The subtitle is suppressed
in the popup, where esc has the more general meaning of closing the
popup. .form-subtitle class is shared between popup and vault
stylesheets so future hooks can reuse it.
Dynamic dirty-state ('unsaved · esc to cancel') wiring is deferred to
Phase 3 (unsaved-changes guard).
Plan 2026-04-30 fullscreen UX phase 1 task 8.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Code-review feedback on Task 4:
- Test expanded from login-only to it.each across all 7 type forms
(14 assertions total). A future revert to <span class="req">*</span>
in any form now fails CI.
- .label .req rule removed from popup/styles.css and vault/vault.css —
zero consumers after the REQUIRED_PILL_HTML migration.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Establishes :root CSS custom properties (accent, surfaces, status, focus
ring) and applies the focus ring to inputs/buttons via :focus-visible.
Adds .req-pill class used by Task 4 to replace the bare-asterisk required
marker. Existing .label .req kept for backward compatibility during the
migration window.
Plan 2026-04-30 fullscreen UX phase 1 task 2.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Replace the placeholder Step 0 with two clickable mode-card buttons (create
new vault / attach this device). Picking a card highlights it and enables
the next button; the back button on Step 1 returns to Step 0 without losing
state. Add .mode-card CSS using the existing dark palette (#30363d, #58a6ff).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Clicking "+ new" now navigates to a type selection view instead of
showing a dropdown that gets clipped by popup bounds. The selection
view displays all item types as buttons in a scrollable list.
Co-Authored-By: Claude <noreply@anthropic.com>
Shows current + historical values for tracked fields (password/concealed).
Click to reveal, copy button per entry (plaintext stored in a module-level
Map, never embedded in the DOM). Grouped by field name if multiple tracked
fields exist. Adds historyItemId to PopupState and 'field-history' to View.
Co-Authored-By: Claude <noreply@anthropic.com>
Shows registered devices with "← you" indicator on current device.
Revoke button on other devices. Unregistered banner if current
device not in list.
Co-Authored-By: Claude <noreply@anthropic.com>
Shows trashed items sorted newest-first with restore buttons.
Empty trash button purges all items + orphan blobs. Header shows
count and days until oldest auto-purges.
Co-Authored-By: Claude <noreply@anthropic.com>
Form requires title + primary_attachment; the primary-row picker is
compact in edit mode (dashed-border when empty, filename row when
filled). Detail view promotes the primary to a gold signature block
(48×60 thumb + filename + meta + ↓ download · 🔍 preview). For image-
mime primaries, the thumb lazy-loads via decrypt + object-URL; the
preview button toggles an inline expanded view.
Supplementary attachments use the standard compact disclosure (Task 7)
when present.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Each existing type form (Login, SecureNote, Identity, Card, Key, TOTP)
renders + wires the attachments-disclosure in both edit and view modes.
Form save reads from attachmentsDraft; teardown revokes any image
object URLs. Item-list rows show a 📎 glyph for items with at least
one attachment.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Compact disclosure rendering attachment rows with an action column
(× in edit, ↓ in view). Image-mime rows lazily decrypt + show a 16×16
thumb via object URLs; teardown revokes them on disclosure close. Edit
mode adds a "+ attach file" button wired to a hidden file input that
checks vault caps client-side before sending upload_attachment to SW.
6 new tests; total ~143.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The popover (which clipped off the popup edge) becomes an inline panel
that mounts inside the form (login.ts) or settings section
(settings-vault.ts). Trigger button is ✨ with aria-expanded toggling.
Action row varies by context: fill-field has cancel+use; configure-
defaults has only the save-default link. Escape key closes the panel.
Tests adapted to new API; 3 new tests for aria-expanded, auto-generate,
and Escape behavior.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
.label drops text-transform: uppercase and tightens letter-spacing.
The `*` required marker gets wrapped in <span class="req"> so it
picks up the gold accent color (matches palette refresh).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two fixes from the T3+T4 code review:
C1 (Critical): renderSectionBlock previously rendered all fields
regardless of kind. For fields with kind url/date/month_year/totp/etc.
(from CLI-created items), the editor showed a blank value input; if
the user typed anything, the input handler cast the kind to the
wrong thing and silently overwrote the structured value with a
string — destroying data. Fix: filter editor to supported kinds
(text/password/concealed); key data-* attributes by field.id (not
by index) so handlers look up the correct field regardless of what
the render loop emitted. Unsupported-kind fields survive save
untouched. A small muted note "N fields of unsupported kind (edit
via CLI)" flags preserved entries. +2 tests.
I1 (Important): totp.ts's kind-toggle reRender read the module-
scope sectionsExpanded flag which was only updated on structural
mutations — so toggling the disclosure open without adding/removing
anything left the flag stale, and clicking Random/BIP39 collapsed
the disclosure. Fix: read data-expanded from the live DOM before
innerHTML swap.
Monospace font stack, #0d1117 background, blue accents, TOTP green,
entry list with keyboard selection, confirm overlay, wizard progress bar,
and custom 4px scrollbar.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>