# Design sweep — shell-basics (daily-use entry surfaces)

Files: `routes/Home.tsx` (+`home.css`), `routes/Login.tsx`, `routes/NotFound.tsx`, `routes/ApiDocs.tsx`
Reached via `App.tsx`: `Login` standalone at `/login`; `Home` is `index` (`/`); `ApiDocs` at `/docs/api` (role-gated, no sidebar entry); `NotFound` is the `*` catch-all.

---

## Home.tsx

**Legacy markers:** 0 (not in `LEGACY_BASELINE` — already fully on `--cm-*`). Raw form controls: 0.

- **IA:** 4 zones (channel cards incl. nested WhatsApp quality block, needs-attention feed merged with notifications, grouped agent-performance card, today strip). Round-6b build target ("is there an issue?" in ten seconds) — concept count is bounded and each zone earns its place.
- **Interaction:** optimistic dismiss (single + bulk) with one silent retry and a restore-on-failure notice; retry button on load error; "go fix →" links per attention row. No dead ends, no raw `<select>`/`<input>`.
- **Content/copy:** plain words throughout — "no data yet", "all clear", "go fix", "silent" vs "receiving" — no engineering vocabulary, no AI-isms.
- **Visual/tokens:** 100% `--cm-*` in `home.css`; no hex, no legacy `var(--navy)`/`var(--gold)`. Cleanest file in this group by a wide margin.
- **a11y/responsive:** `role="alert"` on the error banner, `role="status"` on the dismiss-failure notice, `role="presentation"` on the quota meter; status is icon+dot+text, never colour alone. The "Loading…" state isn't in an `aria-live` region — minor. Grid zones use `auto-fit`/`minmax(min(100%, …))`, survives 320px.

**VERDICT: keep** — already the target-picture screen; no legacy debt, no structural issue.

**Forks:** none — nothing here needs an operator call.

---

## Login.tsx

**Legacy markers:** 29 (pinned in `LEGACY_BASELINE`). Raw form controls: 2 `<input>`.

- **IA:** single concept (email + password), correctly minimal for an auth gate.
- **Interaction:** autofocus, `disabled` during submit, `aria-invalid`, error row height reserved so the card doesn't jump, specific 401 copy vs. generic network-error copy. Already well thought through.
- **Content/copy:** plain, calm error copy ("Those credentials weren't recognised…"), no jargon.
- **Visual/tokens:** the whole file is inline-style objects on the **dead navy/gold palette** — `var(--navy)`, `var(--gold)`, `var(--gold-soft)`, `var(--gold-2)`, `'DM Sans'`/`'DM Mono'` — the exact system `docs/DECISIONS.md` § Design & UI rules OUT of product UI. This is the highest-signal violation in the group: not a missed token, a banned palette, wholesale.
- **a11y/responsive:** labels wrap inputs correctly, `autoComplete`, `role="alert"` on error — solid. Card is `width: 380, maxWidth: "100%"` inside a flex-centered 100vh page — survives 320px.

**VERDICT: redesign** — not because the UX is broken (it isn't) but because it ships the retired navy/gold system wholesale; needs a `--cm-*` rebuild, structure can carry over almost as-is.

**Forks:**
1. Keep the centered-card-with-brand-rule layout, or fold Login into the same shell chrome as the rest of the app (just re-token it)? *Recommend: keep the standalone card — a login screen isn't the appshell, isn't held to appshell IA.*

---

## NotFound.tsx

**Legacy markers:** 8 (pinned). Raw form controls: 0.

- **IA:** single concept, correctly trivial.
- **Interaction:** one primary action (`Back to Home`), no dead ends, no secondary noise.
- **Content/copy:** plain English, terse, on-brand without over-explaining.
- **Visual/tokens:** small: `var(--navy)`, `var(--muted-ink)` (not a `--cm-*` name), `'DM Sans'`, plus the legacy `so-eyebrow`/`so-btn-primary` classes. Cheapest fix in the group — a token swap, no structural change.
- **a11y/responsive:** semantic `h1`, centered column, `maxWidth: 520` — survives 320px without issue.

**VERDICT: polish** — token swap only; the content and structure are already right-sized.

**Forks:** none.

---

## ApiDocs.tsx

**Legacy markers:** 35 (pinned, the heaviest of the four). Raw form controls: 0.

- **IA:** 10 sections (how-it-works → auth → request body → idempotency → response → errors → examples → compatibility promise → go-live checklist). Dense, but this is scan-as-reference developer documentation for external integrators (n8n, CRMs), not a held-in-memory product screen — the count is appropriate to its job.
- **Interaction:** history-aware Back button, per-block Copy with a transient "Copied" label, live origin so examples are copy-pasteable. No dead ends.
- **Content/copy:** curl/JS/HTTP-code vocabulary is inherent to a developer API contract page — this is the one screen in the group where "no engineering vocabulary" is arguably the wrong rule to apply verbatim, worth an explicit operator call rather than silently exempting it.
- **Visual/tokens:** heaviest debt in the group — inline-style objects throughout, `var(--navy)`/`var(--gold-2)` plus **raw hex** (`#fff`, `#FCFBF6`, `#1A2B45`, `#E8EEF8`) for the code-block chrome.
- **a11y/responsive:** tables (`Request body`, `HTTP errors`) have proper `<thead>`/`<th>` but no `overflow-x` wrapper — real risk of horizontal page overflow at 320px given 4-column technical content. Copy button's state change ("Copied") isn't in an `aria-live` region, so screen-reader users get no confirmation.

**VERDICT: polish** — content/IA is right for its audience; the work is a token/hex sweep plus wrapping the two tables for narrow viewports. Not a redesign because nothing about the structure is wrong.

**Forks:**
1. Does the "plain words, no engineering vocabulary" ruling apply to this page, or is developer-facing API documentation an explicit exception? *Recommend: exception — the audience is technical integrators, and the page already frames itself as a frozen v1 contract for that audience.*
