Chapter 02 / 12 · Type system

Typography. The voice on the page.

Four typefaces, ten sizes, one italic. Every word in the product, the site, and the sales motion reads from this page.

2.1 Type families

Four typefaces in defined roles. Bricolage Grotesque carries headlines. DM Sans carries everything you read. Fraunces lends italic warmth to hero moments. JetBrains Mono labels the technical.

Bricolage Grotesque
var(--f-display)
Every lead.
Human touch.
Weights used: 400, 500, 600, 700
Display face. Headings, wordmarks, marketing heroes. Variable — uses optical sizing.
DM Sans
var(--f-body)
Qualify leads with conversation, not pressure. The agent listens, then moves the deal forward.
Weights used: 400, 500, 600
Body face. Paragraphs, UI text, forms. Calm, humanist, high-legibility.
Fraunces
var(--f-serif)
every time.
Italic only · SOFT axis = 80 · weight 400
Editorial italic. Used only in em inside display headings — a warm, literary counterpoint to Bricolage.
JetBrains Mono
var(--f-mono)
const response = await agent.qualify(lead);
Weights used: 400, 500, 600
Code, tokens, technical chrome. Also used in breadcrumbs, eyebrows, meta captions.

2.2 Type scale

Ten type sizes, never more. Each step has a defined role. When in doubt, choose the smaller size — this system reads warmest when it's not shouting.

The scale

56 / 44 / 32 / 24 / 20 / 17 / 19 / 16 / 13 / 11

Every lead.
Display
56px · 1.05
Hero headline. Marketing only.
Qualify faster.
Headline
44px · 1.08
Section hero on product pages.
Conversation.
Title
32px · 1.15
Page titles, big card headers.
In minutes.
Heading
24px · 1.25
Sub-sections.
What it does
Subheading
20px · 1.3
Card titles, field groups.
A common H4
Strong
17px · 1.4
Lists, table headers, callouts.
Warm intro text that sets tone.
Lede
19px · 1.55
Sentence after a headline.
Default paragraph size. Calm, legible, generous line height.
Body
16px · 1.6
Everything.
Metadata / helper text.
Caption
13px · 1.55
Timestamps, hints, micro-copy.
Legal + labels
Micro
11px · 1.5
Footnotes, tags, eyebrow text.
/* canonical scale */
.display    { font: 700 clamp(36px, 5vw, 56px)/1.05 var(--f-display); letter-spacing: -0.025em; }
.headline   { font: 700 44px/1.08 var(--f-display); letter-spacing: -0.02em; }
.title      { font: 700 32px/1.15 var(--f-display); letter-spacing: -0.015em; }
.heading    { font: 600 24px/1.25 var(--f-display); letter-spacing: -0.01em; }
.subheading { font: 600 20px/1.3  var(--f-display); letter-spacing: -0.005em; }

.lede       { font: 400 19px/1.55 var(--f-body); color: var(--fg-soft); }
.body       { font: 400 16px/1.6  var(--f-body); }
.caption    { font: 400 13px/1.55 var(--f-body); color: var(--fg-dim); }
.micro      { font: 500 11px/1.5  var(--f-mono); letter-spacing: 0.06em;
              text-transform: uppercase; color: var(--fg-dim); }

2.3 Headings

h1–h6 map directly to the scale. One Fraunces italic per headline, maximum. Balance-wrapped for short lines.

Heading hierarchy

<h1>–<h6>

Every lead. Every time. In minutes.

h1 — display

How the agent qualifies

h2 — title

Always on. Never annoying.

h3 — heading

What it does

h4 — subheading
Supporting facet
h5 — strong
Caption level
h6 — micro
<h1 class="display">Every lead. <em>Every time.</em> In minutes.</h1>
<h2 class="title">How the agent qualifies</h2>
<h3 class="heading">Always on. Never annoying.</h3>
<h4 class="subheading">What it does</h4>
<h5 class="strong">Supporting facet</h5>
<h6 class="micro">Caption level</h6>
h1, h2, h3, h4, h5, h6 {
  font-family: var(--f-display);
  color: var(--fg);
  margin: 0 0 var(--s-4);
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.12;
  text-wrap: balance;
}
h1 { font-size: clamp(36px, 5vw, 56px); line-height: 1.05; letter-spacing: -0.025em; }
h2 { font-size: 32px; }
h3 { font-size: 24px; font-weight: 600; letter-spacing: -0.01em; }
h4 { font-size: 20px; font-weight: 600; }
h5 { font-size: 17px; font-weight: 600; letter-spacing: 0; }
h6 { font-family: var(--f-mono); font-size: 11px; font-weight: 500;
     text-transform: uppercase; letter-spacing: 0.08em; color: var(--fg-dim); }

