--astryx-font-family-bodyFigtree, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif
English
Two font stacks live on Neutral's semantic tokens.
--astryx-font-family-body and --astryx-font-family-heading start with Figtree, then -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica, Arial, and sans-serif. --astryx-font-family-code starts with JetBrains Mono, then ui-monospace, SFMono-Regular, Menlo, Consolas, and monospace.
The theme package loads Figtree and JetBrains Mono at 400, 500, 600, 700, and 400 italic. Figtree also includes 600 italic. Importing a theme entry loads both faces.
Weight tokens are --astryx-font-weight-normal (400), medium (500), semibold (600), and bold (700). --astryx-font-weight-regular points at normal. Components already use that name. Upstream calls the token normal.
The type values on Text and Heading map to the --astryx-text-* sizes, weights, and line heights: display-1 through display-3, and body, large, label, code, and supporting. Display sizes use weight 400. Scale comes from size, not from bold.
Heading also takes level from 1 to 6, which renders h1 to h6 and sets that level's default size, weight, and line height. When the outline calls for an h2 at a different size, override it with type.
Families, the size ramp, and weights. Sizes start at 14px and step by 1.2, then round.
--astryx-font-family-bodyFigtree, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif
--astryx-font-family-headingFigtree, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif
--astryx-font-family-codeui-monospace, 'SF Mono', Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace
Starts with JetBrains Mono, then ui-monospace, SFMono-Regular, Menlo, Consolas, and monospace. The Neutral theme entry loads 400, 500, 600, 700, and 400 italic.
--astryx-font-size-4xs0.375rem
--astryx-font-size-3xs0.4375rem
--astryx-font-size-2xs0.5rem
--astryx-font-size-xs0.625rem
--astryx-font-size-sm0.75rem
--astryx-font-size-base0.875rem
--astryx-font-size-lg1.0625rem
--astryx-font-size-xl1.25rem
--astryx-font-size-2xl1.5rem
--astryx-font-size-3xl1.8125rem
--astryx-font-size-4xl2.1875rem
--astryx-font-size-5xl2.625rem
--astryx-font-weight-normal400
--astryx-font-weight-regularvar(--astryx-font-weight-normal)
Components already use this name. It points at font-weight-normal, which is 400. Upstream calls that token normal.
--astryx-font-weight-medium500
--astryx-font-weight-semibold600
--astryx-font-weight-bold700
Headings, body, supporting text, and display roles. They point at the size and weight tokens above.
--astryx-text-heading-1-sizevar(--astryx-font-size-2xl)
--astryx-text-heading-1-weightvar(--astryx-font-weight-semibold)
--astryx-text-heading-1-leading1.3333
--astryx-text-heading-2-sizevar(--astryx-font-size-xl)
--astryx-text-heading-2-weightvar(--astryx-font-weight-semibold)
--astryx-text-heading-2-leading1.4
--astryx-text-heading-3-sizevar(--astryx-font-size-lg)
--astryx-text-heading-3-weightvar(--astryx-font-weight-bold)
--astryx-text-heading-3-leading1.4118
--astryx-text-heading-4-sizevar(--astryx-font-size-base)
--astryx-text-heading-4-weightvar(--astryx-font-weight-bold)
--astryx-text-heading-4-leading1.4286
--astryx-text-heading-5-sizevar(--astryx-font-size-sm)
--astryx-text-heading-5-weightvar(--astryx-font-weight-semibold)
--astryx-text-heading-5-leading1.6667
--astryx-text-heading-6-sizevar(--astryx-font-size-xs)
--astryx-text-heading-6-weightvar(--astryx-font-weight-semibold)
--astryx-text-heading-6-leading1.6
--astryx-text-body-sizevar(--astryx-font-size-base)
--astryx-text-body-weightvar(--astryx-font-weight-normal)
--astryx-text-body-leading1.4286
--astryx-text-large-sizevar(--astryx-font-size-lg)
--astryx-text-large-weightvar(--astryx-font-weight-semibold)
--astryx-text-large-leading1.4118
--astryx-text-label-sizevar(--astryx-font-size-base)
--astryx-text-label-weightvar(--astryx-font-weight-medium)
--astryx-text-label-leading1.4286
--astryx-text-code-sizevar(--astryx-font-size-base)
--astryx-text-code-weightvar(--astryx-font-weight-normal)
--astryx-text-code-leading1.4286
--astryx-text-supporting-sizevar(--astryx-font-size-sm)
--astryx-text-supporting-weightvar(--astryx-font-weight-normal)
--astryx-text-supporting-leading1.6667
--astryx-text-display-1-sizevar(--astryx-font-size-5xl)
--astryx-text-display-1-weightvar(--astryx-font-weight-normal)
--astryx-text-display-1-leading1.2381
--astryx-text-display-2-sizevar(--astryx-font-size-4xl)
--astryx-text-display-2-weightvar(--astryx-font-weight-normal)
--astryx-text-display-2-leading1.2571
--astryx-text-display-3-sizevar(--astryx-font-size-3xl)
--astryx-text-display-3-weightvar(--astryx-font-weight-normal)
--astryx-text-display-3-leading1.3793
Bigger is not better. One rule of thumb: body text is body, a page gets one display-1 through display-3, and everything else separates itself by level.
Do:
display-* per page. A landing page hero and a key figure on a dashboard are the two places it earns its keep. Display weight is 400; the size carries the impact, not bold.level by outline. If the page runs h1 then h2 then h3, write that. When a size looks wrong, adjust type or weight on the spot; don't skip a level to get a size.supporting. Table notes, timestamps, and help text belong there: 12px instead of the body's 14px, in the secondary color.type="code" on Text, or the Code component, for inline code. Both switch to the monospace stack.text-wrap="balance" and body text with text-wrap="pretty". The first evens out a two-line heading; the second avoids a lone word on the last line.max-lines. A truncated Heading or Text shows the full string in a tooltip on hover.Don't:
h4 as a small section heading. level 4 is the 14px bold eyebrow size, smaller than level 5. For a step down, use level="5", or give the h4 a type.font-size and line-height. font-size: 18px drifts from the --astryx-text-* line height and weight, and a theme change leaves it misaligned.letter-spacing to headings for style. On Chinese text it only looks loose.