From f9e3b7211910338ec485170f4d18325398bc1d7a Mon Sep 17 00:00:00 2001
From: Kit La Touche <kit@transneptune.net>
Date: Mon, 11 Nov 2024 22:20:35 -0500
Subject: Style own messages

---
 ui/lib/components/MessageRun.svelte | 18 ++++++++++++++++--
 1 file changed, 16 insertions(+), 2 deletions(-)

(limited to 'ui/lib/components/MessageRun.svelte')

diff --git a/ui/lib/components/MessageRun.svelte b/ui/lib/components/MessageRun.svelte
index 2e8c613..2a88a82 100644
--- a/ui/lib/components/MessageRun.svelte
+++ b/ui/lib/components/MessageRun.svelte
@@ -16,7 +16,21 @@
   <span class="chip variant-soft sticky top-o left-0">
     @{name}:
   </span>
-  {#each messages as { at, body }}
-    <Message {at} {body} />
+  {#each messages as message}
+    <Message {...message} />
   {/each}
 </div>
+
+<style>
+  .own-message {
+    background-color: rgb(32, 42, 74);
+  }
+  /* Honestly, I don't love scoping styles per component, and this is a great
+   * example of why. MessageRuns know if they're own-message, but Messages in
+   * them need to get a style based on that fact. I don't wanna bucket-brigade
+   * that fact into the Message, when it's a pure CSS concern.
+   */
+  .own-message :global(*) {
+    color: rgb(198, 198, 198);
+  }
+</style>
-- 
cgit v1.2.3


From 1859be064a5f3ea7e6e0188526b1b125dc1c77a7 Mon Sep 17 00:00:00 2001
From: Kit La Touche <kit@transneptune.net>
Date: Mon, 30 Dec 2024 15:42:37 -0500
Subject: Strip out Tailwind etc

---
 build.rs                                   |    1 -
 package-lock.json                          | 1020 ++++------------------------
 package.json                               |    5 +-
 postcss.config.js                          |    1 -
 tailwind.config.js                         |   25 -
 ui/app.html                                |    2 +-
 ui/lib/components/ChangePassword.svelte    |    5 +-
 ui/lib/components/Channel.svelte           |   14 +-
 ui/lib/components/CreateChannelForm.svelte |    8 +-
 ui/lib/components/Invite.svelte            |    6 +-
 ui/lib/components/Invites.svelte           |    6 +-
 ui/lib/components/LogIn.svelte             |   10 +-
 ui/lib/components/LogOut.svelte            |    2 +-
 ui/lib/components/Message.svelte           |    4 +-
 ui/lib/components/MessageInput.svelte      |    7 +-
 ui/lib/components/MessageRun.svelte        |    3 +-
 ui/routes/(app)/+layout.svelte             |    9 -
 ui/routes/+layout.svelte                   |   19 +-
 18 files changed, 160 insertions(+), 987 deletions(-)
 delete mode 100644 tailwind.config.js

(limited to 'ui/lib/components/MessageRun.svelte')

diff --git a/build.rs b/build.rs
index a61b2db..3b7abda 100644
--- a/build.rs
+++ b/build.rs
@@ -30,7 +30,6 @@ fn main() -> Result<(), io::Error> {
     // println!("cargo::rerun-if-changed=node_modules");
     println!("cargo::rerun-if-changed=postcss.config.js");
     println!("cargo::rerun-if-changed=svelte.config.js");
-    println!("cargo::rerun-if-changed=tailwind.config.js");
     println!("cargo::rerun-if-changed=vite.config.js");
     println!("cargo::rerun-if-changed=ui");
     let status = Command::new("npm").args(["run", "build"]).status()?;
diff --git a/package-lock.json b/package-lock.json
index 7d8be51..edf23f7 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -15,12 +15,9 @@
 				"tinygesture": "^3.0.0"
 			},
 			"devDependencies": {
-				"@skeletonlabs/skeleton": "^2.10.3",
-				"@skeletonlabs/tw-plugin": "^0.4.0",
 				"@sveltejs/adapter-static": "^3.0.6",
 				"@sveltejs/kit": "^2.7.4",
 				"@sveltejs/vite-plugin-svelte": "^4.0.0",
-				"@tailwindcss/forms": "^0.5.9",
 				"@types/eslint": "^9.6.1",
 				"@vitest/coverage-v8": "^2.1.4",
 				"autoprefixer": "^10.4.20",
@@ -33,7 +30,7 @@
 				"prettier": "^3.3.3",
 				"prettier-plugin-svelte": "^3.2.7",
 				"svelte": "^5.1.9",
-				"tailwindcss": "^3.4.14",
+				"svelte-copy": "^2.0.0",
 				"vite": "^5.4.10",
 				"vitest": "^2.1.4"
 			},
@@ -42,19 +39,6 @@
 				"npm": ">=10.0.0 <11.0.0"
 			}
 		},
-		"node_modules/@alloc/quick-lru": {
-			"version": "5.2.0",
-			"resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz",
-			"integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==",
-			"dev": true,
-			"license": "MIT",
-			"engines": {
-				"node": ">=10"
-			},
-			"funding": {
-				"url": "https://github.com/sponsors/sindresorhus"
-			}
-		},
 		"node_modules/@ampproject/remapping": {
 			"version": "2.3.0",
 			"resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz",
@@ -143,40 +127,6 @@
 				"node": ">=12"
 			}
 		},
-		"node_modules/@esbuild/linux-arm64": {
-			"version": "0.21.5",
-			"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz",
-			"integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==",
-			"cpu": [
-				"arm64"
-			],
-			"dev": true,
-			"license": "MIT",
-			"optional": true,
-			"os": [
-				"linux"
-			],
-			"engines": {
-				"node": ">=12"
-			}
-		},
-		"node_modules/@esbuild/linux-x64": {
-			"version": "0.21.5",
-			"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz",
-			"integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==",
-			"cpu": [
-				"x64"
-			],
-			"dev": true,
-			"license": "MIT",
-			"optional": true,
-			"os": [
-				"linux"
-			],
-			"engines": {
-				"node": ">=12"
-			}
-		},
 		"node_modules/@eslint-community/eslint-utils": {
 			"version": "4.4.0",
 			"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
@@ -299,9 +249,9 @@
 			}
 		},
 		"node_modules/@eslint/plugin-kit": {
-			"version": "0.2.1",
-			"resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.1.tgz",
-			"integrity": "sha512-HFZ4Mp26nbWk9d/BpvP0YNL6W4UoZF0VFcTw/aPPA8RpOxeFQgK+ClABGgAUXs9Y/RGX/l1vOmrqz1MQt9MNuw==",
+			"version": "0.2.4",
+			"resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.4.tgz",
+			"integrity": "sha512-zSkKow6H5Kdm0ZUQUB2kV5JIXqoG0+uH5YADhaEHswm664N9Db8dXSi0nMJpacpMf+MyyglF1vnZohpEg5yUtg==",
 			"dev": true,
 			"license": "Apache-2.0",
 			"dependencies": {
@@ -440,6 +390,19 @@
 				"node": ">=6.0.0"
 			}
 		},
+		"node_modules/@jridgewell/source-map": {
+			"version": "0.3.6",
+			"resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz",
+			"integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==",
+			"dev": true,
+			"license": "MIT",
+			"optional": true,
+			"peer": true,
+			"dependencies": {
+				"@jridgewell/gen-mapping": "^0.3.5",
+				"@jridgewell/trace-mapping": "^0.3.25"
+			}
+		},
 		"node_modules/@jridgewell/sourcemap-codec": {
 			"version": "1.5.0",
 			"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
@@ -458,44 +421,6 @@
 				"@jridgewell/sourcemap-codec": "^1.4.14"
 			}
 		},
-		"node_modules/@nodelib/fs.scandir": {
-			"version": "2.1.5",
-			"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
-			"integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
-			"dev": true,
-			"license": "MIT",
-			"dependencies": {
-				"@nodelib/fs.stat": "2.0.5",
-				"run-parallel": "^1.1.9"
-			},
-			"engines": {
-				"node": ">= 8"
-			}
-		},
-		"node_modules/@nodelib/fs.stat": {
-			"version": "2.0.5",
-			"resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
-			"integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
-			"dev": true,
-			"license": "MIT",
-			"engines": {
-				"node": ">= 8"
-			}
-		},
-		"node_modules/@nodelib/fs.walk": {
-			"version": "1.2.8",
-			"resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
-			"integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
-			"dev": true,
-			"license": "MIT",
-			"dependencies": {
-				"@nodelib/fs.scandir": "2.1.5",
-				"fastq": "^1.6.0"
-			},
-			"engines": {
-				"node": ">= 8"
-			}
-		},
 		"node_modules/@pkgjs/parseargs": {
 			"version": "0.11.0",
 			"resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
@@ -528,89 +453,10 @@
 				"darwin"
 			]
 		},
