The rules behind this portfolio: one ink, one spectrum, four typefaces, and interactions that turn something tangled into something clear. Everything here is the live CSS of the site, so what you see is what ships.
What every piece stands on: two modes that share one structure, a spectrum for accent, and type that tells you what you're reading by its voice.
01 / 04
Color and modes
Dark is the default: near-black ground, never pure black. The accent is Opal, a five-stop pastel spectrum. In light mode the ground turns to warm paper and Opal becomes a pearlescent black: the same spectrum pushed almost to black, so accents stay iridescent without losing contrast.
Token
Dark
Light
Used for
--fg
#f7f7f5 · 18.4:1
#121215 · 17.0:1
Titles, active links, body ink
--soft
#b8b5ae · 9.7:1
#47453f · 8.7:1
Reading subtext
--muted
#a9a69f · 8.1:1
#55524c · 7.1:1
Labels, meta
--quiet
#8d8a82 · 5.7:1
#6b6862 · 5.0:1
"Clearer ways through." at rest
--o1
#c6d6ff · 13.6:1
#1e2540 · 13.7:1
First Opal stop, accent text
--cta-ink
#16161a on Opal · ≥16.2:1
#f5f4f0 on pearl · ≥15.5:1
CTA labels
Ratios are against the mode's ground (#0a0a0c / #f5f4f0). All text pairs meet WCAG 2.2 AA; axe 4.10 reports 0 violations on home and case pages in both modes.
02 / 04
Type
Four voices with one job each. Bricolage Grotesque, condensed and heavy, for titles. Instrument Sans for reading. Newsreader only for the hero line, where a human voice helps. JetBrains Mono for everything that labels or acts.
HERO LINE · NEWSREADER · ITALIC NOUNSI design the flows, interfaces and systems that help people make sense of ambitious products.
BODY · INSTRUMENT SANS · 17PX · 1.6Tour scheduling and co-application, with clearer choices and visible progress.
LABEL · JETBRAINS MONO · 13PX01 / 05 · Zillow Rentals · web and mobile
Role
Size
Hero
clamp(3.2rem, 9.2vw, 8.75rem)
Case title
clamp(2.75rem, 7.5vw, 7rem)
Section title
clamp(2.25rem, 5vw, 4.25rem)
Card title
1.75rem
Lead
clamp(1.125rem, 1.6vw, 1.375rem)
Body / label / tag
1.0625rem / .8125rem / .75rem
03 / 04
Space and lines
One fluid gutter for every edge, a 1360px measure, and 1px hairlines in --line to separate rather than boxes. Frames align to the same grid so screenshots line up across a row.
Gutter
clamp(16px, 4vw, 64px)
Max width
1360px
Hairline
1px var(--line); stronger edges var(--line-2)
Hit area
44px minimum for links and controls; nav 40px pill on a 44px row
Image frames
One aspect per row (16:9 prototypes, 1:1 "away" tiles)
04 / 04
Mark
Panes: a filled front screen with two outlined screens behind. Many states, one clear object in front. On hover the panes fan out and the front one picks up the spectrum. It sits in a 32px header slot; the favicon puts it on a dark tile so it reads on white search results.
The few pieces the pages are built from. Each specimen below is the real component.
01 / 05
CTA
The primary action is filled with the soft spectrum; the secondary is an outline. Under the cursor halo the button inverts inside the circle, and it leans slightly toward the pointer.
A thin outline pill takes its size from the active link and glides between links (700ms, settle curve). It never stretches across wrapped rows; on phones the nav stays on one line.
Move across the links. Links: 40px tall, 12px padding, mono 13px; pill 1px ring, 700ms settle.
03 / 05
Chips and tags
Chips list facts in the hero. Tags state what kind of thing a prototype is, so nothing is oversold.
6+ years
SaaS
Enterprise
PlayableGuided demoEarly pilot
04 / 05
Frames
Every image is a button: it tilts a little toward the pointer, shows a reading lens over dense boards, and opens full-window on click with Escape and focus return.
05 / 05
Mode toggle
A 40px outline circle at the end of the nav. It follows the system setting until you choose, then remembers your choice. It's a pressed/unpressed button, so screen readers announce the state.
Storage
localStorage.mode: "light" or "dark"
Default
prefers-color-scheme, else dark
No flash
An inline head script sets data-mode before paint
Motion
Motion explains; it never decorates the reading. Things settle, they don't bounce.
01 / 03
Principles
Complex to clear: motion moves from scattered to aligned, never the other way.
Never block reading. Nothing hides content while it animates; intros stay under one second, once per session.
Respond, don't perform. Most motion answers the pointer or scroll; the only ambient motion is the slow drift of the blobs.
Quiet at rest. Filings sit at 3.5% opacity until the pointer comes near.
02 / 03
Easing and timing
Two curves cover everything. Press play to compare.
Settle · 700ms
Reveal · 800ms
Settle
cubic-bezier(.22, 1, .36, 1)
Nav pill 700ms, logo fan 600ms, intro
Reveal
cubic-bezier(.2, .7, .2, 1)
Sections rise 28px over 800ms
Color
ease
Link and word tints, 300–500ms
03 / 03
Reduced motion
The filings field and blobs stop; a still frame remains.
Reveals, tilt, sweep lift and the intro are skipped; content is shown at once.
Interactions you drive yourself (lens, compare slider) still respond, without easing.
Interaction
How the site answers a mouse, a finger and a keyboard.
01 / 04
Pointer field
A 76px halo ring and a spectrum dot follow the mouse. Behind the page, compass filings turn toward it within 240px, and seven soft blobs drift through the field, bending the filings around them and keeping clear of the halo.
Filings
Rest .035 alpha, up to .31 near the pointer, radius 240px
Blobs
7 metaballs, wandering speed .35–.85px/frame, leave and re-enter at random; 60 fps measured
Halo
Hidden for touch and while tabbing
02 / 04
Light sweep
Titles take a band of spectrum colour that follows the pointer with a 4px lift. Subtext gets a softer word-level tint with no movement. Try it on this paragraph.
Screen readers read the title from its aria-label; the letter spans are hidden from them.
03 / 04
Lens
A thick glass lens with a chromatic edge magnifies dense boards 1.6× under the pointer. It skips playful tiles, where it would only get in the way.
Try it on the frame in Components → Frames.
04 / 04
Keyboard and touch
Skip link first; every control reachable by Tab with a 2px spectrum focus ring.
The image viewer closes with Escape and returns focus to the image that opened it.
Touch gets 44px targets, no halo, and no hover-only information.
Patterns
Whole pieces of the site.
01 / 02
Hero
Positioning line, the two-line title ("Complex products. Clearer ways through."), the Newsreader line, chips, two CTAs, and three proof rows that each point to the work that shows them.
Title, a four-fact strip (role, focus, reported result, materials), then numbered chapters with a progress rail on wide screens. Reported results are labelled as reported; recreated data is captioned.