Vesper
Remix this template to create a similar design — same sections, layout, animations, colors, and typography.
A landing page for a studio working between image and place. Pure black canvas, soft greige type, warm tan accent, Instrument Serif over JetBrains Mono.
Palette
Typography
clamp(42px, 7vw, 96px)
clamp(36px, 4.2vw, 64px)
clamp(44px, 7.6vw, 124px)
clamp(60px, 9vw, 132px)
clamp(20px, 2.3vw, 28px)
clamp(18px, 1.4vw, 22px)
10px
11px
Spacing & Shape
| Token | Value | Preview |
|---|---|---|
| xxs | 2px | |
| xs | 4px | |
| sm | 6px | |
| md | 10px | |
| lg | 14px | |
| xl | 18px | |
| xxl | 24px | |
| pad-x | clamp(20px, 4vw, 56px) | |
| pad-y | clamp(14px, 2.2vw, 28px) |
Border Radius
| Token | Value | Preview |
|---|---|---|
| none | 0px | |
| dot | 50% |
design.md
tokens (raw)
name: vesper-design
version: alpha
description: >
Vesper is a near-black editorial portfolio for an interactive-worlds studio. A
pure-black page (`#000`) carries warm parchment text (`#e8e6e1`) and a single
amber voltage (`#d4a574`) used only as a signal — eyebrow dots, section labels,
diptych seams, hover states. The type story is a two-face pairing: an oversized
italic Instrument Serif for statements and titles against a wide-tracked,
uppercase JetBrains Mono for every label, coordinate, and caption. Signature
moves are cinematic: an animated film-grain + breathing vignette over the whole
page, a counting loader with scrambling coordinates, a Spline iframe framed by
hairline corner ticks, a scroll-bound word-by-word manifesto reveal, and an
asymmetric 12-column "plates" gallery. Geometry is uncompromisingly sharp —
zero border-radius everywhere except the small accent dots.
colors:
# Brand / Accent
accent: '#d4a574' # amber voltage — eyebrow + section dots, labels, diptych seam, hover underlines/titles, contact em
accent-soft: 'rgba(212, 165, 116, 0.18)' # ::selection background
# Surface
bg: '#000' # page background, loader, iframe backdrop
plate-art-bg: '#0a0a0a' # near-black fill behind plate artwork before image loads
# Text
ink: '#e8e6e1' # primary parchment text — wordmark, statements, titles, numbers
ink-dim: '#8a8780' # secondary — subheads, captions, medium labels, marginalia
ink-faint: '#4a4843' # tertiary — footers, counters, hairline rules, corner ticks
# Hairlines (rendered as 1px borders, not a separate token)
hairline: '#4a4843' # = ink-faint; all 1px section dividers, borders, loader bar track
# Decorative
roman-overlay: 'rgba(245, 240, 232, 0.55)' # large roman numeral over plate art
typography:
display:
fontFamily: '"Instrument Serif", "Times New Roman", serif'
fontSize: clamp(42px, 7vw, 96px)
fontWeight: 400
lineHeight: 0.98
letterSpacing: -0.015em
displayItalic:
fontFamily: '"Instrument Serif", "Times New Roman", serif'
fontSize: clamp(36px, 4.2vw, 64px)
fontWeight: 400
lineHeight: 1.04
fontStyle: italic
manifesto:
fontFamily: '"Instrument Serif", "Times New Roman", serif'
fontSize: clamp(44px, 7.6vw, 124px)
fontWeight: 400
lineHeight: 1.04
letterSpacing: -0.018em
numeral:
fontFamily: '"Instrument Serif", "Times New Roman", serif'
fontSize: clamp(60px, 9vw, 132px)
fontWeight: 400
lineHeight: 0.95
letterSpacing: -0.02em
wordmark:
fontFamily: '"Instrument Serif", "Times New Roman", serif'
fontSize: clamp(20px, 2.3vw, 28px)
fontWeight: 400
lineHeight: 1.5
letterSpacing: 0.22em
textTransform: uppercase
body:
fontFamily: '"Instrument Serif", "Times New Roman", serif'
fontSize: clamp(18px, 1.4vw, 22px)
fontWeight: 400
lineHeight: 1.45
label:
fontFamily: '"JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace'
fontSize: 10px
fontWeight: 300
lineHeight: 1.6
letterSpacing: 0.32em
textTransform: uppercase
nav:
fontFamily: '"JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace'
fontSize: 11px
fontWeight: 300
lineHeight: 1.7
letterSpacing: 0.28em
textTransform: uppercase
rounded: # near-zero radius system
none: 0px
dot: 50% # only the 6px accent dots are round
spacing: # base unit 2px; layout padding is fluid clamp()
xxs: 2px
xs: 4px
sm: 6px
md: 10px
lg: 14px
xl: 18px
xxl: 24px
pad-x: 'clamp(20px, 4vw, 56px)'
pad-y: 'clamp(14px, 2.2vw, 28px)'
components:
wordmark:
textColor: '{colors.ink}'
typography: '{typography.wordmark}'
padding: '6px 2px'
rounded: '{rounded.none}'
navLink:
textColor: '{colors.ink}'
typography: '{typography.nav}'
padding: '6px 0'
rounded: '{rounded.none}'
# underline draws on hover (currentColor, scaleX right→left)
eyebrow:
textColor: '{colors.accent}'
typography: '{typography.label}'
rounded: '{rounded.none}'
# leading 6px pulsing accent dot, border-radius 50%
cta:
textColor: '{colors.ink}'
typography: '{typography.label}'
padding: '14px 0 14px 2px'
rounded: '{rounded.none}'
# static ink underline that shifts to accent on hover; → arrow nudges 8px right
sectionLabel:
textColor: '{colors.accent}'
typography: '{typography.label}'
rounded: '{rounded.none}'
# leading 6px solid accent dot
plate:
backgroundColor: '{colors.plate-art-bg}'
rounded: '{rounded.none}'
# art frame: overflow hidden, grain overlay, top/bottom black vignette gradient, italic roman numeral bottom-left
plateTitle:
textColor: '{colors.ink}'
typography: '{typography.displayItalic}'
# shifts to accent on plate hover
plateMeta:
textColor: '{colors.ink-dim}'
typography: '{typography.label}'
numberValue:
textColor: '{colors.ink}'
typography: '{typography.numeral}'
# tabular-nums; count-up on scroll into view
contactEmail:
textColor: '{colors.ink}'
typography:
fontFamily: '"JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace'
fontSize: clamp(20px, 2.4vw, 36px)
letterSpacing: 0.02em
rounded: '{rounded.none}'
# accent underline draws on hover
loaderBar:
backgroundColor: '{colors.ink-faint}'
rounded: '{rounded.none}'
# 1px track, width min(280px, 60vw); fill is ink (#e8e6e1) gradient driven by JS
motion:
grainShift: 'film grain panned via steps(8) over 7s infinite; opacity 0.06, mix-blend overlay'
vignettePulse: 'vignette opacity breathes 0.78→0.92 over 9s ease-in-out infinite'
dotPulse: 'accent dots scale 1→0.85 / opacity 1→0.5 over 2.6s ease-in-out infinite'
closingPulse: 'closing wordmark opacity 1→0.82 + 0.6px nudge over 6s ease-in-out infinite'
loader: 'count 00→100 + bar fill over 2200ms ease-out cubic; coordinates scramble-text cycle; 1100ms fade-out'
intro: 'staged rise/wordUp keyframes after loader (is-ready); words clip-rise from translateY(110%)'
manifesto: 'scroll-bound per-word opacity 0.35→1.0 across a 250vh sticky-pinned runway'
reveal: 'opacity + translateY(22px)→0 over 1.1s ease-out; staggered r-1..r-5 (80–620ms delays)'
plate: 'fade + translateY(28px)→0 over 1s ease-out on intersection; art-img ±6% scroll parallax'
cursorParallax: 'data-parallax elements lerp toward cursor (translate3d, depth 8px/6px)'
numbers: 'count-up 1600ms ease-out cubic on scroll into view'
ease-out: 'cubic-bezier(0.22, 1, 0.36, 1)'
ease-in-out: 'cubic-bezier(0.65, 0, 0.35, 1)'
icons:
library: inline text glyphs
style: 'no icon set; → arrow glyphs for CTA/View affordances, 6px CSS accent dots'
color: '{colors.accent}'Vesper
vesper-design · alpha
Design spec — version alpha. Source: static HTML (
index.html); tokens read from inline styles + class rules. Fictional/sample product; described factually.
Overview
Vesper is a cinematic, near-black editorial site for a fictional interactive-worlds
studio. The page is pure black (#000) over which warm parchment text (#e8e6e1)
floats, with one and only one chromatic voltage — a muted amber (#d4a574) — used
sparingly as a signal: pulsing eyebrow and section dots, mono labels, the hairline
seam splitting each diptych, hover underlines, and the contact emphasis. The whole
canvas is dressed with an always-on, animated SVG film grain (opacity 0.06,
mix-blend-mode: overlay) and a slow breathing vignette, giving every screen a
darkroom texture. Typographically it is a two-voice system: an oversized italic
Instrument Serif carries the statements, plate titles, numerals and wordmark
(clamp(42px, 7vw, 96px) up to 124px for the manifesto), while a wide-tracked,
uppercase JetBrains Mono at 10–11px (letter-spacing 0.28–0.32em) handles
every label, coordinate, caption and nav item. The signature moves are a counting
loader with scrambling GPS coordinates, a Spline iframe framed by four hairline
corner ticks, a 250vh sticky-pinned manifesto whose words brighten one at a time as
you scroll, and an asymmetric 12-column gallery of five "plates." Geometry is
deliberately sharp — zero border-radius anywhere except the 6px accent dots.
Colors
Brand / Accent. A single amber voltage accent #d4a574 is the only color in the
system. It appears as the eyebrow dot and section-label dots, all mono section
labels, the 1px seam down the center of each diptych (at opacity 0.55), the CTA
and View hover underline, the plate title color on hover, the contact <em>, and
the "available" availability marker. accent-soft rgba(212,165,116,0.18) is used
only for ::selection.
Surface. The page, loader, and iframe backdrop are pure black bg #000. Plate
art frames fill with plate-art-bg #0a0a0a behind the photograph while it loads.
Text. Three warm greys form the text ladder: ink #e8e6e1 (primary — wordmark,
statements, titles, numerals), ink-dim #8a8780 (secondary — subhead, captions,
medium labels, studio marginalia), and ink-faint #4a4843 (tertiary — footers,
counters, and every hairline rule and corner tick).
Hairlines. All 1px dividers, borders, the loader-bar track, and frame ticks
reuse ink-faint #4a4843; there is no separate hairline color.
Decorative. The oversized roman numeral sitting inside each plate uses
roman-overlay rgba(245,240,232,0.55) with a soft black text-shadow.
Typography
Two webfonts loaded from Google Fonts in one request: Instrument Serif (regular
- italic) and JetBrains Mono (300/400/500). Both are open-source, so no substitution is needed; the serif falls back to Times New Roman, the mono to the system mono stack. Instrument Serif is used at large display sizes — often italic — for all editorial voice; JetBrains Mono is always small, uppercase, and widely tracked for machine-label voice (coordinates, plate numbers, nav, captions).
| Token | Size | Weight | Line-height | Tracking | Usage |
|---|---|---|---|---|---|
| display | clamp(42px, 7vw, 96px) | 400 | 0.98 | -0.015em | Hero statement lines |
| manifesto | clamp(44px, 7.6vw, 124px) | 400 | 1.04 | -0.018em | Pinned manifesto line |
| numeral | clamp(60px, 9vw, 132px) | 400 | 0.95 | -0.02em | Numbers section values |
| displayItalic | clamp(36px, 4.2vw, 64px) | 400 italic | 1.04 | — | Plate titles, works title |
| wordmark | clamp(20px, 2.3vw, 28px) | 400 | 1.5 | 0.22em | "Vesper" wordmark (uppercase) |
| body | clamp(18px, 1.4vw, 22px) | 400 | 1.45 | — | Studio statement prose |
| nav | 11px | 300 | 1.7 | 0.28em | Nav links, closing meta (uppercase) |
| label | 10px | 300 | 1.6 | 0.32em | Eyebrow, section labels, plate meta, footers (uppercase) |
The closing wordmark scales enormously: clamp(80px, 17vw, 240px) uppercase serif.
The loader count reaches clamp(56px, 9vw, 120px) italic serif with tabular nums.
Layout
Base spacing unit is effectively 2px (the smallest values are 2px/4px/6px),
but most structural padding is fluid via --pad-x: clamp(20px, 4vw, 56px) and
--pad-y: clamp(14px, 2.2vw, 28px). The hero is a full-height grid shell
(grid-template-rows: auto 1fr auto) with a three-column topbar (wordmark · edition ·
nav), a centered stage holding the Spline <iframe> in a 4/3 frame, and a
two-column footbar. Below the hero, sections live in a .page-section wrapper capped
at max-width: 1480px. The manifesto is a 250vh runway with a 100vh sticky inner
pin. Selected Works is a 12-column grid (repeat(12, 1fr)) where each of the five
plates claims a different span and internal layout (2/span 10, 1/span 8, full
bleed, 5/-1 with reversed art/meta, full-bleed centered) — a deliberately
asymmetric editorial rhythm. Studio is 3fr 7fr 3fr with a two-column serif body;
Numbers is repeat(4, 1fr); Contact is 6fr 5fr. Whitespace is generous and
vertical, with clamp() row gaps up to 180px between plates.
Elevation & Depth
There is essentially no shadow-based elevation — the system is flat and depth comes
from layered fixed overlays and hairlines. The two global layers are a fixed film
grain (z-index 50, opacity 0.06, overlay blend) and a fixed vignette
(z-index 40, radial darkening to rgba(0,0,0,0.55) at the edges). Each plate has
its own internal grain (opacity 0.02, screen blend) plus a top-and-bottom black
linear-gradient mask fading the artwork into the page. The only text-shadow is on the
roman numeral (0 0 16px rgba(0,0,0,0.45)). Separation between sections is done with
1px ink-faint borders, not shadows.
Shapes
Uncompromisingly rectangular. Every surface — frames, plates, the iframe, the loader
bar — has border-radius: 0. The only round elements are the 6px status/eyebrow/
section dots (border-radius: 50%). Framing is done with hairlines instead of fills:
the hero frame gets four 18px border corner ticks (ink-faint), and diptychs are
split by a 1px amber seam. This sharpness is the brand.
Components
- Wordmark — serif uppercase
ink, tracking0.22em, padding6px 2px; hover/ hold (1.6s) reveals a hidden mono coordinate line inaccent. - Nav link — mono
11pxuppercaseink, tracking0.28em; underline draws on hover (currentColor, scaleX right→left, 520ms). - Eyebrow — mono
10pxuppercaseaccentwith a leading 6px pulsing accent dot. - CTA "Step inside →" — mono
11pxuppercaseink; persistentinkunderline that recolors toaccenton hover;→arrow nudges +8px right. - Section label — mono
10pxuppercaseaccentwith a leading solid 6px accent dot. - Plate —
#0a0a0aart frame, no radius, internal grain + top/bottom black gradient mask; large italic serif roman numeral bottom-left (roman-overlay); meta block in mono labels with serif italic title; on hover the title and "View →" turnaccentand the View underline draws. - Number — large serif
numeralvalue (tabular nums, counts up on scroll), mono index ("I."), mono uppercase label above a1pxtop rule; the open "∞" item drops its rule and turns the labelaccent. - Contact email — mono
clamp(20px,2.4vw,36px), accent underline draws on hover. - Loader bar — 1px
ink-fainttrack,min(280px,60vw)wide; fill is aninkgradient driven by JS as the count climbs 00→100.
Motion
Motion is constant but restrained and atmospheric. Always-on ambient loops: grainShift
(7s steps-8 grain pan), vignettePulse (9s opacity breath), dotPulse (2.6s on accent
dots), and closingPulse (6s on the closing wordmark). The intro is a staged sequence:
a counting loader (2200ms, ease-out cubic) with scramble-text coordinates and a fading
bar, then is-ready triggers rise / wordUp keyframes — the hero words clip-rise from
translateY(110%). Scroll work uses Lenis smooth scroll (duration 1.2): the manifesto
binds per-word opacity (0.35→1.0) to scroll progress across its 250vh sticky pin;
sections and plates fade-and-rise via IntersectionObserver with staggered r-1..r-5
delays; plate images drift ±6%; and the Numbers count up over 1600ms. The hero also has
cursor parallax — data-parallax elements lerp toward the pointer with per-element depth.
Easing is two curves: --ease-out cubic-bezier(0.22,1,0.36,1) and --ease-in-out cubic-bezier(0.65,0,0.35,1). No prefers-reduced-motion block is present (a comment
marks where one would go).
Iconography
There is no icon library. Affordance arrows are literal → text glyphs (CTA, plate
"View"). The recurring graphic mark is the 6px CSS circle in accent (eyebrow, section
labels, contact availability) which pulses. Framing marks (corner ticks, diptych seam)
are CSS borders, not icons.
Do's and Don'ts
- Do keep the page pure black and use amber
#d4a574only as a signal — never as a fill. - Do pair oversized italic Instrument Serif with tiny wide-tracked uppercase JetBrains Mono.
- Do keep every corner sharp (
border-radius: 0); reserve50%for the 6px dots only. - Do frame with hairlines (corner ticks, seams,
1pxrules inink-faint) rather than shadows. - Do keep grain + vignette on; they are the darkroom signature.
- Don't introduce a second accent color or saturate the amber.
- Don't add drop shadows, glows, or rounded cards — depth comes from grain, vignette, and gradient masks.
- Don't set mono text without uppercase + wide tracking, or let serif body text go below ~
17px. - Don't make the layout symmetric — the plate grid's asymmetry is the editorial point.
Known Gaps
- Spacing scale is inferred from the small literal values (
2/4/6/10/14/18/24px); the template mostly uses fluidclamp()padding andclamp()gaps rather than a fixed token scale. - The loader bar fill color is set inline by JS as a
linear-gradientbetween#e8e6e1and#4a4843; documented here as anink→ink-faintfill. - Body weight is recorded as 400 for Instrument Serif (the face ships a single weight);
the
html/bodydefaultfont-weight: 300applies to the mono stack. - All photographic plate content is remote (CloudFront) and the hero is a remote Spline scene; only the surrounding chrome tokens are documented.