# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview Interactive CV/portfolio for Andy Charlwood, presented as a premium clinical information system. The concept: *what if a GP surgery's patient record system were redesigned by a luxury product studio?* The structure and metaphor of a real clinical system (patient banner, sidebar navigation, record sections) — but elevated with refined typography, considered motion, and atmospheric depth. **This is NOT a faithful NHS system clone.** It's a showcase portfolio that *evokes* the feel of clinical software while being distinctly beautiful. The clinical metaphor is the creative conceit; the execution should feel premium and elegant. Built as a React SPA with TypeScript and Vite. ## Commands - `npm run dev` — Start dev server (localhost:5173) - `npm run build` — TypeScript compile + Vite production build - `npm run typecheck` — TypeScript type checking only (`tsc --noEmit`) - `npm run lint` — ESLint - `npm run preview` — Preview production build No test framework is configured. ## Architecture ### Four-Phase UI Flow `App.tsx` manages a `Phase` state (`'boot'` → `'ecg'` → `'login'` → `'pmr'`). Each phase renders exclusively: 1. **BootSequence** — Terminal typing animation (~4s), green-on-black aesthetic. Fira Code font, matrix-green palette. **Locked — do not change.** 2. **ECGAnimation** — Canvas-based heartbeat animation with mask-based letter tracing. Background transitions from black to `#1E293B`. **Locked — do not change.** 3. **LoginScreen** — Animated login card on dark background. Types credentials at a natural pace, then presents an interactive "Log In" button for the user to click. This phase onward is open to design evolution. 4. **PMRInterface** — The main portfolio experience: patient banner + clinical sidebar + scrollable content views. ### Key Patterns - **Canvas ECG**: `ECGAnimation.tsx` does imperative canvas drawing with requestAnimationFrame — flatline → 3 heartbeats (40px→60px→100px) → mask-based letter tracing → exit. - **Clinical sidebar navigation**: `ClinicalSidebar.tsx` provides hash-routed view switching with keyboard shortcuts (Alt+1-7, arrow keys, "/" for search). - **Patient banner condensation**: `PatientBanner.tsx` uses IntersectionObserver via `useScrollCondensation` hook — full banner (80px) condenses to 48px on scroll. - **Staggered entrance animations**: Framer Motion variants with sequenced delays (banner → sidebar → content). - **View switching**: Instant — no crossfade or slide between views. Content fades in once on initial load only. - **Expandable rows**: Consultation entries, medication rows, and problem entries expand in-place with height animation. - **Responsive breakpoints**: Desktop (full sidebar + banner), Tablet (icon-only sidebar), Mobile (bottom nav bar). ### Path Aliases `@/` maps to `./src/` (configured in both `vite.config.ts` and `tsconfig.json`). ### Type System All data types live in `src/types/index.ts` and `src/types/pmr.ts`. Strict TypeScript — no `any` types. One component per file with typed props interfaces. ## Design Direction: Clinical Luxury The aesthetic direction is **"Clinical Luxury"** — the precision and information density of a medical records system, married to the refinement of high-end product design. Think Bloomberg Terminal redesigned by a Swiss design house. ### Tone - **Precise, not cold.** Every element has a reason. Spacing is generous but intentional. - **Structured, not rigid.** The grid and hierarchy of clinical software, but with room to breathe. - **Technical, not sterile.** Monospace data, status indicators, and coded entries create authentic texture. - **Elegant, not decorative.** No gratuitous ornament. Beauty comes from proportion, contrast, and type. ### Typography Typography is the primary vehicle for premium feel. Avoid generic system fonts. - **UI / Body — two candidates to evaluate (build with both, then choose):** - **Elvaro Grotesque** (by TabojaStudio) — Modern grotesque sans-serif. 7 weights: Light (300), Regular (400), Medium (500), SemiBold (600), Bold (700), ExtraBold (800), Black (900). Also available as variable font. The "grotesque" classification carries institutional credibility (Helvetica/Akzidenz-Grotesk lineage) while feeling distinctly premium. Slightly condensed proportions suit data-dense UI. - **Blumir** (by VisualCreativeStd) — Geometric-humanist hybrid, "blends geometric precision." 7 weights: Thin (100), ExtraLight (200), Light (300), Regular (400), Medium (500), SemiBold (600), Bold (700) — plus oblique variants for each. Also available as variable font. More refined/luxurious feel than Elvaro. - Both fonts are sourced from Envato (licensed), stored locally in `Fonts/`. Web font files (WOFF/WOFF2) are available for both. **Do not use Inter, Roboto, or system defaults** — these read as generic. - Font files for web: - Elvaro: `Fonts/Elvaro Grotesque Sans Family/WOFF/TBJElvaro-*.woff2` - Blumir: `Fonts/blumir-font-family/WOFF/Blumir-VF.woff2` (variable font) - **Monospace / Data**: Geist Mono for timestamps, coded entries, registration numbers, and tabular data. This creates the "technical texture" that sells the clinical metaphor. - **Terminal phase**: Fira Code — locked, do not change. - **Type scale**: Keep it tight. Clinical systems use small text. Headings 15-18px, body 13-14px, labels 11-12px. Precision over drama. - **Weight hierarchy**: Use weight (400/500/600/700) rather than size to establish hierarchy. Bold section headers, medium labels, regular body. ### Color Palette The palette anchors on NHS Blue as the institutional accent, with a predominantly dark sidebar + light content split that creates natural drama. - **NHS Blue `#005EB8`** — The single strong accent color. Used for active states, links, buttons, interactive elements. This IS the brand color of the clinical metaphor. - **Dark sidebar `#1E293B`** — Creates gravitas. The "serious software" feel comes from this dark chrome. - **Patient banner `#334155`** — Slightly lighter than sidebar. The information-dense header bar. - **Content background** — Not flat gray. Consider a very subtle warm tint, or a faint noise/grain texture overlay on `#F5F7FA` to add depth. The content area should feel like paper, not a spreadsheet. - **Cards `#FFFFFF`** — Clean white with refined shadows (layered, not single-value). Cards should feel like they float slightly above the content surface. - **Status colors**: Green `#22C55E`, Amber `#F59E0B`, Red `#EF4444` — used sparingly for traffic-light indicators. Always paired with text labels, never as sole signifier. - **Text**: Primary `#111827`, Secondary `#6B7280`, Muted `#94A3B8`. Use the full range for hierarchy. ### Shadows & Depth Real clinical software is flat and border-heavy. This project should use shadows to create subtle layered depth: - **Cards**: Multi-layered shadow — e.g., `0 1px 2px rgba(0,0,0,0.04), 0 4px 12px rgba(0,0,0,0.03)`. Gentle, not Material Design dramatic. - **Sidebar**: Optional very subtle inner shadow or glow at the right edge where it meets content. - **Patient banner**: Subtle drop shadow below to separate from content. - **Hover states**: Cards may lift very slightly on hover (1-2px translate + shadow deepen). Keep it restrained. ### Motion Motion should feel considered and premium, never flashy: - **Entrance animations**: The PMR interface materializes in sequence — banner slides down → sidebar slides from left → content fades in. Quick (200-300ms) with easing. - **Login typing**: 80ms/char for username, 60ms/dot for password. Natural, readable pace. After typing completes, "Log In" button becomes interactive — user clicks to proceed. - **Login transition**: On button click, card scales slightly and fades. Background carries over to PMR (both are `#1E293B`-derived). - **View switching**: Instant, no transition between views. This preserves the "software application" feel. - **Expandable content**: Height-only animation, 200ms ease-out. Content grows/shrinks — no opacity fade. - **Hover states**: Subtle, immediate. Background color shifts, not transforms. Think: OS-level responsiveness. - **Clinical alert**: Spring animation for entrance (Framer Motion `type: "spring"`). Dismiss: icon crossfade → height collapse. - **`prefers-reduced-motion`**: All animations skip to final state. No exceptions. ### Spatial Composition - **Generous but structured.** More whitespace than a real clinical system. Cards have 16-24px padding. Sections breathe. - **Clear visual hierarchy.** Section headers (uppercase, small, tracked-out) → content. No ambiguity about what's a label vs. data. - **Two-column summary grid** on desktop, single column on mobile. Cards span full width or half width — no orphan columns. - **Tables** use proper `