Design system

slow editorial · print-led · warm restraint · craft modernism · unhurried

The whole identity rests on one warm neutral doing three different jobs — ground, panel and rule — so the lone terracotta accent lands like a signature instead of a style.

This document is one part of a Taste Lens read. Every read also includes the eight-perspective analysis, copy-paste style prompts with flavors for Midjourney, Stable Diffusion and DALL·E, and exports for AI tools & mood boards (AI brief, palette card, style page) as well as code & design apps (shadcn, Tailwind, CSS, JSON, .ASE swatches, Figma tokens).

01 · Colour roles

bg#f4efe6Page ground
surface#e9e2d3Raised panels
ink#221d15Primary text
dim#8a8171Secondary text
accent#b3502dAction + emphasis
line#dbd6cdBorders, rules

Accent ramp

50
100
200
300
400
500
600
700
800
900

Shareable palette card

palette card

Download SVG card  ·  Download .ase swatches — imports into Photoshop, Illustrator, Procreate

02 · Contrast — WCAG 2.1

PairingRatioVerdict
Body text on page 14.62:1 AAA
Body text on surface 12.98:1 AAA
Secondary text on page 3.36:1 AA large only
Secondary text on surface 2.98:1 FAIL
Accent text on page 4.47:1 AA large only
Page on accent (buttons) 4.47:1 AA large only
Border against page 1.26:1 LOW

03 · Typography

Crimson Text — display

Old-style serif with warmth and personality for branding; narrower tracking and tight leading enforce modernist formality against its humanist curves.

Inter — body

Quiet, neutral sans that disappears in long measure; generous line-height enforces slow reading pace and print-like generosity.

Modular scale · ratio 1.25 · base 16px

display49px · 600 Decode why it works
3xl39px · 600 Decode why it works
2xl31px · 600 Decode why it works
xl25px · 600 Decode why it works
lg20px · 400 Decode why it works
base16px · 400 Decode why it works
sm13px · 400 Decode why it works
xs10px · 400 Decode why it works

04 · Spacing — 8px base

space-18px
space-216px
space-324px
space-432px
space-648px
space-864px
space-1296px
space-16128px
space-24192px

05 · Geometry & motion

Letterpress rigour demands square corners and no shadow depth; hairline rules inherit print's structural authority; 8px spacing clips to an invisible eighth-inch grid.

Radiussquare · 0px
Border0.5px
Elevationnone
Motion400ms · cubic-bezier(0.4, 0.0, 0.2, 1)

Slow cubic easing mirrors the unhurried reading pace; 400ms is felt but never announces itself, matching the sub-perceptual texture approach.

06 · Components

button_style: outlined — Outlined terracotta border with no fill; text in the accent colour; monocase labels in smallcaps; on hover fill the interior with a 10% tint of terracotta to match the restraint.

That key wasn't recognised.

Hairline cream border on the surface colour, no shadow; label above in body serif at the secondary value; cursor and focus state only add a terracotta underline, never a box around the field.

tokensfigmacss

Card title sits here

Supporting copy in the secondary tone, one step down the scale.

Cream background with a hairline rule below instead of a border; 3% opacity fibre noise visible only where the panel edge meets the background; generous internal padding enforces the print broadsheet …

07 · Rules

Do

  • Run the left margin nearly a third of the viewport width and allow the right edge to rag — asymmetry creates active tension.
  • Let the cream neutral carry all structural work via value alone; terracotta touches only interactive moments so attention lands exactly where it is spent.
  • Use hairline rules at 0.5px to separate panels and divide space, never drop shadows or tonal gradients.
  • Stack display in the old-style serif for personality and body in the quiet sans; let type character do hierarchy work instead of size alone.

Don't

  • Centre the layout or distribute margins equally — the tension lives in the imbalance.
  • Add colour to anything but moments of action; every accent spend must justify itself against the rest.
  • Introduce rounded corners, glass effects, or any depth simulation — they break the honest flat print metaphor.
  • Animate anything that counts, slides, or blinks; withhold urgency to signal the studio's confidence that it does not need to chase.

08 · Tokens

CSS custom properties

