Curitt
Last updated 1 Oct 2026
CURITT
01 / Foundations

Introduction

Done

This is the single source of truth for how Curitt looks, sounds, and feels — across the clinic, the website, print, and every campaign. It exists so that anyone working on Curitt, whether an in-house team member or an external freelancer, can make on-brand decisions without needing to ask.

Who this is for

  • Anyone writing copy for Curitt — website, social, email, print
  • Anyone designing anything — website, ads, signage, collateral
  • Developers building app.curitt.com or the marketing site
  • External partners — photographers, PR, agencies — who need to get up to speed fast

How to use it

Each section stands alone. If you're writing an Instagram caption, go to Tone of Voice. If you're building a component, go to Digital Design System for the actual token values. When in doubt, the Curitt Language section is the test every decision should pass.

02 / Foundations

The Curitt Language

Done

Nine principles. Every decision in this document, and everything built from it, should trace back to at least one of these.

Reassuring, not clinical

The opposite of a sterile hospital corridor. Warmth through material, not decoration.

Plain-spoken, not simplified

Removing everything that isn't the answer. Confidence expressed through restraint, not jargon or hand-holding.

Considered, not precious

Generous space and a small number of very deliberate decisions — not about looking expensive. Everything present has a reason to be there.

Human-scaled

Wood, warm neutrals, plants, daylight. A residential aesthetic with durable materials, creating an inviting, refined space that centres on well-being.

Time-rich, not rushed

The entire brand promise is real time with a real doctor, in the room, at the moment it matters — the one thing the Dutch system structurally can't offer.

Real, not staged

Every claim, every piece of copy, every testimonial has to survive Dutch scepticism. No stock wellness language, no unverifiable claims.

Present, not futuristic

Good technology in service of a real doctor relationship, not technology as the point. No spaceship, no chrome, no 2045.

Honest about disease, optimistic about health

Disease isn't pleasant, and Curitt won't pretend otherwise. But the clinic, the experience, the tone, is a healthy place. The optimism lives in the space and the relationship.

Relational, not transactional

Health isn't a single appointment. A curated community, a Q&A space between visits, a sense of having a medical advisor beside you rather than a service you occasionally purchase.

The test: if a decision — a colour, a headline, a photo, a font weight — can't be justified by one of these nine lines, it doesn't belong in the Curitt system.

The Name

Curitt — pronounced cure-it.

The name is the promise, said plainly: cure it before it happens. Curitt exists to find and deal with things before symptoms appear — the name should always be explained this simply, without embellishment.

Dictionary-style treatment

For the About page, and usable across brand materials:

Curitt/ˈkjʊər·ɪt/verb, informal
To cure it before it happens.
"Most things are easier to deal with early. So we Curitt."

Usage rules

  • The pronunciation explanation appears on the About page and may be used in introductions, pitch materials, and campaign moments — but sparingly. It's a nice reveal, not a tagline to exhaust.
  • "Cure it before it happens" and "Curitt before symptoms appear" are approved supporting lines. They work because they're literal — keep them that way. No riffing into "Curitt your way to wellness" territory.
  • The dictionary treatment should always follow the format above: bold name, phonetic spelling, part of speech, plain definition, one example sentence. The example sentence can vary by context, but stays short and dry.
  • Never explain the name apologetically ("it's a play on...") — state it as fact. The confidence is part of the register.
03 / Foundations

Tone of Voice

In progress

How the Curitt Language sounds in practice — plus one working decision that affects almost everything downstream.

Patient vs Member — working decision

Member for everything before and around the clinical moment — marketing, booking, the community/Q&A layer, ongoing relationship. It's warm, it signals belonging, and it supports "relational, not transactional" directly. Patient for the clinical moment itself — diagnosis, results, anything medically serious — where the weight of the word is doing real work, not just vibes.

The transition between the two needs to feel deliberate, not jarring — the shift from "member" to "patient" at the point results are delivered should read as a signal that we're in the serious part now, not a random register change. Worth testing the actual transition copy specifically once written.

Working direction: as of 3 Aug 2026 — to be discussed further once the Marketing Lead joins, per Ted.

Before / after

Instead ofSay
Take control of your future health todayBook a full health check
Cutting-edge preventive diagnosticsA full check-up, with a doctor who has time for you
Don't wait until it's too lateMost things are easier to deal with early. That's the whole idea.
✍️

More examples coming. This section will expand with copy for booking flows, results delivery, and the GLP-1 programme specifically — all reviewed for KOAG/KAG compliance before publishing (see Section 14).

04 / Identity

Logo & Identity Marks

Not started

Wordmark, lockups, clear space, minimum size, favicon and app icon.

◇

Likely wordmark-led rather than symbol-led, in keeping with "plain-spoken, not simplified" and "considered, not precious." To be explored once the type pairing (Section 06) is finalised.

05 / Identity

Colour

Done

Named tokens, not arbitrary hex values. Six ramp families, each a full numbered scale with semantic aliases layered on top. Click any swatch to copy its CSS variable.

Surfaces

surface-base
#FFFFFF
Copied!
surface-card
#F5F3F0
Copied!

Neutral Black

neutral-black-600 = text-primary. Body copy, headings — safe everywhere.

950
800
600
400
200
100
50
#0B0B09
#11100E
#161512
#4F4E49
#8B8A89
#D0D0D0
#F3F3F3

Neutral Grey

neutral-grey-600 = text-secondary, 5.03:1 on white. Captions, muted UI text.

950
800
600
400
200
100
50
#2E2D2B
#51504D
#706F6B
#9F9E97
#BCBBB8
#DFDED9
#F4F3F0

Clay

clay-600 = accent-signature — buttons, icons, large fills only (3.35:1, not text-safe). clay-800 = accent-signature-text — the text-safe version (5.50:1), for any clay-coloured text.

950
800
600
400
200
100
50
#6C3727
#A1533D
#D86E4E
#E88C71
#EDB8A9
#F8E2DC
#FEF8F7

Green

green-600 = accent-green, ~9–10:1 on white — the one accent safe to use directly as body text or links, no shade needed.

950
800
600
400
200
100
50
#08271E
#0E372B
#1C483B
#477568
#7DA59A
#C3DDD6
#F5F6F5

Wood

wood-600 = accent-wood — dividers, wayfinding, joinery-toned icons. Fill only, never text.

950
800
600
400
200
100
50
#715C47
#957657
#C1A07F
#D2BCA8
#E5D8CB
#F4EBE4
#FAF8F6

Sand

sand-600 = accent-sand — section backgrounds, alternating bands. Fill only, never text or small UI details.

950
800
600
400
200
100
50
#7F6D5F
#A99687
#DBD2CB
#EAE3DD
#F5EEE8
#FDF7F1
#FBF8F5

Numbered scale vs semantic names

Two layers, on purpose. The raw numbered ramp (--clay-600, --green-800, and so on) is the full palette — every step, for anyone who needs a specific one. The semantic aliases (--accent-signature, --text-primary, --signal-attention, and so on) are what everyone should reach for by default; each one just points at a step in the ramp underneath.

