Repository: fmaclen/hollama
Pull request #33 (2024-04-22 16:02:52)

chore: remove shadcn
Too much complexity for not a lot of gain.

cloudflare-pages[bot]: ## Deploying hollama with &nbsp;<a href="https://pages.dev"><img alt="Cloudflare Pages" src="https://user-images.githubusercontent.com/23264/106598434-9e719e00-654f-11eb-9e59-6167043cfa01.png" width="16"></a> &nbsp;Cloudflare Pages

<table><tr><td><strong>Latest commit:</strong> </td><td>
<code>4215b94</code>
</td></tr>
<tr><td><strong>Status:</strong></td><td>&nbsp;✅&nbsp; Deploy successful!</td></tr>
<tr><td><strong>Preview URL:</strong></td><td>
<a href='https://0b1d6c51.hollama.pages.dev'>https://0b1d6c51.hollama.pages.dev</a>
</td></tr>
<tr><td><strong>Branch Preview URL:</strong></td><td>
<a href='https://remove-shadcn-complexity.hollama.pages.dev'>https://remove-shadcn-complexity.hollama.pages.dev</a>
</td></tr>
</table>

[View logs](https://dash.cloudflare.com/?to=/:account/pages/view/hollama/0b1d6c51-c037-4bf2-bc39-1437d183cfe7)


Patch:
diff --git a/components.json b/components.json
deleted file mode 100644
index 0191a86..0000000
--- a/components.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
-	"$schema": "https://shadcn-svelte.com/schema.json",
-	"style": "default",
-	"tailwind": {
-		"config": "tailwind.config.js",
-		"css": "src/app.pcss",
-		"baseColor": "neutral"
-	},
-	"aliases": {
-		"components": "$lib/components",
-		"utils": "$lib/utils"
-	},
-	"typescript": true
-}
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index 8db7100..de58618 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -7,14 +7,6 @@
 		"": {
 			"name": "hollama",
 			"version": "0.0.1",
-			"dependencies": {
-				"bits-ui": "^0.21.2",
-				"clsx": "^2.1.0",
-				"lucide-svelte": "^0.365.0",
-				"paneforge": "^0.0.4",
-				"tailwind-merge": "^2.2.2",
-				"tailwind-variants": "^0.2.1"
-			},
 			"devDependencies": {
 				"@playwright/test": "^1.43.0",
 				"@sveltejs/adapter-auto": "^3.0.0",
@@ -30,7 +22,9 @@
 				"eslint-config-prettier": "^9.1.0",
 				"eslint-plugin-svelte": "^2.35.1",
 				"highlight.js": "^11.9.0",
+				"lucide-svelte": "^0.372.0",
 				"markdown-it": "^14.1.0",
+				"paneforge": "^0.0.4",
 				"postcss": "^8.4.32",
 				"postcss-load-config": "^5.0.2",
 				"prettier": "^3.1.1",
@@ -58,6 +52,7 @@
 			"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,
 			"engines": {
 				"node": ">=10"
 			},
@@ -69,6 +64,7 @@
 			"version": "2.3.0",
 			"resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz",
 			"integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==",
+			"dev": true,
 			"dependencies": {
 				"@jridgewell/gen-mapping": "^0.3.5",
 				"@jridgewell/trace-mapping": "^0.3.24"
@@ -77,17 +73,6 @@
 				"node": ">=6.0.0"
 			}
 		},
-		"node_modules/@babel/runtime": {
-			"version": "7.24.4",
-			"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.4.tgz",
-			"integrity": "sha512-dkxf7+hn8mFBwKjs9bvBlArzLVxVbS8usaPUDd5p2a9JCL9tB8OaOVN1isD4+Xyk4ns89/xeOmbQvgdK7IIVdA==",
-			"dependencies": {
-				"regenerator-runtime": "^0.14.0"
-			},
-			"engines": {
-				"node": ">=6.9.0"
-			}
-		},
 		"node_modules/@cloudflare/kv-asset-handler": {
 			"version": "0.3.1",
 			"resolved": "https://registry.npmjs.org/@cloudflare/kv-asset-handler/-/kv-asset-handler-0.3.1.tgz",
@@ -693,28 +678,6 @@
 				"node": ">=14"
 			}
 		},
-		"node_modules/@floating-ui/core": {
-			"version": "1.6.0",
-			"resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.0.tgz",
-			"integrity": "sha512-PcF++MykgmTj3CIyOQbKA/hDzOAiqI3mhuoN44WRCopIs1sgoDoU4oty4Jtqaj/y3oDU6fnVSm4QG0a3t5i0+g==",
-			"dependencies": {
-				"@floating-ui/utils": "^0.2.1"
-			}
-		},
-		"node_modules/@floating-ui/dom": {
-			"version": "1.6.3",
-			"resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.3.tgz",
-			"integrity": "sha512-RnDthu3mzPlQ31Ss/BTwQ1zjzIhr3lk1gZB1OC56h/1vEtaXkESrOqL5fQVMfXpwGtRwX+YsZBdyHtJMQnkArw==",
-			"dependencies": {
-				"@floating-ui/core": "^1.0.0",
-				"@floating-ui/utils": "^0.2.0"
-			}
-		},
-		"node_modules/@floating-ui/utils": {
-			"version": "0.2.1",
-			"resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.1.tgz",
-			"integrity": "sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q=="
-		},
 		"node_modules/@humanwhocodes/config-array": {
 			"version": "0.11.14",
 			"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz",
@@ -770,18 +733,11 @@
 			"integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==",
 			"dev": true
 		},
