Accessibility
betaFarn targets WCAG 2.1 Level AA. The token system, focus styles, and motion controls are designed to make accessible output the default rather than an afterthought.
WCAG AA commitment
All semantic foreground/background token pairs are chosen to meet at least 4.5:1 contrast
(AA for normal text) in both light and dark themes. One exception: --in3-ash
(Iron Night's lightest shade, used in light mode as tertiary text and border colour) achieves
3:1 against light backgrounds — AA-large only (18pt+ or 14pt+ bold). Avoid using Ash for
body copy or labels below that size.
The full contrast matrix — every semantic pair in both themes, with AA / AAA / fail markings — is on Styles › Color › Accessibility.
Focus styles
Farn ships a global focus ring in tokens/base.css that applies to every
focusable element without opt-in:
:focus-visible {
outline: 2px solid var(--color-accent);
outline-offset: 3px;
border-radius: inherit;
}
:focus:not(:focus-visible) {
outline: none;
} :focus-visible shows the ring only for keyboard and sequential navigation;
mouse clicks suppress it via :focus:not(:focus-visible). This gives keyboard
users a clear indicator without adding visual noise for pointer users.
border-radius: inherit means the ring hugs the shape of buttons, inputs, and
cards rather than defaulting to a square. Component classes in farn-components.css
inherit this ring automatically — override only when a component needs a custom offset or
colour (see --input-focus-shadow in the Forms component).
Reduced motion
tokens/base.css includes a blanket reduced-motion rule:
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
animation-duration: 0.01ms !important;
transition-duration: 0.01ms !important;
}
}
This covers all CSS animations and transitions globally. The 0.01ms value — rather
than 0 — keeps animation events firing so JavaScript listeners do not stall waiting
for an animationend event that never comes.
Scroll-reveal elements (.scroll-reveal) additionally snap directly to their
revealed state in site/src/styles/site.css, bypassing the observer entirely for
users who prefer reduced motion.
Colour alone
Never use colour as the sole means of conveying information, indicating an action, prompting a response, or distinguishing a visual element (WCAG 1.4.1). Pair every colour-coded signal with at least one of: a text label, an icon, a pattern, or a position cue. Badge variants, for example, combine colour with a text label — the label alone would be sufficient; the colour reinforces but does not replace it.