Write var(--accent-signature) in a component, not var(--clay-600) directly — even though they resolve to the same value today. The semantic name is the one that can be re-pointed at a different step later without touching every component that uses it. Reach for the numbered scale only when there's a specific, documented reason a semantic token doesn't cover.

Colour usage ratio

How often each colour should appear across a typical Curitt page or piece of collateral — not a palette, a proportion guide. White and near-white carry most of the space; colour is used with intention, not decoration.

surface-base
~42%
#FFFFFF
surface-card
~18%
#F5F3F0
text-primary
~3%
#161512
text-secondary
~4%
#706F6B
accent-green
~22%
#1C483B
accent-sand
~8%
#DBD2CB
accent-wood
~2%
#C1A07F
accent-signature
~4%
#D86E4E

What earns each share

ColourWhy it's this proportion
White / surface-cardThe calm backdrop — the majority of any page or room should read as quiet, not coloured. This is the "considered, not precious" principle made literal.
GreenThe largest true colour presence — Curitt is a green-forward brand. It's also the one accent safe as body text, so it naturally appears more than any other hue.
SandSecondary surface tone — section backgrounds, alternating bands — present but never louder than white.
ClaySmall and decisive. A genuine accent, not a co-equal brand colour — buttons, key CTAs, single moments of warmth.
WoodThe smallest slice — dividers, wayfinding, fine detail. Felt more than seen.
Text (black/grey)Small by area, but doing all the reading work — legibility, not decoration.

Where to use which

TokenUse forNever use for
text-primaryBody copy, headingsBackgrounds
text-secondaryCaptions, muted UI textAnything under 12px
accent-signature (clay-600)Buttons, icons, large fillsBody-sized text (3.35:1, fails AA)
accent-signature-text (clay-800)Any clay-coloured textLarge fills (too dark, loses warmth)
accent-greenBody text, links, buttons — safe directly—
accent-woodDividers, wayfinding, joinery-toned iconsText, large fills
accent-sandSection backgrounds, alternating bandsText, small UI details
signal-attention / signal-successStatus badges, inline warningsNever as decorative brand colour — keep functional meaning separate even though values currently match
Focus state (keyboard nav): focus-outline = clay-600, 2px solid outline only — never used as text. The old ochre's outline role is fully retired; clay takes over.

CSS variables

/* Curitt design tokens */
:root {
  /* ===== Surfaces (off-ramp) ===== */
  --surface-base: #FFFFFF;
  --surface-card: #F5F3F0;

  /* ===== Neutral Black ramp (text-primary) ===== */
  --neutral-black-950: #0B0B09;
  --neutral-black-800: #11100E;
  --neutral-black-600: #161512;  /* = text-primary */
  --neutral-black-400: #4F4E49;
  --neutral-black-200: #8B8A89;
  --neutral-black-100: #D0D0D0;
  --neutral-black-50:  #F3F3F3;
  --text-primary: var(--neutral-black-600);

  /* ===== Neutral Grey ramp (text-secondary) ===== */
  --neutral-grey-950: #2E2D2B;
  --neutral-grey-800: #51504D;
  --neutral-grey-600: #706F6B;  /* = text-secondary, 5.03:1 on white */
  --neutral-grey-400: #9F9E97;
  --neutral-grey-200: #BCBBB8;
  --neutral-grey-100: #DFDED9;
  --neutral-grey-50:  #F4F3F0;
  --text-secondary: var(--neutral-grey-600);

  /* ===== Clay ramp (accent-signature) ===== */
  --clay-950: #6C3727;
  --clay-800: #A1533D;  /* text-safe, 5.50:1 */
  --clay-600: #D86E4E;  /* fill/icon only, 3.35:1 */
  --clay-400: #E88C71;
  --clay-200: #EDB8A9;
  --clay-100: #F8E2DC;
  --clay-50:  #FEF8F7;
  --accent-signature: var(--clay-600);
  --accent-signature-text: var(--clay-800);

  /* ===== Green ramp (accent-green) ===== */
  --green-950: #08271E;
  --green-800: #0E372B;
  --green-600: #1C483B;  /* = accent-green, ~9-10:1 on white, safe as text directly */
  --green-400: #477568;
  --green-200: #7DA59A;
  --green-100: #C3DDD6;
  --green-50:  #F5F6F5;
  --accent-green: var(--green-600);

  /* ===== Wood ramp (accent-wood) ===== */
  --wood-950: #715C47;
  --wood-800: #957657;
  --wood-600: #C1A07F;  /* = accent-wood, fill only */
  --wood-400: #D2BCA8;
  --wood-200: #E5D8CB;
  --wood-100: #F4EBE4;
  --wood-50:  #FAF8F6;
  --accent-wood: var(--wood-600);

  /* ===== Sand ramp (accent-sand) ===== */
  --sand-950: #7F6D5F;
  --sand-800: #A99687;
  --sand-600: #DBD2CB;  /* = accent-sand, fill only */
  --sand-400: #EAE3DD;
  --sand-200: #F5EEE8;
  --sand-100: #FDF7F1;
  --sand-50:  #FBF8F5;
  --accent-sand: var(--sand-600);

  /* ===== Functional aliases — separately named even where they currently equal a brand accent ===== */
  --signal-attention: var(--clay-600);
  --signal-attention-text: var(--clay-800);
  --signal-success: var(--green-600);
  --focus-outline: var(--clay-600);  /* old ochre fully retired — clay takes over this role */
}
Rule: name what a colour is for, never what it looks like. Use accent-signature in code and conversation, never "the orange one." And reach for the semantic alias, not the numbered scale, unless there's a documented reason not to.
06 / Identity

Typography

Done

General Sans (Medium/Semibold) carries headlines. Public Sans (Regular) carries body copy and UI. Monospace is removed for now — no element in the system currently uses it. Every size below is derived from a minor third scale (1.200 ratio) at a 16px base — nothing here was picked by eye.

Working direction: as of 3 Aug 2026, per Johannes. General Sans (Medium) replaces the earlier Instrument Serif / Recoleta / Fraunces candidates for now.

Download the typefaces for use on other projects:

The full type scale

display-lg
The quick fox
62px · 1.0 · −0.02em · General Sans Regular
Rare — full-bleed campaign onlyCapped at 62px — exceeds the pure 1.2 ratio at the top end, a deliberate exception.
display
The quick fox
58px · 1.05 · −0.02em · General Sans Regular
Hero headline
display-sm
The quick brown fox
48px · 1.1 · −0.02em · General Sans Regular
Hero, smaller viewport
h1
The quick brown fox jumps
40px · 1.15 · −0.01em · General Sans Regular
Page titlesGrouped with Display (Regular) rather than H2–H4 (Medium).
h2
The quick brown fox jumps over
33px · 1.25 · −0.01em · General Sans Medium
Section titles
h3
The quick brown fox jumps over the
28px · 1.3 · −0.01em · General Sans Medium
Subsections
h4
The quick brown fox jumps over the lazy
23px · 1.4 · −0.01em · General Sans Medium
Small subheads
body-large
The quick brown fox jumps over the lazy dog, again and again.
19px · 1.55 · 0em · Public Sans
Lead paragraphs, intros
body
The quick brown fox jumps over the lazy dog, again and again, without ever losing its balance.
16px · 1.6 · 0em · Public Sans
Base — everything derives from this
caption
The quick brown fox jumps over the lazy dog near the riverbank at dawn.
13px · 1.5 · 0em · Public Sans
Labels, meta, timestamps
caption-small
The quick brown fox jumps over the lazy dog near the riverbank at dawn, every single morning.
11px · 1.5 · 0em · Public Sans
Legal, fine print only
eyebrow / label
The quick brown fox jumps
11px · 1.5 · +0.1em · Public Sans
Uppercase labels — the one place tracking loosens

