diff --git a/apps/dashboard/css/dashboard.scss b/apps/dashboard/css/dashboard.scss
new file mode 100644
index 0000000000000000000000000000000000000000..a320b3e3c99629b762435c5aac966b50ddc5c0fb
--- /dev/null
+++ b/apps/dashboard/css/dashboard.scss
@@ -0,0 +1,71 @@
+// Show Dashboard background image beneath header
+#body-user #header {
+	background-size: cover !important;
+	background-position: center 50% !important;
+	background-repeat: no-repeat !important;
+	background-attachment: fixed !important;
+}
+
+#content {
+	padding-top: 0 !important;
+}
+
+// Hide triangle indicators from navigation since they are out of place without the header bar
+#appmenu li a.active::before,
+#appmenu li:hover a::before,
+#appmenu li:hover a.active::before,
+#appmenu li a:focus::before {
+	display: none !important;
+}
+
+$has-custom-logo: variable_exists('theming-logo-mime') and $theming-logo-mime != '';
+
+body.dashboard-inverted:not(.dashboard-dark) {
+	// Do not invert the default logo
+	@if ($has-custom-logo == false) {
+		$image-logo: url(icon-color-path('logo', 'logo', #ffffff, 1, true));
+		#header .logo {
+			background-image: $image-logo !important;
+			opacity: 1;
+		}
+	}
+
+	#app-dashboard > h2 {
+		color: #fff;
+	}
+	#appmenu li span {
+		color: #fff;
+	}
+	#appmenu svg image {
+		filter: invert(0);
+	}
+	#appmenu .icon-more-white,
+	.header-right > div:not(#settings) > * {
+		filter: invert(1) hue-rotate(180deg);
+	}
+}
+
+body.dashboard-dark:not(.dashboard-inverted) {
+	// invert the default logo
+	@if ($has-custom-logo == false) {
+		$image-logo: url(icon-color-path('logo', 'logo', #000000, 1, true));
+		#header .logo {
+			background-image: $image-logo !important;
+			opacity: 1;
+		}
+	}
+
+	#app-dashboard > h2 {
+		color: #000;
+	}
+	#appmenu li span {
+		color: #000;
+	}
+	#appmenu svg {
+		filter: invert(1) !important;
+	}
+	#appmenu .icon-more-white,
+	.header-right > div:not(#settings) > * {
+		filter: invert(1) hue-rotate(180deg);
+	}
+}
diff --git a/apps/dashboard/lib/Controller/DashboardController.php b/apps/dashboard/lib/Controller/DashboardController.php
index 3f4c9fdbfa4a75b23c4776ef24c17f3c0a521214..95656b260e8452de67b50794d4d9b7b074f0d000 100644
--- a/apps/dashboard/lib/Controller/DashboardController.php
+++ b/apps/dashboard/lib/Controller/DashboardController.php
@@ -87,6 +87,7 @@ class DashboardController extends Controller {
 	 * @return TemplateResponse
 	 */
 	public function index(): TemplateResponse {
+		\OCP\Util::addStyle('dashboard', 'dashboard');
 		$this->eventDispatcher->dispatchTyped(new LoadSidebar());
 		if (class_exists(LoadViewer::class)) {
 			$this->eventDispatcher->dispatchTyped(new LoadViewer());
diff --git a/apps/dashboard/lib/Service/BackgroundService.php b/apps/dashboard/lib/Service/BackgroundService.php
index 30e9d9fe3cb330fdfa514a0396359cb61a380ee1..4e154dd0170ac38b85c76e8c44a5915c35ddd693 100644
--- a/apps/dashboard/lib/Service/BackgroundService.php
+++ b/apps/dashboard/lib/Service/BackgroundService.php
@@ -47,6 +47,7 @@ class BackgroundService {
 		'bernie-cetonia-aurata-take-off-composition.jpg' => [
 			'attribution' => '',
 			'attribution_url' => '',
+			'theming' => self::THEMING_MODE_DARK,
 		],
 		'dejan-krsmanovic-ribbed-red-metal.jpg' => [
 			'attribution' => '',
diff --git a/apps/dashboard/src/App.vue b/apps/dashboard/src/App.vue
index c59e4732373e790dc52b5c6385bff39d1f4fea05..a2cccfce3ff6dca7ce32493b7f8052b012df60c8 100644
--- a/apps/dashboard/src/App.vue
+++ b/apps/dashboard/src/App.vue
@@ -4,8 +4,9 @@
 		<div class="statuses">
 			<div v-for="status in registeredStatus"
 				:id="'status-' + status"
-				:key="status"
-				:ref="'status-' + status" />
+				:key="status">
+				<div :ref="'status-' + status" />
+			</div>
 		</div>
 
 		<Draggable v-model="layout"
@@ -83,6 +84,7 @@ const panels = loadState('dashboard', 'panels')
 const firstRun = loadState('dashboard', 'firstRun')
 const background = loadState('dashboard', 'background')
 const version = loadState('dashboard', 'version')
+const shippedBackgroundList = loadState('dashboard', 'shippedBackgrounds')
 
 export default {
 	name: 'App',
@@ -192,6 +194,8 @@ export default {
 		},
 	},
 	mounted() {
+		this.updateGlobalStyles()
+
 		setInterval(() => {
 			this.timer = new Date()
 		}, 30000)
@@ -268,31 +272,26 @@ export default {
 		updateBackground(data) {
 			this.background = data.type === 'custom' || data.type === 'default' ? data.type : data.value
 			this.version = data.version
+			this.updateGlobalStyles()
+		},
+		updateGlobalStyles() {
+			if (window.OCA.Theming.inverted) {
+				document.body.classList.add('dashboard-inverted')
+			}
+
+			const shippedBackgroundTheme = shippedBackgroundList[this.background] ? shippedBackgroundList[this.background].theming : 'light'
+			if (shippedBackgroundTheme === 'dark') {
+				document.body.classList.add('dashboard-dark')
+			} else {
+				document.body.classList.remove('dashboard-dark')
+			}
 		},
 	},
 }
 </script>
 
 <style lang="scss">
-// Show Dashboard background image beneath header
-#body-user #header {
-	background-size: cover;
-	background-position: center 50%;
-	background-repeat: no-repeat;
-	background-attachment: fixed;
-}
 
-#content {
-	padding-top: 0;
-}
-
-// Hide triangle indicators from navigation since they are out of place without the header bar
-#appmenu li a.active::before,
-#appmenu li:hover a::before,
-#appmenu li:hover a.active::before,
-#appmenu li a:focus::before {
-	display: none;
-}
 </style>
 
 <style lang="scss" scoped>
@@ -490,6 +489,8 @@ export default {
 
 		& > div {
 			max-width: 200px;
+			margin-left: 10px;
+			margin-right: 10px;
 		}
 	}