all lists on lists.proxmox.com
 help / color / mirror / Atom feed
From: Stefan Sterz <s.sterz@proxmox.com>
To: pve-devel@lists.proxmox.com, pbs-devel@lists.proxmox.com,
	pmg-devel@lists.proxmox.com
Subject: [pve-devel] [PATCH widget-toolkit v1 1/6] dark-theme: add initial version of the proxmox-dark theme
Date: Wed,  8 Mar 2023 17:33:12 +0100	[thread overview]
Message-ID: <20230308163312.2441849-1-s.sterz@proxmox.com> (raw)
In-Reply-To: <20230308161840.2396113-1-s.sterz@proxmox.com>

From: Daniel Tschlatscher <d.tschlatscher@proxmox.com>

adds an initial version of a dark theme for all proxmox products. the
theme works by simply loading an additional css file that adjust the
colors of the original theme "crisp" to be more suitable for a dark
theme.

the theme itself is written in scss, so we need to add sassc as a
build dependency. while sassc is deprecated, it is still maintained in
the debian repositories and, thus, needs no additional packaging on
our end.

this version adds the following on-top of Daniel Tschlatscher's
original draft:

* removes checked-in build artifacts and other stuff that shouldn't be
  tracked
* code clean-up and removal of redundant code
* refactors:
    * icon styling
    * color handling for charts (moved to css variables)
    * color variables, consolidates them and makes the "functional"
    * color values, improves contrast and makes the theme appear more
      consistent
    * using the "theme-" prefix
* adds:
    * markdown note styles
    * combo-box trigger styles
    * even more icon styles (e.g., template icons, check boxes etc.)
    * loading spinners styles
    * number field up and down arrow styles
    * an additional auto theme that switches between light and dark
      theme dynamically
    * widget toolkit hints
    * ceph install mask
    * grid group headers
    * color to toggled buttons
    * date picker styles
    * drag and drop proxy styles
* fixes:
    * contrast on control elements for "scrollable" sidebars
    * make the general appearance closer to the light theme ("crisp")
    * buttons (when hovered, toggled etc)
    * background masking (e.g., when showing the log-in form)
    * grid header separator (adds an outline)
    * separator lines in some menus
    * makes the custom unknown icon more discernible
    * makes headers more readable
    * color adjustments to several components for consistency
    * reduces brightness of dividers in toolbars
    * border color on chart legend elements
    * removes a black border from docked toolbars (e.g., tag edit)
    * dims the "invalid" color to appear less aggressive
    * add hover effects in grids and make them consistent with "crisp"
    * summary rows
    * selected and hovered elements in boundlists
    * row numberers in grids
    * contrast of links in hints
    * ceph overview border colors (e.g., OSD in/out/up/down grid)
    * bottom splitter contrast in certain situations
    * tag visibility
    * pbs compatibility (help buttons stylings, icons, tabs)
    * pmg compatibility:
         * remove border around the spanning element in the header
         * style spam score grid
         * style tracking center rows
         * add appropriate colors to buttons in the quarantine
         * style mail-info element in the quarantine

Co-authored-by: Daniel Tschlatscher <d.tschlatscher@proxmox.com>
Co-authored-by: Stefan Sterz <s.sterz@proxmox.com>
Signed-off-by: Daniel Tschlatscher <d.tschlatscher@proxmox.com>
Signed-off-by: Stefan Sterz <s.sterz@proxmox.com>
---
 debian/control                                |   1 +
 src/Makefile                                  |   2 +-
 src/defines.mk                                |   1 +
 src/proxmox-dark/Makefile                     |  47 ++++
 src/proxmox-dark/scss/ProxmoxDark.scss        |  37 ++++
 src/proxmox-dark/scss/abstracts/_mixins.scss  |  12 ++
 .../scss/abstracts/_variables.scss            |  67 ++++++
 src/proxmox-dark/scss/extjs/_body.scss        |  23 ++
 src/proxmox-dark/scss/extjs/_grid.scss        | 146 +++++++++++++
 src/proxmox-dark/scss/extjs/_menu.scss        |  39 ++++
 src/proxmox-dark/scss/extjs/_panel.scss       |  25 +++
 .../scss/extjs/_presentation.scss             |  14 ++
 src/proxmox-dark/scss/extjs/_progress.scss    |  19 ++
 src/proxmox-dark/scss/extjs/_splitter.scss    |  18 ++
 src/proxmox-dark/scss/extjs/_tabbar.scss      |  43 ++++
 src/proxmox-dark/scss/extjs/_tip.scss         |  18 ++
 src/proxmox-dark/scss/extjs/_toolbar.scss     |  21 ++
 src/proxmox-dark/scss/extjs/_treepanel.scss   |  24 +++
 src/proxmox-dark/scss/extjs/_window.scss      |  39 ++++
 src/proxmox-dark/scss/extjs/form/_button.scss |  57 +++++
 .../scss/extjs/form/_combobox.scss            |  23 ++
 .../scss/extjs/form/_formfield.scss           |  40 ++++
 src/proxmox-dark/scss/other/_charts.scss      |  39 ++++
 src/proxmox-dark/scss/other/_icons.scss       | 200 ++++++++++++++++++
 .../scss/proxmox/_datepicker.scss             |  61 ++++++
 src/proxmox-dark/scss/proxmox/_general.scss   |  56 +++++
 .../scss/proxmox/_helpbutton.scss             |  16 ++
 .../scss/proxmox/_loadingindicator.scss       |  14 ++
 src/proxmox-dark/scss/proxmox/_markdown.scss  |  31 +++
 src/proxmox-dark/scss/proxmox/_nodes.scss     |   9 +
 .../scss/proxmox/_quarantine.scss             |  47 ++++
 src/proxmox-dark/scss/proxmox/_storages.scss  |  19 ++
 src/proxmox-dark/scss/proxmox/_tags.scss      |  14 ++
 33 files changed, 1221 insertions(+), 1 deletion(-)
 create mode 100644 src/proxmox-dark/Makefile
 create mode 100644 src/proxmox-dark/scss/ProxmoxDark.scss
 create mode 100644 src/proxmox-dark/scss/abstracts/_mixins.scss
 create mode 100644 src/proxmox-dark/scss/abstracts/_variables.scss
 create mode 100644 src/proxmox-dark/scss/extjs/_body.scss
 create mode 100644 src/proxmox-dark/scss/extjs/_grid.scss
 create mode 100644 src/proxmox-dark/scss/extjs/_menu.scss
 create mode 100644 src/proxmox-dark/scss/extjs/_panel.scss
 create mode 100644 src/proxmox-dark/scss/extjs/_presentation.scss
 create mode 100644 src/proxmox-dark/scss/extjs/_progress.scss
 create mode 100644 src/proxmox-dark/scss/extjs/_splitter.scss
 create mode 100644 src/proxmox-dark/scss/extjs/_tabbar.scss
 create mode 100644 src/proxmox-dark/scss/extjs/_tip.scss
 create mode 100644 src/proxmox-dark/scss/extjs/_toolbar.scss
 create mode 100644 src/proxmox-dark/scss/extjs/_treepanel.scss
 create mode 100644 src/proxmox-dark/scss/extjs/_window.scss
 create mode 100644 src/proxmox-dark/scss/extjs/form/_button.scss
 create mode 100644 src/proxmox-dark/scss/extjs/form/_combobox.scss
 create mode 100644 src/proxmox-dark/scss/extjs/form/_formfield.scss
 create mode 100644 src/proxmox-dark/scss/other/_charts.scss
 create mode 100644 src/proxmox-dark/scss/other/_icons.scss
 create mode 100644 src/proxmox-dark/scss/proxmox/_datepicker.scss
 create mode 100644 src/proxmox-dark/scss/proxmox/_general.scss
 create mode 100644 src/proxmox-dark/scss/proxmox/_helpbutton.scss
 create mode 100644 src/proxmox-dark/scss/proxmox/_loadingindicator.scss
 create mode 100644 src/proxmox-dark/scss/proxmox/_markdown.scss
 create mode 100644 src/proxmox-dark/scss/proxmox/_nodes.scss
 create mode 100644 src/proxmox-dark/scss/proxmox/_quarantine.scss
 create mode 100644 src/proxmox-dark/scss/proxmox/_storages.scss
 create mode 100644 src/proxmox-dark/scss/proxmox/_tags.scss

diff --git a/debian/control b/debian/control
index 41093f3..71c48c4 100644
--- a/debian/control
+++ b/debian/control
@@ -5,6 +5,7 @@ Maintainer: Proxmox Support Team <support@proxmox.com>
 Build-Depends: debhelper (>= 12~),
                libjs-marked,
                pve-eslint (>= 7.28.0),
+               sassc,
 Standards-Version: 4.5.1
 Homepage: https://www.proxmox.com
 
diff --git a/src/Makefile b/src/Makefile
index 95da5aa..54727f6 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -1,6 +1,6 @@
 include defines.mk
 
-SUBDIRS= css images
+SUBDIRS= css images proxmox-dark
 
 # bundle it for now from the libjs-marked debian package to avoid touching our proxies file mapper,
 # we could also just ship a link to the packages file and load from same path as the widget-toolkit
diff --git a/src/defines.mk b/src/defines.mk
index d6bdd2c..2a65e9d 100644
--- a/src/defines.mk
+++ b/src/defines.mk
@@ -3,3 +3,4 @@ DOCDIR=${DESTDIR}/usr/share/doc/${PACKAGE}
 WWWBASEDIR=${DESTDIR}/usr/share/javascript/${PACKAGE}
 WWWCSSDIR=${WWWBASEDIR}/css
 WWWIMAGESDIR=${WWWBASEDIR}/images
