A sample principle, shown to demonstrate the card and its staggered reveal.
Design System
The living style guide
Every token, type style and component this portfolio is built from, rendered live from source. Amend a component here and it updates everywhere it ships.
Colour
Colour
Nine tokens carry the whole palette. Everything on the site resolves to one of these.
Palette and surfaces
--color-bg
#0d0d0d
Page background. Also the knockout text on filled accent buttons, pills and the card arrow badge.
--color-bg-elev
#191919
Raised surfaces: cards, panels, stat cells, figure frames.
Text
--color-ink
#f4f3ee
Headings, lead copy, emphasis and on-card primary text.
--color-ink-muted
#a6a39c
Body and supporting copy, card summaries, stat labels, footer and inactive nav.
--color-ink-soft
#76736c
Tertiary: captions, meta labels, numbering and quiet eyebrows.
Accent
--color-accent
#f98b7d
The interaction colour: links and hovers, focus ring, selection, primary button fill, active nav underline, accent eyebrows and stat values.
--color-accent-hover
#fba99d
Hover fill for filled accent buttons only.
Lines
--color-hairline
#292927
Default borders, dividers and grid gap-lines.
--color-hairline-strong
#3d3d3a
Pill and chip outlines, and secondary (outline) button borders.
Selection paints accent on the background. Focus is a 2px accent outline at a 3px offset, handled once globally. The image placeholder now references its own placeholder tokens, so every surface resolves on-palette.
Typography
Typography
Two families do all the work. Inter Tight for display, Inter for everything else.
Eyebrow / overline
text-xs · 13px · 400 · 0.14em · sans
Design system
Home hero H1
text-4xl→6xl · 40/52/68px · 600 · leading-[1.1] · display
Research-led UX
Page H1
text-4xl→6xl · 40/52/68px · 600 · leading-[1.1] · display
Selected work
Big section H2
text-3xl→5xl · 32/40/52px · 600 · leading-[1.1] · display
Selected projects in depth.
Section H2
text-2xl/3xl · 26/32px · 600 · tight · display
What I found
Card H3
text-xl/2xl · 22/26px · 600 · snug · display
It creates clarity
Lead / large intro
text-xl/2xl · 22/26px · 400 · none · sans
I turn evidence into clear direction teams can act on.
Quote (testimonial)
text-2xl/3xl · 26/32px · 500 · snug · display
It is all based on us and our customers.
Body copy
text-lg · 19px · 400 · none · sans
The work has to be clear enough for stakeholders to support and useful enough for teams to act on.
Card summary / smaller body
text-base · 17px · 400 · none · sans
Research, strategy and design for a new website, portal and app.
Caption
text-sm · 15px · 400 · none · sans
The launched homepage, built on the audience-led structure.
Stat value
text-4xl/5xl · 40/52px · 600 · tight · display
30+ years
Nav / label
text-base · 17px · 600 · wide · display
UX Leadership
Buttons and links
Buttons and links
One geometry across every call to action. Hover goes to salmon.
Primary, filled
rounded-full px-7 py-3.5 bg-[var(--color-accent)] text-[var(--color-bg)] text-sm font-medium tracking-wide hover:bg-[var(--color-accent-hover)]
Secondary, outline
View all workrounded-full px-7 py-3.5 border border-[var(--color-hairline-strong)] text-[var(--color-ink)] hover:border-[var(--color-accent)] hover:text-[var(--color-accent)]
Text link
A text link that hovers to salmontext-[var(--color-ink)] no-underline transition-colors hover:text-[var(--color-accent)]
Disabled state
Send an emailComponents
Components
The live components, rendered from source, so a change to a component shows here and everywhere it is used.
Monogram
components/Monogram.tsx
TagList
components/TagList.tsx
- UX strategy
- Research
- Information architecture
The single tag component: white text at text-sm. Every tag now routes through it, the hero skill pills and the case-study card tags included, so a change here reaches them all.
SectionIntro
components/SectionIntro.tsx
Sample eyebrow
A reusable section intro
Renders the eyebrow, an h2 and an optional intro line.
Eyebrow, heading and optional intro in one. Quiet eyebrows are ink-soft, with accent reserved for counters and impact labels.
StatRow
components/StatRow.tsx
- 3
- Sample stat, not a real result
- 100+
- Sample stat
- 5
- Sample stat
Sample figures, shown only to demonstrate the component, not real results.
RecommendationList
components/RecommendationList.tsx
- A sample recommendation, stated as an action.
- A second sample recommendation.
- A third sample recommendation.
PullQuote
components/PullQuote.tsx
A short, representative quote, shown only to demonstrate the component.
Display weight 500 with an accent left rule, the same feature-text weight as the Testimonial quote.
Testimonial
components/Testimonial.tsx
Client testimonial
A representative endorsement, shown only to demonstrate the component.”
Hanging accent quote marks. The quote and attribution here are samples.
PrincipleCard
components/PrincipleCard.tsx
Figure
components/Figure.tsx

