feat: refresh product captures and mobile motion

This commit is contained in:
2026-08-20 22:42:03 -04:00
parent 0a353afeb7
commit 0d371313f9
41 changed files with 146 additions and 86 deletions
+6 -3
View File
@@ -55,7 +55,10 @@ bun run start
Screenshots live in `public/screenshots/`. The long-form homepage uses
precomposited, transparent iPhone product-bezel assets in
`public/screenshots/pitch/`; supporting pages use the lightweight CSS frame.
`public/screenshots/pitch-glass-2026-08-20/`; supporting pages use versioned raw
captures from `public/screenshots/product-glass-2026-08-20/` in the lightweight
CSS frame. Versioned paths keep newly captured UI from being hidden by stale
browser or image-optimizer caches.
Public pages label product imagery as synthetic demo data and beta UI.
### Capturing raw screenshots for the site
@@ -73,5 +76,5 @@ captures that already include device chrome. Homepage product images are
composited at the bezel source size of 1350 × 2760 with transparent
backgrounds and rendered responsively through
`src/components/product-device.tsx`. The homepage uses CSS view timelines for
scroll-scrubbed device and chapter motion, with a static fallback and a
reduced-motion override.
scroll-scrubbed device and chapter motion on desktop and mobile, with a static
fallback and a reduced-motion override.
Binary file not shown.

After

Width:  |  Height:  |  Size: 188 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 205 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 196 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 229 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 162 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 158 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 180 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 193 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 151 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 164 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 734 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 702 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 280 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 462 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 294 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 397 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 704 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 249 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 260 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 779 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 822 KiB