-		"node_modules/@internationalized/date": {
-			"version": "3.5.2",
-			"resolved": "https://registry.npmjs.org/@internationalized/date/-/date-3.5.2.tgz",
-			"integrity": "sha512-vo1yOMUt2hzp63IutEaTUxROdvQg1qlMRsbCvbay2AK2Gai7wIgCyK5weEX3nHkiLgo4qCXHijFNC/ILhlRpOQ==",
-			"dependencies": {
-				"@swc/helpers": "^0.5.0"
-			}
-		},
 		"node_modules/@isaacs/cliui": {
 			"version": "8.0.2",
 			"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
 			"integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
+			"dev": true,
 			"dependencies": {
 				"string-width": "^5.1.2",
 				"string-width-cjs": "npm:string-width@^4.2.0",
@@ -798,6 +754,7 @@
 			"version": "6.0.1",
 			"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
 			"integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
+			"dev": true,
 			"engines": {
 				"node": ">=12"
 			},
@@ -809,6 +766,7 @@
 			"version": "7.1.0",
 			"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
 			"integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
+			"dev": true,
 			"dependencies": {
 				"ansi-regex": "^6.0.1"
 			},
@@ -823,6 +781,7 @@
 			"version": "0.3.5",
 			"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz",
 			"integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==",
+			"dev": true,
 			"dependencies": {
 				"@jridgewell/set-array": "^1.2.1",
 				"@jridgewell/sourcemap-codec": "^1.4.10",
@@ -836,6 +795,7 @@
 			"version": "3.1.2",
 			"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
 			"integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
+			"dev": true,
 			"engines": {
 				"node": ">=6.0.0"
 			}
@@ -844,6 +804,7 @@
 			"version": "1.2.1",
 			"resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz",
 			"integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
+			"dev": true,
 			"engines": {
 				"node": ">=6.0.0"
 			}
@@ -851,37 +812,24 @@
 		"node_modules/@jridgewell/sourcemap-codec": {
 			"version": "1.4.15",
 			"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
-			"integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg=="
+			"integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==",
+			"dev": true
 		},
 		"node_modules/@jridgewell/trace-mapping": {
 			"version": "0.3.25",
 			"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
 			"integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
+			"dev": true,
 			"dependencies": {
 				"@jridgewell/resolve-uri": "^3.1.0",
 				"@jridgewell/sourcemap-codec": "^1.4.14"
 			}
 		},
-		"node_modules/@melt-ui/svelte": {
-			"version": "0.76.2",
-			"resolved": "https://registry.npmjs.org/@melt-ui/svelte/-/svelte-0.76.2.tgz",
-			"integrity": "sha512-7SbOa11tXUS95T3fReL+dwDs5FyJtCEqrqG3inRziDws346SYLsxOQ6HmX+4BkIsQh1R8U3XNa+EMmdMt38lMA==",
-			"dependencies": {
-				"@floating-ui/core": "^1.3.1",
-				"@floating-ui/dom": "^1.4.5",
-				"@internationalized/date": "^3.5.0",
-				"dequal": "^2.0.3",
-				"focus-trap": "^7.5.2",
-				"nanoid": "^5.0.4"
-			},
-			"peerDependencies": {
-				"svelte": ">=3 <5"
-			}
-		},
 		"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,
 			"dependencies": {
 				"@nodelib/fs.stat": "2.0.5",
 				"run-parallel": "^1.1.9"
@@ -894,6 +842,7 @@
 			"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,
 			"engines": {
 				"node": ">= 8"
 			}
@@ -902,6 +851,7 @@
 			"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,
 			"dependencies": {
 				"@nodelib/fs.scandir": "2.1.5",
 				"fastq": "^1.6.0"
@@ -914,6 +864,7 @@
 			"version": "0.11.0",
 			"resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
 			"integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
+			"dev": true,
 			"optional": true,
 			"engines": {
 				"node": ">=14"
@@ -1233,14 +1184,6 @@
 				"vite": "^5.0.0"
 			}
 		},
-		"node_modules/@swc/helpers": {
-			"version": "0.5.8",
-			"resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.8.tgz",
-			"integrity": "sha512-lruDGw3pnfM3wmZHeW7JuhkGQaJjPyiKjxeGhdmfoOT53Ic9qb5JLDNaK2HUdl1zLDeX28H221UvKjfdvSLVMg==",
-			"dependencies": {
-				"tslib": "^2.4.0"
-			}
-		},
 		"node_modules/@types/cookie": {
 			"version": "0.6.0",
 			"resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz",
@@ -1260,7 +1203,8 @@
 		"node_modules/@types/estree": {
 			"version": "1.0.5",
 			"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz",
-			"integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw=="
+			"integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==",
+			"dev": true
 		},
 		"node_modules/@types/json-schema": {
 			"version": "7.0.15",
@@ -1522,6 +1466,7 @@
 			"version": "8.11.3",
 			"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz",
 			"integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==",
+			"dev": true,
 			"bin": {
 				"acorn": "bin/acorn"
 			},
@@ -1568,6 +1513,7 @@
 			"version": "5.0.1",
 			"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
 			"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+			"dev": true,
 			"engines": {
 				"node": ">=8"
 			}
@@ -1576,6 +1522,7 @@
 			"version": "4.3.0",
 			"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
 			"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+			"dev": true,
 			"dependencies": {
 				"color-convert": "^2.0.1"
 			},
@@ -1589,12 +1536,14 @@
 		"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=="
+			"integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==",
+			"dev": true
 		},
 		"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,
 			"dependencies": {
 				"normalize-path": "^3.0.0",
 				"picomatch": "^2.0.4"
@@ -1606,7 +1555,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=="
+			"integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==",
+			"dev": true
 		},
 		"node_modules/argparse": {
 			"version": "2.0.1",
@@ -1618,6 +1568,7 @@
 			"version": "5.3.0",
 			"resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz",
 			"integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==",
+			"dev": true,
 			"dependencies": {
 				"dequal": "^2.0.3"
 			}
@@ -1682,6 +1633,7 @@
 			"version": "4.0.0",
 			"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.0.0.tgz",
 			"integrity": "sha512-+60uv1hiVFhHZeO+Lz0RYzsVHy5Wr1ayX0mwda9KPDVLNJgZ1T9Ny7VmFbLDzxsH0D87I86vgj3gFrjTJUYznw==",
+			"dev": true,
 			"dependencies": {
 				"dequal": "^2.0.3"
 			}
@@ -1689,12 +1641,14 @@
 		"node_modules/balanced-match": {
 			"version": "1.0.2",
 			"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
-			"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
+			"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+			"dev": true
 		},
 		"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,
 			"engines": {
 				"node": ">=8"
 			},
@@ -1702,22 +1656,6 @@
 				"url": "https://github.com/sponsors/sindresorhus"
 			}
 		},
-		"node_modules/bits-ui": {
-			"version": "0.21.2",
-			"resolved": "https://registry.npmjs.org/bits-ui/-/bits-ui-0.21.2.tgz",
-			"integrity": "sha512-tDOvNdJ+uC/VWlzCZ6Pwv3enQJBw1D7leUfdIqg8WvqcDHnvn3fk4V3Y9VmpMOPnl+xTaiKxSiVpO/Dh8wD6jA==",
-			"dependencies": {
-				"@internationalized/date": "^3.5.1",
-				"@melt-ui/svelte": "0.76.2",
-				"nanoid": "^5.0.5"
-			},
-			"funding": {
-				"url": "https://github.com/sponsors/huntabyte"
-			},
-			"peerDependencies": {
-				"svelte": "^4.0.0"
-			}
-		},
 		"node_modules/blake3-wasm": {
 			"version": "2.1.5",
 			"resolved": "https://registry.npmjs.org/blake3-wasm/-/blake3-wasm-2.1.5.tgz",
@@ -1729,6 +1667,7 @@
 			"version": "2.0.1",
 			"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
 			"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+			"dev": true,
 			"dependencies": {
 				"balanced-match": "^1.0.0"
 			}
@@ -1737,6 +1676,7 @@
 			"version": "3.0.2",
 			"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
 			"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+			"dev": true,
 			"dependencies": {
 				"fill-range": "^7.0.1"
 			},
@@ -1798,6 +1738,7 @@
 			"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,
 			"engines": {
 				"node": ">= 6"
 			}
@@ -1853,6 +1794,7 @@
 			"version": "3.6.0",
 			"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
 			"integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
+			"dev": true,
 			"dependencies": {
 				"anymatch": "~3.1.2",
 				"braces": "~3.0.2",
@@ -1876,6 +1818,7 @@
 			"version": "5.1.2",
 			"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
 			"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+			"dev": true,
 			"dependencies": {
 				"is-glob": "^4.0.1"
 			},
@@ -1883,18 +1826,11 @@
 				"node": ">= 6"
 			}
 		},
-		"node_modules/clsx": {
-			"version": "2.1.0",
-			"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.0.tgz",
-			"integrity": "sha512-m3iNNWpd9rl3jvvcBnu70ylMdrXt8Vlq4HYadnU5fwcOtvkSQWPmj7amUcDT2qYI7risszBjI5AUIUox9D16pg==",
-			"engines": {
-				"node": ">=6"
-			}
-		},
 		"node_modules/code-red": {
 			"version": "1.0.4",
 			"resolved": "https://registry.npmjs.org/code-red/-/code-red-1.0.4.tgz",
 			"integrity": "sha512-7qJWqItLA8/VPVlKJlFXU+NBlo/qyfs39aJcuMT/2ere32ZqvF5OSxgdM5xOfJJ7O429gg2HM47y8v9P+9wrNw==",
+			"dev": true,
 			"dependencies": {
 				"@jridgewell/sourcemap-codec": "^1.4.15",
 				"@types/estree": "^1.0.1",
@@ -1907,6 +1843,7 @@
 			"version": "2.0.1",
 			"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
 			"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+			"dev": true,
 			"dependencies": {
 				"color-name": "~1.1.4"
 			},
@@ -1917,12 +1854,14 @@
 		"node_modules/color-name": {
 			"version": "1.1.4",
 			"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
-			"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
+			"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+			"dev": true
 		},
 		"node_modules/commander": {
 			"version": "4.1.1",
 			"resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
 			"integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==",
+			"dev": true,
 			"engines": {
 				"node": ">= 6"
 			}
@@ -1946,6 +1885,7 @@
 			"version": "7.0.3",
 			"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
 			"integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+			"dev": true,
 			"dependencies": {
 				"path-key": "^3.1.0",
 				"shebang-command": "^2.0.0",
@@ -1959,6 +1899,7 @@
 			"version": "2.3.1",
 			"resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz",
 			"integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==",
+			"dev": true,
 			"dependencies": {
 				"mdn-data": "2.0.30",
 				"source-map-js": "^1.0.1"
@@ -1971,6 +1912,7 @@
 			"version": "3.0.0",
 			"resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
 			"integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
+			"dev": true,
 			"bin": {
 				"cssesc": "bin/cssesc"
 			},
@@ -2021,6 +1963,7 @@
 			"version": "2.0.3",
 			"resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
 			"integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==",
+			"dev": true,
 			"engines": {
 				"node": ">=6"
 			}
@@ -2043,7 +1986,8 @@
 		"node_modules/didyoumean": {
 			"version": "1.2.2",
 			"resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz",
-			"integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw=="
+			"integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==",
+			"dev": true
 		},
 		"node_modules/dir-glob": {
 			"version": "3.0.1",
@@ -2060,7 +2004,8 @@
 		"node_modules/dlv": {
 			"version": "1.1.3",
 			"resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz",
-			"integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA=="
+			"integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==",
+			"dev": true
 		},
 		"node_modules/doctrine": {
 			"version": "3.0.0",
@@ -2077,7 +2022,8 @@
 		"node_modules/eastasianwidth": {
 			"version": "0.2.0",
 			"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
-			"integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="
+			"integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
+			"dev": true
 		},
 		"node_modules/electron-to-chromium": {
 			"version": "1.4.729",
@@ -2088,7 +2034,8 @@
 		"node_modules/emoji-regex": {
 			"version": "9.2.2",
 			"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
-			"integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="
+			"integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
+			"dev": true
 		},
 		"node_modules/entities": {
 			"version": "4.5.0",
@@ -2441,6 +2388,7 @@
 			"version": "3.0.3",
 			"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz",
 			"integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==",
+			"dev": true,
 			"dependencies": {
 				"@types/estree": "^1.0.0"
 			}
@@ -2477,6 +2425,7 @@
 			"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,
 			"dependencies": {
 				"@nodelib/fs.stat": "^2.0.2",
 				"@nodelib/fs.walk": "^1.2.3",
@@ -2492,6 +2441,7 @@
 			"version": "5.1.2",
 			"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
 			"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+			"dev": true,
 			"dependencies": {
 				"is-glob": "^4.0.1"
 			},
@@ -2515,6 +2465,7 @@
 			"version": "1.17.1",
 			"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz",
 			"integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==",
+			"dev": true,
 			"dependencies": {
 				"reusify": "^1.0.4"
 			}
@@ -2535,6 +2486,7 @@
 			"version": "7.0.1",
 			"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
 			"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+			"dev": true,
 			"dependencies": {
 				"to-regex-range": "^5.0.1"
 			},
@@ -2578,18 +2530,11 @@
 			"integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==",
 			"dev": true
 		},
-		"node_modules/focus-trap": {
-			"version": "7.5.4",
-			"resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-7.5.4.tgz",
-			"integrity": "sha512-N7kHdlgsO/v+iD/dMoJKtsSqs5Dz/dXZVebRgJw23LDk+jMi/974zyiOYDziY2JPp8xivq9BmUGwIJMiuSBi7w==",
-			"dependencies": {
-				"tabbable": "^6.2.0"
-			}
-		},
 		"node_modules/foreground-child": {
 			"version": "3.1.1",
 			"resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz",
 			"integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==",
+			"dev": true,
 			"dependencies": {
 				"cross-spawn": "^7.0.0",
 				"signal-exit": "^4.0.1"
@@ -2624,6 +2569,7 @@
 			"version": "2.3.3",
 			"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
 			"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+			"dev": true,
 			"hasInstallScript": true,
 			"optional": true,
 			"os": [
@@ -2637,6 +2583,7 @@
 			"version": "1.1.2",
 			"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
 			"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+			"dev": true,
 			"funding": {
 				"url": "https://github.com/sponsors/ljharb"
 			}
@@ -2676,6 +2623,7 @@
 			"version": "6.0.2",
 			"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
 			"integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+			"dev": true,
 			"dependencies": {
 				"is-glob": "^4.0.3"
 			},
@@ -2784,6 +2732,7 @@
 			"version": "2.0.2",
 			"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
 			"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
+			"dev": true,
 			"dependencies": {
 				"function-bind": "^1.1.2"
 			},
@@ -2870,6 +2819,7 @@
 			"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,
 			"dependencies": {
 				"binary-extensions": "^2.0.0"
 			},
@@ -2881,6 +2831,7 @@
 			"version": "2.13.1",
 			"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz",
 			"integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==",
+			"dev": true,
 			"dependencies": {
 				"hasown": "^2.0.0"
 			},
@@ -2892,6 +2843,7 @@
 			"version": "2.1.1",
 			"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
 			"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+			"dev": true,
 			"engines": {
 				"node": ">=0.10.0"
 			}
@@ -2900,6 +2852,7 @@
 			"version": "3.0.0",
 			"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
 			"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+			"dev": true,
 			"engines": {
 				"node": ">=8"
 			}
@@ -2908,6 +2861,7 @@
 			"version": "4.0.3",
 			"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
 			"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+			"dev": true,
 			"dependencies": {
 				"is-extglob": "^2.1.1"
 			},
@@ -2919,6 +2873,7 @@
 			"version": "7.0.0",
 			"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
 			"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+			"dev": true,
 			"engines": {
 				"node": ">=0.12.0"
 			}
@@ -2936,6 +2891,7 @@
 			"version": "3.0.2",
 			"resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.2.tgz",
 			"integrity": "sha512-v3rht/LgVcsdZa3O2Nqs+NMowLOxeOm7Ay9+/ARQ2F+qEoANRcqrjAZKGN0v8ymUetZGgkp26LTnGT7H0Qo9Pg==",
+			"dev": true,
 			"dependencies": {
 				"@types/estree": "*"
 			}
@@ -2943,12 +2899,14 @@
 		"node_modules/isexe": {
 			"version": "2.0.0",
 			"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
-			"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
+			"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+			"dev": true
 		},
 		"node_modules/jackspeak": {
 			"version": "2.3.6",
 			"resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz",
 			"integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==",
+			"dev": true,
 			"dependencies": {
 				"@isaacs/cliui": "^8.0.2"
 			},
@@ -2966,6 +2924,7 @@
 			"version": "1.21.0",
 			"resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.0.tgz",
 			"integrity": "sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==",
+			"dev": true,
 			"bin": {
 				"jiti": "bin/jiti.js"
 			}
@@ -3052,7 +3011,8 @@
 		"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=="
+			"integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
+			"dev": true
 		},
 		"node_modules/linkify-it": {
 			"version": "5.0.0",
@@ -3066,7 +3026,8 @@
 		"node_modules/locate-character": {
 			"version": "3.0.0",
 			"resolved": "https://registry.npmjs.org/locate-character/-/locate-character-3.0.0.tgz",
-			"integrity": "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA=="
+			"integrity": "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==",
+			"dev": true
 		},
 		"node_modules/locate-path": {
 			"version": "6.0.0",
@@ -3102,9 +3063,10 @@
 			}
 		},
 		"node_modules/lucide-svelte": {
-			"version": "0.365.0",
-			"resolved": "https://registry.npmjs.org/lucide-svelte/-/lucide-svelte-0.365.0.tgz",
-			"integrity": "sha512-px3SDEGepR4sICxU38B9VFJJHglZjWnucTlZbbOgySxkAuZRr+b9CHwTDJKA2Xzs7dSjFKaasequwDg0SRIfiA==",
+			"version": "0.372.0",
+			"resolved": "https://registry.npmjs.org/lucide-svelte/-/lucide-svelte-0.372.0.tgz",
+			"integrity": "sha512-LNcsAyrcqB1ZAhwCFOu880KlQgd6YVSW4tVwLaiZ6KSX7ZOBU74I8IkA/zVlI/2V74flCN6kK6rOmdda2NXn5A==",
+			"dev": true,
 			"peerDependencies": {
 				"svelte": "^3 || ^4 || ^5.0.0-next.42"
 			}
@@ -3113,6 +3075,7 @@
 			"version": "0.30.9",
 			"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.9.tgz",
 			"integrity": "sha512-S1+hd+dIrC8EZqKyT9DstTH/0Z+f76kmmvZnkfQVmOpDEF9iVgdYif3Q/pIWHmCoo59bQVGW0kVL3e2nl+9+Sw==",
+			"dev": true,
 			"dependencies": {
 				"@jridgewell/sourcemap-codec": "^1.4.15"
 			},
@@ -3140,7 +3103,8 @@
 		"node_modules/mdn-data": {
 			"version": "2.0.30",
 			"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz",
-			"integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA=="
+			"integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==",
+			"dev": true
 		},
 		"node_modules/mdurl": {
 			"version": "2.0.0",
@@ -3152,6 +3116,7 @@
 			"version": "1.4.1",
 			"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
 			"integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+			"dev": true,
 			"engines": {
 				"node": ">= 8"
 			}
@@ -3160,6 +3125,7 @@
 			"version": "4.0.5",
 			"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
 			"integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
+			"dev": true,
 			"dependencies": {
 				"braces": "^3.0.2",
 				"picomatch": "^2.3.1"
@@ -3221,6 +3187,7 @@
 			"version": "9.0.3",
 			"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
 			"integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==",
+			"dev": true,
 			"dependencies": {
 				"brace-expansion": "^2.0.1"
 			},
@@ -3244,6 +3211,7 @@
 			"version": "7.0.4",
 			"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz",
 			"integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==",
+			"dev": true,
 			"engines": {
 				"node": ">=16 || 14 >=14.17"
 			}
@@ -3298,6 +3266,7 @@
 			"version": "2.7.0",
 			"resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
 			"integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==",
+			"dev": true,
 			"dependencies": {
 				"any-promise": "^1.0.0",
 				"object-assign": "^4.0.1",
@@ -3308,6 +3277,7 @@
 			"version": "5.0.7",
 			"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.0.7.tgz",
 			"integrity": "sha512-oLxFY2gd2IqnjcYyOXD8XGCftpGtZP2AbHbOkthDkvRywH5ayNtPVy9YlOPcHckXzbLTCHpkb7FB+yuxKV13pQ==",
+			"dev": true,
 			"funding": [
 				{
 					"type": "github",
@@ -3347,6 +3317,7 @@
 			"version": "3.0.0",
 			"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
 			"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+			"dev": true,
 			"engines": {
 				"node": ">=0.10.0"
 			}
@@ -3364,6 +3335,7 @@
 			"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,
 			"engines": {
 				"node": ">=0.10.0"
 			}
@@ -3372,6 +3344,7 @@
 			"version": "3.0.0",
 			"resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz",
 			"integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==",
+			"dev": true,
 			"engines": {
 				"node": ">= 6"
 			}
@@ -3436,6 +3409,7 @@
 			"version": "0.0.4",
 			"resolved": "https://registry.npmjs.org/paneforge/-/paneforge-0.0.4.tgz",
 			"integrity": "sha512-0JRqGHLCGU9MfoIv7lAtzUrCRfaHDkE63xQV5OC7MZ19lbXZntZsdZ3+tsWM8iDZfwmhYrQl1cCioUjorI+Apg==",
+			"dev": true,
 			"dependencies": {
 				"nanoid": "^5.0.4"
 			},
@@ -3477,6 +3451,7 @@
 			"version": "3.1.1",
 			"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
 			"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+			"dev": true,
 			"engines": {
 				"node": ">=8"
 			}
@@ -3484,12 +3459,14 @@
 		"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=="
+			"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+			"dev": true
 		},
 		"node_modules/path-scurry": {
 			"version": "1.10.2",
 			"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.2.tgz",
 			"integrity": "sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA==",
+			"dev": true,
 			"dependencies": {
 				"lru-cache": "^10.2.0",
 				"minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
@@ -3505,6 +3482,7 @@
 			"version": "10.2.0",
 			"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz",
 			"integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==",
+			"dev": true,
 			"engines": {
 				"node": "14 || >=16.14"
 			}
@@ -3529,6 +3507,7 @@
 			"version": "3.1.0",
 			"resolved": "https://registry.npmjs.org/periscopic/-/periscopic-3.1.0.tgz",
 			"integrity": "sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==",
+			"dev": true,
 			"dependencies": {
 				"@types/estree": "^1.0.0",
 				"estree-walker": "^3.0.0",
@@ -3538,12 +3517,14 @@
 		"node_modules/picocolors": {
 			"version": "1.0.0",
 			"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
-			"integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ=="
+			"integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
+			"dev": true
 		},
 		"node_modules/picomatch": {
 			"version": "2.3.1",
 			"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
 			"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+			"dev": true,
 			"engines": {
 				"node": ">=8.6"
 			},
@@ -3555,6 +3536,7 @@
 			"version": "2.3.0",
 			"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
 			"integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==",
+			"dev": true,
 			"engines": {
 				"node": ">=0.10.0"
 			}
@@ -3563,6 +3545,7 @@
 			"version": "4.0.6",
 			"resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz",
 			"integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==",
+			"dev": true,
 			"engines": {
 				"node": ">= 6"
 			}
@@ -3615,6 +3598,7 @@
 			"version": "8.4.38",
 			"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz",
 			"integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==",
+			"dev": true,
 			"funding": [
 				{
 					"type": "opencollective",
@@ -3642,6 +3626,7 @@
 			"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,
 			"dependencies": {
 				"postcss-value-parser": "^4.0.0",
 				"read-cache": "^1.0.0",
@@ -3658,6 +3643,7 @@
 			"version": "4.0.1",
 			"resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz",
 			"integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==",
+			"dev": true,
 			"dependencies": {
 				"camelcase-css": "^2.0.1"
 			},
@@ -3711,6 +3697,7 @@
 			"version": "6.0.1",
 			"resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.1.tgz",
 			"integrity": "sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==",
+			"dev": true,
 			"dependencies": {
 				"postcss-selector-parser": "^6.0.11"
 			},
@@ -3771,6 +3758,7 @@
 			"version": "6.0.16",
 			"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.16.tgz",
 			"integrity": "sha512-A0RVJrX+IUkVZbW3ClroRWurercFhieevHB38sr2+l9eUClMqome3LmEmnhlNy+5Mr2EYN6B2Kaw9wYdd+VHiw==",
+			"dev": true,
 			"dependencies": {
 				"cssesc": "^3.0.0",
 				"util-deprecate": "^1.0.2"
@@ -3782,12 +3770,14 @@
 		"node_modules/postcss-value-parser": {
 			"version": "4.2.0",
 			"resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
-			"integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ=="
+			"integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
+			"dev": true
 		},
 		"node_modules/postcss/node_modules/nanoid": {
 			"version": "3.3.7",
 			"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
 			"integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
+			"dev": true,
 			"funding": [
 				{
 					"type": "github",
@@ -3938,6 +3928,7 @@
 			"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",
@@ -3957,6 +3948,7 @@
 			"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,
 			"dependencies": {
 				"pify": "^2.3.0"
 			}
@@ -3965,6 +3957,7 @@
 			"version": "3.6.0",
 			"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
 			"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
+			"dev": true,
 			"dependencies": {
 				"picomatch": "^2.2.1"
 			},
@@ -3972,11 +3965,6 @@
 				"node": ">=8.10.0"
 			}
 		},
-		"node_modules/regenerator-runtime": {
-			"version": "0.14.1",
-			"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
-			"integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw=="
-		},
 		"node_modules/regexparam": {
 			"version": "3.0.0",
 			"resolved": "https://registry.npmjs.org/regexparam/-/regexparam-3.0.0.tgz",
@@ -3990,6 +3978,7 @@
 			"version": "1.22.8",
 			"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
 			"integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==",
+			"dev": true,
 			"dependencies": {
 				"is-core-module": "^2.13.0",
 				"path-parse": "^1.0.7",
@@ -4025,6 +4014,7 @@
 			"version": "1.0.4",
 			"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
 			"integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
+			"dev": true,
 			"engines": {
 				"iojs": ">=1.0.0",
 				"node": ">=0.10.0"
@@ -4140,6 +4130,7 @@
 			"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",
@@ -4250,6 +4241,7 @@
 			"version": "2.0.0",
 			"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
 			"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+			"dev": true,
 			"dependencies": {
 				"shebang-regex": "^3.0.0"
 			},
@@ -4261,6 +4253,7 @@
 			"version": "3.0.0",
 			"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
 			"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+			"dev": true,
 			"engines": {
 				"node": ">=8"
 			}
@@ -4269,6 +4262,7 @@
 			"version": "4.1.0",
 			"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
 			"integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
+			"dev": true,
 			"engines": {
 				"node": ">=14"
 			},
@@ -4328,6 +4322,7 @@
 			"version": "1.2.0",
 			"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz",
 			"integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==",
+			"dev": true,
 			"engines": {
 				"node": ">=0.10.0"
 			}
@@ -4366,6 +4361,7 @@
 			"version": "5.1.2",
 			"resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
 			"integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
+			"dev": true,
 			"dependencies": {
 				"eastasianwidth": "^0.2.0",
 				"emoji-regex": "^9.2.2",
@@ -4383,6 +4379,7 @@
 			"version": "4.2.3",
 			"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
 			"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+			"dev": true,
 			"dependencies": {
 				"emoji-regex": "^8.0.0",
 				"is-fullwidth-code-point": "^3.0.0",
@@ -4395,12 +4392,14 @@
 		"node_modules/string-width-cjs/node_modules/emoji-regex": {
 			"version": "8.0.0",
 			"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
-			"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
+			"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+			"dev": true
 		},
 		"node_modules/string-width/node_modules/ansi-regex": {
 			"version": "6.0.1",
 			"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
 			"integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
+			"dev": true,
 			"engines": {
 				"node": ">=12"
 			},
@@ -4412,6 +4411,7 @@
 			"version": "7.1.0",
 			"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
 			"integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
+			"dev": true,
 			"dependencies": {
 				"ansi-regex": "^6.0.1"
 			},
@@ -4426,6 +4426,7 @@
 			"version": "6.0.1",
 			"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
 			"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+			"dev": true,
 			"dependencies": {
 				"ansi-regex": "^5.0.1"
 			},
@@ -4438,6 +4439,7 @@
 			"version": "6.0.1",
 			"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
 			"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+			"dev": true,
 			"dependencies": {
 				"ansi-regex": "^5.0.1"
 			},
@@ -4473,6 +4475,7 @@
 			"version": "3.35.0",
 			"resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz",
 			"integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==",
+			"dev": true,
 			"dependencies": {
 				"@jridgewell/gen-mapping": "^0.3.2",
 				"commander": "^4.0.0",
@@ -4494,6 +4497,7 @@
 			"version": "10.3.12",
 			"resolved": "https://registry.npmjs.org/glob/-/glob-10.3.12.tgz",
 			"integrity": "sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg==",
+			"dev": true,
 			"dependencies": {
 				"foreground-child": "^3.1.0",
 				"jackspeak": "^2.3.6",
@@ -4527,6 +4531,7 @@
 			"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,
 			"engines": {
 				"node": ">= 0.4"
 			},
@@ -4538,6 +4543,7 @@
 			"version": "4.2.12",
 			"resolved": "https://registry.npmjs.org/svelte/-/svelte-4.2.12.tgz",
 			"integrity": "sha512-d8+wsh5TfPwqVzbm4/HCXC783/KPHV60NvwitJnyTA5lWn1elhXMNWhXGCJ7PwPa8qFUnyJNIyuIRt2mT0WMug==",
+			"dev": true,
 			"dependencies": {
 				"@ampproject/remapping": "^2.2.1",
 				"@jridgewell/sourcemap-codec": "^1.4.15",
@@ -4682,42 +4688,11 @@
 				}
 			}
 		},
-		"node_modules/tabbable": {
-			"version": "6.2.0",
-			"resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz",
-			"integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew=="
-		},
-		"node_modules/tailwind-merge": {
-			"version": "2.2.2",
-			"resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.2.2.tgz",
-			"integrity": "sha512-tWANXsnmJzgw6mQ07nE3aCDkCK4QdT3ThPMCzawoYA2Pws7vSTCvz3Vrjg61jVUGfFZPJzxEP+NimbcW+EdaDw==",
-			"dependencies": {
-				"@babel/runtime": "^7.24.0"
-			},
-			"funding": {
-				"type": "github",
-				"url": "https://github.com/sponsors/dcastil"
-			}
-		},
-		"node_modules/tailwind-variants": {
-			"version": "0.2.1",
-			"resolved": "https://registry.npmjs.org/tailwind-variants/-/tailwind-variants-0.2.1.tgz",
-			"integrity": "sha512-2xmhAf4UIc3PijOUcJPA1LP4AbxhpcHuHM2C26xM0k81r0maAO6uoUSHl3APmvHZcY5cZCY/bYuJdfFa4eGoaw==",
-			"dependencies": {
-				"tailwind-merge": "^2.2.0"
-			},
-			"engines": {
-				"node": ">=16.x",
-				"pnpm": ">=7.x"
-			},
-			"peerDependencies": {
-				"tailwindcss": "*"
-			}
-		},
 		"node_modules/tailwindcss": {
 			"version": "3.4.3",
 			"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.3.tgz",
 			"integrity": "sha512-U7sxQk/n397Bmx4JHbJx/iSOOv5G+II3f1kpLpY2QeUv5DcPdcTsYLlusZfq1NthHS1c1cZoyFmmkex1rzke0A==",
+			"dev": true,
 			"dependencies": {
 				"@alloc/quick-lru": "^5.2.0",
 				"arg": "^5.0.2",
@@ -4754,6 +4729,7 @@
 			"version": "2.1.0",
 			"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz",
 			"integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==",
+			"dev": true,
 			"engines": {
 				"node": ">=10"
 			}
@@ -4762,6 +4738,7 @@
 			"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",
@@ -4796,6 +4773,7 @@
 			"version": "3.1.1",
 			"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.1.tgz",
 			"integrity": "sha512-O18pf7nyvHTckunPWCV1XUNXU1piu01y2b7ATJ0ppkUkk8ocqVWBrYjJBCwHDjD/ZWcfyrA0P4gKhzWGi5EINQ==",
+			"dev": true,
 			"engines": {
 				"node": ">=14"
 			},
@@ -4813,6 +4791,7 @@
 			"version": "3.3.1",
 			"resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",
 			"integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==",
+			"dev": true,
 			"dependencies": {
 				"any-promise": "^1.0.0"
 			}
@@ -4821,6 +4800,7 @@
 			"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,
 			"dependencies": {
 				"thenify": ">= 3.1.0 < 4"
 			},
@@ -4842,6 +4822,7 @@
 			"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,
 			"dependencies": {
 				"is-number": "^7.0.0"
 			},
@@ -4873,12 +4854,14 @@
 		"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=="
+			"integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==",
+			"dev": true
 		},
 		"node_modules/tslib": {
 			"version": "2.6.2",
 			"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
-			"integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q=="
+			"integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==",
+			"dev": true
 		},
 		"node_modules/type-check": {
 			"version": "0.4.0",
@@ -4985,7 +4968,8 @@
 		"node_modules/util-deprecate": {
 			"version": "1.0.2",
 			"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
-			"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
+			"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
+			"dev": true
 		},
 		"node_modules/vite": {
 			"version": "5.2.8",
@@ -5466,6 +5450,7 @@
 			"version": "2.0.2",
 			"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
 			"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+			"dev": true,
 			"dependencies": {
 				"isexe": "^2.0.0"
 			},
@@ -5986,6 +5971,7 @@
 			"version": "8.1.0",
 			"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
 			"integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
+			"dev": true,
 			"dependencies": {
 				"ansi-styles": "^6.1.0",
 				"string-width": "^5.0.1",
@@ -6003,6 +5989,7 @@
 			"version": "7.0.0",
 			"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
 			"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+			"dev": true,
 			"dependencies": {
 				"ansi-styles": "^4.0.0",
 				"string-width": "^4.1.0",
@@ -6018,12 +6005,14 @@
 		"node_modules/wrap-ansi-cjs/node_modules/emoji-regex": {
 			"version": "8.0.0",
 			"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
-			"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
+			"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+			"dev": true
 		},
 		"node_modules/wrap-ansi-cjs/node_modules/string-width": {
 			"version": "4.2.3",
 			"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
 			"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+			"dev": true,
 			"dependencies": {
 				"emoji-regex": "^8.0.0",
 				"is-fullwidth-code-point": "^3.0.0",
@@ -6037,6 +6026,7 @@
 			"version": "6.0.1",
 			"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
 			"integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
+			"dev": true,
 			"engines": {
 				"node": ">=12"
 			},
@@ -6048,6 +6038,7 @@
 			"version": "6.2.1",
 			"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
 			"integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
+			"dev": true,
 			"engines": {
 				"node": ">=12"
 			},
@@ -6059,6 +6050,7 @@
 			"version": "7.1.0",
 			"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
 			"integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
+			"dev": true,
 			"dependencies": {
 				"ansi-regex": "^6.0.1"
 			},
@@ -6114,6 +6106,7 @@
 			"version": "2.4.1",
 			"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.1.tgz",
 			"integrity": "sha512-pIXzoImaqmfOrL7teGUBt/T7ZDnyeGBWyXQBvOVhLkWLN37GXv8NMLK406UY6dS51JfcQHsmcW5cJ441bHg6Lg==",
+			"dev": true,
 			"bin": {
 				"yaml": "bin.mjs"
 			},
diff --git a/package.json b/package.json
index 6eb2d5d..9d7dcbe 100644
--- a/package.json
+++ b/package.json
@@ -27,7 +27,9 @@
 		"eslint-config-prettier": "^9.1.0",
 		"eslint-plugin-svelte": "^2.35.1",
 		"highlight.js": "^11.9.0",
+		"lucide-svelte": "^0.372.0",
 		"markdown-it": "^14.1.0",
+		"paneforge": "^0.0.4",
 		"postcss": "^8.4.32",
 		"postcss-load-config": "^5.0.2",
 		"prettier": "^3.1.1",
@@ -41,13 +43,5 @@
 		"typescript": "^5.0.0",
 		"vite": "^5.0.3"
 	},
-	"type": "module",
-	"dependencies": {
-		"bits-ui": "^0.21.2",
-		"clsx": "^2.1.0",
-		"lucide-svelte": "^0.365.0",
-		"paneforge": "^0.0.4",
-		"tailwind-merge": "^2.2.2",
-		"tailwind-variants": "^0.2.1"
-	}
+	"type": "module"
 }
diff --git a/src/lib/components/Badge.svelte b/src/lib/components/Badge.svelte
new file mode 100644
index 0000000..a29abf6
--- /dev/null
+++ b/src/lib/components/Badge.svelte
@@ -0,0 +1,28 @@
+<script lang="ts">
+	let className: string | undefined | null = undefined;
+	export let href: string | undefined = undefined;
+	export let variant: 'positive' | 'warning';
+	export { className as class };
+</script>
+
+<svelte:element
+	this={href ? 'a' : 'span'}
+	class="badge badge--{variant} {className}"
+	{href}
+>
+	<slot />
+</svelte:element>
+
+<style lang="scss">
+	.badge {
+		@apply inline-flex select-none items-center rounded-lg border border-transparent px-2.5 py-0.5 text-xs font-semibold capitalize text-primary-foreground transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2;
+
+		&--positive {
+			@apply bg-emerald-600;
+		}
+
+		&--warning {
+			@apply bg-yellow-600;
+		}
+	}
+</style>
diff --git a/src/lib/components/Button.svelte b/src/lib/components/Button.svelte
new file mode 100644
index 0000000..683df77
--- /dev/null
+++ b/src/lib/components/Button.svelte
@@ -0,0 +1,83 @@
+<script lang="ts">
+	let className: string | undefined = undefined;
+	export { className as class };
+	export let variant:
+		| 'default'
+		| 'destructive'
+		| 'outline'
+		| 'secondary'
+		| 'ghost'
+		| 'link'
+		| 'icon'
+		| undefined = 'default';
+	export let size: 'default' | 'icon' | 'link' | undefined = 'default';
+	export let href: string | undefined = undefined;
+</script>
+
+{#if href}
+	<a
+		{...$$restProps}
+		{href}
+		class="
+			button button--{variant}
+			button--size-{size}
+			{className}
+		"
+		on:click
+	>
+		<slot />
+	</a>
+{:else}
+	<button
+		{...$$restProps}
+		class="button button--{variant} button--size-{size} {className}"
+		type="button"
+		on:click
+	>
+		<slot />
+	</button>
+{/if}
+
+<style lang="scss">
+	.button {
+		@apply inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium text-foreground ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50;
+
+		&--default {
+			@apply bg-primary text-primary-foreground hover:bg-primary/90;
+		}
+
+		&--destructive {
+			@apply bg-destructive text-destructive-foreground hover:bg-destructive/90;
+		}
+
+		&--outline {
+			@apply border border-input bg-background hover:bg-accent hover:text-accent-foreground;
+		}
+
+		&--secondary {
+			@apply bg-secondary text-secondary-foreground hover:bg-secondary/80;
+		}
+
+		&--ghost {
+			@apply hover:bg-accent hover:text-accent-foreground;
+		}
+
+		&--link {
+			@apply underline underline-offset-4 hover:text-neutral-500;
+		}
+
+		&--icon {
+			@apply opacity-25 hover:opacity-100;
+		}
+
+		&--size {
+			&-default {
+				@apply h-10 px-4 py-2;
+			}
+
+			&-icon {
+				@apply h-10 w-10;
+			}
+		}
+	}
+</style>
diff --git a/src/lib/components/Field.svelte b/src/lib/components/Field.svelte
new file mode 100644
index 0000000..fa4491f
--- /dev/null
+++ b/src/lib/components/Field.svelte
@@ -0,0 +1,20 @@
+<script lang="ts">
+	export let name: string;
+</script>
+
+<label class="label" for={name}>
+	<p class="title">
+		<slot name="title"></slot>
+	</p>
+	<slot></slot>
+</label>
+
+<style lang="scss">
+	.label {
+		@apply flex flex-col gap-y-3;
+	}
+
+	.title {
+		@apply flex items-center gap-x-2 text-sm font-medium leading-none;
+	}
+</style>
diff --git a/src/lib/components/FieldModels.svelte b/src/lib/components/FieldModels.svelte
new file mode 100644
index 0000000..24c9098
--- /dev/null
+++ b/src/lib/components/FieldModels.svelte
@@ -0,0 +1,27 @@
+<script lang="ts">
+	import type { OllamaModel } from "$lib/ollama";
+	import Field from "./Field.svelte";
+
+	export let models: OllamaModel[];
+  export let value: string;
+</script>
+
+<Field name="model">
+	<span slot="title">Model</span>
+	<select
+		id="model"
+		class="select"
+		disabled={!models.length}
+		bind:value
+	>
+		{#each models as model}
+			<option value={model.name}>{model.name}</option>
+		{/each}
+	</select>
+</Field>
+
+<style lang="scss">
+	.select {
+		@apply flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50;
+	}
+</style>
diff --git a/src/lib/components/Separator.svelte b/src/lib/components/Separator.svelte
new file mode 100644
index 0000000..ef131d6
--- /dev/null
+++ b/src/lib/components/Separator.svelte
@@ -0,0 +1,19 @@
+<script lang="ts">
+	export let orientation: 'horizontal' | 'vertical' | undefined = 'horizontal';
+</script>
+
+<hr class="hr hr--{orientation}" {...$$restProps}>
+
+<style lang="scss">
+	.hr {
+		@apply shrink-0 bg-border m-0;
+
+		&--horizontal {
+			@apply w-full h-[1px];
+		}
+
+		&--vertical {
+			@apply h-full w-[1px];
+		}
+	}
+</style>
diff --git a/src/lib/components/ui/badge/badge.svelte b/src/lib/components/ui/badge/badge.svelte
deleted file mode 100644
index e8817f4..0000000
--- a/src/lib/components/ui/badge/badge.svelte
+++ /dev/null
@@ -1,18 +0,0 @@
-<script lang="ts">
-	import { type Variant, badgeVariants } from "./index.js";
-	import { cn } from "$lib/utils.js";
-
-	let className: string | undefined | null = undefined;
-	export let href: string | undefined = undefined;
-	export let variant: Variant = "default";
-	export { className as class };
-</script>
-
-<svelte:element
-	this={href ? "a" : "span"}
-	{href}
-	class={cn(badgeVariants({ variant, className }))}
-	{...$$restProps}
->
-	<slot />
-</svelte:element>
diff --git a/src/lib/components/ui/badge/index.ts b/src/lib/components/ui/badge/index.ts
deleted file mode 100644
index 6cb8a5d..0000000
--- a/src/lib/components/ui/badge/index.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-import { type VariantProps, tv } from "tailwind-variants";
-export { default as Badge } from "./badge.svelte";
-
-export const badgeVariants = tv({
-	base: "inline-flex select-none items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
-	variants: {
-		variant: {
-			default: "border-transparent bg-primary text-primary-foreground hover:bg-primary/80",
-			secondary:
-				"border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
-			destructive:
-				"border-transparent bg-destructive text-destructive-foreground",
-			warning: "border-transparent bg-amber-600 text-destructive-foreground",
-			positive: "border-transparent bg-emerald-600 text-primary-foreground",
-			outline: "text-foreground",
-		},
-	},
-	defaultVariants: {
-		variant: "default",
-	},
-});
-
-export type Variant = VariantProps<typeof badgeVariants>["variant"];
diff --git a/src/lib/components/ui/button/button.svelte b/src/lib/components/ui/button/button.svelte
deleted file mode 100644
index 86827f3..0000000
--- a/src/lib/components/ui/button/button.svelte
+++ /dev/null
@@ -1,25 +0,0 @@
-<script lang="ts">
-	import { Button as ButtonPrimitive } from "bits-ui";
-	import { type Events, type Props, buttonVariants } from "./index.js";
-	import { cn } from "$lib/utils.js";
-
-	type $$Props = Props;
-	type $$Events = Events;
-
-	let className: $$Props["class"] = undefined;
-	export let variant: $$Props["variant"] = "default";
-	export let size: $$Props["size"] = "default";
-	export let builders: $$Props["builders"] = [];
-	export { className as class };
-</script>
-
-<ButtonPrimitive.Root
-	{builders}
-	class={cn(buttonVariants({ variant, size, className }))}
-	type="button"
-	{...$$restProps}
-	on:click
-	on:keydown
->
-	<slot />
-</ButtonPrimitive.Root>
diff --git a/src/lib/components/ui/button/index.ts b/src/lib/components/ui/button/index.ts
deleted file mode 100644
index 74756fa..0000000
--- a/src/lib/components/ui/button/index.ts
+++ /dev/null
@@ -1,49 +0,0 @@
-import { type VariantProps, tv } from "tailwind-variants";
-import type { Button as ButtonPrimitive } from "bits-ui";
-import Root from "./button.svelte";
-
-const buttonVariants = tv({
-	base: "inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 text-foreground",
-	variants: {
-		variant: {
-			default: "bg-primary text-primary-foreground hover:bg-primary/90",
-			destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
-			outline:
-				"border border-input bg-background hover:bg-accent hover:text-accent-foreground",
-			secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
-			ghost: "hover:bg-accent hover:text-accent-foreground",
-			link: "text-primary underline-offset-4 hover:underline",
-		},
-		size: {
-			default: "h-10 px-4 py-2",
-			sm: "h-9 rounded-md px-3",
-			lg: "h-11 rounded-md px-8",
-			icon: "h-10 w-10",
-		},
-	},
-	defaultVariants: {
-		variant: "default",
-		size: "default",
-	},
-});
-
-type Variant = VariantProps<typeof buttonVariants>["variant"];
-type Size = VariantProps<typeof buttonVariants>["size"];
-
-type Props = ButtonPrimitive.Props & {
-	variant?: Variant;
-	size?: Size;
-};
-
-type Events = ButtonPrimitive.Events;
-
-export {
-	Root,
-	type Props,
-	type Events,
-	//
-	Root as Button,
-	type Props as ButtonProps,
-	type Events as ButtonEvents,
-	buttonVariants,
-};
diff --git a/src/lib/components/ui/input/index.ts b/src/lib/components/ui/input/index.ts
deleted file mode 100644
index 69804e4..0000000
--- a/src/lib/components/ui/input/index.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-import Root from "./input.svelte";
-
-export type FormInputEvent<T extends Event = Event> = T & {
-	currentTarget: EventTarget & HTMLInputElement;
-};
-export type InputEvents = {
-	blur: FormInputEvent<FocusEvent>;
-	change: FormInputEvent<Event>;
-	click: FormInputEvent<MouseEvent>;
-	focus: FormInputEvent<FocusEvent>;
-	focusin: FormInputEvent<FocusEvent>;
-	focusout: FormInputEvent<FocusEvent>;
-	keydown: FormInputEvent<KeyboardEvent>;
-	keypress: FormInputEvent<KeyboardEvent>;
-	keyup: FormInputEvent<KeyboardEvent>;
-	mouseover: FormInputEvent<MouseEvent>;
-	mouseenter: FormInputEvent<MouseEvent>;
-	mouseleave: FormInputEvent<MouseEvent>;
-	paste: FormInputEvent<ClipboardEvent>;
-	input: FormInputEvent<InputEvent>;
-	wheel: FormInputEvent<WheelEvent>;
-};
-
-export {
-	Root,
-	//
-	Root as Input,
-};
diff --git a/src/lib/components/ui/input/input.svelte b/src/lib/components/ui/input/input.svelte
deleted file mode 100644
index 28f8fb9..0000000
--- a/src/lib/components/ui/input/input.svelte
+++ /dev/null
@@ -1,41 +0,0 @@
-<script lang="ts">
-	import type { HTMLInputAttributes } from "svelte/elements";
-	import type { InputEvents } from "./index.js";
-	import { cn } from "$lib/utils.js";
-
-	type $$Props = HTMLInputAttributes;
-	type $$Events = InputEvents;
-
-	let className: $$Props["class"] = undefined;
-	export let value: $$Props["value"] = undefined;
-	export { className as class };
-
-	// Workaround for https://github.com/sveltejs/svelte/issues/9305
-	// Fixed in Svelte 5, but not backported to 4.x.
-	export let readonly: $$Props["readonly"] = undefined;
-</script>
-
-<input
-	class={cn(
-		"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
-		className
-	)}
-	bind:value
-	{readonly}
-	on:blur
-	on:change
-	on:click
-	on:focus
-	on:focusin
-	on:focusout
-	on:keydown
-	on:keypress
-	on:keyup
-	on:mouseover
-	on:mouseenter
-	on:mouseleave
-	on:paste
-	on:input
-	on:wheel
-	{...$$restProps}
-/>
diff --git a/src/lib/components/ui/label/index.ts b/src/lib/components/ui/label/index.ts
deleted file mode 100644
index 8bfca0b..0000000
--- a/src/lib/components/ui/label/index.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import Root from "./label.svelte";
-
-export {
-	Root,
-	//
-	Root as Label,
-};
diff --git a/src/lib/components/ui/label/label.svelte b/src/lib/components/ui/label/label.svelte
deleted file mode 100644
index 2a7d479..0000000
--- a/src/lib/components/ui/label/label.svelte
+++ /dev/null
@@ -1,21 +0,0 @@
-<script lang="ts">
-	import { Label as LabelPrimitive } from "bits-ui";
-	import { cn } from "$lib/utils.js";
-
-	type $$Props = LabelPrimitive.Props;
-	type $$Events = LabelPrimitive.Events;
-
-	let className: $$Props["class"] = undefined;
-	export { className as class };
-</script>
-
-<LabelPrimitive.Root
-	class={cn(
-		"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
-		className
-	)}
-	{...$$restProps}
-	on:mousedown
->
-	<slot />
-</LabelPrimitive.Root>
diff --git a/src/lib/components/ui/resizable/index.ts b/src/lib/components/ui/resizable/index.ts
deleted file mode 100644
index 2e37f11..0000000
--- a/src/lib/components/ui/resizable/index.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-import { Pane } from "paneforge";
-import Handle from "./resizable-handle.svelte";
-import PaneGroup from "./resizable-pane-group.svelte";
-
-export {
-	PaneGroup,
-	Pane,
-	Handle,
-	//
-	PaneGroup as ResizablePaneGroup,
-	Pane as ResizablePane,
-	Handle as ResizableHandle,
-};
diff --git a/src/lib/components/ui/resizable/resizable-handle.svelte b/src/lib/components/ui/resizable/resizable-handle.svelte
deleted file mode 100644
index 46e2bba..0000000
--- a/src/lib/components/ui/resizable/resizable-handle.svelte
+++ /dev/null
@@ -1,28 +0,0 @@
-<script lang="ts">
-	import GripVertical from "lucide-svelte/icons/grip-vertical";
-	import * as ResizablePrimitive from "paneforge";
-	import { cn } from "$lib/utils.js";
-
-	type $$Props = ResizablePrimitive.PaneResizerProps & {
-		withHandle?: boolean;
-	};
-
-	export let withHandle: $$Props["withHandle"] = false;
-	export let el: $$Props["el"] = undefined;
-	let className: $$Props["class"] = undefined;
-	export { className as class };
-</script>
-
-<ResizablePrimitive.PaneResizer
-	bind:el
-	class={cn(
-		"relative flex w-px items-center justify-center bg-border after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-1 data-[direction=vertical]:h-px data-[direction=vertical]:w-full data-[direction=vertical]:after:left-0 data-[direction=vertical]:after:h-1 data-[direction=vertical]:after:w-full data-[direction=vertical]:after:-translate-y-1/2 data-[direction=vertical]:after:translate-x-0 [&[data-direction=vertical]>div]:rotate-90",
-		className
-	)}
->
-	{#if withHandle}
-		<div class="z-10 flex h-4 w-3 items-center justify-center rounded-sm border bg-border">
-			<GripVertical class="h-2.5 w-2.5" />
-		</div>
-	{/if}
-</ResizablePrimitive.PaneResizer>
diff --git a/src/lib/components/ui/resizable/resizable-pane-group.svelte b/src/lib/components/ui/resizable/resizable-pane-group.svelte
deleted file mode 100644
index 2692794..0000000
--- a/src/lib/components/ui/resizable/resizable-pane-group.svelte
+++ /dev/null
@@ -1,22 +0,0 @@
-<script lang="ts">
-	import * as ResizablePrimitive from "paneforge";
-	import { cn } from "$lib/utils.js";
-
-	type $$Props = ResizablePrimitive.PaneGroupProps;
-
-	let className: $$Props["class"] = undefined;
-	export let direction: $$Props["direction"];
-	export let paneGroup: $$Props["paneGroup"] = undefined;
-	export let el: $$Props["el"] = undefined;
-	export { className as class };
-</script>
-
-<ResizablePrimitive.PaneGroup
-	bind:el
-	bind:paneGroup
-	{direction}
-	class={cn("flex h-full w-full data-[direction=vertical]:flex-col", className)}
-	{...$$restProps}
->
-	<slot />
-</ResizablePrimitive.PaneGroup>
diff --git a/src/lib/components/ui/select/index.ts b/src/lib/components/ui/select/index.ts
deleted file mode 100644
index 327541c..0000000
--- a/src/lib/components/ui/select/index.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-import { Select as SelectPrimitive } from "bits-ui";
-
-import Label from "./select-label.svelte";
-import Item from "./select-item.svelte";
-import Content from "./select-content.svelte";
-import Trigger from "./select-trigger.svelte";
-import Separator from "./select-separator.svelte";
-
-const Root = SelectPrimitive.Root;
-const Group = SelectPrimitive.Group;
-const Input = SelectPrimitive.Input;
-const Value = SelectPrimitive.Value;
-
-export {
-	Root,
-	Group,
-	Input,
-	Label,
-	Item,
-	Value,
-	Content,
-	Trigger,
-	Separator,
-	//
-	Root as Select,
-	Group as SelectGroup,
-	Input as SelectInput,
-	Label as SelectLabel,
-	Item as SelectItem,
-	Value as SelectValue,
-	Content as SelectContent,
-	Trigger as SelectTrigger,
-	Separator as SelectSeparator,
-};
diff --git a/src/lib/components/ui/select/select-content.svelte b/src/lib/components/ui/select/select-content.svelte
deleted file mode 100644
index 93d758e..0000000
--- a/src/lib/components/ui/select/select-content.svelte
+++ /dev/null
@@ -1,39 +0,0 @@
-<script lang="ts">
-	import { Select as SelectPrimitive } from "bits-ui";
-	import { scale } from "svelte/transition";
-	import { cn, flyAndScale } from "$lib/utils.js";
-
-	type $$Props = SelectPrimitive.ContentProps;
-	type $$Events = SelectPrimitive.ContentEvents;
-
-	export let sideOffset: $$Props["sideOffset"] = 4;
-	export let inTransition: $$Props["inTransition"] = flyAndScale;
-	export let inTransitionConfig: $$Props["inTransitionConfig"] = undefined;
-	export let outTransition: $$Props["outTransition"] = scale;
-	export let outTransitionConfig: $$Props["outTransitionConfig"] = {
-		start: 0.95,
-		opacity: 0,
-		duration: 50,
-	};
-
-	let className: $$Props["class"] = undefined;
-	export { className as class };
-</script>
-
-<SelectPrimitive.Content
-	{inTransition}
-	{inTransitionConfig}
-	{outTransition}
-	{outTransitionConfig}
-	{sideOffset}
-	class={cn(
-		"relative z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md outline-none",
-		className
-	)}
-	{...$$restProps}
-	on:keydown
->
-	<div class="w-full p-1">
-		<slot />
-	</div>
-</SelectPrimitive.Content>
diff --git a/src/lib/components/ui/select/select-item.svelte b/src/lib/components/ui/select/select-item.svelte
deleted file mode 100644
index 2cd00a7..0000000
--- a/src/lib/components/ui/select/select-item.svelte
+++ /dev/null
@@ -1,40 +0,0 @@
-<script lang="ts">
-	import Check from "lucide-svelte/icons/check";
-	import { Select as SelectPrimitive } from "bits-ui";
-	import { cn } from "$lib/utils.js";
-
-	type $$Props = SelectPrimitive.ItemProps;
-	type $$Events = SelectPrimitive.ItemEvents;
-
-	let className: $$Props["class"] = undefined;
-	export let value: $$Props["value"];
-	export let label: $$Props["label"] = undefined;
-	export let disabled: $$Props["disabled"] = undefined;
-	export { className as class };
-</script>
-
-<SelectPrimitive.Item
-	{value}
-	{disabled}
-	{label}
-	class={cn(
-		"relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none data-[disabled]:pointer-events-none data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground data-[disabled]:opacity-50",
-		className
-	)}
-	{...$$restProps}
-	on:click
-	on:keydown
-	on:focusin
-	on:focusout
-	on:pointerleave
-	on:pointermove
->
-	<span class="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
-		<SelectPrimitive.ItemIndicator>
-			<Check class="h-4 w-4" />
-		</SelectPrimitive.ItemIndicator>
-	</span>
-	<slot>
-		{label || value}
-	</slot>
-</SelectPrimitive.Item>
diff --git a/src/lib/components/ui/select/select-label.svelte b/src/lib/components/ui/select/select-label.svelte
deleted file mode 100644
index d966450..0000000
--- a/src/lib/components/ui/select/select-label.svelte
+++ /dev/null
@@ -1,16 +0,0 @@
-<script lang="ts">
-	import { Select as SelectPrimitive } from "bits-ui";
-	import { cn } from "$lib/utils.js";
-
-	type $$Props = SelectPrimitive.LabelProps;
-
-	let className: $$Props["class"] = undefined;
-	export { className as class };
-</script>
-
-<SelectPrimitive.Label
-	class={cn("py-1.5 pl-8 pr-2 text-sm font-semibold", className)}
-	{...$$restProps}
->
-	<slot />
-</SelectPrimitive.Label>
diff --git a/src/lib/components/ui/select/select-separator.svelte b/src/lib/components/ui/select/select-separator.svelte
deleted file mode 100644
index bc518e6..0000000
--- a/src/lib/components/ui/select/select-separator.svelte
+++ /dev/null
@@ -1,11 +0,0 @@
-<script lang="ts">
-	import { Select as SelectPrimitive } from "bits-ui";
-	import { cn } from "$lib/utils.js";
-
-	type $$Props = SelectPrimitive.SeparatorProps;
-
-	let className: $$Props["class"] = undefined;
-	export { className as class };
-</script>
-
-<SelectPrimitive.Separator class={cn("-mx-1 my-1 h-px bg-muted", className)} {...$$restProps} />
diff --git a/src/lib/components/ui/select/select-trigger.svelte b/src/lib/components/ui/select/select-trigger.svelte
deleted file mode 100644
index ed0bc7e..0000000
--- a/src/lib/components/ui/select/select-trigger.svelte
+++ /dev/null
@@ -1,27 +0,0 @@
-<script lang="ts">
-	import { Select as SelectPrimitive } from "bits-ui";
-	import ChevronDown from "lucide-svelte/icons/chevron-down";
-	import { cn } from "$lib/utils.js";
-
-	type $$Props = SelectPrimitive.TriggerProps;
-	type $$Events = SelectPrimitive.TriggerEvents;
-
-	let className: $$Props["class"] = undefined;
-	export { className as class };
-</script>
-
-<SelectPrimitive.Trigger
-	class={cn(
-		"flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",
-		className
-	)}
-	{...$$restProps}
-	let:builder
-	on:click
-	on:keydown
->
-	<slot {builder} />
-	<div>
-		<ChevronDown class="h-4 w-4 opacity-50" />
-	</div>
-</SelectPrimitive.Trigger>
diff --git a/src/lib/components/ui/separator/index.ts b/src/lib/components/ui/separator/index.ts
deleted file mode 100644
index 82442d2..0000000
--- a/src/lib/components/ui/separator/index.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import Root from "./separator.svelte";
-
-export {
-	Root,
-	//
-	Root as Separator,
-};
diff --git a/src/lib/components/ui/separator/separator.svelte b/src/lib/components/ui/separator/separator.svelte
deleted file mode 100644
index be3843a..0000000
--- a/src/lib/components/ui/separator/separator.svelte
+++ /dev/null
@@ -1,22 +0,0 @@
-<script lang="ts">
-	import { Separator as SeparatorPrimitive } from "bits-ui";
-	import { cn } from "$lib/utils.js";
-
-	type $$Props = SeparatorPrimitive.Props;
-
-	let className: $$Props["class"] = undefined;
-	export let orientation: $$Props["orientation"] = "horizontal";
-	export let decorative: $$Props["decorative"] = undefined;
-	export { className as class };
-</script>
-
-<SeparatorPrimitive.Root
-	class={cn(
-		"shrink-0 bg-border",
-		orientation === "horizontal" ? "h-[1px] w-full" : "h-full w-[1px]",
-		className
-	)}
-	{orientation}
-	{decorative}
-	{...$$restProps}
-/>
diff --git a/src/lib/components/ui/textarea/index.ts b/src/lib/components/ui/textarea/index.ts
deleted file mode 100644
index 6eb6ba3..0000000
--- a/src/lib/components/ui/textarea/index.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-import Root from "./textarea.svelte";
-
-type FormTextareaEvent<T extends Event = Event> = T & {
-	currentTarget: EventTarget & HTMLTextAreaElement;
-};
-
-type TextareaEvents = {
-	blur: FormTextareaEvent<FocusEvent>;
-	change: FormTextareaEvent<Event>;
-	click: FormTextareaEvent<MouseEvent>;
-	focus: FormTextareaEvent<FocusEvent>;
-	keydown: FormTextareaEvent<KeyboardEvent>;
-	keypress: FormTextareaEvent<KeyboardEvent>;
-	keyup: FormTextareaEvent<KeyboardEvent>;
-	mouseover: FormTextareaEvent<MouseEvent>;
-	mouseenter: FormTextareaEvent<MouseEvent>;
-	mouseleave: FormTextareaEvent<MouseEvent>;
-	paste: FormTextareaEvent<ClipboardEvent>;
-	input: FormTextareaEvent<InputEvent>;
-};
-
-export {
-	Root,
-	//
-	Root as Textarea,
-	type TextareaEvents,
-	type FormTextareaEvent,
-};
diff --git a/src/lib/components/ui/textarea/textarea.svelte b/src/lib/components/ui/textarea/textarea.svelte
deleted file mode 100644
index 0c3d9be..0000000
--- a/src/lib/components/ui/textarea/textarea.svelte
+++ /dev/null
@@ -1,36 +0,0 @@
-<script lang="ts">
-	import type { HTMLTextareaAttributes } from "svelte/elements";
-	import { cn } from "$lib/utils.js";
-
-	type $$Props = HTMLTextareaAttributes;
-
-	let className: $$Props["class"] = undefined;
-	export let value: $$Props["value"] = undefined;
-	export { className as class };
-
-	// Workaround for https://github.com/sveltejs/svelte/issues/9305
-	// Fixed in Svelte 5, but not backported to 4.x.
-	export let readonly: $$Props["readonly"] = undefined;
-</script>
-
-<textarea
-	class={cn(
-		"flex min-h-[80px] w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
-		className
-	)}
-	bind:value
-	{readonly}
-	on:blur
-	on:change
-	on:click
-	on:focus
-	on:keydown
-	on:keypress
-	on:keyup
-	on:mouseover
-	on:mouseenter
-	on:mouseleave
-	on:paste
-	on:input
-	{...$$restProps}
-/>
diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte
index 0abb27c..fddddb0 100644
--- a/src/routes/+layout.svelte
+++ b/src/routes/+layout.svelte
@@ -5,8 +5,8 @@
 
 	import '../app.pcss';
 	import Settings from 'lucide-svelte/icons/settings';
-	import Button from '$lib/components/ui/button/button.svelte';
-	import Separator from '$lib/components/ui/separator/separator.svelte';
+	import Button from '$lib/components/Button.svelte';
+	import Separator from '$lib/components/Separator.svelte';
 
 	import { sessionsStore } from '$lib/store';
 
@@ -39,7 +39,7 @@
 				class="w-full"
 				variant="outline"
 				href={`/${newSessionId}`}
-				on:click={() => createNewSession()}
+				on:click={createNewSession}
 			>
 				New session
 			</Button>
@@ -87,7 +87,7 @@
 	<slot />
 </div>
 
-<style>
+<style lang="scss">
 	.hollama-wordmark {
 		width: max-content;
 		height: 7ch;
diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte
index 180d395..b4483d3 100644
--- a/src/routes/+page.svelte
+++ b/src/routes/+page.svelte
@@ -1,15 +1,14 @@
 <script lang="ts">
-	import * as Select from '$lib/components/ui/select';
-	import Input from '$lib/components/ui/input/input.svelte';
-	import Label from '$lib/components/ui/label/label.svelte';
-
-	import { settingsStore } from '$lib/store';
-
 	import { onMount } from 'svelte';
 	import { slide } from 'svelte/transition';
-	import Badge from '$lib/components/ui/badge/badge.svelte';
-	import Separator from '$lib/components/ui/separator/separator.svelte';
+
+	import Badge from '$lib/components/Badge.svelte';
+	import Button from '$lib/components/Button.svelte';
+	import Separator from '$lib/components/Separator.svelte';
+	import FieldModels from '$lib/components/FieldModels.svelte';
+	import Field from '$lib/components/Field.svelte';
 	import type { OllamaTagResponse } from '$lib/ollama';
+	import { settingsStore } from '$lib/store';
 
 	export let ollamaURL: URL | null = null;
 	let ollamaTagResponse: OllamaTagResponse | null = null;
@@ -24,21 +23,12 @@
 		ollamaModel: ollamaModel.value
 	});
 
-	// HACK: triggers function when selecting all and pressing the delete
-	// key on the Ollama server input.
-	$: typeof ollamaServer === 'string' && getModelsList();
-
-	interface Model {
-		name: string;
-		modified_at: string;
-		size: number;
-		digest: string;
-	}
-
 	async function getModelsList(): Promise<void> {
 		try {
+			if (!ollamaServer) throw new Error('No server provided');
+
 			const response = await fetch(`${ollamaServer}/api/tags`);
-			const data = await response.json() as OllamaTagResponse;
+			const data = (await response.json()) as OllamaTagResponse;
 			ollamaTagResponse = data;
 			serverStatus = 'connected';
 		} catch {
@@ -47,7 +37,7 @@
 		}
 	}
 
-	onMount(() => {
+	onMount(async () => {
 		// Get the current URL
 		ollamaURL = new URL(window.location.href);
 		if (ollamaURL.port) {
@@ -55,84 +45,50 @@
 				`${ollamaURL.protocol}//${ollamaURL.hostname}${ollamaURL.pathname}${ollamaURL.search}${ollamaURL.hash}`
 			);
 		}
-	});
 
-	// Styles
-	const _help = `
-		flex
-		flex-col
-		gap-y-3
-	`;
-
-	const _pHelp = `
-		text-sm
-		text-neutral-500
-	`;
-
-	const _code = `
-		text-neutral-800
-	`;
-
-	const _pAbout = `
-		text-sm
-		text-neutral-800
-	`;
-
-	const _container = `
-		flex
-		flex-col
-		gap-y-3
-		mt-6
-		mb-6
-	`;
-
-	const _label = `
-		flex
-		items-center
-		gap-x-2
-	`;
-
-	const _a = `
-		underline
-		underline-offset-4
-		hover:text-neutral-600
-	`;
+		await getModelsList();
+	});
 </script>
 
 <div class="flex w-full flex-col bg-secondary">
 	<div class="justify-content-center m-auto max-w-[40ch] p-6">
-		<div class={_container}>
-			<Label class={_label}>
-				Server
-				<Badge
-					class="capitalize"
-					variant={serverStatus === 'disconnected' ? 'warning' : 'positive'}
-				>
-					{serverStatus}
-				</Badge>
-			</Label>
-			<Input bind:value={ollamaServer} placeholder={DETAULT_OLLAMA_SERVER} />
+		<div class="container">
+			<Field name="server">
+				<span slot="title">
+					Server
+					<Badge variant={serverStatus === 'disconnected' ? 'warning' : 'positive'}>
+						{serverStatus}
+					</Badge>
+				</span>
+				<input
+					placeholder={DETAULT_OLLAMA_SERVER}
+					class="input"
+					id="server"
+					bind:value={ollamaServer}
+					on:keyup={getModelsList}
+				/>
+			</Field>
 
 			{#if ollamaURL && serverStatus === 'disconnected'}
-				<div transition:slide class={_help}>
-					<p class={_pHelp}>
+				<div transition:slide class="help">
+					<p class="p">
 						Needs to allow connections from
-						<code class={_code}>{ollamaURL.origin}</code>
+						<code class="code">{ollamaURL.origin}</code>
 						in
-						<code class={_code}>OLLAMA_ORIGINS</code>,
-						<a
-							class={_a}
+						<code class="code">OLLAMA_ORIGINS</code>,
+						<Button
+							variant="link"
+							size="link"
 							href="https://github.com/jmorganca/ollama/blob/main/docs/faq.md#how-can-i-allow-additional-web-origins-to-access-ollama"
 							target="_blank"
 						>
 							see docs
-						</a>
-						. Also check no browser extensions are blocking the connection.
+						</Button>. Also check no browser extensions are blocking the connection.
 					</p>
 					{#if ollamaURL.protocol === 'https:'}
-						<p class={_pHelp}>
+						<p class="p">
 							If trying to connect to an Ollama server that is not available on
-							<code class={_code}>localhost</code> or <code class={_code}>127.0.0.1</code> you will
+							<code class="code">localhost</code> or <code class="code">127.0.0.1</code> you will
 							need to
 							<a
 								href="https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/get-started/"
@@ -153,39 +109,59 @@
 			{/if}
 		</div>
 
-		<div class={_container}>
-			<Label class={_label}>Model</Label>
-			<Select.Root
-				bind:selected={ollamaModel}
-				disabled={!ollamaTagResponse || ollamaTagResponse.models.length === 0}
-			>
-				<Select.Trigger>
-					<Select.Value placeholder={ollamaModel.value} />
-				</Select.Trigger>
-				<Select.Content>
-					{#if ollamaTagResponse}
-						{#each ollamaTagResponse.models as model}
-							<Select.Item value={model.name}>{model.name}</Select.Item>
-						{/each}
-					{:else}
-						<Select.Item value="">No models available</Select.Item>
-					{/if}
-				</Select.Content>
-			</Select.Root>
+		<div class="container">
+			<FieldModels models={ollamaTagResponse?.models || []} bind:value={ollamaModel.value} />
 		</div>
 
 		<Separator class="mb-8 mt-8" />
 
-		<div class={_container}>
-			<Label class={_label}>About</Label>
-			<p class={_pAbout}>
+		<div class="container">
+			<p class="p"><strong>About</strong></p>
+			<p class="p">
 				<strong>Hollama</strong> is a minimalistic web interface for
-				<a class={_a} href="https://github.com/jmorganca/ollama/" target="_blank">Ollama</a>
+				<Button
+					variant="link"
+					size="link"
+					href="https://github.com/jmorganca/ollama/"
+					target="_blank">Ollama</Button
+				>
 				servers. Code is available on
-				<a class={_a} href="https://github.com/fmaclen/hollama" target="_blank">Github</a>
-				. Made by
-				<a class={_a} href="https://fernando.is" target="_blank">@fmaclen</a>
+				<Button variant="link" size="link" href="https://github.com/fmaclen/hollama" target="_blank"
+					>Github</Button
+				>.
+			</p>
+			<p class="p">
+				Made by
+				<Button variant="link" size="link" href="https://fernando.is" target="_blank"
+					>@fmaclen</Button
+				>
 			</p>
 		</div>
 	</div>
 </div>
+
+<style lang="scss">
+	.container {
+		@apply mb-6 mt-6 flex flex-col gap-y-3;
+	}
+
+	.help {
+		@apply flex flex-col gap-y-3;
+	}
+
+	.code {
+		@apply text-neutral-800;
+	}
+
+	.input {
+		@apply flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50;
+	}
+
+	.p {
+		@apply text-sm text-neutral-600;
+
+		strong {
+			@apply font-medium leading-none;
+		}
+	}
+</style>
diff --git a/src/routes/[id]/+page.svelte b/src/routes/[id]/+page.svelte
index 990fca8..a08b94d 100644
--- a/src/routes/[id]/+page.svelte
+++ b/src/routes/[id]/+page.svelte
@@ -1,11 +1,10 @@
 <script lang="ts">
 	import { goto } from '$app/navigation';
-
-	import * as Resizable from '$lib/components/ui/resizable';
-	import Button from '$lib/components/ui/button/button.svelte';
-	import Separator from '$lib/components/ui/separator/separator.svelte';
-	import Textarea from '$lib/components/ui/textarea/textarea.svelte';
 	import { Trash2 } from 'lucide-svelte';
+
+	import { PaneGroup, Pane, PaneResizer } from "paneforge";
+	import Button from '$lib/components/Button.svelte';
+	import Separator from '$lib/components/Separator.svelte';
 	import Article from './Article.svelte';
 
 	import { sessionsStore } from '$lib/store';
@@ -127,10 +126,10 @@
 
 	<Separator />
 
-	<Resizable.PaneGroup direction="horizontal">
-		<Resizable.Pane defaultSize={60} minSize={30}>
+	<PaneGroup direction="horizontal" class="bg-accent">
+		<Pane defaultSize={60} minSize={30}>
 			<div
-				class="flex h-full flex-col gap-y-4 overflow-y-auto bg-accent pt-6 pb-12 px-6 text-current"
+				class="flex h-full flex-col gap-y-4 overflow-y-auto pt-6 pb-12 px-6 text-current"
 				bind:this={messageWindow}
 			>
 				{#if session.messages.length === 0}
@@ -150,18 +149,27 @@
 					<Article message={{ role: 'ai', content: completion || '...' }} />
 				{/if}
 			</div>
-		</Resizable.Pane>
-		<Resizable.Handle />
-		<Resizable.Pane defaultSize={40} minSize={30}>
-			<div class="flex h-full flex-col gap-y-6 bg-accent p-6">
-				<Textarea
+		</Pane>
+		<PaneResizer class="flex gap-x-1 px-2">
+			<Separator orientation="vertical" />
+			<Separator orientation="vertical" />
+		</PaneResizer>
+		<Pane defaultSize={40} minSize={30}>
+			<div class="flex h-full flex-col gap-y-6 p-6">
+				<textarea
 					placeholder="Prompt"
-					class="h-full resize-none"
+					class="textarea"
 					bind:value={prompt}
 					on:keydown={handleKeyDown}
 				/>
 				<Button on:click={handleSubmit} disabled={!prompt}>Send</Button>
 			</div>
-		</Resizable.Pane>
-	</Resizable.PaneGroup>
+		</Pane>
+	</PaneGroup>
 </div>
+
+<style lang="scss">
+	.textarea {
+		@apply h-full resize-none flex min-h-[80px] w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50;
+	}
+</style>
diff --git a/src/routes/[id]/Article.svelte b/src/routes/[id]/Article.svelte
index 7b7cc09..bd63878 100644
--- a/src/routes/[id]/Article.svelte
+++ b/src/routes/[id]/Article.svelte
@@ -1,13 +1,13 @@
 <script lang="ts">
-	import { slide } from 'svelte/transition';
 	import MarkdownIt from 'markdown-it';
 	import hljs from 'highlight.js';
 	import 'highlight.js/styles/github.css';
+	import { slide } from 'svelte/transition';
 	import { Files } from 'lucide-svelte';
 
 	import { type Message } from '$lib/sessions';
-	import Separator from '$lib/components/ui/separator/separator.svelte';
-	import Button from '$lib/components/ui/button/button.svelte';
+	import Separator from '$lib/components/Separator.svelte';
+	import Button from '$lib/components/Button.svelte';
 
 	const md: MarkdownIt = new MarkdownIt({
 		highlight: function (str, lang) {
@@ -30,7 +30,10 @@
 	}
 </script>
 
-<article class="mx-auto flex w-full max-w-[70ch] flex-col gap-y-3" in:slide={{duration: isUserRole ? 400 : 0 }}>
+<article
+	class="mx-auto flex w-full max-w-[70ch] flex-col gap-y-3"
+	in:slide={{ duration: isUserRole ? 400 : 0 }}
+>
 	<nav class="grid grid-cols-[max-content_auto_max-content] items-center">
 		<p
 			data-testid="session-role"
@@ -39,13 +42,7 @@
 			{isUserRole ? 'You' : message.role}
 		</p>
 		<Separator />
-		<Button
-			class="opacity-25 hover:opacity-100"
-			title="Copy message"
-			variant="ghost"
-			size="icon"
-			on:click={copyMessage}
-		>
+		<Button title="Copy message" variant="icon" size="icon" on:click={copyMessage}>
 			<Files class="h-4 w-4" />
 		</Button>
 	</nav>


Test patch:
diff --git a/tests/settings.test.ts b/tests/settings.test.ts
index 5546d7a..fcf3274 100644
--- a/tests/settings.test.ts
+++ b/tests/settings.test.ts
@@ -8,24 +8,14 @@ test.beforeEach(async ({ page }) => {
 test('displays model list and updates settings store', async ({ page }) => {
   await page.goto('/');
 
-  // Wait for the model list to be loaded
-  await page.waitForSelector('label:has-text("Model")');
-
-  // Click on the button that opens the model list
-  await page.click('button[data-melt-select-trigger]');
-
-  // Wait for the model list to be visible
-  await page.waitForSelector('div[role="listbox"]');
-
   // Check if the model list contains the expected models
-  const modelNames = await page.$$eval('div[role="option"]', options =>
+  const modelNames = await page.$$eval('select#model option', options =>
     options.map(option => option.textContent?.trim())
   );
   expect(modelNames).toContain('gemma:7b');
   expect(modelNames).toContain('openhermes2.5-mistral:latest');
 
-  // Select a model by clicking on its name
-  await page.click('div[role="option"]:has-text("openhermes2.5-mistral:latest")');
+  await page.getByLabel('Model').selectOption('openhermes2.5-mistral:latest');
 
   // Check if the settings store is updated with the selected model
   const localStorageValue = await page.evaluate(() => window.localStorage.getItem('hollama-settings'));
@@ -34,14 +24,12 @@ test('displays model list and updates settings store', async ({ page }) => {
 
 test('handles server status updates correctly', async ({ page }) => {
   await page.goto('/');
-  await page.waitForSelector('label:has-text("Server")');
-
-  // Trigger a new API request by typing in the input field
-  await page.fill('input[placeholder="http://localhost:11434"]', 'http://example.com');
+  await expect (page.getByLabel('Server')).toHaveValue('http://localhost:11434');
 
-  // Wait for the server status to be updated to "connected"
+  // The starting status is "connected"
+  await expect(page.getByText('disconnected')).not.toBeVisible();
   await expect(page.getByText('connected', { exact: true })).toBeVisible();
-  await expect(page.getByText('connected', { exact: true })).toHaveClass(/bg-emerald-600/);
+  await expect(page.getByText('connected', { exact: true })).toHaveClass(/badge--positive/);
 
   // Mock the API to return an error response
   await page.route('**/api/tags', async (route) => {
@@ -49,9 +37,10 @@ test('handles server status updates correctly', async ({ page }) => {
   });
 
   // Trigger a new API request by typing in the input field
-  await page.fill('input[placeholder="http://localhost:11434"]', 'http://example.com/invalid');
+  await page.getByLabel('Server').clear();
 
   // Wait for the server status to be updated to "disconnected"
+  await expect(page.getByText('connected', { exact: true })).not.toBeVisible();
   await expect(page.getByText('disconnected')).toBeVisible();
-  await expect(page.getByText('disconnected')).toHaveClass(/bg-amber-600/);
+  await expect(page.getByText('disconnected')).toHaveClass(/badge--warning/);
 });
diff --git a/tests/utils.ts b/tests/utils.ts
index a954e94..b1a6c56 100644
--- a/tests/utils.ts
+++ b/tests/utils.ts
@@ -199,8 +199,7 @@ export const MOCK_SESSION_2_RESPONSE_1: OllamaCompletionResponse = {
 
 export async function chooseModelFromSettings(page: Page, modelName: string) {
 	await page.getByTitle('Settings').click();
-	await page.locator('button[data-melt-select-trigger]').click();
-	await page.click(`div[role="option"]:has-text('${modelName}')`);
+	await page.getByLabel('Model').selectOption(modelName);
 }
 
 export async function mockTagsResponse(page: Page) {