diff --git a/design-qa.md b/design-qa.md
index 2ec73430a..caa03d415 100644
--- a/design-qa.md
+++ b/design-qa.md
@@ -61,3 +61,7 @@
Final result: **blocked**.
Blocker: an independent source visual target is required to certify concept fidelity. Implementation-level responsive, interaction, accessibility, and regression QA passed, but the design cannot honestly be declared pixel-faithful to an external approved concept that was not supplied.
+
+## Follow-up audit — 2026-07-17
+
+The exhaustive line-level design, accessibility, UX, interaction, and route-coverage follow-up is documented in [`docs/design-audit-2026-07-17.md`](docs/design-audit-2026-07-17.md). It preserves the fixes above, avoids duplicating this pass, and records the new P1/P2/P3 fixes plus the exact local verification limitations.
diff --git a/docs/branch-review-ledger.md b/docs/branch-review-ledger.md
index b5d2bb9ca..7c94ea76d 100644
--- a/docs/branch-review-ledger.md
+++ b/docs/branch-review-ledger.md
@@ -609,6 +609,8 @@ Use this ledger to prevent repeated branch and PR reviews when the reviewed HEAD
| 2026-07-18 | claude/clinical-kb-pwa-review-asi3wb (PR #835) | d46f381ac27b53b1bd5ac0ef77962fbd48cf3aa7 | PWA manifest and install-UX polish (plan Phase 2) | Implemented Phase 2 of the PWA plan with cache semantics untouched: `launch_handler` navigate-existing/auto and `display_override` standalone/minimal-ui in `manifest.ts`; `monochrome-192/512` icon variants rendered as a white alpha-only silhouette from the shared brand mark via `BRAND_MONOCHROME`; a one-time iOS/iPadOS Add to Home Screen hint in `pwa-lifecycle.tsx` (30-day dismissal key, never in standalone, timer-deferred eligibility for the set-state-in-effect lint rule). Docs Installability section updated; manifest screenshots remain deferred per the production-capture precondition. Phase 2 re-scout confirmed zero upstream drift before implementation. | Focused Vitest 55/55. `verify:cheap` 2773 passed/1 failed and `verify:pr-local` unit stage identical — the lone failure is the known container-only `pdf-extraction-budget` artifact (clean-main baselined; hosted CI green on #826). `test:e2e:pwa`: privacy journey passed; icon probes validated both new monochrome PNGs; sole installability error remains the container `in-incognito` artifact. `verify:ui` 219 passed/2 failed — exactly the two clean-main-baselined container artifacts, no new failures. `format:check` clean. Build/bundle stages deferred to the blocking hosted CI Build job on PR #835. No provider-backed checks run. |
| 2026-07-18 | claude/clinical-kb-pwa-review-asi3wb (Phase 3, PR #872, final reviewed head ba46c1581a3c4e87d5d5989f3eb77483c9aa8aa5) | ba46c1581a3c4e87d5d5989f3eb77483c9aa8aa5 | PWA offline-page design upgrade (plan Phase 3) | Rebuilt the `public/offline.html` visual shell on mirrored Clinical White / Aegean Graphite tokens (each value annotated with its source token): pure-white canvas, aligned text/border/hover values, system UI font stack, and the clinical-accent focus ring replacing the off-contract amber. Privacy copy, structure, forced-colors behavior, safe-area insets, and target sizes unchanged. `CACHE_VERSION` bumped to the new unique `2026-07-18-v1` with the offline.html sha256 pairing updated — the Phase 1 binding guard exercised for real and enforced the paired move. A transient typecheck failure from stale `.next/dev` route types (cross-branch dev-server state) self-resolved after server regeneration; nothing was deleted. | Focused Vitest 55/55 including the binding guard on the new pairing. `verify:cheap` 2778 passed/1 failed and `verify:pr-local` unit stage identical — the lone failure is the known container-only `pdf-extraction-budget` artifact (clean-main baselined; hosted CI green on #826/#835). `test:e2e:pwa`: the cold-offline journey rendered and asserted the redesigned page through the new-version worker; sole installability error remains the container `in-incognito` artifact. `verify:ui` 219 passed/2 failed — the same two clean-main-baselined container artifacts, no new failures. Build/bundle stages deferred to the blocking hosted CI Build job. No provider-backed checks run. |
| 2026-07-18 | codex/rag-merge-final-20260718-655a | 20e5964bbfdcac0311b89c96931a43544be545a6 | RAG recovery, grounding, and latency merge closure | Reviewed the recovered historical RAG fix series against fresh `origin/main`. No additional source change was needed: current main already contains the stricter source-scoped numeric grounding, blocked-retrieval-only extractive recovery, generic LAI deterministic recovery, per-case answer latency diagnostics, and agitation lexical-path protections. The only residual branch diff was proven unreachable because every medication-chart trigger yields explicit search terms; it was intentionally not carried forward. | Full local Vitest: 301 files / 2,779 tests passed. Offline RAG fixture and production-contract validation: 36 golden cases, 21 suites, 294 tests passed. Prettier and `git diff --check` passed. `verify:cheap` reached its lint stage after all preceding static guards passed, but was blocked twice by active heavyweight jobs in other registered worktrees; it was not retried. No Supabase, OpenAI, live retrieval, production-readiness, deployment, or hosted CI command was run. |
+| 2026-07-17 | codex/design-audit-20260716 | 47b58ddf95826231a6057b400e7f601c403a129d + reviewed working diff | exhaustive design, accessibility, UX, interaction, route, responsive, HTML/CSS/JS/TSX, and test-coverage audit with remediation | No P0. Fixed two P1 trust/responsive defects and the confirmed P2/P3 set: false Favourites provenance/demo leakage/dead controls, Therapy phone reflow/load recovery/contrast, semantic tabs/search/filters, error focus/theme, deterministic Forms back navigation, honest unavailable actions, application dialog semantics, duplicate differential keys, skip-link target, Playwright project isolation, and route coverage. External visual-target fidelity remains unavailable. | Static 261-file/~67,944-line inventory; independent combined-diff review; focused Vitest 21/21; jsdom 24/24; architecture 6/6; accessibility browser 5/5; focused route/browser recovery; lint; TypeScript; runtime/workflow/sitemap/brand/type/icon checks; production build with 1,043 pages and client-secret scan; `git diff --check`. Canonical aggregate Vitest was Windows-runner inconclusive and full UI was not repeated after focused remediation. No provider/API checks. |
| 2026-07-18 | codex/main-merge-51278-final-20260718-late | 45fa3c6c7, 14a0a898c | merge integration of 51278a70d onto fresh origin/main | Replayed the requested historical design-audit commit onto fresh `origin/main`. Kept current-main versions for five conflicts, including the regenerated drift manifest and current schema assertions. Fixed the duplicate sitemap-generator declaration, corrected redirect-section coverage, and restored the current `Clinical Guide` UI contract. | `git diff --check` and `npm run sitemap:check` passed. `npm run test` was attempted twice but blocked by the repository-wide heavy-command lock held by a separate Playwright worktree; no provider-backed checks ran. |
| 2026-07-18 | origin/main framework and dependency modernization snapshot | 4057677c8b92a5e1d997ec44958764fa91f5d424 | parallel build/infra, backend, and frontend modernization audit | Changes requested. No P0. Confirmed two P1 defects: Supabase SSR 0.12 auth-cookie responses discard mandatory anti-cache headers, and reindex bypasses the server-only-aware TSX runner after mutation-capable setup. Five P2 blockers cover the Webpack-to-Turbopack production cutover, incomplete Railway image-build watch ownership, missing clean `next typegen`, Node 26 types over a Node 24 runtime, and App Router retry actions that reset without re-fetching. P3 removal-readiness debt remains in Zod and Next Image APIs. Manual rewrite zones are auth response ownership, bundler/CSP/artifact consumers, JSZip resource limits, OpenAI request typing, and React Compiler adoption in the stateful dashboard/viewer roots. | Parallel read-only source/config/test audit against the exact snapshot; Node 24.18.0/npm 11.17.0; exact-version Next 16.2.10 bundled upgrade, Turbopack, error-boundary, and codemod guidance; TypeScript 6 backend no-emit analysis and Node import probes via a separately installed exact-version local dependency tree; `git diff --check`. No install, registry outdated/audit, full repo lint/typecheck/test/build/browser/Docker, Supabase/OpenAI, deployment, or hosted CI run; this worktree had no `node_modules`. |
| 2026-07-18 | claude/clinical-kb-pwa-review-asi3wb (PR #890, plan Phase 4; single-batch implementation+ledger commit — Phase 3 landed as squash 44a4c511bc1381168474794d6f89273564659ead) | ceabc04d75fd0cea2a120d504418d44edd704bfb | App-wide performance pass: audit-then-fix + budget ratchet (plan Phase 4) | Audit on post-#872 main: enforced gzip budget +3.13% over the 1,363,382-byte baseline; analyzer treemap showed pdfjs-dist (123 KB) and cross-mode-differentials data (121 KB) already correctly lazy, and disproved the suspected forms-catalog dashboard leak (type-only import). Confirmed one real defect: the 143-line `/services` client home page value-imported `defaultServiceSlug` from `@/lib/services`, compiling the ~915 KB services snapshot (~100 KB gzip) into its route chunk. Fixed by computing the slug in the server page (`src/app/services/page.tsx`) and passing it as a prop; the client component builds its task cards from the prop. Measured result: budget swung from +3.13% to −3.97%; baseline ratcheted down 1,363,382 → 1,309,286 bytes gzip so CI locks the win. pdfjs/differentials/#718 paths deliberately untouched per audit rules. Two transient `.next/dev` generated-type corruptions from the long-lived dev server were resolved by stopping the server and setting the generated dir aside (reversible); nothing hand-deleted. | Build + `check:bundle-budget --json` before/after (artifacts in session scratchpad); `check:bundle-budget -- --update` for the ratchet; `npm run test` 2789 passed/1 failed (known container-only `pdf-extraction-budget` artifact, hosted-CI-green through #826/#835/#872); `verify:cheap` green to the same artifact; `verify:ui` 219 passed/2 failed (the two long-established container artifacts; ui-tools spec covering the services surface passed); `verify:pr-local` unit stage identical; typecheck/lint/format clean. Lighthouse not run (dev-server churn; bundle evidence sufficed for this fix set). No provider-backed checks run. |
+| 2026-07-18 | PR #871 / codex/design-audit-final-pr-20260718 | bb85b546e + ledger closeout | final current-main design/accessibility audit integration, hosted review resolution, and PR-readiness review | No remaining high-confidence P0-P2 defect after current-main reconciliation, two independent read-only reviews, and remediation of every confirmed review finding. The follow-ups made client demo state fail closed in production for both prototype items and set suggestions, separated local no-auth upload capability from Favourites demo treatment, kept unavailable Favourites controls focusable with accessible reasons, restored visible skip-target focus, limited Favourites selection to the wide layout that exposes its workspace, aligned upload/index semantics with each responsive rendering mode, exposed filtered Tools results as a labelled group, and kept Therapy Compass in an honest loading state until its catalogue resolves. The audit also distinguishes completed browser assertions from an incomplete valid document-source redirect case. External design-target fidelity remains unverified without an approved target. | Canonical local PR verification completed through runtime, changed-file formatting, full ESLint, TypeScript, full Vitest, webpack production build/client-secret scan, and offline RAG fixtures. Focused Therapy, navigation/auth, demo-boundary, and unavailable-control regressions passed after correcting one test-order issue; the final demo/upload boundary selection passed 4/4; scoped zero-warning ESLint, changed-file formatting, and `git diff --check` passed. The full local Chromium sweep completed 236/237 with one hydration-timing failure: the app-mode test clicked before React attached its handler. The existing handler-readiness pattern was applied; focused rerun attempts were then lock-blocked by another registered worktree, so exact-head hosted Chromium remains the required proof. Initial hosted checks, including Production UI, passed before these final follow-ups. No OpenAI, Supabase, production-data, deployment, or live clinical workflow ran. |
diff --git a/docs/design-audit-2026-07-17.md b/docs/design-audit-2026-07-17.md
new file mode 100644
index 000000000..1c1fd1054
--- /dev/null
+++ b/docs/design-audit-2026-07-17.md
@@ -0,0 +1,104 @@
+# Design, accessibility, and interaction audit — 2026-07-17
+
+## Outcome
+
+The repository-wide design audit is complete. The implementation pass fixed the two P1 findings, the confirmed P2/P3 design and interaction defects, and three defects found by an independent adversarial review of the combined diff. No P0 was found.
+
+This pass deliberately built on the 2026-07-15 live design audit instead of repeating it. The earlier fixes for phone scroll ownership, app-mode Tab dismissal, decorative icon semantics, reduced-motion press feedback, Sheet backdrop tokens, and forced-colour tokens were treated as resolved.
+
+## Scope and method
+
+- Static line-level inventory: 261 user-facing TSX/CSS files under `src/app` and `src/components`, approximately 67,944 lines.
+- Route and interaction inventory: 37 rendered/redirect route families and approximately 410 actionable controls.
+- Parallel reviews: static product design, accessibility/UX, interaction/test coverage, plus an independent combined-diff review.
+- Live proof: local demo-mode Next.js app only, with external requests blocked or provider variables removed.
+- Breakpoints exercised by this and the inherited audit evidence: 320, 390, 639, 768, 1280/1440, 1536, and 1920 CSS pixels.
+- Source visual target: unavailable. The existing product design system was the consistency baseline; this audit cannot certify pixel fidelity to an external Figma or approved mockup that was not supplied.
+
+## Findings and fixes
+
+| ID | Severity | Detailed issue and user impact | Implemented solution | Principal files |
+| ------ | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| DQA-01 | P1 | Favourites rendered the same acamprosate evidence and lithium note beneath unrelated selected items, creating false item-level provenance. | Evidence and notes now derive from the selected item; absent content has an explicit honest empty state. Copy actions use the item citation and return accessible status. | `favourites-command-library-page.tsx`, `ui-smoke.spec.ts` |
+| DQA-02 | P1 | Therapy Compass used fixed desktop grid tracks wider than a phone while the global shell clipped page overflow, making several production screens unreachable at 320–390 px. | Added semantic responsive layout classes, one-column phone reflow, wrapping actions/metrics, and a contract test across all Therapy Compass screens. | `therapy-compass/*`, `therapy-compass-responsive-contract.test.ts` |
+| DQA-03 | P2 | White text/icons on the dark clinical accent measured materially below accessible contrast and bypassed the existing contrast token. | Replaced hard-coded white foregrounds with `--clinical-accent-contrast`, including answer status and Therapy Compass controls. | `answer-status.tsx`, `therapy-compass/*` |
+| DQA-04 | P2 | Prototype favourites appeared as genuine saved user content in normal mode, including item and set suggestions through universal search; an unconfigured browser auth client could also fail open to demo state in production. | Gated fixture items and sets behind one production-safe demo decision across the direct server route and client shells. Auth-unavailable fallback is non-production only, local no-auth remains consistent, and explicit production demo opt-in is retained. Normal mode shows only real saved items. | `client-env.ts`, `favourites/page.tsx`, `ClinicalDashboard.tsx`, `favourites-hub.tsx`, `global-search-shell.tsx`, `master-search-header.tsx`, `universal-search-command-surface.tsx` |
+| DQA-05 | P2 | Favourites exposed invisible selection below `2xl`, nested/synthetic mobile card controls, no-op edit/sort actions, incomplete menu keyboard behavior, clipboard focus loss, and title-only reasons on unfocusable unavailable controls. | Kept explicit native links and separate buttons on mobile, limited selection to the visible workspace, implemented real citation copy with status/focus restoration and complete menu keyboard behavior, and made unfinished actions honestly `aria-disabled`, focusable, and accessibly described. | `favourites-command-library-page.tsx`, `favourites-hub.tsx`, `favourites-hub-unavailable-controls.dom.test.tsx` |
+| DQA-06 | P2 | Differential presentation controls advertised editing, filtering, reorder/remove behavior, and a fixed `+2` count that did not exist. | Removed false instructions, derived the remaining count from state, and disabled unfinished controls with availability explanations while preserving the read-only comparison. | `differential-presentation-workflow-page.tsx` |
+| DQA-07 | P2 | Services selection led to enabled-looking Edit/Review/View controls that did nothing, while Compare stayed unavailable without an accurate reason. A later diff briefly disabled the real Clear action. | Removed the false actions and restored Clear. During current-main integration, the later functional checklist, confidence-detail, and selected-service comparison controls were preserved instead of replacing them with disabled placeholders. | `services-navigator-page.tsx`, `ui-smoke.spec.ts` |
+| DQA-08 | P2 | Evidence records with no URL were still keyboard-focusable `href="#"` links announced as “Open source”. | Missing-source rows now render as non-links with unavailable semantics; only valid destinations render a Link. | `visual-evidence.tsx`, `visual-evidence-tabs.dom.test.tsx` |
+| DQA-09 | P2 | Therapy cards presented an enabled Favourite button with no handler or state change. | The unavailable feature is now disabled and labelled as coming soon, preventing false save confirmation. | `therapy-card.tsx` |
+| DQA-10 | P2 | Route/global error fallbacks did not reliably move focus or announce a route failure; the global fallback was hard-coded light-only. | Added programmatic heading focus and alert announcement, and made the self-contained global fallback system-colour, dark-mode, and forced-colour aware. | `route-error-boundary.tsx`, `global-error.tsx`, route error tests |
+| DQA-11 | P2 | Clinical Notes, Visual Evidence, and upload/index tab interfaces lacked complete roving keyboard behavior and reciprocal tab/panel relationships. | Added stable unique IDs, `aria-controls`/`aria-labelledby`, roving `tabIndex`, and Left/Right/Home/End auto-activation. Upload/indexing uses tab panels only with its visible mobile tablist and named regions when desktop renders every section. | `ClinicalDashboard.tsx`, `answer-result-surface.tsx`, `visual-evidence.tsx`, UI/DOM tests |
+| DQA-12 | P2 | Universal search visually highlighted an item without exposing it through `aria-activedescendant`. | The combobox now points to the active option and tests verify the relationship through keyboard navigation. | `master-search-header.tsx`, `universal-search-command-surface.tsx`, `ui-universal-search.spec.ts` |
+| DQA-13 | P2 | Differential filters and several selector groups behaved as toggles but lacked grouped/pressed semantics; the Tools result set retained orphaned tab-panel semantics after its controls became pressed filters. | Added labelled groups and stateful `aria-pressed` semantics, and exposed Tools results as a labelled group, with browser accessibility assertions. | `differentials-home.tsx`, `evidence-panels.tsx`, `applications-launcher-page.tsx`, `ui-accessibility.spec.ts`, `ui-tools.spec.ts` |
+| DQA-14 | P2 | Therapy Compass silently swallowed data-load failure, rendered an empty `0`-record catalogue while loading, and still implied a fabricated `200+` catalogue count. | Added distinct loading and failure states, a Retry action, removed fabricated totals, and retained real successful/empty states. The final integration tests the routed workspace that replaced the legacy single-page wrapper. | `use-therapy-data.ts`, `workspace.tsx`, `home-screen.tsx`, `therapy-compass-data-recovery.dom.test.tsx` |
+| DQA-15 | P2 | Direct-entry Forms “Back to forms” used browser history and could leave the application. | The control now deterministically navigates to `/forms?focus=1`; a DOM regression test verifies the destination. | `form-detail-page.tsx`, `forms-back-navigation.dom.test.tsx` |
+| DQA-16 | P2 | Firefox/WebKit production projects unintentionally collected advisory `@mockup` tests; two browser helpers also retried hydration inconsistently. | Applied production matchers and `grepInvert` to all required projects and introduced one shared app-mode hydration retry helper. | `playwright.config.ts`, `playwright-app-mode.ts`, `ui-stress.spec.ts`, `ui-tools.spec.ts` |
+| DQA-17 | P2 | Application/tool cards looked like direct links but prevented navigation to open an internal detail state, obscuring the real action. | Cards are now honest dialog buttons with `aria-haspopup="dialog"`; the dialog contains the actual destination link. | `applications-launcher-page.tsx`, `ui-smoke.spec.ts` |
+| DQA-18 | P2 | Differential diagnosis streams keyed repeated cards only by visible title, producing React duplicate-key errors and unstable list identity. | Cards now use a stable href/index composite key; the route matrix listens for console errors. | `differential-stream-page.tsx`, `ui-route-coverage.spec.ts` |
+| DQA-19 | P2 | The colour-reference skip link targeted `#main-content`, but the route had no matching focus target; app-shell targets also suppressed their focus outline. | Added canonical focusable main-content targets with an explicit visible focus outline and browser proof of both focus transfer and computed outline style. | `reference/colour-coding/page.tsx`, `ClinicalDashboard.tsx`, `global-search-shell.tsx`, `ui-route-coverage.spec.ts` |
+| DQA-20 | P3 | Answer sheets overrode the semantic backdrop token and duplicate mobile CSS retained obsolete layout overrides. | Removed call-site backdrop overrides and redundant CSS so theme, forced-colour, and responsive behavior come from the shared tokens/layout rules. | `answer-result-surface.tsx`, `globals.css`, `ui-overlay-css-contract.test.ts` |
+| DQA-21 | P2 | Route-handler redirects inherited the production server's `0.0.0.0` bind origin, so Chromium rejected Applications, Medications, and differential-presentation redirects with `ERR_ADDRESS_INVALID`. | Return same-origin relative `Location` headers, preserving allowed query state without leaking the server bind address into browser navigation. | `applications/route.ts`, `medications/route.ts`, `differentials/presentations/route.ts`, route tests |
+| DQA-22 | P2 | Local no-auth mode reused the broad Favourites demo flag for uploads, so a development session with working private upload APIs incorrectly presented the upload workspace as read-only. | Added a dedicated upload-read-only resolver that retains explicit demo and unavailable-auth lockout while excluding local no-auth treatment; focused behavior and source contracts protect the boundary. | `client-env.ts`, `ClinicalDashboard.tsx`, `favourites-demo-boundary.test.ts`, `audit-navigation-auth-regressions.test.ts` |
+
+## Route and component interaction proof
+
+The new provider-free route matrix covers Therapy Compass, DSM home/compare/differentials, Specifier compare/map, differential diagnosis stream/detail, colour reference, Applications, Medications and differential-presentation redirects, and the invalid document-source alias at desktop and 390 px. It asserts visible primary content, no document-level horizontal overflow, a representative action, blocked external/API leakage, and route-specific behavior. The valid `/documents/source` case reached the expected redirect request but did not complete its final browser assertion, as recorded below.
+
+Additional focused browser proof covered:
+
+- Clinical Notes roving tabs and universal-search active descendant behavior.
+- Favourites desktop workspace, item-specific evidence/notes, menu keyboard/copy/focus restoration, and native mobile link/menu separation.
+- Applications detail-dialog semantics and real destination link.
+- Tools mobile/desktop navigation and detail interactions.
+- Differential comparison and the differential stream/detail console-error regression.
+- Reduced motion, forced colours, 200% zoom, and axe WCAG A/AA in normal and forced-colour modes.
+
+The Services control test rendered the correct page and retained a screenshot showing the selected rail and working Clear action. Its assertion was incorrectly scoped to a nonexistent test ID; that test now uses the semantic `main` root. The final integration also preserves current main's functional checklist, confidence-detail, and selected-service comparison controls. Per the recovery instruction, the earlier audit test was not launched a third time after two failed attempts (the first was runner/port contention, the second exposed the selector defect).
+
+The valid `/documents/source` browser case issued the correct destination request but the cold document-detail compile (about 24 seconds plus source render) exceeded its 30-second browser poll. The exact local response contains `NEXT_REDIRECT;replace;/documents/11111111-1111-4111-8111-111111111111?page=2&chunk=safety+plan;307;`. The test allowance is now 60 seconds, but the same browser action was not retried a third time.
+
+## Verification results
+
+Passed:
+
+- `npm run build`: webpack production build compiled; TypeScript passed; 1,043/1,043 static pages generated; client-bundle secret scan passed.
+- `npm run typecheck`.
+- `npm run lint`.
+- Runtime, GitHub Actions pin, sitemap, brand, strict type-scale, and strict icon-scale checks.
+- Focused changed-surface Vitest: 9 files, 21/21 tests.
+- Full jsdom project through the Windows worker-thread fallback: 10 files, 24/24 tests.
+- Architecture boundary isolation: 6/6, including no runtime import cycles.
+- Accessibility media/axe browser suite: 5/5.
+- Focused route recovery: Specifier map 1/1; differential stream/detail 1/1; colour reference plus Applications, Medications, and invalid evidence alias 4/4.
+- `git diff --check` before final documentation.
+
+Broad-gate limitations:
+
+- The canonical `npm run verify:cheap` reached the unit phase but Windows repeatedly failed to start Vitest fork workers. The worker-thread fallback exposed only the architecture scan exceeding the global 30-second timeout; that exact file passed 6/6 in isolation with diagnostic headroom. A later aggregate JSON run was terminated before writing its result. The changed-surface and jsdom suites are green, but the canonical aggregate unit command is not recorded as green.
+- The first current-branch `npm run verify:ui` pass was 177/182. Each identified product/test issue was fixed and rerun narrowly; the full suite was not repeated after recovery to avoid repeating the large gate. The inherited prior design branch baseline remains 175/175.
+- No OpenAI, Supabase, GitHub/GitLab, hosted CI, production-like, or paid-provider workflow was run. Provider variables were removed from local verification commands.
+
+## Residual decisions and risk
+
+- External design-target fidelity remains unprovable until an approved Figma file or screenshot set is supplied.
+- Therapy favourite persistence and differential column editing remain intentionally unavailable. They now present disabled or read-only states instead of false actions; Services comparison/details are functional in the final current-main integration.
+- Live authenticated data, provider failure behavior, and production clinical workflows remain outside this offline design audit and require explicit authorization before testing.
+- No dependency, API contract, database schema, production data, or environment file was changed.
+
+## Audit execution state
+
+- Branch: `codex/design-audit-20260716`
+- Isolated worktree: `C:\Dev\Apps\Database\worktrees\design-audit-20260716`
+- Base HEAD: `47b58ddf95826231a6057b400e7f601c403a129d`
+- The audit and verification finished before Git handoff; its reviewed diff is carried forward from this isolated worktree onto the final PR branch.
+- No deployment or provider-backed call was made during the audit.
+
+## Final PR integration verification (2026-07-18)
+
+- Final branch/worktree: `codex/design-audit-final-pr-20260718` in `C:\Dev\Apps\Database\worktrees\design-audit-final-pr-20260718`.
+- The current-main merge preserved the routed Therapy workspace, functional Services checklist/confidence/comparison controls, and dialog-first tool cards. Stale tests for the removed legacy wrappers/placeholders were reconciled without restoring inaccessible or false UI.
+- The local PR plan passed runtime, changed-file formatting, full ESLint, TypeScript, 309 Vitest files / 2,797 tests, a webpack production build with 1,674 generated pages, client-bundle secret scanning, and 36 offline RAG golden fixtures across 21 suites. The build was rerun narrowly after an empty `NEXT_PUBLIC_DEMO_MODE` test-shell value was removed; no source change was required for that environment-only failure.
+- The exact-branch Chromium run passed 230/237 tests on its first pass. Focused production recovery passed Therapy navigation and all three relative redirect journeys; Services and Tools then passed against the identity-verified provider-free branch server. The guest upload journey was proven in production through the Source Library and exact admin-only notice; its final strict alert locator was narrowed to exclude Next's empty route announcer. A later full sweep passed 236/237; the sole failure clicked the app-mode trigger before React attached its handler, so the test now uses the existing handler-readiness guard. Two focused rerun attempts were shared-lock blocked, making hosted exact-head UI the final confirmation.
+- No OpenAI, Supabase, production-data, deployment, or live clinical workflow was invoked. Browser/API fixtures used the repository's offline environment and blocked external requests.
diff --git a/playwright.config.ts b/playwright.config.ts
index 0667d8acf..64f10400f 100644
--- a/playwright.config.ts
+++ b/playwright.config.ts
@@ -10,16 +10,17 @@ const chromiumExecutablePath = process.env.PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH;
// Prototype /mockups journeys live in their own advisory project so a red
// mockup can never mask a production-journey regression (PT-05). The two
// Tag-level filters keep production and prototype journeys disjoint even when
-// they share a spec file.
+// they share a spec file. Every required browser project uses the same
+// production matcher and tag exclusion.
const productionSpecPattern =
- /.*(?:answer-progress-ui-smoke|ui-(smoke|stress|accessibility|tools|overlap|universal-search|specifiers|formulation|pwa))\.spec\.ts/;
+ /.*(?:answer-progress-ui-smoke|ui-(smoke|stress|accessibility|tools|overlap|universal-search|specifiers|formulation|pwa|route-coverage))\.spec\.ts/;
const mockupSpecPattern = /.*ui-(tools|tools-collapse|tools-task-directory)\.spec\.ts/;
const mockupTag = /@mockup/;
export default defineConfig({
testDir: "./tests",
testMatch:
- /.*(?:answer-progress-ui-smoke|ui-(smoke|stress|accessibility|tools|tools-collapse|tools-task-directory|overlap|universal-search|specifiers|formulation|pwa))\.spec\.ts/,
+ /.*(?:answer-progress-ui-smoke|ui-(smoke|stress|accessibility|tools|tools-collapse|tools-task-directory|overlap|universal-search|specifiers|formulation|pwa|route-coverage))\.spec\.ts/,
timeout: 60_000,
retries: 0,
// Fail the run if a stray `test.only` is committed: otherwise it silently
diff --git a/src/app/applications/route.ts b/src/app/applications/route.ts
index 0f19d2c8c..e934c3103 100644
--- a/src/app/applications/route.ts
+++ b/src/app/applications/route.ts
@@ -1,11 +1,12 @@
-import { type NextRequest, NextResponse } from "next/server";
+import { type NextRequest } from "next/server";
// "Tools" is the canonical name and /tools the canonical route (PT-11). A
// route handler redirects the incoming legacy request before React renders it.
export function GET(request: NextRequest) {
- const destination = request.nextUrl.clone();
- destination.pathname = "/tools";
- return NextResponse.redirect(destination);
+ return new Response(null, {
+ status: 307,
+ headers: { Location: `/tools${request.nextUrl.search}` },
+ });
}
export const HEAD = GET;
diff --git a/src/app/favourites/page.tsx b/src/app/favourites/page.tsx
index 6048c35e0..eb3ff4715 100644
--- a/src/app/favourites/page.tsx
+++ b/src/app/favourites/page.tsx
@@ -1,4 +1,6 @@
import { FavouritesCommandLibraryPage } from "@/components/clinical-dashboard/favourites-command-library-page";
+import { resolveClientDemoMode } from "@/lib/client-env";
+import { isDemoMode, isLocalNoAuthMode } from "@/lib/env";
type FavouritesPageProps = {
searchParams?: Promise<{
@@ -13,8 +15,13 @@ function firstSearchParam(value: string | string[] | undefined) {
export default async function FavouritesPage({ searchParams }: FavouritesPageProps) {
const params = searchParams ? await searchParams : {};
const query = firstSearchParam(params.q)?.trim() ?? "";
+ const demoMode = resolveClientDemoMode({
+ explicitDemoMode: isDemoMode(),
+ authUnavailableFallback: false,
+ localNoAuthMode: isLocalNoAuthMode(),
+ });
// No key={query} remount: query is a pure prop, and remounting on query
// change wiped the set/type/view/sort selections when clearing a search.
- return ;
+ return ;
}
diff --git a/src/app/global-error.tsx b/src/app/global-error.tsx
index aed84dad6..157a1b45c 100644
--- a/src/app/global-error.tsx
+++ b/src/app/global-error.tsx
@@ -14,7 +14,7 @@ export default function GlobalError({ error, reset }: { error: Error & { digest?
const headingRef = useRef(null);
useEffect(() => {
console.error("Fatal error captured by global-error boundary:", error);
- headingRef.current?.focus();
+ headingRef.current?.focus({ preventScroll: true });
}, [error]);
return (
@@ -27,6 +27,7 @@ export default function GlobalError({ error, reset }: { error: Error & { digest?
alignItems: "center",
justifyContent: "center",
padding: "1rem",
+ colorScheme: "light dark",
backgroundColor: "Canvas",
color: "CanvasText",
fontFamily:
@@ -68,11 +69,11 @@ export default function GlobalError({ error, reset }: { error: Error & { digest?
style={{
margin: "0 0 1.25rem",
borderRadius: "0.5rem",
- backgroundColor: "Canvas",
+ backgroundColor: "Field",
padding: "0.5rem",
fontFamily: "ui-monospace, SFMono-Regular, Menlo, Consolas, monospace",
fontSize: "0.75rem",
- color: "CanvasText",
+ color: "FieldText",
wordBreak: "break-all",
}}
>
diff --git a/src/app/globals.css b/src/app/globals.css
index d991a1ba1..be324e945 100644
--- a/src/app/globals.css
+++ b/src/app/globals.css
@@ -1159,7 +1159,6 @@ summary::-webkit-details-marker {
width: 1.1rem;
}
}
-
@media (prefers-reduced-motion: no-preference) {
.mode-action-surface[data-placement="up"] {
animation: mode-action-fold-up 170ms cubic-bezier(0.22, 1, 0.36, 1) both;
diff --git a/src/app/medications/route.ts b/src/app/medications/route.ts
index c7ad52d16..5ebeac9a8 100644
--- a/src/app/medications/route.ts
+++ b/src/app/medications/route.ts
@@ -1,7 +1,8 @@
-import { type NextRequest, NextResponse } from "next/server";
-
-export function GET(request: NextRequest) {
- return NextResponse.redirect(new URL("/?mode=prescribing", request.url));
+export function GET() {
+ return new Response(null, {
+ status: 307,
+ headers: { Location: "/?mode=prescribing" },
+ });
}
export const HEAD = GET;
diff --git a/src/app/reference/colour-coding/page.tsx b/src/app/reference/colour-coding/page.tsx
index cb248a1dc..d5e0a946e 100644
--- a/src/app/reference/colour-coding/page.tsx
+++ b/src/app/reference/colour-coding/page.tsx
@@ -31,7 +31,14 @@ const TONE_SAMPLE_LABEL: Record<(typeof SEMANTIC_TONES)[number], string> = {
export default function ColourCodingReferencePage() {
return (
-
+