Foundations
Typography
Type follows the reader's writing system, not just their locale. The root
element carries a data-writing-system attribute — latin or cjk — and the
font stacks and metrics answer to it. The root font size stays 16px at every
breakpoint, so legacy rem values map one to one.
Families
Three families, spent as font-sans, font-serif and font-mono. Latin
leads the sans stack because the unprefixed route is the global site: Geist
Sans (self-hosted through next/font), then Inter, then the CJK families.
Serif is not hypothetical — the clock-collage list style sets its heading
in font-serif.
Curate everything you love — 收集你所热爱的一切
Curate everything you love — 收集你所热爱的一切
Curate everything you love
--font-sans: Geist Sans, Inter, PingFang SC, … --font-serif: Georgia, Cambria, … Songti SC, SimSun, … --font-mono: SFMono-Regular, Menlo, Monaco, …
The fallback order
The CJK families sit ahead of ui-sans-serif and -apple-system, and that
order is load-bearing. Per-character fallback only continues while a font has
no glyph — and the system keywords always produce one, because a missing
character resolves through LastResort, whose glyph is the ▯ box. On any engine
whose system font lacks hanzi, a stack that leads with the system keywords
stops the cascade with tofu and every CJK family after them is unreachable.
Naming the CJK families first costs Latin text nothing: fallback is per
character.
The same rule generalises: sans-serif is terminal — a generic family matches
everything — so new families go before it, never after.
Writing systems
The locale layout stamps data-writing-system on <html>, so future
Latin-script locales inherit the Latin treatment without language-specific
selectors. Content keeps a language of its own: a Chinese list read by an
English reader is the ordinary case, which is why the CJK families stay in the
Latin stack for per-character fallback.
| Writing system | Treatment |
|---|---|
latin | Geist Sans with a tuned rhythm: semibold rides at weight 560, a tighter line-height ladder (text-base 1.5 down to text-4xl 1.1), body letter-spacing −0.006em, and kerning, optical sizing and contextual ligatures switched on. Code runs reset their tracking to 0. |
cjk | The legacy PingFang-first stack and Tailwind's stock type metrics, unchanged. Hiragino Sans earns its odd place in the stack: the iOS Simulator ships no Simplified Chinese font, and Hiragino covers the shared kanji there; on a real device PingFang is ahead of it and always present. |
Scale
Tailwind's stock type scale, spent as utilities. What Curation adds is the
Latin line-height ladder above and the discipline that sizes are stated in rem
— the root never changes, so a text-[0.94rem] ported from legacy renders at
exactly the legacy size.
Taste, kept deliberately
Taste, kept deliberately
Taste, kept deliberately
Taste, kept deliberately
Taste, kept deliberately
Taste, kept deliberately