From 1f4680ceb06587013bbee406a87b833c0f8ebbe5 Mon Sep 17 00:00:00 2001 From: Grant Lindsay Date: Fri, 12 Jun 2026 16:35:17 -0400 Subject: [PATCH] feat (mode): switches dark/light mode based on OS or browser. --- CONTEXT.md | 7 ++++--- src/app/globals.css | 24 +++++++++++++++++++++--- src/app/layout.tsx | 2 +- 3 files changed, 26 insertions(+), 7 deletions(-) diff --git a/CONTEXT.md b/CONTEXT.md index 0e742bb..235f27a 100644 --- a/CONTEXT.md +++ b/CONTEXT.md @@ -157,7 +157,7 @@ reflect what ships. | Layer | Choice | Notes | |---|---|---| | Frontend | Next.js 16 App Router (TypeScript) | `src/` directory; read `node_modules/next/dist/docs/` for API changes | -| Styling | Tailwind CSS v4 | Theme tokens in `src/app/globals.css` (TDS § 3) | +| Styling | Tailwind CSS v4 | Theme tokens in `src/app/globals.css` (TDS § 3); appearance follows OS via `prefers-color-scheme` | | API | GraphQL via Apollo Server 5 | `src/app/api/graphql/route.ts` — **queries only** | | Data fetching | `gqlFetch` + tagged queries | `src/lib/gql/fetch.ts`, `src/lib/gql/queries.ts` | | ORM | Prisma 7 + `@prisma/adapter-pg` | Models: `Page`, `Section`, `PageSection` | @@ -244,8 +244,9 @@ Technical_Design_Spec.md ## Brand & Design Tokens (from TDS § 3) -- **Mode:** Dark-mode first -- **Palette:** `background: #111111`, `surface: #1A1A1A`, `border: #2D2D2D`, `primary: #F5F5F5`, `secondary: #A3A3A3`, `accent: #BE9541`, `accent-hover: #D1A758` +- **Mode:** System-driven via `prefers-color-scheme` — no site-level toggle. Dark palette is the default; light palette applies when the OS/browser prefers light. Source of truth: `src/app/globals.css` (`@theme` — not `inline`, so utilities reference CSS variables + `@media (prefers-color-scheme: light)` overrides on `:root`). +- **Dark palette (default):** `background: #111111`, `surface: #1A1A1A`, `border: #2D2D2D`, `primary: #F5F5F5`, `secondary: #A3A3A3`, `accent: #BE9541`, `accent-hover: #D1A758` +- **Light palette:** `background: #F5F5F5`, `surface: #FFFFFF`, `border: #E5E5E5`, `primary: #111111`, `secondary: #6B6B6B`, `accent: #BE9541`, `accent-hover: #D1A758` - **Font:** Geist Sans (primary), Geist Mono (mono) — via `next/font/google` - **Motion:** Subtle micro-interactions only. No parallax, no hero carousels, no full-page transitions. - **Dog imagery:** None anywhere on the site except potentially one photo on `/about`. diff --git a/src/app/globals.css b/src/app/globals.css index ce27f00..af850e2 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -4,12 +4,12 @@ * Fast Dog Coding — Design System Tokens * Source: Technical Design Spec § 3 * - * Dark-mode-first. There is no light mode. + * Dark-mode-first defaults; light palette applied via prefers-color-scheme. * All token names map 1:1 to Tailwind utility classes: * bg-background, text-primary, border-border, shadow-lift, etc. */ -@theme inline { +@theme { /* ── Colors ── */ --color-background: #111111; /* Primary dark background */ --color-surface: #1A1A1A; /* Card and panel backgrounds */ @@ -56,13 +56,31 @@ --shadow-accent-glow: 0 0 12px rgba(190, 149, 65, 0.4); } +html { + color-scheme: light dark; +} + +@media (prefers-color-scheme: light) { + :root { + --color-background: #F5F5F5; + --color-surface: #FFFFFF; + --color-border: #E5E5E5; + --color-primary: #111111; + --color-secondary: #6B6B6B; + --color-accent: #BE9541; + --color-accent-hover: #D1A758; + --shadow-lift: 0 4px 12px rgba(0, 0, 0, 0.08); + --shadow-accent-glow: 0 0 12px rgba(190, 149, 65, 0.4); + } +} + body { background-color: var(--color-background); color: var(--color-primary); font-family: var(--font-sans); } -/* ── Prose styles for dark-mode Markdown rendering ── */ +/* ── Prose styles for Markdown rendering ── */ .prose-fdc { line-height: 1.75; } diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 6308ff4..0a37d15 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -74,7 +74,7 @@ export default function RootLayout({ return (