+WWWTHEMEDIR=${WWWBASEDIR}/themes
diff --git a/src/proxmox-dark/Makefile b/src/proxmox-dark/Makefile
new file mode 100644
index 0000000..2ac6f22
--- /dev/null
+++ b/src/proxmox-dark/Makefile
@@ -0,0 +1,47 @@
+include ../defines.mk
+
+SCSSSRC=scss/ProxmoxDark.scss 			\
+	scss/abstracts/_mixins.scss 		\
+	scss/abstracts/_variables.scss 		\
+	scss/extjs/_body.scss 			\
+	scss/extjs/form/_button.scss 		\
+	scss/extjs/form/_combobox.scss 		\
+	scss/extjs/form/_formfield.scss 	\
+	scss/extjs/_grid.scss 			\
+	scss/extjs/_menu.scss 			\
+	scss/extjs/_panel.scss 			\
+	scss/extjs/_presentation.scss 		\
+	scss/extjs/_progress.scss 		\
+	scss/extjs/_splitter.scss 		\
+	scss/extjs/_tabbar.scss 		\
+	scss/extjs/_tip.scss 			\
+	scss/extjs/_toolbar.scss 		\
+	scss/extjs/_treepanel.scss 		\
+	scss/extjs/_window.scss 		\
+	scss/other/_charts.scss 		\
+	scss/other/_icons.scss 			\
+	scss/proxmox/_general.scss 		\
+	scss/proxmox/_helpbutton.scss 		\
+	scss/proxmox/_loadingindicator.scss	\
+	scss/proxmox/_markdown.scss 		\
+	scss/proxmox/_nodes.scss 		\
+	scss/proxmox/_quarantine.scss 		\
+	scss/proxmox/_storages.scss 		\
+	scss/proxmox/_tags.scss 		\
+	scss/proxmox/_datepicker.scss
+
+.PHONY: all
+all: theme-proxmox-dark.css
+
+.PHONY: install
+install: theme-proxmox-dark.css
+	install -d ${WWWTHEMEDIR}/
+	install -m 0664 theme-proxmox-dark.css ${WWWTHEMEDIR}/
+
+theme-proxmox-dark.css: ${SCSSSRC}
+	sassc -t compressed $< $@.tmp
+	mv $@.tmp $@
+
+.PHONY: clean
+clean:
+	rm -rf theme-proxmox-dark.css
diff --git a/src/proxmox-dark/scss/ProxmoxDark.scss b/src/proxmox-dark/scss/ProxmoxDark.scss
new file mode 100644
index 0000000..60e69a8
--- /dev/null
+++ b/src/proxmox-dark/scss/ProxmoxDark.scss
@@ -0,0 +1,37 @@
+@charset "utf-8";
+
+// Abstracts
+@import "abstracts/mixins";
+@import "abstracts/variables";
+
+// Chart, Icon, Keyboar-mode fixups
+@import "other/charts";
+@import "other/icons";
+
+// ExtJS re-stylings
+@import "extjs/form/button";
+@import "extjs/form/combobox";
+@import "extjs/form/formfield";
+@import "extjs/grid";
+@import "extjs/menu";
+@import "extjs/panel";
+@import "extjs/progress";
+@import "extjs/splitter";
+@import "extjs/tabbar";
+@import "extjs/tip";
+@import "extjs/toolbar";
+@import "extjs/treepanel";
+@import "extjs/window";
+@import "extjs/body";
+@import "extjs/presentation";
+
+// Proxmox re-stylings
+@import "proxmox/general";
+@import "proxmox/helpbutton";
+@import "proxmox/loadingindicator";
+@import "proxmox/markdown";
+@import "proxmox/nodes";
+@import "proxmox/quarantine";
+@import "proxmox/storages";
+@import "proxmox/tags";
+@import "proxmox/datepicker";
diff --git a/src/proxmox-dark/scss/abstracts/_mixins.scss b/src/proxmox-dark/scss/abstracts/_mixins.scss
new file mode 100644
index 0000000..570a783
--- /dev/null
+++ b/src/proxmox-dark/scss/abstracts/_mixins.scss
@@ -0,0 +1,12 @@
+// A border to the left and on top of the content panels for the
+// selected resource
+@mixin content-border {
+  border-top: solid 3px $background-darkest;
+  border-left: solid 3px $background-darkest;
+}
+
+// selected items in dropdown etc
+@mixin selection {
+  background-color: $selection-background-color;
+  color: $selection-background-text-color;
+}
diff --git a/src/proxmox-dark/scss/abstracts/_variables.scss b/src/proxmox-dark/scss/abstracts/_variables.scss
new file mode 100644
index 0000000..96581df
--- /dev/null
+++ b/src/proxmox-dark/scss/abstracts/_variables.scss
@@ -0,0 +1,67 @@
+// Primary colors
+$primary-color: hsl(205deg, 100%, 32.25%);
+$primary-light: hsl(205deg, 100%, 40.5%);
+$primary-dark: hsl(205deg, 100%, 25%);
+
+// Hightlighted Text (Links, Headers, etc.)
+$highlighted-text: hsl(205deg, 100%, 65%);
+$highlighted-text-alt: hsl(205deg, 100%, 80%);
+$highlighted-text-crit: hsl(360deg, 100%, 65%);
+
+// Icon and Text colors
+$text-color: hsl(0deg, 0%, 95%);
+$text-color-inactive: hsl(0deg, 0%, 60%);
+$icon-color: hsl(0deg, 0%, 90%);
+$icon-color-alt: hsl(0deg, 0%, 55%);
+
+// Borders
+$border-color: hsl(0deg, 0%, 40%);
+$border-color-alt: hsl(0deg, 0%, 25%);
+
+// Backgrounds
+$content-background-color: hsl(0deg, 0%, 20%);
+$content-background-selected: hsl(0deg, 0%, 30%);
+$background-dark: hsl(0deg, 0%, 20%);
+$background-darker: hsl(0deg, 0%, 15%);
+$background-darkest: hsl(0deg, 0%, 10%);
+$background-invalid: hsl(360deg, 60%, 30%);
+$background-warning: hsl(40deg, 100%, 30%);
+
+// Buttons
+$neutral-button-color: hsl(0deg, 0%, 35%);
+$neutral-button-color-alt: hsl(0deg, 0%, 55%);
+$neutral-button-text-color: hsl(0deg, 0%, 100%);
+$neutral-button-icon-color: $neutral-button-text-color;
+
+// Help Buttons
+$help-button-color: hsl(0deg, 0%, 70%);
+$help-button-color-alt: hsl(0deg, 0%, 60%);
+$help-button-text-color: hsl(0deg, 0%, 10%);
+$help-button-icon-color: $help-button-text-color;
+
+// Selection Colors
+$selection-background-color: hsl(0deg, 0%, 35%);
+$selection-background-text-color: hsl(0deg, 0%, 100%);
+
+// Other
+$form-field-body-color: $background-dark;
+$bottom-splitter-color: hsl(0deg, 0%, 5%);
+
+// Some icons are black and do not respect the 'color' style property.
+// For the dark mode these can be turned grey or white with the
+// 'filter: invert(value)' attribute
+$icon-brightness: lightness($icon-color);
+
+// Spam score colors
+
+// for spam scores with an absolute score >= 3
+$spam-high-neg: hsl(205deg, 65%, 20%);
+$spam-high-pos: hsl(360deg, 55%, 20%);
+
+// for spam scores with an absolute score between 0.1 and 3
+$spam-mid-neg: hsl(205deg, 65%, 30%);
+$spam-mid-pos: hsl(360deg, 55%, 30%);
+
+// for spam scores with an absolute score <= 0.1
+$spam-low-neg: hsl(205deg, 65%, 40%);
+$spam-low-pos: hsl(360deg, 55%, 40%);
diff --git a/src/proxmox-dark/scss/extjs/_body.scss b/src/proxmox-dark/scss/extjs/_body.scss
new file mode 100644
index 0000000..2fc6161
--- /dev/null
+++ b/src/proxmox-dark/scss/extjs/_body.scss
@@ -0,0 +1,23 @@
+// Chrome 81, Firefox 96 and Safari 13 support a dark version of the
+// scrollbar and form controls source
+// https://stackoverflow.com/q/65940522
+:root {
+  color-scheme: dark;
+}
+
+.x-body {
+  color: $text-color;
+  background-color: $background-darkest;
+}
+
+// Should be the absolute background of the document
+.x-viewport > .x-body {
+  background-color: $background-darkest;
+}
+
+// necessary for some masks to work properly (e.g. when hidding the
+// attachment grid in pmg)
+body.x-border-layout-ct,
+div.x-border-layout-ct {
+  background-color: $background-darkest;
+}
diff --git a/src/proxmox-dark/scss/extjs/_grid.scss b/src/proxmox-dark/scss/extjs/_grid.scss
new file mode 100644
index 0000000..77872b0
--- /dev/null
+++ b/src/proxmox-dark/scss/extjs/_grid.scss
@@ -0,0 +1,146 @@
+.x-column-header {
+  border-color: $border-color-alt;
+}
+
+.x-grid-item,
+.x-column-header-default,
+// the row number field (e.g. in the ipsets in pve)
+.x-grid-cell-row-numberer {
+  color: $text-color;
+  background-color: $background-darker;
+}
+
+// Trigger in grid/table header cells
+.x-column-header-trigger {
+  border-color: $border-color;
+}
+
+.x-grid-cell-special {
+  border-color: $border-color-alt;
+}
+
+.x-grid-group-hd {
+  background-color: $background-darker;
+  border-color: $border-color-alt;
+}
+
+.x-grid-group-title {
+  color: $text-color;
+}
+
+// Border-top in tables
+.x-grid-header-ct {
+  border: solid 1px $background-dark;
+  background-color: $background-dark;
+}
+
+// alternating row colors
+.x-grid-item-alt {
+  background-color: $background-darkest;
+}
+
+.x-grid-with-row-lines {
+  .x-grid-item {
+    border-color: $border-color-alt;
+    border-right: 0;
+
+    // A border at the bottom of tables
+    &:last-child {
+      border-color: $border-color-alt;
+    }
+
+    // A border at the top of tables
+    &:first-child {
+      border-color: $border-color-alt;
+    }
+
+    // hovered row in a grid
+    &.x-grid-item-over,
+    &.x-grid-item-selected {
+      background-color: $selection-background-color;
+      border-color: $border-color-alt;
+    }
+  }
+
+  // borders on selected elements
+  .x-grid-item-selected + .x-grid-item,
+  .x-grid-item-over + .x-grid-item {
+    border-color: $border-color-alt;
+  }
+}
+
+// Sometimes a selected node in the ResourceTree loses the
+// selection-background-color
+.x-grid-item-over,
+.x-grid-item-selected {
+  // Otherwise .x-grid-item overrides the background color
+  background-color: $selection-background-color;
+}
+
+// Hovering over a grid/table header cell
+.x-column-header-over,
+// When opening the sort/settings header of a table/grid header cell
+.x-column-header-open,
+.x-column-header-last .x-column-header-over .x-column-header-trigger, {
+  background-color: $content-background-selected;
+}
+
+// header element that the grid is currently sorted by
+.x-column-header-sort-ASC,
+.x-column-header-sort-DESC {
+  background-color: $primary-dark;
+}
+
+// summary rows (e.g. ceph pools last row)
+.x-grid-row-summary {
+  .x-grid-cell,
+  .x-grid-rowwrap,
+  .x-grid-cell-rowbody {
+    border-color: $border-color-alt;
+    background-color: $background-darker;
+  }
+}
+
+.x-grid-with-col-lines {
+  .x-grid-cell,
+  .x-grid-item-over .x-grid-cell,
+  .x-grid-item-selected .x-grid-cell {
+    border-color: $border-color-alt;
+  }
+}
+
+// drag and drop proxy
+.x-dd-drag-proxy {
+  background-color: $background-darkest;
+  border-color: $border-color-alt;
+  color: $text-color;
+}
+
+.x-keyboard-mode .x-grid-item-focused {
+  @include selection;
+
+  .x-grid-cell-inner::before {
+    border-color: $primary-color;
+  }
+}
+
+// Grid/table headers that are selected and active
+.x-keyboard-mode .x-column-header.x-column-header-focus {
+  color: $text-color;
+
+  // Elements in table
+  .x-column-header-inner::after {
+    border-color: $primary-color;
+  }
+}
+
+.x-keyboard-mode .proxmox-invalid-row .x-grid-item-focused {
+  background-color: $background-invalid;
+}
+
+// As far as I can tell only used under Node > "System" >
+// "Certificates"
+.x-grid-empty {
+  background-color: $background-darker;
+  color: $text-color;
+}
diff --git a/src/proxmox-dark/scss/extjs/_menu.scss b/src/proxmox-dark/scss/extjs/_menu.scss
new file mode 100644
index 0000000..74be901
--- /dev/null
+++ b/src/proxmox-dark/scss/extjs/_menu.scss
@@ -0,0 +1,39 @@
+.x-menu-default {
+  border-color: $form-field-body-color;
+}
+
+.x-menu-body-default {
+  background-color: $form-field-body-color;
+}
+
+// E.g. the content menu in the resource tree displays a header
+.x-menu-header {
+  background-color: $primary-color;
+}
+
+.x-menu-item-default {
+  // Horizontal divider in menu (e.g. in UserInfo above "Logout")
+  &.x-menu-item-separator {
+    background-color: $background-dark;
+    border-color: $border-color;
+  }
+
+  // When hovering over a menu item
+  &.x-menu-item-focus {
+    @include selection;
+  }
+}
+
+.x-menu-item-text-default {
+  color: $text-color;
+}
+
+.x-menu-item-icon-default {
+  color: $icon-color;
+}
+
+// Vertical divider (e.g. in UserInfo between icons and text)
+.x-menu-icon-separator-default {
+  background-color: $background-dark;
+  border-color: $border-color;
+}
diff --git a/src/proxmox-dark/scss/extjs/_panel.scss b/src/proxmox-dark/scss/extjs/_panel.scss
new file mode 100644
index 0000000..5344c8f
--- /dev/null
+++ b/src/proxmox-dark/scss/extjs/_panel.scss
@@ -0,0 +1,25 @@
+.x-panel-header-default {
+  background-color: $content-background-color;
+  border: none;
+
+  // The small navigation elements in the panel header bar e.g. to
+  // collapse a panel
+  .x-tool-tool-el {
+    background-color: transparent;
+    filter: brightness(120%);
+  }
+
+  .x-tool-over .x-tool-tool-el {
+    filter: brightness(140%);
+  }
+}
+
+.x-panel-header-title-default {
+  color: $highlighted-text;
+}
+
+.x-panel-body-default {
+  background-color: $background-darker;
+  border-color: $border-color-alt;
+  color: $text-color;
+}
diff --git a/src/proxmox-dark/scss/extjs/_presentation.scss b/src/proxmox-dark/scss/extjs/_presentation.scss
new file mode 100644
index 0000000..c7d3c8f
--- /dev/null
+++ b/src/proxmox-dark/scss/extjs/_presentation.scss
@@ -0,0 +1,14 @@
+// The mask that is applied when the window is unaccessible (Login
+// screen, Loading, ...)
+.x-mask {
+  background-color: $background-darker;
+  opacity: 0.85;
+}
+
+// Shadows of floating windows like window modals, form selectors and
+// message boxes
+.x-css-shadow {
+  // the additional styling from the pve css overwrites the setting on
+  // the element with "!important", that's why we need it here.
+  box-shadow: $background-darkest 0 0 5px !important;
+}
diff --git a/src/proxmox-dark/scss/extjs/_progress.scss b/src/proxmox-dark/scss/extjs/_progress.scss
new file mode 100644
index 0000000..4f2bb49
--- /dev/null
+++ b/src/proxmox-dark/scss/extjs/_progress.scss
@@ -0,0 +1,19 @@
+.x-progress-default {
+  background-color: $form-field-body-color;
+
+  .x-progress-bar-default {
+    background-color: $primary-color; // Taken from the chart
+  }
+
+  .x-progress-text {
+    color: $text-color;
+  }
+}
+
+.x-progress.warning .x-progress-bar {
+  background-color: $background-warning;
+}
+
+.x-progress.critical .x-progress-bar {
+  background-color: $background-invalid;
+}
diff --git a/src/proxmox-dark/scss/extjs/_splitter.scss b/src/proxmox-dark/scss/extjs/_splitter.scss
new file mode 100644
index 0000000..ad3d6a8
--- /dev/null
+++ b/src/proxmox-dark/scss/extjs/_splitter.scss
@@ -0,0 +1,18 @@
+// Splitters separating two views (e.g. Firewall > "Security Group",
+// "IPSet", ...)
+.x-splitter {
+  background-color: $background-darkest;
+}
+
+.x-splitter-horizontal {
+  background-color: $bottom-splitter-color;
+}
+
+// Splitters that separate content and resize parts of the window
+.x-keyboard-mode .x-splitter-focus::after {
+  border-color: $primary-color;
+}
+
+.x-layout-split-bottom {
+  opacity: 0.7;
+}
diff --git a/src/proxmox-dark/scss/extjs/_tabbar.scss b/src/proxmox-dark/scss/extjs/_tabbar.scss
new file mode 100644
index 0000000..e1b5f66
--- /dev/null
+++ b/src/proxmox-dark/scss/extjs/_tabbar.scss
@@ -0,0 +1,43 @@
+// The header of the tabbar
+.x-tab-bar-default {
+  background-color: $background-darker;
+}
+
+.x-tab-default {
+  // Hovering over a tab button
+  &.x-tab-over {
+    background-color: $primary-dark;
+    border-color: $primary-dark;
+  }
+
+  // Selected tab buttons
+  &.x-tab.x-tab-active {
+    background-color: $primary-light;
+    border-color: $primary-light;
+  }
+
+  // Disabled tab buttons
+  &.x-tab.x-tab-disabled {
+    background-color: $background-darker;
+
+    // make the border invisible so it matches the light theme, setting
+    // it to none messes with the allignment of the elements.
+    border-color: transparent;
+    color: $text-color;
+  }
+
+  .x-keyboard-mode &.x-tab-focus.x-tab-active {
+    background-color: $primary-color;
+    border-color: $primary-color;
+  }
+}
+
+// Not selected tab buttons
+.x-tab-default-top {
+  background-color: $background-darker;
+  border-color: $background-darker;
+}
+
+.x-tab-inner-default {
+  color: $text-color;
+}
diff --git a/src/proxmox-dark/scss/extjs/_tip.scss b/src/proxmox-dark/scss/extjs/_tip.scss
new file mode 100644
index 0000000..0c2cb6a
--- /dev/null
+++ b/src/proxmox-dark/scss/extjs/_tip.scss
@@ -0,0 +1,18 @@
+.x-tip-default {
+  background-color: $background-darkest;
+  border-color: $border-color-alt;
+}
+
+.x-tip-body-default {
+  color: $text-color;
+}
+
+// Form error tip
+.x-tip-form-invalid {
+  background-color: $background-dark;
+  border-color: $border-color-alt;
+}
+
+.x-tip-body-form-invalid {
+  color: $text-color;
+}
diff --git a/src/proxmox-dark/scss/extjs/_toolbar.scss b/src/proxmox-dark/scss/extjs/_toolbar.scss
new file mode 100644
index 0000000..2ea8527
--- /dev/null
+++ b/src/proxmox-dark/scss/extjs/_toolbar.scss
@@ -0,0 +1,21 @@
+.x-toolbar {
+  background-color: $background-darker;
+}
+
+.x-toolbar-default {
+  background-color: $background-darker;
+  border: solid 3px $background-darkest;
+
+  &.x-docked-top {
+    border-width: 1px;
+    border-color: $border-color-alt;
+  }
+
+  .x-toolbar-separator {
+    border-color: $border-color;
+  }
+}
+
+.x-toolbar-text-default {
+  color: $text-color;
+}
diff --git a/src/proxmox-dark/scss/extjs/_treepanel.scss b/src/proxmox-dark/scss/extjs/_treepanel.scss
new file mode 100644
index 0000000..0480371
--- /dev/null
+++ b/src/proxmox-dark/scss/extjs/_treepanel.scss
@@ -0,0 +1,24 @@
+// individual rows in tree lists (e.g. the menu in the "middle")
+.x-treelist-item {
+  background-color: $background-darker;
+}
+
+.x-treelist-item-text,
+.x-treelist-item-icon,
+.x-treelist-row-over .x-treelist-item-icon,
+.x-treelist-row-over .x-treelist-item-text {
+  color: $text-color;
+}
+
+.x-treelist-item-selected > .x-treelist-row {
+  background-color: $primary-color;
+}
+
+.x-treelist-row-over {
+  background-color: $selection-background-color;
+}
+
+.x-treelist-pve-nav {
+  background-color: $background-darker;
+  border-color: $border-color;
+}
diff --git a/src/proxmox-dark/scss/extjs/_window.scss b/src/proxmox-dark/scss/extjs/_window.scss
new file mode 100644
index 0000000..0fe188d
--- /dev/null
+++ b/src/proxmox-dark/scss/extjs/_window.scss
@@ -0,0 +1,39 @@
+.x-window-default {
+  background-color: $background-darkest;
+
+  // make the color transparent so the border doesn't appear visibly,
+  // like in crisp, but keep to keep the layout intact
+  border-color: transparent;
+}
+
+.x-window-header-default {
+  background-color: $background-darker;
+
+  // make the color transparent so the border doesn't appear visibly,
+  // like in crisp, but keep to keep the layout intact
+  border-color: transparent;
+}
+
+.x-window-header-title-default {
+  color: $highlighted-text;
+}
+
+.x-window-body-default {
+  background-color: $background-darker;
+  border-color: $border-color-alt;
+  color: $text-color;
+}
+
+// Window when dragged
+.x-window-ghost {
+  background-color: $background-darker;
+}
+
+// The X in the right upper corner of closable windows
+.x-window-header-default .x-tool-img {
+  background-color: transparent;
+}
+
+.x-message-box .x-window-body {
+  background-color: $background-dark;
+}
diff --git a/src/proxmox-dark/scss/extjs/form/_button.scss b/src/proxmox-dark/scss/extjs/form/_button.scss
new file mode 100644
index 0000000..0aa1475
--- /dev/null
+++ b/src/proxmox-dark/scss/extjs/form/_button.scss
@@ -0,0 +1,57 @@
+// The "main" buttons like Login, Create, ...
+.x-btn-default-small {
+  background-color: $primary-color;
+  border-color: $primary-color;
+
+  &.x-btn-over,
+  .x-keyboard-mode &.x-btn-focus {
+    background-color: $primary-light;
+    border-color: $primary-light;
+  }
+
+  &.x-btn.x-btn-disabled {
+    background-color: $primary-color;
+  }
+
+  &.x-btn.x-btn-pressed {
+    background-color: $primary-dark;
+    border-color: $primary-color;
+  }
+}
+
+// toolbar butons
+.x-btn-default-toolbar-small {
+  background-color: $neutral-button-color;
+  border-color: $neutral-button-color-alt;
+
+  .x-btn-inner-default-toolbar-small {
+    color: $neutral-button-text-color;
+  }
+
+  .x-btn-icon-el-default-toolbar-small {
+    color: $neutral-button-icon-color;
+  }
+
+  &.x-btn-over,
+  .x-keyboard-mode &.x-btn-focus {
+    background-color: $neutral-button-color-alt;
+
+    // the little arrow in certain toolbar buttons with dropdowns
+    .x-btn-wrap-default-toolbar-small.x-btn-arrow-right::after,
+    .x-btn-wrap-default-toolbar-small.x-btn-split-right::after {
+      filter: invert($icon-brightness);
+    }
+  }
+
+  &.x-btn.x-btn-disabled {
+    // Note: extJS already sets transparency on disabled buttons
+    background-color: $neutral-button-color;
+  }
+
+  // toggled state of toggle buttons (e.g. filter in task history)
+  &.x-btn.x-btn-menu-active,
+  &.x-btn.x-btn-pressed {
+    background-color: $primary-dark;
+    border-color: $primary-color;
+  }
+}
diff --git a/src/proxmox-dark/scss/extjs/form/_combobox.scss b/src/proxmox-dark/scss/extjs/form/_combobox.scss
new file mode 100644
index 0000000..a6405a1
--- /dev/null
+++ b/src/proxmox-dark/scss/extjs/form/_combobox.scss
@@ -0,0 +1,23 @@
+// Combobox "expand" trigger
+.x-form-trigger-default {
+  background-color: $form-field-body-color;
+}
+
+.x-boundlist {
+  border-color: $form-field-body-color;
+}
+
+// Combobox item
+.x-boundlist-item {
+  background-color: $form-field-body-color;
+  border-color: $form-field-body-color;
+  color: $text-color;
+}
+
+.x-boundlist-selected {
+  background-color: mix(black, $selection-background-color, 20%);
+}
+
+.x-boundlist-item-over {
+  background-color: $selection-background-color;
+}
diff --git a/src/proxmox-dark/scss/extjs/form/_formfield.scss b/src/proxmox-dark/scss/extjs/form/_formfield.scss
new file mode 100644
index 0000000..13f0622
--- /dev/null
+++ b/src/proxmox-dark/scss/extjs/form/_formfield.scss
@@ -0,0 +1,40 @@
+// displayfields in forms (e.g. the guest os header in the vm creation
+// form)
+.x-form-display-field-default {
+  color: $text-color;
+}
+
+// The body of a text form field
+.x-form-text-default {
+  background-color: $form-field-body-color;
+  color: $text-color;
+}
+
+// Unselected form field
+.x-form-trigger-wrap-default {
+  border-color: $form-field-body-color;
+
+  // Focused form field
+  &.x-form-trigger-wrap-focus {
+    border-color: mix(black, $primary-color, 3%);
+  }
+}
+
+// Labels
+.x-form-item-label-default {
+  color: $text-color;
+}
+
+// number field arrow up and down buttons
+.x-form-spinner-default {
+  background-color: $form-field-body-color;
+}
+
+.x-form-cb-label-default {
+  color: $icon-color;
+}
+
+// Fieldsets used in e.g. the personal settings
+.x-fieldset-default {
+  border-color: $border-color-alt;
+}
diff --git a/src/proxmox-dark/scss/other/_charts.scss b/src/proxmox-dark/scss/other/_charts.scss
new file mode 100644
index 0000000..5c67282
--- /dev/null
+++ b/src/proxmox-dark/scss/other/_charts.scss
@@ -0,0 +1,39 @@
+// these css variables define the look of all charts and gauges
+:root {
+  // using interpolation here may avoid compatability issues between
+  // sass and css. see:
+  // https://sass-lang.com/documentation/breaking-changes/css-vars
+  --pwt-panel-background: #{$background-darker};
+  --pwt-text-color: #{$text-color};
+  --pwt-gauge-default: #{$primary-color};
+  --pwt-gauge-back: #{$background-dark};
+  --pwt-gauge-warn: #{$background-warning};
+  --pwt-gauge-crit: #{$background-invalid};
+  --pwt-chart-primary: #{$primary-color};
+  --pwt-chart-grid-stroke: #{$content-background-selected};
+}
+
+// Peeks out on the edges of the legend item border
+.x-legend-container {
+  background-color: $content-background-color;
+}
+
+.x-legend-horizontal .x-legend-item {
+  background-color: $background-dark;
+  color: $text-color;
+  border-top: solid 1px $background-darkest;
+  border-right: solid 1px $background-darkest;
+  border-bottom: solid 1px $background-darkest;
+
+  &:first-child {
+    border-left: solid 1px $background-darkest;
+  }
+}
+
+// The "undo zoom" button in the upper right corner of charts when
+// disabled
+.x-tool .x-mask {
+  backdrop-filter: none;
+  background-color: $background-dark;
+  opacity: 0.6;
+}
diff --git a/src/proxmox-dark/scss/other/_icons.scss b/src/proxmox-dark/scss/other/_icons.scss
new file mode 100644
index 0000000..f132dae
--- /dev/null
+++ b/src/proxmox-dark/scss/other/_icons.scss
@@ -0,0 +1,200 @@
+// these styling fix all kinds of icons in grid, treeview etc.
+
+// most icons just use the color attribute..
+// Running containers and VMS
+.x-grid-icon-custom.running,
+.x-tree-icon-custom.running,
+// Icons in trees (e.g. Resource tree)
+.x-tree-icon-custom,
+// Icons in panels, e.g. Search tab
+.fa-database::before,
+// Icon for pools
+.fa-tags::before,
+// The template icon
+.fa-file-o::before,
+// Icon for cluster nodes
+.fa-building::before,
+// e.g. storage list when creating a guest
+.x-action-col-icon::before,
+.fa-shield::before,
+.fa-file-text-o::before,
+.fa-clock-o::before,
+// tab bar icons
+.x-tab-icon-el-default,
+.pve-icon-verify-lettering::after,
+// the small plane when migrating a vm
+.x-tree-icon-custom.lock-migrate::after,
+.x-grid-icon-custom.lock-migrate::after,
+// e.g. permission tree view in pve
+.x-tree-icon-leaf:not(.x-tree-icon-custom)::before,
+.x-tree-icon-parent:not(.x-tree-icon-custom)::before,
+.x-tree-icon-parent-expanded:not(.x-tree-icon-custom)::before {
+  color: $icon-color;
+}
+
+// but some are implement as background SVGs or PNGs. invert them via
+// filters:
+.fa-ceph::before,
+.fa-sdn::before,
+.fa-network-wired::before,
+// Icon for "ISO Images" for storages
+.pve-itype-treelist-item-icon-cdrom,
+// Arrow to the right
+.fa-chevron-right::before,
+// icon indicating a currently open shell session in the task viewer
+.x-grid-row-console,
+// the "triangle" that appears when the sidebar becomes scrollable
+.x-box-scroller-toolbar-default.x-box-scroller,
+// the small triangles in the tree view next to nodes etc.
+.x-tree-elbow-img,
+// the computer icon in the resource pool add menu
+.pve-itype-icon-qemu,
+.x-tree-node-computer,
+.x-grid-tree-node-expanded .x-tree-node-computer,
+.pbs-icon-tape,
+.pbs-icon-tape-drive,
+.x-tree-icon-leaf:not(.x-tree-icon-custom),
+// default tree panel icons (api viewer, pbs backup panel)
+.x-tree-icon-parent:not(.x-tree-icon-custom),
+.x-tree-icon-parent-expanded:not(.x-tree-icon-custom) {
+  filter: invert($icon-brightness);
+}
+
+// the following icons need some additional fix-ups to work well in
+// grids (e.g. when hovered etc.)
+// Icon for the processor in VM hardware settings
+.pve-itype-icon-cpu,
+// Icon for memory in VM hardware settings
+.pve-itype-icon-cdrom,
+// Icon for memory in VM hardware settings
+.pve-itype-icon-memory,
+// the pcie device icon in the vm hardware section
+.pve-itype-icon-pci,
+// the serial device icon in the vm hardware section
+.pve-itype-icon-serial,
+// the rng icon in the vm hardware section
+.pve-itype-icon-die,
+// Processor icon for summary page
+.pmx-itype-icon-processor,
+// Memory icon on summary page
+.pmx-itype-icon-memory,
+// the mount point icon for containers
+.pve-itype-icon-storage,
+.x-tree-node-harddisk,
+.x-grid-tree-node-expanded .x-tree-node-harddisk {
+  filter: invert($icon-brightness);
+
+  // the filter also applies to the text next to the icon
+  .x-grid-cell-inner {
+    color: black;
+  }
+
+  .x-grid-cell-inner::before {
+    // this is a somewhat hacky work-around for the focus borders on
+    // these elements. since we use the invert filter to fix the icon
+    // color we need to also invert the border color first too, not
+    // just the text. add "!important" to properly override.
+    border-color: invert($primary-color, $weight: 90%) !important;
+  }
+}
+
+// pbs show task log in longest task list column
+.x-action-col-icon.fa-chevron-right::before {
+  filter: none;
+}
+
+// checkboxes and radio buttons
+.x-form-checkbox-default,
+.x-form-radio-default,
+.x-column-header-checkbox .x-column-header-checkbox::after,
+.x-grid-checkcolumn::after {
+  filter: invert($icon-brightness) hue-rotate(180deg);
+}
+
+.x-tree-icon-custom,
+.x-grid-icon-custom {
+  &::after {
+    color: $icon-color;
+    text-shadow: -1px 0 1px $background-darker;
+  }
+
+  // stopped containers and VMs
+  &.stopped,
+  // vms/cts that are offline
+  &.offline,
+  // question mark at the bottom right of e.g. unreachable storages
+  &.unknown::after {
+    color: $icon-color-alt;
+  }
+
+  &.lxc::after,
+  &.qemu::after {
+    background-color: $background-darker;
+    color: $icon-color;
+  }
+}
+
+// icons for templates in the storages view
+.x-treelist-item-icon {
+  &.lxc::after,
+  &.qemu::after {
+    background-color: $background-darker;
+    color: $icon-color;
+  }
+}
+
+.x-grid-item .x-grid-icon-custom {
+  &.lxc::after,
+  &.qemu::after {
+    background-color: $background-darker;
+  }
+}
+
+.x-grid-item-alt .x-grid-icon-custom {
+  &.lxc::after,
+  &.qemu::after {
+    background-color: $background-darkest;
+  }
+}
+
+.x-treelist-item-selected {
+  .lxc::after,
+  .qemu::after {
+    background-color: $primary-color;
+    text-shadow: -1px 0 1px $primary-color;
+  }
+}
+
+.x-grid-item-over,
+// hovered items in treelists
+.x-treelist-item-over,
+// template icons when in selected menu item or table row
+.x-grid-item-selected,
+// vm/ct that is focused (e.g. by mouse-down)
+.x-keyboard-mode .x-grid-item-focused {
+  .lxc::after,
+  .qemu::after {
+    background-color: $selection-background-color !important;
+    text-shadow: -1px 0 1px $selection-background-color;
+  }
+}
+
+.x-action-col-icon:hover {
+  &::before,
+  &::after {
+    text-shadow: -1px 0 1px $background-darker;
+  }
+}
+
+// The usage icons dynamically displaying how full a storage is
+.usage-wrapper {
+  border: 1px solid $icon-color;
+}
+
+.usage-negative {
+  background-color: transparent;
+}
+
+.usage {
+  background-color: $icon-color;
+}
diff --git a/src/proxmox-dark/scss/proxmox/_datepicker.scss b/src/proxmox-dark/scss/proxmox/_datepicker.scss
new file mode 100644
index 0000000..068e7e6
--- /dev/null
+++ b/src/proxmox-dark/scss/proxmox/_datepicker.scss
@@ -0,0 +1,61 @@
+.x-datepicker,
+.x-datepicker-column-header,
+.x-monthpicker {
+  background-color: $background-darker;
+  color: $text-color;
+
+  // make the border invisible but keep it to keep the layout intact
+  border-color: transparent;
+}
+
+.x-datepicker-month .x-btn-over.x-btn-default-small {
+  background-color: $selection-background-color;
+}
+
+.x-monthpicker-months {
+  border-color: $border-color-alt;
+}
+
+.x-datepicker-header {
+  background-color: $background-darkest;
+}
+
+.x-datepicker-cell,
+.x-monthpicker-item-inner {
+  // make the border invisible but keep it to keep the layout intact
+  border-color: transparent;
+}
+
+.x-datepicker-date,
+.x-monthpicker-item-inner {
+  color: $text-color;
+}
+
+.x-datepicker-prevday,
+.x-datepicker-nextday {
+  .x-datepicker-date {
+    color: $text-color-inactive;
+  }
+}
+
+.x-datepicker-footer,
+.x-monthpicker-buttons {
+  background-color: $background-darkest;
+}
+
+.x-datepicker-selected div.x-datepicker-date,
+.x-monthpicker-item a.x-monthpicker-selected,
+a.x-monthpicker-item-inner:hover,
+div.x-datepicker-date:hover {
+  @include selection;
+}
+
+.x-datepicker-disabled {
+  .x-datepicker-date {
+    background-color: $background-darkest;
+  }
+
+  div.x-datepicker-date:hover {
+    background-color: $background-darker;
+  }
+}
diff --git a/src/proxmox-dark/scss/proxmox/_general.scss b/src/proxmox-dark/scss/proxmox/_general.scss
new file mode 100644
index 0000000..805a187
--- /dev/null
+++ b/src/proxmox-dark/scss/proxmox/_general.scss
@@ -0,0 +1,56 @@
+// Swapping out the logo with CSS rather than using javascript
+img[id^="proxmoxlogo-"][id$="-img"] {
+  filter: invert(1) hue-rotate(180deg);
+}
+
+// removes the gray line in the header of the mail gateway
+div[id^="versioninfo-"] + div[id^="panel-"] > div[id^="panel-"][id$="-bodyWrap"] > div {
+  background-color: transparent;
+  border-color: transparent;
+}
+
+// border around the main datacenter view
+div[id^="PVE-dc-Config-"][id$="-body"],
+// border around the main pool view
+div[id^="pvePoolConfig-"][id$="-body"],
+// Container content config views
+div[id^="pveLXCConfig-"][id$="-body"],
+// VM content config views
+div[id^="PVE-qemu-Config-"][id$="-body"],
+div[id^="PVE-storage-Browser-"][id$="-body"],
+div[id^="PVE-node-Config-"][id$="-body"] {
+  @include content-border;
+}
+
+// Section header in the "My Settings" page
+.x-fieldset-header-default > .x-fieldset-header-text {
+  color: $text-color;
+}
+
+// Errors and bad configuration (Taskviewer / no repository enabled)
+.proxmox-invalid-row {
+  background-color: $background-invalid;
+}
+
+// Warning rows, e.g. when enabling staging or no-subscription
+// repository
+.proxmox-warning-row {
+  background-color: $background-warning;
+}
+
+// Disabled rows (e.g. disabled repos in Repository view)
+.proxmox-disabled-row td {
+  color: $text-color-inactive;
+}
+
+.pmx-hint {
+  background-color: $background-warning;
+}
+
+.pmx-hint a {
+  color: $highlighted-text-alt;
+}
+
+.pmx-hint a:active {
+  color: $highlighted-text;
+}
diff --git a/src/proxmox-dark/scss/proxmox/_helpbutton.scss b/src/proxmox-dark/scss/proxmox/_helpbutton.scss
new file mode 100644
index 0000000..aad92e2
--- /dev/null
+++ b/src/proxmox-dark/scss/proxmox/_helpbutton.scss
@@ -0,0 +1,16 @@
+// help buttons
+.proxmox-inline-button {
+  background-color: $help-button-color;
+  color: $help-button-text-color;
+
+  &.x-btn-over,
+  &.x-btn.x-btn-pressed.x-btn-default-toolbar-small {
+    background-color: $help-button-color-alt;
+    border-color: $help-button-color-alt;
+  }
+
+  .x-btn-inner,
+  .x-btn-icon-el {
+    color: $help-button-icon-color;
+  }
+}
diff --git a/src/proxmox-dark/scss/proxmox/_loadingindicator.scss b/src/proxmox-dark/scss/proxmox/_loadingindicator.scss
new file mode 100644
index 0000000..5c320b3
--- /dev/null
+++ b/src/proxmox-dark/scss/proxmox/_loadingindicator.scss
@@ -0,0 +1,14 @@
+// loading spinners
+.x-grid-row-loading,
+.x-treelist-item-loading .x-treelist-item-icon,
+.x-treelist-nav .x-treelist-item-loading .x-treelist-item-icon,
+.x-mask-msg-text,
+.x-grid-tree-loading .x-tree-icon {
+  filter: invert($icon-brightness);
+  color: black;
+}
+
+.x-mask-msg {
+  background-color: $form-field-body-color;
+  border: solid 1px mix(black, $form-field-body-color, 25%);
+}
diff --git a/src/proxmox-dark/scss/proxmox/_markdown.scss b/src/proxmox-dark/scss/proxmox/_markdown.scss
new file mode 100644
index 0000000..8531701
--- /dev/null
+++ b/src/proxmox-dark/scss/proxmox/_markdown.scss
@@ -0,0 +1,31 @@
+.pmx-md {
+  code {
+    background-color: $background-darkest;
+  }
+
+  pre code {
+    border-color: $border-color-alt;
+  }
+
+  tbody tr {
+    & td {
+      border-color: $border-color;
+    }
+
+    &:nth-of-type(2n) {
+      background-color: $background-darkest;
+    }
+
+    &:hover td {
+      background-color: $content-background-selected;
+    }
+  }
+
+  a {
+    color: $highlighted-text;
+
+    &:active {
+      color: $highlighted-text-alt;
+    }
+  }
+}
diff --git a/src/proxmox-dark/scss/proxmox/_nodes.scss b/src/proxmox-dark/scss/proxmox/_nodes.scss
new file mode 100644
index 0000000..02b15f9
--- /dev/null
+++ b/src/proxmox-dark/scss/proxmox/_nodes.scss
@@ -0,0 +1,9 @@
+// Table headers under Node > "Updates" > "Repositories"
+.proxmox-apt-repos .x-grid-group-hd {
+  background-color: $background-darker;
+  border-bottom-width: 0;
+}
+
+.proxmox-apt-repos .x-grid-group-title {
+  color: $text-color;
+}
diff --git a/src/proxmox-dark/scss/proxmox/_quarantine.scss b/src/proxmox-dark/scss/proxmox/_quarantine.scss
new file mode 100644
index 0000000..bdda69a
--- /dev/null
+++ b/src/proxmox-dark/scss/proxmox/_quarantine.scss
@@ -0,0 +1,47 @@
+// these css variables define the look of the spamscore grid in pmg
+:root {
+  // using interpolation here may avoid compatability issues between
+  // sass and css. see:
+  // https://sass-lang.com/documentation/breaking-changes/css-vars
+  // for spam with an absolute score >= 3
+  --pmg-spam-high-neg: #{$spam-high-neg};
+  --pmg-spam-high-pos: #{$spam-high-pos};
+
+  // for spam with an absolute score between 0.1 and 3
+  --pmg-spam-mid-neg: #{$spam-mid-neg};
+  --pmg-spam-mid-pos: #{$spam-mid-pos};
+
+  // for spam with an absolute score <= 0.1
+  --pmg-spam-low-neg: #{$spam-low-neg};
+  --pmg-spam-low-pos: #{$spam-low-pos};
+}
+
+.info-blue {
+  // the selector for the button icons have higher specificity than
+  // this one, so we need "!important"
+  color: $highlighted-text !important;
+}
+
+.critical {
+  // the selector for the button icons have higher specificity than
+  // this one, so we need "!important"
+  color: $highlighted-text-crit !important;
+}
+
+// pmg tracking center quarantined rows
+tr.blocked,
+.x-keyboard-mode tr.blocked .x-grid-item-focused {
+  background-color: $background-invalid;
+}
+
+// pmg tracking center quarantined rows
+tr.quarantine,
+.x-keyboard-mode tr.quarantine .x-grid-item-focused {
+  background-color: mix($background-warning, $background-invalid, 50%);
+}
+
+// pmg tracking center blocked rows
+tr.bounced,
+.x-keyboard-mode tr.bounced .x-grid-item-focused {
+  background-color: $background-warning;
+}
diff --git a/src/proxmox-dark/scss/proxmox/_storages.scss b/src/proxmox-dark/scss/proxmox/_storages.scss
new file mode 100644
index 0000000..46b94f4
--- /dev/null
+++ b/src/proxmox-dark/scss/proxmox/_storages.scss
@@ -0,0 +1,19 @@
+// ceph page
+table.osds {
+  tr {
+    border-color: $border-color;
+  }
+
+  td {
+    border-color: $border-color;
+  }
+}
+
+.install-mask {
+  background-color: $background-darker;
+  color: $text-color;
+}
+
+div.monitor {
+  border-color: $border-color;
+}
diff --git a/src/proxmox-dark/scss/proxmox/_tags.scss b/src/proxmox-dark/scss/proxmox/_tags.scss
new file mode 100644
index 0000000..09ad623
--- /dev/null
+++ b/src/proxmox-dark/scss/proxmox/_tags.scss
@@ -0,0 +1,14 @@
+.pve-edit-tag.editable span {
+  background-color: $form-field-body-color;
+  color: $text-color;
+  border-color: $border-color;
+}
+
+// adds a bit of outline to make tags stand out more
+.proxmox-tags-full,
+.proxmox-tags-circle {
+  .proxmox-tag-light,
+  .proxmox-tag-dark {
+    outline: 1px solid rgba($background-dark, 0.3);
+  }
+}
-- 
2.30.2





