Files
layonara-forge/.agents/skills/impeccable/reference/typography.md
T
plenarius f39f1d818b feat: integrate monaco-languageclient v10 with NWScript LSP
Replace hand-rolled LSP client (lspClient.ts, useLspClient.ts) with
monaco-languageclient v10 extended mode using @typefox/monaco-editor-react.
NWScript TextMate grammar from the LSP submodule provides syntax highlighting.
Full LSP features: completion, hover, diagnostics, go-to-definition, signature
help — all wired through WebSocket to the nwscript-language-server.

LSP server patches: fix workspaceFolders null assertion crash, handle missing
workspace/configuration gracefully, derive rootPath from rootUri when null,
guard tokenizer getRawTokenContent against undefined tokens.

Backend fixes: WebSocket routing changed to noServer mode so /ws, /ws/lsp,
and /ws/terminal/* don't conflict. TLK index loaded at startup (41,927 entries
from nwn-haks/layonara.tlk.json). Workspace routes get proper try/catch.
writeConfig creates parent directories. setupClone ensures workspace structure.

Frontend: GffEditor and AreaEditor rewritten with inline styles and TLK
resolution for CExoLocString fields. EditorTabs rewritten with lucide icons.
Tab content hydrates from API on refresh. Setup wizard gets friendly error
messages. SimpleEditor/SimpleDiffEditor for non-LSP editor uses. Vite config
updated for monaco-vscode-api compatibility.
2026-04-21 05:23:52 -04:00

7.5 KiB

Typography

Classic Typography Principles

Vertical Rhythm

Your line-height should be the base unit for ALL vertical spacing. If body text has line-height: 1.5 on 16px type (= 24px), spacing values should be multiples of 24px. This creates subconscious harmony—text and space share a mathematical foundation.

Modular Scale & Hierarchy

The common mistake: too many font sizes that are too close together (14px, 15px, 16px, 18px...). This creates muddy hierarchy.

Use fewer sizes with more contrast. A 5-size system covers most needs:

Role Typical Ratio Use Case
xs 0.75rem Captions, legal
sm 0.875rem Secondary UI, metadata
base 1rem Body text
lg 1.25-1.5rem Subheadings, lead text
xl+ 2-4rem Headlines, hero text

Popular ratios: 1.25 (major third), 1.333 (perfect fourth), 1.5 (perfect fifth). Pick one and commit.

Readability & Measure

Use ch units for character-based measure (max-width: 65ch). Line-height scales inversely with line length—narrow columns need tighter leading, wide columns need more.

Non-obvious: Increase line-height for light text on dark backgrounds. The perceived weight is lighter, so text needs more breathing room. Add 0.05-0.1 to your normal line-height.

Font Selection & Pairing

Choosing Distinctive Fonts

Avoid the invisible defaults: Inter, Roboto, Open Sans, Lato, Montserrat. These are everywhere, making your design feel generic. They're fine for documentation or tools where personality isn't the goal—but if you want distinctive design, look elsewhere.

Pick the font from the brief, not from a category preset. The most common AI typography failure is reaching for the same "tasteful" font for every editorial brief, the same "modern" font for every tech brief, the same "elegant serif" for every premium brief. Those reflexes produce monoculture across projects. The right font is one whose physical character matches this specific brand, audience, and moment.

A working selection process:

  1. Read the brief once. Write down three concrete words for the brand voice. Not "modern" or "elegant" — those are dead categories. Try "warm and mechanical and opinionated" or "calm and clinical and careful" or "fast and dense and unimpressed" or "handmade and a little weird."
  2. Now imagine the font as a physical object the brand could ship: a typewriter ribbon, a hand-lettered shop sign, a 1970s mainframe terminal manual, a fabric label on the inside of a coat, a museum exhibit caption, a tax form, a children's book printed on cheap newsprint. Whichever physical object fits the three words is pointing at the right kind of typeface.
  3. Browse a font catalog (Google Fonts, Pangram Pangram, Adobe Fonts, Future Fonts, ABC Dinamo) with that physical object in mind. Reject the first thing that "looks designy." That's your trained-everywhere reflex. Keep looking.
  4. Avoid your defaults from previous projects. If you find yourself reaching for the same display font you used last time, make yourself pick something else.

Anti-reflexes worth defending against:

  • A technical/utilitarian brief does NOT need a serif "for warmth." Most tech tools should look like tech tools.
  • An editorial/premium brief does NOT need the same expressive serif everyone is using right now. Premium can be Swiss-modern, can be neo-grotesque, can be a literal monospace, can be a quiet humanist sans.
  • A children's product does NOT need a rounded display font. Kids' books use real type.
  • A "modern" brief does NOT need a geometric sans. The most modern thing you can do in 2026 is not use the font everyone else is using.

System fonts are underrated: -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui looks native, loads instantly, and is highly readable. Consider this for apps where performance > personality.

Pairing Principles

The non-obvious truth: You often don't need a second font. One well-chosen font family in multiple weights creates cleaner hierarchy than two competing typefaces. Only add a second font when you need genuine contrast (e.g., display headlines + body serif).

When pairing, contrast on multiple axes:

  • Serif + Sans (structure contrast)
  • Geometric + Humanist (personality contrast)
  • Condensed display + Wide body (proportion contrast)

Never pair fonts that are similar but not identical (e.g., two geometric sans-serifs). They create visual tension without clear hierarchy.

Web Font Loading

The layout shift problem: fonts load late, text reflows, and users see content jump. Here's the fix:

/* 1. Use font-display: swap for visibility */
@font-face {
  font-family: 'CustomFont';
  src: url('font.woff2') format('woff2');
  font-display: swap;
}

