Skip to content
One Stop Future Consultants

Internal reference

Design system

Every token the three sites are built from, rendered at the size it ships at. Three brand colours, two ramps, one typeface, one motion curve.

3 brand colours 21 ramp steps 1 typeface — Inter Variable 1 easing curve

01 — Colour

Three colours, two ramps

The kit names navy, blue and white and nothing else. Everything below is mixed from those three. The previous business's red #C63A2E and secondary blue #1F4E8C are gone.

The brand

Navy

#131A2C

Ground on dark, text on light.

Blue

#2268BE

Accent. Links, buttons, markers.

White

#FFFFFF

Ground on light, text on dark.

Blue ramp

  • blue-50

    #EEF4FC

  • blue-100

    #D8E6F8

  • blue-200

    #B0CCF0

  • blue-300

    #7FADE5

    7.5:1 on navy — links on dark

  • blue-400

    #4B8AD5

  • blue-500

    #2268BE

    BRAND · white on it is 5.5:1

  • blue-600

    #1B54A0

  • blue-700

    #164381

  • blue-800

    #123463

  • blue-900

    #0E2749

Ink ramp

Navy-derived rather than grey, so a light surface and a dark surface read as the same brand. ink-400 is the kit's support tone and it is a dark-ground colour only — 2.99:1 on white fails every threshold.

  • ink-50

    #F5F7FA

    the banded light surface

  • ink-100

    #EAEDF2

  • ink-200

    #D7DCE3

  • ink-300

    #B4BCC8

    9.2:1 on navy — body on dark

  • ink-400

    #8C96A5

    KIT support tone. Dark grounds ONLY — 2.99:1 on white

  • ink-500

    #5A6478

    6.3:1 on white — secondary

  • ink-600

    #39455F

  • ink-700

    #26314A

    12.0:1 on white — body

  • ink-800

    #1B2438

  • ink-900

    #131A2C

    BRAND navy · 17.3:1 against white

  • ink-950

    #0A0E1A

    the deep neutral

02 — Contrast

Every pairing the site ships

Rendered on the ground it is actually used on, because a ratio quoted against the wrong backdrop is worse than none. npm run check:contrast recomputes all of these from the tokens and fails the build on a regression.

On white

Heading — navy · 17.3:1

Body — ink-700 · 12.0:1. The default reading colour.

Secondary — ink-500 · 6.3:1.

A link — blue-500 · 5.5:1

ink-400 on white — 2.99:1. NEVER. Shown only so the failure is visible.

On navy

Heading — white · 17.3:1

Body — ink-300 · 9.2:1. The default on dark.

Secondary — ink-400 · 5.8:1.

A link — blue-300 · 7.5:1

blue-500 on navy — 3.13:1. Large text only. This is the logo's own pairing, which WCAG exempts; body copy is not exempt.

03 — Type

One family, Inter Variable

The brand kit specifies no typeface — the wordmark is outlines, so nothing has to match it. Display character comes from size, weight and optical tracking rather than from a second family. Montserrat was removed: 37KB saved, and a geometric-sans heading over a grotesk body is the single loudest template signal a page can carry.

text-display

44 → 88px · 0.98 · −0.035em · 700

Display — data, AI, software, marketing

text-h1

36 → 64px · 1.05 · −0.03em · 700

Heading 1 — data, AI, software, marketing

text-h2

28 → 48px · 1.1 · −0.025em · 650

Heading 2 — data, AI, software, marketing

text-h3

20 → 26px · 1.25 · −0.015em · 600

Heading 3 — data, AI, software, marketing

text-h4

17 → 19px · 1.35 · 600

Heading 4 — data, AI, software, marketing

text-lead

18 → 22px · 1.55

Lead — data, AI, software, marketing

text-body

17px · 1.7 · 68ch measure

Body — data, AI, software, marketing

text-sm

15px · 1.6

Small — data, AI, software, marketing

text-xs

13px · 1.5 · the floor

Extra small — data, AI, software, marketing

text-eyebrow

12px · 0.16em · 600 · uppercase

Section label

text-figure