WARNING: multiple messages have this Message-ID
From: Stefan Sterz <s.sterz@proxmox.com>
To: pve-devel@lists.proxmox.com, pbs-devel@lists.proxmox.com,
	pmg-devel@lists.proxmox.com
Subject: [pbs-devel] [PATCH widget-toolkit v1 1/6] dark-theme: add initial version of the proxmox-dark theme
Date: Wed,  8 Mar 2023 17:33:12 +0100	[thread overview]
Message-ID: <20230308163312.2441849-1-s.sterz@proxmox.com> (raw)
In-Reply-To: <20230308161840.2396113-1-s.sterz@proxmox.com>

From: Daniel Tschlatscher <d.tschlatscher@proxmox.com>

adds an initial version of a dark theme for all proxmox products. the
theme works by simply loading an additional css file that adjust the
colors of the original theme "crisp" to be more suitable for a dark
theme.

the theme itself is written in scss, so we need to add sassc as a
build dependency. while sassc is deprecated, it is still maintained in
the debian repositories and, thus, needs no additional packaging on
our end.

this version adds the following on-top of Daniel Tschlatscher's
original draft:

* removes checked-in build artifacts and other stuff that shouldn't be
  tracked
* code clean-up and removal of redundant code
* refactors:
    * icon styling
    * color handling for charts (moved to css variables)
    * color variables, consolidates them and makes the "functional"
    * color values, improves contrast and makes the theme appear more
      consistent
    * using the "theme-" prefix
* adds:
    * markdown note styles
    * combo-box trigger styles
    * even more icon styles (e.g., template icons, check boxes etc.)
    * loading spinners styles
    * number field up and down arrow styles
    * an additional auto theme that switches between light and dark
      theme dynamically
    * widget toolkit hints
    * ceph install mask
    * grid group headers
    * color to toggled buttons
    * date picker styles
    * drag and drop proxy styles
* fixes:
    * contrast on control elements for "scrollable" sidebars
    * make the general appearance closer to the light theme ("crisp")
    * buttons (when hovered, toggled etc)
    * background masking (e.g., when showing the log-in form)
    * grid header separator (adds an outline)
    * separator lines in some menus
    * makes the custom unknown icon more discernible
    * makes headers more readable
    * color adjustments to several components for consistency
    * reduces brightness of dividers in toolbars
    * border color on chart legend elements
    * removes a black border from docked toolbars (e.g., tag edit)
    * dims the "invalid" color to appear less aggressive
    * add hover effects in grids and make them consistent with "crisp"
    * summary rows
    * selected and hovered elements in boundlists
    * row numberers in grids
    * contrast of links in hints
    * ceph overview border colors (e.g., OSD in/out/up/down grid)
    * bottom splitter contrast in certain situations
    * tag visibility
    * pbs compatibility (help buttons stylings, icons, tabs)
    * pmg compatibility:
         * remove border around the spanning element in the header
         * style spam score grid
         * style tracking center rows
         * add appropriate colors to buttons in the quarantine
         * style mail-info element in the quarantine

Co-authored-by: Daniel Tschlatscher <d.tschlatscher@proxmox.com>
Co-authored-by: Stefan Sterz <s.sterz@proxmox.com>
Signed-off-by: Daniel Tschlatscher <d.tschlatscher@proxmox.com>
Signed-off-by: Stefan Sterz <s.sterz@proxmox.com>
---
 debian/control                                |   1 +
 src/Makefile                                  |   2 +-
 src/defines.mk                                |   1 +
 src/proxmox-dark/Makefile                     |  47 ++++
 src/proxmox-dark/scss/ProxmoxDark.scss        |  37 ++++
 src/proxmox-dark/scss/abstracts/_mixins.scss  |  12 ++
 .../scss/abstracts/_variables.scss            |  67 ++++++
 src/proxmox-dark/scss/extjs/_body.scss        |  23 ++
 src/proxmox-dark/scss/extjs/_grid.scss        | 146 +++++++++++++
 src/proxmox-dark/scss/extjs/_menu.scss        |  39 ++++
 src/proxmox-dark/scss/extjs/_panel.scss       |  25 +++
 .../scss/extjs/_presentation.scss             |  14 ++
 src/proxmox-dark/scss/extjs/_progress.scss    |  19 ++
 src/proxmox-dark/scss/extjs/_splitter.scss    |  18 ++
 src/proxmox-dark/scss/extjs/_tabbar.scss      |  43 ++++
 src/proxmox-dark/scss/extjs/_tip.scss         |  18 ++
 src/proxmox-dark/scss/extjs/_toolbar.scss     |  21 ++
 src/proxmox-dark/scss/extjs/_treepanel.scss   |  24 +++
 src/proxmox-dark/scss/extjs/_window.scss      |  39 ++++
 src/proxmox-dark/scss/extjs/form/_button.scss |  57 +++++
 .../scss/extjs/form/_combobox.scss            |  23 ++
 .../scss/extjs/form/_formfield.scss           |  40 ++++
 src/proxmox-dark/scss/other/_charts.scss      |  39 ++++
 src/proxmox-dark/scss/other/_icons.scss       | 200 ++++++++++++++++++
 .../scss/proxmox/_datepicker.scss             |  61 ++++++
 src/proxmox-dark/scss/proxmox/_general.scss   |  56 +++++
 .../scss/proxmox/_helpbutton.scss             |  16 ++
 .../scss/proxmox/_loadingindicator.scss       |  14 ++
 src/proxmox-dark/scss/proxmox/_markdown.scss  |  31 +++
 src/proxmox-dark/scss/proxmox/_nodes.scss     |   9 +
 .../scss/proxmox/_quarantine.scss             |  47 ++++
 src/proxmox-dark/scss/proxmox/_storages.scss  |  19 ++
 src/proxmox-dark/scss/proxmox/_tags.scss      |  14 ++
 33 files changed, 1221 insertions(+), 1 deletion(-)
 create mode 100644 src/proxmox-dark/Makefile
 create mode 100644 src/proxmox-dark/scss/ProxmoxDark.scss
 create mode 100644 src/proxmox-dark/scss/abstracts/_mixins.scss
 create mode 100644 src/proxmox-dark/scss/abstracts/_variables.scss
 create mode 100644 src/proxmox-dark/scss/extjs/_body.scss
 create mode 100644 src/proxmox-dark/scss/extjs/_grid.scss
 create mode 100644 src/proxmox-dark/scss/extjs/_menu.scss
 create mode 100644 src/proxmox-dark/scss/extjs/_panel.scss
 create mode 100644 src/proxmox-dark/scss/extjs/_presentation.scss
 create mode 100644 src/proxmox-dark/scss/extjs/_progress.scss
 create mode 100644 src/proxmox-dark/scss/extjs/_splitter.scss
 create mode 100644 src/proxmox-dark/scss/extjs/_tabbar.scss
 create mode 100644 src/proxmox-dark/scss/extjs/_tip.scss
 create mode 100644 src/proxmox-dark/scss/extjs/_toolbar.scss
 create mode 100644 src/proxmox-dark/scss/extjs/_treepanel.scss
 create mode 100644 src/proxmox-dark/scss/extjs/_window.scss
 create mode 100644 src/proxmox-dark/scss/extjs/form/_button.scss
 create mode 100644 src/proxmox-dark/scss/extjs/form/_combobox.scss
 create mode 100644 src/proxmox-dark/scss/extjs/form/_formfield.scss
 create mode 100644 src/proxmox-dark/scss/other/_charts.scss
 create mode 100644 src/proxmox-dark/scss/other/_icons.scss
 create mode 100644 src/proxmox-dark/scss/proxmox/_datepicker.scss
 create mode 100644 src/proxmox-dark/scss/proxmox/_general.scss
 create mode 100644 src/proxmox-dark/scss/proxmox/_helpbutton.scss
 create mode 100644 src/proxmox-dark/scss/proxmox/_loadingindicator.scss
 create mode 100644 src/proxmox-dark/scss/proxmox/_markdown.scss
 create mode 100644 src/proxmox-dark/scss/proxmox/_nodes.scss
 create mode 100644 src/proxmox-dark/scss/proxmox/_quarantine.scss
 create mode 100644 src/proxmox-dark/scss/proxmox/_storages.scss
 create mode 100644 src/proxmox-dark/scss/proxmox/_tags.scss

diff --git a/debian/control b/debian/control
index 41093f3..71c48c4 100644
--- a/debian/control
+++ b/debian/control
@@ -5,6 +5,7 @@ Maintainer: Proxmox Support Team <support@proxmox.com>
 Build-Depends: debhelper (>= 12~),
                libjs-marked,
                pve-eslint (>= 7.28.0),
+               sassc,
 Standards-Version: 4.5.1
 Homepage: https://www.proxmox.com
 
diff --git a/src/Makefile b/src/Makefile
index 95da5aa..54727f6 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -1,6 +1,6 @@
 include defines.mk
 
-SUBDIRS= css images
+SUBDIRS= css images proxmox-dark
 
 # bundle it for now from the libjs-marked debian package to avoid touching our proxies file mapper,
 # we could also just ship a link to the packages file and load from same path as the widget-toolkit
diff --git a/src/defines.mk b/src/defines.mk
index d6bdd2c..2a65e9d 100644
--- a/src/defines.mk
+++ b/src/defines.mk
@@ -3,3 +3,4 @@ DOCDIR=${DESTDIR}/usr/share/doc/${PACKAGE}
 WWWBASEDIR=${DESTDIR}/usr/share/javascript/${PACKAGE}
 WWWCSSDIR=${WWWBASEDIR}/css
 WWWIMAGESDIR=${WWWBASEDIR}/images
