feat: launch public product website
This commit is contained in:
@@ -0,0 +1,308 @@
|
||||
import Image from "next/image";
|
||||
import {
|
||||
HeartPulse,
|
||||
Layers,
|
||||
Mic,
|
||||
MessageSquare,
|
||||
ScanLine,
|
||||
ShieldCheck,
|
||||
} from "lucide-react";
|
||||
|
||||
/**
|
||||
* Pharmacy-specific print summary (CVS-targeted, reusable for other pharmacies).
|
||||
* Two designed pages, built for the product rather than mirroring the Northwell
|
||||
* layout:
|
||||
* Page 1 - what Medscribe can do (capabilities, patient-facing power).
|
||||
* Page 2 - every capability pays off twice (patient value -> CVS value).
|
||||
* Reuses the `northwell-print-*` sheet/label classes from globals.css only as
|
||||
* the page frame; the interior is its own design.
|
||||
*/
|
||||
|
||||
function PrintPage({
|
||||
page,
|
||||
children,
|
||||
}: Readonly<{ page: number; children: React.ReactNode }>) {
|
||||
return (
|
||||
<article
|
||||
className={
|
||||
page === 1
|
||||
? "northwell-print-page"
|
||||
: "northwell-print-page northwell-print-page--continuation"
|
||||
}
|
||||
>
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
<img className="northwell-print-wash" src="/print-wash.svg" alt="" />
|
||||
{page === 1 ? (
|
||||
<header className="northwell-print-header">
|
||||
<div className="flex items-center gap-2.5">
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
<img className="h-6 w-auto" src="/medscribe-ms-logo.svg" alt="" />
|
||||
<span className="font-serif text-[17px] font-semibold text-slate-950">
|
||||
Medscribe
|
||||
</span>
|
||||
</div>
|
||||
<span className="text-[9px] font-semibold tracking-[0.18em] text-slate-500 uppercase">
|
||||
Executive summary · CVS Health
|
||||
</span>
|
||||
</header>
|
||||
) : null}
|
||||
|
||||
<div className="northwell-print-content">{children}</div>
|
||||
|
||||
<footer className="northwell-print-footer">
|
||||
<span>Page {page} of 2</span>
|
||||
</footer>
|
||||
</article>
|
||||
);
|
||||
}
|
||||
|
||||
const capabilities = [
|
||||
{
|
||||
icon: Mic,
|
||||
title: "Understand a visit",
|
||||
body: "Type, paste, snap the after-visit summary, or record the conversation with consent. Medscribe transcribes and summarizes it on the phone.",
|
||||
},
|
||||
{
|
||||
icon: ScanLine,
|
||||
title: "Read a pill bottle",
|
||||
body: "Point the camera at a prescription label and the drug, dose, and schedule land in the record automatically.",
|
||||
},
|
||||
{
|
||||
icon: MessageSquare,
|
||||
title: "Answer the hard questions",
|
||||
body: "Ask whether two medications are safe together and get an answer grounded in bundled FDA drug facts and known interaction pairs, not a chatbot's guess.",
|
||||
},
|
||||
{
|
||||
icon: Layers,
|
||||
title: "Hold the whole picture",
|
||||
body: "Medications, allergies, conditions, baseline, and visit history across every provider, in one place the patient owns.",
|
||||
},
|
||||
{
|
||||
icon: HeartPulse,
|
||||
title: "Be ready for an emergency",
|
||||
body: "A patient-controlled Know Me card puts the time-critical facts one tap away for a caregiver or an ER.",
|
||||
},
|
||||
{
|
||||
icon: ShieldCheck,
|
||||
title: "Share without exposure",
|
||||
body: "End-to-end encrypted sharing lets a caregiver help, without a server ever reading the record.",
|
||||
},
|
||||
] as const;
|
||||
|
||||
const payoffs = [
|
||||
{
|
||||
patientTitle: "One picture, everywhere they are treated",
|
||||
patient:
|
||||
"Nothing falls through the cracks between a specialist, an urgent care, and the pharmacy.",
|
||||
cvsTitle: "One central pharmacy",
|
||||
cvs: "Refills route back to CVS and scattered scripts consolidate, instead of leaking to Amazon, Cost Plus, or mail order. Share of scripts, won.",
|
||||
},
|
||||
{
|
||||
patientTitle: "Medications that fit their day",
|
||||
patient:
|
||||
"Reminders and refill nudges that actually help, so they stay on their medications.",
|
||||
cvsTitle: "Star Ratings",
|
||||
cvs: "Diabetes, hypertension, and statin adherence are triple-weighted in Part D Star Ratings: Quality Bonus Payments and retention for Aetna and SilverScript.",
|
||||
},
|
||||
{
|
||||
patientTitle: "Fewer dangerous surprises",
|
||||
patient:
|
||||
"Interactions and duplicate prescriptions caught across every prescriber, not one pharmacy's slice.",
|
||||
cvsTitle: "Lower cost of care",
|
||||
cvs: "Fewer adverse events and ER visits: direct medical spend saved for the members shared with Caremark and Aetna.",
|
||||
},
|
||||
{
|
||||
patientTitle: "Ready at the counter",
|
||||
patient:
|
||||
"They arrive with a clean list and their routine questions already answered.",
|
||||
cvsTitle: "Pharmacist leverage",
|
||||
cvs: "Less low-value counter volume, more time for the billable MTM and CMR work pharmacists already do.",
|
||||
},
|
||||
{
|
||||
patientTitle: "A tool that is theirs",
|
||||
patient:
|
||||
"An advocate they control, on their own device. Not a sales pitch, and never on a server.",
|
||||
cvsTitle: "Engagement without the liability",
|
||||
cvs: "A CVS-branded habit patients actually open, with no PHI on a server: no new breach surface and no BAA to negotiate.",
|
||||
},
|
||||
] as const;
|
||||
|
||||
export function CvsPrintSummary() {
|
||||
return (
|
||||
<div className="northwell-print-only" aria-hidden="true">
|
||||
<PrintPage page={1}>
|
||||
<div className="grid grid-cols-[1.16fr_0.84fr] items-start gap-9 pt-5">
|
||||
<div>
|
||||
<p className="northwell-print-label">What Medscribe is</p>
|
||||
<h1 className="mt-4 font-serif text-[40px] leading-[1.0] font-semibold tracking-[-0.035em] text-slate-950">
|
||||
It captures, understands, and carries the patient's whole
|
||||
medical picture.
|
||||
</h1>
|
||||
<p className="mt-5 text-[15px] leading-[1.55] text-slate-600">
|
||||
Real medical AI on the patient's phone. Medscribe summarizes
|
||||
visits, reads pill bottles, answers medication questions from
|
||||
bundled drug facts, and keeps one emergency-ready record across
|
||||
every provider. Nothing is sent to the cloud.
|
||||
</p>
|
||||
<div className="mt-6 grid grid-cols-2 gap-x-5 gap-y-2 text-[8.5px] font-bold tracking-[0.08em] text-slate-600 uppercase">
|
||||
{[
|
||||
"On-device AI",
|
||||
"Facts-first",
|
||||
"Patient-owned",
|
||||
"iOS and Android beta",
|
||||
].map((badge) => (
|
||||
<span key={badge} className="flex items-center gap-2">
|
||||
<span className="size-1 rounded-full bg-teal-600" />
|
||||
{badge}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mx-auto w-[186px] rounded-[28px] border-[6px] border-slate-950 bg-slate-950 p-1 shadow-[0_18px_45px_rgba(15,23,42,0.18)]">
|
||||
<div className="overflow-hidden rounded-[19px] bg-white">
|
||||
<Image
|
||||
src="/screenshots/medications.png"
|
||||
alt="Medscribe medications screen"
|
||||
width={1206}
|
||||
height={2622}
|
||||
priority
|
||||
unoptimized
|
||||
className="block h-auto w-full"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mt-8 border-t border-teal-700/25 pt-5">
|
||||
<p className="northwell-print-label">What it can do</p>
|
||||
<h2 className="mt-2 font-serif text-[25px] leading-[1.12] font-semibold text-slate-950">
|
||||
Real medical AI, working entirely on the phone
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div className="mt-6 grid grid-cols-3 gap-x-7 gap-y-7">
|
||||
{capabilities.map(({ icon: Icon, title, body }) => (
|
||||
<div key={title}>
|
||||
<Icon className="size-5 text-teal-700" strokeWidth={1.75} />
|
||||
<h3 className="mt-2.5 font-serif text-[16px] leading-[1.15] font-semibold text-slate-950">
|
||||
{title}
|
||||
</h3>
|
||||
<p className="mt-1.5 text-[10px] leading-[1.5] text-slate-600">
|
||||
{body}
|
||||
</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="mt-8 grid grid-cols-3 gap-7 border-t border-teal-700/25 pt-5">
|
||||
{[
|
||||
[
|
||||
"On the device, not the cloud",
|
||||
"Summarization and medication Q&A run on the phone. No health data goes to a server for AI, so there is no new breach surface and no BAA.",
|
||||
],
|
||||
[
|
||||
"Facts first, not guesswork",
|
||||
"Drug facts, classes, and interaction pairs come from bundled reference data. The model helps phrase the answer; it does not invent it.",
|
||||
],
|
||||
[
|
||||
"Owned by the patient",
|
||||
"One record that spans every provider, that the patient controls, carries, and decides how to share.",
|
||||
],
|
||||
].map(([title, body]) => (
|
||||
<div key={title}>
|
||||
<p className="font-serif text-[14px] font-semibold text-slate-950">
|
||||
{title}
|
||||
</p>
|
||||
<p className="mt-1.5 text-[9.5px] leading-[1.5] text-slate-600">
|
||||
{body}
|
||||
</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</PrintPage>
|
||||
|
||||
<PrintPage page={2}>
|
||||
<section className="pt-3">
|
||||
<p className="northwell-print-label">Who it helps</p>
|
||||
<h2 className="northwell-print-title">Every capability pays off twice</h2>
|
||||
<p className="northwell-print-lede max-w-[660px]">
|
||||
The features that make Medscribe genuinely useful to the patient are
|
||||
the same ones that move the numbers CVS is measured on. Cross-provider
|
||||
by design; one central pharmacy in practice.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<div className="mt-6 grid grid-cols-[0.92fr_1.08fr] gap-8">
|
||||
<p className="text-[9px] font-bold tracking-[0.18em] text-slate-500 uppercase">
|
||||
For the patient
|
||||
</p>
|
||||
<p className="text-[9px] font-bold tracking-[0.18em] text-teal-700 uppercase">
|
||||
For CVS
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="mt-1">
|
||||
{payoffs.map((row) => (
|
||||
<div
|
||||
key={row.cvsTitle}
|
||||
className="grid grid-cols-[0.92fr_1.08fr] gap-8 border-t border-slate-200 py-3"
|
||||
>
|
||||
<div>
|
||||
<h3 className="font-serif text-[14px] leading-[1.2] font-semibold text-slate-950">
|
||||
{row.patientTitle}
|
||||
</h3>
|
||||
<p className="mt-1 text-[9.5px] leading-[1.45] text-slate-600">
|
||||
{row.patient}
|
||||
</p>
|
||||
</div>
|
||||
<div className="border-l border-teal-600/30 pl-8">
|
||||
<h3 className="font-serif text-[14px] leading-[1.2] font-semibold text-teal-900">
|
||||
{row.cvsTitle}
|
||||
</h3>
|
||||
<p className="mt-1 text-[9.5px] leading-[1.45] text-slate-600">
|
||||
{row.cvs}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<p className="mt-5 bg-teal-50/70 px-5 py-3 text-[10px] leading-[1.5] text-slate-700">
|
||||
<span className="font-semibold text-slate-900">
|
||||
It sits beside the CVS stack, not on top of it.{" "}
|
||||
</span>
|
||||
Dispensing, Caremark benefits, and the CVS app keep doing their jobs.
|
||||
Medscribe is the patient-owned layer that feeds value back in with
|
||||
consent. A partnership unlocks co-branding, refill routing, and
|
||||
adherence reporting against Star and EQuIPP measures.
|
||||
</p>
|
||||
|
||||
<section className="mt-6 grid grid-cols-[1.12fr_0.88fr] items-start gap-9 border-t border-slate-300 pt-5">
|
||||
<div>
|
||||
<p className="northwell-print-label">The ask</p>
|
||||
<h3 className="mt-3 font-serif text-[20px] leading-[1.22] font-semibold text-slate-950">
|
||||
A short conversation about a record that moves adherence and keeps
|
||||
refills at CVS.
|
||||
</h3>
|
||||
<p className="mt-2 text-[10.5px] leading-[1.5] text-slate-600">
|
||||
Live in beta on iOS and Android today. The core patient experience
|
||||
ships now; the business layer is what a partnership builds together.
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="northwell-print-label">Who is behind it</p>
|
||||
<h3 className="mt-3 font-serif text-[19px] font-semibold text-slate-950">
|
||||
Sean O'Connor
|
||||
</h3>
|
||||
<p className="mt-3 text-[10.5px] leading-[1.5] text-slate-600">
|
||||
A Bucknell computer science and engineering graduate who built
|
||||
Medscribe after watching his family lose the full picture of his
|
||||
grandfather's care.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
</PrintPage>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,120 +1,122 @@
|
||||
"use client";
|
||||
|
||||
import type { KeyboardEvent } from "react";
|
||||
import { useState } from "react";
|
||||
import {
|
||||
CalendarDays,
|
||||
Camera,
|
||||
Check,
|
||||
ContactRound,
|
||||
Home,
|
||||
MessageCircle,
|
||||
Shield,
|
||||
Pill,
|
||||
} from "lucide-react";
|
||||
|
||||
import { PhoneMockup } from "~/components/phone-mockup";
|
||||
import { cn } from "~/lib/utils";
|
||||
|
||||
const features = [
|
||||
{
|
||||
id: "home",
|
||||
label: "Profile",
|
||||
icon: Home,
|
||||
title: "One profile for the person you care for",
|
||||
description:
|
||||
"Visits, medications, reminders, and questions live together under the person they belong to.",
|
||||
points: [
|
||||
"Switch between everyone you care for",
|
||||
"One home for the whole picture",
|
||||
"Nothing scattered across apps",
|
||||
],
|
||||
image: "/screenshots/home.png",
|
||||
alt: "Medscribe home dashboard with record visit, search, medications, and ask shortcuts",
|
||||
},
|
||||
{
|
||||
id: "context",
|
||||
label: "Context",
|
||||
icon: ContactRound,
|
||||
title: "The context behind the handoff",
|
||||
description:
|
||||
"Conditions, medication changes, visit summaries, and caregiver notes stay close enough to become useful when time is short.",
|
||||
points: [
|
||||
"Baseline, allergies, and conditions up front",
|
||||
"Time-critical medications flagged",
|
||||
"A source trail behind each fact",
|
||||
],
|
||||
image: "/screenshots/emergency-record.png",
|
||||
alt: "Medscribe emergency record with critical care context",
|
||||
},
|
||||
{
|
||||
id: "visits",
|
||||
label: "Visits",
|
||||
icon: CalendarDays,
|
||||
title: "Visit recordings that refresh the record",
|
||||
title: "Turn a visit into context you can review",
|
||||
description:
|
||||
"A visit can become searchable context, so a medication change or follow-up instruction does not depend on memory alone.",
|
||||
"Type or paste notes, import a portal screenshot or document, or use consent-gated recording. The beta creates a local summary for the person to check.",
|
||||
points: [
|
||||
"Consent-gated, on-device recording",
|
||||
"Searchable transcript and summary",
|
||||
"Follow-ups captured, not forgotten",
|
||||
"Supported transcription and summarization run on device",
|
||||
"The person reviews generated information",
|
||||
"Structured visit-to-record change review is still roadmap",
|
||||
],
|
||||
image: "/screenshots/visit-timeline.png",
|
||||
alt: "Medscribe visit timeline with appointment cards",
|
||||
image: "/screenshots/visit-detail.png",
|
||||
alt: "Synthetic Medscribe beta visit detail showing a visit summary and follow-up information",
|
||||
},
|
||||
{
|
||||
id: "meds",
|
||||
label: "Meds",
|
||||
icon: Camera,
|
||||
title: "Medication OCR, reminders, and history",
|
||||
id: "medications",
|
||||
label: "Medications",
|
||||
icon: Pill,
|
||||
title: "Keep the daily medication picture close",
|
||||
description:
|
||||
"Prescription labels, reminders, refill alerts, and dose history help the family see what is supposed to happen and what actually happened.",
|
||||
"Scan a label, correct the extracted fields, set reminders, follow refills, and see a local intake history without asking a language model to invent drug facts.",
|
||||
points: [
|
||||
"Scan labels with the camera",
|
||||
"Reminders and refill alerts",
|
||||
"Dose history at a glance",
|
||||
"Label text remains editable before it becomes the record",
|
||||
"Bundled facts and known pairs use named reference datasets",
|
||||
"Coverage is intentionally bounded, not a complete interaction check",
|
||||
],
|
||||
image: "/screenshots/medications.png",
|
||||
alt: "Medscribe medications screen with active medications",
|
||||
image: "/screenshots/medication-detail.png",
|
||||
alt: "Synthetic Medscribe beta medication detail with schedule and medication information",
|
||||
},
|
||||
{
|
||||
id: "ask",
|
||||
label: "Ask",
|
||||
id: "questions",
|
||||
label: "Questions",
|
||||
icon: MessageCircle,
|
||||
title: "Medication questions grounded in the record",
|
||||
title: "Facts first, fluent answers second",
|
||||
description:
|
||||
"Plain-language questions can draw from the person's record and bundled FDA facts, while keeping diagnosis and dosing with clinicians.",
|
||||
"Medication questions can use the person’s local record and bundled fields. Dosing changes, diagnosis, and treatment decisions stay with a clinician or pharmacist.",
|
||||
points: [
|
||||
"Plain-language answers",
|
||||
"Grounded in the record and FDA facts",
|
||||
"Defers dosing and diagnosis to clinicians",
|
||||
"Known facts render from bundled data",
|
||||
"The local model helps with conversational phrasing",
|
||||
"High-risk or unsupported questions defer to a professional",
|
||||
],
|
||||
image: "/screenshots/chat.png",
|
||||
alt: "Medscribe Ask chat answering a question about blood pressure medications",
|
||||
image: "/screenshots/chat-response.png",
|
||||
alt: "Synthetic Medscribe beta answer with medication context and a safety boundary",
|
||||
},
|
||||
{
|
||||
id: "privacy",
|
||||
label: "Privacy",
|
||||
icon: Shield,
|
||||
title: "Private by architecture, not policy",
|
||||
id: "handoff",
|
||||
label: "Know Me",
|
||||
icon: ContactRound,
|
||||
title: "Prepare one readable handoff",
|
||||
description:
|
||||
"The sensitive work happens on device, so the family record is not another cloud inbox waiting to be mined.",
|
||||
"The Know Me view brings selected medications, allergies, conditions, baseline, and contacts together. Current, unconfirmed, and review-needed states make uncertainty visible.",
|
||||
points: [
|
||||
"On-device AI, no cloud processing",
|
||||
"No inbox to breach or mine",
|
||||
"You control what is ever shared",
|
||||
"Medication schedules can include source and confirmation",
|
||||
"The person can show or share the snapshot they reviewed",
|
||||
"It complements—not replaces—clinical verification",
|
||||
],
|
||||
image: "/screenshots/settings.png",
|
||||
alt: "Medscribe settings showing on-device AI models and privacy notice",
|
||||
image: "/screenshots/emergency-record.png",
|
||||
alt: "Synthetic Medscribe beta Know Me handoff with active medications and review state",
|
||||
},
|
||||
] as const;
|
||||
|
||||
type FeatureId = (typeof features)[number]["id"];
|
||||
|
||||
export function FeatureShowcase() {
|
||||
const [activeId, setActiveId] = useState<(typeof features)[number]["id"]>("home");
|
||||
const active = features.find((f) => f.id === activeId) ?? features[0];
|
||||
const [activeId, setActiveId] = useState<FeatureId>("visits");
|
||||
const active =
|
||||
features.find((feature) => feature.id === activeId) ?? features[0];
|
||||
|
||||
const onTabKeyDown = (event: KeyboardEvent<HTMLButtonElement>) => {
|
||||
const activeIndex = features.findIndex(
|
||||
(feature) => feature.id === activeId,
|
||||
);
|
||||
let nextIndex: number | undefined;
|
||||
|
||||
if (event.key === "ArrowRight" || event.key === "ArrowDown") {
|
||||
nextIndex = (activeIndex + 1) % features.length;
|
||||
} else if (event.key === "ArrowLeft" || event.key === "ArrowUp") {
|
||||
nextIndex = (activeIndex - 1 + features.length) % features.length;
|
||||
} else if (event.key === "Home") {
|
||||
nextIndex = 0;
|
||||
} else if (event.key === "End") {
|
||||
nextIndex = features.length - 1;
|
||||
}
|
||||
|
||||
if (nextIndex === undefined) return;
|
||||
|
||||
event.preventDefault();
|
||||
const nextFeature = features[nextIndex];
|
||||
if (!nextFeature) return;
|
||||
|
||||
setActiveId(nextFeature.id);
|
||||
document.getElementById(`feature-tab-${nextFeature.id}`)?.focus();
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="grid items-center gap-8 lg:grid-cols-[minmax(0,1fr)_300px] lg:gap-12">
|
||||
<div className="flex flex-col gap-5">
|
||||
<div className="flex flex-wrap gap-2">
|
||||
<div className="grid items-center gap-10 lg:grid-cols-[minmax(0,1fr)_340px] lg:gap-16">
|
||||
<div className="flex min-w-0 flex-col gap-6">
|
||||
<div
|
||||
role="tablist"
|
||||
aria-label="Explore the Medscribe beta"
|
||||
className="flex max-w-full gap-2 overflow-x-auto pb-1"
|
||||
>
|
||||
{features.map((feature) => {
|
||||
const Icon = feature.icon;
|
||||
const isActive = feature.id === activeId;
|
||||
@@ -122,49 +124,67 @@ export function FeatureShowcase() {
|
||||
return (
|
||||
<button
|
||||
key={feature.id}
|
||||
id={`feature-tab-${feature.id}`}
|
||||
type="button"
|
||||
role="tab"
|
||||
aria-selected={isActive}
|
||||
aria-controls={`feature-panel-${feature.id}`}
|
||||
tabIndex={isActive ? 0 : -1}
|
||||
onClick={() => setActiveId(feature.id)}
|
||||
onKeyDown={onTabKeyDown}
|
||||
className={cn(
|
||||
"inline-flex items-center gap-2 rounded-full border px-3 py-1.5 text-sm font-medium transition-all",
|
||||
"focus-visible:ring-primary/40 inline-flex min-h-11 shrink-0 items-center gap-2 rounded-full border px-4 py-2 text-sm font-semibold transition-colors outline-none focus-visible:ring-2",
|
||||
isActive
|
||||
? "border-primary-button bg-primary-button text-white shadow-sm"
|
||||
: "border-border-soft bg-surface text-muted-foreground hover:border-primary/20 hover:text-foreground",
|
||||
: "border-border-soft bg-surface text-muted-foreground hover:border-primary/30 hover:text-foreground",
|
||||
)}
|
||||
>
|
||||
<Icon className="size-4" />
|
||||
<Icon className="size-4" aria-hidden="true" />
|
||||
{feature.label}
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<h3 className="font-serif text-2xl font-semibold tracking-tight text-foreground sm:text-3xl">
|
||||
<div
|
||||
id={`feature-panel-${active.id}`}
|
||||
role="tabpanel"
|
||||
aria-labelledby={`feature-tab-${active.id}`}
|
||||
tabIndex={0}
|
||||
className="focus-visible:ring-primary/40 rounded-xl outline-none focus-visible:ring-2"
|
||||
>
|
||||
<p className="text-primary text-xs font-bold tracking-[0.14em] uppercase">
|
||||
Current beta
|
||||
</p>
|
||||
<h3 className="text-foreground mt-3 max-w-xl font-serif text-3xl font-semibold tracking-tight sm:text-4xl">
|
||||
{active.title}
|
||||
</h3>
|
||||
<p className="max-w-xl text-sm leading-relaxed text-muted-foreground sm:text-base">
|
||||
<p className="text-muted-foreground mt-4 max-w-xl leading-relaxed">
|
||||
{active.description}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<ul className="grid gap-x-5 gap-y-2.5 sm:grid-cols-2">
|
||||
{active.points.map((point) => (
|
||||
<li
|
||||
key={point}
|
||||
className="flex items-start gap-2 text-sm leading-snug text-foreground"
|
||||
>
|
||||
<span className="mt-0.5 flex size-4 shrink-0 items-center justify-center rounded-full bg-primary-light">
|
||||
<Check className="size-3 text-primary" />
|
||||
</span>
|
||||
<span>{point}</span>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
<ul className="mt-6 grid gap-3 sm:grid-cols-2">
|
||||
{active.points.map((point) => (
|
||||
<li
|
||||
key={point}
|
||||
className="text-foreground flex items-start gap-2.5 text-sm leading-relaxed"
|
||||
>
|
||||
<span className="bg-primary-light mt-0.5 flex size-5 shrink-0 items-center justify-center rounded-full">
|
||||
<Check className="text-primary size-3" aria-hidden="true" />
|
||||
</span>
|
||||
<span>{point}</span>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="justify-self-center lg:justify-self-end">
|
||||
<div className="flex items-center justify-center rounded-2xl border border-border-soft bg-gradient-to-b from-surface-soft to-primary-light/30 p-6 shadow-[0_18px_45px_rgba(15,23,42,0.10)]">
|
||||
<PhoneMockup src={active.image} alt={active.alt} width={188} />
|
||||
<div className="border-border-soft bg-surface-soft/80 rounded-[2.5rem] border p-5 shadow-[0_30px_80px_rgba(15,23,42,0.10)] sm:p-7">
|
||||
<PhoneMockup src={active.image} alt={active.alt} width={220} />
|
||||
<p className="text-muted-foreground mt-4 text-center text-xs">
|
||||
Synthetic demo data · beta interface
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,381 @@
|
||||
import Image from "next/image";
|
||||
|
||||
function PrintPage({
|
||||
page,
|
||||
children,
|
||||
}: Readonly<{ page: number; children: React.ReactNode }>) {
|
||||
return (
|
||||
<article
|
||||
className={
|
||||
page === 1
|
||||
? "northwell-print-page"
|
||||
: "northwell-print-page northwell-print-page--continuation"
|
||||
}
|
||||
>
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
<img className="northwell-print-wash" src="/print-wash.svg" alt="" />
|
||||
{page === 1 ? (
|
||||
<header className="northwell-print-header">
|
||||
<div className="flex items-center gap-2.5">
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
<img className="h-6 w-auto" src="/medscribe-ms-logo.svg" alt="" />
|
||||
<span className="font-serif text-[17px] font-semibold text-slate-950">
|
||||
Medscribe
|
||||
</span>
|
||||
</div>
|
||||
<span className="text-[9px] font-semibold tracking-[0.18em] text-slate-500 uppercase">
|
||||
Executive summary · Northwell Health
|
||||
</span>
|
||||
</header>
|
||||
) : null}
|
||||
|
||||
<div className="northwell-print-content">{children}</div>
|
||||
|
||||
<footer className="northwell-print-footer">
|
||||
<span>Page {page} of 3</span>
|
||||
</footer>
|
||||
</article>
|
||||
);
|
||||
}
|
||||
|
||||
const people = [
|
||||
[
|
||||
"The student on their own",
|
||||
"Managing prescriptions and appointments for the first time, away from the parent who used to track it all.",
|
||||
],
|
||||
[
|
||||
"The newly diagnosed",
|
||||
"A new routine, new instructions, and follow-ups that are a blur by the next visit.",
|
||||
],
|
||||
[
|
||||
"The long-distance caregiver",
|
||||
"An adult child coordinating a parent's medications with siblings who cover different days.",
|
||||
],
|
||||
[
|
||||
"The emergency",
|
||||
"An older patient at an out-of-network ER, where no one has met them or knows which medications cannot be delayed.",
|
||||
],
|
||||
] as const;
|
||||
|
||||
const productPillars = [
|
||||
[
|
||||
"Capture visits",
|
||||
"Type or paste notes, import a portal screenshot, attach a document, or use consent-gated recording. Summarization stays on device.",
|
||||
],
|
||||
[
|
||||
"Keep medications current",
|
||||
"Pill-bottle label recognition, reminders, refill tracking, dose history, and questions grounded in bundled FDA facts.",
|
||||
],
|
||||
[
|
||||
"Be ready to hand off",
|
||||
"A patient-controlled Know Me record and encrypted caregiver sharing keep critical context ready when the chart is incomplete.",
|
||||
],
|
||||
] as const;
|
||||
|
||||
const northwellFit = [
|
||||
[
|
||||
"AI patients can trust",
|
||||
"Visit summarization and medication Q&A run on the phone, while medication facts come from bundled reference data rather than model recall. It is a clear AI posture for patients, privacy teams, and clinicians.",
|
||||
],
|
||||
[
|
||||
"A Northwell story worth telling",
|
||||
"Northwell can lead with a concrete patient benefit: one private, emergency-ready picture that travels across systems. The experience could carry Northwell's brand without pretending to replace MyChart.",
|
||||
],
|
||||
[
|
||||
"An everyday touchstone",
|
||||
"Reminders, refills, dose tracking, questions, and record updates create useful reasons to return between appointments. Each moment can point the patient back to the Northwell care team.",
|
||||
],
|
||||
] as const;
|
||||
|
||||
const recordContents = [
|
||||
"Active medications, doses, schedules, and refill status",
|
||||
"Allergies, conditions, baseline, and the context that changes a handoff",
|
||||
"Visit summaries, follow-up instructions, and questions for the next visit",
|
||||
"Emergency contacts and a concise, patient-controlled Know Me record",
|
||||
] as const;
|
||||
|
||||
export function NorthwellPrintSummary() {
|
||||
return (
|
||||
<div className="northwell-print-only" aria-hidden="true">
|
||||
<PrintPage page={1}>
|
||||
<div className="grid grid-cols-[1.16fr_0.84fr] items-start gap-9 pt-5">
|
||||
<div>
|
||||
<p className="northwell-print-label">The patient-owned record</p>
|
||||
<h1 className="mt-4 font-serif text-[44px] leading-[0.98] font-semibold tracking-[-0.035em] text-slate-950">
|
||||
Be known when care gets complicated
|
||||
</h1>
|
||||
<p className="mt-5 text-[16px] leading-[1.55] text-slate-600">
|
||||
Medscribe keeps a patient's medications, visits, baseline,
|
||||
and critical care context current between appointments, then makes
|
||||
that picture ready for a caregiver, a new doctor, or an ER.
|
||||
</p>
|
||||
<div className="mt-6 grid grid-cols-2 gap-x-5 gap-y-2 text-[8.5px] font-bold tracking-[0.08em] text-slate-600 uppercase">
|
||||
{[
|
||||
"On-device AI",
|
||||
"Emergency-ready",
|
||||
"Patient-owned",
|
||||
"iOS and Android beta",
|
||||
].map((badge) => (
|
||||
<span key={badge} className="flex items-center gap-2">
|
||||
<span className="size-1 rounded-full bg-teal-600" />
|
||||
{badge}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mx-auto w-[194px] rounded-[28px] border-[6px] border-slate-950 bg-slate-950 p-1 shadow-[0_18px_45px_rgba(15,23,42,0.18)]">
|
||||
<div className="overflow-hidden rounded-[19px] bg-white">
|
||||
<Image
|
||||
src="/screenshots/home.png"
|
||||
alt="Medscribe home screen"
|
||||
width={1206}
|
||||
height={2622}
|
||||
priority
|
||||
unoptimized
|
||||
className="block h-auto w-full"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mt-7 border-t border-teal-700/25 pt-5">
|
||||
<p className="northwell-print-label">The job</p>
|
||||
<p className="mt-3 font-serif text-[25px] leading-[1.2] font-semibold text-slate-950">
|
||||
One trustworthy picture that survives fragmented care, missed
|
||||
appointments, secondhand updates, and emergency handoffs.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="mt-6 grid grid-cols-3 gap-5">
|
||||
{[
|
||||
[
|
||||
"Keep it current",
|
||||
"Everyday visit and medication workflows maintain the record.",
|
||||
],
|
||||
[
|
||||
"Make it obvious",
|
||||
"Time-critical medications and baseline context rise to the top.",
|
||||
],
|
||||
[
|
||||
"Keep it controlled",
|
||||
"The patient decides what is shared, when, and with whom.",
|
||||
],
|
||||
].map(([title, body]) => (
|
||||
<div key={title} className="pr-3">
|
||||
<p className="font-serif text-[16px] font-semibold text-slate-950">
|
||||
{title}
|
||||
</p>
|
||||
<p className="mt-2 text-[10.5px] leading-[1.5] text-slate-600">
|
||||
{body}
|
||||
</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="mt-6 grid grid-cols-[0.72fr_1.28fr] gap-5">
|
||||
<div>
|
||||
<p className="northwell-print-label">One living picture</p>
|
||||
<p className="mt-2 text-[10.5px] leading-[1.5] text-slate-600">
|
||||
The record is useful in an emergency because ordinary use keeps it
|
||||
from becoming a stale export.
|
||||
</p>
|
||||
</div>
|
||||
<ul className="grid grid-cols-2 gap-x-5 gap-y-2 text-[9.5px] leading-[1.45] text-slate-600">
|
||||
{recordContents.map((item) => (
|
||||
<li
|
||||
key={item}
|
||||
className="relative pl-3 before:absolute before:top-[0.42em] before:left-0 before:size-1 before:rounded-full before:bg-teal-500 before:content-['']"
|
||||
>
|
||||
{item}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</PrintPage>
|
||||
|
||||
<PrintPage page={2}>
|
||||
<section className="pt-3">
|
||||
<p className="northwell-print-label">What it is</p>
|
||||
<h2 className="northwell-print-title">
|
||||
A medical record the patient owns and carries
|
||||
</h2>
|
||||
<p className="northwell-print-lede">
|
||||
The daily tools are not separate features. They are the maintenance
|
||||
system for one emergency-ready record.
|
||||
</p>
|
||||
<div className="mt-5 grid grid-cols-3 gap-5">
|
||||
{productPillars.map(([title, body], index) => (
|
||||
<div key={title} className="min-h-[120px] pr-3">
|
||||
<span className="text-[10px] font-bold text-teal-700">
|
||||
0{index + 1}
|
||||
</span>
|
||||
<h3 className="mt-2 font-serif text-[17px] font-semibold text-slate-950">
|
||||
{title}
|
||||
</h3>
|
||||
<p className="mt-2 text-[10.5px] leading-[1.5] text-slate-600">
|
||||
{body}
|
||||
</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="mt-7">
|
||||
<p className="northwell-print-label">Who it is for</p>
|
||||
<h2 className="northwell-print-title">
|
||||
Anyone holding care together
|
||||
</h2>
|
||||
<div className="mt-4 grid grid-cols-2 gap-x-7 gap-y-2">
|
||||
{people.map(([title, body]) => (
|
||||
<div key={title} className="min-h-[70px] pr-4">
|
||||
<h3 className="font-serif text-[15px] font-semibold text-slate-950">
|
||||
{title}
|
||||
</h3>
|
||||
<p className="mt-1.5 text-[10.5px] leading-[1.45] text-slate-600">
|
||||
{body}
|
||||
</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="mt-7 border-l-4 border-teal-600 bg-teal-50/50 py-5 pr-5 pl-6">
|
||||
<p className="northwell-print-label">What makes it different</p>
|
||||
<h2 className="mt-3 font-serif text-[24px] font-semibold text-slate-950">
|
||||
Every alternative owns a slice. Medscribe owns the whole job.
|
||||
</h2>
|
||||
<div className="mt-3 grid grid-cols-2 gap-6 text-[10.5px] leading-[1.55] text-slate-600">
|
||||
<p>
|
||||
Every institutional record stops at its own walls. Epic aggregates
|
||||
Epic; urgent care, community specialists, and facilities on other
|
||||
systems can still sit outside the picture in front of a clinician.
|
||||
</p>
|
||||
<p>
|
||||
Visit notetakers, medication trackers, record vaults, and
|
||||
emergency IDs each solve one slice. Medscribe connects daily
|
||||
maintenance to the handoff across Epic and non-Epic care, on the
|
||||
patient's device and under the patient's control.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="mt-5 grid grid-cols-2 gap-7 border-t border-slate-300 pt-5">
|
||||
<div>
|
||||
<p className="northwell-print-label">Facts first</p>
|
||||
<p className="mt-2 text-[10px] leading-[1.5] text-slate-600">
|
||||
Medication facts, drug classes, and known interaction pairs come
|
||||
from bundled reference data. The language model helps with
|
||||
phrasing; it is not treated as the source of medical facts.
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="northwell-print-label">Local by default</p>
|
||||
<p className="mt-2 text-[10px] leading-[1.5] text-slate-600">
|
||||
Visit summarization and medication Q&A run on the phone.
|
||||
Caregiver sharing is end-to-end encrypted, so a server is not
|
||||
asked to read the patient's record in order to coordinate
|
||||
care.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
</PrintPage>
|
||||
|
||||
<PrintPage page={3}>
|
||||
<section className="pt-3">
|
||||
<p className="northwell-print-label">The Northwell opportunity</p>
|
||||
<h2 className="northwell-print-title">
|
||||
A trusted AI touchstone between visits
|
||||
</h2>
|
||||
<p className="northwell-print-lede max-w-[650px]">
|
||||
Medscribe gives Northwell a useful presence in the part of care no
|
||||
portal owns: the ordinary days when patients remember, refill,
|
||||
question, coordinate, and try to follow the plan.
|
||||
</p>
|
||||
<div className="mt-6 grid grid-cols-3 gap-7">
|
||||
{northwellFit.map(([title, body], index) => (
|
||||
<div key={title}>
|
||||
<span className="text-[10px] font-bold text-teal-700">
|
||||
0{index + 1}
|
||||
</span>
|
||||
<h3 className="font-serif text-[16px] font-semibold text-slate-950">
|
||||
{title}
|
||||
</h3>
|
||||
<p className="mt-2 text-[10px] leading-[1.55] text-slate-600">
|
||||
{body}
|
||||
</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="mt-7 bg-teal-50/60 px-6 py-5">
|
||||
<p className="northwell-print-label">The touchstone</p>
|
||||
<h2 className="mt-2 font-serif text-[24px] leading-[1.18] font-semibold text-slate-950">
|
||||
MyChart organizes the appointment. Medscribe helps the patient live
|
||||
the plan.
|
||||
</h2>
|
||||
<p className="mt-3 text-[11px] leading-[1.55] text-slate-600">
|
||||
A reminder, a refill, a quick question, or an update to the record
|
||||
becomes a small moment of continuity. Presented as part of the
|
||||
Northwell experience, those moments can reinforce the care plan and
|
||||
point the patient back to the team that knows them.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section className="mt-6 border-t border-slate-300 pt-5">
|
||||
<p className="northwell-print-label">How it fits the stack</p>
|
||||
<div className="mt-4 grid grid-cols-2 gap-9">
|
||||
<div>
|
||||
<h3 className="font-serif text-[16px] font-semibold text-slate-950">
|
||||
Epic remains the record of care
|
||||
</h3>
|
||||
<p className="mt-2 text-[10.5px] leading-[1.55] text-slate-600">
|
||||
Northwell's clinical workflows, orders, results, messages,
|
||||
and institutional history stay where they belong. Medscribe is
|
||||
not another EHR and does not need to displace MyChart.
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="font-serif text-[16px] font-semibold text-slate-950">
|
||||
The patient carries the missing context
|
||||
</h3>
|
||||
<p className="mt-2 text-[10.5px] leading-[1.55] text-slate-600">
|
||||
Non-Epic visits, medication changes, caregiver knowledge, and
|
||||
emergency context stay with the patient. Consent governs when
|
||||
that picture is shared back into a Northwell interaction.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="mt-6 grid grid-cols-[1.12fr_0.88fr] gap-9 border-t border-slate-300 pt-5">
|
||||
<div>
|
||||
<p className="northwell-print-label">The marketing value</p>
|
||||
<h3 className="mt-3 font-serif text-[19px] leading-[1.25] font-semibold text-slate-950">
|
||||
A patient promise people can understand
|
||||
</h3>
|
||||
<p className="mt-2 text-[10.5px] leading-[1.5] text-slate-600">
|
||||
Private AI. One current picture. Ready for the caregiver, the new
|
||||
doctor, or the ER. That is a more human story than “AI in
|
||||
healthcare,” and it gives Northwell a visible way to stand
|
||||
for continuity beyond its own walls.
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="northwell-print-label">Built and live</p>
|
||||
<h3 className="mt-3 font-serif text-[19px] font-semibold text-slate-950">
|
||||
Sean O'Connor
|
||||
</h3>
|
||||
<p className="mt-3 text-[10.5px] leading-[1.5] text-slate-600">
|
||||
A Bucknell computer science and engineering graduate who built
|
||||
Medscribe after watching his family lose the full picture of his
|
||||
grandfather's care. The product is live in beta on iOS and
|
||||
Android today.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
</PrintPage>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,7 +1,4 @@
|
||||
"use client";
|
||||
|
||||
import Image from "next/image";
|
||||
import { IPhoneMockup } from "react-device-mockup";
|
||||
|
||||
import { cn } from "~/lib/utils";
|
||||
|
||||
@@ -27,33 +24,26 @@ export function PhoneMockup({
|
||||
const isSimulatorCapture = captureMode === "simulator";
|
||||
|
||||
return (
|
||||
<div className={cn("mx-auto w-fit drop-shadow-[0_18px_45px_rgba(15,23,42,0.14)]", className)}>
|
||||
<IPhoneMockup
|
||||
screenWidth={width}
|
||||
screenType="island"
|
||||
frameColor="#111827"
|
||||
statusbarColor="#f8fafc"
|
||||
hideStatusBar
|
||||
hideNavBar
|
||||
transparentNavBar
|
||||
>
|
||||
<div className="relative h-full w-full overflow-hidden bg-surface">
|
||||
<Image
|
||||
src={src}
|
||||
alt={alt}
|
||||
width={1206}
|
||||
height={2622}
|
||||
priority={priority}
|
||||
unoptimized
|
||||
className={cn(
|
||||
"h-full w-full object-cover",
|
||||
isSimulatorCapture
|
||||
? "scale-[1.22] object-[50%_58%]"
|
||||
: "object-top",
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
</IPhoneMockup>
|
||||
<div
|
||||
className={cn(
|
||||
"mx-auto overflow-hidden rounded-[2.25rem] border-[7px] border-slate-950 bg-slate-950 p-1 shadow-[0_24px_60px_rgba(15,23,42,0.18)]",
|
||||
className,
|
||||
)}
|
||||
style={{ width }}
|
||||
>
|
||||
<div className="bg-surface relative aspect-[1206/2622] overflow-hidden rounded-[1.65rem]">
|
||||
<Image
|
||||
src={src}
|
||||
alt={alt}
|
||||
fill
|
||||
priority={priority}
|
||||
sizes={`${width}px`}
|
||||
className={cn(
|
||||
"object-cover",
|
||||
isSimulatorCapture ? "scale-[1.22] object-[50%_58%]" : "object-top",
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
import Image from "next/image";
|
||||
|
||||
import { cn } from "~/lib/utils";
|
||||
|
||||
type ProductDeviceProps = {
|
||||
src: string;
|
||||
alt: string;
|
||||
className?: string;
|
||||
sizes?: string;
|
||||
priority?: boolean;
|
||||
};
|
||||
|
||||
/**
|
||||
* A precomposited product capture using the licensed device bezels in
|
||||
* `public/screenshots/pitch`. Keeping the frame in the source image preserves
|
||||
* the bezel details without adding layout or client-side work.
|
||||
*/
|
||||
export function ProductDevice({
|
||||
src,
|
||||
alt,
|
||||
className,
|
||||
sizes = "(min-width: 1024px) 360px, (min-width: 640px) 320px, 72vw",
|
||||
priority = false,
|
||||
}: ProductDeviceProps) {
|
||||
return (
|
||||
<Image
|
||||
src={src}
|
||||
alt={alt}
|
||||
width={810}
|
||||
height={1656}
|
||||
sizes={sizes}
|
||||
priority={priority}
|
||||
className={cn(
|
||||
"h-auto w-full drop-shadow-[0_35px_35px_rgba(15,23,42,0.22)] dark:drop-shadow-[0_38px_42px_rgba(0,0,0,0.5)]",
|
||||
className,
|
||||
)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -1,6 +1,19 @@
|
||||
export function SectionLabel({ children }: { children: React.ReactNode }) {
|
||||
import { cn } from "~/lib/utils";
|
||||
|
||||
export function SectionLabel({
|
||||
children,
|
||||
className,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
className?: string;
|
||||
}) {
|
||||
return (
|
||||
<p className="text-xs font-semibold tracking-widest text-muted-foreground uppercase">
|
||||
<p
|
||||
className={cn(
|
||||
"text-muted-foreground text-xs font-semibold tracking-widest uppercase",
|
||||
className,
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
</p>
|
||||
);
|
||||
|
||||
@@ -1,24 +1,69 @@
|
||||
import Link from "next/link";
|
||||
|
||||
import { MedscribeLogo } from "~/components/medscribe-logo";
|
||||
|
||||
const footerLinks = [
|
||||
{ href: "/how-it-works", label: "How it works" },
|
||||
{ href: "/privacy", label: "Privacy & evidence" },
|
||||
{ href: "/beta", label: "Beta access" },
|
||||
] as const;
|
||||
|
||||
export function SiteFooter() {
|
||||
return (
|
||||
<footer className="print-hidden border-t border-border-soft bg-surface/70">
|
||||
<div className="mx-auto flex max-w-5xl flex-col gap-4 px-4 py-10 text-sm text-muted-foreground sm:px-6 sm:flex-row sm:items-center sm:justify-between">
|
||||
<footer className="print-hidden border-border-soft bg-surface/80 border-t">
|
||||
<div className="mx-auto grid max-w-6xl gap-10 px-4 py-12 text-sm sm:px-6 md:grid-cols-[1.3fr_0.7fr_0.7fr]">
|
||||
<div>
|
||||
<p className="font-serif text-base font-semibold text-foreground">Medscribe</p>
|
||||
<p className="mt-1 max-w-md leading-relaxed">
|
||||
Be known when care gets complicated.
|
||||
<Link
|
||||
href="/"
|
||||
className="text-foreground focus-visible:ring-primary/40 inline-flex items-center gap-2.5 rounded-md outline-none focus-visible:ring-2"
|
||||
>
|
||||
<MedscribeLogo className="h-7 w-auto" />
|
||||
<span className="font-serif text-lg font-semibold">Medscribe</span>
|
||||
</Link>
|
||||
<p className="text-muted-foreground mt-4 max-w-md leading-relaxed">
|
||||
A private, patient-controlled beta for keeping visits, medications,
|
||||
and critical context together on the device you carry.
|
||||
</p>
|
||||
<p className="text-muted-foreground mt-3 text-xs leading-relaxed">
|
||||
Medscribe does not diagnose, prescribe, or replace emergency
|
||||
services or a clinician's verification.
|
||||
</p>
|
||||
</div>
|
||||
<div className="sm:text-right">
|
||||
<p>
|
||||
|
||||
<nav aria-label="Footer product navigation">
|
||||
<p className="text-foreground font-semibold">Product</p>
|
||||
<ul className="text-muted-foreground mt-3 space-y-2.5">
|
||||
{footerLinks.map((item) => (
|
||||
<li key={item.href}>
|
||||
<Link
|
||||
href={item.href}
|
||||
className="hover:text-foreground focus-visible:ring-primary/40 rounded-sm underline-offset-4 outline-none hover:underline focus-visible:ring-2"
|
||||
>
|
||||
{item.label}
|
||||
</Link>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<div>
|
||||
<p className="text-foreground font-semibold">Contact</p>
|
||||
<p className="text-muted-foreground mt-3 leading-relaxed">
|
||||
Built by{" "}
|
||||
<a
|
||||
href="https://soconnor.dev"
|
||||
className="text-foreground underline-offset-4 hover:underline"
|
||||
className="text-foreground focus-visible:ring-primary/40 rounded-sm underline-offset-4 outline-none hover:underline focus-visible:ring-2"
|
||||
>
|
||||
Sean O'Connor
|
||||
</a>
|
||||
</p>
|
||||
<p className="mt-1 text-xs text-muted-foreground/80">
|
||||
<a
|
||||
href="mailto:sean@soconnor.dev?subject=Medscribe%20website%20question"
|
||||
className="text-foreground focus-visible:ring-primary/40 mt-2 inline-block rounded-sm underline-offset-4 outline-none hover:underline focus-visible:ring-2"
|
||||
>
|
||||
sean@soconnor.dev
|
||||
</a>
|
||||
<p className="text-muted-foreground/80 mt-5 text-xs">
|
||||
© {new Date().getFullYear()} Hadlock Holdings LLC
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -1,26 +1,73 @@
|
||||
import { Menu } from "lucide-react";
|
||||
import Link from "next/link";
|
||||
|
||||
import { MedscribeLogo } from "~/components/medscribe-logo";
|
||||
import { Button } from "~/components/ui/button";
|
||||
|
||||
const navigation = [
|
||||
{ href: "/how-it-works", label: "How it works" },
|
||||
{ href: "/privacy", label: "Privacy & evidence" },
|
||||
] as const;
|
||||
|
||||
export function SiteHeader() {
|
||||
return (
|
||||
<header className="print-hidden sticky top-3 z-50 px-3 sm:px-6">
|
||||
<div className="relative mx-auto max-w-5xl">
|
||||
<div className="relative flex h-14 items-center rounded-full border border-border-soft/80 bg-canvas/82 px-4 shadow-[0_10px_30px_rgba(15,23,42,0.08)] backdrop-blur-md sm:px-5">
|
||||
<Link
|
||||
href="/"
|
||||
className="relative z-10 flex items-center text-foreground transition-opacity hover:opacity-80"
|
||||
aria-label="Medscribe home"
|
||||
>
|
||||
<MedscribeLogo className="h-7 w-auto" />
|
||||
</Link>
|
||||
<p className="pointer-events-none absolute inset-x-0 text-center font-serif text-lg font-semibold tracking-tight text-foreground">
|
||||
<header className="print-hidden border-border-soft/70 bg-canvas/88 sticky top-0 z-50 border-b backdrop-blur-lg">
|
||||
<div className="mx-auto flex h-16 max-w-6xl items-center gap-5 px-4 sm:px-6">
|
||||
<Link
|
||||
href="/"
|
||||
className="text-foreground focus-visible:ring-primary/40 flex shrink-0 items-center gap-2.5 rounded-md transition-opacity outline-none hover:opacity-75 focus-visible:ring-2"
|
||||
aria-label="Medscribe home"
|
||||
>
|
||||
<MedscribeLogo className="h-7 w-auto" />
|
||||
<span className="font-serif text-lg font-semibold tracking-tight">
|
||||
Medscribe
|
||||
</p>
|
||||
<span className="relative z-10 ml-auto hidden text-xs font-medium tracking-[0.14em] text-muted-foreground uppercase sm:inline">
|
||||
Executive summary
|
||||
</span>
|
||||
</div>
|
||||
</Link>
|
||||
|
||||
<nav
|
||||
aria-label="Primary navigation"
|
||||
className="ml-auto hidden items-center gap-1 md:flex"
|
||||
>
|
||||
{navigation.map((item) => (
|
||||
<Link
|
||||
key={item.href}
|
||||
href={item.href}
|
||||
className="text-muted-foreground hover:bg-surface-soft hover:text-foreground focus-visible:ring-primary/40 rounded-lg px-3 py-2 text-sm font-medium transition-colors outline-none focus-visible:ring-2"
|
||||
>
|
||||
{item.label}
|
||||
</Link>
|
||||
))}
|
||||
<Button asChild size="sm" className="ml-2">
|
||||
<Link href="/beta">Request beta access</Link>
|
||||
</Button>
|
||||
</nav>
|
||||
|
||||
<details className="group relative ml-auto md:hidden">
|
||||
<summary className="border-border-soft bg-surface text-foreground focus-visible:ring-primary/40 flex size-11 cursor-pointer list-none items-center justify-center rounded-xl border outline-none marker:content-none focus-visible:ring-2 [&::-webkit-details-marker]:hidden">
|
||||
<Menu className="size-5" aria-hidden="true" />
|
||||
<span className="sr-only">Open navigation</span>
|
||||
</summary>
|
||||
<nav
|
||||
aria-label="Mobile navigation"
|
||||
className="border-border-soft bg-surface absolute top-13 right-0 flex w-64 flex-col rounded-2xl border p-2 shadow-[0_18px_50px_rgba(15,23,42,0.16)]"
|
||||
>
|
||||
{navigation.map((item) => (
|
||||
<Link
|
||||
key={item.href}
|
||||
href={item.href}
|
||||
className="text-foreground hover:bg-surface-soft focus-visible:ring-primary/40 rounded-xl px-4 py-3 text-sm font-medium outline-none focus-visible:ring-2"
|
||||
>
|
||||
{item.label}
|
||||
</Link>
|
||||
))}
|
||||
<Link
|
||||
href="/beta"
|
||||
className="bg-primary-button hover:bg-primary-button/90 focus-visible:ring-primary/40 mt-1 rounded-xl px-4 py-3 text-center text-sm font-semibold text-white outline-none focus-visible:ring-2"
|
||||
>
|
||||
Request beta access
|
||||
</Link>
|
||||
</nav>
|
||||
</details>
|
||||
</div>
|
||||
</header>
|
||||
);
|
||||
|
||||
@@ -5,7 +5,7 @@ import { cva, type VariantProps } from "class-variance-authority";
|
||||
import { cn } from "~/lib/utils";
|
||||
|
||||
const buttonVariants = cva(
|
||||
"inline-flex shrink-0 items-center justify-center gap-2 rounded-[14px] text-sm font-semibold whitespace-nowrap transition-all outline-none focus-visible:ring-2 focus-visible:ring-primary/30 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0",
|
||||
"print-hidden inline-flex shrink-0 items-center justify-center gap-2 rounded-[14px] text-sm font-semibold whitespace-nowrap transition-all outline-none focus-visible:ring-2 focus-visible:ring-primary/30 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0",
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
|
||||
@@ -0,0 +1,308 @@
|
||||
import Image from "next/image";
|
||||
import {
|
||||
HeartPulse,
|
||||
Layers,
|
||||
Mic,
|
||||
MessageSquare,
|
||||
ScanLine,
|
||||
ShieldCheck,
|
||||
} from "lucide-react";
|
||||
|
||||
/**
|
||||
* Pharmacy-specific print summary (Walgreens variant). Page 1 (the product) is
|
||||
* identical to the CVS piece; page 2's "For Walgreens" column reflects that
|
||||
* Walgreens does not own a PBM or insurer the way CVS owns Caremark and Aetna,
|
||||
* so adherence and cost value flow to pharmacy performance reimbursement and to
|
||||
* Walgreens' plan and value-based-care partners, not an owned plan.
|
||||
* Reuses the `northwell-print-*` sheet/label classes from globals.css as the
|
||||
* page frame only.
|
||||
*/
|
||||
|
||||
function PrintPage({
|
||||
page,
|
||||
children,
|
||||
}: Readonly<{ page: number; children: React.ReactNode }>) {
|
||||
return (
|
||||
<article
|
||||
className={
|
||||
page === 1
|
||||
? "northwell-print-page"
|
||||
: "northwell-print-page northwell-print-page--continuation"
|
||||
}
|
||||
>
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
<img className="northwell-print-wash" src="/print-wash.svg" alt="" />
|
||||
{page === 1 ? (
|
||||
<header className="northwell-print-header">
|
||||
<div className="flex items-center gap-2.5">
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
<img className="h-6 w-auto" src="/medscribe-ms-logo.svg" alt="" />
|
||||
<span className="font-serif text-[17px] font-semibold text-slate-950">
|
||||
Medscribe
|
||||
</span>
|
||||
</div>
|
||||
<span className="text-[9px] font-semibold tracking-[0.18em] text-slate-500 uppercase">
|
||||
Executive summary · Walgreens
|
||||
</span>
|
||||
</header>
|
||||
) : null}
|
||||
|
||||
<div className="northwell-print-content">{children}</div>
|
||||
|
||||
<footer className="northwell-print-footer">
|
||||
<span>Page {page} of 2</span>
|
||||
</footer>
|
||||
</article>
|
||||
);
|
||||
}
|
||||
|
||||
const capabilities = [
|
||||
{
|
||||
icon: Mic,
|
||||
title: "Understand a visit",
|
||||
body: "Type, paste, snap the after-visit summary, or record the conversation with consent. Medscribe transcribes and summarizes it on the phone.",
|
||||
},
|
||||
{
|
||||
icon: ScanLine,
|
||||
title: "Read a pill bottle",
|
||||
body: "Point the camera at a prescription label and the drug, dose, and schedule land in the record automatically.",
|
||||
},
|
||||
{
|
||||
icon: MessageSquare,
|
||||
title: "Answer the hard questions",
|
||||
body: "Ask whether two medications are safe together and get an answer grounded in bundled FDA drug facts and known interaction pairs, not a chatbot's guess.",
|
||||
},
|
||||
{
|
||||
icon: Layers,
|
||||
title: "Hold the whole picture",
|
||||
body: "Medications, allergies, conditions, baseline, and visit history across every provider and pharmacy, in one place the patient owns.",
|
||||
},
|
||||
{
|
||||
icon: HeartPulse,
|
||||
title: "Be ready for an emergency",
|
||||
body: "A patient-controlled Know Me card puts the time-critical facts one tap away for a caregiver or an ER.",
|
||||
},
|
||||
{
|
||||
icon: ShieldCheck,
|
||||
title: "Share without exposure",
|
||||
body: "End-to-end encrypted sharing lets a caregiver help, without a server ever reading the record.",
|
||||
},
|
||||
] as const;
|
||||
|
||||
const payoffs = [
|
||||
{
|
||||
patientTitle: "One picture, everywhere they are treated",
|
||||
patient:
|
||||
"Nothing falls through the cracks between a specialist, an urgent care, and the pharmacy.",
|
||||
bizTitle: "One central pharmacy",
|
||||
biz: "Refills route back to Walgreens and scattered scripts consolidate, instead of leaking to Amazon, CVS, Cost Plus, or mail order. Share of scripts, won.",
|
||||
},
|
||||
{
|
||||
patientTitle: "Medications that fit their day",
|
||||
patient:
|
||||
"Reminders and refill nudges that actually help, so they stay on their medications.",
|
||||
bizTitle: "Pharmacy quality and Star Ratings",
|
||||
biz: "The diabetes, hypertension, and statin adherence measures are triple-weighted in Part D Star Ratings, which drives performance reimbursement (EQuIPP, performance-based networks) and quality for the plans Walgreens serves.",
|
||||
},
|
||||
{
|
||||
patientTitle: "Fewer dangerous surprises",
|
||||
patient:
|
||||
"Interactions and duplicate prescriptions caught across every prescriber, not one pharmacy's slice.",
|
||||
bizTitle: "Lower cost of care",
|
||||
biz: "Fewer adverse events and ER visits: medical spend saved for the plan and value-based-care partners Walgreens shares members with.",
|
||||
},
|
||||
{
|
||||
patientTitle: "Ready at the counter",
|
||||
patient:
|
||||
"They arrive with a clean list and their routine questions already answered.",
|
||||
bizTitle: "Pharmacist leverage",
|
||||
biz: "Less low-value counter volume, more time for the billable MTM and CMR work pharmacists already do.",
|
||||
},
|
||||
{
|
||||
patientTitle: "A tool that is theirs",
|
||||
patient:
|
||||
"An advocate they control, on their own device. Not a sales pitch, and never on a server.",
|
||||
bizTitle: "Engagement without the liability",
|
||||
biz: "A Walgreens-branded habit patients actually open through myWalgreens, with no PHI on a server: no new breach surface and no BAA to negotiate.",
|
||||
},
|
||||
] as const;
|
||||
|
||||
export function WalgreensPrintSummary() {
|
||||
return (
|
||||
<div className="northwell-print-only" aria-hidden="true">
|
||||
<PrintPage page={1}>
|
||||
<div className="grid grid-cols-[1.16fr_0.84fr] items-start gap-9 pt-5">
|
||||
<div>
|
||||
<p className="northwell-print-label">What Medscribe is</p>
|
||||
<h1 className="mt-4 font-serif text-[40px] leading-[1.0] font-semibold tracking-[-0.035em] text-slate-950">
|
||||
It captures, understands, and carries the patient's whole
|
||||
medical picture.
|
||||
</h1>
|
||||
<p className="mt-5 text-[15px] leading-[1.55] text-slate-600">
|
||||
Real medical AI on the patient's phone. Medscribe summarizes
|
||||
visits, reads pill bottles, answers medication questions from
|
||||
bundled drug facts, and keeps one emergency-ready record across
|
||||
every doctor and pharmacy. Nothing is sent to the cloud.
|
||||
</p>
|
||||
<div className="mt-6 grid grid-cols-2 gap-x-5 gap-y-2 text-[8.5px] font-bold tracking-[0.08em] text-slate-600 uppercase">
|
||||
{[
|
||||
"On-device AI",
|
||||
"Facts-first",
|
||||
"Patient-owned",
|
||||
"iOS and Android beta",
|
||||
].map((badge) => (
|
||||
<span key={badge} className="flex items-center gap-2">
|
||||
<span className="size-1 rounded-full bg-teal-600" />
|
||||
{badge}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mx-auto w-[186px] rounded-[28px] border-[6px] border-slate-950 bg-slate-950 p-1 shadow-[0_18px_45px_rgba(15,23,42,0.18)]">
|
||||
<div className="overflow-hidden rounded-[19px] bg-white">
|
||||
<Image
|
||||
src="/screenshots/medications.png"
|
||||
alt="Medscribe medications screen"
|
||||
width={1206}
|
||||
height={2622}
|
||||
priority
|
||||
unoptimized
|
||||
className="block h-auto w-full"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mt-8 border-t border-teal-700/25 pt-5">
|
||||
<p className="northwell-print-label">What it can do</p>
|
||||
<h2 className="mt-2 font-serif text-[25px] leading-[1.12] font-semibold text-slate-950">
|
||||
Real medical AI, working entirely on the phone
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div className="mt-6 grid grid-cols-3 gap-x-7 gap-y-7">
|
||||
{capabilities.map(({ icon: Icon, title, body }) => (
|
||||
<div key={title}>
|
||||
<Icon className="size-5 text-teal-700" strokeWidth={1.75} />
|
||||
<h3 className="mt-2.5 font-serif text-[16px] leading-[1.15] font-semibold text-slate-950">
|
||||
{title}
|
||||
</h3>
|
||||
<p className="mt-1.5 text-[10px] leading-[1.5] text-slate-600">
|
||||
{body}
|
||||
</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="mt-8 grid grid-cols-3 gap-7 border-t border-teal-700/25 pt-5">
|
||||
{[
|
||||
[
|
||||
"On the device, not the cloud",
|
||||
"Summarization and medication Q&A run on the phone. No health data goes to a server for AI, so there is no new breach surface and no BAA.",
|
||||
],
|
||||
[
|
||||
"Facts first, not guesswork",
|
||||
"Drug facts, classes, and interaction pairs come from bundled reference data. The model helps phrase the answer; it does not invent it.",
|
||||
],
|
||||
[
|
||||
"Owned by the patient",
|
||||
"One record that spans every provider and pharmacy, that the patient controls, carries, and decides how to share.",
|
||||
],
|
||||
].map(([title, body]) => (
|
||||
<div key={title}>
|
||||
<p className="font-serif text-[14px] font-semibold text-slate-950">
|
||||
{title}
|
||||
</p>
|
||||
<p className="mt-1.5 text-[9.5px] leading-[1.5] text-slate-600">
|
||||
{body}
|
||||
</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</PrintPage>
|
||||
|
||||
<PrintPage page={2}>
|
||||
<section className="pt-3">
|
||||
<p className="northwell-print-label">Who it helps</p>
|
||||
<h2 className="northwell-print-title">Every capability pays off twice</h2>
|
||||
<p className="northwell-print-lede max-w-[660px]">
|
||||
The features that make Medscribe genuinely useful to the patient are
|
||||
the same ones that move the numbers Walgreens is measured on.
|
||||
Cross-provider by design; one central pharmacy in practice.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<div className="mt-6 grid grid-cols-[0.92fr_1.08fr] gap-8">
|
||||
<p className="text-[9px] font-bold tracking-[0.18em] text-slate-500 uppercase">
|
||||
For the patient
|
||||
</p>
|
||||
<p className="text-[9px] font-bold tracking-[0.18em] text-teal-700 uppercase">
|
||||
For Walgreens
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="mt-1">
|
||||
{payoffs.map((row) => (
|
||||
<div
|
||||
key={row.bizTitle}
|
||||
className="grid grid-cols-[0.92fr_1.08fr] gap-8 border-t border-slate-200 py-3"
|
||||
>
|
||||
<div>
|
||||
<h3 className="font-serif text-[14px] leading-[1.2] font-semibold text-slate-950">
|
||||
{row.patientTitle}
|
||||
</h3>
|
||||
<p className="mt-1 text-[9.5px] leading-[1.45] text-slate-600">
|
||||
{row.patient}
|
||||
</p>
|
||||
</div>
|
||||
<div className="border-l border-teal-600/30 pl-8">
|
||||
<h3 className="font-serif text-[14px] leading-[1.2] font-semibold text-teal-900">
|
||||
{row.bizTitle}
|
||||
</h3>
|
||||
<p className="mt-1 text-[9.5px] leading-[1.45] text-slate-600">
|
||||
{row.biz}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<p className="mt-5 bg-teal-50/70 px-5 py-3 text-[10px] leading-[1.5] text-slate-700">
|
||||
<span className="font-semibold text-slate-900">
|
||||
It sits beside the Walgreens stack, not on top of it.{" "}
|
||||
</span>
|
||||
Dispensing, myWalgreens, and the Walgreens app keep doing their jobs.
|
||||
Medscribe is the patient-owned layer that feeds value back in with
|
||||
consent. A partnership unlocks co-branding, refill routing, and
|
||||
adherence reporting against Star and EQuIPP measures.
|
||||
</p>
|
||||
|
||||
<section className="mt-6 grid grid-cols-[1.12fr_0.88fr] items-start gap-9 border-t border-slate-300 pt-5">
|
||||
<div>
|
||||
<p className="northwell-print-label">The ask</p>
|
||||
<h3 className="mt-3 font-serif text-[20px] leading-[1.22] font-semibold text-slate-950">
|
||||
A short conversation about a record that moves adherence and keeps
|
||||
refills at Walgreens.
|
||||
</h3>
|
||||
<p className="mt-2 text-[10.5px] leading-[1.5] text-slate-600">
|
||||
Live in beta on iOS and Android today. The core patient experience
|
||||
ships now; the business layer is what a partnership builds together.
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="northwell-print-label">Who is behind it</p>
|
||||
<h3 className="mt-3 font-serif text-[19px] font-semibold text-slate-950">
|
||||
Sean O'Connor
|
||||
</h3>
|
||||
<p className="mt-3 text-[10.5px] leading-[1.5] text-slate-600">
|
||||
A Bucknell computer science and engineering graduate who built
|
||||
Medscribe after watching his family lose the full picture of his
|
||||
grandfather's care.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
</PrintPage>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user