summary refs log tree commit diff
path: root/.config
diff options
context:
space:
mode:
Diffstat (limited to '.config')
-rwxr-xr-x.config/aerc/filters/pdf4
-rw-r--r--.config/alacritty/base.ovl.yml9
-rw-r--r--.config/git/config13
-rw-r--r--.config/kanshi/config8
-rw-r--r--.config/mpv/config47
-rw-r--r--.config/mpv/input.conf17
-rw-r--r--.config/mpv/scripts/mouse_coords.lua2
-rw-r--r--.config/mvi/mpv.conf5
l---------.config/mvi/scripts/gallery-thumbgen.lua1
l---------.config/mvi/scripts/lib.disable1
l---------.config/mvi/scripts/playlist-view.lua1
-rw-r--r--.config/oguri/config2
-rw-r--r--.config/sway/auto.conf2
-rw-r--r--.config/sway/binds.conf13
-rw-r--r--.config/sway/config20
-rw-r--r--.config/sway/input.conf4
-rw-r--r--.config/treestyletab.css22
-rw-r--r--.config/tridactyl/tridactylrc6
-rw-r--r--.config/vifm/vifmrc7
-rw-r--r--.config/waybar/config97
-rwxr-xr-x.config/waybar/modules/weather.sh4
-rw-r--r--.config/waybar/style.css15
-rw-r--r--.config/yamlfs/go.yml54
23 files changed, 241 insertions, 113 deletions
diff --git a/.config/aerc/filters/pdf b/.config/aerc/filters/pdf
index a0cd2e9..3fd709a 100755
--- a/.config/aerc/filters/pdf
+++ b/.config/aerc/filters/pdf
@@ -1,4 +1,2 @@
 #!/bin/sh
-
-exec pdftohtml -s -i -stdout /dev/stdin \
-	| /usr/share/aerc/filters/html
+exec pdftotext -q -layout /dev/stdin /dev/stdout
diff --git a/.config/alacritty/base.ovl.yml b/.config/alacritty/base.ovl.yml
index 7e07dce..3ccd271 100644
--- a/.config/alacritty/base.ovl.yml
+++ b/.config/alacritty/base.ovl.yml
@@ -1,6 +1,13 @@
 window:
   decorations: none
 
+cursor:
+  style:
+    shape: Block
+    blinking: Off
+
+  vi_mode_style: Underline
+
 font:
   size: 12.0
   normal:
@@ -36,3 +43,5 @@ key_bindings:
   - { key: 'Escape',                          action: 'ToggleViMode',   mode: 'Vi' }
   - { key: 'Slash',  mods: 'Alt',             action: 'SearchForward',  mode: 'Vi' }
   - { key: 'Slash',                           action: 'SearchBackward', mode: 'Vi' }
+  - { key: 'PageUp',                          action: 'ScrollPageUp',   mode: 'Vi' }
+  - { key: 'PageDown',                        action: 'ScrollPageDown', mode: 'Vi' }
diff --git a/.config/git/config b/.config/git/config
index b16e8c3..631a82a 100644
--- a/.config/git/config
+++ b/.config/git/config
@@ -16,6 +16,14 @@
     multiEdit = true
     confirm = always
 
+[credential "git.sr.ht"]
+    username = robertgzr
+    helper = !sh -c 'pass sr.ht/robertgzr | xargs printf "password=%s\n"'
+
+[credential "github.com"]
+    username = robertgzr
+    helper = !sh -c 'pass github.com/robertgzr | xargs printf "password=%s\n"'
+
 [credential "smtp://mail.gandi.net:465"]
     username = robert@gnzler.io
     helper = !sh -c 'pass email/gnzler.io | xargs printf "password=%s\n"'
@@ -83,8 +91,9 @@
     total-lines = "! git ls-tree -r master --name-only | xargs -I {} git blame --line-porcelain {} | sed -n 's/^author //p' | sort | uniq -c | sort -rn"
     fixup = "!f() { git commit --fixup=${1}; }; f"
     squash = "!f() { git commit --squash=${1}; }; f"
-    rbi = rebase --autosquash -i
-    rbi-pr = !bash -c 'git rebase --autosquash -i `git merge-base HEAD ${1:-origin/master}`'
+    r = rebase
+    ri = rebase --autosquash -i
+    ri-pr = !bash -c 'git rebase --autosquash -i `git merge-base HEAD ${1:-origin/master}`'
     pushf = push --force-with-lease
     root = "rev-parse --show-toplevel"
     trailer = "!f() { trailer=${1:-}; ref=${2:-HEAD}; mode='--amend'; [ $ref != 'HEAD' ] && mode='--fixup=$ref'; msg=$(git rev-parse --show-toplevel)/LAST_COMMIT_MSG; git log -1 --format=%B $ref > $msg; git interpret-trailers --in-place --trailer $trailer $msg; git commit --allow-empty --no-verify --only --edit --file $msg $mode; rm $msg; }; f"