+WWWTHEMEDIR=${WWWBASEDIR}/themes
diff --git a/src/proxmox-dark/Makefile b/src/proxmox-dark/Makefile
new file mode 100644
index 0000000..2ac6f22
--- /dev/null
+++ b/src/proxmox-dark/Makefile
@@ -0,0 +1,47 @@
+include ../defines.mk
+
+SCSSSRC=scss/ProxmoxDark.scss 			\
+	scss/abstracts/_mixins.scss 		\
+	scss/abstracts/_variables.scss 		\
+	scss/extjs/_body.scss 			\
+	scss/extjs/form/_button.scss 		\
+	scss/extjs/form/_combobox.scss 		\
+	scss/extjs/form/_formfield.scss 	\
+	scss/extjs/_grid.scss 			\
+	scss/extjs/_menu.scss 			\
+	scss/extjs/_panel.scss 			\
+	scss/extjs/_presentation.scss 		\
+	scss/extjs/_progress.scss 		\
+	scss/extjs/_splitter.scss 		\
+	scss/extjs/_tabbar.scss 		\
+	scss/extjs/_tip.scss 			\
+	scss/extjs/_toolbar.scss 		\
+	scss/extjs/_treepanel.scss 		\
+	scss/extjs/_window.scss 		\
+	scss/other/_charts.scss 		\
+	scss/other/_icons.scss 			\
+	scss/proxmox/_general.scss 		\
+	scss/proxmox/_helpbutton.scss 		\
+	scss/proxmox/_loadingindicator.scss	\
+	scss/proxmox/_markdown.scss 		\
+	scss/proxmox/_nodes.scss 		\
+	scss/proxmox/_quarantine.scss 		\
+	scss/proxmox/_storages.scss 		\
+	scss/proxmox/_tags.scss 		\
+	scss/proxmox/_datepicker.scss
+
+.PHONY: all
+all: theme-proxmox-dark.css
+
+.PHONY: install
+install: theme-proxmox-dark.css
+	install -d ${WWWTHEMEDIR}/
+	install -m 0664 theme-proxmox-dark.css ${WWWTHEMEDIR}/
+
+theme-proxmox-dark.css: ${SCSSSRC}
+	sassc -t compressed $< $@.tmp
+	mv $@.tmp $@
+
+.PHONY: clean
+clean:
+	rm -rf theme-proxmox-dark.css
diff --git a/src/proxmox-dark/scss/ProxmoxDark.scss b/src/proxmox-dark/scss/ProxmoxDark.scss
new file mode 100644
index 0000000..60e69a8
--- /dev/null
+++ b/src/proxmox-dark/scss/ProxmoxDark.scss
@@ -0,0 +1,37 @@
+@charset "utf-8";
+
+// Abstracts
+@import "abstracts/mixins";
+@import "abstracts/variables";
+
+// Chart, Icon, Keyboar-mode fixups
+@import "other/charts";
+@import "other/icons";
+
+// ExtJS re-stylings
+@import "extjs/form/button";
+@import "extjs/form/combobox";
+@import "extjs/form/formfield";
+@import "extjs/grid";
+@import "extjs/menu";
+@import "extjs/panel";
+@import "extjs/progress";
+@import "extjs/splitter";
+@import "extjs/tabbar";
+@import "extjs/tip";
+@import "extjs/toolbar";
+@import "extjs/treepanel";
+@import "extjs/window";
+@import "extjs/body";
+@import "extjs/presentation";
+
+// Proxmox re-stylings
+@import "proxmox/general";
+@import "proxmox/helpbutton";
+@import "proxmox/loadingindicator";
+@import "proxmox/markdown";
+@import "proxmox/nodes";
+@import "proxmox/quarantine";
+@import "proxmox/storages";
+@import "proxmox/tags";
+@import "proxmox/datepicker";
diff --git a/src/proxmox-dark/scss/abstracts/_mixins.scss b/src/proxmox-dark/scss/abstracts/_mixins.scss
new file mode 100644
index 0000000..570a783
--- /dev/null
+++ b/src/proxmox-dark/scss/abstracts/_mixins.scss
@@ -0,0 +1,12 @@
+// A border to the left and on top of the content panels for the
+// selected resource
+@mixin content-border {
+  border-top: solid 3px $background-darkest;
+  border-left: solid 3px $background-darkest;
+}
+
+// selected items in dropdown etc
+@mixin selection {
+  background-color: $selection-background-color;
+  color: $selection-background-text-color;
+}
diff --git a/src/proxmox-dark/scss/abstracts/_variables.scss b/src/proxmox-dark/scss/abstracts/_variables.scss
new file mode 100644
index 0000000..96581df
--- /dev/null
+++ b/src/proxmox-dark/scss/abstracts/_variables.scss
@@ -0,0 +1,67 @@
+// Primary colors
+$primary-color: hsl(205deg, 100%, 32.25%);
+$primary-light: hsl(205deg, 100%, 40.5%);
+$primary-dark: hsl(205deg, 100%, 25%);
+
+// Hightlighted Text (Links, Headers, etc.)
+$highlighted-text: hsl(205deg, 100%, 65%);
+$highlighted-text-alt: hsl(205deg, 100%, 80%);
+$highlighted-text-crit: hsl(360deg, 100%, 65%);
+
+// Icon and Text colors
+$text-color: hsl(0deg, 0%, 95%);
+$text-color-inactive: hsl(0deg, 0%, 60%);
+$icon-color: hsl(0deg, 0%, 90%);
+$icon-color-alt: hsl(0deg, 0%, 55%);
+
+// Borders
+$border-color: hsl(0deg, 0%, 40%);
+$border-color-alt: hsl(0deg, 0%, 25%);
+
+// Backgrounds
+$content-background-color: hsl(0deg, 0%, 20%);
+$content-background-selected: hsl(0deg, 0%, 30%);
+$background-dark: hsl(0deg, 0%, 20%);
+$background-darker: hsl(0deg, 0%, 15%);
+$background-darkest: hsl(0deg, 0%, 10%);
+$background-invalid: hsl(360deg, 60%, 30%);
+$background-warning: hsl(40deg, 100%, 30%);
+
+// Buttons
+$neutral-button-color: hsl(0deg, 0%, 35%);
+$neutral-button-color-alt: hsl(0deg, 0%, 55%);
+$neutral-button-text-color: hsl(0deg, 0%, 100%);
+$neutral-button-icon-color: $neutral-button-text-color;
+
+// Help Buttons
+$help-button-color: hsl(0deg, 0%, 70%);
+$help-button-color-alt: hsl(0deg, 0%, 60%);
+$help-button-text-color: hsl(0deg, 0%, 10%);
+$help-button-icon-color: $help-button-text-color;
+
+// Selection Colors
+$selection-background-color: hsl(0deg, 0%, 35%);
+$selection-background-text-color: hsl(0deg, 0%, 100%);
+
+// Other
+$form-field-body-color: $background-dark;
+$bottom-splitter-color: hsl(0deg, 0%, 5%);
+
+// Some icons are black and do not respect the 'color' style property.
+// For the dark mode these can be turned grey or white with the
+// 'filter: invert(value)' attribute
+$icon-brightness: lightness($icon-color);
+
+// Spam score colors
+
+// for spam scores with an absolute score >= 3
+$spam-high-neg: hsl(205deg, 65%, 20%);
+$spam-high-pos: hsl(360deg, 55%, 20%);
+
+// for spam scores with an absolute score between 0.1 and 3
+$spam-mid-neg: hsl(205deg, 65%, 30%);
+$spam-mid-pos: hsl(360deg, 55%, 30%);
+
+// for spam scores with an absolute score <= 0.1
+$spam-low-neg: hsl(205deg, 65%, 40%);
+$spam-low-pos: hsl(360deg, 55%, 40%);
diff --git a/src/proxmox-dark/scss/extjs/_body.scss b/src/proxmox-dark/scss/extjs/_body.scss
new file mode 100644
index 0000000..2fc6161
--- /dev/null
+++ b/src/proxmox-dark/scss/extjs/_body.scss
@@ -0,0 +1,23 @@
+// Chrome 81, Firefox 96 and Safari 13 support a dark version of the
+// scrollbar and form controls source
+// https://stackoverflow.com/q/65940522
+:root {
+  color-scheme: dark;
+}
+
+.x-body {
+  color: $text-color;
+  background-color: $background-darkest;
+}
+
+// Should be the absolute background of the document
+.x-viewport > .x-body {
+  background-color: $background-darkest;
+}
+
+// necessary for some masks to work properly (e.g. when hidding the
+// attachment grid in pmg)
+body.x-border-layout-ct,
+div.x-border-layout-ct {
+  background-color: $background-darkest;
+}
diff --git a/src/proxmox-dark/scss/extjs/_grid.scss b/src/proxmox-dark/scss/extjs/_grid.scss
new file mode 100644
index 0000000..77872b0
--- /dev/null
+++ b/src/proxmox-dark/scss/extjs/_grid.scss
@@ -0,0 +1,146 @@
+.x-column-header {
+  border-color: $border-color-alt;
+}
+
+.x-grid-item,
+.x-column-header-default,
+// the row number field (e.g. in the ipsets in pve)
+.x-grid-cell-row-numberer {
+  color: $text-color;
+  background-color: $background-darker;
+}
+
+// Trigger in grid/table header cells
+.x-column-header-trigger {
+  border-color: $border-color;
+}
+
+.x-grid-cell-special {
+  border-color: $border-color-alt;
+}
+
+.x-grid-group-hd {
+  background-color: $background-darker;
+  border-color: $border-color-alt;
+}
+
+.x-grid-group-title {
+  color: $text-color;
+}
+
+// Border-top in tables
+.x-grid-header-ct {
+  border: solid 1px $background-dark;
+  background-color: $background-dark;
+}
+
+// alternating row colors
+.x-grid-item-alt {
+  background-color: $background-darkest;
+}
+
+.x-grid-with-row-lines {
+  .x-grid-item {
+    border-color: $border-color-alt;
+    border-right: 0;
+
+    // A border at the bottom of tables
+    &:last-child {
+      border-color: $border-color-alt;
+    }
+
+    // A border at the top of tables
+    &:first-child {
+      border-color: $border-color-alt;
+    }
+
+    // hovered row in a grid
+    &.x-grid-item-over,
+    &.x-grid-item-selected {
+      background-color: $selection-background-color;
+      border-color: $border-color-alt;
+    }
+  }
+
+  // borders on selected elements
+  .x-grid-item-selected + .x-grid-item,
+  .x-grid-item-over + .x-grid-item {
+    border-color: $border-color-alt;
+  }
+}
+
+// Sometimes a selected node in the ResourceTree loses the
+// selection-background-color
+.x-grid-item-over,
+.x-grid-item-selected {
+  // Otherwise .x-grid-item overrides the background color
+  background-color: $selection-background-color;
+}
+
+// Hovering over a grid/table header cell
+.x-column-header-over,
+// When opening the sort/settings header of a table/grid header cell
+.x-column-header-open,
+.x-column-header-last .x-column-header-over .x-column-header-trigger, {
+  background-color: $content-background-selected;
+}
+
+// header element that the grid is currently sorted by
+.x-column-header-sort-ASC,
+.x-column-header-sort-DESC {
+  background-color: $primary-dark;
+}
+
+// summary rows (e.g. ceph pools last row)
+.x-grid-row-summary {
+  .x-grid-cell,
+  .x-grid-rowwrap,
+  .x-grid-cell-rowbody {
+    border-color: $border-color-alt;
+    background-color: $background-darker;
+  }
+}
+
+.x-grid-with-col-lines {
+  .x-grid-cell,
+  .x-grid-item-over .x-grid-cell,
+  .x-grid-item-selected .x-grid-cell {
+    border-color: $border-color-alt;
+  }
+}
+
+// drag and drop proxy
+.x-dd-drag-proxy {
+  background-color: $background-darkest;
+  border-color: $border-color-alt;
+  color: $text-color;
+}
+
+.x-keyboard-mode .x-grid-item-focused {
+  @include selection;
+
+  .x-grid-cell-inner::before {
+    border-color: $primary-color;
+  }
+}
+
+// Grid/table headers that are selected and active
+.x-keyboard-mode .x-column-header.x-column-header-focus {
+  color: $text-color;
+
+  // Elements in table
+  .x-column-header-inner::after {
+    border-color: $primary-color;
+  }
+}
+
+.x-keyboard-mode .proxmox-invalid-row .x-grid-item-focused {
+  background-color: $background-invalid;
+}
+
+// As far as I can tell only used under Node > "System" >
+// "Certificates"
+.x-grid-empty {
+  background-color: $background-darker;
+  color: $text-color;
+}
diff --git a/src/proxmox-dark/scss/extjs/_menu.scss b/src/proxmox-dark/scss/extjs/_menu.scss
new file mode 100644
index 0000000..74be901
--- /dev/null
+++ b/src/proxmox-dark/scss/extjs/_menu.scss
@@ -0,0 +1,39 @@
+.x-menu-default {
+  border-color: $form-field-body-color;
+}
+
+.x-menu-body-default {
+  background-color: $form-field-body-color;
+}
+
+// E.g. the content menu in the resource tree displays a header
+.x-menu-header {
+  background-color: $primary-color;
+}
+
+.x-menu-item-default {
+  // Horizontal divider in menu (e.g. in UserInfo above "Logout")
+  &.x-menu-item-separator {
+    background-color: $background-dark;
+    border-color: $border-color;
+  }
+
+  // When hovering over a menu item
+  &.x-menu-item-focus {
+    @include selection;
+  }
+}
+
+.x-menu-item-text-default {
+  color: $text-color;
+}
+
+.x-menu-item-icon-default {
+  color: $icon-color;
+}
+
+// Vertical divider (e.g. in UserInfo between icons and text)
+.x-menu-icon-separator-default {
+  background-color: $background-dark;
+  border-color: $border-color;
+}
diff --git a/src/proxmox-dark/scss/extjs/_panel.scss b/src/proxmox-dark/scss/extjs/_panel.scss
new file mode 100644
index 0000000..5344c8f
--- /dev/null
+++ b/src/proxmox-dark/scss/extjs/_panel.scss
@@ -0,0 +1,25 @@
+.x-panel-header-default {
+  background-color: $content-background-color;
+  border: none;
+
+  // The small navigation elements in the panel header bar e.g. to
+  // collapse a panel
+  .x-tool-tool-el {
+    background-color: transparent;
+    filter: brightness(120%);
+  }
+
+  .x-tool-over .x-tool-tool-el {
+    filter: brightness(140%);
+  }
+}
+
+.x-panel-header-title-default {
+  color: $highlighted-text;
+}
+
+.x-panel-body-default {
+  background-color: $background-darker;
+  border-color: $border-color-alt;
+  color: $text-color;
+}
diff --git a/src/proxmox-dark/scss/extjs/_presentation.scss b/src/proxmox-dark/scss/extjs/_presentation.scss
new file mode 100644
index 0000000..c7d3c8f
--- /dev/null
+++ b/src/proxmox-dark/scss/extjs/_presentation.scss
@@ -0,0 +1,14 @@
+// The mask that is applied when the window is unaccessible (Login
+// screen, Loading, ...)
+.x-mask {
+  background-color: $background-darker;
+  opacity: 0.85;
+}
+
+// Shadows of floating windows like window modals, form selectors and
+// message boxes
+.x-css-shadow {
+  // the additional styling from the pve css overwrites the setting on
+  // the element with "!important", that's why we need it here.
+  box-shadow: $background-darkest 0 0 5px !important;
+}
diff --git a/src/proxmox-dark/scss/extjs/_progress.scss b/src/proxmox-dark/scss/extjs/_progress.scss
new file mode 100644
index 0000000..4f2bb49
--- /dev/null
+++ b/src/proxmox-dark/scss/extjs/_progress.scss
@@ -0,0 +1,19 @@
+.x-progress-default {
+  background-color: $form-field-body-color;
+
+  .x-progress-bar-default {
+    background-color: $primary-color; // Taken from the chart
+  }
+
+  .x-progress-text {
+    color: $text-color;
+  }
+}
+
+.x-progress.warning .x-progress-bar {
+  background-color: $background-warning;
+}
+
+.x-progress.critical .x-progress-bar {
+  background-color: $background-invalid;
+}
diff --git a/src/proxmox-dark/scss/extjs/_splitter.scss b/src/proxmox-dark/scss/extjs/_splitter.scss
new file mode 100644
index 0000000..ad3d6a8
--- /dev/null
+++ b/src/proxmox-dark/scss/extjs/_splitter.scss
@@ -0,0 +1,18 @@
+// Splitters separating two views (e.g. Firewall > "Security Group",
+// "IPSet", ...)
+.x-splitter {
+  background-color: $background-darkest;
+}
+
+.x-splitter-horizontal {
+  background-color: $bottom-splitter-color;
+}
+
+// Splitters that separate content and resize parts of the window
+.x-keyboard-mode .x-splitter-focus::after {
+  border-color: $primary-color;
+}
+
+.x-layout-split-bottom {
+  opacity: 0.7;
+}
diff --git a/src/proxmox-dark/scss/extjs/_tabbar.scss b/src/proxmox-dark/scss/extjs/_tabbar.scss
new file mode 100644
index 0000000..e1b5f66
--- /dev/null
+++ b/src/proxmox-dark/scss/extjs/_tabbar.scss
@@ -0,0 +1,43 @@
+// The header of the tabbar
+.x-tab-bar-default {
+  background-color: $background-darker;
+}
+
+.x-tab-default {
+  // Hovering over a tab button
+  &.x-tab-over {
+    background-color: $primary-dark;
+    border-color: $primary-dark;
+  }
+
+  // Selected tab buttons
+  &.x-tab.x-tab-active {
+    background-color: $primary-light;
+    border-color: $primary-light;
+  }
+
+  // Disabled tab buttons
+  &.x-tab.x-tab-disabled {
+    background-color: $background-darker;
+
+    // make the border invisible so it matches the light theme, setting
+    // it to none messes with the allignment of the elements.
+    border-color: transparent;
+    color: $text-color;
+  }
+
+  .x-keyboard-mode &.x-tab-focus.x-tab-active {
+    background-color: $primary-color;
+    border-color: $primary-color;
+  }
+}
+
+// Not selected tab buttons
+.x-tab-default-top {
+  background-color: $background-darker;
+  border-color: $background-darker;
+}
+
+.x-tab-inner-default {
+  color: $text-color;
+}
diff --git a/src/proxmox-dark/scss/extjs/_tip.scss b/src/proxmox-dark/scss/extjs/_tip.scss
new file mode 100644
index 0000000..0c2cb6a
--- /dev/null
+++ b/src/proxmox-dark/scss/extjs/_tip.scss
@@ -0,0 +1,18 @@
+.x-tip-default {
+  background-color: $background-darkest;
+  border-color: $border-color-alt;
+}
+
+.x-tip-body-default {
+  color: $text-color;
+}
+
+// Form error tip
+.x-tip-form-invalid {
+  background-color: $background-dark;
+  border-color: $border-color-alt;
+}
+
+.x-tip-body-form-invalid {
+  color: $text-color;
+}
diff --git a/src/proxmox-dark/scss/extjs/_toolbar.scss b/src/proxmox-dark/scss/extjs/_toolbar.scss
new file mode 100644
index 0000000..2ea8527
--- /dev/null
+++ b/src/proxmox-dark/scss/extjs/_toolbar.scss
@@ -0,0 +1,21 @@
+.x-toolbar {
+  background-color: $background-darker;
+}
+
+.x-toolbar-default {
+  background-color: $background-darker;
+  border: solid 3px $background-darkest;
+
+  &.x-docked-top {
+    border-width: 1px;
+    border-color: $border-color-alt;
+  }
+
+  .x-toolbar-separator {
+    border-color: $border-color;
+  }
+}
+
+.x-toolbar-text-default {
+  color: $text-color;
+}
diff --git a/src/proxmox-dark/scss/extjs/_treepanel.scss b/src/proxmox-dark/scss/extjs/_treepanel.scss
new file mode 100644
index 0000000..0480371
--- /dev/null
+++ b/src/proxmox-dark/scss/extjs/_treepanel.scss
@@ -0,0 +1,24 @@
+// individual rows in tree lists (e.g. the menu in the "middle")
+.x-treelist-item {
+  background-color: $background-darker;
+}
+
+.x-treelist-item-text,
+.x-treelist-item-icon,
+.x-treelist-row-over .x-treelist-item-icon,
+.x-treelist-row-over .x-treelist-item-text {
+  color: $text-color;
+}
+
+.x-treelist-item-selected > .x-treelist-row {
+  background-color: $primary-color;
+}
+
+.x-treelist-row-over {
+  background-color: $selection-background-color;
+}
+
+.x-treelist-pve-nav {
+  background-color: $background-darker;
+  border-color: $border-color;
+}
diff --git a/src/proxmox-dark/scss/extjs/_window.scss b/src/proxmox-dark/scss/extjs/_window.scss
new file mode 100644
index 0000000..0fe188d
--- /dev/null
+++ b/src/proxmox-dark/scss/extjs/_window.scss
@@ -0,0 +1,39 @@
+.x-window-default {
+  background-color: $background-darkest;
+
+  // make the color transparent so the border doesn't appear visibly,
+  // like in crisp, but keep to keep the layout intact
+  border-color: transparent;
+}
+
+.x-window-header-default {
+  background-color: $background-darker;
+
+  // make the color transparent so the border doesn't appear visibly,
+  // like in crisp, but keep to keep the layout intact
+  border-color: transparent;
+}
+
+.x-window-header-title-default {
+  color: $highlighted-text;
+}
+
+.x-window-body-default {
+  background-color: $background-darker;
+  border-color: $border-color-alt;
+  color: $text-color;
+}
+
+// Window when dragged
+.x-window-ghost {
+  background-color: $background-darker;
+}
+
+// The X in the right upper corner of closable windows
+.x-window-header-default .x-tool-img {
+  background-color: transparent;
+}
+
+.x-message-box .x-window-body {
+  background-color: $background-dark;
+}
diff --git a/src/proxmox-dark/scss/extjs/form/_button.scss b/src/proxmox-dark/scss/extjs/form/_button.scss
new file mode 100644
index 0000000..0aa1475
--- /dev/null
+++ b/src/proxmox-dark/scss/extjs/form/_button.scss
@@ -0,0 +1,57 @@
+// The "main" buttons like Login, Create, ...
+.x-btn-default-small {
+  background-color: $primary-color;
+  border-color: $primary-color;
+
+  &.x-btn-over,
+  .x-keyboard-mode &.x-btn-focus {
+    background-color: $primary-light;
+    border-color: $primary-light;
+  }
+
+  &.x-btn.x-btn-disabled {
+    background-color: $primary-color;
+  }
+
+  &.x-btn.x-btn-pressed {
+    background-color: $primary-dark;
+    border-color: $primary-color;
+  }
+}
+
+// toolbar butons
+.x-btn-default-toolbar-small {
+  background-color: $neutral-button-color;
+  border-color: $neutral-button-color-alt;
+
+  .x-btn-inner-default-toolbar-small {
+    color: $neutral-button-text-color;
+  }
+
+  .x-btn-icon-el-default-toolbar-small {
+    color: $neutral-button-icon-color;
+  }
+
+  &.x-btn-over,
+  .x-keyboard-mode &.x-btn-focus {
+    background-color: $neutral-button-color-alt;
+
+    // the little arrow in certain toolbar buttons with dropdowns
+    .x-btn-wrap-default-toolbar-small.x-btn-arrow-right::after,
+    .x-btn-wrap-default-toolbar-small.x-btn-split-right::after {
+      filter: invert($icon-brightness);
+    }
+  }
+
+  &.x-btn.x-btn-disabled {
+    // Note: extJS already sets transparency on disabled buttons
+    background-color: $neutral-button-color;
+  }
+
+  // toggled state of toggle buttons (e.g. filter in task history)
+  &.x-btn.x-btn-menu-active,
+  &.x-btn.x-btn-pressed {
+    background-color: $primary-dark;
+    border-color: $primary-color;
+  }
+}
diff --git a/src/proxmox-dark/scss/extjs/form/_combobox.scss b/src/proxmox-dark/scss/extjs/form/_combobox.scss
new file mode 100644
index 0000000..a6405a1
--- /dev/null
+++ b/src/proxmox-dark/scss/extjs/form/_combobox.scss
@@ -0,0 +1,23 @@
+// Combobox "expand" trigger
+.x-form-trigger-default {
+  background-color: $form-field-body-color;
+}
+
+.x-boundlist {
+  border-color: $form-field-body-color;
+}
+
+// Combobox item
+.x-boundlist-item {
+  background-color: $form-field-body-color;
+  border-color: $form-field-body-color;
+  color: $text-color;
+}
+
+.x-boundlist-selected {
+  background-color: mix(black, $selection-background-color, 20%);
+}
+
+.x-boundlist-item-over {
+  background-color: $selection-background-color;
+}
diff --git a/src/proxmox-dark/scss/extjs/form/_formfield.scss b/src/proxmox-dark/scss/extjs/form/_formfield.scss
new file mode 100644
index 0000000..13f0622
--- /dev/null
+++ b/src/proxmox-dark/scss/extjs/form/_formfield.scss
@@ -0,0 +1,40 @@
+// displayfields in forms (e.g. the guest os header in the vm creation
+// form)
+.x-form-display-field-default {
+  color: $text-color;
+}
+
+// The body of a text form field
+.x-form-text-default {
+  background-color: $form-field-body-color;
+  color: $text-color;
+}
+
+// Unselected form field
+.x-form-trigger-wrap-default {
+  border-color: $form-field-body-color;
+
+  // Focused form field
+  &.x-form-trigger-wrap-focus {
+    border-color: mix(black, $primary-color, 3%);
+  }
+}
+
+// Labels
+.x-form-item-label-default {
+  color: $text-color;
+}
+
+// number field arrow up and down buttons
+.x-form-spinner-default {
+  background-color: $form-field-body-color;
+}
+
+.x-form-cb-label-default {
+  color: $icon-color;
+}
+
+// Fieldsets used in e.g. the personal settings
+.x-fieldset-default {
+  border-color: $border-color-alt;
+}
diff --git a/src/proxmox-dark/scss/other/_charts.scss b/src/proxmox-dark/scss/other/_charts.scss
new file mode 100644
index 0000000..5c67282
--- /dev/null
+++ b/src/proxmox-dark/scss/other/_charts.scss
@@ -0,0 +1,39 @@
+// these css variables define the look of all charts and gauges
+:root {
+  // using interpolation here may avoid compatability issues between
+  // sass and css. see:
+  // https://sass-lang.com/documentation/breaking-changes/css-vars
+  --pwt-panel-background: #{$background-darker};
+  --pwt-text-color: #{$text-color};
+  --pwt-gauge-default: #{$primary-color};
+  --pwt-gauge-back: #{$background-dark};
+  --pwt-gauge-warn: #{$background-warning};
+  --pwt-gauge-crit: #{$background-invalid};
+  --pwt-chart-primary: #{$primary-color};
+  --pwt-chart-grid-stroke: #{$content-background-selected};
+}
+
+// Peeks out on the edges of the legend item border
+.x-legend-container {
+  background-color: $content-background-color;
+}
+
+.x-legend-horizontal .x-legend-item {
+  background-color: $background-dark;
+  color: $text-color;
+  border-top: solid 1px $background-darkest;
+  border-right: solid 1px $background-darkest;
+  border-bottom: solid 1px $background-darkest;
+
+  &:first-child {
+    border-left: solid 1px $background-darkest;
+  }
+}
+
+// The "undo zoom" button in the upper right corner of charts when
+// disabled
+.x-tool .x-mask {
+  backdrop-filter: none;
+  background-color: $background-dark;
+  opacity: 0.6;
+}
diff --git a/src/proxmox-dark/scss/other/_icons.scss b/src/proxmox-dark/scss/other/_icons.scss
new file mode 100644
index 0000000..f132dae
--- /dev/null
+++ b/src/proxmox-dark/scss/other/_icons.scss
@@ -0,0 +1,200 @@
+// these styling fix all kinds of icons in grid, treeview etc.
+
+// most icons just use the color attribute..
+// Running containers and VMS
+.x-grid-icon-custom.running,
+.x-tree-icon-custom.running,
+// Icons in trees (e.g. Resource tree)
+.x-tree-icon-custom,
+// Icons in panels, e.g. Search tab
+.fa-database::before,
+// Icon for pools
+.fa-tags::before,
+// The template icon
+.fa-file-o::before,
+// Icon for cluster nodes
+.fa-building::before,
+// e.g. storage list when creating a guest
+.x-action-col-icon::before,
+.fa-shield::before,
+.fa-file-text-o::before,
+.fa-clock-o::before,
+// tab bar icons
+.x-tab-icon-el-default,
+.pve-icon-verify-lettering::after,
+// the small plane when migrating a vm
+.x-tree-icon-custom.lock-migrate::after,
+.x-grid-icon-custom.lock-migrate::after,
+// e.g. permission tree view in pve
+.x-tree-icon-leaf:not(.x-tree-icon-custom)::before,
+.x-tree-icon-parent:not(.x-tree-icon-custom)::before,
+.x-tree-icon-parent-expanded:not(.x-tree-icon-custom)::before {
+  color: $icon-color;
+}
+
+// but some are implement as background SVGs or PNGs. invert them via
+// filters:
+.fa-ceph::before,
+.fa-sdn::before,
+.fa-network-wired::before,
+// Icon for "ISO Images" for storages
+.pve-itype-treelist-item-icon-cdrom,
+// Arrow to the right
+.fa-chevron-right::before,
+// icon indicating a currently open shell session in the task viewer
+.x-grid-row-console,
+// the "triangle" that appears when the sidebar becomes scrollable
+.x-box-scroller-toolbar-default.x-box-scroller,
+// the small triangles in the tree view next to nodes etc.
+.x-tree-elbow-img,
+// the computer icon in the resource pool add menu
+.pve-itype-icon-qemu,
+.x-tree-node-computer,
+.x-grid-tree-node-expanded .x-tree-node-computer,
+.pbs-icon-tape,
+.pbs-icon-tape-drive,
+.x-tree-icon-leaf:not(.x-tree-icon-custom),
+// default tree panel icons (api viewer, pbs backup panel)
+.x-tree-icon-parent:not(.x-tree-icon-custom),
+.x-tree-icon-parent-expanded:not(.x-tree-icon-custom) {
+  filter: invert($icon-brightness);
+}
+
+// the following icons need some additional fix-ups to work well in
+// grids (e.g. when hovered etc.)
+// Icon for the processor in VM hardware settings
+.pve-itype-icon-cpu,
+// Icon for memory in VM hardware settings
+.pve-itype-icon-cdrom,
+// Icon for memory in VM hardware settings
+.pve-itype-icon-memory,
+// the pcie device icon in the vm hardware section
+.pve-itype-icon-pci,
+// the serial device icon in the vm hardware section
+.pve-itype-icon-serial,
+// the rng icon in the vm hardware section
+.pve-itype-icon-die,
+// Processor icon for summary page
+.pmx-itype-icon-processor,
+// Memory icon on summary page
+.pmx-itype-icon-memory,
+// the mount point icon for containers
+.pve-itype-icon-storage,
+.x-tree-node-harddisk,
+.x-grid-tree-node-expanded .x-tree-node-harddisk {
+  filter: invert($icon-brightness);
+
+  // the filter also applies to the text next to the icon
+  .x-grid-cell-inner {
+    color: black;
+  }
+
+  .x-grid-cell-inner::before {
+    // this is a somewhat hacky work-around for the focus borders on
+    // these elements. since we use the invert filter to fix the icon
+    // color we need to also invert the border color first too, not
+    // just the text. add "!important" to properly override.
+    border-color: invert($primary-color, $weight: 90%) !important;
+  }
+}
+
+// pbs show task log in longest task list column
+.x-action-col-icon.fa-chevron-right::before {
+  filter: none;
+}
+
+// checkboxes and radio buttons
+.x-form-checkbox-default,
+.x-form-radio-default,
+.x-column-header-checkbox .x-column-header-checkbox::after,
+.x-grid-checkcolumn::after {
+  filter: invert($icon-brightness) hue-rotate(180deg);
+}
+
+.x-tree-icon-custom,
+.x-grid-icon-custom {
+  &::after {
+    color: $icon-color;
+    text-shadow: -1px 0 1px $background-darker;
+  }
+
+  // stopped containers and VMs
+  &.stopped,
+  // vms/cts that are offline
+  &.offline,
+  // question mark at the bottom right of e.g. unreachable storages
+  &.unknown::after {
+    color: $icon-color-alt;
+  }
+
+  &.lxc::after,
+  &.qemu::after {
+    background-color: $background-darker;
+    color: $icon-color;
+  }
+}
+
+// icons for templates in the storages view
+.x-treelist-item-icon {
+  &.lxc::after,
+  &.qemu::after {
+    background-color: $background-darker;
+    color: $icon-color;
+  }
+}
+
+.x-grid-item .x-grid-icon-custom {
+  &.lxc::after,
+  &.qemu::after {
+    background-color: $background-darker;
+  }
+}
+
+.x-grid-item-alt .x-grid-icon-custom {
+  &.lxc::after,
+  &.qemu::after {
+    background-color: $background-darkest;
+  }
+}
+
+.x-treelist-item-selected {
+  .lxc::after,
+  .qemu::after {
+    background-color: $primary-color;
+    text-shadow: -1px 0 1px $primary-color;
+  }
+}
+
+.x-grid-item-over,
+// hovered items in treelists
+.x-treelist-item-over,
+// template icons when in selected menu item or table row
+.x-grid-item-selected,
+// vm/ct that is focused (e.g. by mouse-down)
+.x-keyboard-mode .x-grid-item-focused {
+  .lxc::after,
+  .qemu::after {
+    background-color: $selection-background-color !important;
+    text-shadow: -1px 0 1px $selection-background-color;
+  }
+}
+
+.x-action-col-icon:hover {
+  &::before,
+  &::after {
+    text-shadow: -1px 0 1px $background-darker;
+  }
+}
+
+// The usage icons dynamically displaying how full a storage is
+.usage-wrapper {
+  border: 1px solid $icon-color;
+}
+
+.usage-negative {
+  background-color: transparent;
+}
+
+.usage {
+  background-color: $icon-color;
+}
diff --git a/src/proxmox-dark/scss/proxmox/_datepicker.scss b/src/proxmox-dark/scss/proxmox/_datepicker.scss
new file mode 100644
index 0000000..068e7e6
--- /dev/null
+++ b/src/proxmox-dark/scss/proxmox/_datepicker.scss
@@ -0,0 +1,61 @@
+.x-datepicker,
+.x-datepicker-column-header,
+.x-monthpicker {
+  background-color: $background-darker;
+  color: $text-color;
+
+  // make the border invisible but keep it to keep the layout intact
+  border-color: transparent;
+}
+
+.x-datepicker-month .x-btn-over.x-btn-default-small {
+  background-color: $selection-background-color;
+}
+
+.x-monthpicker-months {
+  border-color: $border-color-alt;
+}
+
+.x-datepicker-header {
+  background-color: $background-darkest;
+}
+
+.x-datepicker-cell,
+.x-monthpicker-item-inner {
+  // make the border invisible but keep it to keep the layout intact
+  border-color: transparent;
+}
+
+.x-datepicker-date,
+.x-monthpicker-item-inner {
+  color: $text-color;
+}
+
+.x-datepicker-prevday,
+.x-datepicker-nextday {
+  .x-datepicker-date {
+    color: $text-color-inactive;
+  }
+}
+
+.x-datepicker-footer,
+.x-monthpicker-buttons {
+  background-color: $background-darkest;
+}
+
+.x-datepicker-selected div.x-datepicker-date,
+.x-monthpicker-item a.x-monthpicker-selected,
+a.x-monthpicker-item-inner:hover,
+div.x-datepicker-date:hover {
+  @include selection;
+}
+
+.x-datepicker-disabled {
+  .x-datepicker-date {
+    background-color: $background-darkest;
+  }
+
+  div.x-datepicker-date:hover {
+    background-color: $background-darker;
+  }
+}
diff --git a/src/proxmox-dark/scss/proxmox/_general.scss b/src/proxmox-dark/scss/proxmox/_general.scss
new file mode 100644
index 0000000..805a187
--- /dev/null
+++ b/src/proxmox-dark/scss/proxmox/_general.scss
@@ -0,0 +1,56 @@
+// Swapping out the logo with CSS rather than using javascript
+img[id^="proxmoxlogo-"][id$="-img"] {
+  filter: invert(1) hue-rotate(180deg);
+}
+
+// removes the gray line in the header of the mail gateway
+div[id^="versioninfo-"] + div[id^="panel-"] > div[id^="panel-"][id$="-bodyWrap"] > div {
+  background-color: transparent;
+  border-color: transparent;
+}
+
+// border around the main datacenter view
+div[id^="PVE-dc-Config-"][id$="-body"],
+// border around the main pool view
+div[id^="pvePoolConfig-"][id$="-body"],
+// Container content config views
+div[id^="pveLXCConfig-"][id$="-body"],
+// VM content config views
+div[id^="PVE-qemu-Config-"][id$="-body"],
+div[id^="PVE-storage-Browser-"][id$="-body"],
+div[id^="PVE-node-Config-"][id$="-body"] {
+  @include content-border;
+}
+
+// Section header in the "My Settings" page
+.x-fieldset-header-default > .x-fieldset-header-text {
+  color: $text-color;
+}
+
+// Errors and bad configuration (Taskviewer / no repository enabled)
+.proxmox-invalid-row {
+  background-color: $background-invalid;
+}
+
+// Warning rows, e.g. when enabling staging or no-subscription
+// repository
+.proxmox-warning-row {
+  background-color: $background-warning;
+}
+
+// Disabled rows (e.g. disabled repos in Repository view)
+.proxmox-disabled-row td {
+  color: $text-color-inactive;
+}
+
+.pmx-hint {
+  background-color: $background-warning;
+}
+
+.pmx-hint a {
+  color: $highlighted-text-alt;
+}
+
+.pmx-hint a:active {
+  color: $highlighted-text;
+}
diff --git a/src/proxmox-dark/scss/proxmox/_helpbutton.scss b/src/proxmox-dark/scss/proxmox/_helpbutton.scss
new file mode 100644
index 0000000..aad92e2
--- /dev/null
+++ b/src/proxmox-dark/scss/proxmox/_helpbutton.scss
@@ -0,0 +1,16 @@
+// help buttons
+.proxmox-inline-button {
+  background-color: $help-button-color;
+  color: $help-button-text-color;
+
+  &.x-btn-over,
+  &.x-btn.x-btn-pressed.x-btn-default-toolbar-small {
+    background-color: $help-button-color-alt;
+    border-color: $help-button-color-alt;
+  }
+
+  .x-btn-inner,
+  .x-btn-icon-el {
+    color: $help-button-icon-color;
+  }
+}
diff --git a/src/proxmox-dark/scss/proxmox/_loadingindicator.scss b/src/proxmox-dark/scss/proxmox/_loadingindicator.scss
new file mode 100644
index 0000000..5c320b3
--- /dev/null
+++ b/src/proxmox-dark/scss/proxmox/_loadingindicator.scss
@@ -0,0 +1,14 @@
+// loading spinners
+.x-grid-row-loading,
+.x-treelist-item-loading .x-treelist-item-icon,
+.x-treelist-nav .x-treelist-item-loading .x-treelist-item-icon,
+.x-mask-msg-text,
+.x-grid-tree-loading .x-tree-icon {
+  filter: invert($icon-brightness);
+  color: black;
+}
+
+.x-mask-msg {
+  background-color: $form-field-body-color;
+  border: solid 1px mix(black, $form-field-body-color, 25%);
+}
diff --git a/src/proxmox-dark/scss/proxmox/_markdown.scss b/src/proxmox-dark/scss/proxmox/_markdown.scss
new file mode 100644
index 0000000..8531701
--- /dev/null
+++ b/src/proxmox-dark/scss/proxmox/_markdown.scss
@@ -0,0 +1,31 @@
+.pmx-md {
+  code {
+    background-color: $background-darkest;
+  }
+
+  pre code {
+    border-color: $border-color-alt;
+  }
+
+  tbody tr {
+    & td {
+      border-color: $border-color;
+    }
+
+    &:nth-of-type(2n) {
+      background-color: $background-darkest;
+    }
+
+    &:hover td {
+      background-color: $content-background-selected;
+    }
+  }
+
+  a {
+    color: $highlighted-text;
+
+    &:active {
+      color: $highlighted-text-alt;
+    }
+  }
+}
diff --git a/src/proxmox-dark/scss/proxmox/_nodes.scss b/src/proxmox-dark/scss/proxmox/_nodes.scss
new file mode 100644
index 0000000..02b15f9
--- /dev/null
+++ b/src/proxmox-dark/scss/proxmox/_nodes.scss
@@ -0,0 +1,9 @@
+// Table headers under Node > "Updates" > "Repositories"
+.proxmox-apt-repos .x-grid-group-hd {
+  background-color: $background-darker;
+  border-bottom-width: 0;
+}
+
+.proxmox-apt-repos .x-grid-group-title {
+  color: $text-color;
+}
diff --git a/src/proxmox-dark/scss/proxmox/_quarantine.scss b/src/proxmox-dark/scss/proxmox/_quarantine.scss
new file mode 100644
index 0000000..bdda69a
--- /dev/null
+++ b/src/proxmox-dark/scss/proxmox/_quarantine.scss
@@ -0,0 +1,47 @@
+// these css variables define the look of the spamscore grid in pmg
+:root {
+  // using interpolation here may avoid compatability issues between
+  // sass and css. see:
+  // https://sass-lang.com/documentation/breaking-changes/css-vars
+  // for spam with an absolute score >= 3
+  --pmg-spam-high-neg: #{$spam-high-neg};
+  --pmg-spam-high-pos: #{$spam-high-pos};
+
+  // for spam with an absolute score between 0.1 and 3
+  --pmg-spam-mid-neg: #{$spam-mid-neg};
+  --pmg-spam-mid-pos: #{$spam-mid-pos};
+
+  // for spam with an absolute score <= 0.1
+  --pmg-spam-low-neg: #{$spam-low-neg};
+  --pmg-spam-low-pos: #{$spam-low-pos};
+}
+
+.info-blue {
+  // the selector for the button icons have higher specificity than
+  // this one, so we need "!important"
+  color: $highlighted-text !important;
+}
+
+.critical {
+  // the selector for the button icons have higher specificity than
+  // this one, so we need "!important"
+  color: $highlighted-text-crit !important;
+}
+
+// pmg tracking center quarantined rows
+tr.blocked,
+.x-keyboard-mode tr.blocked .x-grid-item-focused {
+  background-color: $background-invalid;
+}
+
+// pmg tracking center quarantined rows
+tr.quarantine,
+.x-keyboard-mode tr.quarantine .x-grid-item-focused {
+  background-color: mix($background-warning, $background-invalid, 50%);
+}
+
+// pmg tracking center blocked rows
+tr.bounced,
+.x-keyboard-mode tr.bounced .x-grid-item-focused {
+  background-color: $background-warning;
+}
diff --git a/src/proxmox-dark/scss/proxmox/_storages.scss b/src/proxmox-dark/scss/proxmox/_storages.scss
new file mode 100644
index 0000000..46b94f4
--- /dev/null
+++ b/src/proxmox-dark/scss/proxmox/_storages.scss
@@ -0,0 +1,19 @@
+// ceph page
+table.osds {
+  tr {
+    border-color: $border-color;
+  }
+
+  td {
+    border-color: $border-color;
+  }
+}
+
+.install-mask {
+  background-color: $background-darker;
+  color: $text-color;
+}
+
+div.monitor {
+  border-color: $border-color;
+}
diff --git a/src/proxmox-dark/scss/proxmox/_tags.scss b/src/proxmox-dark/scss/proxmox/_tags.scss
new file mode 100644
index 0000000..09ad623
--- /dev/null
+++ b/src/proxmox-dark/scss/proxmox/_tags.scss
@@ -0,0 +1,14 @@
+.pve-edit-tag.editable span {
+  background-color: $form-field-body-color;
+  color: $text-color;
+  border-color: $border-color;
+}
+
+// adds a bit of outline to make tags stand out more
+.proxmox-tags-full,
+.proxmox-tags-circle {
+  .proxmox-tag-light,
+  .proxmox-tag-dark {
+    outline: 1px solid rgba($background-dark, 0.3);
+  }
+}
-- 
2.30.2





