Design system · version 9

How Agency Operator is designed

This is the design system behind agencyoperator.ai, open for you to read. We use it every day to build the product members sign in to. Every colour, size and rule on this page is the one the product uses. Take what's useful.

Last synced from the source: 25 Sep 2026.

Brand book

The design system behind agencyoperator.ai: the product you sign in to, and the Claude plugin that came before it, for designers who work for themselves. Tagline: Keep your campfire warm.

Agency Operator looks like Vercel's dashboard, on purpose: white cards on a light grey ground, flat, hairline borders, small type, one typeface, black buttons, no shadows. Monochrome: nothing is coloured unless it is a state or the Claude badge. It used to wear the Designer Mindset brand's orangered and big soft blocks; as of 23 September 2026 it has its own identity, and designermindset.net keeps the orange. If a page here looks loud, big or soft, it is wrong.

It covers two surfaces: the marketing pages and the members' product behind sign-in. They share the brand and differ in density, radius, navigation and states. surfaces.md says which is which, and which components belong to which. Read it before adding anything.

Content fundamentals

The words do more selling than the visuals. These rules were set through a lot of iteration and are not optional.

  • Plain language, about grade 3. Short sentences, short words. Check with Flesch-Kincaid before shipping, not by eye. The live site scores 2.7 to 2.9.
  • No em dashes. Use a full stop, a comma or a new line.
  • Money as $100K+, never $100,000. The one exception is a panel where the digits are the point.
  • "You" means designers who work for themselves: freelancers, solo designers, small studios. Say it, do not imply it.
  • It is the business side of a design business. Getting clients is the first piece, not the whole thing.
  • Contact, never chase. People are kept warm, not hunted.
  • Show a portion, not the whole thing. Crop tables with a fade, blur the rest. The full walkthrough lives in the community.
  • Never publish how it works inside. Describe what it does, never paste its instructions.
  • Do not overclaim. The morning note names three people at most, so nothing may promise more. Earnings examples are labelled "examples, not promises".

Good: "Designers do not lose clients. They forget them."

Bad: "Leverage AI-powered pipeline automation to maximise revenue."

Visual foundations

Colour. There is none, on purpose. ink on page for text, muted for everything secondary. accent exists as a name and it is ink: the primary button, the active tab, bullets, step numbers. dark is the one dark surface a page may have, the closing callout. The only things that carry a hue are states, danger, warning and green, and the Claude badge. If you reach for a colour to make something matter, use weight or a border instead.