/* The one italic. Fraunces, accent-coloured, inside any display heading. */
h1 em, h2 em, .headline em, .display em {
  font-family: var(--f-serif);
  font-style: italic;
  font-weight: 400;
  color: var(--accent);
  font-variation-settings: "SOFT" 80;
}

2.4 Body text

Paragraphs are 16px DM Sans with 1.6 line-height and a max width of 62ch. First paragraph after a headline is often a lede — 19px, darker, shorter line-length.

Paragraph, lede, emphasis, link

<p> <strong> <em> <a>

Max line-length is a readability token too. Never let paragraphs exceed ~65 characters.

MagicBlocks helps businesses respond faster, qualify better, and convert more leads — without needing a bigger human team.

Our AI sales agents operate 24/7 across chat, email, SMS, and voice. They feel human, but they behave like a consistent, high-performing operator: patient, persistent, and always on context.

When a deal gets nuanced, the agent hands off cleanly to your team. No dropped threads. No lost momentum.

<p class="lede">MagicBlocks helps…</p>
<p>Our AI sales agents operate <strong>patient, persistent…</strong></p>
<p>… the agent <a href="#">hands off cleanly</a>.</p>
p { font: 400 16px/1.6 var(--f-body); color: var(--fg-soft); margin: 0 0 var(--s-5); max-width: 62ch; }
p.lede { font-size: 19px; line-height: 1.55; color: var(--fg); font-weight: 400; max-width: 58ch; }

strong { font-weight: 600; color: var(--fg); }
em     { font-style: italic; }

a { color: var(--fg); text-decoration-color: var(--hair);
    text-decoration-thickness: 1px; text-underline-offset: 3px;
    transition: color var(--dur-2) var(--ease), text-decoration-color var(--dur-2) var(--ease); }
a:hover { color: var(--accent-text); text-decoration-color: currentColor; }

2.5 Eyebrow · lede · caption

Three utilities you'll use in every hero, every card, every feature block.

Utility classes

.eyebrow · .lede · .caption

How it works

Speed-to-lead, without the pressure

Every inbound lead gets a real reply inside 30 seconds — on the channel they arrived.

Updated · April 22, 2026

<p class="eyebrow">How it works</p>
<h2>Speed-to-lead, without the pressure</h2>
<p class="lede">Every inbound lead gets a real reply…</p>
<p class="caption">Updated · April 22, 2026</p>
.eyebrow {
  font-family: var(--f-mono);
  font-size: 11.5px;
  font-weight: 500;
  color: var(--fg-dim);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  margin: 0 0 var(--s-3);
}
.lede { font: 400 19px/1.55 var(--f-body); color: var(--fg); max-width: 58ch; }
.caption { font: 400 13px/1.55 var(--f-body); color: var(--fg-dim); margin-top: var(--s-4); }
.micro { font: 500 11px/1.4 var(--f-mono); text-transform: uppercase; letter-spacing: 0.08em; color: var(--fg-dim); }

2.6 Lists

Unordered lists use a pink dot, not a bullet glyph. Ordered lists use numbered chips. Description lists put the label in mono.

ul · ol · dl

three flavours

Nest no deeper than two levels — if you need three, it probably wants to be a table.

Unordered
  • Speed-to-lead under 30 seconds
  • 24/7 coverage across every channel
  • Clean handoff to humans when it matters
Ordered
  1. Lead arrives on any channel
  2. Agent responds in seconds
  3. Qualified lead is handed off
Descriptive
Speed
Reply in seconds, not hours.
Tone
Calm, empathetic, consistent.
Memory
Full context across every touch.
<ul>
  <li>Speed-to-lead under 30 seconds</li>
  <li>24/7 coverage across every channel</li>
</ul>