-		"node_modules/@rollup/rollup-linux-arm64-gnu": {
-			"version": "4.24.0",
-			"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.24.0.tgz",
-			"integrity": "sha512-i0xTLXjqap2eRfulFVlSnM5dEbTVque/3Pi4g2y7cxrs7+a9De42z4XxKLYJ7+OhE3IgxvfQM7vQc43bwTgPwA==",
-			"cpu": [
-				"arm64"
-			],
-			"dev": true,
-			"license": "MIT",
-			"optional": true,
-			"os": [
-				"linux"
-			]
-		},
-		"node_modules/@rollup/rollup-linux-arm64-musl": {
-			"version": "4.24.0",
-			"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.24.0.tgz",
-			"integrity": "sha512-9E6MKUJhDuDh604Qco5yP/3qn3y7SLXYuiC0Rpr89aMScS2UAmK1wHP2b7KAa1nSjWJc/f/Lc0Wl1L47qjiyQw==",
-			"cpu": [
-				"arm64"
-			],
-			"dev": true,
-			"license": "MIT",
-			"optional": true,
-			"os": [
-				"linux"
-			]
-		},
-		"node_modules/@rollup/rollup-linux-x64-gnu": {
-			"version": "4.24.0",
-			"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.24.0.tgz",
-			"integrity": "sha512-ZXFk7M72R0YYFN5q13niV0B7G8/5dcQ9JDp8keJSfr3GoZeXEoMHP/HlvqROA3OMbMdfr19IjCeNAnPUG93b6A==",
-			"cpu": [
-				"x64"
-			],
-			"dev": true,
-			"license": "MIT",
-			"optional": true,
-			"os": [
-				"linux"
-			]
-		},
-		"node_modules/@rollup/rollup-linux-x64-musl": {
-			"version": "4.24.0",
-			"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.24.0.tgz",
-			"integrity": "sha512-w1i+L7kAXZNdYl+vFvzSZy8Y1arS7vMgIy8wusXJzRrPyof5LAb02KGr1PD2EkRcl73kHulIID0M501lN+vobQ==",
-			"cpu": [
-				"x64"
-			],
-			"dev": true,
-			"license": "MIT",
-			"optional": true,
-			"os": [
-				"linux"
-			]
-		},
-		"node_modules/@skeletonlabs/skeleton": {
-			"version": "2.10.3",
-			"resolved": "https://registry.npmjs.org/@skeletonlabs/skeleton/-/skeleton-2.10.3.tgz",
-			"integrity": "sha512-O1RecF68zEVvZl3GgRS4emqWMUIQLHvTOFoqGOw/2OXCPE06IxUQrHQf2hnxCPxtGZNXY2YX8UNV38l+eH8GNQ==",
-			"dev": true,
-			"license": "MIT",
-			"dependencies": {
-				"esm-env": "1.0.0"
-			},
-			"peerDependencies": {
-				"svelte": "^3.56.0 || ^4.0.0 || ^5.0.0"
-			}
-		},
-		"node_modules/@skeletonlabs/tw-plugin": {
-			"version": "0.4.0",
-			"resolved": "https://registry.npmjs.org/@skeletonlabs/tw-plugin/-/tw-plugin-0.4.0.tgz",
-			"integrity": "sha512-v6Y4deBq9ByRx3kTRGgekhhYkWEYgNNNu8UXOwJngCStB7w8SwmbNFSeHkluxMbgCgMnJyp220EMpw9nj/rEsQ==",
-			"dev": true,
-			"license": "MIT",
-			"peerDependencies": {
-				"tailwindcss": ">=3.0.0"
-			}
-		},
 		"node_modules/@sveltejs/adapter-static": {
-			"version": "3.0.6",
-			"resolved": "https://registry.npmjs.org/@sveltejs/adapter-static/-/adapter-static-3.0.6.tgz",
-			"integrity": "sha512-MGJcesnJWj7FxDcB/GbrdYD3q24Uk0PIL4QIX149ku+hlJuj//nxUbb0HxUTpjkecWfHjVveSUnUaQWnPRXlpg==",
+			"version": "3.0.8",
+			"resolved": "https://registry.npmjs.org/@sveltejs/adapter-static/-/adapter-static-3.0.8.tgz",
+			"integrity": "sha512-YaDrquRpZwfcXbnlDsSrBQNCChVOT9MGuSg+dMAyfsAa1SmiAhrA5jUYUiIMC59G92kIbY/AaQOWcBdq+lh+zg==",
 			"dev": true,
 			"license": "MIT",
 			"peerDependencies": {
@@ -618,9 +464,9 @@
 			}
 		},
 		"node_modules/@sveltejs/kit": {
-			"version": "2.7.4",
-			"resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.7.4.tgz",
-			"integrity": "sha512-3DOPQYck3CpAmPgGq/HuhJMCCz8GF0ukbompPJQ2zShoSzrEKW9iG/l0nZmaxMvuOO3NNLmZj8F3W9uzqmkNdw==",
+			"version": "2.15.1",
+			"resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.15.1.tgz",
+			"integrity": "sha512-8t7D3hQHbUDMiaQ2RVnjJJ/+Ur4Fn/tkeySJCsHtX346Q9cp3LAnav8xXdfuqYNJwpUGX0x3BqF1uvbmXQw93A==",
 			"dev": true,
 			"hasInstallScript": true,
 			"license": "MIT",
@@ -628,7 +474,7 @@
 				"@types/cookie": "^0.6.0",
 				"cookie": "^0.6.0",
 				"devalue": "^5.1.0",
-				"esm-env": "^1.0.0",
+				"esm-env": "^1.2.1",
 				"import-meta-resolve": "^4.1.0",
 				"kleur": "^4.1.5",
 				"magic-string": "^0.30.5",
@@ -645,9 +491,9 @@
 				"node": ">=18.13"
 			},
 			"peerDependencies": {
-				"@sveltejs/vite-plugin-svelte": "^3.0.0 || ^4.0.0-next.1",
+				"@sveltejs/vite-plugin-svelte": "^3.0.0 || ^4.0.0-next.1 || ^5.0.0",
 				"svelte": "^4.0.0 || ^5.0.0-next.0",
-				"vite": "^5.0.3"
+				"vite": "^5.0.3 || ^6.0.0"
 			}
 		},
 		"node_modules/@sveltejs/vite-plugin-svelte": {
@@ -690,19 +536,6 @@
 				"vite": "^5.0.0"
 			}
 		},
-		"node_modules/@tailwindcss/forms": {
-			"version": "0.5.9",
-			"resolved": "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.5.9.tgz",
-			"integrity": "sha512-tM4XVr2+UVTxXJzey9Twx48c1gcxFStqn1pQz0tRsX8o3DvxhN5oY5pvyAbUx7VTaZxpej4Zzvc6h+1RJBzpIg==",
-			"dev": true,
-			"license": "MIT",
-			"dependencies": {
-				"mini-svg-data-uri": "^1.2.3"
-			},
-			"peerDependencies": {
-				"tailwindcss": ">=3.0.0 || >= 3.0.0-alpha.1 || >= 4.0.0-alpha.20"
-			}
-		},
 		"node_modules/@types/cookie": {
 			"version": "0.6.0",
 			"resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz",
@@ -735,6 +568,18 @@
 			"dev": true,
 			"license": "MIT"
 		},
+		"node_modules/@types/node": {
+			"version": "22.10.2",
+			"resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz",
+			"integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==",
+			"dev": true,
+			"license": "MIT",
+			"optional": true,
+			"peer": true,
+			"dependencies": {
+				"undici-types": "~6.20.0"
+			}
+		},
 		"node_modules/@vitest/coverage-v8": {
 			"version": "2.1.4",
 			"resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-2.1.4.tgz",
@@ -973,34 +818,6 @@
 				"url": "https://github.com/chalk/ansi-styles?sponsor=1"
 			}
 		},
-		"node_modules/any-promise": {
-			"version": "1.3.0",
-			"resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
-			"integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==",
-			"dev": true,
-			"license": "MIT"
-		},
-		"node_modules/anymatch": {
-			"version": "3.1.3",
-			"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
-			"integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
-			"dev": true,
-			"license": "ISC",
-			"dependencies": {
-				"normalize-path": "^3.0.0",
-				"picomatch": "^2.0.4"
-			},
-			"engines": {
-				"node": ">= 8"
-			}
-		},
-		"node_modules/arg": {
-			"version": "5.0.2",
-			"resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz",
-			"integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==",
-			"dev": true,
-			"license": "MIT"
-		},
 		"node_modules/argparse": {
 			"version": "2.0.1",
 			"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
@@ -1100,19 +917,6 @@
 			"dev": true,
 			"license": "MIT"
 		},
-		"node_modules/binary-extensions": {
-			"version": "2.3.0",
-			"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
-			"integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
-			"dev": true,
-			"license": "MIT",
-			"engines": {
-				"node": ">=8"
-			},
-			"funding": {
-				"url": "https://github.com/sponsors/sindresorhus"
-			}
-		},
 		"node_modules/brace-expansion": {
 			"version": "1.1.11",
 			"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@@ -1124,19 +928,6 @@
 				"concat-map": "0.0.1"
 			}
 		},
-		"node_modules/braces": {
-			"version": "3.0.3",
-			"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
-			"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
-			"dev": true,
-			"license": "MIT",
-			"dependencies": {
-				"fill-range": "^7.1.1"
-			},
-			"engines": {
-				"node": ">=8"
-			}
-		},
 		"node_modules/browserslist": {
 			"version": "4.24.0",
 			"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.0.tgz",
@@ -1170,6 +961,15 @@
 				"node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
 			}
 		},
+		"node_modules/buffer-from": {
+			"version": "1.1.2",
+			"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
+			"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
+			"dev": true,
+			"license": "MIT",
+			"optional": true,
+			"peer": true
+		},
 		"node_modules/cac": {
 			"version": "6.7.14",
 			"resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz",
@@ -1190,16 +990,6 @@
 				"node": ">=6"
 			}
 		},
-		"node_modules/camelcase-css": {
-			"version": "2.0.1",
-			"resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz",
-			"integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==",
-			"dev": true,
-			"license": "MIT",
-			"engines": {
-				"node": ">= 6"
-			}
-		},
 		"node_modules/caniuse-lite": {
 			"version": "1.0.30001669",
 			"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001669.tgz",
@@ -1265,44 +1055,6 @@
 				"node": ">= 16"
 			}
 		},
-		"node_modules/chokidar": {
-			"version": "3.6.0",
-			"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
-			"integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
-			"dev": true,
-			"license": "MIT",
-			"dependencies": {
-				"anymatch": "~3.1.2",
-				"braces": "~3.0.2",
-				"glob-parent": "~5.1.2",
-				"is-binary-path": "~2.1.0",
-				"is-glob": "~4.0.1",
-				"normalize-path": "~3.0.0",
-				"readdirp": "~3.6.0"
-			},
-			"engines": {
-				"node": ">= 8.10.0"
-			},
-			"funding": {
-				"url": "https://paulmillr.com/funding/"
-			},
-			"optionalDependencies": {
-				"fsevents": "~2.3.2"
-			}
-		},
-		"node_modules/chokidar/node_modules/glob-parent": {
-			"version": "5.1.2",
-			"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
-			"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
-			"dev": true,
-			"license": "ISC",
-			"dependencies": {
-				"is-glob": "^4.0.1"
-			},
-			"engines": {
-				"node": ">= 6"
-			}
-		},
 		"node_modules/color-convert": {
 			"version": "2.0.1",
 			"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
@@ -1336,14 +1088,13 @@
 			}
 		},
 		"node_modules/commander": {
-			"version": "4.1.1",
-			"resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
-			"integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==",
+			"version": "2.20.3",
+			"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+			"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
 			"dev": true,
 			"license": "MIT",
-			"engines": {
-				"node": ">= 6"
-			}
+			"optional": true,
+			"peer": true
 		},
 		"node_modules/concat-map": {
 			"version": "0.0.1",
@@ -1363,9 +1114,9 @@
 			}
 		},
 		"node_modules/cross-spawn": {
-			"version": "7.0.3",
-			"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
-			"integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+			"version": "7.0.6",
+			"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
+			"integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
 			"dev": true,
 			"license": "MIT",
 			"dependencies": {
@@ -1485,20 +1236,6 @@
 			"dev": true,
 			"license": "MIT"
 		},
-		"node_modules/didyoumean": {
-			"version": "1.2.2",
-			"resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz",
-			"integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==",
-			"dev": true,
-			"license": "Apache-2.0"
-		},
-		"node_modules/dlv": {
-			"version": "1.1.3",
-			"resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz",
-			"integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==",
-			"dev": true,
-			"license": "MIT"
-		},
 		"node_modules/dompurify": {
 			"version": "3.1.7",
 			"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.1.7.tgz",
@@ -1757,9 +1494,9 @@
 			}
 		},
 		"node_modules/esm-env": {
-			"version": "1.0.0",
-			"resolved": "https://registry.npmjs.org/esm-env/-/esm-env-1.0.0.tgz",
-			"integrity": "sha512-Cf6VksWPsTuW01vU9Mk/3vRue91Zevka5SjyNf3nEpokFRuqt/KjUQoGAwq9qMmhpLTHmXzSIrFRw8zxWzmFBA==",
+			"version": "1.2.1",
+			"resolved": "https://registry.npmjs.org/esm-env/-/esm-env-1.2.1.tgz",
+			"integrity": "sha512-U9JedYYjCnadUlXk7e1Kr+aENQhtUaoaV9+gZm1T8LC/YBAPJx3NSPIAurFOC0U5vrdSevnUJS2/wUVxGwPhng==",
 			"dev": true,
 			"license": "MIT"
 		},
@@ -1865,36 +1602,6 @@
 			"dev": true,
 			"license": "MIT"
 		},
-		"node_modules/fast-glob": {
-			"version": "3.3.2",
-			"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz",
-			"integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==",
-			"dev": true,
-			"license": "MIT",
-			"dependencies": {
-				"@nodelib/fs.stat": "^2.0.2",
-				"@nodelib/fs.walk": "^1.2.3",
-				"glob-parent": "^5.1.2",
-				"merge2": "^1.3.0",
-				"micromatch": "^4.0.4"
-			},
-			"engines": {
-				"node": ">=8.6.0"
-			}
-		},
-		"node_modules/fast-glob/node_modules/glob-parent": {
-			"version": "5.1.2",
-			"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
-			"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
-			"dev": true,
-			"license": "ISC",
-			"dependencies": {
-				"is-glob": "^4.0.1"
-			},
-			"engines": {
-				"node": ">= 6"
-			}
-		},
 		"node_modules/fast-json-stable-stringify": {
 			"version": "2.1.0",
 			"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
@@ -1909,16 +1616,6 @@
 			"dev": true,
 			"license": "MIT"
 		},
