
Packaging
The text under each photograph never moves.
Every value below comes from src/design/aspects.ts. Change a value there and it changes everywhere it is used — that is the guarantee this page exists to demonstrate.
The kit ships 48 aspect groups. A site can declare which of them it has actually adopted as its own design system — an adopted group is a decision this site made; an inherited group is the kit's own default, still merged into every page's CSS, but not something this site chose. Every value below still renders — this only changes what it claims to be.
coloradoptedfontadoptedtypeinheritedpageadoptedradiusadoptedrevealinheritedmotioninheritedbuttoninheritedcontrolinheritedtextinheritedspaceinheritedscreeninheritedgapinheritedborderinheritedstackinheritedcaseinheritedpairsinheritedfocusinheritedmediainheritedcardinheritedgridinheritedpanelinheritedcarouselinheritedfocusRinginheritedzIndexinheritedconsentinheritednavinheritedcardsRowFeatureinheritedtestimonialQuoteinheritedclientRosterinheritedbodyCopyinheritedbodySlotinheritedlistinheritedstatementinheritedservicesIndexinheritedworkIndexinheritedfilterNavinheritedheroinheritedheroDoorsinheritedheroCopyEntranceinheritedheroSettleinheritedheroPanelsinheritedentranceinheritedlogoinheritedannouncementinheritedfooterinheritedsetsadoptedviewportinheritedcolor.accent#8CBFF2color.accentOnDark#8CBFF2color.accentAlt#8CBFF2color.ink#e4e4ebcolor.paper#07070ecolor.error#b91c1ccolor.inkMuted#8888a0color.rulergba(255, 255, 255, 0.06)color.scrim#000000color.surface#07070ecolor.inkAlt#e4e4ebColor is never used loose — every foreground/background combination is a named pair, measured against the WCAG contrast formula. AA is the level this framework requires; AAA is a stricter, optional bar shown for information only. The ratio a pair must clear comes from its use field — text needs more contrast than a UI border, so the same measured ratio can pass one pair and fail another.
A WCAG contrast issue never stops a local build — it warns, so a genuine violation is visible without blocking someone mid-design. The deploy gate is the check that matters: it still blocks a WCAG failure, and only a human can override it, deliberately and on purpose — see STANDARDS.md#accessibility.
FAILS AA — violation This pair ships with a real contrast violation. It has no recorded exemption — see STANDARDS.md#the-escape-hatch to add one, or fix the pair.
FAILS AA — violation This pair ships with a real contrast violation. It has no recorded exemption — see STANDARDS.md#the-escape-hatch to add one, or fix the pair.
FAILS AAA — informational Passes AA. Nothing to fix — AAA is a stricter, optional bar.
FAILS AA — violation This pair ships with a real contrast violation. It has no recorded exemption — see STANDARDS.md#the-escape-hatch to add one, or fix the pair.
FAILS AAA — informational Passes AA. Nothing to fix — AAA is a stricter, optional bar.
The real palette above has no failing pair to show, and adding one there would ship a genuine violation just to prove a point. These two rows are fabricated fixture data — never part of any site's palette — kept here so the failing states stay visible on every build.
FAILS AA — violation This pair ships with a real contrast violation. Recorded with a signed exemption: Demonstration fixture, not a real pair — shows what a signed AA exemption looks like.
Demonstration fixture — fabricated colors, not part of this site’s palette.
FAILS AAA — informational Passes AA. Nothing to fix — AAA is a stricter, optional bar.
Demonstration fixture — fabricated colors, not part of this site’s palette.
A named set is a value picked by key, not the job-based role color holds — a keyed palette or a line-weight family a page reaches by name (crystal.ruby), rather than a role it fills. The kit ships none: this is a place for a site to put its own. Contrast is measured only for a set that declares a pairWith background and a use — a member with no declared pairing, or one that is not itself a solid color, says so rather than guessing.
goldpaired with color.paper · use: textcrystalpaired with color.paper · use: textVoice is a named, per-site value like a color or a type size, and it sits here for the same reason: a change request has to land in one place. It cascades per field, so a section can be warmer without restating the person or the word choices.
Resolved for about/community
Second person — you, your
Settled once, so they are not re-argued per page.
Kept short on purpose. A long banned list produces stilted avoidance, which reads worse than the phrase did.
The most useful part for whoever writes the next page. A real sentence, its weaker twin, and why one wins.
WriteNo orchestrator required: agents in a quest self-coordinate.
NotAn orchestrator is not a requirement, as agents in a quest are able to coordinate among themselves.
Claim, colon, the concrete thing. The most common move in the copy Chris writes, and it survives being read fast.
WriteThe Quest Master never gets to be the boss; its only job is to author questlines and unblock the quest.
NotThe Quest Master is a powerful orchestration tool that unlocks seamless questline authoring.
Say what it does not do, then name the one thing it does. Denying the software credit is what makes the claim believable.
WriteSummon a single hero as a shard: a solo specialist with its own agent, model, and persona.
NotHero shards are a feature that allows users to create specialists.
A verb the reader can perform, not a sentence about what a feature is. "X is a feature that" is the shape to delete on sight.
WriteYou and the agent see the same list. It checks items off and adds what it finds as it goes.
NotThe workbench provides shared visibility into task state for both the user and the agent.
Two short sentences narrating an action beat one long one classifying a capability.
WriteThis works in the free version too.
NotThis powerful capability is also available to users on our free tier.
Six words, no adjectives, answers the question the reader actually had.
font.body — Inter, falling back to -apple-system, system-ui, sans-serif inherited
Body copy renders in the body font at its real size, constrained to the site's measure.
font.heading — Inter, falling back to -apple-system, system-ui, sans-serif inherited
Kitchen gardens built for the way you cook
font.display — Inter, falling back to -apple-system, system-ui, sans-serif inherited
The quick brown fox jumps over the lazy dog.
font.ui — JetBrains Mono, falling back to ui-monospace, monospace inherited
The quick brown fox jumps over the lazy dog.
font.mono — JetBrains Mono, falling back to ui-monospace, monospace inherited
The quick brown fox jumps over the lazy dog.
font.wordmark — Cormorant Garamond, falling back to Georgia, serif adopted
The quick brown fox jumps over the lazy dog.
font.tagline — IM Fell English, falling back to Georgia, serif adopted
The quick brown fox jumps over the lazy dog.
The most frequently broken thing in a design system — see STANDARDS.md#the-heading-stack. Every gap below is measured off the real rendered DOM, not copied from the aspect value.
Eyebrow + subheading
Services
Built for the way you cook
Body copy begins here, the anchor every gap above is measured against.
eyebrow · upper — heading · sentence — subheading · sentence
Eyebrow only
Services
Body copy begins here, the anchor every gap above is measured against.
eyebrow · upper — heading · sentence — subheading · sentence
Subheading only
Built for the way you cook
Body copy begins here, the anchor every gap above is measured against.
eyebrow · upper — heading · sentence — subheading · sentence
Neither
Body copy begins here, the anchor every gap above is measured against.
eyebrow · upper — heading · sentence — subheading · sentence
Display role · type.lineDisplay
type.lineDisplay · var(--type-line-tight) — type.lineTight · 1.15 — measured · …
How sheet at beside, story-flow and hero-standard at beside share a row between photograph and copy from md up. The larger share follows the photograph to either side. Below md the panel is one column.
This site — 1fr media, 1fr copy · side: 'left'

