diff --git a/.gitignore b/.gitignore
index 41c3d2d..0c5e35d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,3 +4,6 @@ config.tar.gz
# Dépôt git du thème Discord (sources SCSS)
# Le CSS compilé est dans INSTALL/themes/violet-chaton.theme.css
INSTALL/themes/violet-chaton-discord-theme/
+# Dépôt git du thème VSCode
+# Aucune source dans le projet général en 1.0.0
+INSTALL/themes/violet-chaton-VSCode-theme/
\ No newline at end of file
diff --git a/INSTALL/configs/autostart/waybar.desktop b/INSTALL/configs/autostart/waybar.desktop
new file mode 100644
index 0000000..3185bd4
--- /dev/null
+++ b/INSTALL/configs/autostart/waybar.desktop
@@ -0,0 +1,8 @@
+[Desktop Entry]
+Name=Waybar
+Comment=violet-chaton status bar
+Type=Application
+Exec=waybar
+Hidden=false
+NoDisplay=false
+X-GNOME-Autostart-enabled=true
diff --git a/INSTALL/configs/autostart/wob.desktop b/INSTALL/configs/autostart/wob.desktop
new file mode 100644
index 0000000..9c8ca4f
--- /dev/null
+++ b/INSTALL/configs/autostart/wob.desktop
@@ -0,0 +1,8 @@
+[Desktop Entry]
+Name=WOB
+Comment=Wayland overlay bar (volume / luminosité)
+Type=Application
+Exec=/home/tetardtek/.config/waybar/scripts/wob-start.sh
+Hidden=false
+NoDisplay=false
+X-GNOME-Autostart-enabled=true
diff --git a/INSTALL/configs/rofi/config.rasi b/INSTALL/configs/rofi/config.rasi
new file mode 100644
index 0000000..6e06897
--- /dev/null
+++ b/INSTALL/configs/rofi/config.rasi
@@ -0,0 +1,7 @@
+configuration {
+ font: "JetBrainsMono Nerd Font 13";
+ show-icons: false;
+ click-to-exit: true;
+}
+
+@theme "violet-chaton"
diff --git a/INSTALL/configs/waybar/cava-waybar.cfg b/INSTALL/configs/waybar/cava-waybar.cfg
new file mode 100644
index 0000000..e63c679
--- /dev/null
+++ b/INSTALL/configs/waybar/cava-waybar.cfg
@@ -0,0 +1,18 @@
+[general]
+bars = 8
+framerate = 30
+
+[input]
+method = pulse
+source = auto
+
+[output]
+method = raw
+raw_target = /dev/stdout
+data_format = ascii
+ascii_max_range = 8
+bar_delimiter = 59
+
+[smoothing]
+gravity = 100
+noise_reduction = 77
diff --git a/INSTALL/configs/waybar/config b/INSTALL/configs/waybar/config
new file mode 100644
index 0000000..611082e
--- /dev/null
+++ b/INSTALL/configs/waybar/config
@@ -0,0 +1,312 @@
+{
+ // ── violet-chaton Waybar — island floating 3 pills ──────────────────────
+ // LEFT : launcher | cpu + temp | gpu | ram | disk | network
+ // CENTER : cava | clock | date | mpris
+ // RIGHT : wireplumber | backlight | bluetooth | idle_inhibitor |
+ // battery | power-profile | keyboard-state |
+ // systemd-failed | uptime | tray
+ // ────────────────────────────────────────────────────────────────────────
+
+ "layer": "top",
+ "position": "top",
+ "height": 60,
+ "margin-top": 0,
+ "margin-left": 16,
+ "margin-right": 16,
+ "spacing": 0,
+ "exclusive": true,
+
+ "modules-left": [
+ "custom/launcher",
+ "custom/sep",
+ "cpu",
+ "temperature",
+ "custom/gpu",
+ "memory",
+ "disk",
+ "custom/sep",
+ "custom/network"
+ ],
+
+ "modules-center": [
+ "custom/cava",
+ "clock",
+ "custom/date",
+ "mpris"
+ ],
+
+ "modules-right": [
+ "wireplumber",
+ "backlight",
+ "bluetooth",
+ "custom/sep",
+ "idle_inhibitor",
+ "custom/sep",
+ "battery",
+ "custom/power-profile",
+ "custom/sep",
+ "custom/uptime",
+ "tray",
+ "custom/power"
+ ],
+
+ // ── Launcher ────────────────────────────────────────────────────────────
+
+ "custom/launcher": {
+ "format": "",
+ "tooltip": false,
+ "on-click": "~/.config/waybar/scripts/rofi-launcher.sh"
+ },
+
+ // ── Séparateur ──────────────────────────────────────────────────────────
+
+ "custom/sep": {
+ "format": "|",
+ "tooltip": false
+ },
+
+ // ── CPU ─────────────────────────────────────────────────────────────────
+
+ "cpu": {
+ "format": " {usage}%",
+ "tooltip-format": "Intel i5-12450H\n {usage}% @ {avg_frequency} GHz\n\nT00 {usage0}% T01 {usage1}% T02 {usage2}% T03 {usage3}%\nT04 {usage4}% T05 {usage5}% T06 {usage6}% T07 {usage7}%\nT08 {usage8}% T09 {usage9}% T10 {usage10}% T11 {usage11}%",
+ "states": {
+ "warning": 70,
+ "critical": 90
+ },
+ "interval": 2
+ },
+
+ // ── Température ─────────────────────────────────────────────────────────
+
+ "temperature": {
+ "thermal-zone": 9,
+ "format": " {temperatureC}°",
+ "format-critical": " {temperatureC}°",
+ "critical-threshold": 80,
+ "tooltip": false,
+ "interval": 2
+ },
+
+ // ── GPU ─────────────────────────────────────────────────────────────────
+
+ "custom/gpu": {
+ "exec": "~/.config/waybar/scripts/gpu.sh",
+ "return-type": "json",
+ "interval": 2,
+ "format": "{}"
+ },
+
+ // ── RAM ─────────────────────────────────────────────────────────────────
+
+ "memory": {
+ "format": " {used:0.1f}G",
+ "tooltip-format": " RAM\n{used:0.1f} GiB / {total:0.1f} GiB\n{percentage}% utilisé",
+ "states": {
+ "warning": 75,
+ "critical": 90
+ },
+ "interval": 2
+ },
+
+ // ── Disque ──────────────────────────────────────────────────────────────
+
+ "disk": {
+ "format": " {used}",
+ "tooltip-format": " Disque /\n{used} / {total}\n{percentage_used}% utilisé",
+ "interval": 30
+ },
+
+ // ── Réseau ──────────────────────────────────────────────────────────────
+
+ "custom/network": {
+ "exec": "~/.config/waybar/scripts/network.sh",
+ "return-type": "json",
+ "interval": 2,
+ "format": "{}"
+ },
+
+ // ── CAVA ────────────────────────────────────────────────────────────────
+
+ "custom/cava": {
+ "exec": "~/.config/waybar/scripts/cava-read.sh",
+ "return-type": "json",
+ "interval": 1,
+ "format": "{}",
+ "tooltip": false
+ },
+
+ // ── Horloge ─────────────────────────────────────────────────────────────
+
+ "clock": {
+ "format": " {:%H:%M}",
+ "format-alt": " {:%H:%M:%S}",
+ "tooltip-format": "{:%B %Y}\n{calendar}",
+ "calendar": {
+ "mode": "month",
+ "on-scroll": 1,
+ "format": {
+ "months": "{}",
+ "days": "{}",
+ "weeks": "W{}",
+ "weekdays": "{}",
+ "today": "{}"
+ }
+ },
+ "interval": 1
+ },
+
+ // ── Date ────────────────────────────────────────────────────────────────
+
+ "custom/date": {
+ "exec": "LC_ALL=fr_FR.UTF-8 date '+%a %d %b' | awk '{print toupper(substr($0,1,1)) substr($0,2)}'",
+ "interval": 60,
+ "tooltip": false
+ },
+
+ // ── MPRIS ───────────────────────────────────────────────────────────────
+
+ "mpris": {
+ "format": "{player_icon} {dynamic}",
+ "format-paused": "{player_icon} {dynamic}",
+ "player-icons": {
+ "default": "",
+ "spotify": "",
+ "firefox": "",
+ "chromium": "",
+ "vlc": ""
+ },
+ "status-icons": {
+ "paused": "",
+ "playing": "",
+ "stopped": ""
+ },
+ "dynamic-len": 30,
+ "ignored-players": ["firefox"],
+ "tooltip-format": "{player} — {title}\n{artist}\n{album}"
+ },
+
+ // ── Volume (wireplumber) ─────────────────────────────────────────────────
+
+ "wireplumber": {
+ "format": "{icon} {volume}%",
+ "format-muted": " {volume}%",
+ "format-icons": ["", "", ""],
+ "on-click": "python3 ~/.config/waybar/scripts/vc-media-popup.py",
+ "on-click-right": "~/.config/waybar/scripts/wob-volume.sh mute",
+ "on-scroll-up": "~/.config/waybar/scripts/wob-volume.sh up",
+ "on-scroll-down": "~/.config/waybar/scripts/wob-volume.sh down",
+ "tooltip-format": " Volume : {volume}%\n{node_name}"
+ },
+
+ // ── Luminosité ──────────────────────────────────────────────────────────
+
+ "backlight": {
+ "format": "{icon} {percent}%",
+ "format-icons": ["", "", ""],
+ "tooltip": false,
+ "on-click": "python3 ~/.config/waybar/scripts/vc-media-popup.py",
+ "on-scroll-up": "~/.config/waybar/scripts/wob-brightness.sh up",
+ "on-scroll-down": "~/.config/waybar/scripts/wob-brightness.sh down"
+ },
+
+ // ── Bluetooth ───────────────────────────────────────────────────────────
+
+ "bluetooth": {
+ "format": "",
+ "format-disabled": "",
+ "format-connected": " {device_alias}",
+ "tooltip-format": "{controller_alias} — {controller_address}\n{num_connections} connecté(s)",
+ "tooltip-format-connected": "{controller_alias}\n{device_enumerate}",
+ "tooltip-format-enumerate-connected": " {device_alias} ({device_address})"
+ },
+
+ // ── Idle inhibitor ──────────────────────────────────────────────────────
+
+ "idle_inhibitor": {
+ "format": "{icon}",
+ "format-icons": {
+ "activated": "",
+ "deactivated": ""
+ },
+ "tooltip-format-activated": "Veille désactivée",
+ "tooltip-format-deactivated": "Veille active"
+ },
+
+ // ── Batterie ────────────────────────────────────────────────────────────
+
+ "battery": {
+ "bat": "BAT1",
+ "states": {
+ "full": 95,
+ "good": 80,
+ "warning": 30,
+ "critical": 15
+ },
+ "format": "{icon} {capacity}%",
+ "format-charging": " {capacity}%",
+ "format-plugged": " {capacity}%",
+ "format-full": " {capacity}%",
+ "format-icons": ["", "", "", "", "", "", "", "", "", ""],
+ "tooltip-format": "Batterie : {capacity}%\n{timeTo}\nCycles estimés",
+ "interval": 30
+ },
+
+ // ── Profil énergie ──────────────────────────────────────────────────────
+
+ "custom/power-profile": {
+ "exec": "~/.config/waybar/scripts/power-profile.sh",
+ "return-type": "json",
+ "interval": 5,
+ "signal": 8,
+ "on-click": "~/.config/waybar/scripts/power-profile.sh --toggle"
+ },
+
+ // ── Clavier ─────────────────────────────────────────────────────────────
+
+ "keyboard-state": {
+ "numlock": true,
+ "capslock": true,
+ "format": {
+ "numlock": "{icon}",
+ "capslock": "{icon}"
+ },
+ "format-icons": {
+ "locked": "",
+ "unlocked": ""
+ }
+ },
+
+ // ── Systemd failed ──────────────────────────────────────────────────────
+
+ "systemd-failed-units": {
+ "format": " {nr_failed}",
+ "format-ok": "",
+ "hide-on-ok": true,
+ "system": true,
+ "user": true
+ },
+
+ // ── Uptime ──────────────────────────────────────────────────────────────
+
+ "custom/uptime": {
+ "exec": "awk '{s=$1; d=int(s/86400); h=int((s%86400)/3600); m=int((s%3600)/60); if(d>0) printf \" %dj %dh\",d,h; else if(h>0) printf \" %dh %dm\",h,m; else printf \" %dm\",m}' /proc/uptime",
+ "interval": 60,
+ "tooltip": false
+ },
+
+ // ── Tray ────────────────────────────────────────────────────────────────
+
+ "tray": {
+ "spacing": 8,
+ "icon-size": 16
+ },
+
+ // ── Bouton power ────────────────────────────────────────────────────────
+
+ "custom/power": {
+ "format": "",
+ "tooltip": false,
+ "on-click": "~/.config/waybar/scripts/power-menu.sh"
+ }
+}
diff --git a/INSTALL/configs/waybar/scripts/cava-read.sh b/INSTALL/configs/waybar/scripts/cava-read.sh
new file mode 100755
index 0000000..157bd75
--- /dev/null
+++ b/INSTALL/configs/waybar/scripts/cava-read.sh
@@ -0,0 +1,20 @@
+#!/usr/bin/env bash
+# cava-read.sh — lit /tmp/waybar_cava → JSON waybar (interval: 1)
+# Lance automatiquement le démon cava-waybar.sh si absent.
+
+OUT="/tmp/waybar_cava"
+PID="/tmp/waybar_cava.pid"
+DAEMON="$HOME/.config/waybar/scripts/cava-waybar.sh"
+
+# Démarrer le démon si pas actif
+if [[ ! -f "$PID" ]] || ! kill -0 "$(cat "$PID" 2>/dev/null)" 2>/dev/null; then
+ nohup bash "$DAEMON" >/dev/null 2>&1 &
+fi
+
+# Lire et retourner le JSON
+if [[ -f "$OUT" ]]; then
+ BAR=$(tail -1 "$OUT" 2>/dev/null)
+ [[ -n "$BAR" ]] && printf '{"text":"%s","tooltip":"","class":""}\n' "$BAR" && exit 0
+fi
+
+printf '{"text":"▁▁▁▁▁▁▁▁","tooltip":"","class":"muted"}\n'
diff --git a/INSTALL/configs/waybar/scripts/cava-waybar-daemon.sh b/INSTALL/configs/waybar/scripts/cava-waybar-daemon.sh
new file mode 100755
index 0000000..3e5d4fb
--- /dev/null
+++ b/INSTALL/configs/waybar/scripts/cava-waybar-daemon.sh
@@ -0,0 +1,12 @@
+#!/usr/bin/env bash
+# cava-waybar-daemon.sh — lance CAVA en daemon → /tmp/waybar_cava
+# Appeler au démarrage de la session
+
+pkill -f "cava -p.*cava-waybar.cfg" 2>/dev/null
+sleep 0.3
+
+CFG="$HOME/.config/waybar/cava-waybar.cfg"
+[[ ! -f "$CFG" ]] && { echo "Config manquante : $CFG"; exit 1; }
+
+cava -p "$CFG" > /tmp/waybar_cava &
+echo "CAVA daemon lancé (PID $!)"
diff --git a/INSTALL/configs/waybar/scripts/cava-waybar.sh b/INSTALL/configs/waybar/scripts/cava-waybar.sh
new file mode 100755
index 0000000..97d0a4e
--- /dev/null
+++ b/INSTALL/configs/waybar/scripts/cava-waybar.sh
@@ -0,0 +1,22 @@
+#!/usr/bin/env bash
+# cava-waybar.sh — démon CAVA : écrit la visu dans /tmp/waybar_cava
+# Lancé automatiquement par cava-read.sh, ne pas appeler directement.
+
+BLOCKS=('▁' '▁' '▂' '▃' '▄' '▅' '▆' '▇' '█')
+CFG="$HOME/.config/waybar/cava-waybar.cfg"
+OUT="/tmp/waybar_cava"
+PID="/tmp/waybar_cava.pid"
+
+echo $$ > "$PID"
+
+cleanup() { rm -f "$PID" "$OUT"; exit; }
+trap cleanup EXIT INT TERM
+
+cava -p "$CFG" | while IFS=';' read -ra VALUES; do
+ BAR=""
+ for v in "${VALUES[@]}"; do
+ v="${v//[^0-9]/}"
+ [[ -n "$v" ]] && BAR+="${BLOCKS[$v]:-▁}"
+ done
+ [[ -n "$BAR" ]] && printf '%s\n' "$BAR" > "$OUT"
+done
diff --git a/INSTALL/configs/waybar/scripts/gpu.sh b/INSTALL/configs/waybar/scripts/gpu.sh
new file mode 100755
index 0000000..f69226c
--- /dev/null
+++ b/INSTALL/configs/waybar/scripts/gpu.sh
@@ -0,0 +1,26 @@
+#!/usr/bin/env bash
+# gpu.sh — NVIDIA GPU stats → JSON waybar
+
+DATA=$(nvidia-smi --query-gpu=utilization.gpu,temperature.gpu,memory.used,memory.total \
+ --format=csv,noheader,nounits 2>/dev/null)
+
+if [[ -z "$DATA" ]]; then
+ echo '{"text":"","tooltip":"GPU non disponible","class":"","percentage":0}'
+ exit 0
+fi
+
+LOAD=$(echo "$DATA" | awk -F', ' '{print $1}')
+TEMP=$(echo "$DATA" | awk -F', ' '{print $2}')
+MEM_USED=$(echo "$DATA" | awk -F', ' '{print $3}')
+MEM_TOTAL=$(echo "$DATA" | awk -F', ' '{print $4}')
+
+if (( LOAD > 90 )); then CLASS="critical"
+elif (( LOAD > 70 )); then CLASS="warning"
+else CLASS="normal"
+fi
+
+TEXT=" ${LOAD}% ${TEMP}°"
+TOOLTIP=" GPU\nCharge : ${LOAD}%\nTempérature : ${TEMP}°C\nVRAM : ${MEM_USED} / ${MEM_TOTAL} MiB"
+
+printf '{"text":"%s","tooltip":"%s","class":"%s","percentage":%s}\n' \
+ "$TEXT" "$TOOLTIP" "$CLASS" "$LOAD"
diff --git a/INSTALL/configs/waybar/scripts/network.sh b/INSTALL/configs/waybar/scripts/network.sh
new file mode 100755
index 0000000..a3350f5
--- /dev/null
+++ b/INSTALL/configs/waybar/scripts/network.sh
@@ -0,0 +1,66 @@
+#!/usr/bin/env bash
+# network.sh — bande passante réseau → JSON waybar
+
+STATE_FILE="/tmp/waybar_net_state"
+
+# Détecter l'interface active
+IFACE=""
+for candidate in enp7s0 enp6s0 eth0; do
+ if [[ -d "/sys/class/net/$candidate" && "$(cat /sys/class/net/$candidate/operstate 2>/dev/null)" == "up" ]]; then
+ IFACE="$candidate"; TYPE="eth"; break
+ fi
+done
+if [[ -z "$IFACE" ]]; then
+ for candidate in wlp8s0 wlp0s20f3 wlan0; do
+ if [[ -d "/sys/class/net/$candidate" && "$(cat /sys/class/net/$candidate/operstate 2>/dev/null)" == "up" ]]; then
+ IFACE="$candidate"; TYPE="wifi"; break
+ fi
+ done
+fi
+
+if [[ -z "$IFACE" ]]; then
+ echo '{"text":" déco","tooltip":"Déconnecté","class":"disconnected"}'
+ exit 0
+fi
+
+RX_NOW=$(cat "/sys/class/net/$IFACE/statistics/rx_bytes" 2>/dev/null || echo 0)
+TX_NOW=$(cat "/sys/class/net/$IFACE/statistics/tx_bytes" 2>/dev/null || echo 0)
+NOW=$(date +%s%N)
+
+if [[ -f "$STATE_FILE" ]]; then
+ read -r RX_PREV TX_PREV TIME_PREV < "$STATE_FILE"
+ ELAPSED=$(( (NOW - TIME_PREV) / 1000000 )) # ms
+ if (( ELAPSED > 0 )); then
+ DOWN_BPS=$(( (RX_NOW - RX_PREV) * 1000 / ELAPSED ))
+ UP_BPS=$(( (TX_NOW - TX_PREV) * 1000 / ELAPSED ))
+ else
+ DOWN_BPS=0; UP_BPS=0
+ fi
+else
+ DOWN_BPS=0; UP_BPS=0
+fi
+
+echo "$RX_NOW $TX_NOW $NOW" > "$STATE_FILE"
+
+# Formatage humain
+human() {
+ local B=$1
+ if (( B >= 1073741824 )); then LC_ALL=C awk "BEGIN{printf \"%.1fG\", $B/1073741824}"
+ elif (( B >= 1048576 )); then LC_ALL=C awk "BEGIN{printf \"%.1fM\", $B/1048576}"
+ elif (( B >= 1024 )); then LC_ALL=C awk "BEGIN{printf \"%.0fK\", $B/1024}"
+ else echo "${B}B"
+ fi
+}
+
+DOWN_H=$(human $DOWN_BPS)
+UP_H=$(human $UP_BPS)
+RX_TOTAL=$(human $RX_NOW)
+TX_TOTAL=$(human $TX_NOW)
+
+ICON_DOWN=""; ICON_UP=""
+[[ "$TYPE" == "wifi" ]] && ICON_NET="" || ICON_NET=""
+
+TEXT="${ICON_DOWN} ${DOWN_H}/s ${ICON_UP} ${UP_H}/s"
+TOOLTIP="${ICON_NET} ${IFACE}\n${ICON_DOWN} ${DOWN_H}/s ${ICON_UP} ${UP_H}/s\n\n Total reçu : ${RX_TOTAL}\n Total envoyé : ${TX_TOTAL}"
+
+printf '{"text":"%s","tooltip":"%s","class":"%s"}\n' "$TEXT" "$TOOLTIP" "$TYPE"
diff --git a/INSTALL/configs/waybar/scripts/power-menu.sh b/INSTALL/configs/waybar/scripts/power-menu.sh
new file mode 100755
index 0000000..1c0fdee
--- /dev/null
+++ b/INSTALL/configs/waybar/scripts/power-menu.sh
@@ -0,0 +1,27 @@
+#!/usr/bin/env bash
+# power-menu.sh — menu power dédié (wofi)
+
+STYLE="$HOME/.config/wofi/power-style.css"
+
+ENTRIES=(
+ " Verrouiller"
+ " Veille"
+ " Redémarrer"
+ " Éteindre"
+)
+
+CHOICE=$(printf '%s\n' "${ENTRIES[@]}" | \
+ wofi --dmenu \
+ --prompt "⏻ " \
+ --style "$STYLE" \
+ --width 210 \
+ --height 160 \
+ --y 70 \
+ --location top_right)
+
+case "$CHOICE" in
+ " Verrouiller") loginctl lock-session ;;
+ " Veille") systemctl suspend ;;
+ " Redémarrer") systemctl reboot ;;
+ " Éteindre") systemctl poweroff ;;
+esac
diff --git a/INSTALL/configs/waybar/scripts/power-profile.sh b/INSTALL/configs/waybar/scripts/power-profile.sh
new file mode 100755
index 0000000..7de609d
--- /dev/null
+++ b/INSTALL/configs/waybar/scripts/power-profile.sh
@@ -0,0 +1,53 @@
+#!/usr/bin/env bash
+# power-profile.sh — profil énergie ACPI → JSON waybar
+# Sans argument : affiche le profil courant en JSON
+# --toggle : cycle vers le profil suivant + applique la luminosité
+
+# Luminosité par profil (%)
+BRIGHT_performance=80
+BRIGHT_balanced=60
+BRIGHT_low_power=30 # low-power → clé sans tiret
+
+_bright_for() {
+ local key="${1//-/_}"
+ local var="BRIGHT_${key}"
+ echo "${!var:-60}"
+}
+
+if [[ "$1" == "--toggle" ]]; then
+ CURRENT=$(cat /sys/firmware/acpi/platform_profile 2>/dev/null || echo "balanced")
+ case "$CURRENT" in
+ performance) NEXT="balanced" ;;
+ balanced) NEXT="low-power" ;;
+ *) NEXT="performance" ;;
+ esac
+
+ echo "$NEXT" > /sys/firmware/acpi/platform_profile
+
+ # Appliquer la luminosité du nouveau profil
+ BRIGHT=$(_bright_for "$NEXT")
+ brightnessctl set "${BRIGHT}%" -q
+
+ # Feedback overlay
+ if [[ -p /tmp/wob.fifo ]]; then
+ echo "b:${BRIGHT}" > /tmp/wob.fifo 2>/dev/null || true
+ fi
+
+ # Rafraîchir le module waybar
+ pkill -RTMIN+8 waybar
+ exit 0
+fi
+
+# ── Affichage JSON ────────────────────────────────────────────────────────────
+
+PROFILE=$(cat /sys/firmware/acpi/platform_profile 2>/dev/null || echo "unknown")
+
+case "$PROFILE" in
+ performance) ICON=""; CLASS="performance" ;;
+ balanced) ICON=""; CLASS="balanced" ;;
+ low-power) ICON=""; CLASS="low-power" ;;
+ *) ICON=""; CLASS="unknown" ;;
+esac
+
+printf '{"text":"%s","tooltip":"Profil énergie : %s","class":"%s"}\n' \
+ "$ICON" "$PROFILE" "$CLASS"
diff --git a/INSTALL/configs/waybar/scripts/rofi-launcher.sh b/INSTALL/configs/waybar/scripts/rofi-launcher.sh
new file mode 100755
index 0000000..8f2d0de
--- /dev/null
+++ b/INSTALL/configs/waybar/scripts/rofi-launcher.sh
@@ -0,0 +1,116 @@
+#!/usr/bin/env bash
+# launcher.sh — boite à outils violet-chaton avec historique (wofi)
+
+STYLE="$HOME/.config/wofi/style.css"
+TERM="cosmic-term"
+HIST_FILE="$HOME/.cache/waybar-launcher.hist"
+MAX_HIST=5
+HIST_ICON=" "
+
+SEP="────────────────────"
+HIST_HDR=" RÉCENTS"
+
+# ── Favoris (ordre fixe, toujours en haut) ───────────────────────────────────
+FAVORITES=(
+ " Vivaldi"
+ " Terminal"
+ " Nemo"
+ " VSCode"
+ " Vesktop"
+ " btop"
+ " lazygit"
+ " pipes.sh"
+ " cbonsai"
+)
+
+# ── Historique (dernières applis lancées, dédoublonné) ───────────────────────
+RECENT_ENTRIES=""
+if [[ -f "$HIST_FILE" ]]; then
+ RECENT_ENTRIES=$(awk '!seen[$0]++' "$HIST_FILE" | head -"$MAX_HIST" | \
+ sed "s|^|${HIST_ICON}|")
+fi
+
+# ── Toutes les applis installées ─────────────────────────────────────────────
+ALL_APPS=$(for f in \
+ /usr/share/applications/*.desktop \
+ ~/.local/share/applications/*.desktop \
+ /var/lib/flatpak/exports/share/applications/*.desktop \
+ ~/.local/share/flatpak/exports/share/applications/*.desktop; do
+ [[ -f "$f" ]] || continue
+ grep -q "^NoDisplay=true" "$f" && continue
+ grep -q "^Type=Application" "$f" || continue
+ grep -m1 "^Name=" "$f" | cut -d= -f2-
+done | sort -u)
+
+# ── Construction de la liste ─────────────────────────────────────────────────
+FULL_LIST=$(
+ printf '%s\n' "${FAVORITES[@]}"
+ if [[ -n "$RECENT_ENTRIES" ]]; then
+ echo "$SEP"
+ echo "$HIST_HDR"
+ echo "$RECENT_ENTRIES"
+ fi
+ echo "$SEP"
+ echo "$ALL_APPS"
+)
+
+# ── Affichage wofi ───────────────────────────────────────────────────────────
+CHOICE=$(echo "$FULL_LIST" | \
+ wofi --dmenu \
+ --prompt " " \
+ --style "$STYLE" \
+ --width 300 \
+ --height 500 \
+ --x 16 \
+ --y 70 \
+ --location top_left \
+ --cache-file=/dev/null)
+
+[[ -z "$CHOICE" ]] && exit 0
+
+# Enlever le préfixe historique si présent
+CHOICE_CLEAN="${CHOICE#$HIST_ICON}"
+
+# ── Mise à jour historique ────────────────────────────────────────────────────
+save_history() {
+ local app="$1"
+ # Ignorer les favoris (déjà toujours visibles), séparateurs et power
+ case "$app" in
+ " Vivaldi"|" Terminal"|" Nemo"|" VSCode"|" Vesktop") return ;;
+ " btop"|" lazygit"|" pipes.sh"|" cbonsai") return ;;
+ *"────"*|*"RÉCENTS"*|"") return ;;
+ esac
+ # Dépiler l'entrée existante et rajouter en tête
+ local tmp
+ tmp=$(grep -vxF "$app" "$HIST_FILE" 2>/dev/null)
+ printf '%s\n%s\n' "$app" "$tmp" | head -20 > "$HIST_FILE"
+}
+
+# ── Actions ───────────────────────────────────────────────────────────────────
+case "$CHOICE_CLEAN" in
+ " Vivaldi") vivaldi-stable & ;;
+ " Terminal") $TERM & ;;
+ " Nemo") nemo & ;;
+ " VSCode") code & ;;
+ " Vesktop") flatpak run dev.vencord.Vesktop & ;;
+ " btop") $TERM --command btop & ;;
+ " lazygit") $TERM --command lazygit & ;;
+ " pipes.sh") $TERM --command pipes.sh & ;;
+ " cbonsai") $TERM --command bash -c "cbonsai -l; read" & ;;
+ *"────"*|*"RÉCENTS"*) : ;;
+ *)
+ save_history "$CHOICE_CLEAN"
+ DESKTOP=$(grep -rlm1 "^Name=$CHOICE_CLEAN$" \
+ /usr/share/applications \
+ ~/.local/share/applications \
+ /var/lib/flatpak/exports/share/applications \
+ ~/.local/share/flatpak/exports/share/applications \
+ 2>/dev/null | head -1)
+ if [[ -n "$DESKTOP" ]]; then
+ # Lancer via Exec= directement — évite gtk-launch qui enregistre
+ # l'app dans GIO/recently-used et déclenche l'ajout aux favoris COSMIC
+ EXEC=$(grep -m1 "^Exec=" "$DESKTOP" | cut -d= -f2- | sed 's/ *%[a-zA-Z]//g' | xargs)
+ [[ -n "$EXEC" ]] && setsid bash -c "$EXEC" &
+ fi
+ ;;
+esac
diff --git a/INSTALL/configs/waybar/scripts/vc-brightness-popup.py b/INSTALL/configs/waybar/scripts/vc-brightness-popup.py
new file mode 100755
index 0000000..8b16dd2
--- /dev/null
+++ b/INSTALL/configs/waybar/scripts/vc-brightness-popup.py
@@ -0,0 +1,245 @@
+#!/usr/bin/env python3
+# vc-brightness-popup.py — Popup luminosité violet-chaton
+# Lancé par le clic sur le module backlight de waybar
+
+import gi
+gi.require_version('Gtk', '3.0')
+gi.require_version('GtkLayerShell', '0.1')
+from gi.repository import Gtk, Gdk, GtkLayerShell, GLib
+import subprocess
+import os
+import re
+
+# ── CSS ───────────────────────────────────────────────────────────────────────
+
+CSS = b"""
+window {
+ background-color: rgba(52, 28, 74, 0.93);
+ border: 3px solid rgba(255, 121, 198, 0.78);
+ border-radius: 14px;
+}
+
+#container {
+ padding: 14px 20px 16px 20px;
+}
+
+#bright-icon {
+ color: #8be9fd;
+ font-family: "JetBrainsMono Nerd Font";
+ font-size: 18px;
+ min-width: 24px;
+}
+
+#bright-title {
+ color: rgba(248, 248, 242, 0.55);
+ font-family: "JetBrainsMono Nerd Font";
+ font-size: 11px;
+}
+
+#device-name {
+ color: #8be9fd;
+ font-family: "JetBrainsMono Nerd Font";
+ font-size: 11px;
+ font-weight: bold;
+}
+
+#bright-pct {
+ color: #f8f8f2;
+ font-family: "JetBrainsMono Nerd Font";
+ font-size: 13px;
+ font-weight: bold;
+ min-width: 44px;
+}
+
+#separator {
+ color: rgba(92, 73, 108, 0.60);
+ margin: 4px 0;
+}
+
+scale trough {
+ background-color: rgba(92, 73, 108, 0.55);
+ border-radius: 3px;
+ min-height: 6px;
+ border: none;
+}
+
+scale highlight {
+ background-color: #8be9fd;
+ border-radius: 3px;
+ border: none;
+}
+
+scale slider {
+ background-color: #f8f8f2;
+ border-radius: 50%;
+ min-width: 18px;
+ min-height: 18px;
+ border: 2px solid rgba(139, 233, 253, 0.80);
+ box-shadow: none;
+ transition: none;
+}
+
+scale slider:hover {
+ background-color: #8be9fd;
+ border-color: #8be9fd;
+}
+"""
+
+POPUP_WIDTH = 300
+
+# ── Brightness helpers ────────────────────────────────────────────────────────
+
+def get_brightness():
+ """Retourne (valeur 0-100, nom du device)."""
+ try:
+ r = subprocess.run(
+ ['brightnessctl', 'info'],
+ capture_output=True, text=True, timeout=2
+ )
+ pct_match = re.search(r'\((\d+)%\)', r.stdout)
+ dev_match = re.search(r"Device '([^']+)'", r.stdout)
+ pct = int(pct_match.group(1)) if pct_match else 50
+ dev = dev_match.group(1) if dev_match else 'Écran'
+ # Rendre le nom plus lisible
+ dev = dev.replace('_', ' ').replace('backlight', '').strip().title()
+ return pct, dev
+ except Exception:
+ return 50, 'Écran'
+
+def set_brightness(pct):
+ pct = max(1, min(100, pct)) # minimum 1% pour ne pas éteindre l'écran
+ subprocess.run(
+ ['brightnessctl', 'set', f'{pct}%', '-q'],
+ capture_output=True
+ )
+ # Feedback wob
+ fifo = '/tmp/wob.fifo'
+ if os.path.exists(fifo):
+ try:
+ fd = os.open(fifo, os.O_WRONLY | os.O_NONBLOCK)
+ os.write(fd, f'{pct}\n'.encode())
+ os.close(fd)
+ except OSError:
+ pass
+
+def bright_icon(pct):
+ if pct < 34:
+ return ''
+ if pct < 67:
+ return ''
+ return ''
+
+# ── Popup ─────────────────────────────────────────────────────────────────────
+
+class BrightnessPopup(Gtk.Window):
+ def __init__(self):
+ super().__init__()
+ self._blocked = False
+
+ # ── Position : centré sous le module backlight ────────────────────────
+ display = Gdk.Display.get_default()
+ monitor = display.get_primary_monitor() if display else None
+ screen_w = monitor.get_geometry().width if monitor else 1920
+
+ # Backlight est le 2e module de la pill droite (~250px depuis le bord)
+ module_center = screen_w - 16 - 250
+ margin_left = max(0, module_center - POPUP_WIDTH // 2)
+
+ GtkLayerShell.init_for_window(self)
+ GtkLayerShell.set_layer(self, GtkLayerShell.Layer.OVERLAY)
+ GtkLayerShell.set_anchor(self, GtkLayerShell.Edge.TOP, True)
+ GtkLayerShell.set_anchor(self, GtkLayerShell.Edge.LEFT, True)
+ GtkLayerShell.set_margin(self, GtkLayerShell.Edge.TOP, 66)
+ GtkLayerShell.set_margin(self, GtkLayerShell.Edge.LEFT, margin_left)
+ GtkLayerShell.set_keyboard_mode(self, GtkLayerShell.KeyboardMode.ON_DEMAND)
+ GtkLayerShell.set_exclusive_zone(self, -1)
+
+ self.set_decorated(False)
+ self.set_resizable(False)
+ self.set_default_size(POPUP_WIDTH, -1)
+
+ # ── CSS ───────────────────────────────────────────────────────────────
+ provider = Gtk.CssProvider()
+ provider.load_from_data(CSS)
+ Gtk.StyleContext.add_provider_for_screen(
+ Gdk.Screen.get_default(),
+ provider,
+ Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
+ )
+
+ # ── État initial ──────────────────────────────────────────────────────
+ pct, dev = get_brightness()
+
+ # ── Layout ────────────────────────────────────────────────────────────
+ container = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=0)
+ container.set_name('container')
+ self.add(container)
+
+ # Ligne device
+ dev_row = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=6)
+ dev_icon = Gtk.Label(label='')
+ dev_icon.set_name('bright-title')
+ dev_row.pack_start(dev_icon, False, False, 0)
+ dev_label = Gtk.Label(label=dev)
+ dev_label.set_name('device-name')
+ dev_label.set_halign(Gtk.Align.START)
+ dev_label.set_ellipsize(3)
+ dev_row.pack_start(dev_label, True, True, 0)
+ container.pack_start(dev_row, False, False, 0)
+
+ # Séparateur
+ sep = Gtk.Label(label='─' * 30)
+ sep.set_name('separator')
+ container.pack_start(sep, False, False, 4)
+
+ # En-tête : icône + "Luminosité" + %
+ header = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=8)
+ self.icon = Gtk.Label(label=bright_icon(pct))
+ self.icon.set_name('bright-icon')
+ header.pack_start(self.icon, False, False, 0)
+
+ title = Gtk.Label(label='Luminosité')
+ title.set_name('bright-title')
+ title.set_halign(Gtk.Align.START)
+ header.pack_start(title, True, True, 0)
+
+ self.pct = Gtk.Label(label=f'{pct}%')
+ self.pct.set_name('bright-pct')
+ self.pct.set_halign(Gtk.Align.END)
+ header.pack_end(self.pct, False, False, 0)
+ container.pack_start(header, False, False, 0)
+
+ # Slider (min 1% pour ne pas éteindre l'écran)
+ self.scale = Gtk.Scale.new_with_range(
+ Gtk.Orientation.HORIZONTAL, 1, 100, 5
+ )
+ self.scale.set_value(pct)
+ self.scale.set_draw_value(False)
+ self.scale.set_hexpand(True)
+ self.scale.connect('value-changed', self._on_changed)
+ container.pack_start(self.scale, False, False, 0)
+
+ # ── Fermeture ─────────────────────────────────────────────────────────
+ self.connect('key-press-event', self._on_key)
+ self.connect('focus-out-event', lambda *_: self.destroy())
+
+ self.show_all()
+ self.grab_focus()
+
+ def _on_changed(self, scale):
+ if self._blocked:
+ return
+ pct = int(scale.get_value())
+ self.pct.set_label(f'{pct}%')
+ self.icon.set_label(bright_icon(pct))
+ set_brightness(pct)
+
+ def _on_key(self, _widget, event):
+ if event.keyval == Gdk.KEY_Escape:
+ self.destroy()
+
+
+if __name__ == '__main__':
+ win = BrightnessPopup()
+ win.connect('destroy', Gtk.main_quit)
+ Gtk.main()
diff --git a/INSTALL/configs/waybar/scripts/vc-media-popup.py b/INSTALL/configs/waybar/scripts/vc-media-popup.py
new file mode 100755
index 0000000..3415c42
--- /dev/null
+++ b/INSTALL/configs/waybar/scripts/vc-media-popup.py
@@ -0,0 +1,498 @@
+#!/usr/bin/env python3
+# vc-media-popup.py — Popup audio + luminosité violet-chaton
+# Lancé depuis le clic sur wireplumber OU backlight
+
+import gi
+gi.require_version('Gtk', '3.0')
+gi.require_version('GtkLayerShell', '0.1')
+from gi.repository import Gtk, Gdk, GtkLayerShell, GLib
+import subprocess
+import os
+import re
+
+# ── CSS ───────────────────────────────────────────────────────────────────────
+
+CSS = """
+window {
+ background-color: rgba(52, 28, 74, 0.93);
+ border: 3px solid rgba(255, 121, 198, 0.78);
+ border-radius: 14px;
+}
+
+#container {
+ padding: 14px 20px 16px 20px;
+}
+
+/* ── Labels ────────────────────────────────────────────────────────────────── */
+
+#section-label {
+ color: #ff79c6;
+ font-family: "JetBrainsMono Nerd Font";
+ font-size: 10px;
+ font-weight: bold;
+ letter-spacing: 0.08em;
+}
+
+#device-name {
+ color: rgba(248, 248, 242, 0.75);
+ font-family: "JetBrainsMono Nerd Font";
+ font-size: 11px;
+}
+
+#pct-label {
+ color: #f8f8f2;
+ font-family: "JetBrainsMono Nerd Font";
+ font-size: 12px;
+ font-weight: bold;
+ min-width: 38px;
+}
+
+#separator {
+ color: rgba(92, 73, 108, 0.50);
+ margin: 6px 0 4px 0;
+}
+
+/* ── Boutons mute (icônes cliquables) ───────────────────────────────────────── */
+
+#mute-icon {
+ font-family: "JetBrainsMono Nerd Font";
+ font-size: 17px;
+ color: #ff79c6;
+ background: transparent;
+ border: none;
+ border-radius: 6px;
+ padding: 0 4px;
+ min-width: 28px;
+}
+
+#mute-icon:hover {
+ background: rgba(255, 121, 198, 0.15);
+}
+
+#mute-icon.muted {
+ color: rgba(243, 139, 168, 0.70);
+}
+
+#mic-icon {
+ font-family: "JetBrainsMono Nerd Font";
+ font-size: 17px;
+ color: #ff79c6;
+ background: transparent;
+ border: none;
+ border-radius: 6px;
+ padding: 0 4px;
+ min-width: 28px;
+}
+
+#mic-icon:hover {
+ background: rgba(255, 121, 198, 0.15);
+}
+
+#mic-icon.muted {
+ color: rgba(243, 139, 168, 0.70);
+}
+
+/* ── Sliders audio (rose) ───────────────────────────────────────────────────── */
+
+scale.audio {
+ min-height: 22px;
+}
+
+scale.audio trough {
+ background-color: rgba(92, 73, 108, 0.55);
+ border-radius: 3px;
+ min-height: 5px;
+ border: none;
+}
+
+scale.audio trough highlight {
+ background-color: #ff79c6;
+ min-height: 6px;
+ border-radius: 3px;
+ border: none;
+}
+
+scale.audio.muted trough highlight {
+ background-color: rgba(108, 112, 134, 0.40);
+}
+
+scale.audio slider {
+ background-color: #f8f8f2;
+ border-radius: 50%;
+ min-width: 16px;
+ min-height: 16px;
+ border: 2px solid rgba(255, 121, 198, 0.80);
+ box-shadow: none;
+ transition: none;
+}
+
+scale.audio slider:hover {
+ background-color: #e79cfe;
+ border-color: #ff79c6;
+}
+
+scale.audio.muted slider {
+ border-color: rgba(108, 112, 134, 0.60);
+}
+
+/* ── Slider luminosité (cyan) ───────────────────────────────────────────────── */
+
+scale.bright {
+ min-height: 22px;
+}
+
+scale.bright trough {
+ background-color: rgba(92, 73, 108, 0.55);
+ border-radius: 3px;
+ min-height: 5px;
+ border: none;
+}
+
+scale.bright trough highlight {
+ background-color: #8be9fd;
+ min-height: 6px;
+ border-radius: 3px;
+ border: none;
+}
+
+scale.bright slider {
+ background-color: #f8f8f2;
+ border-radius: 50%;
+ min-width: 16px;
+ min-height: 16px;
+ border: 2px solid rgba(139, 233, 253, 0.80);
+ box-shadow: none;
+ transition: none;
+}
+
+scale.bright slider:hover {
+ background-color: #8be9fd;
+ border-color: #8be9fd;
+}
+
+#bright-icon {
+ color: #8be9fd;
+ font-family: "JetBrainsMono Nerd Font";
+ font-size: 17px;
+ min-width: 28px;
+}
+"""
+
+POPUP_WIDTH = 310
+
+# ── Helpers ───────────────────────────────────────────────────────────────────
+
+def run(cmd, **kw):
+ return subprocess.run(cmd, capture_output=True, text=True, timeout=2, **kw)
+
+def get_sink_volume():
+ r = run(['wpctl', 'get-volume', '@DEFAULT_AUDIO_SINK@'])
+ parts = r.stdout.strip().split()
+ vol = int(float(parts[1]) * 100) if len(parts) >= 2 else 50
+ return min(max(vol, 0), 100), '[MUTED]' in r.stdout
+
+def get_source_volume():
+ r = run(['wpctl', 'get-volume', '@DEFAULT_AUDIO_SOURCE@'])
+ parts = r.stdout.strip().split()
+ vol = int(float(parts[1]) * 100) if len(parts) >= 2 else 50
+ return min(max(vol, 0), 100), '[MUTED]' in r.stdout
+
+def get_node_name(target):
+ r = run(['wpctl', 'inspect', target])
+ for field in ('node.description', 'node.nick'):
+ m = re.search(rf'{field}\s*=\s*"([^"]+)"', r.stdout)
+ if m:
+ return m.group(1)
+ return target
+
+def set_sink_vol(v):
+ run(['wpctl', 'set-volume', '-l', '1.0', '@DEFAULT_AUDIO_SINK@', f'{v}%'])
+ _wob(f'v:{v}')
+
+def set_source_vol(v):
+ run(['wpctl', 'set-volume', '@DEFAULT_AUDIO_SOURCE@', f'{v}%'])
+ _wob(f'v:{v}')
+
+def toggle_sink_mute():
+ run(['wpctl', 'set-mute', '@DEFAULT_AUDIO_SINK@', 'toggle'])
+
+def toggle_source_mute():
+ run(['wpctl', 'set-mute', '@DEFAULT_AUDIO_SOURCE@', 'toggle'])
+
+def get_brightness():
+ r = run(['brightnessctl', 'info'])
+ m = re.search(r'\((\d+)%\)', r.stdout)
+ return int(m.group(1)) if m else 50
+
+def set_brightness(v):
+ v = max(1, v)
+ run(['brightnessctl', 'set', f'{v}%', '-q'])
+ _wob(f'b:{v}')
+
+def _wob(msg):
+ fifo = '/tmp/wob.fifo'
+ if os.path.exists(fifo):
+ try:
+ fd = os.open(fifo, os.O_WRONLY | os.O_NONBLOCK)
+ os.write(fd, f'{msg}\n'.encode())
+ os.close(fd)
+ except OSError:
+ pass
+
+def vol_icon(muted):
+ return '' if muted else ''
+
+def mic_icon(muted):
+ return '' if muted else ''
+
+def bright_icon(pct):
+ if pct < 34: return ''
+ if pct < 67: return ''
+ return ''
+
+# ── Popup ─────────────────────────────────────────────────────────────────────
+
+class MediaPopup(Gtk.Window):
+ def __init__(self):
+ super().__init__()
+ self._blk = False
+
+ # ── Position ─────────────────────────────────────────────────────────
+ display = Gdk.Display.get_default()
+ monitor = display.get_primary_monitor() if display else None
+ screen_w = monitor.get_geometry().width if monitor else 1920
+ module_center = screen_w - 16 - 210
+ margin_left = max(0, module_center - POPUP_WIDTH // 2)
+
+ GtkLayerShell.init_for_window(self)
+ GtkLayerShell.set_layer(self, GtkLayerShell.Layer.OVERLAY)
+ GtkLayerShell.set_anchor(self, GtkLayerShell.Edge.TOP, True)
+ GtkLayerShell.set_anchor(self, GtkLayerShell.Edge.LEFT, True)
+ GtkLayerShell.set_margin(self, GtkLayerShell.Edge.TOP, 66)
+ GtkLayerShell.set_margin(self, GtkLayerShell.Edge.LEFT, margin_left)
+ GtkLayerShell.set_keyboard_mode(self, GtkLayerShell.KeyboardMode.ON_DEMAND)
+ GtkLayerShell.set_exclusive_zone(self, -1)
+ self.set_decorated(False)
+ self.set_resizable(False)
+ self.set_default_size(POPUP_WIDTH, -1)
+
+ # ── CSS ───────────────────────────────────────────────────────────────
+ provider = Gtk.CssProvider()
+ provider.load_from_data(CSS.encode())
+ Gtk.StyleContext.add_provider_for_screen(
+ Gdk.Screen.get_default(), provider,
+ Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
+ )
+
+ # ── États initiaux ────────────────────────────────────────────────────
+ sink_vol, sink_muted = get_sink_volume()
+ src_vol, src_muted = get_source_volume()
+ self._sink_muted = sink_muted
+ self._src_muted = src_muted
+
+ # ── Layout ────────────────────────────────────────────────────────────
+ box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=0)
+ box.set_name('container')
+ self.add(box)
+
+ # ╔═══ SORTIE ══════════════════════════════════════════════════════════╗
+ box.pack_start(self._section_header('SORTIE', ''), False, False, 0)
+ box.pack_start(self._device_label(
+ get_node_name('@DEFAULT_AUDIO_SINK@')), False, False, 2)
+ sink_row, self.sink_scale, self.sink_pct, self.sink_icon = \
+ self._slider_row(sink_vol, sink_muted, 'audio', vol_icon(sink_muted),
+ self._toggle_sink_mute, '@DEFAULT_AUDIO_SINK@')
+ box.pack_start(sink_row, False, False, 4)
+
+ # ╔═══ ENTRÉE ══════════════════════════════════════════════════════════╗
+ sep1 = Gtk.Label(label='─' * 34)
+ sep1.set_name('separator')
+ box.pack_start(sep1, False, False, 0)
+
+ box.pack_start(self._section_header('ENTRÉE', ''), False, False, 0)
+ box.pack_start(self._device_label(
+ get_node_name('@DEFAULT_AUDIO_SOURCE@')), False, False, 2)
+ src_row, self.src_scale, self.src_pct, self.src_icon = \
+ self._slider_row(src_vol, src_muted, 'audio', mic_icon(src_muted),
+ self._toggle_src_mute, '@DEFAULT_AUDIO_SOURCE@')
+ box.pack_start(src_row, False, False, 4)
+
+ # ╔═══ LUMINOSITÉ ══════════════════════════════════════════════════════╗
+ sep2 = Gtk.Label(label='─' * 34)
+ sep2.set_name('separator')
+ box.pack_start(sep2, False, False, 0)
+
+ bright_row, self.bright_scale, self.bright_pct, self.bright_icon_lbl = \
+ self._bright_row(get_brightness())
+ box.pack_start(bright_row, False, False, 6)
+
+ # ── Refresh + fermeture ───────────────────────────────────────────────
+ GLib.timeout_add(2000, self._refresh)
+ self.connect('key-press-event', lambda w, e:
+ self.destroy() if e.keyval == Gdk.KEY_Escape else None)
+ self.connect('focus-out-event', lambda *_: self.destroy())
+ self.show_all()
+ # GTK3 bug : set_value() avant réalisation → highlight width=0 à max
+ # Forcer un re-calcul après que les widgets sont visibles
+ GLib.idle_add(self._redraw_scales)
+ self.grab_focus()
+
+ def _redraw_scales(self):
+ """Force GTK3 à recalculer les highlights.
+ set_value(même_valeur) est un no-op — on oscille ±1 pour déclencher
+ un vrai recalcul de la position du highlight dans le trough."""
+ self._blk = True
+ for scale in [self.sink_scale, self.src_scale, self.bright_scale]:
+ v = scale.get_value()
+ adj = scale.get_adjustment()
+ lo = adj.get_lower()
+ scale.set_value(max(lo, v - 1)) # valeur différente → GTK recalcule
+ scale.set_value(v) # retour à la valeur réelle
+ self._blk = False
+ return False
+
+ # ── Builders UI ───────────────────────────────────────────────────────────
+
+ def _section_header(self, label, icon):
+ row = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=6)
+ ico = Gtk.Label(label=icon)
+ ico.set_name('section-label')
+ row.pack_start(ico, False, False, 0)
+ lbl = Gtk.Label(label=label)
+ lbl.set_name('section-label')
+ lbl.set_halign(Gtk.Align.START)
+ row.pack_start(lbl, True, True, 0)
+ return row
+
+ def _device_label(self, name):
+ lbl = Gtk.Label(label=name)
+ lbl.set_name('device-name')
+ lbl.set_halign(Gtk.Align.START)
+ lbl.set_ellipsize(3)
+ lbl.set_margin_start(4)
+ return lbl
+
+ def _slider_row(self, val, muted, css_class, icon_char, mute_cb, target):
+ """Retourne (row, scale, pct_label, icon_btn)"""
+ row = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=6)
+
+ # Icône = bouton mute
+ icon_btn = Gtk.Button(label=icon_char)
+ icon_btn.set_name('mute-icon' if target == '@DEFAULT_AUDIO_SINK@' else 'mic-icon')
+ if muted:
+ icon_btn.get_style_context().add_class('muted')
+ icon_btn.connect('clicked', mute_cb)
+ row.pack_start(icon_btn, False, False, 0)
+
+ # Slider
+ scale = Gtk.Scale.new_with_range(Gtk.Orientation.HORIZONTAL, 0, 100, 5)
+ scale.set_value(val)
+ scale.set_draw_value(False)
+ scale.set_hexpand(True)
+ scale.get_style_context().add_class(css_class)
+ if muted:
+ scale.get_style_context().add_class('muted')
+ scale.connect('value-changed', lambda s, t=target:
+ self._on_audio_changed(s, pct_lbl, t))
+ row.pack_start(scale, True, True, 0)
+
+ # %
+ pct_lbl = Gtk.Label(label=f'{val}%')
+ pct_lbl.set_name('pct-label')
+ pct_lbl.set_halign(Gtk.Align.END)
+ row.pack_end(pct_lbl, False, False, 0)
+
+ return row, scale, pct_lbl, icon_btn
+
+ def _bright_row(self, pct):
+ row = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=8)
+
+ icon_lbl = Gtk.Label(label=bright_icon(pct))
+ icon_lbl.set_name('bright-icon')
+ row.pack_start(icon_lbl, False, False, 0)
+
+ scale = Gtk.Scale.new_with_range(Gtk.Orientation.HORIZONTAL, 1, 100, 5)
+ scale.set_value(pct)
+ scale.set_draw_value(False)
+ scale.set_hexpand(True)
+ scale.get_style_context().add_class('bright')
+ scale.connect('value-changed', self._on_bright_changed)
+ row.pack_start(scale, True, True, 0)
+
+ pct_lbl = Gtk.Label(label=f'{pct}%')
+ pct_lbl.set_name('pct-label')
+ pct_lbl.set_halign(Gtk.Align.END)
+ row.pack_end(pct_lbl, False, False, 0)
+
+ return row, scale, pct_lbl, icon_lbl
+
+ # ── Handlers ──────────────────────────────────────────────────────────────
+
+ def _on_audio_changed(self, scale, pct_lbl, target):
+ if self._blk:
+ return
+ v = int(scale.get_value())
+ pct_lbl.set_label(f'{v}%')
+ if target == '@DEFAULT_AUDIO_SINK@':
+ set_sink_vol(v)
+ else:
+ set_source_vol(v)
+
+ def _on_bright_changed(self, scale):
+ if self._blk:
+ return
+ v = int(scale.get_value())
+ self.bright_pct.set_label(f'{v}%')
+ self.bright_icon_lbl.set_label(bright_icon(v))
+ set_brightness(v)
+
+ def _apply_mute(self, scale, icon_btn, muted, icon_fn):
+ sc = scale.get_style_context()
+ bc = icon_btn.get_style_context()
+ if muted:
+ sc.add_class('muted')
+ bc.add_class('muted')
+ else:
+ sc.remove_class('muted')
+ bc.remove_class('muted')
+ icon_btn.set_label(icon_fn(muted))
+
+ def _toggle_sink_mute(self, _btn):
+ toggle_sink_mute()
+ _, self._sink_muted = get_sink_volume()
+ self._apply_mute(self.sink_scale, self.sink_icon,
+ self._sink_muted, vol_icon)
+
+ def _toggle_src_mute(self, _btn):
+ toggle_source_mute()
+ _, self._src_muted = get_source_volume()
+ self._apply_mute(self.src_scale, self.src_icon,
+ self._src_muted, mic_icon)
+
+ def _refresh(self):
+ sink_vol, sink_muted = get_sink_volume()
+ src_vol, src_muted = get_source_volume()
+
+ if sink_muted != self._sink_muted:
+ self._sink_muted = sink_muted
+ self._apply_mute(self.sink_scale, self.sink_icon,
+ sink_muted, vol_icon)
+ if src_muted != self._src_muted:
+ self._src_muted = src_muted
+ self._apply_mute(self.src_scale, self.src_icon,
+ src_muted, mic_icon)
+
+ self._blk = True
+ self.sink_scale.set_value(sink_vol)
+ self.sink_pct.set_label(f'{sink_vol}%')
+ self.src_scale.set_value(src_vol)
+ self.src_pct.set_label(f'{src_vol}%')
+ self._blk = False
+
+ return True
+
+
+if __name__ == '__main__':
+ win = MediaPopup()
+ win.connect('destroy', Gtk.main_quit)
+ Gtk.main()
diff --git a/INSTALL/configs/waybar/scripts/vc-volume-popup.py b/INSTALL/configs/waybar/scripts/vc-volume-popup.py
new file mode 100755
index 0000000..a51a3ed
--- /dev/null
+++ b/INSTALL/configs/waybar/scripts/vc-volume-popup.py
@@ -0,0 +1,422 @@
+#!/usr/bin/env python3
+# vc-volume-popup.py — Popup volume slider violet-chaton
+# Lancé par le clic sur le module wireplumber de waybar
+
+import gi
+gi.require_version('Gtk', '3.0')
+gi.require_version('GtkLayerShell', '0.1')
+from gi.repository import Gtk, Gdk, GtkLayerShell, GLib
+import subprocess
+import os
+import re
+
+# ── CSS ───────────────────────────────────────────────────────────────────────
+
+CSS = b"""
+window {
+ background-color: rgba(52, 28, 74, 0.93);
+ border: 3px solid rgba(255, 121, 198, 0.78);
+ border-radius: 14px;
+}
+
+#container {
+ padding: 14px 20px 16px 20px;
+}
+
+#vol-icon {
+ color: #ff79c6;
+ font-family: "JetBrainsMono Nerd Font";
+ font-size: 18px;
+ min-width: 24px;
+}
+
+#vol-title {
+ color: rgba(248, 248, 242, 0.55);
+ font-family: "JetBrainsMono Nerd Font";
+ font-size: 11px;
+}
+
+#sink-name {
+ color: #8be9fd;
+ font-family: "JetBrainsMono Nerd Font";
+ font-size: 11px;
+ font-weight: bold;
+}
+
+#vol-pct {
+ color: #f8f8f2;
+ font-family: "JetBrainsMono Nerd Font";
+ font-size: 13px;
+ font-weight: bold;
+ min-width: 44px;
+}
+
+#separator {
+ color: rgba(92, 73, 108, 0.60);
+ margin: 4px 0;
+}
+
+scale trough {
+ background-color: rgba(92, 73, 108, 0.55);
+ border-radius: 3px;
+ min-height: 6px;
+ border: none;
+}
+
+scale highlight {
+ background-color: #ff79c6;
+ border-radius: 3px;
+ border: none;
+}
+
+scale slider {
+ background-color: #f8f8f2;
+ border-radius: 50%;
+ min-width: 18px;
+ min-height: 18px;
+ border: 2px solid rgba(255, 121, 198, 0.80);
+ box-shadow: none;
+ transition: none;
+}
+
+scale slider:hover {
+ background-color: #e79cfe;
+ border-color: #ff79c6;
+}
+
+#mute-btn {
+ background: rgba(73, 49, 97, 0.50);
+ border: 1px solid rgba(92, 73, 108, 0.60);
+ border-radius: 8px;
+ color: rgba(248, 248, 242, 0.65);
+ font-family: "JetBrainsMono Nerd Font";
+ font-size: 12px;
+ padding: 5px 16px;
+ margin-top: 6px;
+}
+
+#mute-btn:hover {
+ background: rgba(255, 121, 198, 0.18);
+ border-color: rgba(255, 121, 198, 0.45);
+ color: #ff79c6;
+}
+
+#mute-btn.muted {
+ color: #f38ba8;
+ border-color: rgba(243, 139, 168, 0.45);
+ background: rgba(243, 139, 168, 0.10);
+}
+
+#mic-btn {
+ background: rgba(73, 49, 97, 0.50);
+ border: 1px solid rgba(139, 233, 253, 0.35);
+ border-radius: 8px;
+ color: #8be9fd;
+ font-family: "JetBrainsMono Nerd Font";
+ font-size: 12px;
+ padding: 5px 16px;
+ margin-top: 4px;
+}
+
+#mic-btn:hover {
+ background: rgba(139, 233, 253, 0.12);
+ border-color: rgba(139, 233, 253, 0.60);
+ color: #8be9fd;
+}
+
+#mic-btn.muted {
+ color: #f38ba8;
+ border-color: rgba(243, 139, 168, 0.45);
+ background: rgba(243, 139, 168, 0.10);
+}
+"""
+
+POPUP_WIDTH = 300
+
+# ── Audio helpers ─────────────────────────────────────────────────────────────
+
+def get_volume():
+ """Retourne (volume 0-100, is_muted)"""
+ try:
+ r = subprocess.run(
+ ['wpctl', 'get-volume', '@DEFAULT_AUDIO_SINK@'],
+ capture_output=True, text=True, timeout=2
+ )
+ parts = r.stdout.strip().split()
+ vol = int(float(parts[1]) * 100)
+ muted = '[MUTED]' in r.stdout
+ return min(max(vol, 0), 100), muted
+ except Exception:
+ return 50, False
+
+def get_sink_name():
+ """Retourne le nom humain de la sortie audio active."""
+ try:
+ r = subprocess.run(
+ ['wpctl', 'inspect', '@DEFAULT_AUDIO_SINK@'],
+ capture_output=True, text=True, timeout=2
+ )
+ # Chercher node.description en priorité, sinon node.nick
+ for field in ('node.description', 'node.nick'):
+ m = re.search(rf'{field}\s*=\s*"([^"]+)"', r.stdout)
+ if m:
+ return m.group(1)
+ except Exception:
+ pass
+ return 'Sortie audio'
+
+def set_volume(vol):
+ subprocess.run(
+ ['wpctl', 'set-volume', '-l', '1.0', '@DEFAULT_AUDIO_SINK@', f'{vol}%'],
+ capture_output=True
+ )
+ # Feedback wob (non-bloquant)
+ fifo = '/tmp/wob.fifo'
+ if os.path.exists(fifo):
+ try:
+ fd = os.open(fifo, os.O_WRONLY | os.O_NONBLOCK)
+ os.write(fd, f'{vol}\n'.encode())
+ os.close(fd)
+ except OSError:
+ pass
+
+def toggle_mute():
+ subprocess.run(
+ ['wpctl', 'set-mute', '@DEFAULT_AUDIO_SINK@', 'toggle'],
+ capture_output=True
+ )
+
+def get_mic_muted():
+ """Retourne True si le micro actif est muté."""
+ try:
+ r = subprocess.run(
+ ['wpctl', 'get-volume', '@DEFAULT_AUDIO_SOURCE@'],
+ capture_output=True, text=True, timeout=2
+ )
+ return '[MUTED]' in r.stdout
+ except Exception:
+ return False
+
+def toggle_mic_mute():
+ subprocess.run(
+ ['wpctl', 'set-mute', '@DEFAULT_AUDIO_SOURCE@', 'toggle'],
+ capture_output=True
+ )
+
+def vol_icon(vol, muted):
+ if muted or vol == 0:
+ return ''
+ if vol < 50:
+ return ''
+ return ''
+
+# ── Popup ─────────────────────────────────────────────────────────────────────
+
+class VolumePopup(Gtk.Window):
+ def __init__(self):
+ super().__init__()
+ self._blocked = False
+
+ # ── Position : centré sous le module wireplumber ──────────────────────
+ # Wireplumber = 1er module de la pill droite (côté droit de l'écran).
+ # On centre le popup horizontalement sous ce module.
+ display = Gdk.Display.get_default()
+ monitor = display.get_primary_monitor() if display else None
+ if monitor:
+ screen_w = monitor.get_geometry().width
+ else:
+ screen_w = 1920 # fallback
+
+ # La pill droite a ~16px de marge depuis le bord droit.
+ # Le module wireplumber est le 1er élément : ~180px depuis le bord droit.
+ module_center = screen_w - 16 - 180
+ margin_left = max(0, module_center - POPUP_WIDTH // 2)
+
+ GtkLayerShell.init_for_window(self)
+ GtkLayerShell.set_layer(self, GtkLayerShell.Layer.OVERLAY)
+ GtkLayerShell.set_anchor(self, GtkLayerShell.Edge.TOP, True)
+ GtkLayerShell.set_anchor(self, GtkLayerShell.Edge.LEFT, True)
+ GtkLayerShell.set_margin(self, GtkLayerShell.Edge.TOP, 66)
+ GtkLayerShell.set_margin(self, GtkLayerShell.Edge.LEFT, margin_left)
+ GtkLayerShell.set_keyboard_mode(self, GtkLayerShell.KeyboardMode.ON_DEMAND)
+ GtkLayerShell.set_exclusive_zone(self, -1)
+
+ self.set_decorated(False)
+ self.set_resizable(False)
+ self.set_default_size(POPUP_WIDTH, -1)
+
+ # ── CSS ───────────────────────────────────────────────────────────────
+ provider = Gtk.CssProvider()
+ provider.load_from_data(CSS)
+ Gtk.StyleContext.add_provider_for_screen(
+ Gdk.Screen.get_default(),
+ provider,
+ Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
+ )
+
+ # ── État initial ──────────────────────────────────────────────────────
+ vol, muted = get_volume()
+ self._muted = muted
+ self._mic_muted = get_mic_muted()
+ sink = get_sink_name()
+
+ # ── Layout ────────────────────────────────────────────────────────────
+ container = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=0)
+ container.set_name('container')
+ self.add(container)
+
+ # Ligne sink (sortie active)
+ sink_row = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=6)
+ sink_icon = Gtk.Label(label='')
+ sink_icon.set_name('vol-title')
+ sink_row.pack_start(sink_icon, False, False, 0)
+ self.sink_label = Gtk.Label(label=sink)
+ self.sink_label.set_name('sink-name')
+ self.sink_label.set_halign(Gtk.Align.START)
+ self.sink_label.set_ellipsize(3) # PANGO_ELLIPSIZE_END
+ sink_row.pack_start(self.sink_label, True, True, 0)
+ container.pack_start(sink_row, False, False, 0)
+
+ # Séparateur
+ sep = Gtk.Label(label='─' * 30)
+ sep.set_name('separator')
+ container.pack_start(sep, False, False, 4)
+
+ # En-tête volume : icône + "Volume" + %
+ header = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=8)
+ self.icon = Gtk.Label(label=vol_icon(vol, muted))
+ self.icon.set_name('vol-icon')
+ header.pack_start(self.icon, False, False, 0)
+
+ title = Gtk.Label(label='Volume')
+ title.set_name('vol-title')
+ title.set_halign(Gtk.Align.START)
+ header.pack_start(title, True, True, 0)
+
+ self.pct = Gtk.Label(label=f'{vol}%')
+ self.pct.set_name('vol-pct')
+ self.pct.set_halign(Gtk.Align.END)
+ header.pack_end(self.pct, False, False, 0)
+ container.pack_start(header, False, False, 0)
+
+ # Slider
+ self.scale = Gtk.Scale.new_with_range(
+ Gtk.Orientation.HORIZONTAL, 0, 100, 5
+ )
+ self.scale.set_value(vol)
+ self.scale.set_draw_value(False)
+ self.scale.set_hexpand(True)
+ self.scale.connect('value-changed', self._on_changed)
+ container.pack_start(self.scale, False, False, 0)
+
+ # Bouton mute
+ self.mute_btn = Gtk.Button(label=f' {"Remettre le son" if muted else "Muet"}')
+ self.mute_btn.set_name('mute-btn')
+ self.mute_btn.set_halign(Gtk.Align.CENTER)
+ if muted:
+ self.mute_btn.get_style_context().add_class('muted')
+ self.mute_btn.connect('clicked', self._on_mute)
+ container.pack_start(self.mute_btn, False, False, 0)
+
+ # ── Section micro ─────────────────────────────────────────────────────
+ sep2 = Gtk.Label(label='─' * 30)
+ sep2.set_name('separator')
+ container.pack_start(sep2, False, False, 4)
+
+ mic_row = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=8)
+ mic_icon = Gtk.Label(label='')
+ mic_icon.set_name('vol-title')
+ mic_icon.set_markup('')
+ mic_row.pack_start(mic_icon, False, False, 0)
+
+ mic_title = Gtk.Label(label='Micro')
+ mic_title.set_name('vol-title')
+ mic_title.set_halign(Gtk.Align.START)
+ mic_row.pack_start(mic_title, True, True, 0)
+
+ mic_label = ' Coupé' if self._mic_muted else ' Actif'
+ self.mic_btn = Gtk.Button(label=mic_label)
+ self.mic_btn.set_name('mic-btn')
+ if self._mic_muted:
+ self.mic_btn.get_style_context().add_class('muted')
+ self.mic_btn.connect('clicked', self._on_mic_mute)
+ mic_row.pack_end(self.mic_btn, False, False, 0)
+
+ container.pack_start(mic_row, False, False, 0)
+
+ # ── Refresh périodique (détecte changement de sink/micro) ─────────────
+ GLib.timeout_add(2000, self._refresh_sink)
+
+ # ── Fermeture ─────────────────────────────────────────────────────────
+ self.connect('key-press-event', self._on_key)
+ self.connect('focus-out-event', lambda *_: self.destroy())
+
+ self.show_all()
+ self.grab_focus()
+
+ def _on_changed(self, scale):
+ if self._blocked:
+ return
+ vol = int(scale.get_value())
+ self.pct.set_label(f'{vol}%')
+ self.icon.set_label(vol_icon(vol, self._muted))
+ set_volume(vol)
+
+ def _on_mute(self, btn):
+ toggle_mute()
+ _, self._muted = get_volume()
+ vol = int(self.scale.get_value())
+ self.icon.set_label(vol_icon(vol, self._muted))
+ if self._muted:
+ btn.get_style_context().add_class('muted')
+ btn.set_label(' Remettre le son')
+ else:
+ btn.get_style_context().remove_class('muted')
+ btn.set_label(' Muet')
+
+ def _refresh_sink(self):
+ """Met à jour la sortie et l'état du micro si changement détecté."""
+ # Sortie audio
+ sink = get_sink_name()
+ if self.sink_label.get_label() != sink:
+ self.sink_label.set_label(sink)
+ vol, muted = get_volume()
+ self._blocked = True
+ self.scale.set_value(vol)
+ self._blocked = False
+ self.pct.set_label(f'{vol}%')
+ self._muted = muted
+ self.icon.set_label(vol_icon(vol, muted))
+
+ # Micro
+ mic_muted = get_mic_muted()
+ if mic_muted != self._mic_muted:
+ self._mic_muted = mic_muted
+ if mic_muted:
+ self.mic_btn.get_style_context().add_class('muted')
+ self.mic_btn.set_label(' Coupé')
+ else:
+ self.mic_btn.get_style_context().remove_class('muted')
+ self.mic_btn.set_label(' Actif')
+
+ return True # continuer le timer
+
+ def _on_mic_mute(self, btn):
+ toggle_mic_mute()
+ self._mic_muted = get_mic_muted()
+ if self._mic_muted:
+ btn.get_style_context().add_class('muted')
+ btn.set_label(' Coupé')
+ else:
+ btn.get_style_context().remove_class('muted')
+ btn.set_label(' Actif')
+
+ def _on_key(self, _widget, event):
+ if event.keyval == Gdk.KEY_Escape:
+ self.destroy()
+
+
+if __name__ == '__main__':
+ win = VolumePopup()
+ win.connect('destroy', Gtk.main_quit)
+ Gtk.main()
diff --git a/INSTALL/configs/waybar/scripts/wob-brightness.sh b/INSTALL/configs/waybar/scripts/wob-brightness.sh
new file mode 100755
index 0000000..25768c0
--- /dev/null
+++ b/INSTALL/configs/waybar/scripts/wob-brightness.sh
@@ -0,0 +1,17 @@
+#!/usr/bin/env bash
+# wob-brightness.sh — scroll luminosité + feedback wob
+# Usage: wob-brightness.sh up|down
+
+STEP=5
+FIFO="/tmp/wob.fifo"
+
+case "$1" in
+ up) brightnessctl set "${STEP}%+" -q ;;
+ down) brightnessctl set "${STEP}%-" -q ;;
+esac
+
+# Feedback overlay
+if [[ -p "$FIFO" ]]; then
+ BRIGHT=$(brightnessctl -m 2>/dev/null | awk -F, '{gsub(/%/,"",$4); print int($4)}')
+ echo "b:${BRIGHT}" > "$FIFO"
+fi
diff --git a/INSTALL/configs/waybar/scripts/wob-overlay.py b/INSTALL/configs/waybar/scripts/wob-overlay.py
new file mode 100644
index 0000000..fc2d984
--- /dev/null
+++ b/INSTALL/configs/waybar/scripts/wob-overlay.py
@@ -0,0 +1,227 @@
+#!/usr/bin/env python3
+# wob-overlay.py — Overlay volume/luminosité violet-chaton (remplace wob)
+# Protocole FIFO : "v:N" = volume (rose), "b:N" = luminosité (cyan), "N" = volume
+
+import gi
+gi.require_version('Gtk', '3.0')
+gi.require_version('GtkLayerShell', '0.1')
+from gi.repository import Gtk, Gdk, GtkLayerShell, GLib
+import os
+import threading
+
+FIFO = '/tmp/wob.fifo'
+POPUP_WIDTH = 280
+POPUP_HEIGHT = -1
+MARGIN_BOTTOM = 48
+HIDE_DELAY = 1200 # ms
+
+CSS = """
+window {
+ background: transparent;
+}
+
+#wob-box {
+ background-color: rgba(38, 21, 55, 0.92);
+ border: 2px solid rgba(92, 73, 108, 0.80);
+ border-radius: 12px;
+ padding: 10px 16px;
+}
+
+#wob-box.vol {
+ border-color: rgba(255, 121, 198, 0.85);
+}
+
+#wob-box.bright {
+ border-color: rgba(139, 233, 253, 0.85);
+}
+
+#wob-icon {
+ font-family: "JetBrainsMono Nerd Font";
+ font-size: 15px;
+ min-width: 22px;
+ margin-right: 4px;
+}
+
+#wob-pct {
+ color: #f8f8f2;
+ font-family: "JetBrainsMono Nerd Font";
+ font-size: 11px;
+ font-weight: bold;
+ min-width: 36px;
+ margin-left: 6px;
+}
+
+/* ── Volume (rose) ──────────────────────────────────────────── */
+
+progressbar.vol trough {
+ background-color: rgba(92, 73, 108, 0.45);
+ border-radius: 5px;
+ min-height: 7px;
+ border: none;
+}
+
+progressbar.vol progress {
+ background-color: #ff79c6;
+ border-radius: 5px;
+ border: none;
+ min-height: 7px;
+}
+
+/* ── Luminosité (cyan) ──────────────────────────────────────── */
+
+progressbar.bright trough {
+ background-color: rgba(92, 73, 108, 0.45);
+ border-radius: 5px;
+ min-height: 7px;
+ border: none;
+}
+
+progressbar.bright progress {
+ background-color: #8be9fd;
+ border-radius: 5px;
+ border: none;
+ min-height: 7px;
+}
+"""
+
+VOL_ICONS = ['', '', '']
+BRIGHT_ICONS = ['', '', '']
+
+def _icon(icons, pct):
+ if pct <= 0:
+ return icons[0]
+ if pct < 50:
+ return icons[1]
+ return icons[2]
+
+
+class WobOverlay(Gtk.Window):
+ def __init__(self):
+ super().__init__()
+ self._hide_timer = None
+
+ # ── Layer shell ──────────────────────────────────────────────────────
+ GtkLayerShell.init_for_window(self)
+ GtkLayerShell.set_layer(self, GtkLayerShell.Layer.OVERLAY)
+ GtkLayerShell.set_anchor(self, GtkLayerShell.Edge.BOTTOM, True)
+ GtkLayerShell.set_margin(self, GtkLayerShell.Edge.BOTTOM, MARGIN_BOTTOM)
+ GtkLayerShell.set_exclusive_zone(self, -1)
+ GtkLayerShell.set_keyboard_mode(self, GtkLayerShell.KeyboardMode.NONE)
+
+ self.set_decorated(False)
+ self.set_resizable(False)
+ self.set_app_paintable(True)
+ self.set_default_size(POPUP_WIDTH, POPUP_HEIGHT)
+
+ # Fenêtre transparente
+ screen = self.get_screen()
+ visual = screen.get_rgba_visual()
+ if visual:
+ self.set_visual(visual)
+
+ # ── CSS ──────────────────────────────────────────────────────────────
+ provider = Gtk.CssProvider()
+ provider.load_from_data(CSS.encode())
+ Gtk.StyleContext.add_provider_for_screen(
+ Gdk.Screen.get_default(), provider,
+ Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
+ )
+
+ # ── Layout ───────────────────────────────────────────────────────────
+ outer = Gtk.Box()
+ outer.set_name('wob-box')
+ self._box = outer
+ self.add(outer)
+
+ self._icon_lbl = Gtk.Label()
+ self._icon_lbl.set_name('wob-icon')
+ outer.pack_start(self._icon_lbl, False, False, 0)
+
+ self._bar = Gtk.ProgressBar()
+ self._bar.set_hexpand(True)
+ self._bar.set_valign(Gtk.Align.CENTER)
+ outer.pack_start(self._bar, True, True, 0)
+
+ self._pct_lbl = Gtk.Label()
+ self._pct_lbl.set_name('wob-pct')
+ self._pct_lbl.set_halign(Gtk.Align.END)
+ outer.pack_end(self._pct_lbl, False, False, 0)
+
+ self.show_all()
+ self.hide()
+
+ def show_value(self, val, kind='v'):
+ """Appelé depuis le thread FIFO via GLib.idle_add."""
+ val = max(0, min(100, val))
+ fraction = val / 100.0
+
+ # Icône + couleur selon le type
+ if kind == 'b':
+ icon = _icon(BRIGHT_ICONS, val)
+ css_class = 'bright'
+ else:
+ icon = _icon(VOL_ICONS, val)
+ css_class = 'vol'
+
+ sc = self._bar.get_style_context()
+ bsc = self._box.get_style_context()
+ for c in ['vol', 'bright']:
+ sc.remove_class(c)
+ bsc.remove_class(c)
+ sc.add_class(css_class)
+ bsc.add_class(css_class)
+
+ self._icon_lbl.set_label(icon)
+ self._icon_lbl.set_markup(
+ f'{icon}'
+ )
+ self._bar.set_fraction(fraction)
+ self._pct_lbl.set_label(f'{val}%')
+
+ self.show()
+
+ # Reset timer
+ if self._hide_timer:
+ GLib.source_remove(self._hide_timer)
+ self._hide_timer = GLib.timeout_add(HIDE_DELAY, self._do_hide)
+
+ def _do_hide(self):
+ self.hide()
+ self._hide_timer = None
+ return False
+
+
+def _fifo_reader(overlay):
+ """Thread : lit le FIFO en boucle et schedule les mises à jour UI."""
+ while True:
+ try:
+ if not os.path.exists(FIFO):
+ os.mkfifo(FIFO)
+ with open(FIFO, 'r') as f:
+ for line in f:
+ line = line.strip()
+ if not line:
+ continue
+ # Protocole : "v:N", "b:N" ou plain "N"
+ if ':' in line:
+ kind, _, raw = line.partition(':')
+ else:
+ kind, raw = 'v', line
+ try:
+ val = int(raw)
+ GLib.idle_add(overlay.show_value, val, kind)
+ except ValueError:
+ pass
+ except OSError:
+ import time
+ time.sleep(0.5)
+
+
+if __name__ == '__main__':
+ win = WobOverlay()
+ win.connect('destroy', Gtk.main_quit)
+
+ t = threading.Thread(target=_fifo_reader, args=(win,), daemon=True)
+ t.start()
+
+ Gtk.main()
diff --git a/INSTALL/configs/waybar/scripts/wob-start.sh b/INSTALL/configs/waybar/scripts/wob-start.sh
new file mode 100755
index 0000000..bf4e3a6
--- /dev/null
+++ b/INSTALL/configs/waybar/scripts/wob-start.sh
@@ -0,0 +1,15 @@
+#!/usr/bin/env bash
+# wob-start.sh — lance l'overlay violet-chaton via FIFO
+# Appelé au démarrage de session (autostart)
+
+FIFO="/tmp/wob.fifo"
+
+pkill -f wob-overlay.py 2>/dev/null
+rm -f "$FIFO"
+mkfifo "$FIFO"
+
+# Ouvrir le FIFO en lecture+écriture sur fd3 :
+# empêche l'overlay de recevoir EOF entre deux écritures
+exec 3<> "$FIFO"
+python3 "$HOME/.config/waybar/scripts/wob-overlay.py" &
+disown $!
diff --git a/INSTALL/configs/waybar/scripts/wob-volume.sh b/INSTALL/configs/waybar/scripts/wob-volume.sh
new file mode 100755
index 0000000..6b47d52
--- /dev/null
+++ b/INSTALL/configs/waybar/scripts/wob-volume.sh
@@ -0,0 +1,28 @@
+#!/usr/bin/env bash
+# wob-volume.sh — scroll volume + feedback wob
+# Usage: wob-volume.sh up|down|mute
+
+STEP=5
+FIFO="/tmp/wob.fifo"
+
+get_vol() {
+ wpctl get-volume @DEFAULT_AUDIO_SINK@ 2>/dev/null | \
+ LC_ALL=C awk '{v=int($2*100); if(v>100)v=100; print v}'
+}
+
+case "$1" in
+ up)
+ wpctl set-volume -l 1.0 @DEFAULT_AUDIO_SINK@ "${STEP}%+"
+ ;;
+ down)
+ wpctl set-volume @DEFAULT_AUDIO_SINK@ "${STEP}%-"
+ ;;
+ mute)
+ wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle
+ ;;
+esac
+
+# Feedback overlay
+if [[ -p "$FIFO" ]]; then
+ echo "v:$(get_vol)" > "$FIFO"
+fi
diff --git a/INSTALL/configs/wob/wob.ini b/INSTALL/configs/wob/wob.ini
new file mode 100644
index 0000000..0035758
--- /dev/null
+++ b/INSTALL/configs/wob/wob.ini
@@ -0,0 +1,20 @@
+# ── violet-chaton wob config (v0.14.2) ───────────────────────────────────────
+
+timeout = 1000
+max = 100
+width = 260
+height = 36
+border_offset = 4
+border_size = 2
+bar_padding = 4
+anchor = bottom
+margin = 40
+
+background_color = 261537e0
+border_color = 5C496Ccc
+bar_color = ff79c6ff
+
+overflow_mode = wrap
+overflow_bar_color = f38ba8ff
+overflow_background_color = 261537e0
+overflow_border_color = f38ba8cc
diff --git a/INSTALL/configs/wofi/config b/INSTALL/configs/wofi/config
new file mode 100644
index 0000000..2dd687a
--- /dev/null
+++ b/INSTALL/configs/wofi/config
@@ -0,0 +1,7 @@
+allow_markup=true
+insensitive=true
+hide_scroll=true
+matching=contains
+no_actions=true
+layer=overlay
+lines=15
diff --git a/INSTALL/install.sh b/INSTALL/install.sh
index 5ccbb7c..72921e1 100755
--- a/INSTALL/install.sh
+++ b/INSTALL/install.sh
@@ -12,6 +12,14 @@ export INSTALL_LOG="$HOME/violet-chaton-install-$(date +%Y%m%d-%H%M%S).log"
source "$SCRIPT_DIR/scripts/lib.sh"
+# ── Refus root ────────────────────────────────────────────────────────────────
+if [ "$EUID" -eq 0 ]; then
+ echo -e "${RED}${BOLD} ERREUR : Ne pas lancer ce script en tant que root !${RESET}"
+ echo -e " Lance-le en tant qu'utilisateur normal : ${CYAN}bash install.sh${RESET}"
+ echo -e " ${MUTED}(sudo sera demandé automatiquement quand nécessaire)${RESET}"
+ exit 1
+fi
+
# ── Vérifications préalables ──────────────────────────────────────────────────
check_requirements() {
local ok=true
diff --git a/INSTALL/scripts/01-packages-apt.sh b/INSTALL/scripts/01-packages-apt.sh
index d7cd107..dd4faa9 100755
--- a/INSTALL/scripts/01-packages-apt.sh
+++ b/INSTALL/scripts/01-packages-apt.sh
@@ -19,6 +19,7 @@ PACKAGES=(
chafa
jq
libgtk-3-bin
+ adw-gtk3
nemo
nemo-fileroller
# fastfetch → installé via .deb GitHub (voir 02-packages-manual.sh)
@@ -26,6 +27,16 @@ PACKAGES=(
btop
# atuin → installé via son propre script (voir 02-packages-manual.sh)
# starship → installé via son propre script (voir 02-packages-manual.sh)
+ # ── Waybar + launcher + dépendances ──────────────────────────────────────
+ waybar
+ wob
+ wofi
+ brightnessctl
+ playerctl
+ wireplumber
+ python3-gi
+ gir1.2-gtk-3.0
+ gir1.2-gtklayershell-0.1
# ── Fun & utils ──────────────────────────────────────────────────────────
cmatrix
toilet
diff --git a/INSTALL/scripts/03-deploy-configs.sh b/INSTALL/scripts/03-deploy-configs.sh
index da160ca..feb67da 100755
--- a/INSTALL/scripts/03-deploy-configs.sh
+++ b/INSTALL/scripts/03-deploy-configs.sh
@@ -11,7 +11,14 @@ deploy_file() {
local src="$1"
local dst="$2"
ensure_dir "$(dirname "$dst")"
- if [ -f "$dst" ]; then
+ if [ -L "$dst" ]; then
+ # Symlink géré par COSMIC : sauvegarder la cible réelle puis supprimer le lien
+ local real; real=$(readlink -f "$dst")
+ local rel="${dst#"$HOME/"}"
+ ensure_dir "$BACKUP_DIR/$(dirname "$rel")"
+ cp "$real" "$BACKUP_DIR/$rel" 2>/dev/null
+ rm "$dst"
+ elif [ -f "$dst" ]; then
local rel="${dst#"$HOME/"}"
ensure_dir "$BACKUP_DIR/$(dirname "$rel")"
cp "$dst" "$BACKUP_DIR/$rel" 2>/dev/null
@@ -82,6 +89,24 @@ else
fail "CosmicTheme.Dark"
fi
+step "COSMIC Theme Light..."
+backup_dir "$COSMIC_DST/com.system76.CosmicTheme.Light/v1"
+ensure_dir "$COSMIC_DST/com.system76.CosmicTheme.Light/v1"
+if cp "$COSMIC_SRC/com.system76.CosmicTheme.Light/v1/"* "$COSMIC_DST/com.system76.CosmicTheme.Light/v1/" 2>/dev/null; then
+ ok "CosmicTheme.Light"
+else
+ fail "CosmicTheme.Light"
+fi
+
+step "COSMIC AppList (favoris dock — pas d'apps en cours)..."
+backup_dir "$COSMIC_DST/com.system76.CosmicAppList/v1"
+ensure_dir "$COSMIC_DST/com.system76.CosmicAppList/v1"
+if cp "$COSMIC_SRC/com.system76.CosmicAppList/v1/"* "$COSMIC_DST/com.system76.CosmicAppList/v1/" 2>/dev/null; then
+ ok "CosmicAppList (filter_top_levels)"
+else
+ fail "CosmicAppList"
+fi
+
step "COSMIC Theme Mode (dark)..."
backup_dir "$COSMIC_DST/com.system76.CosmicTheme.Mode/v1"
ensure_dir "$COSMIC_DST/com.system76.CosmicTheme.Mode/v1"
@@ -100,11 +125,27 @@ else
fail "CosmicTerm"
fi
-# ── GTK3 — thème violet-chaton ─────────────────────────────────────────────
-section "GTK3 — thème violet-chaton"
+# ── GTK3 / GTK4 — thème violet-chaton ─────────────────────────────────────
+section "GTK — thème violet-chaton"
+
+step "Thème GTK3 (adw-gtk3-dark + couleurs violet-chaton)..."
ensure_dir "$HOME/.config/gtk-3.0"
deploy_file "$THEMES/violet-chaton-gtk.css" "$HOME/.config/gtk-3.0/gtk.css"
+step "Thème GTK4 / libadwaita (couleurs violet-chaton)..."
+ensure_dir "$HOME/.config/gtk-4.0"
+deploy_file "$THEMES/violet-chaton-gtk.css" "$HOME/.config/gtk-4.0/gtk.css"
+
+step "Activation adw-gtk3-dark + dark mode (gsettings)..."
+if has_cmd gsettings; then
+ gsettings set org.gnome.desktop.interface gtk-theme 'adw-gtk3-dark' 2>/dev/null && \
+ gsettings set org.gnome.desktop.interface color-scheme 'prefer-dark' 2>/dev/null && \
+ ok "gtk-theme=adw-gtk3-dark, color-scheme=prefer-dark" || \
+ warn "gsettings GTK échoué — thème à appliquer manuellement"
+else
+ warn "gsettings non disponible — thème GTK à appliquer manuellement"
+fi
+
# ── Nemo — gestionnaire de fichiers ────────────────────────────────────────
section "Nemo — configuration et thème"
@@ -205,6 +246,105 @@ PYEOF
fi
fi
+# ── Waybar ─────────────────────────────────────────────────────────────────────
+section "Waybar — island floating 3 pills"
+deploy_file "$CONFIGS/waybar/config" "$HOME/.config/waybar/config"
+deploy_file "$THEMES/violet-chaton-waybar.css" "$HOME/.config/waybar/style.css"
+deploy_file "$CONFIGS/waybar/cava-waybar.cfg" "$HOME/.config/waybar/cava-waybar.cfg"
+
+step "Scripts waybar..."
+ensure_dir "$HOME/.config/waybar/scripts"
+for script in "$CONFIGS/waybar/scripts/"*.sh; do
+ dst="$HOME/.config/waybar/scripts/$(basename "$script")"
+ cp "$script" "$dst" && chmod +x "$dst"
+done
+for script in "$CONFIGS/waybar/scripts/"*.py; do
+ dst="$HOME/.config/waybar/scripts/$(basename "$script")"
+ cp "$script" "$dst" && chmod +x "$dst"
+done
+ok "Scripts waybar"
+
+# ── Autostart ───────────────────────────────────────────────────────────────────
+section "Autostart — waybar + wob"
+ensure_dir "$HOME/.config/autostart"
+deploy_file "$CONFIGS/autostart/waybar.desktop" "$HOME/.config/autostart/waybar.desktop"
+deploy_file "$CONFIGS/autostart/wob.desktop" "$HOME/.config/autostart/wob.desktop"
+
+# ── Règle sudoers — profil énergie ──────────────────────────────────────────────
+section "Sudoers — profil énergie ACPI"
+SUDOERS_FILE="/etc/sudoers.d/waybar-power-profile"
+SUDOERS_RULE="$USER ALL=(ALL) NOPASSWD: /usr/bin/tee /sys/firmware/acpi/platform_profile"
+if [ -f "$SUDOERS_FILE" ]; then
+ ok "Règle sudoers déjà présente"
+else
+ step "Création de la règle sudoers (mot de passe sudo requis)..."
+ echo "$SUDOERS_RULE" > /tmp/waybar-pp-sudoers
+ if sudo cp /tmp/waybar-pp-sudoers "$SUDOERS_FILE" && sudo chmod 440 "$SUDOERS_FILE"; then
+ rm -f /tmp/waybar-pp-sudoers
+ ok "Règle sudoers créée"
+ else
+ rm -f /tmp/waybar-pp-sudoers
+ warn "Échec sudoers — changement de profil énergie nécessitera sudo"
+ fi
+fi
+
+# ── Règle udev — permissions platform_profile ────────────────────────────────
+section "udev — platform_profile accessible au groupe video"
+UDEV_FILE="/etc/udev/rules.d/90-platform-profile.rules"
+if [ -f "$UDEV_FILE" ]; then
+ ok "Règle udev déjà présente"
+else
+ step "Création de la règle udev (mot de passe sudo requis)..."
+ echo 'ACTION=="add|change", KERNEL=="platform_profile", SUBSYSTEM=="acpi", RUN+="/bin/chmod g+w /sys/firmware/acpi/platform_profile", RUN+="/bin/chgrp video /sys/firmware/acpi/platform_profile"' \
+ > /tmp/90-platform-profile.rules
+ if sudo cp /tmp/90-platform-profile.rules "$UDEV_FILE" && sudo chmod 644 "$UDEV_FILE"; then
+ rm -f /tmp/90-platform-profile.rules
+ sudo chmod g+w /sys/firmware/acpi/platform_profile 2>/dev/null
+ sudo chgrp video /sys/firmware/acpi/platform_profile 2>/dev/null
+ ok "Règle udev créée"
+ else
+ rm -f /tmp/90-platform-profile.rules
+ warn "Échec udev — redémarrage requis pour les permissions platform_profile"
+ fi
+fi
+
+# ── Wofi — launcher + power menu ────────────────────────────────────────────────
+section "Wofi — launcher violet-chaton"
+ensure_dir "$HOME/.config/wofi"
+deploy_file "$CONFIGS/wofi/config" "$HOME/.config/wofi/config"
+deploy_file "$THEMES/violet-chaton-wofi.css" "$HOME/.config/wofi/style.css"
+deploy_file "$THEMES/violet-chaton-wofi-power.css" "$HOME/.config/wofi/power-style.css"
+
+# ── Rofi ────────────────────────────────────────────────────────────────────────
+section "Rofi — thème violet-chaton"
+ensure_dir "$HOME/.config/rofi"
+deploy_file "$CONFIGS/rofi/config.rasi" "$HOME/.config/rofi/config.rasi"
+deploy_file "$THEMES/violet-chaton-rofi.rasi" "$HOME/.config/rofi/violet-chaton.rasi"
+
+# ── wob ─────────────────────────────────────────────────────────────────────────
+section "wob — overlay volume/luminosité"
+deploy_file "$CONFIGS/wob/wob.ini" "$HOME/.config/wob.ini"
+
+# ── Désactiver cosmic-osd (remplacé par wob) ─────────────────────────────────
+section "cosmic-osd — désactivation (wob le remplace)"
+if [ -f /usr/bin/cosmic-osd.real ]; then
+ ok "cosmic-osd déjà désactivé via dpkg-divert"
+elif [ -f /usr/bin/cosmic-osd ]; then
+ step "Divert de cosmic-osd (mot de passe sudo requis)..."
+ if sudo dpkg-divert --add --rename --divert /usr/bin/cosmic-osd.real /usr/bin/cosmic-osd; then
+ printf '#!/usr/bin/env bash\nexec sleep infinity\n' > /tmp/cosmic-osd-fake
+ chmod +x /tmp/cosmic-osd-fake
+ sudo cp /tmp/cosmic-osd-fake /usr/bin/cosmic-osd
+ rm -f /tmp/cosmic-osd-fake
+ pkill -x cosmic-osd 2>/dev/null
+ ok "cosmic-osd désactivé — wob gère les overlays"
+ else
+ warn "dpkg-divert échoué — cosmic-osd reste actif"
+ fi
+else
+ warn "cosmic-osd introuvable — rien à faire"
+fi
+
# ── Logo fastfetch ─────────────────────────────────────────────────────────────
section "Logo fastfetch"
if [ -f "$SCRIPT_DIR/assets/violet-chaton-logo.png" ]; then
diff --git a/INSTALL/themes/cosmic/com.system76.CosmicAppList/v1/filter_top_levels b/INSTALL/themes/cosmic/com.system76.CosmicAppList/v1/filter_top_levels
new file mode 100644
index 0000000..907ade8
--- /dev/null
+++ b/INSTALL/themes/cosmic/com.system76.CosmicAppList/v1/filter_top_levels
@@ -0,0 +1 @@
+Some([])
diff --git a/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/accent b/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/accent
new file mode 100644
index 0000000..6d4e48b
--- /dev/null
+++ b/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/accent
@@ -0,0 +1,74 @@
+(
+ base: (
+ red: 0.9058823,
+ green: 0.6117647,
+ blue: 0.99607843,
+ alpha: 1.0,
+ ),
+ hover: (
+ red: 0.7988549,
+ green: 0.5659659,
+ blue: 0.8900906,
+ alpha: 1.0,
+ ),
+ pressed: (
+ red: 0.81436175,
+ green: 0.6745583,
+ blue: 0.91372323,
+ alpha: 1.0,
+ ),
+ selected: (
+ red: 0.7988549,
+ green: 0.5659659,
+ blue: 0.8900906,
+ alpha: 1.0,
+ ),
+ selected_text: (
+ red: 0.9058823,
+ green: 0.6117647,
+ blue: 0.99607843,
+ alpha: 1.0,
+ ),
+ focus: (
+ red: 0.9058823,
+ green: 0.6117647,
+ blue: 0.99607843,
+ alpha: 1.0,
+ ),
+ divider: (
+ red: 0.9999203,
+ green: 0.99998146,
+ blue: 1.0,
+ alpha: 1.0,
+ ),
+ on: (
+ red: 0.9999203,
+ green: 0.99998146,
+ blue: 1.0,
+ alpha: 1.0,
+ ),
+ disabled: (
+ red: 0.9058823,
+ green: 0.6117647,
+ blue: 0.99607843,
+ alpha: 1.0,
+ ),
+ on_disabled: (
+ red: 0.9529013,
+ green: 0.8058731,
+ blue: 0.99803925,
+ alpha: 1.0,
+ ),
+ border: (
+ red: 0.9058823,
+ green: 0.6117647,
+ blue: 0.99607843,
+ alpha: 1.0,
+ ),
+ disabled_border: (
+ red: 0.9058823,
+ green: 0.6117647,
+ blue: 0.99607843,
+ alpha: 0.5,
+ ),
+)
\ No newline at end of file
diff --git a/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/accent_button b/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/accent_button
new file mode 100644
index 0000000..feced8c
--- /dev/null
+++ b/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/accent_button
@@ -0,0 +1,74 @@
+(
+ base: (
+ red: 0.9058823,
+ green: 0.6117647,
+ blue: 0.99607843,
+ alpha: 1.0,
+ ),
+ hover: (
+ red: 0.7988549,
+ green: 0.5659659,
+ blue: 0.8900906,
+ alpha: 1.0,
+ ),
+ pressed: (
+ red: 0.81436175,
+ green: 0.6745583,
+ blue: 0.91372323,
+ alpha: 1.0,
+ ),
+ selected: (
+ red: 0.7988549,
+ green: 0.5659659,
+ blue: 0.8900906,
+ alpha: 1.0,
+ ),
+ selected_text: (
+ red: 0.9058823,
+ green: 0.6117647,
+ blue: 0.99607843,
+ alpha: 1.0,
+ ),
+ focus: (
+ red: 0.9058823,
+ green: 0.6117647,
+ blue: 0.99607843,
+ alpha: 1.0,
+ ),
+ divider: (
+ red: 0.84878576,
+ green: 0.8639131,
+ blue: 0.9608068,
+ alpha: 1.0,
+ ),
+ on: (
+ red: 0.9999203,
+ green: 0.99998146,
+ blue: 1.0,
+ alpha: 1.0,
+ ),
+ disabled: (
+ red: 0.9058823,
+ green: 0.6117647,
+ blue: 0.99607843,
+ alpha: 1.0,
+ ),
+ on_disabled: (
+ red: 0.9999203,
+ green: 0.99998146,
+ blue: 1.0,
+ alpha: 0.5,
+ ),
+ border: (
+ red: 0.9058823,
+ green: 0.6117647,
+ blue: 0.99607843,
+ alpha: 1.0,
+ ),
+ disabled_border: (
+ red: 0.9058823,
+ green: 0.6117647,
+ blue: 0.99607843,
+ alpha: 0.5,
+ ),
+)
\ No newline at end of file
diff --git a/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/accent_text b/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/accent_text
new file mode 100644
index 0000000..4af1832
--- /dev/null
+++ b/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/accent_text
@@ -0,0 +1 @@
+None
\ No newline at end of file
diff --git a/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/active_hint b/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/active_hint
new file mode 100644
index 0000000..e440e5c
--- /dev/null
+++ b/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/active_hint
@@ -0,0 +1 @@
+3
\ No newline at end of file
diff --git a/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/background b/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/background
new file mode 100644
index 0000000..0151143
--- /dev/null
+++ b/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/background
@@ -0,0 +1,100 @@
+(
+ base: (
+ red: 0.20392156,
+ green: 0.109803915,
+ blue: 0.2901961,
+ alpha: 1.0,
+ ),
+ component: (
+ base: (
+ red: 0.28618598,
+ green: 0.19189146,
+ blue: 0.3797182,
+ alpha: 1.0,
+ ),
+ hover: (
+ red: 0.25756738,
+ green: 0.17270231,
+ blue: 0.3417464,
+ alpha: 1.0,
+ ),
+ pressed: (
+ red: 0.22894879,
+ green: 0.15351318,
+ blue: 0.30377457,
+ alpha: 1.0,
+ ),
+ selected: (
+ red: 0.25756738,
+ green: 0.17270231,
+ blue: 0.3417464,
+ alpha: 1.0,
+ ),
+ selected_text: (
+ red: 0.9058823,
+ green: 0.6117647,
+ blue: 0.99607843,
+ alpha: 1.0,
+ ),
+ focus: (
+ red: 0.9058823,
+ green: 0.6117647,
+ blue: 0.99607843,
+ alpha: 1.0,
+ ),
+ divider: (
+ red: 0.8318751,
+ green: 0.8318648,
+ blue: 0.80908096,
+ alpha: 0.2,
+ ),
+ on: (
+ red: 0.8318751,
+ green: 0.8318648,
+ blue: 0.80908096,
+ alpha: 1.0,
+ ),
+ disabled: (
+ red: 0.28618598,
+ green: 0.19189146,
+ blue: 0.3797182,
+ alpha: 0.5,
+ ),
+ on_disabled: (
+ red: 0.8318751,
+ green: 0.8318648,
+ blue: 0.80908096,
+ alpha: 0.65,
+ ),
+ border: (
+ red: 0.072988935,
+ green: 0.079405405,
+ blue: 0.14595589,
+ alpha: 1.0,
+ ),
+ disabled_border: (
+ red: 0.072988935,
+ green: 0.079405405,
+ blue: 0.14595589,
+ alpha: 0.5,
+ ),
+ ),
+ divider: (
+ red: 0.3609102,
+ green: 0.285616,
+ blue: 0.42522332,
+ alpha: 1.0,
+ ),
+ on: (
+ red: 0.98886484,
+ green: 0.98886436,
+ blue: 0.9653322,
+ alpha: 1.0,
+ ),
+ small_widget: (
+ red: 0.20783836,
+ green: 0.20930338,
+ blue: 0.23179808,
+ alpha: 0.25,
+ ),
+)
\ No newline at end of file
diff --git a/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/button b/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/button
new file mode 100644
index 0000000..c01ffd6
--- /dev/null
+++ b/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/button
@@ -0,0 +1,74 @@
+(
+ base: (
+ red: 0.16402894,
+ green: 0.17314792,
+ blue: 0.246458,
+ alpha: 0.25,
+ ),
+ hover: (
+ red: 0.15616347,
+ green: 0.16312802,
+ blue: 0.2164568,
+ alpha: 0.4,
+ ),
+ pressed: (
+ red: 0.3942264,
+ green: 0.40330547,
+ blue: 0.46497566,
+ alpha: 0.625,
+ ),
+ selected: (
+ red: 0.15616347,
+ green: 0.16312802,
+ blue: 0.2164568,
+ alpha: 0.4,
+ ),
+ selected_text: (
+ red: 0.9058823,
+ green: 0.6117647,
+ blue: 0.99607843,
+ alpha: 1.0,
+ ),
+ focus: (
+ red: 0.9058823,
+ green: 0.6117647,
+ blue: 0.99607843,
+ alpha: 1.0,
+ ),
+ divider: (
+ red: 0.8318751,
+ green: 0.8318648,
+ blue: 0.80908096,
+ alpha: 0.2,
+ ),
+ on: (
+ red: 0.8318751,
+ green: 0.8318648,
+ blue: 0.80908096,
+ alpha: 1.0,
+ ),
+ disabled: (
+ red: 0.16402894,
+ green: 0.17314792,
+ blue: 0.246458,
+ alpha: 0.125,
+ ),
+ on_disabled: (
+ red: 0.8318751,
+ green: 0.8318648,
+ blue: 0.80908096,
+ alpha: 0.65,
+ ),
+ border: (
+ red: 0.072988935,
+ green: 0.079405405,
+ blue: 0.14595589,
+ alpha: 1.0,
+ ),
+ disabled_border: (
+ red: 0.072988935,
+ green: 0.079405405,
+ blue: 0.14595589,
+ alpha: 0.5,
+ ),
+)
\ No newline at end of file
diff --git a/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/control_tint b/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/control_tint
new file mode 100644
index 0000000..7158275
--- /dev/null
+++ b/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/control_tint
@@ -0,0 +1,5 @@
+Some((
+ red: 0.46666667,
+ green: 0.46666667,
+ blue: 0.46666667,
+))
\ No newline at end of file
diff --git a/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/corner_radii b/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/corner_radii
new file mode 100644
index 0000000..fc61500
--- /dev/null
+++ b/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/corner_radii
@@ -0,0 +1,8 @@
+(
+ radius_0: (0.0, 0.0, 0.0, 0.0),
+ radius_xs: (2.0, 2.0, 2.0, 2.0),
+ radius_s: (8.0, 8.0, 8.0, 8.0),
+ radius_m: (8.0, 8.0, 8.0, 8.0),
+ radius_l: (8.0, 8.0, 8.0, 8.0),
+ radius_xl: (8.0, 8.0, 8.0, 8.0),
+)
\ No newline at end of file
diff --git a/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/destructive b/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/destructive
new file mode 100644
index 0000000..79dadc8
--- /dev/null
+++ b/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/destructive
@@ -0,0 +1,74 @@
+(
+ base: (
+ red: 0.47058824,
+ green: 0.16078432,
+ blue: 0.18039216,
+ alpha: 1.0,
+ ),
+ hover: (
+ red: 0.45061958,
+ green: 0.20518154,
+ blue: 0.23754153,
+ alpha: 1.0,
+ ),
+ pressed: (
+ red: 0.59671474,
+ green: 0.44906804,
+ blue: 0.5058801,
+ alpha: 1.0,
+ ),
+ selected: (
+ red: 0.45061958,
+ green: 0.20518154,
+ blue: 0.23754153,
+ alpha: 1.0,
+ ),
+ selected_text: (
+ red: 0.9058823,
+ green: 0.6117647,
+ blue: 0.99607843,
+ alpha: 1.0,
+ ),
+ focus: (
+ red: 0.9058823,
+ green: 0.6117647,
+ blue: 0.99607843,
+ alpha: 1.0,
+ ),
+ divider: (
+ red: 0.9999203,
+ green: 0.99998146,
+ blue: 1.0,
+ alpha: 1.0,
+ ),
+ on: (
+ red: 0.9999203,
+ green: 0.99998146,
+ blue: 1.0,
+ alpha: 1.0,
+ ),
+ disabled: (
+ red: 0.47058824,
+ green: 0.16078432,
+ blue: 0.18039216,
+ alpha: 1.0,
+ ),
+ on_disabled: (
+ red: 0.7352543,
+ green: 0.5803829,
+ blue: 0.5901961,
+ alpha: 1.0,
+ ),
+ border: (
+ red: 0.47058824,
+ green: 0.16078432,
+ blue: 0.18039216,
+ alpha: 1.0,
+ ),
+ disabled_border: (
+ red: 0.47058824,
+ green: 0.16078432,
+ blue: 0.18039216,
+ alpha: 0.5,
+ ),
+)
\ No newline at end of file
diff --git a/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/destructive_button b/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/destructive_button
new file mode 100644
index 0000000..9f704d3
--- /dev/null
+++ b/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/destructive_button
@@ -0,0 +1,74 @@
+(
+ base: (
+ red: 0.47058824,
+ green: 0.16078432,
+ blue: 0.18039216,
+ alpha: 1.0,
+ ),
+ hover: (
+ red: 0.45061958,
+ green: 0.20518154,
+ blue: 0.23754153,
+ alpha: 1.0,
+ ),
+ pressed: (
+ red: 0.59671474,
+ green: 0.44906804,
+ blue: 0.5058801,
+ alpha: 1.0,
+ ),
+ selected: (
+ red: 0.45061958,
+ green: 0.20518154,
+ blue: 0.23754153,
+ alpha: 1.0,
+ ),
+ selected_text: (
+ red: 0.9058823,
+ green: 0.6117647,
+ blue: 0.99607843,
+ alpha: 1.0,
+ ),
+ focus: (
+ red: 0.9058823,
+ green: 0.6117647,
+ blue: 0.99607843,
+ alpha: 1.0,
+ ),
+ divider: (
+ red: 0.84878576,
+ green: 0.8639131,
+ blue: 0.9608068,
+ alpha: 1.0,
+ ),
+ on: (
+ red: 0.9999203,
+ green: 0.99998146,
+ blue: 1.0,
+ alpha: 1.0,
+ ),
+ disabled: (
+ red: 0.47058824,
+ green: 0.16078432,
+ blue: 0.18039216,
+ alpha: 1.0,
+ ),
+ on_disabled: (
+ red: 0.9999203,
+ green: 0.99998146,
+ blue: 1.0,
+ alpha: 0.5,
+ ),
+ border: (
+ red: 0.47058824,
+ green: 0.16078432,
+ blue: 0.18039216,
+ alpha: 1.0,
+ ),
+ disabled_border: (
+ red: 0.47058824,
+ green: 0.16078432,
+ blue: 0.18039216,
+ alpha: 0.5,
+ ),
+)
\ No newline at end of file
diff --git a/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/gaps b/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/gaps
new file mode 100644
index 0000000..6fe974b
--- /dev/null
+++ b/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/gaps
@@ -0,0 +1 @@
+(0, 8)
\ No newline at end of file
diff --git a/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/icon_button b/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/icon_button
new file mode 100644
index 0000000..eccee0d
--- /dev/null
+++ b/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/icon_button
@@ -0,0 +1,74 @@
+(
+ base: (
+ red: 0.0,
+ green: 0.0,
+ blue: 0.0,
+ alpha: 0.0,
+ ),
+ hover: (
+ red: 0.37074497,
+ green: 0.38277033,
+ blue: 0.46613896,
+ alpha: 0.2,
+ ),
+ pressed: (
+ red: 0.7228412,
+ green: 0.7373518,
+ blue: 0.8313681,
+ alpha: 0.5,
+ ),
+ selected: (
+ red: 0.37074497,
+ green: 0.38277033,
+ blue: 0.46613896,
+ alpha: 0.2,
+ ),
+ selected_text: (
+ red: 0.9058823,
+ green: 0.6117647,
+ blue: 0.99607843,
+ alpha: 1.0,
+ ),
+ focus: (
+ red: 0.9058823,
+ green: 0.6117647,
+ blue: 0.99607843,
+ alpha: 1.0,
+ ),
+ divider: (
+ red: 0.072988935,
+ green: 0.079405405,
+ blue: 0.14595589,
+ alpha: 0.2,
+ ),
+ on: (
+ red: 0.072988935,
+ green: 0.079405405,
+ blue: 0.14595589,
+ alpha: 1.0,
+ ),
+ disabled: (
+ red: 0.0,
+ green: 0.0,
+ blue: 0.0,
+ alpha: 0.0,
+ ),
+ on_disabled: (
+ red: 0.072988935,
+ green: 0.079405405,
+ blue: 0.14595589,
+ alpha: 0.65,
+ ),
+ border: (
+ red: 0.072988935,
+ green: 0.079405405,
+ blue: 0.14595589,
+ alpha: 1.0,
+ ),
+ disabled_border: (
+ red: 0.072988935,
+ green: 0.079405405,
+ blue: 0.14595589,
+ alpha: 0.5,
+ ),
+)
\ No newline at end of file
diff --git a/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/is_dark b/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/is_dark
new file mode 100644
index 0000000..02e4a84
--- /dev/null
+++ b/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/is_dark
@@ -0,0 +1 @@
+false
\ No newline at end of file
diff --git a/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/is_frosted b/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/is_frosted
new file mode 100644
index 0000000..02e4a84
--- /dev/null
+++ b/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/is_frosted
@@ -0,0 +1 @@
+false
\ No newline at end of file
diff --git a/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/is_high_contrast b/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/is_high_contrast
new file mode 100644
index 0000000..02e4a84
--- /dev/null
+++ b/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/is_high_contrast
@@ -0,0 +1 @@
+false
\ No newline at end of file
diff --git a/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/link_button b/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/link_button
new file mode 100644
index 0000000..f35c295
--- /dev/null
+++ b/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/link_button
@@ -0,0 +1,74 @@
+(
+ base: (
+ red: 0.0,
+ green: 0.0,
+ blue: 0.0,
+ alpha: 0.0,
+ ),
+ hover: (
+ red: 0.0,
+ green: 0.0,
+ blue: 0.0,
+ alpha: 0.0,
+ ),
+ pressed: (
+ red: 0.0,
+ green: 0.0,
+ blue: 0.0,
+ alpha: 0.0,
+ ),
+ selected: (
+ red: 0.0,
+ green: 0.0,
+ blue: 0.0,
+ alpha: 0.0,
+ ),
+ selected_text: (
+ red: 0.9058823,
+ green: 0.6117647,
+ blue: 0.99607843,
+ alpha: 1.0,
+ ),
+ focus: (
+ red: 0.9058823,
+ green: 0.6117647,
+ blue: 0.99607843,
+ alpha: 1.0,
+ ),
+ divider: (
+ red: 0.9058823,
+ green: 0.6117647,
+ blue: 0.99607843,
+ alpha: 0.2,
+ ),
+ on: (
+ red: 0.9058823,
+ green: 0.6117647,
+ blue: 0.99607843,
+ alpha: 1.0,
+ ),
+ disabled: (
+ red: 0.0,
+ green: 0.0,
+ blue: 0.0,
+ alpha: 0.0,
+ ),
+ on_disabled: (
+ red: 0.45294115,
+ green: 0.30588236,
+ blue: 0.49803922,
+ alpha: 0.5,
+ ),
+ border: (
+ red: 0.072988935,
+ green: 0.079405405,
+ blue: 0.14595589,
+ alpha: 1.0,
+ ),
+ disabled_border: (
+ red: 0.072988935,
+ green: 0.079405405,
+ blue: 0.14595589,
+ alpha: 0.5,
+ ),
+)
\ No newline at end of file
diff --git a/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/name b/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/name
new file mode 100644
index 0000000..6a3a7b4
--- /dev/null
+++ b/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/name
@@ -0,0 +1 @@
+"Violet-chaton"
\ No newline at end of file
diff --git a/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/palette b/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/palette
new file mode 100644
index 0000000..610fef9
--- /dev/null
+++ b/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/palette
@@ -0,0 +1,195 @@
+(
+ name: "cosmic-light",
+ bright_red: (
+ red: 0.5372549,
+ green: 0.015686275,
+ blue: 0.09411765,
+ alpha: 1.0,
+ ),
+ bright_green: (
+ red: 0.0,
+ green: 0.34117648,
+ blue: 0.17254902,
+ alpha: 1.0,
+ ),
+ bright_orange: (
+ red: 0.4745098,
+ green: 0.17254902,
+ blue: 0.0,
+ alpha: 1.0,
+ ),
+ gray_1: (
+ red: 0.8666667,
+ green: 0.8666667,
+ blue: 0.8666667,
+ alpha: 1.0,
+ ),
+ gray_2: (
+ red: 0.9098039,
+ green: 0.9098039,
+ blue: 0.9098039,
+ alpha: 1.0,
+ ),
+ neutral_0: (
+ red: 1.0,
+ green: 1.0,
+ blue: 1.0,
+ alpha: 1.0,
+ ),
+ neutral_1: (
+ red: 0.8862745,
+ green: 0.8862745,
+ blue: 0.8862745,
+ alpha: 1.0,
+ ),
+ neutral_2: (
+ red: 0.7764706,
+ green: 0.7764706,
+ blue: 0.7764706,
+ alpha: 1.0,
+ ),
+ neutral_3: (
+ red: 0.67058825,
+ green: 0.67058825,
+ blue: 0.67058825,
+ alpha: 1.0,
+ ),
+ neutral_4: (
+ red: 0.5686275,
+ green: 0.5686275,
+ blue: 0.5686275,
+ alpha: 1.0,
+ ),
+ neutral_5: (
+ red: 0.46666667,
+ green: 0.46666667,
+ blue: 0.46666667,
+ alpha: 1.0,
+ ),
+ neutral_6: (
+ red: 0.36862746,
+ green: 0.36862746,
+ blue: 0.36862746,
+ alpha: 1.0,
+ ),
+ neutral_7: (
+ red: 0.2784314,
+ green: 0.2784314,
+ blue: 0.2784314,
+ alpha: 1.0,
+ ),
+ neutral_8: (
+ red: 0.1882353,
+ green: 0.1882353,
+ blue: 0.1882353,
+ alpha: 1.0,
+ ),
+ neutral_9: (
+ red: 0.105882354,
+ green: 0.105882354,
+ blue: 0.105882354,
+ alpha: 1.0,
+ ),
+ neutral_10: (
+ red: 0.0,
+ green: 0.0,
+ blue: 0.0,
+ alpha: 1.0,
+ ),
+ accent_blue: (
+ red: 0.0,
+ green: 0.32156864,
+ blue: 0.3529412,
+ alpha: 1.0,
+ ),
+ accent_indigo: (
+ red: 0.18039216,
+ green: 0.28627452,
+ blue: 0.42745098,
+ alpha: 1.0,
+ ),
+ accent_purple: (
+ red: 0.40784314,
+ green: 0.12941177,
+ blue: 0.4862745,
+ alpha: 1.0,
+ ),
+ accent_pink: (
+ red: 0.5254902,
+ green: 0.015686275,
+ blue: 0.22745098,
+ alpha: 1.0,
+ ),
+ accent_red: (
+ red: 0.47058824,
+ green: 0.16078432,
+ blue: 0.18039216,
+ alpha: 1.0,
+ ),
+ accent_orange: (
+ red: 0.38431373,
+ green: 0.2509804,
+ blue: 0.0,
+ alpha: 1.0,
+ ),
+ accent_yellow: (
+ red: 0.3254902,
+ green: 0.28235295,
+ blue: 0.0,
+ alpha: 1.0,
+ ),
+ accent_green: (
+ red: 0.09411765,
+ green: 0.33333334,
+ blue: 0.16078432,
+ alpha: 1.0,
+ ),
+ accent_warm_grey: (
+ red: 0.33333334,
+ green: 0.2784314,
+ blue: 0.25882354,
+ alpha: 1.0,
+ ),
+ ext_warm_grey: (
+ red: 0.60784316,
+ green: 0.5568628,
+ blue: 0.5411765,
+ alpha: 1.0,
+ ),
+ ext_orange: (
+ red: 0.9843137,
+ green: 0.72156864,
+ blue: 0.42352942,
+ alpha: 1.0,
+ ),
+ ext_yellow: (
+ red: 0.96862745,
+ green: 0.8784314,
+ blue: 0.38431373,
+ alpha: 1.0,
+ ),
+ ext_blue: (
+ red: 0.41568628,
+ green: 0.7921569,
+ blue: 0.84705883,
+ alpha: 1.0,
+ ),
+ ext_purple: (
+ red: 0.8352941,
+ green: 0.54901963,
+ blue: 1.0,
+ alpha: 1.0,
+ ),
+ ext_pink: (
+ red: 1.0,
+ green: 0.6117647,
+ blue: 0.8666667,
+ alpha: 1.0,
+ ),
+ ext_indigo: (
+ red: 0.58431375,
+ green: 0.76862746,
+ blue: 0.9882353,
+ alpha: 1.0,
+ ),
+)
\ No newline at end of file
diff --git a/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/primary b/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/primary
new file mode 100644
index 0000000..58ec8e0
--- /dev/null
+++ b/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/primary
@@ -0,0 +1,100 @@
+(
+ base: (
+ red: 0.21960787,
+ green: 0.13725492,
+ blue: 0.29411766,
+ alpha: 1.0,
+ ),
+ component: (
+ base: (
+ red: 0.28282174,
+ green: 0.19933021,
+ blue: 0.36183798,
+ alpha: 1.0,
+ ),
+ hover: (
+ red: 0.25453955,
+ green: 0.17939718,
+ blue: 0.32565418,
+ alpha: 1.0,
+ ),
+ pressed: (
+ red: 0.2262574,
+ green: 0.15946417,
+ blue: 0.2894704,
+ alpha: 1.0,
+ ),
+ selected: (
+ red: 0.25453955,
+ green: 0.17939718,
+ blue: 0.32565418,
+ alpha: 1.0,
+ ),
+ selected_text: (
+ red: 0.9058823,
+ green: 0.6117647,
+ blue: 0.99607843,
+ alpha: 1.0,
+ ),
+ focus: (
+ red: 0.9058823,
+ green: 0.6117647,
+ blue: 0.99607843,
+ alpha: 1.0,
+ ),
+ divider: (
+ red: 0.8318751,
+ green: 0.8318648,
+ blue: 0.80908096,
+ alpha: 0.2,
+ ),
+ on: (
+ red: 0.8318751,
+ green: 0.8318648,
+ blue: 0.80908096,
+ alpha: 1.0,
+ ),
+ disabled: (
+ red: 0.28282174,
+ green: 0.19933021,
+ blue: 0.36183798,
+ alpha: 0.5,
+ ),
+ on_disabled: (
+ red: 0.8318751,
+ green: 0.8318648,
+ blue: 0.80908096,
+ alpha: 0.65,
+ ),
+ border: (
+ red: 0.072988935,
+ green: 0.079405405,
+ blue: 0.14595589,
+ alpha: 1.0,
+ ),
+ disabled_border: (
+ red: 0.072988935,
+ green: 0.079405405,
+ blue: 0.14595589,
+ alpha: 0.5,
+ ),
+ ),
+ divider: (
+ red: 0.32675916,
+ green: 0.26087362,
+ blue: 0.38188773,
+ alpha: 1.0,
+ ),
+ on: (
+ red: 0.7553642,
+ green: 0.7553483,
+ blue: 0.732968,
+ alpha: 1.0,
+ ),
+ small_widget: (
+ red: 0.22808892,
+ green: 0.22971416,
+ blue: 0.25254303,
+ alpha: 0.25,
+ ),
+)
\ No newline at end of file
diff --git a/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/secondary b/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/secondary
new file mode 100644
index 0000000..c3fd2ea
--- /dev/null
+++ b/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/secondary
@@ -0,0 +1,100 @@
+(
+ base: (
+ red: 0.30756307,
+ green: 0.21295837,
+ blue: 0.4027321,
+ alpha: 1.0,
+ ),
+ component: (
+ base: (
+ red: 0.3401073,
+ green: 0.24494115,
+ blue: 0.4376148,
+ alpha: 1.0,
+ ),
+ hover: (
+ red: 0.30609655,
+ green: 0.22044702,
+ blue: 0.3938533,
+ alpha: 1.0,
+ ),
+ pressed: (
+ red: 0.27208585,
+ green: 0.19595292,
+ blue: 0.35009184,
+ alpha: 1.0,
+ ),
+ selected: (
+ red: 0.30609655,
+ green: 0.22044702,
+ blue: 0.3938533,
+ alpha: 1.0,
+ ),
+ selected_text: (
+ red: 0.9058823,
+ green: 0.6117647,
+ blue: 0.99607843,
+ alpha: 1.0,
+ ),
+ focus: (
+ red: 0.9058823,
+ green: 0.6117647,
+ blue: 0.99607843,
+ alpha: 1.0,
+ ),
+ divider: (
+ red: 0.8966642,
+ green: 0.8966583,
+ blue: 0.87355375,
+ alpha: 0.2,
+ ),
+ on: (
+ red: 0.8966642,
+ green: 0.8966583,
+ blue: 0.87355375,
+ alpha: 1.0,
+ ),
+ disabled: (
+ red: 0.3401073,
+ green: 0.24494115,
+ blue: 0.4376148,
+ alpha: 0.5,
+ ),
+ on_disabled: (
+ red: 0.8966642,
+ green: 0.8966583,
+ blue: 0.87355375,
+ alpha: 0.65,
+ ),
+ border: (
+ red: 0.072988935,
+ green: 0.079405405,
+ blue: 0.14595589,
+ alpha: 1.0,
+ ),
+ disabled_border: (
+ red: 0.072988935,
+ green: 0.079405405,
+ blue: 0.14595589,
+ alpha: 0.5,
+ ),
+ ),
+ divider: (
+ red: 0.41758668,
+ green: 0.34190118,
+ blue: 0.48913747,
+ alpha: 1.0,
+ ),
+ on: (
+ red: 0.8576811,
+ green: 0.8576725,
+ blue: 0.83475876,
+ alpha: 1.0,
+ ),
+ small_widget: (
+ red: 0.31199428,
+ green: 0.31415156,
+ blue: 0.33818555,
+ alpha: 0.25,
+ ),
+)
\ No newline at end of file
diff --git a/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/shade b/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/shade
new file mode 100644
index 0000000..03085f6
--- /dev/null
+++ b/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/shade
@@ -0,0 +1,6 @@
+(
+ red: 0.0,
+ green: 0.0,
+ blue: 0.0,
+ alpha: 0.08,
+)
\ No newline at end of file
diff --git a/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/spacing b/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/spacing
new file mode 100644
index 0000000..17acdac
--- /dev/null
+++ b/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/spacing
@@ -0,0 +1,12 @@
+(
+ space_none: 0,
+ space_xxxs: 4,
+ space_xxs: 4,
+ space_xs: 8,
+ space_s: 8,
+ space_m: 16,
+ space_l: 24,
+ space_xl: 32,
+ space_xxl: 48,
+ space_xxxl: 64,
+)
\ No newline at end of file
diff --git a/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/success b/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/success
new file mode 100644
index 0000000..e101c3c
--- /dev/null
+++ b/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/success
@@ -0,0 +1,74 @@
+(
+ base: (
+ red: 0.09411765,
+ green: 0.33333334,
+ blue: 0.16078432,
+ alpha: 1.0,
+ ),
+ hover: (
+ red: 0.14944312,
+ green: 0.34322074,
+ blue: 0.22185525,
+ alpha: 1.0,
+ ),
+ pressed: (
+ red: 0.40847942,
+ green: 0.5353426,
+ blue: 0.4960762,
+ alpha: 1.0,
+ ),
+ selected: (
+ red: 0.14944312,
+ green: 0.34322074,
+ blue: 0.22185525,
+ alpha: 1.0,
+ ),
+ selected_text: (
+ red: 0.9058823,
+ green: 0.6117647,
+ blue: 0.99607843,
+ alpha: 1.0,
+ ),
+ focus: (
+ red: 0.9058823,
+ green: 0.6117647,
+ blue: 0.99607843,
+ alpha: 1.0,
+ ),
+ divider: (
+ red: 0.9999203,
+ green: 0.99998146,
+ blue: 1.0,
+ alpha: 1.0,
+ ),
+ on: (
+ red: 0.9999203,
+ green: 0.99998146,
+ blue: 1.0,
+ alpha: 1.0,
+ ),
+ disabled: (
+ red: 0.09411765,
+ green: 0.33333334,
+ blue: 0.16078432,
+ alpha: 1.0,
+ ),
+ on_disabled: (
+ red: 0.547019,
+ green: 0.6666574,
+ blue: 0.5803922,
+ alpha: 1.0,
+ ),
+ border: (
+ red: 0.09411765,
+ green: 0.33333334,
+ blue: 0.16078432,
+ alpha: 1.0,
+ ),
+ disabled_border: (
+ red: 0.09411765,
+ green: 0.33333334,
+ blue: 0.16078432,
+ alpha: 0.5,
+ ),
+)
\ No newline at end of file
diff --git a/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/success_button b/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/success_button
new file mode 100644
index 0000000..8f661e7
--- /dev/null
+++ b/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/success_button
@@ -0,0 +1,74 @@
+(
+ base: (
+ red: 0.09411765,
+ green: 0.33333334,
+ blue: 0.16078432,
+ alpha: 1.0,
+ ),
+ hover: (
+ red: 0.1530087,
+ green: 0.34438127,
+ blue: 0.20634201,
+ alpha: 1.0,
+ ),
+ pressed: (
+ red: 0.41866177,
+ green: 0.53826964,
+ blue: 0.45199502,
+ alpha: 1.0,
+ ),
+ selected: (
+ red: 0.1530087,
+ green: 0.34438127,
+ blue: 0.20634201,
+ alpha: 1.0,
+ ),
+ selected_text: (
+ red: 0.23921569,
+ green: 0.04705882,
+ blue: 0.066666655,
+ alpha: 1.0,
+ ),
+ focus: (
+ red: 0.23921569,
+ green: 0.04705882,
+ blue: 0.066666655,
+ alpha: 1.0,
+ ),
+ divider: (
+ red: 0.8698165,
+ green: 0.8698165,
+ blue: 0.8698163,
+ alpha: 1.0,
+ ),
+ on: (
+ red: 0.99999994,
+ green: 0.99999994,
+ blue: 0.9999997,
+ alpha: 1.0,
+ ),
+ disabled: (
+ red: 0.09411765,
+ green: 0.33333334,
+ blue: 0.16078432,
+ alpha: 1.0,
+ ),
+ on_disabled: (
+ red: 0.99999994,
+ green: 0.99999994,
+ blue: 0.9999997,
+ alpha: 0.5,
+ ),
+ border: (
+ red: 0.09411765,
+ green: 0.33333334,
+ blue: 0.16078432,
+ alpha: 1.0,
+ ),
+ disabled_border: (
+ red: 0.09411765,
+ green: 0.33333334,
+ blue: 0.16078432,
+ alpha: 0.5,
+ ),
+)
\ No newline at end of file
diff --git a/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/text_button b/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/text_button
new file mode 100644
index 0000000..912a415
--- /dev/null
+++ b/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/text_button
@@ -0,0 +1,74 @@
+(
+ base: (
+ red: 0.0,
+ green: 0.0,
+ blue: 0.0,
+ alpha: 0.0,
+ ),
+ hover: (
+ red: 0.37074497,
+ green: 0.38277033,
+ blue: 0.46613896,
+ alpha: 0.2,
+ ),
+ pressed: (
+ red: 0.7228412,
+ green: 0.7373518,
+ blue: 0.8313681,
+ alpha: 0.5,
+ ),
+ selected: (
+ red: 0.37074497,
+ green: 0.38277033,
+ blue: 0.46613896,
+ alpha: 0.2,
+ ),
+ selected_text: (
+ red: 0.9058823,
+ green: 0.6117647,
+ blue: 0.99607843,
+ alpha: 1.0,
+ ),
+ focus: (
+ red: 0.9058823,
+ green: 0.6117647,
+ blue: 0.99607843,
+ alpha: 1.0,
+ ),
+ divider: (
+ red: 0.9058823,
+ green: 0.6117647,
+ blue: 0.99607843,
+ alpha: 0.2,
+ ),
+ on: (
+ red: 0.9058823,
+ green: 0.6117647,
+ blue: 0.99607843,
+ alpha: 1.0,
+ ),
+ disabled: (
+ red: 0.0,
+ green: 0.0,
+ blue: 0.0,
+ alpha: 0.0,
+ ),
+ on_disabled: (
+ red: 0.9058823,
+ green: 0.6117647,
+ blue: 0.99607843,
+ alpha: 0.65,
+ ),
+ border: (
+ red: 0.072988935,
+ green: 0.079405405,
+ blue: 0.14595589,
+ alpha: 1.0,
+ ),
+ disabled_border: (
+ red: 0.072988935,
+ green: 0.079405405,
+ blue: 0.14595589,
+ alpha: 0.5,
+ ),
+)
\ No newline at end of file
diff --git a/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/text_tint b/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/text_tint
new file mode 100644
index 0000000..f0e9e0a
--- /dev/null
+++ b/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/text_tint
@@ -0,0 +1,5 @@
+Some((
+ red: 0.17254902,
+ green: 0.20392157,
+ blue: 0.26666668,
+))
\ No newline at end of file
diff --git a/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/warning b/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/warning
new file mode 100644
index 0000000..2d1af8f
--- /dev/null
+++ b/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/warning
@@ -0,0 +1,74 @@
+(
+ base: (
+ red: 0.3254902,
+ green: 0.28235295,
+ blue: 0.0,
+ alpha: 1.0,
+ ),
+ hover: (
+ red: 0.33454114,
+ green: 0.30243644,
+ blue: 0.093227796,
+ alpha: 1.0,
+ ),
+ pressed: (
+ red: 0.5241657,
+ green: 0.50985235,
+ blue: 0.41568404,
+ alpha: 1.0,
+ ),
+ selected: (
+ red: 0.33454114,
+ green: 0.30243644,
+ blue: 0.093227796,
+ alpha: 1.0,
+ ),
+ selected_text: (
+ red: 0.9058823,
+ green: 0.6117647,
+ blue: 0.99607843,
+ alpha: 1.0,
+ ),
+ focus: (
+ red: 0.9058823,
+ green: 0.6117647,
+ blue: 0.99607843,
+ alpha: 1.0,
+ ),
+ divider: (
+ red: 0.9999203,
+ green: 0.99998146,
+ blue: 1.0,
+ alpha: 1.0,
+ ),
+ on: (
+ red: 0.9999203,
+ green: 0.99998146,
+ blue: 1.0,
+ alpha: 1.0,
+ ),
+ disabled: (
+ red: 0.3254902,
+ green: 0.28235295,
+ blue: 0.0,
+ alpha: 1.0,
+ ),
+ on_disabled: (
+ red: 0.66270524,
+ green: 0.6411672,
+ blue: 0.5,
+ alpha: 1.0,
+ ),
+ border: (
+ red: 0.3254902,
+ green: 0.28235295,
+ blue: 0.0,
+ alpha: 1.0,
+ ),
+ disabled_border: (
+ red: 0.3254902,
+ green: 0.28235295,
+ blue: 0.0,
+ alpha: 0.5,
+ ),
+)
\ No newline at end of file
diff --git a/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/warning_button b/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/warning_button
new file mode 100644
index 0000000..153608d
--- /dev/null
+++ b/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/warning_button
@@ -0,0 +1,74 @@
+(
+ base: (
+ red: 0.3254902,
+ green: 0.28235295,
+ blue: 0.0,
+ alpha: 1.0,
+ ),
+ hover: (
+ red: 0.33454114,
+ green: 0.30243644,
+ blue: 0.093227796,
+ alpha: 1.0,
+ ),
+ pressed: (
+ red: 0.5241657,
+ green: 0.50985235,
+ blue: 0.41568404,
+ alpha: 1.0,
+ ),
+ selected: (
+ red: 0.33454114,
+ green: 0.30243644,
+ blue: 0.093227796,
+ alpha: 1.0,
+ ),
+ selected_text: (
+ red: 0.9058823,
+ green: 0.6117647,
+ blue: 0.99607843,
+ alpha: 1.0,
+ ),
+ focus: (
+ red: 0.9058823,
+ green: 0.6117647,
+ blue: 0.99607843,
+ alpha: 1.0,
+ ),
+ divider: (
+ red: 0.0,
+ green: 0.0,
+ blue: 0.000000000000000000000000000000000000000000036,
+ alpha: 1.0,
+ ),
+ on: (
+ red: 0.9999203,
+ green: 0.99998146,
+ blue: 1.0,
+ alpha: 1.0,
+ ),
+ disabled: (
+ red: 0.3254902,
+ green: 0.28235295,
+ blue: 0.0,
+ alpha: 1.0,
+ ),
+ on_disabled: (
+ red: 0.9999203,
+ green: 0.99998146,
+ blue: 1.0,
+ alpha: 0.5,
+ ),
+ border: (
+ red: 0.3254902,
+ green: 0.28235295,
+ blue: 0.0,
+ alpha: 1.0,
+ ),
+ disabled_border: (
+ red: 0.3254902,
+ green: 0.28235295,
+ blue: 0.0,
+ alpha: 0.5,
+ ),
+)
\ No newline at end of file
diff --git a/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/window_hint b/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/window_hint
new file mode 100644
index 0000000..4af1832
--- /dev/null
+++ b/INSTALL/themes/cosmic/com.system76.CosmicTheme.Light/v1/window_hint
@@ -0,0 +1 @@
+None
\ No newline at end of file
diff --git a/INSTALL/themes/violet-chaton-gtk.css b/INSTALL/themes/violet-chaton-gtk.css
index 5c460ab..e68b24f 100644
--- a/INSTALL/themes/violet-chaton-gtk.css
+++ b/INSTALL/themes/violet-chaton-gtk.css
@@ -1,247 +1,122 @@
-/* ── violet-chaton GTK3 theme — Nemo & GTK apps ───────────────────────────────
+/* ── violet-chaton GTK theme (adw-gtk3-dark compatible) ────────────────────
*
- * Couleurs extraites du thème COSMIC violet-chaton :
- * bg #341C4A background.base
- * surface #493161 background.component.base
- * hover #5B4671 background.component.hover
- * accent #E79CFE accent.base
- * text #FCFCF6 background.on
- * muted #7F849C neutral_7
- * border #5C496C background.divider
- * sidebar #2B1540 (bg légèrement plus sombre)
+ * Contenu identique au dark.css généré par COSMIC pour le thème violet-chaton.
+ * adw-gtk3-dark et libadwaita lisent ces variables @define-color.
+ * Sur le PC principal, COSMIC gère ce fichier via symlink — ce fichier
+ * sert de fallback lors de la première installation.
* ─────────────────────────────────────────────────────────────────────────── */
-@define-color theme_bg_color #341C4A;
-@define-color theme_fg_color #FCFCF6;
-@define-color theme_base_color #493161;
-@define-color theme_selected_bg_color #E79CFE;
-@define-color theme_selected_fg_color #341C4A;
-@define-color theme_text_color #FCFCF6;
-@define-color borders #5C496C;
+@define-color window_bg_color rgba(52, 28, 74, 1.00);
+@define-color window_fg_color rgba(252, 252, 246, 1.00);
-/* ── Fenêtre principale ────────────────────────────────────────────────────── */
-window, .background {
- background-color: #341C4A;
- color: #FCFCF6;
-}
+@define-color view_bg_color rgba(56, 35, 75, 1.00);
+@define-color view_fg_color rgba(193, 193, 187, 1.00);
-/* ── Barre de titre / headerbar ───────────────────────────────────────────── */
-headerbar, .titlebar {
- background-color: #493161;
- color: #FCFCF6;
- border-bottom: 1px solid #5C496C;
-}
+@define-color headerbar_bg_color rgba(52, 28, 74, 1.00);
+@define-color headerbar_fg_color rgba(252, 252, 246, 1.00);
+@define-color headerbar_border_color_color rgba(92, 73, 108, 1.00);
+@define-color headerbar_backdrop_color rgba(52, 28, 74, 1.00);
-headerbar button, .titlebar button {
- background-color: transparent;
- color: #FCFCF6;
- border: none;
- border-radius: 6px;
-}
+@define-color sidebar_bg_color rgba(56, 35, 75, 1.00);
+@define-color sidebar_fg_color rgba(193, 193, 187, 1.00);
+@define-color sidebar_shade_color rgba(0, 0, 0, 0.08);
+@define-color sidebar_backdrop_color rgba(72, 53, 89, 1.00);
-headerbar button:hover, .titlebar button:hover {
- background-color: #5B4671;
-}
+@define-color secondary_sidebar_bg_color rgba(69, 71, 90, 1.00);
+@define-color secondary_sidebar_fg_color rgba(225, 225, 219, 1.00);
+@define-color secondary_sidebar_shade_color rgba(0, 0, 0, 0.08);
+@define-color secondary_sidebar_backdrop_color rgba(84, 86, 103, 1.00);
-headerbar button:active, .titlebar button:active {
- background-color: #E79CFE;
- color: #341C4A;
-}
+@define-color card_bg_color rgba(73, 49, 97, 1.00);
+@define-color card_fg_color rgba(212, 212, 206, 1.00);
-/* ── Sidebar Nemo (paneau des emplacements) ───────────────────────────────── */
-.sidebar, placessidebar {
- background-color: #2B1540;
- color: #FCFCF6;
- border-right: 1px solid #5C496C;
-}
+@define-color thumbnail_bg_color rgba(73, 49, 97, 1.00);
+@define-color thumbnail_fg_color rgba(212, 212, 206, 1.00);
-.sidebar row, placessidebar row {
- border-radius: 6px;
- padding: 2px 4px;
-}
+@define-color dialog_bg_color rgba(56, 35, 75, 1.00);
+@define-color dialog_fg_color rgba(193, 193, 187, 1.00);
-.sidebar row:hover, placessidebar row:hover {
- background-color: #5B4671;
-}
+@define-color popover_bg_color rgba(73, 49, 97, 1.00);
+@define-color popover_fg_color rgba(212, 212, 206, 1.00);
-.sidebar row:selected, placessidebar row:selected {
- background-color: #E79CFE;
- color: #341C4A;
-}
+@define-color shade_color rgba(0, 0, 0, 0.32);
+@define-color scrollbar_outline_color rgba(52, 28, 74, 0.50);
-.sidebar .sidebar-section-header, placessidebar .sidebar-section-header {
- color: #7F849C;
- font-size: smaller;
-}
+@define-color accent_color rgba(231, 156, 254, 1.00);
+@define-color accent_bg_color rgba(231, 156, 254, 1.00);
+@define-color accent_fg_color rgba(0, 0, 0, 1.00);
-/* ── Vue fichiers (icônes + liste) ───────────────────────────────────────── */
-.view, iconview, treeview {
- background-color: #341C4A;
- color: #FCFCF6;
-}
+@define-color destructive_color rgba(243, 139, 168, 1.00);
+@define-color destructive_bg_color rgba(243, 139, 168, 1.00);
+@define-color destructive_fg_color rgba(0, 0, 0, 1.00);
-.view:selected, iconview:selected,
-treeview:selected, .view:focus:selected {
- background-color: #E79CFE;
- color: #341C4A;
-}
+@define-color warning_color rgba(249, 226, 175, 1.00);
+@define-color warning_bg_color rgba(249, 226, 175, 1.00);
+@define-color warning_fg_color rgba(0, 0, 0, 1.00);
-/* En-têtes de colonnes (vue liste) */
-treeview header button {
- background-color: #493161;
- color: #FCFCF6;
- border: none;
- border-right: 1px solid #5C496C;
- border-bottom: 1px solid #5C496C;
-}
+@define-color success_color rgba(166, 227, 161, 1.00);
+@define-color success_bg_color rgba(166, 227, 161, 1.00);
+@define-color success_fg_color rgba(0, 0, 0, 1.00);
-treeview header button:hover {
- background-color: #5B4671;
-}
+@define-color accent_color rgba(231, 156, 254, 1.00);
+@define-color accent_bg_color rgba(231, 156, 254, 1.00);
+@define-color accent_fg_color rgba(0, 0, 0, 1.00);
-/* ── Barre d'outils / pathbar ─────────────────────────────────────────────── */
-toolbar, .path-bar {
- background-color: #493161;
- border-bottom: 1px solid #5C496C;
-}
+@define-color error_color rgba(243, 139, 168, 1.00);
+@define-color error_bg_color rgba(243, 139, 168, 1.00);
+@define-color error_fg_color rgba(0, 0, 0, 1.00);
-.path-bar button {
- background-color: transparent;
- color: #FCFCF6;
- border: none;
- border-radius: 6px;
-}
+@define-color blue_1 rgba(151, 195, 255, 1.00);
+@define-color blue_2 rgba(144, 187, 255, 1.00);
+@define-color blue_3 rgba(137, 180, 250, 1.00);
+@define-color blue_4 rgba(114, 156, 224, 1.00);
+@define-color blue_5 rgba(91, 132, 199, 1.00);
-.path-bar button:hover {
- background-color: #5B4671;
-}
+@define-color green_1 rgba(175, 236, 170, 1.00);
+@define-color green_2 rgba(171, 232, 165, 1.00);
+@define-color green_3 rgba(166, 227, 161, 1.00);
+@define-color green_4 rgba(139, 199, 134, 1.00);
+@define-color green_5 rgba(113, 171, 108, 1.00);
-.path-bar button:checked {
- background-color: #5B4671;
- color: #E79CFE;
-}
+@define-color yellow_1 rgba(254, 231, 180, 1.00);
+@define-color yellow_2 rgba(252, 229, 178, 1.00);
+@define-color yellow_3 rgba(249, 226, 175, 1.00);
+@define-color yellow_4 rgba(219, 196, 146, 1.00);
+@define-color yellow_5 rgba(189, 167, 118, 1.00);
-/* ── Barre de recherche / entrée texte ────────────────────────────────────── */
-entry {
- background-color: #5B4671;
- color: #FCFCF6;
- border: 1px solid #5C496C;
- border-radius: 6px;
- padding: 4px 8px;
-}
+@define-color red_1 rgba(255, 154, 183, 1.00);
+@define-color red_2 rgba(252, 147, 176, 1.00);
+@define-color red_3 rgba(243, 139, 168, 1.00);
+@define-color red_4 rgba(217, 116, 145, 1.00);
+@define-color red_5 rgba(191, 93, 122, 1.00);
-entry:focus {
- border-color: #E79CFE;
- box-shadow: 0 0 0 2px alpha(#E79CFE, 0.3);
-}
+@define-color orange_1 rgba(255, 190, 146, 1.00);
+@define-color orange_2 rgba(255, 185, 140, 1.00);
+@define-color orange_3 rgba(250, 179, 135, 1.00);
+@define-color orange_4 rgba(222, 153, 110, 1.00);
+@define-color orange_5 rgba(195, 128, 85, 1.00);
-entry placeholder {
- color: #7F849C;
-}
+@define-color purple_1 rgba(192, 202, 255, 1.00);
+@define-color purple_2 rgba(186, 196, 255, 1.00);
+@define-color purple_3 rgba(180, 190, 254, 1.00);
+@define-color purple_4 rgba(155, 164, 226, 1.00);
+@define-color purple_5 rgba(130, 139, 200, 1.00);
+@define-color light_0 rgba(0, 0, 0, 1.00);
+@define-color light_1 rgba(3, 3, 16, 1.00);
+@define-color light_2 rgba(24, 25, 43, 1.00);
+@define-color light_3 rgba(50, 53, 72, 1.00);
+@define-color light_4 rgba(79, 82, 103, 1.00);
+@define-color dark_0 rgba(110, 114, 135, 1.00);
+@define-color dark_1 rgba(143, 147, 169, 1.00);
+@define-color dark_2 rgba(177, 181, 205, 1.00);
+@define-color dark_3 rgba(213, 217, 241, 1.00);
+@define-color dark_4 rgba(255, 255, 255, 1.00);
-/* ── Scrollbar ────────────────────────────────────────────────────────────── */
-scrollbar {
- background-color: transparent;
-}
-
-scrollbar slider {
- background-color: #5C496C;
- border-radius: 10px;
- min-width: 6px;
- min-height: 6px;
-}
-
-scrollbar slider:hover {
- background-color: #E79CFE;
-}
-
-/* ── Menu contextuel ──────────────────────────────────────────────────────── */
-menu, .context-menu, .popup {
- background-color: #493161;
- color: #FCFCF6;
- border: 1px solid #5C496C;
- border-radius: 8px;
- padding: 4px;
-}
-
-menuitem {
- border-radius: 6px;
- padding: 4px 8px;
-}
-
-menuitem:hover {
- background-color: #E79CFE;
- color: #341C4A;
-}
-
-menuitem accelerator {
- color: #7F849C;
-}
-
-separator, menuitem separator {
- background-color: #5C496C;
- min-height: 1px;
-}
-
-/* ── Barre de statut ──────────────────────────────────────────────────────── */
-.statusbar, statusbar {
- background-color: #493161;
- color: #7F849C;
- border-top: 1px solid #5C496C;
- font-size: smaller;
-}
-
-/* ── Boutons génériques ───────────────────────────────────────────────────── */
-button {
- background-color: #5B4671;
- color: #FCFCF6;
- border: 1px solid #5C496C;
- border-radius: 6px;
- padding: 4px 12px;
-}
-
-button:hover {
- background-color: #E79CFE;
- color: #341C4A;
- border-color: #E79CFE;
-}
-
-button.suggested-action {
- background-color: #E79CFE;
- color: #341C4A;
- border-color: #E79CFE;
-}
-
-button.destructive-action {
- background-color: #F38BA8;
- color: #341C4A;
-}
-
-/* ── Notebooks / onglets ─────────────────────────────────────────────────── */
-notebook tab {
- background-color: #493161;
- color: #7F849C;
- border-radius: 6px 6px 0 0;
- padding: 4px 12px;
-}
-
-notebook tab:checked {
- background-color: #5B4671;
- color: #FCFCF6;
-}
-
-/* ── Popover ─────────────────────────────────────────────────────────────── */
-popover {
- background-color: #493161;
- color: #FCFCF6;
- border: 1px solid #5C496C;
- border-radius: 8px;
-}
-
-/* ── Tooltip ─────────────────────────────────────────────────────────────── */
-tooltip {
- background-color: #5B4671;
- color: #FCFCF6;
- border-radius: 6px;
- padding: 4px 8px;
-}
+/* ── Variables GTK3 classiques (compat apps legacy) ─────────────────────── */
+@define-color theme_bg_color rgba(52, 28, 74, 1.00);
+@define-color theme_fg_color rgba(252, 252, 246, 1.00);
+@define-color theme_base_color rgba(73, 49, 97, 1.00);
+@define-color theme_selected_bg_color rgba(231, 156, 254, 1.00);
+@define-color theme_selected_fg_color rgba(52, 28, 74, 1.00);
+@define-color theme_text_color rgba(252, 252, 246, 1.00);
+@define-color borders rgba(92, 73, 108, 1.00);
diff --git a/INSTALL/themes/violet-chaton-rofi.rasi b/INSTALL/themes/violet-chaton-rofi.rasi
new file mode 100644
index 0000000..0c63ae0
--- /dev/null
+++ b/INSTALL/themes/violet-chaton-rofi.rasi
@@ -0,0 +1,137 @@
+/* ── violet-chaton rofi theme ─────────────────────────────────────────────── */
+
+* {
+ bg0: #261537;
+ bg1: #341c4a;
+ surface: #493161;
+ pink: #ff79c6;
+ purple: #e79cfe;
+ cyan: #8be9fd;
+ text: #f8f8f2;
+ muted: #6c7086;
+ overlay: #9399b2;
+
+ background-color: transparent;
+ text-color: @text;
+}
+
+/* ── Fenêtre — positionnée sous les pills ─────────────────────────────────── */
+
+window {
+ background-color: rgba(38, 21, 55, 0.94);
+ border: 2px;
+ border-color: rgba(255, 121, 198, 0.38);
+ border-radius: 14px;
+ width: 500px;
+ padding: 0px;
+}
+
+/* ── Layout — résultats en haut, recherche en bas ─────────────────────────── */
+
+mainbox {
+ background-color: transparent;
+ padding: 10px;
+ spacing: 0;
+ children: [ listview, inputbar ];
+}
+
+/* ── Liste des résultats ──────────────────────────────────────────────────── */
+
+listview {
+ background-color: transparent;
+ padding: 4px 0 8px 0;
+ spacing: 2px;
+ lines: 9;
+ columns: 1;
+ scrollbar: false;
+ dynamic: false;
+}
+
+element {
+ background-color: transparent;
+ border-radius: 8px;
+ padding: 7px 10px;
+ spacing: 10px;
+ orientation: horizontal;
+}
+
+element selected {
+ background-color: rgba(255, 121, 198, 0.16);
+ border: 1px;
+ border-color: rgba(255, 121, 198, 0.32);
+}
+
+element hover {
+ background-color: rgba(255, 121, 198, 0.16);
+ border: 1px;
+ border-color: rgba(255, 121, 198, 0.32);
+}
+
+element-icon {
+ size: 22px;
+ background-color: transparent;
+}
+
+element-text {
+ background-color: transparent;
+ text-color: @text;
+ vertical-align: 0.5;
+ highlight: bold;
+}
+
+element-text selected {
+ text-color: @pink;
+}
+
+element-text hover {
+ text-color: @pink;
+}
+
+/* ── Séparateur visuel avant la recherche ─────────────────────────────────── */
+
+inputbar {
+ background-color: rgba(52, 28, 74, 0.75);
+ border-radius: 0 0 12px 12px;
+ border: 1px;
+ border-color: rgba(92, 73, 108, 0.50);
+ padding: 9px 14px;
+ spacing: 8px;
+ children: [ prompt, entry ];
+}
+
+prompt {
+ background-color: transparent;
+ text-color: @pink;
+ font: "JetBrainsMono Nerd Font Bold 14";
+ vertical-align: 0.5;
+}
+
+entry {
+ background-color: transparent;
+ text-color: @text;
+ placeholder: "Rechercher une application...";
+ placeholder-color: @muted;
+ vertical-align: 0.5;
+}
+
+/* ── Scrollbar ────────────────────────────────────────────────────────────── */
+
+scrollbar {
+ background-color: rgba(92, 73, 108, 0.30);
+ handle-color: rgba(255, 121, 198, 0.40);
+ handle-width: 4px;
+ border-radius: 2px;
+ padding: 0;
+}
+
+/* ── Messages ─────────────────────────────────────────────────────────────── */
+
+message {
+ background-color: transparent;
+ padding: 4px 8px;
+}
+
+textbox {
+ text-color: @overlay;
+ background-color: transparent;
+}
diff --git a/INSTALL/themes/violet-chaton-waybar.css b/INSTALL/themes/violet-chaton-waybar.css
new file mode 100644
index 0000000..1d121f5
--- /dev/null
+++ b/INSTALL/themes/violet-chaton-waybar.css
@@ -0,0 +1,419 @@
+/* ── violet-chaton Waybar — island floating 3 pills glassmorphism ───────────
+ *
+ * Palette :
+ * bg-medium rgba(52, 28, 74, 0.88) #341c4a
+ * surface rgba(73, 49, 97, 0.95) #493161
+ * pink #ff79c6 accent primaire
+ * purple #e79cfe accent secondaire
+ * cyan #8be9fd info
+ * text #f8f8f2 texte principal
+ * muted #6c7086 texte secondaire
+ * warning #f9e2af
+ * danger #f38ba8
+ * success #a6e3a1
+ * border #5C496C
+ *
+ * ─────────────────────────────────────────────────────────────────────────── */
+
+/* ── Reset global ─────────────────────────────────────────────────────────── */
+
+* {
+ font-family: "JetBrainsMono Nerd Font", "JetBrains Mono", monospace;
+ font-size: 13px;
+ font-weight: bold;
+ min-height: 0;
+ border: none;
+ border-radius: 0;
+ transition: all 0.2s ease;
+}
+
+/* ── Fenêtre — fond transparent entre les pills ───────────────────────────── */
+
+window#waybar {
+ background: transparent;
+ color: #f8f8f2;
+}
+
+/* ── Pills (glassmorphism) ────────────────────────────────────────────────── */
+
+.modules-left,
+.modules-center,
+.modules-right {
+ background: rgba(52, 28, 74, 0.88);
+ border-radius: 14px;
+ border: 3px solid rgba(255, 121, 198, 0.78);
+ margin: 8px 2px 8px 2px;
+}
+
+/* Hover pill glow */
+.modules-left:hover,
+.modules-center:hover,
+.modules-right:hover {
+ border-color: #ff79c6;
+ box-shadow:
+ 0 4px 28px rgba(231, 156, 254, 0.18),
+ 0 1px 0 rgba(255, 255, 255, 0.06) inset;
+}
+
+/* ── Animations ───────────────────────────────────────────────────────────── */
+
+@keyframes pulse-critical {
+ 0% { color: #f38ba8; }
+ 50% { color: rgba(243, 139, 168, 0.35); }
+ 100% { color: #f38ba8; }
+}
+
+@keyframes pulse-warning {
+ 0% { color: #f9e2af; }
+ 50% { color: rgba(249, 226, 175, 0.50); }
+ 100% { color: #f9e2af; }
+}
+
+@keyframes glow-pink {
+ 0% { box-shadow: 0 0 6px rgba(255, 121, 198, 0.4); }
+ 50% { box-shadow: 0 0 14px rgba(255, 121, 198, 0.8); }
+ 100% { box-shadow: 0 0 6px rgba(255, 121, 198, 0.4); }
+}
+
+/* ── Launcher ─────────────────────────────────────────────────────────────── */
+
+#custom-launcher {
+ color: #ff79c6;
+ font-size: 19px;
+ padding: 0 14px 0 18px;
+ border-radius: 14px 0 0 14px;
+}
+
+#custom-launcher:hover {
+ color: #e79cfe;
+ animation: glow-pink 1.4s ease-in-out infinite;
+}
+
+/* ── Séparateur ───────────────────────────────────────────────────────────── */
+
+#custom-sep {
+ color: rgba(248, 248, 242, 0.12);
+ font-size: 11px;
+ padding: 0 4px;
+ font-weight: normal;
+}
+
+/* ── Base commune modules ─────────────────────────────────────────────────── */
+
+#cpu,
+#temperature,
+#custom-gpu,
+#memory,
+#disk,
+#custom-network,
+#clock,
+#custom-date,
+#mpris,
+#custom-cava,
+#wireplumber,
+#backlight,
+#bluetooth,
+#idle-inhibitor,
+#battery,
+#custom-power-profile,
+#custom-uptime,
+#tray {
+ padding: 0 8px;
+ color: #f8f8f2;
+ background-color: transparent;
+}
+
+/* ── CPU ──────────────────────────────────────────────────────────────────── */
+
+#cpu {
+ color: #8be9fd;
+}
+
+#cpu.warning {
+ color: #f9e2af;
+}
+
+#cpu.critical {
+ color: #f38ba8;
+ animation: pulse-critical 0.8s linear infinite;
+}
+
+/* ── Température ──────────────────────────────────────────────────────────── */
+
+#temperature {
+ color: rgba(139, 233, 253, 0.60);
+ font-size: 11px;
+ font-weight: normal;
+ padding-left: 2px;
+ padding-right: 10px;
+}
+
+#temperature.critical {
+ color: #f38ba8;
+ font-weight: bold;
+ animation: pulse-critical 0.8s linear infinite;
+}
+
+/* ── GPU ──────────────────────────────────────────────────────────────────── */
+
+#custom-gpu {
+ color: #ff79c6;
+}
+
+#custom-gpu.warning {
+ color: #f9e2af;
+}
+
+#custom-gpu.critical {
+ color: #f38ba8;
+ animation: pulse-critical 0.8s linear infinite;
+}
+
+/* ── RAM ──────────────────────────────────────────────────────────────────── */
+
+#memory {
+ color: #ff79c6;
+}
+
+#memory.warning {
+ color: #f9e2af;
+}
+
+#memory.critical {
+ color: #f38ba8;
+ animation: pulse-critical 0.8s linear infinite;
+}
+
+/* ── Disque ───────────────────────────────────────────────────────────────── */
+
+#disk {
+ color: rgba(255, 121, 198, 0.70);
+ font-size: 11px;
+ font-weight: normal;
+}
+
+/* ── Réseau ───────────────────────────────────────────────────────────────── */
+
+#custom-network {
+ color: #8be9fd;
+ font-size: 11px;
+ font-weight: normal;
+ padding-right: 14px;
+}
+
+#custom-network.disconnected {
+ color: #f38ba8;
+}
+
+#custom-network.eth {
+ color: #8be9fd;
+}
+
+#custom-network.wifi {
+ color: rgba(139, 233, 253, 0.80);
+}
+
+/* ── CAVA ─────────────────────────────────────────────────────────────────── */
+
+#custom-cava {
+ color: rgba(231, 156, 254, 0.65);
+ font-size: 11px;
+ letter-spacing: 1px;
+ padding: 0 10px;
+ font-weight: normal;
+}
+
+/* ── Horloge ──────────────────────────────────────────────────────────────── */
+
+#clock {
+ color: #ff79c6;
+ font-weight: 900;
+ font-size: 14px;
+ letter-spacing: 0.04em;
+ padding: 0 10px;
+}
+
+#clock:hover {
+ color: #e79cfe;
+}
+
+/* ── Date ─────────────────────────────────────────────────────────────────── */
+
+#custom-date {
+ color: #8be9fd;
+ font-size: 12px;
+ font-weight: normal;
+ padding: 0 10px 0 2px;
+ letter-spacing: 0.03em;
+}
+
+/* ── MPRIS ────────────────────────────────────────────────────────────────── */
+
+#mpris {
+ color: #e79cfe;
+ font-size: 12px;
+ font-weight: normal;
+ padding: 0 10px;
+}
+
+#mpris.paused {
+ color: rgba(231, 156, 254, 0.50);
+ font-style: italic;
+}
+
+/* ── Volume (wireplumber) ─────────────────────────────────────────────────── */
+
+#wireplumber {
+ color: #ff79c6;
+}
+
+#wireplumber.muted {
+ color: rgba(255, 121, 198, 0.30);
+}
+
+/* ── Luminosité ───────────────────────────────────────────────────────────── */
+
+#backlight {
+ color: #8be9fd;
+}
+
+/* ── Bluetooth ────────────────────────────────────────────────────────────── */
+
+#bluetooth {
+ color: rgba(139, 233, 253, 0.45);
+ font-size: 15px;
+}
+
+#bluetooth.connected {
+ color: #e79cfe;
+}
+
+#bluetooth.disabled {
+ color: rgba(108, 112, 134, 0.50);
+}
+
+/* ── Idle inhibitor ───────────────────────────────────────────────────────── */
+
+#idle-inhibitor {
+ color: rgba(248, 248, 242, 0.35);
+ font-size: 14px;
+}
+
+#idle-inhibitor.activated {
+ color: #f9e2af;
+ animation: pulse-warning 1.6s ease-in-out infinite;
+}
+
+/* ── Batterie ─────────────────────────────────────────────────────────────── */
+
+#battery {
+ color: #ff79c6;
+}
+
+#battery.charging,
+#battery.plugged {
+ color: #a6e3a1;
+}
+
+#battery.full {
+ color: rgba(166, 227, 161, 0.65);
+}
+
+#battery.warning:not(.charging):not(.plugged) {
+ color: #f9e2af;
+}
+
+#battery.critical:not(.charging):not(.plugged) {
+ color: #f38ba8;
+ animation: pulse-critical 0.6s linear infinite;
+}
+
+/* ── Profil énergie ───────────────────────────────────────────────────────── */
+
+#custom-power-profile {
+ color: #8be9fd;
+ font-size: 15px;
+ padding: 0 6px;
+}
+
+#custom-power-profile.performance {
+ color: #f38ba8;
+}
+
+#custom-power-profile.balanced {
+ color: #8be9fd;
+}
+
+#custom-power-profile.low-power {
+ color: #a6e3a1;
+}
+
+/* ── Uptime ───────────────────────────────────────────────────────────────── */
+
+#custom-uptime {
+ color: rgba(139, 233, 253, 0.45);
+ font-size: 11px;
+ font-weight: normal;
+}
+
+/* ── Tray ─────────────────────────────────────────────────────────────────── */
+
+#tray {
+ padding: 0 8px;
+}
+
+/* ── Power ────────────────────────────────────────────────────────────────── */
+
+#custom-power {
+ color: #f38ba8;
+ font-size: 15px;
+ padding: 0 14px 0 8px;
+ border-radius: 0 14px 14px 0;
+}
+
+#custom-power:hover {
+ color: #ff79c6;
+}
+
+#tray > .passive {
+ -gtk-icon-effect: dim;
+}
+
+#tray > .needs-attention {
+ -gtk-icon-effect: highlight;
+ background-color: rgba(255, 121, 198, 0.12);
+ border-radius: 6px;
+}
+
+/* ── Tooltip ──────────────────────────────────────────────────────────────── */
+
+tooltip {
+ background-color: rgba(38, 21, 55, 0.96);
+ border: 1px solid rgba(255, 121, 198, 0.30);
+ border-radius: 10px;
+ color: #f8f8f2;
+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.40);
+}
+
+tooltip label {
+ color: #f8f8f2;
+ padding: 3px;
+}
+
+/* ── Hover global ─────────────────────────────────────────────────────────── */
+
+#cpu:hover,
+#memory:hover,
+#disk:hover,
+#custom-network:hover,
+#wireplumber:hover,
+#backlight:hover,
+#battery:hover,
+#custom-power-profile:hover,
+#custom-uptime:hover {
+ color: #e79cfe;
+}
+
+#bluetooth:hover {
+ color: #e79cfe;
+}
diff --git a/INSTALL/themes/violet-chaton-wofi-power.css b/INSTALL/themes/violet-chaton-wofi-power.css
new file mode 100644
index 0000000..2f7fa87
--- /dev/null
+++ b/INSTALL/themes/violet-chaton-wofi-power.css
@@ -0,0 +1,54 @@
+/* ── violet-chaton wofi — power menu (sans barre de recherche) ─────────────── */
+
+window {
+ background-color: rgba(52, 28, 74, 0.88);
+ border: 2px solid rgba(255, 121, 198, 0.28);
+ border-radius: 14px;
+ font-family: "JetBrainsMono Nerd Font";
+ font-size: 13px;
+ font-weight: bold;
+}
+
+/* Cacher complètement la barre de recherche */
+#input {
+ min-height: 0;
+ min-width: 0;
+ padding: 0;
+ margin: 0;
+ border: 0;
+ opacity: 0;
+}
+
+#outer-box {
+ padding: 0;
+ border-radius: 14px;
+}
+
+#scroll {
+ margin: 6px 0;
+}
+
+#inner-box {
+ padding: 4px 6px;
+}
+
+#entry {
+ border-radius: 8px;
+ padding: 9px 14px;
+ margin: 1px 0;
+ border: 1px solid transparent;
+}
+
+#entry:selected {
+ background-color: rgba(243, 139, 168, 0.16);
+ border-color: rgba(243, 139, 168, 0.35);
+}
+
+#text {
+ color: #f8f8f2;
+ font-family: "JetBrainsMono Nerd Font";
+}
+
+#text:selected {
+ color: #f38ba8;
+}
diff --git a/INSTALL/themes/violet-chaton-wofi.css b/INSTALL/themes/violet-chaton-wofi.css
new file mode 100644
index 0000000..68f198a
--- /dev/null
+++ b/INSTALL/themes/violet-chaton-wofi.css
@@ -0,0 +1,64 @@
+/* ── violet-chaton wofi theme ─────────────────────────────────────────────── */
+
+window {
+ background-color: rgba(52, 28, 74, 0.88);
+ border: 2px solid rgba(255, 121, 198, 0.28);
+ border-radius: 14px;
+ font-family: "JetBrainsMono Nerd Font";
+ font-size: 13px;
+ font-weight: bold;
+}
+
+/* ── Barre de recherche ──────────────────────────────────────────────────── */
+
+#input {
+ all: unset;
+ background-color: rgba(38, 21, 55, 0.60);
+ color: #f8f8f2;
+ border-bottom: 1px solid rgba(92, 73, 108, 0.50);
+ border-radius: 12px 12px 0 0;
+ padding: 10px 14px;
+ margin: 0;
+ font-family: "JetBrainsMono Nerd Font";
+ font-size: 13px;
+ font-weight: bold;
+ caret-color: #ff79c6;
+}
+
+/* ── Conteneurs ──────────────────────────────────────────────────────────── */
+
+#outer-box {
+ padding: 0;
+ border-radius: 14px;
+}
+
+#scroll {
+ margin: 4px 0;
+}
+
+#inner-box {
+ padding: 4px 6px;
+}
+
+/* ── Entrées ─────────────────────────────────────────────────────────────── */
+
+#entry {
+ border-radius: 8px;
+ padding: 7px 10px;
+ margin: 1px 0;
+ border: 1px solid transparent;
+}
+
+#entry:selected {
+ background-color: rgba(255, 121, 198, 0.16);
+ border-color: rgba(255, 121, 198, 0.32);
+}
+
+#text {
+ color: #f8f8f2;
+ font-family: "JetBrainsMono Nerd Font";
+}
+
+#text:selected {
+ color: #ff79c6;
+}
diff --git a/README.md b/README.md
index f43071f..ab89905 100644
--- a/README.md
+++ b/README.md
@@ -63,6 +63,15 @@ Installe les outils via le gestionnaire de paquets système :
| `w3m` | Navigateur web en mode texte dans le terminal |
| `jp2a` | Conversion d'images JPEG/PNG en ASCII art |
| `qalc` | Calculatrice CLI — unités, conversions, expressions complexes |
+| `waybar` | Barre de statut Wayland 3-pills glassmorphism |
+| `wob` | Overlay volume/luminosité animé |
+| `wofi` | Launcher d'applications et menu power |
+| `brightnessctl` | Contrôle de la luminosité rétroéclairage |
+| `playerctl` | Contrôle MPRIS (lecture/pause, titre en cours) |
+| `wireplumber` | Gestionnaire audio PipeWire (`wpctl`) |
+| `python3-gi` | Bindings Python GTK3 (popups volume/luminosité) |
+| `gir1.2-gtk-3.0` | Introspection GTK3 pour Python |
+| `gir1.2-gtklayershell-0.1` | Layer-shell Wayland pour popups GTK flottants |
Définit aussi **zsh comme shell par défaut** via `chsh`.
@@ -139,10 +148,31 @@ Le chemin exact est affiché à la fin du script si des fichiers ont été sauve
**COSMIC Desktop (entièrement automatique) :**
- `~/.config/cosmic/com.system76.CosmicTheme.Dark/v1/` — palette violet-chaton complète
+- `~/.config/cosmic/com.system76.CosmicTheme.Light/v1/` — palette violet-chaton (mode clair)
- `~/.config/cosmic/com.system76.CosmicTheme.Mode/v1/is_dark` — mode sombre activé
- `~/.config/cosmic/com.system76.CosmicTerm/v1/` — police JetBrains Mono, couleurs, profil
- `~/.config/cosmic/com.system76.CosmicTk/v1/` — icônes candy-icons, polices UI 0xProto
+**Waybar — island floating 3 pills :**
+- `~/.config/waybar/config` — modules left/center/right
+- `~/.config/waybar/style.css` — glassmorphism, bordures roses, animations
+- `~/.config/waybar/cava-waybar.cfg` — config CAVA dédié waybar
+- `~/.config/waybar/scripts/` — tous les scripts (gpu, network, power-profile, cava, wob, popups GTK)
+- `~/.config/autostart/waybar.desktop` — démarrage automatique avec COSMIC
+- `~/.config/autostart/wob.desktop` — démarrage automatique de l'overlay wob
+
+**Wofi — launcher + menu power :**
+- `~/.config/wofi/config` — configuration wofi
+- `~/.config/wofi/style.css` — thème violet-chaton (launcher apps)
+- `~/.config/wofi/power-style.css` — thème violet-chaton (menu power)
+
+**wob — overlay volume/luminosité :**
+- `~/.config/wob.ini` — couleurs violet-chaton, position bas de l'écran
+
+**Système (avec sudo) :**
+- `/etc/sudoers.d/waybar-power-profile` — changement de profil énergie sans mot de passe
+- `/etc/udev/rules.d/90-platform-profile.rules` — permissions groupe `video` sur platform_profile
+
**Vivaldi (avec pause de sécurité) :**
- Si Vivaldi n'a pas encore été lancé, le script s'arrête et demande de le démarrer une fois
- Le thème **Rice Violet-Chaton** est ensuite injecté directement dans `~/.config/vivaldi/Default/Preferences`
@@ -226,6 +256,28 @@ gtk-update-icon-cache ~/.local/share/icons/candy-icons-master
gsettings set org.gnome.desktop.interface icon-theme 'candy-icons-master'
```
+### Waybar ne démarre pas
+
+```bash
+waybar & # tester manuellement, lire les erreurs
+pkill -SIGUSR2 waybar # recharger la config à chaud
+```
+
+### Popups volume/luminosité ne s'ouvrent pas
+
+Vérifier que les dépendances Python sont installées :
+```bash
+python3 -c "import gi; gi.require_version('GtkLayerShell', '0.1'); print('OK')"
+```
+
+### Profil énergie ne change pas au clic
+
+Vérifier que la règle sudoers et les permissions udev sont en place :
+```bash
+ls -la /sys/firmware/acpi/platform_profile # doit être g+w groupe video
+cat /etc/sudoers.d/waybar-power-profile
+```
+
---
## Raccourcis configurés
@@ -283,7 +335,18 @@ INSTALL/
│ ├── atuin.toml
│ ├── lazygit.yml
│ ├── yazi.toml
-│ └── glow.yml
+│ ├── glow.yml
+│ ├── autostart/
+│ │ ├── waybar.desktop démarrage automatique waybar
+│ │ └── wob.desktop démarrage automatique wob
+│ ├── waybar/
+│ │ ├── config modules 3-pills
+│ │ ├── cava-waybar.cfg config CAVA dédiée waybar
+│ │ └── scripts/ gpu, network, power-profile, cava, wob, popups GTK
+│ ├── wofi/
+│ │ └── config config wofi
+│ └── wob/
+│ └── wob.ini overlay volume/luminosité
├── assets/
│ └── violet-chaton-logo.png logo fastfetch (1024×1024)
└── themes/ tous les fichiers de thème violet-chaton
@@ -296,8 +359,12 @@ INSTALL/
├── violet-chaton-ls-colors.sh
├── violet-chaton-vivaldi.json thème Rice Violet-Chaton pour Vivaldi
├── violet-chaton.theme.css thème Discord/Vesktop compilé
+ ├── violet-chaton-waybar.css CSS 3-pills glassmorphism
+ ├── violet-chaton-wofi.css thème wofi launcher
+ ├── violet-chaton-wofi-power.css thème wofi menu power
├── cosmic/ configs COSMIC déployées automatiquement
│ ├── com.system76.CosmicTheme.Dark/v1/
+ │ ├── com.system76.CosmicTheme.Light/v1/
│ ├── com.system76.CosmicTheme.Mode/v1/
│ ├── com.system76.CosmicTerm/v1/
│ └── com.system76.CosmicTk/v1/
@@ -317,6 +384,16 @@ cp ~/.config/starship.toml ~/Documents/config-violet-chaton/INSTALL/configs/star
# Mettre à jour les configs COSMIC
cp ~/.config/cosmic/com.system76.CosmicTerm/v1/* \
~/Documents/config-violet-chaton/INSTALL/themes/cosmic/com.system76.CosmicTerm/v1/
+
+# Mettre à jour la config ou le CSS waybar
+cp ~/.config/waybar/config \
+ ~/Documents/config-violet-chaton/INSTALL/configs/waybar/config
+cp ~/.config/waybar/style.css \
+ ~/Documents/config-violet-chaton/INSTALL/themes/violet-chaton-waybar.css
+
+# Mettre à jour un script waybar
+cp ~/.config/waybar/scripts/power-profile.sh \
+ ~/Documents/config-violet-chaton/INSTALL/configs/waybar/scripts/power-profile.sh
```
---