Theme Rules
Dark mode is the primary experience
colorMode: {
defaultMode: 'dark',
respectPrefersColorScheme: false,
}
Every new visitor sees dark mode by default, regardless of their OS color-scheme preference — this is a deliberate choice, not the Docusaurus default (which would otherwise respect system preference over the configured default). Light mode remains fully supported via the manual toggle in the navbar, and uses the exact same brand tokens, only with inverted neutral surfaces (see Colors).
Accessibility
Contrast requirement: WCAG AA — 4.5:1 for normal text, 3:1 for large text (≥18pt / ≥14pt bold) and meaningful UI element boundaries. Full computed table:
| Pairing | Ratio | AA-normal (4.5) | AA-large/UI (3.0) |
|---|---|---|---|
| White text on Dark Background | 18.92 | PASS | PASS |
| White text on Surface | 16.41 | PASS | PASS |
| Secondary text on Dark Background | 7.77 | PASS | PASS |
| Secondary text on Surface | 6.74 | PASS | PASS |
| Primary Blue on Dark Background | 4.58 | PASS | PASS |
| Primary Blue on Surface | 3.97 | FAIL | PASS |
| Primary Teal on Dark Background | 7.16 | PASS | PASS |
| Primary Teal on Surface | 6.21 | PASS | PASS |
White text on Blue-text shade (#0065D8) | 5.45 | PASS | PASS |
White text on Teal-text shade (#007D6F) | 5.04 | PASS | PASS |
| Dark ink on White (light mode) | 18.92 | PASS | PASS |
| Blue-text shade on White (light mode links) | 5.45 | PASS | PASS |
The one row that stays a controlled exception — "Primary Blue on Surface" at 3.97 — is only ever used for large/decorative elements (icons, borders, large badges), never for body-sized text, which is why the AA-large/UI 3.0 threshold (not 4.5) is the one that applies there.
Keyboard navigation & focus: every interactive element (a, button, [tabindex], input) gets a
visible 2px solid var(--shumoul-blue) focus ring with 2px offset on :focus-visible — a consistent,
on-brand replacement for the browser's default focus outline, never removed without a replacement.
Reduced motion: @media (prefers-reduced-motion: reduce) collapses every animation/transition duration
to near-zero site-wide.
Motion
Subtle only — see Spacing § Motion tokens. Two transition speeds exist site-wide (120ms for color/background changes, 200ms for larger movement like card lift-on-hover); nothing animates on page load, and no auto-playing motion exists anywhere.
Code block syntax colors are exempt
The two-hue-only rule governs UI chrome — navbar, buttons, badges, admonitions, links. It does not extend
to code syntax highlighting, which functionally requires multiple distinguishable hues to differentiate
keywords, strings, comments, and identifiers — this is a readability concern, not a branding one, and no
reasonable brand system extends strict UI-chrome color rules into syntax highlighting. vsDark/vsLight
(from prism-react-renderer) were chosen specifically because their background/chrome is neutral, not
because their token colors are restricted to blue/teal.
Performance
No new JavaScript libraries were added — every visual change is CSS plus configuration (docusaurus.config.js)
plus static assets (SVG logo variants, 3 self-hosted WOFF2 font files, ~81KB total). Fonts use
font-display: swap and are self-hosted specifically to avoid the extra DNS lookup, connection, and
possible redirect that loading from fonts.googleapis.com at runtime would add to the critical rendering
path — the single largest lever available for Lighthouse performance on a typography-heavy documentation
site.
Extending this system
- Never hardcode a hex color, font name, spacing value, or border-radius in a component or page — add or
reuse a token from
custom.cssfirst. - Never introduce a third hue. If a new component seems to need a new color, it almost certainly needs a
tint/shade of blue or teal instead — see how
--shumoul-blue-soft/--shumoul-teal-soft(12% opacity tints) solve this for hover/active backgrounds without a new hue. - Any new admonition-like or severity-coded UI must follow the same rule as Colors § Semantic mapping: teal for positive, blue for informational, and weight/icon (not hue) for severity.
- Re-run the contrast check in this page whenever a new text/background pairing is introduced — do not assume a pairing is safe because a similar one passed.