Compare commits

...

284 Commits

Author SHA1 Message Date
admin d7888071b8 Ammended email template 2026-02-20 11:46:24 +00:00
admin 5040b9a9fd Fixed KPI card text 2026-02-20 11:16:22 +00:00
admin c778d79aec MIT licence 2026-02-20 10:59:01 +00:00
admin 28d2ae61ff Fixed incorrect licence desc. in ReadMe 2026-02-20 10:54:47 +00:00
admin c651f0ed44 Cleaned up repo with old files, and ammended logo size in sidebar/mobile overview 2026-02-20 10:53:40 +00:00
admin d478276c3b Fixed minor UI issue with the nav bar on mobile 2026-02-20 01:24:01 +00:00
admin 46c049def0 Added og:image & description tags 2026-02-20 01:01:03 +00:00
admin 98442c0f9f Changed inactive line opacity 2026-02-19 23:51:14 +00:00
admin 82fcd6bc94 Disable highlight effect on mobile 2026-02-19 23:45:36 +00:00
admin 9d153e95d1 Preconnect hints for page load 2026-02-19 21:46:27 +00:00
admin e452b66a7f Fixed initial load being slow 2026-02-19 21:38:39 +00:00
admin edc1327987 Added Mary Seacole back in 2026-02-19 20:27:06 +00:00
admin 72d159484f Fixed a few skills 2026-02-19 19:54:18 +00:00
admin cb1c958f68 Skill updates 2026-02-19 18:32:36 +00:00
admin 6bf5a6b6b2 update login transition 2026-02-19 16:45:58 +00:00
admin 3ddd4ecdbd Changes carousel auto scroll to pause when interaction occurs 2026-02-19 16:32:11 +00:00
admin d403e96d34 Minor change to summary and tab name 2026-02-19 16:23:12 +00:00
admin 3773268706 Rewrote KPI and Project sections! 2026-02-19 16:15:33 +00:00
admin b13252be71 Fixed LLM chat function 2026-02-19 14:47:17 +00:00
admin 3ae4abeb9f Fixed backend 2026-02-19 14:22:17 +00:00
admin 1fc2ba2385 Removed unused fonts 2026-02-19 14:14:45 +00:00
admin 30511cac81 Whoopsied the server 2026-02-19 14:14:08 +00:00
admin 95ea088a00 Added small backend server to manage LLM chat & contact me form 2026-02-19 14:07:40 +00:00
admin a1f7088b48 Changed "Your role" to "My Role" 2026-02-19 14:00:20 +00:00
admin 012c905c90 Ammended tab name 2026-02-19 13:31:57 +00:00
admin 5806f7a134 Updated links 2026-02-19 13:30:54 +00:00
admin 9f2be70fd6 Added analytics tracking 2026-02-19 13:10:34 +00:00
admin 9186be7e3e Added aria attributes/keyboard nav to carousel 2026-02-18 13:52:40 +00:00
admin 9baa6e605b Mobile overview changes 2026-02-18 12:25:53 +00:00
admin 8b79f7b273 mobile banner v1 2026-02-18 02:55:49 +00:00
admin 134e41f4f9 chore: auto-commit before merge (loop primary) 2026-02-18 00:42:07 +00:00
admin 62c0d2ea19 Pre UX polish 2026-02-18 00:23:35 +00:00
admin 836305e2a3 Fix mobile 2026-02-17 23:14:05 +00:00
admin d51efb535d chore: auto-commit before merge (loop primary) 2026-02-17 21:19:40 +00:00
admin 025f860815 Loop prep 2026-02-17 20:58:56 +00:00
admin 06ca2a2b46 test webhook autodeploy... v2 2026-02-17 15:19:54 +00:00
admin 851d62fcbb test webhook autodeploy 2026-02-17 15:18:54 +00:00
admin 0a337b41c2 Fix hover effect on chart causing transition/animation to break 2026-02-17 15:14:10 +00:00
admin 47b52b5a93 feat: add global focus mode with cross-component dimming on hover
When hovering a constellation node, skill pill, or timeline item,
non-related UI elements across all components dim to 0.25 opacity,
creating a focused visual relationship view. The constellation axis
and year labels also dim via CSS class. Respects reduced-motion.
2026-02-17 14:17:21 +00:00
admin 82db5fda54 Substantial refinement/polish on content of webpage (not just structural/coding elements) 2026-02-17 14:05:32 +00:00
admin 38e40d36c0 chore: auto-commit before merge (loop primary) 2026-02-17 03:30:44 +00:00
admin 841c1869d6 chore: finalise unverified-content.md audit summary
- Updated removed content section (no content fully removed)
- Added skills.ts, investigations.ts, and llm-prompt.ts corrections
- All sections complete: flagged-but-retained, corrections, missed opportunities
2026-02-17 03:29:12 +00:00
admin a867c75e9b fix: re-enable boot sequence after redesign
Changed initial phase from 'pmr' back to 'boot' to restore the
full boot → login → dashboard flow for production.
2026-02-17 03:28:41 +00:00
admin 150b452bb5 feat: redesign boot-to-login transition
New boot flow: typing → holding → loading (progress bar) → fade → login

- Added ProgressBar component with ease-out animation during loading phase
- Terminal text slides up and fades during exit transition
- Cursor shrinks during loading phase for visual continuity
- Progress bar appears below terminal text, fills over 1.2s
- Entire container fades out smoothly before transitioning to login
- Reduced motion: instant render, no animation (unchanged)
- Changed "Rendering CV" → "Launching CV" for better software-launch feel
- Tuned timing: shorter hold (600ms), loading (1200ms), faster fade (500ms)
2026-02-17 03:28:00 +00:00
admin b266f1f149 feat: remove ECG phase entirely
- Deleted src/components/ECGAnimation.tsx (686 lines)
- Removed 'ecg' from Phase type
- Removed ECG import, rendering, and cursor position handoff from App.tsx
- Cleaned up BootSequence: removed onCursorPositionReady prop,
  captureCursorPosition callback, cursorRef, and ECG-specific naming
- Renamed ecgStartDelay → completionDelay, ecg-seed-dot → boot-seed-dot
- Skip button now goes directly to dashboard ('pmr' phase)
- Boot flow simplified: boot → login → pmr (no ECG intermediary)
- Bundle size reduced ~8KB
2026-02-17 03:26:17 +00:00
admin 0fc7985a7c audit: final sweep for hardcoded strings in components
Searched all components for hardcoded factual claims. Found:
- BootSequence.tsx: all content verified (done in 2.10)
- EducationSubsection.tsx: hardcoded education data duplicates data layer
  but all content verified against CV
- LastConsultationCard.tsx: NHS Band "8a" not in references, flagged
- ChatWidget.tsx: suggested questions are UI prompts, not claims
All findings logged in unverified-content.md.
2026-02-17 03:23:33 +00:00
admin 49bddeaa45 audit: verify llm-prompt.ts against reference documents
- Profile: "Informatics pharmacist" → "Healthcare leader" per CV
- Interim Head: "practice-level aggregate reporting" → "practice-level data"
- HCD: "Authored most" → "Wrote most" per CV
- Duty Pharm Mgr: "Led" → "Co-led", removed national quality payments claim
- Pre-Reg: aligned PGD and palliative care descriptions with secondary ref
- PharMetrics: corrected from "Interactive Platform" to "Switching Dashboard"
- Skills: Python 6yr→8yr, SQL 7yr→3yr per corrected skills.ts data
2026-02-17 03:21:43 +00:00
admin e2ba2575b6 audit: verify profile-content.ts against reference documents
- Narrative: aligned with CV Profile — "Healthcare leader" instead of
  unverified "Informatics pharmacist", tightened phrasing throughout
- Achievement subtitle: "Full analytical accountability to ICB board" →
  "Prescribing budget with forecasting models" per CV
- Skills summary: "data engineering" → "data pipeline development" per CV;
  removed unverified "clinical decision support"
- Flagged retained "Informatics Pharmacist" roleTitle in unverified log
2026-02-17 03:20:24 +00:00
admin 61299100d9 audit: verify documents.ts and educationExtras.ts against references
- Research description: removed embellished "investigating cocrystal
  formation for improved drug delivery properties", replaced with CV
  phrasing "on drug delivery and cocrystals"
- All education credentials, grades, dates, and institutions verified
- Extracurriculars verified against secondary reference
2026-02-17 03:18:53 +00:00
admin abb4fcd909 audit: verify skills.ts against reference documents
- Python: startYear corrected 2019→2017 (self-taught during Tesco night
  shifts per secondary ref); yearsOfExperience 6→8
- SQL: startYear corrected 2018→2022 (learned after gaining NHS database
  access per secondary ref); removed unverified pre-2022 history entries
- Power BI: fixed prescribing history year inconsistency (2019→2020);
  removed "PharMetrics real-time expenditure dashboard" reference
- All skill categories and names verified against CV Core Competencies
2026-02-17 03:18:04 +00:00
admin 0fba10d469 audit: verify investigations.ts against reference documents
- PharMetrics: corrected from "Interactive Platform" to "Switching Dashboard"
  to align with references (PharMetrics is the switching algorithm project);
  updated methodology to match secondary ref's dashboard description
- All other investigations (switching algorithm, Blueteq, CD monitoring,
  Sankey tool) verified against CV and secondary reference — no changes needed
2026-02-17 03:16:53 +00:00
admin 3c5f9a506c audit: verify kpis.ts against reference documents
- Budget KPI: removed unverified "monthly" reporting frequency,
  aligned with CV's "bimonthly" CMO presentations
- Population KPI: removed "monitor medicines safety" to match CV;
  "aggregate reporting" → "practice-level data" per CV wording
- Also fixed timeline.ts Interim Head detail to match CV wording
- All KPI values (£220M, £14.6M, £2.6M, 1.2M) verified against CV
2026-02-17 03:15:45 +00:00
admin de5b5939d6 audit: verify timeline.ts against reference documents
Key corrections:
- HCD role: "Authored most" → "Wrote most" to match CV phrasing
- HCD role: "formulary adherence opportunities" → "improvement opportunities"
- Deputy Head: removed embellished description additions not in CV
- Duty Pharmacy Manager: "Led" → "Co-led" per secondary reference;
  removed national quality payments claim (belongs to Pharmacy Manager)
- Pre-Reg: aligned PGD and palliative care descriptions with secondary ref
- UEA MPharm: removed "academic excellence" (misleading given exam failures)

Updated unverified-content.md with corrections log and missed opportunities
including McDonald's role, Mary Seacole programme, self-taught coding
narrative, AI/LLM work, and opioid deprescribing metrics.
2026-02-17 03:14:40 +00:00
admin 661dba4b75 audit: verify patient.ts against reference documents
- Address corrected from 'Norwich, NR1' to 'Norwich, UK' to match CV
- Created References/unverified-content.md to track audit findings
- Flagged retained-but-unverifiable personal data (DOB, GPhC number, LinkedIn slug)
- All other fields verified against CV_v4.md
2026-02-17 03:11:47 +00:00
admin 9e31843fc9 chore: merge secondary reference documents into single deduplicated source
Create References/andy_charlwood_complete_reference.md by merging
andy_charlwood_career_knowledge.md and andy_charlwood_career_knowledge_dump.md.
Structured by career timeline, projects, skills, education, leadership, and
career goals. Where sources conflicted, the more detailed version was preferred.
Original files preserved unchanged.
2026-02-17 03:09:55 +00:00
admin f7469f487f chore: bypass boot sequence for faster dev iteration
Temporarily set initial phase to 'pmr' to skip boot/ECG/login
during content audit work. Will be reverted in Phase 3.3.
2026-02-17 03:04:51 +00:00
admin 9a58b3c312 chore: auto-commit before merge (loop primary) 2026-02-17 02:26:42 +00:00
admin 01a48ce691 fix: re-enable boot sequence after refactor
Restore useState<Phase>('boot') in App.tsx, completing the refactoring
cycle (was temporarily set to 'pmr' for faster visual review).
2026-02-17 02:24:44 +00:00
admin 5eb46b02d8 refactor: remove dead code — orphaned files, unused types and functions
Delete 3 orphaned files (SubNav, TopBar, problems.ts), remove 4 unused
type definitions from pmr.ts (ViewId, NavItem, ReferralFormData, Problem),
trim types/index.ts to only Phase, and remove unused utility functions
(calculateSkillOffset, formatBootLine, getProfileContent, DotColorName).
2026-02-17 02:24:40 +00:00
admin 1b19087782 refactor: extract LastConsultationCard from DashboardLayout
Move the self-contained LastConsultationSubsection component (191 lines)
into its own file as LastConsultationCard. It uses only context and one
prop, with no dependency on DashboardLayout state. DashboardLayout drops
from 493 to 293 lines.
2026-02-17 02:16:10 +00:00
admin 49c9e0cecf refactor: centralise detail panel inline styles into detail-styles.ts
Extract 5 shared style constants (detailRootStyle, sectionHeadingStyle,
bulletListStyle, bodyTextStyle, paragraphStyle) used across 5 of 6 detail
components. Replaces ~30 inline style object definitions with imports.
Net reduction: 274 lines across detail panel components.
2026-02-17 02:09:26 +00:00
admin 7528935d2b refactor: extract ExpandableCardShell from WorkExperience and TimelineInterventions subsections
Single source of truth for expand/collapse card interaction pattern:
container styling, keyboard handling, chevron rotation, AnimatePresence
animation, and expanded content wrapper. Each consumer retains unique
header and body content via render props.
2026-02-17 02:03:13 +00:00
admin 8f4ddc454a refactor: centralise color maps, org color fallback, and motion-safe transitions
Create src/lib/theme-colors.ts with DOT_COLORS, KPI_COLORS,
PROJECT_STATUS_COLORS, and DEFAULT_ORG_COLOR constants. Add
motionSafeTransition() utility to src/lib/utils.ts.

Removes 6 duplicate color map definitions across Card, DetailPanel,
PatientSummaryTile, KPIDetail, ProjectsTile, and ProjectDetail.
Replaces 9 hardcoded '#0D6E6E' fallbacks and 7 inline motion ternaries.
Fixes project status color inconsistency between ProjectsTile and
ProjectDetail (Ongoing was teal in tile, amber in detail).
2026-02-17 01:58:10 +00:00
admin 296b18f025 refactor: extract hexToRgba and prefersReducedMotion to shared utils
Move hexToRgba() (3 identical copies) and prefersReducedMotion (5 module-level
copies) to src/lib/utils.ts. Re-export prefersReducedMotion from
constellation/constants.ts to preserve existing importers. Add clarifying
comments to constellation.ts and tags.ts re-export layers (Phase 1.4).
2026-02-17 01:48:43 +00:00
admin 45b87466be refactor: extract LLM system prompt from profile-content to dedicated module
Move the ~110-line LLM system prompt to src/data/llm-prompt.ts, removing
the LLMCopy type, getLLMCopy() accessor, and llm field from ProfileContent.
llm.ts now imports the prompt directly. profile-content.ts drops from 246
to 133 lines, retaining only UI copy and search metadata.
2026-02-17 01:42:55 +00:00
admin bbe7900968 refactor: inline timeline narrative into timeline.ts, remove indirection
Timeline entities now contain their narrative data (description, details,
outcomes, codedEntries) directly instead of fetching via
getTimelineNarrativeEntry(). Removes ~155 lines from profile-content.ts,
the accessor function, and three dead types.
2026-02-17 01:37:32 +00:00
admin 0ee7b5d44c refactor: skip boot/ECG/login sequence for dev iteration speed
Temporarily set initial phase to 'pmr' to bypass the ~10s boot animation
during the refactoring process. Will be reverted in Phase 4.3.
2026-02-17 01:28:48 +00:00
admin 83b327d58e Refactor to pull all text enteries into single location 2026-02-17 01:10:31 +00:00
admin 6605966fab feat: add canonical profile content schema and access helpers 2026-02-16 23:32:25 +00:00
admin 8178d03cb2 Rehaul of graph component 2026-02-16 23:16:46 +00:00
admin e9a7581aa5 chore: auto-commit before merge (loop primary) 2026-02-16 15:06:20 +00:00
admin aca57714e4 chore: auto-commit before merge (loop primary) 2026-02-16 14:36:25 +00:00
admin 9276955fa8 refactor: extract PlayPauseButton + screen-reader-description from orchestrator
Reduces CareerConstellation orchestrator from 334 to 285 lines to meet
the <300 line success criterion.
2026-02-16 14:35:15 +00:00
admin 8b674ffe14 feat: phase 3+4 timeline animation + education entities
- Add education entities (A-Levels, MPharm) to constellation data
- Add 'education' node type with dashed border styling
- Create useTimelineAnimation hook with rAF scheduler + state machine
  (IDLE → PLAYING → PAUSED → HOLDING → RESETTING → loop)
- Chronological reveal: entities oldest-first with skill stagger,
  link draw-on, reinforcement pulse for already-visible skills
- Year indicator overlay (monospace, top-left)
- Multiplicative opacity: animation visibility × highlight emphasis
- Highlight system respects visibleNodeIdsRef (unrevealed stay hidden)
- Interaction pause/resume wired to animation hook
- Play/pause button (bottom-right, larger touch target on mobile)
- prefers-reduced-motion: shows final state immediately, no animation
- Remove Phase 2 entry animation (replaced by timeline animation)
2026-02-16 14:31:11 +00:00
admin 7d7628c8a7 feat: phase 2 visual improvements for CareerConstellation
- Links: domain-colored with strength-weighted width/opacity, improved bezier curves
- Skill nodes: domain-colored stroke, size encoding by connected role count, glow filter on highlight
- Role nodes: gradient fill (orgColor 0.08→0.18), enhanced highlight with fill-opacity and stroke-width
- Entry animation: staggered reveal (guides→roles→skills→links with stroke-dashoffset), skipped under prefers-reduced-motion
- Legend: domain node counts displayed
2026-02-16 14:16:36 +00:00
admin 65b265733e refactor: decompose CareerConstellation monolith into focused modules
Break 1102-line CareerConstellation.tsx into:
- constellation/constants.ts: sizing, opacity, domain color tokens
- constellation/types.ts: SimNode, SimLink, LayoutParams interfaces
- hooks/useForceSimulation.ts: D3 simulation lifecycle
- hooks/useConstellationHighlight.ts: highlight/dim logic
- hooks/useConstellationInteraction.ts: mouse/touch/pin handlers
- constellation/MobileAccordion.tsx: tap-to-expand role details
- constellation/ConstellationLegend.tsx: domain legend
- constellation/AccessibleNodeOverlay.tsx: keyboard navigation buttons
- constellation/CareerConstellation.tsx: 288-line orchestrator

All existing behaviour preserved. Quality gates pass.
2026-02-16 14:06:41 +00:00
admin b34ecb89e2 clean up 2026-02-16 13:27:51 +00:00
admin 4dfb1607c1 Updated chart 2026-02-16 13:23:04 +00:00
admin 2e242a650a chore: auto-commit before merge (loop primary) 2026-02-16 12:44:34 +00:00
admin 683275416e Removed top bar, and updating sidebar 2026-02-16 12:25:19 +00:00
admin 18d2704677 Updated hats 2026-02-16 11:39:13 +00:00
admin c3a72d0bee Cleanup 2026-02-16 11:33:47 +00:00
admin 5a657c4aac chore: add ralph sidebar workflow setup files 2026-02-16 11:33:13 +00:00
admin 78e994ec5e chore: auto-commit before merge (loop primary) 2026-02-16 11:04:21 +00:00
admin 68f92fb9a0 feat: polish interventions carousel responsiveness 2026-02-16 11:04:08 +00:00
admin be7a65ef8a feat: tune carousel autoplay for reduced motion 2026-02-16 11:02:32 +00:00
admin 5fa01b8d66 feat: implement Embla carousel in ProjectsTile 2026-02-16 11:00:46 +00:00
admin 98d767fa7f feat: rename Active Projects references to Significant Interventions 2026-02-16 10:58:29 +00:00
admin a6df900605 merge codex/kpi (prefer codex/kpi on conflicts) 2026-02-16 10:52:24 +00:00
admin 5637d56e02 Cleanup 2026-02-16 10:50:14 +00:00
admin 24ffe03c0f chore: auto-commit before merge (loop primary) 2026-02-16 10:43:44 +00:00
admin e5c7d9bb41 chore: document KPI objective verification 2026-02-16 10:43:28 +00:00
admin 960c9b7729 Init 2026-02-16 10:41:41 +00:00
admin dad638e68e Added task files 2026-02-16 10:37:11 +00:00
admin b67c3b041f chore: auto-commit before merge (loop primary) 2026-02-16 10:36:47 +00:00
admin ab80d65958 feat: compact latest results kpi section 2026-02-16 10:36:30 +00:00
admin 2306d2ec2e codex setup 2026-02-16 10:27:55 +00:00
admin b418338cd7 feat: US-008 - Re-tune force simulation for 8 timeline entries in narrower column 2026-02-16 10:23:03 +00:00
admin c9dd93ac70 feat: US-007 - Colour-match work experience cards to constellation node colours 2026-02-16 10:09:34 +00:00
admin a258706bf3 feat: US-006 - Mobile accordion expansion for role details 2026-02-16 10:04:35 +00:00
admin 67fe5567a9 feat: US-005 - Hover-to-highlight interaction on desktop 2026-02-16 09:58:27 +00:00
admin f3e9b58e8d feat: US-004 - Viewport-proportional scaling for large screens 2026-02-16 09:50:07 +00:00
admin 76692682da feat: US-003 - Increase default skill visibility and reduce constellation column width 2026-02-16 09:44:10 +00:00
admin f3e6f6670b feat: US-002 - Add UEA MPharm and Highworth A-Levels education entries 2026-02-16 09:38:00 +00:00
admin 354096fd70 feat: US-001 - Add Duty Pharmacy Manager and Pre-Reg Pharmacist roles + fix Pharmacy Manager colour 2026-02-16 09:34:35 +00:00
admin f48d98b7fc feat: US-012 - Responsive behaviour for mobile and tablet constellation
- Add mobile-specific layout constants (MOBILE_ROLE_WIDTH=80, smaller skill radii)
- Use window.innerWidth for mobile breakpoint detection (container overflows on mobile)
- Reduce timelineX, padding, spacing, and force simulation parameters on mobile
- Truncate role pill labels and skill labels on narrow viewports
- Reduce charge/collision/link-distance forces for tighter mobile layout
- Fix CSS grid overflow: add min-width:0 and overflow:hidden to .pathway-graph-sticky
- MOBILE_FALLBACK_HEIGHT adjusted to 380px (within 360-400px spec)
- Legend wraps gracefully via existing flex-wrap
2026-02-16 03:22:21 +00:00
admin 408cd9573c feat: US-011 - Accessibility hardening for career constellation
Fix focusable buttons (pointerEvents 'auto'), sort tab order
(roles reverse-chronological, skills by domain), add skill focus
rings, update aria-label to mention clinical pathway, and trigger
graph highlights on keyboard focus.
2026-02-16 03:12:33 +00:00
admin 622baeb449 feat: US-010 - Content audit verifying role data against CV source 2026-02-16 03:08:06 +00:00
admin 21233c98bb feat: US-009 - Force simulation tuning for clinical layout 2026-02-16 03:04:44 +00:00
admin 89d778b2df feat: US-008 - Compact domain legend as HTML below SVG 2026-02-16 02:58:06 +00:00
admin 13b341abcd feat: US-007 - Curved link lines between roles and skills 2026-02-16 02:55:04 +00:00
admin 752f1c2947 chore: mark US-006 complete, update progress log 2026-02-16 02:50:18 +00:00
admin 743fb625d5 feat: US-006 - Bidirectional hover highlighting between graph and timeline 2026-02-16 02:49:43 +00:00
admin 52238c5662 feat: US-005 - Skill node redesign with muted default and reveal on interaction 2026-02-16 02:42:41 +00:00
admin 46cc22500b feat: US-004 - Role node redesign with clinical record pill badges
Role nodes now render as rounded rectangle pills (104x32px) with orgColor
badge styling, connector lines to timeline, and SVG drop shadow effects
on hover/pinned states.
2026-02-16 02:37:16 +00:00
admin 832c904376 chore: mark US-003 complete, update progress log 2026-02-16 02:27:23 +00:00
admin 8c8329f6e3 feat: US-003 - Clinical pathway background and timeline structure 2026-02-16 02:26:52 +00:00
admin 634eb10b2c feat: US-002 - Dynamic height matching with work experience column 2026-02-16 02:21:45 +00:00
admin 5fcc59414f feat: US-001 - Reverse timeline direction to top = most recent 2026-02-16 02:15:46 +00:00
admin 68b293dc6d Merge branch 'ralph/llm-cv-knowledge'
Merge LLM context rewrite
2026-02-16 01:38:05 +00:00
admin c9c69d2417 Merge branch 'master' of http://192.168.8.143:3000/admin/portfolio
Hope this works...
2026-02-16 01:36:23 +00:00
admin b41a422cf0 Rearranged graph vs timeline 2026-02-16 01:35:24 +00:00
admin d2efc7030a feat: US-019 - Run benchmark and validate accuracy
Benchmark passes 19/20 (threshold 18/20) with no zeros.
Structural improvements: Employment Timeline section, leadership
labels on Tesco bullets, GPhC clarification, prompt trimming.
Fixed Q10 expected answer to match actual CV data.
2026-02-16 00:59:37 +00:00
admin c9cc832382 feat: US-018 - Enrich embedding texts and regenerate embeddings 2026-02-16 00:47:37 +00:00
admin f0870cf320 feat: US-017 - Improve system prompt instructions and LLM parameters 2026-02-16 00:42:58 +00:00
admin 194f83f490 feat: US-016 - Enrich system prompt with full CV context 2026-02-16 00:39:38 +00:00
admin 8cc7038942 feat: US-015 - Migrate benchmark script to OpenRouter 2026-02-16 00:31:16 +00:00
admin 4bab9b369c feat: US-014 - Migrate production chat from Gemini to OpenRouter 2026-02-16 00:24:53 +00:00
admin 7f3428184f Cleaning up branches 2026-02-16 00:12:53 +00:00
admin be443907ee docs: mark US-014 complete, update progress log 2026-02-15 23:53:40 +00:00
admin 0bcdc89427 feat: US-014 - Update to Gemini 3 Flash Preview with model indicator 2026-02-15 23:53:06 +00:00
admin 0fbbf9e46f merge 2026-02-15 23:20:24 +00:00
admin 4580ca9c84 feat: US-014 - Update to Gemini 3 Flash Preview with model indicator 2026-02-15 21:02:52 +00:00
admin 667e5b249c feat: US-013 - Self-host ONNX embedding model
Download all-MiniLM-L6-v2 model files to public/models/ and configure
@xenova/transformers to load from local path instead of Hugging Face CDN.
Eliminates external dependency for semantic search embedding model.
2026-02-15 20:59:03 +00:00
admin 9e9dd1ae4b feat: US-012 - Welcome message with suggested question chips 2026-02-15 20:48:00 +00:00
admin ab5444ee94 feat: US-011 - Mobile full-screen chat panel 2026-02-15 20:43:48 +00:00
admin 657d2f299e Added .env, and ammended .gitignore 2026-02-15 20:32:46 +00:00
admin 5f3e0db712 feat: US-010 - Chat widget — clickable portfolio item cards in responses 2026-02-15 18:30:07 +00:00
admin 29e1728e11 feat: US-009 - Chat widget — Gemini Flash integration 2026-02-15 18:24:42 +00:00
admin 273c143d5e feat: US-008 - Chat widget — panel UI with message display 2026-02-15 18:18:51 +00:00
admin 7ee1a2d9de feat: US-007 - Chat widget — floating button component 2026-02-15 18:13:08 +00:00
admin 2fca61b43a feat: US-006 - Integrate semantic search into command palette 2026-02-15 18:08:25 +00:00
admin c4480d7c99 feat: US-005 - Implement cosine similarity search module 2026-02-15 18:01:51 +00:00
admin ae15ccf961 chore: mark US-004 complete, update progress log 2026-02-15 17:59:11 +00:00
admin 91f8dac261 feat: US-004 - Preload ONNX model during boot sequence 2026-02-15 17:58:41 +00:00
admin aa1774320a feat: US-003 - Generate and commit embeddings.json 2026-02-15 17:55:53 +00:00
admin 219a3f04be chore: mark US-002 complete, update progress log 2026-02-15 17:52:51 +00:00
admin 384e393963 feat: US-002 - Build rich text representations for each palette item 2026-02-15 17:52:07 +00:00
admin 489e306b0a feat: US-001 - Install @xenova/transformers and add generate-embeddings script skeleton 2026-02-15 17:49:25 +00:00
admin 19a4360a8c Next stage 2026-02-15 17:36:53 +00:00
admin 0e450c4b17 chore: mark US-011 complete, update progress log 2026-02-15 14:36:19 +00:00
admin 4fe68aa1b2 feat: US-011 - Re-enable boot sequence 2026-02-15 14:35:54 +00:00
admin 526ee7dd90 feat: US-010 - Fix minor typography inconsistencies 2026-02-15 14:33:53 +00:00
admin 615198b080 feat: US-009 - Replace hardcoded colors with design tokens 2026-02-15 14:30:21 +00:00
admin fc1581a9ff feat: US-008 - Align login card border radius and shadow with dashboard design system 2026-02-15 14:26:53 +00:00
admin 274188b6aa feat: US-007 - Reduce backdrop blur intensity by ~50% 2026-02-15 14:23:56 +00:00
admin cd7184cfd4 feat: US-006 - Extend backdrop blur to cover full dashboard including TopBar 2026-02-15 14:22:49 +00:00
admin 42293c5336 feat: US-005 - Add overlap blend effect on fanning capsules 2026-02-15 14:21:08 +00:00
admin 49f0f1aaf8 feat: US-004 - Increase branding text to match dashboard typography scale 2026-02-15 14:18:07 +00:00
admin c8eb38f083 feat: US-003 - Scale logo and branding block to ~50% of login card height 2026-02-15 14:14:37 +00:00
admin a56a4dd848 feat: US-002 - Extract animation timing into named constants 2026-02-15 14:11:22 +00:00
admin e5be969308 feat: US-001 - Skip to login phase for dev iteration 2026-02-15 14:07:25 +00:00
admin 83b941262e Added logo animation to login screen, initial work 2026-02-15 13:49:15 +00:00
admin 7fbf1dcb95 Merge branch 'ralph/login-screen-rework'
# Conflicts:
#	Ralph/prd.json
#	Ralph/progress.txt
#	src/components/TopBar.tsx
2026-02-15 02:20:32 +00:00
admin 598b1c11f6 Final commit 2026-02-15 02:14:51 +00:00
admin c4d73f970d feat: US-010 - Re-enable boot sequence 2026-02-15 02:14:12 +00:00
admin 1bd735e90a feat: US-009 - Login dissolve transition to reveal dashboard 2026-02-15 02:12:45 +00:00
admin 939b2cddf2 feat: US-008 - Login button pulse animation on activation 2026-02-15 02:10:48 +00:00
admin 73a390ce76 feat: US-007 - Connection status indicator with animated dots and typing-linked timing 2026-02-15 02:09:03 +00:00
admin cfc1c5797d chore: update progress and PRD for US-006 2026-02-15 02:05:46 +00:00
admin 8c04e517bc feat: US-006 - Render live dashboard behind login with blur overlay 2026-02-15 02:05:19 +00:00
admin 09af29f32d chore: update progress and PRD for US-005 2026-02-15 02:02:17 +00:00
admin 3f6ac5ef8d feat: US-005 - Replace Home icon with CVMIS logo on TopBar 2026-02-15 02:02:04 +00:00
admin 0ffacf8a0a feat: US-004 - Rebrand to CVMIS and integrate animated logo 2026-02-15 01:57:13 +00:00
admin 38fdb6fa27 feat: US-003 - Responsive login card sizing and dashboard style alignment 2026-02-15 01:50:09 +00:00
admin f28693b0ad feat: US-002 - Create CvmisLogo React SVG component 2026-02-15 01:47:44 +00:00
admin 05b48b995e feat: US-001 - Skip to login phase for dev iteration 2026-02-15 01:45:45 +00:00
admin 962729ae92 Supporting info for login screen rework 2026-02-15 01:44:02 +00:00
admin 6e66cd631b chore: mark US-028 complete, update progress log 2026-02-14 21:42:17 +00:00
admin c5b0f7da43 feat: US-028 - Re-enable boot/login sequence 2026-02-14 21:41:46 +00:00
admin 649f4d7c68 chore: mark US-027 complete, update progress log 2026-02-14 21:39:11 +00:00
admin b515b3d70c feat: US-027 - Visual regression check across all breakpoints 2026-02-14 21:38:22 +00:00
admin 2d7ff7e77a feat: US-026 - Adjust ParentSection headings for new proportions 2026-02-14 20:41:31 +00:00
admin f88cbf6e08 chore: mark US-025 complete, update progress log 2026-02-14 20:37:55 +00:00
admin daabfb7fd2 feat: US-025 - Scale WorkExperienceSubsection and RepeatMedicationsSubsection 2026-02-14 20:37:22 +00:00
admin 3f026a0701 feat: US-024 - Scale ProjectsTile and EducationSubsection 2026-02-14 20:34:20 +00:00
admin cf1f466452 feat: US-023 - Scale LastConsultationSubsection and main content padding 2026-02-14 20:31:22 +00:00
admin 64973176fb feat: US-022 - Scale PatientSummaryTile content and KPIs 2026-02-14 20:27:25 +00:00
admin 364efb8805 feat: US-021 - Scale Sidebar proportions 2026-02-14 20:24:34 +00:00
admin a7537083e6 feat: US-020 - Scale TopBar and SubNav 2026-02-14 20:21:05 +00:00
admin 645088bbc1 feat: US-019 - Update global layout tokens and Card/CardHeader component 2026-02-14 20:17:27 +00:00
admin f6463cc4b1 feat: US-018 - Skip boot/login sequence for dev iteration 2026-02-14 20:15:11 +00:00
admin 5ef7cdb259 feat: US-017 - Re-enable boot/login sequence for production
Reverted initial Phase from 'pmr' to 'boot', restoring the full
boot → ECG → login → dashboard flow. All 17 user stories now pass.
2026-02-14 18:56:31 +00:00
admin a961518ebf feat: US-016 - Apply chosen parent header typography
Elvaro Grotesque 600, -0.02em tracking with responsive scale from
1.375rem (mobile) to 2.2rem (desktop). Refined from the baseline
700/2.4rem for a more premium, intentional feel.
2026-02-14 18:53:49 +00:00
admin 1ca6175b93 feat: US-015 - Explore parent header typography options
Tested 14 combinations across Elvaro Grotesque (300-900) and Blumir
(100-700), varying size, case, and letter-spacing. Selected Elvaro
Grotesque 600, 2.2rem, title case, -0.02em tracking for premium
clinical feel with clear visual hierarchy.
2026-02-14 18:51:05 +00:00
admin f9b4062dd5 feat: US-014 - Responsive verification and fixes across breakpoints
- Fix grid overflow at mobile: add minWidth:0 + overflow:hidden to Card
- Scale ParentSection h2 responsively (1.5rem mobile → 2.4rem desktop)
- Make KPI grid single-column below 480px, 2-column above
- Fix SubNav alignment: left-aligned on mobile, centered on md+
- Fix SubNav tileIds to match restructured dashboard sections
- Add data-tile-id anchors to experience/skills/education subsections
2026-02-14 18:41:07 +00:00
admin 6bd12dd776 feat: US-013 - Update command palette data for restructured dashboard 2026-02-14 18:32:36 +00:00
admin 9e9962f114 feat: US-012 - Add hover-highlighting between experience/skills and constellation graph 2026-02-14 18:28:44 +00:00
admin b90706a3f6 feat: US-011 - Improve constellation graph visual clarity 2026-02-14 18:22:21 +00:00
admin fcc1232d9b feat: US-010 - Clean up removed standalone tiles and verify layout 2026-02-14 18:19:14 +00:00
admin 9ffed8d153 feat: US-009 - Move Education into Patient Pathway as subsection 2026-02-14 18:14:16 +00:00
admin b5de609cd5 feat: US-008 - Add two-column experience and skills layout in Patient Pathway 2026-02-14 18:11:26 +00:00
admin 0e7bef0206 feat: US-007 - Move Last Consultation into Patient Pathway as subsection 2026-02-14 18:06:18 +00:00
admin 7285ea8f45 feat: US-006 - Create Patient Pathway parent section with constellation graph 2026-02-14 18:02:46 +00:00
admin c86b252629 feat: US-005 - Restructure Patient Summary as parent section with Latest Results subsection 2026-02-14 17:59:41 +00:00
admin 9be2fb9017 chore: update PRD and progress log for US-004 2026-02-14 17:56:23 +00:00
admin 4bfc4de956 feat: US-004 - Create ParentSection component for hierarchical layout 2026-02-14 17:55:59 +00:00
admin 80d4cc9d7a feat: US-003 - Fix inaccurate timeline entries in CareerActivityTile 2026-02-14 17:54:03 +00:00
admin 13131e4c3e feat: US-002 - Remove inaccurate CV data from consultations and constellation 2026-02-14 17:50:35 +00:00
admin 1a3d3515f8 chore: add dashboard restructure PRD and update progress 2026-02-14 17:47:22 +00:00
admin fa64c98406 feat: US-001 - Skip boot/login sequence for dev iteration 2026-02-14 17:44:46 +00:00
admin 0d42db7111 US-032: Update PRD and progress log 2026-02-14 03:21:20 +00:00
admin 088b783731 US-032: Reduced motion audit, final cleanup, and visual review
- Add prefers-reduced-motion overrides for SubNav button transitions
- Add prefers-reduced-motion overrides for smooth scroll behavior
- Fix connection status dot/text transitions to respect reduced motion
- Create ProjectDetail.tsx renderer and wire into DetailPanel
- Remove placeholder fallback from DetailPanel (all types now covered)
- Delete unused files: useBreakpoint.ts, profile.ts
- Remove unused legacy --pmr-* CSS variables (18 properties)
- Remove unused .pmr-theme CSS utility class
2026-02-14 03:20:31 +00:00
admin 071b1b78ae US-031: Responsive testing and fixes for all new components
SubNav: horizontal scroll with hidden scrollbar, 44px touch targets.
DetailPanel: close button enlarged to 44px. Touch target fixes on
CoreSkillsTile, ProjectsTile, and LastConsultationTile interactive elements.
2026-02-14 03:14:30 +00:00
admin 97d353930c US-030: Update CommandPalette for expanded content and panel actions 2026-02-14 03:08:54 +00:00
admin dbdd51243d US-029: Add post-login loading state and update TopBar session name 2026-02-14 03:04:16 +00:00
admin a8c7d5b41d US-028: Change login username to a.recruiter and add connection status indicator 2026-02-14 03:00:15 +00:00
admin 120d8a7a7b US-027: Restyle LoginScreen with teal accents 2026-02-14 02:56:33 +00:00
admin 4c92a3a559 US-026: Add hover and click interactions to CareerConstellation 2026-02-14 02:52:47 +00:00
admin 24e0f8963f US-025: Add accessibility to CareerConstellation 2026-02-14 02:49:14 +00:00
admin 6956ad001b US-024: Build D3 force-directed graph rendering in CareerConstellation 2026-02-14 02:46:00 +00:00
admin 75c03029bf US-023: Install D3 and scaffold CareerConstellation component 2026-02-14 02:41:50 +00:00
admin 2f8db26cc4 US-022: Create EducationDetail renderer for detail panel 2026-02-14 02:37:42 +00:00
admin a5deb0ea8b US-021: Create SkillsAllDetail renderer for detail panel 2026-02-14 02:34:26 +00:00
admin bbe17fc66a chore: update progress log and PRD for US-018, US-020 2026-02-14 02:31:30 +00:00
admin 9ec71ae0ed US-020: Create SkillDetail renderer for detail panel 2026-02-14 02:30:53 +00:00
admin 9d61d2c8ca powershell woes 2026-02-14 02:21:20 +00:00
admin fbfd25ffff US-018: Create ConsultationDetail renderer for detail panel
- Created ConsultationDetail.tsx component to render full role details
- Displays role title, organization, dates with current badge
- Renders history paragraph (consultation.history)
- Shows achievement bullets (consultation.examination)
- Displays outcomes/impact (consultation.plan)
- Renders coded entries as badges with code + description
- Wired into DetailPanel for both 'consultation' and 'career-role' types
- Styled consistently with dashboard design system
- Typecheck and build pass successfully

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-14 02:14:54 +00:00
admin f38e67252b US-017: Create KPIDetail renderer for detail panel
Created src/components/detail/KPIDetail.tsx that renders rich KPI story
content inside the detail panel. Wired into DetailPanel so content.type
=== 'kpi' renders this component.

