Design System and Theme
Semantic tokens, the Glass visual system, theme switching, Motion tiers, and accessibility fallbacks
AI Summary of This Chapter
The site's visuals are driven by semantic tokens and modular CSS. tokens.css provides dual variable sets for color, surfaces, radii, shadows, spacing, and motion; glass.css implements the unified glassmorphism trio and business surface classes; theme.css maps CSS variables to Tailwind v4; a11y.css handles three fallback layers: reduced motion, reduced transparency, and unsupported backdrop-filter. Theme switching is done through next-themes and a root element class, temporarily disabling broad transitions during the switch to avoid color animations across long documents.
1. Styles Directory Structure
src/app/globals.css is the aggregation entry point; shared foundations and feature-private styles are split by ownership:
src/
├── ui/
│ ├── tokens/tokens.css # colors, surfaces, radii, shadows, spacing, motion
│ ├── surfaces/glass.css # glass surfaces and controls
│ └── styles/ # Theme, Motion, Typography, and A11y
├── adapters/fumadocs/styles.css # Fumadocs component overrides
├── features/*/styles.css # Search, Tasks, Mermaid, Transition, Community
├── runtime/interaction/styles.css
└── styles/ # Loading, MDX file trees, and page-level structureTask, Mermaid, Transition, Community, Search Spotlight, and Interaction styles follow their owners; page layout and a small number of global integration rules remain in src/styles/. Visual tweaks prefer replacing Tokens or existing surfaces over stacking a second glass, Glow, or shadow system.
2. Semantic Token System
src/ui/tokens/tokens.css is the single source of truth for all visual decisions, providing dual variable sets for light (:root, .light) and dark (.dark).
Token Categories
| Category | Examples | Purpose |
|---|---|---|
| Color semantics | --background-primary, --text-primary, --accent-primary | Background, text, accents |
| Surfaces | --surface-elevated, --surface-panel | Glass surface hierarchy |
| Borders | --border-subtle, --border-strong | Stroke strength |
| Ambient light | --ambient-ice, --ambient-mint, --ambient-violet | Multi-hue radial gradients |
| Geometry | --radius-xs/sm/md/lg/xl/2xl/pill | Radius tiers |
| Shadows | --shadow-float/popover/edge/interactive | Shadow semantics |
| Spacing | --content-max: 72rem, --reading-max: 47rem, --page-gutter | Content width and margins |
| Motion | --motion-instant/fast/standard/expressive/scenic | Duration tiers |
| Easing | the standard, reveal, soft-spring trio | Curve semantics |
Domain-specific Tokens
Beyond the general Tokens, dedicated variables are defined for specific scenarios:
- Glass system:
--glass-tint,--glass-blur,--glass-refraction-fill/line,--glass-shadow-hover - Docs scenarios:
--docs-canvas-surface,--docs-circuit-node/line,--docs-sidebar-* - Mermaid diagrams: full coverage of semantic color slots such as
--mermaid-shape-*,--mermaid-git-branch-0..7,--mermaid-gantt-*,--mermaid-pie-* - Blockquotes:
--docs-quote-background/border/rail/shadow - Alert colors:
--color-alert-note/tip/important/warning/caution/example/hint/ai
Fumadocs Bridging
Tokens bridge to the Fumadocs UI color system through the --color-fd-* and --fd-primary aliases, letting Fumadocs components and project custom components share the same color source.
3. Glassmorphism System
src/ui/surfaces/glass.css implements the unified glass visual language.
The Trio Structure
Each glass surface consists of the border + backdrop-filter + box-shadow trio:
- a single hairline stroke (a
1pxsemi-transparent border); - a top sheen highlight (
insetbox-shadow); - a soft shadow (
--shadow-edge+--glass-shadow); - no stacked multi-layer inset / outer ring ghosts.
Business Surface Classes
| Class | Purpose | contain strategy |
|---|---|---|
.surface-panel / .surface-elevated | Large panels, popovers | contain: layout style (deliberately not paint, because backdrop-filter needs to sample the parent stacking context) |
.control-surface / .control-surface--primary | Compact controls | translateY(-2px) hover feedback |
.glass-panel / .glass-card / .glass-chip / .glass-cta | Large panels, popovers, chips, CTAs | Tiered by size |
.chapter-card / .mdx-doc-card | Home chapter cards, doc cards | contain: layout style isolates hover transforms and cursor tracking |
Unified Hover System
.glass-interactive: full lift + glow + tint switch;.glass-interactive--chip: no lift (to avoid jitter on small elements), only tint and rim glow;- wrapped in
@media (hover: hover)to avoid stuck hover states on touch devices; - an explicit
.glass-interactive:focus-visibleoutline keeps keyboard focus visible.
Global Ambient Light
body::before provides a global ambient light layer:
- a multi-hue, low-concentration, large-radius (
50vmax) radial gradient; filter: blur(100px) saturate(160%)+contain: strictGPU isolation;- the home page hides it entirely via
body:has(.home-page)::before { display: none }, avoiding double layering with the home page's.home-page::before; - on mobile (
max-width: 768px), the live100pxblur is replaced with a pre-blurred static gradient to reduce GPU cost.
4. Theme Entry Point and Tailwind Mapping
src/ui/styles/theme.css is the integration point for Tailwind v4 and Fumadocs:
@import "tailwindcss"
@import "fumadocs-ui/css/neutral.css"
@import "fumadocs-ui/css/preset.css"
@plugin "tailwindcss-animate"@theme inline maps CSS variables to Tailwind utility classes:
--color-background/--color-foregroundmap tobg-background/text-foreground;--font-orbitron/--font-noto-sans/--font-monomap to font utility classes.
Theme-related surfaces share the same color-switch rhythm: transition uses --theme-transition-duration, and the duration drops to zero under prefers-reduced-motion: reduce.
5. Theme Switching Mechanism
The project uses next-themes to manage light, dark, and system-following themes.
Provider Location
ThemeProvider lives in the root src/app/layout.tsx rather than in [lang]/layout.tsx. This way the Provider is not remounted when switching locale segments, avoiding the React 19 warning about remounted scripts.
The Fumadocs RootProvider disables its built-in ThemeProvider via theme={{ enabled: false }} to avoid a nested conflict with the project's ThemeProvider.
Transition Control During Switching
A theme switch makes code highlighting, tables, and diagram nodes in long documents play color animations at the same time, causing noticeable visual flicker. The project controls this as follows:
- set the
data-theme-switchingattribute on the root element before the switch; - the
[data-theme-switching] *selector temporarily disables broadtransitions; - the attribute is removed after the switch completes to restore normal transitions.
Mermaid Theme Adaptation
Mermaid static SVGs adapt to the theme via CSS variables and project class names, so there is no need to generate two diagram sets for light and dark. src/features/mermaid/styles.css provides complete semantic color slots; Mermaid nodes reference variables through class names.
6. Motion Tiers and Base Animations
src/ui/styles/motion.css defines the unified entrance animations and reduced-motion handling.
Three Motion Tiers
The project supports the low / medium / high motion tiers, defaulting to high:
| Tier | Behavior |
|---|---|
high | Full motion, including particles, transitions, and ambient animations |
medium | Particle density halved; transitions and ambient animations kept |
low | animation-duration: 0.01ms !important; transition and particle layers hidden |
Tiers are switched via the html[data-nd-motion-level] attribute. System prefers-reduced-motion: reduce forces a downgrade to low.
Entrance Animations
- unified
nd-fade-upkeyframes; [data-animated-content]triggers fade-up together with[data-visible="true"];- the low tier hides transition and particle layers.
Motion Preferences Provider
src/runtime/motion/provider.tsx exposes effectiveLevel, effectiveExperimental, systemReducedMotion, and experimentalMotionSupported through Context:
useLayoutEffectinitialization: reads localStorage, detectsprefers-reduced-motion, and detects experimental motion support;- listens to
matchMediachange andstorageevents for cross-tab sync; - the
MOTION_PREFERENCES_BOOTSTRAPinline script runs before hydration, avoiding a first-frame flash of the high default.
Experimental Motion Capability Detection
src/runtime/motion/experimental-support.ts detects HTML-in-Canvas capture (drawElementImage + requestPaint) and WebGL2 support; experimental motion is enabled only when both are present. The detection result is cached once so the settings UI and runtime consumers stay consistent. The WebGL2 context is released immediately with loseContext() after creation.
Motion Configuration
src/runtime/motion/config.ts centralizes all motion parameters:
MOTION_DURATION_MS: JS durations aligned with the CSS Tokens (instant / fast / standard / expressive / aperture / overview / surface / content / crossfade);MOTION_EASING: the standard / reveal / softSpring trio;MOTION_FRAME_RATE.homepageAmbient: 60: a shared frame rate budget, avoiding growing GPU cost on high refresh rate screens;TRANSITION_TIMEOUT_MS: navigation 8s, settleBuffer 140ms.
7. Accessibility Fallbacks
src/ui/styles/a11y.css handles three fallback layers so content stays readable when visual enhancements are unavailable.
Reduced Motion
prefers-reduced-motion: reduce:
- disables unnecessary displacement and continuous animations;
- forces the motion tier to
low; - keeps focus rings, button labels, and critical states.
Reduced Transparency
prefers-reduced-transparency: reduce:
- all glass surfaces fall back to opaque backgrounds;
backdrop-filteris disabled;- the
body::beforeambient light layer is hidden.
Unsupported backdrop-filter
@supports not (backdrop-filter: blur(1px)):
- the same fallback strategy as reduced transparency;
- ensures older browsers can still read the content.
Fallbacks only remove decoration and transitions; they never remove body text, focus, button labels, or critical states.
8. Typography and Body Text Rules
src/ui/styles/typography.css defines typography rules for body text, code, blockquotes, and callouts:
- interactive task list (
.mdx-task-progress) styles; - the glass code block (
.glass-codeblock) shell; - blockquote, callout, and alert color styles;
- inline code line-break detection styles;
- an explicit
margin-block: 0.5remon code blocks inside collapsible blocks, avoiding overlap with block edges.
9. Visual Principles
When adding or modifying UI, follow this priority:
Content and readability > decoration
Information hierarchy > number of effects
Semantic consistency > local gimmicks
Refined restraint > adding a second systemGlass, Glow, particles, Blur, and ambient Motion serve as enhancements rather than default component styles. Before adding a new visual effect, consider first: whether the existing visual language can be reused, whether an old effect can be replaced rather than stacked further, whether reading is affected, and whether GPU / JS cost increases noticeably.
Any non-essential Motion respects prefers-reduced-motion.
10. Key Files
| File | Responsibility |
|---|---|
src/ui/tokens/tokens.css | Dual semantic Token variable sets |
src/ui/styles/theme.css | Tailwind / Fumadocs mapping |
src/ui/surfaces/glass.css | Glass trio structure and business surfaces |
src/ui/styles/motion.css | Entrance animations and three motion tiers |
src/ui/styles/a11y.css | Three accessibility fallback layers |
src/ui/styles/typography.css | Body text, code, blockquotes, and callouts |
src/adapters/fumadocs/styles.css | Fumadocs component overrides |
src/runtime/motion/provider.tsx | Motion preferences Context |
src/runtime/motion/preferences.ts | Motion preference parsing and bootstrap |
src/runtime/motion/config.ts | Centralized motion configuration |
src/runtime/motion/experimental-support.ts | Experimental motion capability detection |
Content Pipeline and MDX Enhancements
Frontmatter, MDX components, code blocks, collapsible content, task progress, Remark plugins, and client boundaries
Homepage and Immersive Interaction
Homepage visual composition, ambient motion, chapter cards, immersive particles, TOC scrollbar, and motion preferences