WARNING: multiple messages have this Message-ID
From: Stefan Sterz <s.sterz@proxmox.com>
To: pve-devel@lists.proxmox.com, pbs-devel@lists.proxmox.com,
	pmg-devel@lists.proxmox.com
Subject: [pmg-devel] [PATCH widget-toolkit v1 1/6] dark-theme: add initial version of the proxmox-dark theme
Date: Wed,  8 Mar 2023 17:33:12 +0100	[thread overview]
Message-ID: <20230308163312.2441849-1-s.sterz@proxmox.com> (raw)
In-Reply-To: <20230308161840.2396113-1-s.sterz@proxmox.com>

From: Daniel Tschlatscher <d.tschlatscher@proxmox.com>

adds an initial version of a dark theme for all proxmox products. the
theme works by simply loading an additional css file that adjust the
colors of the original theme "crisp" to be more suitable for a dark
theme.

the theme itself is written in scss, so we need to add sassc as a
build dependency. while sassc is deprecated, it is still maintained in
the debian repositories and, thus, needs no additional packaging on
our end.

this version adds the following on-top of Daniel Tschlatscher's
original draft:

* removes checked-in build artifacts and other stuff that shouldn't be
  tracked
* code clean-up and removal of redundant code
* refactors:
    * icon styling
    * color handling for charts (moved to css variables)
    * color variables, consolidates them and makes the "functional"
    * color values, improves contrast and makes the theme appear more
      consistent
    * using the "theme-" prefix
