Design System

Tokens & Components

Edit src/designsystem/tokenRegistry.json to change tokens, run npm run sync:designsystem and edit src/designsystem/componentShowcaseRegistry.json for component coverage.

Colour primitives

Raw colour spectrums. Components should not reference these directly — always use a semantic token (e.g. --color-section, --color-headline) so that retheming works.

Neutral

black
000000
white
FFFFFF
960
141414

Greige

50
FAFAFA
100
F4F5F5
200
E7E9E9
300
CCD1D0
400
A1AAA8
500
717A79
600
525C5A
700
3F4947
800
26302F
900
172120
950
070E0E

Colour tokens

Semantic tokens resolve to a different primitive per theme. Apply a theme by setting data-theme="light" or data-theme="dark" on any wrapping element.

TokenLightDark
Section
sectionGreige/greige-200Neutral/black
section-whiteNeutral/whiteNeutral/white
section-transparentGreige/greige-900rgba(0, 0, 0, 0.38)
hero-scroll-fadergba(0, 0, 0, 0.45)rgba(0, 0, 0, 0.45)
project-detail-overlay-backdroprgba(0, 0, 0, 0.52)rgba(0, 0, 0, 0.52)
footer-reveal-backdroprgba(0, 0, 0, 0.48)rgba(0, 0, 0, 0.48)
Text
headlineNeutral/blackNeutral/white
headline-highlightGreige/greige-300Greige/greige-300
copy-defaultNeutral/blackNeutral/white
copy-highlightGreige/greige-500Greige/greige-300
eyebrowGreige/greige-600Greige/greige-300
Navigation
nav-item-defaultGreige/greige-500Greige/greige-400
nav-item-activeGreige/greige-700Greige/greige-200
nav-item-underlineGreige/greige-700Neutral/white
Controls / filled
btn-filled-bgNeutral/blackNeutral/white
btn-filled-text+iconNeutral/whiteNeutral/black
btn-filled-bg-hoverNeutral/whiteGreige/greige-300
btn-filled-text+icon-hoverNeutral/blackNeutral/black
Border
borderGreige/greige-300Greige/greige-800
Cards
card-backgroundGreige/greige-50Neutral/neutral-960
icon-card-backgroundF1F2F2Neutral/neutral-960
quote-card-headlineNeutral/blackGreige/greige-300
project-card-titleNeutral/whiteNeutral/white
card-background-hoverGreige/greige-50Greige/greige-800
contact-flyout-backgroundrgba(255, 255, 255, 0.8)rgba(255, 255, 255, 0.8)
Icon
iconNeutral/blackNeutral/white
Feedback
availability5CFF005CFF00
success16A34A16A34A
success-bgF0FDF4F0FDF4
warningD97706D97706
warning-bgFFFBEBFFFBEB
errorDC2626DC2626
error-bgFEF2F2FEF2F2

Typography

Self-hosted typeface

Public Sans

--font-sans
Source
Self-hosted in this repository
Format
ttf (variable)
Files
Normal: /public/fonts/PublicSans-Variable.ttfItalic: /public/fonts/PublicSans-Italic-Variable.ttf
Weight availability
100 – 900 (variable)
Weights used across the project
400 (Regular), 450 (undefined), 500 (Medium) Primary typeface. Regular is used by H1–H3, weight 450 by paragraph body copy, and Medium by H4–H6.

Available weight stops

Aa400 · Regular · active
Aa450 · · active
Aa500 · Medium · active

Swapping the typeface

  1. Drop the new font file or files into /public/fonts/.
  2. Update the @font-face block in src/styles/global.css (family name, src: url(), and font-weight range).
  3. Update --font-sans inside @theme to reference the new family name.

Self-hosted typeface

DejaVu Sans Mono

--font-mono
Source
Self-hosted in this repository
Format
ttf
Files
Normal: /public/fonts/DejaVuSansMono.ttf
Weight availability
550 only
Weights used across the project
550 (Medium) Secondary typeface. Used by Button and Eyebrow.

Available weight stops

Aa550 · Medium · active

Swapping the typeface

  1. Drop the new font file or files into /public/fonts/.
  2. Update the @font-face block in src/styles/global.css (family name, src: url(), and font-weight range).
  3. Update --font-mono inside @theme to reference the new family name.

Self-hosted typeface

Fraunces

--font-serif
Source
Self-hosted in this repository
Format
ttf (variable)
Files
Light: /public/fonts/Fraunces-Variable.ttfLight italic: /public/fonts/Fraunces-LightItalic-Variable.ttf
Weight availability
300 (Light) only
Weights used across the project
300 (Light) Tertiary typeface. Reserved for light upright and italic accents.

