Design system

Morrison, in parts.

The primitives and components the site is built from. Everything below is the real component or token, so this page is always current. The reasoning lives in apps/marketing/docs/site-v2.md.

Rules

Our own system, built from the same primitives as the app. Not Apple's HIG.

Do

  • Black and white first. Ink is the accent.
  • Use the app's shapes: rounded-lg controls, rounded-xl cards, hairlines over shadows.
  • Cut to the point: one message per section, shown once.
  • Show one real piece of the app where it proves the point.
  • Separate sections with space and a hairline rule, opened by a mono tag.
  • Keep nested corners concentric: outer radius = inner radius + inset.

Don’t

  • Brand blue, gradient text or color as decoration.
  • Capsule text buttons, 28px tiles, alternating gray bands (apple.com).
  • Tinted washes across a whole light section.
  • Looping animation for attention, or layout animation that scales text.
  • Weights above 600, or huge display type.
  • Long dashes in copy.

Color

Semantic tokens in styles/tokens.css. Each has a light and a dark value; flip the appearance in the footer to check both.

Ink and surfaces

Ink--m-labelText, primary button, links
Background--m-bgPage
Gray--m-bg-2Quiet bands, stages
Gray 2--m-bg-3Wells, tile on tile
Elevated--m-bg-elevatedCards on gray

Labels and lines

Label 2--m-label-2Secondary text, 7:1
Label 3--m-label-3Small labels only, 4.7:1
Label 4--m-label-4Decorative, never text
Hairline--m-separatorRules between rows
Hairline strong--m-separator-strongBorders, tag boxes

Meaning (product UI only)

Skill--m-skillPurple: Skills, AI
Source--m-sourceBlue: data sources
Good--m-successPassed, live, strong
Mixed--m-warningPartly, fair
Poor--m-dangerMissing, error

Atmosphere

Soft gradients with grain, from three hues. Washes sit behind product UI and inside ink bands. Never behind body copy, never across a whole light section.

Sea #09606D

Petrol teal. Main haze in ink bands.

Sea deep #075057

Depth under the sea haze.

Mist #D2ECF2

Highlights and pale washes.

Dusk #2E5A80

Steel blue, the cool counterweight.

Ember #C8743A

The one warm accent. Sparingly.

Sand #ECE4D8

Warm pale wash on light stages.

Sea from the left, dusk from the right.

Hero band haze

<HeroBand> · .m-band-glow .m-grain

Dusk left, ember low right.

Closing band glow

.m-band-ember .m-grain

Wash: sea

<Stage wash="m-wash-sea">

Wash: sand

<Stage wash="m-wash-sand">

Wash: dusk

<Stage wash="m-wash-dusk">

Palette and layers: one block in styles/v2.css (“Atmosphere”). Rotate washes across a grid so neighbours differ.

Type

Inter, the app's face. Display at weight 500 with tight tracking; nothing above 600. Utilities in styles/v2.css.

Display

.t-display · 36–60px · 500 · −0.04em

The AI that has read every page.

Hero

.t-hero · 38–64px · 500

Every page, scored.

Title 1

.t-title1 · 30–48px · 500

See Morrison on your own site.

Title 2

.t-title2 · 26–36px · 500

Generic AI guesses.

Title 3

.t-title3 · 20–24px · 500

Built into the work you already do.

Lead

.t-lead · 17–20px · 400

Morrison indexes your website and scores every page.

Body

.t-body · 17px · 400

A chat assistant works from whatever you paste in.

Callout

.t-callout · 15px · 400

Recrawls daily, weekly, every two weeks or monthly.

Footnote

.t-footnote · 13px · 400

14-day free trial · From €79 a month

Section tag

<Eyebrow> · mono 11.5px

What it does

Radius & spacing

The app's radius scale. Spacing on a 4px base; sections are 72–112px apart.

6px

--m-r-xs

Badges, tags, keycaps

8px

--m-r-sm

Small buttons, inputs

10px

--m-r-md

Stages, pill with an inner badge

12px

--m-r-lg

App cards

16px

--m-r-xl

Site cards, panels

20px

--m-r-2xl

Ink bands

New6px badge + 4px inset = 10px pill
10px stage + 6px inset = 16px card

Concentric corners

outer radius = inner radius + inset
Tag → rule20px
Rule → headline32–40px
Header → content48–64px
Section → section72–112px

Section rhythm

--m-section 72–112px · hairline rule after the tag