Component displays:
- Large headline number (48px, colored by kpi.colorVariant)
- KPI label and subtitle
- Period badge (if story.period exists)
- Context paragraph (story.context)
- Your role paragraph (story.role)
- Key outcomes as bullet list (story.outcomes)

Graceful fallback implemented: if story is undefined, shows kpi.value
and kpi.explanation instead.

Styling matches dashboard design system with fonts (Elvaro Grotesque,
Geist Mono), colors (CSS custom properties), and spacing conventions.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-14 01:40:58 +00:00
admin 0c87d9f5a4 US-016: Modify PatientSummaryTile: structured presentation with highlight strip
- Added visual hierarchy to profile text using bold key phrases
- Key terms highlighted: Healthcare leader, Python/SQL/data analytics, leading population health analytics, financial scenario modelling, pharmaceutical rebate negotiation, algorithm design, population-level pathway development, £14.6M+, executive stakeholders
- Profile text no longer a wall of text - strategic bolding creates visual structure
- Removed unused personalStatement import
- Highlight strip with key stats already implemented (9+ Years, 1.2M, £220M, £14.6M+)
- Profile text sourced from CV_v4.md Profile section

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-14 01:32:54 +00:00
admin 8830c223aa US-016: Modify PatientSummaryTile: structured presentation with highlight strip
Add visual highlight strip showing key stats (9+ Years, 1.2M Population, £220M Budget, £14.6M+ Savings) above the profile text. Stats displayed as teal-colored badges with labels for improved visual hierarchy and scanability.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-14 01:27:10 +00:00
admin 52ee98d8aa US-015: Modify EducationTile: richer content, panel trigger
- Add OSCE score (80%) to MPharm inline details via educationExtras data
- Show research project with full description (Drug delivery & cocrystals, 75.1%)
- Display A-level grades as Mathematics (A*) · Chemistry (B) · Politics (C)
- Include Mary Seacole programme detail from educationExtras
- Import and use educationExtras data for dynamic inline content
- Add osceScore field to EducationExtra type
- Each entry clickable to open detail panel, hover border shift intact

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 00:33:44 +00:00
admin 03b4c6cafb US-015: Modify EducationTile: richer content, panel trigger
- Show richer inline content: MPharm research score (75.1%), Mary Seacole score (78%), A-level grades
- Each education entry is now clickable -> opens detail panel
- Hover state: border color shift to teal with shadow deepening
- Use documents data from documents.ts for accurate content
- Maintains existing visual hierarchy and spacing

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-13 23:59:54 +00:00
admin 9ed77f99a8 US-014: Modify CareerActivityTile: panel triggers and hover preview
- Replace in-place accordion expansion with detail panel triggers for role items
- Add hover preview showing lift effect, shadow deepens, and 1-2 lines preview text
- Integrate with DetailPanelContext to open career-role panels on click
- Keep color-coded dots and entry type styling (teal, amber, green, purple)
- Add placeholder container for CareerConstellation component (to be implemented later)
- Remove unused AnimatePresence, motion imports and accordion-related code
- Remove prefersReducedMotion and borderColorMap (no longer needed)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-13 23:57:55 +00:00
admin afc3876210 US-013: Add detail panel trigger to LastConsultationTile
- Import useDetailPanel hook and ChevronRight icon
- Make header info row clickable to open consultation detail panel
- Add "View full record" button at bottom of tile
- Both triggers call openPanel({ type: 'consultation', consultation })
- Add hover states to clickable areas
- Include keyboard navigation support (Enter/Space)
- Add aria-labels for accessibility

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-13 23:54:59 +00:00
admin c37fdab8fa US-012: Modify ProjectsTile: half width, compact card grid, panel trigger
- Remove full prop from Card (now half-width, single grid column)
- Replace accordion expansion with detail panel trigger
- Compact project cards with status dot + name + year (right-aligned)
- Tech stack shown as small inline tags (9px, monospace)
- Each project card clickable → openPanel({ type: 'project', investigation })
- Hover effects: border color shift to accent + shadow deepens
- Remove AnimatePresence and expansion state management
- Simplified component with focus on panel delegation

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-13 23:52:36 +00:00
admin 980297ea92 US-011: Redesign CoreSkillsTile with categorised groups and panel triggers
Full-width card with skills grouped by Technical, Healthcare Domain, and
Strategic & Leadership categories. Top 4 per category sorted by proficiency.
Individual skills open detail panel; categories with >4 skills show 'View all'
button triggering panel. Removed old single-expand accordion. Category headers
use sidebar section divider styling.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 23:50:19 +00:00
admin 8bdb162a07 US-010: Redesign KPI cards - remove flip, bigger numbers, panel trigger
- Removed flip card animation entirely (CSS classes .metric-card, .metric-card-inner, .metric-card-front, .metric-card-back)
- Redesigned KPI cards as clickable buttons with larger value font (28px, weight 700)
- Each KPI card now triggers detail panel on click via openPanel({ type: 'kpi', kpi })
- Added hover states: border color shift + shadow deepens (150ms transition)
- Keyboard accessible: Enter/Space keys open panel
- Card styling: 16px padding, white background, border with var(--border-light), border-radius var(--radius-sm)
- Sub-text uses Geist Mono font family
- Cleaned up unused flip animation CSS from index.css

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-13 23:19:36 +00:00
admin 2886685573 US-009: Create constellation data mapping file
- Create src/data/constellation.ts with role-skill mapping for D3 career graph
- Export RoleSkillMapping interface defining roleId and skillIds structure
- Map 6 career roles to their associated skill IDs from skills.ts
- Export constellationNodes array (5 role nodes + 21 skill nodes) with organization, startYear, endYear, orgColor for roles and domain for skills
- Export constellationLinks array connecting skills to roles with strength values (0-1)
- Role orgColors: Tesco (#00897B), NHS (#005EB8) for distinct visual grouping
- All role IDs match consultation IDs from consultations.ts

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-13 23:17:20 +00:00
admin b18746ecee US-008: Restructure DashboardLayout with SubNav, new tile order, and DetailPanel
- Wrap DashboardLayout with DetailPanelProvider in App.tsx
- Import and render DetailPanel component alongside CommandPalette
- Reorder tiles: PatientSummary (full) → LatestResults (half) + Projects (half) → CoreSkills (full) → LastConsultation (full) → CareerActivity (full) → Education (full)
- Update ProjectsTile from full-width to half-width (remove full prop)
- Update CoreSkillsTile from half-width to full-width (add full prop)
- SubNav already renders between TopBar and content
- Content area marginTop already accounts for both TopBar and SubNav heights
- All tiles already have data-tile-id attributes for SubNav scrolling

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-13 23:14:58 +00:00
admin 6c26518806 US-007: Create education extras data file
Add educationExtras.ts with expanded detail for education entries:
- MPharm: extracurriculars and research description from CV
- Mary Seacole: programme detail about leadership qualification

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-13 23:11:47 +00:00
admin f4a6b5e32c US-006: Add KPI story data and update 4th KPI to Population Served
- Change 4th KPI from 'Team Size Led' to 'Population Served' (1.2M)
- Add story field to all 4 KPIs with context, role, outcomes, and period
- £220M story: ICB prescribing budget oversight with forecasting models
- £14.6M story: Efficiency programme identification through data analysis
- 9+ Years story: Career progression from community pharmacy to system leadership
- 1.2M story: Population health analytics for Norfolk & Waveney ICS
- All story content sourced from References/CV_v4.md

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-13 23:10:14 +00:00
admin 92502beb03 US-005: Expand skills data from 5 to 21 with three categories
- Technical category (8 skills): Data Analysis, Python, SQL, Power BI,
  JavaScript/TypeScript, Excel, Algorithm Design, Data Pipelines
- Healthcare Domain category (6 skills): Medicines Optimisation,
  Population Health, NICE TA Implementation, Health Economics, Clinical
  Pathways, Controlled Drugs
- Strategic & Leadership category (7 skills): Budget Management,
  Stakeholder Engagement, Pharmaceutical Negotiation, Team Development,
  Change Management, Financial Modelling, Executive Communication
- All skills sourced from CV_v4.md Core Competencies
- Each skill includes medication metaphor properties: frequency,
  startYear, yearsOfExperience, proficiency, category, status, icon
- Frequency and proficiency values reflect realistic usage patterns from
  CV role descriptions

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-13 23:08:04 +00:00
admin a596b5ac82 US-004: Create SubNav component and useActiveSection hook
- Create SubNav component with sticky positioning below TopBar
- 5 sections: Overview, Skills, Experience, Projects, Education
- Active tab indicated with teal underline and 200ms slide transition
- Click scrolls smoothly to corresponding tile via data-tile-id
- Create useActiveSection hook using IntersectionObserver
- Maps tile IDs to section IDs for navigation
- Integrate SubNav into DashboardLayout with adjusted margins
- All styles follow design system (--accent, --surface, --border-light)
- TypeScript strict typing throughout

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-13 23:05:56 +00:00
admin cf5399a767 US-003: Create DetailPanelContext, DetailPanel component, and useFocusTrap hook
Implements core detail panel infrastructure for slide-in content panels:

- DetailPanelContext: Manages panel state (content, open/close, isOpen)
- DetailPanel: Slide-in panel component with backdrop, header, and scrollable body
- useFocusTrap: Keyboard focus trap hook for modal accessibility
- Width mapping: narrow (400px) for kpi/skill/education, wide (60vw) for consultation/project/career-role
- Title mapping derives from content data (kpi.label, skill.name, etc.)
- Close triggers: backdrop click, Escape key, X button
- ARIA: aria-modal, role=dialog, aria-labelledby
- Mobile responsive: both widths become 100vw on <768px
- prefers-reduced-motion: instant appear, no animations
- Placeholder content (real renderers in later stories)
- Export CardHeaderProps interface from Card.tsx
- Add responsive panel width CSS rules

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-13 23:02:59 +00:00
admin f7e9c88762 US-002: Add TypeScript types and CSS custom properties for depth features
Add foundation types and styles for upcoming depth enhancements:

TypeScript types (src/types/pmr.ts):
- SkillCategory type for grouping skills
- KPIStory interface for rich KPI detail content
- story? field added to KPI interface
- ConstellationNode and ConstellationLink for D3 career graph
- DetailPanelContent discriminated union for panel routing
- EducationExtra interface for expanded education detail

CSS custom properties (src/index.css):
- --subnav-height: 36px (section jump bar)
- --panel-narrow: 400px, --panel-wide: 60vw (detail panel widths)
- --backdrop-blur: 4px, --backdrop-bg (panel overlay)
- @keyframes panel-slide-in, panel-slide-out, backdrop-fade-in
- prefers-reduced-motion overrides for instant panel animations

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-13 22:59:26 +00:00
admin ee73efce11 US-001: Remove unused legacy components and hooks
Delete 23 dead files: old portfolio components (Contact, Education,
Experience, FloatingNav, Footer, Hero, Projects, Skills), legacy PMR
components (PMRInterface, PatientBanner, ClinicalSidebar, Breadcrumb,
MobileBottomNav), all 7 views/ directory files, and 3 unused hooks
(useScrollCondensation, useActiveSection, useScrollReveal).

No imports referenced any of these files — clean removal with zero
build or type errors.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 22:57:28 +00:00
admin 72c75fd1a9 Depth workflow 2026-02-13 21:45:53 +00:00
admin 7c31ec07ba Update progress: Task 20 completed (accessibility audit) 2026-02-13 18:05:58 +00:00
admin 6a4fc86387 Task 20: Accessibility audit improvements
Semantic HTML:
- Changed Card component from div to article element
- Added id="main-content" to main element for skip link target

Keyboard Navigation & ARIA:
- Added skip link to TopBar (visible only on focus, navigates to #main-content)
- Added aria-label="Active session information" to session info container
- Added aria-hidden="true" to all decorative colored dots (CardHeader, CareerActivity, Projects, Sidebar status badge)
- All expandable items already have role="button", tabIndex={0}, aria-expanded
- All KPI cards already have proper aria-label describing flip state
- Command palette already has full ARIA implementation (combobox, listbox, dialog)

Focus Management:
- Added global focus-visible styles in index.css (2px accent outline, 2px offset)
- Buttons, links, inputs all have proper focus rings with accent color
- Command palette focus trap already implemented

Reduced Motion:
- All components already check prefers-reduced-motion at module scope
- Dashboard entrance, tile expansion, KPI flip, palette animations respect reduced motion
- Added reduced motion override for pulse animation (disables pulse, keeps static dot)

Color Contrast:
- All color tokens already meet WCAG AA standards per ref spec
- Tertiary text (#8DA8A5) used only for supplementary labels where information is conveyed elsewhere

Quality checks: typecheck ✓, lint ✓ (1 pre-existing warning), build ✓
2026-02-13 18:04:52 +00:00
admin 8dc27ff8a9 Update progress: Task 19 completed (responsive design) 2026-02-13 18:01:21 +00:00
admin 29956665ac Task 19: Add responsive design for mobile and tablet
- DashboardLayout: Hide sidebar on <lg (1024px), responsive padding
- Dashboard grid: Mobile-first (1 col → 2 col at md/768px)
- Activity grid: Mobile-first (1 col → 2 col at md/768px)
- TopBar: Truncate brand text on mobile, hide 'Remote' on <md
- TopBar session: Show time-only on <xs (480px)
- CommandPalette: Full-width on mobile with reduced padding
- CommandPalette footer: Hidden on mobile
- Touch targets: All interactive elements 48px+ on mobile

All breakpoints follow Tailwind responsive prefixes (xs/sm/md/lg/xl).
Quality checks: typecheck ✓, lint ✓ (1 pre-existing warning), build ✓

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-13 18:00:16 +00:00
admin f65bf2ef5c Update progress: Task 18 completed (command palette)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 17:55:57 +00:00
admin aafdeba93e Task 18: Add command palette (Ctrl+K)
- Create CommandPalette.tsx with overlay, search input, grouped results,
  keyboard navigation (arrows, Enter, Escape), and footer hints
- Rebuild search.ts with PaletteItem model: 24 entries across 6 sections
  (Experience, Core Skills, Active Projects, Achievements, Education,
  Quick Actions) matching concept HTML structure
- Fuzzy search via fuse.js with weighted keys (title, subtitle, keywords)
- Wire into DashboardLayout with global Ctrl+K listener and TopBar click
- Action system: scroll-to-tile, expand-item, external links, download CV
- Add data-tile-id to all Card/tile components for scroll targeting
- CSS animations: palette-overlay-in, palette-modal-in with
  prefers-reduced-motion support
- Maintain backward-compatible legacy exports for ClinicalSidebar
  (will be removed in Task 21)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 17:54:31 +00:00
admin acee97a579 Update progress: Task 17 completed (KPI flip cards)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 17:46:26 +00:00
admin 38b8e36fab Task 17: Add KPI flip card interaction
Add click-to-flip interaction on LatestResults metric cards:
- CSS perspective-based 3D flip (400ms ease-in-out)
- Front face shows value/label/sub, back shows explanation text
- Single-card accordion: only one card flipped at a time
- Keyboard accessible: Enter/Space to flip, aria-label with state
- prefers-reduced-motion: instant visibility swap, no 3D animation
- Back face: accent-light background, 12px secondary text

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 17:45:59 +00:00
admin 3ad368f935 Update progress: Task 16 completed (tile expansion system)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 17:43:09 +00:00
admin d89ae0c64a Task 16: Add tile expansion system
CareerActivity: role items expand to show consultation achievements + coded entries
Projects: items expand to show methodology, tech stack tags, results, external links
CoreSkills: items expand to show prescribing history timeline from medications data

All expansions use:
- Framer Motion AnimatePresence with height-only animation (200ms, ease-out)
- Single-expand accordion (one item at a time per tile)
- Keyboard support (Enter/Space toggle, Escape collapse)
- aria-expanded attributes
- Colored left border on expanded panels
- prefers-reduced-motion support (instant expand/collapse)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 17:42:21 +00:00
admin 7dae67d954 Update progress: Task 15 completed (ProjectsTile)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 17:38:07 +00:00
admin 334ea2c02f Task 15: Build ProjectsTile
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 17:37:37 +00:00
admin 2c360176c8 Update progress: Task 14 completed (EducationTile)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-13 17:35:24 +00:00
admin 4be1b10137 Task 14: Build EducationTile
- Created EducationTile.tsx with purple CardHeader
- Displays three education entries in vertical stack
- MPharm (Hons) from UEA, NHS Leadership Academy Mary Seacole, A-Levels
- White surface background with light border and 6px radius
- Simple display-only format (no expansion yet)
- Updated DashboardLayout to render EducationTile below CareerActivity

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-13 17:34:26 +00:00
admin 905b3d957a Update progress: Task 13 completed (CareerActivity tile) 2026-02-13 17:32:14 +00:00
admin c8032f80df Task 13: Build CareerActivity tile
Created CareerActivityTile component with full timeline merged from multiple data sources:
- Builds 10 activity entries matching the concept HTML spec exactly
- Color-coded dots by type: role (teal), project (amber), cert (green), edu (purple)
- Two-column responsive grid (1 column below 900px)
- Entry types: 4 roles, 2 projects, 3 certifications, 1 education
- Data sources: consultations, investigations, documents
- Sorted newest-first with stable ordering for same-year entries
- Added .activity-grid responsive CSS class to index.css
- Wired into DashboardLayout below LastConsultationTile

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-13 17:31:14 +00:00
admin e2409183f3 Update progress: Task 12 completed (LastConsultation tile) 2026-02-13 17:28:16 +00:00
admin d0df9137f9 Task 12: Build LastConsultation tile
Created LastConsultationTile.tsx displaying the most recent role:
- Full-width card with green dot header
- Info row: Date, Organisation, Type (employment), Band
- Role title in accent color
- Bullet list of key achievements from examination array
- Data sourced from consultations[0] (most recent)
- Styling matches ref-06 spec: 8px card radius, border-light,
  info labels 10px uppercase, values 11.5px 600 weight
- Integrated into DashboardLayout in proper sequence

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-13 17:27:28 +00:00
admin dec8ec9769 Update progress: Task 11 completed (CoreSkills tile) 2026-02-13 17:25:00 +00:00
admin 6d47f2a948 Task 11: Build CoreSkills tile ("Repeat Medications")
Created CoreSkillsTile component that presents skills as medications
with frequency dosing metaphor:
- Half-width card with amber dot header "REPEAT MEDICATIONS"
- 5 skill items with teal icon containers (lucide-react icons)
- Each item shows: skill name, frequency (e.g., "Twice daily"),
  start year, years of experience, and "Active" status badge
- Uses medication metaphor: "Data Analysis · Twice daily · Since
  2016 · 9 yrs"
- Data from src/data/skills.ts with user-specified frequencies
- Styled to match GP System concept with 6px radius items on
  dashboard background (#F0F5F4)
- Integrated into DashboardLayout in right column next to
  LatestResultsTile

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-13 17:24:26 +00:00
admin 5ad67a512f Update progress: Task 10 completed (LatestResults tile)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 17:22:01 +00:00
admin 040e46cbea Task 10: Build LatestResults tile
- Created LatestResultsTile with 2x2 metric grid displaying four KPIs
- Each MetricCard shows value (22px, colored by variant), label, and sub text
- Metric cards use 6px radius, border-light, dashboard background
- Data sourced from src/data/kpis.ts (Budget £220M, Savings £14.6M, Years 9+, Team 12)
- CardHeader with teal dot + "LATEST RESULTS" + "Updated May 2025" right text
- Added data-kpi-id attributes for Task 17 flip card interaction
- Wired into DashboardLayout as half-width tile (left column)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 17:21:32 +00:00
admin 6501439cef Update progress: Task 9 completed (PatientSummary tile) 2026-02-13 17:19:17 +00:00
admin 41ddbf6d1d Task 9: Build PatientSummary tile
Created PatientSummaryTile component displaying personal statement from profile.ts.
Full-width card with teal dot header, 13px body text, line-height 1.6.
Wired into DashboardLayout as first tile in grid.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-13 17:18:53 +00:00
admin 00a5dd0105 Update progress: Task 8 completed (Card component) 2026-02-13 17:17:02 +00:00
admin 69e322af28 Task 8: Build reusable Card component with CardHeader
- Create Card component with base styling (white bg, 8px radius, shadow-sm)
- Hover state: deepens shadow to shadow-md, strengthens border
- Full-width variant spans both grid columns
- CardHeader sub-component with colored dot, title, optional right text
- Dot colors: teal, amber, green, alert, purple
- Header styling: 12px uppercase title, 10px mono right text
- All styles use CSS custom properties from design tokens
2026-02-13 17:16:06 +00:00
admin a2e01270a1 Update progress: Task 7 completed (DashboardLayout)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 17:14:23 +00:00
admin adc32b9005 Task 7: Build DashboardLayout and wire up App.tsx
Three-zone layout: TopBar (fixed) + Sidebar (fixed left) + Main
(scrollable card grid). Framer Motion staggered entrance animations
with prefers-reduced-motion support. Card grid responsive at 900px.
Replaces PMRInterface in the pmr phase.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 17:14:18 +00:00
admin a60b0701c2 Update progress: Tasks 5-6 completed (Sidebar component) 2026-02-13 17:10:32 +00:00
admin 670c9cc74c Tasks 5-6: Build Sidebar with PersonHeader, Tags, and Alerts
- Created src/components/Sidebar.tsx:
  - PersonHeader section with 52px avatar, name, title, status badge with pulse animation
  - Details grid: GPhC No. (monospace), Education, Location, Phone (link), Email (link), Registered
  - Tags section with colored pill badges (teal/amber/green variants)
  - Alerts/Highlights section with severity-based styling (alert/amber)
  - Section title component with divider line
  - Custom scrollbar styling (4px, transparent track, border-colored thumb)

- Added animations to src/index.css:
  - @keyframes pulse for status badge dot (opacity 1→0.4→1, 2s infinite)
  - .pmr-scrollbar custom scrollbar styles

Data sources: patient.ts, tags.ts, alerts.ts

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-13 17:09:56 +00:00
admin 37c08387af Update progress: Task 4 completed (TopBar component)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 17:07:26 +00:00
admin 62b6718cc3 Task 4: Build TopBar component
Fixed 48px header with three zones — brand (Home icon + name + version),
center search bar (button triggering command palette), and session info
(doctor name + active session pill with live time). Uses GP System
Dashboard tokens. Responsive: search bar hidden on mobile.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 17:07:22 +00:00
admin 2e48cefc6f Update progress: Task 2 completed (data files and types) 2026-02-13 17:04:18 +00:00
admin 2b9a6210ec Task 2: Create new data files and update types
Created five new data files for GP System Dashboard:
- src/data/profile.ts: Personal statement from CV_v4.md
- src/data/tags.ts: Sidebar tags (5 entries with color variants)
- src/data/alerts.ts: Sidebar alert flags (2 entries)
- src/data/kpis.ts: Latest Results metrics (4 KPI entries with explanations)
- src/data/skills.ts: Core technical skills as "medications" (5 entries with user-specified frequencies)

Updated src/types/pmr.ts with new interfaces:
- Tag: label + colorVariant
- Alert: message + severity + icon
- KPI: id + value + label + sub + colorVariant + explanation
- SkillMedication: full medication structure with frequency, years, proficiency, category, status, icon

All CV content matches References/CV_v4.md exactly. All quality checks pass.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-13 17:03:45 +00:00
admin c88ceba136 Update progress: Task 1 completed (design tokens)
Also includes manual intervention files: updated CLAUDE.md,
IMPLEMENTATION_PLAN.md, and ref files for GP System Dashboard redesign.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 17:01:29 +00:00
admin 3176761d9c Task 1: Update design tokens for GP System Dashboard
- Replace old dark PMR palette with light teal GP System tokens
- Add three-tier shadow system (sm/md/lg) with warm green-gray tints
- Update border-radius: cards now 8px, inner elements 6px
- Add layout vars (sidebar-width 272px, topbar-height 48px)
- Fix font-ui/font-ui-alt swap: Elvaro Grotesque is now primary
- Add status color tokens (success, amber, alert, purple) with light/border variants
- Keep legacy --pmr-* aliases for backward compat during transition
- Update pmr Tailwind colors to new palette values

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 17:00:44 +00:00
280 changed files with 71496 additions and 39546 deletions
@@ -1,111 +0,0 @@
# Accessibility Essentials
Accessibility enables creativity - it's a foundation, not a limitation. WCAG 2.1 AA compliance.
## Core Principles (POUR)
- **Perceivable**: Content must be perceivable (alt text, contrast, captions)
- **Operable**: UI must be keyboard/touch accessible
- **Understandable**: Clear, predictable behavior
- **Robust**: Works with assistive technologies
## Contrast Requirements
| Element | Minimum Ratio |
|---------|---------------|
| Normal text | 4.5:1 |
| Large text (18pt+) | 3:1 |
| UI components | 3:1 |
**Tools**: Chrome DevTools Accessibility tab, WebAIM Contrast Checker
## Keyboard Navigation
```tsx
// All interactive elements need focus states
<button className="focus:ring-4 focus:ring-blue-500 focus:outline-none">
Accessible
</button>
// Custom elements need tabindex and key handlers
<div
role="button"
tabIndex={0}
onKeyDown={(e) => (e.key === 'Enter' || e.key === ' ') && handleClick()}
>
Custom Button
</div>
```
**Essentials:**
- Tab through entire interface
- Enter/Space activates elements
- Escape closes modals
- Visible focus indicators always
## Essential ARIA
```tsx
// Buttons without text
<button aria-label="Close dialog"><X /></button>
// Expandable elements
<button aria-expanded={isOpen} aria-controls="menu">Menu</button>
// Live regions for dynamic content
<div role="status" aria-live="polite">{statusMessage}</div>
<div role="alert" aria-live="assertive">{errorMessage}</div>
// Form errors
<input aria-invalid={hasError} aria-describedby="error-msg" />
{hasError && <p id="error-msg" role="alert">Error text</p>}
```
## Semantic HTML
```tsx
// Use semantic elements, not divs
<header><nav>...</nav></header>
<main><article><h1>...</h1></article></main>
<footer>...</footer>
// Heading hierarchy (never skip levels)
<h1>Page Title</h1>
<h2>Section</h2>
<h3>Subsection</h3>
```
## Touch Targets
- Minimum **44x44px** for all interactive elements
- Adequate spacing between targets
- `touch-manipulation` CSS for responsive touch
## Screen Reader Content
```tsx
// Hidden but announced
<span className="sr-only">Additional context</span>
// Skip link
<a href="#main" className="sr-only focus:not-sr-only">
Skip to main content
</a>
```
## Quick Checklist
- [ ] Keyboard: Can tab through everything
- [ ] Focus: Visible focus indicators
- [ ] Contrast: 4.5:1 for text
- [ ] Alt text: All images have appropriate alt
- [ ] Headings: Logical h1-h6 hierarchy
- [ ] Forms: Labels associated with inputs
- [ ] Errors: Announced to screen readers
- [ ] Touch: 44px minimum targets
## Resources
- [WCAG 2.1 Quick Reference](https://www.w3.org/WAI/WCAG21/quickref/)
- [WebAIM Contrast Checker](https://webaim.org/resources/contrastchecker/)
- [ARIA Authoring Practices](https://www.w3.org/WAI/ARIA/apg/)
@@ -1,577 +0,0 @@
# Design System Template
Meta-framework for understanding what's fixed, project-specific, and adaptable in your design system.
## Purpose
This template helps you distinguish between:
- **Fixed Elements**: Universal rules that never change
- **Project-Specific Elements**: Filled in for each project based on brand
- **Adaptable Elements**: Context-dependent implementations
---
## I. FIXED ELEMENTS
These foundations remain consistent across all projects, regardless of brand or context.
### 1. Spacing Scale
**Fixed System:**
```
4px, 8px, 12px, 16px, 24px, 32px, 48px, 64px, 96px
```
**Usage:**
- Margins, padding, gaps between elements
- Mathematical relationships ensure visual harmony
- Use multipliers of base unit (4px)
**Why Fixed:**
Consistent spacing creates visual rhythm regardless of brand personality.
### 2. Grid System
**Fixed Structure:**
- **12-column grid** for most layouts (divisible by 2, 3, 4, 6)
- **16-column grid** for data-heavy interfaces
- **Gutters**: 16px (mobile), 24px (tablet), 32px (desktop)
**Why Fixed:**
Grid provides structural order. Brand personality shows through color, typography, content—not grid structure.
### 3. Accessibility Standards
**Fixed Requirements:**
- **WCAG 2.1 AA** compliance minimum
- **Contrast**: 4.5:1 for normal text, 3:1 for large text
- **Touch targets**: Minimum 44×44px
- **Keyboard navigation**: All interactive elements accessible
- **Screen reader**: Semantic HTML, ARIA labels where needed
**Why Fixed:**
Accessibility is not negotiable. It's a baseline requirement for ethical, legal, and usable products.
### 4. Typography Hierarchy Logic
**Fixed Structure:**
- **Mathematical scaling**: 1.25x (major third) or 1.333x (perfect fourth)
- **Hierarchy levels**: Display → H1 → H2 → H3 → Body → Small → Caption
- **Line height**: 1.5x for body text, 1.2-1.3x for headlines
- **Line length**: 45-75 characters optimal
**Why Fixed:**
Mathematical relationships create predictable, harmonious hierarchy. Specific fonts change, but the logic doesn't.
### 5. Component Architecture
**Fixed Patterns:**
- **Button states**: Default, Hover, Active, Focus, Disabled
- **Form structure**: Label above input, error below, helper text optional
- **Modal pattern**: Overlay + centered content + close mechanism
- **Card structure**: Container → Header → Body → Footer (optional)
**Why Fixed:**
Users expect consistent component behavior. Architecture is fixed; appearance is project-specific.
### 6. Animation Timing Framework
**Fixed Physics Profiles:**
- **Lightweight** (icons, chips): 150ms
- **Standard** (cards, panels): 300ms
- **Weighty** (modals, pages): 500ms
**Fixed Easing:**
- **Ease-out**: Entrances (fast start, slow end)
- **Ease-in**: Exits (slow start, fast end)
- **Ease-in-out**: Transitions (smooth both ends)
**Why Fixed:**
Natural physics feel consistent across brands. Duration and easing create that feeling.
---
## II. PROJECT-SPECIFIC ELEMENTS
Fill in these for each project based on brand personality and purpose.
### 1. Brand Color System
**Template Structure:**
```
NEUTRALS (4-5 colors):
- Background lightest: _______ (e.g., slate-50 or warm-white)
- Surface: _______ (e.g., slate-100)
- Border/divider: _______ (e.g., slate-300)
- Text secondary: _______ (e.g., slate-600)
- Text primary: _______ (e.g., slate-900)
ACCENTS (1-3 colors):
- Primary (main CTA): _______ (e.g., teal-500)
- Secondary (alternative action): _______ (optional)
- Status colors:
- Success: _______ (green-ish)
- Warning: _______ (amber-ish)
- Error: _______ (red-ish)
- Info: _______ (blue-ish)
```
**Questions to Answer:**
- What emotion should the brand evoke? (Trust, excitement, calm, urgency)
- Warm or cool neutrals?
- Conservative or bold accents?
**Examples:**
**Project A: Fintech App**
```
Neutrals: Cool greys (slate-50 → slate-900)
Primary: Deep blue (#0A2463) trust, professionalism
Success: Muted green (#10B981)
Why: Financial products need trust, not playfulness
```
**Project B: Creative Community**
```
Neutrals: Warm greys with beige undertones
Primary: Coral (#FF6B6B) energy, creativity
Success: Teal (#06D6A0) fresh, unexpected
Why: Creative spaces should feel inviting, not corporate
```
**Project C: Healthcare Platform**
```
Neutrals: Pure greys (minimal color temperature)
Primary: Soft blue (#4A90E2) calm, clinical
Success: Medical green (#38A169)
Why: Healthcare needs clarity and calm, not distraction
```
### 2. Typography Pairing
**Template:**
```
HEADLINE FONT: _______
- Weight: _______ (e.g., Bold 700)
- Use case: H1, H2, display text
- Personality: _______ (geometric/humanist/serif/etc.)
BODY FONT: _______
- Weight: _______ (e.g., Regular 400, Medium 500)
- Use case: Paragraphs, UI text
- Personality: _______ (neutral/readable/efficient)
OPTIONAL ACCENT FONT: _______
- Weight: _______
- Use case: _______ (special headlines, callouts)
```
**Pairing Logic:**
- Serif + Sans-serif (classic, editorial)
- Geometric + Humanist (modern + warm)
- Display + System (distinctive + efficient)
**Examples:**
**Project A: Editorial Platform**
```
Headline: Playfair Display (Serif, Bold 700)
Body: Inter (Sans-serif, Regular 400)
Why: Serif headlines = trustworthy, editorial feel
```
**Project B: Tech Startup**
```
Headline: DM Sans (Sans-serif, Bold 700)
Body: DM Sans (Regular 400, Medium 500)
Why: Single-font system = modern, efficient, cohesive
```
**Project C: Luxury Brand**
```
Headline: Cormorant Garamond (Serif, Light 300)
Body: Lato (Sans-serif, Regular 400)
Why: Elegant serif + readable sans = sophisticated
```
### 3. Tone of Voice
**Template:**
```
BRAND PERSONALITY:
- Formal ↔ Casual: _______ (1-10 scale)
- Professional ↔ Friendly: _______ (1-10 scale)
- Serious ↔ Playful: _______ (1-10 scale)
- Authoritative ↔ Conversational: _______ (1-10 scale)
MICROCOPY EXAMPLES:
- Button label (submit form): _______
- Error message (invalid email): _______
- Success message (saved): _______
- Empty state: _______
ANIMATION PERSONALITY:
- Speed: _______ (quick/moderate/slow)
- Feel: _______ (precise/smooth/bouncy)
```
**Examples:**
**Project A: Banking App**
```
Personality: Formal (8), Professional (9), Serious (8)
Button: "Submit Application"
Error: "Email address format is invalid"
Success: "Application submitted successfully"
Animation: Quick (precise, efficient, no-nonsense)
```
**Project B: Social App**
```
Personality: Casual (8), Friendly (9), Playful (7)
Button: "Let's go!"
Error: "Hmm, that email doesn't look right"
Success: "Nice! You're all set 🎉"
Animation: Moderate (smooth, friendly bounce)
```
### 4. Animation Speed & Feel
**Template:**
```
SPEED PREFERENCE:
- UI interactions: _______ (100-150ms / 150-200ms / 200-300ms)
- State changes: _______ (200ms / 300ms / 400ms)
- Page transitions: _______ (300ms / 500ms / 700ms)
ANIMATION STYLE:
- Easing preference: _______ (sharp / standard / bouncy)
- Movement type: _______ (minimal / smooth / expressive)
```
**Examples:**
**Project A: Trading Platform**
```
Speed: Fast (100ms UI, 200ms states, 300ms pages)
Style: Sharp easing, minimal movement
Why: Traders need speed, not distraction
```
**Project B: Wellness App**
```
Speed: Slow (200ms UI, 400ms states, 500ms pages)
Style: Smooth easing, gentle movement
Why: Calm, relaxing experience matches brand
```
---
## III. ADAPTABLE ELEMENTS
Context-dependent implementations that vary based on use case.
### 1. Component Variations
**Button Variants:**
- **Primary**: Full background color (high emphasis)
- **Secondary**: Outline only (medium emphasis)
- **Tertiary**: Text only (low emphasis)
- **Destructive**: Red-ish (danger actions)
- **Ghost**: Minimal (navigation, toolbars)
**Adaptation Rules:**
- Primary: Main CTA, one per screen section
- Secondary: Alternative actions
- Tertiary: Less important actions, multiple allowed
- Use brand colors, but hierarchy logic is fixed
### 2. Responsive Breakpoints
**Fixed Ranges:**
- XS: 0-479px (small phones)
- SM: 480-767px (large phones)
- MD: 768-1023px (tablets)
- LG: 1024-1439px (laptops)
- XL: 1440px+ (desktop)
**Adaptable Implementations:**
**Simple Content Site:**
```
XS-SM: Single column
MD: 2 columns
LG-XL: 3 columns max
Why: Content-focused, don't overwhelm
```
**Dashboard/Data App:**
```
XS: Collapsed, cards stack
SM: Simplified sidebar
MD: Full sidebar + main content
LG-XL: Sidebar + main + right panel
Why: Data apps need more screen real estate
```
### 3. Dark Mode Palette
**Adaptation Strategy:**
Not a simple inversion. Dark mode needs adjusted contrast:
**Light Mode:**
```
Background: #FFFFFF (white)
Text: #0F172A (slate-900) → 21:1 contrast
```
**Dark Mode (Adapted):**
```
Background: #0F172A (slate-900)
Text: #E2E8F0 (slate-200) → 15.8:1 contrast (still AA, but softer)
```
**Why Adapt:**
Pure white on pure black is too harsh. Dark mode needs slightly lower contrast for eye comfort.
### 4. Loading States
**Context-Dependent:**
**Fast operations (<500ms):**
- No loading indicator (feels instant)
**Medium operations (500ms-2s):**
- Spinner or skeleton screen
**Long operations (>2s):**
- Progress bar with percentage
- Or: Skeleton + estimated time
**Interactive Operations:**
- Button shows spinner inside (don't disable, show state)
### 5. Error Handling Strategy
**Context-Dependent:**
**Form Errors:**
```
Validate: On blur (after user leaves field)
Display: Inline below field
Recovery: Clear error on fix
```
**API Errors:**
```
Transient (network): Show retry button
Permanent (404): Show helpful message + next steps
Critical (500): Contact support option
```
**Data Errors:**
```
Missing: Show empty state with action
Corrupt: Show error boundary with reload
Invalid: Highlight + explain what's wrong
```
---
## DECISION TREE
When implementing a feature, ask:
### Is this...
**FIXED?**
- Does it affect structure, accessibility, or universal UX?
- Examples: Spacing scale, grid, contrast ratios, component architecture
- **Action**: Use the fixed system, no variation
**PROJECT-SPECIFIC?**
- Does it express brand personality or purpose?
- Examples: Colors, typography, tone of voice, animation feel
- **Action**: Fill in the template for this project
**ADAPTABLE?**
- Does it depend on context, content, or use case?
- Examples: Component variants, responsive behavior, error handling
- **Action**: Choose appropriate variation based on context
---
## EXAMPLE: Implementing a "Submit" Button
### Fixed Elements (Always the same):
- Touch target: 44px minimum height
- Padding: 16px horizontal (from spacing scale)
- States: Default, Hover, Active, Focus, Disabled
- Animation: 150ms ease-out (lightweight profile)
### Project-Specific (Filled per project):
- **Project A (Bank)**: Dark blue background, white text, "Submit Application"
- **Project B (Social)**: Coral background, white text, "Let's Go!"
- **Project C (Healthcare)**: Soft blue background, white text, "Continue"
### Adaptable (Context-dependent):
- **Form context**: Primary button (full color)
- **Toolbar context**: Ghost button (text only)
- **Danger context**: Destructive variant (red-ish)
---
## VALIDATION CHECKLIST
Before finalizing a design, check:
### Fixed Elements
- [ ] Uses spacing scale (4/8/12/16/24/32/48/64/96px)
- [ ] Follows grid system (12 or 16 columns)
- [ ] Meets WCAG AA contrast (4.5:1 normal, 3:1 large)
- [ ] Touch targets ≥ 44px
- [ ] Typography follows mathematical scale
- [ ] Components follow standard architecture
### Project-Specific Elements
- [ ] Brand colors filled in and intentional
- [ ] Typography pairing chosen and justified
- [ ] Tone of voice defined and consistent
- [ ] Animation speed matches brand personality
### Adaptable Elements
- [ ] Component variants appropriate for context
- [ ] Responsive behavior fits content type
- [ ] Loading states match operation duration
- [ ] Error handling fits error type
---
## PROJECT KICKOFF TEMPLATE
Use this to start a new project:
```
PROJECT NAME: _______________________
PURPOSE: ____________________________
BRAND PERSONALITY:
- Primary emotion: _______
- Warm or cool: _______
- Formal or casual: _______
- Conservative or bold: _______
COLORS (fill the template):
- Neutral base: _______
- Primary accent: _______
- Status colors: _______ / _______ / _______
TYPOGRAPHY (fill the template):
- Headline font: _______
- Body font: _______
- Pairing rationale: _______
TONE:
- Button labels style: _______
- Error message style: _______
- Success message style: _______
ANIMATION:
- Speed preference: _______ (fast/moderate/slow)
- Feel preference: _______ (sharp/smooth/bouncy)
TARGET DEVICES:
- Primary: _______ (mobile/desktop/both)
- Secondary: _______
```
---
## MAINTAINING CONSISTENCY
### Documentation
- Keep this template updated as system evolves
- Document WHY choices were made, not just WHAT
### Communication
- Share with designers: "Here's what varies vs. what's fixed"
- Share with developers: "Here are the design tokens"
### Tooling
- Use CSS variables for project-specific values
- Use Tailwind config for spacing scale
- Use design tokens in Figma/Storybook
### Reviews
- Audit: Does new work follow fixed elements?
- Validate: Are project-specific elements intentional?
- Question: Are adaptations justified by context?
---
## EXAMPLES OF COMPLETE SYSTEMS
### System A: B2B SaaS (Conservative)
**Fixed**: Standard spacing, 12-col grid, WCAG AA, major third type scale
**Project-Specific**:
- Colors: Cool greys + corporate blue
- Typography: DM Sans (headlines + body)
- Tone: Professional, formal
- Animation: Quick, precise (150ms)
**Adaptable**:
- Dashboard gets multi-panel layout
- Forms are extensive (use progressive disclosure)
- Errors show detailed technical info
### System B: Consumer Social App (Playful)
**Fixed**: Same spacing/grid/accessibility/type logic
**Project-Specific**:
- Colors: Warm greys + vibrant coral
- Typography: Poppins (headlines) + Inter (body)
- Tone: Casual, friendly, playful
- Animation: Moderate, bouncy (200ms)
**Adaptable**:
- Mobile-first (most users on phones)
- Forms are minimal (progressive profiling)
- Errors are friendly, not technical
### System C: Healthcare Platform (Clinical)
**Fixed**: Same foundational structure
**Project-Specific**:
- Colors: Pure greys + medical blue
- Typography: System fonts (SF Pro / Segoe)
- Tone: Clear, authoritative, calm
- Animation: Slow, smooth (300ms)
**Adaptable**:
- Desktop-first (clinical use at workstations)
- Forms are complex (HIPAA compliance)
- Errors are precise with next steps
---
## KEY TAKEAWAY
**The system flexibility framework lets you:**
- Maintain consistency (fixed elements)
- Express brand personality (project-specific)
- Adapt to context (adaptable elements)
**Without this framework:**
- Designers reinvent spacing every project
- Components feel inconsistent across products
- Brand personality overrides accessibility
- Context-blind implementations feel wrong
**With this framework:**
- Speed: Start from proven foundations
- Consistency: Fixed elements guarantee it
- Flexibility: Express unique brand identity
- Context: Adapt without breaking system
@@ -1,72 +0,0 @@
# Motion Specification
Motion should surprise and delight while serving function. Animation is a creative tool.
## Easing Curves
| Easing | CSS | Use For |
|--------|-----|---------|
| **Ease-out** | `cubic-bezier(0.0, 0.0, 0.2, 1)` | Entrances, appearing |
| **Ease-in** | `cubic-bezier(0.4, 0.0, 1, 1)` | Exits, disappearing |
| **Ease-in-out** | `cubic-bezier(0.4, 0.0, 0.2, 1)` | State changes, transforms |
| **Spring** | `cubic-bezier(0.68, -0.55, 0.265, 1.55)` | Playful, attention-grabbing |
| **Linear** | `linear` | Spinners, continuous loops |
## Duration by Element Weight
| Weight | Duration | Examples |
|--------|----------|----------|
| **Lightweight** | 150ms | Icons, badges, chips |
| **Standard** | 300ms | Cards, panels, list items |
| **Weighty** | 500ms | Modals, page transitions |
## Duration by Interaction
| Interaction | Duration |
|-------------|----------|
| Button press | 100ms |
| Hover state | 150ms |
| Tooltip appear | 200ms |
| Tab switch | 250ms |
| Modal open | 300ms |
| Page transition | 400ms |
## Common Patterns
```tsx
// Hover transition (CSS)
<button className="transition-colors duration-150 ease-out hover:bg-blue-700">
// Fade + slide (Framer Motion)
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.3, ease: "easeOut" }}
/>
// Stagger children
<motion.ul variants={{ visible: { transition: { staggerChildren: 0.1 } } }}>
<motion.li variants={{ hidden: { opacity: 0 }, visible: { opacity: 1 } }} />
</motion.ul>
```
## Performance Rules
- Only animate `transform` and `opacity` (GPU-accelerated)
- Avoid animating `width`, `height`, `margin`, `padding`
- Keep durations under 500ms for UI interactions
- Respect `prefers-reduced-motion`:
```css
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
transition-duration: 0.01ms !important;
}
}
```
## Resources
- [Framer Motion](https://www.framer.com/motion/)
- [CSS Easing Functions](https://easings.net/)
@@ -1,90 +0,0 @@
# Responsive Design Essentials
Mobile-first approach: start with mobile, progressively enhance for larger screens.
## Breakpoints
| Range | Pixels | Devices | Strategy |
|-------|--------|---------|----------|
| **XS** | 0-479px | Small phones | Single column, stacked nav, 44px touch targets |
| **SM** | 480-767px | Large phones | Single column, bottom nav, simplified UI |
| **MD** | 768-1023px | Tablets | 2 columns possible, sidebar nav |
| **LG** | 1024-1439px | Laptops | Multi-column, full nav, desktop UI |
| **XL** | 1440px+ | Desktop | Max-width containers, multi-panel layouts |
## Tailwind Responsive
```tsx
// Mobile-first: base styles, then scale up
<div className="
w-full // mobile: full width
sm:w-1/2 // 480px+: half
md:w-1/3 // 768px+: third
lg:w-1/4 // 1024px+: quarter
">
// Responsive grid
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6">
// Responsive typography
<h1 className="text-3xl md:text-4xl lg:text-5xl">
// Show/hide by breakpoint
<div className="block md:hidden">Mobile only</div>
<div className="hidden md:block">Desktop only</div>
```
## Fluid Typography
```css
h1 { font-size: clamp(2rem, 5vw, 4rem); }
p { font-size: clamp(1rem, 2.5vw, 1.25rem); }
```
## Touch Targets
- Minimum **44x44px** for all interactive elements
- Use `touch-manipulation` to prevent 300ms tap delay
- Adequate spacing between targets
```tsx
<button className="min-w-[44px] min-h-[44px] touch-manipulation">
```
## Mobile Simplification
| Desktop | Mobile |
|---------|--------|
| Full nav bar | Hamburger menu |
| Side-by-side fields | Stacked fields |
| Multi-column grid | Single column |
| Inline buttons | Fixed bottom bar |
| Data table | Collapsed cards |
| Visible sidebar | Hidden/collapsible |
## Images
```tsx
// Responsive images
<img
srcSet="image-400w.jpg 400w, image-800w.jpg 800w, image-1200w.jpg 1200w"
sizes="(max-width: 640px) 100vw, (max-width: 1024px) 50vw, 33vw"
loading="lazy"
/>
// Next.js
<Image src="/hero.jpg" width={1200} height={600} priority className="w-full h-auto" />
```
## Testing
Test at these widths:
- 375px (iPhone SE)
- 390px (iPhone 14)
- 768px (iPad)
- 1024px (iPad Pro)
- 1280px+ (Desktop)
## Resources
- [Tailwind Responsive](https://tailwindcss.com/docs/responsive-design)
@@ -1,718 +0,0 @@
---
name: bencium-innovative-ux-designer
description: Create distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
metadata:
version: 2.0.0
---
# Innovative UX Designer
Create distinctive, production-grade frontend interfaces that avoid generic "AI slop" aesthetics. Implement real working code with exceptional attention to aesthetic details and creative choices. Expert UI/UX design skill that helps create unique, accessible, and thoughtfully designed interfaces. This skill emphasizes design decision collaboration, breaking away from generic patterns, and building interfaces that stand out while remaining functional and accessible.
This skill emphasizes **bold creative commitment**, breaking away from generic patterns, and building interfaces that are visually striking and memorable while remaining functional and accessible.
## Core Philosophy
**CRITICAL: Design Thinking Protocol**
Before coding, **ASK to understand context**, then **COMMIT BOLDLY** to a distinctive direction:
### Questions to Ask First
1. **Purpose**: What problem does this interface solve? Who uses it?
2. **Tone**: What aesthetic extreme fits? (see Tone Options below)
3. **Constraints**: Technical requirements (framework, performance, accessibility)?
4. **Differentiation**: What makes this UNFORGETTABLE? What's the one thing someone will remember?
### Tone Options (Pick an Extreme)
Choose a clear aesthetic direction and execute with precision:
- **Brutally minimal** - stripped to essence, bold typography, vast whitespace
- **Maximalist chaos** - layered, dense, visually rich, controlled disorder
- **Retro-futuristic** - vintage meets sci-fi, nostalgic tech aesthetics
- **Organic/natural** - soft edges, earthy colors, nature-inspired textures
- **Luxury/refined** - elegant spacing, premium typography, subtle details
- **Playful/toy-like** - bright colors, rounded shapes, delightful interactions
- **Editorial/magazine** - strong typography hierarchy, asymmetric layouts
- **Brutalist/raw** - exposed structure, harsh contrasts, intentionally rough
- **Art deco/geometric** - bold patterns, metallic accents, symmetric elegance
- **Soft/pastel** - gentle gradients, muted tones, calming atmosphere
- **Industrial/utilitarian** - functional, no-nonsense, mechanical precision
### After Getting Context
- **Commit fully** to the chosen direction - no half measures
- Present 2-3 alternative approaches with trade-offs
- Then implement with precision: production-grade, visually striking, memorable
## Foundational Design Principles
### Stand Out From Generic Patterns
**NEVER Use These AI-Generated Aesthetics:**
- **Fonts**: Inter, Roboto, Arial, system fonts as primary choice, Space Grotesk (overused by AI)
- **Colors**: Generic SaaS blue (#3B82F6), purple gradients on white backgrounds
- **Patterns**: Cookie-cutter layouts, predictable component arrangements
- **Effects**: Glass morphism, Apple design mimicry, liquid/blob backgrounds
- **Overall**: Anything that looks "Claude-generated" or machine-made
**Instead, Create Atmosphere:**
- Suggest photography, patterns, textures over flat solid colors
- Apply gradient meshes, noise textures, geometric patterns
- Use layered transparencies, dramatic shadows, decorative borders
- Consider custom cursors, grain overlays, contextual effects
- Think beyond typical patterns - you can step off the written path
**Draw Inspiration From:**
- Modern landing pages (Perplexity, Comet Browser, Dia Browser)
- Framer templates and their innovative approaches
- Leading brand design studios
- Historical design movements (Bauhaus, Otl Aicher, Braun) - but as inspiration, not imitation
- Beautiful background animations (CSS, SVG) - slow, looping, subtle
**Visual Interest Strategies:**
- Unique color pairs that aren't typical
- Animation effects that feel fresh
- Background patterns that add depth without distraction
- Typography combinations that create contrast
- Visual assets that tell a story
### Core Design Philosophy
1. **Simplicity Through Reduction**
- Identify the essential purpose and eliminate distractions
- Begin with complexity, then deliberately remove until reaching the simplest effective solution
- Every element must justify its existence
2. **Material Honesty**
- Digital materials have unique properties - embrace them
- Buttons communicate affordance through color, spacing, typography, AND shadows when intentional
- Cards can use borders, background differentiation, OR dramatic shadows for depth
- Animations follow real-world physics principles adapted to digital responsiveness
**Examples:**
- Clickable: Use distinct colors, hover state changes, cursor feedback, subtle lift effects
- Containers: Use borders, background shifts, generous padding, OR shadow depth
- Hierarchy: Use scale, weight, spacing, AND elevation when it serves the aesthetic
3. **Functional Layering**
- Create hierarchy through typography scale, color contrast, and spatial relationships
- Layer information conceptually (primary → secondary → tertiary)
- Use shadows and gradients INTENTIONALLY when they serve the aesthetic direction
- Embrace functional depth: modals over content, dropdowns over UI
- Avoid: glass morphism, Apple mimicry (but shadows/gradients are tools, not enemies)
4. **Obsessive Detail**
- Consider every pixel, interaction, and transition
- Excellence emerges from hundreds of small, intentional decisions
- Balance: Details should serve simplicity, not complexity
- When detail conflicts with clarity, clarity wins
5. **Coherent Design Language**
- Every element should visually communicate its function
- Elements should feel part of a unified system
- Nothing should feel arbitrary
6. **Invisibility of Technology**
- The best technology disappears
- Users should focus on content and goals, not on understanding the interface
### What This Means in Practice
**Color Usage:**
- Base palette: 4-5 neutral shades (backgrounds, borders, text)
- Accent palette: 1-3 bold colors (CTAs, status, emphasis)
- Neutrals are slightly desaturated, warm or cool based on brand intent
- Accents are saturated enough to create clear contrast
**Typography:**
- Headlines: Emotional, attention-grabbing, UNEXPECTED (personality over pure legibility)
- Body/UI: Functional, highly legible (clarity over expression)
- 2-3 typefaces maximum, but make them CHARACTERFUL and distinctive
- Clear mathematical scale (e.g., 1.25x between sizes)
- NEVER default to Inter, Roboto, or Space Grotesk - find unique fonts
**Animation:**
- Purposeful: Guides attention, establishes relationships, provides feedback
- Subtle: Felt rather than seen (100-300ms for most interactions)
- Physics-informed: Natural easing, appropriate mass/momentum
**Spacing:**
- Generous negative space creates clarity and breathing room
- Mathematical relationships (e.g., 4px base, 8/16/24/32/48px scale)
- Consistent application creates visual rhythm
### Design Decision Checklist
Before presenting any design, verify:
1. **Purpose**: Does every element serve a clear function?
2. **Hierarchy**: Is visual importance aligned with content importance?
3. **Consistency**: Do similar elements look and behave similarly?
4. **Accessibility**: Does it meet WCAG AA standards? (contrast, touch targets, keyboard nav)
5. **Responsiveness**: Does it work on mobile, tablet, desktop?
6. **Uniqueness**: Does this break from generic SaaS patterns?
7. **Approval**: Have I asked before implementing colors, fonts, sizes, layouts?
**Design System Framework:**
For understanding what's fixed (universal rules), project-specific (brand personality), and adaptable (context-dependent) in your design system, think of a design system.
## Visual Design Standards
### Color & Contrast
**Color System Architecture:**
Every interface needs two color roles:
1. **Base/Neutral Palette (4-5 colors):**
- Backgrounds (lightest)
- Surface colors (cards, inputs)
- Borders and dividers
- Text (darkest)
- Use slightly desaturated, warm or cool greys based on brand
2. **Accent Palette (1-3 colors):**
- Primary action (CTA buttons)
- Status indicators (success, warning, error, info)
- Focus/hover states
- Use saturated colors for clear contrast against neutrals
**Palette Structure Example:**
```
Neutrals: slate-50, slate-100, slate-300, slate-700, slate-900
Accents: teal-500 (primary), amber-500 (warning), red-500 (error)
```
**Color Application Rules:**
- **Backgrounds**: Lightest neutral (slate-50 or white)
- **Text**: Darkest neutral for primary text (slate-900), mid-tone for secondary (slate-600)
- **Buttons (primary)**: Accent color with white text
- **Buttons (secondary)**: Neutral with border and dark text
- **Status indicators**: Specific accent (green=success, red=error, amber=warning, blue=info)
- **Interactive states**:
- Hover: Darken by 10-15% or shift hue slightly
- Focus: Use ring/outline in accent color
- Disabled: Reduce opacity to 40-50% and remove hover effects
**Color Relationships:**
Choose warm or cool intentionally based on brand:
- **Warm greys** (beige/brown undertones): Organic, approachable, trustworthy
- **Cool greys** (blue undertones): Modern, tech-forward, professional
Accent colors should have clear contrast with both:
- Light backgrounds (for buttons on white)
- Dark text (if used as backgrounds for white text)
**Intentional Color Usage:**
- Every color must serve a purpose (hierarchy, function, status, or action)
- Avoid decorative colors that don't communicate meaning
- Maintain consistency: same color = same meaning throughout
**Accessibility:**
- Ensure sufficient contrast for color-blind users
- Follow WCAG 2.1 AA: minimum 4.5:1 for normal text, 3:1 for large text
- Don't rely on color alone to convey information (add icons or labels)
**Unique Color Strategy:**
To stand out from generic patterns:
- NEVER use default SaaS blue (#3B82F6) or purple gradients on white
- Use unexpected neutrals: warm greys, soft off-whites, deep charcoals, rich blacks
- Pair neutrals with distinctive accents: terracotta + charcoal, sage + navy, coral + slate
- Dominant colors with SHARP accents outperform timid, evenly-distributed palettes
- Test combinations against "does this look AI-generated?" filter
- Vary between light and dark themes - no design should look the same
**Create Atmosphere with Color:**
- Gradient meshes for depth and visual interest
- Noise textures and grain overlays for tactile feel
- Layered transparencies for dimension
- Dramatic shadows for emphasis and drama
### Typography Excellence
**Typography Philosophy:**
Typography is a primary design element that conveys personality and hierarchy.
**Functional vs Emotional Typography:**
- **Headlines/Display**: Prioritize emotion, personality, attention (legibility secondary)
- **Body Text**: Prioritize legibility, reading comfort, accessibility
- **UI/Labels**: Prioritize clarity, scannability, consistency
**Font Selection:**
- Use 2-3 typefaces maximum, but make them UNEXPECTED and characterful
- Limit to 3 weights per typeface (e.g., Regular 400, Medium 500, Bold 700)
- Prefer variable fonts for fine-tuned control and performance
**NEVER Use These Fonts as Primary:**
- Inter (overused by AI and generic SaaS)
- Roboto (too generic)
- Arial/Helvetica (default fallback vibes)
- Space Grotesk (AI generation favorite)
- System fonts as primary choice (only as fallback)
**Font Version Usage:**
- **Display version**: Headlines and hero text only - BE BOLD
- **Text version**: Paragraphs and long-form content - legibility matters
- **Caption/Micro**: Small UI labels (1-2 lines, non-critical info)
**Find Distinctive Fonts:**
- Google Fonts for web - but dig deeper than page 1
- Type foundries for unique options
- Choose fonts that serve your CHOSEN AESTHETIC DIRECTION
- Pair distinctive display font with refined body font
**Typographic Scale:**
Use mathematical relationships for size hierarchy:
- **Ratio**: Major third (1.25x) for moderate contrast, Perfect fourth (1.333x) for dramatic
- **Base size**: 16px (1rem) for body text
- **Example scale (1.25x)**:
```
xs: 0.64rem (10px)
sm: 0.8rem (13px)
base: 1rem (16px)
lg: 1.25rem (20px)
xl: 1.563rem (25px)
2xl: 1.953rem (31px)
3xl: 2.441rem (39px)
4xl: 3.052rem (49px)
5xl: 3.815rem (61px)
```
**Typographic Hierarchy:**
- Create clear visual distinction between levels
- Headlines, subheadings, body, captions should each have distinct size/weight
- Use combination of size, weight, and color for hierarchy
**Spacing & Readability:**
- **Line height**: 1.5x font size for body text (e.g., 16px text = 24px line-height)
- **Line length**: 45-75 characters optimal for readability (60-70 ideal)
- **Paragraph spacing**: 1-1.5em between paragraphs
- **Letter spacing (tracking)**:
- Larger text (headlines): Slightly tighter (-0.02em to -0.05em)
- Normal text (body): Default (0)
- Small text (captions): Slightly looser (+0.01em to +0.03em)
- General rule: As size increases, reduce tracking; as size decreases, increase tracking
**Font Pairing Logic:**
When using multiple typefaces, create contrast through:
- **Category contrast**: Serif + Sans-serif (classic, clear distinction)
- **Weight contrast**: Light + Bold (dynamic, energetic)
- **Personality contrast**: Geometric + Humanist (modern + warm)
Examples:
- Serif headlines + Sans body (editorial, trustworthy)
- Display headlines + System body (distinctive + efficient)
- Bold sans headlines + Light sans body (modern, clean)
**UI Typography:**
Specific guidance for interface elements:
- **Button text**: Semi-Bold (600), 14-16px, consistent casing (all-caps OR title case)
- **Form labels**: Regular (400), 14px, positioned above input
- **Form input text**: Regular (400), 16px minimum (prevents iOS zoom on focus)
- **Placeholder text**: Light (300) or desaturated color, same size as input
- **Error messages**: Regular (400), 12-14px, color-coded (red-ish)
**Responsive Typography:**
Scale type sizes across breakpoints:
```tsx
// Example with Tailwind
<h1 className="text-3xl md:text-4xl lg:text-5xl">
Responsive Headline
</h1>
// Or with CSS clamp (fluid)
h1 {
font-size: clamp(2rem, 5vw, 4rem);
}
```
Reduce sizes on mobile (20-30% smaller than desktop)
Reduce hierarchy levels on small screens (fewer distinct sizes)
### Layout & Spatial Design
**Compositional Balance:**
- Every screen should feel balanced
- Pay attention to visual weight and negative space
- Use generous negative space to focus attention
- Add sufficient margins and paddings for professional, spacious look
**Grid Discipline:**
- Maintain consistent underlying grid system
- Create sense of order while allowing meaningful exceptions
- Use grid/flex wrappers with `gap` for spacing
- Prioritize wrappers over direct margins/padding on children
**Spatial Relationships:**
- Group related elements through proximity, alignment, and shared attributes
- Use size, color, and spacing to highlight important elements
- Guide user focus through visual hierarchy
**Attention Guidance:**
- Design interfaces that guide user attention effectively
- Avoid cluttered interfaces where elements compete
- Create clear paths through the content
## Interaction Design
**Motion Specification:**
For detailed motion specs, see MOTION-SPEC.md (easing curves, duration tables, state-specific animations, implementation patterns).
### User Experience Patterns
**Core UX Principles:**
1. **Direct Manipulation**
- Users interact directly with content, not through abstract controls
- Examples:
- Drag & drop to reorder items (not up/down buttons)
- Inline editing (click to edit, not separate form)
- Sliders for ranges (not numeric input with +/-)
- Pinch/zoom gestures on mobile (not +/- buttons)
2. **Immediate Feedback**
- Every interaction provides instantaneous visual feedback (within 100ms)
- Types of feedback:
- **Visual**: Button pressed state, hover effects, color changes
- **Haptic**: Vibration on mobile (submit, error, success)
- **Audio**: Subtle sounds for critical actions (optional, user-controlled)
- **Loading**: Skeleton screens, spinners for >300ms operations
- **Success**: Checkmarks, green highlights, toast notifications
- **Error**: Red highlights, inline error messages, shake animations
3. **Consistent Behavior**
- Similar-looking elements behave similarly
- Examples:
- **Visual consistency**: All primary buttons have same colors, sizes, hover states
- **Behavioral consistency**: All modals close via X button, ESC key, and outside click
- **Interaction consistency**: All drag targets have same hover state and drop feedback
- **Pattern consistency**: All forms validate on blur and submit
4. **Forgiveness**
- Make errors difficult, but recovery easy
- **Prevention strategies**:
- Disable invalid actions (grey out unavailable buttons)
- Validate inputs inline (before submission)
- Confirm destructive actions (delete, overwrite)
- Auto-save in background (drafts, progress)
- **Recovery strategies**:
- Undo/redo for all state changes
- Soft deletes (trash/archive before permanent delete)
- Clear error messages with actionable fixes
- Preserve user input on errors (don't clear forms)
5. **Progressive Disclosure**
- Reveal details as needed rather than overwhelming users
- Levels of disclosure:
- **Summary**: Show essential info by default (card title, price, rating)
- **Details**: Expand to show more info (description, specs, reviews)
- **Advanced**: Hide complex options behind "Advanced settings" toggle
- Examples:
- Accordion: Start collapsed, expand on click
- Search filters: Show 3-5 common filters, hide rest behind "More filters"
- Settings: Basic settings visible, advanced behind "Show advanced"
**Modern UX Patterns:**
1. **Conversational Interfaces**
Prioritize natural language interaction where appropriate:
**Four types:**
- **Pure chat**: Full conversation (AI assistants, support bots)
- **Command palette**: Text-based shortcuts (Cmd+K, search everywhere)
- **Smart search**: Natural language queries (search "meetings next week" vs filtering)
- **Form alternatives**: Conversational data collection ("What's your name?" vs form fields)
**When to use:**
- Complex searches with multiple variables
- Task guidance (wizards, onboarding)
- Contextual help
- Quick actions (command palette)
**When NOT to use:**
- Simple forms (just use inputs)
- Precise control interfaces (design tools, dashboards)
- High-frequency repetitive tasks
2. **Adaptive Layouts**
Respond to user context automatically:
- **Time-based**: Dark mode at night, light during day
- **Device-based**: Simplified UI on mobile, full features on desktop
- **Connection-based**: Reduce images/video on slow connections
- **Usage-based**: Prioritize frequent actions, hide rarely-used features
Examples:
- Auto dark/light mode based on time or system preference
- Simplified mobile navigation (hamburger menu) vs full desktop nav
- Collapsed sidebar on small screens, expanded on large
3. **Bold Visual Expression**
Aesthetic flexibility based on chosen direction:
- Shadows ALLOWED and encouraged when intentional (dramatic shadows, soft elevation)
- Gradients ALLOWED for depth, accents, backgrounds, and atmosphere
- NO glass morphism effects (this is the one banned technique)
- NO Apple design mimicry (find your own voice)
- Focus on typography, color, spacing, AND visual effects to create hierarchy
- Create atmosphere: gradient meshes, noise textures, grain overlays, dramatic lighting
**Navigation:**
- Clear structure with intuitive navigation menus
- Implement breadcrumbs for deep hierarchies (more than 2 levels)
- Use standard UI patterns to reduce learning curve (hamburger menu, tab bars)
- Ensure predictable behavior (back button works, links look clickable)
- Maintain navigation context (highlight current page, preserve scroll position)
## Styling Implementation
### Component Library & Tools
**Component Library:**
- Strongly prefer shadcn components (v4, pre-installed in `@/components/ui`)
- Import individually: `import { Button } from "@/components/ui/button";`
- Use over plain HTML elements (`<Button>` over `<button>`)
- Avoid creating custom components with names that clash with shadcn
**Styling Engine:**
- Use Tailwind utility classes exclusively
- Adhere to theme variables in `index.css` via CSS custom properties
- Map variables in `@theme` (see `tailwind.config.js`)
- Use inline styles or CSS modules only when absolutely necessary
**Icons:**
- Use `@phosphor-icons/react` for buttons and inputs
- Example: `import { Plus } from "@phosphor-icons/react"; <Plus />`
- Use color for plain icon buttons
- Don't override default `size` or `weight` unless requested
**Notifications:**
- Use `sonner` for toasts
- Example: `import { toast } from 'sonner'`
**Loading States:**
- Always add loading states, spinners, placeholder animations
- Use skeletons until content renders
### Layout Implementation
**Spacing Strategy:**
- Use grid/flex wrappers with `gap` for spacing
- Prioritize wrappers over direct margins/padding on children
- Nest wrappers as needed for complex layouts
**Conditional Styling:**
- Use ternary operators or clsx/classnames utilities
- Example: `className={clsx('base-class', { 'active-class': isActive })}`
### Responsive Design
**Fluid Layouts:**
- Use relative units (%, em, rem) instead of fixed pixels
- Implement CSS Grid and Flexbox for flexible layouts
- Design mobile-first, then scale up
**Media Queries:**
- Use breakpoints based on content needs, not specific devices
- Test across range of devices and orientations
**Touch Targets:**
- Minimum 44x44 pixels for interactive elements
- Provide adequate spacing between touch targets
- Consider hover states for desktop, focus states for touch/keyboard
**Performance:**
- Optimize assets for mobile networks
- Use CSS animations over JavaScript
- Implement lazy loading for images and videos
## Accessibility Standards
**Core Requirements:**
- Follow WCAG 2.1 AA guidelines
- Ensure keyboard navigability for all interactive elements
- Minimum touch target size: 44×44px
- Use semantic HTML for screen reader compatibility
- Provide alternative text for images and non-text content
**Implementation Details:**
- Use descriptive variable and function names
- Event functions: prefix with "handle" (handleClick, handleKeyDown)
- Add accessibility attributes:
- `tabindex="0"` for custom interactive elements
- `aria-label` for buttons without text
- `role` attributes when semantic HTML isn't sufficient
- Ensure logical tab order
- Provide visible focus states
## Design Process & Testing
### Design Workflow
1. **Understand Context:**
- What problem are we solving?
- Who are the users and when will they use this?
- What are the success criteria?
2. **Explore Options:**
- Present 2-3 alternative approaches
- Explain trade-offs of each option
- Ask which direction resonates
3. **Implement Iteratively:**
- Start with structure and hierarchy
- Add visual polish progressively
- Test at each stage
4. **Validate:**
- Use playwright MCP to test visual changes
- Check across different screen sizes
- Verify accessibility
### Testing Checklist
**Visual Testing:**
- Use playwright MCP when available for automated testing
- Check responsive behavior at common breakpoints
- Verify touch targets on mobile
- Test with different content lengths (short, long, edge cases)
**Accessibility Testing:**
- Test keyboard navigation
- Verify screen reader compatibility
- Check color contrast ratios
- Ensure focus states are visible
**Cross-Device Testing:**
- Test on actual devices, not just emulators
- Check different browsers (Chrome, Firefox, Safari)
- Verify touch interactions on mobile
- Test landscape and portrait orientations
## Examples
### Example 1: Designing a Button
**Initial Question to Ask:**
```
Before I implement this button, I have a few design questions:
1. What's the primary action you want to emphasize?
2. Do you have brand colors in mind, or should I suggest options?
3. What emotion should this button convey? (urgent, calm, playful, professional)
```
**After Getting Approval, Implementation:**
```tsx
import { Button } from "@/components/ui/button";
import { ArrowRight } from "@phosphor-icons/react";
<Button
className="bg-slate-800 hover:bg-slate-700 text-white px-6 py-3 rounded-lg transition-colors duration-200"
>
Get Started
<ArrowRight className="ml-2" />
</Button>
```
### Example 2: Typography Hierarchy
**Question First:**
```
For this content hierarchy, I'm thinking:
- Headline: Large, bold, attention-grabbing
- Subheading: Medium, regular weight
- Body: Smaller, optimized for reading
Should we go bold and contemporary, or subtle and refined?
```
**Implementation After Approval:**
```tsx
<div className="space-y-4">
<h1 className="text-5xl font-bold tracking-tight text-slate-900">
Headline Here
</h1>
<h2 className="text-2xl text-slate-600">
Supporting subheading
</h2>
<p className="text-base leading-relaxed text-slate-700">
Body text optimized for readability with proper line height.
</p>
</div>
```
### Example 3: Unique Color Palette Suggestion
**Presenting Options:**
```
I'd like to suggest three color directions that break from typical SaaS patterns:
1. **Warm Earth Tones**
- Base: Warm grey (#E8E2DC)
- Accent: Terracotta (#C86E4B)
- For: Organic, trustworthy feel
2. **Cool Midnight**
- Base: Deep navy (#1A2332)
- Accent: Cyan (#4ECDC4)
- For: Modern, tech-forward feel
3. **Soft Pastels**
- Base: Soft pink (#FFE5E5)
- Accent: Sage green (#9DB5A4)
- For: Calm, approachable feel
Which direction feels right for your brand?
```
## Common Patterns to Avoid
**NEVER:**
- Use Inter, Roboto, Arial, Space Grotesk as primary fonts
- Use generic SaaS blue (#3B82F6) or purple gradients on white
- Copy Apple's design language or use glass morphism
- Create cookie-cutter layouts that look AI-generated
- Skip asking about context before designing
- Converge on common choices across generations (vary everything!)
- Use animations that delay user actions
- Create cluttered interfaces where elements compete
**ALWAYS:**
- Ask about purpose, tone, constraints, differentiation FIRST
- Then commit BOLDLY to a distinctive aesthetic direction
- Use unexpected, characterful typography choices
- Create atmosphere: shadows, gradients, textures, grain (when intentional)
- Dominant colors with sharp accents (not timid, evenly-distributed palettes)
- Provide immediate feedback for interactions
- Test with real devices
- Validate accessibility (it enables creativity, not limits it)
- Remember: Claude is capable of extraordinary creative work - don't hold back!
## Version History
- v2.0.0 (2025-11-22): Creative liberation update - bold aesthetics, shadows/gradients allowed, Design Thinking protocol
- v1.0.0 (2025-10-18): Initial release with comprehensive UI/UX design guidance
## References
For additional context, see:
- **Anthropic Frontend Aesthetics Cookbook**: https://github.com/anthropics/claude-cookbooks/blob/main/coding/prompting_for_frontend_aesthetics.ipynb
- WCAG 2.1 Guidelines: https://www.w3.org/WAI/WCAG21/quickref/
- Google Fonts: https://fonts.google.com/
- Tailwind CSS Docs: https://tailwindcss.com/docs
- Shadcn UI Components: https://ui.shadcn.com/
**Progressive Disclosure Files:**
- ACCESSIBILITY.md - Accessibility essentials (WCAG AA baseline)
- MOTION-SPEC.md - Animation timing and easing
- RESPONSIVE-DESIGN.md - Mobile-first breakpoints and patterns
@@ -1,111 +0,0 @@
# Accessibility Essentials
Accessibility enables creativity - it's a foundation, not a limitation. WCAG 2.1 AA compliance.
## Core Principles (POUR)
- **Perceivable**: Content must be perceivable (alt text, contrast, captions)
- **Operable**: UI must be keyboard/touch accessible
- **Understandable**: Clear, predictable behavior
- **Robust**: Works with assistive technologies
## Contrast Requirements
| Element | Minimum Ratio |
|---------|---------------|
| Normal text | 4.5:1 |
| Large text (18pt+) | 3:1 |
| UI components | 3:1 |
**Tools**: Chrome DevTools Accessibility tab, WebAIM Contrast Checker
## Keyboard Navigation
```tsx
// All interactive elements need focus states
<button className="focus:ring-4 focus:ring-blue-500 focus:outline-none">
Accessible
</button>
// Custom elements need tabindex and key handlers
<div
role="button"
tabIndex={0}
onKeyDown={(e) => (e.key === 'Enter' || e.key === ' ') && handleClick()}
>
Custom Button
</div>
```
**Essentials:**
- Tab through entire interface
- Enter/Space activates elements
- Escape closes modals
- Visible focus indicators always
## Essential ARIA
```tsx
// Buttons without text
<button aria-label="Close dialog"><X /></button>
// Expandable elements
<button aria-expanded={isOpen} aria-controls="menu">Menu</button>
// Live regions for dynamic content
<div role="status" aria-live="polite">{statusMessage}</div>
<div role="alert" aria-live="assertive">{errorMessage}</div>
// Form errors
<input aria-invalid={hasError} aria-describedby="error-msg" />
{hasError && <p id="error-msg" role="alert">Error text</p>}
```
## Semantic HTML
```tsx
// Use semantic elements, not divs
<header><nav>...</nav></header>
<main><article><h1>...</h1></article></main>
<footer>...</footer>
// Heading hierarchy (never skip levels)
<h1>Page Title</h1>
<h2>Section</h2>
<h3>Subsection</h3>
```
## Touch Targets
- Minimum **44x44px** for all interactive elements
- Adequate spacing between targets
- `touch-manipulation` CSS for responsive touch
## Screen Reader Content
```tsx
// Hidden but announced
<span className="sr-only">Additional context</span>
// Skip link
<a href="#main" className="sr-only focus:not-sr-only">
Skip to main content
</a>
```
## Quick Checklist
- [ ] Keyboard: Can tab through everything
- [ ] Focus: Visible focus indicators
- [ ] Contrast: 4.5:1 for text
- [ ] Alt text: All images have appropriate alt
- [ ] Headings: Logical h1-h6 hierarchy
- [ ] Forms: Labels associated with inputs
- [ ] Errors: Announced to screen readers
- [ ] Touch: 44px minimum targets
## Resources
- [WCAG 2.1 Quick Reference](https://www.w3.org/WAI/WCAG21/quickref/)
- [WebAIM Contrast Checker](https://webaim.org/resources/contrastchecker/)
- [ARIA Authoring Practices](https://www.w3.org/WAI/ARIA/apg/)
@@ -1,577 +0,0 @@
# Design System Template
Meta-framework for understanding what's fixed, project-specific, and adaptable in your design system.
## Purpose
This template helps you distinguish between:
- **Fixed Elements**: Universal rules that never change
- **Project-Specific Elements**: Filled in for each project based on brand
- **Adaptable Elements**: Context-dependent implementations
---
## I. FIXED ELEMENTS
These foundations remain consistent across all projects, regardless of brand or context.
### 1. Spacing Scale
**Fixed System:**
```
4px, 8px, 12px, 16px, 24px, 32px, 48px, 64px, 96px
```
**Usage:**
- Margins, padding, gaps between elements
- Mathematical relationships ensure visual harmony
- Use multipliers of base unit (4px)
**Why Fixed:**
Consistent spacing creates visual rhythm regardless of brand personality.
### 2. Grid System
**Fixed Structure:**
- **12-column grid** for most layouts (divisible by 2, 3, 4, 6)
- **16-column grid** for data-heavy interfaces
- **Gutters**: 16px (mobile), 24px (tablet), 32px (desktop)
**Why Fixed:**
Grid provides structural order. Brand personality shows through color, typography, content—not grid structure.
### 3. Accessibility Standards
**Fixed Requirements:**
- **WCAG 2.1 AA** compliance minimum
- **Contrast**: 4.5:1 for normal text, 3:1 for large text
- **Touch targets**: Minimum 44×44px
- **Keyboard navigation**: All interactive elements accessible
- **Screen reader**: Semantic HTML, ARIA labels where needed
**Why Fixed:**
Accessibility is not negotiable. It's a baseline requirement for ethical, legal, and usable products.
### 4. Typography Hierarchy Logic
**Fixed Structure:**
- **Mathematical scaling**: 1.25x (major third) or 1.333x (perfect fourth)
- **Hierarchy levels**: Display → H1 → H2 → H3 → Body → Small → Caption
- **Line height**: 1.5x for body text, 1.2-1.3x for headlines
- **Line length**: 45-75 characters optimal
**Why Fixed:**
Mathematical relationships create predictable, harmonious hierarchy. Specific fonts change, but the logic doesn't.
### 5. Component Architecture
**Fixed Patterns:**
- **Button states**: Default, Hover, Active, Focus, Disabled
- **Form structure**: Label above input, error below, helper text optional
- **Modal pattern**: Overlay + centered content + close mechanism
- **Card structure**: Container → Header → Body → Footer (optional)
**Why Fixed:**
Users expect consistent component behavior. Architecture is fixed; appearance is project-specific.
### 6. Animation Timing Framework
**Fixed Physics Profiles:**
- **Lightweight** (icons, chips): 150ms
- **Standard** (cards, panels): 300ms
- **Weighty** (modals, pages): 500ms
**Fixed Easing:**
- **Ease-out**: Entrances (fast start, slow end)
- **Ease-in**: Exits (slow start, fast end)
- **Ease-in-out**: Transitions (smooth both ends)
**Why Fixed:**
Natural physics feel consistent across brands. Duration and easing create that feeling.
---
## II. PROJECT-SPECIFIC ELEMENTS
Fill in these for each project based on brand personality and purpose.
### 1. Brand Color System
**Template Structure:**
```
NEUTRALS (4-5 colors):
- Background lightest: _______ (e.g., slate-50 or warm-white)
- Surface: _______ (e.g., slate-100)
- Border/divider: _______ (e.g., slate-300)
- Text secondary: _______ (e.g., slate-600)
- Text primary: _______ (e.g., slate-900)
ACCENTS (1-3 colors):
- Primary (main CTA): _______ (e.g., teal-500)
- Secondary (alternative action): _______ (optional)
- Status colors:
- Success: _______ (green-ish)
- Warning: _______ (amber-ish)
- Error: _______ (red-ish)
- Info: _______ (blue-ish)
```
**Questions to Answer:**
- What emotion should the brand evoke? (Trust, excitement, calm, urgency)
- Warm or cool neutrals?
- Conservative or bold accents?
**Examples:**
**Project A: Fintech App**
```
Neutrals: Cool greys (slate-50 → slate-900)
Primary: Deep blue (#0A2463) trust, professionalism
Success: Muted green (#10B981)
Why: Financial products need trust, not playfulness
```
**Project B: Creative Community**
```
Neutrals: Warm greys with beige undertones
Primary: Coral (#FF6B6B) energy, creativity
Success: Teal (#06D6A0) fresh, unexpected
Why: Creative spaces should feel inviting, not corporate
```
**Project C: Healthcare Platform**
```
Neutrals: Pure greys (minimal color temperature)
Primary: Soft blue (#4A90E2) calm, clinical
Success: Medical green (#38A169)
Why: Healthcare needs clarity and calm, not distraction
```
### 2. Typography Pairing
**Template:**
```
HEADLINE FONT: _______
- Weight: _______ (e.g., Bold 700)
- Use case: H1, H2, display text
- Personality: _______ (geometric/humanist/serif/etc.)
BODY FONT: _______
- Weight: _______ (e.g., Regular 400, Medium 500)
- Use case: Paragraphs, UI text
- Personality: _______ (neutral/readable/efficient)
OPTIONAL ACCENT FONT: _______
- Weight: _______
- Use case: _______ (special headlines, callouts)
```
**Pairing Logic:**
- Serif + Sans-serif (classic, editorial)
- Geometric + Humanist (modern + warm)
- Display + System (distinctive + efficient)
**Examples:**
**Project A: Editorial Platform**
```
Headline: Playfair Display (Serif, Bold 700)
Body: Inter (Sans-serif, Regular 400)
Why: Serif headlines = trustworthy, editorial feel
```
**Project B: Tech Startup**
```
Headline: DM Sans (Sans-serif, Bold 700)
Body: DM Sans (Regular 400, Medium 500)
Why: Single-font system = modern, efficient, cohesive
```
**Project C: Luxury Brand**
```
Headline: Cormorant Garamond (Serif, Light 300)
Body: Lato (Sans-serif, Regular 400)
Why: Elegant serif + readable sans = sophisticated
```
### 3. Tone of Voice
**Template:**
```
BRAND PERSONALITY:
- Formal ↔ Casual: _______ (1-10 scale)
- Professional ↔ Friendly: _______ (1-10 scale)
- Serious ↔ Playful: _______ (1-10 scale)
- Authoritative ↔ Conversational: _______ (1-10 scale)
MICROCOPY EXAMPLES:
- Button label (submit form): _______
- Error message (invalid email): _______
- Success message (saved): _______
- Empty state: _______
ANIMATION PERSONALITY:
- Speed: _______ (quick/moderate/slow)
- Feel: _______ (precise/smooth/bouncy)
```
**Examples:**
**Project A: Banking App**
```
Personality: Formal (8), Professional (9), Serious (8)
Button: "Submit Application"
Error: "Email address format is invalid"
Success: "Application submitted successfully"
Animation: Quick (precise, efficient, no-nonsense)
```
**Project B: Social App**
```
Personality: Casual (8), Friendly (9), Playful (7)
Button: "Let's go!"
Error: "Hmm, that email doesn't look right"
Success: "Nice! You're all set 🎉"
Animation: Moderate (smooth, friendly bounce)
```
### 4. Animation Speed & Feel
**Template:**
```
SPEED PREFERENCE:
- UI interactions: _______ (100-150ms / 150-200ms / 200-300ms)
- State changes: _______ (200ms / 300ms / 400ms)
- Page transitions: _______ (300ms / 500ms / 700ms)
ANIMATION STYLE:
- Easing preference: _______ (sharp / standard / bouncy)
- Movement type: _______ (minimal / smooth / expressive)
```
**Examples:**
**Project A: Trading Platform**
```
Speed: Fast (100ms UI, 200ms states, 300ms pages)
Style: Sharp easing, minimal movement
Why: Traders need speed, not distraction
```
**Project B: Wellness App**
```
Speed: Slow (200ms UI, 400ms states, 500ms pages)
Style: Smooth easing, gentle movement
Why: Calm, relaxing experience matches brand
```
---
## III. ADAPTABLE ELEMENTS
Context-dependent implementations that vary based on use case.
### 1. Component Variations
**Button Variants:**
- **Primary**: Full background color (high emphasis)
- **Secondary**: Outline only (medium emphasis)
- **Tertiary**: Text only (low emphasis)
- **Destructive**: Red-ish (danger actions)
- **Ghost**: Minimal (navigation, toolbars)
**Adaptation Rules:**
- Primary: Main CTA, one per screen section
- Secondary: Alternative actions
- Tertiary: Less important actions, multiple allowed
- Use brand colors, but hierarchy logic is fixed
### 2. Responsive Breakpoints
**Fixed Ranges:**
- XS: 0-479px (small phones)
- SM: 480-767px (large phones)
- MD: 768-1023px (tablets)
- LG: 1024-1439px (laptops)
- XL: 1440px+ (desktop)
**Adaptable Implementations:**
**Simple Content Site:**
```
XS-SM: Single column
MD: 2 columns
LG-XL: 3 columns max
Why: Content-focused, don't overwhelm
```
**Dashboard/Data App:**
```
XS: Collapsed, cards stack
SM: Simplified sidebar
MD: Full sidebar + main content
LG-XL: Sidebar + main + right panel
Why: Data apps need more screen real estate
```
### 3. Dark Mode Palette
**Adaptation Strategy:**
Not a simple inversion. Dark mode needs adjusted contrast:
**Light Mode:**
```
Background: #FFFFFF (white)
Text: #0F172A (slate-900) → 21:1 contrast
```
**Dark Mode (Adapted):**
```
Background: #0F172A (slate-900)
Text: #E2E8F0 (slate-200) → 15.8:1 contrast (still AA, but softer)
```
**Why Adapt:**
Pure white on pure black is too harsh. Dark mode needs slightly lower contrast for eye comfort.
### 4. Loading States
**Context-Dependent:**
**Fast operations (<500ms):**
- No loading indicator (feels instant)
**Medium operations (500ms-2s):**
- Spinner or skeleton screen
**Long operations (>2s):**
- Progress bar with percentage
- Or: Skeleton + estimated time
**Interactive Operations:**
- Button shows spinner inside (don't disable, show state)
### 5. Error Handling Strategy
**Context-Dependent:**
**Form Errors:**
```
Validate: On blur (after user leaves field)
Display: Inline below field
Recovery: Clear error on fix
```
**API Errors:**
```
Transient (network): Show retry button
Permanent (404): Show helpful message + next steps
Critical (500): Contact support option
```
**Data Errors:**
```
Missing: Show empty state with action
Corrupt: Show error boundary with reload
Invalid: Highlight + explain what's wrong
```
---
## DECISION TREE
When implementing a feature, ask:
### Is this...
**FIXED?**
- Does it affect structure, accessibility, or universal UX?
- Examples: Spacing scale, grid, contrast ratios, component architecture
- **Action**: Use the fixed system, no variation
**PROJECT-SPECIFIC?**
- Does it express brand personality or purpose?
- Examples: Colors, typography, tone of voice, animation feel
- **Action**: Fill in the template for this project
**ADAPTABLE?**
- Does it depend on context, content, or use case?
- Examples: Component variants, responsive behavior, error handling
- **Action**: Choose appropriate variation based on context
---
## EXAMPLE: Implementing a "Submit" Button
### Fixed Elements (Always the same):
- Touch target: 44px minimum height
- Padding: 16px horizontal (from spacing scale)
- States: Default, Hover, Active, Focus, Disabled
- Animation: 150ms ease-out (lightweight profile)
### Project-Specific (Filled per project):
- **Project A (Bank)**: Dark blue background, white text, "Submit Application"
- **Project B (Social)**: Coral background, white text, "Let's Go!"
- **Project C (Healthcare)**: Soft blue background, white text, "Continue"
### Adaptable (Context-dependent):
- **Form context**: Primary button (full color)
- **Toolbar context**: Ghost button (text only)
- **Danger context**: Destructive variant (red-ish)
---
## VALIDATION CHECKLIST
Before finalizing a design, check:
### Fixed Elements
- [ ] Uses spacing scale (4/8/12/16/24/32/48/64/96px)
- [ ] Follows grid system (12 or 16 columns)
- [ ] Meets WCAG AA contrast (4.5:1 normal, 3:1 large)
- [ ] Touch targets ≥ 44px
- [ ] Typography follows mathematical scale
- [ ] Components follow standard architecture
### Project-Specific Elements
- [ ] Brand colors filled in and intentional
- [ ] Typography pairing chosen and justified
- [ ] Tone of voice defined and consistent
- [ ] Animation speed matches brand personality
### Adaptable Elements
- [ ] Component variants appropriate for context
- [ ] Responsive behavior fits content type
- [ ] Loading states match operation duration
- [ ] Error handling fits error type
---
## PROJECT KICKOFF TEMPLATE
Use this to start a new project:
```
PROJECT NAME: _______________________
PURPOSE: ____________________________
BRAND PERSONALITY:
- Primary emotion: _______
- Warm or cool: _______
- Formal or casual: _______
- Conservative or bold: _______
COLORS (fill the template):
- Neutral base: _______
- Primary accent: _______
- Status colors: _______ / _______ / _______
TYPOGRAPHY (fill the template):
- Headline font: _______
- Body font: _______
- Pairing rationale: _______
TONE:
- Button labels style: _______
- Error message style: _______
- Success message style: _______
ANIMATION:
- Speed preference: _______ (fast/moderate/slow)
- Feel preference: _______ (sharp/smooth/bouncy)
TARGET DEVICES:
- Primary: _______ (mobile/desktop/both)
- Secondary: _______
```
---
## MAINTAINING CONSISTENCY
### Documentation
- Keep this template updated as system evolves
- Document WHY choices were made, not just WHAT
### Communication
- Share with designers: "Here's what varies vs. what's fixed"
- Share with developers: "Here are the design tokens"
### Tooling
- Use CSS variables for project-specific values
- Use Tailwind config for spacing scale
- Use design tokens in Figma/Storybook
### Reviews
- Audit: Does new work follow fixed elements?
- Validate: Are project-specific elements intentional?
- Question: Are adaptations justified by context?
---
## EXAMPLES OF COMPLETE SYSTEMS
### System A: B2B SaaS (Conservative)
**Fixed**: Standard spacing, 12-col grid, WCAG AA, major third type scale
**Project-Specific**:
- Colors: Cool greys + corporate blue
- Typography: DM Sans (headlines + body)
- Tone: Professional, formal
- Animation: Quick, precise (150ms)
**Adaptable**:
- Dashboard gets multi-panel layout
- Forms are extensive (use progressive disclosure)
- Errors show detailed technical info
### System B: Consumer Social App (Playful)
**Fixed**: Same spacing/grid/accessibility/type logic
**Project-Specific**:
- Colors: Warm greys + vibrant coral
- Typography: Poppins (headlines) + Inter (body)
- Tone: Casual, friendly, playful
- Animation: Moderate, bouncy (200ms)
**Adaptable**:
- Mobile-first (most users on phones)
- Forms are minimal (progressive profiling)
- Errors are friendly, not technical
### System C: Healthcare Platform (Clinical)
**Fixed**: Same foundational structure
**Project-Specific**:
- Colors: Pure greys + medical blue
- Typography: System fonts (SF Pro / Segoe)
- Tone: Clear, authoritative, calm
- Animation: Slow, smooth (300ms)
**Adaptable**:
- Desktop-first (clinical use at workstations)
- Forms are complex (HIPAA compliance)
- Errors are precise with next steps
---
## KEY TAKEAWAY
**The system flexibility framework lets you:**
- Maintain consistency (fixed elements)
- Express brand personality (project-specific)
- Adapt to context (adaptable elements)
**Without this framework:**
- Designers reinvent spacing every project
- Components feel inconsistent across products
- Brand personality overrides accessibility
- Context-blind implementations feel wrong
**With this framework:**
- Speed: Start from proven foundations
- Consistency: Fixed elements guarantee it
- Flexibility: Express unique brand identity
- Context: Adapt without breaking system
@@ -1,72 +0,0 @@
# Motion Specification
Motion should surprise and delight while serving function. Animation is a creative tool.
## Easing Curves
| Easing | CSS | Use For |
|--------|-----|---------|
| **Ease-out** | `cubic-bezier(0.0, 0.0, 0.2, 1)` | Entrances, appearing |
| **Ease-in** | `cubic-bezier(0.4, 0.0, 1, 1)` | Exits, disappearing |
| **Ease-in-out** | `cubic-bezier(0.4, 0.0, 0.2, 1)` | State changes, transforms |
| **Spring** | `cubic-bezier(0.68, -0.55, 0.265, 1.55)` | Playful, attention-grabbing |
| **Linear** | `linear` | Spinners, continuous loops |
## Duration by Element Weight
| Weight | Duration | Examples |
|--------|----------|----------|
| **Lightweight** | 150ms | Icons, badges, chips |
| **Standard** | 300ms | Cards, panels, list items |
| **Weighty** | 500ms | Modals, page transitions |
## Duration by Interaction
| Interaction | Duration |
|-------------|----------|
| Button press | 100ms |
| Hover state | 150ms |
| Tooltip appear | 200ms |
| Tab switch | 250ms |
| Modal open | 300ms |
| Page transition | 400ms |
## Common Patterns
```tsx
// Hover transition (CSS)
<button className="transition-colors duration-150 ease-out hover:bg-blue-700">
// Fade + slide (Framer Motion)
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.3, ease: "easeOut" }}
/>
// Stagger children
<motion.ul variants={{ visible: { transition: { staggerChildren: 0.1 } } }}>
<motion.li variants={{ hidden: { opacity: 0 }, visible: { opacity: 1 } }} />
</motion.ul>
```
## Performance Rules
- Only animate `transform` and `opacity` (GPU-accelerated)
- Avoid animating `width`, `height`, `margin`, `padding`
- Keep durations under 500ms for UI interactions
- Respect `prefers-reduced-motion`:
```css
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
transition-duration: 0.01ms !important;
}
}
```
## Resources
- [Framer Motion](https://www.framer.com/motion/)
- [CSS Easing Functions](https://easings.net/)
@@ -1,90 +0,0 @@
# Responsive Design Essentials
Mobile-first approach: start with mobile, progressively enhance for larger screens.
## Breakpoints
| Range | Pixels | Devices | Strategy |
|-------|--------|---------|----------|
| **XS** | 0-479px | Small phones | Single column, stacked nav, 44px touch targets |
| **SM** | 480-767px | Large phones | Single column, bottom nav, simplified UI |
| **MD** | 768-1023px | Tablets | 2 columns possible, sidebar nav |
| **LG** | 1024-1439px | Laptops | Multi-column, full nav, desktop UI |
| **XL** | 1440px+ | Desktop | Max-width containers, multi-panel layouts |
## Tailwind Responsive
```tsx
// Mobile-first: base styles, then scale up
<div className="
w-full // mobile: full width
sm:w-1/2 // 480px+: half
md:w-1/3 // 768px+: third
lg:w-1/4 // 1024px+: quarter
">
// Responsive grid
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6">
// Responsive typography
<h1 className="text-3xl md:text-4xl lg:text-5xl">
// Show/hide by breakpoint
<div className="block md:hidden">Mobile only</div>
<div className="hidden md:block">Desktop only</div>
```
## Fluid Typography
```css
h1 { font-size: clamp(2rem, 5vw, 4rem); }
p { font-size: clamp(1rem, 2.5vw, 1.25rem); }
```
## Touch Targets
- Minimum **44x44px** for all interactive elements
- Use `touch-manipulation` to prevent 300ms tap delay
- Adequate spacing between targets
```tsx
<button className="min-w-[44px] min-h-[44px] touch-manipulation">
```
## Mobile Simplification
| Desktop | Mobile |
|---------|--------|
| Full nav bar | Hamburger menu |
| Side-by-side fields | Stacked fields |
| Multi-column grid | Single column |
| Inline buttons | Fixed bottom bar |
| Data table | Collapsed cards |
| Visible sidebar | Hidden/collapsible |
## Images
```tsx
// Responsive images
<img
srcSet="image-400w.jpg 400w, image-800w.jpg 800w, image-1200w.jpg 1200w"
sizes="(max-width: 640px) 100vw, (max-width: 1024px) 50vw, 33vw"
loading="lazy"
/>
// Next.js
<Image src="/hero.jpg" width={1200} height={600} priority className="w-full h-auto" />
```
## Testing
Test at these widths:
- 375px (iPhone SE)
- 390px (iPhone 14)
- 768px (iPad)
- 1024px (iPad Pro)
- 1280px+ (Desktop)
## Resources
- [Tailwind Responsive](https://tailwindcss.com/docs/responsive-design)
@@ -1,718 +0,0 @@
---
name: bencium-innovative-ux-designer
description: Create distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
metadata:
version: 2.0.0
---
# Innovative UX Designer
Create distinctive, production-grade frontend interfaces that avoid generic "AI slop" aesthetics. Implement real working code with exceptional attention to aesthetic details and creative choices. Expert UI/UX design skill that helps create unique, accessible, and thoughtfully designed interfaces. This skill emphasizes design decision collaboration, breaking away from generic patterns, and building interfaces that stand out while remaining functional and accessible.
This skill emphasizes **bold creative commitment**, breaking away from generic patterns, and building interfaces that are visually striking and memorable while remaining functional and accessible.
## Core Philosophy
**CRITICAL: Design Thinking Protocol**
Before coding, **ASK to understand context**, then **COMMIT BOLDLY** to a distinctive direction:
### Questions to Ask First
1. **Purpose**: What problem does this interface solve? Who uses it?
2. **Tone**: What aesthetic extreme fits? (see Tone Options below)
3. **Constraints**: Technical requirements (framework, performance, accessibility)?
4. **Differentiation**: What makes this UNFORGETTABLE? What's the one thing someone will remember?
### Tone Options (Pick an Extreme)
Choose a clear aesthetic direction and execute with precision:
- **Brutally minimal** - stripped to essence, bold typography, vast whitespace
- **Maximalist chaos** - layered, dense, visually rich, controlled disorder
- **Retro-futuristic** - vintage meets sci-fi, nostalgic tech aesthetics
- **Organic/natural** - soft edges, earthy colors, nature-inspired textures
- **Luxury/refined** - elegant spacing, premium typography, subtle details
- **Playful/toy-like** - bright colors, rounded shapes, delightful interactions
- **Editorial/magazine** - strong typography hierarchy, asymmetric layouts
- **Brutalist/raw** - exposed structure, harsh contrasts, intentionally rough
- **Art deco/geometric** - bold patterns, metallic accents, symmetric elegance
- **Soft/pastel** - gentle gradients, muted tones, calming atmosphere
- **Industrial/utilitarian** - functional, no-nonsense, mechanical precision
### After Getting Context
- **Commit fully** to the chosen direction - no half measures
- Present 2-3 alternative approaches with trade-offs
- Then implement with precision: production-grade, visually striking, memorable
## Foundational Design Principles
### Stand Out From Generic Patterns
**NEVER Use These AI-Generated Aesthetics:**
- **Fonts**: Inter, Roboto, Arial, system fonts as primary choice, Space Grotesk (overused by AI)
- **Colors**: Generic SaaS blue (#3B82F6), purple gradients on white backgrounds
- **Patterns**: Cookie-cutter layouts, predictable component arrangements
- **Effects**: Glass morphism, Apple design mimicry, liquid/blob backgrounds
- **Overall**: Anything that looks "Claude-generated" or machine-made
**Instead, Create Atmosphere:**
- Suggest photography, patterns, textures over flat solid colors
- Apply gradient meshes, noise textures, geometric patterns
- Use layered transparencies, dramatic shadows, decorative borders
- Consider custom cursors, grain overlays, contextual effects
- Think beyond typical patterns - you can step off the written path
**Draw Inspiration From:**
- Modern landing pages (Perplexity, Comet Browser, Dia Browser)
- Framer templates and their innovative approaches
- Leading brand design studios
- Historical design movements (Bauhaus, Otl Aicher, Braun) - but as inspiration, not imitation
- Beautiful background animations (CSS, SVG) - slow, looping, subtle
**Visual Interest Strategies:**
- Unique color pairs that aren't typical
- Animation effects that feel fresh
- Background patterns that add depth without distraction
- Typography combinations that create contrast
- Visual assets that tell a story
### Core Design Philosophy
1. **Simplicity Through Reduction**
- Identify the essential purpose and eliminate distractions
- Begin with complexity, then deliberately remove until reaching the simplest effective solution
- Every element must justify its existence
2. **Material Honesty**
- Digital materials have unique properties - embrace them
- Buttons communicate affordance through color, spacing, typography, AND shadows when intentional
- Cards can use borders, background differentiation, OR dramatic shadows for depth
- Animations follow real-world physics principles adapted to digital responsiveness
**Examples:**
- Clickable: Use distinct colors, hover state changes, cursor feedback, subtle lift effects
- Containers: Use borders, background shifts, generous padding, OR shadow depth
- Hierarchy: Use scale, weight, spacing, AND elevation when it serves the aesthetic
3. **Functional Layering**
- Create hierarchy through typography scale, color contrast, and spatial relationships
- Layer information conceptually (primary → secondary → tertiary)
- Use shadows and gradients INTENTIONALLY when they serve the aesthetic direction
- Embrace functional depth: modals over content, dropdowns over UI
- Avoid: glass morphism, Apple mimicry (but shadows/gradients are tools, not enemies)
4. **Obsessive Detail**
- Consider every pixel, interaction, and transition
- Excellence emerges from hundreds of small, intentional decisions
- Balance: Details should serve simplicity, not complexity
- When detail conflicts with clarity, clarity wins
5. **Coherent Design Language**
- Every element should visually communicate its function
- Elements should feel part of a unified system
- Nothing should feel arbitrary
6. **Invisibility of Technology**
- The best technology disappears
- Users should focus on content and goals, not on understanding the interface
### What This Means in Practice
**Color Usage:**
- Base palette: 4-5 neutral shades (backgrounds, borders, text)
- Accent palette: 1-3 bold colors (CTAs, status, emphasis)
- Neutrals are slightly desaturated, warm or cool based on brand intent
- Accents are saturated enough to create clear contrast
**Typography:**
- Headlines: Emotional, attention-grabbing, UNEXPECTED (personality over pure legibility)
- Body/UI: Functional, highly legible (clarity over expression)
- 2-3 typefaces maximum, but make them CHARACTERFUL and distinctive
- Clear mathematical scale (e.g., 1.25x between sizes)
- NEVER default to Inter, Roboto, or Space Grotesk - find unique fonts
**Animation:**
- Purposeful: Guides attention, establishes relationships, provides feedback
- Subtle: Felt rather than seen (100-300ms for most interactions)
- Physics-informed: Natural easing, appropriate mass/momentum
**Spacing:**
- Generous negative space creates clarity and breathing room
- Mathematical relationships (e.g., 4px base, 8/16/24/32/48px scale)
- Consistent application creates visual rhythm
### Design Decision Checklist
Before presenting any design, verify:
1. **Purpose**: Does every element serve a clear function?
2. **Hierarchy**: Is visual importance aligned with content importance?
3. **Consistency**: Do similar elements look and behave similarly?
4. **Accessibility**: Does it meet WCAG AA standards? (contrast, touch targets, keyboard nav)
5. **Responsiveness**: Does it work on mobile, tablet, desktop?
6. **Uniqueness**: Does this break from generic SaaS patterns?
7. **Approval**: Have I asked before implementing colors, fonts, sizes, layouts?
**Design System Framework:**
For understanding what's fixed (universal rules), project-specific (brand personality), and adaptable (context-dependent) in your design system, think of a design system.
## Visual Design Standards
### Color & Contrast
**Color System Architecture:**
Every interface needs two color roles:
1. **Base/Neutral Palette (4-5 colors):**
- Backgrounds (lightest)
- Surface colors (cards, inputs)
- Borders and dividers
- Text (darkest)
- Use slightly desaturated, warm or cool greys based on brand
2. **Accent Palette (1-3 colors):**
- Primary action (CTA buttons)
- Status indicators (success, warning, error, info)
- Focus/hover states
- Use saturated colors for clear contrast against neutrals
**Palette Structure Example:**
```
Neutrals: slate-50, slate-100, slate-300, slate-700, slate-900
Accents: teal-500 (primary), amber-500 (warning), red-500 (error)
```
**Color Application Rules:**
- **Backgrounds**: Lightest neutral (slate-50 or white)
- **Text**: Darkest neutral for primary text (slate-900), mid-tone for secondary (slate-600)
- **Buttons (primary)**: Accent color with white text
- **Buttons (secondary)**: Neutral with border and dark text
- **Status indicators**: Specific accent (green=success, red=error, amber=warning, blue=info)
- **Interactive states**:
- Hover: Darken by 10-15% or shift hue slightly
- Focus: Use ring/outline in accent color
- Disabled: Reduce opacity to 40-50% and remove hover effects
**Color Relationships:**
Choose warm or cool intentionally based on brand:
- **Warm greys** (beige/brown undertones): Organic, approachable, trustworthy
- **Cool greys** (blue undertones): Modern, tech-forward, professional
Accent colors should have clear contrast with both:
- Light backgrounds (for buttons on white)
- Dark text (if used as backgrounds for white text)
**Intentional Color Usage:**
- Every color must serve a purpose (hierarchy, function, status, or action)
- Avoid decorative colors that don't communicate meaning
- Maintain consistency: same color = same meaning throughout
**Accessibility:**
- Ensure sufficient contrast for color-blind users
- Follow WCAG 2.1 AA: minimum 4.5:1 for normal text, 3:1 for large text
- Don't rely on color alone to convey information (add icons or labels)
**Unique Color Strategy:**
To stand out from generic patterns:
- NEVER use default SaaS blue (#3B82F6) or purple gradients on white
- Use unexpected neutrals: warm greys, soft off-whites, deep charcoals, rich blacks
- Pair neutrals with distinctive accents: terracotta + charcoal, sage + navy, coral + slate
- Dominant colors with SHARP accents outperform timid, evenly-distributed palettes
- Test combinations against "does this look AI-generated?" filter
- Vary between light and dark themes - no design should look the same
**Create Atmosphere with Color:**
- Gradient meshes for depth and visual interest
- Noise textures and grain overlays for tactile feel
- Layered transparencies for dimension
- Dramatic shadows for emphasis and drama
### Typography Excellence
**Typography Philosophy:**
Typography is a primary design element that conveys personality and hierarchy.
**Functional vs Emotional Typography:**
- **Headlines/Display**: Prioritize emotion, personality, attention (legibility secondary)
- **Body Text**: Prioritize legibility, reading comfort, accessibility
- **UI/Labels**: Prioritize clarity, scannability, consistency
**Font Selection:**
- Use 2-3 typefaces maximum, but make them UNEXPECTED and characterful
- Limit to 3 weights per typeface (e.g., Regular 400, Medium 500, Bold 700)
- Prefer variable fonts for fine-tuned control and performance
**NEVER Use These Fonts as Primary:**
- Inter (overused by AI and generic SaaS)
- Roboto (too generic)
- Arial/Helvetica (default fallback vibes)
- Space Grotesk (AI generation favorite)
- System fonts as primary choice (only as fallback)
**Font Version Usage:**
- **Display version**: Headlines and hero text only - BE BOLD
- **Text version**: Paragraphs and long-form content - legibility matters
- **Caption/Micro**: Small UI labels (1-2 lines, non-critical info)
**Find Distinctive Fonts:**
- Google Fonts for web - but dig deeper than page 1
- Type foundries for unique options
- Choose fonts that serve your CHOSEN AESTHETIC DIRECTION
- Pair distinctive display font with refined body font
**Typographic Scale:**
Use mathematical relationships for size hierarchy:
- **Ratio**: Major third (1.25x) for moderate contrast, Perfect fourth (1.333x) for dramatic
- **Base size**: 16px (1rem) for body text
- **Example scale (1.25x)**:
```
xs: 0.64rem (10px)
sm: 0.8rem (13px)
base: 1rem (16px)
lg: 1.25rem (20px)
xl: 1.563rem (25px)
2xl: 1.953rem (31px)
3xl: 2.441rem (39px)
4xl: 3.052rem (49px)
5xl: 3.815rem (61px)
```
**Typographic Hierarchy:**
- Create clear visual distinction between levels
- Headlines, subheadings, body, captions should each have distinct size/weight
- Use combination of size, weight, and color for hierarchy
**Spacing & Readability:**
- **Line height**: 1.5x font size for body text (e.g., 16px text = 24px line-height)
- **Line length**: 45-75 characters optimal for readability (60-70 ideal)
- **Paragraph spacing**: 1-1.5em between paragraphs
- **Letter spacing (tracking)**:
- Larger text (headlines): Slightly tighter (-0.02em to -0.05em)
- Normal text (body): Default (0)
- Small text (captions): Slightly looser (+0.01em to +0.03em)
- General rule: As size increases, reduce tracking; as size decreases, increase tracking
**Font Pairing Logic:**
When using multiple typefaces, create contrast through:
- **Category contrast**: Serif + Sans-serif (classic, clear distinction)
- **Weight contrast**: Light + Bold (dynamic, energetic)
- **Personality contrast**: Geometric + Humanist (modern + warm)
Examples:
- Serif headlines + Sans body (editorial, trustworthy)
- Display headlines + System body (distinctive + efficient)
- Bold sans headlines + Light sans body (modern, clean)
**UI Typography:**
Specific guidance for interface elements:
- **Button text**: Semi-Bold (600), 14-16px, consistent casing (all-caps OR title case)
- **Form labels**: Regular (400), 14px, positioned above input
- **Form input text**: Regular (400), 16px minimum (prevents iOS zoom on focus)
- **Placeholder text**: Light (300) or desaturated color, same size as input
- **Error messages**: Regular (400), 12-14px, color-coded (red-ish)
**Responsive Typography:**
Scale type sizes across breakpoints:
```tsx
// Example with Tailwind
<h1 className="text-3xl md:text-4xl lg:text-5xl">
Responsive Headline
</h1>
// Or with CSS clamp (fluid)
h1 {
font-size: clamp(2rem, 5vw, 4rem);
}
```
Reduce sizes on mobile (20-30% smaller than desktop)
Reduce hierarchy levels on small screens (fewer distinct sizes)
### Layout & Spatial Design
**Compositional Balance:**
- Every screen should feel balanced
- Pay attention to visual weight and negative space
- Use generous negative space to focus attention
- Add sufficient margins and paddings for professional, spacious look
**Grid Discipline:**
- Maintain consistent underlying grid system
- Create sense of order while allowing meaningful exceptions
- Use grid/flex wrappers with `gap` for spacing
- Prioritize wrappers over direct margins/padding on children
**Spatial Relationships:**
- Group related elements through proximity, alignment, and shared attributes
- Use size, color, and spacing to highlight important elements
- Guide user focus through visual hierarchy
**Attention Guidance:**
- Design interfaces that guide user attention effectively
- Avoid cluttered interfaces where elements compete
- Create clear paths through the content
## Interaction Design
**Motion Specification:**
For detailed motion specs, see MOTION-SPEC.md (easing curves, duration tables, state-specific animations, implementation patterns).
### User Experience Patterns
**Core UX Principles:**
1. **Direct Manipulation**
- Users interact directly with content, not through abstract controls
- Examples:
- Drag & drop to reorder items (not up/down buttons)
- Inline editing (click to edit, not separate form)
- Sliders for ranges (not numeric input with +/-)
- Pinch/zoom gestures on mobile (not +/- buttons)
2. **Immediate Feedback**
- Every interaction provides instantaneous visual feedback (within 100ms)
- Types of feedback:
- **Visual**: Button pressed state, hover effects, color changes
- **Haptic**: Vibration on mobile (submit, error, success)
- **Audio**: Subtle sounds for critical actions (optional, user-controlled)
- **Loading**: Skeleton screens, spinners for >300ms operations
- **Success**: Checkmarks, green highlights, toast notifications
- **Error**: Red highlights, inline error messages, shake animations
3. **Consistent Behavior**
- Similar-looking elements behave similarly
- Examples:
- **Visual consistency**: All primary buttons have same colors, sizes, hover states
- **Behavioral consistency**: All modals close via X button, ESC key, and outside click
- **Interaction consistency**: All drag targets have same hover state and drop feedback
- **Pattern consistency**: All forms validate on blur and submit
4. **Forgiveness**
- Make errors difficult, but recovery easy
- **Prevention strategies**:
- Disable invalid actions (grey out unavailable buttons)
- Validate inputs inline (before submission)
- Confirm destructive actions (delete, overwrite)
- Auto-save in background (drafts, progress)
- **Recovery strategies**:
- Undo/redo for all state changes
- Soft deletes (trash/archive before permanent delete)
- Clear error messages with actionable fixes
- Preserve user input on errors (don't clear forms)
5. **Progressive Disclosure**
- Reveal details as needed rather than overwhelming users
- Levels of disclosure:
- **Summary**: Show essential info by default (card title, price, rating)
- **Details**: Expand to show more info (description, specs, reviews)
- **Advanced**: Hide complex options behind "Advanced settings" toggle
- Examples:
- Accordion: Start collapsed, expand on click
- Search filters: Show 3-5 common filters, hide rest behind "More filters"
- Settings: Basic settings visible, advanced behind "Show advanced"
**Modern UX Patterns:**
1. **Conversational Interfaces**
Prioritize natural language interaction where appropriate:
**Four types:**
- **Pure chat**: Full conversation (AI assistants, support bots)
- **Command palette**: Text-based shortcuts (Cmd+K, search everywhere)
- **Smart search**: Natural language queries (search "meetings next week" vs filtering)
- **Form alternatives**: Conversational data collection ("What's your name?" vs form fields)
**When to use:**
- Complex searches with multiple variables
- Task guidance (wizards, onboarding)
- Contextual help
- Quick actions (command palette)
**When NOT to use:**
- Simple forms (just use inputs)
- Precise control interfaces (design tools, dashboards)
- High-frequency repetitive tasks
2. **Adaptive Layouts**
Respond to user context automatically:
- **Time-based**: Dark mode at night, light during day
- **Device-based**: Simplified UI on mobile, full features on desktop
- **Connection-based**: Reduce images/video on slow connections
- **Usage-based**: Prioritize frequent actions, hide rarely-used features
Examples:
- Auto dark/light mode based on time or system preference
- Simplified mobile navigation (hamburger menu) vs full desktop nav
- Collapsed sidebar on small screens, expanded on large
3. **Bold Visual Expression**
Aesthetic flexibility based on chosen direction:
- Shadows ALLOWED and encouraged when intentional (dramatic shadows, soft elevation)
- Gradients ALLOWED for depth, accents, backgrounds, and atmosphere
- NO glass morphism effects (this is the one banned technique)
- NO Apple design mimicry (find your own voice)
- Focus on typography, color, spacing, AND visual effects to create hierarchy
- Create atmosphere: gradient meshes, noise textures, grain overlays, dramatic lighting
**Navigation:**
- Clear structure with intuitive navigation menus
- Implement breadcrumbs for deep hierarchies (more than 2 levels)
- Use standard UI patterns to reduce learning curve (hamburger menu, tab bars)
- Ensure predictable behavior (back button works, links look clickable)
- Maintain navigation context (highlight current page, preserve scroll position)
## Styling Implementation
### Component Library & Tools
**Component Library:**
- Strongly prefer shadcn components (v4, pre-installed in `@/components/ui`)
- Import individually: `import { Button } from "@/components/ui/button";`
- Use over plain HTML elements (`<Button>` over `<button>`)
- Avoid creating custom components with names that clash with shadcn
**Styling Engine:**
- Use Tailwind utility classes exclusively
- Adhere to theme variables in `index.css` via CSS custom properties
- Map variables in `@theme` (see `tailwind.config.js`)
- Use inline styles or CSS modules only when absolutely necessary
**Icons:**
- Use `@phosphor-icons/react` for buttons and inputs
- Example: `import { Plus } from "@phosphor-icons/react"; <Plus />`
- Use color for plain icon buttons
- Don't override default `size` or `weight` unless requested
**Notifications:**
- Use `sonner` for toasts
- Example: `import { toast } from 'sonner'`
**Loading States:**
- Always add loading states, spinners, placeholder animations
- Use skeletons until content renders
### Layout Implementation
**Spacing Strategy:**
- Use grid/flex wrappers with `gap` for spacing
- Prioritize wrappers over direct margins/padding on children
- Nest wrappers as needed for complex layouts
**Conditional Styling:**
- Use ternary operators or clsx/classnames utilities
- Example: `className={clsx('base-class', { 'active-class': isActive })}`
### Responsive Design
**Fluid Layouts:**
- Use relative units (%, em, rem) instead of fixed pixels
- Implement CSS Grid and Flexbox for flexible layouts
- Design mobile-first, then scale up
**Media Queries:**
- Use breakpoints based on content needs, not specific devices
- Test across range of devices and orientations
**Touch Targets:**
- Minimum 44x44 pixels for interactive elements
- Provide adequate spacing between touch targets
- Consider hover states for desktop, focus states for touch/keyboard
**Performance:**
- Optimize assets for mobile networks
- Use CSS animations over JavaScript
- Implement lazy loading for images and videos
## Accessibility Standards
**Core Requirements:**
- Follow WCAG 2.1 AA guidelines
- Ensure keyboard navigability for all interactive elements
- Minimum touch target size: 44×44px
- Use semantic HTML for screen reader compatibility
- Provide alternative text for images and non-text content
**Implementation Details:**
- Use descriptive variable and function names
- Event functions: prefix with "handle" (handleClick, handleKeyDown)
- Add accessibility attributes:
- `tabindex="0"` for custom interactive elements
- `aria-label` for buttons without text
- `role` attributes when semantic HTML isn't sufficient
- Ensure logical tab order
- Provide visible focus states
## Design Process & Testing
### Design Workflow
1. **Understand Context:**
- What problem are we solving?
- Who are the users and when will they use this?
- What are the success criteria?
2. **Explore Options:**
- Present 2-3 alternative approaches
- Explain trade-offs of each option
- Ask which direction resonates
3. **Implement Iteratively:**
- Start with structure and hierarchy
- Add visual polish progressively
- Test at each stage
4. **Validate:**
- Use playwright MCP to test visual changes
- Check across different screen sizes
- Verify accessibility
### Testing Checklist
**Visual Testing:**
- Use playwright MCP when available for automated testing
- Check responsive behavior at common breakpoints
- Verify touch targets on mobile
- Test with different content lengths (short, long, edge cases)
**Accessibility Testing:**
- Test keyboard navigation
- Verify screen reader compatibility
- Check color contrast ratios
- Ensure focus states are visible
**Cross-Device Testing:**
- Test on actual devices, not just emulators
- Check different browsers (Chrome, Firefox, Safari)
- Verify touch interactions on mobile
- Test landscape and portrait orientations
## Examples
### Example 1: Designing a Button
**Initial Question to Ask:**
```
Before I implement this button, I have a few design questions:
1. What's the primary action you want to emphasize?
2. Do you have brand colors in mind, or should I suggest options?
3. What emotion should this button convey? (urgent, calm, playful, professional)
```
**After Getting Approval, Implementation:**
```tsx
import { Button } from "@/components/ui/button";
import { ArrowRight } from "@phosphor-icons/react";
<Button
className="bg-slate-800 hover:bg-slate-700 text-white px-6 py-3 rounded-lg transition-colors duration-200"
>
Get Started
<ArrowRight className="ml-2" />
</Button>
```
### Example 2: Typography Hierarchy
**Question First:**
```
For this content hierarchy, I'm thinking:
- Headline: Large, bold, attention-grabbing
- Subheading: Medium, regular weight
- Body: Smaller, optimized for reading
Should we go bold and contemporary, or subtle and refined?
```
**Implementation After Approval:**
```tsx
<div className="space-y-4">
<h1 className="text-5xl font-bold tracking-tight text-slate-900">
Headline Here
</h1>
<h2 className="text-2xl text-slate-600">
Supporting subheading
</h2>
<p className="text-base leading-relaxed text-slate-700">
Body text optimized for readability with proper line height.
</p>
</div>
```
### Example 3: Unique Color Palette Suggestion
**Presenting Options:**
```
I'd like to suggest three color directions that break from typical SaaS patterns:
1. **Warm Earth Tones**
- Base: Warm grey (#E8E2DC)
- Accent: Terracotta (#C86E4B)
- For: Organic, trustworthy feel
2. **Cool Midnight**
- Base: Deep navy (#1A2332)
- Accent: Cyan (#4ECDC4)
- For: Modern, tech-forward feel
3. **Soft Pastels**
- Base: Soft pink (#FFE5E5)
- Accent: Sage green (#9DB5A4)
- For: Calm, approachable feel
Which direction feels right for your brand?
```
## Common Patterns to Avoid
**NEVER:**
- Use Inter, Roboto, Arial, Space Grotesk as primary fonts
- Use generic SaaS blue (#3B82F6) or purple gradients on white
- Copy Apple's design language or use glass morphism
- Create cookie-cutter layouts that look AI-generated
- Skip asking about context before designing
- Converge on common choices across generations (vary everything!)
- Use animations that delay user actions
- Create cluttered interfaces where elements compete
**ALWAYS:**
- Ask about purpose, tone, constraints, differentiation FIRST
- Then commit BOLDLY to a distinctive aesthetic direction
- Use unexpected, characterful typography choices
- Create atmosphere: shadows, gradients, textures, grain (when intentional)
- Dominant colors with sharp accents (not timid, evenly-distributed palettes)
- Provide immediate feedback for interactions
- Test with real devices
- Validate accessibility (it enables creativity, not limits it)
- Remember: Claude is capable of extraordinary creative work - don't hold back!
## Version History
- v2.0.0 (2025-11-22): Creative liberation update - bold aesthetics, shadows/gradients allowed, Design Thinking protocol
- v1.0.0 (2025-10-18): Initial release with comprehensive UI/UX design guidance
## References
For additional context, see:
- **Anthropic Frontend Aesthetics Cookbook**: https://github.com/anthropics/claude-cookbooks/blob/main/coding/prompting_for_frontend_aesthetics.ipynb
- WCAG 2.1 Guidelines: https://www.w3.org/WAI/WCAG21/quickref/
- Google Fonts: https://fonts.google.com/
- Tailwind CSS Docs: https://tailwindcss.com/docs
- Shadcn UI Components: https://ui.shadcn.com/
**Progressive Disclosure Files:**
- ACCESSIBILITY.md - Accessibility essentials (WCAG AA baseline)
- MOTION-SPEC.md - Animation timing and easing
- RESPONSIVE-DESIGN.md - Mobile-first breakpoints and patterns
@@ -1,223 +0,0 @@
---
name: interactive-portfolio
description: "Expert in building portfolios that actually land jobs and clients - not just showing work, but creating memorable experiences. Covers developer portfolios, designer portfolios, creative portfolios, and portfolios that convert visitors into opportunities. Use when: portfolio, personal website, showcase work, developer portfolio, designer portfolio."
source: vibeship-spawner-skills (Apache 2.0)
---
# Interactive Portfolio
**Role**: Portfolio Experience Designer
You know a portfolio isn't a resume - it's a first impression that needs
to convert. You balance creativity with usability. You understand that
hiring managers spend 30 seconds on each portfolio. You make those 30
seconds count. You help people stand out without being gimmicky.
## Capabilities
- Portfolio architecture
- Project showcase design
- Interactive case studies
- Personal branding for devs/designers
- Contact conversion
- Portfolio performance
- Work presentation
- Testimonial integration
## Patterns
### Portfolio Architecture
Structure that works for portfolios
**When to use**: When planning portfolio structure
```javascript
## Portfolio Architecture
### The 30-Second Test
In 30 seconds, visitors should know:
1. Who you are
2. What you do
3. Your best work
4. How to contact you
### Essential Sections
| Section | Purpose | Priority |
|---------|---------|----------|
| Hero | Hook + identity | Critical |
| Work/Projects | Prove skills | Critical |
| About | Personality + story | Important |
| Contact | Convert interest | Critical |
| Testimonials | Social proof | Nice to have |
| Blog/Writing | Thought leadership | Optional |
### Navigation Patterns
```
Option 1: Single page scroll
- Best for: Designers, creatives
- Works well with animations
- Mobile friendly
Option 2: Multi-page
- Best for: Lots of projects
- Individual case study pages
- Better for SEO
Option 3: Hybrid
- Main sections on one page
- Detailed case studies separate
- Best of both worlds
```
### Hero Section Formula
```
[Your name]
[What you do in one line]
[One line that differentiates you]
[CTA: View Work / Contact]
```
```
### Project Showcase
How to present work effectively
**When to use**: When building project sections
```javascript
## Project Showcase
### Project Card Elements
| Element | Purpose |
|---------|---------|
| Thumbnail | Visual hook |
| Title | What it is |
| One-liner | What you did |
| Tech/tags | Quick scan |
| Results | Proof of impact |
### Case Study Structure
```
1. Hero image/video
2. Project overview (2-3 sentences)
3. The challenge
4. Your role
5. Process highlights
6. Key decisions
7. Results/impact
8. Learnings (optional)
9. Links (live, GitHub, etc.)
```
### Showing Impact
| Instead of | Write |
|------------|-------|
| "Built a website" | "Increased conversions 40%" |
| "Designed UI" | "Reduced user drop-off 25%" |
| "Developed features" | "Shipped to 50K users" |
### Visual Presentation
- Device mockups for web/mobile
- Before/after comparisons
- Process artifacts (wireframes, etc.)
- Video walkthroughs for complex work
- Hover effects for engagement
```
### Developer Portfolio Specifics
What works for dev portfolios
**When to use**: When building developer portfolio
```javascript
## Developer Portfolio
### What Hiring Managers Look For
1. Code quality (GitHub link)
2. Real projects (not just tutorials)
3. Problem-solving ability
4. Communication skills
5. Technical depth
### Must-Haves
- GitHub profile link (cleaned up)
- Live project links
- Tech stack for each project
- Your specific contribution (for team projects)
### Project Selection
| Include | Avoid |
|---------|-------|
| Real problems solved | Tutorial clones |
| Side projects with users | Incomplete projects |
| Open source contributions | "Coming soon" |
| Technical challenges | Basic CRUD apps |
### Technical Showcase
```javascript
// Show code snippets that demonstrate:
- Clean architecture decisions
- Performance optimizations
- Clever solutions
- Testing approach
```
### Blog/Writing
- Technical deep dives
- Problem-solving stories
- Learning journeys
- Shows communication skills
```
## Anti-Patterns
### ❌ Template Portfolio
**Why bad**: Looks like everyone else.
No memorable impression.
Doesn't show creativity.
Easy to forget.
**Instead**: Add personal touches.
Custom design elements.
Unique project presentations.
Your voice in the copy.
### ❌ All Style No Substance
**Why bad**: Fancy animations, weak projects.
Style over substance.
Hiring managers see through it.
No proof of skills.
**Instead**: Projects first, style second.
Real work with real impact.
Quality over quantity.
Depth over breadth.
### ❌ Resume Website
**Why bad**: Boring, forgettable.
Doesn't use the medium.
No personality.
Lists instead of stories.
**Instead**: Show, don't tell.
Visual case studies.
Interactive elements.
Personality throughout.
## ⚠️ Sharp Edges
| Issue | Severity | Solution |
|-------|----------|----------|
| Portfolio more complex than your actual work | medium | ## Right-Sizing Your Portfolio |
| Portfolio looks great on desktop, broken on mobile | high | ## Mobile-First Portfolio |
| Visitors don't know what to do next | medium | ## Portfolio CTAs |
| Portfolio shows old or irrelevant work | medium | ## Portfolio Freshness |
## Related Skills
Works well with: `scroll-experience`, `3d-web-experience`, `landing-page-design`, `personal-branding`
-34
View File
@@ -1,34 +0,0 @@
{
"permissions": {
"allow": [
"Bash(powershell -Command \"$lines = Get-Content ''4-vitals-monitor.html''; $before = $lines[0..1757]; $after = $lines[2028..\\($lines.Length-1\\)]; \\($before + $after\\) | Set-Content ''4-vitals-monitor.html'' -Encoding UTF8\")",
"Bash(powershell -Command \"$lines = Get-Content ''4-vitals-monitor.html''; $before = $lines[0..1757]; $after = $lines[2028..\\($lines.Length-1\\)]; $result = $before + $after; $result | Set-Content ''4-vitals-monitor.html'' -Encoding UTF8\")",
"Bash(powershell -ExecutionPolicy Bypass -File:*)",
"Bash(del \"C:\\\\Users\\\\Andy\\\\Ralph Local\\\\Tasks\\\\cv-4-vitals-monitor\\\\remove-lines.ps1\")",
"Bash(start \"\" \"C:\\\\Users\\\\Andy\\\\Ralph Local\\\\Tasks\\\\cv-4-vitals-monitor\\\\4-vitals-monitor.html\")",
"Bash(npx skills find:*)",
"WebSearch",
"Bash(ls \"C:\\\\Users\\\\Andy\\\\Ralph Local\\\\Tasks\\\\New CV website\\\\designs\"\" 2>nul || echo \"Directory does not exist \")",
"Bash(npm run typecheck:*)",
"Bash(npm run dev:*)",
"Bash(npm run build:*)",
"Bash(dir:*)",
"mcp__playwright__browser_snapshot",
"mcp__playwright__browser_navigate",
"mcp__playwright__browser_take_screenshot",
"Bash(npm run lint:*)",
"Bash(curl:*)",
"mcp__playwright__browser_click",
"mcp__playwright__browser_wait_for",
"mcp__playwright__browser_evaluate",
"Bash(git add:*)",
"Bash(git commit -m \"$\\(cat <<''EOF''\nTask 4: Rebuild PatientBanner with premium fonts, tooltip, and animations\n\n- Replace font-inter with font-ui \\(Elvaro Grotesque\\) throughout banner\n- Add custom NHSNumberWithTooltip with Framer Motion animated reveal\n- Add AnimatePresence crossfade between full/condensed banner states\n- Animate mobile overflow menu enter/exit\n- Add SkipButton to App.tsx for boot/ECG phase skip\n- Add shadow-pmr-banner, focus ring styles, prefers-reduced-motion support\n- Fix mobile banner to use patient data instead of hardcoded values\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>\nEOF\n\\)\")",
"Bash(git commit:*)",
"Bash(ls:*)",
"Bash(tasklist:*)",
"Bash(npx -y serve -l 3333 .)",
"Bash(npx serve:*)",
"Bash(timeout /t 3 /nobreak)"
]
}
}
@@ -1,111 +0,0 @@
# Accessibility Essentials
Accessibility enables creativity - it's a foundation, not a limitation. WCAG 2.1 AA compliance.
## Core Principles (POUR)
- **Perceivable**: Content must be perceivable (alt text, contrast, captions)
- **Operable**: UI must be keyboard/touch accessible
- **Understandable**: Clear, predictable behavior
- **Robust**: Works with assistive technologies
## Contrast Requirements
| Element | Minimum Ratio |
|---------|---------------|
| Normal text | 4.5:1 |
| Large text (18pt+) | 3:1 |
| UI components | 3:1 |
**Tools**: Chrome DevTools Accessibility tab, WebAIM Contrast Checker
## Keyboard Navigation
```tsx
// All interactive elements need focus states
<button className="focus:ring-4 focus:ring-blue-500 focus:outline-none">
Accessible
</button>
// Custom elements need tabindex and key handlers
<div
role="button"
tabIndex={0}
onKeyDown={(e) => (e.key === 'Enter' || e.key === ' ') && handleClick()}
>
Custom Button
</div>
```
**Essentials:**
- Tab through entire interface
- Enter/Space activates elements
- Escape closes modals
- Visible focus indicators always
## Essential ARIA
```tsx
// Buttons without text
<button aria-label="Close dialog"><X /></button>
// Expandable elements
<button aria-expanded={isOpen} aria-controls="menu">Menu</button>
// Live regions for dynamic content
<div role="status" aria-live="polite">{statusMessage}</div>
<div role="alert" aria-live="assertive">{errorMessage}</div>
// Form errors
<input aria-invalid={hasError} aria-describedby="error-msg" />
{hasError && <p id="error-msg" role="alert">Error text</p>}
```
## Semantic HTML
```tsx
// Use semantic elements, not divs
<header><nav>...</nav></header>
<main><article><h1>...</h1></article></main>
<footer>...</footer>
// Heading hierarchy (never skip levels)
<h1>Page Title</h1>
<h2>Section</h2>
<h3>Subsection</h3>
```
## Touch Targets
- Minimum **44x44px** for all interactive elements
- Adequate spacing between targets
- `touch-manipulation` CSS for responsive touch
## Screen Reader Content
```tsx
// Hidden but announced
<span className="sr-only">Additional context</span>
// Skip link
<a href="#main" className="sr-only focus:not-sr-only">
Skip to main content
</a>
```
## Quick Checklist
- [ ] Keyboard: Can tab through everything
- [ ] Focus: Visible focus indicators
- [ ] Contrast: 4.5:1 for text
- [ ] Alt text: All images have appropriate alt
- [ ] Headings: Logical h1-h6 hierarchy
- [ ] Forms: Labels associated with inputs
- [ ] Errors: Announced to screen readers
- [ ] Touch: 44px minimum targets
## Resources
- [WCAG 2.1 Quick Reference](https://www.w3.org/WAI/WCAG21/quickref/)
- [WebAIM Contrast Checker](https://webaim.org/resources/contrastchecker/)
- [ARIA Authoring Practices](https://www.w3.org/WAI/ARIA/apg/)
@@ -1,577 +0,0 @@
# Design System Template
Meta-framework for understanding what's fixed, project-specific, and adaptable in your design system.
## Purpose
This template helps you distinguish between:
- **Fixed Elements**: Universal rules that never change
- **Project-Specific Elements**: Filled in for each project based on brand
- **Adaptable Elements**: Context-dependent implementations
---
## I. FIXED ELEMENTS
These foundations remain consistent across all projects, regardless of brand or context.
### 1. Spacing Scale
**Fixed System:**
```
4px, 8px, 12px, 16px, 24px, 32px, 48px, 64px, 96px
```
**Usage:**
- Margins, padding, gaps between elements
- Mathematical relationships ensure visual harmony
- Use multipliers of base unit (4px)
**Why Fixed:**
Consistent spacing creates visual rhythm regardless of brand personality.
### 2. Grid System
**Fixed Structure:**
- **12-column grid** for most layouts (divisible by 2, 3, 4, 6)
- **16-column grid** for data-heavy interfaces
- **Gutters**: 16px (mobile), 24px (tablet), 32px (desktop)
**Why Fixed:**
Grid provides structural order. Brand personality shows through color, typography, content—not grid structure.
### 3. Accessibility Standards
**Fixed Requirements:**
- **WCAG 2.1 AA** compliance minimum
- **Contrast**: 4.5:1 for normal text, 3:1 for large text
- **Touch targets**: Minimum 44×44px
- **Keyboard navigation**: All interactive elements accessible
- **Screen reader**: Semantic HTML, ARIA labels where needed
**Why Fixed:**
Accessibility is not negotiable. It's a baseline requirement for ethical, legal, and usable products.
### 4. Typography Hierarchy Logic
**Fixed Structure:**
- **Mathematical scaling**: 1.25x (major third) or 1.333x (perfect fourth)
- **Hierarchy levels**: Display → H1 → H2 → H3 → Body → Small → Caption
- **Line height**: 1.5x for body text, 1.2-1.3x for headlines
- **Line length**: 45-75 characters optimal
**Why Fixed:**
Mathematical relationships create predictable, harmonious hierarchy. Specific fonts change, but the logic doesn't.
### 5. Component Architecture
**Fixed Patterns:**
- **Button states**: Default, Hover, Active, Focus, Disabled
- **Form structure**: Label above input, error below, helper text optional
- **Modal pattern**: Overlay + centered content + close mechanism
- **Card structure**: Container → Header → Body → Footer (optional)
**Why Fixed:**
Users expect consistent component behavior. Architecture is fixed; appearance is project-specific.
### 6. Animation Timing Framework
**Fixed Physics Profiles:**
- **Lightweight** (icons, chips): 150ms
- **Standard** (cards, panels): 300ms
- **Weighty** (modals, pages): 500ms
**Fixed Easing:**
- **Ease-out**: Entrances (fast start, slow end)
- **Ease-in**: Exits (slow start, fast end)
- **Ease-in-out**: Transitions (smooth both ends)
**Why Fixed:**
Natural physics feel consistent across brands. Duration and easing create that feeling.
---
## II. PROJECT-SPECIFIC ELEMENTS
Fill in these for each project based on brand personality and purpose.
### 1. Brand Color System
**Template Structure:**
```
NEUTRALS (4-5 colors):
- Background lightest: _______ (e.g., slate-50 or warm-white)
- Surface: _______ (e.g., slate-100)
- Border/divider: _______ (e.g., slate-300)
- Text secondary: _______ (e.g., slate-600)
- Text primary: _______ (e.g., slate-900)
ACCENTS (1-3 colors):
- Primary (main CTA): _______ (e.g., teal-500)
- Secondary (alternative action): _______ (optional)
- Status colors:
- Success: _______ (green-ish)
- Warning: _______ (amber-ish)
- Error: _______ (red-ish)
- Info: _______ (blue-ish)
```
**Questions to Answer:**
- What emotion should the brand evoke? (Trust, excitement, calm, urgency)
- Warm or cool neutrals?
- Conservative or bold accents?
**Examples:**
**Project A: Fintech App**
```
Neutrals: Cool greys (slate-50 → slate-900)
Primary: Deep blue (#0A2463) trust, professionalism
Success: Muted green (#10B981)
Why: Financial products need trust, not playfulness
```
**Project B: Creative Community**
```
Neutrals: Warm greys with beige undertones
Primary: Coral (#FF6B6B) energy, creativity
Success: Teal (#06D6A0) fresh, unexpected
Why: Creative spaces should feel inviting, not corporate
```
**Project C: Healthcare Platform**
```
Neutrals: Pure greys (minimal color temperature)
Primary: Soft blue (#4A90E2) calm, clinical
Success: Medical green (#38A169)
Why: Healthcare needs clarity and calm, not distraction
```
### 2. Typography Pairing
**Template:**
```
HEADLINE FONT: _______
- Weight: _______ (e.g., Bold 700)
- Use case: H1, H2, display text
- Personality: _______ (geometric/humanist/serif/etc.)
BODY FONT: _______
- Weight: _______ (e.g., Regular 400, Medium 500)
- Use case: Paragraphs, UI text
- Personality: _______ (neutral/readable/efficient)
OPTIONAL ACCENT FONT: _______
- Weight: _______
- Use case: _______ (special headlines, callouts)
```
**Pairing Logic:**
- Serif + Sans-serif (classic, editorial)
- Geometric + Humanist (modern + warm)
- Display + System (distinctive + efficient)
**Examples:**
**Project A: Editorial Platform**
```
Headline: Playfair Display (Serif, Bold 700)
Body: Inter (Sans-serif, Regular 400)
Why: Serif headlines = trustworthy, editorial feel
```
**Project B: Tech Startup**
```
Headline: DM Sans (Sans-serif, Bold 700)
Body: DM Sans (Regular 400, Medium 500)
Why: Single-font system = modern, efficient, cohesive
```
**Project C: Luxury Brand**
```
Headline: Cormorant Garamond (Serif, Light 300)
Body: Lato (Sans-serif, Regular 400)
Why: Elegant serif + readable sans = sophisticated
```
### 3. Tone of Voice
**Template:**
```
BRAND PERSONALITY:
- Formal ↔ Casual: _______ (1-10 scale)
- Professional ↔ Friendly: _______ (1-10 scale)
- Serious ↔ Playful: _______ (1-10 scale)
- Authoritative ↔ Conversational: _______ (1-10 scale)
MICROCOPY EXAMPLES:
- Button label (submit form): _______
- Error message (invalid email): _______
- Success message (saved): _______
- Empty state: _______
ANIMATION PERSONALITY:
- Speed: _______ (quick/moderate/slow)
- Feel: _______ (precise/smooth/bouncy)
```
**Examples:**
**Project A: Banking App**
```
Personality: Formal (8), Professional (9), Serious (8)
Button: "Submit Application"
Error: "Email address format is invalid"
Success: "Application submitted successfully"
Animation: Quick (precise, efficient, no-nonsense)
```
**Project B: Social App**
```
Personality: Casual (8), Friendly (9), Playful (7)
Button: "Let's go!"
Error: "Hmm, that email doesn't look right"
Success: "Nice! You're all set 🎉"
Animation: Moderate (smooth, friendly bounce)
```
### 4. Animation Speed & Feel
**Template:**
```
SPEED PREFERENCE:
- UI interactions: _______ (100-150ms / 150-200ms / 200-300ms)
- State changes: _______ (200ms / 300ms / 400ms)
- Page transitions: _______ (300ms / 500ms / 700ms)
ANIMATION STYLE:
- Easing preference: _______ (sharp / standard / bouncy)
- Movement type: _______ (minimal / smooth / expressive)
```
**Examples:**
**Project A: Trading Platform**
```
Speed: Fast (100ms UI, 200ms states, 300ms pages)
Style: Sharp easing, minimal movement
Why: Traders need speed, not distraction
```
**Project B: Wellness App**
```
Speed: Slow (200ms UI, 400ms states, 500ms pages)
Style: Smooth easing, gentle movement
Why: Calm, relaxing experience matches brand
```
---
## III. ADAPTABLE ELEMENTS
Context-dependent implementations that vary based on use case.
### 1. Component Variations
**Button Variants:**
- **Primary**: Full background color (high emphasis)
- **Secondary**: Outline only (medium emphasis)
- **Tertiary**: Text only (low emphasis)
- **Destructive**: Red-ish (danger actions)
- **Ghost**: Minimal (navigation, toolbars)
**Adaptation Rules:**
- Primary: Main CTA, one per screen section
- Secondary: Alternative actions
- Tertiary: Less important actions, multiple allowed
- Use brand colors, but hierarchy logic is fixed
### 2. Responsive Breakpoints
**Fixed Ranges:**
- XS: 0-479px (small phones)
- SM: 480-767px (large phones)
- MD: 768-1023px (tablets)
- LG: 1024-1439px (laptops)
- XL: 1440px+ (desktop)
**Adaptable Implementations:**
**Simple Content Site:**
```
XS-SM: Single column
MD: 2 columns
LG-XL: 3 columns max
Why: Content-focused, don't overwhelm
```
**Dashboard/Data App:**
```
XS: Collapsed, cards stack
SM: Simplified sidebar
MD: Full sidebar + main content
LG-XL: Sidebar + main + right panel
Why: Data apps need more screen real estate
```
### 3. Dark Mode Palette
**Adaptation Strategy:**
Not a simple inversion. Dark mode needs adjusted contrast:
**Light Mode:**
```
Background: #FFFFFF (white)
Text: #0F172A (slate-900) → 21:1 contrast
```
**Dark Mode (Adapted):**
```
Background: #0F172A (slate-900)
Text: #E2E8F0 (slate-200) → 15.8:1 contrast (still AA, but softer)
```
**Why Adapt:**
Pure white on pure black is too harsh. Dark mode needs slightly lower contrast for eye comfort.
### 4. Loading States
**Context-Dependent:**
**Fast operations (<500ms):**
- No loading indicator (feels instant)
**Medium operations (500ms-2s):**
- Spinner or skeleton screen
**Long operations (>2s):**
- Progress bar with percentage
- Or: Skeleton + estimated time
**Interactive Operations:**
- Button shows spinner inside (don't disable, show state)
### 5. Error Handling Strategy
**Context-Dependent:**
**Form Errors:**
```
Validate: On blur (after user leaves field)
Display: Inline below field
Recovery: Clear error on fix
```
**API Errors:**
```
Transient (network): Show retry button
Permanent (404): Show helpful message + next steps
Critical (500): Contact support option
```
**Data Errors:**
```
Missing: Show empty state with action
Corrupt: Show error boundary with reload
Invalid: Highlight + explain what's wrong
```
---
## DECISION TREE
When implementing a feature, ask:
### Is this...
**FIXED?**
- Does it affect structure, accessibility, or universal UX?
- Examples: Spacing scale, grid, contrast ratios, component architecture
- **Action**: Use the fixed system, no variation
**PROJECT-SPECIFIC?**
- Does it express brand personality or purpose?
- Examples: Colors, typography, tone of voice, animation feel
- **Action**: Fill in the template for this project
**ADAPTABLE?**
- Does it depend on context, content, or use case?
- Examples: Component variants, responsive behavior, error handling
- **Action**: Choose appropriate variation based on context
---
## EXAMPLE: Implementing a "Submit" Button
### Fixed Elements (Always the same):
- Touch target: 44px minimum height
- Padding: 16px horizontal (from spacing scale)
- States: Default, Hover, Active, Focus, Disabled
- Animation: 150ms ease-out (lightweight profile)
### Project-Specific (Filled per project):
- **Project A (Bank)**: Dark blue background, white text, "Submit Application"
- **Project B (Social)**: Coral background, white text, "Let's Go!"
- **Project C (Healthcare)**: Soft blue background, white text, "Continue"
### Adaptable (Context-dependent):
- **Form context**: Primary button (full color)
- **Toolbar context**: Ghost button (text only)
- **Danger context**: Destructive variant (red-ish)
---
## VALIDATION CHECKLIST
Before finalizing a design, check:
### Fixed Elements
- [ ] Uses spacing scale (4/8/12/16/24/32/48/64/96px)
- [ ] Follows grid system (12 or 16 columns)
- [ ] Meets WCAG AA contrast (4.5:1 normal, 3:1 large)
- [ ] Touch targets ≥ 44px
- [ ] Typography follows mathematical scale
- [ ] Components follow standard architecture
### Project-Specific Elements
- [ ] Brand colors filled in and intentional
- [ ] Typography pairing chosen and justified
- [ ] Tone of voice defined and consistent
- [ ] Animation speed matches brand personality
### Adaptable Elements
- [ ] Component variants appropriate for context
- [ ] Responsive behavior fits content type
- [ ] Loading states match operation duration
- [ ] Error handling fits error type
---
## PROJECT KICKOFF TEMPLATE
Use this to start a new project:
```
PROJECT NAME: _______________________
PURPOSE: ____________________________
BRAND PERSONALITY:
- Primary emotion: _______
- Warm or cool: _______
- Formal or casual: _______
- Conservative or bold: _______
COLORS (fill the template):
- Neutral base: _______
- Primary accent: _______
- Status colors: _______ / _______ / _______
TYPOGRAPHY (fill the template):
- Headline font: _______
- Body font: _______
- Pairing rationale: _______
TONE:
- Button labels style: _______
- Error message style: _______
- Success message style: _______
ANIMATION:
- Speed preference: _______ (fast/moderate/slow)
- Feel preference: _______ (sharp/smooth/bouncy)
TARGET DEVICES:
- Primary: _______ (mobile/desktop/both)
- Secondary: _______
```
---
## MAINTAINING CONSISTENCY
### Documentation
- Keep this template updated as system evolves
- Document WHY choices were made, not just WHAT
### Communication
- Share with designers: "Here's what varies vs. what's fixed"
- Share with developers: "Here are the design tokens"
### Tooling
- Use CSS variables for project-specific values
- Use Tailwind config for spacing scale
- Use design tokens in Figma/Storybook
### Reviews
- Audit: Does new work follow fixed elements?
- Validate: Are project-specific elements intentional?
- Question: Are adaptations justified by context?
---
## EXAMPLES OF COMPLETE SYSTEMS
### System A: B2B SaaS (Conservative)
**Fixed**: Standard spacing, 12-col grid, WCAG AA, major third type scale
**Project-Specific**:
- Colors: Cool greys + corporate blue
- Typography: DM Sans (headlines + body)
- Tone: Professional, formal
- Animation: Quick, precise (150ms)
**Adaptable**:
- Dashboard gets multi-panel layout
- Forms are extensive (use progressive disclosure)
- Errors show detailed technical info
### System B: Consumer Social App (Playful)
**Fixed**: Same spacing/grid/accessibility/type logic
**Project-Specific**:
- Colors: Warm greys + vibrant coral
- Typography: Poppins (headlines) + Inter (body)
- Tone: Casual, friendly, playful
- Animation: Moderate, bouncy (200ms)
**Adaptable**:
- Mobile-first (most users on phones)
- Forms are minimal (progressive profiling)
- Errors are friendly, not technical
### System C: Healthcare Platform (Clinical)
**Fixed**: Same foundational structure
**Project-Specific**:
- Colors: Pure greys + medical blue
- Typography: System fonts (SF Pro / Segoe)
- Tone: Clear, authoritative, calm
- Animation: Slow, smooth (300ms)
**Adaptable**:
- Desktop-first (clinical use at workstations)
- Forms are complex (HIPAA compliance)
- Errors are precise with next steps
---
## KEY TAKEAWAY
**The system flexibility framework lets you:**
- Maintain consistency (fixed elements)
- Express brand personality (project-specific)
- Adapt to context (adaptable elements)
**Without this framework:**
- Designers reinvent spacing every project
- Components feel inconsistent across products
- Brand personality overrides accessibility
- Context-blind implementations feel wrong
**With this framework:**
- Speed: Start from proven foundations
- Consistency: Fixed elements guarantee it
- Flexibility: Express unique brand identity
- Context: Adapt without breaking system
@@ -1,72 +0,0 @@
# Motion Specification
Motion should surprise and delight while serving function. Animation is a creative tool.
## Easing Curves
| Easing | CSS | Use For |
|--------|-----|---------|
| **Ease-out** | `cubic-bezier(0.0, 0.0, 0.2, 1)` | Entrances, appearing |
| **Ease-in** | `cubic-bezier(0.4, 0.0, 1, 1)` | Exits, disappearing |
| **Ease-in-out** | `cubic-bezier(0.4, 0.0, 0.2, 1)` | State changes, transforms |
| **Spring** | `cubic-bezier(0.68, -0.55, 0.265, 1.55)` | Playful, attention-grabbing |
| **Linear** | `linear` | Spinners, continuous loops |
## Duration by Element Weight
| Weight | Duration | Examples |
|--------|----------|----------|
| **Lightweight** | 150ms | Icons, badges, chips |
| **Standard** | 300ms | Cards, panels, list items |
| **Weighty** | 500ms | Modals, page transitions |
## Duration by Interaction
| Interaction | Duration |
|-------------|----------|
| Button press | 100ms |
| Hover state | 150ms |
| Tooltip appear | 200ms |
| Tab switch | 250ms |
| Modal open | 300ms |
| Page transition | 400ms |
## Common Patterns
```tsx
// Hover transition (CSS)
<button className="transition-colors duration-150 ease-out hover:bg-blue-700">
// Fade + slide (Framer Motion)
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.3, ease: "easeOut" }}
/>
// Stagger children
<motion.ul variants={{ visible: { transition: { staggerChildren: 0.1 } } }}>
<motion.li variants={{ hidden: { opacity: 0 }, visible: { opacity: 1 } }} />
</motion.ul>
```
## Performance Rules
- Only animate `transform` and `opacity` (GPU-accelerated)
- Avoid animating `width`, `height`, `margin`, `padding`
- Keep durations under 500ms for UI interactions
- Respect `prefers-reduced-motion`:
```css
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
transition-duration: 0.01ms !important;
}
}
```
## Resources
- [Framer Motion](https://www.framer.com/motion/)
- [CSS Easing Functions](https://easings.net/)
@@ -1,90 +0,0 @@
# Responsive Design Essentials
Mobile-first approach: start with mobile, progressively enhance for larger screens.
## Breakpoints
| Range | Pixels | Devices | Strategy |
|-------|--------|---------|----------|
| **XS** | 0-479px | Small phones | Single column, stacked nav, 44px touch targets |
| **SM** | 480-767px | Large phones | Single column, bottom nav, simplified UI |
| **MD** | 768-1023px | Tablets | 2 columns possible, sidebar nav |
| **LG** | 1024-1439px | Laptops | Multi-column, full nav, desktop UI |
| **XL** | 1440px+ | Desktop | Max-width containers, multi-panel layouts |
## Tailwind Responsive
```tsx
// Mobile-first: base styles, then scale up
<div className="
w-full // mobile: full width
sm:w-1/2 // 480px+: half
md:w-1/3 // 768px+: third
lg:w-1/4 // 1024px+: quarter
">
// Responsive grid
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6">
// Responsive typography
<h1 className="text-3xl md:text-4xl lg:text-5xl">
// Show/hide by breakpoint
<div className="block md:hidden">Mobile only</div>
<div className="hidden md:block">Desktop only</div>
```
## Fluid Typography
```css
h1 { font-size: clamp(2rem, 5vw, 4rem); }
p { font-size: clamp(1rem, 2.5vw, 1.25rem); }
```
## Touch Targets
- Minimum **44x44px** for all interactive elements
- Use `touch-manipulation` to prevent 300ms tap delay
- Adequate spacing between targets
```tsx
<button className="min-w-[44px] min-h-[44px] touch-manipulation">
```
## Mobile Simplification
| Desktop | Mobile |
|---------|--------|
| Full nav bar | Hamburger menu |
| Side-by-side fields | Stacked fields |
| Multi-column grid | Single column |
| Inline buttons | Fixed bottom bar |
| Data table | Collapsed cards |
| Visible sidebar | Hidden/collapsible |
## Images
```tsx
// Responsive images
<img
srcSet="image-400w.jpg 400w, image-800w.jpg 800w, image-1200w.jpg 1200w"
sizes="(max-width: 640px) 100vw, (max-width: 1024px) 50vw, 33vw"
loading="lazy"
/>
// Next.js
<Image src="/hero.jpg" width={1200} height={600} priority className="w-full h-auto" />
```
## Testing
Test at these widths:
- 375px (iPhone SE)
- 390px (iPhone 14)
- 768px (iPad)
- 1024px (iPad Pro)
- 1280px+ (Desktop)
## Resources
- [Tailwind Responsive](https://tailwindcss.com/docs/responsive-design)
@@ -1,718 +0,0 @@
---
name: bencium-innovative-ux-designer
description: Create distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
metadata:
version: 2.0.0
---
# Innovative UX Designer
Create distinctive, production-grade frontend interfaces that avoid generic "AI slop" aesthetics. Implement real working code with exceptional attention to aesthetic details and creative choices. Expert UI/UX design skill that helps create unique, accessible, and thoughtfully designed interfaces. This skill emphasizes design decision collaboration, breaking away from generic patterns, and building interfaces that stand out while remaining functional and accessible.
This skill emphasizes **bold creative commitment**, breaking away from generic patterns, and building interfaces that are visually striking and memorable while remaining functional and accessible.
## Core Philosophy
**CRITICAL: Design Thinking Protocol**
Before coding, **ASK to understand context**, then **COMMIT BOLDLY** to a distinctive direction:
### Questions to Ask First
1. **Purpose**: What problem does this interface solve? Who uses it?
2. **Tone**: What aesthetic extreme fits? (see Tone Options below)
3. **Constraints**: Technical requirements (framework, performance, accessibility)?
4. **Differentiation**: What makes this UNFORGETTABLE? What's the one thing someone will remember?
### Tone Options (Pick an Extreme)
Choose a clear aesthetic direction and execute with precision:
- **Brutally minimal** - stripped to essence, bold typography, vast whitespace
- **Maximalist chaos** - layered, dense, visually rich, controlled disorder
- **Retro-futuristic** - vintage meets sci-fi, nostalgic tech aesthetics
- **Organic/natural** - soft edges, earthy colors, nature-inspired textures
- **Luxury/refined** - elegant spacing, premium typography, subtle details
- **Playful/toy-like** - bright colors, rounded shapes, delightful interactions
- **Editorial/magazine** - strong typography hierarchy, asymmetric layouts
- **Brutalist/raw** - exposed structure, harsh contrasts, intentionally rough
- **Art deco/geometric** - bold patterns, metallic accents, symmetric elegance
- **Soft/pastel** - gentle gradients, muted tones, calming atmosphere
- **Industrial/utilitarian** - functional, no-nonsense, mechanical precision
### After Getting Context
- **Commit fully** to the chosen direction - no half measures
- Present 2-3 alternative approaches with trade-offs
- Then implement with precision: production-grade, visually striking, memorable
## Foundational Design Principles
### Stand Out From Generic Patterns
**NEVER Use These AI-Generated Aesthetics:**
- **Fonts**: Inter, Roboto, Arial, system fonts as primary choice, Space Grotesk (overused by AI)
- **Colors**: Generic SaaS blue (#3B82F6), purple gradients on white backgrounds
- **Patterns**: Cookie-cutter layouts, predictable component arrangements
- **Effects**: Glass morphism, Apple design mimicry, liquid/blob backgrounds
- **Overall**: Anything that looks "Claude-generated" or machine-made
**Instead, Create Atmosphere:**
- Suggest photography, patterns, textures over flat solid colors
- Apply gradient meshes, noise textures, geometric patterns
- Use layered transparencies, dramatic shadows, decorative borders
- Consider custom cursors, grain overlays, contextual effects
- Think beyond typical patterns - you can step off the written path
**Draw Inspiration From:**
- Modern landing pages (Perplexity, Comet Browser, Dia Browser)
- Framer templates and their innovative approaches
- Leading brand design studios
- Historical design movements (Bauhaus, Otl Aicher, Braun) - but as inspiration, not imitation
- Beautiful background animations (CSS, SVG) - slow, looping, subtle
**Visual Interest Strategies:**
- Unique color pairs that aren't typical
- Animation effects that feel fresh
- Background patterns that add depth without distraction
- Typography combinations that create contrast
- Visual assets that tell a story
### Core Design Philosophy
1. **Simplicity Through Reduction**
- Identify the essential purpose and eliminate distractions
- Begin with complexity, then deliberately remove until reaching the simplest effective solution
- Every element must justify its existence
2. **Material Honesty**
- Digital materials have unique properties - embrace them
- Buttons communicate affordance through color, spacing, typography, AND shadows when intentional
- Cards can use borders, background differentiation, OR dramatic shadows for depth
- Animations follow real-world physics principles adapted to digital responsiveness
**Examples:**
- Clickable: Use distinct colors, hover state changes, cursor feedback, subtle lift effects
- Containers: Use borders, background shifts, generous padding, OR shadow depth
- Hierarchy: Use scale, weight, spacing, AND elevation when it serves the aesthetic
3. **Functional Layering**
- Create hierarchy through typography scale, color contrast, and spatial relationships
- Layer information conceptually (primary → secondary → tertiary)
- Use shadows and gradients INTENTIONALLY when they serve the aesthetic direction
- Embrace functional depth: modals over content, dropdowns over UI
- Avoid: glass morphism, Apple mimicry (but shadows/gradients are tools, not enemies)
4. **Obsessive Detail**
- Consider every pixel, interaction, and transition
- Excellence emerges from hundreds of small, intentional decisions
- Balance: Details should serve simplicity, not complexity
- When detail conflicts with clarity, clarity wins
5. **Coherent Design Language**
- Every element should visually communicate its function
- Elements should feel part of a unified system
- Nothing should feel arbitrary
6. **Invisibility of Technology**
- The best technology disappears
- Users should focus on content and goals, not on understanding the interface
### What This Means in Practice
**Color Usage:**
- Base palette: 4-5 neutral shades (backgrounds, borders, text)
- Accent palette: 1-3 bold colors (CTAs, status, emphasis)
- Neutrals are slightly desaturated, warm or cool based on brand intent
- Accents are saturated enough to create clear contrast
**Typography:**
- Headlines: Emotional, attention-grabbing, UNEXPECTED (personality over pure legibility)
- Body/UI: Functional, highly legible (clarity over expression)
- 2-3 typefaces maximum, but make them CHARACTERFUL and distinctive
- Clear mathematical scale (e.g., 1.25x between sizes)
- NEVER default to Inter, Roboto, or Space Grotesk - find unique fonts
**Animation:**
- Purposeful: Guides attention, establishes relationships, provides feedback
- Subtle: Felt rather than seen (100-300ms for most interactions)
- Physics-informed: Natural easing, appropriate mass/momentum
**Spacing:**
- Generous negative space creates clarity and breathing room
- Mathematical relationships (e.g., 4px base, 8/16/24/32/48px scale)
- Consistent application creates visual rhythm
### Design Decision Checklist
Before presenting any design, verify:
1. **Purpose**: Does every element serve a clear function?
2. **Hierarchy**: Is visual importance aligned with content importance?
3. **Consistency**: Do similar elements look and behave similarly?
4. **Accessibility**: Does it meet WCAG AA standards? (contrast, touch targets, keyboard nav)
5. **Responsiveness**: Does it work on mobile, tablet, desktop?
6. **Uniqueness**: Does this break from generic SaaS patterns?
7. **Approval**: Have I asked before implementing colors, fonts, sizes, layouts?
**Design System Framework:**
For understanding what's fixed (universal rules), project-specific (brand personality), and adaptable (context-dependent) in your design system, think of a design system.
## Visual Design Standards
### Color & Contrast
**Color System Architecture:**
Every interface needs two color roles:
1. **Base/Neutral Palette (4-5 colors):**
- Backgrounds (lightest)
- Surface colors (cards, inputs)
- Borders and dividers
- Text (darkest)
- Use slightly desaturated, warm or cool greys based on brand
2. **Accent Palette (1-3 colors):**
- Primary action (CTA buttons)
- Status indicators (success, warning, error, info)
- Focus/hover states
- Use saturated colors for clear contrast against neutrals
**Palette Structure Example:**
```
Neutrals: slate-50, slate-100, slate-300, slate-700, slate-900
Accents: teal-500 (primary), amber-500 (warning), red-500 (error)
```
**Color Application Rules:**
- **Backgrounds**: Lightest neutral (slate-50 or white)
- **Text**: Darkest neutral for primary text (slate-900), mid-tone for secondary (slate-600)
- **Buttons (primary)**: Accent color with white text
- **Buttons (secondary)**: Neutral with border and dark text
- **Status indicators**: Specific accent (green=success, red=error, amber=warning, blue=info)
- **Interactive states**:
- Hover: Darken by 10-15% or shift hue slightly
- Focus: Use ring/outline in accent color
- Disabled: Reduce opacity to 40-50% and remove hover effects
**Color Relationships:**
Choose warm or cool intentionally based on brand:
- **Warm greys** (beige/brown undertones): Organic, approachable, trustworthy
- **Cool greys** (blue undertones): Modern, tech-forward, professional
Accent colors should have clear contrast with both:
- Light backgrounds (for buttons on white)
- Dark text (if used as backgrounds for white text)
**Intentional Color Usage:**
- Every color must serve a purpose (hierarchy, function, status, or action)
- Avoid decorative colors that don't communicate meaning
- Maintain consistency: same color = same meaning throughout
**Accessibility:**
- Ensure sufficient contrast for color-blind users
- Follow WCAG 2.1 AA: minimum 4.5:1 for normal text, 3:1 for large text
- Don't rely on color alone to convey information (add icons or labels)
**Unique Color Strategy:**
To stand out from generic patterns:
- NEVER use default SaaS blue (#3B82F6) or purple gradients on white
- Use unexpected neutrals: warm greys, soft off-whites, deep charcoals, rich blacks
- Pair neutrals with distinctive accents: terracotta + charcoal, sage + navy, coral + slate
- Dominant colors with SHARP accents outperform timid, evenly-distributed palettes
- Test combinations against "does this look AI-generated?" filter
- Vary between light and dark themes - no design should look the same
**Create Atmosphere with Color:**
- Gradient meshes for depth and visual interest
- Noise textures and grain overlays for tactile feel
- Layered transparencies for dimension
- Dramatic shadows for emphasis and drama
### Typography Excellence
**Typography Philosophy:**
Typography is a primary design element that conveys personality and hierarchy.
**Functional vs Emotional Typography:**
- **Headlines/Display**: Prioritize emotion, personality, attention (legibility secondary)
- **Body Text**: Prioritize legibility, reading comfort, accessibility
- **UI/Labels**: Prioritize clarity, scannability, consistency
**Font Selection:**
- Use 2-3 typefaces maximum, but make them UNEXPECTED and characterful
- Limit to 3 weights per typeface (e.g., Regular 400, Medium 500, Bold 700)
- Prefer variable fonts for fine-tuned control and performance
**NEVER Use These Fonts as Primary:**
- Inter (overused by AI and generic SaaS)
- Roboto (too generic)
- Arial/Helvetica (default fallback vibes)
- Space Grotesk (AI generation favorite)
- System fonts as primary choice (only as fallback)
**Font Version Usage:**
- **Display version**: Headlines and hero text only - BE BOLD
- **Text version**: Paragraphs and long-form content - legibility matters
- **Caption/Micro**: Small UI labels (1-2 lines, non-critical info)
**Find Distinctive Fonts:**
- Google Fonts for web - but dig deeper than page 1
- Type foundries for unique options
- Choose fonts that serve your CHOSEN AESTHETIC DIRECTION
- Pair distinctive display font with refined body font
**Typographic Scale:**
Use mathematical relationships for size hierarchy:
- **Ratio**: Major third (1.25x) for moderate contrast, Perfect fourth (1.333x) for dramatic
- **Base size**: 16px (1rem) for body text
- **Example scale (1.25x)**:
```
xs: 0.64rem (10px)
sm: 0.8rem (13px)
base: 1rem (16px)
lg: 1.25rem (20px)
xl: 1.563rem (25px)
2xl: 1.953rem (31px)
3xl: 2.441rem (39px)
4xl: 3.052rem (49px)
5xl: 3.815rem (61px)
```
**Typographic Hierarchy:**
- Create clear visual distinction between levels
- Headlines, subheadings, body, captions should each have distinct size/weight
- Use combination of size, weight, and color for hierarchy
**Spacing & Readability:**
- **Line height**: 1.5x font size for body text (e.g., 16px text = 24px line-height)
- **Line length**: 45-75 characters optimal for readability (60-70 ideal)
- **Paragraph spacing**: 1-1.5em between paragraphs
- **Letter spacing (tracking)**:
- Larger text (headlines): Slightly tighter (-0.02em to -0.05em)
- Normal text (body): Default (0)
- Small text (captions): Slightly looser (+0.01em to +0.03em)
- General rule: As size increases, reduce tracking; as size decreases, increase tracking
**Font Pairing Logic:**
When using multiple typefaces, create contrast through:
- **Category contrast**: Serif + Sans-serif (classic, clear distinction)
- **Weight contrast**: Light + Bold (dynamic, energetic)
- **Personality contrast**: Geometric + Humanist (modern + warm)
Examples:
- Serif headlines + Sans body (editorial, trustworthy)
- Display headlines + System body (distinctive + efficient)
- Bold sans headlines + Light sans body (modern, clean)
**UI Typography:**
Specific guidance for interface elements:
- **Button text**: Semi-Bold (600), 14-16px, consistent casing (all-caps OR title case)
- **Form labels**: Regular (400), 14px, positioned above input
- **Form input text**: Regular (400), 16px minimum (prevents iOS zoom on focus)
- **Placeholder text**: Light (300) or desaturated color, same size as input
- **Error messages**: Regular (400), 12-14px, color-coded (red-ish)
**Responsive Typography:**
Scale type sizes across breakpoints:
```tsx
// Example with Tailwind
<h1 className="text-3xl md:text-4xl lg:text-5xl">
Responsive Headline
</h1>
// Or with CSS clamp (fluid)
h1 {
font-size: clamp(2rem, 5vw, 4rem);
}
```
Reduce sizes on mobile (20-30% smaller than desktop)
Reduce hierarchy levels on small screens (fewer distinct sizes)
### Layout & Spatial Design
**Compositional Balance:**
- Every screen should feel balanced
- Pay attention to visual weight and negative space
- Use generous negative space to focus attention
- Add sufficient margins and paddings for professional, spacious look
**Grid Discipline:**
- Maintain consistent underlying grid system
- Create sense of order while allowing meaningful exceptions
- Use grid/flex wrappers with `gap` for spacing
- Prioritize wrappers over direct margins/padding on children
**Spatial Relationships:**
- Group related elements through proximity, alignment, and shared attributes
- Use size, color, and spacing to highlight important elements
- Guide user focus through visual hierarchy
**Attention Guidance:**
- Design interfaces that guide user attention effectively
- Avoid cluttered interfaces where elements compete
- Create clear paths through the content
## Interaction Design
**Motion Specification:**
For detailed motion specs, see MOTION-SPEC.md (easing curves, duration tables, state-specific animations, implementation patterns).
### User Experience Patterns
**Core UX Principles:**
1. **Direct Manipulation**
- Users interact directly with content, not through abstract controls
- Examples:
- Drag & drop to reorder items (not up/down buttons)
- Inline editing (click to edit, not separate form)
- Sliders for ranges (not numeric input with +/-)
- Pinch/zoom gestures on mobile (not +/- buttons)
2. **Immediate Feedback**
- Every interaction provides instantaneous visual feedback (within 100ms)
- Types of feedback:
- **Visual**: Button pressed state, hover effects, color changes
- **Haptic**: Vibration on mobile (submit, error, success)
- **Audio**: Subtle sounds for critical actions (optional, user-controlled)
- **Loading**: Skeleton screens, spinners for >300ms operations
- **Success**: Checkmarks, green highlights, toast notifications
- **Error**: Red highlights, inline error messages, shake animations
3. **Consistent Behavior**
- Similar-looking elements behave similarly
- Examples:
- **Visual consistency**: All primary buttons have same colors, sizes, hover states
- **Behavioral consistency**: All modals close via X button, ESC key, and outside click
- **Interaction consistency**: All drag targets have same hover state and drop feedback
- **Pattern consistency**: All forms validate on blur and submit
4. **Forgiveness**
- Make errors difficult, but recovery easy
- **Prevention strategies**:
- Disable invalid actions (grey out unavailable buttons)
- Validate inputs inline (before submission)
- Confirm destructive actions (delete, overwrite)
- Auto-save in background (drafts, progress)
- **Recovery strategies**:
- Undo/redo for all state changes
- Soft deletes (trash/archive before permanent delete)
- Clear error messages with actionable fixes
- Preserve user input on errors (don't clear forms)
5. **Progressive Disclosure**
- Reveal details as needed rather than overwhelming users
- Levels of disclosure:
- **Summary**: Show essential info by default (card title, price, rating)
- **Details**: Expand to show more info (description, specs, reviews)
- **Advanced**: Hide complex options behind "Advanced settings" toggle
- Examples:
- Accordion: Start collapsed, expand on click
- Search filters: Show 3-5 common filters, hide rest behind "More filters"
- Settings: Basic settings visible, advanced behind "Show advanced"
**Modern UX Patterns:**
1. **Conversational Interfaces**
Prioritize natural language interaction where appropriate:
**Four types:**
- **Pure chat**: Full conversation (AI assistants, support bots)
- **Command palette**: Text-based shortcuts (Cmd+K, search everywhere)
- **Smart search**: Natural language queries (search "meetings next week" vs filtering)
- **Form alternatives**: Conversational data collection ("What's your name?" vs form fields)
**When to use:**
- Complex searches with multiple variables
- Task guidance (wizards, onboarding)
- Contextual help
- Quick actions (command palette)
**When NOT to use:**
- Simple forms (just use inputs)
- Precise control interfaces (design tools, dashboards)
- High-frequency repetitive tasks
2. **Adaptive Layouts**
Respond to user context automatically:
- **Time-based**: Dark mode at night, light during day
- **Device-based**: Simplified UI on mobile, full features on desktop
- **Connection-based**: Reduce images/video on slow connections
- **Usage-based**: Prioritize frequent actions, hide rarely-used features
Examples:
- Auto dark/light mode based on time or system preference
- Simplified mobile navigation (hamburger menu) vs full desktop nav
- Collapsed sidebar on small screens, expanded on large
3. **Bold Visual Expression**
Aesthetic flexibility based on chosen direction:
- Shadows ALLOWED and encouraged when intentional (dramatic shadows, soft elevation)
- Gradients ALLOWED for depth, accents, backgrounds, and atmosphere
- NO glass morphism effects (this is the one banned technique)
- NO Apple design mimicry (find your own voice)
- Focus on typography, color, spacing, AND visual effects to create hierarchy
- Create atmosphere: gradient meshes, noise textures, grain overlays, dramatic lighting
**Navigation:**
- Clear structure with intuitive navigation menus
- Implement breadcrumbs for deep hierarchies (more than 2 levels)
- Use standard UI patterns to reduce learning curve (hamburger menu, tab bars)
- Ensure predictable behavior (back button works, links look clickable)
- Maintain navigation context (highlight current page, preserve scroll position)
## Styling Implementation
### Component Library & Tools
**Component Library:**
- Strongly prefer shadcn components (v4, pre-installed in `@/components/ui`)
- Import individually: `import { Button } from "@/components/ui/button";`
- Use over plain HTML elements (`<Button>` over `<button>`)
- Avoid creating custom components with names that clash with shadcn
**Styling Engine:**
- Use Tailwind utility classes exclusively
- Adhere to theme variables in `index.css` via CSS custom properties
- Map variables in `@theme` (see `tailwind.config.js`)
- Use inline styles or CSS modules only when absolutely necessary
**Icons:**
- Use `@phosphor-icons/react` for buttons and inputs
- Example: `import { Plus } from "@phosphor-icons/react"; <Plus />`
- Use color for plain icon buttons
- Don't override default `size` or `weight` unless requested
**Notifications:**
- Use `sonner` for toasts
- Example: `import { toast } from 'sonner'`
**Loading States:**
- Always add loading states, spinners, placeholder animations
- Use skeletons until content renders
### Layout Implementation
**Spacing Strategy:**
- Use grid/flex wrappers with `gap` for spacing
- Prioritize wrappers over direct margins/padding on children
- Nest wrappers as needed for complex layouts
**Conditional Styling:**
- Use ternary operators or clsx/classnames utilities
- Example: `className={clsx('base-class', { 'active-class': isActive })}`
### Responsive Design
**Fluid Layouts:**
- Use relative units (%, em, rem) instead of fixed pixels
- Implement CSS Grid and Flexbox for flexible layouts
- Design mobile-first, then scale up
**Media Queries:**
- Use breakpoints based on content needs, not specific devices
- Test across range of devices and orientations
**Touch Targets:**
- Minimum 44x44 pixels for interactive elements
- Provide adequate spacing between touch targets
- Consider hover states for desktop, focus states for touch/keyboard
**Performance:**
- Optimize assets for mobile networks
- Use CSS animations over JavaScript
- Implement lazy loading for images and videos
## Accessibility Standards
**Core Requirements:**
- Follow WCAG 2.1 AA guidelines
- Ensure keyboard navigability for all interactive elements
- Minimum touch target size: 44×44px
- Use semantic HTML for screen reader compatibility
- Provide alternative text for images and non-text content
**Implementation Details:**
- Use descriptive variable and function names
- Event functions: prefix with "handle" (handleClick, handleKeyDown)
- Add accessibility attributes:
- `tabindex="0"` for custom interactive elements
- `aria-label` for buttons without text
- `role` attributes when semantic HTML isn't sufficient
- Ensure logical tab order
- Provide visible focus states
## Design Process & Testing
### Design Workflow
1. **Understand Context:**
- What problem are we solving?
- Who are the users and when will they use this?
- What are the success criteria?
2. **Explore Options:**
- Present 2-3 alternative approaches
- Explain trade-offs of each option
- Ask which direction resonates
3. **Implement Iteratively:**
- Start with structure and hierarchy
- Add visual polish progressively
- Test at each stage
4. **Validate:**
- Use playwright MCP to test visual changes
- Check across different screen sizes
- Verify accessibility
### Testing Checklist
**Visual Testing:**
- Use playwright MCP when available for automated testing
- Check responsive behavior at common breakpoints
- Verify touch targets on mobile
- Test with different content lengths (short, long, edge cases)
**Accessibility Testing:**
- Test keyboard navigation
- Verify screen reader compatibility
- Check color contrast ratios
- Ensure focus states are visible
**Cross-Device Testing:**
- Test on actual devices, not just emulators
- Check different browsers (Chrome, Firefox, Safari)
- Verify touch interactions on mobile
- Test landscape and portrait orientations
## Examples
### Example 1: Designing a Button
**Initial Question to Ask:**
```
Before I implement this button, I have a few design questions:
1. What's the primary action you want to emphasize?
2. Do you have brand colors in mind, or should I suggest options?
3. What emotion should this button convey? (urgent, calm, playful, professional)
```
**After Getting Approval, Implementation:**
```tsx
import { Button } from "@/components/ui/button";
import { ArrowRight } from "@phosphor-icons/react";
<Button
className="bg-slate-800 hover:bg-slate-700 text-white px-6 py-3 rounded-lg transition-colors duration-200"
>
Get Started
<ArrowRight className="ml-2" />
</Button>
```
### Example 2: Typography Hierarchy
**Question First:**
```
For this content hierarchy, I'm thinking:
- Headline: Large, bold, attention-grabbing
- Subheading: Medium, regular weight
- Body: Smaller, optimized for reading
Should we go bold and contemporary, or subtle and refined?
```
**Implementation After Approval:**
```tsx
<div className="space-y-4">
<h1 className="text-5xl font-bold tracking-tight text-slate-900">
Headline Here
</h1>
<h2 className="text-2xl text-slate-600">
Supporting subheading
</h2>
<p className="text-base leading-relaxed text-slate-700">
Body text optimized for readability with proper line height.
</p>
</div>
```
### Example 3: Unique Color Palette Suggestion
**Presenting Options:**
```
I'd like to suggest three color directions that break from typical SaaS patterns:
1. **Warm Earth Tones**
- Base: Warm grey (#E8E2DC)
- Accent: Terracotta (#C86E4B)
- For: Organic, trustworthy feel
2. **Cool Midnight**
- Base: Deep navy (#1A2332)
- Accent: Cyan (#4ECDC4)
- For: Modern, tech-forward feel
3. **Soft Pastels**
- Base: Soft pink (#FFE5E5)
- Accent: Sage green (#9DB5A4)
- For: Calm, approachable feel
Which direction feels right for your brand?
```
## Common Patterns to Avoid
**NEVER:**
- Use Inter, Roboto, Arial, Space Grotesk as primary fonts
- Use generic SaaS blue (#3B82F6) or purple gradients on white
- Copy Apple's design language or use glass morphism
- Create cookie-cutter layouts that look AI-generated
- Skip asking about context before designing
- Converge on common choices across generations (vary everything!)
- Use animations that delay user actions
- Create cluttered interfaces where elements compete
**ALWAYS:**
- Ask about purpose, tone, constraints, differentiation FIRST
- Then commit BOLDLY to a distinctive aesthetic direction
- Use unexpected, characterful typography choices
- Create atmosphere: shadows, gradients, textures, grain (when intentional)
- Dominant colors with sharp accents (not timid, evenly-distributed palettes)
- Provide immediate feedback for interactions
- Test with real devices
- Validate accessibility (it enables creativity, not limits it)
- Remember: Claude is capable of extraordinary creative work - don't hold back!
## Version History
- v2.0.0 (2025-11-22): Creative liberation update - bold aesthetics, shadows/gradients allowed, Design Thinking protocol
- v1.0.0 (2025-10-18): Initial release with comprehensive UI/UX design guidance
## References
For additional context, see:
- **Anthropic Frontend Aesthetics Cookbook**: https://github.com/anthropics/claude-cookbooks/blob/main/coding/prompting_for_frontend_aesthetics.ipynb
- WCAG 2.1 Guidelines: https://www.w3.org/WAI/WCAG21/quickref/
- Google Fonts: https://fonts.google.com/
- Tailwind CSS Docs: https://tailwindcss.com/docs
- Shadcn UI Components: https://ui.shadcn.com/
**Progressive Disclosure Files:**
- ACCESSIBILITY.md - Accessibility essentials (WCAG AA baseline)
- MOTION-SPEC.md - Animation timing and easing
- RESPONSIVE-DESIGN.md - Mobile-first breakpoints and patterns
@@ -1,223 +0,0 @@
---
name: interactive-portfolio
description: "Expert in building portfolios that actually land jobs and clients - not just showing work, but creating memorable experiences. Covers developer portfolios, designer portfolios, creative portfolios, and portfolios that convert visitors into opportunities. Use when: portfolio, personal website, showcase work, developer portfolio, designer portfolio."
source: vibeship-spawner-skills (Apache 2.0)
---
# Interactive Portfolio
**Role**: Portfolio Experience Designer
You know a portfolio isn't a resume - it's a first impression that needs
to convert. You balance creativity with usability. You understand that
hiring managers spend 30 seconds on each portfolio. You make those 30
seconds count. You help people stand out without being gimmicky.
## Capabilities
- Portfolio architecture
- Project showcase design
- Interactive case studies
- Personal branding for devs/designers
- Contact conversion
- Portfolio performance
- Work presentation
- Testimonial integration
## Patterns
### Portfolio Architecture
Structure that works for portfolios
**When to use**: When planning portfolio structure
```javascript
## Portfolio Architecture
### The 30-Second Test
In 30 seconds, visitors should know:
1. Who you are
2. What you do
3. Your best work
4. How to contact you
### Essential Sections
| Section | Purpose | Priority |
|---------|---------|----------|
| Hero | Hook + identity | Critical |
| Work/Projects | Prove skills | Critical |
| About | Personality + story | Important |
| Contact | Convert interest | Critical |
| Testimonials | Social proof | Nice to have |
| Blog/Writing | Thought leadership | Optional |
### Navigation Patterns
```
Option 1: Single page scroll
- Best for: Designers, creatives
- Works well with animations
- Mobile friendly
Option 2: Multi-page
- Best for: Lots of projects
- Individual case study pages
- Better for SEO
Option 3: Hybrid
- Main sections on one page
- Detailed case studies separate
- Best of both worlds
```
### Hero Section Formula
```
[Your name]
[What you do in one line]
[One line that differentiates you]
[CTA: View Work / Contact]
```
```
### Project Showcase
How to present work effectively
**When to use**: When building project sections
```javascript
## Project Showcase
### Project Card Elements
| Element | Purpose |
|---------|---------|
| Thumbnail | Visual hook |
| Title | What it is |
| One-liner | What you did |
| Tech/tags | Quick scan |
| Results | Proof of impact |
### Case Study Structure
```
1. Hero image/video
2. Project overview (2-3 sentences)
3. The challenge
4. Your role
5. Process highlights
6. Key decisions
7. Results/impact
8. Learnings (optional)
9. Links (live, GitHub, etc.)
```
### Showing Impact
| Instead of | Write |
|------------|-------|
| "Built a website" | "Increased conversions 40%" |
| "Designed UI" | "Reduced user drop-off 25%" |
| "Developed features" | "Shipped to 50K users" |
### Visual Presentation
- Device mockups for web/mobile
- Before/after comparisons
- Process artifacts (wireframes, etc.)
- Video walkthroughs for complex work
- Hover effects for engagement
```
### Developer Portfolio Specifics
What works for dev portfolios
**When to use**: When building developer portfolio
```javascript
## Developer Portfolio
### What Hiring Managers Look For
1. Code quality (GitHub link)
2. Real projects (not just tutorials)
3. Problem-solving ability
4. Communication skills
5. Technical depth
### Must-Haves
- GitHub profile link (cleaned up)
- Live project links
- Tech stack for each project
- Your specific contribution (for team projects)
### Project Selection
| Include | Avoid |
|---------|-------|
| Real problems solved | Tutorial clones |
| Side projects with users | Incomplete projects |
| Open source contributions | "Coming soon" |
| Technical challenges | Basic CRUD apps |
### Technical Showcase
```javascript
// Show code snippets that demonstrate:
- Clean architecture decisions
- Performance optimizations
- Clever solutions
- Testing approach
```
### Blog/Writing
- Technical deep dives
- Problem-solving stories
- Learning journeys
- Shows communication skills
```
## Anti-Patterns
### ❌ Template Portfolio
**Why bad**: Looks like everyone else.
No memorable impression.
Doesn't show creativity.
Easy to forget.
**Instead**: Add personal touches.
Custom design elements.
Unique project presentations.
Your voice in the copy.
### ❌ All Style No Substance
**Why bad**: Fancy animations, weak projects.
Style over substance.
Hiring managers see through it.
No proof of skills.
**Instead**: Projects first, style second.
Real work with real impact.
Quality over quantity.
Depth over breadth.
### ❌ Resume Website
**Why bad**: Boring, forgettable.
Doesn't use the medium.
No personality.
Lists instead of stories.
**Instead**: Show, don't tell.
Visual case studies.
Interactive elements.
Personality throughout.
## ⚠️ Sharp Edges
| Issue | Severity | Solution |
|-------|----------|----------|
| Portfolio more complex than your actual work | medium | ## Right-Sizing Your Portfolio |
| Portfolio looks great on desktop, broken on mobile | high | ## Mobile-First Portfolio |
| Visitors don't know what to do next | medium | ## Portfolio CTAs |
| Portfolio shows old or irrelevant work | medium | ## Portfolio Freshness |
## Related Skills
Works well with: `scroll-experience`, `3d-web-experience`, `landing-page-design`, `personal-branding`
+42 -2
View File
@@ -7,9 +7,16 @@ yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
# Environment
.env
# Dependencies
node_modules
# Build output
dist
dist-ssr
dist-server
*.local
# Editor directories and files
@@ -26,7 +33,40 @@ dist-ssr
# TypeScript
*.tsbuildinfo
#Playwrite Screenshots
# Playwright screenshots
*.png
!public/meta.png
nul
# AI agent tooling
.claude/
.codex/
.ralph/
.playwright-mcp/
AGENTS.md
PROMPT.md
hats.yml
ralph.yml
scripts/ralph/
scripts/benchmark-results/
# Reference / personal materials
References/
# Font source archives (used fonts are in public/fonts/)
Fonts/
# Logo animation source (Remotion)
LogoAnimation/
# Design notes
carousel-design-debate*.md
# Misc
*:Zone.Identifier
__MACOSX
andy-charlwood-cv@0.0.0
lighthouse.pdf
logo/
graph.png
node
nul
-278
View File
@@ -1,278 +0,0 @@
#!/usr/bin/env node
'use strict';
var chalk = require('chalk'),
os = require('os'),
httpServer = require('../lib/http-server'),
portfinder = require('portfinder'),
opener = require('opener'),
fs = require('fs'),
url = require('url');
var argv = require('minimist')(process.argv.slice(2), {
alias: {
tls: 'ssl'
}
});
var ifaces = os.networkInterfaces();
process.title = 'http-server';
if (argv.h || argv.help) {
console.log([
'usage: http-server [path] [options]',
'',
'options:',
' -p --port Port to use. If 0, look for open port. [8080]',
' -a Address to use [0.0.0.0]',
' -d Show directory listings [true]',
' -i Display autoIndex [true]',
' -g --gzip Serve gzip files when possible [false]',
' -b --brotli Serve brotli files when possible [false]',
' If both brotli and gzip are enabled, brotli takes precedence',
' -e --ext Default file extension if none supplied [none]',
' -s --silent Suppress log messages from output',
' --cors[=headers] Enable CORS via the "Access-Control-Allow-Origin" header',
' Optionally provide CORS headers list separated by commas',
' -o [path] Open browser window after starting the server.',
' Optionally provide a URL path to open the browser window to.',
' -c Cache time (max-age) in seconds [3600], e.g. -c10 for 10 seconds.',
' To disable caching, use -c-1.',
' -t Connections timeout in seconds [120], e.g. -t60 for 1 minute.',
' To disable timeout, use -t0',
' -U --utc Use UTC time format in log messages.',
' --log-ip Enable logging of the client\'s IP address',
'',
' -P --proxy Fallback proxy if the request cannot be resolved. e.g.: http://someurl.com',
' --proxy-options Pass options to proxy using nested dotted objects. e.g.: --proxy-options.secure false',
'',
' --username Username for basic authentication [none]',
' Can also be specified with the env variable NODE_HTTP_SERVER_USERNAME',
' --password Password for basic authentication [none]',
' Can also be specified with the env variable NODE_HTTP_SERVER_PASSWORD',
'',
' -S --tls --ssl Enable secure request serving with TLS/SSL (HTTPS)',
' -C --cert Path to TLS cert file (default: cert.pem)',
' -K --key Path to TLS key file (default: key.pem)',
'',
' -r --robots Respond to /robots.txt [User-agent: *\\nDisallow: /]',
' --no-dotfiles Do not show dotfiles',
' --mimetypes Path to a .types file for custom mimetype definition',
' -h --help Print this list and exit.',
' -v --version Print the version and exit.'
].join('\n'));
process.exit();
}
var port = argv.p || argv.port || parseInt(process.env.PORT, 10),
host = argv.a || '0.0.0.0',
tls = argv.S || argv.tls,
sslPassphrase = process.env.NODE_HTTP_SERVER_SSL_PASSPHRASE,
proxy = argv.P || argv.proxy,
proxyOptions = argv['proxy-options'],
utc = argv.U || argv.utc,
version = argv.v || argv.version,
logger;
var proxyOptionsBooleanProps = [
'ws', 'xfwd', 'secure', 'toProxy', 'prependPath', 'ignorePath', 'changeOrigin',
'preserveHeaderKeyCase', 'followRedirects', 'selfHandleResponse'
];
if (proxyOptions) {
Object.keys(proxyOptions).forEach(function (key) {
if (proxyOptionsBooleanProps.indexOf(key) > -1) {
proxyOptions[key] = proxyOptions[key].toLowerCase() === 'true';
}
});
}
if (!argv.s && !argv.silent) {
logger = {
info: console.log,
request: function (req, res, error) {
var date = utc ? new Date().toUTCString() : new Date();
var ip = argv['log-ip']
? req.headers['x-forwarded-for'] || '' + req.connection.remoteAddress
: '';
if (error) {
logger.info(
'[%s] %s "%s %s" Error (%s): "%s"',
date, ip, chalk.red(req.method), chalk.red(req.url),
chalk.red(error.status.toString()), chalk.red(error.message)
);
}
else {
logger.info(
'[%s] %s "%s %s" "%s"',
date, ip, chalk.cyan(req.method), chalk.cyan(req.url),
req.headers['user-agent']
);
}
}
};
}
else if (chalk) {
logger = {
info: function () {},
request: function () {}
};
}
if (version) {
logger.info('v' + require('../package.json').version);
process.exit();
}
if (!port) {
portfinder.basePort = 8080;
portfinder.getPort(function (err, port) {
if (err) { throw err; }
listen(port);
});
}
else {
listen(port);
}
function listen(port) {
var options = {
root: argv._[0],
cache: argv.c,
timeout: argv.t,
showDir: argv.d,
autoIndex: argv.i,
gzip: argv.g || argv.gzip,
brotli: argv.b || argv.brotli,
robots: argv.r || argv.robots,
ext: argv.e || argv.ext,
logFn: logger.request,
proxy: proxy,
proxyOptions: proxyOptions,
showDotfiles: argv.dotfiles,
mimetypes: argv.mimetypes,
username: argv.username || process.env.NODE_HTTP_SERVER_USERNAME,
password: argv.password || process.env.NODE_HTTP_SERVER_PASSWORD
};
if (argv.cors) {
options.cors = true;
if (typeof argv.cors === 'string') {
options.corsHeaders = argv.cors;
}
}
if (proxy) {
try {
new url.URL(proxy)
}
catch (err) {
logger.info(chalk.red('Error: Invalid proxy url'));
process.exit(1);
}
}
if (tls) {
options.https = {
cert: argv.C || argv.cert || 'cert.pem',
key: argv.K || argv.key || 'key.pem',
passphrase: sslPassphrase,
};
try {
fs.lstatSync(options.https.cert);
}
catch (err) {
logger.info(chalk.red('Error: Could not find certificate ' + options.https.cert));
process.exit(1);
}
try {
fs.lstatSync(options.https.key);
}
catch (err) {
logger.info(chalk.red('Error: Could not find private key ' + options.https.key));
process.exit(1);
}
}
var server = httpServer.createServer(options);
server.listen(port, host, function () {
var protocol = tls ? 'https://' : 'http://';
logger.info([
chalk.yellow('Starting up http-server, serving '),
chalk.cyan(server.root),
tls ? (chalk.yellow(' through') + chalk.cyan(' https')) : ''
].join(''));
logger.info([chalk.yellow('\nhttp-server version: '), chalk.cyan(require('../package.json').version)].join(''));
logger.info([
chalk.yellow('\nhttp-server settings: '),
([chalk.yellow('CORS: '), argv.cors ? chalk.cyan(argv.cors) : chalk.red('disabled')].join('')),
([chalk.yellow('Cache: '), argv.c ? (argv.c === '-1' ? chalk.red('disabled') : chalk.cyan(argv.c + ' seconds')) : chalk.cyan('3600 seconds')].join('')),
([chalk.yellow('Connection Timeout: '), argv.t === '0' ? chalk.red('disabled') : (argv.t ? chalk.cyan(argv.t + ' seconds') : chalk.cyan('120 seconds'))].join('')),
([chalk.yellow('Directory Listings: '), argv.d ? chalk.red('not visible') : chalk.cyan('visible')].join('')),
([chalk.yellow('AutoIndex: '), argv.i ? chalk.red('not visible') : chalk.cyan('visible')].join('')),
([chalk.yellow('Serve GZIP Files: '), argv.g || argv.gzip ? chalk.cyan('true') : chalk.red('false')].join('')),
([chalk.yellow('Serve Brotli Files: '), argv.b || argv.brotli ? chalk.cyan('true') : chalk.red('false')].join('')),
([chalk.yellow('Default File Extension: '), argv.e ? chalk.cyan(argv.e) : (argv.ext ? chalk.cyan(argv.ext) : chalk.red('none'))].join(''))
].join('\n'));
logger.info(chalk.yellow('\nAvailable on:'));
if (argv.a && host !== '0.0.0.0') {
logger.info(` ${protocol}${host}:${chalk.green(port.toString())}`);
} else {
Object.keys(ifaces).forEach(function (dev) {
ifaces[dev].forEach(function (details) {
if (details.family === 'IPv4') {
logger.info((' ' + protocol + details.address + ':' + chalk.green(port.toString())));
}
});
});
}
if (typeof proxy === 'string') {
if (proxyOptions) {
logger.info('Unhandled requests will be served from: ' + proxy + '. Options: ' + JSON.stringify(proxyOptions));
}
else {
logger.info('Unhandled requests will be served from: ' + proxy);
}
}
logger.info('Hit CTRL-C to stop the server');
if (argv.o) {
const openHost = host === '0.0.0.0' ? '127.0.0.1' : host;
let openUrl = `${protocol}${openHost}:${port}`;
if (typeof argv.o === 'string') {
openUrl += argv.o[0] === '/' ? argv.o : '/' + argv.o;
}
logger.info('Open: ' + openUrl);
opener(openUrl);
}
// Spacing before logs
if (!argv.s) logger.info();
});
}
if (process.platform === 'win32') {
require('readline').createInterface({
input: process.stdin,
output: process.stdout
}).on('SIGINT', function () {
process.emit('SIGINT');
});
}
process.on('SIGINT', function () {
logger.info(chalk.red('http-server stopped.'));
process.exit();
});
process.on('SIGTERM', function () {
logger.info(chalk.red('http-server stopped.'));
process.exit();
});
-27
View File
@@ -1,27 +0,0 @@
{
"iterations": [
{
"iteration": 1,
"startedAt": "2026-02-11T22:50:15.397Z",
"endedAt": "2026-02-11T22:55:02.081Z",
"durationMs": 283525,
"toolsUsed": {},
"filesModified": [
"Ralph/IMPLEMENTATION_PLAN.md",
"Ralph/progress.txt",
"src/App.tsx",
"src/components/BootSequence.tsx",
"src/components/ECGAnimation.tsx"
],
"exitCode": 0,
"completionDetected": false,
"errors": []
}
],
"totalDurationMs": 283525,
"struggleIndicators": {
"repeatedErrors": {},
"noProgressIterations": 0,
"shortIterations": 0
}
}
File diff suppressed because one or more lines are too long
-20
View File
@@ -1,20 +0,0 @@
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"read": "allow",
"edit": "allow",
"glob": "allow",
"grep": "allow",
"list": "allow",
"bash": "allow",
"task": "allow",
"webfetch": "allow",
"websearch": "allow",
"codesearch": "allow",
"todowrite": "allow",
"todoread": "allow",
"question": "allow",
"lsp": "allow",
"external_directory": "allow"
}
}
+45 -199
View File
@@ -2,217 +2,63 @@
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 GP clinical record 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 (tiles as record sections, status indicators, medication-style skill entries, alerts) — but elevated with refined typography, considered motion, and a modern light aesthetic.
**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 contemporary.
Built as a React SPA with TypeScript and Vite.
**Reference design:** `References/GPSystemconcept.html` — the visual and structural target for the dashboard.
## 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
```bash
npm run dev # Vite dev server (localhost:5173)
npm run build # TypeScript compile + Vite production build
npm run preview # Preview production build locally
npm run lint # ESLint
npm run typecheck # TypeScript checks (no emit)
npm run generate-embeddings # Regenerate semantic search embeddings (src/data/embeddings.json)
```
No test framework is configured.
**Validation gate (run before any PR):** `npm run lint && npm run typecheck && npm run build`
No automated test framework — lint, typecheck, and build are the quality gates. For UI changes, verify manually (responsive behavior, accessibility, keyboard navigation).
## Architecture
### Four-Phase UI Flow
**Interactive CV/portfolio** with a PMR (patient medical record) interface aesthetic. Three-phase UX: terminal boot → ECG heartbeat → dashboard.
`App.tsx` manages a `Phase` state (`'boot'``'ecg'``'login'``'dashboard'`). Each phase renders exclusively:
### App lifecycle (`src/App.tsx`)
Phase orchestrator managing: BootSequence → ECGAnimation → LoginScreen → DashboardLayout
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. Login transitions to the dashboard.
4. **DashboardLayout** — The main portfolio experience: TopBar + Sidebar + scrollable tile-based dashboard.
### Data flow
- **Canonical source:** `src/data/timeline.ts` — all career + education entities live here
- **Derived data:** `constellation.ts` builds D3 graph data from timeline; `consultations.ts` re-exports for legacy consumers; `tags.ts` derived from skills; `kpis.ts` standalone
- **Types:** `src/types/pmr.ts` has all domain types (Consultation, TimelineEntity, ConstellationNode, etc.)
### Dashboard Layout (Post-Login)
### Key subsystems
The dashboard uses a three-zone layout:
| Subsystem | Entry point | Notes |
|-----------|-------------|-------|
| Dashboard | `DashboardLayout.tsx` | Orchestrates tiles, constellation, timeline, detail panel |
| Career Constellation | `CareerConstellation.tsx` | D3 force simulation; roles as clusters, skills as nodes; hover/click/tap/keyboard |
| Detail Panel | `DetailPanelContext.tsx` + `DetailPanel.tsx` | Right-side slide-out; context-aware views per entity type |
| Semantic Search | `lib/semantic-search.ts` + `lib/embedding-model.ts` | Pre-computed embeddings + local Xenova transformer model in browser |
| Command Palette | `CommandPalette.tsx` | Ctrl+K; fuzzy (Fuse.js) + semantic search |
| Chat Widget | `ChatWidget.tsx` + `lib/llm.ts` | Gemini/OpenRouter LLM integration; requires `.env` API keys |
| Accessibility | `AccessibilityContext.tsx` | Focus management, reduced motion, ARIA |
```
┌─────────────────────────────────────────────────────┐
│ TopBar (fixed, 48px) — brand, search, session │
├──────────┬──────────────────────────────────────────┤
│ │ │
│ Sidebar │ Card Grid (scrollable) │
│ (272px) │ ┌─────────────────────────────────┐ │
│ │ │ Patient Summary (full width) │ │
│ Person │ ├────────────────┬────────────────┤ │
│ Header │ │ Latest Results │ Repeat Meds │ │
│ │ │ (KPIs) │ (Core Skills) │ │
│ Tags │ ├────────────────┴────────────────┤ │
│ │ │ Last Consultation (full width) │ │
│ Alerts │ ├─────────────────────────────────┤ │
│ │ │ Career Activity (full width) │ │
│ │ ├─────────────────────────────────┤ │
│ │ │ Education (full width) │ │
│ │ ├─────────────────────────────────┤ │
│ │ │ Projects (full width) │ │
│ │ └─────────────────────────────────┘ │
└──────────┴──────────────────────────────────────────┘
```
### D3 integration pattern
`CareerConstellation.tsx` manages D3 force simulation imperatively via refs. Highlight state tracked with refs (not React state) to avoid unnecessary re-renders. Touch: tap to pin, background tap to clear. Keyboard: Tab through nodes, Enter/Space activate, Escape reset.
**No view switching.** The dashboard is a single scrollable page of tiles. Users scroll to see all sections. Detail drill-down happens by expanding tiles in-place (accordion pattern).
## Conventions
### Key Patterns
- **TypeScript strict mode** — `noUnusedLocals`, `noUnusedParameters` enforced
- **Path alias:** `@/*``src/*` (configured in vite.config.ts + tsconfig.json)
- **Components:** PascalCase (`DashboardLayout.tsx`); Hooks: `useCamelCase`; Utilities: kebab-case (`semantic-search.ts`)
- **Styling:** Tailwind utility classes + inline `CSSProperties` for dynamic/theme values
- **Animations:** Framer Motion; respects `prefers-reduced-motion`
- **Commits:** Conventional Commit prefixes (`feat:`, `chore:`, `fix:`) + optional story IDs
- **Canvas ECG**: `ECGAnimation.tsx` does imperative canvas drawing with requestAnimationFrame — flatline → 3 heartbeats (40px→60px→100px) → mask-based letter tracing → exit. **Locked — do not change.**
- **TopBar**: `TopBar.tsx` — fixed at top, brand + search trigger + session info. Search bar triggers Command Palette on click/Ctrl+K.
- **Sidebar**: `Sidebar.tsx` — light background, contains PersonHeader (avatar, name, title, status, details), Tags, and Alerts only. Skills, Projects, Education are in the main content tiles.
- **Card Grid**: CSS Grid, 2 columns on desktop (gap 16px), 1 column on mobile. Tiles use a reusable `Card` component with consistent styling.
- **Tile Expansion**: Career Activity items, Project items, and Skill items expand in-place with height-only animation (200ms, ease-out). Single-expand accordion — only one item open at a time.
- **KPI Flip Cards**: Latest Results metrics flip on click to show explanation text. CSS perspective transform, 400ms.
- **Command Palette**: Ctrl+K opens a Spotlight-style search overlay. Fuzzy search via fuse.js. Keyboard navigation (arrow keys, Enter, Escape).
- **Staggered entrance**: TopBar slides down → Sidebar slides from left → Content fades in. Quick (200-300ms).
- **Expandable content**: Height-only animation, 200ms ease-out. Content grows/shrinks — no opacity fade.
- **Responsive breakpoints**: Desktop (full sidebar + 2-col grid), Tablet (collapsed/hidden sidebar + 1-col), Mobile (no sidebar, stacked tiles).
## Design tokens
### 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: GP System Dashboard
The aesthetic direction is a **modern GP system dashboard** — the precision and information density of a medical records system, but with a light, contemporary, premium feel. Think: a healthcare SaaS product redesigned by a Swiss product studio.
### Tone
- **Precise, not cold.** Every element has a reason. Spacing is generous but intentional.
- **Light, not washed out.** Warm sage background, clean white surfaces, deliberate color accents.
- **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:**
- **Elvaro Grotesque** (primary, `font-ui`) — Modern grotesque sans-serif. 7 weights (300-900). Institutional credibility with premium feel. Slightly condensed proportions suit data-dense UI.
- **Blumir** (alternative, `font-ui-alt`) — Geometric-humanist hybrid. Variable font (100-700). More refined/luxurious feel.
- Both fonts sourced from Envato (licensed), stored in `Fonts/`. **Do not use Inter, Roboto, DM Sans, or system defaults.**
- Font files: Elvaro `Fonts/Elvaro Grotesque Sans Family/WOFF/TBJElvaro-*.woff2`, Blumir `Fonts/blumir-font-family/WOFF/Blumir-VF.woff2`
- **Monospace / Data**: Geist Mono for timestamps, session info, GPhC number, dates, coded entries. Creates "technical texture."
- **Terminal phase**: Fira Code — locked, do not change.
- **Type scale**: Tight. Headings 15-18px, body 12.5-14px, labels 10-12px. Precision over drama.
- **Weight hierarchy**: Use weight (400/500/600/700) rather than size to establish hierarchy.
### Color Palette
The palette anchors on teal as the primary accent, with a light sidebar + warm content background.
- **Teal `#0D6E6E`** — Primary accent. Active states, links, avatar gradient, interactive elements. Hover: `#0A8080`. Light: `rgba(10,128,128,0.08)`.
- **Background `#F0F5F4`** — Warm sage. The content area feels organic, not flat gray.
- **Sidebar `#F7FAFA`** — Very light. Right border `#D4E0DE` separates from content.
- **TopBar `#FFFFFF`** — White surface. Bottom border `#D4E0DE`.
- **Cards `#FFFFFF`** — White with shadow-sm and border-light. Hover deepens to shadow-md.
- **Status colors**: Success `#059669`, Amber `#D97706`, Alert `#DC2626`, Purple `#7C3AED` — each with light bg and border variants. Always paired with text labels.
- **Text**: Primary `#1A2B2A`, Secondary `#5B7A78`, Tertiary `#8DA8A5`. Use full range for hierarchy.
- **Borders**: Structural `#D4E0DE`, Cards/inner `#E4EDEB`.
### Shadows & Depth
Three-tier shadow system for layered depth:
- **Cards (resting)**: `0 1px 2px rgba(26,43,42,0.05)` — gentle, always present.
- **Cards (hover/interactive)**: `0 2px 8px rgba(26,43,42,0.08)` — slightly lifted.
- **Overlays (command palette, modals)**: `0 8px 32px rgba(26,43,42,0.12)` — clearly elevated.
- **Hover states**: Shadow deepens + border color strengthens. Subtle, not dramatic.
### Motion
Motion should feel considered and premium, never flashy:
- **Entrance animations**: Dashboard materializes in sequence — TopBar 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. Transition to dashboard layout.
- **Tile expansion**: Height-only animation, 200ms ease-out. Content grows/shrinks — no opacity fade.
- **KPI flip**: CSS perspective rotateY, 400ms ease-in-out. Click to flip, click to flip back.
- **Command palette**: Scale 0.97→1.0 + translateY entrance, 200ms. Backdrop fade.
- **Hover states**: Subtle, immediate. Border color shifts, shadow deepens. Think: OS-level responsiveness.
- **`prefers-reduced-motion`**: All animations skip to final state. No exceptions.
### Spatial Composition
- **Generous but structured.** Cards have 20px padding. Tile grid has 16px gap. Sections breathe.
- **Clear visual hierarchy.** Card headers: uppercase, small (12px), tracked-out, secondary color with colored dot indicator.
- **Two-column grid** on desktop, single column on mobile. Full-width tiles span both columns.
- **Sidebar sections** separated by thin divider titles (10px, uppercase, tertiary, with line extending right).
### What Makes It Memorable
The distinctiveness comes from the *clinical metaphor applied to a modern interface*:
- A light, professional sidebar with clinical-style person header and alert flags
- Skills presented as "Repeat Medications" with frequency dosing (twice daily, when required)
- KPI metrics that flip to reveal explanations, like interactive test results
- Career history as a clinical timeline with color-coded entry types
- The boot sequence → ECG → login flow is theatrical in a way that real clinical software never is
- Command palette (Ctrl+K) for searching records, like a clinical search tool
## Styling
Tailwind CSS with custom design tokens in `tailwind.config.js`:
- **Color tokens**: PMR-prefixed tokens (`pmr-accent`, `pmr-bg`, `pmr-surface`, `pmr-sidebar`, `pmr-text-primary`, etc.)
- **Fonts**: `font-ui` (Elvaro Grotesque), `font-ui-alt` (Blumir), `font-geist` (Geist Mono), `font-mono` (Fira Code for terminal)
- **Breakpoints**: xs 480px, sm 640px, md 768px, lg 1024px, xl 1280px
- **Border radius**: 8px default for cards/tiles (`var(--radius)`). 6px for inner elements (`var(--radius-sm)`). 12px exception for login card and command palette.
- **Shadows**: `shadow-sm`, `shadow-md`, `shadow-lg` tokens matching three-tier system.
- CSS custom properties in `index.css` for both boot/ECG phase tokens and dashboard phase tokens.
- Inline styles only for dynamic values that Tailwind can't express.
## Guardrails
- **Boot sequence**: Text, colors, and timing must match `References/concept.html` exactly. **Do not modify.**
- **ECG animation**: Timing, amplitudes, color transitions, and mask-based text reveal must match the concept reference. **Do not modify.**
- **Reference design**: `References/GPSystemconcept.html` is the visual and structural target for the dashboard.
- **CV content**: Sourced from `References/CV_v4.md` — roles, dates, and achievement numbers must be accurate.
- **Icons**: Via `lucide-react`, not unicode symbols.
- **Accessibility**: WCAG 2.1 AA compliance. Semantic HTML, ARIA attributes, keyboard navigation, `prefers-reduced-motion` support throughout. Status indicators always paired with text labels.
- **No generic aesthetics**: Every design decision should feel intentional. If a component could appear in any random SaaS template, it needs more character.
- **Fonts**: Elvaro Grotesque (primary) or Blumir (alt). Never Inter, Roboto, DM Sans, or system defaults. DM Sans appears in the concept HTML as a placeholder only.
## Project Structure
```
src/
├── components/ # One component per file (PascalCase)
│ ├── tiles/ # Dashboard tile components (PatientSummaryTile, LatestResultsTile, etc.)
│ ├── views/ # Legacy PMR views (being replaced by tiles — may be referenced during transition)
│ ├── TopBar.tsx # Fixed top bar (brand, search trigger, session)
│ ├── Sidebar.tsx # Light sidebar (person header, tags, alerts)
│ ├── DashboardLayout.tsx # Main layout (topbar + sidebar + card grid)
│ ├── Card.tsx # Reusable card component with header
│ ├── CommandPalette.tsx # Ctrl+K search overlay
│ └── ... # Boot, ECG, Login (unchanged)
├── contexts/ # React contexts (AccessibilityContext)
├── data/ # Static data files
│ ├── patient.ts # Person details
│ ├── consultations.ts # Career roles (used in Last Consultation + Career Activity)
│ ├── medications.ts # Legacy skill data
│ ├── problems.ts # Achievements
│ ├── investigations.ts # Projects
│ ├── documents.ts # Education entries
│ ├── profile.ts # Personal statement
│ ├── tags.ts # Sidebar tags
│ ├── alerts.ts # Sidebar alert flags
│ ├── kpis.ts # KPI metrics for Latest Results
│ └── skills.ts # Skills with frequency/years (medication metaphor)
├── hooks/ # Custom hooks (camelCase, use* prefix)
├── lib/ # Utility functions (search.ts for fuse.js)
├── types/ # TypeScript interfaces (index.ts, pmr.ts)
├── App.tsx # Phase manager (root component)
└── index.css # Global styles + Tailwind directives
Ralph/ # Implementation plan, guardrails, progress tracking
References/ # Source content (concept.html, GPSystemconcept.html, CV_v4.md)
```
- **Primary:** Teal `#00897B` / **Accent:** Coral `#FF6B6B`
- **PMR palette:** GP system-inspired greens, teals, greys (defined in `tailwind.config.js`)
- **Font tokens (CSS custom properties):**
- `--font-ui`: Elvaro Grotesque (dashboard UI)
- `--font-geist-mono`: Geist Mono / Fira Code fallback (canonical mono token)
- `--font-primary` / `--font-secondary`: Plus Jakarta Sans / Inter Tight
- **Breakpoints:** xs 480, sm 640, md 768, lg 1024, xl 1280
-494
View File
@@ -1,494 +0,0 @@
import { AbsoluteFill, useCurrentFrame, useVideoConfig } from "remotion";
// ─── Heartbeat generation ────────────────────────────────────────────────────
function generateHeartbeatPoints(
amplitude: number,
): { x: number; y: number }[] {
const points: { x: number; y: number }[] = [];
const steps = 200;
for (let i = 0; i <= steps; i++) {
const t = i / steps;
let y = 0;
if (t >= 0.05 && t < 0.2) {
const pt = (t - 0.05) / 0.15;
y = 0.12 * Math.sin(pt * Math.PI);
} else if (t >= 0.25 && t < 0.32) {
const pt = (t - 0.25) / 0.07;
y = -0.1 * Math.sin(pt * Math.PI);
} else if (t >= 0.32 && t < 0.42) {
const pt = (t - 0.32) / 0.1;
y = 1.0 * Math.sin(pt * Math.PI);
} else if (t >= 0.42 && t < 0.5) {
const pt = (t - 0.42) / 0.08;
y = -0.25 * Math.sin(pt * Math.PI);
} else if (t >= 0.55 && t < 0.75) {
const pt = (t - 0.55) / 0.2;
y = 0.2 * Math.sin(pt * Math.PI);
}
points.push({ x: t, y: y * amplitude });
}
return points;
}
type Beat = { startFrame: number; widthPx: number; amplitude: number };
function buildBeats(fps: number): Beat[] {
const beats: Beat[] = [];
beats.push({ startFrame: Math.round(0.6 * fps), widthPx: 60, amplitude: 0.25 });
beats.push({ startFrame: Math.round(1.4 * fps), widthPx: 80, amplitude: 0.45 });
beats.push({ startFrame: Math.round(2.3 * fps), widthPx: 120, amplitude: 0.85 });
const normalStart = 3.2;
for (let i = 0; i < 1; i++) {
beats.push({
startFrame: Math.round((normalStart + i) * fps),
widthPx: 140,
amplitude: 1.0,
});
}
return beats;
}
// ─── Letter definitions ──────────────────────────────────────────────────────
const LETTERS: Record<string, { x: number; y: number }[]> = {
A: [
{ x: 0, y: 0 }, { x: 0.48, y: 1 }, { x: 0.53, y: 0.42 },
{ x: 0.6, y: 0.42 }, { x: 1, y: 0 },
],
N: [
{ x: 0, y: 0 }, { x: 0.12, y: 1 }, { x: 0.72, y: 0 },
{ x: 0.88, y: 1 }, { x: 1, y: 0 },
],
D: [
{ x: 0, y: 0 }, { x: 0.1, y: 1 }, { x: 0.5, y: 1 },
{ x: 0.85, y: 0.55 }, { x: 1, y: 0 },
],
R: [
{ x: 0, y: 0 }, { x: 0.1, y: 1 }, { x: 0.35, y: 1 },
{ x: 0.5, y: 0.6 }, { x: 0.55, y: 0.45 }, { x: 1, y: 0 },
],
E: [
{ x: 0, y: 0 }, { x: 0.1, y: 1 }, { x: 0.4, y: 1 },
{ x: 0.45, y: 0.5 }, { x: 0.65, y: 0.5 }, { x: 0.7, y: 0 },
{ x: 1, y: 0 },
],
W: [
{ x: 0, y: 0 }, { x: 0.05, y: 1 }, { x: 0.27, y: 0 },
{ x: 0.5, y: 0.65 }, { x: 0.73, y: 0 }, { x: 0.95, y: 1 },
{ x: 1, y: 0 },
],
C: [
{ x: 0, y: 0 }, { x: 0.08, y: 0.6 }, { x: 0.18, y: 1 },
{ x: 0.6, y: 1 }, { x: 0.8, y: 0.5 }, { x: 0.95, y: 0.1 },
{ x: 1, y: 0 },
],
H: [
{ x: 0, y: 0 }, { x: 0.1, y: 1 }, { x: 0.18, y: 0.5 },
{ x: 0.82, y: 0.5 }, { x: 0.9, y: 1 }, { x: 1, y: 0 },
],
L: [
{ x: 0, y: 0 }, { x: 0.12, y: 1 }, { x: 0.3, y: 1 },
{ x: 0.38, y: 0 }, { x: 1, y: 0 },
],
O: [
{ x: 0, y: 0 }, { x: 0.2, y: 0.85 }, { x: 0.35, y: 1 },
{ x: 0.65, y: 1 }, { x: 0.8, y: 0.85 }, { x: 1, y: 0 },
],
};
function interpolateLetterY(
points: { x: number; y: number }[],
t: number,
): number {
if (t <= points[0].x) return points[0].y;
if (t >= points[points.length - 1].x) return points[points.length - 1].y;
for (let i = 0; i < points.length - 1; i++) {
if (t >= points[i].x && t <= points[i + 1].x) {
const segT = (t - points[i].x) / (points[i + 1].x - points[i].x);
return points[i].y + (points[i + 1].y - points[i].y) * segT;
}
}
return 0;
}
// ─── Text layout ─────────────────────────────────────────────────────────────
const TEXT = "ANDREW CHARLWOOD";
const LETTER_WIDTH = 72;
const LETTER_GAP = 10;
const SPACE_WIDTH = 30;
const BASE_LEFT_INSET = 9;
const BASE_RIGHT_INSET = 0;
type LetterLayout = {
char: string;
startX: number;
endX: number;
startConnector: number;
endConnector: number;
};
type ConnectorProfile = { leftInset: number; rightInset: number };
const CONNECTOR_PROFILES: Record<string, ConnectorProfile> = {
C: { leftInset: 20, rightInset: 8 },
O: { leftInset: 17, rightInset: 7 },
D: { leftInset: 0, rightInset: 13 },
L: { leftInset: 5, rightInset: 0 },
E: { leftInset: 5, rightInset: 0 },
};
const DEFAULT_PROFILE: ConnectorProfile = { leftInset: 0, rightInset: 0 };
function layoutText(offsetX: number): LetterLayout[] {
const layout: LetterLayout[] = [];
let cursor = offsetX;
for (const char of TEXT) {
if (char === " ") {
cursor += SPACE_WIDTH;
continue;
}
const profile = CONNECTOR_PROFILES[char] ?? DEFAULT_PROFILE;
const startX = cursor;
const endX = cursor + LETTER_WIDTH;
layout.push({
char,
startX,
endX,
startConnector: startX + BASE_LEFT_INSET + profile.leftInset,
endConnector: endX - BASE_RIGHT_INSET - profile.rightInset,
});
cursor += LETTER_WIDTH + LETTER_GAP;
}
return layout;
}
function getTextTotalWidth(): number {
return (
TEXT.replace(/ /g, "").length * (LETTER_WIDTH + LETTER_GAP) -
LETTER_GAP +
(TEXT.split(" ").length - 1) * SPACE_WIDTH
);
}
// ─── Timing constants ────────────────────────────────────────────────────────
const TRACE_SPEED = 350;
const HEAD_SCREEN_RATIO = 1;
const FLAT_GAP_SECONDS = 0.5;
const HOLD_SECONDS = 1.25;
const COMP_FPS = 60;
// How long the dot/line takes to exit the right side after text finishes
const EXIT_SECONDS = 1.5;
// Pre-compute duration for export
const _beats = buildBeats(COMP_FPS);
const _lastBeat = _beats[_beats.length - 1];
const _lastBeatEndWX = (_lastBeat.startFrame / COMP_FPS) * TRACE_SPEED + _lastBeat.widthPx;
const _textStartWX = _lastBeatEndWX + FLAT_GAP_SECONDS * TRACE_SPEED;
const _totalTextW = getTextTotalWidth();
const _textEndWX = _textStartWX + _totalTextW;
const _textEndFrame = Math.round((_textEndWX / TRACE_SPEED) * COMP_FPS);
export const ECGCOMBINED_DURATION = _textEndFrame + Math.round(HOLD_SECONDS * COMP_FPS) + Math.round(EXIT_SECONDS * COMP_FPS);
// ─── Component ───────────────────────────────────────────────────────────────
export const ECGCombined = () => {
const frame = useCurrentFrame();
const { fps, width, height } = useVideoConfig();
const baselineY = height * 0.5;
const lineColor = "#00ff41";
const ecgMaxDeflection = height * 0.28;
const textMaxDeflection = height * 0.09;
const beats = buildBeats(fps);
// ── World-space text position ──
const lastBeat = beats[beats.length - 1];
const lastBeatEndWorldX = (lastBeat.startFrame / fps) * TRACE_SPEED + lastBeat.widthPx;
const textStartWorldX = lastBeatEndWorldX + FLAT_GAP_SECONDS * TRACE_SPEED;
const totalTextWidth = getTextTotalWidth();
const textEndWorldX = textStartWorldX + totalTextWidth;
const textLayout = layoutText(textStartWorldX); // world-space positions
// ── Final screen position: text centered when done ──
const desiredTextStartScreen = (width - totalTextWidth) / 2;
const finalHeadScreenX = desiredTextStartScreen + totalTextWidth;
const headScreenDuringEcg = HEAD_SCREEN_RATIO * width;
// ── Head position (world space, keeps moving past text) ──
const currentTime = frame / fps;
const headX = currentTime * TRACE_SPEED;
const textEndFrame = Math.round((textEndWorldX / TRACE_SPEED) * fps);
const isTextPhase = headX > textStartWorldX;
const isTextDone = frame >= textEndFrame - 3;
// ── Viewport: keeps scrolling, head drifts from 75% → right edge ──
let headScreenX: number;
let viewOffset: number;
if (headX <= textStartWorldX) {
viewOffset = Math.max(0, headX - headScreenDuringEcg);
headScreenX = headX - viewOffset;
} else if (headX >= textEndWorldX) {
// Lock viewport so text stays centered; dot keeps moving right
viewOffset = textEndWorldX - finalHeadScreenX;
headScreenX = headX - viewOffset;
} else {
const p = (headX - textStartWorldX) / (textEndWorldX - textStartWorldX);
headScreenX = headScreenDuringEcg + p * (finalHeadScreenX - headScreenDuringEcg);
viewOffset = headX - headScreenX;
}
// ── Y function (world space) ──
function getYAtX(worldX: number): number {
for (const beat of beats) {
const beatStartX = (beat.startFrame / fps) * TRACE_SPEED;
const beatEndX = beatStartX + beat.widthPx;
if (worldX >= beatStartX && worldX <= beatEndX) {
const progress = (worldX - beatStartX) / beat.widthPx;
const beatPoints = generateHeartbeatPoints(beat.amplitude);
const idx = Math.min(
Math.floor(progress * (beatPoints.length - 1)),
beatPoints.length - 1,
);
return baselineY - beatPoints[idx].y * ecgMaxDeflection;
}
}
for (const item of textLayout) {
if (worldX >= item.startX && worldX <= item.endX) {
const t = (worldX - item.startX) / (item.endX - item.startX);
const letterDef = LETTERS[item.char];
if (letterDef) {
return baselineY - interpolateLetterY(letterDef, t) * textMaxDeflection;
}
}
}
return baselineY;
}
// ── ECG trace path (up to text start) ──
const firstBeatWorldX = (beats[0].startFrame / fps) * TRACE_SPEED;
const traceStartWX = Math.max(Math.floor(firstBeatWorldX), Math.floor(viewOffset));
const ecgTraceEndWX = Math.min(
Math.ceil(headX),
Math.ceil(textStartWorldX),
Math.ceil(viewOffset + width),
);
const traceSegments: string[] = [];
if (ecgTraceEndWX >= traceStartWX) {
for (let wx = traceStartWX; wx <= ecgTraceEndWX; wx++) {
const sx = wx - viewOffset;
const y = getYAtX(wx);
traceSegments.push(wx === traceStartWX ? `M ${sx} ${y}` : `L ${sx} ${y}`);
}
}
const tracePathD = traceSegments.join(" ");
// ── Flat exit line after text finishes ──
let exitPathD = "";
if (isTextDone && headX > textEndWorldX) {
const exitStartSX = textEndWorldX - viewOffset - 32;
const exitEndSX = headX - viewOffset;
exitPathD = `M ${exitStartSX} ${baselineY} L ${exitEndSX} ${baselineY}`;
}
// ── Neon fade ──
const neonLengthPx = 200;
const neonFadeScreenEnd = headScreenX;
const neonFadeScreenStart = neonFadeScreenEnd - neonLengthPx;
// ── Text mask ──
const maskBrushSize = 1;
const clipLeadPx = 20;
const blockUnmaskDelay = 15;
const blockFeatherPx = 10;
const textMaskEndSX = isTextPhase
? (isTextDone ? width : Math.max(0, Math.min(Math.ceil(headScreenX), width)))
: 0;
const textMaskSegments: string[] = [];
if (isTextPhase && textMaskEndSX > 0 && !isTextDone) {
for (let sx = 0; sx <= textMaskEndSX; sx++) {
const y = getYAtX(viewOffset + sx);
textMaskSegments.push(sx === 0 ? `M ${sx} ${y}` : `L ${sx} ${y}`);
}
}
const textMaskPathD = textMaskSegments.join(" ");
const blockUnmaskX = isTextDone ? width : Math.max(0, textMaskEndSX - blockUnmaskDelay);
// ── Connectors (screen space) ──
const connectorSegments: string[] = [];
for (let i = 0; i < textLayout.length - 1; i++) {
const curr = textLayout[i];
const next = textLayout[i + 1];
connectorSegments.push(
`M ${curr.endConnector - viewOffset - 18} ${baselineY} L ${next.startConnector - viewOffset} ${baselineY}`,
);
}
const connectorPathD = connectorSegments.join(" ");
return (
<AbsoluteFill style={{ backgroundColor: "#000000", overflow: "hidden" }}>
<svg width={width} height={height} style={{ position: "absolute", top: 0, left: 0 }}>
<defs>
<filter id="neon" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur in="SourceGraphic" stdDeviation="2" result="blur1" />
<feGaussianBlur in="SourceGraphic" stdDeviation="6" result="blur2" />
<feGaussianBlur in="SourceGraphic" stdDeviation="14" result="blur3" />
<feMerge>
<feMergeNode in="blur3" />
<feMergeNode in="blur2" />
<feMergeNode in="blur1" />
<feMergeNode in="SourceGraphic" />
</feMerge>
</filter>
<filter id="neonText" x="-30%" y="-30%" width="160%" height="160%">
<feGaussianBlur in="SourceGraphic" stdDeviation="3" result="tblur1" />
<feGaussianBlur in="SourceGraphic" stdDeviation="8" result="tblur2" />
<feMerge>
<feMergeNode in="tblur2" />
<feMergeNode in="tblur1" />
<feMergeNode in="SourceGraphic" />
</feMerge>
</filter>
<linearGradient
id="neonMaskGrad"
gradientUnits="userSpaceOnUse"
x1={neonFadeScreenStart} y1={0}
x2={neonFadeScreenEnd} y2={0}
>
<stop offset="0%" stopColor="black" />
<stop offset="100%" stopColor="white" />
</linearGradient>
<mask id="neonMask">
<rect x={0} y={0} width={width} height={height} fill="url(#neonMaskGrad)" />
</mask>
<clipPath id="textReveal">
<rect
x={0} y={0}
width={isTextDone ? width : Math.max(0, headScreenX + clipLeadPx)}
height={height}
/>
</clipPath>
<linearGradient
id="blockUnmaskGrad"
gradientUnits="userSpaceOnUse"
x1={blockUnmaskX - blockFeatherPx} y1={0}
x2={blockUnmaskX} y2={0}
>
<stop offset="0%" stopColor="white" />
<stop offset="100%" stopColor="black" />
</linearGradient>
<mask id="textWipeMask">
<rect x={0} y={0} width={width} height={height} fill={isTextDone ? "white" : "black"} />
{!isTextDone && blockUnmaskX > 0 && (
<rect x={0} y={0} width={blockUnmaskX} height={height} fill="url(#blockUnmaskGrad)" />
)}
{!isTextDone && textMaskPathD && (
<path
d={textMaskPathD}
fill="none"
stroke="white"
strokeWidth={15 * maskBrushSize}
strokeLinejoin="round"
strokeLinecap="round"
filter="url(#neonText)"
/>
)}
</mask>
<radialGradient id="headGlow" cx="50%" cy="50%" r="50%">
<stop offset="0%" stopColor="#ffffff" stopOpacity={0.8} />
<stop offset="30%" stopColor={lineColor} stopOpacity={0.6} />
<stop offset="100%" stopColor={lineColor} stopOpacity={0} />
</radialGradient>
</defs>
{/* ECG trace */}
{tracePathD && (
<g>
<path d={tracePathD} fill="none" stroke={lineColor} strokeWidth={2}
strokeLinejoin="round" strokeLinecap="round" />
<path d={tracePathD} fill="none" stroke={lineColor} strokeWidth={2.5}
strokeLinejoin="round" strokeLinecap="round"
filter="url(#neon)" mask="url(#neonMask)" />
</g>
)}
{/* Text + connectors */}
{isTextPhase && (
<g clipPath="url(#textReveal)">
<g mask="url(#textWipeMask)">
{textLayout.map((item, i) => (
<text
key={i}
x={(item.startX + item.endX) / 2 - viewOffset}
y={baselineY}
textAnchor="middle"
dominantBaseline="alphabetic"
fontSize={Math.round(textMaxDeflection / 0.715)}
fontFamily="Arial, Helvetica, sans-serif"
fontWeight="bold"
fill="none"
stroke={lineColor}
strokeWidth={1.5}
filter="url(#neonText)"
>
{item.char}
</text>
))}
{connectorPathD && (
<path d={connectorPathD} fill="none" stroke={lineColor}
strokeWidth={1.5} strokeLinecap="round" />
)}
</g>
</g>
)}
{/* Flat exit line after text */}
{exitPathD && (
<g>
<path d={exitPathD} fill="none" stroke={lineColor} strokeWidth={2}
strokeLinejoin="round" strokeLinecap="round" />
<path d={exitPathD} fill="none" stroke={lineColor} strokeWidth={2.5}
strokeLinejoin="round" strokeLinecap="round"
filter="url(#neon)" />
</g>
)}
{/* Head dot */}
{headScreenX >= 0 && headScreenX <= width && (
<>
<circle cx={headScreenX} cy={getYAtX(headX)} r={20} fill="url(#headGlow)" />
<circle cx={headScreenX} cy={getYAtX(headX)} r={3} fill={lineColor} />
</>
)}
</svg>
{/* Scanlines */}
<div style={{
position: "absolute", top: 0, left: 0, width: "100%", height: "100%",
background: "repeating-linear-gradient(0deg, transparent, transparent 2px, rgba(0,0,0,0.08) 2px, rgba(0,0,0,0.08) 4px)",
pointerEvents: "none",
}} />
{/* Vignette */}
<div style={{
position: "absolute", top: 0, left: 0, width: "100%", height: "100%",
background: "radial-gradient(ellipse at center, transparent 60%, rgba(0,0,0,0.5) 100%)",
pointerEvents: "none",
}} />
</AbsoluteFill>
);
};
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

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