Design system · Foundations

Tokens & type

Design system / Foundations / 01
Ground truth · landing-veille-taste-real.html
Target viewport 1440 × 900

Everything below is the warm-cream editorial genre reduced to its parts: fifteen colours, eight state constants that are borders and fills only, three faces, one microlabel, one hairline. Screens recombine these; a hex that is not listed on this page does not ship until it is. Contrast figures on this page are measured from the hex values under WCAG 2.1 — every market figure is sample data and is chipped.

01

Palette

15 tokens · click a swatch to copy its hex

Cream paper, ink text, one gold accent. Never pure #000, never a glow, never a gradient used as decoration. Gold is a mark colour — dots, hairlines, the t-zero rule — and only becomes text at its darker cut.

Grounds
Rules
Ink & text
Accent
Prints
Measured contrast — every text token on every ground

WCAG 2.1 relative-luminance ratios computed from the hex values above. AA ≥ 4.5 (any size) · LG ≥ 3.0 (large text ≥ 24px, or ≥ 18.7px semibold) · NO below 3.0 (marks and decoration only).

Token on --paper on --card on --tan on --ink
--ink 13.10 AA 14.24 AA 11.56 AA 1.00 NO
--micro-c 8.28 AA 9.00 AA 7.31 AA 1.58 NO
--ink-2 6.87 AA 7.47 AA 6.06 AA 1.91 NO
--body-c 5.49 AA 5.97 AA 4.85 AA 2.39 NO
--mute 3.35 LG 3.64 LG 2.96 NO 3.91 LG
--gold-text 3.67 LG 3.99 LG 3.24 LG 3.57 LG
--gold 1.93 NO 2.10 NO 1.71 NO 6.78 AA
--pos 5.52 AA 5.99 AA 4.87 AA 2.38 NO
--neg 6.95 AA 7.55 AA 6.13 AA 1.89 NO
--paper (reversed) 1.00 NO 1.09 NO 1.13 NO 13.10 AA

Three consequences, and they are binding. --mute is not a text colour at 10–13px: it may label an axis or repeat a breadcrumb, but the value itself — the n included — is --ink or --ink-2. --gold-text is large text only: 3.67:1 means 24px and up, or 18.7px semibold, so nothing smaller on any screen is set in it; where a small label wants a gold cue it takes a gold dot or a gold border instead. --body-c on --tan is 4.85 — it clears AA, but with no headroom, so do not tint it further.

State constants — the eight hexes that are not palette colours

Borders and fills only. None of them ever carries text, so none has a ratio to clear. They are listed because the fifteen above are a closed set: a screen that needs a hex which is not on this page adds it here first, with its role, before it ships.

TokenHexWhere it is painted
--line-box#C4BBA8The 1px box around the rail's TERMINAL tag
--line-gold#C3B79AThe SAMPLE chip border — gold's cue at chip size, since gold cannot be the letters
--line-hover#B9AE97A swatch's border on hover
--line-dark#1B1815.btn-line border
--fill-hover#D9D2C3The sign-out pill on hover
--fill-dark#17150F.btn-dark fill — paper on it measures 13.10:1
--fill-dark-h#37322A.btn-dark on hover
--fill-line-h#D6CEBE.btn-line on hover

Two gaps, stated rather than hidden. Charts paint their hexes literally — an SVG presentation attribute takes no variable — so every hex in the inline SVG in section 07 is one of the fifteen above, checked by hand rather than enforced by the cascade. Foundations 02 · Components paints three hexes that are not listed here: #6B6459 and #CBC3B2, which the landing declares as --mute-2 and --rule-tan, and #E3DDD1, a table-row hover. They belong in this inventory. Until they are in it, that card is out of contract — the gap is the card's, not a licence.

02

Type ramp

3 faces · sizes at 1440px · every figure below is sample data Sample

Cormorant Garamond 500 carries every display and headline. Archivo carries body and UI. JetBrains Mono carries microlabels, chips and every number. A fourth face is a defect. Clamped sizes are annotated with their computed value at a 1440px viewport. The specimen strings are invented — the percentages, the dates, the n — and are here to show a face at a size, nothing else. The one figure that is not sample data is 72,036, the classified-event count carried over from the landing.

