The system
Every token, component and state, rendered at real size.
This page links the same four stylesheets the site uses, so it renders the actual components rather than a drawing of them. Every hex value and contrast ratio below was read out of css/tokens.css when the page was generated, none of them are typed by hand, so this cannot disagree with the code.
Primitives
Raw values. Never reference these from a component: they exist only to feed the semantic layer below. The neutrals carry a ~2% warm bias at the accent's hue, so the greys read as the yellow's family rather than as an unrelated scale.
Neutrals
Bone
Yellow
Support
Semantic colour
What components read. Each shows the token it points at and its contrast against the ground it is meant to sit on: the page for most, the dark panel for the panel set, the accent fill for the ink that goes on it. There is no third component tier; that layer exists for multi-brand theming and would be structure maintained forever and never used here.
Surfaces
Lines
Text
Accent
The contrasting panel
Focus
Selection
Typography
A 1.25 major-third scale. Bricolage Grotesque carries display, IBM Plex Sans reads, IBM Plex Mono labels. The two largest steps are fluid and clamp with the viewport.
clamp(2.25rem, 7vw, 4rem)
h1 · hero
clamp(1.75rem, 3.5vw, 2.25rem)
h2 · page titles
1.625rem
h3 · section titles
1.3125rem
h4 · card titles
1.0625rem
lead paragraphs
0.9375rem
body · button label
0.8125rem
small UI · tags
0.75rem
meta · captions
0.6875rem
eyebrows · labels
Space
One 4px-based scale for components, patterns and layout alike. Do not add steps, combine existing ones instead. On this page the scale carries the structure, because surfaces sit at 1.12:1 against the page and lines at 1.29:1, so a card is barely a box.
Radius
6px
10px
14px
999px
Button radius is a ratio, not a number. A radius becomes a pill the moment it reaches half the element's height, 29px is a squircle at 72px tall and a pill at 47px. Each button size sets its own radius at ~40% of its height. If you add a size, do the same.
Button variants
Three levels of emphasis. One primary per view. No destructive variant and no loading state: the site has no destructive actions and nothing asynchronous, so both would be dead code. Add them the day something deletes or waits.
Button sizes
Four sizes, all the same shape. Measured heights with borders included: 44px, 56px, 64px, 75px, every size meets the 44px touch minimum.
Button states
The dark panel
A section-level device, not a card style. One or two moments per page: a featured case, a framed screenshot, a bio block. Everywhere and it stops being an accent and becomes a dark site with olive gaps.
Everything inside inverts automatically
Text, headings and rules all swap to the light scale with no extra classes. This paragraph is --color-panel-body at 11.3:1 on the panel.
This link is --color-accent-on-panel: the neon measures 15.6:1 here, so it keeps its colour. On the page it is 1.1:1, and links there use the darkened yellow at 5.2:1 instead.
The yellow fill works on either ground: dark ink on it measures 14.8:1 wherever it sits. Only links change job.
Components
Toggle
Two equal options, not an on/off switch. Built as two real buttons inside a role="group", each carrying aria-pressed, so a screen reader announces which language is active rather than leaving it to colour alone. It is wired to i18n/no.json.
Card sizes
Padding and title size move together, so a large card reads as the same component at a bigger scale rather than a stretched small one. .card--media drops the container padding so an image can sit flush to the edges.
Morescope
Redesigned the SBTi target-setting flow.
Morescope: Making Target Setting Easier
Redesigned the SBTi target-setting flow for an ESG compliance platform.
Morescope: Making Target Setting Easier
SBTi updated its framework mid-project, making the existing module
unworkable. I mapped the gap between the old and new requirements, then redesigned the full target-setting flow.Rules
| Rule | Why |
|---|---|
| Structure comes from space, not lines | Surfaces are 1.12:1 and lines 1.29:1 against the page. A card is barely a box, so spacing and type size carry the layout. |
--color-line is never the only cue on a control | 1.29:1. WCAG 1.4.11 wants 3:1 for interactive elements: use --color-line-interactive at 4.53:1. |
| Button radius scales with height | A fixed radius turns into a pill once it passes half the height. |
| The accent changes job on the page | 15.6:1 on the dark panel, 1.06:1 on the page. Fills keep the neon anywhere; links use --color-link at 5.2:1 instead. |
| A heading that is a link keeps the heading colour | Otherwise the accent wins and every case title turns yellow. |
| The dark panel is section-level | Used everywhere it stops being a contrast and becomes the page. |
| Never reference a Tier 1 token from a component | Breaks the one-way primitive → semantic flow the system depends on. |
| Focus is never removed | It is the only cue a keyboard user gets. Two rings, so it reads on the page and on the panel. |