diff --git a/docs/redesign/02-design-direction.md b/docs/redesign/02-design-direction.md index 7cb72cd454..c11f097cac 100644 --- a/docs/redesign/02-design-direction.md +++ b/docs/redesign/02-design-direction.md @@ -1,5 +1,16 @@ # Design Direction — Clinical KB +## July 1 — Clinical White / Aegean Graphite (active direction) + +This supersedes the earlier "single teal accent for primary actions" principle. The colour system is now **role-split** rather than single-accent: + +- **Command = graphite.** Primary actions (New chat, primary CTAs, the mobile section FAB) use `--command` (`#111827` light / near-white `#F5F7F7` dark) — never teal/green. +- **Clinical accent = Aegean.** A cool blue-teal `--clinical-accent` (`#0B6F86` light / `#4CCFD0` dark) owns clinical identity only: selected mode, evidence/source rails, the composer send action, and focus. +- **Green = success only.** `--success` is reserved for ready/connected/complete; it is never brand, nav, command, send, or evidence. +- **True-white canvas.** The neutral ramp was de-blued to a true-neutral gray scale; the content surface is `#FFFFFF`, with `--surface-chrome` (`#F7F8FA`) for rails/header only. Light mode is de-glassed: flat surfaces + hairline borders + one restrained shadow; glass/blur is reserved for overlays. Dark mode keeps its black polish. + +Migration was token-led: `--primary*` now resolves to the Aegean accent, `--command*` is new, and legacy `--clinical-chat-teal*` / `--clinical-chat-ready` are retained as compat aliases pointing at the role tokens (`--clinical-accent` / `--success`). New code should reference the role tokens directly. Typography (Geist), spacing, radius, and motion are unchanged from below. See decision log **D11**. + ## June 20 scoped run The active direction for the dashboard and document viewer is a quiet clinical command instrument: neutral, precise, source-first. Teal remains reserved for primary action, evidence, and focus; dense operational details should collapse into progressive sheets/drawers on mobile rather than competing with the answer or PDF. diff --git a/docs/redesign/03-decision-log.md b/docs/redesign/03-decision-log.md index 2d8d6f1176..d19968b8f0 100644 --- a/docs/redesign/03-decision-log.md +++ b/docs/redesign/03-decision-log.md @@ -84,3 +84,10 @@ Entries are appended as work lands. Format: what changed / why better / consider **Why better:** The PDF regains priority on mobile when there is no citation to inspect, while source evidence remains discoverable and anchored for navigation. **Rejected:** Removing the evidence anchor entirely (would weaken navigation and tests); always showing the full card (kept the original hierarchy problem). **Verification:** Focused eslint and `npm run typecheck` pass; pinned evidence and PDF ordering are included in visual QA. + +## D11 — Clinical White / Aegean Graphite: role-split colour + +**What:** Split the overloaded accent into three roles. Added `--command` (graphite) for primary actions, `--clinical-accent` (Aegean blue-teal) for clinical identity (selected/evidence/send/focus), and reserved `--success` (green) for status only. De-blued the neutral ramp to true-neutral gray, set the content surface to `#FFFFFF` with a new `--surface-chrome` for rails/header, and de-glassed light-mode materials (flat + hairline + single shadow; glass kept for overlays). `--primary*` now resolves to the Aegean accent; `--clinical-chat-teal*`/`--clinical-chat-ready` retained as compat aliases pointing at the role tokens. +**Why better:** `--primary` previously drove both command buttons and evidence surfaces, so nothing read as deliberate. Roleization makes command vs clinical-identity vs success visually distinct, yields a crisper premium white, and keeps the black-polish dark mode. +**Rejected:** Keeping teal as the primary-action colour (accent keeps doing two jobs); a mass rename of the ~265 `--clinical-chat-teal` call-sites (unreviewable churn — aliases achieve the same end); a warm/cream canvas (the brief's premise; the real issue was blue-grey murk, not warmth). +**Verification:** `npm run typecheck` passes; dev server compiles and serves 200 with 0 console errors; light/dark desktop + mobile screenshots confirm graphite command, Aegean send/evidence, and success-only green; contrast spot-checks — Aegean on white ≈5.8:1, command ≈16:1, soft text ≈5.0:1, semantics ≥4.5:1. diff --git a/docs/redesign/05-changelog.md b/docs/redesign/05-changelog.md index 34b696d954..4d6ee42bb0 100644 --- a/docs/redesign/05-changelog.md +++ b/docs/redesign/05-changelog.md @@ -1,5 +1,22 @@ # Changelog — Premium Redesign +## July 1 — Clinical White / Aegean Graphite + +### Rebuild + +- **Role-split colour system:** graphite `--command` for primary actions, Aegean `--clinical-accent` for clinical identity (selected/evidence/send/focus), green `--success` for status only. Splits the previously overloaded `--primary`. See decision log **D11**, direction doc updated. +- **True-white canvas:** de-blued the neutral ramp to true-neutral gray; content surface `#FFFFFF` + new `--surface-chrome` for rails/header; light-mode materials de-glassed (flat + hairline + one shadow; glass kept for overlays). Dark mode keeps black polish, brightened Aegean accent. + +### Upgrade + +- **Command controls:** sidebar/header New chat and the mobile section FAB now read graphite; the composer send button reads Aegean. +- **Active states:** sidebar tool tiles, recent-chat, and the header mode menu use rail + icon + graphite label instead of broad teal fills. +- **Semantic hygiene:** medication match badge moved off hardcoded `emerald-*`/`blue-*` onto accent/info role tokens; status dots resolve to `--success`. + +### Verification + +- `npm run typecheck` passes; dev server serves 200 with 0 console errors; light/dark desktop + light mobile screenshots confirm the direction; contrast spot-checks pass (Aegean-on-white ≈5.8:1, command ≈16:1, semantics ≥4.5:1). `npm run verify:ui`/`verify:release` not yet run in this pass. + ## June 23 process hardening pass ### Upgrade diff --git a/src/app/globals.css b/src/app/globals.css index 19e53931b4..16b5ec8a39 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -25,6 +25,12 @@ --text-2xs--line-height: 1rem; --text-2xs--letter-spacing: 0.06em; + /* Font families: bind Tailwind's font-sans / font-mono to the loaded Geist + faces (variables set on by next/font). font-mono is used for + clinical codes and IDs (guideline refs, chunk/page numbers, versions). */ + --font-sans: var(--font-geist-sans), ui-sans-serif, system-ui, -apple-system, "Segoe UI", Arial, sans-serif; + --font-mono: var(--font-geist-mono), ui-monospace, "SFMono-Regular", "SF Mono", Menlo, Consolas, monospace; + --ease-out-soft: cubic-bezier(0.22, 1, 0.36, 1); --ease-spring: cubic-bezier(0.34, 1.3, 0.64, 1); @@ -52,6 +58,14 @@ --color-primary: var(--primary); --color-primary-strong: var(--primary-strong); --color-primary-soft: var(--primary-soft); + --color-chrome: var(--surface-chrome); + --color-command: var(--command); + --color-command-hover: var(--command-hover); + --color-command-contrast: var(--command-contrast); + --color-clinical-accent: var(--clinical-accent); + --color-clinical-accent-hover: var(--clinical-accent-hover); + --color-clinical-accent-soft: var(--clinical-accent-soft); + --color-clinical-accent-border: var(--clinical-accent-border); --color-success: var(--success); --color-success-soft: var(--success-soft); --color-danger: var(--danger); @@ -65,82 +79,94 @@ /* Theme tokens */ :root { - /* Neutral foundation tuned toward quiet graphite-to-ash */ - --neutral-0: #f4f7f9; - --neutral-50: #edf2f6; - --neutral-100: #dde4ec; - --neutral-200: #c5d1de; - --neutral-300: #a2b2c5; - --neutral-400: #7f92a5; - --neutral-500: #5a7182; - --neutral-600: #435363; - --neutral-700: #2f4052; - --neutral-800: #1a2737; - --neutral-900: #111a26; - --neutral-950: #080f16; - - /* Primary accent tuned for a restrained luxury look */ - --primary-50: #dff2f0; - --primary-100: #bfe5e1; - --primary-200: #87c9c2; - --primary-300: #4caca3; - --primary-400: #1c8f82; - --primary-500: #137b6f; - --primary-600: #0f645d; - --primary-700: #0d5852; - --primary-800: #0d4743; - --primary-900: #0b3a37; - - --background: #f0f4f7; + /* Clinical White: true-neutral graphite-to-ash ramp (de-blued). */ + --neutral-0: #ffffff; + --neutral-50: #f7f8fa; + --neutral-100: #f1f4f6; + --neutral-200: #e5e7eb; + --neutral-300: #cdd5df; + --neutral-400: #98a2b3; + --neutral-500: #667085; + --neutral-600: #475467; + --neutral-700: #344054; + --neutral-800: #1d2939; + --neutral-900: #101418; + --neutral-950: #080b0f; + + /* Clinical accent (Aegean): cool blue-teal clinical identity ramp. */ + --primary-50: #e7f6f8; + --primary-100: #c5e9ee; + --primary-200: #b9e4ea; + --primary-300: #7fcdd8; + --primary-400: #3ba7ba; + --primary-500: #0b6f86; + --primary-600: #0a6377; + --primary-700: #095d70; + --primary-800: #0b4a5a; + --primary-900: #0a3b47; + + --background: #ffffff; --app-shell: #101a27; --app-shell-muted: #182536; --app-shell-accent: #2d948d; --surface: var(--neutral-0); - --surface-raised: #f8fbfd; - --surface-subtle: #edf2f6; - --surface-inset: #e9eef3; + --surface-chrome: #f7f8fa; + --surface-raised: #fcfcfd; + --surface-subtle: #f7f8fa; + --surface-inset: #f1f4f6; --surface-glass: rgb(255 255 255 / 82%); --surface-highlight: color-mix(in srgb, var(--neutral-0) 64%, transparent); - --surface-lux: color-mix(in srgb, var(--neutral-0) 94%, #ffffff 6%); - --surface-wash: #e9f0f4; + --surface-lux: #ffffff; + --surface-wash: #f7f8fa; --text: var(--neutral-900); - --text-heading: #02080f; - --text-muted: var(--neutral-700); - --text-soft: var(--neutral-600); - --border: #d9e0e7; - --border-strong: #c3ced7; - --border-lux: rgb(138 156 171 / 36%); + --text-heading: #080b0f; + --text-muted: var(--neutral-600); + --text-soft: var(--neutral-500); + --border: #e5e7eb; + --border-strong: #cdd5df; + --border-lux: rgb(205 213 223 / 55%); --primary: var(--primary-500); --primary-strong: var(--primary-700); - --primary-soft: #ddf0ec; - --primary-contrast: #eef8f7; - - /* Clinical chat redesign aliases. These are intentionally conservative and - functional: teal for active/source/send, sand for clinical notes, blue-grey - for document/search surfaces, and tiny dots for source status. */ - --clinical-chat-teal: #006c67; - --clinical-chat-teal-soft: #e7f4f2; + --primary-soft: #e7f6f8; + --primary-contrast: #ffffff; + + /* Command (graphite): primary actions — New chat, primary CTAs. */ + --command: #111827; + --command-hover: #0b1220; + --command-contrast: #ffffff; + + /* Clinical accent role tokens (Aegean). Selected · evidence · send · focus. */ + --clinical-accent: var(--primary-500); + --clinical-accent-hover: var(--primary-700); + --clinical-accent-soft: var(--primary-soft); + --clinical-accent-border: #b9e4ea; + --clinical-accent-contrast: #ffffff; + + /* Migration compat: existing teal/ready call-sites resolve to the new roles. + Remove once all call-sites reference the role tokens directly. */ + --clinical-chat-teal: var(--clinical-accent); + --clinical-chat-teal-soft: var(--clinical-accent-soft); --clinical-chat-sand: #f7f1e6; --clinical-chat-sand-border: #eadcc7; --clinical-chat-sand-border-strong: #ddc7a8; - --clinical-chat-document: #eef3f6; - --clinical-chat-table-header: #f4f7f8; - --clinical-chat-amber: #c88719; - --clinical-chat-ready: #1a8f5a; - - /* Semantic triads (text / background / border), AA on their own bg */ - --info-text: #5e9ad1; - --info-bg: #11213a; - --info-border: #274f85; - --success-text: #65c58b; - --success-bg: #102e1f; - --success-border: #205f42; - --warning-text: #f3bf52; - --warning-bg: #3a2e16; - --warning-border: #6f5d23; - --danger-text: #fd9298; - --danger-bg: #3a161e; - --danger-border: #7a2d34; + --clinical-chat-document: #f1f4f6; + --clinical-chat-table-header: #f7f8fa; + --clinical-chat-amber: var(--warning); + --clinical-chat-ready: var(--success); + + /* Semantic triads (text / background / border), on-white for light mode. */ + --info-text: #2563eb; + --info-bg: #eff4ff; + --info-border: #b2ccff; + --success-text: #0f7a49; + --success-bg: #ecfdf3; + --success-border: #abefc6; + --warning-text: #a15c07; + --warning-bg: #fef7ec; + --warning-border: #f5d9a8; + --danger-text: #b42318; + --danger-bg: #fef3f2; + --danger-border: #fda29b; --info: var(--info-text); --info-soft: var(--info-bg); @@ -151,8 +177,8 @@ --danger: var(--danger-text); --danger-soft: var(--danger-bg); - --disabled: #94a3b8; - --focus: #2aa49a; + --disabled: #98a2b3; + --focus: var(--clinical-accent); --overlay-backdrop: rgb(4 8 14 / 56%); --panel-gloss: color-mix(in srgb, var(--surface-lux) 82%, transparent); @@ -199,27 +225,29 @@ } .dark { + /* Dark neutral ramp (inverted): black-polish canvas to near-white ink. */ --neutral-0: #060708; - --neutral-50: #0c0d0f; - --neutral-100: #121417; - --neutral-200: #1b1d21; - --neutral-300: #24272d; - --neutral-400: #3c414a; - --neutral-500: #6a717f; - --neutral-600: #9ba2ae; - --neutral-700: #d0d4dc; - --neutral-800: #e4e6eb; - --neutral-900: #f2f3f5; - --neutral-950: #f8fafb; - - --primary-50: #092a2a; - --primary-100: #0a3434; - --primary-200: #0f4f4a; - --primary-300: #16756c; - --primary-400: #22a095; - --primary-500: #31bfb2; - --primary-600: #58cfd1; - --primary-700: #7ddfe1; + --neutral-50: #0b0d0f; + --neutral-100: #101214; + --neutral-200: #171a1d; + --neutral-300: #23282c; + --neutral-400: #3b454b; + --neutral-500: #7f8987; + --neutral-600: #a7b0ad; + --neutral-700: #cdd3d1; + --neutral-800: #e6e9e8; + --neutral-900: #f5f7f7; + --neutral-950: #fbfcfc; + + /* Clinical accent (Aegean), brightened + desaturated for dark surfaces. */ + --primary-50: #04252a; + --primary-100: #0a3339; + --primary-200: #12383b; + --primary-300: #1c5a60; + --primary-400: #2f9ca0; + --primary-500: #4ccfd0; + --primary-600: #6fdada; + --primary-700: #6fdada; --primary-800: #a6ebe9; --primary-900: #d0f6f5; @@ -227,14 +255,15 @@ --app-shell: #090a0c; --app-shell-muted: #0e0f11; --app-shell-accent: #33a69f; - --surface: #0e1012; - --surface-raised: #141619; - --surface-subtle: #090a0c; + --surface: #101214; + --surface-chrome: #0b0d0f; + --surface-raised: #171a1d; + --surface-subtle: #0b0d0f; --surface-inset: #040506; --surface-glass: rgb(6 7 8 / 78%); --surface-highlight: rgb(255 255 255 / 5%); - --surface-lux: rgb(11 12 14 / 93%); - --surface-wash: #0c0d0f; + --surface-lux: #101214; + --surface-wash: #0b0d0f; --text: var(--neutral-900); --text-heading: var(--neutral-950); --text-muted: var(--neutral-600); @@ -245,18 +274,28 @@ --primary: var(--primary-500); --primary-strong: var(--primary-700); - --primary-soft: #0e3230; - --primary-contrast: #04111a; + --primary-soft: #12383b; + --primary-contrast: #04252a; + + --command: #f5f7f7; + --command-hover: #e6e9e8; + --command-contrast: #060708; + + --clinical-accent: var(--primary-500); + --clinical-accent-hover: var(--primary-700); + --clinical-accent-soft: var(--primary-soft); + --clinical-accent-border: #235b60; + --clinical-accent-contrast: #04252a; - --clinical-chat-teal: #4ccfd0; - --clinical-chat-teal-soft: #14353a; + --clinical-chat-teal: var(--clinical-accent); + --clinical-chat-teal-soft: var(--clinical-accent-soft); --clinical-chat-sand: #2d2418; --clinical-chat-sand-border: #5a4427; --clinical-chat-sand-border-strong: #806034; --clinical-chat-document: #101215; --clinical-chat-table-header: #141619; - --clinical-chat-amber: #d8ad48; - --clinical-chat-ready: #52d08d; + --clinical-chat-amber: var(--warning); + --clinical-chat-ready: var(--success); --info-text: #89c0f0; --info-bg: #122c4c; @@ -281,7 +320,7 @@ --danger-soft: var(--danger-bg); --disabled: #555e6b; - --focus: #74e0d4; + --focus: var(--clinical-accent); --overlay-backdrop: rgb(0 0 0 / 72%); --panel-gloss: color-mix(in srgb, var(--surface-lux) 82%, transparent); @@ -308,19 +347,13 @@ html { min-height: 100%; min-height: 100dvh; background-color: var(--background); - background: - radial-gradient(circle at 50% -12%, color-mix(in srgb, var(--primary) 5%, transparent), transparent 34rem), - linear-gradient(180deg, var(--background), color-mix(in srgb, var(--background) 90%, var(--surface-inset))); overflow-x: clip; } body { min-height: 100%; min-height: 100dvh; - background: - radial-gradient(circle at 8% 0%, color-mix(in srgb, var(--primary) 4%, transparent), transparent 28rem), - radial-gradient(circle at 98% 12%, color-mix(in srgb, var(--info) 3%, transparent), transparent 26rem), - var(--background); + background: var(--background); color: var(--text); font-family: var(--font-geist-sans), Arial, Helvetica, sans-serif; font-feature-settings: @@ -405,28 +438,16 @@ summary::-webkit-details-marker { /* Layout utilities */ .app-edge-backdrop { - background: - radial-gradient(circle at 18% -10%, color-mix(in srgb, var(--primary) 7%, transparent), transparent 30rem), - radial-gradient(circle at 100% 0%, color-mix(in srgb, var(--info) 5%, transparent), transparent 28rem), - linear-gradient(180deg, var(--background) 0%, color-mix(in srgb, var(--background) 88%, var(--surface)) 100%); + background: var(--background); } .edge-glass-header { isolation: isolate; padding-left: max(0.75rem, var(--safe-area-left)); padding-right: max(0.75rem, var(--safe-area-right)); - border-bottom-color: color-mix(in srgb, var(--border) 48%, transparent); - background: - linear-gradient( - 180deg, - color-mix(in srgb, var(--surface-lux) 88%, transparent) 0%, - color-mix(in srgb, var(--surface-lux) 76%, transparent) 74%, - color-mix(in srgb, var(--background) 46%, transparent) 100% - ), - var(--background); - box-shadow: - 0 1px 0 color-mix(in srgb, var(--surface-highlight) 72%, transparent), - 0 18px 34px rgb(15 31 38 / 5%); + border-bottom: 1px solid var(--border); + background: var(--surface); + box-shadow: none; } .edge-glass-header::after { @@ -441,34 +462,18 @@ summary::-webkit-details-marker { } .universal-header { - background: - radial-gradient( - circle at 44% -135%, - color-mix(in srgb, var(--clinical-chat-teal) 17%, transparent), - transparent 22rem - ), - linear-gradient( - 180deg, - color-mix(in srgb, var(--surface-lux) 96%, transparent) 0%, - color-mix(in srgb, var(--surface-lux) 88%, transparent) 68%, - color-mix(in srgb, var(--background) 64%, transparent) 100% - ), - var(--background); + background: var(--surface); } .universal-header-ledger { min-height: 2.5rem; max-width: min(100%, 27rem); - border: 1px solid color-mix(in srgb, var(--border-lux) 70%, transparent); + border: 1px solid var(--border); border-radius: 999px; - background: - linear-gradient(180deg, color-mix(in srgb, var(--surface-lux) 86%, white 14%), var(--surface-lux)), - var(--surface-lux); + background: var(--surface-raised); padding: 0.25rem 0.55rem 0.25rem 0.7rem; color: var(--text-muted); - box-shadow: - inset 0 1px 0 rgb(255 255 255 / 72%), - 0 6px 16px rgb(15 31 38 / 4%); + box-shadow: none; } .universal-header-ledger-label { @@ -513,48 +518,34 @@ summary::-webkit-details-marker { } .universal-header-mode-button { - border-color: color-mix(in srgb, var(--clinical-chat-teal) 17%, var(--border-lux)); - background: - radial-gradient(circle at 8% 8%, color-mix(in srgb, var(--clinical-chat-teal) 7%, transparent), transparent 7rem), - linear-gradient(180deg, color-mix(in srgb, var(--surface-lux) 88%, white 12%), var(--surface-lux)), - var(--surface-lux); - box-shadow: - inset 0 1px 0 rgb(255 255 255 / 78%), - 0 8px 22px rgb(15 31 38 / 6%); + border-color: var(--border); + background: var(--surface); + box-shadow: var(--shadow-tight); } .universal-header-icon-control { - border-color: color-mix(in srgb, var(--border-lux) 74%, transparent); - background: - linear-gradient(180deg, color-mix(in srgb, var(--surface-lux) 88%, white 12%), var(--surface-lux)), - var(--surface-lux); - box-shadow: - inset 0 1px 0 rgb(255 255 255 / 68%), - 0 4px 12px rgb(15 31 38 / 4%); + border-color: var(--border); + background: var(--surface); + box-shadow: none; } .universal-header-icon-control:hover { - border-color: color-mix(in srgb, var(--clinical-chat-teal) 22%, var(--border-strong)); + border-color: var(--border-strong); + background: var(--surface-subtle); } .universal-header-avatar { - box-shadow: - inset 0 1px 0 rgb(255 255 255 / 74%), - 0 5px 14px color-mix(in srgb, var(--clinical-chat-teal) 10%, transparent); + box-shadow: var(--shadow-tight); } .dark .universal-header-ledger, .dark .universal-header-mode-button { - box-shadow: - inset 0 1px 0 rgb(255 255 255 / 7%), - 0 10px 24px rgb(0 0 0 / 24%); + box-shadow: var(--shadow-tight); } .dark .universal-header-icon-control, .dark .universal-header-avatar { - box-shadow: - inset 0 1px 0 rgb(255 255 255 / 6%), - 0 8px 18px rgb(0 0 0 / 22%); + box-shadow: none; } .floating-composer-edge { @@ -570,15 +561,12 @@ summary::-webkit-details-marker { .answer-footer-search-pill { min-height: 3.8rem; gap: 0.25rem; - border-color: color-mix(in srgb, var(--border-lux) 54%, white 46%); - background: - linear-gradient(180deg, color-mix(in srgb, white 88%, var(--surface-lux)) 0%, var(--surface-lux) 100%), - var(--surface-lux); + border: 1px solid var(--border-strong); + background: var(--surface); padding-inline: 0.375rem; box-shadow: - inset 0 1px 0 rgb(255 255 255 / 82%), - 0 14px 34px rgb(15 31 38 / 13%), - 0 3px 10px rgb(15 31 38 / 6%); + 0 1px 2px rgb(16 24 40 / 5%), + 0 8px 22px rgb(16 24 40 / 8%); transition: border-color 180ms ease, box-shadow 180ms ease, @@ -586,20 +574,18 @@ summary::-webkit-details-marker { } .answer-footer-search-pill:focus-within { - border-color: color-mix(in srgb, var(--clinical-chat-teal) 34%, var(--border-lux)); + border-color: var(--clinical-accent); box-shadow: - inset 0 1px 0 rgb(255 255 255 / 88%), - 0 0 0 3px color-mix(in srgb, var(--clinical-chat-teal) 10%, transparent), - 0 16px 38px rgb(15 31 38 / 14%), - 0 3px 10px rgb(15 31 38 / 7%); + 0 0 0 3px color-mix(in srgb, var(--clinical-accent) 18%, transparent), + 0 8px 22px rgb(16 24 40 / 10%); } .answer-footer-search-action { height: 2.75rem; width: 2.75rem; - border: 1px solid color-mix(in srgb, var(--border-strong) 40%, transparent); - color: #0c1a4d; - box-shadow: inset 0 1px 0 rgb(255 255 255 / 78%); + border: 1px solid var(--border); + color: var(--text-muted); + box-shadow: none; } .answer-footer-search-input { @@ -634,12 +620,13 @@ summary::-webkit-details-marker { .answer-footer-search-send { height: 2.8rem; width: 2.8rem; - background: - radial-gradient(circle at 34% 25%, rgb(255 255 255 / 18%), transparent 42%), - linear-gradient(145deg, var(--clinical-chat-teal), var(--primary-strong)); - box-shadow: - inset 0 1px 0 rgb(255 255 255 / 24%), - 0 7px 18px color-mix(in srgb, var(--clinical-chat-teal) 24%, transparent); + background: var(--clinical-accent); + color: var(--clinical-accent-contrast); + box-shadow: 0 2px 8px color-mix(in srgb, var(--clinical-accent) 30%, transparent); +} + +.answer-footer-search-send:hover { + background: var(--clinical-accent-hover); } .answer-footer-search-chip { @@ -647,28 +634,25 @@ summary::-webkit-details-marker { min-height: 1.9rem; align-items: center; gap: 0.35rem; - border: 1px solid color-mix(in srgb, var(--border-lux) 62%, transparent); + border: 1px solid var(--border); border-radius: 999px; - background: color-mix(in srgb, var(--surface-lux) 70%, transparent); + background: var(--surface); padding-inline: 0.65rem; - color: #0c1a4d; + color: var(--text-muted); font-size: 0.75rem; font-weight: 700; - box-shadow: - inset 0 1px 0 rgb(255 255 255 / 70%), - 0 5px 14px rgb(15 31 38 / 5%); - backdrop-filter: blur(18px); + box-shadow: none; } .answer-footer-search-chip svg { height: 0.875rem; width: 0.875rem; - color: var(--clinical-chat-teal); + color: var(--clinical-accent); } .dark .answer-footer-search-action, .dark .answer-footer-search-chip { - color: var(--text-heading); + color: var(--text-muted); } .mobile-app-shell { @@ -956,6 +940,15 @@ summary::-webkit-details-marker { --primary-strong: LinkText; --primary-soft: Canvas; --primary-contrast: Canvas; + --surface-chrome: Canvas; + --command: ButtonText; + --command-hover: ButtonText; + --command-contrast: ButtonFace; + --clinical-accent: LinkText; + --clinical-accent-hover: LinkText; + --clinical-accent-soft: Canvas; + --clinical-accent-border: ButtonBorder; + --clinical-accent-contrast: Canvas; --info: LinkText; --info-soft: Canvas; --success: CanvasText; diff --git a/src/app/layout.tsx b/src/app/layout.tsx index b4880ae540..f8aec1acd6 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -30,7 +30,7 @@ export const viewport: Viewport = { viewportFit: "cover", colorScheme: "light dark", themeColor: [ - { media: "(prefers-color-scheme: light)", color: "#f0f4f7" }, + { media: "(prefers-color-scheme: light)", color: "#ffffff" }, { media: "(prefers-color-scheme: dark)", color: "#060708" }, ], }; diff --git a/src/components/ClinicalDashboard.tsx b/src/components/ClinicalDashboard.tsx index 498b610d4c..9084f5e6dc 100644 --- a/src/components/ClinicalDashboard.tsx +++ b/src/components/ClinicalDashboard.tsx @@ -80,6 +80,7 @@ import { chatActionRow, chatAnswerText, chatMicroAction, + codeText, clinicalDivider, clinicalNotesRow, cn, @@ -789,7 +790,8 @@ function SourcePreviewContent({ {source.title} - p.{source.pageNumber ?? "n/a"} · {sourceStatusLabel(source.metadata)} + p.{source.pageNumber ?? "n/a"} ·{" "} + {sourceStatusLabel(source.metadata)} @@ -2716,7 +2718,9 @@ function QuoteCards({ {quotes.map((quote, index) => (
- {index + 1} + + {index + 1} +
@@ -2997,8 +3001,9 @@ function WhyThisMatchedPanel({ sources }: { sources: SearchResult[] }) {

{source.title}

-

- page {source.page_number ?? "n/a"} · chunk {source.chunk_index} +

+ page {source.page_number ?? "n/a"} ·{" "} + chunk {source.chunk_index}

@@ -5393,8 +5398,8 @@ function MobileSectionFab({ aria-expanded={open} aria-controls={panelId} className={cn( - "fixed z-40 grid h-14 w-14 place-items-center rounded-full border border-[color:var(--primary)]/25 bg-[color:var(--primary)] text-[color:var(--primary-contrast)] shadow-[var(--glow-soft)] ring-1 ring-[color:var(--border-strong)]/20 transition motion-safe:duration-150 hover:-translate-y-0.5 hover:bg-[color:var(--primary-strong)] active:translate-y-px dark:ring-[color:var(--border-strong)]/10", - open && "bg-[color:var(--primary-strong)] shadow-[var(--glow-primary)]", + "fixed z-40 grid h-14 w-14 place-items-center rounded-full border border-[color:var(--command)] bg-[color:var(--command)] text-[color:var(--command-contrast)] shadow-[var(--shadow-elevated)] transition motion-safe:duration-150 hover:-translate-y-0.5 hover:bg-[color:var(--command-hover)] active:translate-y-px", + open && "bg-[color:var(--command-hover)]", )} style={{ right: "max(0.75rem, env(safe-area-inset-right))", diff --git a/src/components/DocumentViewer.tsx b/src/components/DocumentViewer.tsx index ea79dd7337..41b9a9dd6b 100644 --- a/src/components/DocumentViewer.tsx +++ b/src/components/DocumentViewer.tsx @@ -2808,7 +2808,7 @@ export function DocumentViewer({
Index version
-
+
{indexHealth.indexVersion ?? "unknown"}
diff --git a/src/components/clinical-dashboard/ClinicalSidebar.tsx b/src/components/clinical-dashboard/ClinicalSidebar.tsx index c705aed50b..ba4eeeb2b9 100644 --- a/src/components/clinical-dashboard/ClinicalSidebar.tsx +++ b/src/components/clinical-dashboard/ClinicalSidebar.tsx @@ -124,7 +124,7 @@ export function ClinicalSidebarContent({ onNewChat(); onNavigate?.(); }} - className="inline-flex min-h-[44px] w-full items-center justify-center gap-2 rounded-lg bg-[color:var(--clinical-chat-teal)] px-3 text-sm font-semibold text-white shadow-[var(--shadow-tight)] hover:bg-[color:var(--primary-strong)]" + className="inline-flex min-h-[44px] w-full items-center justify-center gap-2 rounded-lg bg-[color:var(--command)] px-3 text-sm font-semibold text-[color:var(--command-contrast)] shadow-[var(--shadow-tight)] hover:bg-[color:var(--command-hover)]" > New chat @@ -162,10 +162,15 @@ export function ClinicalSidebarContent({ className={cn( sidebarItem, index === 0 && - "bg-[color:var(--clinical-chat-teal-soft)] text-[color:var(--clinical-chat-teal)] hover:bg-[color:var(--clinical-chat-teal-soft)]", + "border-l-2 border-l-[color:var(--clinical-accent)] bg-[color:var(--surface-chrome)] text-[color:var(--text)] hover:bg-[color:var(--surface-chrome)]", )} > - + {recent} )) @@ -202,10 +207,15 @@ export function ClinicalSidebarContent({ className={cn( sidebarToolTile, active && - "border-[color:var(--clinical-chat-teal)]/28 bg-[color:var(--clinical-chat-teal-soft)] text-[color:var(--clinical-chat-teal)] shadow-[var(--shadow-tight)]", + "border-[color:var(--clinical-accent-border)] bg-[color:var(--surface-chrome)] text-[color:var(--text)] shadow-[var(--shadow-tight)]", )} > - + {item.label} ); @@ -217,7 +227,7 @@ export function ClinicalSidebarContent({ onFocus={onPrefetchApplications} onPointerEnter={onPrefetchApplications} onClick={onNavigate} - className="mt-2 inline-flex min-h-10 w-full items-center justify-between rounded-lg border border-[color:var(--clinical-chat-teal)]/16 bg-[color:var(--clinical-chat-teal-soft)]/70 px-3 text-sm font-semibold text-[color:var(--clinical-chat-teal)] shadow-[var(--shadow-inset)]" + className="mt-2 inline-flex min-h-10 w-full items-center justify-between rounded-lg border border-[color:var(--border)] bg-[color:var(--surface)] px-3 text-sm font-semibold text-[color:var(--text-muted)] shadow-[var(--shadow-inset)] transition hover:border-[color:var(--border-strong)] hover:text-[color:var(--text)]" > View tools diff --git a/src/components/clinical-dashboard/master-search-header.tsx b/src/components/clinical-dashboard/master-search-header.tsx index 0de35d5e6f..d1546d371c 100644 --- a/src/components/clinical-dashboard/master-search-header.tsx +++ b/src/components/clinical-dashboard/master-search-header.tsx @@ -796,15 +796,15 @@ export function MasterSearchHeader({ className={cn( "grid min-h-[3.25rem] w-full grid-cols-[2rem_minmax(0,1fr)_auto] items-center gap-2 rounded-md px-2.5 py-2 text-left transition focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[color:var(--focus)]", active - ? "bg-[color:var(--clinical-chat-teal-soft)] text-[color:var(--clinical-chat-teal)]" + ? "border-l-2 border-l-[color:var(--clinical-accent)] bg-[color:var(--surface-chrome)] text-[color:var(--text)]" : "text-[color:var(--text-muted)] hover:bg-[color:var(--surface-subtle)] hover:text-[color:var(--text)]", )} > @@ -816,7 +816,7 @@ export function MasterSearchHeader({ {mode.description} - {active ? : null} + {active ? : null} ); })} @@ -913,7 +913,7 @@ export function MasterSearchHeader({