* adds:
    * markdown note styles
    * combo-box trigger styles
    * even more icon styles (e.g., template icons, check boxes etc.)
    * loading spinners styles
    * number field up and down arrow styles
    * an additional auto theme that switches between light and dark
      theme dynamically
    * widget toolkit hints
    * ceph install mask
    * grid group headers
    * color to toggled buttons
    * date picker styles
    * drag and drop proxy styles
* fixes:
    * contrast on control elements for "scrollable" sidebars
    * make the general appearance closer to the light theme ("crisp")
    * buttons (when hovered, toggled etc)
    * background masking (e.g., when showing the log-in form)
    * grid header separator (adds an outline)
    * separator lines in some menus
    * makes the custom unknown icon more discernible
    * makes headers more readable
    * color adjustments to several components for consistency
    * reduces brightness of dividers in toolbars
    * border color on chart legend elements
    * removes a black border from docked toolbars (e.g., tag edit)
    * dims the "invalid" color to appear less aggressive
    * add hover effects in grids and make them consistent with "crisp"
    * summary rows
    * selected and hovered elements in boundlists
    * row numberers in grids
    * contrast of links in hints
    * ceph overview border colors (e.g., OSD in/out/up/down grid)
    * bottom splitter contrast in certain situations
    * tag visibility
    * pbs compatibility (help buttons stylings, icons, tabs)
    * pmg compatibility:
         * remove border around the spanning element in the header
         * style spam score grid
         * style tracking center rows
         * add appropriate colors to buttons in the quarantine
         * style mail-info element in the quarantine

Co-authored-by: Daniel Tschlatscher <d.tschlatscher@proxmox.com>
Co-authored-by: Stefan Sterz <s.sterz@proxmox.com>
Signed-off-by: Daniel Tschlatscher <d.tschlatscher@proxmox.com>
Signed-off-by: Stefan Sterz <s.sterz@proxmox.com>
---
 debian/control                                |   1 +
 src/Makefile                                  |   2 +-
 src/defines.mk                                |   1 +
 src/proxmox-dark/Makefile                     |  47 ++++
 src/proxmox-dark/scss/ProxmoxDark.scss        |  37 ++++
 src/proxmox-dark/scss/abstracts/_mixins.scss  |  12 ++
 .../scss/abstracts/_variables.scss            |  67 ++++++
 src/proxmox-dark/scss/extjs/_body.scss        |  23 ++
 src/proxmox-dark/scss/extjs/_grid.scss        | 146 +++++++++++++
 src/proxmox-dark/scss/extjs/_menu.scss        |  39 ++++
 src/proxmox-dark/scss/extjs/_panel.scss       |  25 +++
 .../scss/extjs/_presentation.scss             |  14 ++
 src/proxmox-dark/scss/extjs/_progress.scss    |  19 ++
 src/proxmox-dark/scss/extjs/_splitter.scss    |  18 ++
 src/proxmox-dark/scss/extjs/_tabbar.scss      |  43 ++++
 src/proxmox-dark/scss/extjs/_tip.scss         |  18 ++
 src/proxmox-dark/scss/extjs/_toolbar.scss     |  21 ++
 src/proxmox-dark/scss/extjs/_treepanel.scss   |  24 +++
 src/proxmox-dark/scss/extjs/_window.scss      |  39 ++++
 src/proxmox-dark/scss/extjs/form/_button.scss |  57 +++++
 .../scss/extjs/form/_combobox.scss            |  23 ++
 .../scss/extjs/form/_formfield.scss           |  40 ++++
 src/proxmox-dark/scss/other/_charts.scss      |  39 ++++
 src/proxmox-dark/scss/other/_icons.scss       | 200 ++++++++++++++++++
 .../scss/proxmox/_datepicker.scss             |  61 ++++++
 src/proxmox-dark/scss/proxmox/_general.scss   |  56 +++++
 .../scss/proxmox/_helpbutton.scss             |  16 ++
 .../scss/proxmox/_loadingindicator.scss       |  14 ++
 src/proxmox-dark/scss/proxmox/_markdown.scss  |  31 +++
 src/proxmox-dark/scss/proxmox/_nodes.scss     |   9 +
 .../scss/proxmox/_quarantine.scss             |  47 ++++
 src/proxmox-dark/scss/proxmox/_storages.scss  |  19 ++
 src/proxmox-dark/scss/proxmox/_tags.scss      |  14 ++
 33 files changed, 1221 insertions(+), 1 deletion(-)
 create mode 100644 src/proxmox-dark/Makefile
 create mode 100644 src/proxmox-dark/scss/ProxmoxDark.scss
 create mode 100644 src/proxmox-dark/scss/abstracts/_mixins.scss
 create mode 100644 src/proxmox-dark/scss/abstracts/_variables.scss
 create mode 100644 src/proxmox-dark/scss/extjs/_body.scss
 create mode 100644 src/proxmox-dark/scss/extjs/_grid.scss
 create mode 100644 src/proxmox-dark/scss/extjs/_menu.scss
 create mode 100644 src/proxmox-dark/scss/extjs/_panel.scss
 create mode 100644 src/proxmox-dark/scss/extjs/_presentation.scss
 create mode 100644 src/proxmox-dark/scss/extjs/_progress.scss
 create mode 100644 src/proxmox-dark/scss/extjs/_splitter.scss
 create mode 100644 src/proxmox-dark/scss/extjs/_tabbar.scss
 create mode 100644 src/proxmox-dark/scss/extjs/_tip.scss
 create mode 100644 src/proxmox-dark/scss/extjs/_toolbar.scss
 create mode 100644 src/proxmox-dark/scss/extjs/_treepanel.scss
 create mode 100644 src/proxmox-dark/scss/extjs/_window.scss
 create mode 100644 src/proxmox-dark/scss/extjs/form/_button.scss
 create mode 100644 src/proxmox-dark/scss/extjs/form/_combobox.scss
 create mode 100644 src/proxmox-dark/scss/extjs/form/_formfield.scss
 create mode 100644 src/proxmox-dark/scss/other/_charts.scss
 create mode 100644 src/proxmox-dark/scss/other/_icons.scss
 create mode 100644 src/proxmox-dark/scss/proxmox/_datepicker.scss
 create mode 100644 src/proxmox-dark/scss/proxmox/_general.scss
 create mode 100644 src/proxmox-dark/scss/proxmox/_helpbutton.scss
 create mode 100644 src/proxmox-dark/scss/proxmox/_loadingindicator.scss
 create mode 100644 src/proxmox-dark/scss/proxmox/_markdown.scss
 create mode 100644 src/proxmox-dark/scss/proxmox/_nodes.scss
 create mode 100644 src/proxmox-dark/scss/proxmox/_quarantine.scss
 create mode 100644 src/proxmox-dark/scss/proxmox/_storages.scss
 create mode 100644 src/proxmox-dark/scss/proxmox/_tags.scss

diff --git a/debian/control b/debian/control
index 41093f3..71c48c4 100644
--- a/debian/control
+++ b/debian/control
@@ -5,6 +5,7 @@ Maintainer: Proxmox Support Team <support@proxmox.com>
 Build-Depends: debhelper (>= 12~),
                libjs-marked,
                pve-eslint (>= 7.28.0),
+               sassc,
 Standards-Version: 4.5.1
 Homepage: https://www.proxmox.com
 
diff --git a/src/Makefile b/src/Makefile
index 95da5aa..54727f6 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -1,6 +1,6 @@
 include defines.mk
 
-SUBDIRS= css images
+SUBDIRS= css images proxmox-dark
 
 # bundle it for now from the libjs-marked debian package to avoid touching our proxies file mapper,
 # we could also just ship a link to the packages file and load from same path as the widget-toolkit
diff --git a/src/defines.mk b/src/defines.mk
index d6bdd2c..2a65e9d 100644
--- a/src/defines.mk
+++ b/src/defines.mk
@@ -3,3 +3,4 @@ DOCDIR=${DESTDIR}/usr/share/doc/${PACKAGE}
 WWWBASEDIR=${DESTDIR}/usr/share/javascript/${PACKAGE}
 WWWCSSDIR=${WWWBASEDIR}/css
 WWWIMAGESDIR=${WWWBASEDIR}/images
