diff --git a/README.md b/README.md index 82e102e..3202934 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ Flat on purpose. Two module trees, one options file each, no hidden layers. ├── flake.nix # inputs + the downstream API (exports below) ├── lib.nix # nomarchy.lib.mkFlake — one-call downstream wrapper ├── state.json # ★ THE single source of truth (git-tracked!) -├── themes/ # 24 presets: .json + optional / assets +├── themes/ # 28 presets: .json + optional / assets │ ├── nord.json # palette (required, works alone) │ └── nord/ # assets (optional, fixed filenames) │ ├── backgrounds/ # wallpapers (pinned nomarchy-wallpapers input, not this repo) @@ -440,8 +440,9 @@ per theme — a single place to look, unlike the old distro's split: | `waybar.jsonc` | whole-swap for the bar *layout* (must be plain JSON) | | `rofi.rasi` | **whole-swap**: replaces the generated launcher/menu theme entirely | -Four themes ship a `waybar.css` identity (summer-day, summer-night, -executive-slate, boreal). Custom user themes can live in +Eight themes ship a `waybar.css` identity: the three Nomarchy-exclusive +day/night pairs — boreal ↔ boreal-dawn, executive-slate ↔ executive-ivory, +kiln ↔ kiln-clay — plus summer-night ↔ summer-day. Custom user themes can live in `$NOMARCHY_PATH/themes/` (preset lookup) and `nomarchy.themesDir` (eval-time asset probe) — including their own `backgrounds/`, which wins over the pinned `nomarchy-wallpapers` input (checked first); an explicit `wallpaper` @@ -450,7 +451,7 @@ path in `state.json` works too. ## 5. Day-to-day ```sh -nomarchy-state-sync list # 24 presets (nord, gruvbox, rose-pine, …) +nomarchy-state-sync list # 28 presets (nord, gruvbox, rose-pine, …) nomarchy-state-sync apply kanagawa # whole desktop, one generation (~a switch) nomarchy-state-sync set ui.gapsOut 16 # tweak one knob (also a switch) nomarchy-state-sync bg next # cycle wallpapers — instant, no rebuild diff --git a/agent/BACKLOG.md b/agent/BACKLOG.md index ee62a1c..4bef0ff 100644 --- a/agent/BACKLOG.md +++ b/agent/BACKLOG.md @@ -129,6 +129,21 @@ high-ROI, etc.) live in the journal + ROADMAP — not here.* ### Product / day-2 +### 153. Desktop widgets (clock / system stats) as an opt-in per-theme surface + +Pitch (filed while shipping the three exclusive theme pairs, 2026-07-18): +themed desktop widgets — a clock, calendar, or system-stats panel living on +the wallpaper, conky-style — would deepen the identity themes (imagine +kiln's copper stats panel or executive-ivory's letterhead clock). No such +surface exists today, so it is a NEW theming surface: per CONVENTIONS it +must consume the palette from the state JSON (no side pipeline) and ship +as an opt-in `nomarchy.*` toggle with a commented template example. Engine +choice is the real decision — conky is X11-era; a Wayland layer-shell +widget system (eww or a small QML/GTK layer-shell tool) fits the stack +better. Cost: moderate (engine spike + palette bridge + 2–3 widget +layouts; start with the exclusive pairs only, not all 28 themes). Value: +v1+ polish, not a v1 blocker. + ### 146. `[watch]` hypridle hangs instead of exiting when its compositor vanishes **Rewritten 2026-07-16, hours after filing: the premise was disproven and almost diff --git a/agent/CONVENTIONS.md b/agent/CONVENTIONS.md index ac43422..78805c6 100644 --- a/agent/CONVENTIONS.md +++ b/agent/CONVENTIONS.md @@ -46,7 +46,8 @@ those, it probably shouldn't exist. named `writeShellScriptBin`s on PATH (so static configs can exec them by bare name), and are added to **both** the generated `waybar.nix` config **and** every `waybar.jsonc` whole-swap — summer-day, summer-night, - executive-slate and boreal (the parity rule). + executive-slate, executive-ivory, boreal, boreal-dawn, kiln and + kiln-clay (the parity rule). - **Theming:** every new visual surface consumes the palette from the state JSON. There is no second renderer to keep in sync — add the key to the JSON, consume it in the module. diff --git a/agent/HARDWARE-QUEUE.md b/agent/HARDWARE-QUEUE.md index a3211f9..41adc82 100644 --- a/agent/HARDWARE-QUEUE.md +++ b/agent/HARDWARE-QUEUE.md @@ -28,6 +28,27 @@ Everything else below stays open; order is convenience, not a gate. ## Any machine (dev box is fine) +- [ ] **Theme pairs V3 — the four new themes on real GL** — after pulling + the pair commits: `nomarchy-state-sync apply ` for each of + boreal-dawn, executive-ivory, kiln, kiln-clay. Pass = all of: + (1) the bar renders true — boreal-dawn's frosted pills actually blur + what's behind them (softGL VM can't prove blur), kiln's plank shows + its copper edge, no font-fallback boxes (GeistMono / JetBrainsMono / + CaskaydiaCove); (2) wallpaper paints at native res, no banding on the + kiln ember gradient; (3) Kitty + btop under each theme — btop colors + match (the VM never started the GL terminal; btop.theme is + file-asserted only); (4) boreal-dawn app launcher (SUPER+Space) lays + out its icon grid; (5) an nm-applet/tray menu is readable under all + four (the `*`-reset counter-rules). If a VM-rendered preview looks + off in the theme-picker grid next to the hardware-captured ones, + recapture that preview on hardware into themes//preview.png. +- [ ] **Auto-theme pair flip on hardware** — set + `settings.autoTheme.{day,night}` to one of the new pairs (e.g. + kiln-clay / kiln), force sunrise/sunset around the current time, + let the timer flip once each way. Pass = the whole desktop switches + in one generation, and nothing leaks from the previous theme — + fonts, rounding, terminal opacity all reset (the per-theme + appearance block), wallpaper follows. - [ ] **#148 dock-intent enforcement without auto-profiles (dev box, docked)** — after pulling the #148 commit: **log out and back in first** — the watcher is `exec-once`, so `nomarchy-home` alone leaves the old one diff --git a/docs/OVERRIDES.md b/docs/OVERRIDES.md index 3ec9846..4b7aa44 100644 --- a/docs/OVERRIDES.md +++ b/docs/OVERRIDES.md @@ -67,7 +67,7 @@ State lives in `settings.autoTheme`: | Field | Meaning | |---|---| | `enable` | on / off | -| `day` / `night` | theme slugs — e.g. `summer-day` / `summer-night` (see `nomarchy-state-sync list`) | +| `day` / `night` | theme slugs (see `nomarchy-state-sync list`) — the exclusive pairs are made for this: `boreal-dawn`/`boreal`, `executive-ivory`/`executive-slate`, `kiln-clay`/`kiln`, `summer-day`/`summer-night` | | `sunrise` / `sunset` | switch times, `"HH:MM"` (24-hour) | A timer re-checks every ~15 minutes: the day theme applies around sunrise, the diff --git a/themes/kiln-clay.json b/themes/kiln-clay.json new file mode 100644 index 0000000..bb99acf --- /dev/null +++ b/themes/kiln-clay.json @@ -0,0 +1,60 @@ +{ + "version": 1, + "name": "Kiln Clay", + "slug": "kiln-clay", + "mode": "light", + "wallpaper": "", + "colors": { + "base": "#F4EDE3", + "mantle": "#DFD4C4", + "surface": "#EAE1D3", + "overlay": "#B1A28E", + "text": "#39302A", + "subtext": "#5D5142", + "muted": "#877867", + "accent": "#A34F1F", + "accentAlt": "#75621A", + "good": "#586F26", + "warn": "#8A5E08", + "bad": "#AC3B31" + }, + "border": { + "active": "accent", + "inactive": "overlay" + }, + "fonts": { + "mono": "CaskaydiaCove Nerd Font", + "ui": "Inter", + "size": 11 + }, + "ui": { + "gapsIn": 5, + "gapsOut": 12, + "borderSize": 2, + "rounding": 8, + "iconSize": 40, + "activeOpacity": 1.0, + "inactiveOpacity": 0.95, + "terminalOpacity": 0.95, + "blur": true, + "shadow": true + }, + "ansi": [ + "#39302A", + "#AC3B31", + "#586F26", + "#8A5E08", + "#3E5F8A", + "#7E4A8A", + "#33705F", + "#F4EDE3", + "#877867", + "#C05045", + "#6A8332", + "#A06E10", + "#4E70A0", + "#96609F", + "#418472", + "#FAF6EF" + ] +} diff --git a/themes/kiln-clay/btop.theme b/themes/kiln-clay/btop.theme new file mode 100644 index 0000000..5b30cd6 --- /dev/null +++ b/themes/kiln-clay/btop.theme @@ -0,0 +1,25 @@ +theme[main_bg]="#F4EDE3" +theme[main_fg]="#39302A" +theme[title]="#39302A" +theme[hi_fg]="#A34F1F" +theme[selected_bg]="#EAE1D3" +theme[selected_fg]="#39302A" +theme[inactive_fg]="#877867" +theme[graph_text]="#5D5142" +theme[meter_bg]="#DFD4C4" +theme[proc_misc]="#75621A" +theme[cpu_box]="#A34F1F" +theme[mem_box]="#586F26" +theme[net_box]="#75621A" +theme[proc_box]="#B1A28E" +theme[div_line]="#B1A28E" +theme[temp_start]="#586F26" +theme[temp_mid]="#8A5E08" +theme[temp_end]="#AC3B31" +theme[cpu_start]="#586F26" +theme[cpu_mid]="#8A5E08" +theme[cpu_end]="#AC3B31" +theme[free_start]="#586F26" +theme[used_start]="#8A5E08" +theme[download_start]="#A34F1F" +theme[upload_start]="#75621A" diff --git a/themes/kiln-clay/preview.png b/themes/kiln-clay/preview.png new file mode 100644 index 0000000..7545a4d Binary files /dev/null and b/themes/kiln-clay/preview.png differ diff --git a/themes/kiln-clay/rofi.rasi b/themes/kiln-clay/rofi.rasi new file mode 100644 index 0000000..d391128 --- /dev/null +++ b/themes/kiln-clay/rofi.rasi @@ -0,0 +1,122 @@ +/** + * Kiln Clay — rofi whole-swap (themes//rofi.rasi). + * The base theme: the same solid clay panel as Kiln, lit by midday + * terracotta edge glow instead of ember-copper — cream plaster, not + * frost or glass. Element structure mirrors the generated theme so the + * theme-grid picker's per-invocation -theme-str still lays out. The + * `configuration {}` block is omitted on purpose — it comes from + * modules/home/rofi.nix. + */ + +* { + base: #F4EDE3; + panelBg: #F4EDE3F5; + surface: #EAE1D3; + overlay: #B1A28E; + text: #39302A; + subtext: #5D5142; + muted: #877867; + accent: #A34F1F; + accentAlt: #75621A; + accentEdge: #A34F1F59; + accentWash: #A34F1F33; + + font: "CaskaydiaCove Nerd Font 11"; + background-color: transparent; + text-color: @text; +} + +window { + background-color: @panelBg; + border: 1px; + border-color: @accentEdge; + border-radius: 8px; + width: calc( 84ch min 65% ); + location: center; + anchor: center; + padding: 16px; +} + +mainbox { + background-color: transparent; + children: [ inputbar, message, listview ]; + spacing: 12px; +} + +inputbar { + children: [ prompt, entry ]; + background-color: @surface; + text-color: @text; + border-radius: 8px; + padding: 12px 16px; + spacing: 10px; +} + +prompt { text-color: @accent; } + +entry { + text-color: @text; + cursor: text; + placeholder: "Search…"; + placeholder-color: @muted; +} + +listview { + background-color: transparent; + columns: 1; + lines: 8; + dynamic: true; + scrollbar: true; + spacing: 6px; + padding: 4px 0px 0px 0px; +} + +element { + background-color: transparent; + text-color: @text; + orientation: horizontal; + border-radius: 8px; + padding: 10px 14px; + spacing: 12px; +} + +element normal.normal, +element alternate.normal { + background-color: transparent; +} + +/* Selected row lifts on a soft terracotta wash. */ +element selected.normal { + background-color: @accentWash; + text-color: @text; +} + +element-icon { + background-color: transparent; + size: 30px; + cursor: inherit; +} + +element-text { + background-color: transparent; + text-color: inherit; + highlight: bold; + vertical-align: 0.5; +} + +message { padding: 0px; } + +textbox { + background-color: @surface; + text-color: @text; + border-radius: 8px; + padding: 10px 14px; +} + +scrollbar { + width: 4px; + handle-width: 4px; + handle-color: @accent; + background-color: @surface; + border: 0px; +} diff --git a/themes/kiln-clay/waybar.css b/themes/kiln-clay/waybar.css new file mode 100644 index 0000000..2058d49 --- /dev/null +++ b/themes/kiln-clay/waybar.css @@ -0,0 +1,192 @@ +/* + * Kiln Clay — Waybar whole-swap (themes//waybar.css). + * + * A theme waybar.css replaces the ENTIRE generated stylesheet and is read + * raw (no palette is prepended), so this file MUST define its own colors. + * Identity: "the workbench" at midday — the same ONE continuous floating + * island as Kiln's night plank, translated to daylight: cream plaster + * worktop, terracotta edge-glow. No pills, no edge-to-edge strip: every + * module — including the tray — sits directly on the one plank, seamless. + * Companion: waybar.jsonc. + */ + +@define-color base #F4EDE3; +@define-color mantle #DFD4C4; +@define-color surface #EAE1D3; +@define-color overlay #B1A28E; +@define-color text #39302A; +@define-color subtext #5D5142; +@define-color muted #877867; +@define-color accent #A34F1F; +@define-color accentAlt #75621A; +@define-color good #586F26; +@define-color warn #8A5E08; +@define-color bad #AC3B31; + +/* NB: this `*` reset reaches the SNI tray menus Waybar hosts too (its + stylesheet applies process-wide, at a priority user gtk.css cannot + out-rank). The menu block right below undoes the damage — keep the two + in sync. Do NOT scope `*` to window#waybar instead: the id's + specificity would beat the class rules below (the plank) and wreck the + bar. */ +* { + /* Mono Nerd face for status glyphs (tight right bearings on the + proportional Symbols face make icon+percentage collide). */ + font-family: "CaskaydiaCove Nerd Font", "Symbols Nerd Font Mono"; + font-size: 13px; + font-weight: 500; + border: none; + border-radius: 0; + min-height: 0; +} + +/* ── Tray menus (nm-applet & co live in Waybar's process) ───────────── + Undo the `*` reset for them: same stylesheet, higher specificity. + Arrows/checks are CSS-sized nodes — min-height 0 makes them invisible; + separators die the same way; the bar's mono face reads wrong in text + menus. */ +menu, menu * { font-family: "Inter", sans-serif; } +menu menuitem arrow { min-width: 16px; min-height: 16px; } +menu check, menu radio { min-width: 14px; min-height: 14px; } +menu separator { + min-height: 1px; + margin: 5px 0; + background: alpha(@text, 0.15); +} + +/* The plank itself — one solid worktop spanning the island, a faint + terracotta edge-glow lifting it off the wallpaper. */ +window#waybar { + background: alpha(@base, 0.94); + border: 1px solid alpha(@accent, 0.35); + border-radius: 8px; + color: @text; +} + +.modules-left, +.modules-center, +.modules-right { + background: transparent; + padding: 0 6px; + margin: 0; +} + +/* Every module sits ON the plank: transparent, so nothing boxes the tray + off from the status icons — the seamless-cluster requirement. */ +#custom-nomarchy, +#clock, +#custom-recording, +#custom-updates, +#custom-doctor, +#idle_inhibitor, +#custom-nightlight, +#custom-airplane, +#language, +#custom-vpn, +#pulseaudio, +#battery, +#custom-powerprofile, +#tray, +#custom-notification, +#custom-powermenu { + background: transparent; + color: alpha(@text, 0.9); + padding: 0 8px; + margin: 0; +} + +/* ── Launcher — the terracotta Nomarchy mark opens the plank ────────── + The mark lives at U+F000 in the dedicated "Nomarchy" font; pin the + family or the Nerd Font's glass glyph at the same codepoint wins. */ +#custom-nomarchy { + color: @accent; + font-family: Nomarchy; + font-size: 18px; + padding: 0 12px 0 14px; +} +#custom-nomarchy:hover { color: @accentAlt; } + +/* ── Clock — unified time · date ─────────────────────────────────────*/ +#clock { + color: @text; + font-weight: 600; + padding-left: 4px; +} + +/* ── Workspaces — dots that fire to a fired-clay pill when active ─────*/ +#workspaces { padding: 0 2px; } + +#workspaces button { + color: @muted; + padding: 0 9px; + margin: 3px 1px; + border-radius: 6px; + transition: color 0.2s ease, background 0.2s ease; +} +#workspaces button:hover { + color: @text; + background: alpha(@overlay, 0.6); +} +#workspaces button.active { + color: @base; + background: @accent; + border-radius: 6px; +} +#workspaces button.urgent { + color: @base; + background: @bad; + border-radius: 6px; +} + +/* ── Status semantics (neutral until a state fires) ──────────────────*/ +#custom-recording.recording { color: @bad; } +#custom-updates.available { color: @accent; } +#custom-doctor { color: @bad; } +#idle_inhibitor.activated { color: @warn; } +#custom-nightlight.on { color: @warn; } +#custom-airplane.on { color: @warn; } +#custom-vpn.on { color: @good; } +#pulseaudio.muted { color: @muted; } + +#battery.charging { color: @good; } +#battery.warning:not(.charging) { color: @warn; } +#battery.critical:not(.charging) { color: @bad; } + +/* Icon-only status modules carry no text, so they don't get the 13pt + Pango icon span the icon+text modules (volume/battery/language) use — + bump their font-size to match, or these glyphs read noticeably smaller + than their neighbours. */ +#custom-recording, +#custom-updates, +#custom-doctor, +#custom-nightlight, +#custom-airplane, +#custom-vpn, +#custom-notification { font-size: 17px; } +/* Speedometer + caffeine cup render small in their em box — a touch more. */ +#custom-powerprofile, +#idle_inhibitor { font-size: 18px; } + +#custom-notification.notification { color: @accent; } +#custom-notification.dnd-none, +#custom-notification.dnd-notification, +#custom-notification.inhibited-none, +#custom-notification.inhibited-notification { color: @muted; } + +/* Tray shares the plank — same transparent background, its own modest + padding so nm-applet & friends breathe with the status icons. */ +#tray { padding: 0 6px; } +#tray > .passive { -gtk-icon-effect: dim; } +#tray > .needs-attention { -gtk-icon-effect: highlight; } + +/* Power button closes the plank on the right; warms to alert on hover. */ +#custom-powermenu { color: @subtext; padding: 0 12px 0 8px; } +#custom-powermenu:hover { color: @bad; } + +/* ── Tooltips — solid plaster, terracotta edge ───────────────────────*/ +tooltip { + background: alpha(@base, 0.97); + border: 1px solid alpha(@accent, 0.4); + border-radius: 8px; +} +tooltip label { color: @text; } diff --git a/themes/kiln-clay/waybar.jsonc b/themes/kiln-clay/waybar.jsonc new file mode 100644 index 0000000..32133c5 --- /dev/null +++ b/themes/kiln-clay/waybar.jsonc @@ -0,0 +1,183 @@ +{ + "margin-top": 6, + "margin-left": 12, + "margin-right": 12, + "margin-bottom": 0, + "height": 38, + "layer": "bottom", + "position": "top", + "spacing": 4, + "reload_style_on_change": true, + "modules-left": [ + "custom/nomarchy", + "clock" + ], + "modules-center": [ + "hyprland/workspaces" + ], + "modules-right": [ + "custom/recording", + "custom/updates", + "custom/doctor", + "idle_inhibitor", + "custom/nightlight", + "hyprland/language", + "custom/vpn", + "custom/airplane", + "pulseaudio", + "battery", + "custom/powerprofile", + "tray", + "custom/notification", + "custom/powermenu" + ], + "custom/nomarchy": { + "interval": "once", + "format": "", + "on-click": "nomarchy-menu", + "tooltip-format": "Nomarchy menu" + }, + "clock": { + "format": "{:%H:%M · %a %d %b}", + "on-click": "nomarchy-calendar", + "tooltip": true, + "tooltip-format": "{:%A, %d %B %Y\n%Z (UTC%z)}" + }, + "hyprland/workspaces": { + "disable-scroll": true, + "all-outputs": true, + "on-click": "activate", + "on-scroll-up": "hyprctl dispatch workspace r+1", + "on-scroll-down": "hyprctl dispatch workspace r-1" + }, + "custom/recording": { + "return-type": "json", + "interval": 10, + "signal": 8, + "exec": "nomarchy-record status", + "on-click": "nomarchy-record stop" + }, + "custom/updates": { + "return-type": "json", + "interval": 1800, + "signal": 9, + "exec": "nomarchy-updates status", + "on-click": "nomarchy-updates upgrade-window" + }, + "custom/doctor": { + "return-type": "json", + "format": "{}", + "interval": 300, + "signal": 10, + "exec": "nomarchy-doctor-status", + "on-click": "nomarchy-menu doctor" + }, + "idle_inhibitor": { + "format": "{icon}", + "format-icons": { + "activated": " 󰅶 ", + "deactivated": " 󰾪 " + } + }, + "custom/nightlight": { + "return-type": "json", + "interval": 3, + "exec": "nomarchy-nightlight status", + "on-click": "nomarchy-nightlight toggle" + }, + "hyprland/language": { + "format": "󰌌 {short}", + "tooltip": false + }, + "custom/vpn": { + "return-type": "json", + "interval": 5, + "exec": "nomarchy-vpn-status", + "on-click": "nomarchy-vpn" + }, + "pulseaudio": { + "scroll-step": 5, + "format": "{icon}{volume}%", + "format-bluetooth": "{icon} {volume}%", + "format-bluetooth-muted": " {icon}", + "format-muted": "muted", + "format-icons": { + "headphone": " ", + "hands-free": " ", + "headset": " ", + "phone": " ", + "portable": " ", + "car": " ", + "default": [ + " ", + " ", + " " + ] + }, + "on-click": "wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle", + "on-click-right": "pwvucontrol", + "tooltip-format": "{desc} | {volume}%" + }, + "battery": { + "interval": 30, + "states": { + "warning": 25, + "critical": 10 + }, + "format": "{icon}{capacity}%", + "format-charging": "{capacity}%", + "format-plugged": "{capacity}%", + "tooltip-format-plugged": "Plugged in, not charging — held at {capacity}% by the battery charge cap\nCharging resumes ~10% below the cap · click to adjust", + "format-icons": [ + " ", + " ", + " ", + " ", + " " + ], + "on-click": "nomarchy-menu powermgmt", + "tooltip-format": "Battery status" + }, + "custom/powerprofile": { + "return-type": "json", + "interval": 5, + "exec": "nomarchy-powerprofile-status", + "on-click": "nomarchy-menu powermgmt" + }, + "tray": { + "icon-size": 15, + "spacing": 10 + }, + "custom/notification": { + "format": "{icon}", + "return-type": "json", + "exec": "swaync-client -swb", + "exec-if": "which swaync-client", + "escape": true, + "tooltip": true, + "on-click": "swaync-client -t -sw", + "on-click-right": "swaync-client -d -sw", + "format-icons": { + "none": "󰂜", + "notification": "󰂚", + "dnd-none": "󰂛", + "dnd-notification": "󰂛", + "inhibited-none": "󰂛", + "inhibited-notification": "󰂛", + "dnd-inhibited-none": "󰂛", + "dnd-inhibited-notification": "󰂛" + } + }, + "custom/powermenu": { + "format": "", + "on-click": "nomarchy-menu power", + "tooltip": false + }, + "custom/airplane": { + "return-type": "json", + "interval": 5, + "signal": 11, + "exec": "nomarchy-airplane status", + "on-click": "nomarchy-airplane toggle" + } +} diff --git a/themes/kiln.json b/themes/kiln.json new file mode 100644 index 0000000..8273b7e --- /dev/null +++ b/themes/kiln.json @@ -0,0 +1,60 @@ +{ + "version": 1, + "name": "Kiln", + "slug": "kiln", + "mode": "dark", + "wallpaper": "", + "colors": { + "base": "#1D1815", + "mantle": "#151110", + "surface": "#2C241E", + "overlay": "#41362D", + "text": "#EADFD3", + "subtext": "#B5A695", + "muted": "#77685A", + "accent": "#D68C5C", + "accentAlt": "#C8A94E", + "good": "#A0B36A", + "warn": "#E0A458", + "bad": "#E26D5A" + }, + "border": { + "active": "accent", + "inactive": "overlay" + }, + "fonts": { + "mono": "CaskaydiaCove Nerd Font", + "ui": "Inter", + "size": 11 + }, + "ui": { + "gapsIn": 5, + "gapsOut": 12, + "borderSize": 2, + "rounding": 8, + "iconSize": 40, + "activeOpacity": 1.0, + "inactiveOpacity": 0.94, + "terminalOpacity": 0.93, + "blur": true, + "shadow": true + }, + "ansi": [ + "#2C241E", + "#E26D5A", + "#A0B36A", + "#E0A458", + "#90A9C8", + "#BC8FC6", + "#9FBFAE", + "#EADFD3", + "#77685A", + "#EB8272", + "#AFC17C", + "#E8B46E", + "#A3B8D4", + "#CBA3D4", + "#B0CCBD", + "#F4EDE5" + ] +} diff --git a/themes/kiln/btop.theme b/themes/kiln/btop.theme new file mode 100644 index 0000000..5728df8 --- /dev/null +++ b/themes/kiln/btop.theme @@ -0,0 +1,25 @@ +theme[main_bg]="#1D1815" +theme[main_fg]="#EADFD3" +theme[title]="#EADFD3" +theme[hi_fg]="#D68C5C" +theme[selected_bg]="#2C241E" +theme[selected_fg]="#EADFD3" +theme[inactive_fg]="#77685A" +theme[graph_text]="#B5A695" +theme[meter_bg]="#151110" +theme[proc_misc]="#C8A94E" +theme[cpu_box]="#D68C5C" +theme[mem_box]="#A0B36A" +theme[net_box]="#C8A94E" +theme[proc_box]="#41362D" +theme[div_line]="#41362D" +theme[temp_start]="#A0B36A" +theme[temp_mid]="#E0A458" +theme[temp_end]="#E26D5A" +theme[cpu_start]="#A0B36A" +theme[cpu_mid]="#E0A458" +theme[cpu_end]="#E26D5A" +theme[free_start]="#A0B36A" +theme[used_start]="#E0A458" +theme[download_start]="#D68C5C" +theme[upload_start]="#C8A94E" diff --git a/themes/kiln/preview.png b/themes/kiln/preview.png new file mode 100644 index 0000000..caa3d7d Binary files /dev/null and b/themes/kiln/preview.png differ diff --git a/themes/kiln/rofi.rasi b/themes/kiln/rofi.rasi new file mode 100644 index 0000000..3e1f3f9 --- /dev/null +++ b/themes/kiln/rofi.rasi @@ -0,0 +1,121 @@ +/** + * Kiln — rofi whole-swap (themes//rofi.rasi). + * The base theme: a solid warm clay panel lit by ember-copper edge glow — + * no frost, no glass, a potter's workbench at night. Element structure + * mirrors the generated theme so the theme-grid picker's per-invocation + * -theme-str still lays out. The `configuration {}` block is omitted on + * purpose — it comes from modules/home/rofi.nix. + */ + +* { + base: #1D1815; + panelBg: #1D1815F2; + surface: #2C241E; + overlay: #41362D; + text: #EADFD3; + subtext: #B5A695; + muted: #77685A; + accent: #D68C5C; + accentAlt: #C8A94E; + accentEdge: #D68C5C66; + accentWash: #D68C5C33; + + font: "CaskaydiaCove Nerd Font 11"; + background-color: transparent; + text-color: @text; +} + +window { + background-color: @panelBg; + border: 1px; + border-color: @accentEdge; + border-radius: 8px; + width: calc( 84ch min 65% ); + location: center; + anchor: center; + padding: 16px; +} + +mainbox { + background-color: transparent; + children: [ inputbar, message, listview ]; + spacing: 12px; +} + +inputbar { + children: [ prompt, entry ]; + background-color: @surface; + text-color: @text; + border-radius: 8px; + padding: 12px 16px; + spacing: 10px; +} + +prompt { text-color: @accent; } + +entry { + text-color: @text; + cursor: text; + placeholder: "Search…"; + placeholder-color: @muted; +} + +listview { + background-color: transparent; + columns: 1; + lines: 8; + dynamic: true; + scrollbar: true; + spacing: 6px; + padding: 4px 0px 0px 0px; +} + +element { + background-color: transparent; + text-color: @text; + orientation: horizontal; + border-radius: 8px; + padding: 10px 14px; + spacing: 12px; +} + +element normal.normal, +element alternate.normal { + background-color: transparent; +} + +/* Selected row lifts on a soft ember-copper wash. */ +element selected.normal { + background-color: @accentWash; + text-color: @text; +} + +element-icon { + background-color: transparent; + size: 30px; + cursor: inherit; +} + +element-text { + background-color: transparent; + text-color: inherit; + highlight: bold; + vertical-align: 0.5; +} + +message { padding: 0px; } + +textbox { + background-color: @surface; + text-color: @text; + border-radius: 8px; + padding: 10px 14px; +} + +scrollbar { + width: 4px; + handle-width: 4px; + handle-color: @accent; + background-color: @surface; + border: 0px; +} diff --git a/themes/kiln/waybar.css b/themes/kiln/waybar.css new file mode 100644 index 0000000..8940ee8 --- /dev/null +++ b/themes/kiln/waybar.css @@ -0,0 +1,192 @@ +/* + * Kiln — Waybar whole-swap (themes//waybar.css). + * + * A theme waybar.css replaces the ENTIRE generated stylesheet and is read + * raw (no palette is prepended), so this file MUST define its own colors. + * Identity: "the workbench" — ONE continuous floating island, a solid + * worktop plank spanning the screen width minus margins, with a faint + * copper edge-glow border. No pills, no edge-to-edge strip: every module + * — including the tray — sits directly on the one plank, seamless. + * Companion: waybar.jsonc. + */ + +@define-color base #1D1815; +@define-color mantle #151110; +@define-color surface #2C241E; +@define-color overlay #41362D; +@define-color text #EADFD3; +@define-color subtext #B5A695; +@define-color muted #77685A; +@define-color accent #D68C5C; +@define-color accentAlt #C8A94E; +@define-color good #A0B36A; +@define-color warn #E0A458; +@define-color bad #E26D5A; + +/* NB: this `*` reset reaches the SNI tray menus Waybar hosts too (its + stylesheet applies process-wide, at a priority user gtk.css cannot + out-rank). The menu block right below undoes the damage — keep the two + in sync. Do NOT scope `*` to window#waybar instead: the id's + specificity would beat the class rules below (the plank) and wreck the + bar. */ +* { + /* Mono Nerd face for status glyphs (tight right bearings on the + proportional Symbols face make icon+percentage collide). */ + font-family: "CaskaydiaCove Nerd Font", "Symbols Nerd Font Mono"; + font-size: 13px; + font-weight: 500; + border: none; + border-radius: 0; + min-height: 0; +} + +/* ── Tray menus (nm-applet & co live in Waybar's process) ───────────── + Undo the `*` reset for them: same stylesheet, higher specificity. + Arrows/checks are CSS-sized nodes — min-height 0 makes them invisible; + separators die the same way; the bar's mono face reads wrong in text + menus. */ +menu, menu * { font-family: "Inter", sans-serif; } +menu menuitem arrow { min-width: 16px; min-height: 16px; } +menu check, menu radio { min-width: 14px; min-height: 14px; } +menu separator { + min-height: 1px; + margin: 5px 0; + background: alpha(@text, 0.15); +} + +/* The plank itself — one solid worktop spanning the island, a faint + ember-copper edge-glow lifting it off the wallpaper. */ +window#waybar { + background: alpha(@base, 0.92); + border: 1px solid alpha(@accent, 0.25); + border-radius: 8px; + color: @text; +} + +.modules-left, +.modules-center, +.modules-right { + background: transparent; + padding: 0 6px; + margin: 0; +} + +/* Every module sits ON the plank: transparent, so nothing boxes the tray + off from the status icons — the seamless-cluster requirement. */ +#custom-nomarchy, +#clock, +#custom-recording, +#custom-updates, +#custom-doctor, +#idle_inhibitor, +#custom-nightlight, +#custom-airplane, +#language, +#custom-vpn, +#pulseaudio, +#battery, +#custom-powerprofile, +#tray, +#custom-notification, +#custom-powermenu { + background: transparent; + color: alpha(@text, 0.9); + padding: 0 8px; + margin: 0; +} + +/* ── Launcher — the ember-copper Nomarchy mark opens the plank ──────── + The mark lives at U+F000 in the dedicated "Nomarchy" font; pin the + family or the Nerd Font's glass glyph at the same codepoint wins. */ +#custom-nomarchy { + color: @accent; + font-family: Nomarchy; + font-size: 18px; + padding: 0 12px 0 14px; +} +#custom-nomarchy:hover { color: @accentAlt; } + +/* ── Clock — unified time · date ─────────────────────────────────────*/ +#clock { + color: @text; + font-weight: 600; + padding-left: 4px; +} + +/* ── Workspaces — dots that fire to an ember pill when active ─────────*/ +#workspaces { padding: 0 2px; } + +#workspaces button { + color: @muted; + padding: 0 9px; + margin: 3px 1px; + border-radius: 6px; + transition: color 0.2s ease, background 0.2s ease; +} +#workspaces button:hover { + color: @text; + background: alpha(@overlay, 0.6); +} +#workspaces button.active { + color: @base; + background: @accent; + border-radius: 6px; +} +#workspaces button.urgent { + color: @base; + background: @bad; + border-radius: 6px; +} + +/* ── Status semantics (neutral until a state fires) ──────────────────*/ +#custom-recording.recording { color: @bad; } +#custom-updates.available { color: @accent; } +#custom-doctor { color: @bad; } +#idle_inhibitor.activated { color: @warn; } +#custom-nightlight.on { color: @warn; } +#custom-airplane.on { color: @warn; } +#custom-vpn.on { color: @good; } +#pulseaudio.muted { color: @muted; } + +#battery.charging { color: @good; } +#battery.warning:not(.charging) { color: @warn; } +#battery.critical:not(.charging) { color: @bad; } + +/* Icon-only status modules carry no text, so they don't get the 13pt + Pango icon span the icon+text modules (volume/battery/language) use — + bump their font-size to match, or these glyphs read noticeably smaller + than their neighbours. */ +#custom-recording, +#custom-updates, +#custom-doctor, +#custom-nightlight, +#custom-airplane, +#custom-vpn, +#custom-notification { font-size: 17px; } +/* Speedometer + caffeine cup render small in their em box — a touch more. */ +#custom-powerprofile, +#idle_inhibitor { font-size: 18px; } + +#custom-notification.notification { color: @accent; } +#custom-notification.dnd-none, +#custom-notification.dnd-notification, +#custom-notification.inhibited-none, +#custom-notification.inhibited-notification { color: @muted; } + +/* Tray shares the plank — same transparent background, its own modest + padding so nm-applet & friends breathe with the status icons. */ +#tray { padding: 0 6px; } +#tray > .passive { -gtk-icon-effect: dim; } +#tray > .needs-attention { -gtk-icon-effect: highlight; } + +/* Power button closes the plank on the right; warms to alert on hover. */ +#custom-powermenu { color: @subtext; padding: 0 12px 0 8px; } +#custom-powermenu:hover { color: @bad; } + +/* ── Tooltips — solid clay, ember-copper edge ────────────────────────*/ +tooltip { + background: alpha(@mantle, 0.96); + border: 1px solid alpha(@accent, 0.35); + border-radius: 8px; +} +tooltip label { color: @text; } diff --git a/themes/kiln/waybar.jsonc b/themes/kiln/waybar.jsonc new file mode 100644 index 0000000..32133c5 --- /dev/null +++ b/themes/kiln/waybar.jsonc @@ -0,0 +1,183 @@ +{ + "margin-top": 6, + "margin-left": 12, + "margin-right": 12, + "margin-bottom": 0, + "height": 38, + "layer": "bottom", + "position": "top", + "spacing": 4, + "reload_style_on_change": true, + "modules-left": [ + "custom/nomarchy", + "clock" + ], + "modules-center": [ + "hyprland/workspaces" + ], + "modules-right": [ + "custom/recording", + "custom/updates", + "custom/doctor", + "idle_inhibitor", + "custom/nightlight", + "hyprland/language", + "custom/vpn", + "custom/airplane", + "pulseaudio", + "battery", + "custom/powerprofile", + "tray", + "custom/notification", + "custom/powermenu" + ], + "custom/nomarchy": { + "interval": "once", + "format": "", + "on-click": "nomarchy-menu", + "tooltip-format": "Nomarchy menu" + }, + "clock": { + "format": "{:%H:%M · %a %d %b}", + "on-click": "nomarchy-calendar", + "tooltip": true, + "tooltip-format": "{:%A, %d %B %Y\n%Z (UTC%z)}" + }, + "hyprland/workspaces": { + "disable-scroll": true, + "all-outputs": true, + "on-click": "activate", + "on-scroll-up": "hyprctl dispatch workspace r+1", + "on-scroll-down": "hyprctl dispatch workspace r-1" + }, + "custom/recording": { + "return-type": "json", + "interval": 10, + "signal": 8, + "exec": "nomarchy-record status", + "on-click": "nomarchy-record stop" + }, + "custom/updates": { + "return-type": "json", + "interval": 1800, + "signal": 9, + "exec": "nomarchy-updates status", + "on-click": "nomarchy-updates upgrade-window" + }, + "custom/doctor": { + "return-type": "json", + "format": "{}", + "interval": 300, + "signal": 10, + "exec": "nomarchy-doctor-status", + "on-click": "nomarchy-menu doctor" + }, + "idle_inhibitor": { + "format": "{icon}", + "format-icons": { + "activated": " 󰅶 ", + "deactivated": " 󰾪 " + } + }, + "custom/nightlight": { + "return-type": "json", + "interval": 3, + "exec": "nomarchy-nightlight status", + "on-click": "nomarchy-nightlight toggle" + }, + "hyprland/language": { + "format": "󰌌 {short}", + "tooltip": false + }, + "custom/vpn": { + "return-type": "json", + "interval": 5, + "exec": "nomarchy-vpn-status", + "on-click": "nomarchy-vpn" + }, + "pulseaudio": { + "scroll-step": 5, + "format": "{icon}{volume}%", + "format-bluetooth": "{icon} {volume}%", + "format-bluetooth-muted": " {icon}", + "format-muted": "muted", + "format-icons": { + "headphone": " ", + "hands-free": " ", + "headset": " ", + "phone": " ", + "portable": " ", + "car": " ", + "default": [ + " ", + " ", + " " + ] + }, + "on-click": "wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle", + "on-click-right": "pwvucontrol", + "tooltip-format": "{desc} | {volume}%" + }, + "battery": { + "interval": 30, + "states": { + "warning": 25, + "critical": 10 + }, + "format": "{icon}{capacity}%", + "format-charging": "{capacity}%", + "format-plugged": "{capacity}%", + "tooltip-format-plugged": "Plugged in, not charging — held at {capacity}% by the battery charge cap\nCharging resumes ~10% below the cap · click to adjust", + "format-icons": [ + " ", + " ", + " ", + " ", + " " + ], + "on-click": "nomarchy-menu powermgmt", + "tooltip-format": "Battery status" + }, + "custom/powerprofile": { + "return-type": "json", + "interval": 5, + "exec": "nomarchy-powerprofile-status", + "on-click": "nomarchy-menu powermgmt" + }, + "tray": { + "icon-size": 15, + "spacing": 10 + }, + "custom/notification": { + "format": "{icon}", + "return-type": "json", + "exec": "swaync-client -swb", + "exec-if": "which swaync-client", + "escape": true, + "tooltip": true, + "on-click": "swaync-client -t -sw", + "on-click-right": "swaync-client -d -sw", + "format-icons": { + "none": "󰂜", + "notification": "󰂚", + "dnd-none": "󰂛", + "dnd-notification": "󰂛", + "inhibited-none": "󰂛", + "inhibited-notification": "󰂛", + "dnd-inhibited-none": "󰂛", + "dnd-inhibited-notification": "󰂛" + } + }, + "custom/powermenu": { + "format": "", + "on-click": "nomarchy-menu power", + "tooltip": false + }, + "custom/airplane": { + "return-type": "json", + "interval": 5, + "signal": 11, + "exec": "nomarchy-airplane status", + "on-click": "nomarchy-airplane toggle" + } +}