-		"node_modules/fastq": {
-			"version": "1.17.1",
-			"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz",
-			"integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==",
-			"dev": true,
-			"license": "ISC",
-			"dependencies": {
-				"reusify": "^1.0.4"
-			}
-		},
 		"node_modules/file-entry-cache": {
 			"version": "8.0.0",
 			"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
@@ -1932,19 +1629,6 @@
 				"node": ">=16.0.0"
 			}
 		},
-		"node_modules/fill-range": {
-			"version": "7.1.1",
-			"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
-			"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
-			"dev": true,
-			"license": "MIT",
-			"dependencies": {
-				"to-regex-range": "^5.0.1"
-			},
-			"engines": {
-				"node": ">=8"
-			}
-		},
 		"node_modules/find-up": {
 			"version": "5.0.0",
 			"resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
@@ -2063,16 +1747,6 @@
 				"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
 			}
 		},
-		"node_modules/function-bind": {
-			"version": "1.1.2",
-			"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
-			"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
-			"dev": true,
-			"license": "MIT",
-			"funding": {
-				"url": "https://github.com/sponsors/ljharb"
-			}
-		},
 		"node_modules/glob": {
 			"version": "10.4.5",
 			"resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
@@ -2170,19 +1844,6 @@
 				"node": ">=8"
 			}
 		},
-		"node_modules/hasown": {
-			"version": "2.0.2",
-			"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
-			"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
-			"dev": true,
-			"license": "MIT",
-			"dependencies": {
-				"function-bind": "^1.1.2"
-			},
-			"engines": {
-				"node": ">= 0.4"
-			}
-		},
 		"node_modules/html-encoding-sniffer": {
 			"version": "4.0.0",
 			"resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz",
@@ -2292,35 +1953,6 @@
 				"node": ">=0.8.19"
 			}
 		},
-		"node_modules/is-binary-path": {
-			"version": "2.1.0",
-			"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
-			"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
-			"dev": true,
-			"license": "MIT",
-			"dependencies": {
-				"binary-extensions": "^2.0.0"
-			},
-			"engines": {
-				"node": ">=8"
-			}
-		},
-		"node_modules/is-core-module": {
-			"version": "2.15.1",
-			"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz",
-			"integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==",
-			"dev": true,
-			"license": "MIT",
-			"dependencies": {
-				"hasown": "^2.0.2"
-			},
-			"engines": {
-				"node": ">= 0.4"
-			},
-			"funding": {
-				"url": "https://github.com/sponsors/ljharb"
-			}
-		},
 		"node_modules/is-extglob": {
 			"version": "2.1.1",
 			"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
@@ -2354,16 +1986,6 @@
 				"node": ">=0.10.0"
 			}
 		},
-		"node_modules/is-number": {
-			"version": "7.0.0",
-			"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
-			"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
-			"dev": true,
-			"license": "MIT",
-			"engines": {
-				"node": ">=0.12.0"
-			}
-		},
 		"node_modules/is-potential-custom-element-name": {
 			"version": "1.0.1",
 			"resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz",
@@ -2464,6 +2086,8 @@
 			"integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==",
 			"dev": true,
 			"license": "MIT",
+			"optional": true,
+			"peer": true,
 			"bin": {
 				"jiti": "bin/jiti.js"
 			}
@@ -2594,13 +2218,6 @@
 				"node": ">=10"
 			}
 		},
-		"node_modules/lines-and-columns": {
-			"version": "1.2.4",
-			"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
-			"integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
-			"dev": true,
-			"license": "MIT"
-		},
 		"node_modules/locate-character": {
 			"version": "3.0.0",
 			"resolved": "https://registry.npmjs.org/locate-character/-/locate-character-3.0.0.tgz",
@@ -2704,30 +2321,6 @@
 				"node": ">= 18"
 			}
 		},
-		"node_modules/merge2": {
-			"version": "1.4.1",
-			"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
-			"integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
-			"dev": true,
-			"license": "MIT",
-			"engines": {
-				"node": ">= 8"
-			}
-		},
-		"node_modules/micromatch": {
-			"version": "4.0.8",
-			"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
-			"integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
-			"dev": true,
-			"license": "MIT",
-			"dependencies": {
-				"braces": "^3.0.3",
-				"picomatch": "^2.3.1"
-			},
-			"engines": {
-				"node": ">=8.6"
-			}
-		},
 		"node_modules/mime-db": {
 			"version": "1.52.0",
 			"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
@@ -2749,16 +2342,6 @@
 				"node": ">= 0.6"
 			}
 		},
-		"node_modules/mini-svg-data-uri": {
-			"version": "1.4.4",
-			"resolved": "https://registry.npmjs.org/mini-svg-data-uri/-/mini-svg-data-uri-1.4.4.tgz",
-			"integrity": "sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==",
-			"dev": true,
-			"license": "MIT",
-			"bin": {
-				"mini-svg-data-uri": "cli.js"
-			}
-		},
 		"node_modules/minimatch": {
 			"version": "3.1.2",
 			"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
@@ -2809,22 +2392,10 @@
 			"dev": true,
 			"license": "MIT"
 		},
-		"node_modules/mz": {
-			"version": "2.7.0",
-			"resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
-			"integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==",
-			"dev": true,
-			"license": "MIT",
-			"dependencies": {
-				"any-promise": "^1.0.0",
-				"object-assign": "^4.0.1",
-				"thenify-all": "^1.0.0"
-			}
-		},
 		"node_modules/nanoid": {
-			"version": "3.3.7",
-			"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
-			"integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
+			"version": "3.3.8",
+			"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz",
+			"integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==",
 			"dev": true,
 			"funding": [
 				{
@@ -2854,16 +2425,6 @@
 			"dev": true,
 			"license": "MIT"
 		},
-		"node_modules/normalize-path": {
-			"version": "3.0.0",
-			"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
-			"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
-			"dev": true,
-			"license": "MIT",
-			"engines": {
-				"node": ">=0.10.0"
-			}
-		},
 		"node_modules/normalize-range": {
 			"version": "0.1.2",
 			"resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz",
@@ -2881,26 +2442,6 @@
 			"dev": true,
 			"license": "MIT"
 		},
-		"node_modules/object-assign": {
-			"version": "4.1.1",
-			"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
-			"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
-			"dev": true,
-			"license": "MIT",
-			"engines": {
-				"node": ">=0.10.0"
-			}
-		},
-		"node_modules/object-hash": {
-			"version": "3.0.0",
-			"resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz",
-			"integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==",
-			"dev": true,
-			"license": "MIT",
-			"engines": {
-				"node": ">= 6"
-			}
-		},
 		"node_modules/optionator": {
 			"version": "0.9.4",
 			"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
@@ -3004,13 +2545,6 @@
 				"node": ">=8"
 			}
 		},
-		"node_modules/path-parse": {
-			"version": "1.0.7",
-			"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
-			"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
-			"dev": true,
-			"license": "MIT"
-		},
 		"node_modules/path-scurry": {
 			"version": "1.11.1",
 			"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
@@ -3052,39 +2586,6 @@
 			"dev": true,
 			"license": "ISC"
 		},
-		"node_modules/picomatch": {
-			"version": "2.3.1",
-			"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
-			"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
-			"dev": true,
-			"license": "MIT",
-			"engines": {
-				"node": ">=8.6"
-			},
-			"funding": {
-				"url": "https://github.com/sponsors/jonschlinkert"
-			}
-		},
-		"node_modules/pify": {
-			"version": "2.3.0",
-			"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
-			"integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==",
-			"dev": true,
-			"license": "MIT",
-			"engines": {
-				"node": ">=0.10.0"
-			}
-		},
-		"node_modules/pirates": {
-			"version": "4.0.6",
-			"resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz",
-			"integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==",
-			"dev": true,
-			"license": "MIT",
-			"engines": {
-				"node": ">= 6"
-			}
-		},
 		"node_modules/postcss": {
 			"version": "8.4.47",
 			"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz",
@@ -3114,44 +2615,6 @@
 				"node": "^10 || ^12 || >=14"
 			}
 		},
-		"node_modules/postcss-import": {
-			"version": "15.1.0",
-			"resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz",
-			"integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==",
-			"dev": true,
-			"license": "MIT",
-			"dependencies": {
-				"postcss-value-parser": "^4.0.0",
-				"read-cache": "^1.0.0",
-				"resolve": "^1.1.7"
-			},
-			"engines": {
-				"node": ">=14.0.0"
-			},
-			"peerDependencies": {
-				"postcss": "^8.0.0"
-			}
-		},
-		"node_modules/postcss-js": {
-			"version": "4.0.1",
-			"resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz",
-			"integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==",
-			"dev": true,
-			"license": "MIT",
-			"dependencies": {
-				"camelcase-css": "^2.0.1"
-			},
-			"engines": {
-				"node": "^12 || ^14 || >= 16"
-			},
-			"funding": {
-				"type": "opencollective",
-				"url": "https://opencollective.com/postcss/"
-			},
-			"peerDependencies": {
-				"postcss": "^8.4.21"
-			}
-		},
 		"node_modules/postcss-load-config": {
 			"version": "3.1.4",
 			"resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.4.tgz",
@@ -3182,32 +2645,6 @@
 				}
 			}
 		},
-		"node_modules/postcss-nested": {
-			"version": "6.2.0",
-			"resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz",
-			"integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==",
-			"dev": true,
-			"funding": [
-				{
-					"type": "opencollective",
-					"url": "https://opencollective.com/postcss/"
-				},
-				{
-					"type": "github",
-					"url": "https://github.com/sponsors/ai"
-				}
-			],
-			"license": "MIT",
-			"dependencies": {
-				"postcss-selector-parser": "^6.1.1"
-			},
-			"engines": {
-				"node": ">=12.0"
-			},
-			"peerDependencies": {
-				"postcss": "^8.2.14"
-			}
-		},
 		"node_modules/postcss-safe-parser": {
 			"version": "6.0.0",
 			"resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-6.0.0.tgz",
@@ -3326,68 +2763,6 @@
 				"node": ">=6"
 			}
 		},
-		"node_modules/queue-microtask": {
-			"version": "1.2.3",
-			"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
-			"integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
-			"dev": true,
-			"funding": [
-				{
-					"type": "github",
-					"url": "https://github.com/sponsors/feross"
-				},
-				{
-					"type": "patreon",
-					"url": "https://www.patreon.com/feross"
-				},
-				{
-					"type": "consulting",
-					"url": "https://feross.org/support"
-				}
-			],
-			"license": "MIT"
-		},
-		"node_modules/read-cache": {
-			"version": "1.0.0",
-			"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
-			"integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==",
-			"dev": true,
-			"license": "MIT",
-			"dependencies": {
-				"pify": "^2.3.0"
-			}
-		},
-		"node_modules/readdirp": {
-			"version": "3.6.0",
-			"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
-			"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
-			"dev": true,
-			"license": "MIT",
-			"dependencies": {
-				"picomatch": "^2.2.1"
-			},
-			"engines": {
-				"node": ">=8.10.0"
-			}
-		},
-		"node_modules/resolve": {
-			"version": "1.22.8",
-			"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
-			"integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==",
-			"dev": true,
-			"license": "MIT",
-			"dependencies": {
-				"is-core-module": "^2.13.0",
-				"path-parse": "^1.0.7",
-				"supports-preserve-symlinks-flag": "^1.0.0"
-			},
-			"bin": {
-				"resolve": "bin/resolve"
-			},
-			"funding": {
-				"url": "https://github.com/sponsors/ljharb"
-			}
-		},
 		"node_modules/resolve-from": {
 			"version": "4.0.0",
 			"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
@@ -3398,17 +2773,6 @@
 				"node": ">=4"
 			}
 		},
