Twelve targeted skill additions — Tier 1, 2 & 3

Implements all twelve Tier 1, 2, and 3 items from the test-suite
findings (skipping #12 study+redesign and #14 OG cards, both deferred).
Aim: tighten the gaps the six-test exercise surfaced — copy voice,
theme diversification, sub-domain disambiguation, mobile collapse,
illustration recipes, accessibility gates.

SKILL.md (items 3, 6, 10, 11). Version 0.4.0 → 0.5.0. New step 2.5
documents reading .hallmark/log.json before macrostructure pick;
Step 5 (Build) now writes to that file after each output. Theme-
diversification rule expanded: two consecutive themes must differ on
at least one of paper-band / display-style / accent-hue. Slop test
33 → 35 with two new gates: different-knobs check and
aria-label/aria-hidden presence on visual-only SVG / div / canvas.

macrostructures.md (item 1). 21 macrostructures each gain 2–3
example opening-line copy fragments — drawn from Pentagram, Klim,
Linear, Are.na, Resend, Craig Mod, Rauno Freiberg, Tracejam,
Maple Bakery, Anya, Streampipe, Meridian. Imitate the kind of
specificity (named places, dates, verticals; refusal of metaphor),
not the wording.

structure.md (item 2). Domain → trio table refined: developer-docs
split from SaaS-marketing; personal one-pager split from work-led
portfolio. Plus a clarifying note on splits and when to ask one
disambiguating question before picking.

typography.md (item 4). Pairing table doubled: each of 8 tones now
gets a Free baseline row (Geist, Fraunces, Bricolage Grotesque,
JetBrains Mono, system-ui) and a Paid upgrade row (Söhne, Tiempos,
Druk, Berkeley Mono, ABC Diatype). Discipline note: never name a
paid font without confirming the user is licensed — the demo will
fall back to system-default and look broken.

hero-enrichment.md (item 5). Each E1–E8 archetype gains a 4-6 line
worked example: Tracejam clipped-edge, fashion lookbook full-bleed
loop, Linear-style mockup split, code-formatter floating mockup,
Maple Bakery custom illustration, whiteboard CSS-orbit loop, podcast
gradient + grain, Lisbon café photography. Examples reference real
test pages where they exist.

copy.md (item 8). New "Voice samples per tone" section: 7 tones,
3 voice patterns each, 5–8 example sentences per tone (105+ samples
total) drawn from real non-LLM sources. Plus a banned-opening-lines
table — "Built for the modern team", "Unleash your X", "Where X
meets Y", "Empower your...", and 6 more — each with a one-line
reason it fails.

component-cookbook.md (item 9). Single comprehensive Mobile Collapse
table at the end documents all 36 archetypes' collapse behaviour at
60rem (layout breakpoint) and 40rem (typography breakpoint). Plus
five cross-cutting rules (44px hit targets, container padding,
disable scroll-linked motion, lazy-load below-fold, data-saver
respect).

custom-craft.md (item 7). New Recipe library section adds four
hand-built illustration recipes after the existing bakery loaf:
(1) workflow / process diagram with animated stroke-dashoffset flow,
(2) minimal-line mascot with @keyframes blink loop, (3) three-tier
architectural diagram with @property --flow-offset data flow,
(4) botanical leaf flourish (no animation — the design is the
stillness). Each recipe is full code, "use when / avoid when",
reduced-motion fallback, and named real-world inspiration. Plus
a Cross-recipe techniques callout summarising the four habits of
hand-built CSS/SVG illustration in 2026.

site/index.html + components.css (item 13). New section 07 ·
Examples on the landing page links to the six self-contained
test pages under site/_tests/. Six gallery cards display the
test number, name, macrostructure stamp shape, one-line description,
and a "View ↗" affordance. The cards inherit --radius-card,
--rule-card, --shadow-card from the active theme — switching themes
restyles the gallery alongside everything else. Footer slot's --i
shifted from 6 to 7 to preserve reveal-stagger ordering.

README.md updated to reflect: 35-gate slop test, project memory,
theme-diversification rule on three axes, voice fixtures over
LLM defaults.

Defers: #12 study+redesign combined verb, #14 auto-generated OG
cards. Both ready to plan when the user wants them.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Youssef
2026-04-30 12:33:51 +01:00
co-authored by Claude Opus 4.7
parent 756eafff4a
commit b61f1efc8d
11 changed files with 841 additions and 22 deletions
+5 -2
View File
@@ -28,7 +28,7 @@ The differentiator: Hallmark insists on **structural variety**, not just visual
## What's inside
- **[`SKILL.md`](skill/SKILL.md)** — the routing file. Design flow, slop test (33 questions), output contract.
- **[`SKILL.md`](skill/SKILL.md)** — the routing file. Design flow (six steps, including `Step 2.5 · Check project memory` reading `.hallmark/log.json`), slop test (35 questions), output contract.
- **[`references/`](skill/references/)** — sixteen short, opinionated rule files: typography, colour, layout, motion, microinteractions, interaction-and-states, responsive, copy, anti-patterns, the 21 named macrostructures, the 36 component archetypes with variation knobs, the 6 primitive structure axes, the vision-extraction protocol for `study`, and three new files for hero work — `hero-enrichment.md` (when to add visuals to a hero, plus eight enrichment archetypes), `custom-craft.md` (how to hand-build CSS art, SVG, declarative animation, JS-driven motion, with Lottie demoted to last resort), and `assets.md` (sourcing canon for icons, brand logos, generated illustration via Nanobanana / Recraft, library illustration, app mockups, hero video, photography, abstract backgrounds).
- **[`site/`](site/)** — a self-demonstrating landing page. Hand-written HTML + CSS + ES module, no framework, no build step. **Sixteen themes** — Specimen, Newsprint, Atelier, Garden, Salon, Linen, Almanac, Midnight, Terminal, Brutal, Manifesto, Sport, Studio, Pastel, Riso, **Quiet** — that swap not just colour and typography but the page's hero archetype and footer archetype. Switching themes literally rebuilds the page.
- **[`ROADMAP.md`](ROADMAP.md)** — Tier 1, 2, 3 work plus an explicit "things to *not* do" list.
@@ -60,7 +60,10 @@ Press `T` to cycle themes, `R` for random, `?theme=studio` for a shareable link.
- **Macrostructures over axes.** Pick one of 21 named whole-page shapes wholesale; the macrostructure stamp lives in the CSS comment, so the next Hallmark run picks something different.
- **Within-archetype variation.** Two Bento Grids should not be twins; each archetype has 23 picked-per-output knobs.
- **Microinteractions as discipline.** Silent success over celebratory toasts. Optimistic update + Undo over confirm dialogs. Hover delay 800 ms, focus delay 0 ms.
- **A 33-gate slop test** runs before every output. One yes fails the build.
- **A 35-gate slop test** runs before every output. One yes fails the build. New gates 34 (different-knobs check across runs) and 35 (aria-label / aria-hidden on every visual-only SVG / canvas / div).
- **Project memory.** A per-project `.hallmark/log.json` records each run's macrostructure + theme + enrichment + brief summary. The skill reads the last 35 entries before picking, and writes a new entry after each build, so consecutive Hallmark outputs in the same project don't repeat shapes or themes.
- **Theme-diversification rule.** Two consecutive themes must differ on at least one of three axes: paper band (dark / mid / light), display style (italic-serif / roman-serif / geometric-sans / mono / display-condensed-italic / display-heavy / system-native / risograph), accent hue (warm / cool / neutral / chromatic). Specimen-fall-through is no longer the only diversification check.
- **Voice fixtures over LLM defaults.** Each of the 21 macrostructures ships with 23 example opening lines from real designer-engineer sites (Pentagram, Klim, Linear, Are.na, Resend, Lynn Fisher, Rauno Freiberg, etc.). Each of seven tones in `copy.md` has three voice patterns × five sample sentences. "Built for the modern team" is in the banned-phrases list.
- **Hero enrichment is opt-in, not a default.** A typographic-only hero is always acceptable. When enrichment is right, the skill picks from a six-tier hierarchy: typography only → custom-built CSS art → hand-built SVG → generated illustration (Nanobanana / Recraft) → library + customise → Lottie (last resort).
- **`study` extracts DNA, not pixels.** Vision-extraction with refusal heuristics, type-role vocabulary (no font ID guessing), and a confirmation step before any code.
+160
View File
@@ -1638,6 +1638,166 @@
[data-theme="quiet"] .hero--clipped .hero__mock { display: none; }
[data-theme="quiet"] .hero--clipped { grid-template-columns: 1fr; }
/* ───────────── EXAMPLE GALLERY ─────────────
Cards link to the six self-contained test pages under site/_tests/.
The cards inherit the active theme's --radius-card, --rule-card, and
--shadow-card so switching themes restyles them along with everything else. */
.examples__intro,
.examples__outro {
font-family: var(--font-serif);
font-style: italic;
font-size: var(--text-md);
line-height: var(--lh-snug);
color: var(--color-ink-2);
max-width: 56ch;
margin-block-end: var(--space-2xl);
}
.examples__outro {
margin-block: var(--space-xl) 0;
}
.examples__intro code {
font-family: var(--font-mono);
font-style: normal;
font-size: 0.875em;
background: var(--color-paper-2);
padding: 0.1em 0.4em;
border-radius: var(--radius-input, 0);
border: var(--rule-hair) solid var(--color-rule);
color: var(--color-ink);
}
[data-theme="brutal"] .examples__intro,
[data-theme="manifesto"] .examples__intro,
[data-theme="terminal"] .examples__intro,
[data-theme="sport"] .examples__intro,
[data-theme="almanac"] .examples__intro,
[data-theme="brutal"] .examples__outro,
[data-theme="manifesto"] .examples__outro,
[data-theme="terminal"] .examples__outro,
[data-theme="sport"] .examples__outro,
[data-theme="almanac"] .examples__outro {
font-family: var(--font-body);
font-style: normal;
}
.gallery {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: var(--space-lg);
}
@media (max-width: 60rem) {
.gallery { grid-template-columns: 1fr; }
}
.gallery__item {
display: grid;
grid-template-areas:
"num name"
"num shape"
"num desc"
"num open";
grid-template-columns: 4rem 1fr;
gap: 0 var(--space-md);
padding: var(--space-lg);
text-decoration: none;
color: inherit;
background: var(--color-paper);
border: var(--rule-card, 1px) solid var(--color-rule);
border-radius: var(--radius-card, 0);
box-shadow: var(--shadow-card, none);
transition: transform 100ms var(--ease-out),
border-color var(--dur-micro) var(--ease-out),
box-shadow var(--dur-short) var(--ease-out);
position: relative;
}
@media (hover: hover) and (pointer: fine) {
.gallery__item:hover {
border-color: var(--color-ink);
transform: translateY(-1px);
}
}
.gallery__item:focus-visible {
outline: 2px solid var(--color-focus);
outline-offset: 3px;
}
.gallery__num {
grid-area: num;
font-family: var(--font-label);
font-size: var(--text-sm);
letter-spacing: var(--tracking-label);
color: var(--color-muted);
align-self: start;
font-feature-settings: "tnum";
}
.gallery__name {
grid-area: name;
font-family: var(--font-display);
font-weight: var(--display-weight, 500);
font-style: var(--display-style, normal);
font-size: var(--text-xl);
letter-spacing: var(--tracking-tight);
color: var(--color-ink);
line-height: 1.05;
font-optical-sizing: auto;
}
.gallery__shape {
grid-area: shape;
font-family: var(--font-mono);
font-size: var(--text-xs);
letter-spacing: 0.04em;
color: var(--color-accent);
margin-block-start: 0.4em;
}
.gallery__desc {
grid-area: desc;
font-family: var(--font-body);
font-size: var(--text-sm);
color: var(--color-ink-2);
line-height: var(--lh-snug);
margin-block-start: var(--space-sm);
max-width: 36ch;
}
.gallery__open {
grid-area: open;
font-family: var(--font-label);
font-size: var(--text-xs);
letter-spacing: var(--tracking-label);
color: var(--color-muted);
margin-block-start: var(--space-md);
align-self: end;
justify-self: start;
text-transform: uppercase;
transition: color var(--dur-micro) var(--ease-out),
transform var(--dur-short) var(--ease-out);
}
.gallery__item:hover .gallery__open {
color: var(--color-ink);
transform: translateX(2px);
}
[data-theme="riso"] .gallery__name,
[data-theme="brutal"] .gallery__name,
[data-theme="manifesto"] .gallery__name,
[data-theme="sport"] .gallery__name {
text-transform: uppercase;
}
[data-theme="riso"] .gallery__name {
text-transform: lowercase;
}
/* ───────────── SPORT — section title fix ─────────────
The italic display + tight tracking + uppercase + weight 700
produced cramped, almost-touching letterforms. Loosen the
+70 -2
View File
@@ -403,8 +403,76 @@
</div>
</section>
<!-- 07 · FOOTER SLOT — archetype swaps per theme -->
<footer class="slot slot--foot reveal" data-slot="footer" style="--i:6" role="contentinfo" aria-label="Colophon"></footer>
<!-- 07 · EXAMPLES -->
<section class="section reveal" style="--i:6" id="examples" aria-labelledby="s7">
<header class="section__head">
<p class="section-label">
<span class="num">07</span><span class="divider"></span><span>Examples</span>
</p>
<h2 class="section__title" id="s7">
Six pages, six different shapes.
</h2>
</header>
<p class="examples__intro">Six landing pages produced by exercising the skill across contrasting briefs. Each page is its own self-contained HTML + CSS — no shared theme, no shared layout. Every one carries a <code>/* Hallmark · macrostructure: … */</code> stamp at the top of its CSS.</p>
<div class="gallery" role="list">
<a class="gallery__item" href="_tests/01-tide-podcast/index.html" role="listitem">
<span class="gallery__num">01</span>
<span class="gallery__name">Tide</span>
<span class="gallery__shape">Quote-Led · Atelier · no enrichment</span>
<span class="gallery__desc">Indie podcast. Context skipped — the skill inferred the audio domain.</span>
<span class="gallery__open">View ↗</span>
</a>
<a class="gallery__item" href="_tests/02-streampipe-cli/index.html" role="listitem">
<span class="gallery__num">02</span>
<span class="gallery__name">Streampipe</span>
<span class="gallery__shape">Workbench · Terminal · Tier-A CSS-art mockup</span>
<span class="gallery__desc">Open-source CLI. Theme requested. Hand-built phosphor-green terminal.</span>
<span class="gallery__open">View ↗</span>
</a>
<a class="gallery__item" href="_tests/03-maple-bakery/index.html" role="listitem">
<span class="gallery__num">03</span>
<span class="gallery__name">Maple Street Bread</span>
<span class="gallery__shape">Long Document · Linen · Tier-B hand-built SVG loaf</span>
<span class="gallery__desc">Artisan bakery. Letter-style hero, drop-cap body, hand-drawn loaf.</span>
<span class="gallery__open">View ↗</span>
</a>
<a class="gallery__item" href="_tests/04-meridian-manifesto/index.html" role="listitem">
<span class="gallery__num">04</span>
<span class="gallery__name">Meridian</span>
<span class="gallery__shape">Manifesto · Manifesto · no enrichment</span>
<span class="gallery__desc">Studio manifesto. Pure black, oversized white display, single red bleed band.</span>
<span class="gallery__open">View ↗</span>
</a>
<a class="gallery__item" href="_tests/05-tracejam-saas/index.html" role="listitem">
<span class="gallery__num">05</span>
<span class="gallery__name">Tracejam</span>
<span class="gallery__shape">Bento Grid · Pastel · clipped-edge dashboard</span>
<span class="gallery__desc">SaaS observability. Hand-built CSS-art trace waterfall, asymmetric Bento.</span>
<span class="gallery__open">View ↗</span>
</a>
<a class="gallery__item" href="_tests/06-anya-portfolio/index.html" role="listitem">
<span class="gallery__num">06</span>
<span class="gallery__name">Anya</span>
<span class="gallery__shape">Long Document · Studio · no enrichment</span>
<span class="gallery__desc">Software architect personal site. Italic Fraunces + Geist, tabular work sheet.</span>
<span class="gallery__open">View ↗</span>
</a>
</div>
<p class="examples__outro">Findings + improvement list at <a href="_tests/" class="link">site/_tests/</a>.</p>
</section>
<!-- 08 · FOOTER SLOT — archetype swaps per theme -->
<footer class="slot slot--foot reveal" data-slot="footer" style="--i:7" role="contentinfo" aria-label="Colophon"></footer>
</main>
+40 -3
View File
@@ -1,7 +1,7 @@
---
name: hallmark
description: Use this skill when the user asks to design, build, redesign, audit, refine, or study a UI, web page, landing page, dashboard, component, or interface — or when they ask to make something "feel less AI-generated." Hallmark forces intentional design decisions (typography, color, layout, motion, interaction, structure) and refuses to default to the generic AI-UI template. Trigger phrases include "design a", "build a landing page", "make a dashboard", "redesign this site", "redesign the page", "refine this UI", "audit this design", "this looks AI-generated", "fix the design", "polish this", "give this a different look", and any request that will produce HTML / CSS / JSX / Tailwind output. **Also trigger when the user attaches a screenshot of a design they admire** — that is the `hallmark study` verb (extracts design DNA, never pixel-clones).
version: 0.4.0
version: 0.5.0
---
# Hallmark
@@ -65,12 +65,43 @@ Before loading any visual ruleset, **pick one of the twenty-one named macrostruc
2. If you have produced any other Hallmark output for this user in this session, your pick must be a different macrostructure than the last one.
3. **The Specimen macrostructure (numbered left-margin labels + huge serif + asymmetric spans + typographic CTA) is no longer a default.** Reach for it only when the brief is explicitly editorial, foundry-adjacent, or the user has named it.
**State your pick.** Before writing any code, say "Macrostructure: <name>." in plain text. This is a deliberate accountability step — picking on the page (not in your head) prevents the default-attractor sameness that kept the skill emitting Specimen output.
**Theme-diversification rule (mandatory).** Picking a different macrostructure isn't enough on its own — two consecutive Hallmark outputs can share a theme even if their structures differ, and the result reads as repetition. Two consecutive themes must differ on **at least one** of three axes:
- **Paper band** — dark (L < 30 %) / mid (3085 %) / light (> 85 %), per the theme's `--color-paper` lightness
- **Display style** — italic-serif (Specimen, Studio, Atelier) / roman-serif (Newsprint, Salon, Linen) / geometric-sans (Pastel, Manifesto) / mono (Terminal) / display-condensed-italic (Sport) / display-heavy (Brutal) / system-native (Quiet) / risograph-bold (Riso)
- **Accent hue** — warm (red / orange / amber: 1060°) / cool (blue / indigo / cyan: 200300°) / neutral (no chromatic accent: Quiet) / chromatic-other (green: Studio · sage: Garden · phosphor: Terminal)
If the previous output was Specimen (light · italic-serif · warm), the next can be Studio (light · italic-serif · chromatic-green) — the *accent hue* differs. But the next can't be Salon (light · roman-serif · warm) which only differs on display style and shares both paper band and accent — pick a more distant theme.
The per-theme axis values live as comments at the top of each theme's tokens block in [`site/css/tokens.css`](../site/css/tokens.css). When in doubt, name your candidate theme out loud and identify its three axis values; if two of three match the previous output, redirect.
**State your pick.** Before writing any code, say "Macrostructure: <name>. Theme: <name>. Differs from the last on: <axes>." in plain text. This is a deliberate accountability step — picking on the page (not in your head) prevents the default-attractor sameness that kept the skill emitting Specimen output.
If the brief is genuinely vague (no theme, no tone), do **not** default. Offer the user three macrostructures from *categorically different* groups (e.g. one grid-led like Bento, one document-led like Long Document, one poster-led like Manifesto). Three concrete choices, not seven abstract tones.
The macrostructure picks five of the six structural axes for you; you only need to pick the reveal yourself. The deeper axis catalogue is still in [`references/structure.md`](references/structure.md) when you need to deviate from the macrostructure's defaults.
### 2.5. Check project memory
If the project has a `.hallmark/log.json` file (created by previous Hallmark runs), **read it before** picking the macrostructure or theme. The schema is a JSON array, newest entry first:
```json
[
{ "date": "2026-04-30", "macrostructure": "Bento Grid", "theme": "Pastel", "enrichment": "E1 clipped-edge", "brief": "Tracejam · SaaS observability" },
{ "date": "2026-04-28", "macrostructure": "Long Document","theme": "Linen", "enrichment": "E5 hand-built SVG", "brief": "Maple Street Bread · bakery" },
{ "date": "2026-04-25", "macrostructure": "Manifesto", "theme": "Manifesto","enrichment": "none", "brief": "Meridian · studio manifesto" }
]
```
Use the **last 35 entries** to inform diversification:
- Your macrostructure pick must not match any of the last three.
- Your theme pick must differ from the last on at least one axis (see the theme-diversification rule above).
- Your enrichment pick should not be the same enrichment archetype as the last (`E1 clipped` twice in a row reads as templated, even with different content).
If the file doesn't exist, this is the first Hallmark run for this project — no constraint, but **you'll create the file in Step 5**.
If the project has a CSS stamp but no `log.json`, infer one entry from the stamp and proceed.
### 3. Load the visual ruleset
The non-negotiables live in [`references/`](references/). Read only what you need:
@@ -121,10 +152,11 @@ Always:
- For each interaction in the output (button, input, modal, toast, drag, copy, etc.), apply the recipe in [`microinteractions.md`](references/microinteractions.md). Pick *silent success* over celebratory toasts. Pick *optimistic update + Undo* over confirmation dialogs. Pick *delay 800ms* on hover tooltips and *0ms* on focus tooltips.
- Cut motion before adding it. Most pages have too much, not too little. If removing an animation wouldn't lose the user information, remove it.
- **Stamp the output.** The first non-empty line of the produced CSS file (or the top of `<style>` if inline) MUST be a comment of the form: `/* Hallmark · macrostructure: <name> · tone: <tone> · anchor hue: <hue> */`. This stamp is the durable record of what you chose. The next time Hallmark runs in this project, it reads the stamp and picks a *different* macrostructure.
- **Append to project memory.** After you write the stamp, update (or create) `.hallmark/log.json` at the project root. Append a new entry at the **front** of the array: `{ "date": "<YYYY-MM-DD>", "macrostructure": "<name>", "theme": "<name>", "enrichment": "<E# name or 'none'>", "brief": "<one-line summary>" }`. Trim the file to the last 20 entries (rotate the oldest off). Create `.hallmark/` and the file if they don't exist; respect any existing `.gitignore` (the user may or may not want this committed). This file is what Step 2.5 reads on the next run.
### 6. The slop test
Before handing back, run the output through these thirty-three questions. Every answer must be **no**.
Before handing back, run the output through these thirty-five questions. Every answer must be **no**.
**Visual:**
@@ -177,6 +209,11 @@ Before handing back, run the output through these thirty-three questions. Every
32. Does the page mix two or more icon libraries? (Material + Heroicons + Lucide on the same page = the icon-set tell.)
33. If the page has illustration, did I default to a Lottie library when a hand-built SVG or pure-CSS shape would have worked? (Lottie is last resort, not the default.)
**Diversification gates** (cross-reference [`.hallmark/log.json`](#25-check-project-memory) when present):
34. If I used the same archetype as a previous Hallmark output (per `.hallmark/log.json` or the latest macrostructure stamp), did I pick at least one different *variation knob*? Two Bento Grids with `tiles=6, spans=irregular, accent=corner-only` are the same Bento — the within-archetype knobs in [`component-cookbook.md`](references/component-cookbook.md) exist precisely to prevent that. State the knob deltas in the stamp.
35. Does any visual-only `<svg>`, custom-art `<div>`, `<canvas>`, or decorative figure lack `aria-label` or `aria-hidden="true"`? Hand-built CSS art and SVG illustrations need an accessible name *or* an explicit hide. Skipping this is the new accessibility tell.
If any answer is yes, fix it. Do not ship slop.
---
+53
View File
@@ -652,3 +652,56 @@ When building a section:
5. If the macrostructure suggests a default (e.g., Bento Grid → F1 Bento), use it; if it doesn't suggest, vary deliberately.
The goal is composed variety — within a page, sections feel different from each other; across pages Hallmark builds, sections feel different from the last.
---
## Mobile collapse — per archetype
Every archetype has a defined collapse behaviour at narrow viewports. The two breakpoints to know:
- **60 rem (~960 px)** — the *layout* breakpoint. Multi-column grids collapse to single column. Tilts and clip effects drop. Sticky panes unstick.
- **40 rem (~640 px)** — the *typography* breakpoint. Display sizes shrink one step. Side-margin labels move inline. Annotations consolidate.
Below 60 rem the archetype must still feel like itself — same hierarchy, same tone, same rhythm — but in a stacked single-column form. Below 40 rem the page is a phone; treat space like a luxury.
| Archetype | Below 60 rem | Below 40 rem |
| --- | --- | --- |
| **H1 Marquee** | unchanged (typography-only; centres / left-biases naturally) | display size step down (`xl``lg`); reduce side padding |
| **H2 Split Diptych** | grid `1fr` (text top, proof column below); divider becomes hairline-rule between | proof column collapses to a 2-column compact grid for items |
| **H3 Quote-Led** | quote stays full width; attribution wraps to its own line | quote size step down; attribution font-size step down |
| **H4 Stat-Led** | number stays full width, text stacks below; secondary stats become 2-up grid | number size step down (`clamp` floor lifts); qualifier text wraps |
| **H5 Letter** | unchanged single column; aside (if present) moves below body, divider becomes top border | salutation size step down; signoff tightens |
| **H6 Photographic** | image stays full-bleed; caption moves from absolute corner to inline below image | caption font-size step down; corner caption never overlaps text on phones |
| **H7 Demo Video Clipped-Edge** | **drops the clip**; goes `1fr` stacked, full-width media; tilt removed (clipping at 375 px reads as broken) | media reduces to 16/9; poster image used (auto-playing on cellular is hostile) |
| **H8 Mockup Split** | drops the tilt; grid `1fr`; mockup goes full-width below text | annotation pins consolidate; numbered legend moves below mockup |
| **H9 Custom Illustration** | grid `1fr`; illustration moves below text (or above — pick by tone) | illustration scales to ≤ 40 % viewport width; never dominates |
| **F1 Bento** | grid drops from 6/4-col to 2-col; large tiles span 2; small tiles span 1 | drops to 1-col; tile order respects information priority |
| **F2 Sticky-scroll stack** | sticky pane unsticks; content becomes linear sequence of paired text+visual blocks | the visuals shrink to 16/9 inline; no sticky behaviour at all |
| **F3 Tabular spec sheet** | columns reduce: 4-col → 2 (key + value), drop unit + footnote | spec list goes vertical; each row is `dt` above `dd` |
| **F4 Step sequence** | numbering moves from left margin to inline-with-step | step containers tighten; connector lines drop |
| **F5 Annotated screenshot** | screenshot full-width; annotations restack as a numbered list below | screenshot 16/9; annotations consolidate into a legend |
| **F6 Product card grid** | grid 3-up → 2-up | grid 2-up → 1-up; card height becomes flexible |
| **C1 Outlined chip** | unchanged (chips wrap onto multiple lines if needed) | full-width single chip ; min-height 44 px hit target |
| **C2 Inline form-as-CTA** | input + button stack vertically; full-width | label moves above input; button is full-width below |
| **C3 Typographic link** | unchanged (links wrap naturally) | unchanged |
| **C4 Sticky bottom bar** | unchanged (already designed for narrow); ensure 44 px min-height | label truncates if needed; CTA stays right-aligned |
| **T1 Pull quote w/ marginalia** | marginalia move below quote; divider becomes hairline | marginalia consolidate into a single line |
| **T2 Logo wall** | grid 6-up → 3-up | grid 3-up → 2-up; logo height step down (32 px → 24 px) |
| **T3 Single huge quote** | quote remains full width; attribution wraps below | quote size step down by 1.4× |
| **T4 Numbered stat strip** | strip 4-up → 2-up | strip becomes vertical; 1 stat per row |
| **Ft1 Mast-headed** | links wrap to two lines; tagline below wordmark | wordmark size step down; tagline italicises in if not already |
| **Ft2 Inline single line** | links wrap to multiple lines; separator becomes a soft return | becomes a vertical list |
| **Ft3 Index columns** | grid 4-col → 2-col | grid 2-col → 1-col; column heads remain |
| **Ft4 Dense colophon** | unchanged (mono/wraps naturally); reduce padding | font-size step down |
| **N1 Wordmark + 2 links** | unchanged | links wrap to second line if long; wordmark stays |
| **N2 Floating chip** | chip remains floating; reduce padding | chip widens to support 44 px hit target; never below 280 px |
| **N3 Side-rail** | rail unsticks and becomes a hamburger trigger above | hamburger becomes the only nav |
| **N4 ⌘K-only** | hamburger appears for users who don't know ⌘K | unchanged (⌘K equivalent is on-screen tap) |
**Cross-cutting rules:**
- All hit targets ≥ 44 × 44 px below 40 rem (WCAG AA). Never below.
- Padding-inline ≥ `clamp(1rem, 4vw, 1.5rem)` on the page container so content doesn't kiss the screen edge.
- Disable any scroll-linked animation below 40 rem (mobile scroll has its own physics; layered animations fight it).
- Image `loading="lazy"` always below the fold; **never on the LCP element regardless of viewport.**
- Auto-play video respects `data-saver` (`navigator.connection.saveData`) — replaces with poster when set.
+118
View File
@@ -62,3 +62,121 @@ Three beats:
- Non-breaking space before units: `10 kg`, `5 min` (use `&nbsp;` or U+00A0).
If the text is loaded from a CMS, configure Smart Quotes in the CMS. If it's hard-coded, write it correctly.
---
## Voice samples per tone
The skill bends toward distribution-default copy ("Built for the modern team", "Unleash your X", "Where A meets B") unless given non-default voices to imitate. The samples below are *real opening lines* from sites that defy that distribution. **Imitate the kind of specificity** — named places, named dates, named verticals, refusal of metaphor, refusal of the verb — not the wording. The tone column maps to the seven tones the design-context gate (see [`SKILL.md`](../SKILL.md) Step 1) commits the user to.
### Editorial
Three voice patterns: *date-anchored*, *refusal of the verb*, *enumerative*.
- *"Creative direction, design and type for culture since 2003."* — apracticeforeverydaylife.com — date + named verticals
- *"A monthly art publication featuring contributions by some of the most engaged thinkers working today."* — e-flux.com/journal — uses cadence (*monthly*) and a verb (*featuring*) that's specific
- *"A thing well made."* — klim.co.nz — refusal of the verb, treats design as material
- *"Frieze elevates the provocative and brilliant leading voices who shape and challenge today's art world."* — frieze.com — uses *challenge* instead of *empower*
- *"We design everything for everyone."* — pentagram.com — refusal of marketing verbs; democratic claim
- *"Writer + Photographer."* — craigmod.com — three words, two roles, no padding
- *"Type, set with care."* — Hallmark Specimen — three words; the comma is the design
- *"I'm a French design technologist based in London. I make websites and fonts, amongst other physical and digital artefacts."* — mathieutriay.com — named place, named deliverables, "artefacts" signals craft
### Brutalist
Three voice patterns: *flat declarative*, *refusal of metaphor*, *direct address with consequence*.
- *"The product development system for teams and agents."* — linear.app — flat declarative; no flourish, no "powered by AI"
- *"Resend is the email API for developers. Send transactional and marketing emails at scale with a simple, modern API."* — resend.com — names the form factor, the audience, and what it does
- *"Purpose-built for planning and building products. Designed for the AI era."* — linear.app — names the era plainly, no euphemism
- *"WE ARE A STUDIO. WE ARE NOT A PLATFORM."* — Hallmark Meridian (test 04) — defines by refusal, all caps
- *"We design products that last twelve years. We do not design products that need replacing every two."* — concrete number, paired declaration
- *"A toolkit for assembling new worlds from the scraps of the old."* — are.na — second-position copy that breaks template
- *"NO COMPROMISE."* — Hallmark Brutal — two words; the period is the design
- *"We will not put our work behind a chatbot. We will answer the email ourselves."* — declarative refusal, two short sentences
### Soft
Three voice patterns: *poetic restraint*, *passion via enumeration*, *vulnerability with proof*.
- *"It's about time."* — cron.com — pun without winking; restraint
- *"Time is our most precious resource."* — Notion Calendar — opens on the philosophical premise, then gets concrete
- *"Designer for the Web (v. XIX)."* — lynnandtonic.com — version number signals craft-in-progress
- *"Design engineer creating software that makes people feel something."* — rauno.me — emotional outcome over feature list; "feel something" avoids genre cliché
- *"All I want to do is build websites. Typography, motion design, copywriting, performance — the web is an endless medium of opportunity."* — paco.me — passion via enumeration; vulnerability ("scratched the surface")
- *"I craft UI demos that explore the power of the web and help others sharpen their skills."* — jhey.dev — names the verb (*craft*), names the audience (*others*)
- *"Soft, but exact."* — Hallmark Pastel — two short adjectives, one comma, full stop
- *"This page is soft because the surface should be soft. The rules underneath are not."* — pairs claim with refusal
### Technical
Three voice patterns: *spec-embedded prose*, *measured language*, *data-first opening*.
- *"The 14-inch MacBook Pro with M5 brings serious speed and advanced on-device AI to the personal, professional, and creative work you do every day."* — apple.com — spec embedded in prose; "serious speed" is measured language
- *"434 total posts. New CSS you feel like you could use today."* — nerdy.dev (Adam Argyle) — data-first; "feel like" suggests genuine utility
- *"$ streampipe parse access.log --filter status=5xx | jq"* — Streampipe (test 02) — open on a real command, not a marketing claim
- *"Open the trace, find the span, fix the regression. No glossary required."* — Tracejam (test 05) — three concrete verbs, then a refusal
- *"From stdin, through the pipe, into your dashboard."* — names the data path; refuses abstraction
- *"23 spans · 4 services · 482 ms."* — Tracejam mockup — data is the headline
- *"Read anything that emits lines. Files, pipes, sockets, kubectl logs."* — names the inputs, refuses generality
- *"Drop-in OTLP. No agent, no sidecar."* — pairs claim with refusal of common alternatives
### Luxury
Three voice patterns: *heritage with specifics*, *refusal as sophistication*, *named scale*.
- *"The world's most acclaimed creative collective, where 23 partners work independently and collaboratively to shape the future of design."* — pentagram.com — heritage (implied longevity), named scale (23 partners)
- *"By appointment."* — atelier-style — refusal as gatekeeping
- *"A salon for the senses."* — Hallmark Salon — single nominal phrase, comma-free
- *"A page should arrive like a person — composed, deliberate, in good clothes."* — Hallmark Salon — analogy treats the page as social
- *"With pleasure, you are most welcome."* — Hallmark Salon salutation — formal address
- *"Restraint, repeated, becomes a signature."* — Hallmark Atelier — three commas, four words, philosophical
- *"A studied hand."* — three words; the determiner does the work
- *"A small, opinionated craftsmanship engine that argues with your AI assistant on your behalf — and wins."* — Hallmark Atelier — names the role precisely, embraces the conflict
### Playful
Three voice patterns: *analogy via pop-culture*, *food/sensory metaphor*, *anticipated reaction*.
- *"Playlists, but for ideas."* — are.na — analogy that's also useful
- *"Internet memory palace."* — are.na — three-word noun phrase, structural metaphor
- *"Devouring details. Nourishing novelty. Deploying excellence."* — rauno.me — alliteration; food + tech metaphor
- *"The kind that make you say, 'Wait, how did you do that?'"* — jhey.dev — direct address, anticipates the reader's reaction
- *"Built to ship."* — Hallmark Sport — three words, declarative, with a verb that's a verb
- *"Ready? You are two minutes from shipping."* — Hallmark Sport — a question, then a number
- *"design like print: warm, off-register, intentional."* — Hallmark Riso — lowercase + colon + three modifiers
- *"this is not a page that pretends to be paper. it is a page that remembers paper."* — Riso — refuses the imitation framing
### Austere
Three voice patterns: *extreme abbreviation*, *principle as opening*, *refusal of marketing language*.
- *"Hello."* — Hallmark Quiet salutation — one word; the period is the design
- *"This is a page that doesn't try."* — Quiet — declares the position openly
- *"Things Become Other Things."* — craigmod.com — three words; treats brand as essay title
- *"Lightness above weightiness, elevate everyone you encounter."* — craigmod.com — principle-first positioning
- *"A quiet skill."* — Hallmark Quiet — three words; the article is doing work
- *"Software can be soft and exact at once. That's the trick."* — Hallmark Pastel — names the contradiction, names the resolution
- *"One HTML file."* — Anya (test 06) footer — three words; the count is the boast
- *"This page doesn't move."* — names the design decision openly
---
## Banned opening lines (anti-patterns)
These phrases appear across distribution-default LLM copy and reach for none of the specificity above. **Banned outright** — if you find yourself reaching for one, replace it with one of the patterns from the tone above.
| Phrase | Why it fails |
| --- | --- |
| *"Built for the modern team"* | Vague; assumes no specifics; temporal marketing |
| *"Unleash your [X]"* | Hyperbolic; software can't unleash anything |
| *"Where X meets Y"* | False synthesis; creative laziness |
| *"Empower your..."* | Missionary language; avoids concrete benefit |
| *"Reimagine the way you..."* | Suggests dissatisfaction before explaining need |
| *"Supercharge your workflow"* | Energy metaphor without mechanics |
| *"Innovative solutions"* | Meaningless; every product claims innovation |
| *"Seamless integration"* | "Seamless" has no antonym; signals non-specificity |
| *"In today's digital landscape"* | Temporal hand-wave; assumes the reader needs orientation |
| *"Next-generation"* | Implies predecessor inadequacy; offers no differentiation |
If the brief gives you nothing to work with for an opening line, *say so to the user* and ask one question that elicits a specific noun, verb, or place. The user knows their product; the model is not allowed to invent specificity.
+246 -1
View File
@@ -370,7 +370,252 @@ The next bakery brief Hallmark touches gets a *different* loaf — different cur
---
## Common mistakes — and the fixes
## Recipe library
The bakery loaf above is one worked example. This library catalogues four more — each a small, complete, copy-paste-able recipe at Tier A or Tier B. Use them when the brief calls for the named subject; otherwise treat them as *technique references* (the workflow diagram's `stroke-dashoffset` flow is reusable; the mascot's blink-loop is reusable; etc.).
Each recipe ships with: a one-line description, full code, a "use when / avoid when" note, a `prefers-reduced-motion` fallback block, and a real-world inspiration line.
### Recipe 1 · Workflow / process diagram
Three labelled boxes connected by curved arrows. Slight asymmetric rotation (-1° on box one, +0.5° on box three) for hand-drawn feel. One arrow has an animated `stroke-dashoffset` flow suggesting data movement. Use case: feature page showing data flow, decision tree, or user journey steps.
```html
<svg class="flow" viewBox="0 0 720 200" role="img" aria-label="Data flow: input, process, output">
<defs>
<marker id="flow-arrow" markerWidth="10" markerHeight="10" refX="8" refY="3" orient="auto">
<path d="M0,0 L8,3 L0,6" fill="currentColor" />
</marker>
</defs>
<g class="flow__step flow__step--a">
<rect class="flow__box" x="20" y="55" width="160" height="90" rx="0" />
<text class="flow__label" x="100" y="105" text-anchor="middle">Input</text>
</g>
<path class="flow__arrow flow__arrow--live" d="M 180 100 Q 220 80 260 100" marker-end="url(#flow-arrow)" />
<g class="flow__step">
<rect class="flow__box" x="260" y="55" width="200" height="90" rx="0" />
<text class="flow__label" x="360" y="100" text-anchor="middle">Parse + Filter</text>
<text class="flow__sub" x="360" y="118" text-anchor="middle">small predicate language</text>
</g>
<path class="flow__arrow" d="M 460 100 Q 500 120 540 100" marker-end="url(#flow-arrow)" />
<g class="flow__step flow__step--c">
<rect class="flow__box" x="540" y="55" width="160" height="90" rx="0" />
<text class="flow__label" x="620" y="105" text-anchor="middle">Output</text>
</g>
</svg>
```
```css
@property --flow-dash {
syntax: "<length>";
initial-value: 0px;
inherits: false;
}
.flow { width: 100%; max-width: 48rem; height: auto; display: block; margin: 0 auto; color: var(--color-ink); }
.flow__box { fill: none; stroke: currentColor; stroke-width: 1.5; }
.flow__label { font-family: var(--font-display); font-size: 16px; fill: var(--color-ink); }
.flow__sub { font-family: var(--font-mono); font-size: 11px; fill: var(--color-muted); }
.flow__step--a { transform: rotate(-1deg); transform-origin: 100px 100px; }
.flow__step--c { transform: rotate(0.5deg); transform-origin: 620px 100px; }
.flow__arrow { fill: none; stroke: var(--color-muted); stroke-width: 1.5; stroke-linecap: round; }
.flow__arrow--live {
stroke: var(--color-accent);
stroke-dasharray: 6 6;
animation: flow 2.4s linear infinite;
}
@keyframes flow { to { stroke-dashoffset: -24; } }
@media (prefers-reduced-motion: reduce) {
.flow__arrow--live { animation: none; stroke-dasharray: 0; }
}
```
**Use when** the brief is "show the user how data flows" — feature page, docs landing, technical-narrative section. **Avoid when** the diagram has more than five nodes (use Mermaid or a real graph layout) or when relationships are non-linear (this recipe assumes left-to-right flow).
*Inspiration:* Lynn Fisher's `lynnandtonic.com` `<rect>`-rotation experiments; Rauno Freiberg's `stroke-dashoffset` flows on rauno.me.
### Recipe 2 · Minimal-line mascot
A small SVG character — face only, ~120 × 120 px — that has personality without anthropomorphic uncanny-valley risk. Two ellipse eyes (with `@keyframes blink` 3s loop), a single quadratic-curve mouth, and two stem accents (hair / hat / horns / antennae). Pairs beside text.
```html
<figure class="mascot" aria-label="The Hallmark mascot — a face with two eyes and a small smile">
<svg viewBox="0 0 120 130" class="mascot__svg">
<circle class="mascot__head" cx="60" cy="60" r="42" />
<ellipse class="mascot__eye mascot__eye--l" cx="46" cy="56" rx="4" ry="6" />
<ellipse class="mascot__eye mascot__eye--r" cx="74" cy="56" rx="4" ry="6" />
<path class="mascot__mouth" d="M 50 76 Q 60 84 70 76" />
<path class="mascot__accent" d="M 32 22 Q 40 12 52 18" />
<path class="mascot__accent" d="M 88 22 Q 80 12 68 18" />
</svg>
</figure>
```
```css
.mascot { display: inline-block; width: 80px; height: 86px; margin: 0; vertical-align: -8px; }
.mascot__svg { width: 100%; height: 100%; color: var(--color-ink); }
.mascot__head { fill: color-mix(in oklch, var(--color-paper-2) 100%, var(--color-accent) 6%); stroke: var(--color-ink); stroke-width: 2; }
.mascot__eye { fill: var(--color-ink); animation: blink 5s ease-in-out infinite; }
.mascot__eye--r { animation-delay: 80ms; } /* one eye lags slightly — feels organic */
@keyframes blink {
0%, 8%, 92%, 100% { ry: 6px; }
12%, 14% { ry: 0.8px; }
}
.mascot__mouth { fill: none; stroke: var(--color-ink); stroke-width: 1.6; stroke-linecap: round; }
.mascot__accent { fill: none; stroke: var(--color-accent); stroke-width: 1.2; opacity: 0.6; stroke-linecap: round; }
@media (hover: hover) and (pointer: fine) {
.mascot:hover .mascot__head { fill: color-mix(in oklch, var(--color-paper-2) 100%, var(--color-accent) 12%); transition: fill 240ms cubic-bezier(0.16, 1, 0.3, 1); }
}
@media (prefers-reduced-motion: reduce) {
.mascot__eye { animation: none; }
}
```
**Use when** a small product / studio / indie brand needs personality without the uncanny-valley risk of a generated character. **Avoid when** the mascot needs to be expressive across many states (use Rive instead — the @property route is for simple loops, not articulated emotion).
*Inspiration:* Are.na's reductive-aesthetic site mark; the Mailchimp Freddie family (single-colour confidence); Diana Smith's CSS-art portrait constraints.
### Recipe 3 · Three-tier architectural diagram
Browser → API → Database, drawn at ~16/9 with three labelled boxes and animated `stroke-dasharray` flow lines using `@property --flow-offset`. The data-flow lines pulse to suggest live traffic. Use case: a developer-tool landing page showing where the product fits in the stack.
```html
<svg class="arch" viewBox="0 0 320 180" role="img" aria-label="Three-tier architecture: browser, API, database">
<g class="arch__tier">
<rect x="14" y="50" width="76" height="80" />
<text x="52" y="86" text-anchor="middle" class="arch__name">Browser</text>
<text x="52" y="104" text-anchor="middle" class="arch__sub">React / Next</text>
</g>
<line class="arch__flow" x1="90" y1="90" x2="120" y2="90" />
<text class="arch__hop" x="105" y="80" text-anchor="middle">HTTPS · OTLP</text>
<g class="arch__tier arch__tier--mid">
<rect x="120" y="50" width="80" height="80" />
<text x="160" y="86" text-anchor="middle" class="arch__name">API</text>
<text x="160" y="104" text-anchor="middle" class="arch__sub">Edge runtime</text>
</g>
<line class="arch__flow arch__flow--reverse" x1="200" y1="90" x2="230" y2="90" />
<text class="arch__hop" x="215" y="80" text-anchor="middle">SQL · gRPC</text>
<g class="arch__tier">
<rect x="230" y="50" width="76" height="80" />
<text x="268" y="86" text-anchor="middle" class="arch__name">Database</text>
<text x="268" y="104" text-anchor="middle" class="arch__sub">Postgres + vec</text>
</g>
</svg>
```
```css
@property --flow-offset {
syntax: "<number>";
initial-value: 0;
inherits: false;
}
.arch { width: 100%; max-width: 48rem; height: auto; color: var(--color-ink); display: block; margin: 0 auto; }
.arch__tier rect {
fill: var(--color-paper-2);
stroke: var(--color-ink);
stroke-width: 1.5;
}
.arch__tier--mid rect {
fill: color-mix(in oklch, var(--color-paper-2) 100%, var(--color-accent) 8%);
stroke: color-mix(in oklch, var(--color-accent) 60%, var(--color-ink));
}
.arch__name { font-family: var(--font-display); font-size: 11px; font-weight: 500; fill: var(--color-ink); }
.arch__sub { font-family: var(--font-mono); font-size: 8px; fill: var(--color-muted); }
.arch__hop { font-family: var(--font-mono); font-size: 7px; fill: var(--color-muted); letter-spacing: 0.04em; }
.arch__flow {
stroke: var(--color-accent);
stroke-width: 1.4;
stroke-linecap: round;
stroke-dasharray: 4 4;
animation: arch-flow 1.6s linear infinite;
}
.arch__flow--reverse { animation-direction: reverse; }
@keyframes arch-flow { to { stroke-dashoffset: -8; } }
@media (prefers-reduced-motion: reduce) {
.arch__flow { animation: none; stroke-dasharray: 0; }
}
```
**Use when** the brief is a developer-facing product that needs to show its position in a stack — observability tools, edge functions, ORMs, ingestion services. **Avoid when** the architecture has more than five tiers or non-linear topology (this recipe is for the "three-box flow" model only; for graph-like topologies, use a real diagram tool and embed an SVG export).
*Inspiration:* Vercel's network/edge diagrams; Diana Smith's structural precision in placing geometry.
### Recipe 4 · Botanical leaf flourish
A small (~40 × 80 px) hand-drawn sprig with two asymmetric leaves at +25° and -30° rotations. Leaf veins at 0.6 opacity. Sized to sit beside a headline as an inline accent. Pure SVG, no animation by default (the design is the stillness).
```html
<svg class="sprig" viewBox="0 0 40 80" aria-hidden="true">
<path class="sprig__stem" d="M 20 76 Q 18 56 21 36 Q 22 22 20 8" />
<g transform="translate(8 38) rotate(-25)">
<ellipse class="sprig__leaf" cx="0" cy="0" rx="6" ry="11" />
<path class="sprig__vein" d="M 0 -10 Q 1 0 0 10" />
</g>
<g transform="translate(28 52) rotate(30)">
<ellipse class="sprig__leaf" cx="0" cy="0" rx="6" ry="11" />
<path class="sprig__vein" d="M 0 -10 Q -1 0 0 10" />
</g>
<path class="sprig__stem" d="M 20 22 Q 16 19 13 22" />
</svg>
```
```css
.sprig {
width: 32px;
height: 64px;
display: inline-block;
vertical-align: -0.6em;
margin-inline-end: 0.4em;
color: var(--color-accent);
}
.sprig__stem { fill: none; stroke: currentColor; stroke-width: 1.4; stroke-linecap: round; }
.sprig__leaf { fill: none; stroke: currentColor; stroke-width: 1.4; }
.sprig__vein { fill: none; stroke: currentColor; stroke-width: 0.9; opacity: 0.6; stroke-linecap: round; }
/* Use beside a headline */
h1.has-flourish { display: flex; align-items: baseline; gap: 0.4em; }
```
**Use when** the brief is a bakery, restaurant, café, boutique, herbalist, florist, atelier — anything where a hand-drawn signal of *care* fits the brand. **Avoid when** the brand is technical, brutalist, or quietly austere (the sprig adds warmth where the page wants restraint).
*Inspiration:* hand-drawn botanical assets in old broadsheet papers; restaurant menus from Lisbon and Tokyo; Lynn Fisher's constraint-driven simplicity (this recipe could have been *A Single Div* with cleverer clip-paths, but SVG is more legible at small scale).
---
### Cross-recipe techniques
What all four recipes share — the four habits of hand-built CSS/SVG illustration in 2026:
1. **`@property` for declarative interpolation.** Animating a typed custom property (`<length>`, `<number>`, `<angle>`, `<color>`) gives you GPU-composited animation with zero JS. The bakery loaf, the workflow flow line, the architectural data-flow, and the mascot's blink — all use it.
2. **Asymmetric `transform: rotate()` for hand-drawn feel.** The workflow boxes rotate at ±1°, the mascot's eyes have an 80 ms delay between them, the sprig's leaves rotate +25° / -30°. Symmetry reads as algorithmic; controlled asymmetry reads as drawn.
3. **Opacity layering for pencil/secondary detail.** The workflow's reverse arrow is `var(--color-muted)`; the architectural sub-labels are 60% opacity; the sprig veins are 0.6 opacity. The hierarchy of opacity is the hierarchy of attention.
4. **Mono labels grounding decorative work in function.** The architectural diagram's `arch__sub` text uses `var(--font-mono)` at 8 px. The workflow's "small predicate language" uses mono. Decorative work earns its place by being legible and accurate; mono signals that.
Use these recipes verbatim when they fit, or strip them for technique when the brief calls for something different. The point is that *every illustration on a Hallmark page is built, not picked.*
- **Reaching for Lottie when CSS would do.** The new tell. Build the loaf in pure CSS or hand-built SVG; the Lottie is the shortcut that costs you.
- **Importing 50 KB of GSAP for a single fade-in.** Use `transition: opacity 400ms var(--ease-out)`. Zero bytes.
+17 -1
View File
@@ -71,6 +71,8 @@ A display headline left, a demo video right, and the rightmost ~1020 % of the
- Aspect ratio (16/10 · 16/9 · 4/3)
- Frame treatment (hairline 1 px frame · browser chrome · none)
**Example.** Tracejam (SaaS observability — see [`site/_tests/05-tracejam-saas/`](../../site/_tests/05-tracejam-saas/)). Display headline left ("Distributed tracing that explains itself."); hand-built CSS-art trace waterfall right, tilted -0.4°, extending 12 vw past the viewport's right edge. Aspect 16/10. Hairline frame. **Not a real video** — the mockup is custom-built CSS at Tier A (rectangles on a percentage grid simulating a flame chart). Mobile (< 60 rem): drop the clip, stack vertically.
```html
<section class="hero hero--clipped">
<div class="hero__copy">
@@ -132,6 +134,8 @@ Video fills the fold, ghost-tinted via `mix-blend-mode: multiply` over a paper-c
- Text alignment (left-bias / centred)
- Pause behaviour (always-loop · pause-on-hover · pause-when-out-of-viewport)
**Example.** A small fashion brand's spring lookbook. 8-second muted loop of fabric draping in a studio. `mix-blend-mode: multiply` over a 0.5-opacity warm-cream overlay so the italic display headline ("Spring · 2026 · Lookbook 04") reads cleanly over the moving footage. Pauses on hover so the user can read the lede without distraction. Caption track (VTT) describes the footage for accessibility.
### E3 · Mock App Screenshot — Browser-framed split
Display headline left, a browser-frame mockup right, the mockup window slightly tilted (13°) for life. Frames are from [Browserframe](https://browserframe.com) or hand-built (a 1-px hairline + three macOS dots).
@@ -144,6 +148,8 @@ Display headline left, a browser-frame mockup right, the mockup window slightly
- Tilt angle (0° · 1.5° · 3°)
- Screenshot count (1 · stack-of-3 · orbit-of-3)
**Example.** A Linear-style SaaS landing for a project tracker. Headline left ("Plan, build, ship."), browser-frame screenshot of the kanban view right, tilted 1.5° clockwise. Three numbered annotations (1 · assigns automatically · 2 · real-time presence · 3 · keyboard-first), each with a small numbered pin and a margin-aligned caption — never arrows-and-labels. Single screenshot, not a stack — fewer assets to load, sharper read.
### E4 · Mock App Screenshot — Floating no-frame
Same composition as E3 but without browser chrome — the screenshot floats with a soft shadow and 12 px corner radius. Cleaner; demands a higher-quality screenshot since the chrome isn't there to forgive.
@@ -156,6 +162,8 @@ Same composition as E3 but without browser chrome — the screenshot floats with
- Corner radius (0 · 8 px · 16 px)
- Background reveal (gradient / solid / none)
**Example.** A code-formatting CLI marketing page. Headline left ("Format anything, in eight lines."), a single floating screenshot right showing `before` / `after` code side by side. 12 px corner radius, a soft 24 px shadow at -10 px offset, sitting on a barely-tinted gradient surface. **No browser chrome** — the screenshot itself is composed and beautiful enough to stand naked. Use this when the screenshot is unusually high-quality; otherwise switch to E3 (the chrome forgives messier captures).
### E5 · Custom Illustration Centerpiece
A hand-built SVG (the default, Tier B) or a generated raster (Tier C, when characters demand it) sitting on the hero as a single illustrative element — the bakery loaf, the studio's mascot, the diagram of how the workflow flows.
@@ -168,7 +176,9 @@ A hand-built SVG (the default, Tier B) or a generated raster (Tier C, when chara
- Animation (none · loop · scroll-linked)
- Scale (small accent · dominant)
For *how* to build a hand-drawn loaf in 60 lines of SVG and animate its breath with `@property`, see [`custom-craft.md`](custom-craft.md) — there's a full bakery worked example.
**Example.** Maple Street Bread (bakery — see [`site/_tests/03-maple-bakery/`](../../site/_tests/03-maple-bakery/)). Letter-style hero copy left ("Saturday, 6:14 a.m. The dough went in at midnight."), 60-line hand-built SVG loaf right, 3 paths (body, shade, score-marks). Animated with `@property --rise` for a subtle 4 px breathing-loop over 6 s, alternating; the score-marks draw themselves on first paint via `stroke-dasharray`. Tier B, dominant scale, animation: loop. Reduced-motion fallback is a static keyframe.
For *how* to build a hand-drawn loaf in 60 lines of SVG and animate its breath with `@property`, see [`custom-craft.md`](custom-craft.md) — there's a full bakery worked example, plus four more recipes (workflow diagram, mascot, architectural diagram, botanical accent).
### E6 · Animated Loop — pure CSS / SVG / Motion
@@ -182,6 +192,8 @@ A small custom-built loop — an orbiting dot, a breathing rectangle, an animate
- Placement (margin · inline-with-headline · corner-accent)
- Loop duration (≤ 4s — anything longer drags)
**Example.** A collaborative whiteboard app. A 2-second pure-CSS loop next to the headline: a single dot orbiting a slow ellipse, suggesting "real-time collaboration" without a Lottie. Built with `@property --angle` interpolating 0deg → 360deg on a `transform: rotate()`. Margin-placed, ~64 × 64 px, accent colour at low chroma. **Not a Lottie** — pure CSS keeps the bundle at zero bytes and respects reduced-motion gracefully (animation: none on the media query).
### E7 · Abstract Background — subtle gradient + grain
A two-colour CSS gradient at low chroma, overlaid with SVG `<feTurbulence>` grain at < 0.1 opacity. *Not* aurora; *not* purple-to-cyan mesh; *not* floating orbs. The point is *texture you can barely see* — paper-quality, not decoration.
@@ -194,6 +206,8 @@ A two-colour CSS gradient at low chroma, overlaid with SVG `<feTurbulence>` grai
- Grain amount (off · subtle · textured)
- Animation (none · slow drift · scroll-linked parallax)
**Example.** A small podcast site (when the host wants more visual heat than Tide's typography-only quote). Two-stop CSS gradient at 135° (warm-cream → barely-orange, both at < 0.04 chroma) over the *hero only* — never page-wide. SVG `<feTurbulence>` grain overlay at 0.06 opacity, `mix-blend-mode: multiply`. No animation. Resists every aurora-blob temptation.
```html
<section class="hero hero--bg">
<div class="hero__bg" aria-hidden="true">
@@ -226,6 +240,8 @@ A two-colour CSS gradient at low chroma, overlaid with SVG `<feTurbulence>` grai
Existing H6 archetype in the cookbook. Cross-referenced here for completeness. See [`component-cookbook.md`](component-cookbook.md) for variation knobs.
**Example.** A small Lisbon café. One tightly-cropped photograph of the espresso machine at dawn, 4/3 ratio, no full-bleed. Caption sits margin-aligned at lower-left in mono small-caps ("Plate 04 · 6:42 a.m."). The photograph is desaturated 8 % from the source to harmonise with the page's warm-paper tone. Always pair photography with a tone-matched typography pairing (see [`typography.md`](typography.md)) — a luxury-tone photo on a brutalist page jars.
---
## Animation discipline (hero specifically)
+105
View File
@@ -29,6 +29,11 @@ Avoid when the message is a single hero idea — Bento spreads attention; one-id
Reference: Apple in-page sections, Framer feature pages, Tailwind UI templates.
**Sample opening lines** (imitate the *specificity*, not the wording):
> *"Tracejam · v0.4 · for SREs. Distributed tracing that explains itself."* — paraphrased from real observability tools
> *"Resend is the email API for developers. Send transactional and marketing emails at scale."* — resend.com
> *"The product development system for teams and agents."* — linear.app
```html
<header class="hero-fixed">…</header>
<section class="bento">
@@ -60,6 +65,11 @@ Avoid when there's a single decisive action to take — Long Document hides CTAs
Reference: Frank Chimero's site, destroytoday.com, long-form Substack essays in product disguise.
**Sample opening lines** (imitate the *specificity*, not the wording):
> *"Saturday, 6:14 a.m. The dough went in at midnight."* — opens with a time-stamp; the brand introduces itself as a moment in the day
> *"A monthly art publication featuring contributions by some of the most engaged thinkers working today."* — e-flux.com/journal
> *"We design everything for everyone."* — pentagram.com — refusal of the verb, treats design as universal practice
```html
<article class="prose">
<p class="lede">…</p>
@@ -90,6 +100,11 @@ Avoid for products whose value requires explanation in seconds. Marquee makes th
Reference: 14islands.com, destroytoday.com, many design studio homepages.
**Sample opening lines** (imitate the *specificity*, not the wording):
> *"Type, set with care."* — Hallmark Specimen — refusal of the verb, treats type as material
> *"A studio for what's next."* — italic editorial display, names the practice without explaining it
> *"Design like print: warm, off-register, intentional."* — Hallmark Riso — declarative, three modifiers, full stop
```html
<section class="marquee">
<h1 class="display-xxl">A statement.</h1>
@@ -117,6 +132,11 @@ Avoid for products without a defensible single metric. A fake big number is wors
Reference: Ahrefs, Stripe Sessions stat blocks, climate-impact dashboards, venture firm portfolio pages.
**Sample opening lines** (imitate the *specificity*, not the wording — the number does the work):
> *"+47% · faster · decide late."* — italicised number, three-word qualifier
> *"4 seconds. From the alert link to the slow span."* — pairs the number with what it bought
> *"434 total posts. New CSS you feel like you could use today."* — adam argyle, nerdy.dev — the count grounds the page in real volume
```html
<section class="stat-hero">
<div class="figure tnum">99.97<span class="unit">%</span></div>
@@ -145,6 +165,11 @@ Avoid when the product is conceptual or services-led. Workbench needs a UI to sh
Reference: Linear.app, Vercel, Raycast, Arc Browser.
**Sample opening lines** (imitate the *specificity*, not the wording — the page walks the user through):
> *"$ streampipe parse access.log --filter status=5xx | jq"* — open on a real command, not a marketing claim
> *"Read anything that emits lines. Files, pipes, sockets, kubectl logs."* — names the inputs, refuses abstraction
> *"Open the trace, find the span, fix the regression. No glossary required."* — three concrete verbs, then a refusal
```html
<header class="lite">…</header>
<section class="screenshot-frame">
@@ -173,6 +198,11 @@ Avoid as the *primary* page. FAQ usually pairs with another macrostructure that
Reference: many SaaS pricing pages, Casper, Substack help pages.
**Sample opening lines** (imitate the *specificity* — questions are real questions, answers are short and concrete):
> *"What is this for? — A single-binary CLI for parsing log streams from stdin."* — names the form factor, names the input
> *"How is this different from X? — It's about time."* — cron.com — answers obliquely, with a phrase that has weight
> *"Who built this? — Three of us, in Lisbon, since 2014."* — date + place + count, no marketing
```html
<section class="faq">
<details>
@@ -202,6 +232,11 @@ Avoid for transactional pages. Manifesto sells *agreement*, not action.
Reference: Linear's positioning pages, agency rebrand sites, political campaign landing pages.
**Sample opening lines** (imitate the *specificity* — manifestos commit, they don't hedge):
> *"WE ARE A STUDIO. WE ARE NOT A PLATFORM."* — Meridian (test 04) — defines by refusal, all caps, a single accent word
> *"We design products that last twelve years. We do not design products that need replacing every two."* — concrete number, paired declaration
> *"Lightness above weightiness, elevate everyone you encounter."* — craigmod.com — one-line principle, no explanation needed
```html
<section class="manifesto bleed-ink">
<h1 class="caps display-xxl">WE BELIEVE <em class="block-accent">DESIGN</em> IS SLOW.</h1>
@@ -230,6 +265,11 @@ Avoid without real photography. AI-generated stock undoes the macrostructure.
Reference: Aimé Leon Dore, Mr Porter editorial, Stüssy lookbooks.
**Sample opening lines** (imitate the *specificity* — captions for photographs are dates, places, plate numbers — not marketing):
> *"Plate 47 · scored before the proof."* — Maple Street Bread (test 03) — a number, a moment in the process
> *"Spring, 2026."* — Atelier-style — two words, full stop
> *"From the working archive."* — gives the photograph provenance without explaining it
```html
<section class="photo-fold">
<img class="bleed" src="hero.jpg" />
@@ -260,6 +300,11 @@ Avoid for new products without real testimonials. Fake quotes destroy trust on i
Reference: many B2B SaaS landings, agency homepages, university development pages.
**Sample opening lines** (imitate the *specificity* — quote-led pages let someone else say it, then attribute):
> *"I started listening on a long bus ride. By the third episode I'd missed my stop, and I didn't mind."* — Tide (test 01) — story-shaped, attributed to a listener
> *"Restraint, repeated, becomes a signature."* — Hallmark Atelier — short, philosophical, signed by the studio
> *"It told me the span that regressed, the deploy that caused it, and the engineer to ask. We rolled back in eight minutes."* — Tracejam-style — names the outcome with a number
```html
<section class="quote-hero">
<blockquote class="display-italic">"…"</blockquote>
@@ -288,6 +333,11 @@ Reach for it ONLY when the brief is explicitly editorial, type-foundry, journal,
Reference: type foundry homepages (Klim, Pangram Pangram, Production Type), some editorial portfolios.
**Sample opening lines** (imitate the *specificity* — Specimen openings are foundry-voice, treating type as material culture):
> *"A thing well made."* — klim.co.nz — refusal of the verb, treats design as material
> *"Type, set with care."* — Hallmark Specimen — three words, a colon implied
> *"Creative direction, design and type for culture since 2003."* — apracticeforeverydaylife.com — date-anchored, names verticals
```html
<header class="specimen">
<p class="num-label">01 — HELLO.</p>
@@ -316,6 +366,11 @@ Avoid for narrative brands. Catalogue treats every item as equal — wrong for p
Reference: Klim Type Foundry, Pangram Pangram, Coolors palettes.
**Sample opening lines** (imitate the *specificity* — Catalogue openings are inventory headers, dated, with a count):
> *"Today's loaves."* — Maple Street Bread (test 03) — two words, ownership of the day
> *"Five collections, in store now."* — names the count and the where
> *"Thirty-eight items · Spring 2026 · all hand-stitched."* — count, date, qualifier; no adjectives
---
## 12 · Letter
@@ -335,6 +390,11 @@ Avoid for transactional commerce. Letter is intimate; commerce is functional.
Reference: Frank Chimero's site, founder farewell posts, indie newsletter front pages.
**Sample opening lines** (imitate the *specificity* — Letter openings are first-person greetings, dated, with a place if relevant):
> *"Hello, I'm Anya."* — Anya (test 06) — single line, name, full stop
> *"Saturday, 6:14 a.m. The dough went in at midnight."* — opens on a moment, then explains it
> *"Hey there. This page is soft because the surface should be soft."* — Hallmark Pastel — colloquial open + a principle
---
## 13 · Index-First
@@ -354,6 +414,11 @@ Avoid for marketing pages. Index-First is for browsing audiences; selling needs
Reference: Are.na's homepage feel, archive sites, documentation indices.
**Sample opening lines** (imitate the *specificity* — Index-First openings are headers for what's below, sometimes nothing more than a label):
> *"Selected work · 2018 — 2026."* — date range, no preamble
> *"Things Become Other Things · Lightness above weightiness."* — craigmod.com — two phrases joined by a divider
> *"Writer + Photographer."* — craigmod.com — three words, summarises the whole site
---
## 14 · Narrative Workflow
@@ -373,6 +438,11 @@ Avoid for tools that work in *one* moment. Narrative Workflow needs a real seque
Reference: Linear's how-it-works pages, some Figma marketing pages.
**Sample opening lines** (imitate the *specificity* — Narrative Workflow openings are stage labels: numbered, declarative, in process language):
> *"01 · sourdough overnight · 02 · score at dawn · 03 · pull at seven."* — three numbered stages, no marketing
> *"1.0 · parse · 2.0 · filter · 3.0 · route."* — Streampipe (test 02) — versioned numbers, three concrete verbs
> *"I. We design products that last twelve years. II. A material is sustainable when someone, somewhere, can repair it."* — Meridian — Roman numerals + declarative
---
## 15 · Split Studio
@@ -392,6 +462,11 @@ Avoid for narrative or photographic brands. Split halves the attention; some pag
Reference: Vercel feature pages, Stripe Sessions program pages, many dev-tool homepages.
**Sample opening lines** (imitate the *specificity* — Split Studio openings pair a positioning statement with a proof column):
> *"A studio for what's next."* — italic display + selected-work column on the right
> *"Print discipline, on screen."* — Hallmark Newsprint — two-phrase headline, masthead-style
> *"We design and build distinctive products for ambitious teams."* — names the verb (design and build), names the audience
---
## 16 · Feature Stack
@@ -411,6 +486,11 @@ Avoid on mobile-first audiences without strong fallback. Sticky+scroll-sync is r
Reference: Apple product pages, some Stripe Sessions pages, Read.cv onboarding.
**Sample opening lines** (imitate the *specificity* — Feature Stack openings pin a single statement and then walk the user through):
> *"Plan, build, ship."* — three verbs, three sticky panes
> *"Read anything that emits lines."* — Streampipe (test 02) — names what's possible, then walks through it
> *"From stdin, through the pipe, into your dashboard."* — names the data path, then explains each step
---
## 17 · Type Specimen
@@ -430,6 +510,11 @@ Avoid when the brand uses an off-the-shelf face. Type Specimen needs something d
Reference: Klim Type Foundry, Pangram Pangram, Geist Pixel announcement pages.
**Sample opening lines** (imitate the *specificity* — Type Specimen openings are foundry-voice: name the typeface, the weights, the use):
> *"Reckless Display, set in 96 pt."* — names the face and the size, nothing else
> *"Eight weights. Three optical sizes. One good italic."* — counts the system in three short phrases
> *"A type system for editorial."* — refusal of the verb, single noun phrase
---
## 18 · Portfolio Grid
@@ -449,6 +534,11 @@ Avoid for products. Portfolio Grid is service-business shape.
Reference: Pentagram, 14islands, Locomotive, Bureau Borsche.
**Sample opening lines** (imitate the *specificity* — Portfolio Grid openings name the volume and the era):
> *"Selected work · 2018 — 2026."* — date range, two characters of meta
> *"Twelve projects, six clients, two countries."* — three counts, no adjective
> *"Work, indexed by year."* — five-word labels, the index is the whole site
---
## 19 · Map / Diagram
@@ -468,6 +558,11 @@ Avoid as a substitute for narrative. Some stories shouldn't be read spatially.
Reference: process visualisation sites, ecosystem maps, knowledge-graph products.
**Sample opening lines** (imitate the *specificity* — Map / Diagram openings name the path or the territory):
> *"Browser → API → Database. Where Tracejam fits."* — names the layers, names the position
> *"From stdin, through the pipe, into your dashboard."* — labels the spatial flow on the page below
> *"Three tiers · two regions · one ledger."* — counts the system, geographic + structural
---
## 20 · Ecosystem Index
@@ -487,6 +582,11 @@ Avoid for single-product pages. Ecosystem needs multiple things to surface.
Reference: Are.na, Figma Community, Behance.
**Sample opening lines** (imitate the *specificity* — Ecosystem Index openings are surface labels, dated, with a count):
> *"Featured · Latest · By category."* — three discovery surfaces named, divided
> *"What's on this week · Editor's pick · The whole catalogue."* — names cadence, curation, breadth
> *"A toolkit for assembling new worlds from the scraps of the old."* — are.na — second-position copy that breaks template
---
## 21 · Component Playground
@@ -506,6 +606,11 @@ Avoid for marketing pages. Playground is utility, not pitch.
Reference: shadcn/ui, Tailwind UI, Once UI, MUI demos, Framer Motion examples.
**Sample opening lines** (imitate the *specificity* — Component Playground openings are tangible: open on a real example, not a claim):
> *"Try it inline. Then take it home."* — two short imperatives
> *"Every example is editable. Every output is real."* — pairs claim with proof
> *"From `npm install` to your first chart in eight lines."* — names the step count, makes a concrete promise
---
## How to pick
+6 -3
View File
@@ -132,18 +132,21 @@ If you can't infer the domain, ask one question — "what does this thing do?"
| --- | --- |
| **podcast, audio, music, playlist, listening** | **Photographic** · **Quote-Led** · **Letter** |
| **shop, store, product, merch, commerce, ecom** | **Catalogue** · **Photographic** · **Bento Grid** |
| **docs, CLI, SDK, API, library, developer, terminal** | **Workbench** · **Long Document** · **Component Playground** |
| **agency, studio, portfolio, freelance, creative shop** | **Portfolio Grid** · **Split Studio** · **Index-First** |
| **docs, CLI, SDK, API, library, open source, developer reference** | **Workbench** · **Long Document** · **Component Playground** |
| **platform, infra, observability, dashboard SaaS, B2B tool, try-or-talk-to-sales** | **Bento Grid** · **Workbench** · **Stat-Led** |
| **agency, studio (work-led), case studies, multi-project portfolio, freelance creative** | **Portfolio Grid** · **Split Studio** · **Index-First** |
| **personal one-pager, individual, about-me, resume (no case studies)** | **Long Document** · **Letter** · **Index-First** |
| **restaurant, café, bar, food, kitchen, menu** | **Photographic** · **Long Document** · **Catalogue** |
| **fashion, apparel, beauty, lookbook** | **Photographic** · **Catalogue** · **Marquee Hero** |
| **fintech, banking, payments, invest, trading** | **Stat-Led** · **Workbench** · **Long Document** |
| **personal, resume, one-pager, about-me, individual** | **Long Document** · **Letter** · **Index-First** |
| **manifesto, campaign, cause, advocacy, political** | **Manifesto** · **Quote-Led** · **Stat-Led** |
| **editorial, foundry, magazine, type, specimen** | **Specimen** · **Long Document** · **Type Specimen** |
| **product launch, SaaS marketing, B2B** | **Bento Grid** · **Workbench** · **Stat-Led** |
| **conference, event, speaker, keynote** | **Marquee Hero** · **Manifesto** · **Photographic** |
| **fallback (genuinely no signal)** | **Bento Grid** · **Long Document** · **Manifesto** |
**Note on splits.** Some domains split on intent. *Developer-tool docs* and *developer-tool marketing* both have "developer" in them, but the docs page wants a Workbench walkthrough; the marketing page wants Bento Grid + Stat-Led so the SRE can read the value prop in 30 seconds. Same for *personal*: a one-pager about-me and a multi-project portfolio of case studies are *different briefs* — the one-pager wants prose (Long Doc / Letter); the portfolio wants Portfolio Grid / Split Studio. If the brief is ambiguous, **ask one question** to disambiguate ("docs walkthrough or marketing landing?", "one-pager or case studies?") before picking the trio.
If the user shrugs and says "you pick", read the project's CSS for a `/* Hallmark · macrostructure: ... */` stamp; whichever of the trio is most categorically distant from the stamped family is the right pick. Two consecutive outputs should never be from the same family — never two editorial macrostructures, never two grid-led macrostructures.
If the user answers a vague tone word ("modern", "clean", "professional"), that is not a feeling. Re-ask with the domain trio.
+21 -10
View File
@@ -22,17 +22,28 @@ If the user insists on one, do it. Otherwise pick from the allowlist below.
## Pairing patterns that work
| Tone | Display | Body | Mono |
| --- | --- | --- | --- |
| Editorial | Fraunces, Tiempos, Newsreader | Söhne, Haffer, IBM Plex Sans | JetBrains Mono |
| Technical | Söhne Mono, Berkeley Mono | IBM Plex Sans, Inter Display (*not* Inter) | Berkeley Mono |
| Brutalist | Druk, Monument Extended, NaN Jaune | Neue Haas Grotesk, GT America | GT Pressura Mono |
| Luxury | Canela, Tiempos Headline | Suisse Int'l, Söhne | — |
| Playful | Clash Display, Cabinet Grotesk | Satoshi, Plus Jakarta Sans | Space Mono |
| Austere | ABC Diatype, ABC Monument Grotesk | ABC Diatype, Söhne | ABC Diatype Mono |
| Workshop (Hallmark's own) | The Future, Futura, Avenir Next | The Future, Söhne | The Future Mono, Berkeley Mono |
Each tone gets two rows: a **free baseline** (everything Google-Fonts-or-similar; works out of the box) and a **paid upgrade** (foundry licences required; only when the user has confirmed the budget and the licence). The free row is the default. **Never name a paid font in code without confirming the user is licensed** — the demo will fall back to system-default and look broken to the user.
If the project's license budget is zero, free alternatives that are not on-distribution: **Fraunces, Newsreader, Space Grotesk, Plus Jakarta Sans, Bricolage Grotesque, Gabarito, Cabinet Grotesk (via Indian Type Foundry sample), JetBrains Mono, Geist, Geist Mono**.
| Tone | Tier | Display | Body | Mono |
| --- | --- | --- | --- | --- |
| **Editorial** | Free | Fraunces · Newsreader · EB Garamond | IBM Plex Sans · Inter Tight | JetBrains Mono · Geist Mono |
| | *Paid* | *Tiempos Headline · Söhne Breit · Reckless Display* | *Söhne · Haffer · Untitled Sans* | *Söhne Mono · GT America Mono* |
| **Technical** | Free | JetBrains Mono · Geist Mono · Geist (700) | Geist · IBM Plex Sans | Geist Mono · JetBrains Mono |
| | *Paid* | *Berkeley Mono · Söhne Mono · GT Pressura* | *Söhne · Untitled Sans* | *Berkeley Mono · GT Pressura Mono* |
| **Brutalist** | Free | Inter Tight (heavy) · Anton · Bricolage Grotesque (800) | Inter · Geist | Geist Mono |
| | *Paid* | *Druk · Monument Extended · NaN Jaune · Migra* | *Söhne Breit · GT America* | *GT America Mono* |
| **Soft** | Free | Geist · Bricolage Grotesque (500) · Newsreader | Geist · Crimson Pro | Geist Mono |
| | *Paid* | *Söhne · GT Pressura · Pangaia* | *Söhne · Halyard Text* | *Söhne Mono* |
| **Luxury** | Free | Cormorant Garamond · Fraunces · Cardo | EB Garamond · Crimson Pro | (rare; if needed: JetBrains Mono) |
| | *Paid* | *Canela · Tiempos Headline · GT Super · Domaine Display* | *Tiempos Text · Suisse Int'l · Domaine Text* | *(rarely used at this tier)* |
| **Playful** | Free | Bricolage Grotesque · Fraunces (italic) · Newsreader (italic) | Geist · Newsreader | Geist Mono |
| | *Paid* | *Clash Display · Cabinet Grotesk · Migra · Tobias* | *Satoshi · Plus Jakarta Sans · GT Maru* | *Space Mono · GT Maru Mono* |
| **Austere** | Free | system-ui · Inter Tight (regular) · Geist (400) | system-ui · Geist | system-ui · Geist Mono |
| | *Paid* | *ABC Diatype · ABC Monument Grotesk · Söhne (regular) · ABC Pressura* | *ABC Diatype · Söhne* | *ABC Diatype Mono · Söhne Mono* |
| **Workshop** *(Hallmark's own theme)* | Free | The Future · Geist · Inter Tight | The Future · Söhne | The Future Mono · Geist Mono |
| | *Paid* | *Avenir Next · GT Walsheim* | *Söhne · GT Walsheim* | *Berkeley Mono* |
**The discipline.** Default to the free pairings. They're not consolation prizes; Fraunces, Geist, Bricolage Grotesque, and JetBrains Mono are first-rate faces in 2026. The paid upgrades exist for two cases: (a) the user has explicitly confirmed they're licensed, or (b) the user is asking for a specific named foundry voice (e.g., "make it look like Klim", "I want Söhne"). Reach for Tier 2 only then; otherwise the free row is the right answer. Treat the free row as canon, the paid row as a *cited* alternative.
## Scale