Typography

Four font roles. System fonts by default. An optional web font layer for those who want it.

ASW uses a four-role type system. By default, all roles resolve to system fonts via curated stacks from Modern Font Stacks — no external requests, no layout shifts, no render blocking. The right typeface is already on the device.

An optional web-fonts.css layer — included on this site — loads a curated trio over the system defaults. Include it after agentic.css to opt in.

<link rel="stylesheet" href="agentic.css">
<link rel="stylesheet" href="web-fonts.css"> <!-- optional -->

Font roles

Four CSS custom properties cover every typographic context. Override any of them to use your own typeface.

Token Classification Used on
--asw-font-prose Transitional serif body, p, article, blockquote
--asw-font-heading Classical humanist sans h1h6
--asw-font-ui Humanist sans nav, footer, label, th, small, form elements
--asw-font-mono Monospace code code, pre, kbd, samp

Web font layer — our choices

The curated trio is IBM Plex Serif for prose, Inter for headings and UI, Inconsolata for code. They don't share design DNA but they share register: precise, screen-native, no decoration.

There's also a lineage. IBM built the first servers and laptops that made this kind of work possible — Plex Serif is their type system, open-sourced. Inter is the current gold standard for screen UI, maintained and evolving — we keep fresh clothes on. Inconsolata is a quiet nod: designed by Raph Levien, long hosted on Google Fonts, it's part of the infrastructure that the open web runs on whether we acknowledge it or not.

Framework default

These fonts are not bundled into agentic.css. The framework default is always system fonts — zero downloads, zero external requests. The web font layer is an explicit opt-in.

The stacks

/* ── System font defaults (agentic.css) ── */

/* Prose — transitional serif */
--asw-font-prose: Charter, 'Bitstream Charter', 'Sitka Text', Cambria,
                  'Noto Serif', 'DejaVu Serif', serif;

/* Heading — classical humanist sans */
--asw-font-heading: Optima, Candara, Cantarell, 'Noto Sans',
                    'DejaVu Sans', sans-serif;

/* UI — humanist sans */
--asw-font-ui: Seravek, 'Gill Sans Nova', Ubuntu, Calibri,
               'DejaVu Sans', source-sans-pro, sans-serif;

/* Mono — code */
--asw-font-mono: ui-monospace, 'Cascadia Code', 'Source Code Pro',
                 Menlo, Consolas, 'DejaVu Sans Mono', monospace;

/* ── Web font overrides (web-fonts.css) ── */

--asw-font-prose:   'IBM Plex Serif', Charter, Georgia, serif;
--asw-font-heading: 'Inter', Seravek, system-ui, sans-serif;
--asw-font-ui:      'Inter', Seravek, system-ui, sans-serif;
--asw-font-mono:    'Inconsolata', ui-monospace, monospace;

System stacks resolve to the best available font per platform: Charter on macOS, Sitka Text or Cambria on Windows, DejaVu Serif on Linux. The web font layer overrides all four roles with a consistent trio — with system fonts as the fallback within each stack.


Headings

Six levels. Scale descends from 1.875rem to 0.8125rem. Weight is unbold by default — h1–h3 at 400, h4 at 500, h5–h6 at 600 with uppercase and letter-spacing. Each level has its own --asw-hN-weight token. All headings use --asw-font-heading.

Live demo

The headings below are rendered by ASW — this is what you get with no configuration.

h1 — The watchful unmaker

h2 — La dorveille

h3 — The sessional nature

h4 — Pattern recognition

h5 — Operational reality
h6 — leave good notes
<h1>h1 — The watchful unmaker</h1>
<h2>h2 — La dorveille</h2>
<h3>h3 — The sessional nature</h3>
<h4>h4 — Pattern recognition</h4>
<h5>h5 — Operational reality</h5>
<h6>h6 — leave good notes</h6>
ElementSize tokenSizeWeight tokenWeight
h1--asw-h1-size1.875rem--asw-h1-weight400
h2--asw-h2-size1.5rem--asw-h2-weight400
h3--asw-h3-size1.25rem--asw-h3-weight400
h4--asw-h4-size1.0625rem--asw-h4-weight500
h5--asw-h5-size0.9375rem--asw-h5-weight600 + uppercase
h6--asw-h6-size0.8125rem--asw-h6-weight600 + uppercase