-		"node_modules/reusify": {
-			"version": "1.0.4",
-			"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
-			"integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
-			"dev": true,
-			"license": "MIT",
-			"engines": {
-				"iojs": ">=1.0.0",
-				"node": ">=0.10.0"
-			}
-		},
 		"node_modules/rollup": {
 			"version": "4.24.0",
 			"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.24.0.tgz",
@@ -3452,30 +2816,6 @@
 			"dev": true,
 			"license": "MIT"
 		},
-		"node_modules/run-parallel": {
-			"version": "1.2.0",
-			"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
-			"integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
-			"dev": true,
-			"funding": [
-				{
-					"type": "github",
-					"url": "https://github.com/sponsors/feross"
-				},
-				{
-					"type": "patreon",
-					"url": "https://www.patreon.com/feross"
-				},
-				{
-					"type": "consulting",
-					"url": "https://feross.org/support"
-				}
-			],
-			"license": "MIT",
-			"dependencies": {
-				"queue-microtask": "^1.2.2"
-			}
-		},
 		"node_modules/sade": {
 			"version": "1.8.1",
 			"resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz",
@@ -3523,9 +2863,9 @@
 			}
 		},
 		"node_modules/set-cookie-parser": {
-			"version": "2.7.0",
-			"resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.0.tgz",
-			"integrity": "sha512-lXLOiqpkUumhRdFF3k1osNXCy9akgx/dyPZ5p8qAg9seJzXr5ZrlqZuWIMuY6ejOsVLE6flJ5/h3lsn57fQ/PQ==",
+			"version": "2.7.1",
+			"resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz",
+			"integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==",
 			"dev": true,
 			"license": "MIT"
 		},
@@ -3597,6 +2937,31 @@
 				"node": ">=0.10.0"
 			}
 		},
+		"node_modules/source-map-support": {
+			"version": "0.5.21",
+			"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
+			"integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
+			"dev": true,
+			"license": "MIT",
+			"optional": true,
+			"peer": true,
+			"dependencies": {
+				"buffer-from": "^1.0.0",
+				"source-map": "^0.6.0"
+			}
+		},
+		"node_modules/source-map-support/node_modules/source-map": {
+			"version": "0.6.1",
+			"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+			"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+			"dev": true,
+			"license": "BSD-3-Clause",
+			"optional": true,
+			"peer": true,
+			"engines": {
+				"node": ">=0.10.0"
+			}
+		},
 		"node_modules/stackback": {
 			"version": "0.0.2",
 			"resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz",
@@ -3728,29 +3093,6 @@
 				"url": "https://github.com/sponsors/sindresorhus"
 			}
 		},
-		"node_modules/sucrase": {
-			"version": "3.35.0",
-			"resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz",
-			"integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==",
-			"dev": true,
-			"license": "MIT",
-			"dependencies": {
-				"@jridgewell/gen-mapping": "^0.3.2",
-				"commander": "^4.0.0",
-				"glob": "^10.3.10",
-				"lines-and-columns": "^1.1.6",
-				"mz": "^2.7.0",
-				"pirates": "^4.0.1",
-				"ts-interface-checker": "^0.1.9"
-			},
-			"bin": {
-				"sucrase": "bin/sucrase",
-				"sucrase-node": "bin/sucrase-node"
-			},
-			"engines": {
-				"node": ">=16 || 14 >=14.17"
-			}
-		},
 		"node_modules/supports-color": {
 			"version": "7.2.0",
 			"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
@@ -3764,19 +3106,6 @@
 				"node": ">=8"
 			}
 		},
-		"node_modules/supports-preserve-symlinks-flag": {
-			"version": "1.0.0",
-			"resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
-			"integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
-			"dev": true,
-			"license": "MIT",
-			"engines": {
-				"node": ">= 0.4"
-			},
-			"funding": {
-				"url": "https://github.com/sponsors/ljharb"
-			}
-		},
 		"node_modules/svelte": {
 			"version": "5.1.9",
 			"resolved": "https://registry.npmjs.org/svelte/-/svelte-5.1.9.tgz",
@@ -3802,6 +3131,16 @@
 				"node": ">=18"
 			}
 		},
+		"node_modules/svelte-copy": {
+			"version": "2.0.0",
+			"resolved": "https://registry.npmjs.org/svelte-copy/-/svelte-copy-2.0.0.tgz",
+			"integrity": "sha512-wJ784qrc9CF7EtrlT2kwJfHnqae/pp4fkgzYeUxex4iFBm6HosT2904t5cZZ1GAZzg/z9V+lCZVP5rpiYsN6Tw==",
+			"dev": true,
+			"license": "MIT",
+			"peerDependencies": {
+				"svelte": "^5.0.0"
+			}
+		},
 		"node_modules/svelte-eslint-parser": {
 			"version": "0.43.0",
 			"resolved": "https://registry.npmjs.org/svelte-eslint-parser/-/svelte-eslint-parser-0.43.0.tgz",
@@ -3885,104 +3224,25 @@
 			"dev": true,
 			"license": "MIT"
 		},
-		"node_modules/tailwindcss": {
-			"version": "3.4.14",
-			"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.14.tgz",
-			"integrity": "sha512-IcSvOcTRcUtQQ7ILQL5quRDg7Xs93PdJEk1ZLbhhvJc7uj/OAhYOnruEiwnGgBvUtaUAJ8/mhSw1o8L2jCiENA==",
+		"node_modules/terser": {
+			"version": "5.37.0",
+			"resolved": "https://registry.npmjs.org/terser/-/terser-5.37.0.tgz",
+			"integrity": "sha512-B8wRRkmre4ERucLM/uXx4MOV5cbnOlVAqUst+1+iLKPI0dOgFO28f84ptoQt9HEI537PMzfYa/d+GEPKTRXmYA==",
 			"dev": true,
-			"license": "MIT",
-			"dependencies": {
-				"@alloc/quick-lru": "^5.2.0",
-				"arg": "^5.0.2",
-				"chokidar": "^3.5.3",
-				"didyoumean": "^1.2.2",
-				"dlv": "^1.1.3",
-				"fast-glob": "^3.3.0",
-				"glob-parent": "^6.0.2",
-				"is-glob": "^4.0.3",
-				"jiti": "^1.21.0",
-				"lilconfig": "^2.1.0",
-				"micromatch": "^4.0.5",
-				"normalize-path": "^3.0.0",
-				"object-hash": "^3.0.0",
-				"picocolors": "^1.0.0",
-				"postcss": "^8.4.23",
-				"postcss-import": "^15.1.0",
-				"postcss-js": "^4.0.1",
-				"postcss-load-config": "^4.0.1",
-				"postcss-nested": "^6.0.1",
-				"postcss-selector-parser": "^6.0.11",
-				"resolve": "^1.22.2",
-				"sucrase": "^3.32.0"
-			},
-			"bin": {
-				"tailwind": "lib/cli.js",
-				"tailwindcss": "lib/cli.js"
-			},
-			"engines": {
-				"node": ">=14.0.0"
-			}
-		},
-		"node_modules/tailwindcss/node_modules/postcss-load-config": {
-			"version": "4.0.2",
-			"resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz",
-			"integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==",
-			"dev": true,
-			"funding": [
-				{
-					"type": "opencollective",
-					"url": "https://opencollective.com/postcss/"
-				},
-				{
-					"type": "github",
-					"url": "https://github.com/sponsors/ai"
-				}
-			],
-			"license": "MIT",
+			"license": "BSD-2-Clause",
+			"optional": true,
+			"peer": true,
 			"dependencies": {
-				"lilconfig": "^3.0.0",
-				"yaml": "^2.3.4"
-			},
-			"engines": {
-				"node": ">= 14"
-			},
-			"peerDependencies": {
-				"postcss": ">=8.0.9",
-				"ts-node": ">=9.0.0"
-			},
-			"peerDependenciesMeta": {
-				"postcss": {
-					"optional": true
-				},
-				"ts-node": {
-					"optional": true
-				}
-			}
-		},
-		"node_modules/tailwindcss/node_modules/postcss-load-config/node_modules/lilconfig": {
-			"version": "3.1.2",
-			"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz",
-			"integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==",
-			"dev": true,
-			"license": "MIT",
-			"engines": {
-				"node": ">=14"
+				"@jridgewell/source-map": "^0.3.3",
+				"acorn": "^8.8.2",
+				"commander": "^2.20.0",
+				"source-map-support": "~0.5.20"
 			},
-			"funding": {
-				"url": "https://github.com/sponsors/antonk52"
-			}
-		},
-		"node_modules/tailwindcss/node_modules/yaml": {
-			"version": "2.6.0",
-			"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.0.tgz",
-			"integrity": "sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==",
-			"dev": true,
-			"license": "ISC",
 			"bin": {
-				"yaml": "bin.mjs"
+				"terser": "bin/terser"
 			},
 			"engines": {
-				"node": ">= 14"
+				"node": ">=10"
 			}
 		},
 		"node_modules/test-exclude": {
@@ -4033,29 +3293,6 @@
 			"dev": true,
 			"license": "MIT"
 		},
-		"node_modules/thenify": {
-			"version": "3.3.1",
-			"resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",
-			"integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==",
-			"dev": true,
-			"license": "MIT",
-			"dependencies": {
-				"any-promise": "^1.0.0"
-			}
-		},
-		"node_modules/thenify-all": {
-			"version": "1.6.0",
-			"resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz",
-			"integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==",
-			"dev": true,
-			"license": "MIT",
-			"dependencies": {
-				"thenify": ">= 3.1.0 < 4"
-			},
-			"engines": {
-				"node": ">=0.8"
-			}
-		},
 		"node_modules/tiny-glob": {
 			"version": "0.2.9",
 			"resolved": "https://registry.npmjs.org/tiny-glob/-/tiny-glob-0.2.9.tgz",
@@ -4137,19 +3374,6 @@
 			"dev": true,
 			"license": "MIT"
 		},
-		"node_modules/to-regex-range": {
-			"version": "5.0.1",
-			"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
-			"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
-			"dev": true,
-			"license": "MIT",
-			"dependencies": {
-				"is-number": "^7.0.0"
-			},
-			"engines": {
-				"node": ">=8.0"
-			}
-		},
 		"node_modules/totalist": {
 			"version": "3.0.1",
 			"resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz",
@@ -4186,13 +3410,6 @@
 				"node": ">=18"
 			}
 		},
-		"node_modules/ts-interface-checker": {
-			"version": "0.1.13",
-			"resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
-			"integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==",
-			"dev": true,
-			"license": "Apache-2.0"
-		},
 		"node_modules/type-check": {
 			"version": "0.4.0",
 			"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
@@ -4206,6 +3423,15 @@
 				"node": ">= 0.8.0"
 			}
 		},
+		"node_modules/undici-types": {
+			"version": "6.20.0",
+			"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz",
+			"integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==",
+			"dev": true,
+			"license": "MIT",
+			"optional": true,
+			"peer": true
+		},
 		"node_modules/update-browserslist-db": {
 			"version": "1.1.1",
 			"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz",
diff --git a/package.json b/package.json
index 961b44b..392affe 100644
--- a/package.json
+++ b/package.json
@@ -16,12 +16,9 @@
 		"coverage": "vitest run --coverage"
 	},
 	"devDependencies": {
-		"@skeletonlabs/skeleton": "^2.10.3",
-		"@skeletonlabs/tw-plugin": "^0.4.0",
 		"@sveltejs/adapter-static": "^3.0.6",
 		"@sveltejs/kit": "^2.7.4",
 		"@sveltejs/vite-plugin-svelte": "^4.0.0",
-		"@tailwindcss/forms": "^0.5.9",
 		"@types/eslint": "^9.6.1",
 		"@vitest/coverage-v8": "^2.1.4",
 		"autoprefixer": "^10.4.20",
@@ -34,7 +31,7 @@
 		"prettier": "^3.3.3",
 		"prettier-plugin-svelte": "^3.2.7",
 		"svelte": "^5.1.9",
-		"tailwindcss": "^3.4.14",
+		"svelte-copy": "^2.0.0",
 		"vite": "^5.4.10",
 		"vitest": "^2.1.4"
 	},