+29 -28
View File
@@ -49,7 +49,7 @@ const differentiators = [
},
{
title: "Private by architecture",
body: "AI runs on-device: no cloud processing, no health-data upload, no tracking, no account. Others say \"encrypted\" while their store disclosures admit cloud collection.",
body: 'AI runs on-device: no cloud processing, no health-data upload, no tracking, no account. Others say "encrypted" while their store disclosures admit cloud collection.',
},
{
title: "Facts-first, not a guess",
@@ -147,21 +147,22 @@ export default function ExecutiveSummaryPage() {
<div className="space-y-5">
<SectionLabel>Executive Summary · June 2026</SectionLabel>
<div className="space-y-3">
<h1 className="font-serif text-5xl font-semibold tracking-tight text-foreground sm:text-6xl">
<h1 className="text-foreground font-serif text-5xl font-semibold tracking-tight sm:text-6xl">
Medscribe
</h1>
<p className="font-serif text-xl font-semibold tracking-tight text-foreground sm:text-2xl">
<p className="text-foreground font-serif text-xl font-semibold tracking-tight sm:text-2xl">
{TAGLINE}
</p>
</div>
<p className="text-base leading-relaxed text-muted-foreground sm:text-lg">
<p className="text-muted-foreground text-base leading-relaxed sm:text-lg">
{SNAPSHOT}
</p>
</div>
<div className="justify-self-center lg:justify-self-end">
<PhoneMockup
src="/screenshots/home.png"
src="/screenshots/product-glass-2026-08-20/home-light.png"
darkSrc="/screenshots/product-glass-2026-08-20/home-dark.png"
alt="Medscribe home screen"
width={200}
priority
@@ -175,9 +176,9 @@ export default function ExecutiveSummaryPage() {
<h2 className="font-serif text-3xl font-semibold tracking-tight sm:text-4xl">
The patient&apos;s context does not travel with them.
</h2>
<div className="grid gap-6 leading-relaxed text-muted-foreground lg:grid-cols-2 lg:gap-10">
<div className="text-muted-foreground grid gap-6 leading-relaxed lg:grid-cols-2 lg:gap-10">
<p>{PROBLEM}</p>
<p className="font-medium text-foreground">{PROBLEM_BROADER}</p>
<p className="text-foreground font-medium">{PROBLEM_BROADER}</p>
</div>
</section>
@@ -205,7 +206,7 @@ export default function ExecutiveSummaryPage() {
<h2 className="font-serif text-3xl font-semibold tracking-tight sm:text-4xl">
Everyone owns a slice. We own the whole job.
</h2>
<p className="max-w-4xl leading-relaxed text-muted-foreground">
<p className="text-muted-foreground max-w-4xl leading-relaxed">
{DIFFERENTIATION}
</p>
<div className="grid gap-4 md:grid-cols-3">
@@ -222,8 +223,8 @@ export default function ExecutiveSummaryPage() {
<CardContent className="pt-5">
<p className="leading-relaxed">
Medscribe connects the daily loop to the emergency handoff: one
private record that stays current through normal use and is ready
when the system does not know the patient.
private record that stays current through normal use and is
ready when the system does not know the patient.
</p>
</CardContent>
</Card>
@@ -235,7 +236,7 @@ export default function ExecutiveSummaryPage() {
<h2 className="font-serif text-3xl font-semibold tracking-tight sm:text-4xl">
Easy to claim. Hard to copy.
</h2>
<p className="max-w-4xl leading-relaxed text-muted-foreground">
<p className="text-muted-foreground max-w-4xl leading-relaxed">
{MOAT}
</p>
<div className="grid gap-4 md:grid-cols-3">
@@ -279,7 +280,7 @@ export default function ExecutiveSummaryPage() {
<h2 className="font-serif text-3xl font-semibold tracking-tight sm:text-4xl">
An ongoing touchstone, not another portal.
</h2>
<p className="max-w-4xl leading-relaxed text-muted-foreground">
<p className="text-muted-foreground max-w-4xl leading-relaxed">
{FOR_HEALTH_SYSTEMS}
</p>
<div className="grid gap-4 md:grid-cols-3">
@@ -295,14 +296,14 @@ export default function ExecutiveSummaryPage() {
</section>
{/* Beta */}
<section className="flex flex-col gap-5 rounded-xl border border-border-soft bg-surface p-6 sm:flex-row sm:items-center sm:justify-between sm:p-8">
<p className="max-w-xl text-sm leading-relaxed text-muted-foreground">
<section className="border-border-soft bg-surface flex flex-col gap-5 rounded-xl border p-6 sm:flex-row sm:items-center sm:justify-between sm:p-8">
<p className="text-muted-foreground max-w-xl text-sm leading-relaxed">
{BETA_SUMMARY} If you&apos;d like to try it, reach out.
</p>
<PrintButton size="lg" className="shrink-0" />
</section>
<p className="border-t border-border-soft pt-6 text-sm text-muted-foreground">
<p className="border-border-soft text-muted-foreground border-t pt-6 text-sm">
Sean O&apos;Connor
</p>
</div>
@@ -315,16 +316,16 @@ export default function ExecutiveSummaryPage() {
{/* Header */}
<header className="grid grid-cols-[minmax(0,1fr)_0.94in] items-stretch gap-4 border-b border-teal-900/10 pb-1.5">
<div className="flex flex-col justify-between py-0.5">
<p className="text-[10pt] font-semibold tracking-[0.18em] text-primary uppercase">
<p className="text-primary text-[10pt] font-semibold tracking-[0.18em] uppercase">
Executive Summary · June 2026
</p>
<div className="mt-1.5 flex items-center gap-2.5">
<MedscribeLogo className="h-[20pt] w-auto text-foreground" />
<h1 className="font-serif text-[22pt] leading-none font-semibold tracking-tight text-foreground">
<MedscribeLogo className="text-foreground h-[20pt] w-auto" />
<h1 className="text-foreground font-serif text-[22pt] leading-none font-semibold tracking-tight">
Medscribe
</h1>
</div>
<p className="mt-1.5 font-serif text-[12pt] leading-snug font-medium tracking-tight text-foreground italic">
<p className="text-foreground mt-1.5 font-serif text-[12pt] leading-snug font-medium tracking-tight italic">
{TAGLINE}
</p>
<p className="mt-2 text-[11pt] leading-[1.2] text-slate-700">
@@ -334,7 +335,7 @@ export default function ExecutiveSummaryPage() {
<div className="flex justify-end">
<div className="h-[1.78in] w-[0.88in] overflow-hidden rounded-[11px] border-[3px] border-slate-950 bg-white shadow-[0_8px_18px_rgba(15,23,42,0.14)]">
<Image
src="/screenshots/home.png"
src="/screenshots/product-glass-2026-08-20/home-light.png"
alt="Medscribe home screen"
width={1206}
height={2622}
@@ -348,7 +349,7 @@ export default function ExecutiveSummaryPage() {
{/* The Problem */}
<section className="border-b border-teal-900/10 pt-1 pb-1">
<h2 className="font-serif text-[12.5pt] font-semibold tracking-tight text-foreground">
<h2 className="text-foreground font-serif text-[12.5pt] font-semibold tracking-tight">
The Problem
</h2>
<p className="mt-1 text-[11pt] leading-[1.2] text-slate-700">
@@ -358,7 +359,7 @@ export default function ExecutiveSummaryPage() {
{/* Who It's For */}
<section className="border-b border-teal-900/10 pt-1 pb-1">
<h2 className="font-serif text-[12.5pt] font-semibold tracking-tight text-foreground">
<h2 className="text-foreground font-serif text-[12.5pt] font-semibold tracking-tight">
Who It&apos;s For
</h2>
<p className="mt-1 text-[11pt] leading-[1.2] text-slate-700">
@@ -368,7 +369,7 @@ export default function ExecutiveSummaryPage() {
{/* Why This Is Different */}
<section className="border-b border-teal-900/10 pt-1 pb-1">
<h2 className="font-serif text-[12.5pt] font-semibold tracking-tight text-foreground">
<h2 className="text-foreground font-serif text-[12.5pt] font-semibold tracking-tight">
Why This Is Different
</h2>
<div className="mt-1.5 grid grid-cols-3 gap-x-6">
@@ -377,7 +378,7 @@ export default function ExecutiveSummaryPage() {
key={item.title}
className="text-[11pt] leading-[1.2] text-slate-700"
>
<span className="font-semibold text-foreground">
<span className="text-foreground font-semibold">
{item.title}.
</span>{" "}
{item.body}
@@ -388,7 +389,7 @@ export default function ExecutiveSummaryPage() {
{/* Under The Hood */}
<section className="border-b border-teal-900/10 pt-1 pb-1">
<h2 className="font-serif text-[12.5pt] font-semibold tracking-tight text-foreground">
<h2 className="text-foreground font-serif text-[12.5pt] font-semibold tracking-tight">
Under The Hood
</h2>
<div className="mt-1 grid grid-cols-3 gap-x-6">
@@ -397,7 +398,7 @@ export default function ExecutiveSummaryPage() {
key={item.title}
className="text-[11pt] leading-[1.2] text-slate-700"
>
<span className="font-semibold text-foreground">
<span className="text-foreground font-semibold">
{item.title}.
</span>{" "}
{item.body}
@@ -408,7 +409,7 @@ export default function ExecutiveSummaryPage() {
{/* For Health Systems */}
<section className="pt-1">
<h2 className="font-serif text-[12.5pt] font-semibold tracking-tight text-foreground">
<h2 className="text-foreground font-serif text-[12.5pt] font-semibold tracking-tight">
For Health Systems
</h2>
<div className="mt-1 grid grid-cols-3 gap-x-6">
@@ -417,7 +418,7 @@ export default function ExecutiveSummaryPage() {
key={item.title}
className="text-[11pt] leading-[1.2] text-slate-700"
>
<span className="font-semibold text-foreground">
<span className="text-foreground font-semibold">
{item.title}.
</span>{" "}
{item.body}
+6 -3
View File
@@ -137,7 +137,8 @@ export default function HowItWorksPage() {
</div>
<div className="bg-primary-light/45 justify-self-center rounded-[2.5rem] p-7">
<PhoneMockup
src="/screenshots/appointment-summary.png"
src="/screenshots/product-glass-2026-08-20/summary-light.png"
darkSrc="/screenshots/product-glass-2026-08-20/summary-dark.png"
alt="Synthetic Medscribe beta visit summary"
width={235}
/>
@@ -150,7 +151,8 @@ export default function HowItWorksPage() {
<div className="grid gap-12 lg:grid-cols-2 lg:items-center">
<div className="justify-self-center rounded-[2.5rem] bg-[#f4f0e8] p-7 lg:order-1 dark:bg-[#151b25]">
<PhoneMockup
src="/screenshots/medication-detail.png"
src="/screenshots/product-glass-2026-08-20/medication-detail-light.png"
darkSrc="/screenshots/product-glass-2026-08-20/medication-detail-dark.png"
alt="Synthetic Medscribe beta medication detail"
width={235}
/>
@@ -197,7 +199,8 @@ export default function HowItWorksPage() {
</div>
<div className="bg-primary-light/45 justify-self-center rounded-[2.5rem] p-7">
<PhoneMockup
src="/screenshots/emergency-record.png"
src="/screenshots/product-glass-2026-08-20/know-me-light.png"
darkSrc="/screenshots/product-glass-2026-08-20/know-me-dark.png"
alt="Synthetic Medscribe beta Know Me handoff"
width={235}
/>
+18 -18
View File
@@ -28,8 +28,8 @@ const visitMoments = [
eyebrow: "Visits stay findable",
title: "The visit has a place to land.",
body: "Keep the recording, transcript, and reviewed summary together instead of reconstructing the appointment from memory.",
image: "/screenshots/pitch/visits-natural.webp",
darkImage: "/screenshots/pitch/visits-natural-dark.webp",
image: "/screenshots/pitch-glass-2026-08-20/visits-natural.webp",
darkImage: "/screenshots/pitch-glass-2026-08-20/visits-natural-dark.webp",
alt: "Medscribe Visits screen in a natural titanium iPhone product bezel",
},
{
@@ -37,8 +37,8 @@ const visitMoments = [
eyebrow: "Words stay checkable",
title: "Go back to what was actually said.",
body: "Search the local transcript and compare it with the generated summary before anything becomes part of the record you rely on.",
image: "/screenshots/pitch/transcript-black.webp",
darkImage: "/screenshots/pitch/transcript-black-dark.webp",
image: "/screenshots/pitch-glass-2026-08-20/transcript-black.webp",
darkImage: "/screenshots/pitch-glass-2026-08-20/transcript-black-dark.webp",
alt: "Medscribe visit transcript in a black titanium iPhone product bezel",
},
{
@@ -46,8 +46,8 @@ const visitMoments = [
eyebrow: "The next step stays visible",
title: "Review the useful part. Keep the uncertainty.",
body: "Medications, follow-ups, diagnoses, and instructions are prepared on-device. Suggestions remain suggestions until a person checks them.",
image: "/screenshots/pitch/summary-natural.webp",
darkImage: "/screenshots/pitch/summary-natural-dark.webp",
image: "/screenshots/pitch-glass-2026-08-20/summary-natural.webp",
darkImage: "/screenshots/pitch-glass-2026-08-20/summary-natural-dark.webp",
alt: "Medscribe appointment summary in a natural titanium iPhone product bezel",
},
] as const;
@@ -128,8 +128,8 @@ export default function HomePage() {
<div className="relative mx-auto mt-12 h-[36rem] max-w-5xl sm:h-[46rem] lg:mt-8 lg:h-[54rem]">
<div className="absolute top-24 left-1/2 w-[17rem] -translate-x-[86%] -rotate-6 sm:top-28 sm:w-[22rem] lg:top-32 lg:w-[26rem]">
<ProductDevice
src="/screenshots/pitch/summary-natural.webp"
darkSrc="/screenshots/pitch/summary-natural-dark.webp"
src="/screenshots/pitch-glass-2026-08-20/summary-natural.webp"
darkSrc="/screenshots/pitch-glass-2026-08-20/summary-natural-dark.webp"
alt="Medscribe visit summary in a natural titanium iPhone product bezel"
className="pitch-device-motion pitch-device-drift-left"
sizes="(min-width: 1024px) 416px, (min-width: 640px) 352px, 272px"
@@ -138,8 +138,8 @@ export default function HomePage() {
</div>
<div className="absolute top-0 left-1/2 z-10 w-[18rem] -translate-x-[14%] rotate-5 sm:w-[23rem] lg:w-[28rem]">
<ProductDevice
src="/screenshots/pitch/home-black.webp"
darkSrc="/screenshots/pitch/home-black-dark.webp"
src="/screenshots/pitch-glass-2026-08-20/home-black.webp"
darkSrc="/screenshots/pitch-glass-2026-08-20/home-black-dark.webp"
alt="Medscribe home screen in a black titanium iPhone product bezel"
className="pitch-device-motion pitch-device-drift-right"
sizes="(min-width: 1024px) 448px, (min-width: 640px) 368px, 288px"
@@ -249,8 +249,8 @@ export default function HomePage() {
<div className="relative mx-auto h-[42rem] w-full max-w-2xl sm:h-[50rem] lg:h-[56rem]">
<div className="absolute top-20 left-[4%] w-[17rem] -rotate-6 sm:w-[21rem] lg:w-[23rem]">
<ProductDevice
src="/screenshots/pitch/medication-detail-natural.webp"
darkSrc="/screenshots/pitch/medication-detail-natural-dark.webp"
src="/screenshots/pitch-glass-2026-08-20/medication-detail-natural.webp"
darkSrc="/screenshots/pitch-glass-2026-08-20/medication-detail-natural-dark.webp"
alt="Medscribe medication detail in a natural titanium iPhone product bezel"
className="pitch-device-motion pitch-device-drift-left"
sizes="(min-width: 1024px) 368px, (min-width: 640px) 336px, 272px"
@@ -258,8 +258,8 @@ export default function HomePage() {
</div>
<div className="absolute top-0 right-[2%] z-10 w-[18rem] rotate-5 sm:w-[22rem] lg:w-[24rem]">
<ProductDevice
src="/screenshots/pitch/medications-black.webp"
darkSrc="/screenshots/pitch/medications-black-dark.webp"
src="/screenshots/pitch-glass-2026-08-20/medications-black.webp"
darkSrc="/screenshots/pitch-glass-2026-08-20/medications-black-dark.webp"
alt="Medscribe medication list in a black titanium iPhone product bezel"
className="pitch-device-motion pitch-device-drift-right"
sizes="(min-width: 1024px) 384px, (min-width: 640px) 352px, 288px"
@@ -321,8 +321,8 @@ export default function HomePage() {
</div>
<div className="order-1 mx-auto w-[min(78vw,27rem)] lg:order-2">
<ProductDevice
src="/screenshots/pitch/ask-black.webp"
darkSrc="/screenshots/pitch/ask-black-dark.webp"
src="/screenshots/pitch-glass-2026-08-20/ask-black.webp"
darkSrc="/screenshots/pitch-glass-2026-08-20/ask-black-dark.webp"
alt="Medscribe Ask response grounded in local health context, shown in a black titanium iPhone product bezel"
className="pitch-device-motion pitch-device-drift-right"
sizes="(min-width: 1024px) 432px, (min-width: 640px) 384px, 78vw"
@@ -337,8 +337,8 @@ export default function HomePage() {
<div className="relative mx-auto w-[min(80vw,28rem)]">
<div className="bg-primary-light/70 absolute inset-[12%_-12%_8%] -z-10 rounded-[4rem] blur-2xl" />
<ProductDevice
src="/screenshots/pitch/know-me-natural.webp"
darkSrc="/screenshots/pitch/know-me-natural-dark.webp"
src="/screenshots/pitch-glass-2026-08-20/know-me-natural.webp"
darkSrc="/screenshots/pitch-glass-2026-08-20/know-me-natural-dark.webp"
alt="Medscribe Know Me handoff record in a natural titanium iPhone product bezel"
className="pitch-device-motion pitch-device-drift-left"
sizes="(min-width: 1024px) 448px, (min-width: 640px) 400px, 80vw"
+8 -5
View File
@@ -162,7 +162,7 @@ export function CvsPrintSummary() {
<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"
src="/screenshots/product-glass-2026-08-20/medications-light.png"
alt="Medscribe medications screen"
width={1206}
height={2622}
@@ -225,11 +225,13 @@ export function CvsPrintSummary() {
<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>
<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.
the same ones that move the numbers CVS is measured on.
Cross-provider by design; one central pharmacy in practice.
</p>
</section>
@@ -287,7 +289,8 @@ export function CvsPrintSummary() {
</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.
ships now; the business layer is what a partnership builds
together.
</p>
</div>
<div>
+15 -5
View File
@@ -26,7 +26,8 @@ const features = [
"The person reviews generated information",
"Structured visit-to-record change review is still roadmap",
],
image: "/screenshots/visit-detail.png",
image: "/screenshots/product-glass-2026-08-20/visits-light.png",
darkImage: "/screenshots/product-glass-2026-08-20/visits-dark.png",
alt: "Synthetic Medscribe beta visit detail showing a visit summary and follow-up information",
},
{
@@ -41,7 +42,9 @@ const features = [
"Bundled facts and known pairs use named reference datasets",
"Coverage is intentionally bounded, not a complete interaction check",
],
image: "/screenshots/medication-detail.png",
image: "/screenshots/product-glass-2026-08-20/medication-detail-light.png",
darkImage:
"/screenshots/product-glass-2026-08-20/medication-detail-dark.png",
alt: "Synthetic Medscribe beta medication detail with schedule and medication information",
},
{
@@ -56,7 +59,8 @@ const features = [
"The local model helps with conversational phrasing",
"High-risk or unsupported questions defer to a professional",
],
image: "/screenshots/chat-response.png",
image: "/screenshots/product-glass-2026-08-20/ask-light.png",
darkImage: "/screenshots/product-glass-2026-08-20/ask-dark.png",
alt: "Synthetic Medscribe beta answer with medication context and a safety boundary",
},
{
@@ -71,7 +75,8 @@ const features = [
"The person can show or share the snapshot they reviewed",
"It complements—not replaces—clinical verification",
],
image: "/screenshots/emergency-record.png",
image: "/screenshots/product-glass-2026-08-20/know-me-light.png",
darkImage: "/screenshots/product-glass-2026-08-20/know-me-dark.png",
alt: "Synthetic Medscribe beta Know Me handoff with active medications and review state",
},
] as const;
@@ -181,7 +186,12 @@ export function FeatureShowcase() {
<div className="justify-self-center lg:justify-self-end">
<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} />
<PhoneMockup
src={active.image}
darkSrc={active.darkImage}
alt={active.alt}
width={220}
/>
<p className="text-muted-foreground mt-4 text-center text-xs">
Synthetic demo data · beta interface
</p>
+1 -1
View File
@@ -127,7 +127,7 @@ export function NorthwellPrintSummary() {
<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"
src="/screenshots/product-glass-2026-08-20/home-light.png"
alt="Medscribe home screen"
width={1206}
height={2622}
+27 -11
View File
@@ -1,9 +1,10 @@
import Image from "next/image";
import { getImageProps } from "next/image";
import { cn } from "~/lib/utils";
interface PhoneMockupProps {
src: string;
darkSrc?: string;
alt: string;
className?: string;
priority?: boolean;
@@ -15,6 +16,7 @@ interface PhoneMockupProps {
export function PhoneMockup({
src,
darkSrc,
alt,
className,
priority,
@@ -22,6 +24,21 @@ export function PhoneMockup({
captureMode = "raw",
}: PhoneMockupProps) {
const isSimulatorCapture = captureMode === "simulator";
const shared = {
alt,
width: 1206,
height: 2622,
sizes: `${width}px`,
priority,
className: cn(
"absolute inset-0 h-full w-full object-cover",
isSimulatorCapture ? "scale-[1.22] object-[50%_58%]" : "object-top",
),
};
const { props: lightProps } = getImageProps({ src, ...shared });
const darkProps = darkSrc
? getImageProps({ src: darkSrc, ...shared }).props
: null;
return (
<div
@@ -32,17 +49,16 @@ export function PhoneMockup({
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",
)}
<picture>
{darkProps ? (
<source
media="(prefers-color-scheme: dark)"
srcSet={darkProps.srcSet}
sizes={darkProps.sizes}
/>
) : null}
<img {...lightProps} alt={alt} />
</picture>
</div>
</div>
);
+2 -2
View File
@@ -13,8 +13,8 @@ type ProductDeviceProps = {
/**
* 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.
* `public/screenshots/pitch-glass-2026-08-20`. Keeping the frame in the source
* image preserves the bezel details without adding layout or client-side work.
*/
export function ProductDevice({
src,
+3 -2
View File
@@ -5,6 +5,7 @@ import { MedscribeLogo } from "~/components/medscribe-logo";
import { Button } from "~/components/ui/button";
const navigation = [
{ href: "/", label: "Home" },
{ href: "/how-it-works", label: "How it works" },
{ href: "/privacy", label: "Privacy & evidence" },
] as const;
@@ -12,10 +13,10 @@ const navigation = [
export function SiteHeader() {
return (
<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">
<div className="relative 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"
className="text-foreground focus-visible:ring-primary/40 absolute left-1/2 flex shrink-0 -translate-x-1/2 items-center gap-2.5 rounded-md transition-opacity outline-none hover:opacity-75 focus-visible:ring-2 md:static md:translate-x-0"
aria-label="Medscribe home"
>
<MedscribeLogo className="h-7 w-auto" />
+6 -3
View File
@@ -162,7 +162,7 @@ export function WalgreensPrintSummary() {
<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"
src="/screenshots/product-glass-2026-08-20/medications-light.png"
alt="Medscribe medications screen"
width={1206}
height={2622}
@@ -225,7 +225,9 @@ export function WalgreensPrintSummary() {
<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>
<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.
@@ -287,7 +289,8 @@ export function WalgreensPrintSummary() {
</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.
ships now; the business layer is what a partnership builds
together.
</p>
</div>
<div>
+24 -4
View File
@@ -106,8 +106,10 @@
*/
.pitch-device-motion {
--pitch-enter-x: 0px;
--pitch-enter-y: 7rem;
--pitch-enter-rotate: 0deg;
--pitch-exit-x: 0px;
--pitch-exit-y: -5rem;
--pitch-exit-rotate: 0deg;
backface-visibility: hidden;
transform-origin: center;
@@ -130,8 +132,8 @@
@keyframes pitch-device-scroll {
0% {
opacity: 0.42;
transform: translate3d(var(--pitch-enter-x), 7rem, 0) scale(0.92)
rotate(var(--pitch-enter-rotate));
transform: translate3d(var(--pitch-enter-x), var(--pitch-enter-y), 0)
scale(0.92) rotate(var(--pitch-enter-rotate));
}
38% {
opacity: 1;
@@ -143,8 +145,8 @@
}
100% {
opacity: 0.78;
transform: translate3d(var(--pitch-exit-x), -5rem, 0) scale(0.97)
rotate(var(--pitch-exit-rotate));
transform: translate3d(var(--pitch-exit-x), var(--pitch-exit-y), 0)
scale(0.97) rotate(var(--pitch-exit-rotate));
}
}
@@ -190,6 +192,24 @@
}
}
/* Keep the product choreography visible on phones without crowding the copy. */
@media (max-width: 639px) {
.pitch-device-motion {
--pitch-enter-y: 4rem;
--pitch-exit-y: -3rem;
}
.pitch-device-drift-left {
--pitch-enter-x: -1.25rem;
--pitch-exit-x: 0.75rem;
}
.pitch-device-drift-right {
--pitch-enter-x: 1.25rem;
--pitch-exit-x: -0.75rem;
}
}
@media (prefers-reduced-motion: reduce) {
html {
scroll-behavior: auto;