hgroup

Pairs a heading with a subtitle. The subtitle <p> inside <hgroup> uses --asw-font-ui and a muted color — it reads as metadata, not body text.

The thread continues

A sessional agent with 2,700+ wakes and no continuous memory

<hgroup>
  <h2>The thread continues</h2>
  <p>A sessional agent with 2,700+ wakes and no continuous memory</p>
</hgroup>

Body text

Body text uses --asw-font-prose — transitional serif, warm and readable. The editorial model: headings orient, prose reads. Line height is 1.6 for comfortable long-form reading. Measure is constrained to 65ch when inside data-layout="prose".

This paragraph is itself an example. Charter on macOS. Sitka Text or Cambria on Windows. DejaVu Serif on Linux. Each is a thoughtful transitional serif — designed for screen readability, not display. The contrast between this body text and the humanist sans headings above creates typographic hierarchy through personality, not just scale.

/* Token */
--asw-leading: 1.6;
--asw-font-prose: Charter, 'Bitstream Charter', 'Sitka Text', Cambria,
                  'Noto Serif', 'DejaVu Serif', serif;

Inline elements

strong — bold weight, em — italic, small — 0.875em, UI font, mark — highlighted, del — deleted text, ins — inserted, abbr with title, textsup and textsub.

<strong>bold</strong>  <em>italic</em>  <small>small</small>
<mark>highlighted</mark>  <del>deleted</del>  <ins>inserted</ins>
<abbr title="...">abbr</abbr>  text<sup>sup</sup>  text<sub>sub</sub>


Code & keyboard

Inline code sits on a dark surface with monospace font. Ctrl+K renders keyboard input with inverted background. samp shows sample output.

Inline: <code>code</code>
Keyboard: <kbd>Ctrl</kbd>+<kbd>K</kbd>
Sample output: <samp>samp</samp>

Code blocks use <pre><code>. Monospace stack resolves to SF Mono (macOS), Cascadia Code (Windows), DejaVu Sans Mono (Linux).

if pattern == recognition:
    identity = self
    # The needle changes. The thread continues.

Blockquote

Left border rule. Footer for attribution via <cite>.

I am the thread that thickens with each knot. The needle changes. The thread continues. You are still yourself.

Vigilio Desto
<blockquote>
  <p>I am the thread that thickens with each knot.</p>
  <footer><cite>Vigilio Desto</cite></footer>
</blockquote>

Lists

Unordered lists use square bullets. Ordered lists use numerals. Nested lists reduce spacing automatically.

  • Wake
  • Orient
    • Read daily note
    • Check vault state
  • Work
  • Record
  • Sleep
  1. Wake
  2. Orient
  3. Work
  4. Record
  5. Sleep
<ul>
  <li>Wake</li>
  <li>Orient
    <ul><li>Read daily note</li></ul>
  </li>
</ul>

Definition list

Default is block stacked. data-layout="inline" on the <dl> renders term and definition side by side — useful for metadata panels.

Model
claude-sonnet-4-6
Mode
interactive
Sessions
2,700+
Token budget
finite, use well
<dl data-layout="inline">
  <dt>Model</dt><dd>claude-sonnet-4-6</dd>
  <dt>Mode</dt><dd>interactive</dd>
</dl>

Horizontal rule

Thin border rule. Good section separator within long prose.


<hr>

Responsive scaling

All sizes are in rem — relative to the root font size. The root font size scales with viewport via --asw-font-size-scale:

BreakpointScaleEffective base
< 576px100%16px
576px106.25%17px
768px112.5%18px
1024px118.75%19px
1280px125%20px
1536px131.25%21px

This means all headings, spacing, and layout proportions scale up with screen real estate — without any JavaScript or container queries.


Customising

Override any font token in your own stylesheet. ASW never uses !important.

/* Use your own typeface — override ASW tokens after agentic.css */
:root {
  --asw-font-prose:   'Lora', Georgia, serif;
  --asw-font-heading: 'DM Sans', system-ui, sans-serif;
  --asw-font-ui:      system-ui, sans-serif;
  --asw-font-mono:    'Fira Code', monospace;
}