Files
antidrift/docs/superpowers/specs/2026-05-31-m4-look-good-design.md
T
felixm c807a72623 Spec M4: cockpit-style web UI design pass
State-driven accent HUD, stacked bands, CSS/JS split out of the inline
HTML, polished presentational review recap. No behavior changes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 20:57:32 -04:00

135 lines
6.1 KiB
Markdown

# M4 — "Look good" Design
**Goal:** A real design pass on the web UI: a cockpit-style, state-aware HUD that
reads at a glance, with CSS/JS split out of the inline HTML for maintainability,
and a polished review recap. No behavior changes.
**Status:** Design approved 2026-05-31. Supersedes the utilitarian inline UI
shipped through M3.5.
---
## 1. Direction & Visual System
The UI is an **instrument panel you glance at** — a cockpit, not a document.
Dark, near-black cool-neutral base. State is carried by a **single state-driven
accent**: a CSS custom property `--accent` switched by a `data-state` attribute
on the `<main>` element. The accent colors the status band's top border and the
state pill, so the frame itself communicates where you are without reading text.
### State → accent mapping
| State | `data-state` | Accent |
|--------------------|--------------|--------------------|
| locked | `locked` | dim gray |
| planning | `planning` | blue |
| active · on-task | `active` | calm green / cyan |
| active · nudge | `nudge` | amber |
| active · drifting | `drift` | red |
| review | `review` | violet-neutral |
`data-state` is derived in the client render from `runtime_state` plus, when
active, the drift sub-status (`drifting``drift`; a present `nudge``nudge`;
otherwise `active`). This mirrors the precedence already used by the status-file
renderer (drift outranks nudge).
### Design tokens (CSS custom properties)
- Surfaces / text: `--bg`, `--panel`, `--line`, `--ink`, `--ink-dim`
- State accent: `--accent` (the only variable that changes with `data-state`)
- Fixed semantic colors: `--ok`, `--warn`, `--danger`
### Typography
- Timer: heavy weight, `font-variant-numeric: tabular-nums`.
- Evidence times: `ui-monospace` so the bucket columns align.
- Band headers / pills: small, uppercase, letter-spaced (keeps the existing pill
idiom from the current UI).
- Prose: `system-ui`.
## 2. Layout — Stacked HUD Bands
Every state composes the same **band primitive**: a row with a top divider and
consistent horizontal/vertical padding. Stacking bands produces the layered HUD
look. The active session follows the approved sketch:
```
ACTIVE · on task · 7 switches ← status band (accent border-top + pill)
24:18 write the spec section ← timer band
done when: draft saved ← task band
now code·spec ● | code 18:02 … ← evidence band
[ Complete ] ← action band
```
Drift and nudge are **not** a separate floating box. When the session drifts or
is nudged, the **status band itself** changes copy and `data-state` flips, so the
whole frame goes amber/red. The same controls render inside that band:
- Drift: `Back to task` (`/refocus`), `This is on task` (`/ontask`),
`End session` (`/complete`).
- Nudge: `Dismiss` (client-only, current behavior).
- Pending: a quiet "checking focus…" line.
## 3. Per-State Treatment
- **Locked:** one dim band, large `Start planning` button (`/planning`).
- **Planning:** an intent + `Sharpen` band, then field bands — Next action,
Success condition, Minutes, Allowed apps — with the blue accent. All existing
input ids (`#intent`, `#na`, `#sc`, `#mins`, `#apps`, `#start`,
`#coachStatus`) and the coach pre-fill behavior are untouched.
- **Active:** the HUD described in §2.
- **Review (polished, presentational only):** summary bands built from data the
state already carries — `next_action`, `success_condition`, the context-switch
count, and the per-window bucket recap (reusing the existing `evidence`
fields). **No new backend data** is introduced; richer session reflection is
M7's job. The `End` button (`/end`) remains.
## 4. Structure
Split the single inline file into three files under `internal/web/static/`:
- `index.html` — markup shell only (`<head>` links the stylesheet and script).
- `app.css` — the full visual system (tokens, bands, per-state rules).
- `app.js` — the render logic, **moved verbatim**: same `render()` function,
same partial-update paths (`updateActiveDrift`, `updatePlanningCoach`), same
element ids, same `EventSource('/events')` and POST endpoints. The only
additions are the band markup in the template strings and setting
`main.dataset.state` per render.
`web.go` currently serves only `/` via `c.FileFromFS`. Add routes so the two new
assets are served from the embedded `staticFS`:
- `GET /app.css``static/app.css`
- `GET /app.js``static/app.js`
No new Go dependencies, no JavaScript build step, no framework. The embedded
static directory and the conciseness/token-efficiency ethos of the Go rewrite
are preserved.
## 5. Behavior & Data Flow — Unchanged
Same SSE stream, same partial-update `render()` logic, same element ids, same
POST endpoints, same server-authoritative expiry timer. The redesign is markup +
CSS + asset routing only. This is precisely what keeps the existing
`web_test.go` (endpoint and state-JSON assertions, markup-agnostic) green.
## 6. Testing
- **Existing `web_test.go` stays green.** It asserts on endpoint status codes and
the state JSON, not on HTML markup, so the visual rework does not touch it.
- **New Go test:** `GET /app.css` and `GET /app.js` each return `200` with the
correct `Content-Type` (`text/css`, `text/javascript` / `application/javascript`).
Asserted against the router via `httptest`, stdlib `testing` only.
- **Manual visual checklist** across the six `data-state` values: locked,
planning, active (on-task), active (nudge), active (drift), review. There is no
JavaScript test harness in this Go project; the rendering is presentational and
verified by eye, consistent with the existing approach.
## 7. Out of Scope
- Micro-interactions / motion (timer easing, accent transitions, panel slide-in)
— explicitly excluded for M4; can be a later pass.
- Any new backend data or fields on the state payload.
- M7 reflection content (real session summary, time-on-task analytics). The M4
review screen is presentational recap of already-available data only.