Weight pairing

Updated to match the revised Figma type scale — headings moved off Semibold entirely.

UseWeight (was)Weight (now)
Display / H1600 (Semibold)400 (Regular)
H2–H4600 (Semibold)500 (Medium)
Body400400 (unchanged)
Body emphasis / labels500500 (unchanged)
Uppercase eyebrows600600 (unchanged)

H1 is grouped with Display (Regular, 400) rather than H2–H4 (Medium, 500). Confirmed by Johannes, 18 September 2026.

Regular
400 — Display, H1, body copy
Medium
500 — H2–H4, emphasis, labels
Semibold
600 — uppercase eyebrows only
Bold
700 — rare, top-level display only

Pairings in context

Section header · h3 + body
A clinic that feels like coming home.
Every check-up includes a full consultation with a doctor who actually has time for you.
Hero moment · display-sm + body-large
Know more.
Worry less.

CSS variables

/* Curitt type scale — minor third (1.200), base 16px */
:root {
  /* ===== Typefaces ===== */
  --headline: 'General Sans', sans-serif;  /* display, h1–h4 */
  --body: 'Public Sans', sans-serif;      /* body-large, body, caption, caption-small, eyebrow/label */

  --text-caption-small: 0.6875rem;   /* 11px */
  --text-caption: 0.8125rem;         /* 13px */
  --text-body: 1rem;                 /* 16px */
  --text-body-large: 1.1875rem;      /* 19px */
  --text-h4: 1.4375rem;              /* 23px */
  --text-h3: 1.75rem;                /* 28px */
  --text-h2: 2.0625rem;              /* 33px */
  --text-h1: 2.5rem;                 /* 40px */
  --text-display-sm: 3rem;           /* 48px */
  --text-display: 3.625rem;          /* 58px */
  --text-display-lg: 3.875rem;       /* 62px — capped, deliberate exception to the 1.2 ratio */

  --leading-caption: 1.5;
  --leading-body: 1.6;
  --leading-body-large: 1.55;
  --leading-h4: 1.4;
  --leading-h3: 1.3;
  --leading-h2: 1.25;
  --leading-h1: 1.15;
  --leading-display-sm: 1.1;
  --leading-display: 1.05;
  --leading-display-lg: 1.0;

  --tracking-display: -0.02em;
  --tracking-heading: -0.01em;
  --tracking-body: 0em;
  --tracking-label: 0.1em;

  /* ===== Weights ===== */
  --weight-display: 400;   /* Display-lg, Display, Display-sm, H1 */
  --weight-heading: 500;   /* H2, H3, H4 */
  --weight-body: 400;
  --weight-emphasis: 500;
  --weight-label: 600;    /* uppercase eyebrows */
}
07 / Identity

Materials & Space

Done

Crisp white ceiling and walls, warm clay zellige-style tile as a single accent surface, natural wood door frames and joinery, a single sculptural cut-out as a moment of surprise, deep green planting used generously, pale grey polished concrete floor.

Direction: as far from Neko as possible. Think Japandi — Japanese restraint meets Scandinavian warmth — not sci-fi wellness. Natural materials, calm proportions, nothing chrome, nothing pod-like.

Material palette

Clay tileAccent wall only
WhiteCeiling, walls
Natural oakFrames, joinery
Polished concreteFloor
Deep greenPlanting
08 / Identity

Photography & Imagery

Not started

Direction, subject matter, diversity, colour grading, what to avoid.

📷

Real patients and real doctors, reflecting the actual 25–50 urban/expat demographic. No stock wellness photography, no staged stethoscope-and-smile clichés. To be developed alongside the first clinic shoot.

09 / Identity

Iconography & Illustration

In progress

Style, line weight, usage in UI and print.

Icon system

Lucide. Outline style only, matches the "plain-spoken, not simplified" and "considered, not precious" principles directly — clean single-weight strokes, no unnecessary detail.

Full Lucide guide

Sizes

12px, 14px, 16px, 18px, 20px, 24px. Pick by context — 12/14 for dense UI and inline labels, 16 as the default for most interface icons, 18/20 for larger touch targets or standalone icon moments, 24 for the icon browser below and other large/standalone icon moments.

Browse all icons

Every Lucide icon, live. Search by name or keyword, sort by popularity or A–Z, and preview against light or dark. Click any icon to copy or download it.

Loading icons…

Custom icons

Where Curitt needs something Lucide doesn't cover, custom icons should match Lucide's outline conventions — same stroke width logic, same corner radius approach, same visual weight — so a mixed set never reads as two different icon families.

In practice: build it in Figma on a 24×24 artboard, 2px stroke, round caps and joins, no fill (see the JSX example below for the one exception). Export as SVG, strip it down to just the inner shape elements — no <svg> wrapper, no fill/stroke attributes, those are applied globally — and add an entry to curitt-custom-icons.json alongside the brand book:

{
  "my-icon-name": {
    "s": "<path d=\"...\"/>",
    "t": ["search", "tags"]
  }
}

It'll appear in the browser above automatically, flagged with a Custom badge.

Filled icons — exception, not the rule

Lucide's stroke fills aren't officially supported, but work cleanly on select icons via fill + strokeWidth={0} (e.g. <Star fill="var(--accent-signature)" strokeWidth={0} />). Reserve filled icons for specific necessary cases — ratings, favourites/saved states — never as a general style choice. Outline stays the default everywhere else.

import { Star } from "lucide-react";

// Outline (default)
<Star size={16} strokeWidth={1.5} />

// Filled — exception case only (ratings, favourites)
<Star size={16} fill="var(--accent-signature)" strokeWidth={0} />
10 / Product & Data

Data & Health Information Design

In progress

How results, risk, and biomarkers are visualised without alarming the reader or feeling clinical.

The core problem

Traffic-light red/amber/green is the default in most health software, but it works against everything in Section 02 — it's alarming, clinical, and designed for a doctor's dashboard, not a patient's reassurance.

Direction to explore

  • Language-led rather than colour-led — "within range" / "worth a conversation" / "let's look at this together" rather than green/amber/red
  • Where colour is used at all, pull from the Done palette — accent-green for reassurance, signal-attention (muted amber, never red) for anything needing a conversation
  • Decide deliberately whether the same visual language should feel more patient-facing (warm, plain language) or more doctor-facing (precise, clinical) depending on which surface it's on
📊

Full component specs pending — this is one of the highest-priority sections to finish before app.curitt.com design begins.

11 / Product & Data

Digital Design System

In progress

Component logic, design tokens, the curitt.com (Framer) / app.curitt.com split, accessibility standards.