Available weight stops

Aa300 · Light · active

Swapping the typeface

  1. Drop the new font file or files into /public/fonts/.
  2. Update the @font-face block in src/styles/global.css (family name, src: url(), and font-weight range).
  3. Update --font-serif inside @theme to reference the new family name.

Heading tokens

Simple spec table for the heading scale, matching the component visualization layout.

Desktop / MaxMobile / Min
level="h1"78 px / 90 px40 px / 45 px
level="h2"50 px / 58 px32 px / 40 px
level="h3"36 px / 42 px24 px / 28 px
level="h4"24 px / 28 px20 px / 24 px
level="h5"20 px / 25 px18 px / 20 px
level="h6"16 px / 24 px16 px / 19 px

Text tokens

Simple spec table for text variants, matching the component visualization layout.

Desktop / MaxMobile / Min
variant="base"14 px / 22 px14 px / 22 px
variant="sm"12 px / 16 px12 px / 16 px

Spacing tokens

Section spacings

A section has four padding options (top and bottom) and an optional 10px radius on either its top or bottom corners. The width is always full. The container inside the section determines the content width — not the section.

Desktop / MaxMobile / Min
section-padding-big (lg)144 px64 px
section-padding-small (sm)64 px24 px
section-padding-extrasmall (xs)16 px16 px
section-padding-none (none)00
section-rounded-none00
section-rounded10 px10 px

Container spacings

Mobile containers are fluid and keep --container-edge-gutter baked into width (8px on mobile and 16px from md). Width caps apply from md using container tokens and no desktop min-width floor, so the gutter stays visible and prevents horizontal overflow. Sections stay unpadded horizontally.

Desktop / MaxMobile / Min
Container edge gutter (each side when section is narrower than width cap)16 px8 px
container-spacing-big (lg)1800 px359 px
container-spacing-small (sm)1020 px359 px

Card paddings

Responsive inner padding tokens used by card components.