diff --git a/.config/kanshi/config b/.config/kanshi/config
index 77930e8..fc9019d 100644
--- a/.config/kanshi/config
+++ b/.config/kanshi/config
@@ -26,8 +26,14 @@ profile laptop {
     exec oguri-cycle
 }
 
+profile sony {
+    output eDP-1 scale 1 position 0,0 enable
+    output "Sony SONY TV  *00 0x00000101" mode 3840x2160@23.976000Hz transform normal position 2560,0 enable
+    exec oguri-cycle
+}
+
 profile tv {
-    output eDP-1 scale 2 position 0,0 enable
+    output eDP-1 scale 1 position 0,0 enable
     output HDMI-A-1 transform normal position 2560,0 enable
     exec oguri-cycle
 }
diff --git a/.config/mpv/config b/.config/mpv/config
index 3491d76..8d6ac1a 100644
--- a/.config/mpv/config
+++ b/.config/mpv/config
@@ -4,12 +4,15 @@
 autoload-files=no
 input-ipc-server=/var/run/user/1000/mpv 
 profile=gpu-hq
+icc-profile=~~/B140QAN02_0.icm
+tone-mapping=clip
+target-peak=500
 
 #
 # Video
 #
-framedrop=vo
-video-sync=display-resample
+# framedrop=vo
+# video-sync=display-resample
 gpu-context=wayland
 window-maximized=yes # prevent wayland problems with buffer resize
 hwdec=yes
@@ -115,21 +118,39 @@ dscale=ewa_lanczossharp
 correct-downscaling=yes
 sigmoid-upscaling=yes
 
-[gpuscale8]
-profile-desc="Use GLSL shaders to scale via GPU"
+[gpuscale]
+profile-desc="Use GLSL shaders to scale via GPU (FSRCNNX)"
 profile=gpu-hq
-glsl-shaders=~~/shaders/FSRCNNX_x2_16-0-4-1.glsl
+hwdec=auto-copy
+gpu-api=opengl
+fbo-format=rgba16f
+cscale=mitchell
+dscale=mitchell
+linear-downscaling=no
+glsl-shaders-clr
+glsl-shaders=~~/shaders/default-shader-pack/shaders/FSRCNNX_x2_8-0-4-1.glsl
+glsl-shaders=~~/shaders/default-shader-pack/shaders/KrigBilateral.glsl
+glsl-shaders=~~/shaders/default-shader-pack/shaders/SSimDownscaler.glsl
 
-[gpuscale16]
-profile-desc="Use GLSL shaders to scale via GPU"
+[gpuscale-high]
+profile-desc="Use GLSL shaders to scale via GPU (FSRCNNX x16)"
 profile=gpu-hq
-glsl-shaders=~~/shaders/FSRCNNX_x2_8-0-4-1.glsl
+hwdec=auto-copy
+gpu-api=opengl
+fbo-format=rgba16f
+cscale=mitchell
+dscale=mitchell
+linear-downscaling=no
+glsl-shaders-clr
+glsl-shaders=~~/shaders/default-shader-pack/shaders/FSRCNNX_x2_16-0-4-1.glsl
+glsl-shaders=~~/shaders/default-shader-pack/shaders/KrigBilateral.glsl
+glsl-shaders=~~/shaders/default-shader-pack/shaders/SSimDownscaler.glsl
 
 [interpolate]
 profile-desc="Increase framecount by interpolating (with vapoursynth)"
 profile=gpu-hq
 vf=format=yuv420p,scale=w=-1:h=720,vapoursynth=~~/vapoursynth/interpolate.vpy:4:4
-video-sync=display-desync
+video-sync=display-resample
 
 [svp]
 profile-desc="[irrelevant] Integrate with SVP"
@@ -157,3 +178,11 @@ vf-add='stereo3d:ab2l:ml'
 [skip-silence]
 profile-desc="Skip over silent parts"
 af-add='silenceremove=0:0:0:-1:0.001:-45dB:0:rms'
+
+[anime4k]
+profile-desc="Anime4K x2 Perceptual"
+glsl-shaders-clr
+glsl-shaders=~~/shaders/default-shader-pack/shaders/Anime4K_3.0_Upscale_CNN_M_x2_Deblur.glsl
+glsl-shaders=~~/shaders/default-shader-pack/shaders/Anime4K_3.0_ThinLines_HQ.glsl
+glsl-shaders=~~/shaders/default-shader-pack/shaders/Anime4K_3.0_DarkLines_HQ.glsl
+glsl-shaders=~~/shaders/default-shader-pack/shaders/Anime4K_3.0_Denoise_Bilateral_Mode.glsl
diff --git a/.config/mpv/input.conf b/.config/mpv/input.conf
index 67ace36..259eafc 100644
--- a/.config/mpv/input.conf
+++ b/.config/mpv/input.conf
@@ -99,6 +99,7 @@ h cycle-values af lavfi=[bs2b=profile=default] lavfi=[bs2b=profile=jmeier] lavfi
 
 MBTN_RIGHT script_binding uosc/menu
 U script_binding uosc/menu
