25 Commits
Author SHA1 Message Date
soconnor da55f2ab4e Refresh Questions interface screenshots
Deploy to GitHub Pages / deploy (push) Skipped
Deploy to GitHub Pages / build (push) Failing after 29s
2026-08-26 21:25:40 -04:00
soconnor aaa566bbbc Refine website vertical rhythm 2026-08-26 21:03:16 -04:00
soconnor 2b436eeec6 Fix dark and medication screenshots 2026-08-26 20:48:04 -04:00
soconnor 96d152f592 Deploy website to GitHub Pages 2026-08-26 20:06:52 -04:00
soconnor 0c17689368 Restore references background and add deck contact 2026-08-24 16:08:09 -04:00
soconnor 1a76a63ae3 Refresh pitch deck product story 2026-08-24 16:00:42 -04:00
soconnor 0b0d149fba Rebuild pitch deck footers 2026-08-24 15:52:31 -04:00
soconnor 47acac8435 Rebuild pitch deck references page 2026-08-24 15:48:05 -04:00
soconnor e9b5564127 Publish partner deck and open closed beta site 2026-08-24 15:43:39 -04:00
soconnor f6aadc5107 Unify typography and refresh product screenshots 2026-08-24 14:49:06 -04:00
soconnor d2a729b7b9 Show the native Questions workflow 2026-08-24 13:31:39 -04:00
soconnor bd3b8daf5a Refine section transitions and device frames 2026-08-24 13:11:26 -04:00
soconnor 33d4f19bf0 Polish website flow and add Questions story 2026-08-24 12:26:54 -04:00
soconnor dcc1fff784 fix: show completed Home state in screenshots 2026-08-23 02:01:28 -04:00
soconnor 4238f6ab0e Refresh product screenshots for native theme 2026-08-23 01:51:11 -04:00
soconnor a8b7504a15 Refresh web branding for new app theme 2026-08-23 01:20:22 -04:00
soconnor b41f2c643f fix: replace empty visit screenshots 2026-08-21 21:34:24 -04:00
soconnor 5fd5011a9c revert: restore normal hero page flow 2026-08-21 21:07:37 -04:00
soconnor b52eff02e1 feat: choreograph hero devices on scroll 2026-08-21 00:08:50 -04:00
soconnor ec89696c48 fix: separate hero devices from caption 2026-08-20 23:46:40 -04:00
soconnor 8f656e3808 fix: simplify public product messaging 2026-08-20 23:23:01 -04:00
soconnor af7f1b79e9 fix: use fresh product-bezel captures everywhere 2026-08-20 23:01:22 -04:00
soconnor 0d371313f9 feat: refresh product captures and mobile motion 2026-08-20 22:42:03 -04:00
soconnor 0a353afeb7 feat: add scroll-driven product storytelling 2026-08-20 22:15:45 -04:00
soconnor e466b25837 fix: pair website screenshots with color scheme 2026-08-20 21:15:35 -04:00
122 changed files with 1438 additions and 1805 deletions
+3 -2
View File
@@ -13,8 +13,9 @@
# SERVERVAR="foo"
# NEXT_PUBLIC_CLIENTVAR="bar"
# Password required to view the site (login page at /login).
# Leave empty/unset to disable the gate.
# Optional password gate for private previews. The gate is off unless both
# values are set, so a stale password alone cannot hide the public site.
SITE_PASSWORD_ENABLED="false"
SITE_PASSWORD=""
# Umami analytics (optional). Omit NEXT_PUBLIC_UMAMI_WEBSITE_ID to disable tracking.
+65
View File
@@ -0,0 +1,65 @@
name: Deploy to GitHub Pages
on:
push:
branches: [master]
workflow_dispatch:
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: pages
cancel-in-progress: true
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Set up Bun
uses: oven-sh/setup-bun@v2
with:
bun-version: 1.3.14
- name: Configure GitHub Pages
uses: actions/configure-pages@v5
- name: Install dependencies
run: bun install --frozen-lockfile
- name: Check source
run: bun run check
- name: Prepare static-only routes
run: |
rm -f src/proxy.ts
rm -rf src/app/api src/app/login
rm -rf "src/app/(marketing)/beta"
rm -rf "src/app/(marketing)/executive-summary"
rm -rf "src/app/(marketing)/landscape"
- name: Build static site
run: bun run build
env:
GITHUB_PAGES: "true"
- name: Upload GitHub Pages artifact
uses: actions/upload-pages-artifact@v4
with:
path: ./out
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
needs: build
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
+51 -25
View File
@@ -1,10 +1,10 @@
# Medscribe Web
Public product website for [Medscribe](../README.md) — a privacy-first,
on-device medical companion in internal beta on iOS and Android.
Public product website for [Medscribe](../README.md) — a private,
patient-controlled care companion for iOS and Android.
Built with [create-t3-app](https://create.t3.gg/) (Next.js + TypeScript +
Tailwind). There is no product database or beta-form backend.
Tailwind).
Uses **bun** exclusively (`bun.lock`).
@@ -19,12 +19,13 @@ Open [http://localhost:3000](http://localhost:3000).
## Routes
The first public product slice includes:
Public routes include:
- `/` — consumer-first portable-context story
- `/how-it-works` inputs, review loop, medication maintenance, and handoff
- `/privacy`data map, sharing limitations, and evidence boundaries
- `/beta` — expectations and a health-data-free email request
- `/` — consumer-first portable-context story, including Questions
- `/how-it-works` — review loop, medication maintenance, Questions, and handoff
- `/privacy`plain-language privacy and patient-control commitments
- `/access` health-data-free access request
- `/medscribe-corporate-partner-overview.pdf` — public eight-slide partner deck
Named partner print material remains isolated and excluded from search:
@@ -32,10 +33,8 @@ Named partner print material remains isolated and excluded from search:
- `/cvs`
- `/walgreens`
`/executive-summary` and `/landscape` remain retired/internal and are also
excluded from search. `SITE_PASSWORD` still gates the entire site when set; a
future pass should make protection route-specific before the public site is
deployed alongside private briefs.
Legacy routes redirect to the current public experience and are excluded from
search.
### Analytics (optional)
@@ -46,6 +45,19 @@ Set in `.env` (see `.env.example`):
Leave the website ID unset to disable tracking (default for local dev).
### Optional preview password
The public site is open by default. To enable the private-preview gate, set
both values in the deployment environment:
```bash
SITE_PASSWORD_ENABLED="true"
SITE_PASSWORD="choose-a-strong-password"
```
Unset `SITE_PASSWORD_ENABLED` or set it to `false` to keep the site public. A
stored password alone does not enable the gate.
## Build
```bash
@@ -53,22 +65,36 @@ bun run build
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 pages label product imagery as synthetic demo data and beta UI.
## GitHub Pages
Pushes to `master` also publish a static build to GitHub Pages through
`.github/workflows/deploy-pages.yml`. The Pages build keeps the public product
site and partner materials, while omitting the optional server-only password
gate and legacy redirect routes that cannot run on static hosting.
Screenshots live in `public/screenshots/`. Every route uses the same fresh,
precomposited iPhone 17 Pro assets in
`public/screenshots/product-bezel-2026-08-24-unified-type/`; there are no raw or
CSS-framed product captures in the rendered site. The neutral Silver bezel and
the versioned path keep the imagery consistent and prevent stale optimizer
caches from hiding a new capture set.
Public pages label product imagery as an illustrative profile and Medscribe
interface.
### Capturing raw screenshots for the site
Export **in-app content only** from the simulator or device — no simulator chrome or macOS capture toolbar. A normal in-app status bar/tab bar is fine.
1. Run the app on **iPhone 17 Pro** (or 16 Pro) simulator or device, or on an **Android** emulator/device.
2. Capture each screen (⌘S in Simulator saves to Desktop; `adb exec-out screencap -p` on Android).
3. Drop PNGs into `public/screenshots/` and update paths in the relevant route
or `src/components/feature-showcase.tsx`.
1. Run the app on an **iPhone 17 Pro** simulator or device.
2. Capture each screen (⌘S in Simulator saves to Desktop).
3. Place each 1206 × 2622 capture at native size in the 1350 × 2760 Silver
bezel at offset `+72+69`, clip it to the calibrated display-opening mask,
and export a transparent, lossless WebP into the shared versioned asset
directory referenced by the routes.
The CSS frame dimensions assume tall iPhone screenshots and are controlled in
`src/components/phone-mockup.tsx`. Use `captureMode="simulator"` only for old
captures that already include device chrome. Homepage product images are
composited separately at 810 × 1656 with transparent backgrounds and rendered
through `src/components/product-device.tsx`.
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 smaller `PhoneMockup` wrapper reuses
that same component. The homepage uses CSS view timelines for
scroll-scrubbed device and chapter motion on desktop and mobile, with a static
fallback and a reduced-motion override.
+14 -1
View File
@@ -4,7 +4,20 @@
*/
import "./src/env.js";
const isGitHubPages = process.env.GITHUB_PAGES === "true";
/** @type {import("next").NextConfig} */
const config = {};
const config = {
...(isGitHubPages
? {
output: "export",
trailingSlash: true,
}
: {}),
images: {
qualities: [75, 92],
unoptimized: isGitHubPages,
},
};
export default config;
+1
View File
@@ -0,0 +1 @@
Binary file not shown.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 295 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 348 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 454 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 226 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 170 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 260 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 296 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 668 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 186 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 187 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 336 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 145 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

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: 213 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 226 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: 202 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 221 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: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 795 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 887 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 839 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 899 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 796 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 916 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 736 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 854 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 265 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 268 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 173 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 179 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 733 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 820 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 897 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 987 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 878 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 937 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 576 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 589 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 833 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 952 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 833 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 952 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 698 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 787 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 164 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 172 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 331 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 293 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 301 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 768 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 861 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 485 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 198 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 234 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 395 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 217 KiB

+178
View File
@@ -0,0 +1,178 @@
import type { Metadata } from "next";
import {
ArrowRight,
CalendarDays,
Check,
ContactRound,
Mail,
Pill,
Smartphone,
Users,
} from "lucide-react";
import { SectionLabel } from "~/components/section-label";
import { Badge } from "~/components/ui/badge";
import { Button } from "~/components/ui/button";
import { productRelease } from "~/content/product";
import { ACCESS_INVITE_MAILTO } from "~/lib/access";
export const metadata: Metadata = {
title: "Request access",
description:
"Request access to Medscribe's closed beta without including personal health information.",
};
const fitCards = [
{
icon: Smartphone,
title: "Several moving pieces",
body: "You coordinate visits, medications, reminders, or follow-ups across everyday life.",
},
{
icon: Users,
title: "A trusted care circle",
body: "You want an easier way to keep a family caregiver informed when you choose.",
},
{
icon: Check,
title: "Clear, reviewable context",
body: "You value a record you can read, check, and bring into the next conversation.",
},
] as const;
const productCards = [
{
icon: CalendarDays,
title: "Visits that stay useful",
body: "Keep notes, transcripts, summaries, and follow-ups together so the details remain easy to revisit.",
},
{
icon: Pill,
title: "Medication routines at a glance",
body: "See medications, schedules, reminders, and refill details in one calm, readable place.",
},
{
icon: ContactRound,
title: "A ready-to-share picture",
body: "Bring selected medications, allergies, conditions, contacts, and preferences together in Know Me.",
},
] as const;
export default function AccessPage() {
return (
<>
<section className="px-4 pt-16 pb-18 sm:px-6 sm:pt-22">
<div className="mx-auto grid max-w-6xl gap-12 lg:grid-cols-[1fr_0.8fr] lg:items-center">
<div>
<div className="flex flex-wrap gap-2">
<Badge variant="success">{productRelease.stage}</Badge>
<Badge variant="outline">{productRelease.platforms}</Badge>
</div>
<h1 className="text-foreground mt-6 max-w-3xl font-display text-5xl leading-[1.02] font-semibold tracking-[-0.03em] sm:text-6xl">
Bring your care context together.
</h1>
<p className="text-muted-foreground mt-6 max-w-2xl text-lg leading-relaxed sm:text-xl">
Medscribe is made for people managing repeated visits, several
medications, and the trusted family members who help them stay
organized.
</p>
</div>
<div className="surface-panel rounded-[2rem] p-7 sm:p-9">
<div className="bg-primary-light text-primary flex size-12 items-center justify-center rounded-xl">
<Mail className="size-6" aria-hidden="true" />
</div>
<h2 className="text-foreground mt-5 font-display text-3xl font-semibold">
Request Medscribe access
</h2>
<p className="text-muted-foreground mt-4 text-sm leading-relaxed">
The beta is currently closed to a small group. Tell us your
platform and whether you are interested as a patient, caregiver,
or both, and we&apos;ll follow up as access becomes available.
</p>
<Button asChild size="lg" className="mt-7 w-full sm:w-auto">
<a href={ACCESS_INVITE_MAILTO}>
Draft access request
<ArrowRight className="size-4" aria-hidden="true" />
</a>
</Button>
<p className="bg-surface-soft text-muted-foreground mt-5 rounded-xl p-4 text-xs leading-relaxed">
Please do not send diagnoses, medication names, visit notes, or
other health details. Email is not a medical-support or emergency
channel.
</p>
</div>
</div>
</section>
<section className="section-wash px-4 py-20 sm:px-6 lg:py-24">
<div className="mx-auto max-w-6xl">
<SectionLabel>Made for real life</SectionLabel>
<h2 className="text-foreground mt-4 max-w-3xl font-display text-4xl font-semibold tracking-tight sm:text-5xl">
Keep the details close without carrying the whole burden in your
head.
</h2>
<div className="mt-10 grid gap-4 md:grid-cols-3">
{fitCards.map((item) => {
const Icon = item.icon;
return (
<article
key={item.title}
className="surface-panel rounded-2xl p-6"
>
<Icon className="text-primary size-6" aria-hidden="true" />
<h3 className="text-foreground mt-5 font-display text-2xl font-semibold">
{item.title}
</h3>
<p className="text-muted-foreground mt-3 text-sm leading-relaxed">
{item.body}
</p>
</article>
);
})}
</div>
</div>
</section>
<section className="px-4 py-20 sm:px-6 lg:py-28">
<div className="mx-auto max-w-6xl">
<SectionLabel>One connected picture</SectionLabel>
<h2 className="text-foreground mt-4 max-w-3xl font-display text-4xl font-semibold tracking-tight sm:text-5xl">
Visits, medications, and the people who mattertogether.
</h2>
<div className="mt-10 grid gap-4 md:grid-cols-3">
{productCards.map((item) => {
const Icon = item.icon;
return (
<article
key={item.title}
className="surface-panel rounded-2xl p-6"
>
<Icon className="text-primary size-6" aria-hidden="true" />
<h3 className="text-foreground mt-5 font-display text-2xl font-semibold">
{item.title}
</h3>
<p className="text-muted-foreground mt-3 text-sm leading-relaxed">
{item.body}
</p>
</article>
);
})}
</div>
<div className="night-card mt-14 rounded-[2rem] p-7 text-white sm:p-10">
<p className="text-xs font-bold tracking-[0.14em] text-teal-100 uppercase">
Keep your care team in the loop
</p>
<h2 className="mt-4 max-w-3xl font-display text-3xl font-semibold sm:text-4xl">
Medscribe helps you prepare for better conversations. Medical
decisions remain with you and your qualified care team.
</h2>
</div>
</div>
</section>
</>
);
}
+3 -224
View File
@@ -1,226 +1,5 @@
import type { Metadata } from "next";
import {
ArrowRight,
Check,
ClipboardCheck,
Mail,
MessageSquareText,
RotateCcw,
Smartphone,
Users,
} from "lucide-react";
import Link from "next/link";
import { redirect } from "next/navigation";
import { SectionLabel } from "~/components/section-label";
import { Badge } from "~/components/ui/badge";
import { Button } from "~/components/ui/button";
import { productRelease } from "~/content/product";
import { BETA_INVITE_MAILTO } from "~/lib/beta";
export const metadata: Metadata = {
title: "Request beta access",
description:
"Learn who the Medscribe internal beta is for, what participants should expect, and how to request access without submitting health information.",
};
const expectations = [
{
icon: ClipboardCheck,
title: "Review is part of testing",
body: "Check generated summaries, extracted medication fields, and the Know Me view before relying on them.",
},
{
icon: MessageSquareText,
title: "Direct feedback",
body: "Report confusing language, incorrect extraction, notification behavior, and sharing friction.",
},
{
icon: RotateCcw,
title: "Possible resets",
body: "This is an internal beta. Builds, local data, and setup may need to be reset as the product changes.",
},
] as const;
const testFocus = [
"Whether the record still feels current after several weeks",
"Medication-label edge cases and correction flow",
"Reminder permissions, timing, travel, and daylight-saving behavior",
"Caregiver pairing, encrypted export, and import comprehension",
"Whether the Know Me handoff is readable and appropriately cautious",
"Physical-device model performance and battery or thermal behavior",
] as const;
export default function BetaPage() {
return (
<>
<section className="px-4 pt-16 pb-18 sm:px-6 sm:pt-22">
<div className="mx-auto grid max-w-6xl gap-12 lg:grid-cols-[1fr_0.8fr] lg:items-center">
<div>
<div className="flex flex-wrap gap-2">
<Badge variant="success">{productRelease.stage}</Badge>
<Badge variant="outline">{productRelease.platforms}</Badge>
</div>
<h1 className="text-foreground mt-6 max-w-3xl font-serif text-5xl leading-[1.02] font-semibold tracking-[-0.03em] sm:text-6xl">
Test the care context, not just the demo.
</h1>
<p className="text-muted-foreground mt-6 max-w-2xl text-lg leading-relaxed sm:text-xl">
We are looking for people managing repeated visits or several
medications, especially family caregiver pairs willing to review
the record over time and tell us where it fails.
</p>
</div>
<div className="border-border-soft bg-surface rounded-[2rem] border p-7 shadow-[0_24px_70px_rgba(15,23,42,0.08)] sm:p-9">
<div className="bg-primary-light text-primary flex size-12 items-center justify-center rounded-xl">
<Mail className="size-6" aria-hidden="true" />
</div>
<h2 className="text-foreground mt-5 font-serif text-3xl font-semibold">
Request access by email
</h2>
<p className="text-muted-foreground mt-4 text-sm leading-relaxed">
The draft asks only for your platform, whether you are testing as
a patient, caregiver, or both, and whether you can test with
another person.
</p>
<Button asChild size="lg" className="mt-7 w-full sm:w-auto">
<a href={BETA_INVITE_MAILTO}>
Draft beta request
<ArrowRight className="size-4" aria-hidden="true" />
</a>
</Button>
<p className="bg-surface-soft text-muted-foreground mt-5 rounded-xl p-4 text-xs leading-relaxed">
Do not send diagnoses, medication names, visit notes, transcripts,
or other health details. Email is not a medical-support or
emergency channel.
</p>
</div>
</div>
</section>
<section className="border-border-soft border-y bg-[#f4f0e8]/75 px-4 py-20 sm:px-6 lg:py-24 dark:bg-[#151b25]">
<div className="mx-auto max-w-6xl">
<SectionLabel>A good fit</SectionLabel>
<h2 className="text-foreground mt-4 max-w-3xl font-serif text-4xl font-semibold tracking-tight sm:text-5xl">
The beta needs real maintenance and handoff situations.
</h2>
<div className="mt-10 grid gap-4 md:grid-cols-3">
{[
{
icon: Smartphone,
title: "Several moving pieces",
body: "You regularly coordinate visits, medication reminders, or follow-ups.",
},
{
icon: Users,
title: "A caregiver relationship",
body: "You can test a deliberate handoff with a trusted family caregiver.",
},
{
icon: Check,
title: "Comfort reviewing",
body: "You understand generated information can be wrong and will check it.",
},
].map((item) => {
const Icon = item.icon;
return (
<article
key={item.title}
className="border-border-soft bg-surface rounded-2xl border p-6"
>
<Icon className="text-primary size-6" aria-hidden="true" />
<h3 className="text-foreground mt-5 font-serif text-2xl font-semibold">
{item.title}
</h3>
<p className="text-muted-foreground mt-3 text-sm leading-relaxed">
{item.body}
</p>
</article>
);
})}
</div>
</div>
</section>
<section className="px-4 py-20 sm:px-6 lg:py-28">
<div className="mx-auto max-w-6xl">
<div className="grid gap-12 lg:grid-cols-[0.8fr_1.2fr]">
<div>
<SectionLabel>What to expect</SectionLabel>
<h2 className="text-foreground mt-4 font-serif text-4xl font-semibold tracking-tight">
This is collaborative product testing.
</h2>
<p className="text-muted-foreground mt-5 leading-relaxed">
Availability is controlled and continuity is not guaranteed.
Medscribe is not emergency care, diagnosis, dosing guidance, or
a replacement for your care team.
</p>
</div>
<div className="grid gap-4 sm:grid-cols-3">
{expectations.map((item) => {
const Icon = item.icon;
return (
<article
key={item.title}
className="border-border-soft bg-surface rounded-2xl border p-5"
>
<Icon className="text-primary size-5" aria-hidden="true" />
<h3 className="text-foreground mt-4 font-serif text-xl font-semibold">
{item.title}
</h3>
<p className="text-muted-foreground mt-3 text-sm leading-relaxed">
{item.body}
</p>
</article>
);
})}
</div>
</div>
<div className="mt-16 rounded-[2rem] bg-[#0f4f4b] p-7 text-white sm:p-10">
<div className="grid gap-10 lg:grid-cols-[0.7fr_1.3fr]">
<div>
<p className="text-xs font-bold tracking-[0.14em] text-teal-100 uppercase">
Current test focus
</p>
<h2 className="mt-4 font-serif text-3xl font-semibold">
The questions we are trying to answer
</h2>
</div>
<ul className="grid gap-3 sm:grid-cols-2">
{testFocus.map((item) => (
<li
key={item}
className="flex gap-3 rounded-xl border border-white/15 bg-white/8 p-4 text-sm leading-relaxed text-teal-50/85"
>
<Check
className="mt-0.5 size-4 shrink-0 text-teal-100"
aria-hidden="true"
/>
{item}
</li>
))}
</ul>
</div>
</div>
<div className="border-border-soft mt-12 flex flex-col items-start justify-between gap-5 border-t pt-10 sm:flex-row sm:items-center">
<div>
<h2 className="text-foreground font-serif text-2xl font-semibold">
Want the technical boundaries first?
</h2>
<p className="text-muted-foreground mt-2 text-sm">
See what stays local, how sharing works, and the current
evidence.
</p>
</div>
<Button asChild variant="outline">
<Link href="/privacy">Read privacy & evidence</Link>
</Button>
</div>
</div>
</section>
</>
);
export default function LegacyAccessPage() {
redirect("/access");
}
@@ -15,13 +15,12 @@ export default function NorthwellBriefPage() {
<NorthwellPrintSummary />
<div className="print-hidden mx-auto max-w-2xl px-4 py-16 text-center sm:px-6 lg:py-24">
<SectionLabel>Executive summary · Northwell Health</SectionLabel>
<h1 className="text-foreground mt-4 font-serif text-4xl font-semibold tracking-tight sm:text-5xl">
<h1 className="text-foreground mt-4 font-display text-4xl font-semibold tracking-tight sm:text-5xl">
The health-system executive summary
</h1>
<p className="text-muted-foreground mx-auto mt-5 max-w-xl leading-relaxed">
This private, search-excluded route preserves the existing three-page
print document. Use Print PDF (or Cmd+P, then Save as PDF) to export
it.
This page is formatted as a three-page print document. Use Print PDF
(or Cmd+P, then Save as PDF) to export it.
</p>
<div className="mt-8 flex justify-center">
<PrintButton size="lg" />
+1 -1
View File
@@ -15,7 +15,7 @@ export default function CvsSummaryPage() {
<CvsPrintSummary />
<div className="print-hidden mx-auto max-w-2xl px-4 py-16 text-center sm:px-6 lg:py-24">
<SectionLabel>Executive summary · CVS Health</SectionLabel>
<h1 className="text-foreground mt-4 font-serif text-4xl font-semibold tracking-tight sm:text-5xl">
<h1 className="text-foreground mt-4 font-display text-4xl font-semibold tracking-tight sm:text-5xl">
The pharmacy executive summary
</h1>
<p className="text-muted-foreground mx-auto mt-5 max-w-xl leading-relaxed">
+1 -426
View File
@@ -1,436 +1,11 @@
import type { CSSProperties } from "react";
import type { Metadata } from "next";
import { redirect } from "next/navigation";
import Image from "next/image";
import { MedscribeLogo } from "~/components/medscribe-logo";
import { PhoneMockup } from "~/components/phone-mockup";
import { PrintButton } from "~/components/print-button";
import { SectionLabel } from "~/components/section-label";
import { BETA_FOOTER_NOTE, BETA_SUMMARY } from "~/lib/beta";
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from "~/components/ui/card";
export const metadata: Metadata = {
title: "Executive Summary",
description:
"One-page executive summary for Medscribe, a private medical context app for families managing complex care.",
title: "Medscribe",
robots: { index: false, follow: false, nocache: true },
};
const TAGLINE =
"Your medical truth, in your pocket, and only where you say it goes.";
const SNAPSHOT =
"Medscribe is a private, patient-owned medical record and companion for people managing ongoing care and the families beside them. It captures visits, makes medications and instructions easy to understand and keep current day to day, and stays ready to hand to a caregiver, a new specialist, or an ER. Everything runs on the device; nothing is uploaded.";
const PROBLEM =
"Care is fragmented and hard to carry. Patients forget most of what they're told in a visit, juggle medications with no clear picture of what each is for, and lose track of what changed and why. Then they end up somewhere new: a covering doctor, a specialist, an ER outside their network, and none of it travels with them. The family knows, but can't produce a clear, current record under pressure.";
const PROBLEM_BROADER =
"This is not a rare edge case. It happens every day, to patients with Parkinson's, diabetes, heart disease, dementia, and a hundred other conditions that require precise, continuous management across a fragmented system. The failure is not that families don't care. The failure is that the patient's context does not travel with them.";
const WHO_ITS_FOR =
"Anyone managing serious, ongoing care across a fragmented health system, and the families who coordinate it. It spans conditions and ages, and eventually touches almost everyone. The failure is simple: the patient's context does not travel with them.";
const DIFFERENTIATION =
"The market is full of AI visit recorders, medication trackers, health-record apps, and emergency QR cards, each owning one slice. None owns the whole job. In Medscribe, the daily tools are the maintenance system for one emergency-ready record.";
const differentiators = [
{
title: "The record is the product",
body: "Recording, scanning, reminders, and Q&A all feed one private record you actually keep current, useful every day and ready to hand over when it counts. Competitors ship visit summaries; we ship the record you own and carry.",
},
{
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.",
},
{
title: "Facts-first, not a guess",
body: "Medication answers render trusted drug facts deterministically, deferring dosing and diagnosis to a clinician or pharmacist. Built for complex-care families, not a general health bot.",
},
];
const MOAT =
"The privacy promise is easy to claim. The execution is not. Medscribe runs a fine-tuned medical model entirely on the phone, built and measured rather than bolted on.";
const moat = [
{
title: "A model tuned for this job",
body: "A compact, multi-task model handles label scanning, structured extraction, and safe medication Q&A on the device. Fine-tuning lifted prescription-label field extraction from 0% to 97% in evaluation.",
},
{
title: "Safety you can measure",
body: "Each release is scored against a held-out set for grounding and safe refusals. Unsafe-prompt refusals reached 100% after tuning, so “defers to a clinician” is a tested behavior, not a hope.",
},
{
title: "Context that compounds",
body: "Real visit transcripts, a real medication list, and bundled drug facts fuse into one local record, value that grows with use and is hard to replicate without the same on-device capture.",
},
];
const scenarios = [
{
title: "The ER that doesn't know you",
body: "A patient on time-critical medication ends up at a hospital outside their network. Missing a dose by hours isn't an inconvenience; it's a medical event. Nobody has the schedule, and the family can't produce it under pressure.",
},
{
title: "The caregiver handoff",
body: "An adult child manages a parent's medications, appointments, and history. When they're not there, the context disappears: a sibling visits, a home aide covers, a shift changes. Critical details live in one person's memory.",
},
{
title: "The newly diagnosed, overwhelmed",
body: "After a new diagnosis, a patient leaves with a changed medication schedule, lifestyle instructions, and follow-ups they half-remember. By the next visit, the provider can't tell what was understood, tried, or missed.",
},
];
const impact = [
{
title: "Fewer blank handoffs",
body: "When a caregiver or clinician takes over, the facts are already assembled: conditions, medications, allergies, baseline, contacts, and recent changes.",
},
{
title: "Safer medication moments",
body: "Time-critical schedules and dose history stay visible, so a missed or delayed medication is easier to catch before it becomes a crisis.",
},
{
title: "Patients and providers aligned",
body: "Families see what changed and why; providers get a current snapshot instead of reconstructing it from a stressed family's memory.",
},
];
const FOR_HEALTH_SYSTEMS =
"Epic is the definitive record of care inside the network. What no institutional EHR is built to be is the record the patient owns and carries everywhere else: the out-of-network ER, the specialist on another Epic instance, the months between visits at home. That out-of-hospital stretch is a structural blind spot, not a flaw in any one system. Medscribe fills it on the patient's own device, and — only with the patient's consent — hands that context back, so the gap becomes an ongoing connection instead of a black box.";
const forHealthSystems = [
{
title: "Reaches where the EHR can't",
body: "The record lives on the patient's device and travels with them: the out-of-network ER, the covering specialist, the weeks at home between visits. It stays current exactly where an institutional system loses sight of the patient.",
},
{
title: "Feeds context back into Epic",
body: "With the patient's consent, the out-of-network and between-visit context Medscribe captures returns into the workflows you already run. It raises the value of the EHR investment rather than competing for budget or attention.",
},
{
title: "Patient-owned, so it persists",
body: "A branded, patient-facing surface that works the levers systems are measured on — in-network retention, medication adherence, avoidable readmissions. Because the record belongs to the patient, it holds even if the system changes EHRs.",
},
];
const printLightTokens = {
"--color-foreground": "#0f172a",
"--color-primary": "#0f766e",
"--color-surface": "#ffffff",
"--color-border-soft": "#e2e8f0",
"--color-muted-foreground": "#475569",
color: "#0f172a",
} as CSSProperties;
export default function ExecutiveSummaryPage() {
// The home page is now the executive summary (single-page site). This deep
// page is retired but kept in place — its content (incl. the print one-pager)
// is a one-line revert away if we want a longer version back.
redirect("/");
return (
<>
{/* ===================== SCREEN ===================== */}
<div className="print-hidden mx-auto max-w-6xl space-y-14 px-4 py-10 sm:px-6 lg:space-y-20 lg:py-14">
{/* Hero */}
<section className="grid items-start gap-8 lg:grid-cols-[minmax(0,1fr)_minmax(220px,280px)] lg:gap-14">
<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">
Medscribe
</h1>
<p className="font-serif text-xl font-semibold tracking-tight text-foreground sm:text-2xl">
{TAGLINE}
</p>
</div>
<p className="text-base leading-relaxed text-muted-foreground sm:text-lg">
{SNAPSHOT}
</p>
</div>
<div className="justify-self-center lg:justify-self-end">
<PhoneMockup
src="/screenshots/home.png"
alt="Medscribe home screen"
width={200}
priority
/>
</div>
</section>
{/* The Problem */}
<section className="space-y-5">
<SectionLabel>The problem</SectionLabel>
<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">
<p>{PROBLEM}</p>
<p className="font-medium text-foreground">{PROBLEM_BROADER}</p>
</div>
</section>
{/* Scenarios */}
<section className="space-y-6">
<SectionLabel>Who this is for</SectionLabel>
<h2 className="font-serif text-3xl font-semibold tracking-tight sm:text-4xl">
The moments where context is everything.
</h2>
<div className="grid gap-4 md:grid-cols-3">
{scenarios.map((scenario) => (
<Card key={scenario.title} className="card-hover">
<CardHeader>
<CardTitle className="text-lg">{scenario.title}</CardTitle>
<CardDescription>{scenario.body}</CardDescription>
</CardHeader>
</Card>
))}
</div>
</section>
{/* Differentiation */}
<section className="space-y-6">
<SectionLabel>Why this is different</SectionLabel>
<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">
{DIFFERENTIATION}
</p>
<div className="grid gap-4 md:grid-cols-3">
{differentiators.map((item) => (
<Card key={item.title} className="card-hover">
<CardHeader>
<CardTitle className="text-lg">{item.title}</CardTitle>
<CardDescription>{item.body}</CardDescription>
</CardHeader>
</Card>
))}
</div>
<Card className="border-primary-button/20 bg-primary-button text-white">
<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.
</p>
</CardContent>
</Card>
</section>
{/* Under the hood */}
<section className="space-y-6">
<SectionLabel>Under the hood</SectionLabel>
<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">
{MOAT}
</p>
<div className="grid gap-4 md:grid-cols-3">
{moat.map((item) => (
<Card key={item.title} className="card-hover">
<CardHeader>
<CardTitle className="text-lg">{item.title}</CardTitle>
<CardDescription>{item.body}</CardDescription>
</CardHeader>
</Card>
))}
</div>
</section>
{/* Impact */}
<section className="space-y-6">
<SectionLabel>Potential impact</SectionLabel>
<h2 className="font-serif text-3xl font-semibold tracking-tight sm:text-4xl">
Less panic, more context, better handoffs.
</h2>
<div className="grid gap-4 md:grid-cols-3">
{impact.map((item) => (
<Card
key={item.title}
className="card-hover border-primary-button/20 bg-primary-button text-white"
>
<CardHeader>
<CardTitle className="text-white">{item.title}</CardTitle>
<CardDescription className="text-white/75">
{item.body}
</CardDescription>
</CardHeader>
</Card>
))}
</div>
</section>
{/* For health systems */}
<section className="space-y-6">
<SectionLabel>For health systems</SectionLabel>
<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">
{FOR_HEALTH_SYSTEMS}
</p>
<div className="grid gap-4 md:grid-cols-3">
{forHealthSystems.map((item) => (
<Card key={item.title} className="card-hover">
<CardHeader>
<CardTitle className="text-lg">{item.title}</CardTitle>
<CardDescription>{item.body}</CardDescription>
</CardHeader>
</Card>
))}
</div>
</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">
{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">
Sean O&apos;Connor
</p>
</div>
{/* ===================== PRINT: dense one-page PDF ===================== */}
<article
style={printLightTokens}
className="print-sheet hidden print:flex print:h-[10.5in] print:flex-col print:px-[0.4in] print:pt-[0.22in] print:pb-[0.1in] print:text-[11pt] print:leading-[1.2]"
>
{/* 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">
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">
Medscribe
</h1>
</div>
<p className="mt-1.5 font-serif text-[12pt] leading-snug font-medium tracking-tight text-foreground italic">
{TAGLINE}
</p>
<p className="mt-2 text-[11pt] leading-[1.2] text-slate-700">
{SNAPSHOT}
</p>
</div>
<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"
alt="Medscribe home screen"
width={1206}
height={2622}
priority
unoptimized
className="h-full w-full object-cover object-top"
/>
</div>
</div>
</header>
{/* 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">
The Problem
</h2>
<p className="mt-1 text-[11pt] leading-[1.2] text-slate-700">
{PROBLEM}
</p>
</section>
{/* 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">
Who It&apos;s For
</h2>
<p className="mt-1 text-[11pt] leading-[1.2] text-slate-700">
{WHO_ITS_FOR}
</p>
</section>
{/* 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">
Why This Is Different
</h2>
<div className="mt-1.5 grid grid-cols-3 gap-x-6">
{differentiators.map((item) => (
<p
key={item.title}
className="text-[11pt] leading-[1.2] text-slate-700"
>
<span className="font-semibold text-foreground">
{item.title}.
</span>{" "}
{item.body}
</p>
))}
</div>
</section>
{/* 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">
Under The Hood
</h2>
<div className="mt-1 grid grid-cols-3 gap-x-6">
{moat.map((item) => (
<p
key={item.title}
className="text-[11pt] leading-[1.2] text-slate-700"
>
<span className="font-semibold text-foreground">
{item.title}.
</span>{" "}
{item.body}
</p>
))}
</div>
</section>
{/* For Health Systems */}
<section className="pt-1">
<h2 className="font-serif text-[12.5pt] font-semibold tracking-tight text-foreground">
For Health Systems
</h2>
<div className="mt-1 grid grid-cols-3 gap-x-6">
{forHealthSystems.map((item) => (
<p
key={item.title}
className="text-[11pt] leading-[1.2] text-slate-700"
>
<span className="font-semibold text-foreground">
{item.title}.
</span>{" "}
{item.body}
</p>
))}
</div>
</section>
<footer className="mt-auto flex items-center justify-between border-t border-teal-900/10 pt-1.5 text-[10pt] text-slate-500">
<p>Sean O&apos;Connor</p>
<p className="text-slate-400">{BETA_FOOTER_NOTE}</p>
</footer>
</article>
</>
);
}
+117 -93
View File
@@ -1,11 +1,11 @@
import type { Metadata } from "next";
import {
ArrowRight,
Camera,
CalendarDays,
Check,
FileText,
Keyboard,
Mic,
ListChecks,
MessageCircleQuestion,
RotateCcw,
ShieldAlert,
} from "lucide-react";
import Link from "next/link";
@@ -14,34 +14,33 @@ import { PhoneMockup } from "~/components/phone-mockup";
import { SectionLabel } from "~/components/section-label";
import { Badge } from "~/components/ui/badge";
import { Button } from "~/components/ui/button";
import { productClaims } from "~/content/product";
export const metadata: Metadata = {
title: "How it works",
description:
"See how Medscribe turns visits and medication routines into one local record a person can review and carry.",
"See how Medscribe brings visits, medication routines, and important context into one reviewable record.",
};
const inputs = [
const dailyRhythm = [
{
icon: Keyboard,
title: "Type or paste",
body: "Start from notes you already have and keep the source close to the result.",
icon: CalendarDays,
title: "Start with the moment",
body: "Give each visit a clear place so the details remain easy to find later.",
},
{
icon: Camera,
title: "Import a screenshot",
body: "Bring in a portal summary or prescription label, then correct extracted fields.",
icon: ListChecks,
title: "Review what matters",
body: "Check the useful details and keep your own judgment in the loop.",
},
{
icon: FileText,
title: "Attach a document",
body: "Use a photo or document as the input to a local review workflow.",
icon: MessageCircleQuestion,
title: "Keep the next question",
body: "Save what you want to ask while it is still fresh in your mind.",
},
{
icon: Mic,
title: "Record with consent",
body: "Optional visit audio requires consent and is transcribed on the device.",
icon: RotateCcw,
title: "Return when needed",
body: "Revisit the same picture before the next appointment or handoff.",
},
] as const;
@@ -49,7 +48,7 @@ const boundaries = [
"It does not diagnose or recommend treatment.",
"It does not calculate, shift, or supply medication timing.",
"It does not replace a pharmacist, prescribing team, or emergency service.",
"It does not automatically synchronize a household in the background.",
"It does not decide what you should share or who should receive it.",
] as const;
export default function HowItWorksPage() {
@@ -57,32 +56,32 @@ export default function HowItWorksPage() {
<>
<section className="px-4 pt-16 pb-18 sm:px-6 sm:pt-22">
<div className="mx-auto max-w-6xl">
<Badge variant="success">Current beta workflow</Badge>
<h1 className="text-foreground mt-6 max-w-4xl font-serif text-5xl leading-[1.02] font-semibold tracking-[-0.03em] sm:text-6xl">
<Badge variant="success">A day with Medscribe</Badge>
<h1 className="text-foreground mt-6 max-w-4xl font-display text-5xl leading-[1.02] font-semibold tracking-[-0.03em] sm:text-6xl">
One record, built through everyday use.
</h1>
<p className="text-muted-foreground mt-6 max-w-2xl text-lg leading-relaxed sm:text-xl">
Medscribe is useful at a handoff only if ordinary moments keep the
picture current. Every generated result has a person in the review
loop.
picture clear. You stay in the review loop from the first note to
the next conversation.
</p>
</div>
</section>
<section className="border-border-soft bg-surface/75 border-y px-4 py-18 sm:px-6 lg:py-22">
<section className="section-wash px-4 py-16 sm:px-6 lg:py-18">
<div className="mx-auto max-w-6xl">
<SectionLabel>Start where the information is</SectionLabel>
<h2 className="text-foreground mt-4 max-w-3xl font-serif text-4xl font-semibold tracking-tight sm:text-5xl">
Four ways in. One review checkpoint.
<SectionLabel>Start with what matters</SectionLabel>
<h2 className="text-foreground mt-4 max-w-3xl font-display text-4xl font-semibold tracking-tight sm:text-5xl">
A clear rhythm from the moment to the next conversation.
</h2>
<div className="mt-10 grid gap-4 sm:grid-cols-2 lg:grid-cols-4">
{inputs.map((item, index) => {
<div className="mt-8 grid gap-4 sm:grid-cols-2 lg:grid-cols-4">
{dailyRhythm.map((item, index) => {
const Icon = item.icon;
return (
<article
key={item.title}
className="border-border-soft bg-canvas rounded-2xl border p-6"
className="surface-panel rounded-2xl p-6"
>
<div className="flex items-center justify-between">
<span className="bg-primary-light text-primary flex size-11 items-center justify-center rounded-xl">
@@ -92,7 +91,7 @@ export default function HowItWorksPage() {
0{index + 1}
</span>
</div>
<h3 className="text-foreground mt-5 font-serif text-2xl font-semibold">
<h3 className="text-foreground mt-5 font-display text-2xl font-semibold">
{item.title}
</h3>
<p className="text-muted-foreground mt-3 text-sm leading-relaxed">
@@ -102,120 +101,145 @@ export default function HowItWorksPage() {
);
})}
</div>
<div className="border-primary/20 bg-primary-light/45 mt-6 flex gap-3 rounded-2xl border p-5">
<div className="surface-panel mt-6 flex gap-3 rounded-2xl p-5">
<Check
className="text-primary mt-0.5 size-5 shrink-0"
aria-hidden="true"
/>
<p className="text-foreground text-sm leading-relaxed">
The person reviews summaries and extracted medication fields.
Medscribe does not silently turn model output into an
authoritative medical record.
You review the details before they become part of the picture you
carry.
</p>
</div>
</div>
</section>
<section className="px-4 py-20 sm:px-6 lg:py-28">
<div className="mx-auto max-w-6xl space-y-24">
<div className="grid gap-12 lg:grid-cols-2 lg:items-center">
<section className="px-4 py-16 sm:px-6 lg:py-20">
<div className="mx-auto max-w-6xl space-y-16 lg:space-y-20">
<div className="grid gap-8 lg:grid-cols-2 lg:items-center lg:gap-12">
<div>
<SectionLabel>Review what changed</SectionLabel>
<h2 className="text-foreground mt-4 font-serif text-4xl font-semibold tracking-tight sm:text-5xl">
A summary is a draft, not a verdict.
<h2 className="text-foreground mt-4 font-display text-4xl font-semibold tracking-tight sm:text-5xl">
Keep the visit and the takeaway together.
</h2>
<p className="text-muted-foreground mt-5 leading-relaxed">
Supported transcription and summarization run locally. The visit
remains available beside the summary so a person can check
follow-ups and wording.
The visit remains available beside the summary so you can check
wording, follow-ups, and the details you want to remember.
</p>
<p className="border-border-soft bg-surface text-muted-foreground mt-5 rounded-2xl border p-5 text-sm leading-relaxed">
<strong className="text-foreground">What comes next:</strong> a
structured review inbox for accepting, correcting, or dismissing
changes inferred from a visit.
<p className="surface-panel text-muted-foreground mt-5 rounded-2xl p-5 text-sm leading-relaxed">
<strong className="text-foreground">Stay oriented:</strong> move
between the transcript and summary whenever you want the fuller
context.
</p>
</div>
<div className="bg-primary-light/45 justify-self-center rounded-[2.5rem] p-7">
<div className="justify-self-center py-2">
<PhoneMockup
src="/screenshots/appointment-summary.png"
alt="Synthetic Medscribe beta visit summary"
width={235}
src="/screenshots/product-bezel-2026-08-24-unified-type/summary-reviewed-natural.webp"
darkSrc="/screenshots/product-bezel-2026-08-24-unified-type/summary-reviewed-natural-dark.webp"
alt="Illustrative Medscribe visit summary"
width={260}
/>
<p className="text-muted-foreground mt-4 text-center text-xs">
Synthetic demo data · beta interface
Illustrative profile · Medscribe interface
</p>
</div>
</div>
<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]">
<div className="grid gap-8 lg:grid-cols-2 lg:items-center lg:gap-12">
<div className="justify-self-center py-2 lg:order-1">
<PhoneMockup
src="/screenshots/medication-detail.png"
alt="Synthetic Medscribe beta medication detail"
width={235}
src="/screenshots/product-bezel-2026-08-24-unified-type/medication-detail-lisinopril-natural.webp"
darkSrc="/screenshots/product-bezel-2026-08-24-unified-type/medication-detail-lisinopril-natural-dark.webp"
alt="Illustrative Medscribe medication detail"
width={260}
/>
<p className="text-muted-foreground mt-4 text-center text-xs">
Synthetic demo data · beta interface
Illustrative profile · Medscribe interface
</p>
</div>
<div className="lg:order-2">
<SectionLabel>Maintain the medication picture</SectionLabel>
<h2 className="text-foreground mt-4 font-serif text-4xl font-semibold tracking-tight sm:text-5xl">
Facts and schedules carry their boundary with them.
<h2 className="text-foreground mt-4 font-display text-4xl font-semibold tracking-tight sm:text-5xl">
Keep the daily routine easy to read.
</h2>
<p className="text-muted-foreground mt-5 leading-relaxed">
{productClaims.medicationFacts.publicCopy} Schedules can record
whether they are fixed-time or as-needed, the times supplied by
the person&apos;s source, confirmation, and timezone.
See medication details, schedules, reminders, and refill
information together without hunting through separate notes.
</p>
<p className="text-muted-foreground mt-5 text-sm leading-relaxed">
Medscribe records timing supplied by a label, pharmacist, or
prescribing team. It does not calculate or shift medication
times.
Keep medication timing easy to read and confirm changes with
the care professional who gave you the instructions.
</p>
</div>
</div>
<div className="grid gap-12 lg:grid-cols-2 lg:items-center">
<div className="grid gap-8 lg:grid-cols-2 lg:items-center lg:gap-12">
<div className="lg:order-2">
<SectionLabel>Keep the next question</SectionLabel>
<h2 className="text-foreground mt-4 font-display text-4xl font-semibold tracking-tight sm:text-5xl">
Save it while it is on your mind.
</h2>
<p className="text-muted-foreground mt-5 leading-relaxed">
Add questions as they come up between visits. If Ask reaches a
question that needs professional judgment, Medscribe can offer
to save it and suggest who may be helpful to ask.
</p>
<p className="text-muted-foreground mt-5 text-sm leading-relaxed">
Your list is ready when the appointment starts, so the most
important question does not disappear in the moment.
</p>
</div>
<div className="justify-self-center py-2 lg:order-1">
<PhoneMockup
src="/screenshots/product-bezel-2026-08-24-unified-type/questions-inline-natural.webp"
darkSrc="/screenshots/product-bezel-2026-08-24-unified-type/questions-inline-natural-dark.webp"
alt="Illustrative Medscribe Questions to ask interface"
width={260}
/>
<p className="text-muted-foreground mt-4 text-center text-xs">
Illustrative profile · Medscribe interface
</p>
</div>
</div>
<div className="grid gap-8 lg:grid-cols-2 lg:items-center lg:gap-12">
<div>
<SectionLabel>Prepare the handoff</SectionLabel>
<h2 className="text-foreground mt-4 font-serif text-4xl font-semibold tracking-tight sm:text-5xl">
<h2 className="text-foreground mt-4 font-display text-4xl font-semibold tracking-tight sm:text-5xl">
Know Me is the view. Sharing is a separate choice.
</h2>
<p className="text-muted-foreground mt-5 leading-relaxed">
Open the local Know Me screen when someone needs a concise
picture. For a caregiver, pair devices, compare a safety number,
review the record, and manually export an encrypted snapshot.
Open Know Me when someone needs a concise picture. Review the
details first, then show or share the selected context with a
trusted caregiver.
</p>
<p className="text-muted-foreground mt-5 text-sm leading-relaxed">
The current import path does not yet require the sender to be in
the recipient&apos;s active trust list, so recipients must
verify the sender out of band. Revocation prevents a future
local export; it cannot invalidate already-exported ciphertext
or erase a copy the recipient imported.
You stay in control of the handoff: what is included, who sees
it, and when the conversation happens.
</p>
</div>
<div className="bg-primary-light/45 justify-self-center rounded-[2.5rem] p-7">
<div className="justify-self-center py-2">
<PhoneMockup
src="/screenshots/emergency-record.png"
alt="Synthetic Medscribe beta Know Me handoff"
width={235}
src="/screenshots/product-bezel-2026-08-24-unified-type/know-me-natural.webp"
darkSrc="/screenshots/product-bezel-2026-08-24-unified-type/know-me-natural-dark.webp"
alt="Illustrative Medscribe Know Me handoff"
width={260}
/>
<p className="text-muted-foreground mt-4 text-center text-xs">
Synthetic demo data · beta interface
Illustrative profile · Medscribe interface
</p>
</div>
</div>
</div>
</section>
<section className="border-border-soft border-t bg-[#f4f0e8]/75 px-4 py-20 sm:px-6 dark:bg-[#151b25]">
<div className="mx-auto grid max-w-6xl gap-12 lg:grid-cols-2">
<section className="section-wash px-4 py-16 sm:px-6">
<div className="mx-auto grid max-w-6xl gap-8 lg:grid-cols-2 lg:gap-12">
<div>
<div className="bg-primary-light text-primary flex size-12 items-center justify-center rounded-xl">
<ShieldAlert className="size-6" aria-hidden="true" />
</div>
<h2 className="text-foreground mt-5 font-serif text-4xl font-semibold tracking-tight">
<h2 className="text-foreground mt-5 font-display text-4xl font-semibold tracking-tight">
What Medscribe does not do
</h2>
<p className="text-muted-foreground mt-4 leading-relaxed">
@@ -226,7 +250,7 @@ export default function HowItWorksPage() {
{boundaries.map((item) => (
<li
key={item}
className="border-border-soft bg-surface text-foreground flex gap-3 rounded-2xl border p-4 text-sm leading-relaxed"
className="surface-panel text-foreground flex gap-3 rounded-2xl p-4 text-sm leading-relaxed"
>
<Check
className="text-primary mt-0.5 size-5 shrink-0"
@@ -239,15 +263,15 @@ export default function HowItWorksPage() {
</div>
</section>
<section className="px-4 py-20 sm:px-6">
<div className="mx-auto flex max-w-6xl flex-col items-start justify-between gap-7 rounded-[2rem] bg-[#0f4f4b] px-7 py-10 text-white sm:px-10 md:flex-row md:items-center">
<section className="px-4 py-16 sm:px-6">
<div className="night-card mx-auto flex max-w-6xl flex-col items-start justify-between gap-7 rounded-[2rem] px-7 py-10 text-white sm:px-10 md:flex-row md:items-center">
<div>
<h2 className="font-serif text-3xl font-semibold">
See the trust boundary task by task.
<h2 className="font-display text-3xl font-semibold">
Privacy should feel understandable.
</h2>
<p className="mt-2 text-sm leading-relaxed text-teal-50/75">
Read what stays local, what can use a network, and what remains
unfinished.
See how Medscribe keeps you in control of the context you keep,
review, and share.
</p>
</div>
<Button
@@ -257,7 +281,7 @@ export default function HowItWorksPage() {
className="border-white/20 bg-white text-[#0f4f4b] hover:bg-teal-50"
>
<Link href="/privacy">
Privacy & evidence
Read about privacy
<ArrowRight className="size-4" aria-hidden="true" />
</Link>
</Button>
+1 -157
View File
@@ -1,167 +1,11 @@
import type { Metadata } from "next";
import { redirect } from "next/navigation";
import { SectionLabel } from "~/components/section-label";
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from "~/components/ui/card";
export const metadata: Metadata = {
title: "Solution Landscape",
description:
"How the medical-context space is divided today, and the combined job no existing product owns.",
title: "Medscribe",
robots: { index: false, follow: false, nocache: true },
};
const INTRO =
"The space is crowded. Visit recorders, medication apps, health-record vaults, emergency IDs, and caregiver tools all exist and are improving. But each owns one slice. None owns the whole job: a private, patient-owned medical context that stays current through daily use and is ready to hand over in a crisis.";
const categories = [
{
category: "Patient AI visit notetakers",
examples: "Kin, AlignCare, Emilia, PatientScribe, Medcorder",
gap: "Capture and summarize the visit, but the summary is the product. It is not turned into an emergency-ready record a family can hand over.",
},
{
category: "Medication trackers",
examples: "Medisafe, MyTherapy, Dosecast",
gap: "Know the pill list and reminders, but never heard the visit. No grounded understanding of why a medication is on the list or what changed.",
},
{
category: "Personal health records",
examples: "KeepMD, Available Health, Replicoo, Guava, DrOwl",
gap: "Store and aggregate documents, but are passive. Nothing keeps them current, and a broad PHR is undifferentiated.",
},
{
category: "Emergency IDs and QR cards",
examples: "Apple Medical ID, MedicAlert, tenderID, Epic Share Everywhere",
gap: "A static snapshot with no daily maintenance loop, so the card is only as accurate as the last manual edit.",
},
{
category: "Caregiver coordination",
examples: "Innerhive, Alula, Connected Caregiver, Caring Village",
gap: "Tend toward tasks, calendars, and messaging. They coordinate people, not the integrity of the medical context itself.",
},
{
category: "Provider-side scribes",
examples: "Abridge, Nuance DAX, Suki",
gap: "Built for the clinician's chart and billing, in clinical language. Not for the patient or the family carrying context across systems.",
},
];
const bundle = [
"Patient- and caregiver-owned mobile app",
"On-device visit transcription",
"Medication OCR and intake tracking",
"Facts-first medication Q&A grounded in trusted drug data",
"Current medications and visit context fused into one local record",
"An emergency “know me” handoff",
"Caregiver sharing designed for complex-care families",
"End-to-end encrypted, peer-to-peer sharing as a core architecture",
];
export default function LandscapePage() {
// Unpublished for now — not part of what external contacts (e.g. the
// Northwell introduction) should see. Content is kept in place, not
// deleted, so this is a one-line revert when we want it public again.
redirect("/");
return (
<div className="mx-auto max-w-6xl space-y-14 px-4 py-10 sm:px-6 lg:space-y-20 lg:py-14">
{/* Hero */}
<section className="space-y-5">
<SectionLabel>Solution landscape</SectionLabel>
<h1 className="max-w-3xl font-serif text-4xl leading-[1.05] font-semibold tracking-tight text-foreground sm:text-5xl">
The field, and the gap
</h1>
<p className="max-w-3xl text-base leading-relaxed text-muted-foreground sm:text-lg">
{INTRO}
</p>
</section>
{/* Category map */}
<section className="space-y-6">
<div className="space-y-2">
<SectionLabel>Who owns which slice</SectionLabel>
<h2 className="font-serif text-3xl font-semibold tracking-tight sm:text-4xl">
Six categories, each solving part of it
</h2>
</div>
<div className="grid gap-4 md:grid-cols-2">
{categories.map((item) => (
<Card key={item.category} className="card-hover">
<CardHeader className="gap-1.5">
<CardTitle className="text-lg">{item.category}</CardTitle>
<p className="text-xs font-medium tracking-wide text-primary">
{item.examples}
</p>
<CardDescription className="pt-1">{item.gap}</CardDescription>
</CardHeader>
</Card>
))}
</div>
</section>
{/* Closest competitor */}
<section className="space-y-4">
<SectionLabel>The closest direct competitor</SectionLabel>
<Card className="border-primary/15 bg-primary-light/40">
<CardContent className="space-y-3 pt-5 text-sm leading-relaxed text-foreground">
<p>
AlignCare matches the consumer bundle on paper: visit recording,
summaries, an AI assistant, medication reminders and logging,
documents, and caregiver sharing. It is real competition, not a
strawman.
</p>
<p>
The openings it leaves: its app-store disclosures indicate cloud
collection and tracking rather than on-device processing; it has no
first-class emergency handoff for a patient who cannot explain
themselves; and its medication answers are not described as
deterministic, on-device, facts-first rendering. Those are
Medscribe&apos;s wedges.
</p>
</CardContent>
</Card>
</section>
{/* The unowned bundle */}
<section className="space-y-6">
<div className="space-y-2">
<SectionLabel>What no one owns as one bundle</SectionLabel>
<h2 className="font-serif text-3xl font-semibold tracking-tight sm:text-4xl">
The combined job is the opening
</h2>
<p className="max-w-3xl text-muted-foreground">
Each box above has partial substitutes. No single incumbent unites
all of this into one private, patient-owned record:
</p>
</div>
<Card>
<CardContent className="pt-5">
<ul className="grid gap-x-8 gap-y-3 sm:grid-cols-2">
{bundle.map((point) => (
<li
key={point}
className="flex items-start gap-3 text-sm leading-snug text-foreground"
>
<span className="mt-1.5 size-1.5 shrink-0 rounded-full bg-primary" />
<span>{point}</span>
</li>
))}
</ul>
</CardContent>
</Card>
<p className="max-w-3xl leading-relaxed text-muted-foreground">
That intersection, the daily maintenance loop that keeps an
emergency-ready record current and private by architecture, is the lane
Medscribe is built to own.
</p>
</section>
</div>
);
}
+248 -162
View File
@@ -3,7 +3,9 @@ import {
ArrowRight,
Check,
ContactRound,
KeyRound,
Download,
FileText,
HeartHandshake,
LockKeyhole,
ScanLine,
ShieldCheck,
@@ -14,12 +16,12 @@ import Link from "next/link";
import { ProductDevice } from "~/components/product-device";
import { Button } from "~/components/ui/button";
import { productClaims, productRelease } from "~/content/product";
import { BETA_INVITE_MAILTO } from "~/lib/beta";
import { ACCESS_INVITE_MAILTO } from "~/lib/access";
export const metadata: Metadata = {
title: "Carry the context when care gets complicated",
description:
"Medscribe is a private, patient-controlled beta that helps keep visits, medications, and critical context together on your device.",
"Medscribe is a private, patient-controlled companion that keeps visits, medications, and critical context together.",
};
const visitMoments = [
@@ -28,71 +30,78 @@ 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",
alt: "Medscribe Visits screen in a natural titanium iPhone product bezel",
image: "/screenshots/product-bezel-2026-08-24-unified-type/visits-natural.webp",
darkImage:
"/screenshots/product-bezel-2026-08-24-unified-type/visits-natural-dark.webp",
alt: "Medscribe Visits screen in an iPhone 17 Pro product bezel",
},
{
number: "02",
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",
alt: "Medscribe visit transcript in a black titanium iPhone product bezel",
body: "Search the transcript and compare it with the generated summary before relying on it later.",
image:
"/screenshots/product-bezel-2026-08-24-unified-type/transcript-populated-black.webp",
darkImage:
"/screenshots/product-bezel-2026-08-24-unified-type/transcript-populated-black-dark.webp",
alt: "Medscribe visit transcript in an iPhone 17 Pro product bezel",
},
{
number: "03",
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",
alt: "Medscribe appointment summary in a natural titanium iPhone product bezel",
title: "Review the useful part. Keep your judgment.",
body: "Bring medications, follow-ups, diagnoses, and instructions into view, then check the details that matter.",
image:
"/screenshots/product-bezel-2026-08-24-unified-type/summary-reviewed-natural.webp",
darkImage:
"/screenshots/product-bezel-2026-08-24-unified-type/summary-reviewed-natural-dark.webp",
alt: "Medscribe appointment summary in an iPhone 17 Pro product bezel",
},
] as const;
const proofStats = [
{
value: productRelease.drugFacts.toLocaleString("en-US"),
label: "bundled medication records",
value: "One place",
label: "for visits, medications, and important context",
},
{
value: productRelease.rxNormTerms.toLocaleString("en-US"),
label: "RxNorm terms for matching",
value: "At a glance",
label: "for daily routines and reminders",
},
{
value: productRelease.interactionPairs.toLocaleString("en-US"),
label: "known interaction pairs",
value: "Your choice",
label: "when and what to share",
},
] as const;
const privacyPrinciples = [
{
icon: Smartphone,
title: "Your working record stays local",
title: "Built around the person",
body: productClaims.localRecord.publicCopy,
},
{
icon: LockKeyhole,
title: "AI runs on the device",
title: "Private by design",
body: productClaims.localAi.publicCopy,
},
{
icon: ShieldCheck,
title: "Facts do not come from model memory",
title: "Care decisions stay human",
body: productClaims.medicationFacts.publicCopy,
},
] as const;
const betaFit = [
const accessFit = [
"Managing several medications or repeated visits",
"Coordinating care with a family caregiver",
"Willing to review generated information and report errors",
"Keeping a clear record for the next conversation",
] as const;
export default function HomePage() {
return (
<>
<section className="relative isolate min-h-[calc(100svh-4rem)] overflow-hidden px-4 pt-14 sm:px-6 sm:pt-20 lg:pt-24">
<div className="bg-primary-light/55 absolute top-0 left-1/2 -z-10 h-[38rem] w-[68rem] max-w-[120vw] -translate-x-1/2 rounded-full blur-3xl" />
<section className="section-wash relative isolate min-h-[calc(100svh-4rem)] overflow-hidden px-4 pt-12 sm:px-6 sm:pt-16 lg:pt-20">
<div className="mx-auto max-w-7xl text-center">
<div className="animate-fade-in-up flex items-center justify-center gap-3">
<span className="bg-success-light text-success rounded-full px-3 py-1.5 text-xs font-bold tracking-[0.12em] uppercase">
@@ -102,17 +111,17 @@ export default function HomePage() {
{productRelease.platforms}
</span>
</div>
<h1 className="animate-fade-in-up-delay-1 text-foreground mx-auto mt-7 max-w-6xl font-serif text-[clamp(3.6rem,9vw,8.5rem)] leading-[0.86] font-semibold tracking-[-0.055em]">
<h1 className="animate-fade-in-up-delay-1 text-foreground mx-auto mt-7 max-w-6xl font-display text-[clamp(3.6rem,9vw,8.5rem)] leading-[0.86] font-semibold tracking-[-0.055em]">
Carry the context.
</h1>
<p className="animate-fade-in-up-delay-2 text-muted-foreground mx-auto mt-7 max-w-2xl text-lg leading-relaxed sm:text-xl lg:text-2xl">
Visits, medications, and the critical details between themkept
together on the device you carry.
together wherever care takes you.
</p>
<div className="animate-fade-in-up-delay-3 mt-8 flex flex-col items-center justify-center gap-3 sm:flex-row">
<Button asChild size="lg">
<Link href="/beta">
Request beta access
<Link href="/access">
Request access
<ArrowRight className="size-4" aria-hidden="true" />
</Link>
</Button>
@@ -122,38 +131,42 @@ export default function HomePage() {
</div>
</div>
<div className="relative mx-auto mt-12 h-[36rem] max-w-5xl sm:h-[46rem] lg:mt-8 lg:h-[54rem]">
<div className="relative mx-auto mt-10 h-[42rem] max-w-5xl sm:h-[52rem] lg:mt-6 lg:h-[60rem]">
<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"
alt="Medscribe visit summary in a natural titanium iPhone product bezel"
src="/screenshots/product-bezel-2026-08-24-unified-type/summary-reviewed-natural.webp"
darkSrc="/screenshots/product-bezel-2026-08-24-unified-type/summary-reviewed-natural-dark.webp"
alt="Medscribe visit summary in an iPhone 17 Pro product bezel"
className="pitch-device-motion pitch-device-drift-left"
sizes="(min-width: 1024px) 416px, (min-width: 640px) 352px, 272px"
priority
/>
</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"
alt="Medscribe home screen in a black titanium iPhone product bezel"
src="/screenshots/product-bezel-2026-08-24-unified-type/home-black.webp"
darkSrc="/screenshots/product-bezel-2026-08-24-unified-type/home-black-dark.webp"
alt="Medscribe home screen in an iPhone 17 Pro product bezel"
className="pitch-device-motion pitch-device-drift-right"
sizes="(min-width: 1024px) 448px, (min-width: 640px) 368px, 288px"
priority
/>
</div>
<p className="text-muted-foreground absolute inset-x-0 bottom-5 text-center text-xs font-medium tracking-wide sm:bottom-10">
Synthetic demo data · beta interface
</p>
</div>
<p className="text-muted-foreground relative z-20 mx-auto pb-6 text-center text-xs font-medium tracking-wide">
Illustrative profile · Medscribe interface
</p>
</section>
<section className="pitch-lazy border-border-soft bg-surface/80 flex min-h-[78svh] items-center border-y px-4 py-24 sm:px-6 lg:py-32">
<div className="mx-auto max-w-6xl text-center">
<section className="pitch-lazy section-wash px-4 pt-12 pb-20 sm:px-6 lg:pt-16 lg:pb-24">
<div className="pitch-copy-motion mx-auto max-w-6xl text-center">
<p className="text-primary text-xs font-bold tracking-[0.2em] uppercase">
The missing picture
The connected picture
</p>
<h2 className="text-foreground mx-auto mt-7 max-w-5xl font-serif text-[clamp(2.8rem,7vw,6.5rem)] leading-[0.98] font-semibold tracking-[-0.045em]">
<h2 className="text-foreground mx-auto mt-6 max-w-5xl font-display text-[clamp(2.8rem,7vw,6.5rem)] leading-[0.98] font-semibold tracking-[-0.045em]">
Care happens in fragments. Your context shouldn&apos;t.
</h2>
<p className="text-muted-foreground mx-auto mt-8 max-w-2xl text-lg leading-relaxed sm:text-xl">
<p className="text-muted-foreground mx-auto mt-6 max-w-2xl text-lg leading-relaxed sm:text-xl">
One instruction lives in a portal. A medication label sits in a
cabinet. The latest change lives in someone&apos;s memory. Medscribe
is the patient-held thread between those moments.
@@ -161,21 +174,21 @@ export default function HomePage() {
</div>
</section>
<section className="pitch-lazy px-4 py-24 sm:px-6 lg:py-36">
<div className="mx-auto grid max-w-7xl gap-16 lg:grid-cols-[0.78fr_1.22fr] lg:gap-24">
<section className="pitch-lazy px-4 py-20 sm:px-6 lg:py-28">
<div className="mx-auto grid max-w-7xl gap-12 lg:grid-cols-[0.78fr_1.22fr] lg:gap-20">
<div className="lg:sticky lg:top-28 lg:h-fit">
<p className="text-primary text-xs font-bold tracking-[0.2em] uppercase">
After the visit
</p>
<h2 className="text-foreground mt-6 max-w-xl font-serif text-5xl leading-[0.98] font-semibold tracking-[-0.04em] sm:text-6xl">
<h2 className="text-foreground mt-5 max-w-xl font-display text-5xl leading-[0.98] font-semibold tracking-[-0.04em] sm:text-6xl">
Turn what happened into something you can check.
</h2>
<p className="text-muted-foreground mt-7 max-w-lg text-lg leading-relaxed">
Bring in typed notes, a portal screenshot, a document, or an
optional consent-gated recording. The work happens locally. You
decide what is useful.
<p className="text-muted-foreground mt-6 max-w-lg text-lg leading-relaxed">
Bring the important details from a visit into one reviewable
record. You decide what is useful and what belongs in the picture
you carry forward.
</p>
<div className="border-primary/25 bg-primary-light/35 mt-8 max-w-lg rounded-2xl border p-5">
<div className="surface-panel mt-6 max-w-lg rounded-2xl p-5">
<p className="text-foreground text-sm leading-relaxed">
<strong className="font-semibold">The safety loop:</strong>{" "}
review generated information before acting. Medscribe does not
@@ -184,11 +197,11 @@ export default function HomePage() {
</div>
</div>
<ol className="space-y-8 sm:space-y-12">
{visitMoments.map((moment) => (
<ol className="space-y-6 sm:space-y-8">
{visitMoments.map((moment, index) => (
<li
key={moment.number}
className="border-border-soft bg-surface relative overflow-hidden rounded-[2.5rem] border px-5 pt-8 shadow-[0_30px_90px_rgba(15,23,42,0.08)] sm:px-10 sm:pt-10 dark:shadow-[0_30px_90px_rgba(0,0,0,0.25)]"
className="pitch-card-motion surface-panel relative overflow-hidden rounded-[2.5rem] px-5 pt-7 sm:px-10 sm:pt-9"
>
<div className="relative z-10 max-w-xl">
<div className="flex items-center gap-3">
@@ -199,7 +212,7 @@ export default function HomePage() {
{moment.eyebrow}
</p>
</div>
<h3 className="text-foreground mt-5 font-serif text-3xl font-semibold tracking-[-0.025em] sm:text-4xl">
<h3 className="text-foreground mt-5 font-display text-3xl font-semibold tracking-[-0.025em] sm:text-4xl">
{moment.title}
</h3>
<p className="text-muted-foreground mt-4 max-w-lg leading-relaxed">
@@ -207,10 +220,12 @@ export default function HomePage() {
</p>
</div>
<div className="bg-primary-light/45 absolute -right-36 bottom-14 -z-0 size-96 rounded-full blur-3xl" />
<div className="relative mx-auto mt-10 w-[min(72vw,21rem)] translate-y-14">
<div className="relative mx-auto mt-8 w-[min(72vw,20rem)] translate-y-10">
<ProductDevice
src={moment.image}
darkSrc={moment.darkImage}
alt={moment.alt}
className={`pitch-device-motion ${index % 2 === 0 ? "pitch-device-drift-right" : "pitch-device-drift-left"}`}
sizes="(min-width: 1024px) 336px, (min-width: 640px) 320px, 72vw"
/>
</div>
@@ -220,61 +235,64 @@ export default function HomePage() {
</div>
</section>
<section className="pitch-lazy relative isolate overflow-hidden bg-[#082f2c] px-4 py-24 text-white sm:px-6 lg:py-36">
<div className="absolute inset-0 -z-10 bg-[radial-gradient(circle_at_78%_18%,rgba(45,212,191,0.25),transparent_32%),radial-gradient(circle_at_16%_80%,rgba(20,184,166,0.15),transparent_28%)]" />
<section className="pitch-lazy brand-night relative isolate overflow-hidden px-4 py-20 text-white sm:px-6 lg:py-28">
<div className="mx-auto max-w-7xl">
<div className="mx-auto max-w-4xl text-center">
<div className="pitch-copy-motion mx-auto max-w-4xl text-center">
<p className="text-xs font-bold tracking-[0.2em] text-teal-200 uppercase">
Between visits
</p>
<h2 className="mt-6 font-serif text-[clamp(3rem,7vw,6.7rem)] leading-[0.94] font-semibold tracking-[-0.045em]">
Keep the medication picture from going stale.
<h2 className="mt-5 font-display text-[clamp(3rem,7vw,6.7rem)] leading-[0.94] font-semibold tracking-[-0.045em]">
Keep the medication picture current.
</h2>
<p className="mx-auto mt-8 max-w-2xl text-lg leading-relaxed text-teal-50/75 sm:text-xl">
<p className="mx-auto mt-6 max-w-2xl text-lg leading-relaxed text-teal-50/75 sm:text-xl">
The list, the label, the schedule, and the latest confirmation
belong in the same viewnot scattered across paper and memory.
</p>
</div>
<div className="mt-16 grid gap-14 lg:grid-cols-2 lg:items-center lg:gap-6">
<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]">
<div className="mt-12 grid gap-10 lg:grid-cols-2 lg:items-center lg:gap-6">
<div className="relative mx-auto h-[36rem] w-full max-w-2xl sm:h-[44rem] lg:h-[50rem]">
<div className="absolute top-12 left-[4%] w-[15rem] -rotate-6 sm:top-16 sm:w-[19rem] lg:w-[22rem]">
<ProductDevice
src="/screenshots/pitch/medication-detail-natural.webp"
alt="Medscribe medication detail in a natural titanium iPhone product bezel"
src="/screenshots/product-bezel-2026-08-24-unified-type/medication-detail-lisinopril-natural.webp"
darkSrc="/screenshots/product-bezel-2026-08-24-unified-type/medication-detail-lisinopril-natural-dark.webp"
alt="Medscribe medication detail in an iPhone 17 Pro product bezel"
className="pitch-device-motion pitch-device-drift-left"
sizes="(min-width: 1024px) 368px, (min-width: 640px) 336px, 272px"
/>
</div>
<div className="absolute top-0 right-[2%] z-10 w-[18rem] rotate-5 sm:w-[22rem] lg:w-[24rem]">
<div className="absolute top-0 right-[2%] z-10 w-[16rem] rotate-5 sm:w-[20rem] lg:w-[23rem]">
<ProductDevice
src="/screenshots/pitch/medications-black.webp"
alt="Medscribe medication list in a black titanium iPhone product bezel"
src="/screenshots/product-bezel-2026-08-24-unified-type/medications-black.webp"
darkSrc="/screenshots/product-bezel-2026-08-24-unified-type/medications-black-dark.webp"
alt="Medscribe medication list in an iPhone 17 Pro product bezel"
className="pitch-device-motion pitch-device-drift-right"
sizes="(min-width: 1024px) 384px, (min-width: 640px) 352px, 288px"
/>
</div>
</div>
<div className="grid gap-px overflow-hidden rounded-[2rem] border border-white/12 bg-white/12">
<div className="overflow-hidden rounded-[2rem] bg-white/[0.055]">
{[
{
title: "Show where a schedule came from",
body: "Schedules can carry their source, confirmation, timezone, and freshness state.",
title: "Keep schedules easy to understand",
body: "See timing, reminders, and refill details together in one calm view.",
},
{
title: "Keep facts deterministic",
title: "See the important details",
body: productClaims.medicationFacts.publicCopy,
},
{
title: "Make uncertainty visible",
body: "Missing or stale details stay visible so the person or clinician can verify them.",
title: "Make review simple",
body: "Keep the details readable so you can check them with a clinician or pharmacist.",
},
].map((item) => (
<article
key={item.title}
className="bg-[#0b3b37]/90 p-7 sm:p-9"
className="border-white/10 border-t p-6 first:border-t-0 sm:p-8"
>
<Check className="size-5 text-teal-200" aria-hidden="true" />
<h3 className="mt-5 font-serif text-2xl font-semibold sm:text-3xl">
<h3 className="mt-4 font-display text-2xl font-semibold sm:text-3xl">
{item.title}
</h3>
<p className="mt-3 leading-relaxed text-teal-50/70">
@@ -287,60 +305,83 @@ export default function HomePage() {
</div>
</section>
<section className="pitch-lazy bg-[#f0ece4] px-4 py-24 sm:px-6 lg:py-36 dark:bg-[#111827]">
<div className="mx-auto grid max-w-7xl items-center gap-14 lg:grid-cols-[1fr_0.9fr] lg:gap-24">
<div className="order-2 lg:order-1">
<section className="pitch-lazy section-wash overflow-hidden px-4 py-20 sm:px-6 lg:py-28">
<div
id="questions"
className="mx-auto grid max-w-7xl scroll-mt-24 items-center gap-10 lg:grid-cols-[0.82fr_1.18fr] lg:gap-16"
>
<div className="pitch-copy-motion">
<p className="text-primary text-xs font-bold tracking-[0.2em] uppercase">
Ask from the record
Questions for the doctor
</p>
<h2 className="text-foreground mt-6 max-w-2xl font-serif text-[clamp(3.25rem,6vw,6.5rem)] leading-[0.94] font-semibold tracking-[-0.045em]">
Better questions begin with your context.
<h2 className="text-foreground mt-5 max-w-2xl font-display text-[clamp(3.25rem,6vw,6.5rem)] leading-[0.94] font-semibold tracking-[-0.045em]">
Ask now. Save what belongs in the room.
</h2>
<p className="text-muted-foreground mt-8 max-w-xl text-lg leading-relaxed sm:text-xl">
Ask about a visit or medication without uploading the record to a
remote model. Answers are grounded in local history and bundled
facts, with the boundary kept in view.
<p className="text-muted-foreground mt-6 max-w-xl text-lg leading-relaxed sm:text-xl">
Ask about a visit or medication. When the answer needs a care
professional&apos;s judgment, Medscribe can suggest saving the
question and who may be helpful to ask.
</p>
<p className="border-primary/35 text-muted-foreground mt-7 max-w-xl border-l-2 pl-5 text-sm leading-relaxed">
Informational only. Medication changes still belong with a
clinician or pharmacist.
<div className="text-muted-foreground mt-6 flex max-w-xl items-start gap-3 text-sm leading-relaxed">
<span className="bg-primary-light text-primary mt-0.5 flex size-7 shrink-0 items-center justify-center rounded-full">
<Check className="size-3.5" aria-hidden="true" />
</span>
<p>
Keep a calm, ready list for your next appointment instead of
relying on memory when the conversation begins.
</p>
</div>
<div className="order-1 mx-auto w-[min(78vw,27rem)] lg:order-2">
</div>
<div className="mx-auto grid w-full max-w-[40rem] grid-cols-2 items-center justify-center gap-1 sm:gap-2 lg:justify-end">
<div className="mx-auto w-full -rotate-2">
<ProductDevice
src="/screenshots/pitch/ask-black.webp"
alt="Medscribe Ask response grounded in local health context, shown in a black titanium iPhone product bezel"
sizes="(min-width: 1024px) 432px, (min-width: 640px) 384px, 78vw"
src="/screenshots/product-bezel-2026-08-24-unified-type/ask-questions-black.webp"
darkSrc="/screenshots/product-bezel-2026-08-24-unified-type/ask-questions-black-dark.webp"
alt="Medscribe Ask response shown in an iPhone 17 Pro product bezel"
className="pitch-device-motion pitch-device-drift-left"
sizes="(min-width: 640px) 288px, 72vw"
/>
</div>
<div className="mx-auto w-full rotate-2">
<ProductDevice
src="/screenshots/product-bezel-2026-08-24-unified-type/questions-inline-natural.webp"
darkSrc="/screenshots/product-bezel-2026-08-24-unified-type/questions-inline-natural-dark.webp"
alt="Medscribe Questions to ask interface shown in an iPhone 17 Pro product bezel"
className="pitch-device-motion pitch-device-drift-right"
sizes="(min-width: 640px) 288px, 72vw"
/>
</div>
</div>
</div>
</section>
<section className="pitch-lazy overflow-hidden px-4 py-24 sm:px-6 lg:py-36">
<section className="pitch-lazy overflow-hidden px-4 py-20 sm:px-6 lg:py-28">
<div className="mx-auto max-w-7xl">
<div className="grid items-center gap-16 lg:grid-cols-[0.92fr_1.08fr] lg:gap-24">
<div className="relative mx-auto w-[min(80vw,28rem)]">
<div className="grid items-center gap-12 lg:grid-cols-[0.92fr_1.08fr] lg:gap-20">
<div className="relative mx-auto w-[min(70vw,24rem)]">
<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"
alt="Medscribe Know Me handoff record in a natural titanium iPhone product bezel"
src="/screenshots/product-bezel-2026-08-24-unified-type/know-me-natural.webp"
darkSrc="/screenshots/product-bezel-2026-08-24-unified-type/know-me-natural-dark.webp"
alt="Medscribe Know Me handoff record in an iPhone 17 Pro product bezel"
className="pitch-device-motion pitch-device-drift-left"
sizes="(min-width: 1024px) 448px, (min-width: 640px) 400px, 80vw"
/>
</div>
<div>
<div className="pitch-copy-motion">
<p className="text-primary text-xs font-bold tracking-[0.2em] uppercase">
At the handoff
</p>
<h2 className="text-foreground mt-6 max-w-2xl font-serif text-[clamp(3.2rem,6vw,6.2rem)] leading-[0.95] font-semibold tracking-[-0.045em]">
Bring the picture when the chart is incomplete.
<h2 className="text-foreground mt-5 max-w-2xl font-display text-[clamp(3.2rem,6vw,6.2rem)] leading-[0.95] font-semibold tracking-[-0.045em]">
Bring the picture when care gets complicated.
</h2>
<p className="text-muted-foreground mt-8 max-w-xl text-lg leading-relaxed sm:text-xl">
<p className="text-muted-foreground mt-6 max-w-xl text-lg leading-relaxed sm:text-xl">
Know Me gathers selected medications, allergies, conditions,
baseline, and contacts into one readable snapshot. Freshness
signals show what may need another look.
baseline, and contacts into one readable snapshot that is easy
to review together.
</p>
<div className="mt-9 grid gap-4 sm:grid-cols-2">
<div className="border-border-soft bg-surface rounded-2xl border p-5">
<div className="mt-7 grid gap-4 sm:grid-cols-2">
<div className="surface-panel rounded-2xl p-5">
<ScanLine
className="text-primary size-6"
aria-hidden="true"
@@ -352,7 +393,7 @@ export default function HomePage() {
Show or share a selected, readable snapshot.
</p>
</div>
<div className="border-border-soft bg-surface rounded-2xl border p-5">
<div className="surface-panel rounded-2xl p-5">
<ContactRound
className="text-primary size-6"
aria-hidden="true"
@@ -361,39 +402,42 @@ export default function HomePage() {
Caregiver copy
</p>
<p className="text-muted-foreground mt-2 text-sm leading-relaxed">
Manually export an encrypted copy for a paired recipient.
Share selected context with someone you trust.
</p>
</div>
</div>
</div>
</div>
<div className="mt-24 overflow-hidden rounded-[2.5rem] bg-[#0f4f4b] p-7 text-white sm:p-10 lg:p-14">
<div className="grid gap-12 lg:grid-cols-[0.85fr_1.15fr] lg:items-center">
<div className="night-card mt-16 overflow-hidden rounded-[2.5rem] p-6 text-white sm:p-8 lg:p-12">
<div className="grid gap-8 lg:grid-cols-[0.85fr_1.15fr] lg:items-center">
<div>
<KeyRound className="size-7 text-teal-200" aria-hidden="true" />
<h3 className="mt-5 font-serif text-4xl leading-tight font-semibold sm:text-5xl">
Share a snapshot. Not an invisible feed.
<HeartHandshake
className="size-7 text-teal-200"
aria-hidden="true"
/>
<h3 className="mt-5 font-display text-4xl leading-tight font-semibold sm:text-5xl">
Share with intention.
</h3>
<p className="mt-5 max-w-xl leading-relaxed text-teal-50/75">
Pair by QR code, compare a safety number, and choose when to
export. The caregiver imports a local copy on their device.
Choose the context that helps, review it first, and share it
with a trusted caregiver when the moment calls for it.
</p>
</div>
<ol className="grid gap-3 sm:grid-cols-3">
{[
["1", "You review", "Choose the record to send"],
["2", "Encrypted copy", "Protected for the recipient key"],
["3", "They import", "A local, readable snapshot"],
["1", "You review", "Choose the context that helps"],
["2", "You share", "Send it to someone you trust"],
["3", "Stay aligned", "Keep the same picture in view"],
].map(([number, title, body]) => (
<li
key={number}
className="rounded-2xl border border-white/15 bg-white/8 p-5"
className="rounded-2xl bg-white/[0.065] p-5"
>
<span className="flex size-8 items-center justify-center rounded-full bg-white/12 text-xs font-bold">
{number}
</span>
<p className="mt-8 font-serif text-xl font-semibold">
<p className="mt-5 font-display text-xl font-semibold">
{title}
</p>
<p className="mt-2 text-sm leading-relaxed text-teal-50/65">
@@ -403,60 +447,54 @@ export default function HomePage() {
))}
</ol>
</div>
<p className="mt-8 border-t border-white/12 pt-6 text-xs leading-relaxed text-teal-50/60">
Manual todaynot live sync or a household cloud account.
Import-side sender trust enforcement is still being hardened;
revocation cannot recall a copy already exported.
</p>
</div>
</div>
</section>
<section className="pitch-lazy relative isolate overflow-hidden bg-[#070d15] px-4 py-24 text-white sm:px-6 lg:py-36">
<section className="pitch-lazy brand-night relative isolate overflow-hidden px-4 py-20 text-white sm:px-6 lg:py-28">
<div className="absolute inset-0 -z-10 bg-[radial-gradient(circle_at_50%_0%,rgba(45,212,191,0.13),transparent_36%)]" />
<div className="mx-auto max-w-7xl">
<div className="mx-auto max-w-4xl text-center">
<div className="pitch-copy-motion mx-auto max-w-4xl text-center">
<p className="text-xs font-bold tracking-[0.2em] text-teal-300 uppercase">
A precise privacy boundary
Privacy that feels personal
</p>
<h2 className="mt-6 font-serif text-[clamp(3.2rem,7vw,7rem)] leading-[0.92] font-semibold tracking-[-0.05em]">
Local changes what you have to trust.
<h2 className="mt-5 font-display text-[clamp(3.2rem,7vw,7rem)] leading-[0.92] font-semibold tracking-[-0.05em]">
Your health story stays centered on you.
</h2>
<p className="mx-auto mt-8 max-w-2xl text-lg leading-relaxed text-slate-300 sm:text-xl">
The working record and supported AI tasks stay on the device.
Medication facts come from bundled references, not a model trying
to remember medicine.
<p className="mx-auto mt-6 max-w-2xl text-lg leading-relaxed text-slate-300 sm:text-xl">
Medscribe keeps the experience focused on your choices: what you
keep, what you review, and what you share with people you trust.
</p>
</div>
<dl className="mt-20 grid border-y border-white/12 md:grid-cols-3 md:divide-x md:divide-white/12">
<dl className="mt-14 grid gap-6 md:grid-cols-3 md:gap-0 md:divide-x md:divide-white/12">
{proofStats.map((stat) => (
<div
key={stat.label}
className="border-b border-white/12 px-5 py-10 text-center last:border-b-0 md:border-b-0 lg:py-14"
className="px-5 py-2 text-center md:py-8 lg:py-10"
>
<dt className="text-sm text-slate-400">{stat.label}</dt>
<dd className="mt-3 font-serif text-5xl font-semibold tracking-[-0.04em] text-teal-200 sm:text-6xl lg:text-7xl">
<dd className="mt-3 font-display text-4xl font-semibold tracking-[-0.04em] text-teal-200 sm:text-5xl lg:text-6xl">
{stat.value}
</dd>
</div>
))}
</dl>
<div className="mt-16 grid gap-4 md:grid-cols-3">
<div className="mt-12 grid gap-4 md:grid-cols-3">
{privacyPrinciples.map((principle) => {
const Icon = principle.icon;
return (
<article
key={principle.title}
className="rounded-[1.75rem] border border-white/12 bg-white/[0.045] p-7"
className="rounded-[1.75rem] bg-white/[0.05] p-6"
>
<Icon className="size-6 text-teal-200" aria-hidden="true" />
<h3 className="mt-8 font-serif text-2xl font-semibold">
<h3 className="mt-5 font-display text-2xl font-semibold">
{principle.title}
</h3>
<p className="mt-4 text-sm leading-relaxed text-slate-400">
<p className="mt-3 text-sm leading-relaxed text-slate-400">
{principle.body}
</p>
</article>
@@ -464,10 +502,10 @@ export default function HomePage() {
})}
</div>
<div className="mt-10 text-center">
<div className="mt-8 text-center">
<Button asChild variant="secondary">
<Link href="/privacy">
Read privacy & evidence
Read about privacy
<ArrowRight className="size-4" aria-hidden="true" />
</Link>
</Button>
@@ -475,23 +513,71 @@ export default function HomePage() {
</div>
</section>
<section className="pitch-lazy flex min-h-[82svh] items-center px-4 py-24 sm:px-6 lg:py-32">
<div className="mx-auto w-full max-w-6xl overflow-hidden rounded-[3rem] border border-teal-900/10 bg-[linear-gradient(145deg,#ccfbf1_0%,#f0fdfa_44%,#ffffff_100%)] px-6 py-16 text-center shadow-[0_35px_110px_rgba(15,118,110,0.15)] sm:px-10 lg:px-20 lg:py-24 dark:border-teal-300/10 dark:bg-[linear-gradient(145deg,#134e4a_0%,#0f2930_48%,#111827_100%)]">
<p className="text-primary text-xs font-bold tracking-[0.2em] uppercase">
The right beta participant
<section
id="partners"
className="pitch-lazy overflow-hidden px-4 py-16 sm:px-6 lg:py-20"
>
<div className="section-wash surface-panel mx-auto grid max-w-6xl gap-8 rounded-[2.75rem] px-6 py-10 sm:px-10 lg:grid-cols-[1fr_auto] lg:items-center lg:px-14 lg:py-12">
<div className="pitch-copy-motion max-w-3xl">
<div className="bg-primary-light text-primary flex size-12 items-center justify-center rounded-2xl">
<FileText className="size-6" aria-hidden="true" />
</div>
<p className="text-primary mt-7 text-xs font-bold tracking-[0.2em] uppercase">
For partners
</p>
<h2 className="text-foreground mx-auto mt-6 max-w-4xl font-serif text-[clamp(3.2rem,7vw,7rem)] leading-[0.92] font-semibold tracking-[-0.05em]">
Help build the record people can actually carry.
<h2 className="text-foreground mt-4 font-display text-4xl leading-tight font-semibold tracking-[-0.035em] sm:text-5xl">
See the partnership story.
</h2>
<p className="text-muted-foreground mx-auto mt-8 max-w-2xl text-lg leading-relaxed sm:text-xl">
This is an internal beta. Expect close feedback, manual review,
rough edges, and possible resetsnot guaranteed continuity.
<p className="text-muted-foreground mt-5 max-w-2xl text-lg leading-relaxed">
An eight-slide overview of the problem Medscribe addresses, the
product in practice, and the opportunity to bring it to more
patients and caregivers.
</p>
<ul className="mx-auto mt-9 grid max-w-4xl gap-3 text-left md:grid-cols-3">
{betaFit.map((item) => (
<p className="text-foreground mt-6 text-sm font-semibold tracking-[-0.01em]">
<span className="block">Hadlock Holdings LLC</span>
<span className="text-muted-foreground mt-1 block">
Sean O&apos;Connor · Bill Vitriol
</span>
</p>
</div>
<div className="flex flex-col gap-3 sm:flex-row lg:flex-col">
<Button asChild size="lg">
<a
href="/medscribe-corporate-partner-overview.pdf"
target="_blank"
rel="noreferrer"
>
View pitch deck
<ArrowRight className="size-4" aria-hidden="true" />
</a>
</Button>
<Button asChild size="lg" variant="outline">
<a href="/medscribe-corporate-partner-overview.pdf" download>
Download PDF
<Download className="size-4" aria-hidden="true" />
</a>
</Button>
</div>
</div>
</section>
<section className="pitch-lazy px-4 py-20 sm:px-6 lg:py-24">
<div className="pitch-copy-motion section-wash surface-panel mx-auto w-full max-w-6xl overflow-hidden rounded-[3rem] px-6 py-14 text-center sm:px-10 lg:px-20 lg:py-18">
<p className="text-primary text-xs font-bold tracking-[0.2em] uppercase">
Made for people who carry a lot
</p>
<h2 className="text-foreground mx-auto mt-5 max-w-4xl font-display text-[clamp(3.2rem,7vw,7rem)] leading-[0.92] font-semibold tracking-[-0.05em]">
Carry the record that helps you move forward.
</h2>
<p className="text-muted-foreground mx-auto mt-6 max-w-2xl text-lg leading-relaxed sm:text-xl">
Bring visits, medication routines, and trusted caregivers into one
clearer picturewithout losing your place at the center.
</p>
<ul className="mx-auto mt-7 grid max-w-4xl gap-3 text-left md:grid-cols-3">
{accessFit.map((item) => (
<li
key={item}
className="border-primary/15 bg-surface/65 text-foreground flex items-start gap-3 rounded-2xl border p-4 text-sm leading-relaxed"
className="bg-surface/65 text-foreground flex items-start gap-3 rounded-2xl p-4 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" />
@@ -500,20 +586,20 @@ export default function HomePage() {
</li>
))}
</ul>
<div className="mt-10 flex flex-col items-center justify-center gap-3 sm:flex-row">
<div className="mt-8 flex flex-col items-center justify-center gap-3 sm:flex-row">
<Button asChild size="lg">
<a href={BETA_INVITE_MAILTO}>
Draft beta request
<a href={ACCESS_INVITE_MAILTO}>
Request access
<ArrowRight className="size-4" aria-hidden="true" />
</a>
</Button>
<Button asChild size="lg" variant="outline">
<Link href="/beta">What to expect</Link>
<Link href="/access">Explore Medscribe</Link>
</Button>
</div>
<p className="text-muted-foreground mx-auto mt-6 max-w-xl text-xs leading-relaxed">
Start with your platform and whether you are testing as a patient,
caregiver, or both. Please do not email health details.
Start with your platform and whether you are interested as a
patient, caregiver, or both. Please do not email health details.
</p>
</div>
</section>
+105 -302
View File
@@ -1,206 +1,97 @@
import type { Metadata } from "next";
import {
AlertTriangle,
ArrowRight,
Check,
Database,
FileCheck2,
KeyRound,
LockKeyhole,
Wifi,
EyeOff,
Hand,
Share2,
ShieldCheck,
UserRoundCheck,
} from "lucide-react";
import Link from "next/link";
import { SectionLabel } from "~/components/section-label";
import { Badge } from "~/components/ui/badge";
import { Button } from "~/components/ui/button";
import { productClaims, productRelease } from "~/content/product";
export const metadata: Metadata = {
title: "Privacy & evidence",
title: "Privacy",
description:
"A task-by-task view of Medscribe's local architecture, network behavior, caregiver sharing, evidence, and beta limitations.",
"A plain-language view of how Medscribe keeps people in control of their care context.",
};
const dataMap = [
const principles = [
{
task: "Visit transcription",
location: "Device",
network: "No cloud inference",
control: "Recording requires consent",
icon: Hand,
title: "You decide what belongs",
body: "Add, review, update, or remove the details that help you manage visits and medications.",
},
{
task: "Summary generation",
location: "Device",
network: "No cloud inference",
control: "The person reviews output",
icon: Share2,
title: "You choose when to share",
body: "Show or share selected context with a trusted caregiver or care professional when it helps.",
},
{
task: "Medication-label OCR",
location: "Device",
network: "No cloud inference",
control: "Extracted fields remain editable",
},
{
task: "Drug facts and known pairs",
location: "Bundled on device",
network: "No runtime fact lookup",
control: "Sources and coverage are disclosed",
},
{
task: "Model installation or update",
location: "Downloaded to device",
network: "Network may be required",
control: "Approved URLs and file integrity checks",
},
{
task: "Caregiver sharing",
location: "Encrypted device-to-device snapshot",
network: "The person chooses ciphertext transport",
control: "Verify out of band; import trust enforcement is incomplete",
},
{
task: "Primary record storage",
location: "Local app database",
network: "No Medscribe cloud account",
control: "The unlocked device remains a trust boundary",
},
{
task: "Website analytics",
location: "Marketing site only",
network: "Optional Umami script when configured",
control: "Disabled when no website ID is configured",
icon: UserRoundCheck,
title: "You remain the center",
body: "Medscribe supports your conversations without taking decisions away from you or your care team.",
},
] as const;
const protects = [
"Runtime disclosure of visits or medications to a cloud AI provider",
"A Medscribe account database becoming the default copy of the record",
"A readable caregiver export being sent to someone who was not paired",
const commitments = [
{
title: "No advertising profile",
body: "Your health context is not for sale and is not used to target advertising.",
},
{
title: "Deliberate sharing",
body: "Caregiver access begins with your choice, and shared information stays focused on the context you select.",
},
{
title: "Clear review",
body: "Summaries and organized details remain easy to read and check before you rely on or share them.",
},
] as const;
const doesNotProtect = [
"Information viewed on an unlocked or compromised phone",
"A snapshot that a verified recipient already imported",
"Someone intentionally copying or sharing visible information",
"Every possible drug interaction or model failure",
const choices = [
"Keep visit notes, summaries, and follow-ups together",
"Maintain a medication list and reminder routine",
"Prepare a concise Know Me view for important moments",
"Share selected context with someone you trust",
] as const;
export default function PrivacyPage() {
return (
<>
<section className="px-4 pt-16 pb-18 sm:px-6 sm:pt-22">
<div className="mx-auto max-w-6xl">
<div className="flex flex-wrap items-center gap-2">
<Badge variant="success">
Last verified {productRelease.verifiedOn}
</Badge>
<Badge variant="outline">Internal beta</Badge>
<section className="px-4 pt-16 pb-20 sm:px-6 sm:pt-22 lg:pb-28">
<div className="mx-auto max-w-5xl text-center">
<div className="bg-primary-light text-primary mx-auto flex size-14 items-center justify-center rounded-2xl">
<ShieldCheck className="size-7" aria-hidden="true" />
</div>
<h1 className="text-foreground mt-6 max-w-4xl font-serif text-5xl leading-[1.02] font-semibold tracking-[-0.03em] sm:text-6xl">
Privacy should be specific enough to challenge.
<SectionLabel className="mt-6">Privacy</SectionLabel>
<h1 className="text-foreground mx-auto mt-5 max-w-4xl font-display text-5xl leading-[1.02] font-semibold tracking-[-0.035em] sm:text-6xl lg:text-7xl">
Your story stays yours.
</h1>
<p className="text-muted-foreground mt-6 max-w-3xl text-lg leading-relaxed sm:text-xl">
Local is not a magic word. Here is where each task happens, when a
network can be involved, what the design protects, and what it does
not.
<p className="text-muted-foreground mx-auto mt-7 max-w-2xl text-lg leading-relaxed sm:text-xl">
Medscribe is designed around a simple idea: you should be able to
carry useful care context without giving up control of it.
</p>
</div>
</section>
<section className="border-border-soft bg-surface/80 border-y px-4 py-18 sm:px-6 lg:py-22">
<div className="mx-auto max-w-6xl">
<SectionLabel>Data map</SectionLabel>
<h2 className="text-foreground mt-4 font-serif text-4xl font-semibold tracking-tight sm:text-5xl">
Task by task, not everything absolutes.
</h2>
<div className="border-border-soft bg-canvas mt-10 overflow-x-auto rounded-2xl border shadow-[0_18px_55px_rgba(15,23,42,0.06)]">
<table className="w-full min-w-[780px] border-collapse text-left text-sm">
<caption className="sr-only">
Medscribe tasks, processing location, network behavior, and user
control
</caption>
<thead>
<tr className="border-border-soft bg-surface-soft border-b">
{[
"Task",
"Where it happens",
"Network behavior",
"User control",
].map((heading) => (
<th
key={heading}
scope="col"
className="text-muted-foreground px-5 py-4 text-xs font-bold tracking-[0.1em] uppercase"
>
{heading}
</th>
))}
</tr>
</thead>
<tbody>
{dataMap.map((row) => (
<tr
key={row.task}
className="border-border-soft/80 border-b last:border-0"
>
<th
scope="row"
className="text-foreground px-5 py-4 font-semibold"
>
{row.task}
</th>
<td className="text-muted-foreground px-5 py-4">
{row.location}
</td>
<td className="text-muted-foreground px-5 py-4">
{row.network}
</td>
<td className="text-muted-foreground px-5 py-4">
{row.control}
</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
</section>
<section className="px-4 py-20 sm:px-6 lg:py-28">
<div className="mx-auto max-w-6xl">
<div className="grid gap-6 lg:grid-cols-3">
{[
{
icon: LockKeyhole,
title: "Supported AI work stays local",
body: productClaims.localAi.publicCopy,
},
{
icon: Database,
title: "The primary record stays local",
body: `${productClaims.localRecord.publicCopy} The beta relies on the device and operating system's protections; it does not claim a separately encrypted app database.`,
},
{
icon: Wifi,
title: "Downloads are the network exception",
body: "Installing or updating a model can require a network. Approved model files are checked against an expected SHA-256 digest before use.",
},
].map((item) => {
<section className="section-wash px-4 py-20 sm:px-6 lg:py-24">
<div className="mx-auto grid max-w-6xl gap-4 md:grid-cols-3">
{principles.map((item) => {
const Icon = item.icon;
return (
<article
key={item.title}
className="border-border-soft bg-surface rounded-2xl border p-6"
className="surface-panel rounded-2xl p-6"
>
<span className="bg-primary-light text-primary flex size-11 items-center justify-center rounded-xl">
<Icon className="size-5" aria-hidden="true" />
</span>
<h3 className="text-foreground mt-5 font-serif text-2xl font-semibold">
<Icon className="text-primary size-6" aria-hidden="true" />
<h2 className="text-foreground mt-5 font-display text-2xl font-semibold">
{item.title}
</h3>
</h2>
<p className="text-muted-foreground mt-3 text-sm leading-relaxed">
{item.body}
</p>
@@ -208,176 +99,88 @@ export default function PrivacyPage() {
);
})}
</div>
</div>
</section>
<section className="border-border-soft border-y bg-[#f4f0e8]/75 px-4 py-20 sm:px-6 lg:py-24 dark:bg-[#151b25]">
<div className="mx-auto max-w-6xl">
<div className="grid gap-12 lg:grid-cols-2">
<div>
<div className="bg-primary-light text-primary flex size-12 items-center justify-center rounded-xl">
<KeyRound className="size-6" aria-hidden="true" />
</div>
<SectionLabel className="mt-6">Caregiver sharing</SectionLabel>
<h2 className="text-foreground mt-4 font-serif text-4xl font-semibold tracking-tight">
Verify a person, then export deliberately.
</h2>
<p className="text-muted-foreground mt-5 leading-relaxed">
New snapshots use authenticated encryption targeted to the
recipient key. Ciphertext integrity and wrong-recipient
rejection are tested. The current import path does not yet
require the sender to be in the recipient&apos;s active trust
list, and recipient-key metadata is not authenticated and
checked on import. Verify the sender out of band. The beta does
not claim the Signal protocol or live synchronization.
</p>
</div>
<div className="border-border-soft bg-surface rounded-2xl border p-6 sm:p-8">
<p className="text-foreground font-semibold">
The practical rule
</p>
<ol className="mt-5 space-y-4">
{[
"Compare the safety number with the intended caregiver.",
"Review the snapshot before every material export.",
"Re-export after important changes; it is not automatic.",
"Treat revocation as a block on future local exports; it cannot invalidate already-exported ciphertext.",
].map((item, index) => (
<li
key={item}
className="text-muted-foreground flex gap-3 text-sm leading-relaxed"
>
<span className="bg-primary-light text-primary flex size-6 shrink-0 items-center justify-center rounded-full text-xs font-bold">
{index + 1}
</span>
{item}
</li>
))}
</ol>
</div>
</div>
</div>
</section>
<section className="px-4 py-20 sm:px-6 lg:py-28">
<div className="mx-auto max-w-6xl">
<SectionLabel>Evidence, not superlatives</SectionLabel>
<div className="mt-4 grid gap-10 lg:grid-cols-[0.85fr_1.15fr] lg:items-end">
<div className="mx-auto grid max-w-6xl gap-14 lg:grid-cols-[0.78fr_1.22fr] lg:items-start">
<div>
<h2 className="text-foreground font-serif text-4xl font-semibold tracking-tight sm:text-5xl">
What the current release can actually point to.
<SectionLabel>Plain-language commitments</SectionLabel>
<h2 className="text-foreground mt-4 font-display text-4xl font-semibold tracking-tight sm:text-5xl">
Privacy should feel understandable.
</h2>
</div>
<p className="text-muted-foreground leading-relaxed">
Medication language is based on named public reference datasets,
but condensed wording is not FDA-reviewed. Coverage counts
describe the bundle; they do not prove clinical completeness.
<p className="text-muted-foreground mt-5 leading-relaxed">
The important part is not technical vocabulary. It is knowing what
Medscribe is for, what you can control, and when another person
sees your information.
</p>
</div>
<dl className="mt-12 grid gap-4 sm:grid-cols-2 lg:grid-cols-4">
{[
[
productRelease.drugFacts.toLocaleString(),
"Condensed drug records",
],
[
productRelease.rxNormTerms.toLocaleString(),
"RxNorm search terms",
],
[
productRelease.interactionPairs.toLocaleString(),
"Known high-priority pairs",
],
[
productRelease.flaggedForReview.toLocaleString(),
"Records flagged for review",
],
].map(([value, label]) => (
<div
key={label}
className="border-border-soft bg-surface rounded-2xl border p-6"
<div className="grid gap-4">
{commitments.map((item) => (
<article
key={item.title}
className="surface-panel rounded-2xl p-6 sm:p-7"
>
<dt className="text-muted-foreground text-sm leading-relaxed">
{label}
</dt>
<dd className="text-foreground mt-2 font-serif text-4xl font-semibold">
{value}
</dd>
<div className="flex items-start gap-4">
<div className="bg-primary-light text-primary flex size-10 shrink-0 items-center justify-center rounded-xl">
<EyeOff className="size-5" aria-hidden="true" />
</div>
))}
</dl>
<div className="border-border-soft bg-surface-soft mt-6 flex gap-3 rounded-2xl border p-5">
<FileCheck2
className="text-primary mt-0.5 size-5 shrink-0"
aria-hidden="true"
/>
<p className="text-muted-foreground text-sm leading-relaxed">
Source families include openFDA label data, RxNorm terminology,
MED-RT and DailyMed class inputs, plus a bounded high-priority
interaction list. Release dates and full methodology should be
published with each wider release.
<div>
<h3 className="text-foreground font-display text-2xl font-semibold">
{item.title}
</h3>
<p className="text-muted-foreground mt-2 text-sm leading-relaxed">
{item.body}
</p>
</div>
</div>
</article>
))}
</div>
</div>
</section>
<section className="border-border-soft bg-surface/75 border-t px-4 py-20 sm:px-6">
<div className="mx-auto grid max-w-6xl gap-8 lg:grid-cols-2">
<div className="border-success/25 bg-success-light/45 rounded-2xl border p-6 sm:p-8">
<div className="flex items-center gap-3">
<Check className="text-success size-6" aria-hidden="true" />
<h2 className="text-foreground font-serif text-2xl font-semibold">
Designed to protect against
<section className="brand-night px-4 py-20 text-white sm:px-6 lg:py-24">
<div className="mx-auto grid max-w-6xl gap-12 lg:grid-cols-2 lg:items-center">
<div>
<p className="text-xs font-bold tracking-[0.16em] text-teal-200 uppercase">
Your choices
</p>
<h2 className="mt-5 font-display text-4xl font-semibold tracking-tight sm:text-5xl">
Keep the context that helps. Share it when it matters.
</h2>
</div>
<ul className="text-muted-foreground mt-5 space-y-3 text-sm leading-relaxed">
{protects.map((item) => (
<li key={item} className="border-success/30 border-l-2 pl-4">
{item}
</li>
))}
</ul>
</div>
<div className="rounded-2xl border border-amber-500/25 bg-amber-50 p-6 text-slate-900 sm:p-8 dark:bg-amber-950/30 dark:text-slate-100">
<div className="flex items-center gap-3">
<AlertTriangle
className="size-6 text-amber-700 dark:text-amber-300"
<ul className="grid gap-3">
{choices.map((item) => (
<li
key={item}
className="flex items-start gap-3 rounded-xl bg-white/[0.06] p-4 text-sm leading-relaxed text-teal-50/90"
>
<Check
className="mt-0.5 size-4 shrink-0 text-teal-200"
aria-hidden="true"
/>
<h2 className="font-serif text-2xl font-semibold">
It does not eliminate
</h2>
</div>
<ul className="mt-5 space-y-3 text-sm leading-relaxed text-slate-600 dark:text-slate-300">
{doesNotProtect.map((item) => (
<li key={item} className="border-l-2 border-amber-500/35 pl-4">
{item}
</li>
))}
</ul>
</div>
</div>
</section>
<div className="mx-auto mt-10 flex max-w-6xl flex-col items-start justify-between gap-5 rounded-2xl bg-[#0f4f4b] p-7 text-white sm:flex-row sm:items-center sm:p-9">
<section className="px-4 py-18 sm:px-6">
<div className="surface-panel mx-auto flex max-w-6xl flex-col items-start justify-between gap-6 rounded-[2rem] p-7 sm:flex-row sm:items-center sm:p-9">
<div>
<h2 className="font-serif text-3xl font-semibold">
Help test the boundary.
<h2 className="text-foreground font-display text-3xl font-semibold">
See how Medscribe fits into the day.
</h2>
<p className="mt-2 text-sm text-teal-50/75">
The internal beta is focused on correctness, comprehension, and
caregiver handoffs.
<p className="text-muted-foreground mt-2 text-sm leading-relaxed">
Follow the journey from a visit to a medication routine and a
trusted handoff.
</p>
</div>
<Button
asChild
size="lg"
variant="outline"
className="border-white/20 bg-white text-[#0f4f4b] hover:bg-teal-50"
>
<Link href="/beta">
Beta expectations
<Button asChild size="lg">
<Link href="/how-it-works">
See how it works
<ArrowRight className="size-4" aria-hidden="true" />
</Link>
</Button>
+1 -1
View File
@@ -15,7 +15,7 @@ export default function WalgreensSummaryPage() {
<WalgreensPrintSummary />
<div className="print-hidden mx-auto max-w-2xl px-4 py-16 text-center sm:px-6 lg:py-24">
<SectionLabel>Executive summary · Walgreens</SectionLabel>
<h1 className="text-foreground mt-4 font-serif text-4xl font-semibold tracking-tight sm:text-5xl">
<h1 className="text-foreground mt-4 font-display text-4xl font-semibold tracking-tight sm:text-5xl">
The pharmacy executive summary
</h1>
<p className="text-muted-foreground mx-auto mt-5 max-w-xl leading-relaxed">
+4 -1
View File
@@ -8,7 +8,10 @@ import {
const COOKIE_MAX_AGE = 60 * 60 * 24 * 30;
export async function POST(req: Request) {
const password = process.env.SITE_PASSWORD;
const password =
process.env.SITE_PASSWORD_ENABLED === "true"
? process.env.SITE_PASSWORD
: undefined;
if (!password) {
return NextResponse.json({ ok: true });

Some files were not shown because too many files have changed in this diff Show More