{"id":50825350,"url":"https://github.com/parazeeknova/zen-wabi","last_synced_at":"2026-06-13T18:04:40.677Z","repository":{"id":362936601,"uuid":"1261353229","full_name":"parazeeknova/zen-wabi","owner":"parazeeknova","description":"Matugen-driven dynamic theme for Zen Browser wallpaper-aware, per-site, hot-reloadable","archived":false,"fork":false,"pushed_at":"2026-06-06T15:42:24.000Z","size":4529,"stargazers_count":5,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-06T17:13:37.890Z","etag":null,"topics":["dotfiles","firefox","hyprland","matugen","ricing","userchrome","userstyles","zen-browser","zen-browser-mod","zen-browser-theme"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/parazeeknova.png","metadata":{"files":{"readme":".github/README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-06T15:16:26.000Z","updated_at":"2026-06-06T17:04:29.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/parazeeknova/zen-wabi","commit_stats":null,"previous_names":["parazeeknova/zen-wabi"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/parazeeknova/zen-wabi","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/parazeeknova%2Fzen-wabi","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/parazeeknova%2Fzen-wabi/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/parazeeknova%2Fzen-wabi/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/parazeeknova%2Fzen-wabi/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/parazeeknova","download_url":"https://codeload.github.com/parazeeknova/zen-wabi/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/parazeeknova%2Fzen-wabi/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34294416,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-13T02:00:06.617Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dotfiles","firefox","hyprland","matugen","ricing","userchrome","userstyles","zen-browser","zen-browser-mod","zen-browser-theme"],"created_at":"2026-06-13T18:04:39.600Z","updated_at":"2026-06-13T18:04:40.671Z","avatar_url":"https://github.com/parazeeknova.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# zen-wabi\n\n![wabi](./assets/wabi.png)\n\n\u003e **Matugen-driven dynamic theme for [Zen Browser](https://zen-browser.app/) — wallpaper-aware, per-site, hot-reloadable.**\n\n`zen-wabi` turns the matugen palette generator into a live theming engine\nfor Zen Browser. The same wallpaper-switcher event that re-tints your\nterminal, status bar, and launcher also re-tints every tab you have open —\nincluding per-site overrides for sites like GitHub that have their own\ndesign system.\n\nThe repo ships three layers:\n\n1. **Browser chrome** — Zen's own UI (`userChrome.css` + `userContent.css`).\n2. **Per-site userstyles** — content CSS injected into matching hostnames\n   via Zen Boosts' `customCSS` field. Currently: `github.com` and\n   subdomains.\n3. **Universal tint** — every visited http(s) domain gets a Zen Boost\n   that drives Zen's C++ color-boost layer from the matugen accent.\n\nBoth layers read `--matugen-*` CSS variables, so a single palette change\nfades the entire browser from one look to another.\n\n---\n\n## Table of contents\n\n- [zen-wabi](#zen-wabi)\n  - [Table of contents](#table-of-contents)\n  - [How it works](#how-it-works)\n    - [Why a JSWindowActor?](#why-a-jswindowactor)\n    - [Why Zen Boosts for the universal tint?](#why-zen-boosts-for-the-universal-tint)\n  - [Features](#features)\n  - [Requirements](#requirements)\n  - [Installation](#installation)\n    - [1. Clone](#1-clone)\n    - [2. Deploy templates](#2-deploy-templates)\n    - [3. Install fx-autoconfig](#3-install-fx-autoconfig)\n    - [4. Enable the experimental actor runtime](#4-enable-the-experimental-actor-runtime)\n    - [5. Restart Zen](#5-restart-zen)\n    - [6. Trigger a wallpaper change](#6-trigger-a-wallpaper-change)\n  - [Usage](#usage)\n    - [Switching themes](#switching-themes)\n    - [Per-site toggling](#per-site-toggling)\n    - [Per-profile](#per-profile)\n    - [Logs](#logs)\n  - [Repository layout](#repository-layout)\n  - [Risks \\\u0026 limitations](#risks--limitations)\n    - [Hard risks](#hard-risks)\n    - [Soft limitations](#soft-limitations)\n    - [Known visual nits](#known-visual-nits)\n  - [Roadmap / TODOs](#roadmap--todos)\n    - [Short term](#short-term)\n    - [Medium term](#medium-term)\n    - [Long term](#long-term)\n    - [Done (recent)](#done-recent)\n  - [Contributing](#contributing)\n    - [Quick start](#quick-start)\n    - [Adding a new site](#adding-a-new-site)\n    - [Theming rules \\\u0026 conventions](#theming-rules--conventions)\n    - [Debugging tips](#debugging-tips)\n  - [License](#license)\n\n---\n\n## How it works\n\n```\n┌──────────────────┐    JSON     ┌──────────────────┐\n│  wallpaper       │────────────▶│  theme_switcher  │\n│  switcher (QML)  │             │  (Rust binary)   │\n└──────────────────┘             └────────┬─────────┘\n                                           │ renders templates\n                                           ▼\n                           ┌──────────────────────────────┐\n                           │  ~/.config/zen/\u003cprofile\u003e/    │\n                           │  chrome/                     │\n                           │    matugen-vars.json         │\n                           │    matugen-userstyles.css    │\n                           │    matugen-userstyles-       │\n                           │         github.css           │\n                           └────────┬─────────────────────┘\n                                    │ mtime watcher\n                                    ▼\n                           ┌──────────────────────────────┐\n                           │  matugen-bridge.uc.js        │\n                           │  (fx-autoconfig chrome side) │\n                           │   • sets prefs (8 vars)      │\n                           │   • updates :root in chrome  │\n                           │   • broadcasts to actors     │\n                           │   • syncs per-site CSS into  │\n                           │     Zen Boosts (customCSS)   │\n                           │   • creates universal Zen    │\n                           │     Boosts for visited       │\n                           │     http(s) domains          │\n                           │   • syncs workspace gradient │\n                           │     or HSL fallback          │\n                           └────────┬──────────┬──────────┘\n                                    │          │\n                            actor   │          │ Zen Boosts API\n                          messages  │          ▼\n                                    │  ┌──────────────────────┐\n                                    │  │  ZenBoostsParent     │\n                                    │  │   • reads customCSS  │\n                                    │  │   • registers as     │\n                                    │  │     AGENT_SHEET      │\n                                    │  │   • drives C++       │\n                                    │  │     color-boost      │\n                                    │  └────────┬─────────────┘\n                                    │           │\n                          ┌─────────▼──┐    ┌──▼──────────────┐\n                          │ Matugen    │    │ ZenBoostsChild  │\n                          │ Child      │    │  (per process)  │\n                          │ • :root    │    │  • applies CSS  │\n                           │ • userCSS  │    │  • applies tint │\n                           └────────────┘    └─────────────────┘\n```\n\nThe `theme_switcher` binary is the only piece this repo **does not**\nship — it is built from your wallpaper switcher's source tree and is\nexpected to know how to read the palette JSON and call\n`render_template()`. A reference implementation lives in the\n[dotfiles](https://github.com/parazeeknova/doty) used to develop this\nproject; see the [Contributing](https://github.com/parazeeknova/zen-wabi/blob/main/docs/ADDING-A-SITE.md) section for the\ntemplate-rendering contract.\n\n### Why a JSWindowActor?\n\nFirefox's `userContent.css` is unreliable in Zen ≥ 1.20 — it is gated\nbehind a pref that often resets, and `@-moz-document` rules only work\ninside `userContent.css`, not inside stylesheets dynamically injected\ninto the content process. The actor approach:\n\n- injects CSS as a real `\u003cstyle\u003e` element in the content document,\n- lets us match hostnames from the parent side (no hardcoded URL\n  prefixes in the CSS itself),\n- gets a clean re-injection point on theme change with no page reload,\n- survives Fission (multi-process) — each content process has its own\n  `MatugenChild`.\n\nFor per-site CSS injection we now **prefer Zen Boosts' `customCSS`\nfield** over the actor — Zen handles the `AGENT_SHEET` registration\nand Fission correctly out of the box. The actor is kept for the\n`:root` variable push (which Zen Boosts don't expose a public API\nfor) and as a fallback for per-site content.\n\n### Why Zen Boosts for the universal tint?\n\nZen's C++ color-boost layer is what actually tints pixel content on\na page (think: an HSL hue shift applied as a paint pass). It reads\nfrom the active Zen Boost's dot-picker knobs (HSL) or from\n`workspace.theme.gradientColors[primary].c` when `autoTheme: true`.\nBy creating one boost per visited domain, we get this tint for free\non every site — no per-site CSS template needed.\n\n---\n\n## Features\n\n- **Hot reload, no restart.** Change wallpapers and every open tab\n  fades from the old palette to the new one in 0.35s. No reload, no\n  flicker.\n- **Universal Zen Boost tint (quick path).** Every visited http(s)\n  domain auto-gets a Zen Boost that drives Zen's C++ color-boost\n  layer from your matugen accent. Zero config — just visit a site.\n  Hot-swaps on every wallpaper change.\n- **Per-site overrides (detailed path).** The bridge ships\n  `matugen-userstyles-\u003csite\u003e.css` per supported site. Contents are\n  pushed into the site's Zen Boost `customCSS` field (registered\n  as `AGENT_SHEET`). Currently: `github.com` and subdomains.\n  **GitHub coverage is functional but a work in progress** — most\n  pages look right, but specific elements (Pinned cards on the\n  dashboard, some dropdowns, niche admin pages) still leak the\n  default Primer styling. Pull requests welcome.\n- **No hardcoded CSS class names** for Primer/React components. Every\n  `prc-ModuleName-HASH` selector is written as `[class*=\"prc-ModuleName\"]`\n  so GitHub's nightly deploys don't break the theme.\n- **Smooth color transitions.** 0.35s ease on `background-color`,\n  `color`, `border-color`, `fill`, `stroke`, and `box-shadow` for every\n  element. Looks like a real desktop theme, not a flash-cut.\n- **No \"card look\" leak.** Surfaces blend to the page background\n  (`--matugen-bg`); only true content cards (pinned items, file tree\n  rows, code viewer) get the lighter `--matugen-bg-dark` tint.\n- **Catppuccin-faithful accents.** The 26 Catppuccin colors are mapped\n  to 8 matugen variables; the danger color stays a neutral rose that\n  reads correctly on both warm and cool palettes.\n- **Per-profile isolation.** Each Zen profile under\n  `~/.config/zen/\u003cprofile\u003e/chrome/` is independent. You can theme one\n  profile for work and another for personal without cross-talk.\n- **Workspaces-aware.** With Zen Workspaces enabled, the bridge\n  pushes the accent into your active workspace's gradient palette\n  and fires `zen-space-gradient-update` so the C++ layer re-tints.\n  With Workspaces disabled, it falls back to writing the accent as\n  HSL (`dotAngleDeg`/`saturation`/`brightness`) directly on each\n  universal boost.\n\n---\n\n## Requirements\n\n| Tool         | Version  | Notes                                    |\n| ------------ | -------- | ---------------------------------------- |\n| Zen Browser  | ≥ 1.20   | Earlier builds lack Fission-safe actors. |\n| matugen      | latest   | Generates the JSON palette.              |\n| A matugen-   | any      | Hyprland, Quickshell, river, sway, etc.  |\n| aware WM     |          |                                          |\n| fx-autoconfig| latest   | Provides the `JSWindowActor` runtime.    |\n| Rust (build) | stable   | Only needed if rebuilding `theme_switcher`. |\n\nYou also need a wallpaper that goes through matugen — the color\nextraction is the palette source. If your WM doesn't run matugen yet,\nsee [Adding a new site](#adding-a-new-site) for the JSON contract and\nadapt any external palette source.\n\n---\n\n## Installation\n\n### 1. Clone\n\n```sh\ngit clone https://github.com/parazeeknova/zen-wabi.git ~/Repository/zen-wabi\n```\n\n### 2. Deploy templates\n\nThe repo ships `*.template` files. Either:\n\n- copy them into your existing `~/.config/zen/` and let your\n  `theme_switcher` render them on next wallpaper change, **or**\n- symlink them so template edits are live:\n\n  ```sh\n  ln -sf ~/Repository/zen-wabi/userChrome.css.template \\\n         ~/.config/zen/userChrome.css.template\n  ln -sf ~/Repository/zen-wabi/userContent.css.template \\\n         ~/.config/zen/userContent.css.template\n  ln -sf ~/Repository/zen-wabi/userContent.github.template \\\n         ~/.config/zen/userContent.github.template\n  ln -sf ~/Repository/zen-wabi/user.js.template \\\n         ~/.config/zen/user.js.template\n  ```\n\n### 3. Install fx-autoconfig\n\nThe `fx-autoconfig/` directory in this repo is a **drop-in** for the\n`fx-autoconfig` Zen distribution layout:\n\n```sh\n# merge with the rest of your fx-autoconfig config\ncp -r fx-autoconfig/* /opt/zen-browser-bin/\n```\n\nIf you use a different fx-autoconfig layout, just merge the contents\nof `fx-autoconfig/profile/chrome/JS/Matugen/` and the bridge file into\nyour existing `chrome/JS/` directory.\n\n### 4. Enable the experimental actor runtime\n\nAdd to `~/.config/zen/\u003cprofile\u003e/user.js`:\n\n```js\nuserChromeJS.experimental.enabled = true;\n```\n\n(The `user.js.template` already does this — merge it into your\nexisting `user.js` if you have one.)\n\n### 5. Restart Zen\n\n```sh\npkill -9 zen-bin\n/opt/zen-browser-bin/zen-bin \u0026\n```\n\nTail the bridge log to confirm boot:\n\n```sh\ntail -f ~/.config/zen/\u003cprofile\u003e/chrome/matugen-bridge.log\n```\n\nYou should see:\n\n```\n[matugen-bridge] [INFO] SCRIPT TOP  version 1.4\n[matugen-bridge] [INFO] Registered Matugen JSWindowActor\n[matugen-bridge] [INFO] Watching: .../matugen-userstyles*.css\n```\n\n### 6. Trigger a wallpaper change\n\nSwitch your wallpaper through whatever mechanism your WM exposes\n(Hyprland `hyprpaper`, `swaybg`, `wpaperd`, `wallutils`, etc.). The\nswitcher should call:\n\n```sh\ntheme_switcher wallpaper /path/to/wallpaper.jpg\n```\n\nEvery open GitHub tab will fade from the old palette to the new one\nover ~0.35s.\n\n---\n\n## Usage\n\n### Switching themes\n\nTheme changes are driven by the wallpaper event — there is no manual\n\"rebuild CSS\" step. If you want to test a palette without changing\nwallpaper:\n\n```sh\ntheme_switcher palette /path/to/matugen-vars.json\n```\n\nThe JSON must have these keys:\n\n```json\n{\n  \"accent\":      \"#fcb974\",\n  \"bg\":          \"#19120c\",\n  \"bg_dark\":     \"#261e18\",\n  \"bg_light\":    \"#50453a\",\n  \"fg\":          \"#eee0d5\",\n  \"fg_light\":    \"#cdb89e\",\n  \"secondary\":   \"#3a3027\",\n  \"tertiary\":    \"#5a4c40\"\n}\n```\n\n### Per-site toggling\n\nTo disable a site theme without removing the file, rename it to drop\nthe `.css` extension — the bridge only loads `matugen-userstyles*.css`.\n\n### Per-profile\n\nThe bridge auto-detects the running profile by reading its own\nlocation at startup. Two Zen profiles running side-by-side are\nfully isolated: each has its own `matugen-vars.json` watcher and\nits own set of injected styles.\n\n### Logs\n\n```sh\ntail -f ~/.config/zen/\u003cprofile\u003e/chrome/matugen-bridge.log\n```\n\nThe log is overwritten on every restart (the bridge opens it with\n`O_TRUNC`). The actor child re-forwards its log lines to the parent\nvia `sendSyncMessage`, so this single file is the only place you need\nto look.\n\n---\n\n## Repository layout\n\n```\nzen-wabi/\n├── README.md                        ← you are here\n├── .gitignore\n├── userChrome.css.template          ← Zen chrome (9 sections)\n├── userContent.css.template         ← global :root vars + about:*\n├── userContent.github.template      ← github.com / *.github.com\n├── user.js.template                 ← required Zen prefs\n├── fx-autoconfig/\n│   ├── program/\n│   │   ├── config.js                ← fx-autoconfig entry\n│   │   └── defaults/pref/\n│   │       └── config-prefs.js\n│   └── profile/chrome/\n│       ├── utils/                   ← fx-autoconfig runtime\n│       │   ├── boot.sys.mjs\n│       │   ├── chrome.manifest\n│       │   ├── fs.sys.mjs\n│       │   ├── module_loader.mjs\n│       │   ├── uc_api.sys.mjs\n│       │   └── utils.sys.mjs\n│       └── JS/\n│           ├── matugen-bridge.uc.js ← theme_switcher ↔ actors\n│           └── Matugen/\n│               ├── MatugenParent.sys.mjs\n│               └── MatugenChild.sys.mjs\n├── docs/                            ← per-site how-tos (see Contributing)\n│   ├── ADDING-A-SITE.md\n│   ├── THEMING-RULES.md\n│   └── DEBUGGING.md\n└── sites/                           ← per-site userstyles (planned)\n    ├── github.userstyles.template\n    └── ...\n```\n\n---\n\n## Risks \u0026 limitations\n\n\u003e **Read this section before reporting an issue.** Most \"the theme\n\u003e broke\" reports are one of these.\n\n### Hard risks\n\n- **fx-autoconfig required.** Without it, the bridge script never\n  loads and the actor never registers. Zen 1.20 ships without\n  autoconfig enabled by default — install it from\n  [https://github.com/MrOtherGuy/fx-autoconfig](https://github.com/MrOtherGuy/fx-autoconfig).\n- **`userChromeJS.experimental.enabled = true` must be set.** The\n  JSWindowActor runtime is gated behind this pref. If it's missing,\n  the bridge logs `ChromeUtils.registerWindowActor is not a function`.\n- **CSS variables don't cross document boundaries.** Chrome vars\n  (`:root` in `userChrome.css`) are not visible in content documents.\n  That's why we re-set `--matugen-*` on `html[data-color-mode]` in\n  `userContent.github.template` — a second copy of the variables.\n- **`@-moz-document` is ignored in injected `\u003cstyle\u003e` elements.** It\n  only works in `userContent.css`. Per-site stylesheets are filtered\n  by hostname **on the parent side** before the actor ever sees them.\n- **Single `export class` per ESM file.** Defining `MatugenChild`\n  twice in the same file (e.g. once at the top, once in an alternate\n  import path) throws `SyntaxError: Identifier 'MatugenChild' has\n  already been declared` at MODULE LOAD — not at first use.\n- **CSS in `userContent.css` is unreliable on Zen 1.20.1b.** The\n  pref exists but doesn't always load. We compensate by injecting\n  the same rules via the actor.\n\n### Soft limitations\n\n- **GitHub coverage is a work in progress.** The template is\n  3700+ lines and covers most pages, but specific elements still\n  leak the default Primer styling — dashboard Pinned cards, some\n  dropdown menus, niche admin pages. The universal Zen Boost tint\n  handles these cases gracefully (it tints *every* site), but the\n  explicit per-site CSS is under active finetuning. PRs welcome.\n- **GitHub Primer hashes can rotate.** Today the rule is\n  `[class*=\"prc-Button-ButtonBase\"]`. If GitHub renames the\n  module, the wildcard still matches (it falls through to the\n  prefix), but a renamed module needs a new rule.\n- **Universal Zen Boost creates a boost per domain.** Every http(s)\n  domain you visit gets a boost entry in `zen-boosts.json`. Over\n  months of browsing this can grow to hundreds of entries. Zen\n  handles this fine (the JSON is re-read on every boost lookup)\n  but if you're a privacy-sensitive user, prune the file\n  periodically.\n- **Universal tint is hue-only.** It does not restyle surfaces,\n  borders, or text contrast. It changes the hue of whatever the\n  page already shows. For sites where the default is white-on-white\n  in light mode, the tint won't fix readability — use a per-site\n  template for those.\n- **No form control theming in `userChrome.css`.** `\u003cinput\n  type=\"checkbox\"\u003e` etc. would leak styling to every website. The\n  GitHub ruleset themes the in-content checkboxes via\n  `[class*=\"prc-Checkbox-Checkbox\"]` selectors instead.\n- **Two Zen profiles = two bridges.** Each profile has its own\n  `chrome/` and its own actor registration. Switching wallpapers\n  only refreshes the active profile's tabs.\n- **Smooth transitions have a small perf cost.** `transition: *` on\n  `*` is ~0.5% extra paint time on slow GPUs. Negligible on modern\n  hardware, noticeable on a 2015 ThinkPad.\n- **No wayland-specific features.** This is a CSS / JS layer; it\n  has nothing to do with Wayland. It will work in any Zen session.\n\n### Known visual nits\n\n- The \"Public\" repo badge is the `--color-btn-primary-bg` accent on\n  `--color-fg-on-emphasis` dark text. On very low-contrast palettes\n  the badge may be hard to read. Fix in\n  `userContent.github.template:Label--secondary` rule.\n- GitHub's search filter input has a hidden measurement mirror div\n  (`aria-hidden=\"true\"`) that GitHub uses to size the input. We push\n  it off-screen with `position: absolute; top: -9999px; visibility:\n  hidden`. If you remove that rule, the input will show duplicate\n  text.\n\n---\n\n## Roadmap / TODOs\n\n### Short term\n\n- [ ] **More sites.** Add userstyles for: YouTube, Reddit, Mastodon\n      instances, Hacker News, Twitter/X, Gmail, Google Docs, Notion,\n      Linear, Figma. The GitHub file is the reference implementation.\n- [ ] **Light-palette first-class support.** Right now everything\n      assumes `--matugen-bg` is the darkest. On a true light palette\n      that breaks — `bg` is the lightest, `bg-dark` is the medium\n      surface. The CSS uses `color-mix(in srgb, ...)` in a few\n      places to handle this, but the rule order needs auditing.\n- [ ] **CSS variable parity check.** Confirm that the chrome\n      variables and the content variables don't drift. Right now\n      they're duplicated in `userChrome.css.template` and\n      `userContent.github.template`; a single source of truth would\n      be better.\n- [ ] **Auto-extract PrimeReact / Material / Chakra tokens.** Add\n      a small CLI that walks a site, finds the CSS vars it actually\n      uses, and emits a starter template.\n\n### Medium term\n\n- [ ] **Per-site config files** with per-site settings (toggle\n      animations, force dark mode for the page, override the danger\n      color, etc.). Move the hostname-match table out of the\n      bridge into a JSON config.\n- [ ] **Hover-state color extraction.** Generate accent-tinted\n      hover states automatically from the base accent, instead of\n      hand-writing `color-mix(in srgb, accent 88%, fg 12%)` for\n      every button.\n- [ ] **Wider Zen coverage.** Sidebery workspace indicator, Zen\n      Glance, Zen Split View, Zen Picture-in-Picture, Zen Modals.\n      These are all `userChrome.css` work.\n- [ ] **A \"dev mode\" that pulls the live matugen JSON from the\n      current wallpaper and re-applies every N seconds** so you can\n      see the theme work without actually changing wallpaper.\n\n### Long term\n\n- [ ] **Native theming API.** Replace the `theme_switcher` shell-out\n      with a D-Bus signal that the bridge listens for. Eliminates\n      the file-watcher round-trip and works in non-Linux WMs.\n- [ ] **Theme presets** that ship as `.json` files — \"Catppuccin\n      Mocha\", \"Gruvbox\", \"Nord\", \"Rose Pine\", etc. — selectable\n      independent of the wallpaper. Useful for screenshots and\n      accessibility audits.\n- [ ] **A webview-mode theme picker** — a Zen sidebar panel that\n      lets you switch palettes without leaving the page you're\n      theming.\n\n### Done (recent)\n\n- [x] Matugen CSS variables on `:root` for both chrome and content.\n- [x] JSWindowActor-based content injection (survives Fission).\n- [x] **Zen Boost universal tint.** Every visited http(s) domain\n      auto-gets a Zen Boost driving the C++ color-boost layer from\n      the matugen accent. Hot-swaps on every wallpaper change.\n- [x] **Zen Boost per-site CSS.** Per-site templates are pushed\n      into the site's Zen Boost `customCSS` field (AGENT_SHEET),\n      eliminating the need for our own actor to handle per-site\n      injection.\n- [x] **Workspace gradient sync.** Bridge pushes the matugen\n      accent into `gZenWorkspaces.getActiveWorkspace().theme.gradientColors`\n      and fires `zen-space-gradient-update`. With workspaces\n      disabled, falls back to HSL on each universal boost.\n- [x] **Rename-to-disable.** Renaming\n      `matugen-userstyles-\u003csite\u003e.css` to `.css.disabled` clears\n      the per-site CSS from the boost; the domain falls through\n      to the universal tint.\n- [x] 109 `[class*=\"prc-...\"]` wildcards covering all Primer modules\n      used on profile, dashboard, and repo pages.\n- [x] File tree, file preview, file nav bar, header bar, action\n      buttons, PR/issue list, filter search bar — all themed.\n- [x] Smooth 0.35s color transitions on theme switch.\n- [x] Transparent user-status button + circle badge.\n- [x] Removed Refined GitHub heat-map coloring on `\u003crelative-time\u003e`.\n\n---\n\n## Contributing\n\n**The main objective of this project is for contributors to add\nsupport for new websites and to improve the GitHub coverage.** The\nGitHub file is the reference implementation — copy its style, copy\nits conventions, and submit a PR.\n\n### Quick start\n\n1. Fork this repo.\n2. **Decide which path you need:**\n   - **Quick path (universal Zen Boost tint)** — works for every\n     site out of the box, no code changes. See the top of\n     [docs/ADDING-A-SITE.md](docs/ADDING-A-SITE.md).\n   - **Detailed path (per-site CSS template)** — copy the\n     GitHub template as a starting point and write per-site\n     overrides. See the rest of\n     [docs/ADDING-A-SITE.md](docs/ADDING-A-SITE.md).\n3. If you take the detailed path, add a `BOOST_SITES` entry in\n   `fx-autoconfig/profile/chrome/JS/matugen-bridge.uc.js` (the\n   table at the top of the file). This binds the hostname to a\n   CSS file.\n4. Submit a PR with:\n   - the new template file (or just the bridge change if you only\n     fixed a regression),\n   - the corresponding `BOOST_SITES` entry,\n   - a screenshot of before/after,\n   - a one-line entry in this README's \"Features\" section.\n\n### Adding a new site\n\nSee [docs/ADDING-A-SITE.md](docs/ADDING-A-SITE.md) for a full\nwalkthrough. TL;DR:\n\n1. Generate a `.css.template` from the site's design tokens.\n2. Use the 8 matugen variables — never hardcode hex.\n3. Use `[class*=\"...\"]` wildcards for hashed class names.\n4. Aim for \"blends to page bg\" — not \"every box is a card\".\n5. Test on at least: profile/account, dashboard/home, a content\n   page, a search/filter page, and a modal.\n\n### Theming rules \u0026 conventions\n\nSee [docs/THEMING-RULES.md](docs/THEMING-RULES.md) for the\nnon-obvious ones. The short version:\n\n- **`bg` = page background, `bg-dark` = card surface, `bg-light` =\n  hover/elevated.** Don't use `bg-light` for body backgrounds; it\n  reads as a \"raised\" color.\n- **No `border: 1px solid` on action buttons.** Use `bg-dark` with\n  no border; the bg difference is the affordance.\n- **Accent is for links, focus rings, and the accent border on\n  popups.** Don't tint large surfaces with accent — it makes the\n  whole page vibrate.\n- **Never round the corners.** This is a sharp / flat theme. If\n  the site uses `border-radius: 8px`, set it to `0`.\n- **Transitions only on `background-color`, `color`,\n  `border-color`, `fill`, `stroke`, `box-shadow`.** Don't add\n  `transition: all` — it animates `transform` and `opacity` on\n  spinners, which is wrong.\n\n### Debugging tips\n\nSee [docs/DEBUGGING.md](docs/DEBUGGING.md). The 30-second version:\n\n```sh\n# is the bridge alive?\ntail -f ~/.config/zen/\u003cprofile\u003e/chrome/matugen-bridge.log\n\n# did the CSS file get rendered?\nls -la ~/.config/zen/\u003cprofile\u003e/chrome/matugen-userstyles*.css\n\n# is the actor registered? (open about:debugging → This Firefox → tabs)\n# search for \"MatugenChild\" in the process list\n```\n\nFor inspecting a specific element, use `about:devtools-toolbox` →\nInspector → click the element → look at the `Style` panel for\n`background-color: var(--matugen-...)`. If a `!important` rule from\nGitHub's Primer is winning, prefix your override with `:where()` to\nkeep specificity at 0, or use `[class*=\"...\"]` with a longer\nsuffix.\n\n---\n\n## License\n\nMIT. See the source headers — the original fx-autoconfig runtime\nfiles retain their respective licenses (BSD-2-Clause for utils.*,\nMPL-2.0 for the bridge).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fparazeeknova%2Fzen-wabi","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fparazeeknova%2Fzen-wabi","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fparazeeknova%2Fzen-wabi/lists"}