+Enter script_binding uosc/menu
 P script-binding uosc/playlist  #! select > playlist
 C script-binding uosc/chapters  #! select > chapters
 Ctrl+space script-binding uosc/peek-timeline
@@ -110,7 +111,7 @@ Alt+r script-binding slicing/slicing_mark      #! utils > slicing > mark
 Alt+t script-binding autodeint                 #! utils > autodeint
 Alt+y script-binding autocrop/toggle_crop      #! utils > autocrop
 c script-binding contact-sheet-toggle          #! utils > contact sheet
-g script-binding playlist-view-toggle          #! utils > playlist view
+# g script-binding playlist-view-toggle          #! utils > playlist view
 Alt+m script-binding mouse_coords              #! utils > mouse coords
 
 K ignore
@@ -126,8 +127,12 @@ J ignore
 8 ignore
 9 ignore
 
-Ctrl+Shift+1 apply-profile anime       # ! profile > anime
-Ctrl+Shift+2 apply-profile cache       # ! profile > cache
-Ctrl+Shift+3 apply-profile scale       # ! profile > scale
-Ctrl+Shift+4 apply-profile interpolate # ! profile > interpolate
-Ctrl+Shift+5 apply-profile 3d          # ! profile > 3d fix
+Ctrl+Shift+0 apply-profile reset         #! profiles > reset
+Ctrl+Shift+1 apply-profile anime         #! profiles > anime
+Ctrl+Shift+2 apply-profile cache         #! profiles > cache
+Ctrl+Shift+3 apply-profile scale         #! profiles > scale
+Ctrl+Shift+4 apply-profile interpolate   #! profiles > interpolate
+Ctrl+Shift+5 apply-profile 3d            #! profiles > 3d fix
+Ctrl+Shift+6 apply-profile anime4k       #! profiles > 3d fix
+Ctrl+Shift+7 apply-profile gpuscale      #! profiles > gpuscale x8
+Ctrl+Shift+8 apply-profile gpuscale-high #! profiles > gpuscale x16
diff --git a/.config/mpv/scripts/mouse_coords.lua b/.config/mpv/scripts/mouse_coords.lua
index dae6239..3bc59b9 100644
--- a/.config/mpv/scripts/mouse_coords.lua
+++ b/.config/mpv/scripts/mouse_coords.lua
@@ -21,7 +21,7 @@ local msg = require('mp.msg')
 
 function print_pos()
     x, y = mp.get_mouse_pos()
-    pos = "x: " .. x .. ", y: " .. y
+    pos = "xy: " .. x .. "," .. y
     mp.msg.warn(pos)
     mp.osd_message(pos)
 end
diff --git a/.config/mvi/mpv.conf b/.config/mvi/mpv.conf
index 1032b0e..2218a59 100644
--- a/.config/mvi/mpv.conf
+++ b/.config/mvi/mpv.conf
@@ -1,6 +1,11 @@
 gpu-context=wayland
 autofit-larger=x90%
 
+osd-font="Iosevka Aile"
+osd-font-size=15
+osd-scale-by-window=yes
+hidpi-window-scale
+
 ## IMAGE
 # classic opengl-hq parameter, change at will
 scale=spline36
diff --git a/.config/mvi/scripts/gallery-thumbgen.lua b/.config/mvi/scripts/gallery-thumbgen.lua
deleted file mode 120000
index 92816c8..0000000
--- a/.config/mvi/scripts/gallery-thumbgen.lua
+++ /dev/null
@@ -1 +0,0 @@
-../../mpv/scripts/mpv-gallery-view/scripts/gallery-thumbgen.lua
\ No newline at end of file
diff --git a/.config/mvi/scripts/lib.disable b/.config/mvi/scripts/lib.disable
deleted file mode 120000
index bc6efec..0000000
--- a/.config/mvi/scripts/lib.disable
+++ /dev/null
@@ -1 +0,0 @@
-../../mpv/scripts/mpv-gallery-view/scripts/lib.disable
\ No newline at end of file
diff --git a/.config/mvi/scripts/playlist-view.lua b/.config/mvi/scripts/playlist-view.lua
deleted file mode 120000
index ed4ac05..0000000
--- a/.config/mvi/scripts/playlist-view.lua
+++ /dev/null
@@ -1 +0,0 @@
-../../mpv/scripts/mpv-gallery-view/scripts/playlist-view.lua
\ No newline at end of file
diff --git a/.config/oguri/config b/.config/oguri/config
index 2288dae..cb2ea09 100644
--- a/.config/oguri/config
+++ b/.config/oguri/config
@@ -1,4 +1,4 @@
 [output *]