News moves markets
Display — landing hero only Cormorant Garamond 500
clamp(54px, 5.2vw, 84px) = 74.9px
line-height 1.04 · tracking −.015em
Markets overview
Page title — terminal header row Cormorant Garamond 500
clamp(28px, 2.2vw, 38px) = 31.7px
line-height 1.12 · tracking −.01em
This has happened before.
Section headline Cormorant Garamond 500
clamp(34px, 3.4vw, 51px) = 49.0px
line-height 1.10
Rank-1 precedent, 9 June 1982
Panel headline Cormorant Garamond 500
clamp(22px, 1.8vw, 27px) = 25.9px
line-height 1.30
72,036
Serif statistic Cormorant Garamond 500 · 34px
font-variant-numeric: tabular-nums
white-space: nowrap
A piece of news, the daily closes around it, and the measured move that followed.
Lede Archivo 400 · 16.5px
line-height 1.66 · colour --ink-2
max-width 760px · text-wrap: pretty
Running prose inside a section. Two sentences is usually the limit before a panel does the work better.
Body Archivo 400 · 15px
line-height 1.60 · colour --body-c
max-width 820px
Brent crude · front month
Table label Archivo 500 · 13.5px
line-height 1.45 · colour --ink
row padding 16px / 24px
+2.41%  −0.87%  1,204.50  n = 21
Numeric JetBrains Mono 400 · 13px
tracking .02em · tabular-nums
every number in the system, without exception
Precedent matching
Microlabel JetBrains Mono 400 · 11px
tracking .17em · uppercase
colour #3E3A33 (--micro-c)
Archive query · 16 Mar 2022 · USD / yen
Microlabel, muted JetBrains Mono 400 · 10.5px
tracking .15em · uppercase
colour --mute · context only, never a value
Sanctions action Sample
Chip JetBrains Mono 400 · 10px
tracking .14em · uppercase
padding 3px 7px 2px · 1px --rule border
Open the terminal
Button label JetBrains Mono 500 · 12px
tracking .13em · uppercase
.btn-sm drops to 11.5px
VEILLE Terminal
Wordmark — rail head Cormorant Garamond 600 · 26px · tracking .15em
tag: JetBrains Mono 400 · 9px · .16em
boxed 1px #C4BBA8 · gap 10px
03

Microlabel & kicker anatomy

The single most repeated unit in the system

The kicker is a 5px gold dot, a 9px gap, then a microlabel. It sits above every section headline and above the rail's nav. It is the only place gold appears at the top of a block, so it does the whole job of saying "a new thing starts here" — which is why no rule or box is needed above it.

Kicker — at size
Precedent matching

This has happened before.

Dot 5 Gap 9 Kicker → headline 24
Specification
  • 01Dot: 5 × 5px, border-radius:50%, background:var(--gold), flex:0 0 auto. Never any other size.
  • 02Row: display:flex; align-items:center; gap:9px. The 9px gap is a fixed constant, off the 4px spacing scale — do not round it to 8.
  • 03Label: mono 11px / .17em / uppercase in #3E3A33. The muted variant drops to 10.5px / .15em in --mute.
  • 04Headline follows at 24px. On the landing the kicker also opens the ink closer, where the label colour becomes rgba(226,220,208,.62).
  • 05Choosing between the two: --mute for context that repeats (a date already in the row, an axis unit); #3E3A33 or --ink-2 when the microlabel is the only place the fact appears.
04

Spacing scale

4px grid · 12 steps · 2 fixed exceptions

A 4px grid. Where the shell contract gives a range, the scale picks the single value so that screens agree: panel padding is 24px (contract 18–24), table rows are 16px vertical / 24px horizontal (contract 14–18 vertical).

Steps and their contracted use
--s1 · 4Chip inner top/bottom · gap between a sign and its number
--s2 · 8Stat-row gap · label to value inside one cell · swatch caption lead
--s3 · 12Button gap · rail nav vertical padding · panel title to subtitle
--s4 · 16Table row vertical padding · gap between elements inside a panel
--s5 · 20Page-title block to the header hairline · legend to chart
--s6 · 24Panel padding · table row horizontal padding · gap between panels in a row · kicker to headline
--s7 · 32Gap between a header's title and its right-aligned status
--s8 · 40Stacked panels inside one page section · type-ramp column gap
--s9 · 56Between page sections · content-area left/right padding
--s10 · 72Landing section padding on a phone
--s11 · 96Bottom of a terminal page · landing hero top padding
--s12 · 128Landing closer only — too much air for a terminal screen

The two exceptions, both fixed constants: the kicker dot gap is 9px and the rail nav padding is 12px 22px. Both are inherited from the landing and are not negotiable per-screen.

05

Hairlines

Structure comes from rules, never from shadow

Nothing in this system floats. There are no shadows, no rounded corners except the sign-out pill and the kicker dot, and no borders thicker than 2px. If a thing needs separating, it gets a hairline.

Rule inventory
1px --rule Panel border, rail right edge, section top, table header underline. The default.
1px --rule-2 Interior of a --card only: row rules, stat dividers, chart legend tops.
2px --rule Landing section boundaries and the sticky nav. The terminal does not use it — inside the shell a 2px rule reads as a heading.
1px --gold The t-zero hairline in a chart, and the 56px mark above a closer. Gold rules are always short or always vertical — never a full-width gold divider.
2px --gold, left The active rail item, and nothing else. This is how a screen says where you are.
1px --rule on --card A data panel. Border and fill always travel together — a --card with no border is a mistake.
06

