118 lines
5.8 KiB
Markdown
118 lines
5.8 KiB
Markdown
# Design
|
||
|
||
Terminal / ops-console visual language for an IMAP migration tool. Near-black,
|
||
green-tinted dark surface; a single amber functional accent; monospaced body with
|
||
a condensed display face for headings. Dense, instrument-panel layouts where the
|
||
system state is always legible. Captured from `web/src/index.css` and
|
||
`web/src/app.css` — these tokens are canonical; new work extends them, it does not
|
||
replace them.
|
||
|
||
## Theme
|
||
|
||
Dark, committed. Not "dark to look cool" — the scene is an operator running a
|
||
long-lived migration and watching thousands of counters tick; a dark console
|
||
keeps the amber accent and the ok/fail/pending signal colors doing the reading
|
||
work with minimal eye strain. Color strategy: **restrained** — tinted neutrals
|
||
carry the surface, one amber accent stays under ~10% of the pixels, and the
|
||
green/red/yellow/blue roles appear only as status semantics.
|
||
|
||
Signature textures (keep, don't multiply):
|
||
- A faint amber radial glow at the top of the page (`radial-gradient` at 50% -10%).
|
||
- A 3px repeating-linear scanline overlay at ~1.2% white — the CRT tell.
|
||
- Panels wear a floating uppercase tab label (`.panel-label`) punched through the
|
||
border; the log panel mirrors it on the right (`.log-clear`).
|
||
|
||
## Color
|
||
|
||
OKLCH is the target space for any new color; existing tokens are hex and stay hex.
|
||
|
||
### Surfaces (green-tinted neutrals, darkest → raised)
|
||
- `--bg` `#0a0d0b` — page base
|
||
- `--bg-inset` `#070a08` — insets: inputs, progress track, log pane
|
||
- `--bg-panel` `#0f1512` — panels, cards, login card
|
||
- `--bg-panel-raised` `#141b17` — topbar, table headers, modal dialog
|
||
|
||
### Borders
|
||
- `--border` `#23342b` — default hairline (1px)
|
||
- `--border-bright` `#3a5443` — raised/interactive edges, dashed underlines
|
||
|
||
### Ink
|
||
- `--fg` `#dbe8de` — primary text
|
||
- `--fg-dim` `#6f8478` — labels, secondary text, nav idle
|
||
- `--fg-faint` `#4a5c50` — hints, empty states, faint indices
|
||
|
||
### Accent (amber — attention & primary action)
|
||
- `--accent` `#ffb238` — primary buttons, active nav, panel labels, progress fill
|
||
- `--accent-strong` `#ffd27a` — hover/emphasis
|
||
- `--accent-dim` `#7a5a26` — active borders, tinted glows
|
||
- Primary-button ink is near-black `#1a1200` on amber, never white.
|
||
|
||
### Status semantics (color always carries meaning)
|
||
- `--ok` `#52e6a0` / `--ok-dim` `#234a37` — success (glowing dot)
|
||
- `--fail` `#ff5d5d` / `--fail-dim` `#4a2323` — error
|
||
- `--pending` `#f0c419` — waiting/queued
|
||
- `--info` `#57c2ff` — in-progress / scan / new-folder marker (pulsing dot)
|
||
|
||
> Contrast watch: `--fg-dim` on `--bg-panel` is the thinnest pairing — for real
|
||
> body copy (not just uppercase micro-labels) prefer `--fg`. Placeholder and
|
||
> small print must still clear AA; don't push text below `--fg-faint`.
|
||
|
||
## Typography
|
||
|
||
Two families on a real contrast axis (mono vs. condensed display) — never two
|
||
similar sans.
|
||
|
||
- **Body / UI / data:** `--font-mono` = JetBrains Mono (400/500/700), 14px base,
|
||
line-height 1.5. Numbers use `font-variant-numeric: tabular-nums`
|
||
(`.mono-num`, `.num-cell`, stat values) so columns align.
|
||
- **Display / headings / brand:** `--font-display` = Big Shoulders Display
|
||
(600/800), uppercase, letter-spacing ~0.3–0.5px. Page titles 34px, brand 22px,
|
||
login brand 30px.
|
||
- **Micro-labels:** uppercase, 10–12px, letter-spacing 0.08–0.14em, `--fg-dim`.
|
||
This is the workhorse label style (nav, field labels, badges, table headers,
|
||
panel tabs). Used as a deliberate system, not a per-section eyebrow.
|
||
|
||
## Components
|
||
|
||
- **Panels** (`.panel`): bordered surface, 3px radius, floating uppercase tab
|
||
label. The primary content container — used instead of stacked cards.
|
||
- **Buttons**: `.btn` (ghost outline, uppercase, 2px radius) · `.btn-primary`
|
||
(solid amber, dark ink, amber glow on hover) · `.btn-danger` · `.btn-ghost` ·
|
||
`.link-btn` (dashed-underline text button, `.danger` variant).
|
||
- **Status badges** (`.badge` + `.badge-ok/-fail/-pending/-info`): dot + uppercase
|
||
label, tinted 6%-alpha background, colored dot (glowing/pulsing per state).
|
||
- **Tables** (`table.tbl` in `.tbl-wrap`): dense, hairline row borders, raised
|
||
uppercase header, right-aligned `.num-cell`, subtle row-hover, `.empty-row` for
|
||
empty states. Horizontal scroll lives on `.tbl-wrap`.
|
||
- **Forms** (`.field`, `.field-row`): uppercase label above inset input; focus =
|
||
amber border + 3px amber-12% ring.
|
||
- **Modals** (`.modal-overlay` + `.modal-dialog`, `.modal-md/-lg`): fixed overlay,
|
||
backdrop-blur(2px), fade + 6px rise entrance. Folder-mapping grid
|
||
(`.map-row`: src → select). z-index scale: topbar 10 → overlay 100.
|
||
- **Live progress** (`.acct-progress`, `.pbar`/`.pbar-fill`, `.pmeta`, `.pscan`,
|
||
`.acct-error`): thin amber bar + mono meta; scan phase in `--info`; persisted
|
||
last-error in `--fail`, ellipsis-truncated.
|
||
- **Log pane** (`.log-pane`): reversed-column inset console, tagged lines
|
||
(`.tag` amber + `.payload`).
|
||
- **Chrome**: sticky `.topbar` with bracketed `.brand`, uppercase `.topnav`
|
||
(active = amber), `.session-indicator` with pulsing `.pulse-dot`.
|
||
|
||
## Layout
|
||
|
||
- App shell: sticky topbar (56px) over a centered `.main`, `max-width: 1180px`,
|
||
padding `32px 24px 64px`.
|
||
- Grids: `repeat(auto-fit, minmax(340px, 1fr))` for panel grids — responsive
|
||
without breakpoints. Flexbox for 1D rows (`.btn-row`, `.stat-row`, `.upload-row`).
|
||
- Radii: tight — 2px (controls) / 3px (surfaces). Nothing pill-shaped.
|
||
- Dividers: centered uppercase `.divider-label` with rule lines both sides.
|
||
|
||
## Motion
|
||
|
||
Restrained, functional. Ease-out only; no bounce/elastic.
|
||
- Entrances: modal fade 0.12s + rise 0.14s.
|
||
- Feedback: 0.15s color/border transitions on nav, buttons, inputs.
|
||
- Ambient: `pulse` (2.4s) on session/info dots; progress-bar width 0.3s ease-out.
|
||
- Amber glow bloom on primary-button hover.
|
||
- **Owed:** a `prefers-reduced-motion: reduce` block — the pulsing dots and
|
||
progress transitions need a static fallback. Add before shipping motion work.
|