Features
Smart Detection
When you visit a site, Solstice analyzes it for native dark mode support by checking six signals:
| Signal | Weight | What It Checks |
|---|---|---|
color-scheme meta | 30 | <meta name="color-scheme"> includes “dark” |
prefers-color-scheme CSS | 40 | Stylesheets contain @media (prefers-color-scheme: dark) |
light-dark() function | 30 | CSS uses the light-dark() color function |
| CSS variables | 15 | Custom properties suggest theming (e.g., --bg, --color) |
| Theme toggle | 10 | DOM contains a theme toggle button (via aria-labels, data attributes) |
| Already dark | 50 | Page background luminance is below 0.2 |
Weights are summed into a confidence score (0–100%). Based on the result, Solstice recommends the best strategy for the site.
Detection Banner
The popup shows a detection banner that tells you what Solstice found:
- “This site is already dark” — No dark mode needed
- “Using site’s native dark mode” — Native strategy active
- “Using filter inversion” — Filter strategy active
- “Using CSS overrides” — Override strategy active
Expand the banner to see the confidence percentage and individual signals.
Three Strategies
Native
Sets color-scheme: dark on the page, which forces the browser to render the site’s built-in dark theme. This is the highest-quality option because it uses the design the site’s developers intended.
Used when: The site has a color-scheme meta tag, light-dark() CSS function, or is already rendering dark.
Filter
Applies invert(1) hue-rotate(180deg) to the page body, which flips all colors to their dark equivalents. Images, videos, iframes, and <figure> elements containing media are automatically un-inverted so they look correct.
Used when: The site has no native dark mode support. This is the default fallback and works well on most sites.
Override
Applies blanket CSS rules that force dark backgrounds (#1a1a2e), light text (#e0e0e0), and styled links (#8ab4f8) on all common HTML elements. Image and video opacity is reduced slightly.
Used when: Filter inversion produces poor results on a particular site. You can manually select this from the popup.
Manual Override
By default, Solstice auto-selects the best strategy. You can override this per site using the mode selector in the popup: Auto, Native, Filter, or Override.
Per-Site Controls
Every site gets independent settings that persist across sessions:
- Brightness (80–120%) — Adjusts overall brightness of the dark mode result
- Contrast (80–120%) — Adjusts contrast between light and dark elements
- Sepia (0–100%) — Applies a warm sepia tone
Double-click any slider to reset it to the default value. Click the Reset button to restore all settings for the current site.
Quality Analysis
After applying dark mode, Solstice samples up to 50 visible text elements and checks their contrast ratio against their background using the WCAG 2.0 formula.
| Quality Level | Pass Rate | Meaning |
|---|---|---|
| Good | > 95% | Excellent readability |
| Acceptable | 80–95% | Mostly readable, minor issues |
| Poor | < 80% | Many readability problems |
| Broken | Any ratio < 2.0:1 | Some text is essentially invisible |
If quality is poor, consider switching to a different strategy via the mode selector.
FOUC Guard
FOUC (Flash of Unstyled Content) is the brief white flash you see before dark mode kicks in. Solstice prevents this by injecting a dark background CSS rule as a registered content script — it runs before the page renders, so there’s no flash.
The guard is automatically managed:
- In Everywhere mode, it registers for all URLs
- In Allowlist mode, it registers only for your allowlisted hostnames
SPA Support
Single-page applications (SPAs) navigate without full page reloads. Solstice uses a mutation observer to detect DOM changes and automatically re-applies dark mode when the content updates. The observer:
- Ignores Solstice’s own DOM mutations
- Debounces re-application (100ms) to avoid unnecessary work
- Re-assesses quality after content changes
Caching
Detection and quality results are cached per hostname for 7 days. This means repeat visits to the same site skip the detection step entirely. Caches are automatically cleaned on extension startup.