diff --git a/postcss.config.js b/postcss.config.js
index 2e7af2b..b6dc034 100644
--- a/postcss.config.js
+++ b/postcss.config.js
@@ -1,6 +1,5 @@
 export default {
   plugins: {
-    tailwindcss: {},
     autoprefixer: {},
   },
 }
diff --git a/tailwind.config.js b/tailwind.config.js
deleted file mode 100644
index d6511b8..0000000
--- a/tailwind.config.js
+++ /dev/null
@@ -1,25 +0,0 @@
-// @ts-check
-import { join } from 'path';
-import { skeleton } from '@skeletonlabs/tw-plugin';
-import forms from '@tailwindcss/forms';
-
-/** @type {import('tailwindcss').Config} */
-export default {
-	darkMode: 'class',
-	content: [
-		'ui/**/*.{html,js,svelte,ts}',
-		join(
-			require.resolve('@skeletonlabs/skeleton'),
-			'../**/*.{html,js,svelte,ts}'
-		)
-	],
-	theme: {
-		extend: {},
-	},
-	plugins: [
-    forms,
-    skeleton({
-      themes: { preset: [ "skeleton" ] }
-    })
-  ]
-}
diff --git a/ui/app.html b/ui/app.html
index 5e7d92b..942e328 100644
--- a/ui/app.html
+++ b/ui/app.html
@@ -7,7 +7,7 @@
     <link rel="manifest" href="%sveltekit.assets%/manifest.json" />
     %sveltekit.head%
   </head>
-  <body data-sveltekit-preload-data="hover" data-theme="skeleton">
+  <body data-sveltekit-preload-data="hover">
     <div class="m-0 p-0 h-vh w-full">%sveltekit.body%</div>
   </body>
 </html>
diff --git a/ui/lib/components/ChangePassword.svelte b/ui/lib/components/ChangePassword.svelte
index 1e48bee..109a83a 100644
--- a/ui/lib/components/ChangePassword.svelte
+++ b/ui/lib/components/ChangePassword.svelte
@@ -26,7 +26,6 @@
   <label
     >current password
     <input
-      class="input"
       name="currentPassword"
       type="password"
       placeholder="password"
@@ -37,7 +36,6 @@
   <label
     >new password
     <input
-      class="input"
       name="newPassword"
       type="password"
       placeholder="password"
@@ -48,7 +46,6 @@
   <label
     >confirm new password
     <input
-      class="input"
       name="confirmPassword"
       type="password"
       placeholder="password"
@@ -56,5 +53,5 @@
     />
   </label>
 
-  <button class="btn bg-orange-500 mt-4" type="submit" {disabled}>change password</button>
+  <button type="submit" {disabled}>change password</button>
 </form>
diff --git a/ui/lib/components/Channel.svelte b/ui/lib/components/Channel.svelte
index 01b1c87..dc019a0 100644
--- a/ui/lib/components/Channel.svelte
+++ b/ui/lib/components/Channel.svelte
@@ -2,13 +2,13 @@
   let { id, name, active, hasUnreads } = $props();
 </script>
 
-<li class="rounded-full" class:bg-slate-400={active}>
-  <a href="/ch/{id}">
+<a href="/ch/{id}">
+  <li class:active={active}>
     {#if hasUnreads}
-      <span class="badge bg-warning-500">❦</span>
+      <span>❦</span>
     {:else}
-      <span class="badge bg-primary-500">¶</span>
+      <span>¶</span>
     {/if}
-    <span class="flex-auto">{name}</span>
-  </a>
-</li>
+    <span>{name}</span>
+  </li>
+</a>
diff --git a/ui/lib/components/CreateChannelForm.svelte b/ui/lib/components/CreateChannelForm.svelte
index d50e60d..8fab4c4 100644
--- a/ui/lib/components/CreateChannelForm.svelte
+++ b/ui/lib/components/CreateChannelForm.svelte
@@ -15,16 +15,12 @@
   }
 </script>
 
-<form onsubmit={handleSubmit} class="form form-row flex-nowrap">
+<form onsubmit={handleSubmit}>
   <input
     type="text"
     placeholder="create channel"
     bind:value={name}
     {disabled}
-    class="input flex-auto h-6 w-9/12"
   />
-  <button type="submit" class="flex-none w-6 h-6">&#x2795;</button>
+  <button type="submit">&#x2795;</button>
 </form>
-
-<style>
-</style>
diff --git a/ui/lib/components/Invite.svelte b/ui/lib/components/Invite.svelte
index 937c911..ce45930 100644
--- a/ui/lib/components/Invite.svelte
+++ b/ui/lib/components/Invite.svelte
@@ -1,9 +1,9 @@
 <script>
-  import { clipboard } from '@skeletonlabs/skeleton';
+  import { copy } from 'svelte-copy';
 
   let { id } = $props();
   let inviteUrl = $derived(new URL(`/invite/${id}`, document.location));
 </script>
 
-<button class="btn bg-secondary-500" use:clipboard={inviteUrl}>copy</button>
-<span data-clipboard="inviteUrl">{inviteUrl}</span>
+<button use:copy={inviteUrl}>copy</button>
+<span>{inviteUrl}</span>
diff --git a/ui/lib/components/Invites.svelte b/ui/lib/components/Invites.svelte
index 493bf1c..5c5d601 100644
--- a/ui/lib/components/Invites.svelte
+++ b/ui/lib/components/Invites.svelte
@@ -14,11 +14,11 @@
 </script>
 
 <form {onsubmit}>
-  <button class="btn bg-primary-500" type="submit">create invitation</button>
+  <button type="submit">create invitation</button>
 </form>
 
-<ul class="mt-4">
+<ul>
   {#each invites as invite}
-    <li class="my-1"><Invite id={invite.id} /></li>
+    <li><Invite id={invite.id} /></li>
   {/each}
 </ul>
diff --git a/ui/lib/components/LogIn.svelte b/ui/lib/components/LogIn.svelte
index 7fb91e8..7e0f7cd 100644
--- a/ui/lib/components/LogIn.svelte
+++ b/ui/lib/components/LogIn.svelte
@@ -8,12 +8,11 @@
   } = $props();
 </script>
 
-<div class="card m-4 p-4">
+<div>
   <form {onsubmit}>
-    <label class="label" for="username">
+    <label for="username">
       username
       <input
-        class="input"
         name="username"
         type="text"
         placeholder="username"
@@ -21,10 +20,9 @@
         {disabled}
       />
     </label>
-    <label class="label" for="password">
+    <label for="password">
       password
       <input
-        class="input"
         name="password"
         type="password"
         placeholder="password"
@@ -32,7 +30,7 @@
         {disabled}
       />
     </label>
-    <button class="btn variant-filled" type="submit">
+    <button type="submit">
       {legend}
     </button>
   </form>
diff --git a/ui/lib/components/LogOut.svelte b/ui/lib/components/LogOut.svelte
index 52aa039..8b182e7 100644
--- a/ui/lib/components/LogOut.svelte
+++ b/ui/lib/components/LogOut.svelte
@@ -14,5 +14,5 @@
 </script>
 
 <form {onsubmit}>
-  <button class="btn bg-orange-400" type="submit">log out</button>
+  <button type="submit">log out</button>
 </form>
diff --git a/ui/lib/components/Message.svelte b/ui/lib/components/Message.svelte
index aa9e3e9..cfadbba 100644
--- a/ui/lib/components/Message.svelte
+++ b/ui/lib/components/Message.svelte
@@ -32,13 +32,13 @@
     data-at={at}
     {onmouseleave}
     >
-  <div class="handle chip bg-surface-700 absolute -top-6 right-0">
+  <div class="handle">
     {atFormatted}
     {#if editable}
       <button onclick={onDelete}>&#x1F5D1;&#xFE0F;</button>
     {/if}
   </div>
-  <section use:scroll class="py-1 message-body">
+  <section use:scroll class="message-body">
     <!-- eslint-disable-next-line svelte/no-at-html-tags -->
     {@html renderedBody}
   </section>
diff --git a/ui/lib/components/MessageInput.svelte b/ui/lib/components/MessageInput.svelte
index 22456f3..25a0352 100644
--- a/ui/lib/components/MessageInput.svelte
+++ b/ui/lib/components/MessageInput.svelte
@@ -23,17 +23,14 @@
   }
 </script>
 
-<form bind:this={form} onsubmit={onSubmit} class="flex flex-row flex-nowrap">
+<form bind:this={form} onsubmit={onSubmit}>
   <textarea
     onkeydown={onKeyDown}
     bind:value
     {disabled}
     type="search"
-    class="flex-auto h-6 py-0 input rounded-r-none text-nowrap"
   ></textarea>
   <button
-    color="primary variant-filled-secondary"
     type="submit"
-    class="flex-none w-6 h-6 btn-icon variant-filled rounded-l-none">&raquo;</button
-  >
+  >&raquo;</button>
 </form>
diff --git a/ui/lib/components/MessageRun.svelte b/ui/lib/components/MessageRun.svelte
index 581682e..6cad381 100644
--- a/ui/lib/components/MessageRun.svelte
+++ b/ui/lib/components/MessageRun.svelte
@@ -9,11 +9,10 @@
 </script>
 
 <div
-  class="card my-4 px-4 py-1 relative"
   class:own-message={ownMessage}
   class:other-message={!ownMessage}
 >
