Typography

Diwa uses Outfit for base UI text and Instrument Sans for display headings to create a premium but readable hierarchy. The static scale runs from 11–48px, with a fluid layer powered by clamp() that adapts between the 480px and 1760px breakpoints.

Example

Live type specimens for each role in the Diwa type system. Every size is driven by a CSS custom property so it reflects the active token values.

Display

Display Large

The quick brown fox jumps over the lazy dog

Display Medium

The quick brown fox jumps over the lazy dog

Display Small

The quick brown fox jumps over the lazy dog

Heading

Heading XX Large

The quick brown fox jumps over the lazy dog

Heading X Large

The quick brown fox jumps over the lazy dog

Heading Large

The quick brown fox jumps over the lazy dog

Heading Medium

The quick brown fox jumps over the lazy dog

Heading Small

The quick brown fox jumps over the lazy dog

Text

Text X Large

The quick brown fox jumps over the lazy dog

Text Large

The quick brown fox jumps over the lazy dog

Text Medium

The quick brown fox jumps over the lazy dog

Text Small

The quick brown fox jumps over the lazy dog

Text X Small

The quick brown fox jumps over the lazy dog

Text XX Small

The quick brown fox jumps over the lazy dog

Font families

--diwa-font-family-base

The quick brown fox

Outfit, Segoe UI, Roboto fallback stack

--diwa-font-family-mono

const x = 'value';

Geist Mono, Consolas fallback

Static type scale

ScaleTokenValueSample
xs--diwa-font-size-xs11pxAa
sm--diwa-font-size-sm12pxAa
md--diwa-font-size-md13pxAa
base--diwa-font-size-base15pxAa
lg--diwa-font-size-lg17pxAa
xl--diwa-font-size-xl20pxAa
2xl--diwa-font-size-2xl24pxAa
3xl--diwa-font-size-3xl32pxAa
4xl--diwa-font-size-4xl48pxAa

Fluid type scale

Fluid tokens use clamp(min, preferred, max) to scale continuously. They are intended for headings and display text — not body copy, which should use static tokens for consistent reading rhythm.

TokenRangeSuggested use
--diwa-font-size-fluid-sm11–13pxCaption text, labels
--diwa-font-size-fluid-base13–15pxBody copy
--diwa-font-size-fluid-lg14–17pxLead paragraph
--diwa-font-size-fluid-xl16–20pxSubheadings
--diwa-font-size-fluid-2xl18–24pxSection headings
--diwa-font-size-fluid-3xl20–28pxPage headings
--diwa-font-size-fluid-4xl24–36pxHero / display medium
--diwa-font-size-fluid-5xl36–60pxHero / display large

Font weights

--diwa-font-weight-normalNormal — body copy400
--diwa-font-weight-mediumMedium — UI labels, buttons500
--diwa-font-weight-semiboldSemibold — headings600
--diwa-font-weight-boldBold — emphasis, display700

Line heights

--diwa-line-height-tight

1.1Display, headings

--diwa-line-height-normal

1.5UI labels, buttons, captions

--diwa-line-height-relaxed

1.6Body copy

--diwa-line-height-loose

1.8Long-form prose

Usage

Do

  • Use fluid tokens for headings and display text so they scale gracefully across breakpoints.
  • Use static tokens for body copy and UI labels to maintain consistent reading rhythm.
  • Match font weight to semantic role: 400 body, 500 UI labels, 600 headings, 700 display.
  • Use --diwa-font-family-mono for all code, tokens, and technical strings.

Don't

  • Don't use fluid tokens for body text — fluid scaling breaks reading rhythm.
  • Don't mix font families within a single semantic role.
  • Don't use font-weight above 700 unless a heavier token is explicitly introduced and tested.
  • Don't hard-code font sizes in px from outside the token scale.

Styles

Import JS tokens for CSS-in-JS or Framer Motion. Consume CSS custom properties directly in stylesheets.

// JS — import typography tokens
import {
  fontSizeBase, fontSizeSm, fontSizeLg, fontSizeXl,
  fontSizeFluidSm, fontSizeFluidBase, fontSizeFluidLg,
  fontWeightNormal, fontWeightMedium, fontWeightSemibold, fontWeightBold,
  lineHeightTight, lineHeightNormal, lineHeightRelaxed,
  fontFamilyBase, fontFamilyMono,
} from '@diwacopilot/components/styles';

/* ─── CSS ─────────────────────────────────────────────────────────────── */
.heading {
  font-family: var(--diwa-font-family-base);
  font-size: var(--diwa-font-size-fluid-xl);
  font-weight: var(--diwa-font-weight-semibold);
  line-height: var(--diwa-line-height-tight);
  color: var(--diwa-text-primary);
}

.body {
  font-family: var(--diwa-font-family-base);
  font-size: var(--diwa-font-size-base);
  font-weight: var(--diwa-font-weight-normal);
  line-height: var(--diwa-line-height-relaxed);
  color: var(--diwa-text-secondary);
}

.code {
  font-family: var(--diwa-font-family-mono);
  font-size: var(--diwa-font-size-sm);
  color: var(--diwa-accent);
}
@use '@diwacopilot/components/styles' as *;

.heading {
  font-family: $diwa-font-family-base;
  font-size: $diwa-font-size-fluid-xl;
  font-weight: $diwa-font-weight-semibold;
  line-height: $diwa-line-height-tight;
  color: $diwa-text-primary;
}

.body {
  font-family: $diwa-font-family-base;
  font-size: $diwa-font-size-base;
  font-weight: $diwa-font-weight-normal;
  line-height: $diwa-line-height-relaxed;
  color: $diwa-text-secondary;
}

.code {
  font-family: $diwa-font-family-mono;
  font-size: $diwa-font-size-sm;
  color: $diwa-accent;
}