Buttons & links

The app's Button at marketing sizes: rounded-lg, medium weight. One filled action per view.

filled

The one primary action

gray

Secondary (app “outline”)

bordered

Secondary on ink bands

tinted

Quiet action inside content

plain

Inline text action

On an ink band

<TrialButton /> <DemoButton variant="bordered" />

Text link

<MoreLink href>

Layout

A 12-column grid in a 1408px container. Headlines take columns 1–7, leads start at column 9.

Why Morrison

Generic AI guesses. Morrison has read the site.

A chat assistant works from whatever you paste in.

All features

Split section header

<SectionHeader align="split" size="title2" eyebrow title lead action />

Built by Bonzer

Section tag

<Eyebrow>
Scores every page New

New badge

<NewBadge />

Icon tile

<IconTile><Icon /></IconTile>

Encrypted credentials

Integration tokens are encrypted at rest.

Personal data filtered

PII is stripped from analytics.

Admin controls

Roles, invites and admin-only deletes.

Hairline item (capability lists, trust, steps)

border-t border-[var(--m-separator-strong)] pt-5

Surfaces

Flat white cards with a hairline. Gray stages hold app elements. Ink bands for heroes and the close. Dark toasts float.

Runs on a schedule

Write the instructions once.

Card with stage

rounded-xl card · p-1.5 · <Stage>

Try Morrison free for 14 days

Start free trial

Dark toast

m-dark · bg-elevated · rounded-xl · --m-shadow-toast

Content blocks

Larger shared pieces. Use them as they are; don't restyle per page.

A general AI assistant
Morrison

Your website

A general AI assistant: Sees the pages you paste in

Your website

Morrison: Has read every page

Memory

A general AI assistant: Starts from zero each chat

Memory

Morrison: Remembers your brand and rules

Comparison

<Comparison them us rows />
How long does setup take?
Minutes. Enter your URL and Morrison reads your sitemap.
Which models can we use?
Current models from Anthropic, Google and OpenAI, picked per message.

FAQ

<Faq items /> · <FaqSection items /> for the split layout

Lifting a flat section

Give the visual an ink panel with atmosphere, run it top to bottom and out to the screen edge, scale the visual up, make the section taller, and pin the title to the top and the lead to the bottom. One prop: <FeatureChapter stage="dark" />. See the “Checklist and fixes” section on the content analyzer page. Use it for the one section that should carry a page, not every section.

Also shared: FeatureChapter, CapabilityGrid, FeatureHero, RelatedFeatures, DemoCta. See any feature page for them in place.

Product UI

Pieces of the real app (components/m/app/parts.tsx), rebuilt from apps/web with its labels, radii and colors. Always decorative: wrap scenes in aria-hidden and describe them in text.

Which pages lost the most clicks?
Search Console

Composer

<Composer text chips />
GA4Brand Voice & Readability AuditorPillar guide94%200301404SuccessRunningFailed

Chips, badges, status

<SourceChip> <SkillChip> <TypeBadge> <HttpBadge> <StatusPill> <Switch>
refresh-plan.xlsxSpreadsheet · 38 rowsbrief.mdMarkdown · 2 KB

File tile

<FileTile name meta kind />

Logo mark

<Mark size />

Motion

Emil Kowalski's rules. Short, purposeful, and never in the reader's way. Tokens in styles/tokens.css, presets in lib/motion.ts.

ease-out

var(--m-ease)

Entering, exiting, anything the user triggers.

ease-in-out

var(--m-ease-in-out)

Something on screen moving or morphing.

ease

ease

Hover and color changes.

Durations

150 / 200 / 250 / 300ms

UI stays under 300ms. Exits are faster.

  • Buttons give press feedback: scale(0.97), 150ms.
  • Menus, popovers and toasts enter with 200ms ease-out and exit in 150ms. Paired elements (panel + scrim) share timing.
  • Intro animations play once per session (the hero chat film), then rest on the final state.
  • Product scenes play when in view and pause off screen. Animate transform, opacity and clip only.
  • Reduce Motion: no movement and no fades. Show the final state.
  • Scroll animations: no fade-ups, slide-ins or parallax on marketing pages.
  • Bounce in controls. Springs in scenes stay at bounce ≤ 0.15.
  • ease-in, or linear outside constant loops.
  • Layout animations that scale text or icons (use layout="position").
  • Transitions during a theme switch, or replaying a menu's entrance when switching tabs.
  • transition: all.