-  <span class="chip variant-soft sticky top-o left-0">
+  <span>
     @{name}:
   </span>
   {#each messages as message}
diff --git a/ui/routes/(app)/+layout.svelte b/ui/routes/(app)/+layout.svelte
index a82d302..8a70c4b 100644
--- a/ui/routes/(app)/+layout.svelte
+++ b/ui/routes/(app)/+layout.svelte
@@ -142,15 +142,6 @@
 {/if}
 
 <style>
-  /* Just some global CSS variables, don't mind them.
-   */
-  :root {
-    --app-bar-height: 48px;
-    --input-row-height: 2rem;
-    --interface-padding: 16px;
-    --nav-width: 21rem;
-  }
-
   #interface {
     margin: unset;
     display: grid;
diff --git a/ui/routes/+layout.svelte b/ui/routes/+layout.svelte
index 26033e0..750f1f8 100644
--- a/ui/routes/+layout.svelte
+++ b/ui/routes/+layout.svelte
@@ -4,7 +4,6 @@
   import '../app.css';
   import logo from '$lib/assets/logo.png';
 
-  import { AppBar } from '@skeletonlabs/skeleton';
   import { currentUser } from '$lib/store';
 
   let pageContext = $state({
@@ -24,20 +23,20 @@
   let { children } = $props();
 </script>
 
-<AppBar padding="px-4 pt-0 pb-4">
-  <svelte:fragment slot="lead">
-    <button onclick={toggleMenu} class="cursor-pointer">
-      <img class="w-8 h-8" alt="logo" src={logo} />
+<div class="app-bar">
+  <div class="lead">
+    <button onclick={toggleMenu}>
+      <img alt="logo" src={logo} />
     </button>
-  </svelte:fragment>
+  </div>
   <a href="/">pilcrow</a>
-  <svelte:fragment slot="trail">
+  <div class="trail">
     {#if $currentUser}
-      <div class="rounded-full bg-secondary-400 px-3 py-1">
+      <div>
         <a href="/me">@{$currentUser.username}</a>
       </div>
     {/if}
-  </svelte:fragment>
-</AppBar>
+  </div>
+</div>
 
 {@render children?.()}
-- 
cgit v1.2.3


From c9b3394e9fc2cf6eb505ab03a6479eae996ed6e9 Mon Sep 17 00:00:00 2001
From: Kit La Touche <kit@transneptune.net>
Date: Wed, 1 Jan 2025 18:09:46 -0500
Subject: Just oh so many styles

---
 ui/app.css                                |  6 +++
 ui/lib/components/Message.svelte          | 40 +--------------
 ui/lib/components/MessageRun.svelte       | 15 +-----
 ui/routes/(app)/+layout.svelte            | 54 ++------------------
 ui/routes/(app)/ch/[channel]/+page.svelte | 20 +-------
 ui/styles/active-channel.css              |  3 ++
 ui/styles/app-bar.css                     |  1 +
 ui/styles/app-layout.css                  | 56 +++++++++++++++++++++
 ui/styles/messages.css                    | 83 +++++++++++++++++++++++++++++++
 ui/styles/sidebar.css                     | 11 ++++
 ui/styles/textarea.css                    | 38 ++++++++++++++
 ui/styles/variables.css                   | 28 ++++++++---
 12 files changed, 228 insertions(+), 127 deletions(-)
 create mode 100644 ui/styles/active-channel.css
 create mode 100644 ui/styles/app-layout.css
 create mode 100644 ui/styles/messages.css
 create mode 100644 ui/styles/textarea.css

(limited to 'ui/lib/components/MessageRun.svelte')

diff --git a/ui/app.css b/ui/app.css
index c4b464b..a945c6a 100644
--- a/ui/app.css
+++ b/ui/app.css
@@ -2,11 +2,17 @@
 @import url("styles/variables.css");
 @import url("styles/overscroll.css");
 @import url("styles/app-bar.css");
+@import url("styles/app-layout.css");
 @import url("styles/sidebar.css");
+@import url("styles/active-channel.css");
+@import url("styles/messages.css");
+@import url("styles/textarea.css");
 
 /* Debugging */
+/* * /
 div {
   outline: 1px dashed grey;
   background-color: var(--colour-background);
   box-shadow: 5px 5px 5px var(--colour-border);
 }
+/* */
diff --git a/ui/lib/components/Message.svelte b/ui/lib/components/Message.svelte
index cfadbba..6918b5d 100644
--- a/ui/lib/components/Message.svelte
+++ b/ui/lib/components/Message.svelte
@@ -26,8 +26,8 @@
 </script>
 
 <div
-    class="message relative"
-    class:bg-warning-800={deleteArmed}
+    class="message"
+    class:delete-armed={deleteArmed}
     role="article"
     data-at={at}
     {onmouseleave}
@@ -43,39 +43,3 @@
     {@html renderedBody}
   </section>
 </div>
-
-<style>
-  .message .handle {
-    display: none;
-  }
-  .message:hover .handle {
-    display: flex;
-  }
-  .message-body {
-    overflow: auto;
-    max-width: 80vw;
-    @media (width > 640px) {
-      /* 21rem is width of the nav bar in full-screen mode. */
-      max-width: calc(90vw - 21rem);
-    }
-  }
-  .message-body:empty:after {
-    content: '.';
-    visibility: hidden;
-  }
-  /* Without the global selector, the Svelte CSS compiler will see this as
-   * unused, and purge it from the output. However, this is "plausibly used"
-   * because it may occur in renderedBody.
-   */
-  :global(.message-body blockquote) {
-    border-left: 0.25rem solid lightgrey;
-    margin-left: 0.5rem;
-    padding-left: 0.5rem;
-  }
-  :global(.message-body pre) {
-    border: 1px solid #312e81;
-    border-radius: 0.25rem;
-    background-color: #282555;;
-    padding: 0.25rem;
-  }
-</style>
diff --git a/ui/lib/components/MessageRun.svelte b/ui/lib/components/MessageRun.svelte
index 6cad381..09388ac 100644
--- a/ui/lib/components/MessageRun.svelte
+++ b/ui/lib/components/MessageRun.svelte
@@ -9,6 +9,7 @@
 </script>
 
 <div
+  class="message-run"
   class:own-message={ownMessage}
   class:other-message={!ownMessage}
 >
@@ -19,17 +20,3 @@
     <Message {...message} editable={ownMessage} />
   {/each}
 </div>
-
-<style>
-  .own-message {
-    background-color: rgb(32, 42, 74);
-  }
-  /* Honestly, I don't love scoping styles per component, and this is a great
-   * example of why. MessageRuns know if they're own-message, but Messages in
-   * them need to get a style based on that fact. I don't wanna bucket-brigade
-   * that fact into the Message, when it's a pure CSS concern.
-   */
-  .own-message :global(*) {
-    color: rgb(198, 198, 198);
-  }
-</style>
diff --git a/ui/routes/(app)/+layout.svelte b/ui/routes/(app)/+layout.svelte
index 8a70c4b..cacfc2d 100644
--- a/ui/routes/(app)/+layout.svelte
+++ b/ui/routes/(app)/+layout.svelte
@@ -126,63 +126,19 @@
 {#if loading}
   <h2>Loading&hellip;</h2>
 {:else}
-  <div id="interface" class="p-2">
+  <div id="interface">
     <nav id="sidebar" data-expanded={pageContext.showMenu}>
-      <div class="channel-list">
         <ChannelList active={channel} channels={enrichedChannels} />
+        <!--
+      <div class="channel-list">
       </div>
+        -->
       <div class="create-channel">
         <CreateChannelForm />
       </div>
     </nav>
-    <main class="pl-4">
+    <main>
       {@render children?.()}
     </main>
   </div>
 {/if}
-
-<style>
-  #interface {
-    margin: unset;
-    display: grid;
-    grid-template:
-      'side main' 1fr
-      / auto 1fr;
-    height: calc(100vh - var(--app-bar-height));
-
-    @media (width > 640px) {
-      --overlay: static;
-      --translate: 0;
-    }
-  }
-  nav {
-    grid-area: side;
-    background-color: rgb(var(--color-surface-800));
-    inset: auto auto 0 0;
-    padding: 0.25rem;
-    position: var(--overlay, absolute);
-    transition: translate 300ms ease-out;
-    width: var(--nav-width);
-    height: 100vh;
-    @media (width > 640px) {
-      height: calc(100vh - var(--app-bar-height) - var(--interface-padding));
-    }
-    z-index: 10;
-    border-top-right-radius: 1.4rem;
-    border-bottom-right-radius: 1.4rem;
-  }
-  main {
-    grid-area: main;
-    height: calc(100vh - var(--app-bar-height) - var(--interface-padding));
-  }
-  .channel-list {
-    height: calc(100vh - var(--input-row-height));
-    @media (width > 640px) {
-      height: calc(100vh - var(--app-bar-height) - var(--input-row-height) - var(--interface-padding));
-    }
-    overflow: auto;
-  }
-  nav[data-expanded='false'] {
-    translate: var(--translate, -100% 0);
-  }
-</style>
diff --git a/ui/routes/(app)/ch/[channel]/+page.svelte b/ui/routes/(app)/ch/[channel]/+page.svelte
index d4e04fe..8eba709 100644
--- a/ui/routes/(app)/ch/[channel]/+page.svelte
+++ b/ui/routes/(app)/ch/[channel]/+page.svelte
@@ -67,24 +67,6 @@
 <div class="active-channel" on:scroll={handleScroll} bind:this={activeChannel}>
   <ActiveChannel {messageRuns} />
 </div>
-<div class="create-message max-h-full">
+<div class="create-message">
   <MessageInput {channel} />
 </div>
-
-<style>
-  .active-channel {
-    height: calc(
-      100vh - var(--app-bar-height) - var(--interface-padding) - var(--input-row-height)
-    );
-    overflow: auto;
-  }
-  .create-message {
-    position: fixed;
-    bottom: 0.5rem;
-    width: calc(100% - var(--nav-width) - 2rem);
-    @media (width <= 640px) {
-      width: 100%;
-      left: 0;
-    }
-  }
-</style>
diff --git a/ui/styles/active-channel.css b/ui/styles/active-channel.css
new file mode 100644
index 0000000..6efc3e3
--- /dev/null
+++ b/ui/styles/active-channel.css
@@ -0,0 +1,3 @@
+.active-channel {
+  padding: 1rem;
+}
diff --git a/ui/styles/app-bar.css b/ui/styles/app-bar.css
index 401a278..caa50ed 100644
--- a/ui/styles/app-bar.css
+++ b/ui/styles/app-bar.css
@@ -5,6 +5,7 @@
   flex-direction: row;
   justify-content: space-between;
   align-items: stretch;
+  background-color: var(--colour-background);
 }
 
 .app-bar > * {
diff --git a/ui/styles/app-layout.css b/ui/styles/app-layout.css
new file mode 100644
index 0000000..ef1eb10
--- /dev/null
+++ b/ui/styles/app-layout.css
@@ -0,0 +1,56 @@
+/* TODO: generally remove literals from this file. */
+
+#interface {
+  margin: unset;
+  display: grid;
+  grid-template:
+    'side main' 1fr
+    / auto 1fr;
+  height: calc(100vh - var(--app-bar-height));
+
+  @media (width > 640px) {
+    --overlay: static;
+    --translate: 0;
+  }
+}
+
+nav#sidebar {
+  grid-area: side;
+  inset: auto auto 0 0;
+  padding-right: 0.5rem;
+  position: var(--overlay, absolute);
+  transition: translate 300ms ease-out;
+  width: var(--nav-width);
+  height: 100vh;
+  z-index: 10;
+
+  border-radius: 0 1.4rem 1.4rem 0;
+
+  background-color: var(--colour-background-alt);
+
+  @media (width > 640px) {
+    height: calc(100vh - var(--app-bar-height));
+  }
+}
+
+nav.list-nav {
+  height: calc(100vh - var(--input-row-height) - var(--interface-padding));
+  overflow: auto;
+
+  @media (width > 640px) {
+    height: calc(100vh - var(--app-bar-height) - var(--input-row-height) - var(--interface-padding));
+  }
+}
+
+main {
+  grid-area: main;
+  height: calc(100vh - var(--app-bar-height));
+}
+
+main textarea {
+  resize: none;
+}
+
+nav[data-expanded='false'] {
+  translate: var(--translate, -100% 0);
+}
diff --git a/ui/styles/messages.css b/ui/styles/messages.css
new file mode 100644
index 0000000..bd46baf
--- /dev/null
+++ b/ui/styles/messages.css
@@ -0,0 +1,83 @@
+.message-run {
+  position: relative;
+  border-radius: 0.25rem;
+  border: 1px solid var(--colour-border);
+  padding: 0 0 0.5rem 0;
+  margin-bottom: 1rem;
+  box-shadow: 0 0.25rem 0.25rem rgba(0, 0, 0, 0.5);
+}
+
+/* TODO: replace these with colour variables. */
+.own-message {
+  background-color: rgb(32, 42, 74);
+}
+
+.own-message * {
+  color: rgb(198, 198, 198);
+}
+
+.message-run > span {
+  /* Username */
+  color: var(--colour-text);
+  background-color: rgb(67, 88, 156);
+}
+
+.message {
+  padding: 0.5rem 0 0 0.5rem;
+}
+
+.message:hover {
+  background-color: rgb(21, 28, 49);
+}
+
+.message .handle {
+  --text-size: 0.5rem;
+  float: right;
+  line-height: var(--text-size);
+  font-size: var(--text-size);
+  top: -0.5rem;
+  position: relative;
+  padding: 0.25rem;
+  border-radius: 0.25rem;
+  display: none;
+  background-color: rgb(67, 88, 156);
+}
+
+.message:hover .handle {
+  display: flex;
+}
+
+.message .handle button {
+  line-height: 0.35rem;
+  background: none;
+  border: none;
+  cursor: pointer;
+}
+
+.message-body {
+  overflow: auto;
+  max-width: 80vw;
+
+  @media (width > 640px) {
+    /* 21rem is width of the nav bar in full-screen mode. */
+    max-width: calc(90vw - 21rem);
+  }
+}
+
+.message-body:empty:after {
+  content: '.';
+  visibility: hidden;
+}
+
+/* For rendered message bodies: */
+.message-body blockquote {
+  border-left: 0.25rem solid lightgrey;
+  margin-left: 0.5rem;
+  padding-left: 0.5rem;
+}
+.message-body pre {
+  border: 1px solid #312e81;
+  border-radius: 0.25rem;
+  background-color: #282555;;
+  padding: 0.25rem;
+}
diff --git a/ui/styles/sidebar.css b/ui/styles/sidebar.css
index e512847..e9098f2 100644
--- a/ui/styles/sidebar.css
+++ b/ui/styles/sidebar.css
@@ -3,6 +3,10 @@
   background-color: var(--colour-background-alt);
 }
 
+.list-nav ul {
+  padding: 0.5rem;
+}
+
 .list-nav li {
   padding: 0.5rem;
   border-radius: 0.5rem;
@@ -32,8 +36,15 @@
   border: 1px solid var(--colour-border);
   z-index: 1;  /* Just to make the focus-active border go over the following button. */
   flex-grow: 1;
+  background-color: var(--colour-text);
+  color: var(--colour-background);
 }
 
 .create-channel button {
   border-radius: 0 0.5rem 0.5rem 0;
+  border: 1px solid var(--colour-border);
+  background-color: var(--colour-text);
+  color: var(--colour-background);
 }
+
+/* TODO: media-query stuff. Margin-left at a constant zero? */
diff --git a/ui/styles/textarea.css b/ui/styles/textarea.css
new file mode 100644
index 0000000..72d727f
--- /dev/null
+++ b/ui/styles/textarea.css
@@ -0,0 +1,38 @@
+/* Message input */
+.create-message form {
+  display: flex;
+  flex-direction: row;
+  justify-content: flex-start;
+  align-items: stretch;
+}
+
+.create-message textarea {
+  padding: 0.5rem;
+  border-radius: 0.5rem 0 0 0.5rem;
+  border: 1px solid var(--colour-border);
+  z-index: 1;  /* Just to make the focus-active border go over the following button. */
+  flex-grow: 1;
+  background-color: var(--colour-text);
+  color: var(--colour-background);
+}
+
+.create-message button {
+  border-radius: 0 0.5rem 0.5rem 0;
+  border: 1px solid var(--colour-border);
+  background-color: var(--colour-text);
+  color: var(--colour-background);
+}
+
+.active-channel {
+  overflow: auto;
+  flex-grow: 1;
+  /* TODO: make this all-app background */
+  background-color: var(--colour-background);
+}
+
+main {
+  display: flex;
+  flex-direction: column;
+  justify-content: flex-start;
+  align-items: stretch;
+}
diff --git a/ui/styles/variables.css b/ui/styles/variables.css
index e948c71..5ea4d74 100644
--- a/ui/styles/variables.css
+++ b/ui/styles/variables.css
@@ -8,11 +8,25 @@
   --nav-width: 21rem;
 
   /* coloUrs */
-  --colour-background: rgba(0, 0, 0, 0.25);
-  --colour-background-alt: rgba(0, 0, 0, 0.35);
-  --colour-border: rgba(0, 0, 0, 0.45);
-  --colour-text: rgb(240, 240, 240);
-  --colour-okay: #2a9d8f;
-  --colour-warn: #e9c46a;
-  --colour-error: #e76f51;
+  /* Really, we need:
+   * - Dark header background
+   * - Medium sidebar background
+   * - Light channel background
+   * - okay/warn/error
+   * - Border colours?
+   * - Text colour
+   * - Hover colour
+   * - Active colour
+   */
+  --colour-background: #253031;
+  --colour-border: #192122;
+
+  --colour-background-alt: #426A5A;
+  --colour-border-alt: #2E4A3E;
+
+  --colour-text: #FFFFEA;
+
+  --colour-okay: #6A994E;
+  --colour-warn: #EBC3BE;
+  --colour-error: #DE5F55;
 }