/* 2. Match fallback metrics to minimize shift */
@font-face {
  font-family: 'CustomFont-Fallback';
  src: local('Arial');
  size-adjust: 105%;        /* Scale to match x-height */
  ascent-override: 90%;     /* Match ascender height */
  descent-override: 20%;    /* Match descender depth */
  line-gap-override: 10%;   /* Match line spacing */
}

body {
  font-family: 'CustomFont', 'CustomFont-Fallback', sans-serif;
}

Tools like Fontaine calculate these overrides automatically.

Modern Web Typography

Fluid Type

Fluid typography via clamp(min, preferred, max) scales text smoothly with the viewport. The middle value (e.g., 5vw + 1rem) controls scaling rate—higher vw = faster scaling. Add a rem offset so it doesn't collapse to 0 on small screens.

Use fluid type for: Headings and display text on marketing/content pages where text dominates the layout and needs to breathe across viewport sizes.

Use fixed rem scales for: App UIs, dashboards, and data-dense interfaces. No major app design system (Material, Polaris, Primer, Carbon) uses fluid type in product UI — fixed scales with optional breakpoint adjustments give the spatial predictability that container-based layouts need. Body text should also be fixed even on marketing pages, since the size difference across viewports is too small to warrant it.

OpenType Features

Most developers don't know these exist. Use them for polish:

/* Tabular numbers for data alignment */
.data-table { font-variant-numeric: tabular-nums; }

/* Proper fractions */
.recipe-amount { font-variant-numeric: diagonal-fractions; }

/* Small caps for abbreviations */
abbr { font-variant-caps: all-small-caps; }

/* Disable ligatures in code */
code { font-variant-ligatures: none; }

/* Enable kerning (usually on by default, but be explicit) */
body { font-kerning: normal; }

Check what features your font supports at Wakamai Fondue.

Typography System Architecture

Name tokens semantically (--text-body, --text-heading), not by value (--font-size-16). Include font stacks, size scale, weights, line-heights, and letter-spacing in your token system.

Accessibility Considerations

Beyond contrast ratios (which are well-documented), consider:

  • Never disable zoom: user-scalable=no breaks accessibility. If your layout breaks at 200% zoom, fix the layout.
  • Use rem/em for font sizes: This respects user browser settings. Never px for body text.
  • Minimum 16px body text: Smaller than this strains eyes and fails WCAG on mobile.
  • Adequate touch targets: Text links need padding or line-height that creates 44px+ tap targets.

Avoid: More than 2-3 font families per project. Skipping fallback font definitions. Ignoring font loading performance (FOUT/FOIT). Using decorative fonts for body text.