Use only these 9 text styles. Define them once in ui/theme/Type.kt as WeftType.*, and never write a raw fontSize / fontWeight anywhere else.
Weights are only Regular (400) and SemiBold (600). Line height: about 1.3 for titles and labels, 1.5 for body and notes.
| Style | Font | Size | Weight | Colour | Use it for (and nothing else) |
|---|---|---|---|---|---|
display |
Lexend* | 40sp | SemiBold | text | Big input numbers: amount stepper “15”, the widget streak “11”, the Welcome headline |
screenTitle |
Lexend* | 28sp | SemiBold | text | Tab titles (Today, Habits, Journal, Insights, More), the habit name in habit detail, hero numbers “40%” / “87%”, the middle row of the time wheel (“9”, “00”, “AM”) |
title |
Lexend* | 22sp | SemiBold | text | Top-bar titles (New habit, New note, About), sheet and dialog titles, stat values (“13 days”), the reminder time “9:00 AM”, the time wheel’s other rows (muted) |
cardTitle |
Lexend* | 16sp | SemiBold | text | Habit names in every card and row, section headers above a group (text colour: “Today”, “Yesterday”, “Habit breakdown”, “Notes”, “Backup & restore”, “Icon”, “Days”; see Grouping in SPACING.md, 2026-10-19), card titles (“Habits per day”, “Theme”, the sample banner’s “These are sample habits”, About’s “Free and open source”), list row titles, the week range “21 – 27 Sep” |
body |
Lexend* | 16sp | Regular | text | Note text, paragraphs, text fields |
supporting |
Lexend* | 14sp | Regular | muted | The line under a cardTitle (“15 / 20 pages”, “7 of 7 days · 2-day streak”, “Best streak · 6 days”), all trailing text on cards (“Every day”, “4-day streak”, note time “9:12 AM”, “2 notes”, “Best: Tuesday”), descriptions |
label |
Lexend* | 14sp | SemiBold | depends | Buttons, chips, segmented buttons, the date line under a tab title (muted), summary values (“31 done · 5 partial”, muted), main trailing value (“100%”, text colour), calendar day numbers |
caption |
Lexend* | 12sp | Regular / SemiBold | muted | Helper text under fields, legends, field labels (“Name”, “Target”; SemiBold), nav bar labels, font descriptions, small labels inside rings (“75%”; SemiBold), “today” under “1/7” |
tiny |
Lexend* | 11sp | SemiBold | muted | Weekday names (Mon…Sun, M…S), heatmap month labels, the % inside the Today partial ring (text colour) |
* Every style uses the font chosen in More → Font (Lexend by default), titles included (user, 2026-10-19: “if I change font then it must change consistently”). Until then titles were always Outfit. Only the Font sheet (each font drawn in itself) and the home-screen widgets (Android only allows system fonts there) differ.
Numbers follow the body font. A number drawn at display, screenTitle or title size (the amount “15 / 20”, the time wheel, the hero “40%” / “87%”, stat values “13 days”) uses displayNumber, screenTitleNumber or titleNumber: the same size and weight in the chosen font, so it matches the text around it (2026-10-07). The widget streak “11” stays in the system font, like all widget text.
Space Grotesk draws about 17% thinner than Lexend and Outfit at the same weight, so Type.kt sets its weight axis to 470 for Regular and 700 for SemiBold. The weights in code stay 400 and 600.
Exceptions (only these):
cardTitle for the name, supporting for the line under it, supporting for plain trailing text, or label (text colour) when the trailing text is the main value.label in muted colour, 4dp from the left edge of the cards. Never 16sp, never 22sp, never primary colour.cardTitle. A card never contains a title or screenTitle, except stat cards, whose value uses title.screenTitle + “average” supporting).supporting). “By habit” became a muted 14sp section label (was 16sp).supporting (were 12sp).supporting, the weekday letters are 11sp tiny, and the day numbers are 14sp SemiBold (same as the habit detail calendar).display (was 36sp).