Desktop / MaxMobile / Min
card-padding-xl40 px16 px
card-padding-s24 px16 px
card-padding-xs16 px8 px
--button-padding-blockButton vertical padding6px
--button-padding-inlineButton horizontal padding7px
--button-gapButton content gap16px
--eyebrow-padding-bottomEyebrow bottom padding24px
--eyebrow-gapEyebrow content gap12px
--icon-card-widthIcon card width346px
--icon-card-body-gapIcon card body gap24px
--icon-card-icon-sizeIcon card icon size12px
--icon-card-icon-radiusIcon card icon radius1px
--quote-card-padding-topQuote card top padding40px
--quote-card-padding-bottomQuote card bottom padding24px
--quote-card-padding-inlineQuote card horizontal padding16px
--quote-card-content-gapQuote card content gap24px
--quote-card-author-padding-bottomQuote card author bottom padding24px
--quote-card-author-gapQuote card author content gap16px
--quote-card-avatar-sizeQuote card author image size36px
--quote-card-meta-font-sizeQuote card workplace font size10px
--quote-card-meta-line-heightQuote card workplace line height14px
--quote-card-meta-letter-spacingQuote card workplace letter spacing1px
--quote-card-sticker-overlapQuote card sticker overlap16px
--quote-card-sticker-widthQuote card sticker width114px
--quote-card-sticker-heightQuote card sticker height31px
--quote-card-arrow-sizeQuote card arrow size16px
--project-card-max-widthProject card mobile maximum width375px
--project-card-mobile-heightProject card mobile height300px
--project-card-default-heightDefault project card desktop height500px
--project-card-screen-widthProject card screen responsive width68.4736%
--project-card-screen-max-widthProject card screen maximum width480px
--project-card-big-heightBig project card desktop height850px
--project-card-big-screen-widthBig project card screen responsive width82.1683%
--project-card-big-screen-max-widthBig project card screen maximum width576px
--project-card-mobile-screen-widthProject card mobile screen width320px
--project-card-screen-aspect-ratioProject card screen aspect ratio8 / 5
--project-card-screen-hover-scaleProject card screen hover scale1.015
--project-card-screen-transition-durationProject card screen transition duration450ms
--project-card-screen-transition-easingProject card screen transition easingcubic-bezier(0.22, 1, 0.36, 1)
--project-card-meta-padding-inlineProject card metadata horizontal padding16px
--project-card-meta-padding-bottomProject card metadata bottom padding16px
--project-card-meta-layout-gapProject card metadata layout gap16px
--project-card-meta-item-gapProject card metadata item gap10px
--project-card-meta-dot-sizeProject card metadata dot size5px
--project-card-reveal-durationProject card metadata reveal duration300ms
--project-grid-gapProject grid gap6px
--service-row-padding-blockService row vertical padding12px
--footer-smiley-sizeFooter smiley size44px
--footer-reveal-content-min-heightFooter reveal minimum content height100svh
--header-nav-padding-blockHeader navigation vertical padding12px
--header-nav-padding-inlineHeader navigation horizontal padding24px
--header-logo-column-widthHeader logo column preferred percentage width50%
--header-nav-items-gapHeader navigation items gap24px
--header-nav-item-padding-blockHeader navigation item vertical padding2px
--header-nav-item-underline-heightHeader navigation item underline height2px
--header-mobile-nav-padding-blockMobile header navigation vertical padding12px
--header-mobile-nav-padding-inlineMobile header navigation horizontal padding16px
--header-mobile-nav-toggle-hit-sizeMobile header navigation toggle hit area44px
--header-mobile-nav-item-underline-heightMobile header navigation item underline height1px
--header-mobile-nav-brand-frame-widthMobile navigation brand frame width85px
--header-mobile-nav-brand-frame-heightMobile navigation brand frame height21.048px
--header-mobile-nav-brand-widthMobile navigation brand width81.582px
--header-mobile-nav-brand-heightMobile navigation brand height16.19px
--header-mobile-nav-toggle-widthMobile navigation toggle glyph width73px
--header-mobile-nav-toggle-heightMobile navigation toggle glyph height16px
--header-mobile-menu-padding-topMobile navigation submenu top padding80px
--header-mobile-menu-padding-bottomMobile navigation submenu bottom padding40px
--header-mobile-menu-row-padding-blockMobile navigation submenu row vertical padding8px
--header-mobile-menu-nav-item-heightMobile navigation submenu item height38px
--header-mobile-menu-nav-item-max-widthMobile navigation submenu item maximum width335px
--header-mobile-menu-contact-heading-gapMobile navigation contact heading gap16px
--header-mobile-menu-contact-label-widthMobile navigation contact label width49px
--header-mobile-menu-contact-row-min-heightMobile navigation contact row minimum height32px
--header-mobile-menu-divider-heightMobile navigation submenu divider height1px
--header-mobile-menu-transition-durationMobile navigation overlay transition duration400ms
--header-mobile-menu-transition-easingMobile navigation overlay transition easingcubic-bezier(0.22, 1, 0.36, 1)
--contact-flyout-widthContact flyout width263px
--contact-flyout-padding-blockContact flyout vertical padding12px
--contact-flyout-padding-inlineContact flyout horizontal padding8px
--contact-flyout-row-padding-blockContact flyout row vertical padding6px
--contact-flyout-row-gapContact flyout row content gap24px
--contact-flyout-label-widthContact flyout row label width48px
--contact-flyout-rows-gapContact flyout rows gap6px
--contact-flyout-dot-sizeContact flyout dot size8px
--contact-flyout-backdrop-blurContact flyout backdrop blur8px
--about-hero-foreground-width-mobileAbout hero foreground mobile width72%
--about-hero-foreground-width-desktopAbout hero foreground desktop width35.5%
--hero-heading-font-size-mobileHero heading mobile font size40px
--hero-heading-font-size-desktopHero heading desktop font size78px
--hero-heading-line-height-mobileHero heading mobile line height42px
--hero-heading-line-height-desktopHero heading desktop line height80px
--hero-entrance-media-durationHero entrance media duration1800ms
--hero-entrance-content-durationHero entrance content duration1300ms
--hero-entrance-foreground-delayHero entrance foreground delay160ms
--hero-entrance-heading-delayHero entrance heading delay320ms
--hero-entrance-meta-delayHero entrance metadata delay560ms
--work-entrance-projects-delayWork page projects entrance delay720ms
--hero-entrance-easingHero entrance easingcubic-bezier(0.16, 1, 0.3, 1)
--hero-entrance-offsetHero entrance content offset16px
--hero-entrance-media-scaleHero entrance media scale1.025
--hero-availability-dot-sizeHero availability indicator size8px
--hero-availability-pulse-durationHero availability pulse duration1800ms
--hero-availability-pulse-scaleHero availability pulse scale2.25
--closing-cta-font-size-fluidClosing CTA fluid font sizeclamp(48px, 7.2vw, 128px)
--closing-cta-line-height-fluidClosing CTA fluid line height1
--project-list-sticky-offsetSticky all-projects button viewport offset64px
--project-detail-sidebar-widthProject detail fixed sidebar width210px
--section-min-height-halfSection half viewport minimum height50svh
--section-min-height-fullSection full viewport minimum height100svh
--project-detail-section-min-height-halfProject detail half overlay minimum heightcalc((100svh - 2 * var(--margin-sm)) / 2)
--project-detail-section-min-height-fullProject detail full overlay minimum heightcalc(100svh - 2 * var(--margin-sm))
--project-detail-media-height-mobileProject detail mobile media height75svh
--project-detail-mobile-content-gapProject detail mobile navigation-to-content gap40px
--project-detail-overlay-backdrop-blurProject detail overlay backdrop blur14px
--project-detail-overlay-entry-offsetProject detail overlay entry offset12px
--project-detail-overlay-transition-durationProject detail overlay transition duration360ms
--project-detail-overlay-easingProject detail overlay easingcubic-bezier(0.22, 1, 0.36, 1)
--project-detail-related-section-gapProject detail related section top gap40px
--project-detail-metadata-label-gapProject detail metadata label-to-value gap16px