-- 
cgit v1.2.3


From 61fd2701a93e1c75408f75ea95de7a48581327a2 Mon Sep 17 00:00:00 2001
From: Kit La Touche <kit@transneptune.net>
Date: Sat, 4 Jan 2025 12:15:33 -0500
Subject: Add username class to username span

---
 ui/lib/components/MessageRun.svelte | 2 +-
 ui/styles/messages.css              | 3 +--
 2 files changed, 2 insertions(+), 3 deletions(-)

(limited to 'ui/lib/components/MessageRun.svelte')

diff --git a/ui/lib/components/MessageRun.svelte b/ui/lib/components/MessageRun.svelte
index 09388ac..dec5f4f 100644
--- a/ui/lib/components/MessageRun.svelte
+++ b/ui/lib/components/MessageRun.svelte
@@ -13,7 +13,7 @@
   class:own-message={ownMessage}
   class:other-message={!ownMessage}
 >
-  <span>
+  <span class="username">
     @{name}:
   </span>
   {#each messages as message}
diff --git a/ui/styles/messages.css b/ui/styles/messages.css
index ebb01c9..af4252a 100644
--- a/ui/styles/messages.css
+++ b/ui/styles/messages.css
@@ -24,8 +24,7 @@
   color: var(--colour-message-run-text);
 }
 