Prints, chips, buttons

Every figure below is sample data

Positive and negative prints carry a sign as well as a colour, so the table still reads with the colour removed. Both clear AA on cream and on card. Gold never prints a move — a gold figure is a similarity or a rank, never a return.

Sample
Print colours in situ

Fabricated rows, shown to fix the table idiom: Archivo 500 labels, mono tabular numbers, 1px --rule-2 row rules, 16/24px padding.

Instrument t+1 t+20 Window
Brent crude+2.41%+5.08%n = 21 closes
S&P 500−1.86%−4.30%n = 21 closes
USD / yen−0.72%+1.14%n = 21 closes
Gold+0.95%+2.67%n = 21 closes
Positive #2E5E3F · 5.99:1 on card Negative #7A2C25 · 7.55:1 on card
Chips and buttons

Chips label; buttons act. A chip is never clickable and a button never carries a value.

Rate decision Sanctions action Energy Sample

The SAMPLE chip sits at the panel's top-right, 24px in from both edges. It is a disclosure, so it has to be legible on its own terms: ink-2 letters at 7.47:1, inside a gold hairline border. Gold is the border and not the type, because gold type at 10px measures 3.99:1 and fails. Any panel showing invented figures carries one — see the table to the left, and the head of section 02.

Dark fill #17150F · paper text 13.10:1 Line 1px #1B1815 · hover fill #D6CEBE
07

Chart idiom

Inline SVG only · no canvas · no libraries

Every chart in this system is hand-built inline SVG: an ink path at 1.5–2px, a gold vertical hairline at t-zero, a --rule baseline, and mono axis labels in --mute. Nothing is filled, nothing is gridded beyond the zero line.

Sample
Event-study panel

Rebased to the close before the event. Sample path, plausible magnitudes only.

0 −10% t₀ +5 +10 SESSIONS
Path ink #191714 · 2px t₀ hairline gold · 1.2px n = 21 closes · t₀ to +20
Sample
Sparkline — inline in a row

The same idiom shrunk: no axis, no labels, keep the gold t-zero and the marker dot so the reader still knows where the event sits.

RuleValue
Path stroke, panel chart#191714 · 2px
Path stroke, sparkline#191714 · 1.5px
Second path (precedent)#8A6A33 · 1.5px
Baseline / zero rule#CDC5B4 · 1px
Axis labelsmono 10px · #7C7566
Colliding labeldropped within 13px of zero
08

Shell contract

This page is the specimen — the rail on the left is the contract

Every screen file in this system reproduces the rail and the header row exactly, so that two screens opened side by side agree. The rail on the left of this page is not a picture of the contract; it is the contract, and screens should copy its markup.

Left rail — fixed
Width248px, fixed, full height
Ground / edge--paper · 1px --rule right
WordmarkCormorant 600 · 26px · .15em
Tagmono 9px boxed · "TERMINAL"
Kicker"The instrument set"
Nav itemmono 10.5px · 12px 22px
Active item--ink · 2px gold left rule
Inactive item--mute
Footemail mono 10px · pill "Sign out"

Nav order is fixed: Markets, Charts, News, Analogues, Backtest, Datasets, Economist, Logbook, Account.

Content area
Offset / paddingmargin-left 248px · 34/56/96px
Header rowserif title + right mono status
Header rule1px --rule below, 20px gap
Section gap56px · 1px --rule top
Panel--card · 1px --rule · 24px
Table row16px / 24px · 1px --rule-2
Target viewport1440 × 900 minimum
Motiongated in prefers-reduced-motion
Selectiongold ground, ink text

Grain is one fixed overlay at opacity .05, mix-blend-mode:multiply, z-index:80, copied verbatim from the landing. It is optional per screen but must not be re-tuned.

09

What this system refuses

Read this before adding anything
  • 01Pure #000, glows, drop shadows, and gradients used as decoration. Ink is #191714; depth comes from a hairline.
  • 02A fourth typeface, or a serif used for UI, or a sans used for a headline.
  • 03Gold #C0995D as text on cream — 1.93:1. --gold-text is the only text cut, and only at 24px and up; below that gold is a mark — a dot, a hairline, a border — never letters.
  • 04A number that is not mono and not tabular-nums.
  • 05An invented figure presented as a product statistic. Sample data is allowed and expected on mocks — it must carry the SAMPLE chip, and any statistic must show its n.
  • 06Canvas, charting libraries, external images, or motion that runs regardless of prefers-reduced-motion.
Veille design system · Foundations 01 · Tokens & type Tokens lifted from landing-veille-taste-real.html
Contrast measured under WCAG 2.1 · market figures are sample data