diff --git a/docs/site-map.md b/docs/site-map.md
index 6602ceb5ad..407744edab 100644
--- a/docs/site-map.md
+++ b/docs/site-map.md
@@ -1148,6 +1148,7 @@ This file is generated by `npm run docs:update` (or `npm run sitemap:update` dir
- `/mockups/accessible-table-browser-fixture` - Route discovered from app directory Source: `src/app/mockups/accessible-table-browser-fixture/page.tsx`.
- `/mockups/also-matches-accents` - Route discovered from app directory Source: `src/app/mockups/also-matches-accents/page.tsx`.
+- `/mockups/answer-chat-redesign` - Route discovered from app directory Source: `src/app/mockups/answer-chat-redesign/page.tsx`.
- `/mockups/answer-evidence-popups` - Route discovered from app directory Source: `src/app/mockups/answer-evidence-popups/page.tsx`.
- `/mockups/answer-home-proposal` - Route discovered from app directory Source: `src/app/mockups/answer-home-proposal/page.tsx`.
- `/mockups/calculators-bedside-sheet` - Route discovered from app directory Source: `src/app/mockups/calculators-bedside-sheet/page.tsx`.
diff --git a/src/app/mockups/answer-chat-redesign/page.tsx b/src/app/mockups/answer-chat-redesign/page.tsx
new file mode 100644
index 0000000000..95539b94e1
--- /dev/null
+++ b/src/app/mockups/answer-chat-redesign/page.tsx
@@ -0,0 +1,12 @@
+import type { Metadata } from "next";
+
+import { AnswerChatRedesignMockups } from "@/components/answer-chat-redesign-mockups";
+
+export const metadata: Metadata = {
+ title: "Answer chat redesign mockups - Clinical KB",
+ description: "Three ChatGPT-style directions for the Answer result, with distinct citation treatments.",
+};
+
+export default function AnswerChatRedesignMockupRoute() {
+ return ;
+}
diff --git a/src/app/mockups/mockups-layout-client.tsx b/src/app/mockups/mockups-layout-client.tsx
index 010a9f93fe..2b50b3005a 100644
--- a/src/app/mockups/mockups-layout-client.tsx
+++ b/src/app/mockups/mockups-layout-client.tsx
@@ -59,6 +59,10 @@ export function MockupsLayoutClient({ children }: { children: ReactNode }) {
// sit on top of a study about results-card identity.
const isAlsoMatchesAccentMockup = pathname === "/mockups/also-matches-accents";
const isAnswerHomeProposalMockup = pathname === "/mockups/answer-home-proposal";
+ // Draws its own Answer chrome, thread, citations and composer inside every
+ // device frame. Shared mockup chrome would read as a second, real search bar
+ // over a study whose subject is the chat itself.
+ const isAnswerChatRedesignMockup = pathname === "/mockups/answer-chat-redesign";
// Draws its own sticky chrome + device frames for /privacy; shared shell would
// read as a second real header over the study.
const isPrivacyPageDirectionsMockup = pathname === "/mockups/privacy-page-directions";
@@ -131,6 +135,7 @@ export function MockupsLayoutClient({ children }: { children: ReactNode }) {
!isWarningLineMockup &&
!isAlsoMatchesAccentMockup &&
!isAnswerHomeProposalMockup &&
+ !isAnswerChatRedesignMockup &&
!isPrivacyPageDirectionsMockup &&
!isPrivacyLiveSignalPerfectedMockup &&
!isSearchLensMenuMockup &&
@@ -157,6 +162,7 @@ export function MockupsLayoutClient({ children }: { children: ReactNode }) {
!isWarningLineMockup &&
!isAlsoMatchesAccentMockup &&
!isAnswerHomeProposalMockup &&
+ !isAnswerChatRedesignMockup &&
!isPrivacyPageDirectionsMockup &&
!isPrivacyLiveSignalPerfectedMockup &&
!isSearchLensMenuMockup &&
diff --git a/src/components/answer-chat-redesign-mockups.tsx b/src/components/answer-chat-redesign-mockups.tsx
new file mode 100644
index 0000000000..3547368462
--- /dev/null
+++ b/src/components/answer-chat-redesign-mockups.tsx
@@ -0,0 +1,854 @@
+"use client";
+
+// Design-scratch: the Answer RESULT after a question has returned — ChatGPT-style
+// thread, three citation treatments. Does not change production retrieval, ranking,
+// or the live answer card. Shared mockup chrome is suppressed for this route
+// (`src/app/mockups/mockups-layout-client.tsx`) because every frame draws its own
+// Answer top bar and docked composer.
+
+import Link from "next/link";
+import { useMemo, useState, type ReactNode } from "react";
+import {
+ Check,
+ ChevronDown,
+ Copy,
+ ExternalLink,
+ FileText,
+ Menu,
+ MessageSquareText,
+ Plus,
+ RefreshCw,
+ Send,
+ ShieldAlert,
+ X,
+} from "lucide-react";
+
+import { cn } from "@/components/ui-primitives";
+
+const PRIVACY_LINE = "Do not enter patient-identifiable information.";
+const PRIVACY_LINK = "Privacy and data processing";
+
+const focusRing =
+ "focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[color:var(--focus)]";
+
+type Device = "phone" | "desktop";
+type DirectionId = "simple" | "sophisticated" | "perfected";
+type SourceStatus = "current" | "review-due";
+
+type Source = {
+ id: number;
+ title: string;
+ locator: string;
+ status: SourceStatus;
+ quote: string;
+ reviewed: string;
+};
+
+const QUESTION = "When can weekly clozapine FBCs move to monthly, and what neutrophil threshold applies?";
+
+const FOLLOW_UP = "What if the ANC is 1.4?";
+
+const SOURCES: Source[] = [
+ {
+ id: 1,
+ title: "WA Clozapine Protocol 2024",
+ locator: "p. 14 · Monitoring schedule",
+ status: "current",
+ quote:
+ "After 18 weeks of weekly full blood counts with ANC remaining at or above 1.5 × 10⁹/L, monitoring may move to monthly.",
+ reviewed: "Reviewed Mar 2026",
+ },
+ {
+ id: 2,
+ title: "Haematology monitoring table",
+ locator: "Table 2 · Neutrophil thresholds",
+ status: "current",
+ quote:
+ "Green zone: ANC ≥ 1.5 × 10⁹/L — continue and, after 18 weeks, monthly FBC is permitted. Amber: 1.0–1.49 — increase frequency; do not extend the interval.",
+ reviewed: "Reviewed Jan 2026",
+ },
+ {
+ id: 3,
+ title: "Clozapine shared-care checklist",
+ locator: "p. 3 · Dispensing gate",
+ status: "review-due",
+ quote:
+ "The GP or nominated prescriber must sight the latest valid blood result before authorising supply. Do not dispense on an overdue FBC.",
+ reviewed: "Review due",
+ },
+];
+
+const currentDefects = [
+ "The answer is a raised verified card (query echo, verification notice, support strength, footer) rather than an assistant message.",
+ "UserQuestionBubble exists, but the result path often uses AnswerCardQueryEcho — the page does not read as a conversation.",
+ "Citations are a count capsule plus sheets. Claims in the prose have no numbered marks, so a reader cannot jump from a sentence to its source.",
+ "Verification, support, and degraded banners sit above the prose and compete with it, instead of living on the claim they qualify.",
+ "Evidence opens in drawers, so checking a reference leaves the reading position.",
+ "Prior turns can persist, but the current result still wears card chrome — two models on one page.",
+ "The composer is the universal search pill, not a docked chat input, so the page still feels like search-with-a-result.",
+];
+
+const directions: Array<{
+ id: DirectionId;
+ kicker: string;
+ title: string;
+ verdict: string;
+ description: string;
+ changes: string[];
+}> = [
+ {
+ id: "simple",
+ kicker: "Simple · ChatGPT-faithful",
+ title: "A message, not a card",
+ verdict: "Smallest change that reads as chat",
+ description:
+ "Right-aligned question, left-aligned prose, numbered pills in the sentence, quiet source chips under the message. Trust is a whisper. No support card, no verification banner, no evidence drawer.",
+ changes: [
+ "Drop AnswerCard chrome on the current turn — the assistant message is the surface.",
+ "Inline numbered pills are the only citation control; chips below repeat them for scanability.",
+ "A tap opens a quote preview in the thread, not a sheet over the page.",
+ "Composer docks as a chat pill. Privacy line stays verbatim under it.",
+ ],
+ },
+ {
+ id: "sophisticated",
+ kicker: "Sophisticated · Claim ↔ source",
+ title: "The sentence lights the source",
+ verdict: "Best for verification while reading",
+ description:
+ "Superscript citations highlight the supporting sentence. Desktop keeps a slim sources rail that lights the match; phone uses a sheet inside the frame. Hover and tap work both ways: rail to claim, claim to rail.",
+ changes: [
+ "Each cited sentence is a highlight target, not only the mark beside it.",
+ "Desktop rail shows currency (current / review due) beside the source — green and amber stay clinical, never decorative.",
+ "Phone sheet is framed, not a page-level modal, so the thread stays in view.",
+ "Follow-up chips sit above the composer, still inside the chat.",
+ ],
+ },
+ {
+ id: "perfected",
+ kicker: "Perfected · Never leave the chat",
+ title: "The source comes to the paragraph",
+ verdict: "The product direction if one ships",
+ description:
+ "A follow-up turn is already on screen. Tapping a footnote expands an inline source card under that paragraph (desktop) or a compact sheet (phone). A Sources strip at the end of the message mirrors the marks. Copy and regenerate stay ghosted under the assistant turn.",
+ changes: [
+ "No modal. The quote is an inline card in the reading flow, or a compact in-frame sheet on a phone.",
+ "End-of-message Sources strip expands the same records; hovering a mark also lights the strip.",
+ "A second turn shows the thread compounding, which today’s card replaces.",
+ "ChatGPT pill composer: plus, field, send. Privacy line unchanged.",
+ ],
+ },
+];
+
+function sourceById(id: number): Source {
+ const found = SOURCES.find((source) => source.id === id);
+ if (!found) {
+ throw new Error(`Unknown mock source ${id}`);
+ }
+ return found;
+}
+
+function StatusChip({ status }: { status: SourceStatus }) {
+ const current = status === "current";
+ return (
+
+ {current ? "Current" : "Review due"}
+
+ );
+}
+
+function CiteMark({
+ n,
+ variant,
+ active,
+ onActivate,
+ onHover,
+}: {
+ n: number;
+ variant: "pill" | "super" | "note";
+ active: boolean;
+ onActivate: (id: number) => void;
+ onHover?: (id: number | null) => void;
+}) {
+ const source = sourceById(n);
+ return (
+
+ );
+}
+
+function Claim({ active, children }: { active: boolean; children: ReactNode }) {
+ return (
+
+ {children}
+
+ );
+}
+
+function FrameTopBar({ device }: { device: Device }) {
+ return (
+
+ After 18 weeks of weekly full blood counts, monitoring may move to monthly{" "}
+ if the absolute neutrophil count
+ has stayed at or above 1.5 × 10⁹/L
+ . An ANC of 1.0–1.49 stays in the
+ amber band — increase frequency; do not extend the interval{" "}
+ . Before supply, the shared-care
+ checklist still requires the latest valid result to be sighted{" "}
+ .
+
+
+ {SOURCES.map((source) => (
+
+ ))}
+
+ {activeId ? onActivate(null)} /> : null}
+
+ 3 sources · 2 current · 1 review due. Verify doses and thresholds against the cited page.
+
+
+ Weekly FBC continues for the first 18 weeks of treatment, after which monthly monitoring is permitted when
+ counts have been stable
+
+ {" "}
+
+ The neutrophil threshold for that extension is ANC ≥ 1.5 × 10⁹/L. Below that, in the 1.0–1.49 band, the
+ interval must not be lengthened
+
+ {" "}
+
+ Shared-care still gates dispensing on a sighted, in-date result — this checklist is marked review due
+
+
+
+ An ANC of 1.4 sits in the amber band: increase monitoring frequency and do not extend to monthly
+ . Supply still
+ requires a sighted in-date result
+ .
+
+ 1.4 × 10⁹/L is amber, not green. Keep or increase FBC frequency; monthly is not permitted until
+ ANC is back at or above 1.5
+
+ . Do not authorise supply on an overdue result
+
+ .
+
+ Today’s Answer page is the centrepiece and still a verified document: AnswerResultSurface{" "}
+ stages an AnswerCard with query echo, verification notice, support strength, prose, a sources
+ capsule, and evidence sheets. Pieces of chat already exist (UserQuestionBubble, prior-turn
+ collapse) but the current result keeps card chrome, so the page does not read as a conversation. These three
+ frames keep the same clozapine-monitoring question and the same three sources. They change only how the
+ thread and the references are presented. Retrieval is untouched. {composerCount} composers, one per frame.
+