:root{
  --bg: #f4efe6;
  --surface: #e9e2d3;
  --ink: #221d15;
  --dim: #8a8171;
  --accent: #b3502d;
  --line: #dbd6cd;
  --accent-50: #f9f1ee;
  --accent-100: #f3e3dd;
  --accent-200: #e7c7bc;
  --accent-300: #d7a492;
  --accent-400: #c57a5f;
  --accent-500: #b3502d;
  --accent-600: #964326;
  --accent-700: #7a361f;
  --accent-800: #5a2817;
  --accent-900: #3d1b0f;
  --radius: 0px;
  --shadow: none;
  --space-0: 0px;
  --space-1: 8px;
  --space-2: 16px;
  --space-3: 24px;
  --space-4: 32px;
  --space-6: 48px;
  --space-8: 64px;
  --space-12: 96px;
  --space-16: 128px;
  --space-24: 192px;

  --font-display: Crimson Text, Georgia, serif;
  --font-body: Inter, -apple-system, BlinkMacSystemFont, sans-serif;
  --font-mono: IBM Plex Mono, Menlo, monospace;
  --weight-display: 600;
  --weight-body: 400;
  --leading-display: 1.2;
  --leading-body: 1.7;
  --tracking-display: −0.02em;
  --tracking-body: 0em;

  --text-xs: 10px;
  --text-sm: 13px;
  --text-base: 16px;
  --text-lg: 20px;
  --text-xl: 25px;
  --text-2xl: 31px;
  --text-3xl: 39px;
  --text-display: 49px;
}

/* Text styles — size, family, weight and leading together */
.text-xs{font:400 10px/1.7 Inter, -apple-system, BlinkMacSystemFont, sans-serif;letter-spacing:0em}
.text-sm{font:400 13px/1.7 Inter, -apple-system, BlinkMacSystemFont, sans-serif;letter-spacing:0em}
.text-base{font:400 16px/1.7 Inter, -apple-system, BlinkMacSystemFont, sans-serif;letter-spacing:0em}
.text-lg{font:400 20px/1.7 Inter, -apple-system, BlinkMacSystemFont, sans-serif;letter-spacing:0em}
.text-xl{font:600 25px/1.2 Crimson Text, Georgia, serif;letter-spacing:−0.02em}
.text-2xl{font:600 31px/1.2 Crimson Text, Georgia, serif;letter-spacing:−0.02em}
.text-3xl{font:600 39px/1.2 Crimson Text, Georgia, serif;letter-spacing:−0.02em}
.text-display{font:600 49px/1.2 Crimson Text, Georgia, serif;letter-spacing:−0.02em}

Components — CSS

This is the exact CSS rendering the components above. Paste it after the custom properties.

/* Buttons */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:var(--space-2);
  border:var(--border) solid transparent;border-radius:var(--radius);
  padding:var(--space-1) var(--space-3);cursor:pointer;
  font:var(--weight-body) var(--text-sm)/1 var(--font-body);
  transition:background var(--duration) var(--easing),color var(--duration) var(--easing)}
