1
0

2 Revīzijas b5fb63e31d ... ffcd07c5d4

Autors SHA1 Ziņojums Datums
  Mariano Z. ffcd07c5d4 dev: automated commit - 2026-03-11 15:02:11 2 nedēļas atpakaļ
  Mariano Z. 83adeb68ad dev: automated commit - 2026-03-02 20:44:52 3 nedēļas atpakaļ

+ 3 - 3
i3/.config/i3/config

@@ -167,7 +167,7 @@ bindsym $mod+y exec --no-startup-id clipmenu -i -fn 'monospace:size=12' -nb "$ro
 bindsym $mod+t exec $devlauncher $devroot
 bindsym $mod+shift+t exec $devlauncher --clear-cache $devroot
 # Pomodoro (small always-on-top terminal)
-bindsym $mod+Shift+o exec --no-startup-id $term --class pomodoro --title Pomodoro -o font.size=12 -e /home/mzunino/.local/bin/wo
+bindsym $mod+Shift+o exec --no-startup-id $term --class pomodoro --title Pomodoro -o font.size=12 -e /home/mzunino/.local/bin/pomo
 # File manager (match niri)
 bindsym $mod+e exec --no-startup-id ~/.local/bin/i3-launch-or-focus $filemgr
 # StrongDM UI
@@ -208,7 +208,7 @@ for_window [instance="dropdown"]          resize set 1800 1268
 for_window [instance="dropdown"]          move scratchpad
 
 for_window [instance="sdm-connect"] floating enable, resize set 1366 768, move position center
-for_window [class="pomodoro"] floating enable, sticky enable, resize set 400 110, move position 2160 1330
+for_window [class="pomodoro"] floating enable, resize set 500 160, move position bottom right, sticky enable
 
 # Workspace assignments
 for_window [workspace=$ws1] layout tabbed
@@ -273,7 +273,7 @@ exec --no-startup-id xidlehook \
   --not-when-fullscreen \
   --timer 300 'betterlockscreen -l' '' \
   --timer 120 'xset dpms force off' '' \
-  --timer 300 'systemctl suspend' ''
+  --timer 120 'systemctl suspend' ''
 exec --no-startup-id lxqt-policykit-agent
 exec --no-startup-id clipmenud
 exec --no-startup-id autorandr --change

+ 2 - 1
local-bin/.local/bin/niri-dev-launcher

@@ -81,7 +81,8 @@ def find_git_repos(dev_dir, no_cache=False):
 
 
 def get_project_name(repo_path):
-    name = Path(repo_path).name.lower()
+    p = Path(repo_path)
+    name = "-".join(p.parts[-2:]).lower()
     name = re.sub(r"[^a-z0-9]", "-", name)
     name = re.sub(r"-+", "-", name)
     return name.strip("-")

+ 4 - 0
niri/.config/niri/config.d/binds.kdl

