Portfolio design system

Night is home, paper is the case study. One typeface, one teal, glass only as floating chrome.

Every specimen on this page is the live component, painted with the site's own tokens. The code tabs read each component's file when the site is built.

Principles

  • “Is it as obvious as knowing to sit in a chair?”
  • “Prominence = importance.”
  • “State before words.”
  • “Fact ≠ forecast.”
  • “Actionable looks actionable.”
  • “One element, one job.”
  • “SCALE leads the hierarchy — weight stays quiet. … Size makes things loud, not weight.”
  • “Main-site palette: one set, shared by the homepage and every page. Two surfaces, two line greys, three inks, one teal; paper has one ink and one muted ink. Data hues are for drawn product screens only.”
  • “Radius, three steps: pill, card 16px, inner 8px. 50% for circles.”
  • “Elevation is tone, not shadow: night → raised → floating glass.”
  • “Teal as a scalpel (not glow).”

Brand and voice

A design system is the vocabulary. This is the reason.

I didn't pull this palette from a trend deck. I built the view I see when I close my eyes.

I grew up in Mumbai, on the water, and my first home in America was by Boston Harbor. And nothing — nothing — has ever matched the feeling of the ocean and the waves for me. It's the one landscape that has felt like home on two coasts, an entire ocean apart — and I've carried it with me everywhere since. So the waves in this site aren't decoration. They're the closest thing I have to a place that has always been mine.

Then there's the light. I've painted since I was five, I keep my rooms dim, and I'm most awake at night — so the northern lights are, quite simply, the most beautiful thing I can imagine watching. For a painter, colour that dances on its own is a kind of magic. A dim room, moving light, deep water — that isn't a mood board. It's just where my mind goes when it's happiest.

This whole site is those two loves in a single frame: the ocean below, the aurora above, and everything I've made floating in the middle of it. It's my most beautiful daydream, rendered — the view I'd want to live inside.

So no — this isn't a portfolio with a nice background. It's me showing you the inside of my imagination. If you want to know who I am, you're already standing in it.

The dark
Focus. I keep my rooms dim and I work at night — the site should feel the way my studio feels.
The teal
The one colour I trust to lead. Everything else exists to support it.
One voice, quietly
I dropped the second font, then the heavy weights. One typeface, a restrained 300–600 range, and size does the shouting — the restraint is the statement.
The brain you can step into
The closest I could get to showing you the inside of my head — not just what I made.
The light that moves when you arrive
The aurora. Always. Dancing colour above, deep water below.
The stillness underneath it
A dim room at night. Somewhere I would actually want to sit.

The system in brief

Modes

Night (--bg-cinematic) is the homepage. Paper (--paper) is the white case-study page; the first-light transition moves between the two.

Accent

Teal: the color of deep ocean + aurora. It is the system, not decoration.

Buttons

One look: the teal pill. No variants, one size.

Capitals

Actions are sentence case at 14px, weight 500. Small capitals are for navigation chrome only: the header, Back, Skim and Full.

Type

One typeface, Hanken Grotesk. No monospace face; every label is Hanken held in weight, caps and tracking.

Weight

600 for display and headings, 500 for labels, 350 for body, 300 for the quietest asides.

Glass

Dark glass for floating chrome only: the nav island, icon buttons and the lightbox.

Depth

Nothing casts a shadow and no button has a border. Floating chrome is glass fill and blur; the case studies use tonal steps.

Status

A status is information, not an action: dot and plain text, no pill, no outline.

Motion

Blur-to-focus entering, focus-to-blur leaving. No crossfades.

Color

One set, the same on the homepage and every page. Night has two surfaces, two greys for lines and marks, three inks and one teal. Paper has its own inks and a darker teal so it clears contrast on white. Every older token name points at this set.

Night

Surfaces, lines, inks, teal. --glow is teal on night; --teal is teal on paper and in fills.

--night

#03070a

--raised

#0b1517

--line

#222b29

--mark

#5d6966

Aa

--ink-1

#f2f5f4

Aa

--ink-2

#c9d1cf

Aa

--ink-3

#93a09c

--teal

#078b9c

--glow

#2fc6d5

Paper

The white case studies: one ink for headings and body, one muted ink for captions and meta.

--paper

#f6f7f7

Aa

--paper-ink

#1f2a2e

Aa

--paper-ink-muted

#485459

--paper-line

#dfe4e5

--paper-teal

#066a78

Data hues

One per hue, only inside the drawn product screens and charts. Never for the site's own chrome.

--accent-amber

#f59e0b

--semantic-emerald

#10b981

--semantic-blue

#3b82f6

--semantic-rose

#f43f5e

--semantic-orange

#f97316

--semantic-purple

#a855f7