-.message-run > span {
-  /* Username */
+.message-run > .username {
   color: var(--colour-message-run-text);
   background-color: rgb(67, 88, 156);
 }
-- 
cgit v1.2.3


From 6d51f8568e337e768505ccfdef916b84dd6eb1b3 Mon Sep 17 00:00:00 2001
From: Owen Jacobson <owen@grimoire.ca>
Date: Sat, 11 Jan 2025 13:34:13 -0500
Subject: npm run format

---
 ui/app.css                                 |  22 ++---
 ui/lib/components/ChangePassword.svelte    |   7 +-
 ui/lib/components/Channel.svelte           |   2 +-
 ui/lib/components/CreateChannelForm.svelte |   7 +-
 ui/lib/components/LogIn.svelte             |   8 +-
 ui/lib/components/Message.svelte           |   8 +-
 ui/lib/components/MessageInput.svelte      |  11 +--
 ui/lib/components/MessageRun.svelte        |   6 +-
 ui/lib/store/channels.svelte.js            |   9 +-
 ui/lib/store/messages.svelte.js            |   2 +-
 ui/routes/(app)/+layout.svelte             |   6 +-
 ui/routes/(app)/+page.svelte               |   4 +-
 ui/routes/(app)/ch/[channel]/+page.svelte  |  14 +--
 ui/styles/app-layout.css                   |   4 +-
 ui/styles/reset.css                        | 147 ++++++++++++++++++++++-------
 ui/styles/sidebar.css                      |   2 +-
 ui/styles/textarea.css                     |   2 +-
 ui/styles/variables.css                    |  18 +++-
 18 files changed, 167 insertions(+), 112 deletions(-)

(limited to 'ui/lib/components/MessageRun.svelte')

diff --git a/ui/app.css b/ui/app.css
index 2df588e..a02106d 100644
--- a/ui/app.css
+++ b/ui/app.css
@@ -1,14 +1,14 @@
-@import url("styles/reset.css");
-@import url("styles/variables.css");
-@import url("styles/overscroll.css");
-@import url("styles/app-bar.css");
-@import url("styles/app-layout.css");
-@import url("styles/sidebar.css");
-@import url("styles/active-channel.css");
-@import url("styles/messages.css");
-@import url("styles/textarea.css");
-@import url("styles/forms.css");
-@import url("styles/invites.css");
+@import url('styles/reset.css');
+@import url('styles/variables.css');
+@import url('styles/overscroll.css');
+@import url('styles/app-bar.css');
+@import url('styles/app-layout.css');
+@import url('styles/sidebar.css');
+@import url('styles/active-channel.css');
+@import url('styles/messages.css');
+@import url('styles/textarea.css');
+@import url('styles/forms.css');
+@import url('styles/invites.css');
 
 body {
   background-color: var(--colour-active-channel-bg);
diff --git a/ui/lib/components/ChangePassword.svelte b/ui/lib/components/ChangePassword.svelte
index 51ebccd..bf94ea7 100644
--- a/ui/lib/components/ChangePassword.svelte
+++ b/ui/lib/components/ChangePassword.svelte
@@ -35,12 +35,7 @@
 
   <label
     >new password
-    <input
-      name="newPassword"
-      type="password"
-      placeholder="password"
-      bind:value={newPassword}
-    />
+    <input name="newPassword" type="password" placeholder="password" bind:value={newPassword} />
   </label>
 
   <label
diff --git a/ui/lib/components/Channel.svelte b/ui/lib/components/Channel.svelte
index 2fc3249..c73340f 100644
--- a/ui/lib/components/Channel.svelte
+++ b/ui/lib/components/Channel.svelte
@@ -3,7 +3,7 @@
 </script>
 
 <a href="/ch/{id}">
-  <li class:active={active}>
+  <li class:active>
     {#if hasUnreads}
       <span class="badge has-unreads">❦</span>
     {:else}
diff --git a/ui/lib/components/CreateChannelForm.svelte b/ui/lib/components/CreateChannelForm.svelte
index 8fab4c4..85c85bb 100644
--- a/ui/lib/components/CreateChannelForm.svelte
+++ b/ui/lib/components/CreateChannelForm.svelte
@@ -16,11 +16,6 @@
 </script>
 
 <form onsubmit={handleSubmit}>
-  <input
-    type="text"
-    placeholder="create channel"
-    bind:value={name}
-    {disabled}
-  />
+  <input type="text" placeholder="create channel" bind:value={name} {disabled} />
   <button type="submit">&#x2795;</button>
 </form>
diff --git a/ui/lib/components/LogIn.svelte b/ui/lib/components/LogIn.svelte
index 44aab44..5bfdae2 100644
--- a/ui/lib/components/LogIn.svelte
+++ b/ui/lib/components/LogIn.svelte
@@ -12,13 +12,7 @@
   <form class="form" {onsubmit}>
     <label for="username">
       username
-      <input
-        name="username"
-        type="text"
-        placeholder="username"
-        bind:value={username}
-        {disabled}
-      />
+      <input name="username" type="text" placeholder="username" bind:value={username} {disabled} />
     </label>
     <label for="password">
       password
diff --git a/ui/lib/components/Message.svelte b/ui/lib/components/Message.svelte
index 6918b5d..1b1598b 100644
--- a/ui/lib/components/Message.svelte
+++ b/ui/lib/components/Message.svelte
@@ -25,13 +25,7 @@
   }
 </script>
 
-<div
-    class="message"
-    class:delete-armed={deleteArmed}
-    role="article"
-    data-at={at}
-    {onmouseleave}
-    >
+<div class="message" class:delete-armed={deleteArmed} role="article" data-at={at} {onmouseleave}>
   <div class="handle">
     {atFormatted}
     {#if editable}
diff --git a/ui/lib/components/MessageInput.svelte b/ui/lib/components/MessageInput.svelte
index 25a0352..162db1b 100644
--- a/ui/lib/components/MessageInput.svelte
+++ b/ui/lib/components/MessageInput.svelte
@@ -24,13 +24,6 @@
 </script>
 
 <form bind:this={form} onsubmit={onSubmit}>
-  <textarea
-    onkeydown={onKeyDown}
-    bind:value
-    {disabled}
-    type="search"
-  ></textarea>
-  <button
-    type="submit"
-  >&raquo;</button>
+  <textarea onkeydown={onKeyDown} bind:value {disabled} type="search"></textarea>
+  <button type="submit">&raquo;</button>
 </form>
diff --git a/ui/lib/components/MessageRun.svelte b/ui/lib/components/MessageRun.svelte
index dec5f4f..bee64e8 100644
--- a/ui/lib/components/MessageRun.svelte
+++ b/ui/lib/components/MessageRun.svelte
@@ -8,11 +8,7 @@
   let ownMessage = $derived($currentUser !== null && $currentUser.id == sender);
 </script>
 
-<div
-  class="message-run"
-  class:own-message={ownMessage}
-  class:other-message={!ownMessage}
->
+<div class="message-run" class:own-message={ownMessage} class:other-message={!ownMessage}>
   <span class="username">
     @{name}:
   </span>
diff --git a/ui/lib/store/channels.svelte.js b/ui/lib/store/channels.svelte.js
index 8919be0..c82f9aa 100644
--- a/ui/lib/store/channels.svelte.js
+++ b/ui/lib/store/channels.svelte.js
@@ -1,5 +1,5 @@
 import { DateTime } from 'luxon';
-const EPOCH_STRING = "1970-01-01T00:00:00Z";
+const EPOCH_STRING = '1970-01-01T00:00:00Z';
 
 // For reasons unclear to me, a straight up class definition with a constructor
 // doesn't seem to work, reactively. So we resort to this.
@@ -15,7 +15,7 @@ function makeChannelObject({ id, name, draft = '', lastReadAt = null, scrollPosi
     name,
     lastReadAt: lastReadAt || DateTime.fromISO(EPOCH_STRING),
     draft,
-    scrollPosition,
+    scrollPosition
   };
 }
 
@@ -33,10 +33,7 @@ export class Channels {
   }
 
   addChannel(id, name) {
-    this.channels = [
-      ...this.channels,
-      makeChannelObject({ id, name }),
-    ];
+    this.channels = [...this.channels, makeChannelObject({ id, name })];
     this.sort();
     return this;
   }
diff --git a/ui/lib/store/messages.svelte.js b/ui/lib/store/messages.svelte.js
index ba4c895..dadade6 100644
--- a/ui/lib/store/messages.svelte.js
+++ b/ui/lib/store/messages.svelte.js
@@ -5,7 +5,7 @@ import DOMPurify from 'dompurify';
 const RUN_COALESCE_MAX_INTERVAL = 10 /* min */ * 60 /* sec */ * 1000; /* ms */
 
 export class Messages {
-  channels = $state({});  // Mapping<ChannelId, Message>
+  channels = $state({}); // Mapping<ChannelId, Message>
 
   inChannel(channel) {
     return this.channels[channel] || [];
diff --git a/ui/routes/(app)/+layout.svelte b/ui/routes/(app)/+layout.svelte
index 08444bd..cbfef54 100644
--- a/ui/routes/(app)/+layout.svelte
+++ b/ui/routes/(app)/+layout.svelte
@@ -41,7 +41,7 @@
         let hasUnreads = lastMessageAt > ch.lastReadAt;
         enrichedChannels.push({
           ...ch,
-          hasUnreads,
+          hasUnreads
         });
       }
     }
@@ -116,7 +116,7 @@
   }
 </script>
 
-<svelte:window on:beforeunload={beforeUnload}/>
+<svelte:window on:beforeunload={beforeUnload} />
 
 <svelte:head>
   <!-- TODO: unread count? -->
@@ -128,7 +128,7 @@
 {:else}
   <div id="interface">
     <nav id="sidebar" data-expanded={pageContext.showMenu}>
-        <ChannelList active={channel} channels={enrichedChannels} />
+      <ChannelList active={channel} channels={enrichedChannels} />
       <div class="create-channel">
         <CreateChannelForm />
       </div>
diff --git a/ui/routes/(app)/+page.svelte b/ui/routes/(app)/+page.svelte
index e15bca8..007c5c6 100644
--- a/ui/routes/(app)/+page.svelte
+++ b/ui/routes/(app)/+page.svelte
@@ -1,5 +1,3 @@
 <div class="no-active-channel">
-  <span class="vertical-aligner">
-    Please select or create a channel.
-  </span>
+  <span class="vertical-aligner"> Please select or create a channel. </span>
 </div>
diff --git a/ui/routes/(app)/ch/[channel]/+page.svelte b/ui/routes/(app)/ch/[channel]/+page.svelte
index 8eba709..dbdb507 100644
--- a/ui/routes/(app)/ch/[channel]/+page.svelte
+++ b/ui/routes/(app)/ch/[channel]/+page.svelte
@@ -18,15 +18,17 @@
     const elementTop = elRect.top;
     const elementBottom = elRect.bottom;
 
-    return ((parentTop < elementTop) && (parentBottom > elementBottom));
+    return parentTop < elementTop && parentBottom > elementBottom;
   }
 
   function getLastVisibleMessage() {
     const parentElement = activeChannel;
     const childElements = parentElement.getElementsByClassName('message');
-    const lastInView = Array.from(childElements).reverse().find((el) => {
-      return inView(parentElement, el);
-    });
+    const lastInView = Array.from(childElements)
+      .reverse()
+      .find((el) => {
+        return inView(parentElement, el);
+      });
     return lastInView;
   }
 
@@ -50,14 +52,14 @@
   });
 
   function handleKeydown(event) {
-		if (event.key === 'Escape') {
+    if (event.key === 'Escape') {
       setLastRead(); // TODO: pass in "last message DT"?
     }
   }
 
   let lastReadCallback = null;
   function handleScroll() {
-    clearTimeout(lastReadCallback);  // Fine if lastReadCallback is null still.
+    clearTimeout(lastReadCallback); // Fine if lastReadCallback is null still.
     lastReadCallback = setTimeout(setLastRead, 2 * 1000);
   }
 </script>
diff --git a/ui/styles/app-layout.css b/ui/styles/app-layout.css
index 50fa704..82d9914 100644
--- a/ui/styles/app-layout.css
+++ b/ui/styles/app-layout.css
@@ -36,7 +36,9 @@ nav.list-nav {
   overflow: auto;
 
   @media (width > 640px) {
-    height: calc(100vh - var(--app-bar-height) - var(--input-row-height) - var(--interface-padding));
+    height: calc(
+      100vh - var(--app-bar-height) - var(--input-row-height) - var(--interface-padding)
+    );
   }
 }
 
diff --git a/ui/styles/reset.css b/ui/styles/reset.css
index e29c0f5..a3f7681 100644
--- a/ui/styles/reset.css
+++ b/ui/styles/reset.css
@@ -3,46 +3,127 @@
    License: none (public domain)
 */
 
-html, body, div, span, applet, object, iframe,
-h1, h2, h3, h4, h5, h6, p, blockquote, pre,
-a, abbr, acronym, address, big, cite, code,
-del, dfn, em, img, ins, kbd, q, s, samp,
-small, strike, strong, sub, sup, tt, var,
-b, u, i, center,
-dl, dt, dd, ol, ul, li,
-fieldset, form, label, legend,
-table, caption, tbody, tfoot, thead, tr, th, td,
-article, aside, canvas, details, embed, 
-figure, figcaption, footer, header, hgroup, 
-menu, nav, output, ruby, section, summary,
-time, mark, audio, video {
-	margin: 0;
-	padding: 0;
-	border: 0;
-	font-size: 100%;
-	font: inherit;
-	vertical-align: baseline;
+html,
+body,
+div,
+span,
+applet,
+object,
+iframe,
+h1,
+h2,
+h3,
+h4,
+h5,
+h6,
+p,
+blockquote,
+pre,
+a,
+abbr,
+acronym,
+address,
+big,
+cite,
+code,
+del,
+dfn,
+em,
+img,
+ins,
+kbd,
+q,
+s,
+samp,
+small,
+strike,
+strong,
+sub,
+sup,
+tt,
+var,
+b,
+u,
+i,
+center,
+dl,
+dt,
+dd,
+ol,
+ul,
+li,
+fieldset,
+form,
+label,
+legend,
+table,
+caption,
+tbody,
+tfoot,
+thead,
+tr,
+th,
+td,
+article,
+aside,
+canvas,
+details,
+embed,
+figure,
+figcaption,
+footer,
+header,
+hgroup,
+menu,
+nav,
+output,
+ruby,
+section,
+summary,
+time,
+mark,
+audio,
+video {
+  margin: 0;
+  padding: 0;
+  border: 0;
+  font-size: 100%;
+  font: inherit;
+  vertical-align: baseline;
 }
 /* HTML5 display-role reset for older browsers */
-article, aside, details, figcaption, figure, 
-footer, header, hgroup, menu, nav, section {
-	display: block;
+article,
+aside,
+details,
+figcaption,
+figure,
+footer,
+header,
+hgroup,
+menu,
+nav,
+section {
+  display: block;
 }
 body {
-	line-height: 1;
+  line-height: 1;
 }
-ol, ul {
-	list-style: none;
+ol,
+ul {
+  list-style: none;
 }
-blockquote, q {
-	quotes: none;
+blockquote,
+q {
+  quotes: none;
 }
-blockquote:before, blockquote:after,
-q:before, q:after {
-	content: '';
-	content: none;
+blockquote:before,
+blockquote:after,
+q:before,
+q:after {
+  content: '';
+  content: none;
 }
 table {
-	border-collapse: collapse;
-	border-spacing: 0;
+  border-collapse: collapse;
+  border-spacing: 0;
 }
diff --git a/ui/styles/sidebar.css b/ui/styles/sidebar.css
index b31c4fd..5e5e16a 100644
--- a/ui/styles/sidebar.css
+++ b/ui/styles/sidebar.css
@@ -44,7 +44,7 @@
   padding: 0.5rem;
   border-radius: 0.5rem 0 0 0.5rem;
   border: 1px solid var(--colour-input-border);
-  z-index: 1;  /* Just to make the focus-active border go over the following button. */
+  z-index: 1; /* Just to make the focus-active border go over the following button. */
   flex-grow: 1;
   background-color: var(--colour-input-bg);
   color: var(--colour-input-text);
diff --git a/ui/styles/textarea.css b/ui/styles/textarea.css
index b45a66d..c38de46 100644
--- a/ui/styles/textarea.css
+++ b/ui/styles/textarea.css
@@ -10,7 +10,7 @@
   padding: 0.5rem;
   border-radius: 0.5rem 0 0 0.5rem;
   border: 1px solid var(--colour-input-border);
-  z-index: 1;  /* Just to make the focus-active border go over the following button. */
+  z-index: 1; /* Just to make the focus-active border go over the following button. */
   flex-grow: 1;
   background-color: var(--colour-input-bg);
   color: var(--colour-input-text);
diff --git a/ui/styles/variables.css b/ui/styles/variables.css
index fa51506..80817f3 100644
--- a/ui/styles/variables.css
+++ b/ui/styles/variables.css
@@ -8,9 +8,9 @@
   --nav-width: 21rem;
 
   /* coloUrs */
-  --colour-okay: #6A994E;
-  --colour-warn: #EBC3BE;
-  --colour-error: #DE5F55;
+  --colour-okay: #6a994e;
+  --colour-warn: #ebc3be;
+  --colour-error: #de5f55;
 
   /* I dunno, I liked this colour: */
   --colour-base: rgb(121, 96, 159);
@@ -43,9 +43,17 @@
 
   /* MessageRun */
   --colour-message-run-self-bg: color-mix(in srgb, var(--colour-base) 30%, white);
-  --colour-message-run-self-border: color-mix(in srgb, var(--colour-message-run-self-bg) 50%, black);
+  --colour-message-run-self-border: color-mix(
+    in srgb,
+    var(--colour-message-run-self-bg) 50%,
+    black
+  );
   --colour-message-run-other-bg: color-mix(in srgb, var(--colour-base) 50%, white);
-  --colour-message-run-other-border: color-mix(in srgb, var(--colour-message-run-other-bg) 50%, black);
+  --colour-message-run-other-border: color-mix(
+    in srgb,
+    var(--colour-message-run-other-bg) 50%,
+    black
+  );
   --colour-message-run-self-text: var(--dark-text);
   --colour-message-run-other-text: var(--dark-text);
 
-- 
cgit v1.2.3

