diff --git a/src/components/medications/__tests__/card-parts.test.tsx b/src/components/medications/__tests__/card-parts.test.tsx index f39baaf64..07f351996 100644 --- a/src/components/medications/__tests__/card-parts.test.tsx +++ b/src/components/medications/__tests__/card-parts.test.tsx @@ -373,10 +373,11 @@ describe("streak-token parity — generic vs GLP-1 card", () => { }); /** - * v1.15.9 — the ONE shared `` both cards render. These - * tests pin the state-driven presentation (green take-window highlight, - * overdue / heavily-overdue top line) and the structural identity that makes - * the two variants impossible to diverge — they pass content into THIS body. + * v1.15.18 — the ONE shared `` both cards render. These + * tests pin that the card surface is a CONSTANT neutral surface — dose status + * is never expressed as a background / border tint (Marc, recurring) — while + * status is still surfaced via the discreet top line / pill, plus the + * structural identity that makes the two variants impossible to diverge. */ describe("medication card body — shared shell + dose-state presentation", () => { function renderBody(doseStatus: DoseStatus, active = true) { @@ -406,17 +407,30 @@ describe("medication card body — shared shell + dose-state presentation", () = ); } - it("highlights the card green when the dose is in its take-window", () => { + it("never tints the card surface when the dose is in its take-window", () => { + // Marc (recurring): the whole card washing green reads as "take it now" + // and is a permanent removal. The take-window status survives ONLY as the + // discreet "Take now" pill, never as a card background / ring tint. const html = renderBody("on_time_window"); - // Green ring + tinted background on the Card shell. - expect(html).toContain("ring-success/40"); - expect(html).toContain("bg-success/5"); + expect(html).not.toContain("ring-success/40"); + expect(html).not.toContain("bg-success/5"); + // The discreet status pill still communicates the state. + expect(html).toContain("Take now"); }); - it("stays calm (no green highlight) for upcoming / taken states", () => { - for (const status of ["upcoming", "taken_on_time", "taken_late", "skipped"] as const) { + it("never tints the card surface across any dose status", () => { + for (const status of [ + "on_time_window", + "upcoming", + "taken_on_time", + "taken_late", + "skipped", + "overdue", + "missed", + ] as const) { const html = renderBody(status); expect(html).not.toContain("ring-success/40"); + expect(html).not.toContain("bg-success/5"); } }); @@ -433,9 +447,10 @@ describe("medication card body — shared shell + dose-state presentation", () = expect(html).toContain("text-destructive"); }); - it("never highlights green on an inactive medication", () => { + it("keeps the inactive surface muted without any status tint", () => { const html = renderBody("on_time_window", false); expect(html).not.toContain("ring-success/40"); + expect(html).not.toContain("bg-success/5"); expect(html).toContain("opacity-60"); }); diff --git a/src/components/medications/card-parts/medication-card-body.tsx b/src/components/medications/card-parts/medication-card-body.tsx index 9d34fc9e1..6566c1c9a 100644 --- a/src/components/medications/card-parts/medication-card-body.tsx +++ b/src/components/medications/card-parts/medication-card-body.tsx @@ -35,11 +35,16 @@ import type { MedicationWindowStatus } from "@/lib/medications/window-status"; * the single `mt-auto pt-0` action wrapper — there is no per-variant spacing * left to diverge. * - * State-driven presentation (like the iOS app): - * - `on_time_window` → the card highlights green (`ring` + tinted bg): the - * actionable "take it now" state stands out at a glance. + * State-driven presentation: + * - The card surface itself is a CONSTANT neutral surface — dose status + * never tints the card background or border. A whole card washing green + * reads as "take it now everywhere" and drowns the page; status is shown + * ONLY through the discreet top line / pill below. + * - `on_time_window` → the discreet "Take now" pill (success-toned text + + * glyph), no card wash. * - `overdue` → a calm top status line; `missed` (at / past the miss - * cutoff) escalates to "Stark überfällig" in the destructive tone. + * cutoff) escalates to "Stark überfällig" in the destructive tone — both + * are a single text line with an icon, not a surface tint. * - `upcoming` / `taken_*` / `skipped` → no escalation; the card stays calm. */ export interface MedicationCardBodyProps { @@ -123,10 +128,6 @@ export function MedicationCardBody({ }: MedicationCardBodyProps) { const { t } = useTranslations(); - // Green take-window highlight — the actionable "take it now" state, mirrored - // from the iOS card. Suppressed on an inactive med (it carries no actions). - const inTakeWindow = active && doseStatus === "on_time_window"; - // Overdue escalation line: a dose past its on-time window. `missed` (at / // past the clinical miss cutoff) reads "Stark überfällig"; the still-takeable // `overdue` tail reads the calmer "Überfällig". Both use the destructive @@ -140,11 +141,10 @@ export function MedicationCardBody({ return (