+WWWTHEMEDIR=${WWWBASEDIR}/themes
diff --git a/src/proxmox-dark/Makefile b/src/proxmox-dark/Makefile
new file mode 100644
index 0000000..2ac6f22
--- /dev/null
+++ b/src/proxmox-dark/Makefile
@@ -0,0 +1,47 @@
+include ../defines.mk
+
+SCSSSRC=scss/ProxmoxDark.scss 			\
+	scss/abstracts/_mixins.scss 		\
+	scss/abstracts/_variables.scss 		\
+	scss/extjs/_body.scss 			\
+	scss/extjs/form/_button.scss 		\
+	scss/extjs/form/_combobox.scss 		\
+	scss/extjs/form/_formfield.scss 	\
+	scss/extjs/_grid.scss 			\
+	scss/extjs/_menu.scss 			\
+	scss/extjs/_panel.scss 			\
+	scss/extjs/_presentation.scss 		\
+	scss/extjs/_progress.scss 		\
+	scss/extjs/_splitter.scss 		\
+	scss/extjs/_tabbar.scss 		\
+	scss/extjs/_tip.scss 			\
+	scss/extjs/_toolbar.scss 		\
+	scss/extjs/_treepanel.scss 		\
+	scss/extjs/_window.scss 		\
+	scss/other/_charts.scss 		\
+	scss/other/_icons.scss 			\
+	scss/proxmox/_general.scss 		\
+	scss/proxmox/_helpbutton.scss 		\
+	scss/proxmox/_loadingindicator.scss	\
+	scss/proxmox/_markdown.scss 		\
+	scss/proxmox/_nodes.scss 		\
+	scss/proxmox/_quarantine.scss 		\
+	scss/proxmox/_storages.scss 		\
+	scss/proxmox/_tags.scss 		\
+	scss/proxmox/_datepicker.scss
+
+.PHONY: all
+all: theme-proxmox-dark.css
+
+.PHONY: install
+install: theme-proxmox-dark.css
+	install -d ${WWWTHEMEDIR}/
+	install -m 0664 theme-proxmox-dark.css ${WWWTHEMEDIR}/
+
+theme-proxmox-dark.css: ${SCSSSRC}
+	sassc -t compressed $< $@.tmp
+	mv $@.tmp $@
+
+.PHONY: clean
+clean:
+	rm -rf theme-proxmox-dark.css
diff --git a/src/proxmox-dark/scss/ProxmoxDark.scss b/src/proxmox-dark/scss/ProxmoxDark.scss
new file mode 100644
index 0000000..60e69a8
--- /dev/null
+++ b/src/proxmox-dark/scss/ProxmoxDark.scss
@@ -0,0 +1,37 @@
+@charset "utf-8";
+
+// Abstracts
+@import "abstracts/mixins";
+@import "abstracts/variables";
+
+// Chart, Icon, Keyboar-mode fixups
+@import "other/charts";
+@import "other/icons";
+
+// ExtJS re-stylings
+@import "extjs/form/button";
+@import "extjs/form/combobox";
+@import "extjs/form/formfield";
+@import "extjs/grid";
+@import "extjs/menu";
+@import "extjs/panel";
+@import "extjs/progress";
+@import "extjs/splitter";
+@import "extjs/tabbar";
+@import "extjs/tip";
+@import "extjs/toolbar";
+@import "extjs/treepanel";
+@import "extjs/window";
+@import "extjs/body";
+@import "extjs/presentation";
+
+// Proxmox re-stylings
+@import "proxmox/general";
+@import "proxmox/helpbutton";
+@import "proxmox/loadingindicator";
+@import "proxmox/markdown";
+@import "proxmox/nodes";
+@import "proxmox/quarantine";
+@import "proxmox/storages";
+@import "proxmox/tags";
+@import "proxmox/datepicker";
diff --git a/src/proxmox-dark/scss/abstracts/_mixins.scss b/src/proxmox-dark/scss/abstracts/_mixins.scss
new file mode 100644
index 0000000..570a783
--- /dev/null
+++ b/src/proxmox-dark/scss/abstracts/_mixins.scss
@@ -0,0 +1,12 @@
+// A border to the left and on top of the content panels for the
+// selected resource
+@mixin content-border {
+  border-top: solid 3px $background-darkest;
+  border-left: solid 3px $background-darkest;
+}
+
+// selected items in dropdown etc
+@mixin selection {
+  background-color: $selection-background-color;
+  color: $selection-background-text-color;
+}
diff --git a/src/proxmox-dark/scss/abstracts/_variables.scss b/src/proxmox-dark/scss/abstracts/_variables.scss
new file mode 100644
index 0000000..96581df
--- /dev/null
+++ b/src/proxmox-dark/scss/abstracts/_variables.scss
@@ -0,0 +1,67 @@
+// Primary colors
+$primary-color: hsl(205deg, 100%, 32.25%);
+$primary-light: hsl(205deg, 100%, 40.5%);
+$primary-dark: hsl(205deg, 100%, 25%);
+
+// Hightlighted Text (Links, Headers, etc.)
+$highlighted-text: hsl(205deg, 100%, 65%);
+$highlighted-text-alt: hsl(205deg, 100%, 80%);
+$highlighted-text-crit: hsl(360deg, 100%, 65%);
+
+// Icon and Text colors
+$text-color: hsl(0deg, 0%, 95%);
+$text-color-inactive: hsl(0deg, 0%, 60%);
+$icon-color: hsl(0deg, 0%, 90%);
+$icon-color-alt: hsl(0deg, 0%, 55%);
+
+// Borders
+$border-color: hsl(0deg, 0%, 40%);
+$border-color-alt: hsl(0deg, 0%, 25%);
+
+// Backgrounds
+$content-background-color: hsl(0deg, 0%, 20%);
+$content-background-selected: hsl(0deg, 0%, 30%);
+$background-dark: hsl(0deg, 0%, 20%);
+$background-darker: hsl(0deg, 0%, 15%);
+$background-darkest: hsl(0deg, 0%, 10%);
+$background-invalid: hsl(360deg, 60%, 30%);
+$background-warning: hsl(40deg, 100%, 30%);
+
+// Buttons
+$neutral-button-color: hsl(0deg, 0%, 35%);
+$neutral-button-color-alt: hsl(0deg, 0%, 55%);
+$neutral-button-text-color: hsl(0deg, 0%, 100%);
+$neutral-button-icon-color: $neutral-button-text-color;
+
+// Help Buttons
+$help-button-color: hsl(0deg, 0%, 70%);
+$help-button-color-alt: hsl(0deg, 0%, 60%);
+$help-button-text-color: hsl(0deg, 0%, 10%);
+$help-button-icon-color: $help-button-text-color;
+
+// Selection Colors
+$selection-background-color: hsl(0deg, 0%, 35%);
+$selection-background-text-color: hsl(0deg, 0%, 100%);
+
+// Other
+$form-field-body-color: $background-dark;
+$bottom-splitter-color: hsl(0deg, 0%, 5%);
+
+// Some icons are black and do not respect the 'color' style property.
+// For the dark mode these can be turned grey or white with the
+// 'filter: invert(value)' attribute
+$icon-brightness: lightness($icon-color);
+
+// Spam score colors
+
+// for spam scores with an absolute score >= 3
+$spam-high-neg: hsl(205deg, 65%, 20%);
+$spam-high-pos: hsl(360deg, 55%, 20%);
+
+// for spam scores with an absolute score between 0.1 and 3
+$spam-mid-neg: hsl(205deg, 65%, 30%);
+$spam-mid-pos: hsl(360deg, 55%, 30%);
+
+// for spam scores with an absolute score <= 0.1
+$spam-low-neg: hsl(205deg, 65%, 40%);
+$spam-low-pos: hsl(360deg, 55%, 40%);
diff --git a/src/proxmox-dark/scss/extjs/_body.scss b/src/proxmox-dark/scss/extjs/_body.scss
new file mode 100644
index 0000000..2fc6161
--- /dev/null
+++ b/src/proxmox-dark/scss/extjs/_body.scss
@@ -0,0 +1,23 @@
+// Chrome 81, Firefox 96 and Safari 13 support a dark version of the
+// scrollbar and form controls source
+// https://stackoverflow.com/q/65940522
+:root {
+  color-scheme: dark;
+}
+
+.x-body {
+  color: $text-color;
+  background-color: $background-darkest;
+}
+
+// Should be the absolute background of the document
+.x-viewport > .x-body {
+  background-color: $background-darkest;
+}
+
+// necessary for some masks to work properly (e.g. when hidding the
+// attachment grid in pmg)
+body.x-border-layout-ct,
+div.x-border-layout-ct {
+  background-color: $background-darkest;
+}
diff --git a/src/proxmox-dark/scss/extjs/_grid.scss b/src/proxmox-dark/scss/extjs/_grid.scss
new file mode 100644
index 0000000..77872b0
--- /dev/null
+++ b/src/proxmox-dark/scss/extjs/_grid.scss
@@ -0,0 +1,146 @@
+.x-column-header {
+  border-color: $border-color-alt;
+}
+
+.x-grid-item,
+.x-column-header-default,
+// the row number field (e.g. in the ipsets in pve)
+.x-grid-cell-row-numberer {
+  color: $text-color;
+  background-color: $background-darker;
+}
+
+// Trigger in grid/table header cells
+.x-column-header-trigger {
+  border-color: $border-color;
+}
+
+.x-grid-cell-special {
+  border-color: $border-color-alt;
+}
+
+.x-grid-group-hd {
+  background-color: $background-darker;
+  border-color: $border-color-alt;
+}
+
+.x-grid-group-title {
+  color: $text-color;
+}
+
+// Border-top in tables
+.x-grid-header-ct {
+  border: solid 1px $background-dark;
+  background-color: $background-dark;
+}
+
+// alternating row colors
+.x-grid-item-alt {
+  background-color: $background-darkest;
+}
+
+.x-grid-with-row-lines {
+  .x-grid-item {
+    border-color: $border-color-alt;
+    border-right: 0;
+
+    // A border at the bottom of tables
+    &:last-child {
+      border-color: $border-color-alt;
+    }
+
+    // A border at the top of tables
+    &:first-child {
+      border-color: $border-color-alt;
+    }
+
+    // hovered row in a grid
+    &.x-grid-item-over,
+    &.x-grid-item-selected {
+      background-color: $selection-background-color;
+      border-color: $border-color-alt;
+    }
+  }
+
+  // borders on selected elements
+  .x-grid-item-selected + .x-grid-item,
+  .x-grid-item-over + .x-grid-item {
+    border-color: $border-color-alt;
+  }
+}
+
+// Sometimes a selected node in the ResourceTree loses the
+// selection-background-color
+.x-grid-item-over,
+.x-grid-item-selected {
+  // Otherwise .x-grid-item overrides the background color
+  background-color: $selection-background-color;
+}
+
+// Hovering over a grid/table header cell
+.x-column-header-over,
+// When opening the sort/settings header of a table/grid header cell
+.x-column-header-open,
+.x-column-header-last .x-column-header-over .x-column-header-trigger, {
+  background-color: $content-background-selected;
+}
+
+// header element that the grid is currently sorted by
+.x-column-header-sort-ASC,
+.x-column-header-sort-DESC {
+  background-color: $primary-dark;
+}
+
+// summary rows (e.g. ceph pools last row)
+.x-grid-row-summary {
+  .x-grid-cell,
+  .x-grid-rowwrap,
+  .x-grid-cell-rowbody {
+    border-color: $border-color-alt;
+    background-color: $background-darker;
+  }
+}
+
+.x-grid-with-col-lines {
+  .x-grid-cell,
+  .x-grid-item-over .x-grid-cell,
+  .x-grid-item-selected .x-grid-cell {
+    border-color: $border-color-alt;
+  }
+}
+
+// drag and drop proxy
+.x-dd-drag-proxy {
+  background-color: $background-darkest;
+  border-color: $border-color-alt;
+  color: $text-color;
+}
+
+.x-keyboard-mode .x-grid-item-focused {
+  @include selection;
+
+  .x-grid-cell-inner::before {
+    border-color: $primary-color;
+  }
+}
+
+// Grid/table headers that are selected and active
+.x-keyboard-mode .x-column-header.x-column-header-focus {
+  color: $text-color;
+
+  // Elements in table
+  .x-column-header-inner::after {
+    border-color: $primary-color;
+  }
+}
+
+.x-keyboard-mode .proxmox-invalid-row .x-grid-item-focused {
+  background-color: $background-invalid;
+}
+
+// As far as I can tell only used under Node > "System" >
+// "Certificates"
+.x-grid-empty {
+  background-color: $background-darker;
+  color: $text-color;
+}
diff --git a/src/proxmox-dark/scss/extjs/_menu.scss b/src/proxmox-dark/scss/extjs/_menu.scss
new file mode 100644
index 0000000..74be901
--- /dev/null
+++ b/src/proxmox-dark/scss/extjs/_menu.scss
@@ -0,0 +1,39 @@
+.x-menu-default {
+  border-color: $form-field-body-color;
+}
+
+.x-menu-body-default {
+  background-color: $form-field-body-color;
+}
+
+// E.g. the content menu in the resource tree displays a header
+.x-menu-header {
+  background-color: $primary-color;
+}
+
+.x-menu-item-default {
+  // Horizontal divider in menu (e.g. in UserInfo above "Logout")
+  &.x-menu-item-separator {
+    background-color: $background-dark;
+    border-color: $border-color;
+  }
+
+  // When hovering over a menu item
+  &.x-menu-item-focus {
+    @include selection;
+  }
+}
+
+.x-menu-item-text-default {
+  color: $text-color;
+}
+
+.x-menu-item-icon-default {
+  color: $icon-color;
+}
+
+// Vertical divider (e.g. in UserInfo between icons and text)
+.x-menu-icon-separator-default {
+  background-color: $background-dark;
+  border-color: $border-color;
+}
diff --git a/src/proxmox-dark/scss/extjs/_panel.scss b/src/proxmox-dark/scss/extjs/_panel.scss
new file mode 100644
index 0000000..5344c8f
--- /dev/null
+++ b/src/proxmox-dark/scss/extjs/_panel.scss
@@ -0,0 +1,25 @@
+.x-panel-header-default {
+  background-color: $content-background-color;
+  border: none;
+
+  // The small navigation elements in the panel header bar e.g. to
+  // collapse a panel
+  .x-tool-tool-el {
+    background-color: transparent;
+    filter: brightness(120%);
+  }
+
+  .x-tool-over .x-tool-tool-el {
+    filter: brightness(140%);
+  }
+}
+
+.x-panel-header-title-default {
+  color: $highlighted-text;
+}
+
+.x-panel-body-default {
+  background-color: $background-darker;
+  border-color: $border-color-alt;
+  color: $text-color;
+}
diff --git a/src/proxmox-dark/scss/extjs/_presentation.scss b/src/proxmox-dark/scss/extjs/_presentation.scss
new file mode 100644
index 0000000..c7d3c8f
--- /dev/null
+++ b/src/proxmox-dark/scss/extjs/_presentation.scss
@@ -0,0 +1,14 @@
+// The mask that is applied when the window is unaccessible (Login
+// screen, Loading, ...)
+.x-mask {
+  background-color: $background-darker;
+  opacity: 0.85;
+}
+
+// Shadows of floating windows like window modals, form selectors and
+// message boxes
+.x-css-shadow {
+  // the additional styling from the pve css overwrites the setting on
+  // the element with "!important", that's why we need it here.
+  box-shadow: $background-darkest 0 0 5px !important;
+}
diff --git a/src/proxmox-dark/scss/extjs/_progress.scss b/src/proxmox-dark/scss/extjs/_progress.scss
new file mode 100644
index 0000000..4f2bb49
--- /dev/null
+++ b/src/proxmox-dark/scss/extjs/_progress.scss
@@ -0,0 +1,19 @@
+.x-progress-default {
+  background-color: $form-field-body-color;
+
+  .x-progress-bar-default {
+    background-color: $primary-color; // Taken from the chart
+  }
+
+  .x-progress-text {
+    color: $text-color;
+  }
+}
+
+.x-progress.warning .x-progress-bar {
+  background-color: $background-warning;
+}
+
+.x-progress.critical .x-progress-bar {
+  background-color: $background-invalid;
+}
diff --git a/src/proxmox-dark/scss/extjs/_splitter.scss b/src/proxmox-dark/scss/extjs/_splitter.scss
new file mode 100644
index 0000000..ad3d6a8
--- /dev/null
+++ b/src/proxmox-dark/scss/extjs/_splitter.scss
@@ -0,0 +1,18 @@
+// Splitters separating two views (e.g. Firewall > "Security Group",
+// "IPSet", ...)
+.x-splitter {
+  background-color: $background-darkest;
+}
+
+.x-splitter-horizontal {
+  background-color: $bottom-splitter-color;
+}
+
+// Splitters that separate content and resize parts of the window
+.x-keyboard-mode .x-splitter-focus::after {
+  border-color: $primary-color;
+}
+
+.x-layout-split-bottom {
+  opacity: 0.7;
+}
diff --git a/src/proxmox-dark/scss/extjs/_tabbar.scss b/src/proxmox-dark/scss/extjs/_tabbar.scss
new file mode 100644
index 0000000..e1b5f66
--- /dev/null
+++ b/src/proxmox-dark/scss/extjs/_tabbar.scss
@@ -0,0 +1,43 @@
+// The header of the tabbar
+.x-tab-bar-default {
+  background-color: $background-darker;
+}
+
+.x-tab-default {
+  // Hovering over a tab button
+  &.x-tab-over {
+    background-color: $primary-dark;
+    border-color: $primary-dark;
+  }
+
+  // Selected tab buttons
+  &.x-tab.x-tab-active {
+    background-color: $primary-light;
+    border-color: $primary-light;
+  }
+
+  // Disabled tab buttons
+  &.x-tab.x-tab-disabled {
+    background-color: $background-darker;
+
+    // make the border invisible so it matches the light theme, setting
+    // it to none messes with the allignment of the elements.
+    border-color: transparent;
+    color: $text-color;
+  }
+
+  .x-keyboard-mode &.x-tab-focus.x-tab-active {
+    background-color: $primary-color;
+    border-color: $primary-color;
+  }
+}
+
+// Not selected tab buttons
+.x-tab-default-top {
+  background-color: $background-darker;
+  border-color: $background-darker;
+}
+
+.x-tab-inner-default {
+  color: $text-color;
+}
diff --git a/src/proxmox-dark/scss/extjs/_tip.scss b/src/proxmox-dark/scss/extjs/_tip.scss
new file mode 100644
index 0000000..0c2cb6a
--- /dev/null
+++ b/src/proxmox-dark/scss/extjs/_tip.scss
@@ -0,0 +1,18 @@
+.x-tip-default {
+  background-color: $background-darkest;
+  border-color: $border-color-alt;
+}
+
+.x-tip-body-default {
+  color: $text-color;
+}
+
+// Form error tip
+.x-tip-form-invalid {
+  background-color: $background-dark;
+  border-color: $border-color-alt;
+}
+
+.x-tip-body-form-invalid {
+  color: $text-color;
+}
diff --git a/src/proxmox-dark/scss/extjs/_toolbar.scss b/src/proxmox-dark/scss/extjs/_toolbar.scss
new file mode 100644
index 0000000..2ea8527
--- /dev/null
+++ b/src/proxmox-dark/scss/extjs/_toolbar.scss
@@ -0,0 +1,21 @@
+.x-toolbar {
+  background-color: $background-darker;
+}
+
+.x-toolbar-default {
+  background-color: $background-darker;
+  border: solid 3px $background-darkest;
+
+  &.x-docked-top {
+    border-width: 1px;
+    border-color: $border-color-alt;
+  }
+
+  .x-toolbar-separator {
+    border-color: $border-color;
+  }
+}
+
+.x-toolbar-text-default {
+  color: $text-color;
+}
diff --git a/src/proxmox-dark/scss/extjs/_treepanel.scss b/src/proxmox-dark/scss/extjs/_treepanel.scss
new file mode 100644
index 0000000..0480371
--- /dev/null
+++ b/src/proxmox-dark/scss/extjs/_treepanel.scss
@@ -0,0 +1,24 @@
+// individual rows in tree lists (e.g. the menu in the "middle")
+.x-treelist-item {
+  background-color: $background-darker;
+}
+
+.x-treelist-item-text,
+.x-treelist-item-icon,
+.x-treelist-row-over .x-treelist-item-icon,
+.x-treelist-row-over .x-treelist-item-text {
+  color: $text-color;
+}
+
+.x-treelist-item-selected > .x-treelist-row {
+  background-color: $primary-color;
+}
+
+.x-treelist-row-over {
+  background-color: $selection-background-color;
+}
+
+.x-treelist-pve-nav {
+  background-color: $background-darker;
+  border-color: $border-color;
+}
diff --git a/src/proxmox-dark/scss/extjs/_window.scss b/src/proxmox-dark/scss/extjs/_window.scss
new file mode 100644
index 0000000..0fe188d
--- /dev/null
+++ b/src/proxmox-dark/scss/extjs/_window.scss
@@ -0,0 +1,39 @@
+.x-window-default {
+  background-color: $background-darkest;
+
+  // make the color transparent so the border doesn't appear visibly,
+  // like in crisp, but keep to keep the layout intact
+  border-color: transparent;
+}
+
+.x-window-header-default {
+  background-color: $background-darker;
+
+  // make the color transparent so the border doesn't appear visibly,
+  // like in crisp, but keep to keep the layout intact
+  border-color: transparent;
+}
+
+.x-window-header-title-default {
+  color: $highlighted-text;
+}
+
+.x-window-body-default {
+  background-color: $background-darker;
+  border-color: $border-color-alt;
+  color: $text-color;
+}
+
+// Window when dragged
+.x-window-ghost {
+  background-color: $background-darker;
+}
+
+// The X in the right upper corner of closable windows
+.x-window-header-default .x-tool-img {
+  background-color: transparent;
+}
+
+.x-message-box .x-window-body {
+  background-color: $background-dark;
+}
diff --git a/src/proxmox-dark/scss/extjs/form/_button.scss b/src/proxmox-dark/scss/extjs/form/_button.scss
new file mode 100644
index 0000000..0aa1475
--- /dev/null
+++ b/src/proxmox-dark/scss/extjs/form/_button.scss
@@ -0,0 +1,57 @@
+// The "main" buttons like Login, Create, ...
+.x-btn-default-small {
+  background-color: $primary-color;
+  border-color: $primary-color;
+
+  &.x-btn-over,
+  .x-keyboard-mode &.x-btn-focus {
+    background-color: $primary-light;
+    border-color: $primary-light;
+  }
+
+  &.x-btn.x-btn-disabled {
+    background-color: $primary-color;
+  }
+
+  &.x-btn.x-btn-pressed {
+    background-color: $primary-dark;
+    border-color: $primary-color;
+  }
+}
+
+// toolbar butons
+.x-btn-default-toolbar-small {
+  background-color: $neutral-button-color;
+  border-color: $neutral-button-color-alt;
+
+  .x-btn-inner-default-toolbar-small {
+    color: $neutral-button-text-color;
+  }
+
+  .x-btn-icon-el-default-toolbar-small {
+    color: $neutral-button-icon-color;
+  }
+
+  &.x-btn-over,
+  .x-keyboard-mode &.x-btn-focus {
+    background-color: $neutral-button-color-alt;
+
+    // the little arrow in certain toolbar buttons with dropdowns
+    .x-btn-wrap-default-toolbar-small.x-btn-arrow-right::after,
+    .x-btn-wrap-default-toolbar-small.x-btn-split-right::after {
+      filter: invert($icon-brightness);
+    }
+  }
+
+  &.x-btn.x-btn-disabled {
+    // Note: extJS already sets transparency on disabled buttons
+    background-color: $neutral-button-color;
+  }
+
+  // toggled state of toggle buttons (e.g. filter in task history)
+  &.x-btn.x-btn-menu-active,
+  &.x-btn.x-btn-pressed {
+    background-color: $primary-dark;
+    border-color: $primary-color;
+  }
+}
diff --git a/src/proxmox-dark/scss/extjs/form/_combobox.scss b/src/proxmox-dark/scss/extjs/form/_combobox.scss
new file mode 100644
index 0000000..a6405a1
--- /dev/null
+++ b/src/proxmox-dark/scss/extjs/form/_combobox.scss
@@ -0,0 +1,23 @@
+// Combobox "expand" trigger
+.x-form-trigger-default {
+  background-color: $form-field-body-color;
+}
+
+.x-boundlist {
+  border-color: $form-field-body-color;
+}
+
+// Combobox item
+.x-boundlist-item {
+  background-color: $form-field-body-color;
+  border-color: $form-field-body-color;
+  color: $text-color;
+}
+
+.x-boundlist-selected {
+  background-color: mix(black, $selection-background-color, 20%);
+}
+
+.x-boundlist-item-over {
+  background-color: $selection-background-color;
+}
diff --git a/src/proxmox-dark/scss/extjs/form/_formfield.scss b/src/proxmox-dark/scss/extjs/form/_formfield.scss
new file mode 100644
index 0000000..13f0622
--- /dev/null
+++ b/src/proxmox-dark/scss/extjs/form/_formfield.scss
@@ -0,0 +1,40 @@
+// displayfields in forms (e.g. the guest os header in the vm creation
+// form)
+.x-form-display-field-default {
+  color: $text-color;
+}
+
+// The body of a text form field
+.x-form-text-default {
+  background-color: $form-field-body-color;
+  color: $text-color;
+}
+
+// Unselected form field
+.x-form-trigger-wrap-default {
+  border-color: $form-field-body-color;
+
+  // Focused form field
+  &.x-form-trigger-wrap-focus {
+    border-color: mix(black, $primary-color, 3%);
+  }
+}
+
+// Labels
+.x-form-item-label-default {
+  color: $text-color;
+}
+
+// number field arrow up and down buttons
+.x-form-spinner-default {
+  background-color: $form-field-body-color;
+}
+
+.x-form-cb-label-default {
+  color: $icon-color;
+}
+
+// Fieldsets used in e.g. the personal settings
+.x-fieldset-default {
+  border-color: $border-color-alt;
+}
diff --git a/src/proxmox-dark/scss/other/_charts.scss b/src/proxmox-dark/scss/other/_charts.scss
new file mode 100644
index 0000000..5c67282
--- /dev/null
+++ b/src/proxmox-dark/scss/other/_charts.scss
@@ -0,0 +1,39 @@
+// these css variables define the look of all charts and gauges
+:root {
+  // using interpolation here may avoid compatability issues between
+  // sass and css. see:
+  // https://sass-lang.com/documentation/breaking-changes/css-vars
+  --pwt-panel-background: #{$background-darker};
+  --pwt-text-color: #{$text-color};
+  --pwt-gauge-default: #{$primary-color};
+  --pwt-gauge-back: #{$background-dark};
+  --pwt-gauge-warn: #{$background-warning};
+  --pwt-gauge-crit: #{$background-invalid};
+  --pwt-chart-primary: #{$primary-color};
+  --pwt-chart-grid-stroke: #{$content-background-selected};
+}
+
+// Peeks out on the edges of the legend item border
+.x-legend-container {
+  background-color: $content-background-color;
+}
+
+.x-legend-horizontal .x-legend-item {
+  background-color: $background-dark;
+  color: $text-color;
+  border-top: solid 1px $background-darkest;
+  border-right: solid 1px $background-darkest;
+  border-bottom: solid 1px $background-darkest;
+
+  &:first-child {
+    border-left: solid 1px $background-darkest;
+  }
+}
+
+// The "undo zoom" button in the upper right corner of charts when
+// disabled
+.x-tool .x-mask {
+  backdrop-filter: none;
+  background-color: $background-dark;
+  opacity: 0.6;
+}
diff --git a/src/proxmox-dark/scss/other/_icons.scss b/src/proxmox-dark/scss/other/_icons.scss
new file mode 100644
index 0000000..f132dae
--- /dev/null
+++ b/src/proxmox-dark/scss/other/_icons.scss
@@ -0,0 +1,200 @@
+// these styling fix all kinds of icons in grid, treeview etc.
+
+// most icons just use the color attribute..
+// Running containers and VMS
+.x-grid-icon-custom.running,
+.x-tree-icon-custom.running,
+// Icons in trees (e.g. Resource tree)
+.x-tree-icon-custom,
+// Icons in panels, e.g. Search tab
+.fa-database::before,
+// Icon for pools
+.fa-tags::before,
+// The template icon
+.fa-file-o::before,
+// Icon for cluster nodes
+.fa-building::before,
+// e.g. storage list when creating a guest
+.x-action-col-icon::before,
+.fa-shield::before,
+.fa-file-text-o::before,
+.fa-clock-o::before,
+// tab bar icons
+.x-tab-icon-el-default,
+.pve-icon-verify-lettering::after,
+// the small plane when migrating a vm
+.x-tree-icon-custom.lock-migrate::after,
+.x-grid-icon-custom.lock-migrate::after,
+// e.g. permission tree view in pve
+.x-tree-icon-leaf:not(.x-tree-icon-custom)::before,
+.x-tree-icon-parent:not(.x-tree-icon-custom)::before,
+.x-tree-icon-parent-expanded:not(.x-tree-icon-custom)::before {
+  color: $icon-color;
+}
+
+// but some are implement as background SVGs or PNGs. invert them via
+// filters:
+.fa-ceph::before,
+.fa-sdn::before,
+.fa-network-wired::before,
+// Icon for "ISO Images" for storages
+.pve-itype-treelist-item-icon-cdrom,
+// Arrow to the right
+.fa-chevron-right::before,
+// icon indicating a currently open shell session in the task viewer
+.x-grid-row-console,
+// the "triangle" that appears when the sidebar becomes scrollable
+.x-box-scroller-toolbar-default.x-box-scroller,
+// the small triangles in the tree view next to nodes etc.
+.x-tree-elbow-img,
+// the computer icon in the resource pool add menu
+.pve-itype-icon-qemu,
+.x-tree-node-computer,
+.x-grid-tree-node-expanded .x-tree-node-computer,
+.pbs-icon-tape,
+.pbs-icon-tape-drive,
+.x-tree-icon-leaf:not(.x-tree-icon-custom),
+// default tree panel icons (api viewer, pbs backup panel)
+.x-tree-icon-parent:not(.x-tree-icon-custom),
+.x-tree-icon-parent-expanded:not(.x-tree-icon-custom) {
+  filter: invert($icon-brightness);
+}
+
+// the following icons need some additional fix-ups to work well in
+// grids (e.g. when hovered etc.)
+// Icon for the processor in VM hardware settings
+.pve-itype-icon-cpu,
+// Icon for memory in VM hardware settings
+.pve-itype-icon-cdrom,
+// Icon for memory in VM hardware settings
+.pve-itype-icon-memory,
+// the pcie device icon in the vm hardware section
+.pve-itype-icon-pci,
+// the serial device icon in the vm hardware section
+.pve-itype-icon-serial,
+// the rng icon in the vm hardware section
+.pve-itype-icon-die,
+// Processor icon for summary page
+.pmx-itype-icon-processor,
+// Memory icon on summary page
+.pmx-itype-icon-memory,
+// the mount point icon for containers
+.pve-itype-icon-storage,
+.x-tree-node-harddisk,
+.x-grid-tree-node-expanded .x-tree-node-harddisk {
+  filter: invert($icon-brightness);
+
+  // the filter also applies to the text next to the icon
+  .x-grid-cell-inner {
+    color: black;
+  }
+
+  .x-grid-cell-inner::before {
+    // this is a somewhat hacky work-around for the focus borders on
+    // these elements. since we use the invert filter to fix the icon
+    // color we need to also invert the border color first too, not
+    // just the text. add "!important" to properly override.
+    border-color: invert($primary-color, $weight: 90%) !important;
+  }
+}
+
+// pbs show task log in longest task list column
+.x-action-col-icon.fa-chevron-right::before {
+  filter: none;
+}
+
+// checkboxes and radio buttons
+.x-form-checkbox-default,
+.x-form-radio-default,
+.x-column-header-checkbox .x-column-header-checkbox::after,
+.x-grid-checkcolumn::after {
+  filter: invert($icon-brightness) hue-rotate(180deg);
+}
+
+.x-tree-icon-custom,
+.x-grid-icon-custom {
+  &::after {
+    color: $icon-color;
+    text-shadow: -1px 0 1px $background-darker;
+  }
+
+  // stopped containers and VMs
+  &.stopped,
+  // vms/cts that are offline
+  &.offline,
+  // question mark at the bottom right of e.g. unreachable storages
+  &.unknown::after {
+    color: $icon-color-alt;
+  }
+
+  &.lxc::after,
+  &.qemu::after {
+    background-color: $background-darker;
+    color: $icon-color;
+  }
+}
+
+// icons for templates in the storages view
+.x-treelist-item-icon {
+  &.lxc::after,
+  &.qemu::after {
+    background-color: $background-darker;
+    color: $icon-color;
+  }
+}
+
+.x-grid-item .x-grid-icon-custom {
+  &.lxc::after,
+  &.qemu::after {
+    background-color: $background-darker;
+  }
+}
+
+.x-grid-item-alt .x-grid-icon-custom {
+  &.lxc::after,
+  &.qemu::after {
+    background-color: $background-darkest;
+  }
+}
+
+.x-treelist-item-selected {
+  .lxc::after,
+  .qemu::after {
+    background-color: $primary-color;
+    text-shadow: -1px 0 1px $primary-color;
+  }
+}
+
+.x-grid-item-over,
+// hovered items in treelists
+.x-treelist-item-over,
+// template icons when in selected menu item or table row
+.x-grid-item-selected,
+// vm/ct that is focused (e.g. by mouse-down)
+.x-keyboard-mode .x-grid-item-focused {
+  .lxc::after,
+  .qemu::after {
+    background-color: $selection-background-color !important;
+    text-shadow: -1px 0 1px $selection-background-color;
+  }
+}
+
+.x-action-col-icon:hover {
+  &::before,
+  &::after {
+    text-shadow: -1px 0 1px $background-darker;
+  }
+}
+
+// The usage icons dynamically displaying how full a storage is
+.usage-wrapper {
+  border: 1px solid $icon-color;
+}
+
+.usage-negative {
+  background-color: transparent;
+}
+
+.usage {
+  background-color: $icon-color;
+}
diff --git a/src/proxmox-dark/scss/proxmox/_datepicker.scss b/src/proxmox-dark/scss/proxmox/_datepicker.scss
new file mode 100644
index 0000000..068e7e6
--- /dev/null
+++ b/src/proxmox-dark/scss/proxmox/_datepicker.scss
@@ -0,0 +1,61 @@
+.x-datepicker,
+.x-datepicker-column-header,
+.x-monthpicker {
+  background-color: $background-darker;
+  color: $text-color;
+
+  // make the border invisible but keep it to keep the layout intact
+  border-color: transparent;
+}
+
+.x-datepicker-month .x-btn-over.x-btn-default-small {
+  background-color: $selection-background-color;
+}
+
+.x-monthpicker-months {
+  border-color: $border-color-alt;
+}
+
+.x-datepicker-header {
+  background-color: $background-darkest;
+}
+
+.x-datepicker-cell,
+.x-monthpicker-item-inner {
+  // make the border invisible but keep it to keep the layout intact
+  border-color: transparent;
+}
+
+.x-datepicker-date,
+.x-monthpicker-item-inner {
+  color: $text-color;
+}
+
+.x-datepicker-prevday,
+.x-datepicker-nextday {
+  .x-datepicker-date {
+    color: $text-color-inactive;
+  }
+}
+
+.x-datepicker-footer,
+.x-monthpicker-buttons {
+  background-color: $background-darkest;
+}
+
+.x-datepicker-selected div.x-datepicker-date,
+.x-monthpicker-item a.x-monthpicker-selected,
+a.x-monthpicker-item-inner:hover,
+div.x-datepicker-date:hover {
+  @include selection;
+}
+
+.x-datepicker-disabled {
+  .x-datepicker-date {
+    background-color: $background-darkest;
+  }
+
+  div.x-datepicker-date:hover {
+    background-color: $background-darker;
+  }
+}
diff --git a/src/proxmox-dark/scss/proxmox/_general.scss b/src/proxmox-dark/scss/proxmox/_general.scss
new file mode 100644
index 0000000..805a187
--- /dev/null
+++ b/src/proxmox-dark/scss/proxmox/_general.scss
@@ -0,0 +1,56 @@
+// Swapping out the logo with CSS rather than using javascript
+img[id^="proxmoxlogo-"][id$="-img"] {
+  filter: invert(1) hue-rotate(180deg);
+}
+
+// removes the gray line in the header of the mail gateway
+div[id^="versioninfo-"] + div[id^="panel-"] > div[id^="panel-"][id$="-bodyWrap"] > div {
+  background-color: transparent;
+  border-color: transparent;
+}
+
+// border around the main datacenter view
+div[id^="PVE-dc-Config-"][id$="-body"],
+// border around the main pool view
+div[id^="pvePoolConfig-"][id$="-body"],
+// Container content config views
+div[id^="pveLXCConfig-"][id$="-body"],
+// VM content config views
+div[id^="PVE-qemu-Config-"][id$="-body"],
+div[id^="PVE-storage-Browser-"][id$="-body"],
+div[id^="PVE-node-Config-"][id$="-body"] {
+  @include content-border;
+}
+
+// Section header in the "My Settings" page
+.x-fieldset-header-default > .x-fieldset-header-text {
+  color: $text-color;
+}
+
+// Errors and bad configuration (Taskviewer / no repository enabled)
+.proxmox-invalid-row {
+  background-color: $background-invalid;
+}
+
+// Warning rows, e.g. when enabling staging or no-subscription
+// repository
+.proxmox-warning-row {
+  background-color: $background-warning;
+}
+
+// Disabled rows (e.g. disabled repos in Repository view)
+.proxmox-disabled-row td {
+  color: $text-color-inactive;
+}
+
+.pmx-hint {
+  background-color: $background-warning;
+}
+
+.pmx-hint a {
+  color: $highlighted-text-alt;
+}
+
+.pmx-hint a:active {
+  color: $highlighted-text;
+}
diff --git a/src/proxmox-dark/scss/proxmox/_helpbutton.scss b/src/proxmox-dark/scss/proxmox/_helpbutton.scss
new file mode 100644
index 0000000..aad92e2
--- /dev/null
+++ b/src/proxmox-dark/scss/proxmox/_helpbutton.scss
@@ -0,0 +1,16 @@
+// help buttons
+.proxmox-inline-button {
+  background-color: $help-button-color;
+  color: $help-button-text-color;
+
+  &.x-btn-over,
+  &.x-btn.x-btn-pressed.x-btn-default-toolbar-small {
+    background-color: $help-button-color-alt;
+    border-color: $help-button-color-alt;
+  }
+
+  .x-btn-inner,
+  .x-btn-icon-el {
+    color: $help-button-icon-color;
+  }
+}
diff --git a/src/proxmox-dark/scss/proxmox/_loadingindicator.scss b/src/proxmox-dark/scss/proxmox/_loadingindicator.scss
new file mode 100644
index 0000000..5c320b3
--- /dev/null
+++ b/src/proxmox-dark/scss/proxmox/_loadingindicator.scss
@@ -0,0 +1,14 @@
+// loading spinners
+.x-grid-row-loading,
+.x-treelist-item-loading .x-treelist-item-icon,
+.x-treelist-nav .x-treelist-item-loading .x-treelist-item-icon,
+.x-mask-msg-text,
+.x-grid-tree-loading .x-tree-icon {
+  filter: invert($icon-brightness);
+  color: black;
+}
+
+.x-mask-msg {
+  background-color: $form-field-body-color;
+  border: solid 1px mix(black, $form-field-body-color, 25%);
+}
diff --git a/src/proxmox-dark/scss/proxmox/_markdown.scss b/src/proxmox-dark/scss/proxmox/_markdown.scss
new file mode 100644
index 0000000..8531701
--- /dev/null
+++ b/src/proxmox-dark/scss/proxmox/_markdown.scss
@@ -0,0 +1,31 @@
+.pmx-md {
+  code {
+    background-color: $background-darkest;
+  }
+
+  pre code {
+    border-color: $border-color-alt;
+  }
+
+  tbody tr {
+    & td {
+      border-color: $border-color;
+    }
+
+    &:nth-of-type(2n) {
+      background-color: $background-darkest;
+    }
+
+    &:hover td {
+      background-color: $content-background-selected;
+    }
+  }
+
+  a {
+    color: $highlighted-text;
+
+    &:active {
+      color: $highlighted-text-alt;
+    }
+  }
+}
diff --git a/src/proxmox-dark/scss/proxmox/_nodes.scss b/src/proxmox-dark/scss/proxmox/_nodes.scss
new file mode 100644
index 0000000..02b15f9
--- /dev/null
+++ b/src/proxmox-dark/scss/proxmox/_nodes.scss
@@ -0,0 +1,9 @@
+// Table headers under Node > "Updates" > "Repositories"
+.proxmox-apt-repos .x-grid-group-hd {
+  background-color: $background-darker;
+  border-bottom-width: 0;
+}
+
+.proxmox-apt-repos .x-grid-group-title {
+  color: $text-color;
+}
diff --git a/src/proxmox-dark/scss/proxmox/_quarantine.scss b/src/proxmox-dark/scss/proxmox/_quarantine.scss
new file mode 100644
index 0000000..bdda69a
--- /dev/null
+++ b/src/proxmox-dark/scss/proxmox/_quarantine.scss
@@ -0,0 +1,47 @@
+// these css variables define the look of the spamscore grid in pmg
+:root {
+  // using interpolation here may avoid compatability issues between
+  // sass and css. see:
+  // https://sass-lang.com/documentation/breaking-changes/css-vars
+  // for spam with an absolute score >= 3
+  --pmg-spam-high-neg: #{$spam-high-neg};
+  --pmg-spam-high-pos: #{$spam-high-pos};
+
+  // for spam with an absolute score between 0.1 and 3
+  --pmg-spam-mid-neg: #{$spam-mid-neg};
+  --pmg-spam-mid-pos: #{$spam-mid-pos};
+
+  // for spam with an absolute score <= 0.1
+  --pmg-spam-low-neg: #{$spam-low-neg};
+  --pmg-spam-low-pos: #{$spam-low-pos};
+}
+
+.info-blue {
+  // the selector for the button icons have higher specificity than
+  // this one, so we need "!important"
+  color: $highlighted-text !important;
+}
+
+.critical {
+  // the selector for the button icons have higher specificity than
+  // this one, so we need "!important"
+  color: $highlighted-text-crit !important;
+}
+
+// pmg tracking center quarantined rows
+tr.blocked,
+.x-keyboard-mode tr.blocked .x-grid-item-focused {
+  background-color: $background-invalid;
+}
+
+// pmg tracking center quarantined rows
+tr.quarantine,
+.x-keyboard-mode tr.quarantine .x-grid-item-focused {
+  background-color: mix($background-warning, $background-invalid, 50%);
+}
+
+// pmg tracking center blocked rows
+tr.bounced,
+.x-keyboard-mode tr.bounced .x-grid-item-focused {
+  background-color: $background-warning;
+}
diff --git a/src/proxmox-dark/scss/proxmox/_storages.scss b/src/proxmox-dark/scss/proxmox/_storages.scss
new file mode 100644
index 0000000..46b94f4
--- /dev/null
+++ b/src/proxmox-dark/scss/proxmox/_storages.scss
@@ -0,0 +1,19 @@
+// ceph page
+table.osds {
+  tr {
+    border-color: $border-color;
+  }
+
+  td {
+    border-color: $border-color;
+  }
+}
+
+.install-mask {
+  background-color: $background-darker;
+  color: $text-color;
+}
+
+div.monitor {
+  border-color: $border-color;
+}
diff --git a/src/proxmox-dark/scss/proxmox/_tags.scss b/src/proxmox-dark/scss/proxmox/_tags.scss
new file mode 100644
index 0000000..09ad623
--- /dev/null
+++ b/src/proxmox-dark/scss/proxmox/_tags.scss
@@ -0,0 +1,14 @@
+.pve-edit-tag.editable span {
+  background-color: $form-field-body-color;
+  color: $text-color;
+  border-color: $border-color;
+}
+
+// adds a bit of outline to make tags stand out more
+.proxmox-tags-full,
+.proxmox-tags-circle {
+  .proxmox-tag-light,
+  .proxmox-tag-dark {
+    outline: 1px solid rgba($background-dark, 0.3);
+  }
+}
-- 
2.30.2





  parent reply	other threads:[~2023-03-08 16:33 UTC|newest]