Curitt runs on two platforms with two different levels of guarantee. The app is code, so tokens can be enforced — an off-brand value simply won't compile. The marketing site is built visually in Framer, so tokens are encouraged through convenience — the easiest path is the on-brand one, but nothing physically blocks someone from picking an arbitrary colour on the canvas. Both aim at the same tokens; only the strength of the guarantee differs.

Spacing — the 4px grid

Every padding, margin, and gap value in the app or Framer site must be a multiple of 4px — no arbitrary values, no 13px "close enough" spacing. This is the same discipline as the colour and type systems: a fixed, named scale rather than eyeballed numbers.

The one exception: border and stroke widths (1px, 2px, 3px) sit outside the spacing grid entirely — hairline details genuinely need sub-4px precision and should use --stroke-hairline, --stroke-thin, or --stroke-medium directly, never treated as spacing.

:root {
  /* Spacing scale — strict 4px grid */
  --space-2xs: 4px;
  --space-xs:  8px;
  --space-s:   12px;
  --space-m:   16px;
  --space-l:   24px;
  --space-xl:  32px;
  --space-2xl: 48px;
  --space-3xl: 64px;
  --space-4xl: 96px;

  /* Hairline exception — NOT part of the spacing grid, borders/strokes only */
  --stroke-hairline: 1px;
  --stroke-thin: 2px;
  --stroke-medium: 3px;
}

App — app.curitt.com (React)

Core principle: one primitive, typed props, enforced at build time. Off-brand decisions should be inexpressible, not just discouraged.

The Box primitive

Every layout element — what would normally be a raw <div> — goes through a single <Box> component. No other component or raw div is used for layout, spacing, or background anywhere in the app.

type SpaceToken = "2xs" | "xs" | "s" | "m" | "l" | "xl" | "2xl" | "3xl" | "4xl";
type SurfaceToken = "base" | "card" | "sunken";
type TextToken = "primary" | "secondary" | "tertiary";
type RadiusToken = "none" | "s" | "m" | "full";
type BoxProps = {
  background?: SurfaceToken;
  padding?: SpaceToken;
  paddingX?: SpaceToken;
  paddingY?: SpaceToken;
  gap?: SpaceToken;
  radius?: RadiusToken;
  direction?: "row" | "column";
  as?: keyof JSX.IntrinsicElements; // default "div"
  children: React.ReactNode;
};
export function Box({
  background, padding, paddingX, paddingY, gap, radius,
  direction = "column", as: Tag = "div", children,
}: BoxProps) {
  return (
    <Tag
      className={cx(
        background && `bg-${background}`,
        padding && `p-${padding}`,
        paddingX && `px-${paddingX}`,
        paddingY && `py-${paddingY}`,
        gap && `gap-${gap}`,
        radius && `radius-${radius}`,
        `dir-${direction}`
      )}
    >
      {children}
    </Tag>
  );
}
Why this matters: background="card" can only ever resolve to var(--surface-card) — there is no path to typing a hex code, because the prop's type is a fixed union, not a string. A developer, or an LLM writing code against this component, physically cannot pass background="#F5F3F0" — TypeScript rejects it before it ever reaches a browser.

Token reference table

Token typeValuesCSS variable
backgroundbase / card / sunken--surface-base, --surface-card, --surface-sunken
padding, gap2xs / xs / s / m / l / xl / 2xl / 3xl / 4xl--space-2xs through --space-4xl
radiusnone / s / m / full--radius-s, --radius-m, 9999px

Dark mode — light-dark(), no dark: variants