-image=$HOME/.config/oguri/leaves.jpg
+image=/home/robert/.config/oguri/leaves.jpg
 scaling-mode=tile
 filter=best
diff --git a/.config/sway/auto.conf b/.config/sway/auto.conf
index 6afe96b..fe004f9 100644
--- a/.config/sway/auto.conf
+++ b/.config/sway/auto.conf
@@ -18,6 +18,8 @@ for_window [app_id="firefox" title="^Developer Tools"] floating enable
 for_window [app_id="firefox" title="Sharing Indicator$"] floating enable, border none, move position 0 ppt 50 ppt, sticky enable
 for_window [app_id="firefox" title="^Close tabs?"] floating enable
 for_window [app_id="firefox" title="^File Upload$"] exec centercon -w .6
+for_window [app_id="firefox" title="^Save As$"] exec centercon -w .6
+for_window [app_id="Telegram" title="^Choose Files$"] floating enable; exec centercon -w .6
 
 # Tag windows
 for_window [app_id="firefox"] mark browser
diff --git a/.config/sway/binds.conf b/.config/sway/binds.conf
index f8591d6..838c78e 100644
--- a/.config/sway/binds.conf
+++ b/.config/sway/binds.conf
@@ -35,6 +35,7 @@ bindsym $mod+Shift+e exec swaynag \
 
 bindsym $mod+Shift+backspace exec lock
 