Thread overview: 55+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-03-08 16:18 [pve-devel] [PATCH widget-toolkit v1] Proxmox Dark Theme Stefan Sterz
2023-03-08 16:18 ` [pmg-devel] " Stefan Sterz
2023-03-08 16:18 ` [pbs-devel] " Stefan Sterz
2023-03-08 16:25 ` [pve-devel] " Stefan Sterz
2023-03-08 16:25   ` [pmg-devel] " Stefan Sterz
2023-03-08 16:25   ` [pbs-devel] " Stefan Sterz
2023-03-08 16:33 ` Stefan Sterz [this message]
2023-03-08 16:33   ` [pmg-devel] [PATCH widget-toolkit v1 1/6] dark-theme: add initial version of the proxmox-dark theme Stefan Sterz
2023-03-08 16:33   ` [pbs-devel] " Stefan Sterz
2023-03-08 16:36 ` [pve-devel] [PATCH widget-toolkit v1 2/6] subscription/summary/backup: stop setting the background color Stefan Sterz
2023-03-08 16:36   ` [pmg-devel] " Stefan Sterz
2023-03-08 16:36   ` [pbs-devel] " Stefan Sterz
2023-03-08 16:36   ` [pve-devel] [PATCH widget-toolkit v1 3/6] gauge widget: add support for a dark theme and dynamic theme switching Stefan Sterz
2023-03-08 16:36     ` [pmg-devel] " Stefan Sterz
2023-03-08 16:36     ` [pbs-devel] " Stefan Sterz
2023-03-08 16:36   ` [pve-devel] [PATCH widget-toolkit v1 4/6] rrd chart: add support for the " Stefan Sterz
2023-03-08 16:36     ` [pmg-devel] " Stefan Sterz
2023-03-08 16:36     ` [pbs-devel] " Stefan Sterz
2023-03-08 16:37 ` [pve-devel] [PATCH widget-toolkit v1 5/6] util/window/form: add a theme selector Stefan Sterz
2023-03-08 16:37   ` [pmg-devel] " Stefan Sterz
2023-03-08 16:37   ` [pbs-devel] " Stefan Sterz
2023-03-08 16:37   ` [pve-devel] [PATCH widget-toolkit v1 6/6] dark-theme: add support for the pmg quarantine theme toggle Stefan Sterz
2023-03-08 16:37     ` [pmg-devel] " Stefan Sterz
2023-03-08 16:37     ` [pbs-devel] " Stefan Sterz
2023-03-08 16:40 ` [pve-devel] [PATCH manager v1 1/4] gui: create user info menu intro for selecting the theme Stefan Sterz
2023-03-08 16:40   ` [pve-devel] [PATCH manager v1 2/4] pveproxy/template: add support for switching themes Stefan Sterz
2023-03-08 16:40   ` [pve-devel] [PATCH manager v1 3/4] subscription/summary/backup: stop setting the background color Stefan Sterz
2023-03-08 16:40   ` [pve-devel] [PATCH manager v1 4/4] ui: make ceph charts change color more dynamically Stefan Sterz
2023-03-08 16:40   ` [pve-devel] [PATCH docs v1] docs: add dark mode support to the api viewer Stefan Sterz
2023-03-08 17:05   ` [pve-devel] applied-series: [PATCH manager v1 1/4] gui: create user info menu intro for selecting the theme Thomas Lamprecht
2023-03-09  8:07     ` [pve-devel] Shell command and Emacs Lisp code injection in emacsclient-mail.desktop Stefan Sterz
2023-03-09  8:16       ` [pve-devel] applied-series: [PATCH manager v1 1/4] gui: create user info menu intro for selecting the theme Thomas Lamprecht
2023-03-09  8:29         ` Stefan Sterz
2023-03-08 16:41 ` [pbs-devel] [PATCH proxmox-backup v1 1/3] proxy/ui: implement theme switcher Stefan Sterz
2023-03-08 16:41   ` [pbs-devel] [PATCH proxmox-backup v1 2/3] ui: remove white backgrounds from package versions and system report Stefan Sterz
2023-03-14 16:56   ` [pbs-devel] applied: [PATCH proxmox-backup v1 1/3] proxy/ui: implement theme switcher Thomas Lamprecht
2023-03-08 16:43 ` [pbs-devel] [PATCH proxmox-backup v1 2/3] ui: remove white backgrounds from package versions and system report Stefan Sterz
2023-03-08 16:45 ` [pbs-devel] From 39998aadbf833c19a83fea3549105e625b029c50 Mon Sep 17 00:00:00 2001 Stefan Sterz
2023-03-08 16:51   ` Stefan Sterz
2023-03-08 17:04 ` [pve-devel] applied-series: [PATCH widget-toolkit v1] Proxmox Dark Theme Thomas Lamprecht
2023-03-08 17:04   ` [pmg-devel] applied-series: [pve-devel] " Thomas Lamprecht
2023-03-08 17:04   ` [pbs-devel] " Thomas Lamprecht
2023-03-09  8:00 ` [pmg-devel] [PATCH pmg-api v1] proxy: add support for switching themes Stefan Sterz
2023-03-10 10:14   ` Dominik Csapak
2023-03-10 10:24     ` Stefan Sterz
2023-03-15 15:42   ` [pmg-devel] applied: " Thomas Lamprecht
2023-03-09  8:00 ` [pmg-devel] [PATCH pmg-gui v1 1/6] mainview/quarantine: add theme switcher Stefan Sterz
2023-03-15 15:42   ` [pmg-devel] applied: " Thomas Lamprecht
2023-03-09  8:00 ` [pmg-devel] [PATCH pmg-gui v1 2/6] spam-info-grid: style the spam info grid via css variables Stefan Sterz
2023-03-09  8:01 ` [pmg-devel] [PATCH pmg-gui v1 3/6] subscription: remove hard-coded white background Stefan Sterz
2023-03-09  8:01 ` [pmg-devel] [PATCH pmg-gui v1 4/6] hourly mail distribution chart: add dynamic color switching Stefan Sterz
2023-03-09  8:01 ` [pmg-devel] [PATCH pmg-gui v1 5/6] mobile quarantine: add dark theme support to the mobile quarantine Stefan Sterz
2023-03-09  8:01 ` [pmg-devel] [PATCH pmg-gui v1 6/6] quarantines: add support for a theme toggle Stefan Sterz
2023-03-09  8:02 ` [pmg-devel] [PATCH pmg-docs v1] docs: add dark mode support to the api viewer Stefan Sterz
2023-03-23 16:11   ` [pmg-devel] applied: " Thomas Lamprecht

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230308163312.2441849-1-s.sterz@proxmox.com \
    --to=s.sterz@proxmox.com \
    --cc=pbs-devel@lists.proxmox.com \
    --cc=pmg-devel@lists.proxmox.com \
    --cc=pve-devel@lists.proxmox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal