From 4270bbf95c5319bf6b292d2247e624c4a0dcfba8 Mon Sep 17 00:00:00 2001 From: Lukas Hirt Date: Sat, 26 Sep 2026 00:59:01 +0200 Subject: [PATCH] fix: wrap theme overrides in Starlight's cascade layer The previous commit's :root override was unlayered CSS. Astro's customCss is injected unlayered by default, and unlayered CSS always wins over layered CSS regardless of selector specificity - Starlight's own theme rules live in @layer starlight.base, so my unscoped :root was beating its more-specific :root[data-theme='light'] rule for every property this file touches, breaking the light/dark switch. Nav bar correctly followed the theme (it uses --sl-color-bg-nav, which resolves through a primitive this file never touched), while the page body, sidebar, and search dialog all stayed dark regardless of the selected theme, since they resolve through --sl-color-black/-gray-*, which this file did override. Wrapping the same rules in @layer starlight.base restores normal cascade behavior: light mode's more specific selector now correctly wins when active. Verified both themes, and the search dialog specifically, in an actual browser before pushing this time. Signed-off-by: Lukas Hirt --- src/styles/theme.css | 43 ++++++++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/src/styles/theme.css b/src/styles/theme.css index 2b100c8..b07cb78 100644 --- a/src/styles/theme.css +++ b/src/styles/theme.css @@ -13,25 +13,34 @@ * defines those once as `var(--sl-color-black)` etc, so they resolve * correctly under both themes only if the primitives they reference are * the ones overridden per theme, not the derived variables themselves. + * + * This must be wrapped in Starlight's own `starlight.base` layer: + * customCss is injected unlayered by default, and unlayered CSS always + * wins over layered CSS regardless of selector specificity - an + * unscoped `:root` here would otherwise beat Starlight's own, more + * specific `:root[data-theme='light']` rule (itself inside this layer), + * breaking the light/dark switch for every property this file touches. */ -:root { - --sl-color-black: #0a0d10; - --sl-color-white: #e7ecef; - --sl-color-gray-1: #e7ecef; - --sl-color-gray-2: #e7ecef; - --sl-color-gray-3: #8a97a3; - --sl-color-gray-4: #78838d; - --sl-color-gray-5: #232b32; - --sl-color-gray-6: #12171c; +@layer starlight.base { + :root { + --sl-color-black: #0a0d10; + --sl-color-white: #e7ecef; + --sl-color-gray-1: #e7ecef; + --sl-color-gray-2: #e7ecef; + --sl-color-gray-3: #8a97a3; + --sl-color-gray-4: #78838d; + --sl-color-gray-5: #232b32; + --sl-color-gray-6: #12171c; - --sl-color-accent-low: #7a3b2c; - --sl-color-accent: #ff6b4a; - --sl-color-accent-high: color-mix(in srgb, #ff6b4a 35%, white); -} + --sl-color-accent-low: #7a3b2c; + --sl-color-accent: #ff6b4a; + --sl-color-accent-high: color-mix(in srgb, #ff6b4a 35%, white); + } -:root[data-theme='light'] { - --sl-color-accent-low: hsl(11, 90%, 88%); - --sl-color-accent: hsl(11, 90%, 56%); - --sl-color-accent-high: hsl(11, 80%, 28%); + :root[data-theme='light'] { + --sl-color-accent-low: hsl(11, 90%, 88%); + --sl-color-accent: hsl(11, 90%, 56%); + --sl-color-accent-high: hsl(11, 80%, 28%); + } }