:root {
  --surface-base: light-dark(#FFFFFF, #141310);
  --surface-card: light-dark(#F5F3EF, #1E1C18);
  --text-primary: light-dark(#161512, #F7F5F0);
  color-scheme: light dark;
}

One definition per token, not a parallel dark: class system. Dark mode is a value, not a separate styling pass.

Enforcement — ESLint, not just documentation

A lint rule fails the build if anyone writes a raw colour, an arbitrary Tailwind utility, or a bare <div> for layout. See box-component-spec.md and .eslintrc-tokens-example.json in the project root for the starter spec and config — this is what makes the system watertight: the rule, not the reminder.

The test for this section: a developer, or an LLM, should get a build error, not a code review comment, if they try to write background: #D86E4E directly instead of <Box background="signature">.

Marketing Website — curitt.com (Framer)

Enforcement level: best-effort, via Shared Styles and Code Components — not a hard compile-time block.

Shared Styles setup

Every token from Section 05 (Colour) should exist as a Framer Shared Style before anyone starts building pages — named to match the CSS tokens exactly, so there's no translation step between the brand book and what shows up in Framer's style picker.

Framer Shared Style nameMatches tokenValue
Surface / Base--surface-base#FFFFFF
Surface / Card--surface-card#F5F3F0
Text / Primary--text-primary#161512
Text / Secondary--text-secondary#706F6B
Accent / Signature (clay-600)--accent-signature#D86E4E
Accent / Signature Text (clay-800)--accent-signature-text#A1533D
Accent / Signature Soft (clay-100)--accent-signature-soft#F8E2DC
Accent / Green (green-600)--accent-green#1C483B
Accent / Green Bright (green-400)--accent-green-bright#477568
Accent / Green Soft (green-100)--accent-green-soft#C3DDD6
Accent / Wood (wood-600)--accent-wood#C1A07F
Accent / Sand (sand-600)--accent-sand#DBD2CB
Signal / Attention (= clay-600)--signal-attention#D86E4E
Signal / Attention Text (= clay-800)--signal-attention-text#A1533D
Signal / Success (= green-600)--signal-success#1C483B

Text styles (headline, body, caption) should be set up the same way once the headline typeface is finalised — named Display / H1, Body / Regular, Caption, etc., never left as ad hoc per-element formatting.

Code Components — the closer equivalent to real enforcement

For anything reused often — buttons, cards, section headers, the booking CTA — build these as Framer Code Components rather than canvas-assembled elements. A code component can have genuinely typed props, same principle as the app's Box:

type CurittButtonProps = {
  variant: "primary" | "secondary"; // not a free string
  size: "s" | "m" | "l";
};

This gives hard enforcement for that specific component, even though the surrounding page canvas remains best-effort.

What this doesn't solve

Someone can still open the canvas and pick an arbitrary hex from the colour wheel, or drag a padding value that doesn't match the spacing scale. There's no build step to catch this. The mitigation is process, not code: whoever's building pages uses the Shared Styles library and Code Components as the default path, and anything off-brand gets caught in review rather than at compile time.

Practical takeaway: get the Shared Styles library set up correctly before a single page is built — retrofitting it after twenty pages exist is far more painful than starting with it in place.

Use this design system in AI tools

One Markdown file that turns any AI assistant into a Curitt designer. It opens with instructions telling the model this is Curitt's design system and to follow it, then carries the hard rules, every token as live CSS, the component CSS, and the full brand book. It's built from this page when you click, so it's always current. The filename and the file itself carry the version (e.g. curitt-design-system-v0.10.md), and the file tells the AI to check this brand book for a newer version before starting work, and to tell you if yours is out of date.

ToolHow to install it as a persistent design system
Claude (claude.ai)As a Skill: put the file in a folder called curitt-design-system, rename it SKILL.md, zip the folder and upload it under Settings → Capabilities → Skills. Or add it to a Project's knowledge.
Claude CodeSave it as .claude/skills/curitt-design-system/SKILL.md in the repo. The file's header is already a valid skill header.
ChatGPTUpload it as a knowledge file in a Project or custom GPT, and paste the opening instructions into the custom instructions.
CursorSave it as .cursor/rules/curitt-design-system.mdc.
Figma Make, v0, LovableAdd it to the project's knowledge or custom instructions.

Components

Mirrored from the "02 · Components" page of the Curitt Figma file. Figma is the source of truth: each component here binds to the same tokens Figma's variables do, so a value only ever changes in one place. Buttons first; inputs, badges, cards and navigation follow the same pattern.

Button

Four styles, two sizes, four states. Primary for the one action that matters on a screen, Secondary beside it, Ghost for low-emphasis actions, and White on photography or the green band. The Default column is live, so hover and press those; the other columns are pinned for reference.

DefaultHoverActiveDisabled
Primary · Default
Primary · Small
Secondary · Default
Secondary · Small
Ghost · Default
Ghost · Small
White · Default
White · Small

The icon is always Lucide arrow-right at 16px, leading or trailing, with an 8px gap.

No iconLeadingTrailing
Primary · Default
Secondary · Small
StyleFillTextHoverActive
Primaryaccent-greenneutral-black-50green-800green-950
SecondaryNone, 1.5px inside ring in text-primarytext-primaryneutral-grey-50neutral-grey-100
GhostNonetext-primaryneutral-black-100neutral-black-200
Whitesurface-basegreen-800neutral-grey-50neutral-grey-100
Disabled (all)neutral-grey-200 fill or ring, 50% opacityneutral-grey-400——
SizeTypePaddingHeight
DefaultCuritt/Body: Public Sans 400, 16/2610px / 16px46px
SmallCuritt/Label: General Sans 600, 11/16, +10%, uppercase10px / 16px36px

All styles are fully rounded pills. Keyboard focus shows a 2px focus-outline ring with a 2px offset.

<button class="btn btn--primary">Book a check-up</button>
<button class="btn btn--secondary">How it works</button>
<button class="btn btn--ghost btn--small">
  Learn more <svg class="icon"><use href="#icon-arrow-right"/></svg>
</button>

Button group

One to four buttons in a row, 12px apart, in descending emphasis: Primary, then Secondary, then Ghost.

To fix in Figma

porting the Button set surfaced a few inconsistencies in the source file. The brand book follows Figma as-is for now, apart from the focus ring.

  • Vertical padding is 10px (46px and 36px tall), which is off the 4px grid. 12px would give 50px and 40px; 8px would give 42px and 32px.
  • Secondary's 1.5px ring isn't on the stroke scale (1px, 2px, 3px).
  • Secondary · Small is 39px tall in Figma, against 36px for the other Small styles.
  • Every Small variant with a leading icon is 46px tall, the Default height.
  • There's no focus state in Figma. The brand book adds one for keyboard users.
  • The Small label uses Curitt/Label in General Sans, but Section 06's eyebrow / label specimen says Public Sans. One of the two needs updating.
  • The leading-icon variants overlap the Button Group on the Figma canvas.

Tabs

A segmented control for switching views inside a panel. The selected tab fills with accent-green. A tab can carry the clay highlight badge to mark a recommended option. The control below is live.

Tab control
Default
Hover
Selected
Disabled
Default · highlighted
Hover · highlighted
Selected · highlighted
Disabled · highlighted
To fix in Figma
  • Tab labels use raw Public Sans Medium 13, not one of the Curitt text styles.

Calendar day & time slot

The two atoms of the booking date-and-time picker. Today gets a 1.5px accent-green ring; a selected day or slot fills in accent-green.

Default
Hover
Today
Selected
Disabled
Default
Hover
Selected
Disabled
To fix in Figma
  • The day number is raw Public Sans Medium 14px, which isn't on the type scale (13px and 16px are the neighbours).
  • Time slots have 10px vertical padding (off the 4px grid) and an 8px corner radius. Figma has no radius variables, so radii are hand-set across the library.
  • Like the Secondary button, the Today ring is 1.5px, off the 1/2/3px stroke scale.

Tag

Short category or attribute labels. Outlined on light surfaces; Filled where the tag needs to stand out.

Tag labelOutlined · Medium
Tag labelOutlined · Small
Tag labelFilled · Medium
Tag labelFilled · Small
SizeTypePadding
MediumCuritt/Caption, 13/196px / 12px
SmallCuritt/Caption-sm, 11/164px / 10px
To fix in Figma
  • Padding of 6px and 10px is off the 4px grid.

Badge

Status and emphasis labels. Label for neutral metadata, Highlight to flag a recommended option (e.g. "Most popular"), Overlay to sit on top of imagery, and the clay Highlight badge for a single standout marker.

LabelLabel
Most popularHighlight
Badge titleBadge subtitleOverlay
Highlight badgeHighlight badge · text
Highlight badgeText + icon
Icon only
To fix in Figma
  • The Highlight badge tracks at 1.5px, while every other uppercase label uses 10% (1.1px at 11px).
  • The Overlay badge uses a 27px radius and a 2px gap, both hand-set.

Section label

The small uppercase eyebrow above a section heading. The padded-left variant indents 12px to align with content inside a card.

Default
Padded left
To fix in Figma
  • It carries Curitt/Label's values (General Sans Semibold 11/16, +10%) but isn't bound to the style, so a change to the style won't reach it.

Star rating, avatar stack & social proof

Patient ratings and the social proof strip that pairs them with faces.

★★★★★Rating 1
★★★★★Rating 2
★★★★★Rating 3
★★★★★Rating 4
★★★★★Rating 5
3 avatars
4 avatars
5 avatars
Social proof strip
To fix in Figma
  • Stars are the ★ text character rather than Lucide star with a fill, which Section 09 specifies for ratings. They also sit 2px apart.
  • The "4.9" score is raw General Sans Medium 17/19 and "from our patients" is raw Public Sans Medium 13/19, neither bound to a Curitt text style.
  • Avatars are photo fills in Figma; the brand book shows grey placeholders.

Trust signals

Registration and compliance marks: a single trust point for inline use, the 40px tile set, and the stacked trust icon with label.

Trust pointTrust strip point
BIG-registerBIG
ISO
NEN
GDPR
Klachtenportaal ZorgComplaints
BIG-geregistreerdDutch Medical RegisterTrust icon
To fix in Figma
  • The BIG-register and Klachtenportaal tiles are raster images, exported here at 3×. The BIG tile's blue is a raw hex (#154273, the register's own colour), the only colour in the library not bound to a variable.

Spacer & divider

Fixed vertical gaps and horizontal rules. Prefer layout gap tokens over spacer elements where the layout allows it.

Hairline · 1px
XXS · 2px
XS · 4px
S · 8px
M · 16px
L · 24px
XL · 32px
XXL · 48px

Hairline · Subtle

Hairline · Default

Hairline · Strong

Medium · Subtle

Medium · Default

Medium · Strong
To fix in Figma
  • Spacer names don't match the spacing tokens: Figma's Spacer S is 8px and XS is 4px, but --space-s is 12px and --space-xs is 8px. Hairline (1px) and XXS (2px) also sit below the 4px grid.
  • Divider has a Hairline and a Light weight that are both 1px, so one of them is redundant. The brand book shows Hairline and Medium only.

Text input, textarea & select

Single-line, multi-line and dropdown fields share one shell: a 1px neutral-grey-400 border, text-secondary on hover or once filled, a 2px accent-green ring on focus and accent-signature-text on error. Every field here is a real input, so type into them.

Text · Default
Text · Hover
Text · Focus
Text · Filled
Text · Error
Text · Disabled
Textarea · Default
Textarea · Hover
Textarea · Focus
Textarea · Filled
Textarea · Error
Textarea · Disabled
Select · Default
Select · Hover
Select · Focus
Select · Filled
Select · Error
Select · Disabled
PartValue
Height / padding36px · 10px / 14px (textarea 100px · 12px / 14px)
Radius7px (search is a pill)
TextPublic Sans 400, 14px; placeholder text-secondary
Border1px neutral-grey-400 → text-secondary (hover, filled) → 2px accent-green (focus) → accent-signature-text (error)
Disabledsurface-card fill, neutral-grey-100 border, neutral-grey-400 text

Search & password

Search is a pill with a leading 14px search icon. Password adds a trailing 14px eye icon to reveal the value.

Search · Default
Search · Hover
Search · Focus
Search · Filled
Search · Disabled
Password · Default
Password · Hover
Password · Focus
Password · Filled
Password · Error
Password · Disabled

Checkbox & radio

Real checkboxes and radios, restyled. 20px, 1.5px neutral-grey-400 outline, filling accent-green when on. Click them.

Unchecked
Checked
Unchecked · disabled
Checked · disabled
Off
Off · hover
Off · disabled
On
On · disabled
To fix in Figma
  • Disabled works differently in the two: Checkbox dims to 50% opacity, Radio swaps to neutral-grey-100 with no opacity change.
  • Both use a 1.5px outline, off the 1/2/3px stroke scale; Checkbox has a hand-set 6px radius.

Language option

A row in the language picker. The whole row toggles its checkbox; the selected language turns accent-green.

Default
Hover
Selected
Selected · hover
To fix in Figma
  • The language name is raw General Sans Medium 16/26 (Curitt/Body-medium's values, but not bound to it). The row has a hand-set 10px radius and 10px / 12px padding.

File upload

A dashed drop zone. Once a file is attached it turns solid accent-green on green-100.

Drag a file here, or click to browse
Default
Drag a file here, or click to browse
Hover
blood-results.pdf · uploaded
Filled
File too large · max 10MB
Error
Drag a file here, or click to browse
Disabled
To fix in Figma
  • Figma's dashes are 4px on, 4px off at 1.5px; CSS dashed borders can't set dash length, so the browser's own dash is used.
  • Padding is 24px / 20px with a 6px gap and 10px radius; 20px and 6px are off the 4px grid.

Date input & form field

Date of birth is split into day, month and year boxes. A form field stacks label, hint, an error line when needed, and the input.

Date · Default
Date · Filled
Enter a valid date of birth
Date · Error
Date · Disabled
Email addressWe'll send your booking confirmation here.
Form field · Default
Email addressWe'll send your booking confirmation here.Enter a valid email address
Form field · Error
Email addressWe'll send your booking confirmation here.
Form field · Password
To fix in Figma
  • Form text is unstyled throughout: input text is Public Sans 14px, labels Public Sans Medium 13, hints and errors 12px, and date-part labels Medium 11. 12px and 14px aren't on the type scale.
  • Errors are inconsistent: the form field shows a circle-alert icon with Medium 12 text, the date input shows Regular 12 text with no icon.
  • In the form field the error sits above the input, between hint and field, rather than below it.
  • Inputs use a hand-set 7px radius and 10px / 14px padding; the 6px stacks in form fields are off the 4px grid.

Elevation

Three shadows, each bound end to end to Figma variables (offset, blur, spread and colour). Available as --shadow-sm, --shadow-card and --shadow-lg.

Shadow-sm
Shadow-card
Shadow-lg
TokenOffset YBlurColour
--shadow-sm2px8pxblack, 8%
--shadow-card8px32pxblack, 12%
--shadow-lg16px48pxblack, 18%

Booking search bar

The primary booking entry point: service, city and date, then search. It comes in four layouts (desktop, tablet, mobile and a vertical desktop card), a two-step version without the date, and a version that swaps search for Book now and Call us. Opening a segment highlights it and drops the matching picker below.

ServiceSelect your service
CityChoose your city
DateChoose a date
Desktop · full
ServiceCheck-ups
CityAmsterdam Oud-Zuid
DateChoose a date
Desktop · Service open (active segment)
ServiceSelect your service
CityChoose your city
Desktop · Service + City · call on
ServiceSelect your service
CityChoose your city
DateChoose a date
Mobile

Choose your blood test

Select from set blood panels, or make your own bespoke choices.

ServiceSelect your service
CityChoose your city
DateChoose a date
Desktop vertical
To fix in Figma
  • The active segment's label uses accent-signature (clay-600) as text. Section 05 marks that token fill-only (3.4:1); text should use accent-signature-text.
  • Inside the bar, Button instances are overridden to a 12px radius instead of the component's pill shape, and the full-width search button is a one-off rather than a Button instance.
  • The 30 variants are Breakpoint × Drawer × Steps × Call combinations; the brand book shows the distinct layouts rather than all 30.

Booking pickers

The drawers that open under the search bar. The service picker uses Curitt's service photography; the date picker composes the calendar day and time slot atoms.

Check-upsACTIVEBlood, heart, lungs + dedicated time with a doctor

Blood & Lab Tests55+ parameter blood panel

UltrasoundAbdominal, pelvic, or specific lumps and bumps

Weight Loss (GLP-1)Pre-prescription blood tests, prescription, monitoring

Service picker
City picker
September 2026
MTWTFSS
Available times · Amsterdam Oud-Zuid
Date & time picker
To fix in Figma
  • Picker text is unstyled: service titles are General Sans Semibold 15, descriptions Public Sans 12/16, city names General Sans 14, the month heading General Sans Semibold 16, and the ACTIVE pill is Public Sans SemiBold 9px, smaller than anything on the type scale.
  • The city search box isn't the Search input component: it's 13px text, an 8px radius and a 1.5px neutral-grey-200 border, against the component's pill, 14px text and 1px neutral-grey-400.
  • The Service and City pickers use a 16px radius with a shadow; the Date & time picker uses 12px with a sand border and no shadow.

Cards

Content cards for testimonials, stats, pricing, doctors, values and listings. Cards sit on surface-card with a 16px radius unless noted.

Reviewer nameRole or context

"Review text goes here with the patient's testimonial about their experience."

★★★★★03/2025
Testimonial
2,400+Patients served

48hrsResults turnaround

4.9★Average rating
Stats
EssentialBrief tier description text.
€479/yearor €46/month (12 months)
Pricing · standard and featured
Doctor nameSpecialisationTag 1Tag 2Tag 3
Doctor
Value titleTwo or three lines describing the value in plain language.
Value
To fix in Figma
  • Pricing cards have square corners, unlike every other card (16px).
  • Listing row's frame has collapsed to 100px wide in Figma, so its text wraps into a ~400px-tall column. The brand book shows it full width.
  • The doctor name is raw General Sans Semibold 11/16, Curitt/Label's values without the style. The doctor photo is a grey placeholder in Figma.
  • Testimonial cards use 28px padding and pricing cards 36px, both off the 4px grid. The "4.9★" stat and the testimonial stars use the ★ character.

Location card, location list item & map pin

How clinics are presented: a large card for location pages, a compact list item beside the map, and the map pins themselves. Hover the default location card.

Location nameStreet Address, Postcode, City
Location card · default (hover it)
Location nameStreet Address, Postcode, City
Selected
Location nameStreet Address, Postcode, City
Hover
Location nameStreet Address, Postcode, City
New location
UtrechtUtrecht, SmakkelaarshoekSmakkelaarshoek 5, 3511 EC Utrecht
List item · open
Rotterdam/The HagueRotterdam/The HagueOpening soon.
List item · opening soon
AmsterdamDefault
AmsterdamSelected
Rotterdam · Opening soonOpening soon
Location card stateTreatment
Hoversand-400 fill, shadow 0 4px 16px black 8%
Activeshadow 0 2px 4px black 4%
Selected2px accent-green ring
New locationphoto at 20% opacity, single "I'm interested" button
To fix in Figma
  • The hover and active shadows, and the map pin shadow (black 12% on an 8px blur), are hand-set rather than the bound Curitt/Shadow styles.
  • In the list item, the Directions button is too narrow for its label, which is clipped in the 368px card. The brand book lets the button and card grow to fit.
  • The open and opening-soon list items use different border colours: neutral-black-100 and neutral-grey-100.
  • Location cards carry a hidden "Transport details" block; it's left out here.

Service item

A service row for listing pages: image left on desktop, stacked on tablet and mobile.

Service nameBrief service description text.
Desktop
Service nameBrief service description text.
Tablet / mobile
To fix in Figma
  • The image is a raw #CCCCCC placeholder, the title is raw General Sans Medium 23/32 (H4's values, unbound), and the fill is bound to surface/card from the Colour collection rather than the semantic surface-card. Figma has both, and components mix them.

Navigation

The site navbar, desktop and mobile, with its links, language picker and menu toggle.

Navbar · desktop
Navbar · mobile, closed
Navbar · mobile, open
Nav linkDefault
Nav linkActive
Nav linkDisabled
Nav linkDefault
Nav linkActive
Nav linkDisabled
Language picker · open
Closed
Menu · closed
Menu · open
Scroll behaviour (from Figma's interaction spec): by default the navbar sits in the normal page flow and scrolls away going down. Scrolling up, by any amount and from anywhere on the page, fixes it to the top of the viewport and slides it down into view; scrolling down again slides it back out of view.
To fix in Figma
  • The CURITT wordmark is live text in HK Grotesk Medium 21px with 18% tracking, a typeface outside the system that isn't loaded anywhere. The brand book renders it in General Sans. It should become an SVG logo (Section 04 is still a stub), and Section 01's hero wordmark should then use the same asset.
  • Desktop nav links are raw General Sans Semibold 11/16 with 1.5% tracking, where every other uppercase label uses 10%.
  • Disabled nav links are accent-sand at 50% opacity, which is nearly invisible on white.
  • Menu toggle icons are a raw grey (#808080), not bound to a variable.
  • The language dropdown uses two hand-set shadows rather than a Curitt/Shadow style, and the desktop links sit 40px apart (no spacing token).

Section header & hero content

The two heading blocks that open a page section. Both align left, centre or right; the hero also has a spaced layout with the call to action pushed to the right. Sizes step down at tablet and mobile.

Section titleSection heading textSection description text that provides additional context about this section.
Section header · centre · desktop
Section titleSection heading textSection description text that provides additional context about this section.
Left · desktop
Section titleSection heading textSection description text that provides additional context about this section.
Right · desktop
Section titleSection heading textSection description text that provides additional context about this section.
Centre · tablet
Section titleSection heading textSection description text that provides additional context about this section.
Centre · mobile
Choose your care.

Prices from €99. No referral needed, booking takes two minutes.

Hero · left · desktop
Choose your care.

Prices from €99. No referral needed, booking takes two minutes.

Centre · desktop
Choose your care.

Prices from €99. No referral needed, booking takes two minutes.

Right · desktop
Choose your care.

Prices from €99. No referral needed, booking takes two minutes.

Spaced · desktop
Choose your care.

Prices from €99. No referral needed, booking takes two minutes.

Left · mobile
To fix in Figma
  • The kicker ("Section title") is accent-signature text, the fill-only clay. It should be accent-signature-text.
  • The tablet and mobile section headers use raw text (General Sans Medium 28/35 and 23/29, Public Sans 15/24 and 14/22) instead of Curitt styles, and the mobile header has 36px side padding.
  • The hero stacks with a 28px gap on desktop and 17px on mobile, both off the 4px grid.

Feedback & utility

Small pieces used across the site and app: breadcrumb, tooltip, inline notifications, the cookie banner and the "AI summary" prompt.

Breadcrumb
Results reviewed by your doctorTooltip
Your booking is confirmedSuccess
Something went wrong · try againError
Your appointment starts in 24 hoursInfo
Cookie consent banner
To fix in Figma
  • The cookie banner's "Reject non-essential" is a Ghost button overridden to white text; the Button set has no on-dark ghost.
  • The tooltip, toasts and cookie banner use unstyled text (Public Sans 12 and 13, General Sans Semibold 14).
  • The AI prompt uses ✳ and ◆ characters as stand-ins for the Claude and ChatGPT marks; its 9px glyphs are bound to text-on-dark, a Figma variable the brand book didn't have (now --text-on-dark).

Discovery & content

Pieces from the services and results pages: FAQ, legal clause, panel tabs, filter chips, the biomarker search and row, the contact prompt, next-available slot chips and the service nav.

Question goes here?

Answer copy goes here. Keep it to two or three sentences so the list stays scannable.

Question goes here?

Answer copy goes here. Keep it to two or three sentences so the list stays scannable.

FAQ item · collapsed and expanded (click to toggle)
Legal clause
Panel tabs
Filter chips · active and default
Search bar
Biomarker name
Biomarker row
Not sure which test you need?
Contact prompt · light
Not sure which test you need?
Contact prompt · dark
Today14:30AmsterdamToday16:00UtrechtTomorrow09:15Amsterdam
Slot chips · row
Today14:30AmsterdamToday16:00UtrechtTomorrow09:15Amsterdam
Slot chips · ticker
Today14:30AmsterdamSlot chip · dark
Default
Active
Hover
Focus
To fix in Figma
  • Slot chips use signal-live (#34C759, the iOS system green) for the status dot, a colour outside the brand palette. The day label is clay-600 as text, the fill-only clay.
  • The dark slot chip and dark contact prompt get their colours by switching Figma's variable mode to Dark, where surface-base becomes near-black. The brand book has no equivalent "dark island" mode, so these specimens set the dark values directly.
  • Panel tabs (Public Sans Medium 15), filter chips, the search bar and biomarker row (Public Sans 13 and 16) and service nav labels (Public Sans 11) use unstyled text. Panel tabs, the search bar and the biomarker row also use hand-set paddings (22px, 28px, 9px) and shadows.
  • The FAQ toggle and biomarker expand buttons are drawn as plain frames and a "+" character rather than icon buttons.

Service page

Building blocks of a service page: spec items, the who-it's-for list, what's included, and the example results report.

Duration60 minutes
Spec item
✓You want a clear picture of your current health
–You have acute symptoms needing urgent care
Suitability · good fit and not a fit
✓Full blood countRed and white cells, haemoglobin and platelets, the baseline for energy, immunity and clotting.
Inclusion · default
✓Vitamin D
Inclusion · compact
Example reportReviewed by a BIG-registered doctor
Haemoglobin8.8 mmol/LNormal
Vitamin D42 nmol/LLow
Ferritin78 µg/LNormal
TSH2.1 mU/LNormal
What this meansYour vitamin D is below the healthy range, common in the Netherlands over winter. We'll talk through supplementation in your consultation.
Results preview
To fix in Figma
  • The results preview contradicts Section 10. It labels results "Normal" on a green pill and "Low" on a clay pill, the colour-led status treatment Section 10 steers away from in favour of language like "within range" and "worth a conversation". This needs a decision before results UI is built.
  • Ticks and dashes are text characters (✓ –) in circles rather than Lucide icons. Card titles and the spec value use raw General Sans Medium 18, 19 and 20.
  • Inclusion cards use a 14px radius and 22px padding; the results preview 22/24/18px padding.

City request modal

Captures interest in a city without a clinic yet: a short form, then a confirmation. The form is live.

Form
Success
To fix in Figma
  • The modal's inputs are a third input style: 54px tall, 12px radius, 16px text and a neutral-grey-200 border, unlike both the Text input component and the city search in the booking picker.
  • Its shadow (0 24px 48px, 16%) is hand-set, close to but not the same as Curitt/Shadow-lg. The consent checkbox is a plain frame, not the Checkbox component.

Service nav (mini)

A slim, sticky service switcher for service pages, with a blurred background in Figma.

Logo strip

A "trusted by" strip of company logos. Shown here as a layout only.

AppleASMLNVIDIASiemensSpotifyAirbnbIBM
Logo strip
To fix in Figma
  • The Figma strip uses Apple, ASML, NVIDIA, Siemens, Spotify, Airbnb and IBM logos. Third-party logos must come from each company's official assets and be used with their permission, so the brand book shows placeholders only.
  • A "Trusted by teams at…" claim needs to be true and substantiated before it ships. Per principle 6 (Real, not staged), drop the strip if it isn't.

Library-wide notes

Patterns that repeat across the Figma library, worth fixing once at the source rather than component by component.

To fix in Figma
  • Type drift: Figma has 31 text styles against the brand book's 12-step scale, and many components use raw, unstyled text (12, 14, 15, 17, 18, 19, 20px…). The extras are mirrored as component type tokens; decide whether to fold them into the scale or retire them.
  • Clay as text: accent-signature / clay-600 is used for text in the booking bar, section header kicker and slot chips, but it's fill-only (3.4:1). Text should use accent-signature-text.
  • Duplicate variables: the Colour and Semantic collections both define surfaces (surface/base and surface-base, surface/card and surface-card), and components use both. Bind components to the semantic set only.
  • No radius or shadow discipline: there are no radius variables (radii of 6, 7, 8, 10, 12, 14, 16, 18, 20, 27px and pills all appear), and several shadows are hand-set instead of using the three Curitt/Shadow styles.
  • Three input styles: the Text input component, the booking city search and the modal inputs all differ in height, radius, text size and border.
  • Off-palette colours: signal-live (#34C759) and the menu icon grey (#808080) aren't brand colours.
  • Wordmark: the navbar CURITT is live text in HK Grotesk, a typeface outside the system. It should be an SVG logo from Section 04.

Optional: Section Hero

A full-bleed image banner (.section-hero) available at the top of any section — dark gradient overlay, Curitt logomark and wordmark reversed in white, centred. Currently live on Section 01 (Introduction) as a placeholder gradient, pending real photography from the Section 08 shoot.

Not yet resolved: there's no "Open C" logomark SVG anywhere in this codebase to drop into .hero-mark — Section 01's hero is running wordmark-only until one is supplied. Flagging rather than guessing at the shape.

Use sparingly — Introduction and maybe one or two flagship sections at most, never on every section. The point is a considered moment, not a decorative pattern repeated down the sidebar.

<div class="section-hero" style="background-image: url('PHOTO_URL_HERE');">
  <div class="section-hero-overlay">
    <svg class="hero-mark"><!-- Open C logomark, white --></svg>
    <div class="hero-wordmark">CURITT</div>
  </div>
</div>
/* Full-bleed: breaks out of .content's horizontal padding (48px,
   exactly --space-2xl) rather than sitting inside it like body text.
   Match the negative margin to whatever .content's padding is. */
.section-hero {
  width: calc(100% + var(--space-2xl) * 2);
  margin-left: calc(var(--space-2xl) * -1);
  margin-right: calc(var(--space-2xl) * -1);
  height: 60vh;
  min-height: 400px;
  background-size: cover;
  background-position: center;
  position: relative;
  margin-bottom: var(--space-4xl);
}
.section-hero-overlay {
  position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(22,21,18,0.15) 0%, rgba(22,21,18,0.55) 100%);
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: var(--space-m);
}
.hero-wordmark {
  font-family: var(--headline); font-weight: 500;
  font-size: var(--text-h1); letter-spacing: 0.16em; color: #FFFFFF;
}
12 / Physical & Print

Clinic & Spatial Design — The Lookbook

Not started

What's fixed versus flexible per location, and the spatial and material brief for new clinics as Curitt expands.

🏛

Fixed: material palette, colour logic, typography in-clinic. Flexible: layout, given each building's constraints. To be developed as a standalone visual document, likely in Figma, and linked from here.

13 / Physical & Print

Print & Collateral

Not started

Business cards, letterheads, patient reports, giveaways, signage.

Needs clarifying: a note from the original brief mentioned "Kombucha — doing what we did yesterday in life but better," which doesn't yet have clear context. Flagging here rather than guessing at what it refers to — worth checking with Ted before this section is developed.
🖨

To be developed once the visual identity (Sections 04–07) is locked.

14 / Activation

Advertising & Campaign Guidelines

Not started

Digital ads, billboards, social templates, KOAG/KAG compliance notes.

KOAG/KAG: the Dutch self-regulatory bodies governing health and medical advertising. Any claim about detecting or preventing disease, and anything about the GLP-1 programme specifically, needs to be substantiated and reviewed before publishing. Directly protects the "Real, not staged" principle in Section 02.
15 / Activation

Governance

Not started

Ownership, how the system evolves, who approves exceptions.

🗂

Proposed owner: Johannes (Creative Director). Proposed process: exceptions or new additions get added here directly, with a short changelog rather than a separate approval thread.