.btn--primary{background:transparent;color:var(--accent);border-color:var(--accent)}
.btn--primary:hover{background:var(--accent);color:#ffffff}
.btn--secondary{background:transparent;color:var(--ink);border-color:var(--line)}
.btn--secondary:hover{border-color:var(--ink)}
.btn--ghost{background:transparent;color:var(--dim);border-color:transparent}
.btn--ghost:hover{color:var(--ink)}
.btn:disabled{opacity:.42;cursor:not-allowed;filter:none}

/* Form field */
.field{display:block}
.field__label{display:block;margin-bottom:var(--space-1);
  font:600 var(--text-xs)/1 var(--font-body);color:var(--ink)}
.field__input{width:100%;padding:var(--space-1) var(--space-2);
  border:var(--border) solid var(--line);border-radius:var(--radius);
  background:var(--bg);color:var(--ink);font:var(--text-sm)/1 var(--font-body)}
.field__input::placeholder{color:var(--dim)}
.field__input:focus{outline:2px solid var(--accent);outline-offset:1px;border-color:var(--accent)}
.field__input[aria-invalid="true"]{border-color:var(--accent)}
.field__error{margin-top:var(--space-1);color:var(--accent);font-size:var(--text-xs)}

/* Card */
.card{background:var(--surface);border:var(--border) solid var(--line);
  border-radius:var(--radius);padding:var(--space-3);box-shadow:var(--shadow)}
.card__title{margin:0 0 var(--space-1);font:var(--weight-display) var(--text-lg)/1.3 var(--font-display)}
.card__body{margin:0;color:var(--dim);font:var(--text-sm)/1.6 var(--font-body)}

/* Tag */
.tag{display:inline-block;background:var(--accent-100);color:var(--accent-800);
  border-radius:var(--radius);padding:2px var(--space-1);
  font:600 var(--text-xs)/1.5 var(--font-mono)}

Tailwind — merge into theme.extend

{
  "colors": {
    "bg": "#f4efe6",
    "surface": "#e9e2d3",
    "ink": "#221d15",
    "dim": "#8a8171",
    "accent": {
      "50": "#f9f1ee",
      "100": "#f3e3dd",
      "200": "#e7c7bc",
      "300": "#d7a492",
      "400": "#c57a5f",
      "500": "#b3502d",
      "600": "#964326",
      "700": "#7a361f",
      "800": "#5a2817",
      "900": "#3d1b0f",
      "DEFAULT": "#b3502d"
    },
    "line": "#dbd6cd"
  },
  "borderRadius": {
    "DEFAULT": "0px"
  },
  "fontFamily": {
    "display": [
      "Crimson Text"
    ],
    "body": [
      "Inter"
    ],
    "mono": [
      "IBM Plex Mono"
    ]
  },
  "fontSize": {
    "xs": [
      "10px",
      {
        "lineHeight": "1.7",
        "letterSpacing": "0em",
        "fontWeight": "400"
      }
    ],
    "sm": [
      "13px",
      {
        "lineHeight": "1.7",
        "letterSpacing": "0em",
        "fontWeight": "400"
      }
    ],
    "base": [
      "16px",
      {
        "lineHeight": "1.7",
        "letterSpacing": "0em",
        "fontWeight": "400"
      }
    ],
    "lg": [
      "20px",
      {
        "lineHeight": "1.7",
        "letterSpacing": "0em",
        "fontWeight": "400"
      }
    ],
    "xl": [
      "25px",
      {
        "lineHeight": "1.2",
        "letterSpacing": "−0.02em",
        "fontWeight": "600"
      }
    ],
    "2xl": [
      "31px",
      {
        "lineHeight": "1.2",
        "letterSpacing": "−0.02em",
        "fontWeight": "600"
      }
    ],
    "3xl": [
      "39px",
      {
        "lineHeight": "1.2",
        "letterSpacing": "−0.02em",
        "fontWeight": "600"
      }
    ],
    "display": [
      "49px",
      {
        "lineHeight": "1.2",
        "letterSpacing": "−0.02em",
        "fontWeight": "600"
      }
    ]
  },
  "fontWeight": {
    "display": "600",
    "body": "400"
  },
  "letterSpacing": {
    "display": "−0.02em",
    "body": "0em"
  },
  "spacing": {
    "0": "0px",
    "1": "8px",
    "2": "16px",
    "3": "24px",
    "4": "32px",
    "6": "48px",
    "8": "64px",
    "12": "96px",
    "16": "128px",
    "24": "192px"
  },
  "boxShadow": {
    "DEFAULT": "none"
  }
}

shadcn/ui + Tailwind v4 — globals.css

The shadcn variable theme and the v4 @theme mapping in one file. Dark theme is derived — treat it as a starting point.

/* Taste Lens — shadcn/ui theme (+ Tailwind v4 @theme)
   Vibe: slow editorial, print-led, warm restraint, craft modernism, unhurried
   Drop into your globals.css. Dark theme is derived from the light read — tune it. */

:root {
  --radius: 0.5rem;
  --background: #f4efe6;
  --foreground: #221d15;
  --card: #e9e2d3;
  --card-foreground: #221d15;
  --popover: #e9e2d3;
  --popover-foreground: #221d15;
  --primary: #b3502d;
  --primary-foreground: #ffffff;
  --secondary: #e9e2d3;
  --secondary-foreground: #221d15;
  --muted: #e9e2d3;
  --muted-foreground: #8a8171;
  --accent: #f3e3dd;
  --accent-foreground: #5a2817;
  --destructive: #b3261e;
  --border: #dbd6cd;
  --input: #dbd6cd;
  --ring: #b3502d;
}

.dark {
  --background: #1a1610;
  --foreground: #f4efe6;
  --card: #25221c;
  --card-foreground: #f4efe6;
  --popover: #25221c;
  --popover-foreground: #f4efe6;
  --primary: #b3502d;
  --primary-foreground: #ffffff;
  --secondary: #25221c;
  --secondary-foreground: #f4efe6;
  --muted: #25221c;
  --muted-foreground: #aba69d;
  --accent: #5a2817;
  --accent-foreground: #f3e3dd;
  --destructive: #e5484d;
  --border: #3a3731;
  --input: #3a3731;
  --ring: #b3502d;
}

/* Tailwind v4 — exposes the variables above as color utilities (bg-background, …) */
@theme inline {
  --color-background: var(--background);
  --color-foreground: var(--foreground);
  --color-card: var(--card);
  --color-card-foreground: var(--card-foreground);
  --color-popover: var(--popover);
  --color-popover-foreground: var(--popover-foreground);
  --color-primary: var(--primary);
  --color-primary-foreground: var(--primary-foreground);
  --color-secondary: var(--secondary);
  --color-secondary-foreground: var(--secondary-foreground);
  --color-muted: var(--muted);
  --color-muted-foreground: var(--muted-foreground);
  --color-accent: var(--accent);
  --color-accent-foreground: var(--accent-foreground);
  --color-destructive: var(--destructive);
  --color-border: var(--border);
  --color-input: var(--input);
  --color-ring: var(--ring);
  --radius-sm: calc(var(--radius) - 4px);
  --radius-md: calc(var(--radius) - 2px);
  --radius-lg: var(--radius);
}

Tokens Studio for Figma

{
  "global": {
    "color": {
      "bg": {
        "value": "#f4efe6",
        "type": "color"
      },
      "surface": {
        "value": "#e9e2d3",
        "type": "color"
      },
      "ink": {
        "value": "#221d15",
        "type": "color"
      },
      "dim": {
        "value": "#8a8171",
        "type": "color"
      },
      "accent": {
        "value": "#b3502d",
        "type": "color"
      },
      "line": {
        "value": "#dbd6cd",
        "type": "color"
      },
      "accent-ramp": {
        "50": {
          "value": "#f9f1ee",
          "type": "color"
        },
        "100": {
          "value": "#f3e3dd",
          "type": "color"
        },
        "200": {
          "value": "#e7c7bc",
          "type": "color"
        },
        "300": {
          "value": "#d7a492",
          "type": "color"
        },
        "400": {
          "value": "#c57a5f",
          "type": "color"
        },
        "500": {
          "value": "#b3502d",
          "type": "color"
        },
        "600": {
          "value": "#964326",
          "type": "color"
        },
        "700": {
          "value": "#7a361f",
          "type": "color"
        },
        "800": {
          "value": "#5a2817",
          "type": "color"
        },
        "900": {
          "value": "#3d1b0f",
          "type": "color"
        }
      }
    },
    "fontFamilies": {
      "display": {
        "value": "Crimson Text",
        "type": "fontFamilies"
      },
      "body": {
        "value": "Inter",
        "type": "fontFamilies"
      },
      "mono": {
        "value": "IBM Plex Mono",
        "type": "fontFamilies"
      }
    },
    "fontWeights": {
      "display": {
        "value": "600",
        "type": "fontWeights"
      },
      "body": {
        "value": "400",
        "type": "fontWeights"
      },
      "regular": {
        "value": "400",
        "type": "fontWeights"
      }
    },
    "fontSize": {
      "xs": {
        "value": "10",
        "type": "fontSizes"
      },
      "sm": {
        "value": "13",
        "type": "fontSizes"
      },
      "base": {
        "value": "16",
        "type": "fontSizes"
      },
      "lg": {
        "value": "20",
        "type": "fontSizes"
      },
      "xl": {
        "value": "25",
        "type": "fontSizes"
      },
      "2xl": {
        "value": "31",
        "type": "fontSizes"
      },
      "3xl": {
        "value": "39",
        "type": "fontSizes"
      },
      "display": {
        "value": "49",
        "type": "fontSizes"
      }
    },
    "lineHeights": {
      "xs": {
        "value": "17",
        "type": "lineHeights"
      },
      "sm": {
        "value": "22",
        "type": "lineHeights"
      },
      "base": {
        "value": "27",
        "type": "lineHeights"
      },
      "lg": {
        "value": "34",
        "type": "lineHeights"
      },
      "xl": {
        "value": "30",
        "type": "lineHeights"
      },
      "2xl": {
        "value": "37",
        "type": "lineHeights"
      },
      "3xl": {
        "value": "47",
        "type": "lineHeights"
      },
      "display": {
        "value": "59",
        "type": "lineHeights"
      }
    },
    "letterSpacing": {
      "display": {
        "value": "−0.02em",
        "type": "letterSpacing"
      },
      "body": {
        "value": "0em",
        "type": "letterSpacing"
      }
    },
    "typography": {
      "xs": {
        "value": {
          "fontFamily": "Inter",
          "fontWeight": "400",
          "fontSize": "10",
          "lineHeight": "17",
          "letterSpacing": "0em"
        },
        "type": "typography"
      },
      "sm": {
        "value": {
          "fontFamily": "Inter",
          "fontWeight": "400",
          "fontSize": "13",
          "lineHeight": "22",
          "letterSpacing": "0em"
        },
        "type": "typography"
      },
      "base": {
        "value": {
          "fontFamily": "Inter",
          "fontWeight": "400",
          "fontSize": "16",
          "lineHeight": "27",
          "letterSpacing": "0em"
        },
        "type": "typography"
      },
      "lg": {
        "value": {
          "fontFamily": "Inter",
          "fontWeight": "400",
          "fontSize": "20",
          "lineHeight": "34",
          "letterSpacing": "0em"
        },
        "type": "typography"
      },
      "xl": {
        "value": {
          "fontFamily": "Crimson Text",
          "fontWeight": "600",
          "fontSize": "25",
          "lineHeight": "30",
          "letterSpacing": "−0.02em"
        },
        "type": "typography"
      },
      "2xl": {
        "value": {
          "fontFamily": "Crimson Text",
          "fontWeight": "600",
          "fontSize": "31",
          "lineHeight": "37",
          "letterSpacing": "−0.02em"
        },
        "type": "typography"
      },
      "3xl": {
        "value": {
          "fontFamily": "Crimson Text",
          "fontWeight": "600",
          "fontSize": "39",
          "lineHeight": "47",
          "letterSpacing": "−0.02em"
        },
        "type": "typography"
      },
      "display": {
        "value": {
          "fontFamily": "Crimson Text",
          "fontWeight": "600",
          "fontSize": "49",
          "lineHeight": "59",
          "letterSpacing": "−0.02em"
        },
        "type": "typography"
      }
    },
    "spacing": {
      "0": {
        "value": "0",
        "type": "spacing"
      },
      "1": {
        "value": "8",
        "type": "spacing"
      },
      "2": {
        "value": "16",
        "type": "spacing"
      },
      "3": {
        "value": "24",
        "type": "spacing"
      },
      "4": {
        "value": "32",
        "type": "spacing"
      },
      "6": {
        "value": "48",
        "type": "spacing"
      },
      "8": {
        "value": "64",
        "type": "spacing"
      },
      "12": {
        "value": "96",
        "type": "spacing"
      },
      "16": {
        "value": "128",
        "type": "spacing"
      },
      "24": {
        "value": "192",
        "type": "spacing"
      }
    },
    "borderRadius": {
      "DEFAULT": {
        "value": "0",
        "type": "borderRadius"
      }
    },
    "boxShadow": {
      "DEFAULT": {
        "value": "none",
        "type": "boxShadow"
      }
    }
  }
}

09 · The eight perspectives

Where this system comes from. Every decision above traces back to one of these readings.

01

Print logic, rendered on a screen

Medium & Technique

The site behaves like a letterpress broadsheet — flat ink on warm paper, hairline rules doing the structural work, zero gradients or glass.

Why it works Borrowing print's physics gives every element a reason to sit where it sits; nothing floats, so nothing feels arbitrary.

02

One warm neutral doing three jobs

Color & Palette

A single cream family carries ground, panels and dividers through value shifts alone; terracotta appears only at moments of action.

Why it works When the neutral does the structural work, the one saturated colour reads as a decision rather than decoration — attention goes exactly where it is spent.

03

A wide left margin is the grid

Composition & Layout

Every block hangs from one hard left axis with a margin nearly a third of the viewport; the right edge is allowed to rag.

Why it works The exaggerated asymmetry creates tension a centred layout can't — the whitespace is an active shape, not leftover space.

04

Paper grain you feel, not see

Texture & Surface

A faint fibre noise sits under everything at maybe 3% opacity — visible only where panels meet, like stock showing at a cut edge.

Why it works Sub-perceptual texture keeps large flat fields from going sterile while never announcing itself as an effect.

05

Swiss discipline, softened by craft

Style & Movement

Modernist grid rigour and mono labels meet a humanist serif and hand-drawn underlines — system and hand in the same frame.

Why it works The tension between mechanical structure and human gesture is the studio's whole argument: slow, considered, made by people.

06

Quiet authority, zero urgency

Mood & Atmosphere

Nothing blinks, slides or counts down; generous line-height and long measure invite reading at a walking pace.

Why it works Withholding urgency signals confidence — a studio that doesn't chase you reads as one that doesn't need to.

07

The serif is the identity

Typography & Graphics

An old-style serif at display sizes does the branding; body text steps down to a quiet sans, and mono smallcaps handle wayfinding.

Why it works Giving one face all the personality and keeping the others silent produces hierarchy through character, not just size.

08

Flat daylight, shadows banned

Light & Space

There is no simulated depth anywhere — no drop shadows, no elevation; separation is done entirely with rules and value steps.

Why it works Refusing depth keeps the page honest to its print metaphor and makes the few tonal shifts read clearly as structure.