-
Notifications
You must be signed in to change notification settings - Fork 0
Example Three Kernel Desk
locainin edited this page Feb 13, 2026
·
1 revision

This page contains the exact active local configuration and theme overrides used for the screenshot above.
It includes all runtime files required for this setup, including custom widget scripts referenced by config.toml.
config.toml
rules = []
[general]
dnd_default = false
[inhibit]
mode = "no_popups"
[popups]
anchor = "top-right"
width = 372
spacing = 12
max_visible = 4
default_timeout_ms = 5000
allow_click_through = false
[popups.margin]
top = 14
right = 14
bottom = 14
left = 14
[panel]
anchor = "right"
width = 420
height = 0
keyboard_interactivity = "on-demand"
empty_text = "0x0000 EVENT QUEUE EMPTY"
empty_offset_top = 98
close_on_blur = false
close_on_click_outside = true
respect_work_area = true
[panel.margin]
top = 16
right = 10
bottom = 14
left = 10
[history]
max_entries = 200
max_active = 500
transient_to_history = false
[media]
enabled = true
include_browsers = true
browser_tokens = [
"firefox",
"librewolf",
"waterfox",
"floorp",
"brave",
"chromium",
"chrome",
"vivaldi",
"edge",
"opera",
"epiphany",
"midori",
"zen",
]
title_char_limit = 32
allowlist = []
denylist = ["playerctld"]
[widgets]
refresh_interval_ms = 1400
refresh_interval_slow_ms = 4200
[widgets.volume]
enabled = true
label = "Volume"
icon = "audio-volume-high-symbolic"
icon_muted = "audio-volume-muted-symbolic"
get_cmd = "wpctl get-volume @DEFAULT_AUDIO_SINK@"
set_cmd = "wpctl set-volume @DEFAULT_AUDIO_SINK@ {value}%"
toggle_cmd = "wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle"
min = 0.0
max = 100.0
step = 1.0
parse_mode = "auto"
[widgets.brightness]
enabled = true
label = "Brightness"
icon = "display-brightness-symbolic"
get_cmd = "brightnessctl -m"
set_cmd = "brightnessctl s {value}%"
watch_cmd = "brightnessctl -w"
min = 0.0
max = 100.0
step = 1.0
parse_mode = "auto"
[[widgets.toggles]]
enabled = true
kind = "wifi"
label = "Wi-Fi"
icon = "network-wireless-signal-excellent-symbolic"
state_cmd = "nmcli radio wifi"
on_cmd = "nmcli radio wifi on"
off_cmd = "nmcli radio wifi off"
watch_cmd = "nmcli -t monitor"
[[widgets.toggles]]
enabled = true
kind = "bluetooth"
label = "Bluetooth"
icon = "bluetooth-active-symbolic"
state_cmd = "bluetoothctl show"
on_cmd = "bluetoothctl power on"
off_cmd = "bluetoothctl power off"
watch_cmd = "dbus-monitor --system type=signal,sender=org.bluez"
[[widgets.toggles]]
enabled = true
kind = "airplane"
label = "Airplane"
icon = "airplane-mode-symbolic"
state_cmd = """rfkill list all | awk '/Soft blocked:/ { seen=1; if ($3 != "yes") bad=1 } END { exit (seen && !bad) ? 0 : 1 }'"""
on_cmd = "rfkill block all"
off_cmd = "rfkill unblock all"
watch_cmd = "udevadm monitor --udev --subsystem-match=rfkill"
[[widgets.toggles]]
enabled = true
kind = "night"
label = "Night"
icon = "weather-clear-night-symbolic"
state_cmd = "pgrep -x gammastep >/dev/null 2>&1"
on_cmd = "nohup gammastep -m wayland -l 0:0 -t 4500:4500 -P >/dev/null 2>&1 &"
off_cmd = "pkill -x gammastep >/dev/null 2>&1; gammastep -x >/dev/null 2>&1"
[[widgets.stats]]
enabled = true
label = "CPU"
icon = "utilities-system-monitor-symbolic"
cmd = "builtin:cpu"
min_height = 56
[[widgets.stats]]
enabled = true
label = "RAM"
icon = "drive-harddisk-symbolic"
cmd = "builtin:memory"
min_height = 56
[[widgets.stats]]
enabled = true
label = "Battery"
icon = "battery-full-symbolic"
cmd = "builtin:battery"
min_height = 56
[[widgets.stats]]
enabled = true
label = "Load"
icon = "view-statistics-symbolic"
cmd = "builtin:load"
min_height = 56
[[widgets.stats]]
enabled = true
label = "Net Flux"
icon = "network-transmit-receive-symbolic"
cmd = """sh -c '${XDG_CONFIG_HOME:-$HOME/.config}/unixnotis/scripts/unixnotis-net-rate-stat | jq -r .text'"""
min_height = 56
[[widgets.stats]]
enabled = true
label = "Thermal"
icon = "temperature-high-symbolic"
cmd = """sh -c '${XDG_CONFIG_HOME:-$HOME/.config}/unixnotis/scripts/unixnotis-thermal-stat | jq -r .text'"""
min_height = 56
[[widgets.cards]]
enabled = true
kind = "custom"
title = "Kernel Pulse"
subtitle = "runtime telemetry"
icon = "applications-system-symbolic"
cmd = """sh -c '${XDG_CONFIG_HOME:-$HOME/.config}/unixnotis/scripts/unixnotis-creative-status | jq -r .text'"""
min_height = 112
monospace = true
[[widgets.cards]]
enabled = false
kind = "custom"
title = "Storage Map"
subtitle = "filesystem telemetry"
icon = "drive-harddisk-symbolic"
cmd = """sh -c '${XDG_CONFIG_HOME:-$HOME/.config}/unixnotis/scripts/unixnotis-storage-card | jq -r .text'"""
min_height = 112
monospace = true
[[widgets.cards]]
enabled = false
kind = "custom"
title = "Hot Process"
subtitle = "top scheduler entry"
icon = "utilities-system-monitor-symbolic"
cmd = """sh -c '${XDG_CONFIG_HOME:-$HOME/.config}/unixnotis/scripts/unixnotis-process-card | jq -r .text'"""
min_height = 112
monospace = true
[[widgets.cards]]
enabled = true
kind = "custom"
title = "Toolchain"
subtitle = "compiler snapshot"
icon = "text-x-csrc-symbolic"
cmd = """sh -c '${XDG_CONFIG_HOME:-$HOME/.config}/unixnotis/scripts/unixnotis-toolchain-card'"""
min_height = 112
monospace = true
[sound]
enabled = true
default_name = "message-new-instant"
[theme]
base_css = "base.css"
popup_css = "popup.css"
panel_css = "panel.css"
widgets_css = "widgets.css"
border_width = 2
card_radius = 4
surface_alpha = 0.94
surface_strong_alpha = 0.98
card_alpha = 0.96
shadow_soft_alpha = 0.46
shadow_strong_alpha = 0.72base.css
/* UnixNotis base theme: Kernel Desk */
/* Foundation surfaces */
@define-color unixnotis-surface-base #090b10;
@define-color unixnotis-surface-strong-base #11151c;
@define-color unixnotis-card-base #171d27;
/* Runtime alpha hooks */
@define-color unixnotis-surface alpha(@unixnotis-surface-base, 0.90);
@define-color unixnotis-surface-strong alpha(@unixnotis-surface-strong-base, 0.94);
@define-color unixnotis-surface-soft alpha(#202939, 0.84);
@define-color unixnotis-card alpha(@unixnotis-card-base, 0.92);
/* Typography */
@define-color unixnotis-text #d9e2ef;
@define-color unixnotis-muted #8595ab;
/* Accent system */
@define-color unixnotis-accent #ffbf66;
@define-color unixnotis-accent-2 #86b4ff;
@define-color unixnotis-urgent #ff4b68;
/* Per-toggle accents */
@define-color unixnotis-accent-wifi #5fd6a3;
@define-color unixnotis-accent-bluetooth #86b4ff;
@define-color unixnotis-accent-airplane #ffbf66;
@define-color unixnotis-accent-night #ad9fe8;
/* Border + elevation */
@define-color unixnotis-card-border alpha(#9aabc6, 0.30);
@define-color unixnotis-outline alpha(#adbed6, 0.38);
@define-color unixnotis-shadow-soft alpha(#02060b, 0.46);
@define-color unixnotis-shadow-strong alpha(#02060b, 0.72);
@define-color unixnotis-glass-shine alpha(#ffffff, 0.15);
@define-color unixnotis-glass-sheen alpha(#ffffff, 0.04);
@define-color unixnotis-glass-depth alpha(#000000, 0.18);
/* Glow helpers */
@define-color unixnotis-glow-cyan alpha(@unixnotis-accent, 0.22);
@define-color unixnotis-glow-pink alpha(@unixnotis-accent-2, 0.18);
@define-color unixnotis-glow-violet alpha(@unixnotis-accent-night, 0.20);
@define-color unixnotis-glow-wifi alpha(@unixnotis-accent-wifi, 0.24);
@define-color unixnotis-glow-bluetooth alpha(@unixnotis-accent-bluetooth, 0.24);
@define-color unixnotis-glow-airplane alpha(@unixnotis-accent-airplane, 0.24);
@define-color unixnotis-glow-night alpha(@unixnotis-accent-night, 0.22);
/* Shared gradients */
@define-color unixnotis-panel-grad-1 alpha(#0b0d13, 0.98);
@define-color unixnotis-panel-grad-2 alpha(#121722, 0.99);
@define-color unixnotis-panel-grad-3 alpha(#1b2230, 1.0);
@define-color unixnotis-notification-bg-1 alpha(#151b27, 0.98);
@define-color unixnotis-notification-bg-2 alpha(#101622, 0.98);
@define-color unixnotis-popup-bg-1 #151b27;
@define-color unixnotis-popup-bg-2 #101622;
@define-color unixnotis-pill-bg #1c2432;
@define-color unixnotis-pill-border #3f536f;
@define-color unixnotis-pill-hover #273247;
@define-color unixnotis-action-bg alpha(#182130, 0.98);
@define-color unixnotis-action-bg-hover alpha(#24334c, 0.98);
@define-color unixnotis-action-bg-active alpha(#334765, 0.92);
@define-color unixnotis-popup-action-bg alpha(#182130, 0.98);
@define-color unixnotis-popup-action-hover alpha(#24334c, 0.98);
@define-color unixnotis-popup-action-active alpha(#334765, 0.92);
/* Global window defaults */
.unixnotis-panel-window,
.unixnotis-popup-window {
background: transparent;
color: @unixnotis-text;
font-family: "Iosevka Term", "JetBrains Mono", "CaskaydiaCove Nerd Font Mono", "Noto Sans Mono", monospace;
}panel.css
/* UnixNotis panel theme: Kernel Desk */
.unixnotis-panel {
background-image:
radial-gradient(circle at 18% -12%, alpha(#ffffff, 0.18), transparent 46%),
linear-gradient(178deg, @unixnotis-glass-shine 0%, @unixnotis-glass-sheen 16%, alpha(#ffffff, 0.01) 38%, @unixnotis-glass-depth 100%),
linear-gradient(160deg, @unixnotis-panel-grad-1 0%, @unixnotis-panel-grad-2 58%, @unixnotis-panel-grad-3 100%),
repeating-linear-gradient(0deg, alpha(#9aa8be, 0.08), alpha(#9aa8be, 0.08) 1px, transparent 1px, transparent 14px);
color: @unixnotis-text;
border-radius: 9px;
padding: 12px;
border: 2px solid alpha(@unixnotis-outline, 0.78);
box-shadow:
inset 0 1px 0 alpha(#ffffff, 0.08),
inset 0 0 0 1px alpha(#aab3c1, 0.08),
0 26px 46px -26px @unixnotis-shadow-strong,
0 12px 24px -16px @unixnotis-shadow-soft;
}
.unixnotis-panel-header {
margin-bottom: 10px;
padding: 8px 9px;
border-radius: 5px;
background-image:
linear-gradient(180deg, alpha(#ffffff, 0.12) 0%, alpha(#ffffff, 0.02) 42%, alpha(#000000, 0.08) 100%),
linear-gradient(150deg, alpha(@unixnotis-surface-strong, 0.97), alpha(@unixnotis-surface-soft, 0.96));
border: 1px solid alpha(@unixnotis-outline, 0.58);
box-shadow:
inset 0 1px 0 alpha(#ffffff, 0.08),
0 8px 16px -14px @unixnotis-shadow-soft;
}
.unixnotis-panel-header-top {
min-height: 32px;
}
.unixnotis-panel-title-stack {
min-width: 0;
}
.unixnotis-panel-title-row {
min-height: 30px;
}
.unixnotis-panel-title {
font-weight: 700;
font-size: 12px;
letter-spacing: 0.18em;
text-transform: uppercase;
}
.unixnotis-panel-count {
background-image: linear-gradient(130deg, alpha(@unixnotis-accent, 0.28), alpha(@unixnotis-accent-2, 0.20));
color: @unixnotis-text;
font-size: 11px;
font-weight: 700;
letter-spacing: 0.10em;
border-radius: 3px;
padding: 1px 7px;
border: 1px solid alpha(@unixnotis-accent, 0.52);
min-width: 26px;
box-shadow: inset 0 0 0 1px alpha(@unixnotis-accent, 0.12);
}
.unixnotis-panel-actions {
border-radius: 4px;
margin-top: 4px;
}
.unixnotis-panel-action-group {
border-radius: 4px;
}
.unixnotis-panel-action {
background-image:
linear-gradient(180deg, alpha(#ffffff, 0.11) 0%, alpha(#ffffff, 0.02) 38%, alpha(#000000, 0.07) 100%),
linear-gradient(150deg, @unixnotis-action-bg, alpha(@unixnotis-surface, 0.88));
color: @unixnotis-text;
border-radius: 3px;
padding: 4px 8px;
border: 1px solid alpha(@unixnotis-outline, 0.6);
min-height: 26px;
box-shadow:
inset 0 1px 0 alpha(#ffffff, 0.07),
0 6px 12px -10px @unixnotis-shadow-soft;
font-size: 10px;
font-weight: 700;
letter-spacing: 0.09em;
text-transform: uppercase;
}
.unixnotis-panel-action-focus,
.unixnotis-panel-action-muted {
/* Keep compact labels readable while honoring fixed panel width. */
min-width: 86px;
}
.unixnotis-panel-action-primary {
/* DND text is intentionally short ("DND") to cap horizontal growth. */
min-width: 78px;
}
.unixnotis-panel-action-search {
/* Search toggle is icon-only; expanded search input is revealed below. */
min-width: 32px;
}
.unixnotis-panel-action-with-icon {
padding-left: 9px;
padding-right: 9px;
}
.unixnotis-panel-action-content {
min-height: 15px;
}
.unixnotis-panel-action-glyph {
min-width: 12px;
min-height: 12px;
}
.unixnotis-panel-action-label {
font-weight: 600;
letter-spacing: 0.02em;
font-size: 10px;
}
.unixnotis-panel-action:hover {
background-image: linear-gradient(150deg, @unixnotis-action-bg-hover, alpha(@unixnotis-surface-strong, 0.76));
border-color: alpha(@unixnotis-accent, 0.58);
box-shadow:
inset 0 1px 0 alpha(#ffffff, 0.08),
inset 0 0 0 1px alpha(@unixnotis-accent, 0.10),
0 8px 14px -10px @unixnotis-shadow-soft;
}
.unixnotis-panel-action:checked {
background-image: linear-gradient(140deg, alpha(@unixnotis-accent, 0.28), alpha(@unixnotis-accent-2, 0.22));
border-color: alpha(@unixnotis-accent, 0.74);
color: @unixnotis-text;
box-shadow: inset 0 0 0 1px alpha(@unixnotis-accent, 0.14);
}
.unixnotis-panel-action:checked .unixnotis-panel-action-glyph,
.unixnotis-panel-action:checked .unixnotis-panel-action-label {
color: @unixnotis-text;
}
.unixnotis-panel-action-icon {
min-width: 26px;
min-height: 26px;
padding: 0;
}
.unixnotis-panel-action-close {
margin-left: 6px;
background-image: linear-gradient(150deg, alpha(@unixnotis-surface-strong, 0.96), alpha(@unixnotis-surface, 0.9));
border-color: alpha(@unixnotis-outline, 0.64);
box-shadow:
inset 0 1px 0 alpha(#ffffff, 0.08),
0 6px 12px -10px @unixnotis-shadow-soft;
}
.unixnotis-panel-action-close:hover {
background-image: linear-gradient(150deg, alpha(@unixnotis-action-bg-hover, 0.9), alpha(@unixnotis-surface-strong, 0.84));
border-color: alpha(@unixnotis-accent, 0.44);
}
.unixnotis-panel-search-revealer {
margin-top: 2px;
}
.unixnotis-panel-search {
min-height: 28px;
border-radius: 3px;
background-image: linear-gradient(150deg, alpha(@unixnotis-surface, 0.94), alpha(@unixnotis-surface-soft, 0.8));
border: 1px solid alpha(@unixnotis-outline, 0.62);
padding: 0 8px;
box-shadow: inset 0 1px 0 alpha(#ffffff, 0.07);
}
.unixnotis-panel-search:focus-within {
border-color: alpha(@unixnotis-accent, 0.62);
box-shadow:
inset 0 1px 0 alpha(#ffffff, 0.08),
0 0 18px -12px @unixnotis-glow-cyan;
}
.unixnotis-panel-close,
.unixnotis-popup-close {
background: alpha(@unixnotis-surface-strong, 0.98);
color: @unixnotis-text;
border-radius: 3px;
border: 1px solid alpha(@unixnotis-outline, 0.64);
padding: 2px;
min-width: 24px;
min-height: 24px;
box-shadow:
inset 0 1px 0 alpha(#ffffff, 0.08),
0 6px 12px -10px @unixnotis-shadow-soft;
}
.unixnotis-panel-close:hover,
.unixnotis-popup-close:hover {
background: alpha(@unixnotis-urgent, 0.30);
color: #ffffff;
border-color: alpha(@unixnotis-urgent, 0.68);
}
.unixnotis-panel-list {
background: transparent;
}
.unixnotis-panel-list row {
background: transparent;
padding: 0;
margin: 0;
}
/*
* Group headers (app pills)
*/
.unixnotis-group {
background: transparent;
margin-bottom: 8px;
}
.unixnotis-group-header {
background-image: linear-gradient(135deg, @unixnotis-pill-bg, alpha(@unixnotis-pill-hover, 0.95));
color: @unixnotis-text;
border-radius: 3px;
padding: 6px 10px;
border: 1px solid @unixnotis-pill-border;
box-shadow:
inset 0 1px 0 alpha(#ffffff, 0.08),
0 8px 14px -12px @unixnotis-shadow-soft;
outline: none;
}
.unixnotis-group-header:hover {
background-image: linear-gradient(135deg, @unixnotis-pill-hover, alpha(@unixnotis-accent, 0.3));
}
.unixnotis-group-header:focus,
.unixnotis-group-header:active {
outline: none;
box-shadow:
0 10px 18px -16px @unixnotis-shadow-soft,
inset 0 0 0 1px alpha(#ffffff, 0.05);
}
.unixnotis-panel-list row:selected,
.unixnotis-panel-list row:focus,
.unixnotis-panel-list row:active {
background: transparent;
outline: none;
box-shadow: none;
}
.unixnotis-group-title {
font-weight: 600;
font-size: 12px;
letter-spacing: 0.2px;
}
.unixnotis-group-count {
background-image: linear-gradient(140deg, alpha(@unixnotis-accent, 0.28), alpha(@unixnotis-accent-2, 0.22));
color: @unixnotis-text;
border-radius: 3px;
padding: 1px 7px;
font-size: 10px;
font-weight: 700;
letter-spacing: 0.08em;
border: 1px solid alpha(@unixnotis-accent, 0.56);
min-width: 22px;
}
.unixnotis-group-chevron {
color: @unixnotis-muted;
}
.unixnotis-group-cards {
margin-top: 3px;
}
.unixnotis-group.collapsed .unixnotis-group-cards {
margin-left: 4px;
margin-right: 4px;
padding-bottom: 2px;
}
.unixnotis-group.collapsed .unixnotis-panel-card {
margin-bottom: 5px;
}
.unixnotis-group .unixnotis-panel-card {
margin-left: 8px;
}
/*
* Notification cards (panel)
*/
.unixnotis-panel-card {
background-image:
linear-gradient(180deg, alpha(#ffffff, 0.11) 0%, alpha(#ffffff, 0.02) 40%, alpha(#000000, 0.08) 100%),
linear-gradient(155deg, @unixnotis-notification-bg-1 0%, @unixnotis-notification-bg-2 100%),
repeating-linear-gradient(0deg, alpha(#9aa8be, 0.07), alpha(#9aa8be, 0.07) 1px, transparent 1px, transparent 14px);
border: 1px solid @unixnotis-card-border;
border-radius: 4px;
padding: 9px 10px;
margin-bottom: 6px;
box-shadow:
inset 0 1px 0 alpha(#ffffff, 0.08),
inset 0 0 0 1px alpha(@unixnotis-outline, 0.10),
0 10px 18px -14px @unixnotis-shadow-soft;
}
.unixnotis-panel-card.stacked {
box-shadow:
0 8px 0 -4px alpha(@unixnotis-outline, 0.18),
0 16px 0 -8px alpha(@unixnotis-outline, 0.12),
0 12px 22px -18px @unixnotis-shadow-soft;
}
.unixnotis-stack-ghost {
background-image:
repeating-linear-gradient(
135deg,
alpha(@unixnotis-surface-soft, 0.42),
alpha(@unixnotis-surface-soft, 0.42) 7px,
alpha(@unixnotis-surface, 0.78) 7px,
alpha(@unixnotis-surface, 0.78) 14px
);
border-radius: 3px;
padding: 0;
min-height: 24px;
opacity: 0.74;
margin-left: 12px;
margin-right: 12px;
margin-top: -8px;
border: 1px dashed alpha(@unixnotis-outline, 0.4);
box-shadow: none;
}
.unixnotis-stack-ghost-2 {
min-height: 18px;
opacity: 0.42;
margin-left: 20px;
margin-right: 20px;
margin-top: -10px;
box-shadow: none;
}
.unixnotis-panel-card.active {
border-color: alpha(@unixnotis-accent, 0.78);
box-shadow:
inset 0 0 0 1px alpha(@unixnotis-accent, 0.20),
0 0 18px -12px alpha(@unixnotis-accent, 0.32);
}
.unixnotis-panel-card.critical {
border-color: alpha(@unixnotis-urgent, 0.84);
background-image: linear-gradient(155deg, alpha(#2a1118, 0.95), alpha(#1f0d14, 0.95));
box-shadow:
inset 0 0 0 1px alpha(@unixnotis-urgent, 0.26),
0 12px 20px -16px alpha(@unixnotis-urgent, 0.35);
}
/*
* Empty-state
*
* The list uses a centered overlay label; styling is kept here so the empty
* state visually matches the rest of the panel.
*/
.unixnotis-empty {
background: transparent;
}
.unixnotis-empty-label {
color: alpha(@unixnotis-muted, 0.96);
font-weight: 700;
font-size: 10px;
letter-spacing: 0.16em;
text-transform: uppercase;
background: alpha(@unixnotis-surface-strong, 0.88);
border: 1px dashed alpha(@unixnotis-outline, 0.40);
border-radius: 3px;
padding: 4px 8px;
}
.unixnotis-panel-app {
color: @unixnotis-muted;
text-transform: uppercase;
letter-spacing: 0.07em;
font-size: 10px;
font-weight: 700;
margin-bottom: 3px;
}
.unixnotis-panel-summary {
font-size: 14px;
font-weight: 700;
}
.unixnotis-panel-body {
color: alpha(@unixnotis-text, 0.94);
font-size: 13px;
line-height: 1.33;
font-family: "JetBrains Mono", "Iosevka Aile", monospace;
}
.unixnotis-panel-icon {
margin-right: 8px;
}
.unixnotis-notification-actions {
margin-top: 4px;
}
.unixnotis-notification-action {
background-image:
linear-gradient(180deg, alpha(#ffffff, 0.11) 0%, alpha(#ffffff, 0.02) 40%, alpha(#000000, 0.07) 100%),
linear-gradient(150deg, @unixnotis-action-bg, alpha(@unixnotis-surface, 0.92));
color: @unixnotis-text;
border-radius: 3px;
padding: 4px 8px;
border: 1px solid alpha(@unixnotis-outline, 0.62);
min-height: 25px;
font-size: 10px;
font-weight: 700;
letter-spacing: 0.09em;
text-transform: uppercase;
box-shadow: inset 0 1px 0 alpha(#ffffff, 0.07);
}
.unixnotis-notification-action:hover {
background-image: linear-gradient(150deg, @unixnotis-action-bg-hover, alpha(@unixnotis-surface-strong, 0.82));
border-color: alpha(@unixnotis-accent, 0.46);
}popup.css
/* UnixNotis popup theme: Kernel Desk */
.unixnotis-popup-stack {
padding: 12px;
background: transparent;
}
.unixnotis-popup-revealer {
margin-bottom: 8px;
background: transparent;
}
.unixnotis-popup-card {
background-image:
linear-gradient(180deg, alpha(#ffffff, 0.12) 0%, alpha(#ffffff, 0.03) 40%, alpha(#000000, 0.08) 100%),
linear-gradient(155deg, @unixnotis-popup-bg-1 0%, @unixnotis-popup-bg-2 100%),
repeating-linear-gradient(0deg, alpha(#9aa8be, 0.08), alpha(#9aa8be, 0.08) 1px, transparent 1px, transparent 14px);
color: @unixnotis-text;
border-radius: 4px;
border: 1px solid alpha(@unixnotis-outline, 0.74);
padding: 13px;
box-shadow:
inset 0 1px 0 alpha(#ffffff, 0.08),
inset 0 0 0 1px alpha(@unixnotis-outline, 0.10),
0 14px 24px -16px @unixnotis-shadow-soft;
}
.unixnotis-popup-card.unixnotis-popup-stacked {
box-shadow: 0 8px 16px -14px @unixnotis-shadow-soft;
opacity: 0.95;
}
.unixnotis-popup-card.unixnotis-popup-visible {
opacity: 1;
}
.unixnotis-popup-card.critical {
border-color: alpha(@unixnotis-urgent, 0.86);
background-image: linear-gradient(155deg, alpha(#2a1118, 0.96), alpha(#1f0d14, 0.96));
box-shadow:
inset 0 0 0 1px alpha(@unixnotis-urgent, 0.24),
0 14px 24px -16px alpha(@unixnotis-urgent, 0.26);
}
.unixnotis-popup-header-row {
margin-bottom: 8px;
padding: 7px 9px;
border-radius: 3px;
background: alpha(@unixnotis-surface-strong, 0.72);
border: 1px solid alpha(@unixnotis-outline, 0.42);
}
.unixnotis-popup-icon {
color: @unixnotis-accent-2;
}
.unixnotis-popup-header {
color: @unixnotis-muted;
text-transform: uppercase;
letter-spacing: 0.10em;
font-size: 11px;
font-weight: 700;
}
.unixnotis-popup-summary {
color: @unixnotis-text;
font-size: 14px;
font-weight: 760;
margin-top: 4px;
}
.unixnotis-popup-body {
color: alpha(@unixnotis-text, 0.94);
font-size: 13px;
line-height: 1.33;
margin-top: 6px;
font-family: "JetBrains Mono", "Iosevka Aile", monospace;
}
.unixnotis-popup-actions {
margin-top: 11px;
}
.unixnotis-popup-action {
background: @unixnotis-popup-action-bg;
color: @unixnotis-text;
border-radius: 3px;
border: 1px solid alpha(@unixnotis-outline, 0.62);
padding: 6px 11px;
text-transform: uppercase;
letter-spacing: 0.09em;
font-size: 10px;
font-weight: 700;
box-shadow: inset 0 1px 0 alpha(#ffffff, 0.08);
}
.unixnotis-popup-action:hover {
background: @unixnotis-popup-action-hover;
border-color: alpha(@unixnotis-accent, 0.58);
box-shadow: inset 0 0 0 1px alpha(@unixnotis-accent, 0.10);
}
.unixnotis-popup-action:active,
.unixnotis-popup-action:checked {
background: linear-gradient(150deg, alpha(@unixnotis-accent, 0.28), alpha(@unixnotis-accent-2, 0.22));
color: @unixnotis-text;
}widgets.css
/* UnixNotis widgets + media theme
*
* Quick controls, toggles, stats, info cards, and media carousel.
*/
.unixnotis-quick-controls {
margin-bottom: 5px;
}
.unixnotis-quick-slider {
background-image:
linear-gradient(180deg, alpha(#ffffff, 0.12) 0%, alpha(#ffffff, 0.03) 40%, alpha(#000000, 0.08) 100%),
linear-gradient(150deg, alpha(@unixnotis-surface, 0.98), alpha(@unixnotis-surface-soft, 0.94)),
repeating-linear-gradient(0deg, alpha(#9aa8be, 0.08), alpha(#9aa8be, 0.08) 1px, transparent 1px, transparent 14px);
border-radius: 4px;
padding: 8px;
border: 1px solid alpha(@unixnotis-outline, 0.68);
box-shadow:
inset 0 1px 0 alpha(#ffffff, 0.08),
inset 0 0 0 1px alpha(@unixnotis-outline, 0.10),
0 8px 16px -14px @unixnotis-shadow-soft;
}
.unixnotis-quick-slider:hover {
border-color: alpha(@unixnotis-accent, 0.60);
box-shadow:
inset 0 1px 0 alpha(#ffffff, 0.10),
inset 0 0 0 1px alpha(@unixnotis-accent, 0.10),
0 10px 18px -14px @unixnotis-shadow-soft;
}
.unixnotis-quick-slider-volume {
border-color: alpha(@unixnotis-accent, 0.35);
}
.unixnotis-quick-slider-brightness {
border-color: alpha(@unixnotis-accent-2, 0.35);
}
.unixnotis-quick-slider-icon {
background-image: linear-gradient(145deg, @unixnotis-pill-bg 0%, @unixnotis-pill-hover 100%);
color: #ffffff;
border-radius: 3px;
border: 1px solid alpha(@unixnotis-outline, 0.62);
padding: 4px;
min-width: 28px;
min-height: 28px;
box-shadow:
inset 0 1px 0 alpha(#ffffff, 0.10),
0 6px 12px -10px @unixnotis-shadow-soft;
}
.unixnotis-quick-slider-icon:hover {
background-image: linear-gradient(145deg, alpha(@unixnotis-accent, 0.85), alpha(@unixnotis-accent-2, 0.7));
border-color: alpha(@unixnotis-accent, 0.5);
}
.unixnotis-quick-slider-value {
color: @unixnotis-muted;
font-size: 12px;
letter-spacing: 0.06em;
min-width: 34px;
/* Alignment is controlled by the widget code (set_xalign) for GTK compatibility. */
font-variant-numeric: tabular-nums;
font-feature-settings: "tnum";
}
.unixnotis-quick-slider-scale trough {
background: alpha(#05080d, 0.72);
border-radius: 3px;
min-height: 8px;
border: 1px solid alpha(@unixnotis-outline, 0.58);
}
.unixnotis-quick-slider-scale highlight {
background-image: linear-gradient(90deg, @unixnotis-accent 0%, @unixnotis-accent-2 100%);
border-radius: 2px;
}
.unixnotis-quick-slider-scale slider {
background: alpha(@unixnotis-surface-strong, 0.98);
border-radius: 2px;
min-width: 12px;
min-height: 12px;
border: 1px solid alpha(@unixnotis-outline, 0.74);
margin: -1px;
padding: 0;
box-shadow: inset 0 0 0 1px alpha(#ffffff, 0.08);
}
/*
* Toggle grid
*/
.unixnotis-toggle-section {
margin-bottom: 3px;
}
.unixnotis-toggle-grid {
padding: 0;
}
.unixnotis-toggle {
background-image:
linear-gradient(180deg, alpha(#ffffff, 0.12) 0%, alpha(#ffffff, 0.03) 38%, alpha(#000000, 0.08) 100%),
linear-gradient(165deg, alpha(@unixnotis-surface, 0.98), alpha(@unixnotis-surface-soft, 0.92)),
repeating-linear-gradient(135deg, alpha(#9aa8be, 0.08), alpha(#9aa8be, 0.08) 4px, transparent 4px, transparent 10px);
border-radius: 4px;
padding: 7px 8px;
border: 1px solid alpha(@unixnotis-outline, 0.68);
min-height: 56px;
min-width: 82px;
box-shadow:
inset 0 1px 0 alpha(#ffffff, 0.08),
inset 0 0 0 1px alpha(@unixnotis-outline, 0.10),
0 6px 12px -10px alpha(@unixnotis-shadow-soft, 0.28);
color: @unixnotis-muted;
}
/* Kind-specific toggle accents
*
* The center UI assigns a stable class: `.unixnotis-toggle-kind-<kind>`.
* These overrides provide a distinct accent per control while preserving the
* same layout and interaction behavior. */
.unixnotis-toggle.unixnotis-toggle-kind-wifi {
border-color: alpha(@unixnotis-accent-wifi, 0.55);
}
.unixnotis-toggle.unixnotis-toggle-kind-bluetooth {
border-color: alpha(@unixnotis-accent-bluetooth, 0.55);
}
.unixnotis-toggle.unixnotis-toggle-kind-airplane {
border-color: alpha(@unixnotis-accent-airplane, 0.55);
}
.unixnotis-toggle.unixnotis-toggle-kind-night {
border-color: alpha(@unixnotis-accent-night, 0.55);
}
.unixnotis-toggle:hover {
background-image: linear-gradient(165deg, alpha(@unixnotis-surface, 0.98), alpha(@unixnotis-surface-soft, 0.92));
border-color: alpha(@unixnotis-accent, 0.60);
color: @unixnotis-text;
box-shadow:
inset 0 1px 0 alpha(#ffffff, 0.10),
inset 0 0 0 1px alpha(@unixnotis-accent, 0.10),
0 8px 14px -10px alpha(@unixnotis-shadow-soft, 0.32);
}
.unixnotis-toggle.unixnotis-toggle-kind-wifi:hover {
border-color: alpha(@unixnotis-accent-wifi, 0.62);
}
.unixnotis-toggle.unixnotis-toggle-kind-bluetooth:hover {
border-color: alpha(@unixnotis-accent-bluetooth, 0.62);
}
.unixnotis-toggle.unixnotis-toggle-kind-airplane:hover {
border-color: alpha(@unixnotis-accent-airplane, 0.62);
}
.unixnotis-toggle.unixnotis-toggle-kind-night:hover {
border-color: alpha(@unixnotis-accent-night, 0.62);
}
.unixnotis-toggle:checked {
color: @unixnotis-text;
border-color: alpha(@unixnotis-accent, 0.74);
background-image: linear-gradient(150deg, alpha(@unixnotis-accent, 0.28) 0%, alpha(@unixnotis-accent-2, 0.22) 100%);
box-shadow:
inset 0 1px 0 alpha(#ffffff, 0.10),
inset 0 0 0 1px alpha(@unixnotis-accent, 0.10),
0 8px 16px -10px alpha(@unixnotis-shadow-soft, 0.36);
}
.unixnotis-toggle.unixnotis-toggle-kind-wifi:checked {
background-image: linear-gradient(150deg, alpha(@unixnotis-accent-wifi, 0.28) 0%, alpha(@unixnotis-accent-wifi, 0.14) 100%);
}
.unixnotis-toggle.unixnotis-toggle-kind-bluetooth:checked {
background-image: linear-gradient(150deg, alpha(@unixnotis-accent-bluetooth, 0.28) 0%, alpha(@unixnotis-accent-bluetooth, 0.14) 100%);
}
.unixnotis-toggle.unixnotis-toggle-kind-airplane:checked {
background-image: linear-gradient(150deg, alpha(@unixnotis-accent-airplane, 0.30) 0%, alpha(@unixnotis-accent-airplane, 0.14) 100%);
}
.unixnotis-toggle.unixnotis-toggle-kind-night:checked {
background-image: linear-gradient(150deg, alpha(@unixnotis-accent-night, 0.30) 0%, alpha(@unixnotis-accent-night, 0.14) 100%);
}
/* Keep outlines and depth visible when the panel is unfocused (GTK backdrop). */
.unixnotis-toggle:backdrop {
border-color: alpha(@unixnotis-outline, 0.56);
box-shadow: inset 0 1px 0 alpha(#ffffff, 0.62);
}
.unixnotis-toggle.unixnotis-toggle-kind-wifi:backdrop {
border-color: alpha(@unixnotis-accent-wifi, 0.55);
}
.unixnotis-toggle.unixnotis-toggle-kind-bluetooth:backdrop {
border-color: alpha(@unixnotis-accent-bluetooth, 0.55);
}
.unixnotis-toggle.unixnotis-toggle-kind-airplane:backdrop {
border-color: alpha(@unixnotis-accent-airplane, 0.55);
}
.unixnotis-toggle.unixnotis-toggle-kind-night:backdrop {
border-color: alpha(@unixnotis-accent-night, 0.55);
}
.unixnotis-toggle-icon {
-gtk-icon-size: 16px;
min-width: 21px;
min-height: 21px;
border-radius: 2px;
border: 1px solid alpha(@unixnotis-outline, 0.58);
background: alpha(@unixnotis-surface-strong, 0.88);
padding: 3px;
}
.unixnotis-toggle-label {
font-size: 11px;
font-weight: 760;
text-transform: uppercase;
line-height: 1.14;
letter-spacing: 0.04em;
}
.unixnotis-toggle:checked .unixnotis-toggle-icon {
background: alpha(@unixnotis-surface-strong, 0.96);
border-color: alpha(@unixnotis-accent, 0.54);
}
.unixnotis-stat-header,
.unixnotis-info-header {
margin-bottom: 4px;
}
.unixnotis-stat-icon,
.unixnotis-info-icon {
background: alpha(@unixnotis-surface-strong, 0.86);
border-radius: 2px;
padding: 3px;
border: 1px solid alpha(@unixnotis-outline, 0.58);
color: @unixnotis-muted;
}
/*
* Stat grid
*/
.unixnotis-stat-section {
margin-bottom: 3px;
}
.unixnotis-stat-grid {
padding: 0;
}
.unixnotis-stat-card {
background-image:
linear-gradient(180deg, alpha(#ffffff, 0.12) 0%, alpha(#ffffff, 0.02) 42%, alpha(#000000, 0.08) 100%),
linear-gradient(155deg, alpha(@unixnotis-surface, 0.98), alpha(@unixnotis-surface-soft, 0.94)),
repeating-linear-gradient(0deg, alpha(#9aa8be, 0.07), alpha(#9aa8be, 0.07) 1px, transparent 1px, transparent 14px);
border-radius: 4px;
padding: 7px 8px;
border: 1px solid alpha(@unixnotis-accent, 0.52);
min-height: 52px;
box-shadow:
inset 0 1px 0 alpha(#ffffff, 0.08),
inset 0 0 0 1px alpha(@unixnotis-accent, 0.14),
0 0 0 1px alpha(@unixnotis-accent-2, 0.14),
0 8px 16px -14px @unixnotis-shadow-soft;
}
.unixnotis-stat-card:hover {
border-color: alpha(@unixnotis-accent-2, 0.68);
box-shadow:
inset 0 1px 0 alpha(#ffffff, 0.10),
inset 0 0 0 1px alpha(@unixnotis-accent-2, 0.14),
0 0 0 1px alpha(@unixnotis-accent-2, 0.22),
0 10px 18px -14px @unixnotis-shadow-soft;
}
.unixnotis-stat-card:backdrop {
border-color: alpha(@unixnotis-accent, 0.46);
box-shadow:
inset 0 1px 0 alpha(#ffffff, 0.64),
inset 0 0 0 1px alpha(@unixnotis-accent, 0.10),
0 8px 14px -14px @unixnotis-shadow-soft;
}
.unixnotis-stat-title {
font-size: 11px;
text-transform: uppercase;
letter-spacing: 0.08em;
color: @unixnotis-muted;
}
.unixnotis-stat-value {
font-size: 14px;
font-weight: 700;
color: @unixnotis-text;
letter-spacing: 0.03em;
}
/*
* Info cards
*/
.unixnotis-card-section {
margin-top: 0;
margin-bottom: 3px;
padding-top: 0;
border-top: 1px solid alpha(@unixnotis-outline, 0.30);
box-shadow:
inset 0 1px 0 alpha(#ffffff, 0.03),
0 -1px 0 alpha(#06080a, 0.48);
}
.unixnotis-card-grid {
padding: 0;
}
.unixnotis-info-card {
background-image:
linear-gradient(180deg, alpha(#ffffff, 0.12) 0%, alpha(#ffffff, 0.02) 42%, alpha(#000000, 0.08) 100%),
linear-gradient(155deg, alpha(@unixnotis-surface, 0.98), alpha(@unixnotis-surface-soft, 0.94)),
repeating-linear-gradient(0deg, alpha(#9aa8be, 0.07), alpha(#9aa8be, 0.07) 1px, transparent 1px, transparent 14px);
border-radius: 4px;
padding: 8px;
border: 1px solid alpha(@unixnotis-outline, 0.68);
min-height: 52px;
box-shadow:
inset 0 1px 0 alpha(#ffffff, 0.08),
inset 0 0 0 1px alpha(@unixnotis-outline, 0.10),
0 8px 16px -14px @unixnotis-shadow-soft;
}
.unixnotis-info-card:hover {
border-color: alpha(@unixnotis-accent-2, 0.58);
box-shadow:
inset 0 1px 0 alpha(#ffffff, 0.10),
inset 0 0 0 1px alpha(@unixnotis-accent-2, 0.10),
0 10px 18px -14px @unixnotis-shadow-soft;
}
.unixnotis-info-card:backdrop {
border-color: alpha(@unixnotis-outline, 0.56);
box-shadow:
inset 0 1px 0 alpha(#ffffff, 0.66),
0 8px 14px -14px @unixnotis-shadow-soft;
}
.unixnotis-info-title {
font-size: 12px;
font-weight: 700;
letter-spacing: 0.04em;
}
.unixnotis-info-body {
font-size: 12px;
color: @unixnotis-muted;
line-height: 1.20;
}
.unixnotis-info-card-mono .unixnotis-info-body {
font-family: "Iosevka Term", "CaskaydiaCove Nerd Font Mono", "JetBrains Mono", monospace;
color: @unixnotis-text;
letter-spacing: 0.02em;
}
/* Calendar card */
.unixnotis-calendar {
background-image:
linear-gradient(180deg, alpha(#ffffff, 0.10) 0%, alpha(#ffffff, 0.02) 42%, alpha(#000000, 0.08) 100%),
linear-gradient(160deg, alpha(@unixnotis-card, 0.98), alpha(@unixnotis-surface, 0.96)),
repeating-linear-gradient(0deg, alpha(#9aa8be, 0.07), alpha(#9aa8be, 0.07) 1px, transparent 1px, transparent 14px);
border: 1px solid alpha(@unixnotis-outline, 0.68);
border-radius: 3px;
padding: 6px;
color: @unixnotis-text;
box-shadow:
inset 0 1px 0 alpha(#ffffff, 0.08),
inset 0 0 0 1px alpha(@unixnotis-outline, 0.10),
0 8px 16px -14px @unixnotis-shadow-soft;
}
.unixnotis-calendar button {
background-image: linear-gradient(160deg, alpha(@unixnotis-action-bg, 0.9), alpha(@unixnotis-surface-strong, 0.94));
border-radius: 2px;
border: 1px solid alpha(@unixnotis-outline, 0.66);
padding: 2px;
min-width: 18px;
min-height: 18px;
color: @unixnotis-accent;
-gtk-icon-size: 12px;
-gtk-icon-style: symbolic;
-gtk-icon-shadow: 0 0 6px alpha(@unixnotis-accent, 0.45);
-gtk-icon-palette: success @unixnotis-accent, warning @unixnotis-accent, error @unixnotis-accent;
box-shadow: inset 0 1px 0 alpha(#ffffff, 0.08);
}
.unixnotis-calendar button:hover {
background-image: linear-gradient(160deg, alpha(@unixnotis-action-bg-hover, 0.9), alpha(@unixnotis-accent, 0.22));
border-color: alpha(@unixnotis-accent, 0.55);
color: @unixnotis-accent;
}
.unixnotis-calendar button:active {
background-image: linear-gradient(160deg, alpha(@unixnotis-action-bg-active, 0.85), alpha(@unixnotis-accent, 0.3));
border-color: alpha(@unixnotis-accent, 0.62);
color: #ffffff;
}
.unixnotis-calendar button:disabled {
color: alpha(@unixnotis-muted, 0.6);
border-color: alpha(@unixnotis-outline, 0.4);
}
.unixnotis-calendar button image,
.unixnotis-calendar button label,
.unixnotis-calendar button arrow,
.unixnotis-calendar button .image,
.unixnotis-calendar button .icon {
/* Force symbolic icons to render with the same contrast as text. */
color: inherit;
-gtk-icon-shadow: 0 0 0 transparent;
-gtk-icon-palette: success @unixnotis-text, warning @unixnotis-text, error @unixnotis-text;
}
.unixnotis-calendar .header button image,
.unixnotis-calendar .header button label,
.unixnotis-calendar .header button arrow {
/* Header arrows sometimes inherit muted colors; force the accent to ensure visibility. */
color: @unixnotis-accent;
-gtk-icon-shadow: 0 0 6px alpha(@unixnotis-accent, 0.35);
}
.unixnotis-calendar header > button:nth-child(1) {
/* Prev month */
-gtk-icon-source: -gtk-icontheme("go-previous-symbolic");
background-image:
-gtk-icontheme("go-previous-symbolic"),
linear-gradient(160deg, alpha(@unixnotis-action-bg, 0.8), alpha(@unixnotis-surface-strong, 0.9));
background-size: 12px 12px, auto;
background-repeat: no-repeat, no-repeat;
background-position: center, center;
}
.unixnotis-calendar header > button:nth-child(3) {
/* Next month */
-gtk-icon-source: -gtk-icontheme("go-next-symbolic");
background-image:
-gtk-icontheme("go-next-symbolic"),
linear-gradient(160deg, alpha(@unixnotis-action-bg, 0.8), alpha(@unixnotis-surface-strong, 0.9));
background-size: 12px 12px, auto;
background-repeat: no-repeat, no-repeat;
background-position: center, center;
}
.unixnotis-calendar header > button:nth-child(4) {
/* Prev year */
-gtk-icon-source: -gtk-icontheme("go-down-symbolic");
background-image:
-gtk-icontheme("go-down-symbolic"),
linear-gradient(160deg, alpha(@unixnotis-action-bg, 0.8), alpha(@unixnotis-surface-strong, 0.9));
background-size: 12px 12px, auto;
background-repeat: no-repeat, no-repeat;
background-position: center, center;
}
.unixnotis-calendar header > button:nth-child(6) {
/* Next year */
-gtk-icon-source: -gtk-icontheme("go-up-symbolic");
background-image:
-gtk-icontheme("go-up-symbolic"),
linear-gradient(160deg, alpha(@unixnotis-action-bg, 0.8), alpha(@unixnotis-surface-strong, 0.9));
background-size: 12px 12px, auto;
background-repeat: no-repeat, no-repeat;
background-position: center, center;
}
.unixnotis-calendar .header {
color: @unixnotis-muted;
font-weight: 700;
letter-spacing: 0.10em;
text-transform: uppercase;
border-bottom: 1px solid alpha(@unixnotis-outline, 0.42);
padding-bottom: 6px;
margin-bottom: 6px;
}
.unixnotis-calendar .day-name {
color: alpha(@unixnotis-muted, 0.9);
font-weight: 600;
font-size: 11px;
letter-spacing: 0.08em;
}
.unixnotis-calendar .day-number {
color: @unixnotis-text;
font-weight: 600;
}
.unixnotis-calendar .day-number.other-month {
color: alpha(@unixnotis-muted, 0.45);
}
.unixnotis-calendar:selected,
.unixnotis-calendar .day-number:selected {
background-image: linear-gradient(135deg, alpha(@unixnotis-accent, 0.30), alpha(@unixnotis-accent-2, 0.22));
color: @unixnotis-text;
border-radius: 2px;
box-shadow:
0 0 0 1px alpha(@unixnotis-accent, 0.52),
0 0 14px -12px alpha(@unixnotis-accent, 0.52);
}
.unixnotis-calendar .day-number.today {
box-shadow:
inset 0 0 0 1px alpha(@unixnotis-accent-2, 0.60),
0 0 10px -8px alpha(@unixnotis-accent-2, 0.48);
border-radius: 2px;
}
.unixnotis-info-card-weather {
background-image:
radial-gradient(circle at 85% 18%, alpha(@unixnotis-accent, 0.14), transparent 55%),
linear-gradient(155deg, alpha(@unixnotis-surface-soft, 0.94), alpha(@unixnotis-surface, 0.98));
border-color: alpha(@unixnotis-accent-2, 0.45);
box-shadow:
inset 0 1px 0 alpha(#ffffff, 0.08),
inset 0 0 0 1px alpha(@unixnotis-accent-2, 0.10),
0 10px 18px -14px @unixnotis-shadow-soft;
}
.unixnotis-info-card-weather .unixnotis-info-title {
font-size: 11px;
letter-spacing: 0.08em;
text-transform: uppercase;
color: @unixnotis-muted;
}
.unixnotis-info-card-weather .unixnotis-info-body {
font-size: 16px;
font-weight: 900;
letter-spacing: 0.03em;
font-family: "JetBrains Mono", "Iosevka Aile", monospace;
}
.unixnotis-info-icon-weather {
color: @unixnotis-accent;
}
/*
* Media carousel
*
* Displays active MPRIS players with navigation buttons.
*/
.unixnotis-media-container {
margin-bottom: 6px;
}
.unixnotis-media-stack {
background: transparent;
}
.unixnotis-media-row {
background: transparent;
}
.unixnotis-media-nav {
background-image: linear-gradient(150deg, @unixnotis-action-bg, alpha(@unixnotis-surface, 0.9));
border-radius: 3px;
padding: 2px;
border: 1px solid alpha(@unixnotis-outline, 0.64);
font-weight: 700;
font-size: 10px;
min-width: 18px;
color: @unixnotis-text;
box-shadow: inset 0 1px 0 alpha(#ffffff, 0.08);
}
.unixnotis-media-nav:hover {
background-image: linear-gradient(150deg, @unixnotis-action-bg-hover, alpha(@unixnotis-surface-strong, 0.82));
border-color: alpha(@unixnotis-accent, 0.45);
}
.unixnotis-media-position {
color: @unixnotis-muted;
font-size: 10px;
letter-spacing: 0.08em;
}
.unixnotis-media-card {
background-image:
linear-gradient(180deg, alpha(#ffffff, 0.11) 0%, alpha(#ffffff, 0.02) 40%, alpha(#000000, 0.08) 100%),
linear-gradient(155deg, @unixnotis-notification-bg-1 0%, @unixnotis-notification-bg-2 100%),
repeating-linear-gradient(0deg, alpha(#9aa8be, 0.07), alpha(#9aa8be, 0.07) 1px, transparent 1px, transparent 14px);
border-radius: 4px;
border: 1px solid @unixnotis-card-border;
padding: 6px 8px;
min-height: 56px;
box-shadow:
inset 0 1px 0 alpha(#ffffff, 0.08),
inset 0 0 0 1px alpha(@unixnotis-outline, 0.10),
0 10px 18px -14px @unixnotis-shadow-soft;
}
.unixnotis-media-card.playing {
border-left: 2px solid alpha(@unixnotis-accent, 0.7);
}
.unixnotis-media-art {
min-width: 40px;
min-height: 40px;
border-radius: 2px;
background: alpha(@unixnotis-surface-strong, 0.72);
}
.unixnotis-media-art-frame {
min-width: 44px;
min-height: 44px;
border-radius: 2px;
background: alpha(@unixnotis-surface-strong, 0.80);
border: 1px solid alpha(@unixnotis-outline, 0.62);
box-shadow: inset 0 1px 0 alpha(#ffffff, 0.08);
}
.unixnotis-media-art.empty {
background: alpha(@unixnotis-surface-strong, 0.60);
}
.unixnotis-media-source {
font-size: 10px;
letter-spacing: 0.1em;
text-transform: uppercase;
color: @unixnotis-muted;
}
.unixnotis-media-title {
font-weight: 700;
font-size: 11px;
}
.unixnotis-marquee {
background: transparent;
padding: 0;
margin: 0;
}
.unixnotis-media-artist {
color: @unixnotis-muted;
font-size: 10px;
}
.unixnotis-media-artist.empty {
color: transparent;
}
.unixnotis-media-controls {
background: transparent;
}
.unixnotis-media-button {
background-image: linear-gradient(160deg, @unixnotis-action-bg, alpha(@unixnotis-surface, 0.95));
border-radius: 3px;
border: 1px solid alpha(@unixnotis-outline, 0.64);
padding: 3px 5px;
box-shadow: inset 0 1px 0 alpha(#ffffff, 0.08);
}
.unixnotis-media-button:hover {
background-image: linear-gradient(160deg, @unixnotis-action-bg-hover, alpha(@unixnotis-surface-strong, 0.84));
border-color: alpha(@unixnotis-accent, 0.46);
}
.unixnotis-media-button.primary {
background-image: linear-gradient(160deg, @unixnotis-action-bg-active, alpha(@unixnotis-accent-2, 0.22));
border-color: alpha(@unixnotis-accent, 0.62);
color: #ffffff;
}installer.toml
# UnixNotis installer settings
# Backup retention for config/theme resets.
[backups]
keep = 3scripts/unixnotis-creative-status
#!/usr/bin/env bash
set -euo pipefail
# Emit a compact system pulse card for UnixNotis widget plugin API v1
# Command selection stays lightweight to keep refresh cost low
now_hm="$(date '+%H:%M')"
read -r uptime_seconds _ < /proc/uptime
uptime_minutes=$(( ${uptime_seconds%.*} / 60 ))
uptime_hours=$(( uptime_minutes / 60 ))
uptime_remainder_minutes=$(( uptime_minutes % 60 ))
if (( uptime_hours > 0 )); then
uptime_human="${uptime_hours}h ${uptime_remainder_minutes}m"
else
uptime_human="${uptime_remainder_minutes}m"
fi
read -r load_1 load_5 load_15 _ < /proc/loadavg
battery_line="AC power"
for battery_dir in /sys/class/power_supply/BAT*; do
if [[ -d "$battery_dir" ]]; then
capacity="$(cat "$battery_dir/capacity" 2>/dev/null || echo "?")"
status="$(cat "$battery_dir/status" 2>/dev/null || echo "Unknown")"
battery_line="${capacity}% (${status})"
break
fi
done
title="Kernel Pulse"
text="$(printf 'time : %s\nup : %s\nload : %s %s %s\nbatt : %s' "$now_hm" "$uptime_human" "$load_1" "$load_5" "$load_15" "$battery_line")"
jq -nc --arg title "$title" --arg text "$text" '{api_version:1,title:$title,text:$text}'scripts/unixnotis-net-rate-stat
#!/usr/bin/env bash
set -euo pipefail
# Emit aggregate network throughput as a stat payload for widget plugin API v1.
# State is persisted under the runtime directory to derive a short-interval rate.
state_dir="${XDG_RUNTIME_DIR:-/tmp}/unixnotis"
state_file="${state_dir}/net-rate.state"
mkdir -p "$state_dir"
now_ns="$(date +%s%N)"
read -r rx_now tx_now <<DATA
$(awk -F '[: ]+' 'BEGIN { rx=0; tx=0 } $1 !~ /^lo$/ && $1 != "" { rx += $3; tx += $11 } END { print rx, tx }' /proc/net/dev)
DATA
format_rate() {
local bytes_per_sec="$1"
if (( bytes_per_sec >= 1048576 )); then
printf '%.1fM' "$(awk -v b="$bytes_per_sec" 'BEGIN { print b / 1048576.0 }')"
elif (( bytes_per_sec >= 1024 )); then
printf '%.0fK' "$(awk -v b="$bytes_per_sec" 'BEGIN { print b / 1024.0 }')"
else
printf '%dB' "$bytes_per_sec"
fi
}
if [[ -f "$state_file" ]]; then
read -r prev_ns prev_rx prev_tx < "$state_file" || true
else
prev_ns=0
prev_rx="$rx_now"
prev_tx="$tx_now"
fi
rate_rx=0
rate_tx=0
if [[ "$prev_ns" =~ ^[0-9]+$ ]] && (( prev_ns > 0 )) && (( now_ns > prev_ns )); then
dt_ns=$(( now_ns - prev_ns ))
drx=$(( rx_now - prev_rx ))
dtx=$(( tx_now - prev_tx ))
if (( drx < 0 )); then drx=0; fi
if (( dtx < 0 )); then dtx=0; fi
rate_rx=$(( drx * 1000000000 / dt_ns ))
rate_tx=$(( dtx * 1000000000 / dt_ns ))
fi
printf '%s %s %s\n' "$now_ns" "$rx_now" "$tx_now" > "$state_file"
text="$(printf 'D:%s U:%s' "$(format_rate "$rate_rx")" "$(format_rate "$rate_tx")")"
jq -nc --arg text "$text" '{api_version:1,text:$text}'scripts/unixnotis-process-card
#!/usr/bin/env bash
set -euo pipefail
# Emit process pressure snapshot as a compact card payload for widget plugin API v1
read_proc_line() {
ps -eo comm=,%cpu=,%mem= --sort=-%cpu | awk 'NR==1 { print $1, $2, $3 }'
}
proc_line="$(read_proc_line 2>/dev/null || true)"
if [[ -z "$proc_line" ]]; then
text="cpu : n/a\nmem : n/a"
else
proc_cpu="$(awk '{print $2}' <<< "$proc_line")"
proc_mem="$(awk '{print $3}' <<< "$proc_line")"
if [[ -z "$proc_cpu" ]]; then proc_cpu="0.0"; fi
if [[ -z "$proc_mem" ]]; then proc_mem="0.0"; fi
text="$(printf 'cpu : %s%%\nmem : %s%%' "$proc_cpu" "$proc_mem")"
fi
jq -nc --arg title "Hot Process" --arg text "$text" '{api_version:1,title:$title,text:$text}'scripts/unixnotis-storage-card
#!/usr/bin/env bash
set -euo pipefail
# Emit storage summary as a compact card payload for widget plugin API v1
read_root_line() {
df -h --output=target,size,used,avail,pcent / | awk 'NR==2 { print $0 }'
}
read_home_line() {
df -h --output=target,size,used,avail,pcent "$HOME" | awk 'NR==2 { print $0 }'
}
root_line="$(read_root_line 2>/dev/null || true)"
home_line="$(read_home_line 2>/dev/null || true)"
if [[ -z "$root_line" ]]; then
text="storage: n/a"
else
root_size="$(awk '{print $2}' <<< "$root_line")"
root_used="$(awk '{print $3}' <<< "$root_line")"
root_avail="$(awk '{print $4}' <<< "$root_line")"
root_pct="$(awk '{print $5}' <<< "$root_line")"
printf -v text '/ used %s of %s | free %s\nutil: %s' "$root_used" "$root_size" "$root_avail" "$root_pct"
if [[ -n "$home_line" ]]; then
home_used="$(awk '{print $3}' <<< "$home_line")"
home_size="$(awk '{print $2}' <<< "$home_line")"
home_pct="$(awk '{print $5}' <<< "$home_line")"
printf -v text '%s\nhome: %s/%s (%s)' "$text" "$home_used" "$home_size" "$home_pct"
fi
fi
jq -nc --arg title "Storage Map" --arg text "$text" '{api_version:1,title:$title,text:$text}'scripts/unixnotis-thermal-stat
#!/usr/bin/env bash
set -euo pipefail
# Emit CPU/package thermal data as a stat payload for widget plugin API v1.
best_temp_milli=""
best_label=""
for zone in /sys/class/thermal/thermal_zone*; do
[[ -d "$zone" ]] || continue
temp_file="$zone/temp"
type_file="$zone/type"
[[ -r "$temp_file" ]] || continue
temp_raw="$(cat "$temp_file" 2>/dev/null || true)"
[[ "$temp_raw" =~ ^[0-9]+$ ]] || continue
(( temp_raw > 0 )) || continue
zone_type="$(cat "$type_file" 2>/dev/null || echo "thermal")"
zone_type="${zone_type,,}"
# Prefer package/cpu zones where available, otherwise keep the hottest reading.
if [[ "$zone_type" == *"pkg"* || "$zone_type" == *"cpu"* ]]; then
best_temp_milli="$temp_raw"
best_label="cpu"
break
fi
if [[ -z "$best_temp_milli" ]] || (( temp_raw > best_temp_milli )); then
best_temp_milli="$temp_raw"
best_label="sys"
fi
done
if [[ -z "$best_temp_milli" ]]; then
text="n/a"
else
temp_c="$(awk -v t="$best_temp_milli" 'BEGIN { printf "%.1f", t / 1000.0 }')"
text="${best_label}:${temp_c}C"
fi
jq -nc --arg text "$text" '{api_version:1,text:$text}'scripts/unixnotis-toolchain-card
#!/usr/bin/env bash
set -euo pipefail
# Emit compiler/toolchain snapshot as compact text for a card widget
first_num() {
grep -Eo '[0-9]+([.][0-9]+)+' | head -n 1
}
get_ver() {
local bin="$1"
local line=""
local ver=""
if ! command -v "$bin" >/dev/null 2>&1; then
printf 'n/a'
return
fi
case "$bin" in
ld) line="$(ld -v 2>/dev/null | head -n 1 || true)" ;;
*) line="$($bin --version 2>/dev/null | head -n 1 || true)" ;;
esac
if [[ -z "$line" ]]; then
printf 'n/a'
return
fi
ver="$(printf '%s\n' "$line" | first_num)"
if [[ -z "$ver" ]]; then
printf 'ok'
else
printf '%s' "$ver"
fi
}
kernel_raw="$(uname -r 2>/dev/null || echo n/a)"
machine="$(uname -m 2>/dev/null || echo n/a)"
gcc_v="$(get_ver gcc)"
clang_v="$(get_ver clang)"
rust_v="$(get_ver rustc)"
nasm_v="$(get_ver nasm)"
ld_v="$(get_ver ld)"
# Keep only major.minor kernel version so the card stays informative
# without printing full distro/build identifiers
kernel_short="$(printf '%s\n' "$kernel_raw" | grep -Eo '^[0-9]+([.][0-9]+){0,2}' | cut -d. -f1-2)"
if [[ -z "$kernel_short" ]]; then
kernel_short="n/a"
fi
printf 'kernel: %s | %s\n' "$kernel_short" "$machine"
printf 'gcc/clang: %s / %s\n' "$gcc_v" "$clang_v"
printf 'rust/nasm: %s / %s\n' "$rust_v" "$nasm_v"
printf 'binutils : %s\n' "$ld_v"