One block for images and video, with optional aspect framing and a caption.
ImagePlaceholder
components/ImagePlaceholder.tsx
Image placeholder
Missing image
The fallback surface now references the --color-placeholder and --color-placeholder-hatch tokens, so it renders on-palette.
CaseStudySection
components/CaseStudySection.tsx
01
A sample section
Body copy sits in the wide column. The number and title sit in the sticky column to its left on larger screens.
The structural shell for each case-study beat: a numbered, sticky title column beside the body and its media.
Components, full width
Full-width blocks
The page-level bands, rendered full width exactly as they ship. The header and footer here are duplicates of the chrome around this page, shown as catalogue items.
Hero
components/Hero.tsx
Hi, I'm James. I turn evidence into action.
Research-led UX strategy and design solutions for complex users, products and services.

I lead UX research, strategy and design for complex websites, portals and services, turning evidence into direction teams can act on, from discovery through to delivery.
- UX strategy
- Workshopping
- Primary research
- Information architecture
- Digital solutions design
LogoMarquee
components/LogoMarquee.tsx
An edge-faded, autoplaying client-logo carousel. Pauses on hover and is static under reduced motion.
WorkScroller
components/WorkScroller.tsx
Decorative two-row drifting image band. Aria-hidden.
ContactCTA
components/ContactCTA.tsx
The closing call-to-action band, with the oversized monogram watermark and the primary button.
Ready to talk about your next experience challenge?
I'm interested in roles and projects where UX has to connect user needs, business goals, content, product decisions and delivery quality.
SiteHeader
components/SiteHeader.tsx
Also the bar at the very top of this page.
SiteFooter
components/SiteFooter.tsx
Also the footer at the very bottom of this page.
Things to reconcile
Known drift
Real divergences found across colour, type, buttons and components, each with a single recommended choice.
01Eyebrow colour now has a rule
The same uppercase overline was accent in some places and ink-soft in others, sometimes within one file.
Canonical: Reconciled: quiet page, section and metadata eyebrows are now ink-soft, with accent reserved for counters and impact labels such as Step 01 or The impact.
02Eyebrow tracking unified
CaseStudyCard used tracking-[0.16em] while everywhere else was 0.14em.
Canonical: Reconciled: tracking-[0.14em] is now used everywhere.
03Headings no longer set family and weight inline
Almost every heading set font and weight via a style object rather than utilities, and a couple relied on an unset-weight fallback.
Canonical: Reconciled: headings now use the font-display and font-semibold utilities, with no reliance on a weight fallback.
04Feature-text weight unified at 500
Pull-quotes were 500, testimonials and PrincipleCard 400, headings 600, the footer line unset.
Canonical: Reconciled: headings stay 600 and quote and feature text now use font-medium (500) consistently.
05Nav weight brought to 600
Nothing else used 700; the wordmark beside it was 600.
Canonical: Reconciled: the nav is now 600, matching the wordmark.
06Heading sizes mapped to the scale
The hero H1, card H3, case-study lead and a text-[0.95rem] card summary bypassed the token scale.
Canonical: Reconciled: off-scale sizes now map to tokens, the card summary is text-sm, and a single page-H1 ramp is used.
07H2 reduced to two structural levels
Section H2 was 52px on home, 40px on leadership and 32px in case studies.
Canonical: Reconciled: two levels only, big section H2 at text-3xl→5xl and nested section H2 at text-2xl/3xl, applied by level not by file.
08Heading leading collapsed
Six different leading values were used across large headings.
Canonical: Reconciled: large display headings use leading-[1.1], the rest leading-tight, with leading-snug only on the pull quote.
09Secondary button hover unified
The home outline button hovered border and text to accent; the 404 one hovered border to ink only.
Canonical: Reconciled: secondary buttons now hover border and text to accent, matching the site-wide convention.
10Tag pills unified
Previously three hand-rolled variants at different sizes and colours: TagList was muted grey, the hero pills white, the card tags a third near-copy.
Canonical: Reconciled: every tag now routes through TagList at white text, text-sm.
11Stat-value emphasis colour fixed
The same headline figure was accent in the impact block and ink lower on the same page.
Canonical: Reconciled: headline figures are accent everywhere.
12Quote marks unified
Testimonial marks were accent; the case-study lead marks were ink-soft.
Canonical: Reconciled: all quote ornaments are now accent.
13Bullet-dot colour and size unified
Accent 1.5px dots were used in most lists; ink-soft 1px dots in the case-study bullets helper.
Canonical: Reconciled: all bullet dots are now accent at w-1.5 h-1.5.
14Off-token surface tokenised
ImagePlaceholder used raw #f0ede5 and #1a1a1a, near-twins of existing tokens.
Canonical: Reconciled: placeholder tokens were added and ImagePlaceholder now references them, so nothing renders off-palette.
15Mask stops unified
WorkScroller and LogoMarquee used #000 mask stops with mismatched fade widths (4/96 vs 5/95).
Canonical: Reconciled: both use a single 6% / 94% edge fade.
16Stat duplication removed
Three stat components existed: StatRow (canonical), the hand-rolled impact list, and StatBand (superseded).
Canonical: Reconciled: StatRow is the canonical stat block and the superseded StatBand is gone. The case-study overview keeps a distinct vertical headline-impact treatment by choice.
17Mobile nav now has an active underline
Desktop active got a 2px accent underline; mobile active was colour-only.
Canonical: Reconciled: the mobile active link now carries the same 2px accent underline as desktop.
18Superseded components removed
Eight earlier components remained in the folder and were shown for reference only.
Canonical: Reconciled: the build now uses only the canonical set and the superseded components have been retired.














