Files
relicario/docs/superpowers/specs/2026-05-02-phase-2b-form-layout-design.md
adlee-was-taken d6d07a19c1 docs(spec): expand Phase 2B to polish foundation + form layout
Bundles patina palette shift, logo update (translucent gradient gem),
glass-card vocabulary across login/setup/fullscreen, and the original
two-column form layout. Updates relicario-logo.svg and -16.svg to the
patina palette.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-02 13:19:54 -04:00

15 KiB

Phase 2B: Polish Foundation + Form Layout

Date: 2026-05-02 Status: Spec, awaiting review Surface: Browser extension — popup, fullscreen vault, setup wizard Parent spec: docs/superpowers/specs/2026-04-30-relicario-fullscreen-ux-redesign-design.md

Goal

Bring the extension up to a "professional, contained" feel — like opening 1Password or another polished password manager — without losing the terminal-monospace soul. Three surfaces (login popup, setup wizard, fullscreen vault) all get the same polish vocabulary applied. Phase 2B also lands the two-column login form layout from the parent spec.

What changed from the original Phase 2B scope

The original Phase 2B was scoped to form layout only. After visual review, we expanded scope to include:

  • A patina palette shift — gold accent dialed from bright #d2ab43 toward weathered #a88a4a/#cdb47a/#5a3f12. Red theca dialed from saturated #9a1a1a toward brick #7d2622.
  • Logo update — same composition, patina palette, translucent gradient gem.
  • Polish vocabulary — backdrop with subtle radial glow + 18px grid texture, glass cards (translucent panels with backdrop-blur), refined typography lockup, primary/secondary button hierarchy.
  • Arrow glyph (U+25B8) for "next" buttons, matching the / disclosure glyphs already in use.

These items now ship together so the form layout lands inside an already-polished surface, rather than as a layout change inside flat CSS.

Non-goals

  • Three-pane shell, keyboard nav, command palette — deferred to Phase 3.
  • New affordances — Phase 2A already shipped the 8 smart inputs.
  • Light theme — single dark theme stays.
  • Mobile/narrow layouts under 720px — popup handles narrow.
  • Animated transitions / motion — focus state is the only transition.
  • Item types other than login getting a two-column treatment.

Visual language

The polish vocabulary lives in extension/src/popup/styles.css and extension/src/vault/vault.css. Both files share token definitions and class names where possible.

Palette (patina)

:root {
  /* Patina gold — replaces the bright amber */
  --gold-base:    #a88a4a;          /* base, less yellow / more bronze */
  --gold-mid:     #cdb47a;          /* duller mid-highlight */
  --gold-shadow:  #5a3f12;          /* deeper bronze shadow */
  --gold-text:    #c9a868;          /* legible on dark, brand text */
  --gold-soft:    rgba(184,149,86,0.14);   /* hover/active fill */
  --gold-ring:    rgba(184,149,86,0.18);   /* focus ring */
  --gold-stroke:  #b89556;          /* default border on emphasized elements */

  /* Surface — slightly deeper than current bg */
  --bg-base:      #0a0e14;          /* page (was #0d1117) */
  --bg-pane:      #11161e;          /* slightly elevated surface */
  --bg-card:      rgba(22, 27, 34, 0.55);  /* glass card fill */
  --bg-input:     #0a0e14;          /* matches base for sunken feel */

  /* Borders */
  --border-soft:  rgba(255,255,255,0.05);   /* card edges */
  --border-mid:   #262d36;          /* input borders */
  --border-warm:  #2a3140;          /* slightly warmer for vault.css */

  /* Text */
  --text:         #c9d1d9;
  --text-muted:   #8b949e;
  --text-dim:     #6b7888;
}

The bright accent token --accent: #d2ab43 is renamed to --gold-base: #a88a4a. Aliases keep existing component code working during the migration (--accent: var(--gold-base)).

Backdrop

A reusable backdrop applied to popup body, setup wizard body, and the vault shell:

.surface-backdrop {
  position: relative;
  background:
    radial-gradient(ellipse 700px 240px at 50% -40px, rgba(184,149,86,0.05), transparent 65%),
    linear-gradient(180deg, #11161e 0%, #0a0e14 100%);
}
.surface-backdrop::before {
  content: '';
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(rgba(255,255,255,0.012) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,0.012) 1px, transparent 1px);
  background-size: 18px 18px;
  pointer-events: none;
}
.surface-backdrop > * { position: relative; z-index: 1; }

The radial top-glow opacity is intentionally low (0.05) so it doesn't wash out on cheaper monitors. The grid texture is barely visible (0.012 white) — adds a sense of "place" without becoming busy.

Glass card

Used for the unlock card, setup step card, mode-picker cards, and form section cards (Identity / Credentials):