Separation. The hairline, border (#eaeaea), does the work that fills and shadows used to. Every card is page white with a 1px border. soft is for hover and quiet backgrounds only, never a card fill.

Ground. The product behind sign-in sits on canvas (#fafafa), a light grey, and every card, table and the header are white on it. That is Vercel's dashboard. Only headings and their one-line subs sit straight on the canvas; anything in a box is a white card, never a grey one, because grey on grey vanishes. Marketing pages stay on page white.

Claude colours are borrowed, not ours. claude, claude-tint and the claude-ink family only appear in the "Runs inside Claude" badge and strip. They signal the platform. They are never used as Agency Operator's own accent.

Dark. The product has a dark theme; members pick System, Light or Dark in the header or on Settings, and System is the default. It is the same system with the lights off, not a second brand: canvas goes to a soft black (#0a0a0a, not pure black), cards go one step up to page #111111, the hairline is #333333, and ink becomes a light grey. accent is still ink, so the primary button turns light, and its text is on-accent, never a hard-coded white. The states lighten so they still pass on dark. Marketing pages have no dark theme and stay white.

Type. One family, Geist, for everything; Geist Mono for code. The scale is anchored to 14px body, as Vercel's is, and it is small: 24 page title, 18 section, 14 card title, 28 for a metric number. Weights 400, 500 and 600, never 700. Labels are sentence case and untracked; nothing is uppercase. Marketing's hero may go to 32px and no further.

Shape. Rounder than Vercel, on purpose. radius-md (10px) for buttons, inputs, nav items and the board's cells; radius-card (14px) for cards, tables and panels. Only status pills, the Claude badge and progress bars are fully round. The nav is flat and square. Always the token, never a pixel value: the whole scale moved once already and nothing should be left behind next time.

Depth. None. There are no shadows anywhere; the shadow tokens resolve to none. Focus is drawn with outline, not box-shadow.

Space. Tight. Cards pad 16 to 20px, grids gap 12px, sections open with 32px above.

Layout. A flat white top nav with a hairline bottom edge, over the canvas, then the main column. In the product, one gutter sets the space from the browser edge to both the nav and the content, so the wordmark lines up with the cards: space-12 (48px) on desktop, space-8 (32px) under 1024px, space-4 (16px) under 640px. When the tabs don't fit, the nav scrolls sideways on its own; it never pushes Sign out off the screen or scrolls the page.

Iconography and marks

There is no icon set. Meaning is carried by small shapes in ink: 4px dots as list bullets, a 2px underline on the active nav item, numbered 24px discs on a hairline rail for steps.

There is no Agency Operator logo. The site uses a type-only wordmark, "AgencyOperator" in ink with ".ai" in muted, set in the wordmark style. The Claude and Notion marks on the site belong to those companies and are not part of this system.

Accessibility notes

The product tokens added later were picked to pass rather than to match: danger is deeper than a stock red and warning deeper than a stock amber so both clear 4.5:1 on page, on soft and on their own tint. field-border is the lightest grey that clears 3:1 on both grounds, because border and rule sit near 1.2:1 and vanish as a control edge.

Going monochrome removed every pair that used to fall under AA. accent is ink at 19.8:1, so white on the primary button and accent as text both pass by a mile, and green was deepened so the Shipped pill clears 4.5:1 on its own tint. There are no flagged exceptions left. Keep it that way: a new colour has to pass on every ground it is used on, or it does not go in.

Colour

33 tokens, almost all of them grey. Each has a light value and a dark one, says where it goes, and the text colours say how well they read.

accent #000000 #ededed

The one signal colour, and it is ink. Primary button, active tab underline, list bullets, step numbers. Nothing on a page is coloured unless it is a state or the Claude badge. Dark: light grey #ededed, still ink, so the primary button turns light with on-accent text.

accent-hover #333333 #cccccc

Hover of the primary button.

accent-soft #f5f5f5 #222222

The signal as a surface: the row being edited, your own row on the board, the 'this week' badge. Pair it with a label; it is one step darker than soft.

accent-strong #000000 #ededed

Kept for older consumers. It is ink.

dark #000000 #222222

The one dark surface a page may have: the closing callout. Contrast, not colour. Dark theme: a raised #222222, since a black callout would vanish on a dark ground. on-dark text still reads 15.9:1 on it.

ink #000000 #ededed

All primary text. 21:1 on page. Dark: #ededed, 16.1:1 on page, 16.9:1 on canvas.

muted #666666 #a1a1a1

Secondary text: descriptions, labels, table cells. 5.7:1 on page, 5.5:1 on soft. Dark: #a1a1a1, 7.3:1 on page, 6.7:1 on soft.

muted-soft #767676 #878787

The faded coming-soon nav items. The lightest grey that still clears 4.5:1 on page: 4.5:1 light; dark #878787, 5.3:1 on page, 4.8:1 on soft.

page #ffffff #111111

Every card, the header, and the marketing pages' background. Cards are white with a hairline border, not a fill. Dark: #111111, one step up from the canvas, so cards still read as lifted.

canvas #fafafa #0a0a0a

The ground of the product behind sign-in, as on Vercel's dashboard. White cards and the white header sit on it. Nothing sits straight on it except headings and their one-line subs; anything with a box is a white card. muted is 5.5:1 on it. Marketing pages stay on page. Dark: #0a0a0a, a soft black rather than pure black (Oykun, 25 Sep 2026).

soft #fafafa #1a1a1a

Hover and quiet backgrounds inside a card: a hovered row, a table header, a code block. Never a card fill. Same value as canvas, so never use it for something that sits straight on the canvas.

soft-2 #f5f5f5 #222222

Pressed and selected backgrounds.

border #eaeaea #333333

The hairline. Every card, the nav's bottom edge, table rules, dividers. This is what separates things now that fills and shadows do not. Dark: #333333.

rule #eaeaea #333333

Same as border; kept as a name for table rules.

pill-grey #eaeaea #333333

Background of neutral status pills.

on-dark #ffffff #ffffff

Text on dark.

on-dark-muted rgba(255, 255, 255, 0.6) rgba(255, 255, 255, 0.6)

Secondary text on dark.

on-accent #ffffff #0a0a0a

Text on a filled accent or state: the primary button, a step disc, the You pill. White in light, near-black in dark, because accent flips. Use this, not on-dark, on anything filled with accent or ink.

code-bg #f5f5f5 #222222

Inline code chips.

green #166534 #4ade80

Positive state: the Shipped pill, a target hit. 7.1:1 on page, 6.4:1 on green-soft. The old value failed at 12px on its own tint; this one does not. Dark: #4ade80, 10.8:1 on page, 8.8:1 on green-soft.

green-soft #e7f6ec #0f2a19

'Shipped' pill background.

claude #d97757 #d97757

Claude's colour, only inside the 'Runs inside Claude' moments. Never as Agency Operator's own accent.

claude-tint #fdf3ef #2a1a13

Background of the Claude badge and Claude strip.

claude-tint-border #f6ded4 #4a2d21

Border of the Claude badge.

claude-ink #7a4b38 #f0c3ae

Heading text on claude-tint. 6.7:1. Dark: 10.5:1 on the dark claude-tint.

claude-ink-muted #8a5a45 #e0a88f

Badge label on claude-tint. 5.3:1.

claude-strong #b4593a #e8906f

The word 'Claude' in the badge. 4.3:1 on claude-tint, used at 13px semibold: just under AA. Dark: 6.9:1 on the dark claude-tint, so the dark badge passes where the light one is just under.

danger #c81e1e #ff6b6b

Error text, the danger Alert, a destructive action. 5.7:1 on page. Dark: #ff6b6b, 6.8:1 on page, 6.3:1 on danger-soft.

danger-soft #fdecec #2e1212

Background of the danger Alert and invalid field hints.

warning #b45309 #f5a524

Warning text and the warning Alert. 5.0:1 on page, 4.6:1 on soft, 4.6:1 on warning-soft. Dark: #f5a524, 9.3:1 on page, 8.0:1 on warning-soft.

warning-soft #fdf3e3 #2b1e08

Background of the warning Alert.

focus-ring #000000 #ededed

Keyboard focus: a 2px ink outline, never removed. Drawn with outline, not box-shadow, because there are no shadows.

field-border #8c8c8c #6e6e6e

Input borders. The one place this system is deliberately darker than Vercel's #eaeaea: a control the user has to find needs 3:1 against its ground, and #eaeaea is 1.2:1. Dark: #6e6e6e, 3.7:1 on page, 3.9:1 on canvas.

Type

One family, Geist, and a small scale. Each style below is set in itself.

Display

Agency Operator
page-title24px / 1.25 · 600 · -0.02em

One per page, the H1. Marketing's hero goes one rung up to 32px and no further.

250
metric-value28px / 1.15 · 600 · -0.02em

The number in a metric card.

The system to run your design agency with
page-sub16px / 1.5 · 400

The line under the H1, in muted. Not bold.

v2.3
release-version18px / 1.3 · 600 · -0.01em

Version numbers.

What's inside
section-title18px / 1.3 · 600 · -0.01em

Section headings.

It lives inside Claude
card-title14px / 1.4 · 600

Titles of cards and steps.

AgencyOperator.ai
wordmark15px / 1.2 · 600 · -0.01em

The type-only wordmark. '.ai' goes in muted.

Text

Designers do not lose clients. They forget them.
intro15px / 1.6 · 400

Page intro, in muted, with ink for strong words.

Every morning it has already picked the one person to talk to.
body14px / 1.6 · 400

Default body. The scale is anchored here, as Vercel's is.

You just talk to Claude, the way you already do.
body-sm13px / 1.5 · 400

Card body, list items, table cells.

Get it with Mastery
label13px / 1.4 · 500

Buttons and nav items.

Real conversations a year, at one a day
caption12px / 1.45 · 400

Metric labels, footnotes, the version stamp.

Skill
overline12px / 1.3 · 500

Table headers and field labels. Sentence case, muted. Not uppercase, not tracked.

Code

/find-prospects
code13px / 1.5 · 400

Commands inline, on a code-bg chip.

skills/pipeline/
tree12px / 1.8 · 400

File trees.

Space

Tight, on purpose. Eight steps, each with a job.

space-2 8px

Gap inside badges and page headers.

space-3 12px

Gap between metric and panel cards in a grid.

space-4 16px

The product gutter on a phone (under 640px), gap between stacked items.

space-6 24px

Card padding (22 to 28 in the source), gap between sidebar and main.

space-7 28px

Space below a card block before the next one.

space-8 32px

Space below the page intro; the product gutter on a tablet (under 1024px).

space-10 40px

Space above a section title; main column side padding.

space-12 48px

The product gutter on desktop: browser edge to header and to content, the same on both so they line up.

Shape

Rounder than Vercel, flat, no shadows. The hairline does the separating.

radius-block
14px

Marketing section blocks. Same as a card; there is no bigger shape.

radius-sm
6px

Code chips, small tags, the focus ring on a bare text button.

radius-md
10px

Buttons, inputs, nav items, alerts, the board's cells. The working radius.

radius-lg
14px

Screenshot frames.

radius-card
14px

Every card, table and panel. Rounder than Vercel's 8px, on purpose (Oykun, 23 Sep 2026).

radius-shell
14px

The sign-in card. The nav is flat and has no radius.

radius-pill
999px

Status pills, the Claude badge, progress bars. Fully round.

Components

Each one with the rules for using it. The examples are the site's own code.

Actions Both

Button

Vercel-style button: primary is black with white text, quiet is white with a hairline border. radius-md, 14px medium, 36px tall.

  • One primary per view. It is the one thing you want clicked.
  • dark is the same as primary; kept as a name. Inside a dark Callout the primary inverts to white.
  • text is bare muted text, 12px, no border or fill; ink and underlined on hover. For a secondary action next to a quiet button, like Cancel beside Save. Never for a view's main action.
  • icon is a 24px square with one 14px stroke icon (1.75 stroke, round caps), muted, no border or fill; on hover the square fills pill-grey and the icon goes ink. For small actions repeated on every item in a list, like edit and delete on each comment, sitting at the right end of the item's first line. Always give it aria-label and title. Never for a view's main action.
  • Labels are short verbs in plain words. No arrows or icons beside a label; an icon stands alone only in the icon variant.
  • The consumer provides href (renders a link) or onClick.
  • Focus is a 2px outline, never removed.

Callout

Every week you log is a week you can learn from.

Two minutes on a Monday. That is the whole habit.

The one dark surface a page may have. It asks for the one action, near the end.

  • One per page. size="lg" for the closing band.
  • Title says what they get, body says who it is for, button says what to do.
  • The button inverts to white on the dark ground.

Content Both

Metric

3
Real conversations a week
21
Emails and DMs sent
7
Days in a row you logged

A bordered white card with one number and a short caption.

  • Sits in a grid of cards 160px and up, gap space-3.
  • The number is metric-value (28px, 600) in ink. accent is accepted and does nothing; nothing here is coloured.
  • The caption says what the number means in plain words, not a unit.
  • Numbers must be true. Never promise more than the product does.

Panel

It lives inside Claude

  • Your people stay in your own Notion.
  • You talk to Claude, the way you already do.

The card that holds most content: white, a 1px border, radius-card, 20px padding.

  • Title in card-title (14px, 600), body in body muted, key words in <strong> at 500.
  • Lists use 4px ink dot bullets, never icons or emoji.
  • No fill, no shadow. The hairline is the separation.
  • dark is for the one panel on a page that must stand out, if the Callout is not already doing that job.

StepFlow

1

Log your week

Type your numbers into your own row.

2

See where you stand

Your week next to everyone else's.

3

Talk to one person

The one conversation to move today.

Numbered steps as cards on a vertical grey rail.

  • Discs are accent; mark a step alt for a dark disc when it is a different kind of step (something you do, not the plugin).
  • Titles are short actions. Body is one or two plain sentences.
  • On the site each card is fixed height and fades out: show a portion, not everything.

Navigation Both

NavItem

Check-inProgressAbout

A top-bar tab: 14px medium, muted, with a 2px ink underline when active.

  • Sits in a flat nav with a hairline bottom edge. No fills, no dots, no radius.
  • Labels are plain phrases: "How to use it", "What changed", never jargon.
  • The consumer marks the current page with active.

WeekStrip

Only makes sense signed in, so no example here.

Which week am I looking at, and what's around it. The selected week sits large in the middle; its neighbours line up on either side, each step further out smaller and fainter (14px at 75%, 12px at 45%, 11px at 25%), and the far ends dissolve under a mask. Every visible week is a link, so the strip is also how you move.

  • Product only. It heads any page that shows one week at a time.
  • No card. It is the page's heading, so it sits straight on the canvas, the one boxless thing allowed there besides headings. The mask fades to transparent, so it dissolves into whatever ground it's on.
  • The date is 28px, the metric-value size (22px under 760px): the week is what the page is about.
  • Future weeks leave empty slots. Don't pad with weeks that can't be opened, and don't collapse the gap: the selected week always stays centred.
  • Nothing sits beside it in the bar. A button on one side pushes the strip off centre. "Back to this week" goes in the meta line under the date, as a plain underlined link.
  • The meta line is two centred rows under the date. First, seven day ticks, Monday to Sunday: days gone in ink, today in ink and a little taller, days to come in field-border grey (3:1, so each can be counted). A past week is all ink. Second, the *This week* tag, or on a past week the "Back to this week" link. No *Past week* tag, and no counts; the board below says who logged.
  • Each tick names itself on hover ("Thu 24 · Today"), in a small white tooltip with a hairline, below the ticks so it never covers the date. The mask clips anything outside the strip's box, so the strip carries 28px of bottom padding, given back with an equal negative margin, to leave the tooltips room. The row as a whole is labelled for screen readers ("Day 4 of 7, 3 days left"). "Today" is the UTC day, the clock the week turns over on.
  • It steps down with the width: three a side on desktop, two under 1100px, one under 760px, and under 480px only the selected week, with no fade.
  • Weight 600 for the date, 500 for the neighbours. Colour never changes; distance is carried by size and opacity alone.

Status Marketing

Pill

NowNextPlannedShippedInternal

Small status pill for the roadmap and changelog.

  • now = black, next = white with an ink border, planned and internal = grey, shipped = green on its tint.
  • Only one now at a time. It is the release being built.
  • Text defaults to the status name; keep it to one word.

Brand Both

ClaudeBadge

Runs inside Claude

The "Runs inside Claude" platform badge in Claude's own tint.

  • Used once, under the wordmark. It tells people this is a Claude plugin, not another app.
  • The consumer provides the Claude mark as iconSrc; it belongs to Anthropic and is not stored in this system. Without it a Claude-coloured dot stands in.
  • Claude colours stay inside this badge and the Claude strip. Never reuse them elsewhere.

Forms Product

Field

A labelled text input. The product's workhorse: sign-in, the weekly log, the claim page.

  • Label in label, always present and always above. No placeholder-as-label.
  • The border is field-border, not border or rule. Those are hairlines at about 1.2:1 and disappear as a control edge.
  • Focus draws a 2px focus-ring. Never remove it. It is the only thing a keyboard user has.
  • hint sits under the field in caption muted. With invalid, the hint turns danger and the border with it, and it gets aria-describedby and aria-invalid so it is announced, not just coloured.
  • A placeholder is an example of the answer, never a repeat of the label.
  • Numeric fields in a table row are the exception: they lose the label and take bare, because the column header is the label.

Textarea

A labelled multi-line input, for the parts of a weekly log that are sentences rather than numbers.

  • Same label, border, focus and hint rules as Field. It is Field with height.
  • Three rows by default. It grows, it does not scroll, until it has to.
  • The placeholder asks the actual question: "What's the one thing holding the week back?" beats "Enter text".
  • Never put a character counter on something a member writes for themselves.

Data Product

Table

MemberConversationsBookedWon
Sara K.421
Tom R.31—
Ana P.———

Rows of numbers people compare. The weekly board and the funnel history.

  • Headers in overline: uppercase, muted, 12px. A header may carry a target under it, which is the quieter second line.
  • Rows are separated by rule, nothing else. No zebra striping, no cell borders, no outer border. The table sits on a soft card like everything else.
  • An empty cell is an em dash, not a zero. A week nobody filled in has to read as blank. Zero is a claim that they did nothing, and it is usually wrong.
  • highlight marks the viewer's own row: a tint and a heavier first cell. One row at most.
  • The first column is the row's name and stays put when the table scrolls sideways.
  • Numbers are right-aligned so digits line up. Text is left-aligned.
  • On narrow screens it scrolls horizontally. It does not reflow into cards, which would destroy the comparison the table exists for.

Feedback Product

Alert

That email isn't on the board. Use the one you joined Mastery with.
You haven't logged this week yet.
Blank is fine. Zero is a claim.

One line telling someone what just went wrong, or what is about to.

  • danger for something that failed or was refused. warning for something that will bite if ignored. info for the neutral aside. info is white with a hairline, like a card, so it reads on the canvas.
  • It carries role="alert" when it appears after an action, so a screen reader says it without being asked.
  • Say what happened and what to do about it. "That email isn't on the board. Use the one you joined Mastery with" beats "Authentication error".
  • Never a bare server message. Signups not allowed for otp means nothing to a member and reads like their fault.
  • One at a time. Two stacked alerts mean the first one was not clear enough.

Teach Product

HowItWorks

How this is worked out
  1. Conversations started is the number that decides the week.
  2. 2 ÷ 29 = 7% of your reach turned into a conversation.

The section at the bottom of any page that computes something a member sees. It says, in plain words, how the number was worked out.

  • Collapsed by default, a native details, so it costs nothing until opened. Never hidden behind a role or a setting.
  • Summary reads "How this is worked out". Body is numbered rules in body, with the member's own numbers substituted in: "2 ÷ 29 = 7%", not "conversations divided by reach".
  • It is generated from the same constants the logic uses. If a target or a band lives in code, the explanation reads it from there. A hand-written explanation drifts from the rule the day the rule changes.
  • Says what is fixed. If a sentence is one of four canned sentences, the section says so. Nothing a member sees is a black box.
  • One per page, last thing before the footer. It is not a help panel; it is the working.

SidePanel

Only makes sense signed in, so no example here.

The explanation behind something on the page, opened from the thing itself. On the board, a Why? link under every column opens one: why that number is there, its target and source, the other numbers to jump to, and the questions to ask before logging.

  • Product only. It replaced a whole page ("Why these numbers"): the reasoning lives beside the number now, not two tabs away.
  • It explains, it never asks. No forms, no decisions, no primary button inside. If the page needs an answer from the member, that is a page, not a panel.
  • From the right, 440px (the full width on a phone), page white with a hairline on its open edge, no shadow, over a 40% ink scrim so the page stays visible behind it.
  • Three ways out, all equal: the scrim, Escape, and the icon Button in the head. Focus lands on that button when it opens and goes back to the opener when it closes; page scroll is locked while it is open.
  • Head then body. A muted kicker (what kind of thing this is), an 18px title, a hairline, then the content. Sections inside are a 12px muted title over the content, 28px apart.
  • The opener is a real link, and it says what it is. Under each column: a small underlined "Why?" in muted, ink on hover, 11px. Not the title, and never a tooltip: a tooltip on the title covered the very text it explained, and a dotted underline read as decoration. Everything in that header is left-aligned so title, target, blurb and link read as one block.

Two surfaces, one brand

This system covers two things that look related and behave differently: the marketing pages (designermindset.net, the agencyoperator.ai site, campaign and landing pages) and the product, the members' web app behind sign-in.

It was built from the marketing stylesheet first, so for a while it only described half of what it claimed to. This page says which half is which, so the question does not have to be argued again.

What never differs

These are the brand. If a surface changes one of them, the surface is wrong.

  • The neutral ramp: ink, page, soft, muted, dark, on-dark. There is no brand colour. accent is ink.
  • Geist, for everything.
  • Buttons are rounded rectangles at radius-md. Only status pills and the Claude badge are pills.
  • Cards are white with a hairline border. No fills, no shadows.
  • One primary action per view, and one dark surface per page at most. Nothing is coloured unless it is a state or the Claude badge.
  • Claude's colours belong to the "Runs inside Claude" moments and are never ours.
  • The content rules in the README. They apply to every word on both surfaces.

What legitimately differs

Density. Marketing gets one rung more room: a 32px hero, space-10 between sections. The product is dense: body-sm and caption carry most of it, space-3 and space-4 between things. The type scale is small on both.

Ground. The product sits on canvas grey with white cards on it; marketing sits on page white. Cards are white with a hairline on both, so a card looks the same wherever it lands.

Theme. The product has a dark theme as well as the light one; marketing is light only. Every token has a dark value, so a component that uses tokens and never a literal colour works in both without a second look.

Radius. The same everywhere: radius-card (14px) for anything bigger than a button, radius-md (10px) for the button itself. radius-block exists as a name and equals the card.

Navigation. Marketing uses a floating 268px sidebar against a 920px column, which suits a long page you scroll and jump around. The product has three destinations and uses a floating top bar. The *arrangement* is a surface decision. The *treatment*, flat with a hairline bottom edge and an underlined active item, is the brand and is shared.

States. Marketing has almost none: a hover, a visited link. The product needs focus, disabled, invalid, empty and loading on nearly everything. focus-ring, field-border, danger and warning exist for the product and mean nothing on a marketing page.

Which components belong where

GroupComponentsSurface
ActionsButton, CalloutBoth. Callout leans marketing.
ContentMetric, Panel, StepFlowBoth. StepFlow is marketing in practice.
NavigationNavItem, WeekStripNavItem both, arranged differently per surface. WeekStrip is product: it heads any page that shows one week at a time.
StatusPillMarketing. Its statuses are a public roadmap.
BrandClaudeBadgeBoth.
FormsField, TextareaProduct.
DataTableProduct.
FeedbackAlertProduct.
TeachHowItWorks, SidePanelProduct. HowItWorks on every page that computes something a member sees; SidePanel for the reasoning behind a thing on the page, opened from the thing itself.

A component's group is set on the first line of its preview.html, in the @dsCard comment. That is the only place it lives.

When you are about to add something

Ask which surface needs it, then ask whether the other one would want it too. If both, it belongs in a shared group and its guidelines say how density changes between them. If one, put it in that surface's group and say so in its card. Do not build the same thing twice under two names. That is how one system quietly becomes two.

Built and kept by Oykun, with Claude Code.