Atoms
The smallest interactive parts — buttons, badges, inputs, toggles, avatars. Sized for an older, big-screen audience: 44px minimum targets, AA contrast, visible focus.
Badges & tags
Status shorthand — skill state, tier, catalog flags.
<span class="sg-badge sg-badge--brand">New</span>
<span class="sg-badge sg-badge--success">Mastered</span>
<span class="sg-badge sg-badge--outline">Outline</span><span class="sg-badge sg-badge--success">StoaBadge(tone: .success)Padding is font-relative (badgePadY / badgePadX × the font size), not a spacing step. Semantic tone tokens (success / warning / danger / info / brand) — danger and info take the brighter -light ink in dark only, where the plain hue clears just ~4:1 on its own dim tint.
Inputs
Label + control + help/error, at a comfortable target height.
<div class="sg-field">
<label class="sg-label">Email</label>
<input class="sg-input" type="email" />
<span class="sg-help">…</span>
</div><input class="sg-input"> · sg-input--errorStoaField(label:…, error:…)An InputDecorationTheme derived from the shared border/danger/radius tokens. Error help text takes a per-theme ink swap — dangerLight in dark, danger in light — because plain danger is 4.16:1 on a card surface in dark.
Toggles & avatars
Switches, avatars, and the segmented mode picker.
<label class="sg-switch"><input type="checkbox" checked><span></span></label>
<span class="sg-avatar">SS</span>
<span class="sg-segmented" role="group">…</span><label class="sg-switch"> · sg-avatar · sg-segmentedStoaSwitch · StoaAvatar · StoaSegmentedSwitch uses ease-spring and reads switchTrack / switchThumb — its own tokens, because WCAG 1.4.11 wants 3:1 on the track and under the thumb. Avatar fills with a solid brand + textOnBrand: on the brand gradient that ink is 1.06:1 at the pale stop, so there is no gradient to assert against.