<dl>
  <dt>Speed</dt><dd>Reply in seconds, not hours.</dd>
</dl>
ul, ol {
  margin: 0 0 var(--s-5);
  padding: 0 0 0 var(--s-5);
  color: var(--fg-soft);
}
ul { list-style: none; padding-left: 0; }
ul li { position: relative; padding-left: var(--s-5); margin-bottom: var(--s-2); }
ul li::before {
  content: ""; position: absolute; left: 0; top: .7em;
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--accent);
}
ol { counter-reset: step; list-style: none; padding-left: 0; }
ol li { counter-increment: step; position: relative; padding-left: var(--s-7); margin-bottom: var(--s-3); }
ol li::before {
  content: counter(step); position: absolute; left: 0; top: -1px;
  width: 20px; height: 20px; border-radius: 50%;
  background: var(--accent-soft); color: var(--accent-text);
  font: 600 11px/20px var(--f-mono); text-align: center;
}

dl { margin: 0; display: grid; grid-template-columns: auto 1fr; gap: var(--s-2) var(--s-5); }
dt { font-family: var(--f-mono); font-size: 12px; color: var(--fg-dim);
     text-transform: uppercase; letter-spacing: 0.06em; padding-top: 4px; }
dd { margin: 0; color: var(--fg-soft); }

2.7 Blockquote

Pull quotes and testimonials. The glyph is Fraunces italic, the attribution is Bricolage + mono — never switch.

Figure + blockquote + figcaption

<figure class='quote'>

Most sales outcomes are driven by emotion, trust, and clarity — not just information. The goal isn't pressure. It's momentum.
Jay Stockwell Founder · MagicBlocks
<figure class="quote">
  <blockquote>
    Most sales outcomes are driven by <em>emotion…</em>
  </blockquote>
  <figcaption>
    <span>Jay Stockwell</span>
    <span>Founder · MagicBlocks</span>
  </figcaption>
</figure>
figure.quote {
  margin: 0; padding: var(--s-7) var(--s-7) var(--s-7) var(--s-9);
  background: var(--bg-paper);
  border-left: 3px solid var(--accent);
  border-radius: 0 var(--r-lg) var(--r-lg) 0;
  position: relative;
}
figure.quote::before {
  content: "\201C";
  position: absolute; top: -8px; left: var(--s-5);
  font-family: var(--f-serif); font-style: italic;
  font-size: 72px; line-height: 1; color: var(--accent);
  font-variation-settings: "SOFT" 80;
}
figure.quote blockquote {
  margin: 0 0 var(--s-4);
  font: 400 21px/1.4 var(--f-body);
  color: var(--fg);
  letter-spacing: -0.005em;
}
figure.quote blockquote em {
  font-family: var(--f-serif);
  font-style: italic; font-weight: 400;
  color: var(--accent);
  font-variation-settings: "SOFT" 80;
}
figure.quote figcaption {
  display: flex; flex-direction: column; gap: 2px;
}
figure.quote figcaption span:first-child {
  font-family: var(--f-display); font-weight: 600; font-size: 14px;
}
figure.quote figcaption span:last-child {
  font-family: var(--f-mono); font-size: 12px; color: var(--fg-dim);
}

2.8 Inline code · kbd · mark

Technical punctuation for docs, changelogs, and agent configuration copy.

Inline technical

<code> <kbd> <mark> <pre>

Use var(--accent) for hero CTAs. Press K to open command palette. A highlighted phrase sits comfortably inside a sentence.

const agent = new Agent({
  voice:   "warm",
  channel: ["chat", "sms", "email"],
});
<p>
  Use <code>var(--accent)</code> for hero CTAs.
  Press <kbd></kbd> <kbd>K</kbd>
  to open command palette. A <mark>highlighted phrase</mark></p>