--semantic-cyan

#06b6d4

Older names

Kept so existing code keeps working. Each one resolves to the set above; none adds a colour.

--palette-zinc-100 → --ink-1

--palette-zinc-200 → --ink-1

--palette-zinc-300 → --ink-2

--palette-zinc-400 → --ink-2

--palette-zinc-500 → --ink-3

--palette-zinc-600 → --ink-3

--palette-zinc-700 → --mark

--palette-zinc-800 → --line

--palette-zinc-900 → --raised

--palette-zinc-950 → --night

--bg-primary → --night

--bg-secondary → --raised

--bg-tertiary → --raised

--bg-cinematic → --night

--button-ink → --glow

--bg-ink-950 → --night

--bg-ink-900 → --raised

--bg-monitor → --night

--bg-monitor-alt → --raised

--text-heading → --ink-1

--text-primary → --ink-1

--text-body → --ink-2

--text-muted → --ink-3

--text-dim → --mark

--text-monitor → --ink-1

--text-monitor-muted → --ink-3

--text-monitor-dim → --ink-3

--accent-teal → --teal

--accent-teal-bright → --glow

--border-monitor → --line

--focus-ring → --accent-teal

--radius-sm → --r-inner

--section-padding-mobile → --space-20

--section-padding-tablet → --space-24

--section-padding-desktop → --space-32

Case-study scope, night and paper

The case studies read their own --cs-* tokens. Paper re-points them; each pair below is painted inside the real scope.

--cs-space

var(--night) · paper var(--paper)

--cs-silver

var(--ink-1) · paper var(--paper-ink)

--cs-slate

var(--ink-2) · paper var(--paper-ink)

--cs-steel

var(--ink-3) · paper var(--paper-ink-muted)

--cs-ink

var(--ink-1) · paper var(--paper-ink)

--cs-line

var(--line) · paper var(--paper-line)

--cs-reject

#b9556a · paper #a8324d

--cs-teal

var(--teal) · paper var(--paper-teal)

Typography

One family, Hanken Grotesk, and no monospace anywhere. Size leads the hierarchy; weight stays between 300 and 600.

Family

Aa Gg Rr 0123

--font-sans

'Hanken Grotesk', 'SF Pro Text', -apple-system, BlinkMacSystemFont, sans-serif

Roles

Made obvious.

Display

--text-6xl · --weight-heading

Same weight, scale sets the rank.

Heading

--text-4xl · --weight-heading

The chair tells you it is a chair.

Subheading

--text-xl · --weight-subheading

Body sits at 350, with relaxed leading for long-form reading.

Body

--text-base · --weight-body

Label voice: weight, caps, tracking

Label

--text-xs · --weight-label

Scale

The quick brown fox, 1,234

--text-xs

0.75rem

The quick brown fox, 1,234

--text-sm

0.875rem

The quick brown fox, 1,234

--text-base

1.0625rem

The quick brown fox, 1,234

--text-lg

1.1875rem

The quick brown fox, 1,234

--text-xl

1.3125rem

The quick brown fox, 1,234

--text-2xl

1.75rem

The quick brown fox, 1,234

--text-3xl

2.1875rem

The quick brown fox, 1,234

--text-4xl

2.5rem

The quick brown fox, 1,234

--text-5xl

3rem

The quick brown fox, 1,234

--text-6xl

4rem

Weights

Restraint is the statement

--weight-heading

600

Restraint is the statement

--weight-subheading

600

Restraint is the statement

--weight-label

500

Restraint is the statement

--weight-body

350

Restraint is the statement

--weight-light

300

Leading and tracking

Two lines of sample text to show the leading between them.

--leading-tight

1.1

Two lines of sample text to show the leading between them.

--leading-snug

1.25

Two lines of sample text to show the leading between them.

--leading-normal

1.47059

Two lines of sample text to show the leading between them.

--leading-relaxed

1.6

Two lines of sample text to show the leading between them.

--leading-loose

1.8

Letter spacing

--tracking-tighter

-0.05em

Letter spacing

--tracking-tight

-0.022em

Letter spacing

--tracking-normal

-0.011em

Letter spacing

--tracking-wide

0.025em

Letter spacing

--tracking-wider

0.05em

Spacing

A 4px rhythm. Every gap and pad steps off it.

--space-1

0.25rem

--space-2

0.5rem

--space-3

0.75rem

--space-4

1rem

--space-5

1.25rem

--space-6

1.5rem

--space-8

2rem

--space-10

2.5rem

--space-12

3rem

--space-16

4rem

--space-20

5rem

--space-24

6rem

--space-32

8rem

Radius

Three steps, each with one job. Circles use 50%. The 2px and 4px corners appear only inside drawn product screens.

