Refresh web branding for new app theme

This commit is contained in:
2026-08-23 01:20:22 -04:00
parent b41f2c643f
commit a8b7504a15
10 changed files with 182 additions and 79 deletions
+5 -5
View File
@@ -78,7 +78,7 @@ export default function AccessPage() {
</p> </p>
</div> </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="glass-panel rounded-[2rem] p-7 sm:p-9">
<div className="bg-primary-light text-primary flex size-12 items-center justify-center rounded-xl"> <div className="bg-primary-light text-primary flex size-12 items-center justify-center rounded-xl">
<Mail className="size-6" aria-hidden="true" /> <Mail className="size-6" aria-hidden="true" />
</div> </div>
@@ -104,7 +104,7 @@ export default function AccessPage() {
</div> </div>
</section> </section>
<section className="border-border-soft border-y bg-[#f4f0e8]/75 px-4 py-20 sm:px-6 lg:py-24 dark:bg-[#151b25]"> <section className="brand-warm border-border-soft/70 border-y px-4 py-20 sm:px-6 lg:py-24">
<div className="mx-auto max-w-6xl"> <div className="mx-auto max-w-6xl">
<SectionLabel>Made for real life</SectionLabel> <SectionLabel>Made for real life</SectionLabel>
<h2 className="text-foreground mt-4 max-w-3xl font-serif text-4xl font-semibold tracking-tight sm:text-5xl"> <h2 className="text-foreground mt-4 max-w-3xl font-serif text-4xl font-semibold tracking-tight sm:text-5xl">
@@ -118,7 +118,7 @@ export default function AccessPage() {
return ( return (
<article <article
key={item.title} key={item.title}
className="border-border-soft bg-surface rounded-2xl border p-6" className="glass-panel rounded-2xl p-6"
> >
<Icon className="text-primary size-6" aria-hidden="true" /> <Icon className="text-primary size-6" aria-hidden="true" />
<h3 className="text-foreground mt-5 font-serif text-2xl font-semibold"> <h3 className="text-foreground mt-5 font-serif text-2xl font-semibold">
@@ -147,7 +147,7 @@ export default function AccessPage() {
return ( return (
<article <article
key={item.title} key={item.title}
className="border-border-soft bg-surface rounded-2xl border p-6" className="glass-panel rounded-2xl p-6"
> >
<Icon className="text-primary size-6" aria-hidden="true" /> <Icon className="text-primary size-6" aria-hidden="true" />
<h3 className="text-foreground mt-5 font-serif text-2xl font-semibold"> <h3 className="text-foreground mt-5 font-serif text-2xl font-semibold">
@@ -161,7 +161,7 @@ export default function AccessPage() {
})} })}
</div> </div>
<div className="mt-14 rounded-[2rem] bg-[#0f4f4b] p-7 text-white sm:p-10"> <div className="brand-night mt-14 rounded-[2rem] p-7 text-white shadow-[0_28px_70px_rgba(7,20,21,0.2)] sm:p-10">
<p className="text-xs font-bold tracking-[0.14em] text-teal-100 uppercase"> <p className="text-xs font-bold tracking-[0.14em] text-teal-100 uppercase">
Keep your care team in the loop Keep your care team in the loop
</p> </p>
+7 -7
View File
@@ -68,7 +68,7 @@ export default function HowItWorksPage() {
</div> </div>
</section> </section>
<section className="border-border-soft bg-surface/75 border-y px-4 py-18 sm:px-6 lg:py-22"> <section className="brand-warm border-border-soft/70 border-y px-4 py-18 sm:px-6 lg:py-22">
<div className="mx-auto max-w-6xl"> <div className="mx-auto max-w-6xl">
<SectionLabel>Start where the information is</SectionLabel> <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"> <h2 className="text-foreground mt-4 max-w-3xl font-serif text-4xl font-semibold tracking-tight sm:text-5xl">
@@ -81,7 +81,7 @@ export default function HowItWorksPage() {
return ( return (
<article <article
key={item.title} key={item.title}
className="border-border-soft bg-canvas rounded-2xl border p-6" className="glass-panel rounded-2xl p-6"
> >
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<span className="bg-primary-light text-primary flex size-11 items-center justify-center rounded-xl"> <span className="bg-primary-light text-primary flex size-11 items-center justify-center rounded-xl">
@@ -126,7 +126,7 @@ export default function HowItWorksPage() {
The visit remains available beside the summary so you can check The visit remains available beside the summary so you can check
wording, follow-ups, and the details you want to remember. wording, follow-ups, and the details you want to remember.
</p> </p>
<p className="border-border-soft bg-surface text-muted-foreground mt-5 rounded-2xl border p-5 text-sm leading-relaxed"> <p className="glass-panel text-muted-foreground mt-5 rounded-2xl p-5 text-sm leading-relaxed">
<strong className="text-foreground">Stay oriented:</strong> move <strong className="text-foreground">Stay oriented:</strong> move
between the transcript and summary whenever you want the fuller between the transcript and summary whenever you want the fuller
context. context.
@@ -146,7 +146,7 @@ export default function HowItWorksPage() {
</div> </div>
<div className="grid gap-12 lg:grid-cols-2 lg:items-center"> <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="brand-warm justify-self-center rounded-[2.5rem] p-7 lg:order-1">
<PhoneMockup <PhoneMockup
src="/screenshots/product-bezel-2026-08-20/medication-detail-natural.webp" src="/screenshots/product-bezel-2026-08-20/medication-detail-natural.webp"
darkSrc="/screenshots/product-bezel-2026-08-20/medication-detail-natural-dark.webp" darkSrc="/screenshots/product-bezel-2026-08-20/medication-detail-natural-dark.webp"
@@ -205,7 +205,7 @@ export default function HowItWorksPage() {
</div> </div>
</section> </section>
<section className="border-border-soft border-t bg-[#f4f0e8]/75 px-4 py-20 sm:px-6 dark:bg-[#151b25]"> <section className="brand-warm border-border-soft/70 border-t px-4 py-20 sm:px-6">
<div className="mx-auto grid max-w-6xl gap-12 lg:grid-cols-2"> <div className="mx-auto grid max-w-6xl gap-12 lg:grid-cols-2">
<div> <div>
<div className="bg-primary-light text-primary flex size-12 items-center justify-center rounded-xl"> <div className="bg-primary-light text-primary flex size-12 items-center justify-center rounded-xl">
@@ -222,7 +222,7 @@ export default function HowItWorksPage() {
{boundaries.map((item) => ( {boundaries.map((item) => (
<li <li
key={item} key={item}
className="border-border-soft bg-surface text-foreground flex gap-3 rounded-2xl border p-4 text-sm leading-relaxed" className="glass-panel text-foreground flex gap-3 rounded-2xl p-4 text-sm leading-relaxed"
> >
<Check <Check
className="text-primary mt-0.5 size-5 shrink-0" className="text-primary mt-0.5 size-5 shrink-0"
@@ -236,7 +236,7 @@ export default function HowItWorksPage() {
</section> </section>
<section className="px-4 py-20 sm:px-6"> <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"> <div className="brand-night mx-auto flex max-w-6xl flex-col items-start justify-between gap-7 rounded-[2rem] px-7 py-10 text-white shadow-[0_28px_70px_rgba(7,20,21,0.2)] sm:px-10 md:flex-row md:items-center">
<div> <div>
<h2 className="font-serif text-3xl font-semibold"> <h2 className="font-serif text-3xl font-semibold">
Privacy should feel understandable. Privacy should feel understandable.
+12 -12
View File
@@ -99,7 +99,8 @@ export default function HomePage() {
return ( 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"> <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" /> <div className="bg-primary-light/60 absolute -top-32 left-1/2 -z-10 h-[42rem] w-[74rem] max-w-[125vw] -translate-x-1/2 rounded-full blur-3xl" />
<div className="absolute top-48 -right-28 -z-10 size-[28rem] rounded-full bg-[#d9ecff]/35 blur-3xl dark:bg-[#123d5b]/28" />
<div className="mx-auto max-w-7xl text-center"> <div className="mx-auto max-w-7xl text-center">
<div className="animate-fade-in-up flex items-center justify-center gap-3"> <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"> <span className="bg-success-light text-success rounded-full px-3 py-1.5 text-xs font-bold tracking-[0.12em] uppercase">
@@ -156,7 +157,7 @@ export default function HomePage() {
</p> </p>
</section> </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"> <section className="pitch-lazy brand-warm border-border-soft/70 flex min-h-[78svh] items-center border-y px-4 py-24 sm:px-6 lg:py-32">
<div className="pitch-copy-motion mx-auto max-w-6xl text-center"> <div className="pitch-copy-motion mx-auto max-w-6xl text-center">
<p className="text-primary text-xs font-bold tracking-[0.2em] uppercase"> <p className="text-primary text-xs font-bold tracking-[0.2em] uppercase">
The connected picture The connected picture
@@ -199,7 +200,7 @@ export default function HomePage() {
{visitMoments.map((moment, index) => ( {visitMoments.map((moment, index) => (
<li <li
key={moment.number} key={moment.number}
className="pitch-card-motion 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 glass-panel relative overflow-hidden rounded-[2.5rem] px-5 pt-8 sm:px-10 sm:pt-10"
> >
<div className="relative z-10 max-w-xl"> <div className="relative z-10 max-w-xl">
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
@@ -233,8 +234,7 @@ export default function HomePage() {
</div> </div>
</section> </section>
<section className="pitch-lazy relative isolate overflow-hidden bg-[#082f2c] 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-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%)]" />
<div className="mx-auto max-w-7xl"> <div className="mx-auto max-w-7xl">
<div className="pitch-copy-motion 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"> <p className="text-xs font-bold tracking-[0.2em] text-teal-200 uppercase">
@@ -288,7 +288,7 @@ export default function HomePage() {
].map((item) => ( ].map((item) => (
<article <article
key={item.title} key={item.title}
className="bg-[#0b3b37]/90 p-7 sm:p-9" className="bg-[#0c2727]/88 p-7 backdrop-blur-sm sm:p-9"
> >
<Check className="size-5 text-teal-200" aria-hidden="true" /> <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-5 font-serif text-2xl font-semibold sm:text-3xl">
@@ -304,7 +304,7 @@ export default function HomePage() {
</div> </div>
</section> </section>
<section className="pitch-lazy bg-[#f0ece4] px-4 py-24 sm:px-6 lg:py-36 dark:bg-[#111827]"> <section className="pitch-lazy brand-warm px-4 py-24 sm:px-6 lg:py-36">
<div className="mx-auto grid max-w-7xl items-center gap-14 lg:grid-cols-[1fr_0.9fr] lg:gap-24"> <div className="mx-auto grid max-w-7xl items-center gap-14 lg:grid-cols-[1fr_0.9fr] lg:gap-24">
<div className="pitch-copy-motion order-2 lg:order-1"> <div className="pitch-copy-motion order-2 lg:order-1">
<p className="text-primary text-xs font-bold tracking-[0.2em] uppercase"> <p className="text-primary text-xs font-bold tracking-[0.2em] uppercase">
@@ -360,7 +360,7 @@ export default function HomePage() {
to review together. to review together.
</p> </p>
<div className="mt-9 grid gap-4 sm:grid-cols-2"> <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="glass-panel rounded-2xl p-5">
<ScanLine <ScanLine
className="text-primary size-6" className="text-primary size-6"
aria-hidden="true" aria-hidden="true"
@@ -372,7 +372,7 @@ export default function HomePage() {
Show or share a selected, readable snapshot. Show or share a selected, readable snapshot.
</p> </p>
</div> </div>
<div className="border-border-soft bg-surface rounded-2xl border p-5"> <div className="glass-panel rounded-2xl p-5">
<ContactRound <ContactRound
className="text-primary size-6" className="text-primary size-6"
aria-hidden="true" aria-hidden="true"
@@ -388,7 +388,7 @@ export default function HomePage() {
</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="brand-night mt-24 overflow-hidden rounded-[2.5rem] p-7 text-white shadow-[0_35px_90px_rgba(7,20,21,0.22)] sm:p-10 lg:p-14">
<div className="grid gap-12 lg:grid-cols-[0.85fr_1.15fr] lg:items-center"> <div className="grid gap-12 lg:grid-cols-[0.85fr_1.15fr] lg:items-center">
<div> <div>
<HeartHandshake <HeartHandshake
@@ -430,7 +430,7 @@ export default function HomePage() {
</div> </div>
</section> </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-24 text-white sm:px-6 lg:py-36">
<div className="absolute inset-0 -z-10 bg-[radial-gradient(circle_at_50%_0%,rgba(45,212,191,0.13),transparent_36%)]" /> <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-7xl">
<div className="pitch-copy-motion mx-auto max-w-4xl text-center"> <div className="pitch-copy-motion mx-auto max-w-4xl text-center">
@@ -493,7 +493,7 @@ export default function HomePage() {
</section> </section>
<section className="pitch-lazy flex min-h-[82svh] items-center px-4 py-24 sm:px-6 lg:py-32"> <section className="pitch-lazy flex min-h-[82svh] items-center px-4 py-24 sm:px-6 lg:py-32">
<div className="pitch-copy-motion 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%)]"> <div className="pitch-copy-motion brand-warm border-border-soft/65 mx-auto w-full max-w-6xl overflow-hidden rounded-[3rem] border px-6 py-16 text-center shadow-[0_35px_110px_rgba(15,118,110,0.14)] sm:px-10 lg:px-20 lg:py-24">
<p className="text-primary text-xs font-bold tracking-[0.2em] uppercase"> <p className="text-primary text-xs font-bold tracking-[0.2em] uppercase">
Made for people who carry a lot Made for people who carry a lot
</p> </p>
+5 -8
View File
@@ -78,16 +78,13 @@ export default function PrivacyPage() {
</div> </div>
</section> </section>
<section className="border-border-soft border-y bg-[#f4f0e8]/75 px-4 py-20 sm:px-6 lg:py-24 dark:bg-[#151b25]"> <section className="brand-warm border-border-soft/70 border-y px-4 py-20 sm:px-6 lg:py-24">
<div className="mx-auto grid max-w-6xl gap-4 md:grid-cols-3"> <div className="mx-auto grid max-w-6xl gap-4 md:grid-cols-3">
{principles.map((item) => { {principles.map((item) => {
const Icon = item.icon; const Icon = item.icon;
return ( return (
<article <article key={item.title} className="glass-panel rounded-2xl p-6">
key={item.title}
className="border-border-soft bg-surface rounded-2xl border p-6"
>
<Icon className="text-primary size-6" aria-hidden="true" /> <Icon className="text-primary size-6" aria-hidden="true" />
<h2 className="text-foreground mt-5 font-serif text-2xl font-semibold"> <h2 className="text-foreground mt-5 font-serif text-2xl font-semibold">
{item.title} {item.title}
@@ -119,7 +116,7 @@ export default function PrivacyPage() {
{commitments.map((item) => ( {commitments.map((item) => (
<article <article
key={item.title} key={item.title}
className="border-border-soft bg-surface rounded-2xl border p-6 sm:p-7" className="glass-panel rounded-2xl p-6 sm:p-7"
> >
<div className="flex items-start gap-4"> <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"> <div className="bg-primary-light text-primary flex size-10 shrink-0 items-center justify-center rounded-xl">
@@ -140,7 +137,7 @@ export default function PrivacyPage() {
</div> </div>
</section> </section>
<section className="bg-[#082f2c] px-4 py-20 text-white sm:px-6 lg:py-24"> <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 className="mx-auto grid max-w-6xl gap-12 lg:grid-cols-2 lg:items-center">
<div> <div>
<p className="text-xs font-bold tracking-[0.16em] text-teal-200 uppercase"> <p className="text-xs font-bold tracking-[0.16em] text-teal-200 uppercase">
@@ -168,7 +165,7 @@ export default function PrivacyPage() {
</section> </section>
<section className="px-4 py-18 sm:px-6"> <section className="px-4 py-18 sm:px-6">
<div className="border-border-soft bg-surface mx-auto flex max-w-6xl flex-col items-start justify-between gap-6 rounded-[2rem] border p-7 sm:flex-row sm:items-center sm:p-9"> <div className="glass-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> <div>
<h2 className="text-foreground font-serif text-3xl font-semibold"> <h2 className="text-foreground font-serif text-3xl font-semibold">
See how Medscribe fits into the day. See how Medscribe fits into the day.
+2 -2
View File
@@ -143,7 +143,7 @@ export function FeatureShowcase() {
"focus-visible:ring-primary/40 inline-flex min-h-11 shrink-0 items-center gap-2 rounded-full border px-4 py-2 text-sm font-semibold transition-colors outline-none focus-visible:ring-2", "focus-visible:ring-primary/40 inline-flex min-h-11 shrink-0 items-center gap-2 rounded-full border px-4 py-2 text-sm font-semibold transition-colors outline-none focus-visible:ring-2",
isActive isActive
? "border-primary-button bg-primary-button text-white shadow-sm" ? "border-primary-button bg-primary-button text-white shadow-sm"
: "border-border-soft bg-surface text-muted-foreground hover:border-primary/30 hover:text-foreground", : "border-border-soft bg-surface/75 text-muted-foreground hover:border-primary/30 hover:text-foreground backdrop-blur-xl",
)} )}
> >
<Icon className="size-4" aria-hidden="true" /> <Icon className="size-4" aria-hidden="true" />
@@ -187,7 +187,7 @@ export function FeatureShowcase() {
</div> </div>
<div className="justify-self-center lg:justify-self-end"> <div className="justify-self-center lg:justify-self-end">
<div className="border-border-soft bg-surface-soft/80 rounded-[2.5rem] border p-5 shadow-[0_30px_80px_rgba(15,23,42,0.10)] sm:p-7"> <div className="glass-panel rounded-[2.5rem] p-5 sm:p-7">
<PhoneMockup <PhoneMockup
src={active.image} src={active.image}
darkSrc={active.darkImage} darkSrc={active.darkImage}
+4 -11
View File
@@ -1,17 +1,10 @@
export function ScreenBackground() { export function ScreenBackground() {
return ( return (
<div className="pointer-events-none fixed inset-0 -z-10 overflow-hidden print:hidden"> <div className="pointer-events-none fixed inset-0 -z-10 overflow-hidden print:hidden">
<div <div className="ambient-canvas absolute inset-0" />
className="absolute inset-0 bg-canvas" <div className="bg-primary-light/22 absolute -top-48 -left-40 size-[34rem] rounded-full blur-3xl" />
style={{ <div className="absolute top-[28vh] -right-52 size-[38rem] rounded-full bg-[#d9ecff]/30 blur-3xl dark:bg-[#123d5b]/28" />
backgroundImage: ` <div className="absolute bottom-[6vh] -left-56 size-[38rem] rounded-full bg-[#fbe9d7]/32 blur-3xl dark:bg-[#4a3026]/24" />
linear-gradient(to right, var(--grid-line) 1px, transparent 1px),
linear-gradient(to bottom, var(--grid-line) 1px, transparent 1px)
`,
backgroundSize: "28px 28px",
}}
/>
<div className="absolute inset-x-0 top-0 h-[260px] bg-gradient-to-b from-primary-light/24 to-transparent" />
</div> </div>
); );
} }
+2 -2
View File
@@ -10,8 +10,8 @@ const footerLinks = [
export function SiteFooter() { export function SiteFooter() {
return ( return (
<footer className="print-hidden border-border-soft bg-surface/80 border-t"> <footer className="print-hidden px-3 pb-3 sm:px-5 sm:pb-5">
<div className="mx-auto grid max-w-6xl gap-10 px-4 py-12 text-sm sm:px-6 md:grid-cols-[1.3fr_0.7fr_0.7fr]"> <div className="glass-panel mx-auto grid max-w-6xl gap-10 rounded-[2rem] px-6 py-10 text-sm sm:px-8 md:grid-cols-[1.3fr_0.7fr_0.7fr]">
<div> <div>
<Link <Link
href="/" href="/"
+24 -6
View File
@@ -1,8 +1,12 @@
"use client";
import { Menu } from "lucide-react"; import { Menu } from "lucide-react";
import Link from "next/link"; import Link from "next/link";
import { usePathname } from "next/navigation";
import { MedscribeLogo } from "~/components/medscribe-logo"; import { MedscribeLogo } from "~/components/medscribe-logo";
import { Button } from "~/components/ui/button"; import { Button } from "~/components/ui/button";
import { cn } from "~/lib/utils";
const navigation = [ const navigation = [
{ href: "/", label: "Home" }, { href: "/", label: "Home" },
@@ -11,9 +15,11 @@ const navigation = [
] as const; ] as const;
export function SiteHeader() { export function SiteHeader() {
const pathname = usePathname();
return ( return (
<header className="print-hidden border-border-soft/70 bg-canvas/88 sticky top-0 z-50 border-b backdrop-blur-lg"> <header className="print-hidden sticky top-0 z-50 px-3 pt-3 sm:px-5">
<div className="relative mx-auto flex h-16 max-w-6xl items-center gap-5 px-4 sm:px-6"> <div className="glass-panel-strong relative mx-auto flex h-14 max-w-6xl items-center gap-5 rounded-[1.25rem] px-3.5 sm:px-5">
<Link <Link
href="/" href="/"
className="text-foreground focus-visible:ring-primary/40 absolute left-1/2 flex shrink-0 -translate-x-1/2 items-center gap-2.5 rounded-md transition-opacity outline-none hover:opacity-75 focus-visible:ring-2 md:static md:translate-x-0" className="text-foreground focus-visible:ring-primary/40 absolute left-1/2 flex shrink-0 -translate-x-1/2 items-center gap-2.5 rounded-md transition-opacity outline-none hover:opacity-75 focus-visible:ring-2 md:static md:translate-x-0"
@@ -33,7 +39,13 @@ export function SiteHeader() {
<Link <Link
key={item.href} key={item.href}
href={item.href} href={item.href}
className="text-muted-foreground hover:bg-surface-soft hover:text-foreground focus-visible:ring-primary/40 rounded-lg px-3 py-2 text-sm font-medium transition-colors outline-none focus-visible:ring-2" aria-current={pathname === item.href ? "page" : undefined}
className={cn(
"focus-visible:ring-primary/40 rounded-full px-3 py-2 text-sm font-medium transition-all outline-none focus-visible:ring-2",
pathname === item.href
? "text-foreground border border-white/45 bg-white/[0.48] shadow-[inset_0_1px_0_rgba(255,255,255,0.5),0_5px_16px_rgba(15,118,110,0.1)] dark:border-white/10 dark:bg-white/8"
: "text-muted-foreground hover:bg-primary-light/60 hover:text-foreground",
)}
> >
{item.label} {item.label}
</Link> </Link>
@@ -44,19 +56,25 @@ export function SiteHeader() {
</nav> </nav>
<details className="group relative ml-auto md:hidden"> <details className="group relative ml-auto md:hidden">
<summary className="border-border-soft bg-surface text-foreground focus-visible:ring-primary/40 flex size-11 cursor-pointer list-none items-center justify-center rounded-xl border outline-none marker:content-none focus-visible:ring-2 [&::-webkit-details-marker]:hidden"> <summary className="border-border-soft/70 bg-surface/70 text-foreground focus-visible:ring-primary/40 flex size-10 cursor-pointer list-none items-center justify-center rounded-full border outline-none marker:content-none focus-visible:ring-2 [&::-webkit-details-marker]:hidden">
<Menu className="size-5" aria-hidden="true" /> <Menu className="size-5" aria-hidden="true" />
<span className="sr-only">Open navigation</span> <span className="sr-only">Open navigation</span>
</summary> </summary>
<nav <nav
aria-label="Mobile navigation" aria-label="Mobile navigation"
className="border-border-soft bg-surface absolute top-13 right-0 flex w-64 flex-col rounded-2xl border p-2 shadow-[0_18px_50px_rgba(15,23,42,0.16)]" className="glass-panel-strong absolute top-12 right-0 flex w-64 flex-col rounded-[1.4rem] p-2"
> >
{navigation.map((item) => ( {navigation.map((item) => (
<Link <Link
key={item.href} key={item.href}
href={item.href} href={item.href}
className="text-foreground hover:bg-surface-soft focus-visible:ring-primary/40 rounded-xl px-4 py-3 text-sm font-medium outline-none focus-visible:ring-2" aria-current={pathname === item.href ? "page" : undefined}
className={cn(
"text-foreground focus-visible:ring-primary/40 rounded-xl px-4 py-3 text-sm font-medium outline-none focus-visible:ring-2",
pathname === item.href
? "bg-primary-light/75 shadow-[inset_0_1px_0_rgba(255,255,255,0.35)]"
: "hover:bg-primary-light/60",
)}
> >
{item.label} {item.label}
</Link> </Link>
+6 -6
View File
@@ -5,17 +5,17 @@ import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "~/lib/utils"; import { cn } from "~/lib/utils";
const buttonVariants = cva( const buttonVariants = cva(
"print-hidden inline-flex shrink-0 items-center justify-center gap-2 rounded-[14px] text-sm font-semibold whitespace-nowrap transition-all outline-none focus-visible:ring-2 focus-visible:ring-primary/30 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0", "print-hidden inline-flex shrink-0 items-center justify-center gap-2 rounded-full text-sm font-semibold whitespace-nowrap transition-all outline-none focus-visible:ring-2 focus-visible:ring-primary/30 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0",
{ {
variants: { variants: {
variant: { variant: {
default: default:
"bg-primary-button text-white shadow-sm hover:bg-primary-button/90", "bg-primary-button text-white shadow-[0_10px_25px_rgba(15,118,110,0.2)] hover:-translate-y-0.5 hover:bg-primary-button/90",
outline: outline:
"border border-border-soft bg-surface text-foreground hover:bg-surface-soft", "border border-border-soft bg-surface/75 text-foreground backdrop-blur-xl hover:-translate-y-0.5 hover:bg-surface-soft",
secondary: secondary: "bg-primary-light text-primary hover:bg-primary-light/80",
"bg-primary-light text-primary hover:bg-primary-light/80", ghost:
ghost: "text-muted-foreground hover:bg-surface-soft hover:text-foreground", "text-muted-foreground hover:bg-surface-soft hover:text-foreground",
}, },
size: { size: {
default: "h-11 px-5", default: "h-11 px-5",
+115 -20
View File
@@ -5,24 +5,30 @@
var(--font-instrument-sans), ui-sans-serif, system-ui, sans-serif; var(--font-instrument-sans), ui-sans-serif, system-ui, sans-serif;
--font-serif: var(--font-playfair), ui-serif, Georgia, serif; --font-serif: var(--font-playfair), ui-serif, Georgia, serif;
/* Light palette: mirrors the app's `lightColors` (constants/colors.ts). */ /* Calm, layered palette shared with the current iOS visual language. */
--color-canvas: #f8fafc; --color-canvas: #f4f9f7;
--color-surface: #ffffff; --color-surface: #fcfffe;
--color-surface-soft: #f1f5f9; --color-surface-soft: #e7f1ee;
--color-primary: #0f766e; --color-primary: #0f766e;
--color-primary-light: #ccfbf1; --color-primary-light: #d6f5ed;
--color-primary-button: #0f766e; --color-primary-button: #0f766e;
--color-foreground: #0f172a; --color-foreground: #102523;
--color-muted-foreground: #64748b; --color-muted-foreground: #58716e;
--color-border-soft: #e2e8f0; --color-border-soft: #ccddda;
--color-success: #047857; --color-success: #0f766e;
--color-success-light: #d1fae5; --color-success-light: #d6f5ed;
} }
@layer base { @layer base {
:root { :root {
color-scheme: light; color-scheme: light;
--grid-line: rgba(15, 23, 42, 0.055); --ambient-teal: rgba(83, 211, 192, 0.24);
--ambient-blue: rgba(132, 194, 255, 0.2);
--ambient-warm: rgba(244, 184, 128, 0.2);
--glass-fill: rgba(252, 255, 254, 0.74);
--glass-fill-strong: rgba(252, 255, 254, 0.9);
--glass-border: rgba(255, 255, 255, 0.78);
--glass-shadow: rgba(16, 65, 60, 0.13);
} }
/* /*
@@ -34,18 +40,24 @@
@media (prefers-color-scheme: dark) { @media (prefers-color-scheme: dark) {
:root { :root {
color-scheme: dark; color-scheme: dark;
--color-canvas: #0b1220; --color-canvas: #071415;
--color-surface: #1e293b; --color-surface: #142728;
--color-surface-soft: #111827; --color-surface-soft: #0e2021;
--color-primary: #2dd4bf; --color-primary: #2dd4bf;
--color-primary-light: #134e4a; --color-primary-light: #124842;
--color-primary-button: #115e59; --color-primary-button: #115e59;
--color-foreground: #f1f5f9; --color-foreground: #eaf6f2;
--color-muted-foreground: #94a3b8; --color-muted-foreground: #96afab;
--color-border-soft: #334155; --color-border-soft: #294243;
--color-success: #34d399; --color-success: #34d399;
--color-success-light: #064e3b; --color-success-light: #124238;
--grid-line: rgba(45, 212, 191, 0.08); --ambient-teal: rgba(45, 212, 191, 0.18);
--ambient-blue: rgba(41, 122, 179, 0.2);
--ambient-warm: rgba(161, 91, 55, 0.16);
--glass-fill: rgba(20, 39, 40, 0.68);
--glass-fill-strong: rgba(20, 39, 40, 0.9);
--glass-border: rgba(180, 228, 218, 0.13);
--glass-shadow: rgba(0, 0, 0, 0.34);
} }
} }
@@ -55,6 +67,7 @@
body { body {
@apply bg-canvas text-foreground font-sans antialiased; @apply bg-canvas text-foreground font-sans antialiased;
min-height: 100svh;
} }
::selection { ::selection {
@@ -62,6 +75,88 @@
} }
} }
.ambient-canvas {
background:
radial-gradient(
ellipse 78% 54% at 4% -8%,
var(--ambient-teal),
transparent 68%
),
radial-gradient(
ellipse 66% 50% at 102% 22%,
var(--ambient-blue),
transparent 70%
),
radial-gradient(
ellipse 64% 48% at -8% 88%,
var(--ambient-warm),
transparent 72%
),
var(--color-canvas);
}
.glass-panel {
border: 1px solid var(--glass-border);
background: var(--glass-fill);
box-shadow:
0 24px 70px var(--glass-shadow),
inset 0 1px 0 rgba(255, 255, 255, 0.32);
backdrop-filter: blur(24px) saturate(140%);
-webkit-backdrop-filter: blur(24px) saturate(140%);
}
.glass-panel-strong {
border: 1px solid var(--glass-border);
background: var(--glass-fill-strong);
box-shadow:
0 18px 55px var(--glass-shadow),
inset 0 1px 0 rgba(255, 255, 255, 0.28);
backdrop-filter: blur(30px) saturate(150%);
-webkit-backdrop-filter: blur(30px) saturate(150%);
}
.brand-warm {
background:
radial-gradient(
circle at 84% 12%,
color-mix(in srgb, var(--ambient-blue) 82%, transparent),
transparent 34%
),
linear-gradient(145deg, #fbf1e7 0%, #f4f9f7 56%, #e8f7f3 100%);
}
.brand-night {
background:
radial-gradient(
circle at 82% 12%,
rgba(45, 212, 191, 0.21),
transparent 34%
),
radial-gradient(
circle at 8% 88%,
rgba(58, 134, 185, 0.17),
transparent 31%
),
linear-gradient(150deg, #071415 0%, #0b2928 54%, #102b3c 100%);
}
@media (prefers-color-scheme: dark) {
.brand-warm {
background:
radial-gradient(
circle at 84% 12%,
rgba(41, 122, 179, 0.17),
transparent 34%
),
radial-gradient(
circle at 8% 84%,
rgba(161, 91, 55, 0.14),
transparent 36%
),
linear-gradient(145deg, #142421 0%, #0d1f20 58%, #102a32 100%);
}
}
.card-hover { .card-hover {
@apply transition-all duration-200 hover:-translate-y-0.5 hover:shadow-[0_8px_24px_rgba(15,23,42,0.08)]; @apply transition-all duration-200 hover:-translate-y-0.5 hover:shadow-[0_8px_24px_rgba(15,23,42,0.08)];
} }