Gaps

Spacing between elements inside a section and inside a container.

Desktop / MaxMobile / Min
gap-none00
gap-sm8 px8 px
gap-md16 px8 px
gap-lg32 px24 px
gap-xl32 px32 px

Margins

Responsive outer spacing tokens for section and component margins.

Desktop / MaxMobile / Min
Margin XS8 px8 px
Margin SM16 px16 px
Margin MD32 px24 px
Margin LG100 px64 px

Border radius tokens

radius-full

radius-xl

24px

radius-lg

16px

radius-md

8px

radius-sm

6px

radius-xs

4px

radius-2xs

2px

Shadow tokens

Small

--shadow-sm

Medium

--shadow-md

Large

--shadow-lg

Quick reference — all CSS tokens

VariableDefault valueUsage in Tailwind
--color-black#000000bg-[var(--color-black)]
--color-white#FFFFFFbg-[var(--color-white)]
--color-neutral-960#141414bg-[var(--color-neutral-960)]
--color-greige-50#FAFAFAbg-[var(--color-greige-50)]
--color-greige-100#F4F5F5bg-[var(--color-greige-100)]
--color-greige-200#E7E9E9bg-[var(--color-greige-200)]
--color-greige-300#CCD1D0bg-[var(--color-greige-300)]
--color-greige-400#A1AAA8bg-[var(--color-greige-400)]
--color-greige-500#717A79bg-[var(--color-greige-500)]
--color-greige-600#525C5Abg-[var(--color-greige-600)]
--color-greige-700#3F4947bg-[var(--color-greige-700)]
--color-greige-800#26302Fbg-[var(--color-greige-800)]
--color-greige-900#172120bg-[var(--color-greige-900)]
--color-greige-950#070E0Ebg-[var(--color-greige-950)]
--color-sectionlight: Greige/greige-200 · dark: Neutral/blackbg-[var(--color-section)] or text-[var(--color-section)]
--color-section-whitelight: Neutral/white · dark: Neutral/whitebg-[var(--color-section-white)] or text-[var(--color-section-white)]
--color-section-transparentlight: Greige/greige-900 · dark: rgba(0, 0, 0, 0.38)bg-[var(--color-section-transparent)] or text-[var(--color-section-transparent)]
--color-hero-scroll-fadelight: rgba(0, 0, 0, 0.45) · dark: rgba(0, 0, 0, 0.45)bg-[var(--color-hero-scroll-fade)] or text-[var(--color-hero-scroll-fade)]
--color-project-detail-overlay-backdroplight: rgba(0, 0, 0, 0.52) · dark: rgba(0, 0, 0, 0.52)bg-[var(--color-project-detail-overlay-backdrop)] or text-[var(--color-project-detail-overlay-backdrop)]
--color-footer-reveal-backdroplight: rgba(0, 0, 0, 0.48) · dark: rgba(0, 0, 0, 0.48)bg-[var(--color-footer-reveal-backdrop)] or text-[var(--color-footer-reveal-backdrop)]
--color-headlinelight: Neutral/black · dark: Neutral/whitebg-[var(--color-headline)] or text-[var(--color-headline)]
--color-headline-highlightlight: Greige/greige-300 · dark: Greige/greige-300bg-[var(--color-headline-highlight)] or text-[var(--color-headline-highlight)]
--color-copy-defaultlight: Neutral/black · dark: Neutral/whitebg-[var(--color-copy-default)] or text-[var(--color-copy-default)]
--color-copy-highlightlight: Greige/greige-500 · dark: Greige/greige-300bg-[var(--color-copy-highlight)] or text-[var(--color-copy-highlight)]
--color-eyebrowlight: Greige/greige-600 · dark: Greige/greige-300bg-[var(--color-eyebrow)] or text-[var(--color-eyebrow)]
--color-nav-item-defaultlight: Greige/greige-500 · dark: Greige/greige-400bg-[var(--color-nav-item-default)] or text-[var(--color-nav-item-default)]
--color-nav-item-activelight: Greige/greige-700 · dark: Greige/greige-200bg-[var(--color-nav-item-active)] or text-[var(--color-nav-item-active)]
--color-nav-item-underlinelight: Greige/greige-700 · dark: Neutral/whitebg-[var(--color-nav-item-underline)] or text-[var(--color-nav-item-underline)]
--color-btn-filled-bglight: Neutral/black · dark: Neutral/whitebg-[var(--color-btn-filled-bg)] or text-[var(--color-btn-filled-bg)]
--color-btn-filled-text-iconlight: Neutral/white · dark: Neutral/blackbg-[var(--color-btn-filled-text-icon)] or text-[var(--color-btn-filled-text-icon)]
--color-btn-filled-bg-hoverlight: Neutral/white · dark: Greige/greige-300bg-[var(--color-btn-filled-bg-hover)] or text-[var(--color-btn-filled-bg-hover)]
--color-btn-filled-text-icon-hoverlight: Neutral/black · dark: Neutral/blackbg-[var(--color-btn-filled-text-icon-hover)] or text-[var(--color-btn-filled-text-icon-hover)]
--color-borderlight: Greige/greige-300 · dark: Greige/greige-800bg-[var(--color-border)] or text-[var(--color-border)]
--color-card-backgroundlight: Greige/greige-50 · dark: Neutral/neutral-960bg-[var(--color-card-background)] or text-[var(--color-card-background)]
--color-icon-card-backgroundlight: F1F2F2 · dark: Neutral/neutral-960bg-[var(--color-icon-card-background)] or text-[var(--color-icon-card-background)]
--color-quote-card-headlinelight: Neutral/black · dark: Greige/greige-300bg-[var(--color-quote-card-headline)] or text-[var(--color-quote-card-headline)]
--color-project-card-titlelight: Neutral/white · dark: Neutral/whitebg-[var(--color-project-card-title)] or text-[var(--color-project-card-title)]
--color-card-background-hoverlight: Greige/greige-50 · dark: Greige/greige-800bg-[var(--color-card-background-hover)] or text-[var(--color-card-background-hover)]
--color-contact-flyout-backgroundlight: rgba(255, 255, 255, 0.8) · dark: rgba(255, 255, 255, 0.8)bg-[var(--color-contact-flyout-background)] or text-[var(--color-contact-flyout-background)]
--color-iconlight: Neutral/black · dark: Neutral/whitebg-[var(--color-icon)] or text-[var(--color-icon)]
--color-availabilitylight: 5CFF00 · dark: 5CFF00bg-[var(--color-availability)] or text-[var(--color-availability)]
--color-successlight: 16A34A · dark: 16A34Abg-[var(--color-success)] or text-[var(--color-success)]
--color-success-bglight: F0FDF4 · dark: F0FDF4bg-[var(--color-success-bg)] or text-[var(--color-success-bg)]
--color-warninglight: D97706 · dark: D97706bg-[var(--color-warning)] or text-[var(--color-warning)]
--color-warning-bglight: FFFBEB · dark: FFFBEBbg-[var(--color-warning-bg)] or text-[var(--color-warning-bg)]
--color-errorlight: DC2626 · dark: DC2626bg-[var(--color-error)] or text-[var(--color-error)]
--color-error-bglight: FEF2F2 · dark: FEF2F2bg-[var(--color-error-bg)] or text-[var(--color-error-bg)]
--font-sans'Public Sans', ui-sans-serif, system-ui, sans-serifstyle={{ fontFamily: 'var(--font-sans)' }}
--font-mono'DejaVu Sans Mono', ui-monospace, SFMono-Regular, monospacestyle={{ fontFamily: 'var(--font-mono)' }}
--font-serif'Fraunces', ui-serif, Georgia, serifstyle={{ fontFamily: 'var(--font-serif)' }}
--button-padding-block6pxp-[var(--button-padding-block)]
--button-padding-inline7pxp-[var(--button-padding-inline)]
--button-gap16pxp-[var(--button-gap)]
--eyebrow-padding-bottom24pxp-[var(--eyebrow-padding-bottom)]
--eyebrow-gap12pxp-[var(--eyebrow-gap)]
--icon-card-width346pxp-[var(--icon-card-width)]
--icon-card-body-gap24pxp-[var(--icon-card-body-gap)]
--icon-card-icon-size12pxp-[var(--icon-card-icon-size)]
--icon-card-icon-radius1pxp-[var(--icon-card-icon-radius)]
--quote-card-padding-top40pxp-[var(--quote-card-padding-top)]
--quote-card-padding-bottom24pxp-[var(--quote-card-padding-bottom)]
--quote-card-padding-inline16pxp-[var(--quote-card-padding-inline)]
--quote-card-content-gap24pxp-[var(--quote-card-content-gap)]
--quote-card-author-padding-bottom24pxp-[var(--quote-card-author-padding-bottom)]
--quote-card-author-gap16pxp-[var(--quote-card-author-gap)]
--quote-card-avatar-size36pxp-[var(--quote-card-avatar-size)]
--quote-card-meta-font-size10pxp-[var(--quote-card-meta-font-size)]
--quote-card-meta-line-height14pxp-[var(--quote-card-meta-line-height)]
--quote-card-meta-letter-spacing1pxp-[var(--quote-card-meta-letter-spacing)]
--quote-card-sticker-overlap16pxp-[var(--quote-card-sticker-overlap)]
--quote-card-sticker-width114pxp-[var(--quote-card-sticker-width)]
--quote-card-sticker-height31pxp-[var(--quote-card-sticker-height)]
--quote-card-arrow-size16pxp-[var(--quote-card-arrow-size)]
--project-card-max-width375pxp-[var(--project-card-max-width)]
--project-card-mobile-height300pxp-[var(--project-card-mobile-height)]
--project-card-default-height500pxp-[var(--project-card-default-height)]
--project-card-screen-width68.4736%p-[var(--project-card-screen-width)]
--project-card-screen-max-width480pxp-[var(--project-card-screen-max-width)]
--project-card-big-height850pxp-[var(--project-card-big-height)]
--project-card-big-screen-width82.1683%p-[var(--project-card-big-screen-width)]
--project-card-big-screen-max-width576pxp-[var(--project-card-big-screen-max-width)]
--project-card-mobile-screen-width320pxp-[var(--project-card-mobile-screen-width)]
--project-card-screen-aspect-ratio8 / 5p-[var(--project-card-screen-aspect-ratio)]
--project-card-screen-hover-scale1.015p-[var(--project-card-screen-hover-scale)]
--project-card-screen-transition-duration450msp-[var(--project-card-screen-transition-duration)]
--project-card-screen-transition-easingcubic-bezier(0.22, 1, 0.36, 1)p-[var(--project-card-screen-transition-easing)]
--project-card-meta-padding-inline16pxp-[var(--project-card-meta-padding-inline)]
--project-card-meta-padding-bottom16pxp-[var(--project-card-meta-padding-bottom)]
--project-card-meta-layout-gap16pxp-[var(--project-card-meta-layout-gap)]
--project-card-meta-item-gap10pxp-[var(--project-card-meta-item-gap)]
--project-card-meta-dot-size5pxp-[var(--project-card-meta-dot-size)]
--project-card-reveal-duration300msp-[var(--project-card-reveal-duration)]
--project-grid-gap6pxp-[var(--project-grid-gap)]
--service-row-padding-block12pxp-[var(--service-row-padding-block)]
--footer-smiley-size44pxp-[var(--footer-smiley-size)]
--footer-reveal-content-min-height100svhp-[var(--footer-reveal-content-min-height)]
--header-nav-padding-block12pxp-[var(--header-nav-padding-block)]
--header-nav-padding-inline24pxp-[var(--header-nav-padding-inline)]
--header-logo-column-width50%p-[var(--header-logo-column-width)]
--header-nav-items-gap24pxp-[var(--header-nav-items-gap)]
--header-nav-item-padding-block2pxp-[var(--header-nav-item-padding-block)]
--header-nav-item-underline-height2pxp-[var(--header-nav-item-underline-height)]
--header-mobile-nav-padding-block12pxp-[var(--header-mobile-nav-padding-block)]
--header-mobile-nav-padding-inline16pxp-[var(--header-mobile-nav-padding-inline)]
--header-mobile-nav-toggle-hit-size44pxp-[var(--header-mobile-nav-toggle-hit-size)]
--header-mobile-nav-item-underline-height1pxp-[var(--header-mobile-nav-item-underline-height)]
--header-mobile-nav-brand-frame-width85pxp-[var(--header-mobile-nav-brand-frame-width)]
--header-mobile-nav-brand-frame-height21.048pxp-[var(--header-mobile-nav-brand-frame-height)]
--header-mobile-nav-brand-width81.582pxp-[var(--header-mobile-nav-brand-width)]
--header-mobile-nav-brand-height16.19pxp-[var(--header-mobile-nav-brand-height)]
--header-mobile-nav-toggle-width73pxp-[var(--header-mobile-nav-toggle-width)]
--header-mobile-nav-toggle-height16pxp-[var(--header-mobile-nav-toggle-height)]
--header-mobile-menu-padding-top80pxp-[var(--header-mobile-menu-padding-top)]
--header-mobile-menu-padding-bottom40pxp-[var(--header-mobile-menu-padding-bottom)]
--header-mobile-menu-row-padding-block8pxp-[var(--header-mobile-menu-row-padding-block)]
--header-mobile-menu-nav-item-height38pxp-[var(--header-mobile-menu-nav-item-height)]
--header-mobile-menu-nav-item-max-width335pxp-[var(--header-mobile-menu-nav-item-max-width)]
--header-mobile-menu-contact-heading-gap16pxp-[var(--header-mobile-menu-contact-heading-gap)]
--header-mobile-menu-contact-label-width49pxp-[var(--header-mobile-menu-contact-label-width)]
--header-mobile-menu-contact-row-min-height32pxp-[var(--header-mobile-menu-contact-row-min-height)]
--header-mobile-menu-divider-height1pxp-[var(--header-mobile-menu-divider-height)]
--header-mobile-menu-transition-duration400msp-[var(--header-mobile-menu-transition-duration)]
--header-mobile-menu-transition-easingcubic-bezier(0.22, 1, 0.36, 1)p-[var(--header-mobile-menu-transition-easing)]
--contact-flyout-width263pxp-[var(--contact-flyout-width)]
--contact-flyout-padding-block12pxp-[var(--contact-flyout-padding-block)]
--contact-flyout-padding-inline8pxp-[var(--contact-flyout-padding-inline)]
--contact-flyout-row-padding-block6pxp-[var(--contact-flyout-row-padding-block)]
--contact-flyout-row-gap24pxp-[var(--contact-flyout-row-gap)]
--contact-flyout-label-width48pxp-[var(--contact-flyout-label-width)]
--contact-flyout-rows-gap6pxp-[var(--contact-flyout-rows-gap)]
--contact-flyout-dot-size8pxp-[var(--contact-flyout-dot-size)]
--contact-flyout-backdrop-blur8pxp-[var(--contact-flyout-backdrop-blur)]
--about-hero-foreground-width-mobile72%p-[var(--about-hero-foreground-width-mobile)]
--about-hero-foreground-width-desktop35.5%p-[var(--about-hero-foreground-width-desktop)]
--hero-heading-font-size-mobile40pxp-[var(--hero-heading-font-size-mobile)]
--hero-heading-font-size-desktop78pxp-[var(--hero-heading-font-size-desktop)]
--hero-heading-line-height-mobile42pxp-[var(--hero-heading-line-height-mobile)]
--hero-heading-line-height-desktop80pxp-[var(--hero-heading-line-height-desktop)]
--hero-entrance-media-duration1800msp-[var(--hero-entrance-media-duration)]
--hero-entrance-content-duration1300msp-[var(--hero-entrance-content-duration)]
--hero-entrance-foreground-delay160msp-[var(--hero-entrance-foreground-delay)]
--hero-entrance-heading-delay320msp-[var(--hero-entrance-heading-delay)]
--hero-entrance-meta-delay560msp-[var(--hero-entrance-meta-delay)]
--work-entrance-projects-delay720msp-[var(--work-entrance-projects-delay)]
--hero-entrance-easingcubic-bezier(0.16, 1, 0.3, 1)p-[var(--hero-entrance-easing)]
--hero-entrance-offset16pxp-[var(--hero-entrance-offset)]
--hero-entrance-media-scale1.025p-[var(--hero-entrance-media-scale)]
--hero-availability-dot-size8pxp-[var(--hero-availability-dot-size)]
--hero-availability-pulse-duration1800msp-[var(--hero-availability-pulse-duration)]
--hero-availability-pulse-scale2.25p-[var(--hero-availability-pulse-scale)]
--closing-cta-font-size-fluidclamp(48px, 7.2vw, 128px)p-[var(--closing-cta-font-size-fluid)]
--closing-cta-line-height-fluid1p-[var(--closing-cta-line-height-fluid)]
--project-list-sticky-offset64pxp-[var(--project-list-sticky-offset)]
--project-detail-sidebar-width210pxp-[var(--project-detail-sidebar-width)]
--section-min-height-half50svhp-[var(--section-min-height-half)]
--section-min-height-full100svhp-[var(--section-min-height-full)]
--project-detail-section-min-height-halfcalc((100svh - 2 * var(--margin-sm)) / 2)p-[var(--project-detail-section-min-height-half)]
--project-detail-section-min-height-fullcalc(100svh - 2 * var(--margin-sm))p-[var(--project-detail-section-min-height-full)]
--project-detail-media-height-mobile75svhp-[var(--project-detail-media-height-mobile)]
--project-detail-mobile-content-gap40pxp-[var(--project-detail-mobile-content-gap)]
--project-detail-overlay-backdrop-blur14pxp-[var(--project-detail-overlay-backdrop-blur)]
--project-detail-overlay-entry-offset12pxp-[var(--project-detail-overlay-entry-offset)]
--project-detail-overlay-transition-duration360msp-[var(--project-detail-overlay-transition-duration)]
--project-detail-overlay-easingcubic-bezier(0.22, 1, 0.36, 1)p-[var(--project-detail-overlay-easing)]
--project-detail-related-section-gap40pxp-[var(--project-detail-related-section-gap)]
--project-detail-metadata-label-gap16pxp-[var(--project-detail-metadata-label-gap)]
--gap-none0pxgap-[var(--gap-none)]
--gap-sm8pxgap-[var(--gap-sm)]
--gap-mdmin 8px · max 16px (viewport ≥768px)gap-[var(--gap-md)]
--gap-lgmin 24px · max 32px (viewport ≥768px)gap-[var(--gap-lg)]
--gap-xl32pxgap-[var(--gap-xl)]
--margin-xs8pxmt-[var(--margin-xs)] · mb-[var(--margin-xs)]
--margin-sm16pxmt-[var(--margin-sm)] · mb-[var(--margin-sm)]
--margin-mdmin 24px · max 32px (viewport ≥768px)mt-[var(--margin-md)] · mb-[var(--margin-md)]
--margin-lgmin 64px · max 100px (viewport ≥768px)mt-[var(--margin-lg)] · mb-[var(--margin-lg)]
--section-padding-lgmin 64px · max 144px (viewport ≥768px)py-[var(--section-padding-lg)] · Section padding prop
--section-padding-smmin 24px · max 64px (viewport ≥768px)py-[var(--section-padding-sm)] · Section padding prop
--section-padding-xs16pxpy-[var(--section-padding-xs)] · Section padding prop
--section-padding-none0pxpy-[var(--section-padding-none)] · Section padding prop
--section-rounded-none0pxrounded-[var(--section-rounded-none)] · Section rounded prop
--section-rounded10pxrounded-[var(--section-rounded)] · Section rounded prop
--container-edge-guttermin 8px · max 16px (viewport ≥768px)w-[calc(100%-2*var(--container-edge-gutter))] · Container mobile
--container-max-widthmin 359px · max 1800px (viewport ≥768px)md:w-[min(var(--container-max-width),calc(100%-2*var(--container-edge-gutter)))] · Container big
--container-min-widthmin 359px · max 1020px (viewport ≥768px)md:w-[min(var(--container-min-width),calc(100%-2*var(--container-edge-gutter)))] · Container small
--card-padding-xlmin 16px · max 40px (viewport ≥768px)p-[var(--card-padding-xl)] · Card padding
--card-padding-smmin 16px · max 24px (viewport ≥768px)p-[var(--card-padding-sm)] · Card padding
--card-padding-xsmin 8px · max 16px (viewport ≥768px)p-[var(--card-padding-xs)] · Card padding
--radius-full9999pxrounded-[var(--radius-full)]
--radius-xl24pxrounded-[var(--radius-xl)]
--radius-lg16pxrounded-[var(--radius-lg)]
--radius-md8pxrounded-[var(--radius-md)]
--radius-sm6pxrounded-[var(--radius-sm)]
--radius-xs4pxrounded-[var(--radius-xs)]
--radius-2xs2pxrounded-[var(--radius-2xs)]
--shadow-sm0 1px 2px 0 rgb(0 0 0 / 0.05)shadow-[var(--shadow-sm)]
--shadow-md0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)shadow-[var(--shadow-md)]
--shadow-lg0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)shadow-[var(--shadow-lg)]