Created
June 26, 2026 03:00
-
-
Save LeaveNhA/d25fd0fbaac45d22f6bd25d8be2e27ac to your computer and use it in GitHub Desktop.
KhanAcademy.org Dark Mode, CSS, injection-ready
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* ============================================================================ | |
| KHAN ACADEMY: HIGH-FIDELITY DARK MODE INJECTION | |
| -------------------------------------------------------------------------- | |
| Design Philosophy: Declarative structural mapping, reduced luminance | |
| spikes, and micro-contrast optimization for long-form reading comfort. | |
| ============================================================================ */ | |
| @media (prefers-color-scheme: dark) { | |
| /* ========================================================================== | |
| TIER 1: THE TOKEN DICTIONARY (Variable Overrides) | |
| ========================================================================== */ | |
| :root, | |
| .wb-root-container, | |
| [data-theme="dark"], | |
| body { | |
| /* --- 1. Core Surfaces (Deep, warm charcoals) --- */ | |
| --wb-semanticColor-core-background-base-default: #0f131a; | |
| --wb-semanticColor-core-background-base-subtle: #0c1016; | |
| --wb-semanticColor-core-background-base-strong: #141923; | |
| /* --- 2. Typography (Off-whites to prevent halation/astigmatism glare) --- */ | |
| --wb-semanticColor-core-foreground-neutral-default: #b8bfcc; | |
| --wb-semanticColor-core-foreground-neutral-strong: #d0d6e1; | |
| --wb-semanticColor-core-foreground-neutral-subtle: #6b7280; | |
| /* KNOCKOUT FIX: This must be bright so it contrasts against dark UI elements */ | |
| --wb-semanticColor-core-foreground-knockout-default: #d0d6e1; | |
| /* --- 3. Borders & Dividers (Muted structural lines) --- */ | |
| --wb-semanticColor-core-border-neutral-default: #242a35; | |
| --wb-semanticColor-core-border-neutral-strong: #1c222e; | |
| --wb-semanticColor-core-border-neutral-subtle: #1a2030; | |
| --wb-semanticColor-core-border-disabled-default: #242a35; | |
| --wb-semanticColor-core-border-knockout-default: #141923; | |
| --wb-semanticColor-core-border-disabled-subtle: transparent; | |
| /* --- 4. System Status & Feedback (Desaturated to prevent optical popping) --- */ | |
| --wb-semanticColor-core-foreground-instructive-default: #6b82b3; | |
| --wb-semanticColor-core-background-instructive-default: #161d2e; | |
| --wb-semanticColor-core-foreground-success-default: #4f8c62; | |
| --wb-semanticColor-core-background-success-default: #132019; | |
| --wb-semanticColor-core-foreground-warning-default: #a89345; | |
| --wb-semanticColor-core-background-warning-default: #211c14; | |
| --wb-semanticColor-core-foreground-critical-default: #963f48; | |
| --wb-semanticColor-core-background-critical-default: #201316; | |
| /* --- 5. Interactive Elements (Muted power colors) --- */ | |
| --wb-semanticColor-action-primary-progressive-default-background: #374a6b; | |
| --wb-semanticColor-action-primary-progressive-default-foreground: #d0d6e1; | |
| --wb-semanticColor-action-primary-destructive-default-background: #6e2b31; | |
| --wb-semanticColor-action-primary-destructive-default-foreground: #d0d6e1; | |
| --wb-semanticColor-action-primary-neutral-default-background: #242a35; | |
| --wb-semanticColor-action-primary-neutral-default-foreground: #b8bfcc; | |
| /* --- 6. Form & Input States --- */ | |
| --wb-semanticColor-input-default-background: #141923; | |
| --wb-semanticColor-input-default-foreground: #b8bfcc; | |
| --wb-semanticColor-input-error-background: #1a1320; | |
| --wb-semanticColor-input-disabled-background: #0c1016; | |
| /* --- 7. Math & Perseus Renderers (Preserving structural contrast) --- */ | |
| --wb-semanticColor-mafs-fg: var(--wb-semanticColor-core-foreground-neutral-default); | |
| --wb-semanticColor-mafs-line-color: var(--wb-semanticColor-core-border-neutral-default); | |
| --wb-semanticColor-mafs-blue: #6b82b3; | |
| --wb-semanticColor-mads-green: #4f8c62; | |
| --mafs-red: #963f48; | |
| --mafs-yellow: #a89345; | |
| --perseus-multiple-choice-divider-color: var(--wb-semanticColor-core-border-neutral-default); | |
| --perseus-multiple-choice-correctness-outline-color: #4f8c62; | |
| --perseus-multiple-choice-fade-color: var(--wb-semanticColor-core-background-base-strong); | |
| /* --- 8. Accessibility & Focus --- */ | |
| --wb-semanticColor-focus-outer: #6b82b3; | |
| --wb-semanticColor-focus-inner: #0f131a; | |
| --wb-semanticColor-link-rest: #6b82b3; | |
| --wb-semanticColor-link-hover: #7d91c4; | |
| --wb-semanticColor-link-press: #8ea0d5; | |
| } | |
| /* ========================================================================== | |
| TIER 2: THE CANVAS FOUNDATION | |
| ========================================================================== */ | |
| /* Force dark scheme natively to stop browser glare */ | |
| * { color-scheme: dark; } | |
| /* Root background enforcement and text anti-aliasing */ | |
| body, | |
| .wb-root-container { | |
| background-color: var(--wb-semanticColor-core-background-base-default) !important; | |
| color: var(--wb-semanticColor-core-foreground-neutral-default) !important; | |
| -webkit-font-smoothing: antialiased !important; | |
| -moz-osx-font-smoothing: grayscale !important; | |
| } | |
| /* Target legacy wrappers explicitly */ | |
| #outer-wrapper, | |
| #top-header-container, | |
| #footer { | |
| background-color: var(--wb-semanticColor-core-background-base-default) !important; | |
| background-image: none !important; | |
| } | |
| /* Force deeply nested footer lists to inherit typography correctly */ | |
| #footer *, | |
| #footer li, | |
| #footer a { | |
| color: var(--wb-semanticColor-core-foreground-neutral-default) !important; | |
| } | |
| /* Inputs & Textareas */ | |
| input:not(:disabled), | |
| textarea:not(:disabled) { | |
| background-color: var(--wb-semanticColor-input-default-background) !important; | |
| color: var(--wb-semanticColor-input-default-foreground) !important; | |
| border-color: var(--wb-semanticColor-core-border-neutral-default) !important; | |
| } | |
| /* Accessibility Ring softening */ | |
| :focus-visible { | |
| outline: 2px solid var(--wb-semanticColor-focus-outer) !important; | |
| outline-offset: 3px !important; | |
| border-radius: 3px !important; | |
| } | |
| /* ========================================================================== | |
| TIER 3: STRUCTURAL ARMOR (Defeating React Hydration specificities) | |
| ========================================================================== */ | |
| /* 1. The Surgical Hashes */ | |
| ._bnw2wia, | |
| ._am72iea { | |
| background: transparent !important; | |
| background-color: transparent !important; | |
| } | |
| /* 2. The Bulldozer Fallback | |
| Targets hashes, block-links, AND unclassed layout divs nesting inside lists. | |
| Forces both 'background' and 'background-color' to defeat shorthand overrides. */ | |
| #outer-wrapper div[class^="_"], | |
| #outer-wrapper ul[class^="_"], | |
| #outer-wrapper li[class^="_"], | |
| #outer-wrapper a[class^="_"]:has(div), | |
| #outer-wrapper ul > div, | |
| #outer-wrapper li > div, | |
| div[class*="Page"], | |
| div[class*="Layout"] { | |
| background: transparent !important; | |
| background-color: transparent !important; | |
| } | |
| /* 3. Kill hardcoded inline white styles injected during hydration */ | |
| *[style*="background-color: white" i], | |
| *[style*="background-color: rgb(255, 255, 255)" i], | |
| *[style*="background: #fff" i], | |
| *[style*="background: #ffffff" i], | |
| *[style*="background: white" i] { | |
| background: transparent !important; | |
| background-color: transparent !important; | |
| } | |
| /* 4. Standardized specific overrides */ | |
| .stp-animated-banner { | |
| background-color: var(--wb-semanticColor-core-background-base-subtle) !important; | |
| } | |
| /* ========================================================================== | |
| TIER 4: MORPHOLOGICAL UI (Targeting nodes by relationship, not by name) | |
| ========================================================================== */ | |
| /* 1. Neutralize small React UI wrappers (checkboxes, arrows, icon backgrounds) */ | |
| span:has(> svg), | |
| span:empty, | |
| button span, | |
| a span { | |
| background: transparent !important; | |
| background-color: transparent !important; | |
| } | |
| /* 2. Normalize SVG fills and strokes to match the new typography */ | |
| svg { | |
| fill: currentColor !important; | |
| color: var(--wb-semanticColor-core-foreground-neutral-strong) !important; | |
| } | |
| /* Inherit current color for paths, overriding hardcoded stroke colors */ | |
| svg path[stroke] { | |
| stroke: currentColor !important; | |
| } | |
| /* More forgiving (case-insensitive matching) */ | |
| p[style*="color:#21242c" i], | |
| p[style*="color: #21242c" i] { | |
| color: var(--wb-semanticColor-core-foreground-neutral-default) !important; | |
| } | |
| /* #>£#½ dollar support for KA and this seems a good enough start to write a dark-mode. | |
| I could resign from that team. */ | |
| span { | |
| color: var(--wb-semanticColor-core-foreground-neutral-default) !important; | |
| } | |
| div > ul > li > div > a > div > div + div { | |
| color: var(--wb-semanticColor-core-foreground-neutral-default) !important; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment