Coffee Roastery

# Bloom — Design System
## Concept
Most of the trade writes coffee down as a spec sheet: cold numbers, clinical
tables. Bloom does the opposite. It treats a roastery the way a literary
publication treats its subject — warm cream pages, a serif display voice, and
long editorial breathing room — and then, when precision matters, it shows the
work as *code*. Brew recipes and roast profiles are set in a dark, monospaced
"recipe window," the way a developer tool shows a real code block instead of a
marketing illustration of one. Grams, degrees, seconds, ratios: honest data,
rendered honestly.
The name is **Bloom** — the moment ground coffee first meets water and swells,
releasing gas. It is the gentle, considered, human beat in an otherwise
technical craft, and it sets the register: warm and literary on the surface,
exact underneath. Warmth comes from the cream canvas, the serif headlines, and
sparing copper; rigor comes from the monospace data and the disciplined
cream-to-dark band rhythm.
The register is editorial, not lifestyle. No latte-art romance, no
smiling-customer stock. The story is the coffee — where it grew, how it was
roasted, exactly how to brew it — told well.
## Palette
| Token | Hex | Role |
| ------------------------ | --------- | -------------------------------------------------------------- |
| `--canvas` | `#faf9f5` | Tinted cream. Page floor, dominant surface. Never pure white. |
| `--surface-soft` | `#f5f0e8` | Soft band background, quiet dividers. |
| `--surface-card` | `#efe9de` | Cream feature/info cards. One step darker than canvas. |
| `--surface-cream-strong` | `#e8e0d2` | Emphasized bands, active tabs. |
| `--roast` | `#181715` | Warm near-black. Dark bands, recipe windows, footer. |
| `--roast-elevated` | `#252320` | Elevated cards / secondary buttons inside dark bands. |
| `--roast-soft` | `#1f1e1b` | Inner code block inside a recipe window. |
| `--ember` | `#cc785c` | Roasted-copper coral. Primary CTA + full-bleed callouts only. |
| `--ember-active` | `#a9583e` | Press / active variant of ember. |
| `--ink` | `#141413` | Headlines, primary text. Warm off-black. |
| `--body-strong` | `#252523` | Lead paragraphs, emphasis. |
| `--body` | `#3d3d3a` | Default running text. |
| `--muted` | `#6c6a64` | Sub-heads, breadcrumbs, secondary labels. |
| `--muted-soft` | `#8e8b82` | Captions, fine print, code line numbers. |
| `--hairline` | `#e6dfd8` | 1px borders on cream surfaces. |
| `--hairline-soft` | `#ebe6df` | Barely-visible in-band dividers. |
| `--on-dark` | `#faf9f5` | Cream-tinted text on dark surfaces (echoes the canvas). |
| `--on-dark-soft` | `#a09d96` | Secondary text in dark bands and recipe windows. |
| `--teal` | `#5db8a6` | Recipe-window syntax: units and comments. Scarce. |
| `--amber` | `#e8a55a` | Optional inline highlight / roast-level cue. Scarce. |
Rules:
- Cream dominates. `--ember` never exceeds roughly 5% of any viewport; it is
scarce on individual elements and generous only on a full-bleed callout.
- No gradients anywhere. No box shadows. Depth comes from the cream-vs-dark
surface contrast and 1px hairlines.
- Never two consecutive bands on the same surface. The page alternates:
cream -> cream-card -> dark -> cream -> ember-callout -> dark-footer.
- Inside recipe windows, color is meaning, not decoration: keys stay
`--on-dark`, numeric values go `--ember`, units and comments go `--teal`.
## Typography
Three faces, three jobs. All self-hosted woff2 under `assets/fonts/` via
`@font-face`; no font CDN.
- **Display — Cormorant Garamond** 500, letter-spacing `-0.02em`. The literary,
considered voice: page titles, section headlines, origin names, large numbers
in callouts. Never bold (500, never 700). Negative tracking is non-negotiable
— Cormorant without it reads generic. At most one display-XL headline per
viewport.
- **Body / UI — Inter** 400 and 500. Humanist, plain, legible. Body, nav,
buttons, badges, captions. Sentence case.
- **Data — JetBrains Mono** 400. Every brew parameter, roast spec, line number,
and eyebrow label. This is the "recipe as code" mechanism. Eyebrow labels are
uppercase with `0.12em` tracking.
Type scale (desktop / mobile):
| Role | Desktop | Mobile | Face |
| ---------- | -------------- | ------------- | ------------------ |
| Display XL | 64px / 1.05 | 40px / 1.08 | Cormorant 500 |
| Display L | 48px / 1.1 | 34px / 1.12 | Cormorant 500 |
| Display M | 34px / 1.15 | 27px / 1.2 | Cormorant 500 |
| Display S | 27px / 1.2 | 24px / 1.25 | Cormorant 500 |
| Title | 18px / 1.4 | 17px / 1.4 | Inter 500 |
| Body | 17px / 1.6 | 16px / 1.6 | Inter 400 |
| Data | 14px / 1.6 | 13px / 1.6 | JetBrains Mono 400 |
| Label | 12px / 1.4 | 12px / 1.4 | JetBrains Mono 400 |
Display letter-spacing: XL `-1.5px`, L `-1px`, M `-0.5px`, S `-0.3px`. Labels
`+0.12em`. Body and title tracking is 0.
## Spacing & layout
- 4px base unit. Section padding 96px top/bottom desktop, 64px mobile.
- Content max-width 1200px, 12-column grid, 24px gutters.
- Editorial left-alignment throughout. Centered text only inside the ember
callout band.
- Hero and story bands use a 6/6 split (headline left, artifact right),
collapsing to single column on mobile — text first, artifact below.
- Border radius: `md` 8px (buttons, inputs, badges' square kin), `lg` 12px
(all cards + recipe windows), `xl` 16px (hero artifact container), `pill`
9999px (badges). Images sit in `lg`/`xl` rounded containers.
- Section dividers are 1px `--hairline` rules; occasionally annotated with a
small mono label sitting on the rule.
## Signature
Two elements carry the identity. Both are direct translations of the reference's
own signatures into coffee.
### 1. The bloom mark
A small inline-SVG glyph: three concentric rings with a center dot, seen from
above — coffee blooming in a pour-over cone. It anchors the wordmark
("[bloom-mark] First Crack") in the nav and footer, and appears once, larger, as
a quiet section ornament. Drawn in `--ink` on cream, `--on-dark` on dark. This
is our own coffee-native mark — not a borrowed logo.
### 2. The recipe window
The load-bearing component. Any parametric data — brew guides, the roasting
process, the roast schedule — is rendered as a dark editor "window," the way a
developer tool shows real code:
- `--roast` card, rounded `lg`, with a title bar carrying a mono filename
(`pour-over.brew`, `espresso.brew`, `roast.log`) at left and a small
three-dot cluster at right.
- Inner block on `--roast-soft`, gutter of line numbers in `--muted-soft`,
content in JetBrains Mono.
- Syntax coloring is semantic: parameter keys `--on-dark`, numeric values
`--ember`, units + `#` comments `--teal`.
Example (pour-over):
```
# First Crack pour-over
dose = 15 g
water = 250 g @ 94 °C
grind = medium-fine
time = 3:00 total
ratio = 1:16.7
```
Example (espresso):
```
# First Crack espresso
dose = 18 g in
yield = 36 g out
time = 28 s
temp = 93 °C
ratio = 1:2
```
The recipe window is where the design earns its concept; it should feel exact
and a little bit code, surrounded by warm editorial calm.
## Components
- **Nav.** Cream top bar, 64px, 1px bottom hairline. Bloom mark + "First Crack"
wordmark left (Cormorant 500, small). Page links right in Inter 500 14px
(Beans, Visit). Primary ember "Order beans" button at the far right. Active
page gets a 2px ember underline and `aria-current="page"`.
- **Buttons.** Primary: solid `--ember` fill, white text, 8px radius, Inter 500;
active darkens to `--ember-active`. Secondary: `--canvas` fill, `--ink` text,
1px hairline border. On dark bands the secondary becomes `--roast-elevated`
fill with `--on-dark` text (never inverts to a light button on dark).
- **Text link.** Inline `--ember` link, underline on hover — the one small place
copper appears in running text.
- **Origin comparison card.** The three origins presented as a comparison triad
(like a model/pricing lineup). `--canvas` fill, 1px hairline, rounded `lg`,
32px padding. Serif origin name (Display M), a roast-level badge pill, tasting
notes in body, and a mono micro-row for process/elevation. The house origin
(San Agustin, medium) is **featured**: its surface flips to `--roast` with
`--on-dark` text — the dark surface is the featured signal.
- **Feature / info card.** `--surface-card` fill, rounded `lg`, 32px padding.
Used for visit info (address, hours, cupping).
- **Badge pill.** `--surface-card` fill, `--ink` text, Inter caption, pill
radius, 4x12px. Roast-level pills read `LIGHT ROAST` / `MEDIUM ROAST` /
`DARK ROAST` in mono label style; no color-coding beyond the label to keep
ember scarce.
- **Recipe window.** As specified in Signature.
- **Ember callout band.** Full-bleed `--ember` card, white text, rounded `lg`,
48px padding, centered. Carries a Display S serif line and an inverted cream
button. The copper surface is the voltage — the CTA lives here.
- **Footer.** Full-width `--roast`, `--on-dark-soft` text, bloom mark + wordmark
in `--on-dark`, column links. The footer never inverts to cream.
## Motion
One orchestrated moment: on load, the hero bloom mark's three rings expand
outward once over 1.2s (scale + fade), settling into place; the hero recipe
window's first line may fade in just after. Nothing else animates except hover
transitions (100ms ease-out on color and underline). Under
`prefers-reduced-motion: reduce`, everything renders complete with no animation.
## Image treatment
Warm and editorial, used sparingly — the recipe windows carry the "product
chrome" load, so photography stays a supporting voice. Natural diffuse daylight,
tones harmonized toward cream, copper, and roast-brown. Close, considered
compositions: the bloom in the cone, green beans in the hand, the cooling tray,
the cupping table, the room. Images sit in rounded `lg`/`xl` containers with no
filters or overlays. No latte-art, no smiling-customer cafe stock, no
white-marble flat lays.
Needed images: a hero roasting/pour moment, a sourcing image, one per origin
(Yirgacheffe, San Agustin, Kerinci), a roasting-process image, and for About a
space image and a cupping-table image.
## Do / Don't
Do:
- Anchor every page on the cream canvas. Pure white or cool gray reads as any
other tool; the warm tint is the brand.
- Use Cormorant serif for every display headline, with negative tracking.
- Keep ember scarce on individual elements; spend it generously only on the
full-bleed callout.
- Render every brew parameter and roast spec inside a recipe window, in
JetBrains Mono. Set every inline number in mono too.
- Alternate cream and dark bands; let the contrast do the pacing.
- Anchor the wordmark with the bloom mark.
Don't:
- No pure-white or cool-gray canvas; no cream-to-terracotta drift.
- No bold serif — Cormorant stays 500, never 700.
- No coral scattered as decoration; no coral text outside links and callouts.
- No Inter (or any sans) for display headlines.
- No two consecutive bands on the same surface.
- No gradients, no box shadows, no radius above 16px.
- No emoji. No decorative icons doing a label's job.
- No latte-art lifestyle photography.