Saline Letter
Remix this template to create a similar design — same sections, layout, animations, colors, and typography.
A landing page for a quarterly print culinary magazine. Warm cream canvas, olive-green and tomato-red accents, Fraunces serif over Cormorant Garamond.
Palette
Typography
clamp(56px, 6vw, 104px)
clamp(48px, 6.5vw, 110px)
19px
17px
11px
11px
10px
16px
Spacing & Shape
| Token | Value | Preview |
|---|---|---|
| xs | 4px | |
| sm | 8px | |
| md | 16px | |
| lg | 24px | |
| xl | 32px | |
| 2xl | 40px | |
| section-y | 96px | |
| gutter | 32px |
Border Radius
| Token | Value | Preview |
|---|---|---|
| none | 0 | |
| sm | 2px | |
| full | 9999px |
design.md
tokens (raw)
name: saline-letter-design
version: alpha
description: >
A printed-magazine editorial system rendered on warm cream paper. The surface
is uncoated stock (#F3EDD8) carrying near-black ink (#141210); a culinary triad
of tomato red (#B82A2A), olive (#4A5A2A), and saffron (#D2A038) does all the
accenting. The voice is a high-contrast Fraunces serif display against a
Cormorant Garamond reading body, with JetBrains Mono running every eyebrow,
caption, byline, and recipe table. Signature moves: a 12-column magazine
spread, hairline rules everywhere, dashed-ink recipe cards on saffron washes,
paper grain + crosshatch textures, a smooth-scroll parallax cover, and a
drop-cap long read. Geometry is almost entirely square — sharp corners, thin
rules, full pills only for nav arrows and pantry chips.
colors:
# Surface
cream: '#F3EDD8' # page paper; primary background, light-card fill, ink-on-dark text color
cream-2: '#EAE2C8' # declared secondary cream (defined in :root; rarely applied)
# Text / Ink
ink: '#141210' # near-black headings/body on cream; also the dark inverted surface (footer, hero bundle, dark pantry cards)
body-warm: '#3a3530' # warm dark-brown for long body copy / dek paragraphs
# Brand voltages
tomato: '#B82A2A' # primary accent: italic display words, CTA button fill, dots, list markers
olive: '#4A5A2A' # secondary accent: section eyebrows, rules, progress fill, margin borders
saffron: '#D2A038' # tertiary accent: cat-italic categories, dark-surface accents, saffron washes
# Hairlines
hairline: 'rgba(20,18,16,0.18)' # 1px ink dividers, card borders, table rules
dashed-ink: 'rgba(20,18,16,0.4)' # 1.5px dashed border on recipe/callout cards
saffron-wash: 'rgba(210,160,56,0.22)' # pale saffron card fill behind dashed-ink cards
# On-dark hairline
cream-hairline: 'rgba(243,237,216,0.2)' # dividers inside ink-surface blocks
typography:
display:
fontFamily: "'Fraunces', serif"
fontSize: clamp(56px, 6vw, 104px) # hero; also fixed 6xl/3xl/2xl across headings
fontWeight: 500
lineHeight: 0.95
letterSpacing: -0.01em # tracking-tight
display-italic:
fontFamily: "'Fraunces', serif"
fontSize: clamp(48px, 6.5vw, 110px)
fontWeight: 500
fontStyle: italic # accent words colored tomato / saffron
body:
fontFamily: "'Cormorant Garamond', serif"
fontSize: 19px
fontWeight: 400
lineHeight: 1.65
body-sm:
fontFamily: "'Cormorant Garamond', serif"
fontSize: 17px
fontWeight: 400
lineHeight: 1.55
eyebrow:
fontFamily: "'JetBrains Mono', monospace"
fontSize: 11px
fontWeight: 400
letterSpacing: 0.28em
textTransform: uppercase
mono-caption:
fontFamily: "'JetBrains Mono', monospace"
fontSize: 11px
fontWeight: 400
lineHeight: 1.6
num-badge:
fontFamily: "'JetBrains Mono', monospace"
fontSize: 10px
fontWeight: 400
letterSpacing: 0.2em
cat-italic:
fontFamily: "'Fraunces', serif"
fontSize: 16px
fontWeight: 400
fontStyle: italic
letterSpacing: 0.02em # category labels, colored saffron
rounded: # almost everything is square
none: '0'
sm: '2px' # rounded-sm on dashed-ink recipe/callout cards
full: '9999px' # nav arrow buttons, pantry chips, the dot
spacing: # Tailwind 4px base unit
xs: 4px
sm: 8px
md: 16px
lg: 24px
xl: 32px
'2xl': 40px
section-y: 96px # py-24 section padding
gutter: 32px # px-8 page gutter
components:
button-primary:
backgroundColor: '{colors.tomato}'
textColor: '{colors.cream}'
typography: '{typography.eyebrow}'
rounded: '{rounded.none}'
padding: '16px 36px' # px-9 py-4
hover: 'background → ink, letter-spacing → 0.18em, 0.25s ease'
nav-link:
textColor: '{colors.ink}'
typography: '{typography.eyebrow}'
hover: 'animated underline grows 0%→100% width over 0.4s (link-underline)'
recipe-card:
backgroundColor: '{colors.saffron-wash}'
border: '1.5px dashed {colors.dashed-ink}'
rounded: '{rounded.sm}'
padding: '32px' # p-8
typography: '{typography.mono-caption}'
light-card:
backgroundColor: '{colors.cream}'
border: '1px solid {colors.hairline}'
rounded: '{rounded.none}'
padding: '24px–32px' # p-6 / p-8
hover: 'lift translateY(-6px) over 0.5s (lift)'
dark-card:
backgroundColor: '{colors.ink}'
textColor: '{colors.cream}'
rounded: '{rounded.none}'
padding: '24px–48px' # crosshatch texture on hero bundle
chip:
backgroundColor: 'transparent'
textColor: '{colors.ink}'
border: '1px solid rgba(20,18,16,0.5)'
typography: '{typography.eyebrow}'
rounded: '{rounded.full}'
padding: '6px 12px' # py-1.5 px-3
active: 'background → ink, text → cream (chip-active)'
nav-arrow:
backgroundColor: 'transparent'
border: '1px solid {colors.hairline}'
rounded: '{rounded.full}'
size: '48px' # w-12 h-12
typography: '{typography.mono-caption}'
pantry-accordion:
backgroundColor: '{colors.cream}'
border: '1px solid {colors.hairline}'
rounded: '{rounded.none}'
padding: '24px' # p-6, details/summary, chev "+" rotates 45° when open
input-search:
backgroundColor: 'transparent'
border: 'bottom 2px solid {colors.ink}'
typography: '{typography.body}'
placeholderColor: 'rgba(58,53,48,0.4)'
motion:
smooth-scroll: 'Lenis smooth wheel, duration 1.1s — drives the whole page'
read-progress: 'fixed 2px top bar, olive fill scaled by Lenis scroll progress'
parallax: 'cover images translateY by scroll-center × -0.08, 0.15s linear'
reveal: 'opacity 0→1 + translateY 28px→0, 0.9s cubic-bezier(.2,.7,.2,1), staggered by --i × 90ms'
line-mask: 'hero lines slide up from 110% translateY, 1s cubic-bezier(.2,.7,.2,1), staggered .15s'
lift: 'card translateY(-6px), 0.5s cubic-bezier(.2,.7,.2,1)'
cover-tilt: 'archive cover rotate(-1.2deg) + translateY(-4px) on hover, 0.6s'
link-underline: 'background-size 0%→100% width over 0.4s ease'
btn-hover: 'background + letter-spacing transition 0.25s'
icons:
library: inline unicode glyphs (no icon font)
style: typographic — arrows → ← ⌕ ⌘K, em-dashes, dot
sizes: { sm: 10px, md: 11px, lg: 24px }
color: '{colors.ink}'Saline Letter
saline-letter-design · alpha
Design spec — version alpha. Source: static HTML (
index.html); tokens read from inline styles +:rootvariables + class rules. Fictional/sample product ("Hearth Quarterly"); described factually.
Overview
Saline Letter is a printed culinary quarterly translated to the screen with
near-total fidelity to paper. The page is warm uncoated cream (#F3EDD8 --cream)
printed in near-black ink (#141210 --ink), and every accent comes from a
three-spice palette: tomato red (#B82A2A), olive (#4A5A2A), and saffron
(#D2A038). Type does the heavy lifting — a high-contrast Fraunces serif for
display, set medium with tight tracking and dropping to 0.95 line-height for
the giant clamp(56px, 6vw, 104px) hero; a Cormorant Garamond serif for the
generous 19px/1.65 reading body; and JetBrains Mono for every eyebrow,
folio, byline, recipe table, and price. The signature moves are unmistakably
editorial: a split 12-column magazine spread with a parallax cover, hairline
rules (rgba(20,18,16,0.18)) dividing every section, dashed-ink recipe and
callout cards floating on pale saffron washes, paper-grain and crosshatch
textures, a drop-cap long read with margin notes, a horizontal back-issue rail of
tilting covers, and a smooth Lenis scroll with a thin olive read-progress bar.
Geometry is square almost everywhere — corners are sharp (rounded-sm = 2px at
most); only nav arrows, the dot, and pantry chips go fully round.
Colors
Surface. The whole document sits on --cream #F3EDD8, an uncoated-paper
warm off-white, applied to body, all light cards, and reused as the text
color on dark surfaces. A second --cream-2 #EAE2C8 is declared in :root but
barely used in practice. The inverted surface is --ink #141210 — it powers
the footer, the hero subscription bundle, and select dark pantry cards.
Text / Ink. Headings and primary copy are --ink #141210. Long body
paragraphs and deks shift to a warmer #3a3530 brown so reading copy reads
softer than headlines.
Brand voltages. Three culinary accents share the work. --tomato #B82A2A
is the primary — it fills the CTA button, colors italic display words, the dot,
and list markers. --olive #4A5A2A is secondary — section eyebrows (§ I…§ V),
the rule-olive divider, the read-progress fill, and margin-note borders.
--saffron #D2A038 is tertiary — cat-italic categories, accents on dark
surfaces, and the fill tint behind dashed cards.
Hairlines. rgba(20,18,16,0.18) (.hairline) is the 1px rule used for every
section divider, card border, and table line. rgba(20,18,16,0.4) (.dashed-ink)
is a 1.5px dashed border for recipe/callout cards. Pale rgba(210,160,56,0.22)
saffron washes sit behind those dashed cards. On dark surfaces, dividers use
rgba(243,237,216,0.15–0.30) cream.
Typography
Three Google-Fonts families, all served from one @import. Fraunces (the
optical serif display, font-optical-sizing: auto) is the headline voice — open
substitutes are negligible since it's already open-source. Cormorant Garamond
is the reading serif body. JetBrains Mono carries all small structural text.
Display is set weight 500, tight tracking, very low line-heights (0.92–0.95);
eyebrows are 11px mono, uppercase, with wide 0.28em tracking.
| Token | Size | Weight | Line-height | Tracking | Usage |
|---|---|---|---|---|---|
| display | clamp(56,6vw,104)px | 500 | 0.95 | -0.01em | Hero & section H2/H3 |
| display-italic | clamp(48,6.5vw,110)px | 500 italic | 0.92 | -0.01em | Accent words (tomato/saffron) |
| body | 19px | 400 | 1.65 | — | Long-read reading column |
| body-sm | 17px | 400 | 1.55 | — | Deks, card paragraphs |
| eyebrow | 11px | 400 | — | 0.28em / UPPER | Section labels, nav, captions |
| mono-caption | 11px | 400 | 1.6 | — | Folios, bylines, table cells |
| num-badge | 10px | 400 | — | 0.2em | Numeric badges |
| cat-italic | 16px | 400 italic | — | 0.02em | Category labels (saffron) |
Layout
Base unit is Tailwind's 4px scale; sections are padded py-24 (96px) and the
page gutter is px-8 (32px). Content lives in a max-w-[1400px] centered
column, but the hero and the long-read body break to wider/asymmetric grids. The
hero is a 12-column spread split 6/6 (parallax cover left, editorial right,
min-h-[88vh]). The curated preview is a 3-column offset cascade (columns
staggered with mt-12/mt-24). The long read uses an asymmetric
1fr 620px 1fr grid with margin asides. Subscribe is a bento (col-span-2 row-span-2 hero bundle + two small cards). Archive is a horizontal scroll rail
of 280px covers. Whitespace is generous and rules — not boxes — do the
separating.
Elevation & Depth
This is a flat, paper-first system: there are almost no shadows. Depth comes from
hairline borders, dashed-ink cards, and texture (paper grain radial-dot
overlay at 5% opacity multiply; crosshatch repeating diagonal lines on dark
surfaces). The single real shadow is on archive covers:
0 2px 4px rgba(0,0,0,0.05), 0 8px 24px rgba(0,0,0,0.08). The full-bleed long-read
hero adds a bottom-up ink gradient scrim (rgba(20,18,16,0)→0.55) for caption
legibility. No glass/backdrop-blur anywhere.
Shapes
Overwhelmingly square. Cards, buttons, sections, inputs, and tables all have
sharp 0 corners. The only softening is rounded-sm (2px) on the dashed-ink
recipe/callout cards. Fully round (rounded-full / 9999px) is reserved for the
48px nav-arrow buttons, the 6px tomato dot, and the pantry filter chips. The
character is letterpress-precise, not soft.
Components
- button-primary (
.btn-tomato) — tomato fill, cream text, eyebrow mono, sharp corners,px-9 py-4; hover flips to ink and widens letter-spacing to 0.18em. Label e.g. "Get This Issue →", "Begin Subscription →". - nav-link (
.link-underline) — ink/tomato eyebrow text; hover grows a 1px underline from 0→100% width. e.g. "Current · Archive · Pantry · Subscribe". - recipe-card (
.dashed-ink.rounded-sm) — 1.5px dashed ink border on a pale saffron wash,p-8, mono caption + serif heading; holds gram-weighted recipe tables. e.g. "Recipe · 04 — Costoluto, raw, with bread and oil." - light-card (
.border.hairline.lift) — cream fill, 1px hairline, sharp corners,p-6/p-8; hover lifts -6px. Used for pantry tiles & subscribe minors. - dark-card — ink fill, cream text, crosshatch texture; the hero subscription bundle and editor's-pick pantry card. Huge ghost "04" at 280px / 10% opacity.
- chip (
.chip) — transparent pill, 0.5-alpha ink border, eyebrow mono;.chip-activeinverts to ink fill + cream text. e.g. "All · Herbs · Proteins". - nav-arrow — 48px round button, 1px hairline, mono "←/→" for the rail.
- pantry-accordion (
details.pantry) — hairline card; summary with mono "+" chev that rotates 45° (to ×) when open, revealing a mono recipe list. - input-search — transparent field on a 2px ink bottom-border, 24px serif, with "⌕" and "⌘K" mono affordances. Placeholder "Search 412 ingredients…".
Motion
Motion is driven by Lenis smooth scroll (duration 1.1, smooth wheel). A fixed
2px read-progress bar at the top fills olive proportional to scroll progress.
Cover images parallax (translateY by scroll-center × -0.08, 0.15s linear).
Sections reveal on intersection (opacity + 28px rise, 0.9s, staggered by
--i × 90ms). Hero headline lines do a line-mask rise from 110% translateY
(1s, staggered .15s) on load. Cards lift -6px (0.5s) and archive covers
tilt -1.2deg on hover. Buttons animate fill + letter-spacing; links animate an
underline sweep. All easings favor cubic-bezier(.2,.7,.2,1).
Iconography
There is no icon font. All "icons" are typographic unicode glyphs set in JetBrains
Mono: directional arrows (→ ← ↑), the search lozenge ⌕, the shortcut hint
⌘K, the accordion +, em-dashes as list bullets, and the tomato dot span.
Sizes follow the mono caption scale (10–11px) up to 24px for chevrons. Color is
ink, with accents picking up tomato/olive/saffron contextually. Decorative, not a
UI-control library.
Do's and Don'ts
- Do keep cream + ink as the only base; spend tomato, olive, and saffron sparingly as accent voltages.
- Do set display in Fraunces medium with tight tracking and color italic words; keep eyebrows in mono at 0.28em uppercase.
- Do divide with hairline rules and dashed cards, not drop shadows.
- Do keep corners sharp; reserve full-round only for chips, nav arrows, and the dot.
- Don't introduce soft/rounded card corners, gradients (beyond the one scrim), or glassmorphism — it breaks the printed-paper character.
- Don't mix accent colors within a single element or use them for large fills (tomato is the only large fill, on the CTA).
- Don't drop the texture (grain/crosshatch) or the mono small-caps — they are the system's editorial fingerprint.
Known Gaps
--cream-2#EAE2C8is declared in:rootbut I did not find an applied usage in the markup; documented as defined-but-near-unused.- Several alpha hairline tints on dark surfaces vary (
/.15,/.20,/.30); consolidated under a singlecream-hairlinetoken at 0.2. - Body-copy brown
#3a3530is used as a Tailwind arbitrary value, not a:rootvariable; namedbody-warmhere for the token system. - Font substitution is not needed — all three faces are open-source Google Fonts.