# CSS Reduction — Baseline (2026-06-23) ## Goal Reduce `dist/assets/index-*.css` bytes without changing any tested screen. One declaration/rule at a time, verified by pixel-identical screenshots and project checks. This file is the baseline the iterative loop is compared against. ## Build (the size we are trying to shrink) | metric | bytes | | ------------ | ------ | | raw | 60,695 | | gzip | 11,786 | | brotli | 9,875 | `dist/assets/index-BznqBut5.css`, built with `npx vite build` (Vite 5.4.21, 8.9s). ## Test matrix (the screens we will hold pixel-identical) - **Theme**: dark only (the app is `` + `theme="dark"` for the Toaster; no light path exists in the design system). - **Sizes**: 3 (desktop 1440×900, tablet 768×1024, mobile 375×812). - **Routes**: 13 (`/`, `/upload`, `/inbox`, `/claims`, `/claims?status=denied`, `/remittances`, `/providers`, `/reconciliation`, `/acks`, `/batches`, `/batch-diff`, `/activity`, `/does-not-exist`). - **Interactive states**: 6 (claim drawer open, remit drawer open, inbox row focused, search focused, keyboard cheatsheet open, upload dropzone focused) × 3 sizes = 18 captures. - **Total**: 13 × 3 + 6 × 3 = **57 screenshots** per build. Capture source: `audit-uiux-extended.mjs` (new, superset of `audit-uiux.mjs`). Pixel-diff harness: `tools/css-screenshots-diff.mjs` using `pixelmatch` (threshold 0). ## Project checks (the gates we hold green) | check | baseline | used as gate? | reason | | --------------------------- | -------- | ------------- | --------------------------------------- | | `npx vite build` | passes | **yes** | produces the CSS bundle under reduction | | `npx vitest run` | 498 / 501 | **yes** | pre-existing 3 failures, see "Known failures" below | | `tsc -b` (in `npm run build`)| **fails**| no | 15 type errors in test files + `Upload.tsx`, all pre-existing | | `npm run typecheck` | fails | no | same as above | | `npm run lint` | fails | no | `sh: eslint: command not found` (eslint not installed) | ### Known pre-existing failures (not caused by this work) `vitest run` — 3 failing tests: - `src/pages/Inbox.test.tsx > Inbox page > SP14: payer-rejected row count rolls up into the need-eyes header` - `src/store/tail-store.test.ts > useTailStore > test_fifo_cap_evicts_oldest_when_over_10000` - `src/components/inbox/InboxHeader.test.tsx > InboxHeader > renders the date and counts` None touch CSS. Each candidate run will compare the new `vitest` exit status and failure set to the baseline — a candidate is rejected if it adds a new failure, even if the count stays at 3. `tsc -b` / `npm run typecheck` — 15 errors in test files and `src/pages/Upload.tsx`. Not exercised by the reduction loop. `npm run lint` — `eslint` is not installed in `devDependencies`; the script `npm run lint` exits 127. Not exercised. ## Interactive-state coverage Out of 18 interactive captures, 15 succeed and 3 fail (the same 3 every run): - `remittances-drawer` × all sizes — the `/remittances` page renders with no table rows in the current backend state, so the row-click step finds nothing. The screenshot falls back to the static `/remittances` page with no drawer; pixel-identical comparison still works for that fallback, but the remittance-drawer CSS itself is not exercised. This is captured here as an **untested state** for the final report. The other 15 interactions (`claims-drawer`, `inbox-row-focused`, `search-focused`, `cheatsheet-open`, `upload-dropzone-focused` × 3 sizes) all succeed. They exercise the CSS for the open claim drawer, the keyboard cheatsheet overlay, the focused search button, the focused upload dropzone, and the focus ring on inbox rows. ## Pre-existing noise (not regressions, not caused by this work) From the baseline run (`baseline-report.json`): - 6/57 flows have ≥1 console error. All from the `inbox` route and the `inbox-row-focused` state. The 4 interactive ones are the same source. - 24/57 flows have ≥1 failed request. Likely the dashboard summary endpoint (`/api/dashboard/summary`) and a few analytics / SSE probes in the inbox. - 0 page errors. A candidate that does not increase these counts is fine; an increase is informational, not a gate. ## Self-diff sanity check `tools/css-screenshots-diff.mjs compare` with `BASE == CAND` returns `PIXEL-IDENTICAL — 57 compared, 0 differing`. The harness works. ## What is in scope for the iterative loop - Source: `src/index.css` (custom CSS + Tailwind base/components/utilities) - Config: `tailwind.config.js` - Component `.tsx` files (only if removing a Tailwind utility from a `className` produces a smaller bundle) ## What is out of scope - `index.html` (Google Fonts preconnect, hard to prove pixel-identical after font source change) - The JS bundle (separate goal) - The backend (`backend/`) - Any non-CSS build artifact