A short paragraph of copy, so the column the copy gets is visible.
This site — 1fr media, 1fr copy · side: 'right'

A short paragraph of copy, so the column the copy gets is visible.
Demonstration — 3fr media, 2fr copy · side: 'left'

A short paragraph of copy, so the column the copy gets is visible.
Demonstration — 3fr media, 2fr copy · side: 'right'

A short paragraph of copy, so the column the copy gets is visible.
This site: reveal.cards: 'module'. Demonstration of 'media':

The text under each photograph never moves.

Only the photograph fades and rises.

Each one once, as it scrolls in.
What hero.copySurface: 'card' puts under a photo hero's copy, on every photo hero: a solid card in the hero-card and hero-card-heading pairs. This site sets copySurface: 'scrim' andcopyCardOpacity: '1'. Below md the card spans the gutter.
This site — hero-card ink on paper, h1 ink · copyPosition: 'bottom-start'

Kitchen gardens
Every plan starts with the dishes you make most.
Demonstration — an ink card: both pairs { fg: paper, bg: ink }, as invert · copyPosition: 'bottom-start'

Kitchen gardens
Every plan starts with the dishes you make most.
Demonstration — this site's card at 0.85, the photograph showing through (hero.copyCardOpacity) · copyPosition: 'bottom-start'

Kitchen gardens
Every plan starts with the dishes you make most.
Demonstration — this site's card, hanging 3rem below the photograph (hero.copyCardOverlap) · copyPosition: 'bottom-start'

Kitchen gardens
Every plan starts with the dishes you make most.
Demonstration — this site's card, the photograph ending in the gap after the h1 (hero.copyCardOverlap: 'after-heading') · copyPosition: 'bottom-start'

Kitchen gardens
Every plan starts with the dishes you make most.
space.section6remspace.sectionTightcalc(var(--space-section) / 2)space.heroStartclamp(2rem, 10vw, 9rem)space.heroEnd4remspace.kickerStart8remspace.pageEnd5remspace.flushEnd3remstack.eyebrowSizevar(--type-scale-base)stack.eyebrowTrackingnormalstack.eyebrowWeightvar(--type-weight-ui)stack.eyebrowToHeading0.5remstack.headingToSubheading0.75remstack.headingToBody1.5remstack.subheadingToBody1remstack.headingToBlock3remstack.displayTrim0emstack.titleSubheadingSizevar(--type-scale-lg)stack.titleSubheadingLeadingvar(--type-line-snug)radius.sm4pxradius.lg16pxmotion.hover150ms easemotion.panel620ms cubic-bezier(0.19, 0.86, 0.24, 1)motion.swap260msmotion.zoomIn600msmotion.zoomOut400msmotion.zoomScale1.07Named rather than numeric, because the name is what gets said out loud.
| Name | Value |
|---|---|
sm | 40rem |
md | 48rem |
lg | 64rem |
xl | 80rem |
— × —viewport —module —