.glass {
  background: rgba(22, 27, 34, 0.55);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border: 1px solid rgba(255,255,255,0.05);
  border-radius: 10px;
  box-shadow:
    0 1px 0 rgba(255,255,255,0.03) inset,
    0 6px 18px rgba(0,0,0,0.35);
}

Browsers without backdrop-filter support fall back gracefully — the card stays semi-translucent over the backdrop without the blur.

Buttons

Two clear tiers:

.btn-primary {
  background: var(--gold-base);
  color: var(--bg-base);
  border: none;
  padding: 9px 14px;
  font-size: 12px;
  font-weight: 600;
  border-radius: 6px;
  letter-spacing: 0.3px;
}
.btn-primary:hover { background: #c9a868; }

.btn-secondary {
  background: transparent;
  border: 1px solid rgba(255,255,255,0.06);
  color: var(--text-muted);
  padding: 6px 12px;
  font-size: 11px;
  border-radius: 5px;
}

Existing .btn class keeps existing styling for backwards compatibility; new .btn-primary / .btn-secondary are used in updated views.

Typography lockup

Logo + brand + tagline group with tighter spacing on login and setup:

  • Logo mark: 40-44px square, 9-10px corner radius, inner highlight only (no outer glow).
  • Brand text: weight 600, color var(--gold-text), letter-spacing 0.5px.
  • Tagline: 11px, var(--text-dim), letter-spacing 0.3px.

Inputs

.input {
  background: var(--bg-input);
  border: 1px solid var(--border-mid);
  color: var(--text);
  padding: 9px 10px;
  border-radius: 6px;
  transition: border-color 0.15s, box-shadow 0.15s;
}
.input:focus {
  outline: none;
  border-color: var(--gold-stroke);
  box-shadow: 0 0 0 2px var(--gold-ring);
}

Arrow glyph

The (U+25B8, small right triangle) replaces ASCII in "next" buttons. Reuses the existing disclosure-glyph vocabulary already used in ▾ custom sections / ▸ attachments.

Logo update

extension/icons/relicario-logo.svg and extension/icons/relicario-logo-16.svg updated:

  • Gold gradient stops shifted: #d2ab43 → #f5d97a → #7c5719 becomes #a88a4a → #cdb47a → #5a3f12.
  • Red theca radial: #9a1a1a → #3a0a0a becomes #7d2622 → #2c0d0a.
  • Highlight gradient: #fde9a8 → #d2ab43 becomes #dac8a0 → #a88a4a.
  • Solid gold tones (#7c5719, #fff3cf, #8a5e1c) remapped to patina equivalents.
  • Center asterisk gem now translucent: facets use vertical gradients (gemFacetLight / gemFacetDark) that fade to transparent at the tip; gem core uses a radial glass gradient (gemCore); two refraction highlights replace the single white-yellow dot.

The composition (pedestal, theca, gem, hinge collar, fleur-de-lis) is unchanged.

Surface-by-surface changes

Login popup (extension/src/popup/)

unlock.ts view:

┌──────────────────────────────────┐
│      [logo]                       │
│      Relicario                    │
│      two-factor vault             │
│                                   │
│  ┌─[ glass card ]──────────────┐  │
│  │ UNLOCK                       │  │
│  │ [passphrase input        ]   │  │
│  │ [   unlock vault          ]  │  │ ← btn-primary, full width
│  └──────────────────────────────┘  │
│                                   │
│      [open vault] [settings]      │ ← btn-secondary, demoted
└──────────────────────────────────┘
  • Body gets .surface-backdrop.
  • Logo lockup grouped (logo / brand / tagline) with tighter spacing (8-12px between).
  • Form moves into .glass card with UNLOCK label inside.
  • Primary action is a real button ("unlock vault") — replaces the "press Enter to submit" implicit flow.
  • Open-vault and settings demoted to secondary buttons below the card.

Setup wizard (extension/src/setup/)

  • Body gets .surface-backdrop.
  • Header lockup at top (logo + "Relicario vault setup").
  • Progress dots get a tiny shadow on the current step (box-shadow: 0 0 4px rgba(184,149,86,0.4)).
  • Each wizard-step becomes a .glass card.
  • Mode-picker cards become smaller .glass cards with patina active state.
  • All "next" buttons use glyph.

Fullscreen vault (extension/src/vault/)

  • Body gets .surface-backdrop.
  • Form section panels (Identity, Credentials) are .glass cards.
  • Save bar matches glass treatment with translucent fill + backdrop-blur.
  • Form layout switches to two-column for login (see below).

Form layout (login, fullscreen only)

The original Phase 2B scope:

┌────────────────────────────────────────────────────────────┐
│ edit login                              ⌘+S to save        │
│ unsaved · esc to cancel                                    │
├──────────────────────────┬─────────────────────────────────┤
│ [ glass: IDENTITY ]      │ [ glass: CREDENTIALS ]          │
│   title  [required]      │   username                      │
│   url + ⤓                │   password ⊙ ↻                  │
│   group (autocomplete)   │     strength: ████░             │
│                          │   totp secret ◫                 │
│                          │     live: 492 837 · 23s         │
├──────────────────────────┴─────────────────────────────────┤
│ NOTES                                                       │
│ ▾ custom sections    ▸ attachments                          │
├────────────────────────────────────────────────────────────┤
│  STICKY SAVE BAR              [cancel] [save]              │
└────────────────────────────────────────────────────────────┘

Layout rules

  • Form pane content: max-width: 960px, margin: 0 auto.
  • Two-column wrapper: display: grid; grid-template-columns: 1fr 1fr; gap: 24px;.
  • Below 720px viewport: grid-template-columns: 1fr (single column stack).
  • Notes / custom sections / attachments live in a sibling block below the grid, full-width.

Column assignment (login)

Left column — IDENTITY:

  • title (required pill)
  • url + fill-from-tab button + hostname chip below
  • group input + datalist autocomplete

Right column — CREDENTIALS:

  • username
  • password + reveal + generate; strength bar below the input
  • totp secret + QR button; live preview below the input

Full-width below grid:

  • notes (with mono toggle)
  • custom sections / fields disclosure
  • attachments disclosure

Sticky save bar

  • position: sticky; bottom: 0; inside the form pane scroll container.
  • Translucent fill matching the glass vocabulary, with a 24px gradient fade above (content scrolls under).
  • Right-aligned [cancel] [save] buttons.
  • Save button reflects validity state — disabled when required fields are empty.

Header treatment

  • Title (left): new login / edit login, weight 500, size 18px.
  • Subtitle (left, below title): unsaved · esc to cancel (dirty) or no changes (pristine), var(--text-muted), size 12px.
  • Hint (right): ⌘+S to save (visual only — actual save shortcut arrives in Phase 3 keymap), var(--text-dim), size 12px. Renders Ctrl+S on non-mac.
  • Popout-to-tab removed from fullscreen forms (already done in Phase 1).

Other item types

Single-column stays for secure_note, identity, card, key, totp, document. They still get the new glass-card treatment around the form section, sticky save bar, and header treatment — only the column grid is login-specific.

Files touched

File Change
extension/icons/relicario-logo.svg Patina palette + gradient glass gem
extension/icons/relicario-logo-16.svg Patina palette (toolbar size)
extension/src/popup/styles.css Patina tokens, .surface-backdrop, .glass, .btn-primary/secondary
extension/src/popup/components/unlock.ts Logo lockup, glass card, primary unlock button
extension/src/popup/components/types/login.ts Add surface: 'popup' | 'fullscreen' param; column wrapping when fullscreen
extension/src/setup/setup.ts .surface-backdrop, glass step cards, glass mode-picker cards, arrows
extension/src/setup/setup.html Body wrapper class
extension/src/vault/vault.css Patina tokens, glass form sections, form-grid, sticky save bar, header treatment
extension/src/vault/vault.ts Header subtitle dirty-state subscriber, surface flag passed to login renderer
extension/src/vault/components/*.ts Glass class on form panels

The login renderer needs to know which surface it's rendering into (popup vs fullscreen). Add an optional surface: 'popup' | 'fullscreen' parameter to renderForm(). Default to popup to preserve existing behavior.

Testing

Per-area tests using existing vitest + happy-dom setup:

  1. Palette migration test: computed style on .btn-primary resolves to #a88a4a.
  2. Layout test: mount login form with surface: 'fullscreen', assert grid layout, Identity / Credentials columns contain expected fields.
  3. Stack-down test: simulate viewport ≤720px, assert single-column.
  4. Dirty subtitle test: mount form, simulate input, assert subtitle text changes.
  5. Sticky bar test: assert save bar exists, position style, save button validity.
  6. Glass class application: unlock card, setup step card, form panels all get .glass class.
  7. Arrow glyph test: all "next" buttons render (no ).
  8. Other-type non-regression: mount secure_note, assert single-column layout.
  9. Logo regression: snapshot test on relicario-logo.svg defs/colors.

Manual QA pass per surface with the rebuilt extension loaded in Chrome and Firefox.

CLI parity

This phase is purely visual / layout-shaped. No CLI counterpart. The CLI already accepts all login fields as flags (--title, --username, --password, etc.).

Out of scope / deferred

  • Two-column layout for non-login types.
  • User-resizable column widths.
  • Animated transitions on subtitle text change (snap is fine).
  • Functional ⌘+S keyboard shortcut — arrives with Phase 3 keymap. The hint is a visual label until then.
  • Diff view / form-level "you changed N fields" indicator.
  • Light theme.