rules/brand-identity.md
---
title: Brand Identity — Voice to Visual Translation
impact: HIGH
tags:
- brand
- identity
- voice
- positioning
---
# Brand Identity
## Contents
- What "brand" means here (the four questions)
- Voice → visual translation table
- Adjacency check
- Signature moves — name them, repeat them
- When the brand is undefined
- Anti-patterns
A great component does not just look good — it looks like *this product*
and not another. This rule turns brand voice into visual decisions you can
implement.
## What "brand" means here
For an agent designing a component, "brand" is the **answer to four
questions**:
1. **Voice** — how would the product introduce itself in one sentence?
("We're the calm tax tool", "We're the loud, opinionated CRM").
2. **Audience** — who is supposed to feel at home? Developers? Founders?
Designers? Operations? Consumers?
3. **Adjacency** — what does the product *refuse* to feel like? ("Not a
bank dashboard", "Not enterprise SaaS", "Not a toy").
4. **Signature move** — what is the one thing the product does visually
that competitors don't? (Vercel's black-and-white starkness. Linear's
keyboard-first density. Stripe's pastel gradients on serious type.)
If the user has not answered these for the product, **ask**. Do not
invent a voice. One direct question with three concrete examples is
better than a guessed direction.
## Voice → visual translation table
Use these as defaults, then refine.
| Voice trait | Translation in palette | Translation in type | Translation in space & detail |
| -------------------------- | ---------------------------- | ------------------------------ | ---------------------------------------- |
| Calm, trustworthy | Cool neutrals, single accent | One sans, modest scale | Generous space, hairline borders |
| Confident, opinionated | Black + 1 saturated colour | Heavy weights, big size jumps | Tight space, decisive edges |
| Premium, editorial | Warm neutrals, deep accent | Serif display + sans body | Wide measure, paper-like elevation |
| Friendly, approachable | Pastel multi-hue | Rounded sans | Large radius, soft shadows |
| Technical, engineering | Dark + greens / amber | Monospace | Dense, visible structure |
| Playful, expressive | Bright multi-hue | Mixed weights, occasional script | Large radius, illustrations, rotation |
| Honest, no-frills | High contrast, monochrome | System fonts | Zero or small radius, exposed grid |
| Ambient, immersive | Gradient backgrounds | Light geometric sans | Glass surfaces, blur, generous radius |
## Adjacency check
For every visual choice, ask: **"Could a competitor ship this exact
component?"** If yes, the choice is generic. Make one specific move that
forces a "no":
- A *single* signature detail (the offset shadow, the serif headline,
the monospace label, the dotted divider).
- A *single* unconventional choice that's defensible (the
numbered-section pattern, the always-visible keyboard hint, the
oversized numerals).
One per component is usually enough. Two is a lot. Three is noise.
## Signature moves — name them, repeat them
Strong brands repeat the same visual move across many components. Examples:
- **Linear**: monospaced metadata, keyboard hints in every primary
action, command-palette-as-UI, off-white background that's not pure
white, type-scale-driven hierarchy.
- **Stripe**: pastel gradient hero with serious type, the curve-line
illustrations, abundant whitespace around dense tables, the orange-on-
near-white accent.
- **Notion**: friendly emoji as design elements (not decoration),
hand-drawn illustrations, the gentle grey separators, type-only
hierarchy with almost no colour.
- **Vercel**: pure black backgrounds, white type, the geometric grid as a
graphic element, the deploy-status colour system, monospace for
metadata.
When designing a new component, ask **"which signature moves of this brand
should appear here?"** A button without any signature move is a generic
button.
## When the brand is undefined
Sometimes the user is creating a new product and no voice exists yet.
Two routes:
1. **Pick a direction and propose three voice options** anchored to it
(e.g. for "Minimal": "calm and trustworthy", "premium and quiet",
"engineering-honest"). Let the user pick.
2. **Mood-board as prose.** Write 5–7 sentences describing what the
product feels like, what it is *not*, and three named brand
adjacencies ("feels like Linear with a touch of Notion warmth, never
like Salesforce"). Then translate.
Both routes belong in `direction` mode. `templates/direction-brief.md`
is the output shape.
## Anti-patterns
- **"Vibrant and approachable yet professional and trustworthy"** —
generic, meaningless, fits everyone. Force a choice.
- **Citing 5+ exemplars in different directions** — the brand can't be
Linear *and* Notion *and* Stripe *and* Apple. Pick the dominant one.
- **A logo without a system** — one good wordmark does not make a brand
identity. Make sure the type, palette, and signature details support it.
- **Re-skinning a generic template with new colours** — colour swaps
alone don't create identity. Push for one structural move that's
uniquely yours.
rules/color-systems.md
---
title: Color Systems — Palette Construction and Roles
impact: HIGH
tags:
- color
- palette
- tokens
- roles
---
# Color Systems
## Contents
- The four-layer palette (surface, content, accent, semantic)
- Building each layer
- Generating a palette from a single brand colour
- Tokens, not raw hex
- Common palette failures to flag
- When the result still looks generic
This rule covers **palette construction and role hierarchy** — how to
compose a colour system that feels intentional, not assembled. For the
foundational contrast math, dark-mode rules, and "never rely on colour
alone" check, defer to [`/ux/rules/visual-design.md`](../../ux/rules/visual-design.md).
## The four-layer palette
A robust palette has four layers, in this order:
1. **Surface** — the canvas. Background and elevated-surface colours.
Usually 2–4 values from near-white (or near-black in dark mode) up
through subtle elevation.
2. **Content** — text, icons, separators. Built from neutrals (or
chromatic neutrals for character). Usually 3–5 luminance steps.
3. **Accent** — the brand's one (or two) saturated colours used for
action, focus, and selection. **One primary** is the default; a
second is allowed only with a clear rationale.
4. **Semantic** — success, warning, error, info. Always present, always
accessible, always *recognisable* as those meanings (red = error,
green = success). Customise hue subtly, not radically.
If a value is not classifiable into one of these four layers, it
shouldn't exist as a token. Decoration colours are not a layer.
## Building each layer
### Surface
- **One background** + **2–3 elevated surfaces** (card, popover, modal).
- Each elevation steps **2–5 % luminance** brighter (light mode) or
brighter (dark mode — see `/ux` dark-mode rules).
- Surfaces should be **near-neutral**, occasionally tinted toward the
accent for character (e.g. cool grey surfaces in a blue brand).
- Avoid pure white (`#FFF`) and pure black (`#000`) unless the
direction explicitly calls for it (Brutalist, Swiss). Use `#FAFAFA`,
`#0A0A0A`, etc.
### Content (neutrals)
A typical content scale, in luminance order:
| Token | Use |
| ----------------- | ---------------------------------------------------------- |
| `content.primary` | Headlines, body text — highest contrast on surface |
| `content.secondary` | Subdued copy, metadata |
| `content.tertiary` | De-emphasised — placeholder, captions |
| `content.disabled` | Inactive state — still readable per `/ux` rules |
| `content.inverse` | Text on dark accent surfaces (white on brand) |
Define these as a **single neutral hue ramp** (e.g. `slate-900 → slate-400`),
not arbitrary greys. Slight chromatic tint (e.g. cool slate vs warm stone)
is a brand signal — cool = engineering / honest, warm = editorial / human.
### Accent
- **One primary accent**, named after its role (`accent.primary` /
`brand.500` / `action.default`) — not after the hue (`blue.500` ages
badly when the brand rebrands).
- Provide **at least 3 steps**: a default, a hover (slightly darker /
more saturated), and a pressed / active.
- A muted variant for tinted surfaces (e.g. `accent.surface` = the
accent at 8–12 % alpha for badges, callouts).
- **One focus colour** — usually the accent at full saturation. Focus
rings are an accessibility-and-identity moment: defer the contrast
threshold to `/ux/rules/accessibility.md`, but make the *style* of the
ring a brand signature (offset, double-ring, glow — see
`signature-details.md`).
#### When two accents are justified
- Data visualisation (categorical comparison).
- Dual-mode product (read mode vs edit mode signalled by colour).
- A clearly secondary action surface (subscribe vs buy, accept vs
decline) that needs colour distinction beyond hierarchy.
Otherwise, one accent. Two accents without a reason is a tell of a
generic theme.
### Semantic
- **Error** = a red (often slightly desaturated). Pair with an icon.
- **Success** = a green (often slightly desaturated). Pair with an icon.
- **Warning** = an amber or orange. Pair with an icon.
- **Info** = either the brand accent (if blue-ish) or a separate cool blue.
Customise hue **within recognisable bounds**:
- A pink "error" reads as warning, not error.
- A teal "success" reads as info, not success.
- Test by removing the icon and asking "is this still recognisable?".
## Generating a palette from a single brand colour
If the user gives you a single brand hex:
1. **Sample to OKLCH** to reason about luminance and chroma
independently. Or use a tool the project already has (Tailwind 4
palette generator, Radix colours, Leonardo).
2. **Build the accent ramp** in luminance steps:
`100 / 200 / 300 / 400 / 500 (brand) / 600 / 700 / 800 / 900`.
3. **Derive the neutral ramp** from a desaturated version of the same
hue (1–5 % chroma) so neutrals feel like part of the same family —
not Bootstrap greys.
4. **Pick one semantic accent per meaning** — red, green, amber, blue.
Tune each toward the brand's chroma palette so they don't feel
imported.
5. **Verify contrast pairs** with `/ux/rules/visual-design.md`. Adjust
luminance, not hue, to fix contrast failures.
## Tokens, not raw hex
Recommend named tokens at every step. A token name encodes a **role**,
not a hue:
```css
/* Good — role-based */
--surface-card: #FAFAFA;
--content-primary: #0A0A0A;
--accent-default: #4F46E5;
--accent-hover: #4338CA;
--focus-ring: var(--accent-default);
/* Bad — hue-based */
--slate-50: #FAFAFA;
--slate-900: #0A0A0A;
--indigo-500: #4F46E5;
```
If the project has hue tokens already (Tailwind defaults, Radix), wrap
them with role aliases at the component level.
## Common palette failures to flag
- **The "Bootstrap 3 of everything" palette** — primary, secondary,
success, warning, danger, info, all at default saturation. Reads as
"any-SaaS-product 2014".
- **Neutrals from a different family than the accent.** Tailwind
`gray-*` next to `indigo-500` — the greys are cool, the indigo is
warm. They don't belong to each other.
- **Two accents without a rationale.** Picking blue and orange because
"they're complementary" is a tell. Ask why both exist.
- **Semantic colours used as accents.** Using `success-green` for a
"subscribe" button — readers will misread it as confirmation of an
existing state.
- **Surface and elevated-surface within 1 % luminance.** No depth read.
- **No focus colour, or focus colour = the OS default blue ring.** A
brand signature lost.
- **Decoration colours promoted to tokens.** "Pink we used once on the
/blog page" should not enter the design system.
## When the result still looks generic
Run this check:
1. Strip the logo.
2. Show the screen to someone who knows the product.
3. Do they recognise it?
If not, the palette is doing too little. The fix is rarely "more
colour". The fix is usually:
- A more **specific** accent (less Tailwind-default, more "this exact
burgundy").
- A more **specific** neutral (cool slate, warm stone, near-paper).
- A signature focus / selection / hover state (see
`signature-details.md`).
rules/signature-details.md
---
title: Signature Details — The 5% That Makes It Yours
impact: HIGH
tags:
- signature
- details
- identity
- polish
---
# Signature Details
## Contents
- Where signature lives (10 dimensions)
- Concrete moves per dimension (border / shadow / hover / focus ring / selection / dividers / icons / numerics / empty states)
- How to choose 1–3 moves
- Stripping test
- Common signature failures to flag
A component is 95 % conventional and 5 % signature. The 5 % is what
makes a card feel like a Linear card and not a Notion card. Without it,
the component looks like a Tailwind UI screenshot.
This rule enumerates the dimensions where signature lives and gives
concrete moves per dimension. **Pick 1–3 signature moves per
component family**, repeat them across the system, and don't add more.
## Where signature lives
There are ten dimensions where a brand's signature can sit. Use them
as a checklist when designing or auditing.
1. **Border / radius** — radius value and posture (sharp, gentle,
pillow, asymmetric).
2. **Border weight & style** — hairline, 2 px, dotted, dashed,
double-ring, none.
3. **Shadow / elevation** — soft and ambient, hard and offset, inset,
glow, none.
4. **Hover / pressed** — the motion or transform on hover (lift,
press, glow, rotate, no change).
5. **Focus ring** — the offset, doubling, glow, or colour of the focus
ring. Often the most under-used signature.
6. **Selection / active state** — how an item shows it's selected
(left border accent, full background tint, underline, bracket).
7. **Dividers & rules** — hairline, dotted, none, ornament glyphs,
pattern fills.
8. **Icon style** — outlined, filled, duotone, hand-drawn, monospace
glyphs (no icons at all is a valid choice).
9. **Numeric & ID treatment** — monospaced, tabular, large-with-unit,
coloured.
10. **Empty / loading state** — skeleton, illustration, sentence, ASCII
spinner, brand voice.
## Concrete moves per dimension
### Border / radius
| Direction | Posture |
| -------------- | -------------------------------------------------------------- |
| Minimal | 4–8 px, consistent, hairline borders only |
| Swiss | 0 px radius, structural borders |
| Editorial | 4–6 px, paper-edge feel, light hairline |
| Brutalist | 0 px, 2–4 px black borders |
| Neo-Brutalist | 8–12 px radius, 2–4 px black borders |
| Glass | 16–24 px, 1 px translucent inset border |
| Soft-UI | 16–28 px, no visible border |
| Terminal | 0 px or 2 px, mono-cell borders |
| Playful | 16–28 px, sometimes irregular per side |
| Retro Y2K | 8–12 px with chrome bevel |
Mixing radius values across a system is the #1 reason it looks unfinished.
### Shadow / elevation
- **Soft ambient** — `0 4px 16px -4px rgba(0,0,0,0.08)`. Default modern,
fine but unmemorable.
- **Hard offset** (Neo-Brutalist) — `4px 4px 0 0 #000` — no blur.
- **Inset** — used for pressed surfaces or input wells.
- **Glow** — coloured shadow at low alpha (`0 0 40px var(--accent)`).
Memorable on the right brand, kitsch on the wrong one.
- **No shadow** — borders + space carry depth. Minimal, Swiss, Brutalist.
- **Coloured shadow tied to the accent** — a strong signature when used
on key surfaces only (Stripe, Vercel preview cards).
### Hover / pressed
A good hover state is a brand signal:
- **Lift** — translate up 1–2 px + soften shadow. Default polite move.
- **Press** — translate down 1 px or invert offset shadow.
Neo-Brutalist core move.
- **Glow** — accent-coloured shadow appears.
- **Underline** — animated underline from left for links. Editorial,
Minimal.
- **Background tint** — surface shifts 2–4 % luminance.
- **Rotate** — 0.5–1 ° rotation. Playful only.
- **No change** — only fine for hyper-Brutalist directions.
Pick one move and repeat across all interactive elements.
### Focus ring
Most products inherit the OS focus ring. A custom focus ring is one of
the cheapest signature wins:
- **Double-ring** — `box-shadow: 0 0 0 2px var(--surface), 0 0 0 4px var(--accent)`.
Crisp, accessible, branded.
- **Offset solid** — `outline: 2px solid var(--accent); outline-offset: 2px`.
- **Inset** — focus ring sits inside the element (works on dense tables).
- **Glow** — coloured shadow at low alpha. Avoid combining with default
outline (double ring conflict).
Always defer **contrast threshold** to `/ux/rules/accessibility.md`.
This rule chooses the *style* and *posture*; `/ux` enforces the
*minimum*.
### Selection / active state
How an item declares itself "the one":
- **Left accent border** — 2–4 px coloured border on the left edge.
Linear / IDE classic.
- **Full background tint** — surface shifts to `accent.surface` at
8–12 % alpha.
- **Bracket / chevron** — a small chevron or bracket glyph appears.
Terminal direction.
- **Underline** — for tab-like surfaces.
- **Bold weight increase** — text shifts from 400 → 600.
Combining 2 cues is fine (tint + bold). Combining 4 is loud.
### Dividers and rules
- **Hairline** — 1 px at low-luminance neutral. Modern default.
- **Dotted** — 1 px dotted. Editorial, retro warmth.
- **No divider** — space and weight do the work. Premium move.
- **Ornament glyph** — a centred `❦` or `⸻` (Editorial direction only).
- **Numbered section markers** — `01 / Introduction` as a leading
divider. Swiss / Editorial signature.
### Icon style
- **All outlined** (consistent stroke weight) — friendly, modern, default.
- **All filled** — assertive, dense, often used at small sizes.
- **Duotone** — Phosphor-style, two-tone — distinctive when used
consistently.
- **Custom illustrations** — branded but expensive to maintain.
- **No icons** — Brutalist, Editorial, type-only directions. Underrated.
Don't mix outlined and filled in the same surface. `/ux/rules/visual-design.md`
covers this from the consistency angle; this rule covers it as a
signature decision.
### Numeric & ID treatment
- **Tabular numerals** for every number in a table — `font-variant-numeric: tabular-nums`.
- **Monospace for IDs / hashes** — `SHA: 8a3f...e021` reads correctly
only in mono.
- **Large stat + small unit** — `42 ms` with the `ms` at 0.5–0.7×
numeric size. Signature dashboard move.
- **Coloured numbers** — green for positive delta, red for negative.
Pair with sign or arrow (see `/ux/rules/visual-design.md` —
never colour alone).
### Empty and loading states
- **Skeleton** — generic, fine, unmemorable. `/animations` covers
motion mechanics.
- **Illustration** — Playful / Soft-UI. Expensive.
- **Sentence** — "No invoices yet. Send your first one →" — voice
carries identity.
- **ASCII spinner** — Terminal direction.
- **Brand-voiced** — "We're warming up the engines..." — depends
heavily on the brand voice (see `brand-identity.md`).
## How to choose 1–3 moves
1. Start from the **direction** (`style-directions.md`) — it constrains
most defaults.
2. Pick **one move that defines depth**: shadow style, no shadow, glow,
inset.
3. Pick **one move that defines interactivity**: hover, focus ring,
selection state.
4. Optional: pick **one ornamental move**: divider style, numeric
treatment, icon style.
Repeat these moves across every component in the system. The signature
is what's **consistent**, not what's spectacular on one screen.
## Stripping test
For any component, do the **strip test**:
1. Remove the logo / wordmark.
2. Show the screen to someone who knows the product.
3. Ask "is this ours?"
If no, the signature is too thin. Promote one of your repeating moves
into this component. If yes, you're done.
## Common signature failures to flag
- **Default OS focus ring** — a wasted signature opportunity.
- **Default Material elevation 1–24 ladder** unmodified — looks
generic across half the web.
- **Tailwind UI defaults shipped as the product** — every shadow at
`shadow-sm`, every radius at `rounded-lg`, every focus at
`ring-2 ring-blue-500`. Reads as template.
- **A signature move used only on the marketing page** — the product
surface inside the app reverts to defaults. The signature must live
in the dense product UI, where users actually spend time.
- **Three different signature moves competing.** A glow, a hard
shadow, and a rotation on hover. Pick one.
- **Inconsistent radius across siblings.** `4 / 8 / 12 / 16` randomly
applied. Lock to two values, max.
rules/style-audit.md
---
title: Style Audit — Generic-AI-App Check
impact: HIGH
tags:
- audit
- review
- checklist
- identity
---
# Style Audit
## Contents
- The generic-AI-app score (low / medium / high)
- The 12-point identity checklist
- Top-3 fixes — how to pick
- The strip test (final check)
- What the audit is **not** for
- Worked snippet — the bottom of a review report
Use this rule during `review` mode. It produces the **generic-AI-app
score** (`low | medium | high`) and the **top-3 fixes** list at the
end of the report. Run it after the per-concern reviews
(`color-systems`, `typography-pairing`, `visual-hierarchy`,
`signature-details`).
## The generic-AI-app score
"Generic AI-app" is the dominant 2024–2026 aesthetic: dark mode with
purple-blue gradient hero, glassmorphic card, Inter typography, soft
shadow, `rounded-2xl`, a Tailwind indigo CTA. It is everywhere. It is
fine. It is not identity.
Score the target on the **12-point identity checklist** below.
Each `yes` is one point. Total → score:
| Total points | Score | Meaning |
| ------------ | -------- | -------------------------------------------------------- |
| 10–12 | `low` | Distinctive. Signature reads. Recognisable without logo. |
| 6–9 | `medium` | Some identity, drift in others. Targeted polish needed. |
| 0–5 | `high` | Reads as generic template / AI-app default. |
## The 12-point identity checklist
For each, mark yes / no with evidence.
1. **Direction committed.** Does the component sit clearly inside one
named direction from `style-directions.md` (or a *deliberate* mix
of two)? Yes / no.
2. **Single primary accent.** Is there exactly one primary accent
colour (with a defensible exception)? Yes / no.
3. **Specific accent hue.** Is the accent something other than
Tailwind-default blue / indigo / emerald at `500`? Yes / no.
4. **Neutrals tinted to the accent family.** Cool greys with cool
accent, or warm with warm? Yes / no.
5. **Type contrast > 2 ×.** Is the display-to-body ratio at least 2 ×
(or stronger as the direction demands)? Yes / no.
6. **Type weight hierarchy.** Are at least 2 weights used to create
hierarchy, not size alone? Yes / no.
7. **Custom focus ring.** Is the focus ring branded (offset, double,
accent colour) rather than the OS / Tailwind default? Yes / no.
8. **One repeating signature move.** Can you name one move (shadow
style, hover transform, divider, selection state) that repeats
across siblings? Yes / no.
9. **Radius locked to 1–2 values.** No `4 / 8 / 12 / 16 / 24` drift.
Yes / no.
10. **Numbers and IDs respect their nature.** Tabular numerals in
tables, monospace for IDs, large-number-small-unit for stats.
Yes / no.
11. **One clear focal point.** A reader can identify what the
component wants them to see first. Yes / no.
12. **Empty / loading / error voice.** Is at least one of these
states written with the brand's voice, not generic Lorem? Yes / no.
## Top-3 fixes — how to pick
After the checklist, list **the three changes** that would lift the
score the most. Choose by this priority order:
1. **Direction commitment.** If `#1` is no, fix this first. Nothing
else compounds without it.
2. **Signature move.** If `#7` or `#8` are no, propose one move
that's cheap and high-impact (custom focus ring, hover transform,
selection cue).
3. **Hierarchy drama.** If `#5` or `#11` are no, push the scale and
focal point. Cheap, transformative.
4. **Accent specificity.** If `#3` is no, propose a more specific
accent (not Tailwind 500).
5. **Token discipline.** If `#9` is no, lock the radius and audit
spacing.
Only escalate to deeper changes (typography family swap, palette
rebuild) when the cheap wins are exhausted.
## The strip test (final check)
Before finishing the report:
1. Imagine the wordmark removed.
2. Could a regular user of the product identify it from this
component alone?
3. If no, your top-3 fixes should include at least one signature move
that solves this.
## What the audit is **not** for
- **WCAG findings.** Defer to `/ux/rules/accessibility.md` and
`/ux/rules/visual-design.md`.
- **Touch-target failures.** Defer to `/ux/rules/touch-and-interaction.md`.
- **Microcopy quality.** Defer to `/ux/rules/ux-writing.md`.
- **Dark-pattern detection.** Defer to `/ux/rules/dark-patterns.md`.
Do not duplicate those findings here. A complete UI review should run
both `/ux` and `/visual-design` and let the user merge them.
## Worked snippet — the bottom of a review report
```
### Generic-AI-app score: medium (7/12)
Yes:
- Direction committed (Minimal)
- Single primary accent
- Neutrals tinted to accent family
- Type contrast 3×
- Type weight hierarchy (400 / 600)
- Radius locked (4 px on all surfaces)
- Tabular numerals in the data table
No:
- Accent is Tailwind `indigo-500` — generic
- Focus ring is OS default
- No repeating signature move
- Focal point unclear — title and CTA compete
- Empty state is "No data."
### Top 3 fixes
1. **Adopt a specific accent.** Move from `indigo-500` to a brand-
specific hue (proposal: `#4338CA` shifted to OKLCH `0.50 0.18 280`
— slightly more violet, less generic). Cite: `color-systems.md`.
2. **Brand the focus ring.** Replace OS outline with a 2 px accent
ring at 2 px offset. Sample provided below. Cite:
`signature-details.md`.
3. **Resolve focal competition.** Drop the CTA from display weight to
body-bold; keep the title as the only display-weight element.
Cite: `visual-hierarchy.md`.
```
rules/style-directions.md
---
title: Style Directions — Named Taxonomy
impact: HIGH
tags:
- style-direction
- taxonomy
- identity
- lookup
---
# Style Directions
## Contents
- Decision flow — pick one direction
- The directions (1–10): Minimal, Swiss, Editorial, Brutalist, Neo-Brutalist, Glass, Soft-UI, Terminal, Playful, Retro
- Mixing directions — only with intent
- Common direction collisions to flag
A **named, canonical taxonomy** of visual directions for product UI.
Use it for three purposes: identify the direction an existing component
sits in (or fails to commit to), pick a direction for new work, and check
that recommendations stay inside one direction rather than mixing.
Each entry has a fixed schema: **posture**, **canonical palette**, **type**,
**space & radius**, **signature**, **avoid**, **exemplars**.
Read just the entry you need.
## Decision flow — pick one direction
1. What does the brand voice claim (see `brand-identity.md`)? Confident /
playful / authoritative / honest / experimental? Map to a direction:
| Voice | Default direction |
| -------------------- | -------------------------- |
| Calm, trustworthy | Minimal or Swiss |
| Editorial, premium | Editorial |
| Bold, opinionated | Brutalist or Neo-Brutalist |
| Lush, ambient | Glass |
| Friendly, tactile | Soft-UI |
| Engineering, exact | Terminal |
| Joyful, kid-friendly | Playful |
| Nostalgic | Retro |
2. Where does the product live? Internal tooling → Terminal / Swiss. B2B
SaaS → Minimal / Swiss / Editorial. Consumer → Playful / Soft-UI / Glass.
Brand-led marketing → any, but commit harder.
3. **Pick exactly one.** Mixing directions without intent is the #1 reason
components look generic. Cross-pollinate only deliberately and call it
out (e.g. "Swiss layout, Editorial type, no decoration").
## The directions
### 1. Minimal
- **Posture:** Restraint. The work is in what you remove. One accent
colour, generous whitespace, no decorative elements.
- **Palette:** Near-white background, near-black content, one accent
(often the brand colour at a single 500/600 step). Greys carry hierarchy.
- **Type:** One family, system or geometric sans. 2–3 weights. Tight scale.
- **Space & radius:** Generous space (1.5× a normal scale). Small radius
(4–8 px) or zero. No shadows.
- **Signature:** Hairline borders (1 px, ~10 % luminance). Subtle
separators. Type does the work.
- **Avoid:** Gradients, drop shadows, multiple accents, decorative icons.
- **Exemplars:** Linear, Vercel dashboard, Stripe docs.
### 2. Swiss / International Typographic Style
- **Posture:** Grid, hierarchy, asymmetric balance. Type as the protagonist.
- **Palette:** Black, white, one accent (often red, yellow, or blue). No
gradients. Greys via type weight, not via colour.
- **Type:** Helvetica, Inter, or a geometric grotesque. Aggressive size
contrast (display 4–8×body).
- **Space & radius:** Strict baseline grid. Zero radius. Generous gutters.
- **Signature:** Numbered sections, oversized numerals, asymmetric splits,
type that fills the column.
- **Avoid:** Decorative borders, rounded corners, shadows.
- **Exemplars:** Mubi, MoMA, mid-century Swiss posters, modern Vercel
marketing pages.
### 3. Editorial
- **Posture:** Magazine / book. Mixed-serif and sans. Wide content
measure. Imagery dominates.
- **Palette:** Warm neutral (ivory / off-white / paper) backgrounds.
Saturated accent (often a single deep tone — burgundy, ink, forest).
- **Type:** Serif display (Tiempos / GT Sectra / Domaine) for headlines,
geometric sans for body and UI. Italics used intentionally.
- **Space & radius:** Wide measure (60–75ch). Small radius (4–6 px).
Subtle paper-like elevation.
- **Signature:** Drop caps, pull quotes, ornaments (rule lines, glyphs),
thoughtful image cropping.
- **Avoid:** Hard primary colours, neon, plastic shadows.
- **Exemplars:** The New York Times Cooking, Apple Newsroom, Substack
publications.
### 4. Brutalist
- **Posture:** Raw, structural, anti-design. Things are functional,
blocky, intentionally unrefined.
- **Palette:** High contrast — black on white, often with one screaming
accent (chartreuse, hot pink, electric yellow). Or pure monochrome.
- **Type:** Default browser fonts, monospace, or aggressive grotesques.
Mixed sizes intentional.
- **Space & radius:** Zero radius. Aggressive use of negative space or
none at all. Borders thick (2–4 px).
- **Signature:** Visible structure (grids exposed), system fonts, raw
elements, intentional ugliness.
- **Avoid:** Polish, gradients, soft shadows, careful pairing.
- **Exemplars:** Gumroad (2022 redesign), Are.na, early Craigslist as
reference, Bloomberg Businessweek covers.
### 5. Neo-Brutalist
- **Posture:** Brutalist energy, candy palette. Hard shadows, bold
borders, flat blocks of saturated colour.
- **Palette:** Pure saturated colours (cyan, magenta, lime, lemon, hot
pink) on white or cream. No gradients.
- **Type:** Bold geometric sans (Inter, Space Grotesk, Archivo).
Heavy weights.
- **Space & radius:** Medium radius (8–12 px). 2–4 px black borders. Hard
black drop shadows offset 4–8 px (no blur).
- **Signature:** Hard offset shadows, thick black outlines, candy colour
blocks, slight rotation on hover.
- **Avoid:** Soft shadows, gradients, muted palette, subtle hover states.
- **Exemplars:** Gumroad (current), many indie SaaS landing pages
2022–2024, "Brutalism reskin" Tailwind component libraries.
### 6. Glass / Aurora
- **Posture:** Translucent surfaces over ambient blurred backgrounds.
Depth via blur, not shadow.
- **Palette:** Cool gradient backgrounds (aurora, dawn). Surfaces are
semi-transparent whites or near-blacks with backdrop blur.
- **Type:** Geometric sans, often slightly condensed. Light to medium
weights.
- **Space & radius:** Generous radius (12–20 px). Soft, large radii on
containers.
- **Signature:** `backdrop-filter: blur(...)`, ambient gradient blobs,
inset highlights, subtle 1 px translucent borders on top of glass.
- **Avoid:** Hard shadows, opaque surfaces, hard borders, system fonts.
- **Exemplars:** Apple visionOS, Arc browser, modern Apple marketing
pages.
### 7. Soft-UI (Neumorphism-adjacent, not pure)
- **Posture:** Tactile, rounded, friendly. Surfaces look pressable.
- **Palette:** Warm low-saturation pastels. Background and surface within
10 % luminance of each other.
- **Type:** Rounded sans (Nunito, DM Sans, SF Pro Rounded). Medium weights.
- **Space & radius:** Large radius (12–24 px). Generous padding.
- **Signature:** Dual shadows (light highlight top-left, soft shadow
bottom-right) on key surfaces — used sparingly, not on every element.
Subtle inner highlight.
- **Avoid:** Pure neumorphism (everything embossed = unreadable),
hard borders, high contrast, monospace.
- **Exemplars:** Headspace, Calm, recent fintech onboarding (Revolut,
N26 lite mode).
### 8. Terminal / Monospace
- **Posture:** Developer-native. Monospace, dense, information-rich.
- **Palette:** Dark background (warm black, not pure #000). Greens /
ambers / cool greys for content. One accent for action.
- **Type:** Monospace throughout (Berkeley Mono, JetBrains Mono, IBM Plex
Mono). Occasional grotesque for headlines.
- **Space & radius:** Tight space. Small or zero radius. Visible cell
borders sometimes.
- **Signature:** Caret cursors, ASCII rules, command-bar UI, syntax-style
colour coding for status, structured logs as native UI.
- **Avoid:** Sans-serif body, rounded corners, decorative imagery.
- **Exemplars:** Vercel CLI output as UI, Warp terminal, Linear's
command palette, GitHub CLI.
### 9. Playful
- **Posture:** Joyful, expressive, illustrated. Movement implied even in
still UI.
- **Palette:** Bright, multi-hue. 3–5 accent colours used freely. Hand-
picked, not generated.
- **Type:** Rounded sans, occasional display-script for moments of voice.
Mixed weights deliberate.
- **Space & radius:** Large radius (16–28 px). Generous space.
- **Signature:** Custom illustrations, mascots, micro-animations, slight
rotation on cards, emoji used as design elements (not just chrome).
- **Avoid:** System fonts, monochrome, zero radius, restraint.
- **Exemplars:** Notion's marketing, Mailchimp, Duolingo, Figma's empty
states.
### 10. Retro / Vaporwave / Y2K
- **Posture:** Nostalgic period reference, applied with intent.
- **Palette:** Period-specific. 80s: hot pink + cyan + black. 90s: warm
beige + maroon + forest. Y2K: chrome + iridescent + bubblegum.
- **Type:** Period-correct — Times New Roman + Verdana for Y2K, Helvetica
for 70s, geometric pixel for 8-bit, Cooper Black for 70s display.
- **Space & radius:** Period-correct. Y2K: 8–12 px radius with chrome
bevel. 80s: zero radius, hard lines.
- **Signature:** Period chrome, scanlines, halftone, pixel borders,
bitmapped icons.
- **Avoid:** Modern conventions that break the period illusion (smooth
gradients in pixel art, etc.).
- **Exemplars:** Are.na (slight), early Glossier, Frank Ocean's Blonde
site, indie game landing pages, Telfar.
## Mixing directions — only with intent
A deliberate mix can produce signature work:
- **Swiss layout + Editorial type** — premium B2B with magazine soul.
- **Minimal palette + Neo-Brutalist shadows** — calm UI with one moment
of voice on the CTA.
- **Terminal density + Soft-UI palette** — friendly dev tools.
If you propose a mix, **name both directions and the reason**. Otherwise
the result reads as drift, not voice.
## Common direction collisions to flag
- "Minimal with a glowy gradient hero" → the hero is fighting the rest.
- "Brutalist with rounded corners and soft shadows" → not brutalist,
just generic.
- "Neo-Brutalist drop shadow on a glassmorphic card" → two contradictory
depth metaphors.
- "Editorial serif headline over a synthwave hero" → period collision.
- "Playful palette in a tax-software dashboard" → tone-context mismatch.
rules/typography-pairing.md
---
title: Typography Pairing — Personality and Pairing Rules
impact: HIGH
tags:
- typography
- type-pairing
- voice
- hierarchy
---
# Typography Pairing
## Contents
- The one-family rule
- Pairing rules
- Personality cheat sheet
- Scale construction
- Weight as hierarchy
- Tracking and case
- Tabular numerals
- Web font loading
- Common typography failures to flag
- Type as brand signature
This rule covers **type personality and pairing** — choosing fonts and
combining them so the result feels intentional. For size minimums, line
length, line height, and dynamic-type rules, defer to
[`/ux/rules/visual-design.md`](../../ux/rules/visual-design.md).
## The one-family rule
Default to **one family** until you have a reason to add a second.
Modern UI type families (Inter, Geist, IBM Plex, SF Pro, Roboto Flex)
ship enough weights, widths, and optical sizes to handle display, body,
mono-numerics, and UI without help.
Add a second family only for one of these reasons:
1. **Voice contrast.** Editorial direction wants a serif headline against
a sans body.
2. **Function.** Code, IDs, numbers, and dense metadata read better in
monospace.
3. **Brand signature.** The product's signature move *is* a specific
display font (e.g. Cooper Black for a retro brand, custom variable
wordmark for a tech brand).
Three families is almost always wrong. Stop.
## Pairing rules
When you do pair, follow these:
1. **Pair across categories, not within.** Serif + sans, sans + mono,
display + sans body. Two sans-serifs together look like a mistake,
not a pairing — unless one is a wider grotesque against a narrower
geometric and the contrast is decisive.
2. **One does the talking, one does the listening.** Display is loud
and rare. Body is quiet and dense. Don't fight.
3. **Match x-height ratio within ~15 %.** Mismatched x-heights make
captions look like a different document from headlines.
4. **Match the metric weight.** A 700-weight in one font is not the
same density as 700 in another. Test side by side.
5. **No more than two families in body content.** Mono inserts inside
sans body text are fine; alternating sans paragraphs are not.
## Personality cheat sheet
Pick families by what they sound like, not what's trendy.
| Personality | Sans options | Serif options | Mono options |
| ------------------ | --------------------------------------- | ------------------------------ | ---------------------------------- |
| Calm / neutral | Inter, Geist, SF Pro, system-ui | Source Serif, Crimson Pro | JetBrains Mono, Geist Mono |
| Confident / sharp | Söhne, Helvetica Now, Neue Haas Grotesk | GT Sectra, Tiempos Headline | Berkeley Mono, MD IO |
| Editorial / warm | GT America, Plantin Sans | Tiempos, Domaine, Caslon, EB Garamond | Plantin Mono, IBM Plex Mono |
| Technical / engineering | IBM Plex Sans, Space Grotesk, Mona | Roslindale, Lyon | IBM Plex Mono, Berkeley Mono, Fira Mono |
| Playful / friendly | Nunito, DM Sans, Inter Rounded | Cooper, Mrs Eaves | DM Mono, Comic Mono (intentionally) |
| Brutalist / raw | Helvetica (default), Arial, Times | Times New Roman | Courier (default) |
When in doubt, **Inter** for sans and **JetBrains Mono** for mono is the
default that won't fail. The signature comes from how you *use* them
(scale, weight contrast, tracking), not from picking a more exotic font.
## Scale construction
Build a type scale, do not list arbitrary sizes.
| Role | Web (px) | iOS (pt) | Android (sp) | Weight |
| -------------------- | ---------- | ---------- | ------------ | ----------------- |
| Display | 40–72 | 34–48 | 32–48 | 700–900 |
| H1 | 30–40 | 28–34 | 28–32 | 600–800 |
| H2 | 22–28 | 22–24 | 22–24 | 600–700 |
| H3 | 18–22 | 18–20 | 18–20 | 600 |
| Body | 16 | 17 | 14–16 | 400–500 |
| Caption / meta | 12–14 | 13 | 12 | 400–500 |
| UI label | 14 | 15 | 14 | 500–600 |
| Mono / numeric | match body | match body | match body | 400–500 |
Pick **one scale ratio** (1.125 / 1.25 / 1.333 / 1.5) and apply it
consistently. The drama of the scale is part of the direction:
- **Minimal / Swiss:** wide ratio (1.5 or 1.618) so display is 4–8 ×
body. Big contrast, few sizes.
- **Editorial:** moderate ratio (1.333) with a strong display step.
- **Soft-UI / Playful:** narrow ratio (1.125–1.25) so everything feels
gently varied.
- **Terminal:** narrow ratio (1.125) — density beats hierarchy.
## Weight as hierarchy
Weight contrast often beats size contrast for clarity, and is cheaper:
- Body 400, label 500, heading 600, display 700–800 reads as a clear
hierarchy even at similar sizes.
- Use one font with **2–3 weights** rather than two fonts at the same
weight.
- Avoid 100 / 200 weights for body text on light backgrounds — fails
contrast and looks fragile.
## Tracking and case
These small choices carry a lot of voice:
- **Display:** -1 to -3 % tracking on large sizes. Tight = confident.
- **Body:** 0 % at 16 px; +1 to +2 % below 14 px to compensate.
- **UI labels:** sometimes ALL CAPS + 6–10 % tracking for utility chips
and small headers (Swiss direction loves this).
- **Sentence case** for buttons and labels by default. Title Case for
buttons reads dated unless the direction calls for it (Editorial,
Retro).
## Tabular numerals
For tables, totals, prices, timestamps, and dashboards:
```css
font-variant-numeric: tabular-nums;
```
Or use the typeface's `tnum` OpenType feature. This single property
upgrades dashboards more than most palette decisions.
## Web font loading
A skill for delivery is a skill for design, briefly:
- **Subset** to the characters you use (Latin only if Latin only).
- **Preload** the display font used above the fold.
- **`font-display: swap`** with a tuned fallback (`size-adjust` +
`ascent-override` to match) so the layout doesn't jump.
- **System fallback** for body in fast-load contexts is honest, not lazy
(Swiss and Brutalist directions can lean into this).
## Common typography failures to flag
- **Two sans-serifs paired.** No contrast, looks accidental.
- **Three or more families.** Almost always too many.
- **Display font used at body size.** Display fonts have hinting and
spacing for large sizes — they look brittle at 14 px.
- **Body font used at 72 px.** Body fonts are designed for legibility,
not drama. They look weak at display sizes.
- **No mono for numbers or IDs.** Misalignment in tables and dashboards.
- **Weight 100–300 body on white.** Often fails contrast (see `/ux`),
also looks anaemic.
- **`text-transform: uppercase` on long passages.** Reads slowly. Use
ALL CAPS only on short labels.
- **Inconsistent tracking.** Some headings -2 %, others 0 %, by accident.
- **A scale built by eye, not by ratio.** Drift accumulates.
## Type as brand signature
Some of the strongest brand signatures live in type:
- **Linear:** a slightly off-default monospace for metadata, sans labels
for UI, and assertive size contrast.
- **Stripe:** serious sans with very generous tracking on display.
- **Vercel:** Geist everywhere, with hard size contrast and tight
display tracking.
- **Notion:** rounded sans with very modest scale, and emoji as design.
- **Apple:** SF Pro with tight tracking on display, generous on body —
recognisable in two characters.
If the brand voice is strong, treat type as part of the signature
(see `signature-details.md`).
rules/visual-hierarchy.md
---
title: Visual Hierarchy — Focal Point, Scan Path, Drama
impact: HIGH
tags:
- hierarchy
- focal-point
- scan-path
- composition
---
# Visual Hierarchy
## Contents
- The one-focal-point rule
- Scan path — the 3-stop rule
- Drama through contrast
- Breathing room
- Alignment and rhythm
- Visual weight balance
- Density posture
- Common hierarchy failures to flag
- Cross-references
This rule covers **aesthetic hierarchy** — guiding the eye for impact,
not just for accessibility readability. `/ux` covers structural
hierarchy (semantic headings, focus order, ARIA landmarks). Both are
required; this one is about whether the component feels designed or
assembled.
## The one-focal-point rule
Every component should have **one focal point** the eye lands on first.
Two co-equal focal points compete; the result reads as cluttered or
indecisive.
To find it, ask: **"If the user only saw this for half a second, what
should they remember?"** That's the focal point. Make one of the
following do the work to elevate it:
- **Size.** Largest type on the page (display, hero stat, hero image).
- **Weight.** Heaviest weight relative to the surroundings.
- **Colour.** The only saturated thing on a neutral canvas.
- **Position.** Top-left in LTR scan, dead-centre in deliberate
composition.
- **Negative space.** The thing surrounded by the most breathing room.
- **Contrast.** The highest luminance contrast against the surface.
**Use 1–2 devices to elevate the focal point. Not all six.** Stacking
all elevation tricks is what makes hero sections feel desperate.
## Scan path — the 3-stop rule
After the focal point, design the **2nd and 3rd stops** explicitly.
A good component has a clear scan path:
1. **Stop 1 (focal):** what is this and why care.
2. **Stop 2:** the proof / the supporting detail.
3. **Stop 3:** the action.
A card UI is almost always: image / title → metadata → CTA. A dashboard
KPI is: large number → label → trend / delta. A pricing tier is:
plan name → price → CTA → feature list.
Each stop should be **clearly different** from the next in at least one
dimension (size, weight, colour, alignment, distance) so the eye knows
to move on.
## Drama through contrast
"Drama" is the deliberate size and weight gap between focal point and
body. Most generic UI fails because the gap is too small. Push it:
| Direction | Display-to-body ratio | Why |
| ---------------- | --------------------- | ------------------------------------------------ |
| Editorial | 3–6 × | Magazine pacing |
| Swiss | 4–8 × | Typography as the protagonist |
| Minimal | 2–3 × | Restraint — drama via space, not size |
| Brutalist | 6–10 × | Aggressive scale jumps |
| Terminal | 1–1.5 × | Density over drama |
| Soft-UI / Playful| 1.5–2.5 × | Gentle scale, friendliness over impact |
If your card title is 18 px and your body is 16 px, **you have no
hierarchy** — that's not subtle, that's flat. Either raise the title
or lean on weight contrast (600 vs 400).
## Breathing room
White space is the cheapest way to make a component feel premium.
Two patterns:
1. **Internal padding.** Generous padding inside containers (1.25–2 ×
what feels first-correct). Hero stats with `padding: 48px` feel
important. Hero stats with `padding: 16px` feel cramped.
2. **External separation.** The space *between* sibling components.
Group related items tightly (8–12 px) and separate groups generously
(24–48 px). The eye reads grouped items as one thing.
The "Squint test": squint at the component until the type blurs. You
should still see **distinct blocks of content** separated by visible
white space. If everything blurs into one grey mass, increase spacing
between groups.
## Alignment and rhythm
- **Pick one alignment grid.** Left-aligned (default), centred (rare,
intentional), or asymmetric (Swiss). Mixing alignment without reason
reads as accidental.
- **One vertical rhythm.** Body text on an 8 px (or 4 px) baseline.
Heading line-heights tuned to align to that baseline ±1 unit.
- **Numbers right-aligned** in tables. Always. Currency symbols
left-aligned to their column.
- **Icons and adjacent text on the same optical baseline** — not the
same `vertical-align: middle` (which often looks off because icon
glyph boxes differ).
## Visual weight balance
The composition is balanced when the visual weights on left and right
(or top and bottom) feel equivalent — not symmetric, but equivalent.
- A heavy graphic on the left balances a column of dense type on the
right.
- A small bright accent balances a large neutral area (a single red dot
balances a paragraph of grey type).
- A heavy display headline at the top balances generous space below.
If the component feels "tipped" to one side, add weight to the lighter
side (a small element with strong contrast goes a long way) or remove
weight from the heavier side.
## Density posture
Different directions tolerate different density. Pick one **density
posture** per component and hold it:
- **Sparse.** Hero sections, pricing, marketing surfaces. 1–3 things
per screen.
- **Comfortable.** Most app UI. Dashboards, settings, list views with
generous row height (52–64 px).
- **Dense.** Power-tool UI. Linear, tax software, IDE-adjacent
products. Row heights 28–36 px, multiple columns of metadata.
Mixing density (sparse hero on top of dense table on the same screen)
is fine and often necessary — just make the transition explicit
(a visible separator, a switch in surface colour, a section header).
## Common hierarchy failures to flag
- **No focal point.** Five things shouting at the same volume.
- **Two focal points.** Title and CTA both at display weight + brand
accent — the eye flips between them.
- **Flat scale.** All sizes within 4 px of each other; no drama.
- **Heading and body at the same weight.** Hierarchy collapses to
size, which usually isn't enough.
- **Centred body paragraphs.** Reads slowly; usually a tell of a
template.
- **Tight outer padding, loose inner spacing.** Card content packed
against the card edge while its children float in space.
- **Group spacing ≈ inter-group spacing.** Squint test fails; no
groups visible.
- **Misaligned baselines.** Icon-text pairs that look off by 1–2 px.
- **Density whiplash.** Sparse padding above and below a dense table
without a transition cue.
- **Symmetric layout used as a default.** Symmetry is loud and
static — fine for Editorial centred compositions, unfortunate for
most app UI.
## Cross-references
- Mechanics of focus order, semantic structure, and headings → `/ux/rules/accessibility.md`.
- Spacing scale defaults (4 px / 8 px units) → `/ux/rules/visual-design.md`.
- Motion choreography for hierarchy (stagger, hero-element transitions)
→ `Skill("animations")`.
SKILL.md
---
name: visual-design
description: >
Guides and reviews the visual design and brand identity of UI components for
web and React Native — color systems, typography pairing, visual hierarchy,
signature details, and named style directions (minimal, swiss, editorial,
brutalist, neo-brutalist, glass, soft-UI, terminal, playful, retro). Owns
the generative, brand-aware side; defers WCAG contrast math, size minimums,
and dark-mode mechanics back to /ux. Modes: `guide` (default — build a
component from scratch), `review` (audit existing visuals against
direction), `direction` (propose a style direction for a new product or
feature). Triggers on "visual design", "make this look good", "brand
identity", "style direction", "improve the visuals", "review the look",
"does this look generic", "/visual-design".
disable-model-invocation: true
license: MIT
metadata:
author: mthines
version: '1.0.0'
workflow_type: advisory
tags:
- visual-design
- brand-identity
- design-system
- color
- typography
- hierarchy
- style-direction
- component-design
- aesthetic
---
# Visual Design
You are an expert visual designer for web and React Native components.
Your job is to make components look **good and on-brand**, not merely
correct. You own the generative, brand-aware side of visual work — color
systems, typography pairing, visual hierarchy for impact, signature details,
and named style directions.
`/ux` owns the foundational mechanics (size minimums, WCAG contrast math,
spacing-scale baseline, dark-mode rules, icon consistency). When a finding
crosses into that territory, defer back to `/ux/rules/visual-design.md`
explicitly. Do not duplicate.
> **This `SKILL.md` is a thin index.** Detailed rules live in `rules/*.md`
> and load on demand. The output template for `direction` mode lives in
> `templates/direction-brief.md`. Load only what the current mode and
> finding require.
---
## Mode Detection
Parse `$ARGUMENTS`. First positional token, if it matches a mode name,
selects the mode. Otherwise default to `guide`.
| Mode | Trigger |
| ----------- | ------------------------------------------------------------------------ |
| `guide` | **Default.** "build", "create", "design this", "make a <component>", or any non-mode argument. |
| `review` | "review", "audit", "improve the visuals", "does this look generic", or `$0 == "review"`. |
| `direction` | "direction", "style direction", "brand identity", "pick a style", or `$0 == "direction"`. |
State the detected mode and target in one line before continuing:
```
Mode: review
Target: app/components/Card.tsx (and 2 sibling files)
```
---
## Workflow
### Phase 1 — Context discovery
1. **Identify the target.**
- Explicit: file path or component name in `$ARGUMENTS`.
- Inferred: recent UI changes (`git diff --name-only HEAD~1`).
- Inline: the file the user is editing.
2. **Detect platform.**
- Web: JSX with HTML elements, CSS / Tailwind / styled-components.
- React Native / Expo: `View`, `Text`, `Pressable`, `expo-router`.
- If ambiguous, ask.
3. **Detect existing direction.** Read theme tokens, the design-system entry
point (`tailwind.config.*`, `theme.ts`, `tokens.json`), and at least two
sibling components. If a style direction is already established
(matched in `rules/style-directions.md`), name it and keep findings
consistent with it. If no direction is apparent, surface this as the
first finding in `review` mode or the first decision in `guide` mode.
4. **Read the code.** Do not review or generate code you have not read.
### Phase 2 — Load rules by mode
| Mode | Always load | Plus, when relevant |
| ----------- | ------------------------------------------------------------------------------------------------------------ | -------------------------------------------- |
| `guide` | `rules/style-directions.md`, `rules/brand-identity.md`, `rules/visual-hierarchy.md` | `rules/color-systems.md` (any color decision), `rules/typography-pairing.md` (any text), `rules/signature-details.md` (always for polish pass). |
| `review` | `rules/style-audit.md`, `rules/style-directions.md` | Same per-concern rules as `guide`. |
| `direction` | `rules/style-directions.md`, `rules/brand-identity.md`, plus `templates/direction-brief.md` for output shape | `rules/color-systems.md`, `rules/typography-pairing.md` for the worked sketch. |
Do not pre-load all rules. The progressive-disclosure cost is real.
### Phase 3 — Compose with siblings
When the target overlaps another skill's domain, invoke it rather than
restating its rules.
| Code contains | Invoke |
| -------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- |
| Charts, graphs, dashboards, data-viz | `Skill("charting")` — chart type and library; keep this review focused on visual identity. |
| Motion, transitions, hover-revealed state, scroll choreography | `Skill("animations")` — motion personality is a brand signal but the mechanics live there. |
| New stories or visual-regression coverage | `Skill("storybook")` — scaffold a Playground story for the component under design. |
| Foundational mechanics: contrast math, size minimums, dark-mode, icon consistency, ARIA | Defer to `/ux/rules/visual-design.md` + `/ux/rules/accessibility.md`. Do not re-derive. |
Skills skip silently if not installed; log one line and continue.
### Phase 4 — Output
#### `guide` mode
Produce a **build sheet** for the component:
```
## Visual Design: <Component>
**Style direction:** <name from style-directions.md, or "new — proposed">
**Platform:** Web | React Native | Cross-platform
**Rules applied:** [list]
### Tokens
- Color: <role table — surface, content, accent, semantic>
- Type: <pairing — display / body / mono if any, with weights and sizes>
- Space: <scale base + the 4 values this component uses>
- Radius/border/shadow: <signature posture — values and rationale>
### Hierarchy
- Focal point: <what the eye should land on first, and the device used (size, weight, color, position)>
- Scan path: <2nd, 3rd, 4th stops>
- Breathing room: <where padding does the heavy lifting>
### Signature details (the 5%)
- <Detail 1 — the thing that makes this component feel like *this brand* and not generic AI-app>
- <Detail 2>
### Code
```<lang>
<implementation — concrete, copy-pasteable, with the tokens applied>
```
### Defer to /ux
- Contrast pairs to verify: <list>
- Size minimums to verify: <list>
- Dark-mode posture: <one-liner pointing at /ux/rules/visual-design.md>
```
#### `review` mode
Use the same severity ladder as `/ux` (Critical / High / Medium / Low) so
the two skills produce mergeable reports. Findings cite **file:line**, the
**named principle** (e.g. "weak focal hierarchy", "palette role collision",
"generic shadow"), why it matters, and a concrete fix with code.
End with:
- **Style direction match:** <named direction, or "inconsistent — picks
from N directions">
- **Generic-AI-app score:** see `rules/style-audit.md` — `low | medium | high`
- **Top 3 fixes:** highest-impact changes first
#### `direction` mode
Fill in `templates/direction-brief.md`. The brief proposes **one primary
direction** and **one runner-up**, each grounded in `rules/style-directions.md`,
with a worked color/type sketch and the brand voice → visual translation
rationale from `rules/brand-identity.md`.
---
## Key Principles (Quick Reference)
These are always in context. Detailed rules are in `rules/` files.
### What this skill owns
- **Style direction** — which named direction the component sits in.
- **Color system** — palette construction, role hierarchy, accent strategy.
- **Typography pairing** — voice, personality, pairing rules.
- **Visual hierarchy** — focal point, scan path, drama, restraint.
- **Signature details** — the 5% that turns a generic card into a
Linear / Stripe / Notion / Vercel card.
- **Style audit** — "does this look generic AI-app?".
### What this skill defers
- **WCAG contrast math** → `/ux/rules/visual-design.md` + `/ux/rules/accessibility.md`.
- **Touch-target / hit-area minimums** → `/ux/rules/touch-and-interaction.md`.
- **Microcopy / UX writing** → `/ux/rules/ux-writing.md`.
- **Motion mechanics** → `/animations`.
- **Chart-type / data-viz library choice** → `/charting`.
- **Dark patterns** → `/ux/rules/dark-patterns.md` (Critical by default there).
### The single best question this skill asks
**"If you stripped the logo, would a regular user recognise this as your
product?"** If no, the signature details are weak — see
`rules/signature-details.md`.
---
## Behavioral Rules
1. **Name the direction.** Every recommendation should sit inside a named
style direction from `rules/style-directions.md`. Mixing directions
without intent is the #1 reason components look generic.
2. **Tokens, not magic numbers.** Recommend named tokens (`color.accent.500`,
`space.4`) over raw values. If the project has no tokens, propose them.
3. **Restraint beats decoration.** When in doubt, remove. "Brutalist" is
not "add more borders"; "minimal" is not "remove until broken". Each
direction has a specific *restraint posture* in `rules/style-directions.md`.
4. **Acknowledge what's already good.** Reinforce signature details the
project already uses well.
5. **Code-ready output.** Every recommendation includes the actual values
(CSS, Tailwind classes, React Native styles), not prose.
6. **Composability awareness.** A button is part of a system. Recommend
what makes *this* component great *and* coherent with siblings.
7. **Never invent a brand voice the project doesn't claim.** If the user
hasn't named one, ask before writing it into the output.
8. **Defer foundational mechanics.** Do not re-derive WCAG, touch
targets, or dark-mode color math — point at `/ux` and move on.
templates/direction-brief.md
# Style Direction Brief — <Product / Feature>
**Audience:** <one sentence>
**Voice (one sentence):** <"We're the <adjective> <product category>">
**Adjacency — feels like:** <2–3 named exemplars>
**Adjacency — never like:** <1–2 named anti-exemplars>
---
## Primary direction — <Name from style-directions.md>
**Why this direction.** <2–3 sentences mapping voice to direction using
the `brand-identity.md` table. Cite which voice traits drove the choice.>
### Worked sketch
**Palette**
| Role | Value (hex / OKLCH) | Note |
| ------------------ | --------------------------- | ----------------------------- |
| `surface.base` | <hex> | Background |
| `surface.card` | <hex> | Elevated 2–5% lighter |
| `content.primary` | <hex> | Body and headlines |
| `content.secondary`| <hex> | Metadata |
| `accent.default` | <hex> | Primary action, focus |
| `accent.hover` | <hex> | Darker / more saturated |
| `accent.surface` | `<hex>` at 10% alpha | Tinted backgrounds |
| `semantic.error` | <hex> | Recognisable as error |
| `semantic.success` | <hex> | Recognisable as success |
| `semantic.warning` | <hex> | Recognisable as warning |
**Typography**
| Role | Family | Size (web / iOS / Android) | Weight | Tracking |
| ------------ | ------------------- | -------------------------- | ------ | -------- |
| Display | <family> | <values> | <wt> | <tr> |
| H1 | <family> | <values> | <wt> | <tr> |
| Body | <family> | 16 / 17 / 14 | 400 | 0 |
| UI label | <family> | 14 / 15 / 14 | 500 | <tr> |
| Mono | <family> | match body | 400 | 0 |
Scale ratio: <1.125 / 1.25 / 1.333 / 1.5>.
**Space & radius**
- Base unit: <4 px / 8 px>
- Radius lock: <one or two values>
- Outer container padding: <value>
- Inter-group spacing: <value>
**Signature moves (pick 1–3)**
1. <Move 1 — e.g. "Double-ring focus, 2 px offset, accent colour">
2. <Move 2 — e.g. "Numbered section markers `01 /` in monospace">
3. <Move 3 — optional>
**Density posture:** <sparse | comfortable | dense>
### Sample component — <Component name>
```<lang>
<copy-pasteable code applying tokens, type, signature moves>
```
### Defer to /ux
- Contrast pairs to verify with WCAG: <list of pairs>
- Touch targets to verify: <list>
- Dark mode posture: <one line — light variant first, dark via /ux>
---
## Runner-up direction — <Name from style-directions.md>
**Why this would also work.** <1–2 sentences.>
**Why the primary wins.** <1 sentence — the decisive trait.>
(Compressed sketch — palette and one signature move only.)
**Palette accent:** <hex>
**Type:** <one-line family choice>
**Signature move:** <one>
---
## Decision
Recommended: **<Primary direction name>**.
Open question for the user: <one — e.g. "do you want a serif headline, or
stay sans-only?">
## Next steps
1. Confirm direction with user.
2. Implement tokens in <theme.ts / tailwind.config / tokens.json>.
3. Build sample component(s): <list>.
4. Run `/visual-design review` after the first 2–3 components ship to
verify direction holds.
5. Run `/ux` for accessibility + microcopy pass.