36 → 56px · 700 · tabular

2022 · 725318 · 100%

The measure

Body copy is capped at 68ch, which lands between 62 and 70 characters per line at 17px. The rule below marks the cap.

Buying technical work usually means choosing between two bad shapes: the firm that sells senior and delivers junior, or the one that never had senior at all. The enterprise consultancy sends partners to the pitch and graduates to the project. The offshore shop quotes a rate that only works if nobody senior touches it. Both are answering a staffing question, and neither is answering yours, which is whether the thing should be built.

04 — Space

Eight-point scale

Steps 1 and 2 are the half steps icon gaps and label margins need. Everything from 3 up is a multiple of eight.

  • space-1 4px
  • space-2 8px
  • space-3 12px
  • space-4 16px
  • space-5 24px
  • space-6 32px
  • space-7 40px
  • space-8 48px
  • space-9 64px
  • space-10 80px
  • space-11 96px
  • space-12 120px
  • space-13 144px
  • space-14 176px

Section rhythm

--section-y

144px

The default band. 72px on a phone.

--section-y-lg

176px

Used once, under the hero.

--section-y-sm

96px

Strips and the closing band.

Read section padding as half a seam. Bands stack, so two adjacent sections contribute 288px between their content. That is affordable because the ground colour alternates — a seam reads as a change of surface rather than as a void.

05 — Elevation and radius

Hairline first, shadow second

A card is defined by its edge. The shadow only appears when it lifts. Every shadow is tinted with navy rather than black, so shade reads as the page's own colour. Dark surfaces get borders and never shadows — a shadow on navy is invisible and still costs a paint.

--shadow-sm

Resting chip, focused input.

--shadow-md

A raised panel.

--shadow-lg

A card under the pointer.

--radius-sm

0.5rem

--radius-md

0.75rem

--radius-lg

1.25rem

--radius-xl

2rem

06 — Motion

One curve, three durations

Restrained and confident, which rules out overshoot. The previous system's spring curve — cubic-bezier(0.34, 1.4, 0.64, 1) — sprang past its end value and back. It was deleted rather than retuned.

--ease

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

Entering, and anything responding to a pointer.

--dur

400ms

The standard. Transform, size, anything spatial.

--dur-slow

700ms

Scroll reveals, which travel further.

--stagger

90ms

Between siblings in a revealed group.

The four cards above are a live stagger — reload to watch them arrive. Everything on this page respects prefers-reduced-motion, and the reveal starting state only applies when the document is scripted, so a crawler sees finished content rather than an empty page.

07 — Components

Buttons, cards, chips, fields

Buttons on light

The primary button was red. It is blue now, and white on blue-500 is 5.53:1 — which is the whole reason the CTA could move off the retired colour without inventing a fourth brand hue.

Buttons on dark

Cards

A linked card

Hairline edge, an accent rule drawn on hover, and the whole surface as the hit area.

Read more

A static card

No lift, because nothing here is clickable.

On a dark section

Border, never a shadow.

Chips

Power BI PostgreSQL TypeScript Fixed price

Fields

That email address does not look right.

The invalid state cannot be colour alone now that the palette has no red — blue on blue would be indistinguishable from focus. It is a thicker, darker edge plus the message, and aria-invalid carries it either way.

An alert. Navy-tinted with a blue edge. The old panel was a red tint, and before that Tailwind's red-50, which was itself a colour the brand tokens forbid.

Icons

Inline stroke paths on a 24px grid, 1.5 stroke, currentColor throughout. Referenced by name from page frontmatter.

  • globe
  • users
  • shield
  • grid
  • academic
  • book
  • plane
  • passport
  • briefcase
  • building
  • chat
  • home
  • tag
  • handshake
  • alert
  • arrow-right
  • arrow-up-right
  • chevron-down
  • check
  • menu
  • close
  • mail
  • map-pin
  • clock
  • scale
  • chart
  • cpu
  • code
  • server
  • megaphone
  • file-text
  • database
  • git
  • gauge
  • layers
  • search
  • sparkle
  • plug
  • lock
  • eye
  • refresh