feat: design system v1.0.0 — reconcile tokens from cross-repo audit
Extracted real production usage from 8 KDC repos and consolidated the consensus (kdcsurveyadd / kdcvault / kdc_void_planner) into the canonical design.md + tokens. Highlights: - brand.ink #000000 -> #1A1530 (purple-tinted, matches real usage) - brand.canvas #F5F4F0 -> #F7F4ED (warm) - neutral ramp rebuilt around ink (purple-tinted, not cold slate) - semantic palette retuned for warm canvas + soft tints - elevation shadows retinted with brand-ink rgb - new accent.gold (product) and accent.mint (marketing) tokens - real themes/light, themes/dark, themes/high-contrast - fleshed out every component + foundation README - docs/consolidation-2026-05.md captures the full audit + drift inventory Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,8 +1,30 @@
|
||||
# Foundations · Breakpoints
|
||||
|
||||
Reference documentation for the **breakpoints** foundation. The canonical token values
|
||||
live in [`../../design.md`](../../design.md) and the machine-readable export
|
||||
in [`../../tokens/`](../../tokens/).
|
||||
Five mobile-first breakpoints, aligned to Tailwind defaults so utility classes work without remapping.
|
||||
|
||||
This page is for human-facing rationale: when to use which token, examples,
|
||||
and platform notes.
|
||||
| Token | Min width | Use |
|
||||
|-------|-----------|-----|
|
||||
| `sm` | 640px | Larger phone / small tablet |
|
||||
| `md` | 768px | Tablet portrait |
|
||||
| `lg` | 1024px | Tablet landscape / small laptop |
|
||||
| `xl` | 1280px | Standard desktop |
|
||||
| `2xl` | 1536px | Wide desktop |
|
||||
|
||||
## App shell behaviour
|
||||
|
||||
| Width | Layout |
|
||||
|-------|--------|
|
||||
| < 768px (`md`) | Sidebar off-canvas (drawer). Top bar collapses to brand + menu icon. |
|
||||
| 768–1023px (`md`–`lg`) | Sidebar icon-only (72px). |
|
||||
| ≥ 1024px (`lg`) | Sidebar expanded (240px). |
|
||||
| ≥ 1280px (`xl`) | Optional right-rail / detail column appears. |
|
||||
|
||||
## Container
|
||||
|
||||
Max content width is 1200px, centered, with side padding of 16px (mobile) → 24px (tablet) → 32px (desktop).
|
||||
|
||||
## Rules
|
||||
|
||||
- ✅ Always mobile-first. Stack to single column below `md`; introduce side-by-side at `md`+.
|
||||
- ✅ Test the 320px width — that's the floor.
|
||||
- ❌ Don't use device-specific breakpoints (iPad, iPhone). Design for content reflow, not specific hardware.
|
||||
|
||||
@@ -1,8 +1,35 @@
|
||||
# Foundations · Colors
|
||||
|
||||
Reference documentation for the **colors** foundation. The canonical token values
|
||||
live in [`../../design.md`](../../design.md) and the machine-readable export
|
||||
in [`../../tokens/`](../../tokens/).
|
||||
Canonical values live in [`../../design.md`](../../design.md) and [`../../tokens/colors.json`](../../tokens/colors.json). This page is the human-facing rationale.
|
||||
|
||||
This page is for human-facing rationale: when to use which token, examples,
|
||||
and platform notes.
|
||||
## The system in one paragraph
|
||||
|
||||
KDC's palette is built around **Kode purple** `#6B35A7`, a **purple-tinted ink** `#1A1530` (never pure black), and a **warm off-white canvas** `#F7F4ED`. Together they give surfaces a craft / editorial feel rather than the cold slate look of generic SaaS. A muted **gold accent** `#C9892B` is reserved for emphasis CTAs in product surfaces; a **mint accent** `#46C194` is reserved for marketing surfaces. Both accents are deliberately scarce — one per surface.
|
||||
|
||||
## Layers
|
||||
|
||||
1. **Brand** — `brand.primary` and its four variants (`primaryHover`, `primaryPressed`, `primaryLight`, `primarySoft`), `brand.ink`, `brand.canvas`.
|
||||
2. **Accent** — `accent.gold` (product emphasis) and `accent.mint` (marketing).
|
||||
3. **Neutral** — a 13-step ink-tinted ramp (`neutral.0` → `neutral.1000`). Aliases: `100` ≡ `canvas`, `900` ≡ `ink`.
|
||||
4. **Semantic** — `success` `#2F7A5A`, `warning` `#C9892B`, `danger` `#B0382F`, `info` `#5C2D90`. Each has a `*Soft` tint for backgrounds.
|
||||
5. **Role tokens** — always consume `text.default`, `surface.canvas`, `border.default`, etc. in product code. Never hardcode the palette.
|
||||
|
||||
## Choosing a colour
|
||||
|
||||
- **Default text** → `text.default` (`brand.ink`). For supporting copy, `text.soft`; for meta, `text.muted`.
|
||||
- **Page surface** → `surface.canvas` (`brand.canvas`) for product UIs, `surface.background` (`#FFFFFF`) for content cards.
|
||||
- **Primary CTA** → `brand.primary` + hover `brand.primaryHover`.
|
||||
- **Emphasis CTA / commit** → `accent.gold`. Only one per surface, and only when there's a meaningful one-way action.
|
||||
- **Status pill / badge** → `semantic.{success|warning|danger}Soft` background + matching semantic text.
|
||||
|
||||
## Contrast (WCAG 2.2 AA minimums)
|
||||
|
||||
- Body text on background ≥ 4.5:1.
|
||||
- Large text (≥ 24px, or ≥ 19px bold) and UI icons ≥ 3:1.
|
||||
- `text.muted` `#6B647A` on `surface.background` `#FFFFFF` → 5.4:1 ✓
|
||||
- `brand.primary` `#6B35A7` on `surface.background` → 6.9:1 ✓
|
||||
- `accent.gold` `#C9892B` on `surface.background` → 3.0:1 — meets large-text only; pair with text labels for small UI.
|
||||
|
||||
## Drift to be aware of
|
||||
|
||||
The legacy apps (kdcdiary, kdctracker, kdcdocs, kdcmapper) currently use different purples (#6B4EFF, #A37CD9, #5567E8) and fonts (Geist, Inter+Outfit). Treat anything not in this swatch sheet as drift; new work follows the canonical palette.
|
||||
|
||||
@@ -4,24 +4,60 @@
|
||||
|
||||
| Token | Hex | Use |
|
||||
|-------|-----|-----|
|
||||
| `brand.primary` | `#6B35A7` | Kode purple — primary brand color, links, primary actions. |
|
||||
| `brand.ink` | `#000000` | Wordmark, high-emphasis text. |
|
||||
| `neutral.0` | `#FFFFFF` | Pure white — cards, modals, top-bar. |
|
||||
| `brand.canvas` | `#F5F4F0` | Brand off-white — default page background. |
|
||||
| `brand.primary` | `#6B35A7` | Kode purple — primary brand colour, links, primary actions. |
|
||||
| `brand.primaryHover` | `#5C2D90` | Hover state on `brand.primary` surfaces. |
|
||||
| `brand.primaryPressed`| `#45216E` | Pressed / deepest variant. |
|
||||
| `brand.primaryLight` | `#8456C2` | Gradient end, dark-mode primary. |
|
||||
| `brand.primarySoft` | `#F1E9F8` | Tinted surface for chips, callouts, focus halos. |
|
||||
| `brand.ink` | `#1A1530` | Brand ink — high-emphasis text. **Not** pure black. |
|
||||
| `brand.canvas` | `#F7F4ED` | Warm off-white — default page surface. |
|
||||
| `brand.canvasCool` | `#F7F6FB` | Cool off-white — marketing dashboard only. |
|
||||
| `neutral.0` | `#FFFFFF` | Pure white — cards, modals, top-bar. |
|
||||
|
||||
## Primary state ramp
|
||||
## Accent
|
||||
|
||||
| Token | Hex |
|
||||
|-------|-----|
|
||||
| `brand.primary` | `#6B35A7` |
|
||||
| `brand.primaryHover` | `#582A8D` |
|
||||
| `brand.primaryPressed` | `#45216E` |
|
||||
| Token | Hex | Use |
|
||||
|-------|-----|-----|
|
||||
| `accent.gold` | `#C9892B` | Product emphasis CTA (one per surface). |
|
||||
| `accent.goldStrong` | `#A86F1F` | Pressed / dark text on gold-soft. |
|
||||
| `accent.goldSoft` | `#F5E9D2` | Background for accent chips and warning pills. |
|
||||
| `accent.mint` | `#46C194` | Marketing accent — workspace dashboard only. |
|
||||
|
||||
## Neutral ramp (purple-tinted)
|
||||
|
||||
| Token | Hex | Role |
|
||||
|-------|-----|------|
|
||||
| `neutral.0` | `#FFFFFF` | Pure surface |
|
||||
| `neutral.50` | `#FBF8F1` | Inset / secondary surface |
|
||||
| `neutral.100` | `#F7F4ED` | = `brand.canvas` |
|
||||
| `neutral.150` | `#ECE9F3` | Cool subtle line |
|
||||
| `neutral.200` | `#E6E0D2` | Hairline border |
|
||||
| `neutral.300` | `#D4CCB8` | Strong border |
|
||||
| `neutral.400` | `#A39DB0` | Disabled / placeholder |
|
||||
| `neutral.500` | `#8C869C` | Muted meta text |
|
||||
| `neutral.600` | `#6B647A` | Mute text |
|
||||
| `neutral.700` | `#4A4360` | Soft ink |
|
||||
| `neutral.800` | `#3A2D5A` | Secondary ink |
|
||||
| `neutral.900` | `#1A1530` | = `brand.ink` |
|
||||
| `neutral.1000` | `#000000` | Pure black (sparingly) |
|
||||
|
||||
## Semantic
|
||||
|
||||
| Token | Hex | Soft tint |
|
||||
|-------|-----|-----------|
|
||||
| `semantic.success` | `#2F7A5A` | `#E2F0E8` |
|
||||
| `semantic.warning` | `#C9892B` | `#F5E9D2` |
|
||||
| `semantic.danger` | `#B0382F` | `#F7E4E1` |
|
||||
| `semantic.info` | `#5C2D90` | `#F1E9F8` |
|
||||
|
||||
## Brand-scale (Tailwind compatibility)
|
||||
|
||||
| Token | Hex |
|
||||
|-------|-----|
|
||||
| `semantic.success` | `#16A34A` |
|
||||
| `semantic.warning` | `#F59E0B` |
|
||||
| `semantic.danger` | `#DC2626` |
|
||||
| `semantic.info` | `#0EA5E9` |
|
||||
| `scale.brand-50` | `#F3EDFB` |
|
||||
| `scale.brand-100` | `#E6DAF7` |
|
||||
| `scale.brand-200` | `#F1E9F8` |
|
||||
| `scale.brand-500` | `#6B35A7` (= `brand.primary`) |
|
||||
| `scale.brand-600` | `#5D2C93` |
|
||||
| `scale.brand-700` | `#52287F` |
|
||||
| `scale.brand-800` | `#45216E` |
|
||||
|
||||
@@ -1,8 +1,27 @@
|
||||
# Foundations · Elevation
|
||||
|
||||
Reference documentation for the **elevation** foundation. The canonical token values
|
||||
live in [`../../design.md`](../../design.md) and the machine-readable export
|
||||
in [`../../tokens/`](../../tokens/).
|
||||
Five-step shadow scale tinted with the brand ink so shadows read **warm** against the canvas — not cold slate.
|
||||
|
||||
This page is for human-facing rationale: when to use which token, examples,
|
||||
and platform notes.
|
||||
## Scale
|
||||
|
||||
| Level | Shadow | Use |
|
||||
|-------|--------|-----|
|
||||
| `0` | none | Flush surfaces, page background |
|
||||
| `1` | `0 1px 2px rgba(26,21,48,0.04)` | Cards, list rows, buttons |
|
||||
| `2` | `0 4px 12px -4px rgba(26,21,48,0.08)` | Dropdowns, popovers |
|
||||
| `3` | `0 16px 40px -16px rgba(26,21,48,0.18)` | Modals, dialogs |
|
||||
| `4` | `0 24px 80px -24px rgba(26,21,48,0.22)` | Toasts, command palette |
|
||||
| `focusRing` | `0 0 0 3px rgba(107,53,167,0.18)` | Any focusable element |
|
||||
|
||||
`rgb(26 21 48)` is `brand.ink`; `rgb(107 53 167)` is `brand.primary`.
|
||||
|
||||
## Rules
|
||||
|
||||
- ✅ Treat the scale as discrete. Hover may bump elevation one step, never two.
|
||||
- ✅ Use `focusRing` consistently — never invent a per-component focus style.
|
||||
- ❌ Don't use elevation for decoration. Reserve it for hierarchy and affordance.
|
||||
- ❌ Don't use grey / black shadows; they look dirty on the warm canvas.
|
||||
|
||||
## Dark theme
|
||||
|
||||
In dark theme, elevation is communicated primarily through **lighter surface tints** rather than darker shadows. Shadows still exist but with reduced alpha (0.3–0.4 of brand.ink). See `themes/dark/theme.json`.
|
||||
|
||||
@@ -1,8 +1,23 @@
|
||||
# Foundations · Grid
|
||||
|
||||
Reference documentation for the **grid** foundation. The canonical token values
|
||||
live in [`../../design.md`](../../design.md) and the machine-readable export
|
||||
in [`../../tokens/`](../../tokens/).
|
||||
12-column responsive grid, with gutters that scale by breakpoint.
|
||||
|
||||
This page is for human-facing rationale: when to use which token, examples,
|
||||
and platform notes.
|
||||
| Breakpoint | Columns | Gutter | Margin |
|
||||
|------------|---------|--------|--------|
|
||||
| < `md` (mobile) | 4 | 16px | 16px |
|
||||
| `md` (tablet) | 8 | 24px | 24px |
|
||||
| ≥ `lg` (desktop) | 12 | 24px | 32px |
|
||||
|
||||
Max content width: **1200px**, centered.
|
||||
|
||||
## Composition
|
||||
|
||||
- **Cards** snap to multiples of 3 columns (4-up / 3-up / 2-up).
|
||||
- **Form fields** snap to multiples of 4 (full / half / third / quarter).
|
||||
- **Sidebar layouts** reserve 3 columns left (240px ≈ 3 cols at 1200px container) and 9 columns for content.
|
||||
|
||||
## Rules
|
||||
|
||||
- ✅ Use CSS Grid for page layout, Flexbox for component internals.
|
||||
- ✅ When in doubt, give content more room — KDS is generous with whitespace.
|
||||
- ❌ Don't fight the grid for visual interest. Asymmetry comes from content rhythm, not from breaking the column structure.
|
||||
|
||||
@@ -1,8 +1,43 @@
|
||||
# Foundations · Motion
|
||||
|
||||
Reference documentation for the **motion** foundation. The canonical token values
|
||||
live in [`../../design.md`](../../design.md) and the machine-readable export
|
||||
in [`../../tokens/`](../../tokens/).
|
||||
Motion is functional, not decorative — it provides feedback (state change), continuity (route / modal transitions), and confirmation (success / commit).
|
||||
|
||||
This page is for human-facing rationale: when to use which token, examples,
|
||||
and platform notes.
|
||||
## Durations
|
||||
|
||||
| Token | ms | Use |
|
||||
|-------|-----|-----|
|
||||
| `instant` | 0 | Reset / disable |
|
||||
| `fast` | 120 | Hover, focus, control state |
|
||||
| `base` | 200 | Tooltips, dropdowns |
|
||||
| `slow` | 320 | Modals, sheets, route transitions |
|
||||
| `slower` | 480 | Hero animations, marketing |
|
||||
|
||||
## Easing
|
||||
|
||||
| Token | Curve | Use |
|
||||
|-------|-------|-----|
|
||||
| `standard` | `cubic-bezier(0.2, 0, 0, 1)` | Default — most state changes |
|
||||
| `enter` | `cubic-bezier(0, 0, 0.2, 1)` | Enter-only (decelerate to rest) |
|
||||
| `exit` | `cubic-bezier(0.4, 0, 1, 1)` | Exit-only (accelerate away) |
|
||||
| `emphasis` | `cubic-bezier(0.2, 0, 0, 1.2)` | Overshoot — success, commit, attention |
|
||||
|
||||
## Signature animation
|
||||
|
||||
`kdc-fade-up` — used on the product family for content reveal:
|
||||
|
||||
```css
|
||||
@keyframes kdc-fade-up {
|
||||
from { opacity: 0; transform: translateY(6px); }
|
||||
to { opacity: 1; transform: translateY(0); }
|
||||
}
|
||||
.kdc-fade-up { animation: kdc-fade-up 360ms cubic-bezier(0.2, 0, 0, 1) both; }
|
||||
```
|
||||
|
||||
Stagger children at 40–60ms intervals.
|
||||
|
||||
## Rules
|
||||
|
||||
- ✅ Respect `prefers-reduced-motion: reduce` — collapse all transitions to ≤ 10ms.
|
||||
- ✅ Use `fast` for state, `base` for surfaces, `slow` for layout shifts.
|
||||
- ❌ Don't animate `width` / `height` — animate `transform` and `opacity`.
|
||||
- ❌ Don't bounce or spin without reason. Loading spinners are the only exception.
|
||||
|
||||
@@ -1,8 +1,28 @@
|
||||
# Foundations · Radius
|
||||
|
||||
Reference documentation for the **radius** foundation. The canonical token values
|
||||
live in [`../../design.md`](../../design.md) and the machine-readable export
|
||||
in [`../../tokens/`](../../tokens/).
|
||||
Corner radius scales with component density. Pick from the curated set — never hand-roll a value.
|
||||
|
||||
This page is for human-facing rationale: when to use which token, examples,
|
||||
and platform notes.
|
||||
## Scale
|
||||
|
||||
| Token | px | Use |
|
||||
|-------|-----|-----|
|
||||
| `none` | 0 | Resets, full-bleed images |
|
||||
| `xs` | 2 | Chips, inline tags |
|
||||
| `sm` | 4 | Inputs, small controls, tooltips |
|
||||
| `md` | 8 | Buttons, default surfaces |
|
||||
| `lg` | 12 | Cards, sections |
|
||||
| `xl` | 16 | Modals, sheets, elevated cards |
|
||||
| `2xl` | 24 | Marketing surfaces, feature panels |
|
||||
| `full` | 9999 | Pills, avatars, badges, circular buttons |
|
||||
|
||||
## Rules
|
||||
|
||||
- ✅ Match radius to size: small controls get `sm`, big surfaces get `lg`/`xl`. A 600px modal at `rounded.sm` looks broken.
|
||||
- ✅ Nested radii — the inner radius should be `outer - padding` to keep the corner concentric. Most of the time `lg` outside + `md` inside reads right.
|
||||
- ❌ Don't mix more than two radii in a single composition.
|
||||
- ❌ Don't use `full` on anything taller than 32px unless it's intentionally circular.
|
||||
|
||||
## Per-platform notes
|
||||
|
||||
- iOS: Apple's continuous corners are not directly available in CSS — accept the small perceptual difference rather than approximating.
|
||||
- Tailwind v4: bind these to `--radius-{token}` in `@theme`, e.g. `--radius-md: 8px`. The product family does this in `globals.css`.
|
||||
|
||||
@@ -1,8 +1,39 @@
|
||||
# Foundations · Spacing
|
||||
|
||||
Reference documentation for the **spacing** foundation. The canonical token values
|
||||
live in [`../../design.md`](../../design.md) and the machine-readable export
|
||||
in [`../../tokens/`](../../tokens/).
|
||||
KDS is built on a **4px base unit**. All spacing, sizing, and layout dimensions are multiples of 4.
|
||||
|
||||
This page is for human-facing rationale: when to use which token, examples,
|
||||
and platform notes.
|
||||
## Scale
|
||||
|
||||
| Token | px | rem | Use |
|
||||
|-------|-----|-----|-----|
|
||||
| `0` | 0 | 0 | Reset |
|
||||
| `1` | 4 | 0.25 | Hairline / icon-to-text |
|
||||
| `2` | 8 | 0.5 | Tight stack |
|
||||
| `3` | 12 | 0.75 | Default field-to-label |
|
||||
| `4` | 16 | 1 | Default container padding (mobile) |
|
||||
| `5` | 20 | 1.25 | Card inner gap |
|
||||
| `6` | 24 | 1.5 | Default card padding, section gap |
|
||||
| `8` | 32 | 2 | Form section separator |
|
||||
| `10` | 40 | 2.5 | Page section separator (small) |
|
||||
| `12` | 48 | 3 | Page section separator (default) |
|
||||
| `16` | 64 | 4 | Hero block padding |
|
||||
| `20` | 80 | 5 | Marketing hero |
|
||||
| `24` | 96 | 6 | Marketing hero, very generous |
|
||||
|
||||
## Density
|
||||
|
||||
Product apps expose `[data-density="compact|default|cozy"]` on the `<html>` root (see kdcmapper). Each density rebinds two CSS variables:
|
||||
|
||||
| Density | `--gap` | `--pad` |
|
||||
|---------|---------|---------|
|
||||
| compact | 12px (`3`) | 14px |
|
||||
| default | 18px | 22px |
|
||||
| cozy | 18px | 22px |
|
||||
|
||||
Use density for table-heavy / wizard-heavy screens. Don't fork component padding per screen — change density instead.
|
||||
|
||||
## Rules
|
||||
|
||||
- ✅ Always pick from the scale. If the value isn't on the scale, you're probably making the wrong choice.
|
||||
- ✅ Pair gap and padding from the same step where possible (`gap-4` inside `p-4`).
|
||||
- ❌ Don't use 1px, 3px, 5px etc. as spacing — those are border / decoration only.
|
||||
|
||||
@@ -1,14 +1,54 @@
|
||||
# Foundations · Typography
|
||||
|
||||
KDS uses two brand typefaces:
|
||||
KDS uses two brand typefaces.
|
||||
|
||||
| Family | Use | Weights |
|
||||
|--------|-----|---------|
|
||||
| **Opificio** | Wordmark and display moments only. | Bold (700) — canonical. Rounded and Regular cuts available for editorial. |
|
||||
| **Manrope** | All UI typography — headings, body, labels, captions. | 200 ExtraLight, 300 Light, 400 Regular, 500 Medium, 600 SemiBold, 700 Bold, 800 ExtraBold |
|
||||
| **Manrope** (variable) | All UI typography — headings, body, labels, captions. | 200 ExtraLight, 300 Light, 400 Regular, 500 Medium, 600 SemiBold, 700 Bold, 800 ExtraBold |
|
||||
| **Roboto Mono** *(non-brand)* | Code, tabular figures, identifiers. | 400, 500 |
|
||||
|
||||
Roboto Mono is available as a non-brand fallback for code and tabular figures.
|
||||
Manrope is loaded as a variable font via `@fontsource-variable/manrope` (product apps) or `next/font/google` (Next.js apps). Use the **Variable** build wherever possible — it lets us interpolate weight without shipping multiple files.
|
||||
|
||||
The wordmark lockup pairs them: `kode` in Opificio Bold (72pt, 52pt spacing) above `design consultants` in Manrope ExtraLight (20pt, 76pt spacing).
|
||||
## Wordmark lockup
|
||||
|
||||
Canonical token values live in [`../../design.md`](../../design.md); machine-readable typography tokens are in [`../../tokens/typography.json`](../../tokens/typography.json).
|
||||
`kode` in Opificio Bold (72pt) above `design consultants` in Manrope ExtraLight (20pt, +4% letter-spacing).
|
||||
|
||||
## Type scale (UI)
|
||||
|
||||
| Token | Family | Size | Weight | Line height | Use |
|
||||
|-------|--------|------|--------|-------------|-----|
|
||||
| `display` | Opificio | 72px | 700 | 80px | Hero / wordmark only |
|
||||
| `wordmarkSecondary` | Manrope | 20px | 200 | 28px | Wordmark second line |
|
||||
| `headingXL` | Manrope | 32px | 700 | 40px | Page hero |
|
||||
| `headingL` | Manrope | 24px | 600 | 32px | Section heading |
|
||||
| `headingM` | Manrope | 20px | 600 | 28px | Subsection / card title |
|
||||
| `headingS` | Manrope | 16px | 600 | 24px | Group label |
|
||||
| `bodyL` | Manrope | 18px | 400 | 28px | Lead paragraph |
|
||||
| `bodyM` *(default)* | Manrope | 16px | 400 | 24px | Body copy |
|
||||
| `bodyS` | Manrope | 14px | 400 | 20px | Secondary / helper |
|
||||
| `caption` | Manrope | 12px | 500 | 16px | Labels, badges, meta |
|
||||
| `mono` | Roboto Mono | 14px | 400 | 20px | Code, identifiers |
|
||||
|
||||
## OpenType features
|
||||
|
||||
Product apps enable `font-feature-settings: "ss01", "cv11"` on Manrope. These swap the default `a` and adjust the `1` / `l` for clearer numeric reading on the warm canvas. Keep them on by default — they are part of the brand voice.
|
||||
|
||||
For numerics use `font-variant-numeric: tabular-nums` (utility class `.tnum`) so columns don't jitter.
|
||||
|
||||
## Display weight
|
||||
|
||||
`.font-display` class is `Manrope 800` with `letter-spacing: -0.02em`. Use for hero headlines where Opificio would be too much.
|
||||
|
||||
## Web font delivery
|
||||
|
||||
- Self-host Manrope from `/assets/fonts/manrope/` and preload **400** + **600** in the document head.
|
||||
- Opificio is licensed; self-host from `/assets/fonts/opificio/`. Don't expose source files publicly.
|
||||
- Fallback stack: `'Manrope', -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif`.
|
||||
|
||||
## Do / Don't
|
||||
|
||||
- ✅ Default body to `bodyM` with `line-height: 1.5` for readability.
|
||||
- ✅ Use Opificio for the wordmark and nowhere else.
|
||||
- ❌ Don't mix Manrope with Geist / Inter / Outfit. The legacy apps that do so are drift to be migrated.
|
||||
- ❌ Don't justify text. Don't underline anything that isn't a link.
|
||||
|
||||
Reference in New Issue
Block a user