--r-pill

999px · buttons, chips, the nav, icon buttons

--r-card

16px · pictures, tiles, panels, frames, chat bubbles

--r-inner

8px · focus outlines, kbd, list buttons, the scrollbar thumb

Elevation

Depth is tone, not shadow. Nothing on the site casts a shadow or carries a border; a surface rises by getting lighter, and floating chrome is glass.

Night

the page

Raised

tiles, panels, wells

Glass

nav and controls over pictures

--shadow-sm, --shadow-md, --shadow-lg, --shadow-xl remain only for the drawn product screens, where the real products float their menus.

Glass and scrim

Ink over blur, for the nav and the controls that sit over pictures and video. Glass is not the button: the button is the teal fill. Defined once.

GLASS_PILL

--overlay-white-02

rgba(var(--white-rgb), 0.02)

--overlay-white-03

rgba(var(--white-rgb), 0.03)

--overlay-white-05

rgba(var(--white-rgb), 0.05)

--overlay-white-08

rgba(var(--white-rgb), 0.08)

--overlay-white-10

rgba(var(--white-rgb), 0.1)

--overlay-white-15

rgba(var(--white-rgb), 0.15)

--overlay-white-20

rgba(var(--white-rgb), 0.2)

--overlay-ink-55

rgba(var(--black-rgb), 0.55)

--overlay-ink-70

rgba(var(--black-rgb), 0.7)

--overlay-ink-75

rgba(var(--black-rgb), 0.75)

Motion

Every easing and duration token. Select a track to run it. Mirrored 1:1 for framer-motion.

Easings, at --duration-slow

--ease-cinematic

cubic-bezier(0.22, 1, 0.36, 1)

--ease-spring

cubic-bezier(0.34, 1.56, 0.64, 1)

--ease-smooth

cubic-bezier(0.4, 0, 0.2, 1)

--ease-expo

cubic-bezier(0.16, 1, 0.3, 1)

Durations, on --ease-cinematic

--duration-fast

200ms

--duration-normal

300ms

--duration-medium

400ms

--duration-slow

500ms

Contrast

Measured live in your browser from the computed tokens, with translucent fills composited over their real ground. Semantic hues never carry text in chrome, so there are no semantic text-on-tint pairs to test.

Night

PairSampleRatioWCAG AA

Heading text on page

--text-heading on --bg-primary

Aa 123measuring

Primary text on page

--text-primary on --bg-primary

Aa 123measuring

Body text on page

--text-body on --bg-primary

Aa 123measuring

Muted text on card

--text-muted on --bg-secondary

Aa 123measuring

Dim text on page

--text-dim on --bg-primary

Bar 3:1, large or decorative text only, per its token note

Aa 123measuring

Accent text on page

--accent-teal on --bg-primary

Aa 123measuring

Button label on its fill

--button-ink on --button-fill

Aa 123measuring

Button label on hover fill

--button-ink on --button-fill-hover

Aa 123measuring

Glass label over night

--palette-zinc-300 on --overlay-ink-70

Aa 123measuring

Glass label over paper

--palette-zinc-300 on --overlay-ink-70

Aa 123measuring

Focus ring against page

--focus-ring on --bg-primary

Aa 123measuring

Paper

PairSampleRatioWCAG AA

Ink (headings and body) on paper

--cs-ink on --cs-space

Aa 123measuring

Muted ink (captions) on paper

--cs-steel on --cs-space

Aa 123measuring

Teal link on paper

--cs-teal on --cs-space

Aa 123measuring

Button label on its fill

--button-ink on --button-fill

Aa 123measuring

Button label on hover fill

--button-ink on --button-fill-hover

Aa 123measuring

Focus ring against paper

--focus-ring on --cs-space

Aa 123measuring

Components

One component per job. Each one below shows where it belongs, its states side by side, its other versions, a live copy to try, and its real source.

Button

The one action on the site. One teal pill with a soft fill at rest, so it reads as a button before you hover; the border draws itself on hover and keyboard focus.

Use when

  • Any action or link that is the next step: a case-study video, a PDF download, a way back from an error
  • A disclosure that opens more detail: the case-study drill-downs (pass aria-expanded)

Don't

  • A status label: use the status dot and text
  • A link inside prose: use the inline teal link
  • Styling a one-off button with its own classes

States and variants

Hover, focus and pressed are forced from the site's own CSS, so they sit side by side.

VariantDefaultHoverFocusPressedDisabled
on night
Not in code
on paper
Not in code

Button has no disabled state in code, and no variants or sizes: one look, one size.

More versions

Contextual icon (default is the forward arrow)
External link icon
Disclosure: the case-study drill-down

Live, try it

IconButton