+bindsym Print exec grimshot copy output
 bindsym $mod+Shift+s mode "screengrab"
 mode "screengrab" {
 bindsym a exec grimshot save screen; mode "default"
@@ -49,7 +50,7 @@ bindsym Escape mode "default"
 bindsym $mod+Shift+b border toggle
 bindsym $mod+Shift+r output - transform 90 clockwise
 
-bindsym $mod+a exec soundswitch
+bindsym $mod+Shift+a exec soundswitch
 # }}}
 
 # Moving around {{{
@@ -236,4 +237,14 @@ bindsym XF86MonBrightnessDown exec light -U 5
 bindsym XF86AudioPlay exec playerctl -p playerctld play-pause
 bindsym XF86AudioNext exec playerctl -p playerctld next
 bindsym XF86AudioPrev exec playerctl -p playerctld previous
+
+bindsym XF86WakeUp exec true
+# switch video mode
+bindsym XF86Display exec sh -c 'killall kanshi; exec kanshi'
+# config
+bindsym XF86Tools exec true
+# keyboard
+bindsym XF86Keyboard exec light -S 0
+# bookmarks
+bindsym XF86Favorites exec light -S 100
 # }}}
diff --git a/.config/sway/config b/.config/sway/config
index a2a64e4..c5b46dd 100644
--- a/.config/sway/config
+++ b/.config/sway/config
@@ -1,20 +1,22 @@
 # vim: ft=i3config fdm=marker
 
-exec doas rc gui
-
 output * scale 1
 output * max_render_time 1
 output * adaptive_sync on
 
-exec_always sh -c 'killall kanshi; exec kanshi'
-exec_always sh -c 'killall oguri; exec oguri; oguri-cycle'
-exec_always sh -c 'killall waybar; exec waybar'
-#exec_always kanshictl reload
+# exec_always sh -c 'killall oguri; exec oguri;'
+exec oguri
+# exec_always sh -c 'killall kanshi; exec kanshi;'
+exec kanshi
+# exec_always sh -c 'killall waybar; exec waybar;'
+exec waybar
+
+#exec doas rc sway
 
 exec light -S 80
 exec redshift
+exec pipewire
 exec mako
-# exec mpd-mpris -no-instance
 exec swayidle -w \
 	timeout 540 'lock' \
 	timeout 800 'swaymsg output \* dpms off' \
@@ -39,6 +41,8 @@ set $right l
 
 set $term alacritty
 set $floating_term $term --config-file $HOME/.config/alacritty/launcher.yml --class '__floating-Alacritty'
+# set $term foot
+# set $floating_term $term --app-id '__floating-term'
 set $menu menu -drun
 # set $menu wofi -k /dev/null --terminal $term --show drun
 set $run_menu menu -run
@@ -101,4 +105,4 @@ client.urgent $urgent2 $urgent $text $indicator $urgent
 # }}}
 
 # include config.d/*
-include "`uname -n`"
+# include "`uname -n`"
diff --git a/.config/sway/input.conf b/.config/sway/input.conf
index dc617a6..2635a50 100644
--- a/.config/sway/input.conf
+++ b/.config/sway/input.conf
@@ -14,7 +14,7 @@ input 65261:25700:Input_Club_Infinity_keyboard/QMK {
    repeat_rate 70
    repeat_delay 200
 }
-input 65261:24672:OLKB_Planck {
+input 12951:50895:ZSA_Technology_Labs_Planck_EZ_Glow {
    xkb_layout us
    xkb_variant mac
    xkb_options 'caps:hyper,lvl3:ralt_switch_multikey,eurosign:5'
@@ -22,7 +22,7 @@ input 65261:24672:OLKB_Planck {
    repeat_delay 200
 }
 
-input 2:7:SynPS/2_Synaptics_TouchPad {
+input 1739:0:Synaptics_TM3289-021 {
    tap enabled
    natural_scroll enabled
    accel_profile adaptive
diff --git a/.config/treestyletab.css b/.config/treestyletab.css
index 9339e73..8e62f48 100644
--- a/.config/treestyletab.css
+++ b/.config/treestyletab.css
@@ -1,17 +1,8 @@
 /* Show title of unread tabs with red and italic font */
-/*
 :root.sidebar tab-item.unread .label-content {
-  color: red !important;
   font-style: italic !important;
 }
-*/
 
-/* Add private browsing indicator per tab */
-/*
-:root.sidebar tab-item.private-browsing tab-label:before {
-  content: "🕶";
-}
-*/
 /* Less visible tab dividers. 
    A black border with a very low alpha slightly darkens any color. */
 tab-item {
@@ -20,11 +11,11 @@ tab-item {
 
 /* Change styling of pending (unloaded) tabs */
 tab-item.discarded {
-  opacity: 0.75;
+  opacity: 0.5;
 }
 
 tab-item.discarded .label-content {
-  opacity: 0.7;
+  opacity: 0.5;
 }
 
 :root.right tab-item tab-twisty {
@@ -42,7 +33,10 @@ tab-item.discarded .label-content {
 /* As little space before the tab name as possible.
    The fold/unfold icon is not affected. */
 tab-item:not(.pinned) {
-  padding-left: 6px !important; /* !important is required when there are enough tabs to cause a scrollbar */
+  padding-left: 6px !important;
+}
+tab-item:not(.pinned) .label-content {
+  padding-left: 2px;
 }
 
 tab-item tab-twisty {
@@ -50,4 +44,8 @@ tab-item tab-twisty {
   opacity: 0 !important;
   position: relative;
   z-index: 10000;
+}
+
+:root[theme="photon"], #background {
+  background-color: #2a2a2e;
 }
\ No newline at end of file
diff --git a/.config/tridactyl/tridactylrc b/.config/tridactyl/tridactylrc
index b196ae2..62a2753 100644
--- a/.config/tridactyl/tridactylrc
+++ b/.config/tridactyl/tridactylrc
@@ -2,8 +2,8 @@
 " sanitise tridactyllocal tridactylsync
 
 " rebind j/k for TST
-reset j
-reset k
+reset J
+reset K
 bind J tabnext
 bind K tabprev
 
@@ -31,6 +31,7 @@ bind <Space>ts fillcmdline tabopen -c shop
 
 bind <space>s fillcmdline tabopen search
 bind <space>n fillcmdline nativeopen
+bind <space>c fillcmdline recontain
 
 bind <C-o> back
 bind <C-i> forward
@@ -76,6 +77,7 @@ seturl overleaf.com mode ignore
 seturl jel.ly.fish mode ignore
 seturl gather.town mode ignore
 seturl typingclub.com mode ignore
+autocmd TabEnter typingclub.com mode ignore
 
 " fix youtube
 seturl youtube.com noiframe true
diff --git a/.config/vifm/vifmrc b/.config/vifm/vifmrc
index 26479b4..18da8dd 100644
--- a/.config/vifm/vifmrc
+++ b/.config/vifm/vifmrc
@@ -93,6 +93,8 @@ filextype *.avi,*.mp4,*.wmv,*.dat,*.3gp,*.ogv,*.mkv,*.mpg,*.mpeg,*.vob,
         \ mpv --mute %f,
         \ {View using ffplay}
         \ ffplay -fs %f,
+       \ {Enqueue using xap}
+       \ xap add %c:p,
 
 fileviewer *.avi,*.mp4,*.wmv,*.dat,*.3gp,*.ogv,*.mkv,*.mpg,*.mpeg,*.vob,
           \*.fl[icv],*.m2v,*.mov,*.webm,*.ts,*.mts,*.m4v,*.r[am],*.qt,*.divx,
@@ -164,6 +166,11 @@ filetype *.7z
        \ 7z x %c,
 fileviewer *.7z 7z l %c
 
+filetype *.rar
+       \ {Extract RAR}
+       \ unrar x %c,
+fileviewer *.rar unrar v %c
+
 " ArchiveMount
 fileviewer *.tgz,*.tar.gz tar -tzf %c
 fileviewer *.tar.bz2,*.tbz2 tar -tjf %c
diff --git a/.config/waybar/config b/.config/waybar/config
index aed7d08..40e06a4 100644
--- a/.config/waybar/config
+++ b/.config/waybar/config
@@ -7,7 +7,7 @@
 
     "modules-left": ["sway/mode", "sway/workspaces", "sway/window", "custom/mpv", "custom/mpd", "custom/spotify", "custom/toggl"],
     "modules-center": ["custom/weather", "clock#local", "clock#utc"],
-    "modules-right": ["tray", "cpu", "memory", "disk#root", "disk#home", "temperature", "idle_inhibitor", "backlight", "custom/redshift", "pulseaudio", "network#wg", "network", "battery"],
+    "modules-right": ["tray", "cpu", "memory", "disk#root", "disk#home", "temperature", "idle_inhibitor", "backlight", "custom/redshift", "pulseaudio", "network#vpn", "network#tailscale", "network", "battery"],
 
     "sway/workspaces": {
         "disable-scroll": true,
@@ -30,30 +30,31 @@
     "idle_inhibitor": {
         "format": "{icon}",
         "format-icons": {
-            "activated": "󰛐",
-            "deactivated": "󰛑"
+            "activated": "󰅶",
+            "deactivated": "󰾪"
         }
     },
     "tray": {
         "spacing": 10
     },
     "clock#local": {
-        "timezone": "Europe/Berlin",
+        // "timezone": "Europe/Berlin",
+        // "timezone": "Europe/Istanbul",
         "format": "{:<i>%a</i> %d %b <b>%H:%M</b>}",
-	"tooltip-format": "TZ: {:%Z %z}\n\n{calendar}"
+        "tooltip-format": "TZ: {:%Z %z}\n\n{calendar}"
     },
     "clock#utc": {
         "timezone": "UTC",
         "format": "({:<small>%Z</small> %H:%M})",
-	"tooltip-format": "{:%Z %z}"
+        "tooltip-format": "{:%Z %z}"
     },
     "disk#root": {
-	"path": "/",
-	"format": "󰋊 <small>/ </small>{percentage_used}%"
+        "path": "/",
+        "format": "󰋊 <small>/ </small>{percentage_used}%"
     },
     "disk#home": {
-	"path": "/home",
-	"format": "<small>/home </small>{percentage_used}%"
+        "path": "/home",
+        "format": "<small>/home </small>{percentage_used}%"
     },
     "cpu": {
         "format": "󰊚 {}%",
@@ -69,13 +70,15 @@
         "format-icons": ["󱃃", "󰔏", "󱃂", "󰸁"]
     },
     "backlight": {
-        "states": {
-	    "off": "1"
-	},
         "format": "{icon} {percent}%",
         "format-icons": ["󰹐", "󰌶", "󰛩"],
-        "on-scroll-down": "light -D 5",
+        "on-scroll-down": "light -A 5",
         "on-scroll-up": "light -U 5",
+        // save current level
+        // then set to minimum brightness
+        "on-click-right": "light -O; light -S $(light -P)",
+        // revert to previously saved brightness
+        "on-click-middle": "light -I"
     },
     "battery": {
         "states": {
@@ -100,13 +103,21 @@
         "tooltip-format-disconnected": "disconnected",
         "on-click": "swx -t -f iwctl"
     },
-    "network#wg": {
+    "network#vpn": {
         "interface": "wg0",
-        "format": "󰯄",
-	"tooltip-format": "wg0: {ipaddr}/{cidr}",
+        "format": "󰌆",
+        "tooltip-format": "{ifname}: {ipaddr}/{cidr}",
+        "tooltip-format-disconnected": "disconnected",
+        "on-click": "doas wg-quick up wg0",
+        "on-click-right": "doas wg-quick down wg0"
+    },
+    "network#tailscale": {
+        "interface": "tailscale0",
+        "format": "󰹻", // "󰈓", // "󰠳",
+        "tooltip-format": "{ifname}: {ipaddr}/{cidr}",
         "tooltip-format-disconnected": "disconnected",
-	"on-click": "doas wg-quick up wg0",
-	"on-click-right": "doas wg-quick down wg0"
+        "on-click": "doas rc-service tailscale start",
+        "on-click-right": "doas rc-service tailscale stop"
     },
     "pulseaudio": {
         "format": "{icon} {volume}%",
@@ -131,46 +142,46 @@
         "return-type": "json",
         "max-length": 80,
         "escape": false,
-	"interval": 2,
+        "interval": 2,
         "exec": "$HOME/.config/waybar/modules/waybar-media spotify",
-	"exec-if": "pgrep spotify"
+        "exec-if": "pgrep spotify"
      },
     "custom/mpd": {
-        "format": "󰴙 {}",
+        "format": "󰐹 {}",
         "return-type": "json",
         "max-length": 80,
-	"interval": 2,
+        "interval": 2,
         "exec": "$HOME/.config/waybar/modules/waybar-media mpd",
-	"exec-if": "pgrep mpd"
+        "exec-if": "pgrep mpd"
     },
     "custom/mpv": {
         "format": "󰐍 {}",
         "return-type": "json",
         "max-length": 80,
-	"interval": 2,
+        "interval": 2,
         "exec": "$HOME/.config/waybar/modules/waybar-media mpv",
-	"exec-if": "pgrep mpv"
+        "exec-if": "pgrep mpv"
     },
     "custom/toggl": {
-	"format": "󰔟 {}",
+    "format": "󰔟 {}",
         "exec": "$HOME/.config/waybar/modules/toggl.lua 2>/dev/null",
         "interval": 30
     },
     "custom/redshift": {
-	"format": "{icon}",
-	"format-icons": {
+    "format": "{icon}",
+    "format-icons": {
             "day": "󰱌",
-	    "night": "󰱊"
+            "night": "󰱊"
         },
         "exec-if": "pgrep redshift",
         "exec": "$HOME/.config/waybar/modules/waybar-redshift",
-	"return-type": "json",
-	"on-click": "pkill -x -USR1 redshift",
-	"on-click-right": "pkill -x -HUP waybar-redshift"
+        "return-type": "json",
+        "on-click": "pkill -x -USR1 redshift",
+        "on-click-right": "pkill -x -HUP waybar-redshift"
     },
     "custom/weather": {
-	"format": "{icon} {percentage}℃",
-	"format-icons": {
+        "format": "{icon} {percentage}℃",
+        "format-icons": {
             "sunny": "󰖙",
             "partlycloudy": "󰖕",
             "cloudy": "󰖐",
@@ -182,15 +193,15 @@
             "thunder": "󰖓",
             "lightsnow": "󰖘",
             "heavysnow": "󰼶",
-            "snowrain": "󰙿",
+            "snowrain": "󰙿"
         },
-	"exec": "$HOME/.config/waybar/modules/weather.sh Berlin",
-	"interval": 600,
-	"return-type": "json",
-	"tooltip": true,
-	"signal": 4,
-	"on-click-right": "pkill -SIGRTMIN+5 waybar",
-	"on-click": "swx -t env REPORT=1 $HOME/.config/waybar/modules/weather.sh Berlin"
+        "exec": "$HOME/.config/waybar/modules/weather.sh",
+        "interval": 600,
+        "return-type": "json",
+        "tooltip": true,
+        "signal": 4,
+        "on-click-right": "pkill -SIGRTMIN+5 waybar",
+        "on-click": "swx -t env REPORT=1 $HOME/.config/waybar/modules/weather.sh Berlin"
     },
     "mpd": {
         "format": "{stateIcon} {artist} - {title} ({elapsedTime:%M:%S}/{totalTime:%M:%S})",
diff --git a/.config/waybar/modules/weather.sh b/.config/waybar/modules/weather.sh
index 210c20a..0b83de1 100755
--- a/.config/waybar/modules/weather.sh
+++ b/.config/waybar/modules/weather.sh
@@ -3,6 +3,10 @@ set -e
 [ -n "$DEBUG" ] && set -x
 
 loc=$1
+if [ -z "${loc}" ]; then
+	# use /etc/localtime
+	loc=$(basename "$(readlink -f /etc/localtime)")
+fi
 
 if [ -n "$REPORT" ]; then
 	curl -s v2.wttr.in/"${loc}"?F | less
diff --git a/.config/waybar/style.css b/.config/waybar/style.css
index e3d6206..9e41694 100644
--- a/.config/waybar/style.css
+++ b/.config/waybar/style.css
@@ -143,14 +143,22 @@ label:focus {
   border-top: 2px solid @urgent;
   color: @dimmed;
 }
-#network.wg.disconnected {
+#network.vpn.disconnected {
   border-top: 2px solid @dimmeddarker;
 }
-#network.wg:not(.disconnected) {
+#network.vpn:not(.disconnected) {
   border-top: 2px solid #c476ff;
   /* background: #c476ff; */
   /* color: @dimmeddarker; */
 }
+#network.tailscale.disconnected {
+  border-top: 2px solid @dimmeddarker;
+}
+#network.tailscale:not(.disconnected) {
+  border-top: 2px solid #497e7a;
+  /* background: #497e7a; */
+  /* color: @dimmeddarker; */
+}
 #pulseaudio {}
 #pulseaudio.muted {
   border-top: 2px solid @urgent;
@@ -169,6 +177,7 @@ label:focus {
 }
 #idle_inhibitor.activated {
   color: unset;
+  border-top: 2px solid #7a8530;
 }
 
 #custom-mpd,
@@ -203,7 +212,7 @@ label:focus {
   }
 }
 #custom-redshift.night {
-  border-top: 2px solid #ffae42;
+  border-top: 2px solid #97822e;
   color: @foreground;
   animation-name: flash;
   animation-duration: 0.3s;
diff --git a/.config/yamlfs/go.yml b/.config/yamlfs/go.yml
index a634f92..21fb36d 100644
--- a/.config/yamlfs/go.yml
+++ b/.config/yamlfs/go.yml
@@ -1,6 +1,4 @@
-{% $goversion := 1.14 %}
-{% $gopkg := (printf "example.com/%s" .name) %}
-{% with .pkg %}{% $gopkg = . %}{% end %}
+{% $goversion := 1.15 %}
 cmd:
   {% .name %}:
     main.go: |
@@ -15,12 +13,13 @@ version:
     package version
 
     var (
-    	Version = "0.0.0+unknown"
+    	Package = "{% .gopkg %}"
     	Revision = ""
+    	Version = "0.0.0+unknown"
     )
 
 go.mod: |
-  module {% $gopkg %}
+  module {% .gopkg %}
 
   go {% $goversion %}
 
@@ -28,15 +27,30 @@ Dockerfile: |
   # syntax=docker/dockerfile:1.1-experimental
   # vim: ft=dockerfile
 
-  FROM --platform=$BUILDPLATFORM docker.io/library/alpine:3.11 AS base
-  RUN apk add -U --no-cache ca-certificates
+  ARG GO_VERSION={% $goversion %}
 
-  FROM --platform=$BUILDPLATFORM docker.io/tonistiigi/xx:golang AS xx
-  FROM --platform=$BUILDPLATFORM docker.io/library/golang:{% $goversion %}-alpine AS build
+  FROM --platform=${BUILDPLATFORM:?err} docker.io/tonistiigi/xx:golang AS xx
+  FROM --platform=${BUILDPLATFORM:?err} docker.io/library/golang:${GO_VERSION:?err}-alpine AS buildenv
   COPY --from=xx / /
   ARG TARGETPLATFORM
   WORKDIR /src
-  RUN apk add -U --no-cache make
+  RUN apk --update-cache --no-cache add make
+
+  FROM buildenv AS gotestsum
+  RUN go get gotest.tools/gotestsum@0.6.0
+
+  FROM buildenv AS golangcilint
+  RUN go get github.com/golangci/golangci-lint/cmd/golangci-lint@v1.27.0
+
+  FROM buildenv AS test
+  COPY --from=gotestsum /go/bin/gotestsum /usr/local/bin/
+  COPY --from=golangcilint /go/bin/golangci-lint /usr/local/bin/
+  RUN --mount=target=/src,rw \
+      --mount=type=cache,target=/go/pkg \
+      --mount=type=cache,target=/root/.cache \
+      make DESTDIR=/out clean validate test
+
+  FROM buildenv AS build
   RUN --mount=target=/src,rw \
       --mount=type=cache,target=/go/pkg \
       --mount=type=cache,target=/root/.cache \
@@ -45,7 +59,10 @@ Dockerfile: |
   FROM scratch AS final
   COPY --from=build /out/{% .name %} /
 
-  FROM base AS run
+  FROM --platform=${TARGETPLATFORM:?err} docker.io/library/alpine:3.11 AS runtime-base
+  RUN apk --update-cache --no-cache add ca-certificates
+
+  FROM runtime-base AS run
   COPY --from=build /out/{% .name %} /usr/local/bin/
   ENTRYPOINT [ "{% .name %}" ]
 
@@ -60,10 +77,10 @@ Makefile: |
   REVISION ?= $(shell git rev-parse HEAD)
 
   GO ?= go
-  GO_PKG ?= {% $gopkg %}
+  GO_PKG ?= {% .gopkg %}
   GO_BUILDTAGS ?= netgo osusergo static_build
   GO_LDFLAGS ?= -s -w -extldflags "-static"
-  GO_VERSIONFLAGS = -X {% $gopkg %}/version.Version=$(VERSION) -X {% $gopkg %}/version.Revision=$(REVISION)
+  GO_VERSIONFLAGS = -X $(GO_PKG)/version.Version=$(VERSION) -X $(GO_PKG)/version.Revision=$(REVISION)
 
   .PHONY: build
   build: {% .name %}
@@ -82,6 +99,11 @@ Makefile: |
   	DOCKER_BUILDKIT=1 \
   	docker build --platform $(PLATFORM) --target final -o . .
 
+  .PHONY: container-test
+  container-test:
+  	DOCKER_BUILDKIT=1 \
+  	docker build --platform $(PLATFORM) --target test -o type=tar,dest=/dev/null .
+
   .PHONY: container-image
   container-image:
   	DOCKER_BUILDKIT=1 \
@@ -138,9 +160,9 @@ Makefile: |
   	@printf "  container-image   image build\n"
   	@printf "  cross             build w/ buildkit (multi-platform support)\n"
   	@printf "\n"
-  	@printf "  DESTDIR, PREFIX   output location\n"
-  	@printf "  PLATFORM          output platform\n"
-  	@printf "  REPO, TAG         image repository:tag\n"
+  	@printf "  DESTDIR, PREFIX   output location (default: $(DESTDIR)/$(PREFIX))\n"
+  	@printf "  PLATFORM          output platform (default: $(PLATFORM))\n"
+  	@printf "  REPO, TAG         image repository:tag (default: $(REPO):$(TAG))\n"
   	@printf "\n"
 
 .editorconfig: |