This site supports both dark and light themes, yet the stylesheet contains no second set of section styles and no JavaScript toggle logic. There is only one secret: no color is ever hard-coded — everything references a CSS variable, and the two themes are just two sets of variable values.
How to extract the variables
Define a semantic set of variables on :root — --bg, --text, --accent, --card-surface, --card-shadow, and so on — with dark values as the default. Then override the same set inside @media (prefers-color-scheme: light). Every section style references var(--*), so 'changing the theme' goes from editing hundreds of style lines to editing a dozen variables.
Naming makes or breaks it
Name variables by meaning, not by color. --card-surface can be a dark gray gradient in dark mode and white in light mode — the name holds either way. Call it --dark-gray and the light-mode override turns the name into a lie. Semantic naming turns your variables into a design-system vocabulary: when adding a new section, pick the right word and both themes are automatically correct.
The devil in the details
A few easily-missed spots: set color-scheme: dark light on :root so native browser widgets (scrollbars, form controls) switch along; the theme-color meta tag accepts a media attribute, letting the mobile browser chrome follow the theme too; and shadows and glows need different opacities on light backgrounds, so even something as seemingly constant as --card-shadow belongs in a variable.
Why no manual toggle button
Following the system preference is the better default for most personal sites: the user has already expressed a preference at the OS level — respect it. If a manual toggle ever becomes necessary, this architecture only needs the variable sets hung on a data attribute and a few lines of JS to switch it — the variable layer itself stays untouched.
Extracting colors into variables is one of those investments that costs an extra hour up front and saves a day on every redesign after. If you are starting a new project, write your very first line of CSS this way.
Max Chu