The handbook is dark-only. There is no light mode, no theme toggle, and no accommodation for color vision deficiencies. The foundation for theming is solid: all colors are defined as CSS custom properties in a single @theme block (Tailwind CSS v4), not scattered as hardcoded hex values. Changing the theme means changing 10 variables.
Current color palette
| Variable |
Hex |
Role |
navy |
#0a0e1a |
Primary background |
navy-light |
#0f1629 |
Code blocks, panels |
navy-border |
#1e2a42 |
Borders |
teal |
#14d4d4 |
Primary accent |
blue |
#0f3fcf |
Secondary accent |
blue-mid |
#5ba3f5 |
Links, function names |
lime |
#c2cf0e |
Comments, strings |
green |
#78ddb6 |
Gradient accent |
text |
#c8d2e0 |
Body text |
text-muted |
#8899b4 |
Secondary text |
33 .svelte files reference these through semantic Tailwind classes (text-text, bg-navy). Swapping the underlying variables handles most components without touching their markup.
Work items
1. Light mode palette and toggle
Define a second set of CSS custom properties in app.css for light mode. Add a toggle to +layout.svelte and persist the choice in localStorage. Include a blocking <script> in app.html to prevent flash of wrong theme on load.
2. Shiki code highlighting
shiki-beacon-theme.json has its own hardcoded hex values for syntax tokens. Shiki renders at build time via mdsvex, so runtime theme switching requires one of two approaches: generate both themes and toggle with CSS, or use Shiki's css-variables theme mode so token colors follow the same CSS custom properties as the rest of the page.
3. Hardcoded hex values outside @theme
A few places bypass the theme system:
app.css has #e8edf5 hardcoded in ~6 places for prose headings and strong text
static/favicon.svg has inline gradient stops matching theme colors
- Scattered
text-[#e8a46e] arbitrary values in versioned landing page code snippets
These should be extracted into the @theme block so they follow the active theme.
4. Accessibility color themes
The current palette leans on teal and lime, which can be hard to distinguish for some types of color vision deficiency. Possible additions:
- High contrast: push all text/background contrast ratios to 7:1+ (current
text-muted on navy is ~5.8:1, passes AA but not AAA)
- Protanopia / Deuteranopia / Tritanopia: replace teal/lime/green accents with distinguishable alternatives for each CVD type
Each accessibility theme is another set of CSS custom property values. The toggle UI becomes a dropdown instead of a binary switch. The choice should persist across sessions.
5. Scrollbar and animation colors
Scrollbar styling in app.css uses hardcoded references that should follow the theme. Gradient animation keyframes already use CSS variables and would update automatically.
Effort estimate
| Task |
Effort |
| CSS variable light palette |
Small |
| Theme toggle + persistence |
Small |
| Shiki dual-theme or CSS variables |
Medium |
| Extract hardcoded hex to variables |
Small |
| Accessibility themes (CVD, high contrast) |
Medium-Large |
| Visual testing across all 33 components |
Medium |
The handbook is dark-only. There is no light mode, no theme toggle, and no accommodation for color vision deficiencies. The foundation for theming is solid: all colors are defined as CSS custom properties in a single
@themeblock (Tailwind CSS v4), not scattered as hardcoded hex values. Changing the theme means changing 10 variables.Current color palette
navy#0a0e1anavy-light#0f1629navy-border#1e2a42teal#14d4d4blue#0f3fcfblue-mid#5ba3f5lime#c2cf0egreen#78ddb6text#c8d2e0text-muted#8899b433
.sveltefiles reference these through semantic Tailwind classes (text-text,bg-navy). Swapping the underlying variables handles most components without touching their markup.Work items
1. Light mode palette and toggle
Define a second set of CSS custom properties in
app.cssfor light mode. Add a toggle to+layout.svelteand persist the choice in localStorage. Include a blocking<script>inapp.htmlto prevent flash of wrong theme on load.2. Shiki code highlighting
shiki-beacon-theme.jsonhas its own hardcoded hex values for syntax tokens. Shiki renders at build time via mdsvex, so runtime theme switching requires one of two approaches: generate both themes and toggle with CSS, or use Shiki'scss-variablestheme mode so token colors follow the same CSS custom properties as the rest of the page.3. Hardcoded hex values outside
@themeA few places bypass the theme system:
app.csshas#e8edf5hardcoded in ~6 places for prose headings and strong textstatic/favicon.svghas inline gradient stops matching theme colorstext-[#e8a46e]arbitrary values in versioned landing page code snippetsThese should be extracted into the
@themeblock so they follow the active theme.4. Accessibility color themes
The current palette leans on teal and lime, which can be hard to distinguish for some types of color vision deficiency. Possible additions:
text-mutedonnavyis ~5.8:1, passes AA but not AAA)Each accessibility theme is another set of CSS custom property values. The toggle UI becomes a dropdown instead of a binary switch. The choice should persist across sessions.
5. Scrollbar and animation colors
Scrollbar styling in
app.cssuses hardcoded references that should follow the theme. Gradient animation keyframes already use CSS variables and would update automatically.Effort estimate