<pre><code>const agent = new Agent({ … });</code></pre>
code {
  font-family: var(--f-mono); font-size: 0.9em;
  padding: 1px 6px;
  background: var(--bg-sunk);
  border: 1px solid var(--hair);
  border-radius: var(--r-xs);
  color: var(--fg);
}
kbd {
  font-family: var(--f-mono); font-size: 0.85em;
  padding: 2px 7px;
  background: var(--bg-paper);
  border: 1px solid var(--hair);
  border-bottom-width: 2px;
  border-radius: var(--r-sm);
  box-shadow: 0 1px 0 var(--hair-soft);
}
mark {
  background: linear-gradient(transparent 60%, var(--yellow-300) 0);
  padding: 0 2px;
  color: var(--fg);
}
pre {
  font-family: var(--f-mono); font-size: 13px; line-height: 1.65;
  padding: var(--s-5);
  background: var(--ink); color: var(--warm-3);
  border-radius: var(--r-lg);
  overflow-x: auto;
  margin: var(--s-4) 0;
}
pre code { background: transparent; border: 0; padding: 0; color: inherit; }

2.9 Code block

Block-level fenced code — for docs, changelogs, config snippets. Ink surface with a language pill and filename in the header. Syntax colours are desaturated and warm; the pink keyword picks up the brand accent even in code.

Code snippet

.codeblk

Keeps the ink surface contained to the block. Use the mono-uppercase language pill as a small brand hit.

JS agent.qualify.js
const response = await agent.qualify(lead);
if (response.intent === "book") {
  calendar.schedule(response.slot);
}
<figure class="codeblk">
  <header class="codeblk-head">
    <span class="codeblk-lang">JS</span>
    <span class="codeblk-file">agent.qualify.js</span>
    <button class="codeblk-copy">copy</button>
  </header>
  <pre><code>…</code></pre>
</figure>
.codeblk { background: var(--ink); border-radius: var(--r-md); overflow: hidden; }
.codeblk-head { display: flex; align-items: center; gap: var(--s-3);
  padding: var(--s-3) var(--s-4); border-bottom: 1px solid rgba(255,255,255,.08); }
.codeblk-lang { font: 600 10.5px/1 var(--f-mono); text-transform: uppercase;
  letter-spacing: 0.08em; color: var(--accent-text);
  padding: 3px 6px; border: 1px solid var(--accent); border-radius: var(--r-xs); }
.codeblk-file { font: 400 12px/1 var(--f-mono); color: rgba(255,255,255,.55); flex: 1; }
.codeblk-copy { font: 500 11px/1 var(--f-mono); color: rgba(255,255,255,.7);
  background: transparent; border: 1px solid rgba(255,255,255,.15);
  border-radius: var(--r-xs); padding: 4px 8px; cursor: pointer; }
.codeblk pre { margin: 0; padding: var(--s-4); overflow: auto;
  font: 400 13px/1.55 var(--f-mono); color: rgba(255,255,255,.88); }
.tk-kw { color: #FE84A9; } .tk-fn { color: #5BD9FC; }
.tk-pr { color: #FFD878; } .tk-st { color: #7DF4D0; }

2.10 Text utilities

Small classes that prevent the most common typographic paper cuts: ugly widows, runaway strings in tables, mismatched digit widths.

Utilities

balance · pretty · truncate · nums

.text-balance

A long heading that balance-wraps across two lines gracefully

.text-pretty

Body copy that avoids ugly widows and orphans when the paragraph wraps.

.truncate

Very long text that we don't want to wrap — trimmed with ellipsis to keep rows tidy

.lining-nums

0123456789 — tabular, lining numerals for tables and dashboards

.text-balance { text-wrap: balance; }
.text-pretty  { text-wrap: pretty; }

.truncate {
  display: block;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
}

.lining-nums {
  font-variant-numeric: tabular-nums lining-nums;
}

/* antialiasing on for marketing surfaces */
.antialias {
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

2.11 Anatomy

How a headline block comes together — a Bricolage display with one Fraunces italic em, an accent-coloured pink, and a DM Sans lede sitting 24px below.

MARKETING HERO

Every lead. In conversation.

A quiet lede sentence that carries the tone for everything below — written in DM Sans, 19px, 1.6 line height, capped at 62ch.

  1. 1Eyebrow · .chapter-eyebrow · mono 12 / uppercase
  2. 2Display · Bricolage 700 · clamp(36,5vw,56) · -0.025em
  3. 3Accent em · Fraunces italic 400 · SOFT 80 · colour --accent
  4. 4Lede · DM Sans 400 / 19 · line-height 1.6 · max 62ch
  5. 5Rhythm · 16/24/32/48 vertical scale between blocks