# appshell-scope-6 — the real design sweep

> **Operator order, 2026-07-27:** "a proper sweep to ensure everything follows
> the new design and not the old design and colour, and overall improve UX/UI."
> Authorised explicitly — this is NOT a re-rethink and NOT a design round
> (DECISIONS "Design rounds are the exception"); it is conformance plus the
> plain-words/UX pass the standing law already asks of every screen we touch.

## The debt, measured (2026-07-27, not estimated)

`cd apps/web && npx vitest run --pool=forks --poolOptions.forks.maxForks=2 src/styles/conformance.test.ts`

> **1924 legacy markers across 76 files** — every one baselined and shrink-only,
> so the oracle is GREEN today. Green here means "measured and fenced from
> growing", not "clean". This package is what turns it into clean.

Also measured directly:
- **249 raw form controls** — 157 `<input>`, 66 `<select>`, 26 `<textarea>`.
- **163 hard-coded hex colours** in `.tsx`/`.css` outside `styles/tokens.css`.

The ten worst files carry ~45% of everything:

| Markers | File | Note |
|---|---|---|
| 237 | `styles/global.css` | **the shared fence — every legacy screen consumes it** |
| 112 | `components/flows/flow-step-editors.tsx` | legacy Flow editor; Stage G retires this screen |
| 91 | `routes/FlowEditor.tsx` | same — retiring |
| 90 | `routes/CampaignDetail.tsx` | WhatsApp surface, scope DORMANT |
| 82 | `routes/Campaigns.tsx` | WhatsApp surface, scope DORMANT |
| 68 | `routes/Templates.tsx` | WhatsApp surface, scope DORMANT |
| 57 | `components/templates/TemplateEditorForm.tsx` | WhatsApp surface, DORMANT |
| 55 | `components/flows/ExecutionsView.tsx` | retiring |
| 52 | `components/templates/TemplateStatsPanel.tsx` | WhatsApp surface, DORMANT |
| 48 | `components/flows/FlowCanvas.tsx` | retiring |

## The sequencing this table forces — read before planning stages

**Nine of the ten worst files are on screens that are either DORMANT or being
DELETED.** The WhatsApp surfaces (Campaigns, Templates) are parked because the
number is Meta-disabled; the Flow editor family is ruled obsolete by
channels-scope-5 Stage G. Sweeping them first would be the single most expensive
way to produce the least value — and repainting a screen we are about to delete
is pure waste.

So the order is by LEVERAGE, not by marker count:

- **Stage 1 — `global.css` (237).** The shared fence. Every legacy screen
  consumes it, so it lands and deploys FIRST and alone; everything else rebases
  onto it. Nothing else may run concurrently with this stage.
- **Stage 2 — the shared component set** (`StatusPill` 26, `QueryState` 20,
  `ErrorBoundary` 18, `Toast` 12, `Skeleton` 11, `Modal` 9, `Pagination` 7,
  `ConfirmDialog` 5, `forms/FileInput` 8 ≈ 116 markers). These render on
  *every* screen, so one pass here improves surfaces we are not otherwise
  touching. Highest leverage per line in the package.
- **Stage 3 — the form-control retirement.** Replace the 249 raw controls with
  `cm-input`/`cm-select`/`cm-field`. ⚠ **Depends on the primitives seat landing
  first** (in flight 2026-07-27, channels-scope-5 Stage E primitives). Do not
  start Stage 3 until those exist, or two seats will invent the same control.
- **Stage 4 — the live screens**: `Inbox`, `Contacts`, `ContactDetail`,
  `Login`, `NotFound`, `ApiDocs`. These are the ones in daily use and NOT
  slated for deletion. This is where the UX/UI half earns its keep.
- **Stage 5 — DEFERRED, deliberately**: the WhatsApp surfaces and the Flow
  editor family. Boarded, not silently dropped. They are swept when their own
  scope wakes (WhatsApp: the number returns; Flows: Stage G retires the screen,
  which may delete the debt outright rather than fix it).

## Non-negotiables

1. **No fencing.** "When I say sweep, I mean a sweep" (DECISIONS 2026-07-22). A
   stage is done when its files are DELETED from `LEGACY_BASELINE`, not lowered
   and not excused. A stage that lowers a number without emptying its files has
   not finished.
2. **The oracle is mechanical and already exists** — `conformance.test.ts`.
   Eyeball evidence does not close a stage. The baseline shrinks or the stage
   is not done.
3. **`design/tokens.md` is law.** A screen may not ship outside it. If a stage
   needs something the sheet lacks, STOP and ask — a missing token is an
   operator decision, never an invention (this is how the gold focus ring got
   in).
4. **UX/UI improvement is in scope, redesign is not.** Plainer words, fewer
   visible concepts, no engineering vocabulary, honest empty states, real focus
   states, 320/375/768 clean. Not new layouts, not new concepts, no design
   round unless the operator calls one.
5. **Accessibility is not optional** (it is a "never simplify away"): visible
   focus on every interactive element, labels tied to controls, contrast that
   passes. The known gold focus-ring failure dies here.
6. **Nothing ships as temporary** (DECISIONS 2026-07-25) — no transitional
   class, no "will clean up later" shim.

## The one open fork — 21st.dev (operator ruling owed)

The operator asked to "maybe use 21st.dev". The tension, stated plainly:
21st.dev components are React + **Tailwind** + shadcn/Radix. This app is React +
Vite + **plain CSS on `--cm-*` tokens**, and `web-adopt-audit-2026-07-17.md`
already records *"three competing styling systems"* as its top Critical.

- **Option A (recommended): 21st.dev as visual REFERENCE, rebuilt on our
  tokens.** We copy the interaction patterns and visual polish, implement them
  as `cm-*` components. No new dependency, the conformance oracle keeps working
  unchanged, and the Critical shrinks instead of growing.
- **Option B: adopt Tailwind + shadcn for real.** Genuinely faster to good-
  looking screens, and it is what 21st.dev is actually FOR — but it adds a
  fourth styling system to a codebase whose top Critical is having three, and
  `conformance.test.ts` would need rewriting (it flags raw colours and
  off-scale type, which is roughly what a utility framework emits).
- **Option C: Tailwind on new screens only.** Rejected in advance — it
  guarantees a permanent split and violates "nothing ships as temporary".

**This must be ruled before Stage 2**, because Stage 2 rebuilds the shared
components and that is precisely where the answer changes what gets written.

## Out of scope

- The Agent surfaces — already on `--cm-*` and swept (zero markers under
  `routes/agent/`, verified 2026-07-27).
- Analytics — the operator has ruled it needs a *definition* round first
  ("what to show and how"), which he owns. Not a conformance problem.
- The flow canvas primitives — another seat owns them.
- Any new screen, feature, or concept.

## Definition of done

`conformance.test.ts` green with the stage's files **removed from the
baseline**; `apps/web` tests green; `corepack pnpm --filter @channels/web build`
clean; 320/375/768 verified per touched screen; deployed and published.