@@ -9,6 +9,9 @@ binds {
     Mod+N { spawn-sh "~/.local/bin/niri-launch-or-focus --class sdm-connect alacritty -e /home/mzunino/.local/share/go/bin/sdm-tui "; }
     Mod+Shift+k { spawn-sh "~/.local/bin/niri-launch-or-focus --class k9s alacritty -e k9s "; }
     Mod+E { spawn-sh "~/.local/bin/niri-launch-or-focus thunar"; }
+    Mod+Shift+P { spawn-sh "niri msg action set-dynamic-cast-window --id $(niri msg --json pick-window | jq .id)";}
+
+
     Mod+Shift+N { spawn-sh "~/.local/bin/dotedit"; }
     Super+Alt+L hotkey-overlay-title="Lock the Screen: swaylock" { spawn "swaylock"; }
     Super+Alt+S allow-when-locked=true hotkey-overlay-title=null { spawn-sh "pkill orca || exec orca"; }
@@ -141,6 +144,7 @@ binds {
 
     Mod+P { spawn-sh "~/.local/bin/screenshot"; }
 
+
     // Mod+Escape allow-inhibiting=false { toggle-keyboard-shortcuts-inhibit; }
 }
 

+ 5 - 0
niri/.config/niri/noctalia/binds.kdl

@@ -55,6 +55,11 @@ binds {
     Mod+Shift+R hotkey-overlay-title="Screen Recorder" {
         spawn "qs" "-c" "noctalia-shell" "ipc" "call" "screenRecorder" "toggle";
     }
+
+    // Idle Inhibitor
+    Mod+I hotkey-overlay-title="Idle Inhibitor" {
+        spawn "qs" "-c" "noctalia-shell" "ipc" "call" "idleInhibitor" "toggle";
+    }
 }
 
 

+ 16 - 16
noctalia/.config/noctalia/colors.json

@@ -1,18 +1,18 @@
 {
-    "mError": "#eb6f92",
-    "mHover": "#524f67",
-    "mOnError": "#191724",
-    "mOnHover": "#e0def4",
-    "mOnPrimary": "#191724",
-    "mOnSecondary": "#191724",
-    "mOnSurface": "#e0def4",
-    "mOnSurfaceVariant": "#908caa",
-    "mOnTertiary": "#e0def4",
-    "mOutline": "#403d52",
-    "mPrimary": "#ebbcba",
-    "mSecondary": "#9ccfd8",
-    "mShadow": "#191724",
-    "mSurface": "#191724",
-    "mSurfaceVariant": "#26233a",
-    "mTertiary": "#31748f"
+    "mError": "#d95757",
+    "mHover": "#39bae6",
+    "mOnError": "#0b0e14",
+    "mOnHover": "#0b0e14",
+    "mOnPrimary": "#0b0e14",
+    "mOnSecondary": "#0b0e14",
+    "mOnSurface": "#bfbdb6",
+    "mOnSurfaceVariant": "#636a72",
+    "mOnTertiary": "#0b0e14",
+    "mOutline": "#565b66",
+    "mPrimary": "#e6b450",
+    "mSecondary": "#aad94c",
+    "mShadow": "#000000",
+    "mSurface": "#0b0e14",
+    "mSurfaceVariant": "#1e222a",
+    "mTertiary": "#39bae6"
 }

+ 164 - 60
noctalia/.config/noctalia/settings.json

@@ -1,14 +1,22 @@
 {
     "appLauncher": {
+        "autoPasteClipboard": false,
+        "clipboardWatchImageCommand": "wl-paste --type image --watch cliphist store",
+        "clipboardWatchTextCommand": "wl-paste --type text --watch cliphist store",
+        "clipboardWrapText": true,
         "customLaunchPrefix": "",
         "customLaunchPrefixEnabled": false,
         "enableClipPreview": true,
         "enableClipboardHistory": true,
+        "enableSettingsSearch": true,
         "iconMode": "tabler",
-        "pinnedExecs": [
+        "ignoreMouseInput": false,
+        "pinnedApps": [
         ],
         "position": "center",
+        "screenshotAnnotationTool": "",
         "showCategories": true,
+        "showIconBackground": false,
         "sortByMostUsed": true,
         "terminalCommand": "alacritty -e",
         "useApp2Unit": false,
@@ -16,35 +24,47 @@
     },
     "audio": {
         "cavaFrameRate": 60,
-        "externalMixer": "pwvucontrol || pavucontrol",
         "mprisBlacklist": [
         ],
         "preferredPlayer": "mpv",
         "visualizerType": "linear",
+        "volumeFeedback": false,
         "volumeOverdrive": false,
         "volumeStep": 5
     },
     "bar": {
+        "backgroundOpacity": 0,
+        "barType": "simple",
         "capsuleOpacity": 1,
         "density": "default",
         "exclusive": true,
         "floating": false,
+        "frameRadius": 12,
+        "frameThickness": 8,
+        "hideOnOverview": false,
         "marginHorizontal": 0,
         "marginVertical": 0,
         "monitors": [
         ],
         "outerCorners": false,
         "position": "top",
+        "screenOverrides": [
+        ],
         "showCapsule": true,
         "showOutline": false,
-        "transparent": true,
+        "useSeparateOpacity": true,
         "widgets": {
             "center": [
                 {
+                    "compactMode": false,
+                    "compactShowAlbumArt": true,
+                    "compactShowVisualizer": false,
                     "hideMode": "hidden",
                     "hideWhenIdle": false,
                     "id": "MediaMini",
                     "maxWidth": 145,
+                    "panelShowAlbumArt": true,
+                    "panelShowVisualizer": true,
                     "scrollingMode": "always",
                     "showAlbumArt": true,
                     "showArtistFirst": true,
@@ -58,13 +78,21 @@
                 {
                     "characterCount": 10,
                     "colorizeIcons": false,
+                    "emptyColor": "secondary",
                     "enableScrollWheel": true,
+                    "focusedColor": "primary",
                     "followFocusedScreen": true,
+                    "groupedBorderOpacity": 1,
                     "hideUnoccupied": true,
+                    "iconScale": 0.8,
                     "id": "Workspace",
                     "labelMode": "index+name",
+                    "occupiedColor": "secondary",
+                    "reverseScroll": false,
                     "showApplications": false,
-                    "showLabelsOnlyWhenOccupied": true
+                    "showBadge": true,
+                    "showLabelsOnlyWhenOccupied": true,
+                    "unfocusedIconsOpacity": 1
                 },
                 {
                     "colorizeIcons": false,
@@ -77,12 +105,10 @@
                 }
             ],
             "right": [
-                {
-                    "id": "ScreenRecorder"
-                },
                 {
                     "deviceNativePath": "",
                     "displayMode": "alwaysShow",
+                    "hideIfIdle": false,
                     "hideIfNotDetected": true,
                     "id": "Battery",
                     "showNoctaliaPerformance": false,
@@ -95,24 +121,28 @@
                 },
                 {
                     "displayMode": "alwaysShow",
-                    "id": "WiFi"
+                    "id": "Network"
                 },
                 {
                     "displayMode": "alwaysShow",
-                    "id": "Volume"
+                    "id": "Volume",
+                    "middleClickCommand": "pwvucontrol || pavucontrol"
                 },
                 {
                     "customFont": "Arial",
                     "formatHorizontal": "HH:mm ddd, MMM dd",
                     "formatVertical": "HH mm - dd MM",
                     "id": "Clock",
+                    "tooltipFormat": "HH:mm ddd, MMM dd",
                     "useCustomFont": true,
                     "usePrimaryColor": true
                 },
                 {
                     "hideWhenZero": true,
+                    "hideWhenZeroUnread": false,
                     "id": "NotificationHistory",
-                    "showUnreadBadge": true
+                    "showUnreadBadge": true,
+                    "unreadBadgeColor": "primary"
                 },
                 {
                     "blacklist": [
@@ -126,6 +156,42 @@
                     "pinned": [
                         "nm-applet"
                     ]
+                },
+                {
+                    "defaultSettings": {
+                        "refreshInterval": 5000
+                    },
+                    "id": "plugin:mini-docker"
+                },
+                {
+                    "defaultSettings": {
+                        "autoStartBreaks": false,
+                        "autoStartWork": false,
+                        "compactMode": false,
+                        "longBreakDuration": 15,
+                        "sessionsBeforeLongBreak": 4,
+                        "shortBreakDuration": 5,
+                        "workDuration": 25
+                    },
+                    "id": "plugin:pomodoro"
+                },
+                {
+                    "defaultSettings": {
+                        "audioCodec": "opus",
+                        "audioSource": "default_output",
+                        "colorRange": "limited",
+                        "copyToClipboard": false,
+                        "directory": "",
+                        "filenamePattern": "recording_yyyyMMdd_HHmmss",
+                        "frameRate": "60",
+                        "hideInactive": false,
+                        "quality": "very_high",
+                        "resolution": "original",
+                        "showCursor": true,
+                        "videoCodec": "h264",
+                        "videoSource": "portal"
+                    },
+                    "id": "plugin:screen-recorder"
                 }
             ]
         }
@@ -157,10 +223,10 @@
     },
     "colorSchemes": {
         "darkMode": true,
-        "generateTemplatesForPredefined": true,
+        "generationMethod": "tonal-spot",
         "manualSunrise": "06:30",
         "manualSunset": "18:30",
-        "matugenSchemeType": "scheme-monochrome",
+        "monitorForColors": "",
         "predefinedScheme": "Ayu",
         "schedulingMode": "off",
         "useWallpaperColors": false
@@ -188,18 +254,16 @@
                 "id": "media-sysmon-card"
             }
         ],
+        "diskPath": "/",
         "position": "top_center",
         "shortcuts": {
             "left": [
                 {
-                    "id": "WiFi"
+                    "id": "Network"
                 },
                 {
                     "id": "Bluetooth"
                 },
-                {
-                    "id": "ScreenRecorder"
-                },
                 {
                     "id": "WallpaperSelector"
                 }
@@ -241,30 +305,37 @@
         "pinnedApps": [
         ],
         "pinnedStatic": false,
+        "position": "bottom",
         "size": 0.89
     },
     "general": {
         "allowPanelsOnScreenWithoutBar": true,
+        "allowPasswordWithFprintd": false,
         "animationDisabled": true,
         "animationSpeed": 0.1,
+        "autoStartAuth": false,
         "avatarImage": "/home/mzunino/Sync/Documents/cv/img/profile.jpg",
         "boxRadiusRatio": 1,
         "compactLockScreen": true,
         "dimmerOpacity": 0.8,
+        "enableLockScreenCountdown": true,
         "enableShadows": false,
         "forceBlackScreenCorners": false,
         "iRadiusRatio": 1,
         "language": "",
         "lockOnSuspend": true,
+        "lockScreenCountdownDuration": 10000,
         "radiusRatio": 0.41000000000000003,
         "scaleRatio": 1,
         "screenRadiusRatio": 0,
         "shadowDirection": "bottom_right",
         "shadowOffsetX": 2,
         "shadowOffsetY": 3,
+        "showChangelogOnStartup": true,
         "showHibernateOnLockScreen": false,
         "showScreenCorners": true,
-        "showSessionButtonsOnLockScreen": true
+        "showSessionButtonsOnLockScreen": true,
+        "telemetryEnabled": true
     },
     "hooks": {
         "darkModeChange": "",
@@ -273,11 +344,15 @@
         "performanceModeEnabled": "",
         "screenLock": "",
         "screenUnlock": "",
+        "session": "",
+        "startup": "",
         "wallpaperChange": ""
     },
     "location": {
         "analogClockInCalendar": false,
         "firstDayOfWeek": -1,
+        "hideWeatherCityName": false,
+        "hideWeatherTimezone": false,
         "name": "Montevideo, Uruguay",
         "showCalendarEvents": true,
         "showCalendarWeather": true,
@@ -288,6 +363,11 @@
         "weatherShowEffects": true
     },
     "network": {
+        "bluetoothDetailsViewMode": "grid",
+        "bluetoothHideUnnamedDevices": false,
+        "bluetoothRssiPollIntervalMs": 10000,
+        "bluetoothRssiPollingEnabled": false,
+        "wifiDetailsViewMode": "grid",
         "wifiEnabled": true
     },
     "nightLight": {
@@ -303,6 +383,7 @@
         "backgroundOpacity": 0.91,
         "criticalUrgencyDuration": 15,
         "enableKeyboardLayoutToast": true,
+        "enableMediaToast": false,
         "enabled": true,
         "location": "top_right",
         "lowUrgencyDuration": 3,
@@ -311,6 +392,11 @@
         "normalUrgencyDuration": 8,
         "overlayLayer": true,
         "respectExpireTimeout": true,
+        "saveToHistory": {
+            "critical": true,
+            "low": true,
+            "normal": true
+        },
         "sounds": {
             "criticalSoundFile": "",
             "enabled": false,
@@ -336,59 +422,56 @@
         ],
         "overlayLayer": true
     },
-    "screenRecorder": {
-        "audioCodec": "opus",
-        "audioSource": "both",
-        "colorRange": "limited",
-        "directory": "/home/mzunino/Videos/recordings",
-        "frameRate": 60,
-        "quality": "high",
-        "showCursor": true,
-        "videoCodec": "h264",
-        "videoSource": "portal"
-    },
     "sessionMenu": {
         "countdownDuration": 5000,
         "enableCountdown": true,
+        "largeButtonsLayout": "grid",
         "largeButtonsStyle": false,
         "position": "center",
         "powerOptions": [
             {
                 "action": "lock",
+                "command": "",
                 "countdownEnabled": true,
                 "enabled": true
             },
             {
                 "action": "suspend",
+                "command": "",
                 "countdownEnabled": true,
                 "enabled": true
             },
             {
                 "action": "hibernate",
+                "command": "",
                 "countdownEnabled": true,
                 "enabled": true
             },
             {
                 "action": "reboot",
+                "command": "",
                 "countdownEnabled": true,
                 "enabled": true
             },
             {
                 "action": "logout",
+                "command": "",
                 "countdownEnabled": true,
                 "enabled": true
             },
             {
                 "action": "shutdown",
+                "command": "",
                 "countdownEnabled": true,
                 "enabled": true
             }
         ],
-        "showHeader": true
+        "showHeader": true,
+        "showNumberLabels": true
     },
-    "settingsVersion": 32,
+    "settingsVersion": 46,
     "systemMonitor": {
-        "cpuCriticalThreshold": 90,
+        "cpuCriticalThreshold": 80,
         "cpuPollingInterval": 3000,
         "cpuWarningThreshold": 80,
         "criticalColor": "#e67e80",
@@ -396,13 +479,17 @@
         "diskPollingInterval": 3000,
         "diskWarningThreshold": 80,
         "enableDgpuMonitoring": false,
+        "externalMonitor": "resources || missioncenter || jdsystemmonitor || corestats || system-monitoring-center || gnome-system-monitor || plasma-systemmonitor || mate-system-monitor || ukui-system-monitor || deepin-system-monitor || pantheon-system-monitor",
         "gpuCriticalThreshold": 90,
         "gpuPollingInterval": 3000,
         "gpuWarningThreshold": 80,
+        "loadAvgPollingInterval": 3000,
         "memCriticalThreshold": 90,
         "memPollingInterval": 3000,
         "memWarningThreshold": 80,
         "networkPollingInterval": 3000,
+        "swapCriticalThreshold": 90,
+        "swapWarningThreshold": 80,
         "tempCriticalThreshold": 90,
         "tempPollingInterval": 3000,
         "tempWarningThreshold": 80,
@@ -410,39 +497,51 @@
         "warningColor": "#9da9a0"
     },
     "templates": {
-        "alacritty": true,
-        "cava": true,
-        "code": false,
-        "discord": true,
-        "emacs": false,
-        "enableUserTemplates": false,
-        "foot": false,
-        "fuzzel": true,
-        "ghostty": true,
-        "gtk": true,
-        "helix": false,
-        "hyprland": false,
-        "kcolorscheme": true,
-        "kitty": false,
-        "mango": false,
-        "niri": false,
-        "pywalfox": false,
-        "qt": true,
-        "spicetify": false,
-        "telegram": false,
-        "vicinae": false,
-        "walker": false,
-        "wezterm": false,
-        "yazi": false,
-        "zed": false
+        "activeTemplates": [
+            {
+                "enabled": true,
+                "id": "gtk"
+            },
+            {
+                "enabled": true,
+                "id": "qt"
+            },
+            {
+                "enabled": true,
+                "id": "kcolorscheme"
+            },
+            {
+                "enabled": true,
+                "id": "alacritty"
+            },
+            {
+                "enabled": true,
+                "id": "ghostty"
+            },
+            {
+                "enabled": true,
+                "id": "fuzzel"
+            },
+            {
+                "enabled": true,
+                "id": "discord"
+            },
+            {
+                "enabled": true,
+                "id": "cava"
+            }
+        ],
+        "enableUserTheming": false
     },
     "ui": {
         "bluetoothDetailsViewMode": "grid",
         "bluetoothHideUnnamedDevices": false,
+        "boxBorderEnabled": false,
         "fontDefault": "Roboto",
         "fontDefaultScale": 1,
         "fontFixed": "DejaVu Sans Mono",
         "fontFixedScale": 1,
+        "networkPanelView": "wifi",
         "panelBackgroundOpacity": 0.4,
         "panelsAttachedToBar": true,
         "settingsPanelMode": "attached",
@@ -450,7 +549,8 @@
         "wifiDetailsViewMode": "grid"
     },
     "wallpaper": {
-        "directory": "/home/mzunino/Pictures",
+        "automationEnabled": true,
+        "directory": "/home/mzunino/Pictures/Wallpapers",
         "enableMultiMonitorDirectories": false,
         "enabled": true,
         "fillColor": "#000000",
@@ -460,14 +560,17 @@
         ],
         "overviewEnabled": true,
         "panelPosition": "follow_bar",
-        "randomEnabled": true,
         "randomIntervalSec": 900,
-        "recursiveSearch": true,
         "setWallpaperOnAllMonitors": true,
+        "showHiddenFiles": false,
+        "solidColor": "#1a1a2e",
         "transitionDuration": 1500,
         "transitionEdgeSmoothness": 0,
         "transitionType": "random",
+        "useSolidColor": false,
         "useWallhaven": false,
+        "viewMode": "recursive",
+        "wallhavenApiKey": "",
         "wallhavenCategories": "100",
         "wallhavenOrder": "desc",
         "wallhavenPurity": "111",
@@ -476,6 +579,7 @@
         "wallhavenResolutionHeight": "",
         "wallhavenResolutionMode": "atleast",
         "wallhavenResolutionWidth": "",
-        "wallhavenSorting": "views"
+        "wallhavenSorting": "views",
+        "wallpaperChangeMode": "random"
     }
 }

+ 10 - 0
web-apps/.local/share/applications/screencast.desktop

@@ -0,0 +1,10 @@
+[Desktop Entry]
+Name=Screen Cast
+GenericName=Screen Sharing
+Comment=Share or present your screen
+Exec=chromium --app=file:///home/mzunino/.local/share/screencast/app.html --start-fullscreen
+Icon=/home/mzunino/.local/share/screencast/icon.png
+Type=Application
+Categories=Utility;Video;
+Keywords=screen;cast;share;present;mirror;
+StartupWMClass=screencast.html

+ 349 - 0
web-apps/.local/share/screencast/app.html

@@ -0,0 +1,349 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Screen Cast</title>
+<style>
+* { box-sizing: border-box; margin: 0; padding: 0; }
+
+html, body {
+  width: 100%; height: 100%;
+  background: #000;
+  overflow: hidden;
+  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
+}
+
+video {
+  width: 100%; height: 100%;
+  object-fit: contain;
+  display: block;
+}
+
+/* ── Controls bar ── */
+#controls {
+  position: fixed;
+  top: 16px;
+  left: 50%;
+  transform: translateX(-50%);
+  display: flex;
+  align-items: center;
+  gap: 4px;
+  padding: 6px;
+  background: rgba(18, 18, 18, 0.82);
+  backdrop-filter: blur(24px);
+  -webkit-backdrop-filter: blur(24px);
+  border: 1px solid rgba(255,255,255,0.09);
+  border-radius: 12px;
+  z-index: 100;
+  transition: opacity 0.25s ease;
+  white-space: nowrap;
+  cursor: grab;
+  user-select: none;
+}
+
+#controls.dragging { cursor: grabbing; transition: none; }
+
+#controls.hidden {
+  opacity: 0;
+  pointer-events: none;
+}
+
+.sep {
+  width: 1px;
+  height: 18px;
+  background: rgba(255,255,255,0.1);
+  margin: 0 2px;
+  flex-shrink: 0;
+}
+
+button {
+  background: transparent;
+  color: rgba(255,255,255,0.78);
+  border: none;
+  padding: 5px 13px;
+  font-size: 13px;
+  font-weight: 500;
+  border-radius: 7px;
+  cursor: pointer;
+  transition: background 0.12s, color 0.12s;
+  letter-spacing: 0.01em;
+  line-height: 1.4;
+}
+
+button:hover  { background: rgba(255,255,255,0.1);  color: #fff; }
+button:active { background: rgba(255,255,255,0.18); color: #fff; }
+button:disabled { opacity: 0.3; cursor: default; pointer-events: none; }
+button.on { background: rgba(255,255,255,0.14); color: #fff; }
+
+/* ── Placeholder ── */
+#placeholder {
+  position: fixed;
+  inset: 0;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  gap: 14px;
+  color: rgba(255,255,255,0.35);
+  z-index: 50;
+  transition: opacity 0.3s;
+  user-select: none;
+}
+
+#placeholder.hidden { opacity: 0; pointer-events: none; }
+
+#placeholder svg { opacity: 0.25; }
+
+#placeholder .label {
+  font-size: 15px;
+  font-weight: 400;
+  letter-spacing: 0.01em;
+}
+
+#placeholder .hint {
+  font-size: 12px;
+  opacity: 0.6;
+}
+
+kbd {
+  font-family: inherit;
+  font-size: 11px;
+  background: rgba(255,255,255,0.08);
+  border: 1px solid rgba(255,255,255,0.14);
+  border-radius: 4px;
+  padding: 1px 6px;
+}
+
+/* ── Black overlay ── */
+#overlay {
+  position: fixed;
+  inset: 0;
+  background: #000;
+  z-index: 80;
+  opacity: 0;
+  pointer-events: none;
+  transition: opacity 0.2s;
+}
+#overlay.on { opacity: 1; pointer-events: auto; }
+
+/* ── Keyboard shortcut hint (fades after a few seconds) ── */
+#kbd-hint {
+  position: fixed;
+  bottom: 20px;
+  left: 50%;
+  transform: translateX(-50%);
+  font-size: 11px;
+  color: rgba(255,255,255,0.22);
+  z-index: 100;
+  letter-spacing: 0.04em;
+  white-space: nowrap;
+  transition: opacity 0.6s;
+  pointer-events: none;
+}
+#kbd-hint.hidden { opacity: 0; }
+
+/* ── Connecting pulse ── */
+.pulse { display: inline-flex; gap: 4px; align-items: center; }
+.pulse i {
+  display: block;
+  width: 5px; height: 5px;
+  border-radius: 50%;
+  background: rgba(255,255,255,0.6);
+  animation: p 1.1s ease-in-out infinite;
+  font-style: normal;
+}
+.pulse i:nth-child(2) { animation-delay: 0.18s; }
+.pulse i:nth-child(3) { animation-delay: 0.36s; }
+@keyframes p {
+  0%,80%,100% { transform: scale(0.65); opacity: 0.35; }
+  40%          { transform: scale(1);    opacity: 1; }
+}
+</style>
+</head>
+<body>
+
+<div id="controls">
+  <button id="btn-select">Select Stream</button>
+  <button id="btn-reconnect" disabled>Reconnect</button>
+  <div class="sep"></div>
+  <button id="btn-black">Black</button>
+  <button id="btn-fs">Fullscreen</button>
+</div>
+
+<div id="placeholder">
+  <svg width="56" height="56" viewBox="0 0 24 24" fill="none" stroke="currentColor"
+       stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round">
+    <rect x="2" y="3" width="20" height="14" rx="2.5"/>
+    <line x1="8"  y1="21" x2="16" y2="21"/>
+    <line x1="12" y1="17" x2="12" y2="21"/>
+  </svg>
+  <p class="label">No stream selected</p>
+  <p class="hint">Press <kbd>S</kbd> to pick a screen or window</p>
+</div>
+
+<video id="video" autoplay playsinline></video>
+
+<div id="overlay"></div>
+
+<div id="kbd-hint">S · select &nbsp;·&nbsp; R · reconnect &nbsp;·&nbsp; B · black &nbsp;·&nbsp; F · fullscreen &nbsp;·&nbsp; Esc · un-black</div>
+
+<script>
+const video    = document.getElementById("video")
+const overlay  = document.getElementById("overlay")
+const controls = document.getElementById("controls")
+const ph       = document.getElementById("placeholder")
+const kbdHint  = document.getElementById("kbd-hint")
+const btnSel   = document.getElementById("btn-select")
+const btnRec   = document.getElementById("btn-reconnect")
+const btnBlack = document.getElementById("btn-black")
+const btnFs    = document.getElementById("btn-fs")
+
+let stream      = null
+let isBlack     = false
+let connecting  = false
+let hideTimer   = null
+
+// ── Auto-hide controls + cursor ────────────────────────────────
+
+function showControls() {
+  controls.classList.remove("hidden")
+  document.body.style.cursor = ""
+  clearTimeout(hideTimer)
+  if (stream) hideTimer = setTimeout(hideControls, 2500)
+}
+
+function hideControls() {
+  controls.classList.add("hidden")
+  document.body.style.cursor = "none"
+}
+
+document.addEventListener("mousemove", showControls)
+document.addEventListener("mousedown", showControls)
+
+setTimeout(() => kbdHint.classList.add("hidden"), 4000)
+
+// ── Stream ─────────────────────────────────────────────────────
+
+async function connect() {
+  if (connecting) return
+  connecting = true
+  btnSel.innerHTML = `<span class="pulse"><i></i><i></i><i></i></span>`
+  btnSel.disabled  = true
+
+  const saved = localStorage.getItem("displaySurface")
+  const constraints = { video: saved ? { displaySurface: saved } : true, audio: false }
+
+  try {
+    const s = await navigator.mediaDevices.getDisplayMedia(constraints)
+    const surface = s.getVideoTracks()[0].getSettings().displaySurface
+    if (surface) localStorage.setItem("displaySurface", surface)
+    attach(s)
+  } catch(e) {
+    console.error(e)
+    reset()
+  }
+}
+
+function attach(s) {
+  stream = s
+  video.srcObject = s
+  ph.classList.add("hidden")
+  btnRec.disabled = false
+  reset()
+
+  s.getVideoTracks()[0].onended = () => {
+    stream = null
+    ph.classList.remove("hidden")
+    btnRec.disabled = true
+    showControls()
+    clearTimeout(hideTimer)
+    setTimeout(connect, 1000)
+  }
+
+  showControls()
+}
+
+function reset() {
+  connecting      = false
+  btnSel.disabled = false
+  btnSel.textContent = "Select Stream"
+}
+
+function reconnect() {
+  if (stream) { stream.getTracks().forEach(t => t.stop()); stream = null }
+  connect()
+}
+
+function toggleBlack() {
+  isBlack = !isBlack
+  overlay.classList.toggle("on", isBlack)
+  btnBlack.classList.toggle("on", isBlack)
+}
+
+function toggleFs() {
+  if (!document.fullscreenElement) document.documentElement.requestFullscreen()
+  else document.exitFullscreen()
+}
+
+// ── Buttons ────────────────────────────────────────────────────
+
+btnSel.onclick   = connect
+btnRec.onclick   = reconnect
+btnBlack.onclick = toggleBlack
+btnFs.onclick    = toggleFs
+
+// ── Keyboard ───────────────────────────────────────────────────
+
+document.addEventListener("keydown", e => {
+  if (e.target.tagName === "INPUT") return
+  const k = e.key.toLowerCase()
+  if (k === "s")      connect()
+  if (k === "r")      reconnect()
+  if (k === "b")      toggleBlack()
+  if (k === "f")      toggleFs()
+  if (k === "escape" && isBlack) toggleBlack()
+})
+
+document.addEventListener("fullscreenchange", () => {
+  btnFs.textContent = document.fullscreenElement ? "Exit Fullscreen" : "Fullscreen"
+})
+
+// ── Drag to reposition controls ────────────────────────────────
+
+;(function () {
+  let dragging = false, ox = 0, oy = 0
+
+  function applyPos(x, y) {
+    // Clamp within viewport
+    const r = controls.getBoundingClientRect()
+    x = Math.max(0, Math.min(window.innerWidth  - r.width,  x))
+    y = Math.max(0, Math.min(window.innerHeight - r.height, y))
+    controls.style.left      = x + "px"
+    controls.style.top       = y + "px"
+    controls.style.transform = "none"
+  }
+
+  controls.addEventListener("mousedown", e => {
+    if (e.target.tagName === "BUTTON") return
+    dragging = true
+    controls.classList.add("dragging")
+    const r = controls.getBoundingClientRect()
+    ox = e.clientX - r.left
+    oy = e.clientY - r.top
+    e.preventDefault()
+  })
+
+  document.addEventListener("mousemove", e => {
+    if (!dragging) return
+    applyPos(e.clientX - ox, e.clientY - oy)
+  })
+
+  document.addEventListener("mouseup", () => {
+    if (!dragging) return
+    dragging = false
+    controls.classList.remove("dragging")
+  })
+})()
+</script>
+</body>
+</html>

BIN
web-apps/.local/share/screencast/icon.png