Polish pass on the translate panel: the four export buttons overflowed both transcript cards at 390 px. Also record the headless-Chrome translation run and a re-measured bench in D-WS4b. Co-Authored-By: Claude Opus 5.5 <[email protected]>
42 lines
2.7 KiB
Markdown
42 lines
2.7 KiB
Markdown
# Design
|
||
|
||
Derived from the shipped `src/index.css` (single stylesheet, plain CSS, no framework). Describes what
|
||
exists, not an aspiration. Update in the same commit as visual changes.
|
||
|
||
## Foundations
|
||
|
||
- **Theme:** dark by default, light when the OS prefers it (`@media (prefers-color-scheme: light)`
|
||
overrides the tokens; no in-app toggle). `<meta name="theme-color">` has a variant per scheme. The
|
||
PWA manifest and icons stay dark (`#16181d`).
|
||
- **Tokens (`:root`, dark → light):** `--bg #16181d → #f5f6f8` · `--fg #e8e8e8 → #1a1d23` ·
|
||
`--muted #9aa3b2 → #5b6372` · `--panel #1f232b → #ffffff` · `--border #343a46 → #d3d8e0` ·
|
||
`--surface-raised` (inputs, code) · `--surface-selected` (selected/drag-active) ·
|
||
`--accent #7aa2f7 → #2f5bd3` + `--on-accent` · `--success` / `-bg` / `-border` ·
|
||
`--danger` / `-muted` / `-bg` / `-border` + `--on-danger` · `--live` (recording) · `--shadow`.
|
||
**No raw colours outside the token block** — add a token (with both values) instead.
|
||
- **Contrast:** every text/background token pair is ≥ 4.5:1 in both themes (checked when the light
|
||
theme landed, D-037). Re-check any new pair.
|
||
- **Type:** Inter Variable, self-hosted (`@fontsource-variable/inter`, 7 unicode-range subsets served
|
||
from `/fonts/`, precached; see `scripts/fonts.ts`, D-037). Body line-height 1.5; `h1` 2.2rem / 1.15.
|
||
- **Layout:** single centred column, `.app { max-width: 720px; padding: 2.5rem 1.25rem 3rem; gap: 1.5rem }`,
|
||
`body { min-width: 320px }`.
|
||
- **Radius:** 8px for controls (most common); 10–14px for panels/cards; 999px for pills/badges.
|
||
- **Motion:** `0.15s` colour/border transitions; `pulse` (live dot) and `blink` (cursor) animations,
|
||
disabled under `prefers-reduced-motion`.
|
||
- **Browser surfaces:** `accent-color` and `::selection` come from `--accent`.
|
||
|
||
## Components
|
||
|
||
One BEM-ish class block per React component in `src/components/` (`.model-picker`, `.dropzone`,
|
||
`.live-controls`, `.engine-toggle`, `.auth-panel`, `.update-toast`, …), with modifier classes like
|
||
`-selected`, `-active`, `-disabled`. Interactive states use `:hover:enabled` and `:focus-visible`.
|
||
`.visually-hidden` exists for screen-reader-only text.
|
||
Card headers (`.transcript-header`: title + export/Copy buttons) wrap, so on a phone the buttons
|
||
move under the title instead of overflowing the card.
|
||
|
||
Secondary disclosures (`.storage-manager`, `.translate-panel`) share one look: a 12px-radius
|
||
`--panel` card with a semibold `<summary>`, muted 0.85rem hints, outlined 8px buttons. Inside the
|
||
translate panel the one action (`.translate-button`) is the only accent-outlined button and fills
|
||
with `--accent` / `--on-accent` on hover; a translation renders as a second `.transcript` card below
|
||
it rather than a card nested inside the panel.
|