# Gogh Theme Engine A production-grade Chrome Extension (Manifest V3) that applies Gogh-style 16-color terminal palettes to all web pages by intelligently computing and rewriting styles at runtime using perceptual OKLCH color remapping. ## Features - **OKLCH Perceptual Color Model** — All color math uses OKLCH for perceptually uniform transformations - **Semantic Theme Derivation** — Automatically maps 16 terminal colors to semantic roles (error, success, accent, etc.) using hue + brightness analysis - **Smart DOM Processing** — TreeWalker-based traversal, MutationObserver with batched/debounced updates, Shadow DOM support - **WCAG Contrast Enforcement** — Ensures minimum 4.5:1 contrast ratio for text - **Gradient & SVG Support** — Parses and transforms CSS gradients and inline SVG fill/stroke - **Dynamic CSS Class Generation** — Reuses CSS classes instead of inline styles for performance - **Per-site Toggle** — Enable/disable theming on a per-domain basis - **Intensity Slider** — Blend between original and themed colors (0–100%) - **Options Page** — YAML editor, live preview, contrast diagnostics, site management ## Build Instructions ### Prerequisites - Node.js ≥ 18 - npm ≥ 9 ### Setup ```bash cd gogh-theme-engine npm install ``` ### Development Build (with watch) ```bash npm run dev ``` ### Production Build ```bash npm run build ``` ### Load in Chrome 1. Run `npm run build` 2. Open `chrome://extensions/` 3. Enable **Developer mode** 4. Click **Load unpacked** 5. Select the `dist/` folder ## Project Structure ``` src/ ├── background.ts # Service worker — storage, per-domain toggle, messaging ├── content.ts # Content script — DOM processing, style injection, coordination ├── color.ts # OKLCH color engine — all color math and transforms ├── themeEngine.ts # YAML parsing, validation, semantic theme derivation ├── observer.ts # DOM observation — TreeWalker, MutationObserver, Shadow DOM ├── js-yaml.d.ts # Type declarations for js-yaml └── options/ ├── options.html # Options page UI └── options.ts # Options page controller public/ ├── manifest.json # Manifest V3 configuration └── icons/ # Extension icons ``` ## Palette Format Provide a YAML palette in Gogh format: ```yaml name: My Theme author: Your Name variant: dark color_01: "#282a36" color_02: "#ff5555" color_03: "#50fa7b" color_04: "#f1fa8c" color_05: "#bd93f9" color_06: "#ff79c6" color_07: "#8be9fd" color_08: "#f8f8f2" color_09: "#44475a" color_10: "#ff6e6e" color_11: "#69ff94" color_12: "#ffffa5" color_13: "#d6acff" color_14: "#ff92df" color_15: "#a4ffff" color_16: "#ffffff" background: "#282a36" foreground: "#f8f8f2" cursor: "#f8f8f2" ``` ## How It Works ### Color Pipeline 1. **Parse** — CSS color strings are parsed into RGBA 2. **Convert** — RGBA → sRGB → Linear RGB → OKLAB → OKLCH 3. **Classify** — Colors are classified as neutral (achromatic) or chromatic with a hue bucket 4. **Remap** — Neutral colors map to surface/background bands; chromatic colors map to semantic roles 5. **Contrast** — WCAG contrast is enforced by adjusting the L (lightness) channel 6. **Blend** — Final color is blended with original based on intensity setting 7. **Cache** — Results are memoized by color + context key ### Theme Derivation Instead of fixed index mapping, semantic roles are derived by analyzing each palette color's OKLCH properties: - Red hue range → `error` - Green → `success` - Blue/Cyan → `accentPrimary` / `info` - Yellow/Orange → `warning` - Purple → `accentSecondary` - Low chroma → `muted` - Surface/border colors are synthesized from background by shifting lightness ## Architecture Notes - No naive CSS inversion or global filters - `TreeWalker` for initial traversal (faster than `querySelectorAll`) - `MutationObserver` with `requestIdleCallback` batching - `WeakSet` for tracking processed nodes - `Element.prototype.attachShadow` monkey-patching for shadow DOM - Dynamic CSS class generation with reuse to minimize inline styles - Transform results cached with LRU-like eviction (max 8192 entries)