diff --git a/.forgejo/workflows/mirror.yml b/.forgejo/workflows/mirror.yml
deleted file mode 100644
index 2128050..0000000
--- a/.forgejo/workflows/mirror.yml
+++ /dev/null
@@ -1,21 +0,0 @@
-name: Mirror to GitHub
-
-on:
- push:
- branches: ['**']
- tags: ['**']
-
-jobs:
- mirror:
- runs-on: [self-hosted, hestia]
- steps:
- - name: Mirror to GitHub
- run: |
- set -euo pipefail
- git clone --mirror "https://git.breadway.dev/${GITHUB_REPOSITORY}.git" repo.git
- cd repo.git
- # Mirror only branches and tags (not refs/pull/*, which GitHub rejects);
- # --prune deletes GitHub refs that no longer exist on Forgejo.
- git push --prune \
- "https://x-access-token:${{ secrets.MIRROR_TOKEN }}@github.com/Breadway/bread-ecosystem.git" \
- '+refs/heads/*:refs/heads/*' '+refs/tags/*:refs/tags/*'
diff --git a/.forgejo/workflows/package.yml b/.forgejo/workflows/package.yml
deleted file mode 100644
index 6725e22..0000000
--- a/.forgejo/workflows/package.yml
+++ /dev/null
@@ -1,40 +0,0 @@
-name: Build and publish package
-
-on:
- push:
- tags: ['v*']
-
-jobs:
- package:
- runs-on: [self-hosted, hestia]
- container:
- image: archlinux:latest
- steps:
- # Note: no actions/checkout — the archlinux image has no Node, which JS
- # actions require. Everything runs as shell steps and clones manually.
- - name: Build and publish
- env:
- PUBLISH_TOKEN: ${{ secrets.REGISTRY_TOKEN }}
- run: |
- set -euo pipefail
- VERSION="${GITHUB_REF_NAME#v}"
- pacman -Syu --noconfirm base-devel git rust cargo
- useradd -m builder
- git config --global --add safe.directory '*'
- git clone --branch "${GITHUB_REF_NAME}" --depth 1 \
- "https://git.breadway.dev/${GITHUB_REPOSITORY}.git" /home/builder/src
- cd /home/builder/src
- git archive --format=tar.gz --prefix="bakery-${VERSION}/" HEAD \
- > packaging/arch/bakery-${VERSION}.tar.gz
- SHA=$(sha256sum packaging/arch/bakery-${VERSION}.tar.gz | awk '{print $1}')
- sed -i "s/^pkgver=.*/pkgver=${VERSION}/" packaging/arch/PKGBUILD
- sed -i "s/^sha256sums=.*/sha256sums=('${SHA}')/" packaging/arch/PKGBUILD
- chown -R builder:builder /home/builder/src
- # --nocheck: packaging builds the artifact; tests belong in a CI job.
- su builder -c "cd /home/builder/src/packaging/arch && makepkg -f --noconfirm --nocheck"
- PKG=$(find /home/builder/src/packaging/arch -name '*.pkg.tar.zst' | head -1)
- curl -fsS -X PUT \
- -H "Authorization: token ${PUBLISH_TOKEN}" \
- -H "Content-Type: application/octet-stream" \
- --data-binary "@${PKG}" \
- "https://git.breadway.dev/api/packages/Breadway/arch/os"
diff --git a/BREAD_DESIGN_SYSTEM.md b/BREAD_DESIGN_SYSTEM.md
deleted file mode 100644
index 942f7a2..0000000
--- a/BREAD_DESIGN_SYSTEM.md
+++ /dev/null
@@ -1,118 +0,0 @@
-# Bread Design System
-
-Unified visual identity for breadbar, breadbox, breadpad/breadman, and
-bos-settings.
-
-## Architecture (single source of truth)
-
-The tokens below are implemented once in the **`bread-theme`** crate as
-`stylesheet(&Palette)` — the full component stylesheet (buttons, entries,
-switches, lists/rows/sidebars, cards, chips, scrollbars, headings) over a
-canonical `@define-color` palette (`surface`=color0, `overlay`=color7,
-`accent`=color4).
-
-- The `bread-theme` **CLI** renders it from the live pywal palette to
- `$XDG_RUNTIME_DIR/bread/theme.css` (run at login and from a pywal hook).
-- Every GUI loads that file via `bread_theme::gtk::apply_shared()` and
- **live-reloads** it, then layers on only its own app-specific rules.
-
-Result: one definition, no per-app drift, and palette changes recolour the
-whole desktop with no rebuilds. Apps reference the shared `@define-color`
-names rather than raw palette slots.
-
-## Typography
-
-- **Font Family**: Varela Round, sans-serif
-- **Base Size**: 14px
-- **Secondary**: 12px (metadata, helper text, secondary labels)
-- **Font Weight**: Normal (400) for body, Bold (700) for emphasis
-
-## Spacing Scale (4px units)
-
-Use these values consistently across all projects:
-
-- **xs**: 4px (small gaps, internal padding)
-- **sm**: 8px (default spacing between elements)
-- **md**: 12px (medium spacing, main padding)
-- **lg**: 16px (large padding, major spacing)
-- **xl**: 20px (extra large spacing, section breaks)
-
-## Border Radius
-
-Establish a visual hierarchy with consistent rounding:
-
-- **Primary** (buttons, cards, main containers): **8px**
-- **Secondary** (input fields, chips, entries): **6px**
-- **Tertiary** (small interactive elements): **4px**
-- **Pill** (fully rounded buttons, badges): **999px**
-
-## Color System
-
-All projects use **pywal dynamic theming** with **Catppuccin Mocha** as the fallback palette:
-
-- **Background**: `#1e1e2e` (Catppuccin)
-- **Foreground**: `#cdd6f4` (Catppuccin)
-- **Surface**: `#181825` (Catppuccin)
-- **Accent**: Dynamic (from pywal)
-
-Color palette slots (via wal):
-- color0–color7: ANSI colors
-- Semantic: red, green, yellow, blue, pink, teal
-
-## Component Standards
-
-### Buttons
-- Border Radius: 8px
-- Padding: 8px 16px (primary), 4px 8px (secondary)
-- Font Size: 14px
-- Background: Theme accent color
-
-### Input Fields
-- Border Radius: 6px
-- Padding: 12px 16px
-- Font Size: 14px
-- Border: 1px or 2px solid (blue on focus)
-
-### Cards
-- Border Radius: 8px
-- Padding: 12px
-- Margin: 8px
-- Box Shadow: Optional, for depth
-
-### Stat Labels
-- Font Size: 14px
-- Margin Right (between icon/text): 5px
-- Group Margin Right: 12px
-
-### Notification Cards
-- Border Radius: 8px
-- Padding: 12px
-- Margin Bottom: 8px
-- Font Size: 14px (summary), 12px (body)
-
-## Current Implementation
-
-All GUI apps load `bread_theme::stylesheet` (via the generated shared file) and
-add only app-specific rules:
-
-- **breadbar** — shared base + bar window, workspace buttons, stats, notification
- and OSD cards.
-- **breadbox** — shared base + launcher panel, search entry, result rows.
-- **breadpad / breadman** — shared base + capture popup, type chips, note cards,
- reminder window, sidebar rows.
-- **bos-settings** — shared base + content padding only (was previously a
- hardcoded Nord palette; migrated to the shared stylesheet).
-- **breadcrumbs** — CLI tool; ANSI colours only, no GUI styling.
-
-> Palette note: the fallback is Catppuccin Mocha, but installs (e.g. BOS) drive
-> the real palette from pywal — BOS ships a black-base palette.
-
-## Future Consistency Checks
-
-When adding new components or updating existing ones:
-1. Use Varela Round for all text
-2. Set base font size to 14px (12px for secondary)
-3. Use spacing scale (4px units: 4, 8, 12, 16, 20)
-4. Use border radius from this system (8px default, 6px secondary)
-5. Leverage pywal colors for dynamic theming
-6. Keep margins/padding consistent across similar components
diff --git a/README.md b/README.md
index 1ec4cff..405c193 100644
--- a/README.md
+++ b/README.md
@@ -18,36 +18,6 @@ bakery install breadbar
| `breadcrumbs` | Profile-aware Wi-Fi state machine with Tailscale exit-node management and a self-healing watch daemon |
| `breadpad` | Quick-capture scratchpad popup with AI-powered note classification, reminders, recurrence, and a full note viewer (`breadman`) |
-## Recommended keybinds
-
-The ecosystem assumes a Hyprland setup with `SUPER` as the modifier. The
-conventional bindings (used by BOS and recommended for any install):
-
-| Keys | Action |
-|------|--------|
-| `SUPER+Space` | `breadbox` — app launcher |
-| `SUPER+U` | `breadpad` — quick-capture notes/reminders |
-| `SUPER+M` | `breadman` — note viewer / manager |
-| `SUPER+,` | settings (`bos-settings`, where installed) |
-
-`breadbar` and `breadd` are services started at login (`exec-once`), not bound
-to keys.
-
-## Theming
-
-All GUIs share one look via `bread-theme`. The `bread-theme` CLI renders the
-component stylesheet from your pywal palette (Catppuccin Mocha fallback) to
-`$XDG_RUNTIME_DIR/bread/theme.css`; every app loads that file and **live-reloads**
-it, so changing your wallpaper recolours the whole ecosystem with no rebuilds:
-
-```sh
-wal -i ~/Pictures/wall.png # regenerate pywal palette
-bread-theme generate # render the shared stylesheet (run from a wal hook)
-```
-
-See [`BREAD_DESIGN_SYSTEM.md`](BREAD_DESIGN_SYSTEM.md) for the tokens (fonts,
-spacing, radii, colour roles) the stylesheet is built from.
-
## Installing bakery
`bakery` is the package manager for the ecosystem. Install it with the bootstrap script:
diff --git a/bread-theme/Cargo.toml b/bread-theme/Cargo.toml
index 8dc41e7..39930a1 100644
--- a/bread-theme/Cargo.toml
+++ b/bread-theme/Cargo.toml
@@ -18,9 +18,3 @@ gtk4 = { version = "0.11", features = ["v4_12"], optional = true }
# Enable GTK4 CSS provider helpers (breadbar, breadbox, breadpad use this).
# bread (daemon) and breadcrumbs (CLI) depend on this crate without the feature.
gtk = ["dep:gtk4"]
-
-# The generator CLI. It only touches the gtk-free lib API (render + write), so
-# it builds without the gtk feature and stays light.
-[[bin]]
-name = "bread-theme"
-path = "src/bin/bread-theme.rs"
diff --git a/bread-theme/src/bin/bread-theme.rs b/bread-theme/src/bin/bread-theme.rs
deleted file mode 100644
index 266ea9c..0000000
--- a/bread-theme/src/bin/bread-theme.rs
+++ /dev/null
@@ -1,62 +0,0 @@
-//! `bread-theme` — generates the ecosystem's shared GTK stylesheet from the
-//! current pywal palette and writes it to the canonical path that every bread
-//! GUI loads. Run it at session start, and again after the wallpaper/palette
-//! changes (e.g. from a pywal hook); apps watch the file and recolour live.
-//!
-//! bread-theme # same as `generate`
-//! bread-theme generate # render + write the shared stylesheet
-//! bread-theme reload # re-render from the current pywal palette and
-//! # signal every running bread GUI to recolour
-//! bread-theme path # print the stylesheet path
-//! bread-theme print # render to stdout (no write)
-
-use std::process::ExitCode;
-
-fn write_and_report(verb: &str) -> ExitCode {
- match bread_theme::write_shared_css() {
- Ok(path) => {
- eprintln!("bread-theme: {verb} {}", path.display());
- ExitCode::SUCCESS
- }
- Err(e) => {
- eprintln!("bread-theme: failed to write stylesheet: {e}");
- ExitCode::FAILURE
- }
- }
-}
-
-fn main() -> ExitCode {
- let cmd = std::env::args().nth(1).unwrap_or_else(|| "generate".into());
- match cmd.as_str() {
- "path" => {
- println!("{}", bread_theme::shared_css_path().display());
- ExitCode::SUCCESS
- }
- "print" => {
- print!("{}", bread_theme::render());
- ExitCode::SUCCESS
- }
- "generate" => write_and_report("wrote"),
- // `reload` is `generate` from the caller's view, but it's the verb to use
- // after changing pywal colours: rewriting the file (atomic rename) trips
- // the file monitor in every running bread GUI, so they all re-read the
- // palette and recolour live — shared widgets *and* each app's own rules.
- "reload" => write_and_report("reloaded"),
- "-h" | "--help" | "help" => {
- eprintln!(
- "bread-theme — shared stylesheet generator\n\n\
- USAGE:\n bread-theme [generate|reload|path|print]\n\n\
- generate render the pywal palette to the shared stylesheet (default)\n\
- reload re-render and signal running bread GUIs to recolour live\n\
- path print the stylesheet path ({})\n\
- print render to stdout without writing",
- bread_theme::shared_css_path().display()
- );
- ExitCode::SUCCESS
- }
- other => {
- eprintln!("bread-theme: unknown command '{other}' (try generate|reload|path|print)");
- ExitCode::FAILURE
- }
- }
-}
diff --git a/bread-theme/src/gtk.rs b/bread-theme/src/gtk.rs
index aab7d01..6e62cb4 100644
--- a/bread-theme/src/gtk.rs
+++ b/bread-theme/src/gtk.rs
@@ -1,100 +1,7 @@
-use gtk4::gio;
-use gtk4::prelude::*;
use gtk4::CssProvider;
use std::cell::RefCell;
use std::path::Path;
-thread_local! {
- static SHARED_PROVIDER: RefCell