Documentdocs/BRAND-GUIDELINES.md
SurveyStream — Master Brand Guidelines
| Document | Master Brand Guidelines |
| Version | 1.0 |
| Date | 2026-08-26 |
| Status | Approved for internal use; four decisions open (§6) |
| Owner | Brand & Design |
| Supersedes | Brand Reference v1.0 (strategy only) |
| Machine-readable sources | color-system/tokens.json · typography/type-tokens.json · logo/metrics.json |
Every measurement, ratio and colour value in this document is generated from the token files listed above. Where a number appears here it is the same number the code ships. If the two ever disagree, the token files win and this document is stale.
Contents
- Brand Strategy & Core Thesis
- Logo & Mark System
- Colour Architecture & Specifications
- Typography & Numerical Hierarchy
- Visual Assets, Patterns & Stationery
- Governance, Open Decisions & Known Limits
1. Brand Strategy & Core Thesis
1.1 Mission, Vision, Positioning
Mission To turn everyday opinions into data people can act on — and to pay for them the moment they land.
Vision A market where every decision made on survey data can be traced back to a real, verified, fairly-paid human voice.
Positioning statement
SurveyStream turns everyday opinions into high-integrity, real-time data — paying people the moment their voice moves markets.
Essence: Flowing Trust.
1.2 The core thesis
The brand lives where two truths meet. Opinions must move effortlessly — speed, liquidity, reward. Data must be absolutely trustworthy — integrity, verification, real-time fidelity. Most survey brands pick one. The entire advantage is refusing to.
The word doing the strategic work is “Stream”: continuous, live, directional, alive. Not a pool, not a panel, not a bank. A stream never stops moving.
Design DNA — structure holds the frame; flow moves within it. A disciplined grid with a streaming, transformative element passing through it. Reserve the “magic” for one hero moment per surface, never everywhere.
1.3 Archetype blend
Order first, wonder second. A trust business must lead with credibility — a brand that feels too magical reads as “too good to be true,” which is fatal both to a payout promise and to a data-quality claim.
| Archetype | Role | Governs | Contribution | |
|---|---|---|---|---|
| Primary | The Ruler | The Precision Engine | Demand side, the brand’s spine | Order from chaos, guaranteed quality, enterprise credibility. What makes an aggregator wire real budget through the pipe. |
| Secondary | The Magician | The Transformer | Supply side, the brand’s spark | Ordinary opinion into instant reward; scattered voices into coherent market signal. Wonder, momentum, “how did that happen so fast.” |
Translation to design
| Force | Expression |
|---|---|
| Ruler → structure | Strong baseline grid, stable geometry, generous negative space, a deep authoritative anchor colour, typography with architectural backbone. |
| Magician → flow | A single luminous accent that shows state changing — opinion → payout, input → signal. One expressive gradient or motion, held in reserve. |
| The blend | Rigid container, liquid content. |
1.4 Dual-audience value pillars
One visual system, two calibrated dialects. Warm and rewarding for the supply side; rigorous and enterprise-grade for the demand side — without ever fracturing into two brands.
| Survey Takers — Supply · B2C | Enterprise Aggregators — Demand · B2B | |
|---|---|---|
| Value proposition | Get paid fast for opinions you already have. Frictionless earning, near-instant payout, no minimum-threshold games. | A live, high-integrity data feed you can build on. Real-time delivery, fraud-screened respondents, verifiable provenance, auditable dashboards. |
| Emotional hook | Empowered momentum. “My voice has value — and I feel it land immediately.” Counters the industry’s default suspicion with felt reliability. | Confident control. “I can finally trust the pipe — and stop babysitting the data.” Authority through clarity. |
| Tone of voice | Warm, direct, energising, plainspoken. Second person. Short sentences. Zero jargon. | Precise, measured, credible, quietly confident. Evidence over adjectives. Never breathless. |
| Sounds like | “Answer. Submit. Get paid. That’s the whole thing.” | “Continuous data. Verified sources. Full-stream visibility.” |
| Permitted accents | Stream, Signal, Payout | Stream, Signal, Current |
| Tempo | Brighter accent, faster motion | Cooler palette, slower motion, more whitespace |
The bridging rule
Both audiences are sold the same underlying property — integrity of flow — expressed in their own currency. The taker experiences it as “I get paid what I was promised, instantly.” The aggregator experiences it as “every data point is real, sourced, and live.” Never let the two dialects contradict each other on fairness, speed, or truth.
1.5 Personality guardrails
Five dials, calibrated on purpose rather than centred. Check every artefact against these before it ships.
| Spectrum | Position | Implication |
|---|---|---|
| Approachable ←→ Corporate | 4 / 10 | Leans approachable, still credible. Rounded-but-not-soft geometry, open letterforms, friendly line-height. Warmth in the copy, backbone in the layout. Avoid childish rounding and sterile rigidity alike. |
| Playful ←→ Precise | 7 / 10 | Precise-leaning with sanctioned play. Grid-true, data-driven layouts. Play is permitted only in motion and the accent moment — never in structural type or the numbers. |
| Energetic ←→ Calm | 5 / 10 | The audience-tunable dial. Taker surfaces push energetic; enterprise surfaces push calm. Same system, different tempo. |
| Transparent ←→ Guarded | 2 / 10 | Aggressively transparent — the ethical core. Show payout status, data provenance, real-time counters. Live indicators, visible timestamps, honest empty states. No dark patterns, ever. |
| Human ←→ Systematic | 5 / 10 | The deliberate 50/50, and the whole thesis. Human voices running through a systematic pipe. Pair organic marks with engineered ones. Never fully humanise, never fully systematise. |
1.6 Tone of voice
Copy is design material. Active voice, specific over clever, transparency over hype — the same rules that govern the visuals govern the words.
| Do | Don’t |
|---|---|
| Lead with the concrete outcome — “Paid in minutes,” “99.9% verified respondents.” | Hype that reads “too good to be true.” It kills trust on both sides. |
| Plain second person for takers; evidence and metrics for aggregators. | Jargon or fine-print games in front of survey takers. |
| Name a control by what it does, then confirm it happened: Cash out → Paid. | Breathless, exclamation-heavy tone on enterprise surfaces. |
| Show the live state: counters, timestamps, provenance. | Dark patterns, hidden thresholds, vague error states. |
| Keep sentences short. Let whitespace carry the calm. | Letting warmth (Payout) shout over integrity (Stream). |
The one-line test
Does this feel like flowing trust — structured enough for an enterprise buyer, rewarding enough for a survey taker, and honest enough to prove it?
If a choice cannot be traced to a personality dial (§1.5) or the archetype blend (§1.3), it is decoration, not brand.
2. Logo & Mark System
2.1 Construction
The mark is two tangent elliptical arcs — there is no freehand curve anywhere in it.
| Parameter | Value |
|---|---|
| Bowl radii | rx 30 / ry 20 |
| Bowl centres | (0, −20) and (0, +20), tangent at the origin |
| Arc sweep | 230° each, from −38° to −268° |
| Base stroke | 12 units, round caps |
| Aspect ratio | 0.7826 (width ÷ height) |
| Curve encoding | Elliptical arc commands; the 600×140 cut uses exact arc→cubic conversion, α = 4/3·tan(Δt/4), three spans per bowl |
rx > ry is load-bearing. Circular bowls produce an S with a 0.50 aspect, which reads spindly
beside a Bold wordmark. Elliptical bowls give 0.7826 — what a bold grotesk S
actually measures.
The tangent point is where the stroke hands off from one bowl to the other, and it is the only moment of complexity in an otherwise plain figure: the Magician’s spark held inside the Ruler’s grid.
2.2 The wordmark
| Property | Value |
|---|---|
| Typeface | Archivo Bold |
| Delivery | Outlined paths, not live text — every file renders identically with no font installed, no webfont request, no substitution risk |
| Tracking | -0.04em |
| Cap height | 68.6 units |
| Wordmark width | 635.4 units |
| Two-tone split | After “Survey”: Ink #04171F then Current #0A6E86 |
| Kerning | Archivo’s GPOS pair kerning applied where defined. Exactly one pair fires on this string (re, −10 units) |
2.3 Lockups
| Lockup | File | Use |
|---|---|---|
| Primary horizontal | logo/lockup-horizontal.svg | The default. Transparent ground, two-tone wordmark. |
| Horizontal on white | logo/lockup-horizontal-on-white.svg | Over imagery — carries an opaque white plate. |
| Horizontal reversed | logo/lockup-horizontal-reversed.svg | Dark grounds. Mist wordmark, Signal second half. |
| Horizontal mono | logo/lockup-horizontal-mono.svg | One colour via currentColor. Mark stroke thickened to hold. |
| Vertical / stacked | logo/lockup-stacked.svg | Narrow columns, square placements, avatars with room for the word. |
| Standalone monogram | logo/icon.svg | The Stream monogram alone. Full colour with pulse trail. |
| Monogram mono | logo/icon-mono.svg | currentColor, no trail. |
| Monogram reversed | logo/icon-reversed.svg | On Deepwater. |
| App icon | logo/app-icon.svg | 512 px, rounded-rect Deepwater ground. iOS / Android / PWA. |
| Favicon 32 / 16 | logo/favicon-32.svg, logo/favicon-16.svg | Trail removed, stroke thickened. |
| Wordmark alone | logo/wordmark.svg | Where the mark already appears nearby. |
| Construction diagram | logo/construction.svg | Documentation only. Never ship. |
2.4 Lockup geometry — all ratios expressed in cap heights
The wordmark’s cap height is the single unit of measure for the whole system. Every relationship below scales with it, so the lockup can be reproduced at any size without a lookup table.
| Rule | Value | Rationale |
|---|---|---|
| Mark height | 1.38 × cap height | Taller than the caps so the mark reads as a sibling of the word, not a letter inside it. |
| Gap, mark → wordmark | 0.46 × cap height | Tight enough to read as one object; wide enough that the monogram does not collide with the S of “Survey”. |
| Vertical alignment | Mark’s optical centre on the cap-height centre | Not the baseline. The mark has no baseline; aligning to one makes it sit low. |
| Clear space | 0.5 × cap height on all sides | Measured from the trim of the lockup’s bounding box. |
| Stacked lockup | Mark height 2.05 × cap height; vertical gap 0.62 × cap height | Centred on the wider of the two elements. |
Clear-space bounding box
Let C be the wordmark cap height.
┌──────────────────────────────────────────────┐
│ ↕ 0.5 C │
│ ┌────────────────────────────────┐ │
│ 0.5C │ ◯ mark ·gap· SurveyStream │ 0.5C │
│ └────────────────────────────────┘ │
│ ↕ 0.5 C │
└──────────────────────────────────────────────┘
mark height = 1.38 C gap = 0.46 C
Nothing may enter the clear-space box — no type, no rule, no image edge, no other logo. The one permitted exception: the monogram’s pulse-trail accent may overhang into it, because the trail is part of the mark’s own silhouette.
2.5 Minimum sizes
| Context | Minimum | Behaviour below the minimum |
|---|---|---|
| Horizontal lockup, digital | 96 px for the horizontal lockup; below that use icon.svg | Use the stacked lockup, or the monogram alone. |
| Horizontal lockup, print | 28 mm wide | Below this the two-tone split stops registering at normal reading distance. |
| Stacked lockup, digital | 64 px wide | — |
| Stacked lockup, print | 20 mm wide | — |
| Monogram, digital | 20 px | Below 20 px the weave closes up — use favicon-16.svg, which drops the second ribbon and thickens the first to 2.4 units. |
| Monogram, print | 6 mm | Single-ribbon cut only. |
| Wordmark cap height, print | 2 mm (≈ 5.7 pt) | Below this, outline the paths and check on a proof. |
2.6 The interlock variant
A parallel family in logo/interlock/ re-skins the identical bowl geometry as a solid Ink loop
with a thin flow line threading it, crossing once at the waist.
| Primary | Interlock | |
|---|---|---|
| Loop | Gradient stroke, weight 12 | Solid Ink #04171F, weight 13 |
| Accent | Three trail dashes outside the bowl | Continuous flow line, weight 5.4, offset +11 |
| Crossings | None | One, at the waist |
| Aspect | 0.7826 | 0.9398 including the flow |
| Reads as | A luminous letterform | Structure with flow moving through it |
The weight and hue difference is what makes the crossing legible: a 5.4-unit accent over a 13-unit base leaves nothing ambiguous to resolve. Four earlier interlock attempts using equal weights produced a visible lump at the crossing and were abandoned.
Hard rule — the small-size floor. below 40 px the accent is dropped and the base thickened — see favicon-32/16 and icon-mono. The mark is the base/accent
separation; at one device pixel that separation turns to mud. icon-mono and the mono lockup also
drop the accent, because in a single colour the crossing has nothing to distinguish it.
2.7 Prohibited usage
Capitalisation — the exact rule
The name is SurveyStream: one word, one medial capital, no space, no hyphen.
The medial capital is not styling. It is the structural device that splits the name into its two halves — the same two-audience idea the mark encodes. Lose it and the brand reads as a single undifferentiated word.
| Form | Verdict | Note |
|---|---|---|
SurveyStream | ✅ Correct | The only form permitted in prose, UI and the lockup. |
Surveystream | ❌ Never | Destroys the split. The most common error in third-party copy. |
Survey Stream | ❌ Never | Two words is a different name. |
SURVEYSTREAM | ❌ Never | All-caps collapses the medial capital — the one thing carrying the structure. This holds even inside an all-caps context: in a tracked uppercase eyebrow or table header, the brand name stays sentence case as a deliberate exception. |
surveyStream | ❌ Never | Lower camel is a code convention leaking into the brand. |
SurveyStream™ in body copy | ❌ Never | Trademark marks belong in legal lines, not prose. |
surveystream | ⚠️ Technical only | Domains, package names, handles, CSS classes: surveystream.com, @surveystream. Never in prose. |
SURVEYSTREAM_API_KEY | ✅ Permitted | Screaming snake case in code is a language convention, not typography. |
Enforce the uppercase exception rather than trusting authors:
.ss-brand { text-transform: none !important; hyphens: none; white-space: nowrap; }
Prohibited treatments
| # | Never | Why |
|---|---|---|
| 1 | Redraw, retrace or “rebuild” the mark | It is generated from exact arc geometry. Any redraw loses the tangency. |
| 2 | Alter the mark-to-wordmark ratio or the gap | Both are cap-height multiples and are brand constants. |
| 3 | Stretch, squash, skew, rotate or mirror | The mark’s 11° lean and 0.78 aspect are fixed. |
| 4 | Apply drop shadows, bevels, outer glows, strokes or outlines | The mark carries its own glow where glow is wanted. |
| 5 | Recolour outside the palette, or apply a gradient not specified in §3 | — |
| 6 | Place the full-colour lockup on a mid-tone ground | Use reversed on dark, primary on light. Mid-tones kill both. |
| 7 | Place any lockup on a busy image without the white-plate variant | — |
| 8 | Use the monogram as a letter inside a word | It is a mark, not a glyph. |
| 9 | Break the wordmark across two lines, or letter-space it to fill a measure | — |
| 10 | Use the interlock mark below its 40 px floor without the simplified cut | The accent becomes noise. |
| 11 | Ship construction.svg | Documentation only. |
| 12 | Reconstruct the wordmark in a substitute typeface | Use wordmark.svg; the outlines are the wordmark. |
3. Colour Architecture & Specifications
3.1 Architecture
Three layers. Components may only reference layer 3.
primitive → semantic (per mode) → component
deepwater-500 → interactive → button.primary.bg (light)
stream-500 → interactive → button.primary.bg (dark)
A component that reaches past its layer is how a system rots: a button referencing
stream-500 directly cannot be re-themed, and will break silently in the mode nobody tested.
One deep anchor, one live current, a spark of warmth. Deepwater carries authority (Ruler). Stream is the single bold hue — the live, flowing accent (Magician). Payout is warmth held in reserve for value transfer. Everything else is a considered cool neutral.
Balance: roughly 60% neutral ground, 30% anchor, 10% accent. Payout never exceeds a spark. If warmth competes with Stream, the brand fractures.
3.2 Complete palette
CMYK values are unmanaged mathematical conversions — a starting point, not a press spec. See §5.4. ⚠ marks a colour with no usable Pantone equivalent (ΔE > 5).
| Name | Role | Hex | RGB | HSL | CMYK | Nearest PMS | Use |
|---|---|---|---|---|---|---|---|
| Ink | Base | #04171F | 4, 23, 31 | 198°, 77%, 7% | 87 / 26 / 0 / 88 | 5395 C (ΔE 2.4) | Darkest ground. Dark-mode canvas; light-mode primary text. |
| Deepwater | Base | #08222E | 8, 34, 46 | 199°, 70%, 11% | 83 / 26 / 0 / 82 | 5395 C (ΔE 1.7) | The primary brand colour. Dark-mode surface, print anchor. |
| Deepwater 800 | Surface | #0D2E3D | 13, 46, 61 | 199°, 65%, 15% | 79 / 25 / 0 / 76 | 5463 C (ΔE 4.2) | Dark-mode elevated surface — menus, dialogs, popovers. |
| Current | Accent | #0A6E86 | 10, 110, 134 | 192°, 86%, 28% | 93 / 18 / 0 / 47 | 3145 C (ΔE 3.8) | Light-mode primary action, links, focus ring. |
| Stream | Accent | #10BBD1 | 16, 187, 209 | 187°, 86%, 44% | 92 / 11 / 0 / 18 | 3125 C (ΔE 2.1) | The one bold hue. Dark-mode primary action, the live accent. |
| Signal | Accent | #5FE3EC | 95, 227, 236 | 184°, 79%, 65% | 60 / 4 / 0 / 7 | 318 C (ΔE 7.3) ⚠ | Dark-mode links and focus ring. Highlights on dark grounds. |
| Pulse | Accent | #2FE3A2 | 47, 227, 162 | 158°, 76%, 54% | 79 / 0 / 29 / 11 | 3385 C (ΔE 5) | Flow accent. Live states, the mark, the pattern. |
| Payout | Accent | #F2A23C | 242, 162, 60 | 34°, 87%, 59% | 0 / 33 / 75 / 5 | 1375 C (ΔE 3.4) | Warmth, reserved for value transfer. Never decorative. |
| Mist | Surface | #F4F8F9 | 244, 248, 249 | 192°, 29%, 97% | 2 / 0 / 0 / 2 | 7541 C (ΔE 5.4) ⚠ | Light-mode canvas. |
| Fog | Surface | #D3E0E2 | 211, 224, 226 | 188°, 21%, 86% | 7 / 1 / 0 / 11 | 7541 C (ΔE 2) | Light dividers, sunken wells, disabled fills. |
| Neutral 400 | Surface | #8199A0 | 129, 153, 160 | 194°, 14%, 57% | 19 / 4 / 0 / 37 | 430 C (ΔE 7.3) ⚠ | Light-mode disabled text. Exempt from contrast minima. |
| Neutral 500 | Surface | #758D94 | 117, 141, 148 | 194°, 13%, 52% | 21 / 5 / 0 / 42 | 7544 C (ΔE 5) | Light-mode default border. Clears 3:1 on canvas and surface. |
| Neutral 600 | Surface | #566A70 | 86, 106, 112 | 194°, 13%, 39% | 23 / 5 / 0 / 56 | 7545 C (ΔE 8.6) ⚠ | Light-mode muted text. Dark-mode borders derive from here. |
| Neutral 800 | Surface | #2E4A55 | 46, 74, 85 | 197°, 30%, 26% | 46 / 13 / 0 / 67 | 546 C (ΔE 5.2) ⚠ | Light-mode secondary text. |
| Success | Feedback | #2E9E6B | 46, 158, 107 | 153°, 55%, 40% | 71 / 0 / 32 / 38 | 339 C (ΔE 3.4) | Solid success fill. The system did the thing. |
| Success 600 | Feedback | #1B7A57 | 27, 122, 87 | 158°, 64%, 29% | 78 / 0 / 29 / 52 | 341 C (ΔE 1.4) | Light-mode success text. |
| Success 400 | Feedback | #4FD69A | 79, 214, 154 | 153°, 62%, 57% | 63 / 0 / 28 / 16 | 3385 C (ΔE 4.8) | Dark-mode success text. |
| Warning | Feedback | #DE8A2A | 222, 138, 42 | 32°, 73%, 52% | 0 / 38 / 81 / 13 | 1385 C (ΔE 5.1) ⚠ | Solid warning fill. |
| Warning 600 | Feedback | #A85B10 | 168, 91, 16 | 30°, 83%, 36% | 0 / 46 / 90 / 34 | 1395 C (ΔE 5.2) ⚠ | Light-mode warning text. Pushed browner to clear Payout. |
| Warning 400 | Feedback | #F0B45E | 240, 180, 94 | 35°, 83%, 65% | 0 / 25 / 61 / 6 | 143 C (ΔE 5.6) ⚠ | Dark-mode warning text. |
| Error | Feedback | #CF463D | 207, 70, 61 | 4°, 60%, 53% | 0 / 66 / 71 / 19 | 179 C (ΔE 3.7) | Destructive action fill. |
| Error 600 | Feedback | #A82F27 | 168, 47, 39 | 4°, 62%, 41% | 0 / 72 / 77 / 34 | 186 C (ΔE 6.6) ⚠ | Light-mode error text. |
| Error 400 | Feedback | #F0847B | 240, 132, 123 | 5°, 80%, 71% | 0 / 45 / 49 / 6 | 179 C (ΔE 16.5) ⚠ | Dark-mode error text. |
Semantic token map
| Token | Light | Dark |
|---|---|---|
bg-canvas | #F4F8F9 | #04171F |
bg-surface | #FFFFFF | #08222E |
bg-elevated | #FFFFFF | #0D2E3D |
bg-sunken | #D3E0E2 | #020E14 |
text-primary | #04171F | #EDF3F4 |
text-secondary | #2E4A55 | #AEC4C9 |
text-muted | #566A70 | #7E969C |
text-disabled | #8199A0 | #3F6273 |
text-link | #0A6E86 | #5FE3EC |
text-on-brand | #FFFFFF | #FFFFFF |
text-on-accent | #04171F | #04171F |
text-on-interactive | #FFFFFF | #04171F |
border-subtle | #D3E0E2 | #1C3440 |
border-default | #758D94 | #4E7687 |
interactive | #0A6E86 | #10BBD1 |
interactive-hover | #085A6E | #3ACFE1 |
interactive-active | #064A5B | #0BA3B7 |
interactive-disabled | #D3E0E2 | #1C3440 |
focus-ring | #0A6E86 | #5FE3EC |
feedback-success | #1B7A57 | #4FD69A |
feedback-payout | #8A4E08 | #F2A23C |
feedback-warning | #A85B10 | #F0B45E |
feedback-error | #A82F27 | #F0847B |
fill-success | #2E9E6B | #2E9E6B |
fill-payout | #F2A23C | #F2A23C |
fill-payout-edge | #C77A1E | #F2A23C |
fill-error | #CF463D | #CF463D |
Three rules that are easy to get wrong
1. The on-fill tokens are chosen by luminance, not semantics.
text-on-brand= white. For deep fills:interactivein light mode,fill-error.text-on-accent= Ink. For bright fills:stream-500,pulse-500,payout-500,success-500.text-on-interactive= mode-resolved. Light mode’s action fill is dark, so white; dark mode’s is bright cyan, so Ink. One shared value fails — white onstream-500is 2.32:1.
2. Warning and Payout must never share a component. Both were amber in the source palette —
“you earned this” and “something is wrong” would have looked alike. Warning is pushed browner in
both modes (#A85B10 light, #F0B45E dark). Colour alone must not carry the
distinction: always pair with an icon.
3. Success and Payout are different tokens. feedback-success (mint) means the system
succeeded. feedback-payout (amber) means money moved. Merging them spends the strongest colour
in the palette on “settings saved”.
3.3 WCAG 2.1 compliance matrix
Computed against 1.4.3 (text: 4.5:1 normal, 3:1 large; AAA at 7:1 / 4.5:1) and 1.4.11 (non-text: 3:1 for component boundaries and state indicators). Disabled controls, decorative dividers and adjacent background surfaces are exempt and marked as such.
Result: 56 pairs checked — 18 AAA, 30 AA, 8 exempt, 0 failures.
Light theme
| Group | Token | Foreground | Background | Ratio | Applied as | Result |
|---|---|---|---|---|---|---|
| Body text | text-primary | #04171F | #F4F8F9 | 17.12:1 | Normal text | AAA |
| Body text | text-primary | #04171F | #FFFFFF | 18.30:1 | Normal text | AAA |
| Body text | text-secondary | #2E4A55 | #FFFFFF | 9.43:1 | Normal text | AAA |
| Body text | text-secondary | #2E4A55 | #F4F8F9 | 8.82:1 | Normal text | AAA |
| Body text | text-muted | #566A70 | #FFFFFF | 5.69:1 | Normal text | AA |
| Body text | text-muted | #566A70 | #F4F8F9 | 5.32:1 | Normal text | AA |
| Body text | text-link | #0A6E86 | #FFFFFF | 5.85:1 | Normal text | AA |
| Disabled | text-disabled | #8199A0 | #FFFFFF | 3.00:1 | Exempt | Exempt |
| Button label | text-on-interactive | #FFFFFF | #0A6E86 | 5.85:1 | Normal text | AA |
| Button label | text-on-interactive | #FFFFFF | #085A6E | 7.78:1 | Normal text | AAA |
| Button label | text-on-interactive | #FFFFFF | #064A5B | 9.82:1 | Normal text | AAA |
| Button label | text-on-accent | #04171F | #F2A23C | 8.72:1 | Normal text | AAA |
| Button label | text-on-accent | #04171F | #2E9E6B | 5.42:1 | Normal text | AA |
| Button label | text-on-brand | #FFFFFF | #CF463D | 4.57:1 | Normal text | AA |
| Feedback text | feedback-success | #1B7A57 | #FFFFFF | 5.29:1 | Normal text | AA |
| Feedback text | feedback-payout | #8A4E08 | #FFFFFF | 6.62:1 | Normal text | AA |
| Feedback text | feedback-warning | #A85B10 | #FFFFFF | 5.04:1 | Normal text | AA |
| Feedback text | feedback-error | #A82F27 | #FFFFFF | 6.77:1 | Normal text | AA |
| Component edge | interactive | #0A6E86 | #FFFFFF | 5.85:1 | UI / non-text | AA |
| Component edge | interactive | #0A6E86 | #F4F8F9 | 5.47:1 | UI / non-text | AA |
| Component edge | border-default | #758D94 | #FFFFFF | 3.50:1 | UI / non-text | AA |
| Component edge | border-default | #758D94 | #F4F8F9 | 3.28:1 | UI / non-text | AA |
| Component edge | fill-payout-edge | #C77A1E | #FFFFFF | 3.37:1 | UI / non-text | AA |
| Focus indicator | focus-ring | #0A6E86 | #FFFFFF | 5.85:1 | UI / non-text | AA |
| Focus indicator | focus-ring | #0A6E86 | #F4F8F9 | 5.47:1 | UI / non-text | AA |
| Divider | border-subtle | #D3E0E2 | #FFFFFF | 1.35:1 | Exempt | Exempt |
| Elevation | bg-surface | #FFFFFF | #F4F8F9 | 1.07:1 | Exempt | Exempt |
| Elevation | bg-elevated | #FFFFFF | #FFFFFF | 1.00:1 | Exempt | Exempt |
Dark theme
| Group | Token | Foreground | Background | Ratio | Applied as | Result |
|---|---|---|---|---|---|---|
| Body text | text-primary | #EDF3F4 | #04171F | 16.32:1 | Normal text | AAA |
| Body text | text-primary | #EDF3F4 | #08222E | 14.65:1 | Normal text | AAA |
| Body text | text-secondary | #AEC4C9 | #08222E | 9.02:1 | Normal text | AAA |
| Body text | text-secondary | #AEC4C9 | #04171F | 10.06:1 | Normal text | AAA |
| Body text | text-muted | #7E969C | #08222E | 5.26:1 | Normal text | AA |
| Body text | text-muted | #7E969C | #04171F | 5.86:1 | Normal text | AA |
| Body text | text-link | #5FE3EC | #08222E | 10.70:1 | Normal text | AAA |
| Disabled | text-disabled | #3F6273 | #08222E | 2.51:1 | Exempt | Exempt |
| Button label | text-on-interactive | #04171F | #10BBD1 | 7.89:1 | Normal text | AAA |
| Button label | text-on-interactive | #04171F | #3ACFE1 | 9.75:1 | Normal text | AAA |
| Button label | text-on-interactive | #04171F | #0BA3B7 | 6.05:1 | Normal text | AA |
| Button label | text-on-accent | #04171F | #F2A23C | 8.72:1 | Normal text | AAA |
| Button label | text-on-accent | #04171F | #2E9E6B | 5.42:1 | Normal text | AA |
| Button label | text-on-brand | #FFFFFF | #CF463D | 4.57:1 | Normal text | AA |
| Feedback text | feedback-success | #4FD69A | #08222E | 8.93:1 | Normal text | AAA |
| Feedback text | feedback-payout | #F2A23C | #08222E | 7.83:1 | Normal text | AAA |
| Feedback text | feedback-warning | #F0B45E | #08222E | 8.91:1 | Normal text | AAA |
| Feedback text | feedback-error | #F0847B | #08222E | 6.48:1 | Normal text | AA |
| Component edge | interactive | #10BBD1 | #08222E | 7.08:1 | UI / non-text | AA |
| Component edge | interactive | #10BBD1 | #04171F | 7.89:1 | UI / non-text | AA |
| Component edge | border-default | #4E7687 | #08222E | 3.34:1 | UI / non-text | AA |
| Component edge | border-default | #4E7687 | #04171F | 3.72:1 | UI / non-text | AA |
| Component edge | fill-payout-edge | #F2A23C | #08222E | 7.83:1 | UI / non-text | AA |
| Focus indicator | focus-ring | #5FE3EC | #08222E | 10.70:1 | UI / non-text | AA |
| Focus indicator | focus-ring | #5FE3EC | #04171F | 11.93:1 | UI / non-text | AA |
| Divider | border-subtle | #1C3440 | #08222E | 1.26:1 | Exempt | Exempt |
| Elevation | bg-surface | #08222E | #04171F | 1.11:1 | Exempt | Exempt |
| Elevation | bg-elevated | #0D2E3D | #08222E | 1.15:1 | Exempt | Exempt |
Three findings that changed token values
| Finding | Measurement | Resolution |
|---|---|---|
| Light borders needed a seventh neutral | neutral-400 is 3.00:1 on white but 2.81:1 on the tinted canvas — a 1.4.11 failure | Borders use neutral-500 #758D94: 3.28:1 on canvas, 3.50:1 on surface |
| Amber fills have no discernible edge on white | payout-500 is 2.10:1 against white | Amber fills require a payout-600 #C77A1E border at 3.37:1, enforced as .ss-badge-payout |
| Dark hairlines were invisible to 1.4.11 | A conventional #2B4653 border is 1.65:1 on bg-surface | Real borders take #4E7687 at 3.34:1. The darker hairline survives only as a decorative divider, which is exempt |
Elevation is deliberately asymmetric
In light mode bg-elevated equals bg-surface and lift is carried entirely by shadow. In
dark mode shadow is nearly invisible, so lift is carried by lightness. Adjacent surfaces are
not UI components and are exempt from 3:1 — but a card that must read as a distinct object still
takes border-subtle.
4. Typography & Numerical Hierarchy
4.1 The three faces
Chosen by downloading 17 candidates and parsing their GSUB feature tables and OS/2 metrics —
not by reputation.
| Role | Face | x-height | Variable axes | Why |
|---|---|---|---|---|
| Display / wordmark | Archivo | 0.526 em | wght 100–900, wdth 62–125 | The only display candidate with a width axis — the wordmark can be optically widened without commissioning a custom cut. Carries zero, case, lnum, onum. |
| UI / body | Inter | 0.546 em (highest measured) | opsz 14–32, wght 100–900 | Tallest x-height of every candidate, and the only one with an optical-size axis, so 13 px captions and 40 px titles get different letterforms rather than one scaled outline. Richest feature set found: tnum pnum zero case calt ss01 ss02 ss03 cv01 frac salt subs sups dlig. |
| Monospace / telemetry | JetBrains Mono | 0.550 em | wght 100–800 | Near-identical x-height to Inter, so mono cells and body copy sit on the same optical line. Slashed zero and case both present, and its measured x-height is within 0.6% of Menlo — the closest fallback match of any mono tested. |
Faces rejected, with the measured reason
| Face | Finding | Consequence |
|---|---|---|
| IBM Plex Sans | No tnum. Ships lnum onum zero ss01–03 | Widely assumed to have tabular figures. It does not. Currency columns would shift as digits change — disqualifying for a payouts product. |
| Source Sans 3 | No tnum | Same failure. |
| Martian Mono | No zero | Tallest x-height measured (0.600) and an attractive width axis, but with no disambiguated zero it cannot carry an ID or a hash. Usable for tracked uppercase labels; not for data. |
| Roboto Mono | No features of interest at all | No zero, no case, no calt. |
| Outfit | x-height 0.460 — lowest measured | Costs legibility at caption sizes. |
4.2 Font stacks
--ss-font-display: "Archivo", "Archivo Fallback", "Helvetica Neue", "Arial Nova",
Helvetica, Arial, system-ui, sans-serif;
--ss-font-body: "Inter", "Inter Fallback", system-ui, -apple-system, "Segoe UI",
Roboto, "Helvetica Neue", Arial, sans-serif;
--ss-font-mono: "JetBrains Mono", "JBM Fallback", ui-monospace, "SF Mono",
SFMono-Regular, Menlo, Consolas, monospace;
Metric-matched fallbacks — measured, not estimated
A fallback with a different x-height makes the page reflow when the webfont lands. The fix is
size-adjust, and the correct value is a ratio of measured x-heights. Both sides were read out of
the actual font binaries.
| Webfont | x-height | Fallback | x-height | size-adjust | Shipped |
|---|---|---|---|---|---|
| Inter | 0.546 | Helvetica Neue | 0.5170 | 105.6% | ✅ |
| Inter | 0.546 | Helvetica | 0.5229 | 104.4% | alt |
| Inter | 0.546 | Arial | 0.5186 | 105.3% | alt |
| Archivo | 0.526 | Helvetica Neue | 0.5170 | 101.7% | ✅ |
| Archivo | 0.526 | Helvetica | 0.5229 | 100.6% | alt |
| JetBrains Mono | 0.550 | Menlo | 0.5469 | 100.6% | ✅ |
Full @font-face overrides are in typography/type.css.
4.3 Modular scale
1.200 minor third from a 16 px base. Leading is snapped to a 4 px grid. Tracking is systematic rather than eyeballed:
track(px) = 0.096398 − 0.033684 · ln(px)
which yields +0.010 em at 13 px and −0.034 em at 48 px, tightening monotonically as size grows — the behaviour type wants, expressed as a rule instead of a table of guesses.
| Token | rem | px | Line height | Weight | Tracking | Face | Use case |
|---|---|---|---|---|---|---|---|
caption | 0.8125rem | 13 px | 20 px / 1.538 | 500 | +0.010 em | Inter | Metadata, table captions, helper text, timestamps. |
body | 1rem | 16 px | 24 px / 1.5 | 400 | +0.003 em | Inter | Default UI and reading size. Survey questions, form labels. |
body-lg | 1.1875rem | 19 px | 28 px / 1.474 | 400 | −0.003 em | Inter | Intro paragraphs, taker-facing prompts, empty states. |
title | 1.4375rem | 23 px | 32 px / 1.391 | 600 | −0.009 em | Inter | Card titles, table group headers, modal titles. |
h3 | 1.75rem | 28 px | 36 px / 1.286 | 600 | −0.016 em | Archivo | Subsection headings inside dashboards. |
h2 | 2.0625rem | 33 px | 40 px / 1.212 | 600 | −0.021 em | Archivo | Section headings, panel headers. |
h1 | 2.5rem | 40 px | 44 px / 1.1 | 700 | −0.028 em | Archivo | Page titles. |
display | 3rem | 48 px | 52 px / 1.083 | 700 | −0.034 em | Archivo | Marketing hero, payout confirmation, the wordmark. |
Two off-scale exceptions, declared
A geometric scale from a 16 px base yields only three sizes at or below 20 px (13 / 16 / 19).
A dense aggregator table needs a fourth. Rather than pretend the ratio covers it, the exception is
named — and both carry $offScale: true in type-tokens.json so a linter can enforce where they
appear.
| Token | rem | px | Line height | Weight | Tracking | Face | Use case |
|---|---|---|---|---|---|---|---|
body-dense | 0.875rem | 14 px | 20 px / 1.429 | 400 | +0.006 em | Inter | Off-scale. High-density data tables in the aggregator dashboard. |
display-xl | 4rem | 64 px | 68 px / 1.063 | 700 | −0.039 em | Archivo | Off-scale. Marketing hero only. Never inside the product. |
Why 1.200 and not 1.250. Both were computed. At 1.250 the mid-range opens too far for a
dashboard — a 25 px card title and a 31 px subsection heading inside a dense metric panel read as
marketing, not instrumentation. The minor third keeps title at 23 px and h3 at 28 px, clearly
above 16 px body without shouting. Marketing drama is recovered by display-xl rather than by
stretching the product’s whole scale to reach it.
4.4 Numerical hierarchy — micro-rules
This is where a typography system either earns its keep or fails silently.
4.4.1 Reward payouts — currency and tokens
.ss-currency {
font-variant-numeric: tabular-nums lining-nums;
font-feature-settings: "tnum" 1, "lnum" 1, "zero" 0;
}
| Rule | Reason |
|---|---|
| Tabular, always | A balance changing from $1,199.00 to $1,284.50 must not change width. Proportional figures make a live balance visibly twitch. |
| Slashed zero OFF | The rule people get backwards. Inside money a slashed zero reads as a correction mark — $1,0̸24.00 looks annotated, not authoritative. The slash belongs to identifiers, not to value. |
Always two decimals, even at .00 | $40 beside $39.50 breaks the decimal column. |
| True minus U+2212 for debits, not a hyphen | tnum governs figures, not punctuation, so a hyphen stays narrow even in a tabular font. |
| Right-align in tables | Tabular figures give decimal alignment only if the column is right-aligned. |
| Token counts follow the same rules minus the decimals | Tabular, lining, integer. |
The one place numerals may leave Inter: the payout confirmation moment, set in Archivo at
display size. Archivo carries tnum and zero, so the rules still hold. Nowhere else.
4.4.2 Progress and completion indicators
.ss-percent {
font-variant-numeric: tabular-nums;
font-feature-settings: "tnum" 1;
min-width: 4ch; text-align: right; display: inline-block;
}
| Rule | Reason |
|---|---|
Zero decimals — 68%, never 68.4% | A completion bar is a glance target, not a measurement. |
| Reserve 4ch | The label must already be as wide as 100% when it reads 7%, or the bar and its label shuffle sideways as the survey fills. This is the single most common progress-bar defect, and it is a typography bug, not a layout one. |
No space before % in English locales | The glyph is part of the number. |
| Percentages take no lining override and no zero rule | A percentage never contains a leading zero worth disambiguating. |
4.4.3 Telemetry — IDs, hashes, timestamps
.ss-telemetry {
font-family: var(--ss-font-mono);
font-variant-numeric: slashed-zero;
font-feature-settings: "zero" 1, "calt" 0;
letter-spacing: 0;
}
| Rule | Reason |
|---|---|
No tnum needed — and this is not an omission | A monospace face is fixed-advance by construction: every glyph already occupies one cell, so tnum has nothing to do. That is why none of the six monos tested carries the feature. Specifying tnum on a mono is a no-op that signals the author did not know why they were asking. |
| Slashed zero ON | The exact inverse of the currency rule. In 0OB3D0 the distinction is the entire payload. |
| Contextual alternates OFF | calt drives code ligatures; an ID needs the literal character sequence, not != fused into ≠. |
| Never letter-space mono data | It breaks the column grid that makes a mono face worth using. |
ISO-8601 timestamps — 2026-08-26T13:04:22Z | Sortable as a string, unambiguous across locales, fixed-width so it columnises. |
4.4.4 Print minimums for type
| Constraint | Value |
|---|---|
| Body, print | 10 pt / 15 pt leading, ~125 mm measure (≈ 62 characters) |
| Absolute minimum, body | 8 pt |
| Absolute minimum, legal / caption | 6 pt |
| Reversed type | ≥ 7 pt — small reversed type fills in on uncoated stock |
| Optical size for print | Use Inter’s text cut (opsz 14). The display cut is built for backlit screens and looks cramped in ink |
| Variable fonts in print | Export static instances. Some RIPs mishandle variable axes and silently render the default |
5. Visual Assets, Patterns & Stationery
5.1 The data-stream background pattern
A seamless 400 × 400 tile: a telemetry node matrix with continuous stream waveforms running through it. Drawn twice — once for dark grounds, once for light.
| File | Use |
|---|---|
pattern/tile-brand-400.svg | Canonical dark tile |
pattern/tile-brand-400-light.svg | Canonical light tile |
pattern/tile-brand-400-subtle.svg | Dark, half-strength accents — behind text |
pattern/tile-brand-400-light-subtle.svg | Light, half strength |
pattern/tile-slate-200.svg / -light | 200 px tile, denser grid |
pattern/pattern.css | Theme-swapping custom properties and ready classes |
The five seamlessness rules
- Every wave has an integer number of periods across the tile width. That is the whole seam
condition — it makes value and slope agree at
x=0andx=W. The four waves run 2, 3, 1 and 4 periods across 400 px. - Wave paths are drawn from −1 period to W+1 period. The overhang is clipped by
<pattern>, and because the path is W-periodic the clipped part is exactly what the neighbouring tile draws. No phase break at the join. - No filters. This is the trap. An
feGaussianBlurrenders its glow outside the path, that output is clipped at the tile boundary, and the clipped halo does not wrap — a visible bright seam on every edge. The glow here is three layered strokes on the same path: pure geometry, which joins correctly. - Grid lines are drawn at
0 … W−step, never atW. Drawing both edges doubles the line on every boundary and halves the apparent spacing there. - Nodes on an edge are duplicated on the opposite edge. A dot centred at
x=0is clipped to its right half; its mirror atx=Wsupplies the left half from the neighbour. Corner dots get all four positions.
Two further rules govern the repeat being invisible rather than merely seamless: waves are
spaced uniformly at 1/8, 3/8, 5/8 and 7/8 of the height so the gap that wraps across the tile
edge matches the internal gaps; and packet segments stay clear of the edges, because
stroke-dasharray phase is measured from the path start and would restart at every tile.
Verification
Rendered 3 × 3 at 1:1; for each pixel column the mean |I(x+1,y) − I(x,y)| was computed. A seam
shows up as an outlier column.
| Tile | Axis | Interior mean Δ | sd | Boundary Δ | z | Periodicity error |
|---|---|---|---|---|---|---|
| brand 400 dark | vertical | 0.910 | 1.946 | 0.403 | −0.26 | 0 |
| brand 400 dark | horizontal | 1.592 | 2.518 | 0.000 | −0.63 | 0 |
| brand 400 light | vertical | 0.993 | 2.892 | 0.345 | −0.22 | 0 |
| brand 400 light | horizontal | 1.524 | 3.073 | 0.003 | −0.50 | 0 |
| slate 200 light | vertical | 2.677 | 3.391 | 1.460 | −0.36 | 0 |
The boundary columns are quieter than the average interior column — negative z-scores — so there is not merely no detectable seam; the joins are smoother than typical content. Periodicity error of 0 means the tiling is pixel-identical, not approximately so.
The light tile is drawn, not inverted
On a dark ground the accents are additive: a bright cyan stroke over near-black reads as glow, and three stacked strokes build a halo. Invert that and the halo becomes a dirty smudge while the whisper-thin grid turns into a heavy dark cage.
| Dark | Light | |
|---|---|---|
| Accent A | Stream #10BBD1 | Current #0A6E86 |
| Accent B | Pulse #2FE3A2 | Pulse-deep #12987A |
| Grid | rgba(126,150,156,0.09) | rgba(86,106,112,0.11) |
| Nodes | rgba(126,150,156,0.18) | rgba(86,106,112,0.22) |
| Glow layers | 100% | 62% — dark ink on light shows far more |
| Geometry | identical | identical |
Application rules
| Rule | Detail |
|---|---|
| Density | 28–40 behind text. Anything denser competes with body copy. |
| Full strength | Hero bands, empty states, login screens. |
| Subtle preset | Anywhere text sits on top. Non-negotiable, in either theme. |
| Keep copy off the wave bands | The light tile is quieter than the dark one, but a wave crest still runs through a line of 14 px text. |
| Never behind data tables or charts | Two grids fight, and the real one loses. |
| Scaling | Free — it is vector. Halving reads denser, not blurrier. .ss-bg--dense (200 px) and .ss-bg--wide (640 px) are provided. |
| Animation | Shift background-position by exactly 400 px per cycle. Any other distance produces a visible jump when the loop restarts. .ss-bg-drift does this over 60 s and respects prefers-reduced-motion. |
| Production delivery | Reference the file, not a data URI. The SVG gzips to 1.8 KB as a file; the same tile percent-encoded inside a stylesheet is 12.3 KB raw and compresses far worse, because URI escaping destroys the repetition gzip feeds on. |
5.2 Business card
| Specification | Value |
|---|---|
| Trim | 85 × 55 mm (EU standard) |
| Bleed document | 91 × 61 mm — 3 mm all round |
| Safe area | 4 mm inside trim → 77 × 47 mm live |
| Sides | Double-sided |
| Front | Full-bleed dark field, centred monogram at 21 mm, generative telemetry watermark at 38% of the subtle tile, URL in mono 6.5 pt reversed |
| Back | Mist ground, lockup top-left at 33 mm wide, contact grid on a 4.6 mm baseline rhythm, 16.5 mm QR, full-bleed accent strip on the bottom edge |
| Stock | 400 gsm, soft-touch matt laminate both sides |
| Finish | Spot UV on the monogram only, front side |
Stock and finish rationale
400 gsm rather than 350. The dark front field needs the snap that only a heavier board gives; at 350 gsm a full-bleed dark card feels flimsy in the hand, which undercuts an enterprise trust claim. If a printer’s house stock runs 350 gsm, it is acceptable — but request a dummy first.
Soft-touch matt laminate both sides. The dark field shows every fingerprint on gloss. Soft-touch also suppresses the scuffing that a solid dark card picks up in a wallet. It will darken the Deepwater field by roughly one tone — proof it on the actual stock before signing off.
Spot UV on the monogram only. The mark is the one element the design supports singling out, and gloss-on-soft-touch is the strongest contrast available without foil. Keep the UV strictly inside the mark’s silhouette; do not flood the pulse trail, which is too fine to register reliably.
Optional, budget permitting: edge painting in Spot 2 at 400 gsm carries the accent-strip idea onto the card’s edge. Mention only if the budget is real.
The US card is a different artwork
The 3.5 × 2 in card is 88.9 × 50.8 mm — aspect 1.75 against the EU card’s 1.545. It is not a scale of the same artwork: the safe area loses 4.2 mm of height and the contact block must be re-set. Decide which market ships first rather than assuming one converts.
5.3 Letterhead and invoice
| Specification | A4 | US Letter |
|---|---|---|
| Trim | 210 × 297 mm | 215.9 × 279.4 mm |
| Bleed document | 216 × 303 mm | 221.9 × 285.4 mm |
| Margins | 20 mm all round | 20 mm all round |
| Body measure | ~125 mm (≈ 62 characters at 10 pt) | ~131 mm |
| Stock | 100–120 gsm uncoated | 100–120 gsm uncoated |
| Zone | Rule |
|---|---|
| Header | Lockup top-left at 44 mm wide, inside the 20 mm margin. Registered company details right-aligned in mono 7 pt. |
| Accent rule | Asymmetric: 1.1 mm deep from the left margin, Stream → Pulse → Stream tint, running off the right trim edge at a real 24% tint. A 46 mm hairline under-rule at 0.15 mm. |
| Watermark | The monogram at 5% in the lower quadrant, 62 mm wide. Below 5% a screen tint can fail to hold on press; above 10% it competes with body text. |
| Footer | Two legal lines at 6.4 pt, three accreditation badges at 23 × 7 mm, web address right-aligned — all inside the 20 mm margin. |
| Bleed | Required only because the accent rule crosses the right trim edge. The sheet is otherwise unprinted paper. If the rule’s bleed is dropped, drop the 3 mm with it. |
The letterhead templates ship with specimen registration data — entity name, address, NIPC and VAT numbers are illustrative and must be replaced with the real registration before any file goes to press.
5.4 Print colour execution
SVG and CSS have no CMYK
Every template in print/ is RGB. They are layout and position masters — exact to the
millimetre — not colour-managed press files. Sending an SVG straight to a printer hands the brand
colour to an uncontrolled RGB→CMYK conversion at their end.
The correct workflow: use the files as the geometry master → re-apply colour as CMYK or spot swatches in Illustrator/InDesign → outline all live text (or supply the fonts; all three are OFL and embeddable) → export PDF/X-4 with the bleed box.
The two-ink stationery specification
| Ink | Matches | ΔE2000 | Carries | |
|---|---|---|---|---|
| Spot 1 | PMS 5395 C | Deepwater #08222E | 1.7 | The card front field, the wordmark, all body setting |
| Spot 2 | PMS 3125 C | Stream #10BBD1 | 2.1 | The mark, the accent strip, the letterhead rule |
Stationery should run two spot inks, not four-colour process. A large flat dark field is exactly where process betrays you — registration shift and banding show on a solid dark card in a way a spot ink never does. Saturated cyan-turquoise also sits outside the coated CMYK gamut, so process renders Stream visibly duller than the screen brand.
Consequences you must decide before artwork goes out
Gradients become tint ramps. The card’s accent strip and the letterhead rule are Current → Stream → Pulse gradients. Pulse has no spot equivalent (ΔE 5) and is out of CMYK gamut, so on a two-ink job they become a tint ramp of Spot 2 — 100% → 40% — rather than a hue shift. It reads as intended; it is simply not the same gradient.
The front’s glow becomes a tint halo. On a two-ink job, a 20% tint of Spot 2, not a blur.
Two colours must never go to press:
| Colour | Nearest spot | ΔE | Instruction |
|---|---|---|---|
Signal #5FE3EC | 318 C | 7.3 | Screen only |
Pulse #2FE3A2 | 3385 C | 5 | Screen only |
Both are high-luminance saturated cyan-greens — the region neither the CMYK gamut nor the Pantone solid range reaches. Where print needs a light accent, tint Spot 2 at 25–40% instead of chasing the on-screen colour.
If a job must run process
Use a controlled rich black for the Deepwater field rather than the naive conversion:
C70 M50 Y40 K100 total area coverage 260%
Inside GRACoL’s 320% limit, dense enough to read as black beside the reversed mark, and it holds detail in reversed type. A flat K100 alone looks washed grey across an area this size. The naive conversion of Deepwater — C83 M26 Y0 K82 — is a muddy, high-ink build no printer would accept.
Production minimums
| Constraint | Value | Reason |
|---|---|---|
| Hairline stroke | 0.15 mm (0.43 pt) | Below ~0.09 mm (0.25 pt) a rule can drop out or vary with plate wear |
| Minimum tint | 5% | Below that a screen tint can fail to hold |
| Maximum watermark | ~10% | Above that it competes with body text |
| Reversed type | ≥ 7 pt, single ink where possible | Reversed type across four plates shows registration shift at small sizes |
| Total area coverage | ≤ 300% coated, ≤ 260% uncoated | — |
| QR code | 16.5 mm, quiet zone 4 modules, pure K or Spot 1 | Below ~15 mm scanning is unreliable at card distance. Never screen a QR or set it in two inks |
Proof on the actual stock. Dark teals shift green on uncoated.
5.5 Open Graph social share banner
| Specification | Value |
|---|---|
| Canvas | 1200 × 630 px |
| Exports | 1× (1200 × 630) and 2× (2400 × 1260) |
Served as og:image | The 1× PNG. Several scrapers refuse images over 1 MB, and the 2× file is 1.2 MB |
| Fonts | Embedded as base64 — an OG card that falls back to Helvetica is a different design |
Layout rules
| Zone | Rule |
|---|---|
| Padding | 58 px top, 64 px sides, 54 px bottom |
| Lockup | Top-left, 44 px tall |
| Headline | Archivo 700 at 67 px, line-height 1.045, tracking −0.032 em, max 15.5 characters per line. The final phrase carries a Signal → Pulse gradient via background-clip: text |
| Subhead | Inter at 20.5 px, max 46 characters, text-wrap: balance |
| Metric panel | Right side, 356 px wide, glass treatment: backdrop-filter: blur(22px) saturate(150%), 1 px rgba(237,243,244,.16) border, inset highlight and shadow |
| Footer row | Mono 12.5 px, tracked 0.11 em, uppercase. Nothing load-bearing — it is at the edge of legibility at feed size |
| Bottom edge | 3 px Stream → Pulse → Signal gradient hairline, full width |
| The scrim is mandatory | A linear-gradient(96deg, …) holds a clean field under the headline while the stream visualisation lives on the right. Without it the waves run straight through the type and the headline is unreadable |
Non-negotiable checks
Test at feed size. A timeline shows the card at roughly 504 px wide — 42% of full size. The headline, the metric and the payout amount must all still read. Most OG cards fail here, not at full resolution.
Numerals follow §4.4. tabular-nums throughout; the payout amount carries
"tnum" 1, "lnum" 1, "zero" 0.
Export with --hide-scrollbars. Without it, headless Chrome reserves gutter width and the card
is cropped a few pixels on the right — the kind of thing noticed only after the card is live.
CHROME="/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
"$CHROME" --headless --disable-gpu --hide-scrollbars \
--window-size=1200,630 --screenshot=og-card.png "file://$PWD/og-card.html"
<meta property="og:image" content="https://surveystream.com/og-card.png">
<meta property="og:image:width" content="1200">
<meta property="og:image:height" content="630">
<meta name="twitter:card" content="summary_large_image">
backdrop-filter does not survive server-side rendering
The glass panel depends on it, and Satori / @vercel/og do not implement it. Generating this
card at request time in that stack renders the panel as a flat translucent rectangle — the layout
holds, the effect is gone. Ship the exported PNG. If per-page dynamic cards are genuinely needed,
replace the glass with an explicit gradient that approximates the blur rather than hoping the
filter lands.
6. Governance, Open Decisions & Known Limits
6.1 Open decisions
Four decisions remain open. Each has a recommendation; none is a blocker for internal use.
| # | Decision | Recommendation | Consequence if deferred |
|---|---|---|---|
| 1 | Does Pulse #2FE3A2 enter the palette? It is success-500 #2E9E6B pushed into the neon range; the source palette had no neon mint. | Adopt. It gives the flow accent a colour of its own rather than a tint of Stream. | The mark, pattern and OG card all use it. Rejecting it is a two-hex change in each, documented per file. |
| 2 | Primary or interlock mark? | The interlock is stronger at display size and maps onto the archetype structurally rather than through a gradient. Adopt it, and enforce the 40 px floor. | Two lockup families coexist. Not harmful, but it is the kind of ambiguity that becomes a fork. |
| 3 | Seven neutrals, not six. | Keep seven. Light borders cannot clear 3:1 on a tinted canvas with six steps. | The alternative is an untinted white canvas, which costs the teal bias that ties neutrals to the accent. |
| 4 | The taker side’s action colour. Both sides currently share Stream and differ only in whether Payout appears. | Consider giving the taker side Pulse outright. This is an identity decision more than a colour one. | The dual-audience split stays expressed through Payout alone. |
6.2 Known limits
Stated plainly, because each one is a place where this document stops being authoritative.
| Limit | Detail |
|---|---|
| Pantone matches are unverified | Computed as ΔE2000 against published screen approximations of Pantone solid coated colours — the best available on a monitor. Confirm on a physical Bridge or Formula Guide under D50 before releasing artwork. Values here are candidates for specification, not final. |
| The premium type stack is unverified | The alternative recommendation (Klim’s Söhne suite; GT Walsheim for display) is reasoned from foundry characteristics and the single-foundry argument for shared vertical metrics and figure widths. Those binaries are paywalled and were not parsed. Confirm tnum, zero, case and figure-width behaviour on trial fonts before committing budget. |
| Kerning needs a designer’s eye | Archivo’s GPOS fires exactly one pair on “SurveyStream”. yS and St deserve manual review before final release. |
| Letterhead registration data is specimen | Entity name, address and tax numbers in the templates are illustrative. Replace before press. |
| No motion system | Durations, easings and the choreography of the “flow” moment are unspecified. The natural next deliverable. |
| No iconography | No icon set, grid or stroke specification exists. |
| No component library | Tokens exist; components do not. |
6.3 Change control
| Rule | |
|---|---|
| Tokens are the source of truth | color-system/tokens.json and typography/type-tokens.json. This document is generated from them. Change the token, regenerate the document. |
| Never hand-edit this file | Edits will be overwritten on the next regeneration. |
| Contrast is a gate, not a guideline | Any new colour pair must be run through the matrix in §3.3 before it ships. The current state is 0 failures across 56 pairs; that number is the bar. |
| Off-scale type steps are linted | body-dense and display-xl carry $offScale: true. Any other off-scale size is a bug. |
| Print files are never SVG | §5.4. PDF/X-4 with a bleed box, colour re-applied as CMYK or spot. |
6.4 Licence
Archivo, Inter, JetBrains Mono and Gabarito are all SIL Open Font Licence 1.1 — commercial use,
web embedding, PDF embedding and outlining are all permitted. The reserved-name clause means a
modified font must not ship under the same name. The wordmark SVGs ship as outlines, so no font is
required at render time. Include the four OFL.txt files alongside any distributed font bundle.
SurveyStream Master Brand Guidelines v1.0 — 2026-08-26. Generated from color-system/tokens.json,
typography/type-tokens.json, logo/metrics.json and logo/interlock/metrics.json.
56 contrast pairs validated, 0 failures.