The circular glass control for every icon-only action: lightbox close, zoom, play, the arrows.

Use when

  • An icon everyone reads without a caption (close, play, next)
  • Floating controls over imagery or the lightbox

Don't

  • Primary actions, which deserve words: use Button
  • A second icon button styled a little differently

States and variants

Hover, focus and pressed are forced from the site's own CSS, so they sit side by side.

VariantDefaultHoverFocusPressedDisabled
md, 40px: every control
Not in code
lg: the lightbox arrows
Not in code

IconButton has no disabled state in code.

More versions

Close
Zoom
Play, filled glyph
Previous and next (lg)

Live, try it

GLASS_PILL

The one glass surface language for floating chrome, defined once as shared class strings. The chip is the smaller hint surface (⌘K, audio).

Use when

  • Anything that floats over the page: nav, lightbox chrome, icon buttons

Don't

  • Cards and panels in the page flow
  • The case studies, which have no glass
  • Re-typing the blur and ink values by hand

States and variants

Hover, focus and pressed are forced from the site's own CSS, so they sit side by side.

VariantDefaultHoverFocusPressed
GLASS_PILL_INTERACTIVE

No border and no shadow: the fill and the blur carry the edge.

More versions

Resting surface
GLASS_PILL at rest

Live, try it

Case-study status

StatusBadge: a dot and plain caps text. Information, never an action, so it is deliberately not a pill.

Use when

  • The state of the work in a case-study hero
  • A section label inside a case study

Don't

  • Anything clickable
  • A pill, outline or teal text, which would read as a button

States and versions

Live
Paper
Design done
Paper, longer label

Homepage

The homepage is the night page, built from its own file. Four type sizes, the site palette, three radii and one set of buttons that matches the case studies in shape. Every value here is read from that file.

Type: four sizes

--fs-display
The chair line, the about-me list, section headings, Let’s talk
As obvious as a chair.
--fs-title
Tile names, quotes, testimonials, the email address
As obvious as a chair.
--fs-body
Hero lines, receipts, the facts line
As obvious as a chair.
--fs-label
Labels, captions, buttons, status, tags, footer
As obvious as a chair.

Color

--night
#03070a

--raised
#0b1517

--ink-1
#f2f5f4

--ink-2
#c9d1cf

--ink-3
#93a09c

--ink-off
rgba(242,245,244,.2)

--glow
#2fc6d5

--glow-fill
rgba(47,198,213,.14)

--fill
rgba(255,255,255,.055)

--emerald
#34d3a6

Buttons: one set

Reach out →
Primary
View demo ↗
Secondary
Résumé
Chrome pill · navigation only
×
Icon button
How I work
Chip
Hiring
Chip, selected
See the systems →
Text link

Tile

WardenDecides what AI agents may do. Pausing one actually stops it.Personal tool · live demo · 299 testsView demo ↗

The picture fills edge to edge; the title sits underneath. The whole tile opens the case study, and the button opens the demo.

Rules

  • Four type sizes: display 64, title 28, body 17, label 14.
  • Primary button: teal fill, 14px weight 500, sentence case, full pill. Reach out and Ask.
  • Secondary button: tonal fill, same type and shape. View demo, Read case study, Ask Anu anything.
  • Chrome pill: 11px small capitals, tracked. Navigation only.
  • Icon button: a 40px circle, 36 in the header to match its pills.
  • Text link: teal, no underline, the arrow in the label.
  • Tiles: the whole tile opens the case study; the button beside the status opens the demo.

Rules

Do

  • Blur-to-focus (entering) and focus-to-blur (leaving) instead — everywhere.

  • Every button on the site uses this. Same surface, same shape, same hover, same press, same focus.

  • Case studies: no scroll-reveal, no decorative hover, no glow behind visuals. The ONLY motion is functional.

  • States are standardized here once so that hover / press feel identical everywhere a glass pill appears.

Don’t

  • No hex values, no Tailwind default-palette colors (text-red-500 etc.) — only semantic tokens.

  • NO crossfades. NO opacity fades.

  • No primary-only glow halos, no light-sweeps, no dark blur patches dropped over the aurora background.

  • Locked experiences: the brain experience, HeroAurora and the case-study trailers. Never modify their internals.

Spec decisions

None on this page. Every value here resolves to a site token or a case-study token. Where the site has no token, the page says so instead of inventing one: the full pill radius and the chip radius are Tailwind's, and there are no chart tokens.

The master spec fills those gaps for its shared components with --radius-md, --radius-lg and --radius-xl (10, 16 and 24px), semantic tints at 12%, and --border-strong at white 14%. The live site does not use them.

Never a loose end.

A design system is only finished when it leaves nothing dangling, so this page ends the way every path should: with a clear way forward.