aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatarLarge Libravatar memdmp <memdmpestrogenzone>2025-08-18 18:30:04 +0200
committerLibravatarLarge Libravatar memdmp <memdmpestrogenzone>2025-08-18 18:30:04 +0200
commitc2ed0f84cef644ba28096f01ec14764114b68c0f (patch)
treefbdc236ba8ba646cf27fc51d250ea018a2fa7f25
downloadpixelsvg-c2ed0f84cef644ba28096f01ec14764114b68c0f.tar.gz
pixelsvg-c2ed0f84cef644ba28096f01ec14764114b68c0f.tar.bz2
pixelsvg-c2ed0f84cef644ba28096f01ec14764114b68c0f.tar.lz
pixelsvg-c2ed0f84cef644ba28096f01ec14764114b68c0f.zip

feat: initial commit

HEADmaster
-rw-r--r--.gitignore23
-rw-r--r--.npmrc1
-rw-r--r--LICENSE21
-rw-r--r--README.md38
-rw-r--r--deno.lock609
-rw-r--r--package.json23
-rw-r--r--src/app.d.ts13
-rw-r--r--src/app.html11
-rw-r--r--src/lib/Alerts.svelte184
-rw-r--r--src/lib/assets/favicon.old.svg9
-rw-r--r--src/lib/assets/favicon.pngbin0 -> 1149 bytes
-rw-r--r--src/lib/assets/favicon.svg1
-rw-r--r--src/lib/index.ts1
-rw-r--r--src/routes/+layout.svelte11
-rw-r--r--src/routes/+page.svelte202
-rw-r--r--static/cs16.css684
-rw-r--r--static/robots.txt3
-rw-r--r--svelte.config.js12
-rw-r--r--tsconfig.json19
-rw-r--r--vite.config.ts6
20 files changed, 1871 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..3b462cb
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,23 @@
+node_modules
+
+# Output
+.output
+.vercel
+.netlify
+.wrangler
+/.svelte-kit
+/build
+
+# OS
+.DS_Store
+Thumbs.db
+
+# Env
+.env
+.env.*
+!.env.example
+!.env.test
+
+# Vite
+vite.config.js.timestamp-*
+vite.config.ts.timestamp-*
diff --git a/.npmrc b/.npmrc
new file mode 100644
index 0000000..b6f27f1
--- /dev/null
+++ b/.npmrc
@@ -0,0 +1 @@
+engine-strict=true
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..0bf372b
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2025 memdmp
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..75842c4
--- /dev/null
+++ b/README.md
@@ -0,0 +1,38 @@
+# sv
+
+Everything you need to build a Svelte project, powered by [`sv`](https://github.com/sveltejs/cli).
+
+## Creating a project
+
+If you're seeing this, you've probably already done this step. Congrats!
+
+```sh
+# create a new project in the current directory
+npx sv create
+
+# create a new project in my-app
+npx sv create my-app
+```
+
+## Developing
+
+Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:
+
+```sh
+npm run dev
+
+# or start the server and open the app in a new browser tab
+npm run dev -- --open
+```
+
+## Building
+
+To create a production version of your app:
+
+```sh
+npm run build
+```
+
+You can preview the production build with `npm run preview`.
+
+> To deploy your app, you may need to install an [adapter](https://svelte.dev/docs/kit/adapters) for your target environment.
diff --git a/deno.lock b/deno.lock
new file mode 100644
index 0000000..2b7fc36
--- /dev/null
+++ b/deno.lock
@@ -0,0 +1,609 @@
+{
+ "version": "5",
+ "specifiers": {
+ "npm:@sveltejs/adapter-static@^3.0.8": "3.0.8_@sveltejs+kit@2.25.1__@sveltejs+vite-plugin-svelte@6.1.0___svelte@5.36.8____acorn@8.15.0___vite@7.0.5____picomatch@4.0.3__svelte@5.36.8___acorn@8.15.0__vite@7.0.5___picomatch@4.0.3__acorn@8.15.0_@sveltejs+vite-plugin-svelte@6.1.0__svelte@5.36.8___acorn@8.15.0__vite@7.0.5___picomatch@4.0.3_svelte@5.36.8__acorn@8.15.0_vite@7.0.5__picomatch@4.0.3",
+ "npm:@sveltejs/kit@^2.22.0": "2.25.1_@sveltejs+vite-plugin-svelte@6.1.0__svelte@5.36.8___acorn@8.15.0__vite@7.0.5___picomatch@4.0.3_svelte@5.36.8__acorn@8.15.0_vite@7.0.5__picomatch@4.0.3_acorn@8.15.0",
+ "npm:@sveltejs/vite-plugin-svelte@6": "6.1.0_svelte@5.36.8__acorn@8.15.0_vite@7.0.5__picomatch@4.0.3",
+ "npm:svelte-check@4": "4.3.0_svelte@5.36.8__acorn@8.15.0_typescript@5.8.3",
+ "npm:svelte@5": "5.36.8_acorn@8.15.0",
+ "npm:typescript@5": "5.8.3",
+ "npm:vite@^7.0.4": "7.0.5_picomatch@4.0.3"
+ },
+ "npm": {
+ "@ampproject/remapping@2.3.0": {
+ "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==",
+ "dependencies": [
+ "@jridgewell/gen-mapping",
+ "@jridgewell/trace-mapping"
+ ]
+ },
+ "@esbuild/aix-ppc64@0.25.6": {
+ "integrity": "sha512-ShbM/3XxwuxjFiuVBHA+d3j5dyac0aEVVq1oluIDf71hUw0aRF59dV/efUsIwFnR6m8JNM2FjZOzmaZ8yG61kw==",
+ "os": ["aix"],
+ "cpu": ["ppc64"]
+ },
+ "@esbuild/android-arm64@0.25.6": {
+ "integrity": "sha512-hd5zdUarsK6strW+3Wxi5qWws+rJhCCbMiC9QZyzoxfk5uHRIE8T287giQxzVpEvCwuJ9Qjg6bEjcRJcgfLqoA==",
+ "os": ["android"],
+ "cpu": ["arm64"]
+ },
+ "@esbuild/android-arm@0.25.6": {
+ "integrity": "sha512-S8ToEOVfg++AU/bHwdksHNnyLyVM+eMVAOf6yRKFitnwnbwwPNqKr3srzFRe7nzV69RQKb5DgchIX5pt3L53xg==",
+ "os": ["android"],
+ "cpu": ["arm"]
+ },
+ "@esbuild/android-x64@0.25.6": {
+ "integrity": "sha512-0Z7KpHSr3VBIO9A/1wcT3NTy7EB4oNC4upJ5ye3R7taCc2GUdeynSLArnon5G8scPwaU866d3H4BCrE5xLW25A==",
+ "os": ["android"],
+ "cpu": ["x64"]
+ },
+ "@esbuild/darwin-arm64@0.25.6": {
+ "integrity": "sha512-FFCssz3XBavjxcFxKsGy2DYK5VSvJqa6y5HXljKzhRZ87LvEi13brPrf/wdyl/BbpbMKJNOr1Sd0jtW4Ge1pAA==",
+ "os": ["darwin"],
+ "cpu": ["arm64"]
+ },
+ "@esbuild/darwin-x64@0.25.6": {
+ "integrity": "sha512-GfXs5kry/TkGM2vKqK2oyiLFygJRqKVhawu3+DOCk7OxLy/6jYkWXhlHwOoTb0WqGnWGAS7sooxbZowy+pK9Yg==",
+ "os": ["darwin"],
+ "cpu": ["x64"]
+ },
+ "@esbuild/freebsd-arm64@0.25.6": {
+ "integrity": "sha512-aoLF2c3OvDn2XDTRvn8hN6DRzVVpDlj2B/F66clWd/FHLiHaG3aVZjxQX2DYphA5y/evbdGvC6Us13tvyt4pWg==",
+ "os": ["freebsd"],
+ "cpu": ["arm64"]
+ },
+ "@esbuild/freebsd-x64@0.25.6": {
+ "integrity": "sha512-2SkqTjTSo2dYi/jzFbU9Plt1vk0+nNg8YC8rOXXea+iA3hfNJWebKYPs3xnOUf9+ZWhKAaxnQNUf2X9LOpeiMQ==",
+ "os": ["freebsd"],
+ "cpu": ["x64"]
+ },
+ "@esbuild/linux-arm64@0.25.6": {
+ "integrity": "sha512-b967hU0gqKd9Drsh/UuAm21Khpoh6mPBSgz8mKRq4P5mVK8bpA+hQzmm/ZwGVULSNBzKdZPQBRT3+WuVavcWsQ==",
+ "os": ["linux"],
+ "cpu": ["arm64"]
+ },
+ "@esbuild/linux-arm@0.25.6": {
+ "integrity": "sha512-SZHQlzvqv4Du5PrKE2faN0qlbsaW/3QQfUUc6yO2EjFcA83xnwm91UbEEVx4ApZ9Z5oG8Bxz4qPE+HFwtVcfyw==",
+ "os": ["linux"],
+ "cpu": ["arm"]
+ },
+ "@esbuild/linux-ia32@0.25.6": {
+ "integrity": "sha512-aHWdQ2AAltRkLPOsKdi3xv0mZ8fUGPdlKEjIEhxCPm5yKEThcUjHpWB1idN74lfXGnZ5SULQSgtr5Qos5B0bPw==",
+ "os": ["linux"],
+ "cpu": ["ia32"]
+ },
+ "@esbuild/linux-loong64@0.25.6": {
+ "integrity": "sha512-VgKCsHdXRSQ7E1+QXGdRPlQ/e08bN6WMQb27/TMfV+vPjjTImuT9PmLXupRlC90S1JeNNW5lzkAEO/McKeJ2yg==",
+ "os": ["linux"],
+ "cpu": ["loong64"]
+ },
+ "@esbuild/linux-mips64el@0.25.6": {
+ "integrity": "sha512-WViNlpivRKT9/py3kCmkHnn44GkGXVdXfdc4drNmRl15zVQ2+D2uFwdlGh6IuK5AAnGTo2qPB1Djppj+t78rzw==",
+ "os": ["linux"],
+ "cpu": ["mips64el"]
+ },
+ "@esbuild/linux-ppc64@0.25.6": {
+ "integrity": "sha512-wyYKZ9NTdmAMb5730I38lBqVu6cKl4ZfYXIs31Baf8aoOtB4xSGi3THmDYt4BTFHk7/EcVixkOV2uZfwU3Q2Jw==",
+ "os": ["linux"],
+ "cpu": ["ppc64"]
+ },
+ "@esbuild/linux-riscv64@0.25.6": {
+ "integrity": "sha512-KZh7bAGGcrinEj4qzilJ4hqTY3Dg2U82c8bv+e1xqNqZCrCyc+TL9AUEn5WGKDzm3CfC5RODE/qc96OcbIe33w==",
+ "os": ["linux"],
+ "cpu": ["riscv64"]
+ },
+ "@esbuild/linux-s390x@0.25.6": {
+ "integrity": "sha512-9N1LsTwAuE9oj6lHMyyAM+ucxGiVnEqUdp4v7IaMmrwb06ZTEVCIs3oPPplVsnjPfyjmxwHxHMF8b6vzUVAUGw==",
+ "os": ["linux"],
+ "cpu": ["s390x"]
+ },
+ "@esbuild/linux-x64@0.25.6": {
+ "integrity": "sha512-A6bJB41b4lKFWRKNrWoP2LHsjVzNiaurf7wyj/XtFNTsnPuxwEBWHLty+ZE0dWBKuSK1fvKgrKaNjBS7qbFKig==",
+ "os": ["linux"],
+ "cpu": ["x64"]
+ },
+ "@esbuild/netbsd-arm64@0.25.6": {
+ "integrity": "sha512-IjA+DcwoVpjEvyxZddDqBY+uJ2Snc6duLpjmkXm/v4xuS3H+3FkLZlDm9ZsAbF9rsfP3zeA0/ArNDORZgrxR/Q==",
+ "os": ["netbsd"],
+ "cpu": ["arm64"]
+ },
+ "@esbuild/netbsd-x64@0.25.6": {
+ "integrity": "sha512-dUXuZr5WenIDlMHdMkvDc1FAu4xdWixTCRgP7RQLBOkkGgwuuzaGSYcOpW4jFxzpzL1ejb8yF620UxAqnBrR9g==",
+ "os": ["netbsd"],
+ "cpu": ["x64"]
+ },
+ "@esbuild/openbsd-arm64@0.25.6": {
+ "integrity": "sha512-l8ZCvXP0tbTJ3iaqdNf3pjaOSd5ex/e6/omLIQCVBLmHTlfXW3zAxQ4fnDmPLOB1x9xrcSi/xtCWFwCZRIaEwg==",
+ "os": ["openbsd"],
+ "cpu": ["arm64"]
+ },
+ "@esbuild/openbsd-x64@0.25.6": {
+ "integrity": "sha512-hKrmDa0aOFOr71KQ/19JC7az1P0GWtCN1t2ahYAf4O007DHZt/dW8ym5+CUdJhQ/qkZmI1HAF8KkJbEFtCL7gw==",
+ "os": ["openbsd"],
+ "cpu": ["x64"]
+ },
+ "@esbuild/openharmony-arm64@0.25.6": {
+ "integrity": "sha512-+SqBcAWoB1fYKmpWoQP4pGtx+pUUC//RNYhFdbcSA16617cchuryuhOCRpPsjCblKukAckWsV+aQ3UKT/RMPcA==",
+ "os": ["openharmony"],
+ "cpu": ["arm64"]
+ },
+ "@esbuild/sunos-x64@0.25.6": {
+ "integrity": "sha512-dyCGxv1/Br7MiSC42qinGL8KkG4kX0pEsdb0+TKhmJZgCUDBGmyo1/ArCjNGiOLiIAgdbWgmWgib4HoCi5t7kA==",
+ "os": ["sunos"],
+ "cpu": ["x64"]
+ },
+ "@esbuild/win32-arm64@0.25.6": {
+ "integrity": "sha512-42QOgcZeZOvXfsCBJF5Afw73t4veOId//XD3i+/9gSkhSV6Gk3VPlWncctI+JcOyERv85FUo7RxuxGy+z8A43Q==",
+ "os": ["win32"],
+ "cpu": ["arm64"]
+ },
+ "@esbuild/win32-ia32@0.25.6": {
+ "integrity": "sha512-4AWhgXmDuYN7rJI6ORB+uU9DHLq/erBbuMoAuB4VWJTu5KtCgcKYPynF0YI1VkBNuEfjNlLrFr9KZPJzrtLkrQ==",
+ "os": ["win32"],
+ "cpu": ["ia32"]
+ },
+ "@esbuild/win32-x64@0.25.6": {
+ "integrity": "sha512-NgJPHHbEpLQgDH2MjQu90pzW/5vvXIZ7KOnPyNBm92A6WgZ/7b6fJyUBjoumLqeOQQGqY2QjQxRo97ah4Sj0cA==",
+ "os": ["win32"],
+ "cpu": ["x64"]
+ },
+ "@jridgewell/gen-mapping@0.3.12": {
+ "integrity": "sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==",
+ "dependencies": [
+ "@jridgewell/sourcemap-codec",
+ "@jridgewell/trace-mapping"
+ ]
+ },
+ "@jridgewell/resolve-uri@3.1.2": {
+ "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="
+ },
+ "@jridgewell/sourcemap-codec@1.5.4": {
+ "integrity": "sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw=="
+ },
+ "@jridgewell/trace-mapping@0.3.29": {
+ "integrity": "sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==",
+ "dependencies": [
+ "@jridgewell/resolve-uri",
+ "@jridgewell/sourcemap-codec"
+ ]
+ },
+ "@polka/url@1.0.0-next.29": {
+ "integrity": "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww=="
+ },
+ "@rollup/rollup-android-arm-eabi@4.45.1": {
+ "integrity": "sha512-NEySIFvMY0ZQO+utJkgoMiCAjMrGvnbDLHvcmlA33UXJpYBCvlBEbMMtV837uCkS+plG2umfhn0T5mMAxGrlRA==",
+ "os": ["android"],
+ "cpu": ["arm"]
+ },
+ "@rollup/rollup-android-arm64@4.45.1": {
+ "integrity": "sha512-ujQ+sMXJkg4LRJaYreaVx7Z/VMgBBd89wGS4qMrdtfUFZ+TSY5Rs9asgjitLwzeIbhwdEhyj29zhst3L1lKsRQ==",
+ "os": ["android"],
+ "cpu": ["arm64"]
+ },
+ "@rollup/rollup-darwin-arm64@4.45.1": {
+ "integrity": "sha512-FSncqHvqTm3lC6Y13xncsdOYfxGSLnP+73k815EfNmpewPs+EyM49haPS105Rh4aF5mJKywk9X0ogzLXZzN9lA==",
+ "os": ["darwin"],
+ "cpu": ["arm64"]
+ },
+ "@rollup/rollup-darwin-x64@4.45.1": {
+ "integrity": "sha512-2/vVn/husP5XI7Fsf/RlhDaQJ7x9zjvC81anIVbr4b/f0xtSmXQTFcGIQ/B1cXIYM6h2nAhJkdMHTnD7OtQ9Og==",
+ "os": ["darwin"],
+ "cpu": ["x64"]
+ },
+ "@rollup/rollup-freebsd-arm64@4.45.1": {
+ "integrity": "sha512-4g1kaDxQItZsrkVTdYQ0bxu4ZIQ32cotoQbmsAnW1jAE4XCMbcBPDirX5fyUzdhVCKgPcrwWuucI8yrVRBw2+g==",
+ "os": ["freebsd"],
+ "cpu": ["arm64"]
+ },
+ "@rollup/rollup-freebsd-x64@4.45.1": {
+ "integrity": "sha512-L/6JsfiL74i3uK1Ti2ZFSNsp5NMiM4/kbbGEcOCps99aZx3g8SJMO1/9Y0n/qKlWZfn6sScf98lEOUe2mBvW9A==",
+ "os": ["freebsd"],
+ "cpu": ["x64"]
+ },
+ "@rollup/rollup-linux-arm-gnueabihf@4.45.1": {
+ "integrity": "sha512-RkdOTu2jK7brlu+ZwjMIZfdV2sSYHK2qR08FUWcIoqJC2eywHbXr0L8T/pONFwkGukQqERDheaGTeedG+rra6Q==",
+ "os": ["linux"],
+ "cpu": ["arm"]
+ },
+ "@rollup/rollup-linux-arm-musleabihf@4.45.1": {
+ "integrity": "sha512-3kJ8pgfBt6CIIr1o+HQA7OZ9mp/zDk3ctekGl9qn/pRBgrRgfwiffaUmqioUGN9hv0OHv2gxmvdKOkARCtRb8Q==",
+ "os": ["linux"],
+ "cpu": ["arm"]
+ },
+ "@rollup/rollup-linux-arm64-gnu@4.45.1": {
+ "integrity": "sha512-k3dOKCfIVixWjG7OXTCOmDfJj3vbdhN0QYEqB+OuGArOChek22hn7Uy5A/gTDNAcCy5v2YcXRJ/Qcnm4/ma1xw==",
+ "os": ["linux"],
+ "cpu": ["arm64"]
+ },
+ "@rollup/rollup-linux-arm64-musl@4.45.1": {
+ "integrity": "sha512-PmI1vxQetnM58ZmDFl9/Uk2lpBBby6B6rF4muJc65uZbxCs0EA7hhKCk2PKlmZKuyVSHAyIw3+/SiuMLxKxWog==",
+ "os": ["linux"],
+ "cpu": ["arm64"]
+ },
+ "@rollup/rollup-linux-loongarch64-gnu@4.45.1": {
+ "integrity": "sha512-9UmI0VzGmNJ28ibHW2GpE2nF0PBQqsyiS4kcJ5vK+wuwGnV5RlqdczVocDSUfGX/Na7/XINRVoUgJyFIgipoRg==",
+ "os": ["linux"],
+ "cpu": ["loong64"]
+ },
+ "@rollup/rollup-linux-powerpc64le-gnu@4.45.1": {
+ "integrity": "sha512-7nR2KY8oEOUTD3pBAxIBBbZr0U7U+R9HDTPNy+5nVVHDXI4ikYniH1oxQz9VoB5PbBU1CZuDGHkLJkd3zLMWsg==",
+ "os": ["linux"],
+ "cpu": ["ppc64"]
+ },
+ "@rollup/rollup-linux-riscv64-gnu@4.45.1": {
+ "integrity": "sha512-nlcl3jgUultKROfZijKjRQLUu9Ma0PeNv/VFHkZiKbXTBQXhpytS8CIj5/NfBeECZtY2FJQubm6ltIxm/ftxpw==",
+ "os": ["linux"],
+ "cpu": ["riscv64"]
+ },
+ "@rollup/rollup-linux-riscv64-musl@4.45.1": {
+ "integrity": "sha512-HJV65KLS51rW0VY6rvZkiieiBnurSzpzore1bMKAhunQiECPuxsROvyeaot/tcK3A3aGnI+qTHqisrpSgQrpgA==",
+ "os": ["linux"],
+ "cpu": ["riscv64"]
+ },
+ "@rollup/rollup-linux-s390x-gnu@4.45.1": {
+ "integrity": "sha512-NITBOCv3Qqc6hhwFt7jLV78VEO/il4YcBzoMGGNxznLgRQf43VQDae0aAzKiBeEPIxnDrACiMgbqjuihx08OOw==",
+ "os": ["linux"],
+ "cpu": ["s390x"]
+ },
+ "@rollup/rollup-linux-x64-gnu@4.45.1": {
+ "integrity": "sha512-+E/lYl6qu1zqgPEnTrs4WysQtvc/Sh4fC2nByfFExqgYrqkKWp1tWIbe+ELhixnenSpBbLXNi6vbEEJ8M7fiHw==",
+ "os": ["linux"],
+ "cpu": ["x64"]
+ },
+ "@rollup/rollup-linux-x64-musl@4.45.1": {
+ "integrity": "sha512-a6WIAp89p3kpNoYStITT9RbTbTnqarU7D8N8F2CV+4Cl9fwCOZraLVuVFvlpsW0SbIiYtEnhCZBPLoNdRkjQFw==",
+ "os": ["linux"],
+ "cpu": ["x64"]
+ },
+ "@rollup/rollup-win32-arm64-msvc@4.45.1": {
+ "integrity": "sha512-T5Bi/NS3fQiJeYdGvRpTAP5P02kqSOpqiopwhj0uaXB6nzs5JVi2XMJb18JUSKhCOX8+UE1UKQufyD6Or48dJg==",
+ "os": ["win32"],
+ "cpu": ["arm64"]
+ },
+ "@rollup/rollup-win32-ia32-msvc@4.45.1": {
+ "integrity": "sha512-lxV2Pako3ujjuUe9jiU3/s7KSrDfH6IgTSQOnDWr9aJ92YsFd7EurmClK0ly/t8dzMkDtd04g60WX6yl0sGfdw==",
+ "os": ["win32"],
+ "cpu": ["ia32"]
+ },
+ "@rollup/rollup-win32-x64-msvc@4.45.1": {
+ "integrity": "sha512-M/fKi4sasCdM8i0aWJjCSFm2qEnYRR8AMLG2kxp6wD13+tMGA4Z1tVAuHkNRjud5SW2EM3naLuK35w9twvf6aA==",
+ "os": ["win32"],
+ "cpu": ["x64"]
+ },
+ "@sveltejs/acorn-typescript@1.0.5_acorn@8.15.0": {
+ "integrity": "sha512-IwQk4yfwLdibDlrXVE04jTZYlLnwsTT2PIOQQGNLWfjavGifnk1JD1LcZjZaBTRcxZu2FfPfNLOE04DSu9lqtQ==",
+ "dependencies": [
+ "acorn"
+ ]
+ },
+ "@sveltejs/adapter-static@3.0.8_@sveltejs+kit@2.25.1__@sveltejs+vite-plugin-svelte@6.1.0___svelte@5.36.8____acorn@8.15.0___vite@7.0.5____picomatch@4.0.3__svelte@5.36.8___acorn@8.15.0__vite@7.0.5___picomatch@4.0.3__acorn@8.15.0_@sveltejs+vite-plugin-svelte@6.1.0__svelte@5.36.8___acorn@8.15.0__vite@7.0.5___picomatch@4.0.3_svelte@5.36.8__acorn@8.15.0_vite@7.0.5__picomatch@4.0.3": {
+ "integrity": "sha512-YaDrquRpZwfcXbnlDsSrBQNCChVOT9MGuSg+dMAyfsAa1SmiAhrA5jUYUiIMC59G92kIbY/AaQOWcBdq+lh+zg==",
+ "dependencies": [
+ "@sveltejs/kit"
+ ]
+ },
+ "@sveltejs/kit@2.25.1_@sveltejs+vite-plugin-svelte@6.1.0__svelte@5.36.8___acorn@8.15.0__vite@7.0.5___picomatch@4.0.3_svelte@5.36.8__acorn@8.15.0_vite@7.0.5__picomatch@4.0.3_acorn@8.15.0": {
+ "integrity": "sha512-8H+fxDEp7Xq6tLFdrGdS5fLu6ONDQQ9DgyjboXpChubuFdfH9QoFX09ypssBpyNkJNZFt9eW3yLmXIc9CesPCA==",
+ "dependencies": [
+ "@sveltejs/acorn-typescript",
+ "@sveltejs/vite-plugin-svelte",
+ "@types/cookie",
+ "acorn",
+ "cookie",
+ "devalue",
+ "esm-env",
+ "kleur",
+ "magic-string",
+ "mrmime",
+ "sade",
+ "set-cookie-parser",
+ "sirv",
+ "svelte",
+ "vite"
+ ],
+ "bin": true
+ },
+ "@sveltejs/vite-plugin-svelte-inspector@5.0.0_@sveltejs+vite-plugin-svelte@6.1.0__svelte@5.36.8___acorn@8.15.0__vite@7.0.5___picomatch@4.0.3_svelte@5.36.8__acorn@8.15.0_vite@7.0.5__picomatch@4.0.3": {
+ "integrity": "sha512-iwQ8Z4ET6ZFSt/gC+tVfcsSBHwsqc6RumSaiLUkAurW3BCpJam65cmHw0oOlDMTO0u+PZi9hilBRYN+LZNHTUQ==",
+ "dependencies": [
+ "@sveltejs/vite-plugin-svelte",
+ "debug",
+ "svelte",
+ "vite"
+ ]
+ },
+ "@sveltejs/vite-plugin-svelte@6.1.0_svelte@5.36.8__acorn@8.15.0_vite@7.0.5__picomatch@4.0.3": {
+ "integrity": "sha512-+U6lz1wvGEG/BvQyL4z/flyNdQ9xDNv5vrh+vWBWTHaebqT0c9RNggpZTo/XSPoHsSCWBlYaTlRX8pZ9GATXCw==",
+ "dependencies": [
+ "@sveltejs/vite-plugin-svelte-inspector",
+ "debug",
+ "deepmerge",
+ "kleur",
+ "magic-string",
+ "svelte",
+ "vite",
+ "vitefu"
+ ]
+ },
+ "@types/cookie@0.6.0": {
+ "integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA=="
+ },
+ "@types/estree@1.0.8": {
+ "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="
+ },
+ "acorn@8.15.0": {
+ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
+ "bin": true
+ },
+ "aria-query@5.3.2": {
+ "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw=="
+ },
+ "axobject-query@4.1.0": {
+ "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ=="
+ },
+ "chokidar@4.0.3": {
+ "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==",
+ "dependencies": [
+ "readdirp"
+ ]
+ },
+ "clsx@2.1.1": {
+ "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="
+ },
+ "cookie@0.6.0": {
+ "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw=="
+ },
+ "debug@4.4.1": {
+ "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
+ "dependencies": [
+ "ms"
+ ]
+ },
+ "deepmerge@4.3.1": {
+ "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A=="
+ },
+ "devalue@5.1.1": {
+ "integrity": "sha512-maua5KUiapvEwiEAe+XnlZ3Rh0GD+qI1J/nb9vrJc3muPXvcF/8gXYTWF76+5DAqHyDUtOIImEuo0YKE9mshVw=="
+ },
+ "esbuild@0.25.6": {
+ "integrity": "sha512-GVuzuUwtdsghE3ocJ9Bs8PNoF13HNQ5TXbEi2AhvVb8xU1Iwt9Fos9FEamfoee+u/TOsn7GUWc04lz46n2bbTg==",
+ "optionalDependencies": [
+ "@esbuild/aix-ppc64",
+ "@esbuild/android-arm",
+ "@esbuild/android-arm64",
+ "@esbuild/android-x64",
+ "@esbuild/darwin-arm64",
+ "@esbuild/darwin-x64",
+ "@esbuild/freebsd-arm64",
+ "@esbuild/freebsd-x64",
+ "@esbuild/linux-arm",
+ "@esbuild/linux-arm64",
+ "@esbuild/linux-ia32",
+ "@esbuild/linux-loong64",
+ "@esbuild/linux-mips64el",
+ "@esbuild/linux-ppc64",
+ "@esbuild/linux-riscv64",
+ "@esbuild/linux-s390x",
+ "@esbuild/linux-x64",
+ "@esbuild/netbsd-arm64",
+ "@esbuild/netbsd-x64",
+ "@esbuild/openbsd-arm64",
+ "@esbuild/openbsd-x64",
+ "@esbuild/openharmony-arm64",
+ "@esbuild/sunos-x64",
+ "@esbuild/win32-arm64",
+ "@esbuild/win32-ia32",
+ "@esbuild/win32-x64"
+ ],
+ "scripts": true,
+ "bin": true
+ },
+ "esm-env@1.2.2": {
+ "integrity": "sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA=="
+ },
+ "esrap@2.1.0": {
+ "integrity": "sha512-yzmPNpl7TBbMRC5Lj2JlJZNPml0tzqoqP5B1JXycNUwtqma9AKCO0M2wHrdgsHcy1WRW7S9rJknAMtByg3usgA==",
+ "dependencies": [
+ "@jridgewell/sourcemap-codec"
+ ]
+ },
+ "fdir@6.4.6_picomatch@4.0.3": {
+ "integrity": "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==",
+ "dependencies": [
+ "picomatch"
+ ],
+ "optionalPeers": [
+ "picomatch"
+ ]
+ },
+ "fsevents@2.3.3": {
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "os": ["darwin"],
+ "scripts": true
+ },
+ "is-reference@3.0.3": {
+ "integrity": "sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==",
+ "dependencies": [
+ "@types/estree"
+ ]
+ },
+ "kleur@4.1.5": {
+ "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ=="
+ },
+ "locate-character@3.0.0": {
+ "integrity": "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA=="
+ },
+ "magic-string@0.30.17": {
+ "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==",
+ "dependencies": [
+ "@jridgewell/sourcemap-codec"
+ ]
+ },
+ "mri@1.2.0": {
+ "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA=="
+ },
+ "mrmime@2.0.1": {
+ "integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ=="
+ },
+ "ms@2.1.3": {
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
+ },
+ "nanoid@3.3.11": {
+ "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
+ "bin": true
+ },
+ "picocolors@1.1.1": {
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="
+ },
+ "picomatch@4.0.3": {
+ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="
+ },
+ "postcss@8.5.6": {
+ "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==",
+ "dependencies": [
+ "nanoid",
+ "picocolors",
+ "source-map-js"
+ ]
+ },
+ "readdirp@4.1.2": {
+ "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="
+ },
+ "rollup@4.45.1": {
+ "integrity": "sha512-4iya7Jb76fVpQyLoiVpzUrsjQ12r3dM7fIVz+4NwoYvZOShknRmiv+iu9CClZml5ZLGb0XMcYLutK6w9tgxHDw==",
+ "dependencies": [
+ "@types/estree"
+ ],
+ "optionalDependencies": [
+ "@rollup/rollup-android-arm-eabi",
+ "@rollup/rollup-android-arm64",
+ "@rollup/rollup-darwin-arm64",
+ "@rollup/rollup-darwin-x64",
+ "@rollup/rollup-freebsd-arm64",
+ "@rollup/rollup-freebsd-x64",
+ "@rollup/rollup-linux-arm-gnueabihf",
+ "@rollup/rollup-linux-arm-musleabihf",
+ "@rollup/rollup-linux-arm64-gnu",
+ "@rollup/rollup-linux-arm64-musl",
+ "@rollup/rollup-linux-loongarch64-gnu",
+ "@rollup/rollup-linux-powerpc64le-gnu",
+ "@rollup/rollup-linux-riscv64-gnu",
+ "@rollup/rollup-linux-riscv64-musl",
+ "@rollup/rollup-linux-s390x-gnu",
+ "@rollup/rollup-linux-x64-gnu",
+ "@rollup/rollup-linux-x64-musl",
+ "@rollup/rollup-win32-arm64-msvc",
+ "@rollup/rollup-win32-ia32-msvc",
+ "@rollup/rollup-win32-x64-msvc",
+ "fsevents"
+ ],
+ "bin": true
+ },
+ "sade@1.8.1": {
+ "integrity": "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==",
+ "dependencies": [
+ "mri"
+ ]
+ },
+ "set-cookie-parser@2.7.1": {
+ "integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ=="
+ },
+ "sirv@3.0.1": {
+ "integrity": "sha512-FoqMu0NCGBLCcAkS1qA+XJIQTR6/JHfQXl+uGteNCQ76T91DMUjPa9xfmeqMY3z80nLSg9yQmNjK0Px6RWsH/A==",
+ "dependencies": [
+ "@polka/url",
+ "mrmime",
+ "totalist"
+ ]
+ },
+ "source-map-js@1.2.1": {
+ "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="
+ },
+ "svelte-check@4.3.0_svelte@5.36.8__acorn@8.15.0_typescript@5.8.3": {
+ "integrity": "sha512-Iz8dFXzBNAM7XlEIsUjUGQhbEE+Pvv9odb9+0+ITTgFWZBGeJRRYqHUUglwe2EkLD5LIsQaAc4IUJyvtKuOO5w==",
+ "dependencies": [
+ "@jridgewell/trace-mapping",
+ "chokidar",
+ "fdir",
+ "picocolors",
+ "sade",
+ "svelte",
+ "typescript"
+ ],
+ "bin": true
+ },
+ "svelte@5.36.8_acorn@8.15.0": {
+ "integrity": "sha512-8JbZWQu96hMjH/oYQPxXW6taeC6Awl6muGHeZzJTxQx7NGRQ/J9wN1hkzRKLOlSDlbS2igiFg7p5xyTp5uXG3A==",
+ "dependencies": [
+ "@ampproject/remapping",
+ "@jridgewell/sourcemap-codec",
+ "@sveltejs/acorn-typescript",
+ "@types/estree",
+ "acorn",
+ "aria-query",
+ "axobject-query",
+ "clsx",
+ "esm-env",
+ "esrap",
+ "is-reference",
+ "locate-character",
+ "magic-string",
+ "zimmerframe"
+ ]
+ },
+ "tinyglobby@0.2.14_picomatch@4.0.3": {
+ "integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==",
+ "dependencies": [
+ "fdir",
+ "picomatch"
+ ]
+ },
+ "totalist@3.0.1": {
+ "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ=="
+ },
+ "typescript@5.8.3": {
+ "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
+ "bin": true
+ },
+ "vite@7.0.5_picomatch@4.0.3": {
+ "integrity": "sha512-1mncVwJxy2C9ThLwz0+2GKZyEXuC3MyWtAAlNftlZZXZDP3AJt5FmwcMit/IGGaNZ8ZOB2BNO/HFUB+CpN0NQw==",
+ "dependencies": [
+ "esbuild",
+ "fdir",
+ "picomatch",
+ "postcss",
+ "rollup",
+ "tinyglobby"
+ ],
+ "optionalDependencies": [
+ "fsevents"
+ ],
+ "bin": true
+ },
+ "vitefu@1.1.1_vite@7.0.5__picomatch@4.0.3": {
+ "integrity": "sha512-B/Fegf3i8zh0yFbpzZ21amWzHmuNlLlmJT6n7bu5e+pCHUKQIfXSYokrqOBGEMMe9UG2sostKQF9mml/vYaWJQ==",
+ "dependencies": [
+ "vite"
+ ],
+ "optionalPeers": [
+ "vite"
+ ]
+ },
+ "zimmerframe@1.1.2": {
+ "integrity": "sha512-rAbqEGa8ovJy4pyBxZM70hg4pE6gDgaQ0Sl9M3enG3I0d6H4XSAM3GeNGLKnsBpuijUow064sf7ww1nutC5/3w=="
+ }
+ },
+ "workspace": {
+ "packageJson": {
+ "dependencies": [
+ "npm:@sveltejs/adapter-static@^3.0.8",
+ "npm:@sveltejs/kit@^2.22.0",
+ "npm:@sveltejs/vite-plugin-svelte@6",
+ "npm:svelte-check@4",
+ "npm:svelte@5",
+ "npm:typescript@5",
+ "npm:vite@^7.0.4"
+ ]
+ }
+ }
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..36592a6
--- /dev/null
+++ b/package.json
@@ -0,0 +1,23 @@
+{
+ "name": "pixelsvg",
+ "private": true,
+ "version": "0.0.1",
+ "type": "module",
+ "scripts": {
+ "dev": "vite dev",
+ "build": "vite build",
+ "preview": "vite preview",
+ "prepare": "svelte-kit sync || echo ''",
+ "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
+ "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch"
+ },
+ "devDependencies": {
+ "@sveltejs/adapter-static": "^3.0.8",
+ "@sveltejs/kit": "^2.22.0",
+ "@sveltejs/vite-plugin-svelte": "^6.0.0",
+ "svelte": "^5.0.0",
+ "svelte-check": "^4.0.0",
+ "typescript": "^5.0.0",
+ "vite": "^7.0.4"
+ }
+}
diff --git a/src/app.d.ts b/src/app.d.ts
new file mode 100644
index 0000000..da08e6d
--- /dev/null
+++ b/src/app.d.ts
@@ -0,0 +1,13 @@
+// See https://svelte.dev/docs/kit/types#app.d.ts
+// for information about these interfaces
+declare global {
+ namespace App {
+ // interface Error {}
+ // interface Locals {}
+ // interface PageData {}
+ // interface PageState {}
+ // interface Platform {}
+ }
+}
+
+export {};
diff --git a/src/app.html b/src/app.html
new file mode 100644
index 0000000..b0b3788
--- /dev/null
+++ b/src/app.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8" />
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
+ %sveltekit.head%
+ </head>
+ <body data-sveltekit-preload-data="hover" class="cs">
+ <div style="display: contents">%sveltekit.body%</div>
+ </body>
+</html>
diff --git a/src/lib/Alerts.svelte b/src/lib/Alerts.svelte
new file mode 100644
index 0000000..1e4641b
--- /dev/null
+++ b/src/lib/Alerts.svelte
@@ -0,0 +1,184 @@
+<!--
+MIT License
+
+Copyright (c) 2025 memdmp
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+ -->
+
+<script lang="ts" module>
+ let ids = $state([] as number[]);
+ let idCtr = $state(0);
+ let dialogObject = $state({
+ open: false,
+ title: '',
+ content: '',
+ closeBtn: false,
+ buttons: [
+ {
+ text: 'Close',
+ },
+ ] as {
+ text: string;
+ callback?: () =>
+ | {
+ success: true;
+ content: string;
+ }
+ | {
+ success: false;
+ content: any;
+ };
+ }[],
+ });
+ let closeAlert = (m: string) => void 0;
+ let cancelAlert = (err?: any) => void 0;
+ let dialogPromises = [] as Promise<string>[];
+ let dialogPromise = Promise.resolve('');
+ const createDialogPromise = (setAlertTo?: typeof dialogObject) => (
+ dialogPromises.push(
+ (dialogPromise = new Promise<string>((rs, rj) => {
+ let oldCloseAlert = closeAlert;
+ let oldCancelAlert = cancelAlert;
+ closeAlert = (m) => {
+ closeAlert = oldCloseAlert;
+ dialogObject = setAlertTo ?? dialogObject;
+ rs(m);
+ };
+ cancelAlert = (m) => {
+ cancelAlert = oldCancelAlert;
+ dialogObject = setAlertTo ?? dialogObject;
+ rj(m);
+ };
+ }))
+ ),
+ dialogPromise
+ );
+ export const alert = async (
+ message: string,
+ options?: {
+ title?: string;
+ /** prioritise over existing alerts */
+ priority?: boolean;
+ /** if we can close the dialog with the x at the top */
+ canClose?: boolean;
+ /** button list */
+ buttons?: typeof dialogObject.buttons;
+ }
+ ) => {
+ if (!options?.priority) await Promise.allSettled(dialogPromises);
+ const oldAlert = dialogObject;
+ dialogObject = {
+ open: true,
+ title: options?.title ?? 'Alert',
+ closeBtn: options?.canClose ?? true,
+ buttons: options?.buttons ?? [
+ {
+ text: 'Close',
+ },
+ ],
+ content: message,
+ };
+ return createDialogPromise(oldAlert);
+ };
+ export const confirm = async (
+ message: string,
+ options?: Omit<Parameters<typeof alert>[1], 'buttons'>
+ ) => {
+ const rs = await alert(message, {
+ title: 'Confirmation',
+ ...(options ?? {}),
+ buttons: [
+ {
+ text: 'OK',
+ callback: () => ({
+ success: true,
+ content: 'OK',
+ }),
+ },
+ {
+ text: 'Cancel',
+ callback: () => ({
+ success: true,
+ content: 'Cancel',
+ }),
+ },
+ ],
+ });
+ return rs === 'OK';
+ };
+</script>
+
+<script lang="ts">
+ import { onDestroy, onMount } from 'svelte';
+
+ let dialog = $state(null as HTMLDialogElement | null);
+ let id: number = $state(-1);
+ onMount(() => {
+ id = idCtr++;
+ ids.push(id);
+ });
+ onDestroy(() => (ids = ids.filter((v) => v !== id)));
+ $effect(() => {
+ dialog?.showModal();
+ });
+</script>
+
+{#if ids[0] === id && dialogObject.open}
+ <section>
+ <dialog bind:this={dialog}>
+ <form method="dialog">
+ <div class="heading">
+ <div class="wrapper">
+ <div class="icon"></div>
+ <p class="text">{dialogObject.title}</p>
+ </div>
+ <button
+ class="close"
+ aria-label="Close"
+ disabled={!dialogObject.closeBtn}
+ onclick={() => {
+ cancelAlert(new Error('User Cancelled Alert'));
+ }}
+ ></button>
+ </div>
+ <div class="content">
+ {dialogObject.content}
+ </div>
+ <menu class="footer-btns" style="gap: 4px; display: flex;">
+ {#each dialogObject.buttons as button}
+ <button
+ onclick={(e) => {
+ const callback =
+ button.callback ??
+ (() => ({
+ success: true,
+ content: button.text,
+ }));
+ const result = callback();
+ if (result.success) closeAlert(result.content);
+ else cancelAlert(result.content);
+ }}>{button.text}</button
+ >
+ {/each}
+ </menu>
+ </form>
+ </dialog>
+ </section>
+{/if}
diff --git a/src/lib/assets/favicon.old.svg b/src/lib/assets/favicon.old.svg
new file mode 100644
index 0000000..d69dee8
--- /dev/null
+++ b/src/lib/assets/favicon.old.svg
@@ -0,0 +1,9 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="107" height="128" viewBox="0 0 107 128">
+ <title>svelte-logo</title>
+ <path
+ d="M94.157 22.819c-10.4-14.885-30.94-19.297-45.792-9.835L22.282 29.608A29.92 29.92 0 0 0 8.764 49.65a31.5 31.5 0 0 0 3.108 20.231 30 30 0 0 0-4.477 11.183 31.9 31.9 0 0 0 5.448 24.116c10.402 14.887 30.942 19.297 45.791 9.835l26.083-16.624A29.92 29.92 0 0 0 98.235 78.35a31.53 31.53 0 0 0-3.105-20.232 30 30 0 0 0 4.474-11.182 31.88 31.88 0 0 0-5.447-24.116"
+ style="fill:#BF64CC" />
+ <path
+ d="M45.817 106.582a20.72 20.72 0 0 1-22.237-8.243 19.17 19.17 0 0 1-3.277-14.503 18 18 0 0 1 .624-2.435l.49-1.498 1.337.981a33.6 33.6 0 0 0 10.203 5.098l.97.294-.09.968a5.85 5.85 0 0 0 1.052 3.878 6.24 6.24 0 0 0 6.695 2.485 5.8 5.8 0 0 0 1.603-.704L69.27 76.28a5.43 5.43 0 0 0 2.45-3.631 5.8 5.8 0 0 0-.987-4.371 6.24 6.24 0 0 0-6.698-2.487 5.7 5.7 0 0 0-1.6.704l-9.953 6.345a19 19 0 0 1-5.296 2.326 20.72 20.72 0 0 1-22.237-8.243 19.17 19.17 0 0 1-3.277-14.502 17.99 17.99 0 0 1 8.13-12.052l26.081-16.623a19 19 0 0 1 5.3-2.329 20.72 20.72 0 0 1 22.237 8.243 19.17 19.17 0 0 1 3.277 14.503 18 18 0 0 1-.624 2.435l-.49 1.498-1.337-.98a33.6 33.6 0 0 0-10.203-5.1l-.97-.294.09-.968a5.86 5.86 0 0 0-1.052-3.878 6.24 6.24 0 0 0-6.696-2.485 5.8 5.8 0 0 0-1.602.704L37.73 51.72a5.42 5.42 0 0 0-2.449 3.63 5.79 5.79 0 0 0 .986 4.372 6.24 6.24 0 0 0 6.698 2.486 5.8 5.8 0 0 0 1.602-.704l9.952-6.342a19 19 0 0 1 5.295-2.328 20.72 20.72 0 0 1 22.237 8.242 19.17 19.17 0 0 1 3.277 14.503 18 18 0 0 1-8.13 12.053l-26.081 16.622a19 19 0 0 1-5.3 2.328"
+ style="fill:#fff" />
+</svg> \ No newline at end of file
diff --git a/src/lib/assets/favicon.png b/src/lib/assets/favicon.png
new file mode 100644
index 0000000..d7ac7dd
--- /dev/null
+++ b/src/lib/assets/favicon.png
Binary files differ
diff --git a/src/lib/assets/favicon.svg b/src/lib/assets/favicon.svg
new file mode 100644
index 0000000..45f50a4
--- /dev/null
+++ b/src/lib/assets/favicon.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" shape-rendering="crispEdges" viewBox="0 0 24 24" width="256" height="256"><rect fill="#bd61ce2f" x="13" y="1" width="1" height="1"/><rect fill="#bf64cc65" x="14" y="1" width="1" height="1"/><rect fill="#be63cc73" x="15" y="1" width="1" height="1"/><rect fill="#bf64cb54" x="16" y="1" width="1" height="1"/><rect fill="#bb5dc913" x="17" y="1" width="1" height="1"/><rect fill="#bf62cd34" x="11" y="2" width="1" height="1"/><rect fill="#bf64ccc4" x="12" y="2" width="1" height="1"/><rect fill="#bf64cc" x="13" y="2" width="1" height="1"/><rect fill="#bf64cc" x="14" y="2" width="1" height="1"/><rect fill="#bf64cc" x="15" y="2" width="1" height="1"/><rect fill="#bf64cc" x="16" y="2" width="1" height="1"/><rect fill="#be63ccfa" x="17" y="2" width="1" height="1"/><rect fill="#bf63cb94" x="18" y="2" width="1" height="1"/><rect fill="#bf6ad40c" x="19" y="2" width="1" height="1"/><rect fill="#b95cd00b" x="9" y="3" width="1" height="1"/><rect fill="#be64cc8e" x="10" y="3" width="1" height="1"/><rect fill="#bf64ccfc" x="11" y="3" width="1" height="1"/><rect fill="#bf64cc" x="12" y="3" width="1" height="1"/><rect fill="#bf64cc" x="13" y="3" width="1" height="1"/><rect fill="#bf64cc" x="14" y="3" width="1" height="1"/><rect fill="#c26bce" x="15" y="3" width="1" height="1"/><rect fill="#bf64cc" x="16" y="3" width="1" height="1"/><rect fill="#bf64cc" x="17" y="3" width="1" height="1"/><rect fill="#bf64cc" x="18" y="3" width="1" height="1"/><rect fill="#bf64cbd1" x="19" y="3" width="1" height="1"/><rect fill="#c369d211" x="20" y="3" width="1" height="1"/><rect fill="#bf63cd48" x="8" y="4" width="1" height="1"/><rect fill="#be63cbdf" x="9" y="4" width="1" height="1"/><rect fill="#bf64cc" x="10" y="4" width="1" height="1"/><rect fill="#bf64cc" x="11" y="4" width="1" height="1"/><rect fill="#c26bce" x="12" y="4" width="1" height="1"/><rect fill="#e1b5e7" x="13" y="4" width="1" height="1"/><rect fill="#fbf5fc" x="14" y="4" width="1" height="1"/><rect fill="#ffffff" x="15" y="4" width="1" height="1"/><rect fill="#f8edf9" x="16" y="4" width="1" height="1"/><rect fill="#daa5e1" x="17" y="4" width="1" height="1"/><rect fill="#bf64cc" x="18" y="4" width="1" height="1"/><rect fill="#bf64cc" x="19" y="4" width="1" height="1"/><rect fill="#be64cbb2" x="20" y="4" width="1" height="1"/><rect fill="#bb66cc0f" x="6" y="5" width="1" height="1"/><rect fill="#bf63cba4" x="7" y="5" width="1" height="1"/><rect fill="#bf64cc" x="8" y="5" width="1" height="1"/><rect fill="#bf64cc" x="9" y="5" width="1" height="1"/><rect fill="#bf64cc" x="10" y="5" width="1" height="1"/><rect fill="#d190db" x="11" y="5" width="1" height="1"/><rect fill="#f7ecf9" x="12" y="5" width="1" height="1"/><rect fill="#ffffff" x="13" y="5" width="1" height="1"/><rect fill="#ffffff" x="14" y="5" width="1" height="1"/><rect fill="#ffffff" x="15" y="5" width="1" height="1"/><rect fill="#ffffff" x="16" y="5" width="1" height="1"/><rect fill="#ffffff" x="17" y="5" width="1" height="1"/><rect fill="#ddade4" x="18" y="5" width="1" height="1"/><rect fill="#bf64cc" x="19" y="5" width="1" height="1"/><rect fill="#bf64cc" x="20" y="5" width="1" height="1"/><rect fill="#bd65ca3a" x="21" y="5" width="1" height="1"/><rect fill="#bb5dc913" x="5" y="6" width="1" height="1"/><rect fill="#be63cbd7" x="6" y="6" width="1" height="1"/><rect fill="#bf64cc" x="7" y="6" width="1" height="1"/><rect fill="#bf64cc" x="8" y="6" width="1" height="1"/><rect fill="#c571d0" x="9" y="6" width="1" height="1"/><rect fill="#e8c8ed" x="10" y="6" width="1" height="1"/><rect fill="#ffffff" x="11" y="6" width="1" height="1"/><rect fill="#ffffff" x="12" y="6" width="1" height="1"/><rect fill="#ffffff" x="13" y="6" width="1" height="1"/><rect fill="#f5e7f7" x="14" y="6" width="1" height="1"/><rect fill="#deafe5" x="15" y="6" width="1" height="1"/><rect fill="#f7ecf9" x="16" y="6" width="1" height="1"/><rect fill="#ffffff" x="17" y="6" width="1" height="1"/><rect fill="#fbf6fc" x="18" y="6" width="1" height="1"/><rect fill="#c26ccf" x="19" y="6" width="1" height="1"/><rect fill="#bf64cc" x="20" y="6" width="1" height="1"/><rect fill="#be64cb8b" x="21" y="6" width="1" height="1"/><rect fill="#be64ccaa" x="5" y="7" width="1" height="1"/><rect fill="#bf64cc" x="6" y="7" width="1" height="1"/><rect fill="#bf64cc" x="7" y="7" width="1" height="1"/><rect fill="#d497dd" x="8" y="7" width="1" height="1"/><rect fill="#faf3fb" x="9" y="7" width="1" height="1"/><rect fill="#ffffff" x="10" y="7" width="1" height="1"/><rect fill="#ffffff" x="11" y="7" width="1" height="1"/><rect fill="#fdfbfe" x="12" y="7" width="1" height="1"/><rect fill="#dfb2e6" x="13" y="7" width="1" height="1"/><rect fill="#c168cd" x="14" y="7" width="1" height="1"/><rect fill="#bf64cc" x="15" y="7" width="1" height="1"/><rect fill="#d59ade" x="16" y="7" width="1" height="1"/><rect fill="#fffeff" x="17" y="7" width="1" height="1"/><rect fill="#ffffff" x="18" y="7" width="1" height="1"/><rect fill="#cb81d5" x="19" y="7" width="1" height="1"/><rect fill="#bf64cc" x="20" y="7" width="1" height="1"/><rect fill="#bf63ccac" x="21" y="7" width="1" height="1"/><rect fill="#c164c821" x="4" y="8" width="1" height="1"/><rect fill="#be64cbfe" x="5" y="8" width="1" height="1"/><rect fill="#bf64cc" x="6" y="8" width="1" height="1"/><rect fill="#d496dd" x="7" y="8" width="1" height="1"/><rect fill="#fefeff" x="8" y="8" width="1" height="1"/><rect fill="#ffffff" x="9" y="8" width="1" height="1"/><rect fill="#ffffff" x="10" y="8" width="1" height="1"/><rect fill="#f0dcf3" x="11" y="8" width="1" height="1"/><rect fill="#ca7ed5" x="12" y="8" width="1" height="1"/><rect fill="#bf64cc" x="13" y="8" width="1" height="1"/><rect fill="#bf64cc" x="14" y="8" width="1" height="1"/><rect fill="#bf64cc" x="15" y="8" width="1" height="1"/><rect fill="#bf64cc" x="16" y="8" width="1" height="1"/><rect fill="#c97cd4" x="17" y="8" width="1" height="1"/><rect fill="#ecd0f0" x="18" y="8" width="1" height="1"/><rect fill="#c879d3" x="19" y="8" width="1" height="1"/><rect fill="#bf64cc" x="20" y="8" width="1" height="1"/><rect fill="#be64cca2" x="21" y="8" width="1" height="1"/><rect fill="#be63cb5f" x="4" y="9" width="1" height="1"/><rect fill="#bf64cc" x="5" y="9" width="1" height="1"/><rect fill="#bf64cc" x="6" y="9" width="1" height="1"/><rect fill="#f3e1f5" x="7" y="9" width="1" height="1"/><rect fill="#ffffff" x="8" y="9" width="1" height="1"/><rect fill="#fdfafd" x="9" y="9" width="1" height="1"/><rect fill="#daa5e1" x="10" y="9" width="1" height="1"/><rect fill="#bf65cc" x="11" y="9" width="1" height="1"/><rect fill="#bf64cc" x="12" y="9" width="1" height="1"/><rect fill="#bf64cc" x="13" y="9" width="1" height="1"/><rect fill="#c676d2" x="14" y="9" width="1" height="1"/><rect fill="#ca7ed4" x="15" y="9" width="1" height="1"/><rect fill="#c066cd" x="16" y="9" width="1" height="1"/><rect fill="#bf64cc" x="17" y="9" width="1" height="1"/><rect fill="#bf64cc" x="18" y="9" width="1" height="1"/><rect fill="#bf64cc" x="19" y="9" width="1" height="1"/><rect fill="#bf64cc" x="20" y="9" width="1" height="1"/><rect fill="#be65cc6a" x="21" y="9" width="1" height="1"/><rect fill="#bf64cc70" x="4" y="10" width="1" height="1"/><rect fill="#bf64cc" x="5" y="10" width="1" height="1"/><rect fill="#bf64cc" x="6" y="10" width="1" height="1"/><rect fill="#fbf5fc" x="7" y="10" width="1" height="1"/><rect fill="#ffffff" x="8" y="10" width="1" height="1"/><rect fill="#e8c6ec" x="9" y="10" width="1" height="1"/><rect fill="#bf64cc" x="10" y="10" width="1" height="1"/><rect fill="#bf64cc" x="11" y="10" width="1" height="1"/><rect fill="#cd86d7" x="12" y="10" width="1" height="1"/><rect fill="#f1def4" x="13" y="10" width="1" height="1"/><rect fill="#ffffff" x="14" y="10" width="1" height="1"/><rect fill="#ffffff" x="15" y="10" width="1" height="1"/><rect fill="#faf2fb" x="16" y="10" width="1" height="1"/><rect fill="#d69ddf" x="17" y="10" width="1" height="1"/><rect fill="#bf64cc" x="18" y="10" width="1" height="1"/><rect fill="#bf64cc" x="19" y="10" width="1" height="1"/><rect fill="#be63cbee" x="20" y="10" width="1" height="1"/><rect fill="#bb66cc0f" x="21" y="10" width="1" height="1"/><rect fill="#be65ca53" x="4" y="11" width="1" height="1"/><rect fill="#bf64cc" x="5" y="11" width="1" height="1"/><rect fill="#bf64cc" x="6" y="11" width="1" height="1"/><rect fill="#f2dff4" x="7" y="11" width="1" height="1"/><rect fill="#ffffff" x="8" y="11" width="1" height="1"/><rect fill="#faf4fb" x="9" y="11" width="1" height="1"/><rect fill="#d8a1e0" x="10" y="11" width="1" height="1"/><rect fill="#e4bfea" x="11" y="11" width="1" height="1"/><rect fill="#fefeff" x="12" y="11" width="1" height="1"/><rect fill="#ffffff" x="13" y="11" width="1" height="1"/><rect fill="#ffffff" x="14" y="11" width="1" height="1"/><rect fill="#ffffff" x="15" y="11" width="1" height="1"/><rect fill="#ffffff" x="16" y="11" width="1" height="1"/><rect fill="#fffeff" x="17" y="11" width="1" height="1"/><rect fill="#d394dc" x="18" y="11" width="1" height="1"/><rect fill="#bf64cc" x="19" y="11" width="1" height="1"/><rect fill="#be63ccf6" x="20" y="11" width="1" height="1"/><rect fill="#c369d211" x="21" y="11" width="1" height="1"/><rect fill="#c369d211" x="4" y="12" width="1" height="1"/><rect fill="#be63ccf6" x="5" y="12" width="1" height="1"/><rect fill="#bf64cc" x="6" y="12" width="1" height="1"/><rect fill="#d394dc" x="7" y="12" width="1" height="1"/><rect fill="#fffeff" x="8" y="12" width="1" height="1"/><rect fill="#ffffff" x="9" y="12" width="1" height="1"/><rect fill="#ffffff" x="10" y="12" width="1" height="1"/><rect fill="#ffffff" x="11" y="12" width="1" height="1"/><rect fill="#ffffff" x="12" y="12" width="1" height="1"/><rect fill="#fefeff" x="13" y="12" width="1" height="1"/><rect fill="#e4bfea" x="14" y="12" width="1" height="1"/><rect fill="#d8a0e0" x="15" y="12" width="1" height="1"/><rect fill="#faf4fb" x="16" y="12" width="1" height="1"/><rect fill="#ffffff" x="17" y="12" width="1" height="1"/><rect fill="#f2dff4" x="18" y="12" width="1" height="1"/><rect fill="#bf64cc" x="19" y="12" width="1" height="1"/><rect fill="#bf64cc" x="20" y="12" width="1" height="1"/><rect fill="#be65ca53" x="21" y="12" width="1" height="1"/><rect fill="#bf5fcf10" x="4" y="13" width="1" height="1"/><rect fill="#be63cbee" x="5" y="13" width="1" height="1"/><rect fill="#bf64cc" x="6" y="13" width="1" height="1"/><rect fill="#bf64cc" x="7" y="13" width="1" height="1"/><rect fill="#d69ddf" x="8" y="13" width="1" height="1"/><rect fill="#faf2fb" x="9" y="13" width="1" height="1"/><rect fill="#ffffff" x="10" y="13" width="1" height="1"/><rect fill="#ffffff" x="11" y="13" width="1" height="1"/><rect fill="#f1def4" x="12" y="13" width="1" height="1"/><rect fill="#cd86d7" x="13" y="13" width="1" height="1"/><rect fill="#bf64cc" x="14" y="13" width="1" height="1"/><rect fill="#bf64cc" x="15" y="13" width="1" height="1"/><rect fill="#e8c6ec" x="16" y="13" width="1" height="1"/><rect fill="#ffffff" x="17" y="13" width="1" height="1"/><rect fill="#fbf5fc" x="18" y="13" width="1" height="1"/><rect fill="#bf64cc" x="19" y="13" width="1" height="1"/><rect fill="#bf64cc" x="20" y="13" width="1" height="1"/><rect fill="#be63cc6e" x="21" y="13" width="1" height="1"/><rect fill="#be64cc6b" x="4" y="14" width="1" height="1"/><rect fill="#bf64cc" x="5" y="14" width="1" height="1"/><rect fill="#bf64cc" x="6" y="14" width="1" height="1"/><rect fill="#bf64cc" x="7" y="14" width="1" height="1"/><rect fill="#bf64cc" x="8" y="14" width="1" height="1"/><rect fill="#c066cd" x="9" y="14" width="1" height="1"/><rect fill="#c97cd4" x="10" y="14" width="1" height="1"/><rect fill="#c674d1" x="11" y="14" width="1" height="1"/><rect fill="#bf64cc" x="12" y="14" width="1" height="1"/><rect fill="#bf64cc" x="13" y="14" width="1" height="1"/><rect fill="#bf65cc" x="14" y="14" width="1" height="1"/><rect fill="#daa5e1" x="15" y="14" width="1" height="1"/><rect fill="#fdfafd" x="16" y="14" width="1" height="1"/><rect fill="#ffffff" x="17" y="14" width="1" height="1"/><rect fill="#f3e1f5" x="18" y="14" width="1" height="1"/><rect fill="#bf64cc" x="19" y="14" width="1" height="1"/><rect fill="#bf64cc" x="20" y="14" width="1" height="1"/><rect fill="#bd64cb5e" x="21" y="14" width="1" height="1"/><rect fill="#be64cba3" x="4" y="15" width="1" height="1"/><rect fill="#bf64cc" x="5" y="15" width="1" height="1"/><rect fill="#c879d3" x="6" y="15" width="1" height="1"/><rect fill="#ecd0f0" x="7" y="15" width="1" height="1"/><rect fill="#c97dd4" x="8" y="15" width="1" height="1"/><rect fill="#bf64cc" x="9" y="15" width="1" height="1"/><rect fill="#bf64cc" x="10" y="15" width="1" height="1"/><rect fill="#bf64cc" x="11" y="15" width="1" height="1"/><rect fill="#bf64cc" x="12" y="15" width="1" height="1"/><rect fill="#ca7ed5" x="13" y="15" width="1" height="1"/><rect fill="#f0dcf3" x="14" y="15" width="1" height="1"/><rect fill="#ffffff" x="15" y="15" width="1" height="1"/><rect fill="#ffffff" x="16" y="15" width="1" height="1"/><rect fill="#fefdfe" x="17" y="15" width="1" height="1"/><rect fill="#d395dc" x="18" y="15" width="1" height="1"/><rect fill="#bf64cc" x="19" y="15" width="1" height="1"/><rect fill="#be64cbfe" x="20" y="15" width="1" height="1"/><rect fill="#bd62cd1f" x="21" y="15" width="1" height="1"/><rect fill="#be63cbae" x="4" y="16" width="1" height="1"/><rect fill="#bf64cc" x="5" y="16" width="1" height="1"/><rect fill="#cb81d6" x="6" y="16" width="1" height="1"/><rect fill="#ffffff" x="7" y="16" width="1" height="1"/><rect fill="#fffeff" x="8" y="16" width="1" height="1"/><rect fill="#d59ade" x="9" y="16" width="1" height="1"/><rect fill="#bf64cc" x="10" y="16" width="1" height="1"/><rect fill="#c168cd" x="11" y="16" width="1" height="1"/><rect fill="#dfb2e6" x="12" y="16" width="1" height="1"/><rect fill="#fdfbfe" x="13" y="16" width="1" height="1"/><rect fill="#ffffff" x="14" y="16" width="1" height="1"/><rect fill="#ffffff" x="15" y="16" width="1" height="1"/><rect fill="#faf3fb" x="16" y="16" width="1" height="1"/><rect fill="#d496dd" x="17" y="16" width="1" height="1"/><rect fill="#bf64cc" x="18" y="16" width="1" height="1"/><rect fill="#bf64cc" x="19" y="16" width="1" height="1"/><rect fill="#be63cca7" x="20" y="16" width="1" height="1"/><rect fill="#bf64cb8c" x="4" y="17" width="1" height="1"/><rect fill="#bf64cc" x="5" y="17" width="1" height="1"/><rect fill="#c36dcf" x="6" y="17" width="1" height="1"/><rect fill="#fbf6fc" x="7" y="17" width="1" height="1"/><rect fill="#ffffff" x="8" y="17" width="1" height="1"/><rect fill="#f7ecf9" x="9" y="17" width="1" height="1"/><rect fill="#deafe5" x="10" y="17" width="1" height="1"/><rect fill="#f5e7f7" x="11" y="17" width="1" height="1"/><rect fill="#ffffff" x="12" y="17" width="1" height="1"/><rect fill="#ffffff" x="13" y="17" width="1" height="1"/><rect fill="#ffffff" x="14" y="17" width="1" height="1"/><rect fill="#e8c8ed" x="15" y="17" width="1" height="1"/><rect fill="#c571d0" x="16" y="17" width="1" height="1"/><rect fill="#bf64cc" x="17" y="17" width="1" height="1"/><rect fill="#bf64cc" x="18" y="17" width="1" height="1"/><rect fill="#bf64cbd5" x="19" y="17" width="1" height="1"/><rect fill="#b863c612" x="20" y="17" width="1" height="1"/><rect fill="#bf66cc3c" x="4" y="18" width="1" height="1"/><rect fill="#bf64cc" x="5" y="18" width="1" height="1"/><rect fill="#bf64cc" x="6" y="18" width="1" height="1"/><rect fill="#ddaee4" x="7" y="18" width="1" height="1"/><rect fill="#ffffff" x="8" y="18" width="1" height="1"/><rect fill="#ffffff" x="9" y="18" width="1" height="1"/><rect fill="#ffffff" x="10" y="18" width="1" height="1"/><rect fill="#ffffff" x="11" y="18" width="1" height="1"/><rect fill="#ffffff" x="12" y="18" width="1" height="1"/><rect fill="#f7ecf9" x="13" y="18" width="1" height="1"/><rect fill="#d190db" x="14" y="18" width="1" height="1"/><rect fill="#bf64cc" x="15" y="18" width="1" height="1"/><rect fill="#bf64cc" x="16" y="18" width="1" height="1"/><rect fill="#bf64cc" x="17" y="18" width="1" height="1"/><rect fill="#bf63cba4" x="18" y="18" width="1" height="1"/><rect fill="#b65bc80e" x="19" y="18" width="1" height="1"/><rect fill="#be64cbb2" x="5" y="19" width="1" height="1"/><rect fill="#bf64cc" x="6" y="19" width="1" height="1"/><rect fill="#bf64cc" x="7" y="19" width="1" height="1"/><rect fill="#daa5e1" x="8" y="19" width="1" height="1"/><rect fill="#f8edf9" x="9" y="19" width="1" height="1"/><rect fill="#ffffff" x="10" y="19" width="1" height="1"/><rect fill="#fbf5fc" x="11" y="19" width="1" height="1"/><rect fill="#e1b5e7" x="12" y="19" width="1" height="1"/><rect fill="#c26bce" x="13" y="19" width="1" height="1"/><rect fill="#bf64cc" x="14" y="19" width="1" height="1"/><rect fill="#bf64cc" x="15" y="19" width="1" height="1"/><rect fill="#be63cbdf" x="16" y="19" width="1" height="1"/><rect fill="#bf63cd48" x="17" y="19" width="1" height="1"/><rect fill="#c369d211" x="5" y="20" width="1" height="1"/><rect fill="#bf64cbd1" x="6" y="20" width="1" height="1"/><rect fill="#bf64cc" x="7" y="20" width="1" height="1"/><rect fill="#bf64cc" x="8" y="20" width="1" height="1"/><rect fill="#bf64cc" x="9" y="20" width="1" height="1"/><rect fill="#c26bce" x="10" y="20" width="1" height="1"/><rect fill="#bf64cc" x="11" y="20" width="1" height="1"/><rect fill="#bf64cc" x="12" y="20" width="1" height="1"/><rect fill="#bf64cc" x="13" y="20" width="1" height="1"/><rect fill="#bf64ccfc" x="14" y="20" width="1" height="1"/><rect fill="#be64cc8e" x="15" y="20" width="1" height="1"/><rect fill="#b95cd00b" x="16" y="20" width="1" height="1"/><rect fill="#bf6ad40c" x="6" y="21" width="1" height="1"/><rect fill="#be64cc93" x="7" y="21" width="1" height="1"/><rect fill="#bf64cbf9" x="8" y="21" width="1" height="1"/><rect fill="#bf64cc" x="9" y="21" width="1" height="1"/><rect fill="#bf64cc" x="10" y="21" width="1" height="1"/><rect fill="#bf64cc" x="11" y="21" width="1" height="1"/><rect fill="#bf64cc" x="12" y="21" width="1" height="1"/><rect fill="#be63cbc3" x="13" y="21" width="1" height="1"/><rect fill="#bf62cd34" x="14" y="21" width="1" height="1"/><rect fill="#c369d211" x="8" y="22" width="1" height="1"/><rect fill="#be65ca53" x="9" y="22" width="1" height="1"/><rect fill="#bf64cc70" x="10" y="22" width="1" height="1"/><rect fill="#bd62ca62" x="11" y="22" width="1" height="1"/><rect fill="#bd64c92b" x="12" y="22" width="1" height="1"/></svg> \ No newline at end of file
diff --git a/src/lib/index.ts b/src/lib/index.ts
new file mode 100644
index 0000000..856f2b6
--- /dev/null
+++ b/src/lib/index.ts
@@ -0,0 +1 @@
+// place files you want to import through the `$lib` alias in this folder.
diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte
new file mode 100644
index 0000000..20f8d04
--- /dev/null
+++ b/src/routes/+layout.svelte
@@ -0,0 +1,11 @@
+<script lang="ts">
+ import favicon from '$lib/assets/favicon.svg';
+
+ let { children } = $props();
+</script>
+
+<svelte:head>
+ <link rel="icon" href={favicon} />
+</svelte:head>
+
+{@render children?.()}
diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte
new file mode 100644
index 0000000..7cc3eb7
--- /dev/null
+++ b/src/routes/+page.svelte
@@ -0,0 +1,202 @@
+<!--
+MIT License
+
+Copyright (c) 2025 memdmp
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+ -->
+
+<script lang="ts">
+ import Alerts, { alert, confirm } from '$lib/Alerts.svelte';
+ import { onMount } from 'svelte';
+
+ let fileInput = $state(null as unknown as HTMLInputElement);
+ let fileName = $state('');
+ let fileRaw = $state(null as null | File);
+ let canvas = $state(null as unknown as HTMLCanvasElement);
+ let imgUrl = $state('');
+ let output = $state('');
+ $effect(() => {
+ if (fileInput?.files?.length) {
+ const file = fileInput.files![0];
+ fileName = file.name;
+ fileRaw = file ?? null;
+ }
+ });
+ onMount(() => {
+ const el = document.createElement('canvas');
+ const ctx = el.getContext('2d');
+ if (!ctx) {
+ alert(
+ "Could not create 2d Canvas Context. This application will not work. Make sure any privacy-resistance features are disabled and your browser isn't ancient.",
+ {
+ title: 'Fatal Error',
+ }
+ );
+ } else {
+ if (
+ JSON.stringify(ctx.getImageData(0, 0, 32, 32).data) !==
+ JSON.stringify(ctx.getImageData(0, 0, 32, 32).data)
+ ) {
+ alert(
+ "Canvas readbacks not identical. This application may not work correctly. Make sure any privacy-resistance features are disabled and your browser isn't ancient.",
+ {
+ title: 'Error',
+ }
+ );
+ }
+ }
+ });
+ const update = async (fileRaw: File) => {
+ const blob = new Blob([await fileRaw.bytes()]);
+ const blobUrl = URL.createObjectURL(blob);
+ imgUrl = blobUrl;
+ };
+ $effect(() => {
+ if (fileRaw) update(fileRaw);
+ else imgUrl = '';
+ });
+ const toHex = (v: number) => Math.floor(v).toString(16).padStart(2, '0');
+ const save = (
+ data: [r: number, g: number, b: number, a: number][],
+ width: number,
+ height: number
+ ) => {
+ let content = `<svg xmlns="http://www.w3.org/2000/svg" shape-rendering="crispEdges" viewBox=${JSON.stringify(`0 0 ${width} ${height}`)} width=${JSON.stringify('' + width)} height=${JSON.stringify('' + height)}>`;
+ let item: (typeof data)[0];
+ let x = 0;
+ let y = 0;
+ while ((item = data.shift()!)) {
+ if (++x >= width) (x = 0), y++;
+ if (item[3] !== 0)
+ content += `<rect fill="#${toHex(item[0])}${toHex(item[1])}${toHex(item[2])}${item[3] !== 255 ? toHex(item[3]) : ''}" x=${JSON.stringify('' + x)} y=${JSON.stringify('' + y)} width="1" height="1"/>`;
+ }
+ content += '</svg>';
+ output = URL.createObjectURL(
+ new Blob([content], {
+ type: 'image/svg+xml',
+ })
+ );
+ };
+</script>
+
+<svelte:head>
+ <title>Bitmap to Pixelated SVG</title>
+ <link rel="stylesheet" href="/cs16.css" />
+</svelte:head>
+
+<Alerts />
+<div>
+ <h1>PixelSVG</h1>
+ <div>
+ <label style="display: flex; gap:4px;">
+ <span class="cs-btn"
+ >{fileName ? `File: ${fileName}` : 'Upload a File'}</span
+ >
+ <img
+ src={imgUrl}
+ alt=""
+ style="height: 24px"
+ onload={async (e) => {
+ const imgEl = e.currentTarget as HTMLImageElement;
+ const rect = {
+ width: imgEl.naturalWidth,
+ height: imgEl.naturalHeight,
+ };
+ if (
+ rect.width * rect.height > 65536 &&
+ !(await confirm(
+ `This image isn't small; it's made up of ${rect.width * rect.height} pixels. The outputted file could be up to ${((`<svg xmlns="http://www.w3.org/2000/svg" shape-rendering="crispEdges" viewBox=${JSON.stringify(`0 0 ${rect.width} ${rect.height}`)} width=${JSON.stringify('' + rect.width)} height=${JSON.stringify('' + rect.height)}></svg>`.length + `<rect fill="#ffffffff" x="${rect.width}" y="${rect.height}" width="1" height="1"/>`.length * rect.width * rect.height) / 1024 / 1024).toFixed(1)} MB large. It may crash your browser. Are you sure you wish to continue?`,
+ {
+ title: 'Confirmation',
+ }
+ ))
+ )
+ return (imgUrl = ''), (fileName = '');
+ canvas.width = rect.width;
+ canvas.height = rect.height;
+ const ctx = canvas.getContext('2d', {
+ alpha: true,
+ colorSpace: 'display-p3',
+ });
+ if (!ctx) throw new Error('no 2d context obtainable');
+ try {
+ ctx.drawImage(e.currentTarget as HTMLImageElement, 0, 0);
+ } catch (error) {
+ await alert(
+ "Failed to draw image to canvas. The image's data may be invalid or the image may be too big. Check the Console.",
+ {
+ title: 'Failed to draw image',
+ }
+ );
+ throw error;
+ }
+ const data = ctx.getImageData(0, 0, rect.width, rect.height, {
+ colorSpace: 'display-p3',
+ });
+ let out = [] as [r: number, g: number, b: number, a: number][];
+ for (let i = 0; i < data.data.length; i += 4) {
+ const r = data.data[i + 0];
+ const g = data.data[i + 1];
+ const b = data.data[i + 2];
+ const a = data.data[i + 3];
+ out.push([r, g, b, a]);
+ }
+ save(out, rect.width, rect.height);
+ }}
+ onerror={(e) => {
+ if (imgUrl !== '')
+ alert(
+ 'Failed to load the image into an HTML Image Element. Please make sure the image you provided is valid and in a format your browser understands.',
+ {
+ title: 'Failed to load image',
+ }
+ );
+ }}
+ />
+ <input
+ type="file"
+ bind:this={fileInput}
+ onchange={() => {
+ if (fileInput?.files?.length) {
+ const file = fileInput.files![0];
+ fileName = file.name;
+ fileRaw = file ?? null;
+ }
+ }}
+ style="opacity:0;position:fixed;top:0;left:0;width:0;height:0;pointer-events:none;"
+ />
+ </label>
+ </div>
+ {#if output}
+ <div style="margin-top:12px;margin-bottom:12px;">
+ Output:<br />
+ <a href={output} target="_blank"
+ ><img src={output} alt="could not render" /> (open)</a
+ >
+ </div>
+ {/if}
+ <div style="opacity:0.5">
+ {imgUrl ? 'Canvas:' : ''}<br /><canvas
+ bind:this={canvas}
+ width="0"
+ height="0"
+ ></canvas>
+ </div>
+</div>
diff --git a/static/cs16.css b/static/cs16.css
new file mode 100644
index 0000000..60a7ad9
--- /dev/null
+++ b/static/cs16.css
@@ -0,0 +1,684 @@
+:root {
+ --bg: #4a5942;
+ --secondary-bg: #3e4637;
+ --accent: #c4b550;
+ --secondary-accent: #958831;
+ --text: #dedfd6;
+ --secondary-text: #d8ded3;
+ --text-3: #a0aa95;
+ --border-light: #8c9284;
+ --border-dark: #292c21;
+ --disabled-text: #292c21;
+ --disabled-text-shadow: #75806f;
+ --outline: #000;
+ --slider: #7f8c7f;
+ --slider-bg: #1f1f1f;
+ --scrollbar-track: #5a6a50;
+}
+@font-face {
+ font-family: ArialPixel;
+ font-style: normal;
+ font-weight: 400;
+ src: url(https://cdn.jsdelivr.net/gh/ekmas/cs16.css@main/ArialPixel.ttf)
+ format('truetype');
+}
+.cs {
+ & {
+ background-color: var(--bg);
+ color: var(--text);
+ font-family: ArialPixel, system-ui, sans-serif;
+ font-weight: 400;
+ line-height: 1.5;
+ }
+ *,
+ :after,
+ :before {
+ box-sizing: border-box;
+ }
+ * {
+ margin: 0;
+ padding: 0;
+ }
+ button,
+ input,
+ select,
+ textarea {
+ font: inherit;
+ }
+ h1,
+ h2,
+ h3,
+ h4,
+ h5,
+ h6,
+ p {
+ font-weight: 400;
+ overflow-wrap: break-word;
+ }
+ ::-webkit-scrollbar {
+ width: 18px;
+ }
+ ::-webkit-scrollbar-track {
+ background-color: var(--scrollbar-track);
+ border: 1px solid var(--border-dark);
+ border-left: 0;
+ width: 18px;
+ }
+ ::-webkit-scrollbar-thumb {
+ background-color: var(--bg);
+ border: 1px solid;
+ border-color: var(--border-light) var(--border-dark) var(--border-dark)
+ var(--border-light);
+ width: 17px;
+ }
+ ::-webkit-scrollbar-corner {
+ background-color: var(--scrollbar-track);
+ }
+ ::-webkit-scrollbar-button:vertical:end:increment,
+ ::-webkit-scrollbar-button:vertical:start:decrement {
+ display: block;
+ }
+ ::-webkit-scrollbar-button:vertical:end:decrement,
+ ::-webkit-scrollbar-button:vertical:end:increment,
+ ::-webkit-scrollbar-button:vertical:start:decrement,
+ ::-webkit-scrollbar-button:vertical:start:increment {
+ background-repeat: no-repeat;
+ height: 17px;
+ }
+ ::-webkit-scrollbar-button:vertical:start {
+ background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='15' height='16' viewBox='0 0 15 16'%3E%3Cpath fill='%23a0aa95' d='M5 9h1v1H5m1-1h1v1H6m0-2h1v1H6m1 0h1v1H7m0-2h1v1H7m0-2h1v1H7m1 1h1v1H8m0-2h1v1H8m0-2h1v1H8m0-2h1v1H8m1 2h1v1H9m0-2h1v1H9m0-2h1v1H9m1 1h1v1h-1m0-2h1v1h-1m1 0h1v1h-1'/%3E%3C/svg%3E");
+ }
+ ::-webkit-scrollbar-button:vertical:end,
+ ::-webkit-scrollbar-button:vertical:start {
+ border: 1px solid;
+ border-color: var(--border-light) var(--border-dark) var(--border-dark)
+ var(--border-light);
+ }
+ ::-webkit-scrollbar-button:vertical:end:active,
+ ::-webkit-scrollbar-button:vertical:start:active {
+ border-color: var(--border-dark) var(--border-light) var(--border-light)
+ var(--border-dark);
+ }
+ ::-webkit-scrollbar-button:vertical:start:active,
+ ::-webkit-scrollbar-button:vertical:start:hover {
+ background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='15' height='16' viewBox='0 0 15 16'%3E%3Cpath fill='%23fff' d='M5 9h1v1H5m1-1h1v1H6m1-1h1v1H7m1-1h1v1H8m1-1h1v1H9m1-1h1v1h-1m1-1h1v1h-1M6 8h1v1H6m1-1h1v1H7m1-1h1v1H8m1-1h1v1H9m1-1h1v1h-1M7 7h1v1H7m1-1h1v1H8m1-1h1v1H9M8 6h1v1H8'/%3E%3C/svg%3E");
+ }
+ ::-webkit-scrollbar-button:vertical:end {
+ background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='15' height='16' viewBox='0 0 15 16'%3E%3Cpath fill='%23a0aa95' d='M5 6h1v1H5m1-1h1v1H6m0 0h1v1H6m1-1h1v1H7m0 0h1v1H7m1 0h1v1H8m0-2h1v1H8m0-2h1v1H8M7 6h1v1H7m1-1h1v1H8m3-1h1v1h-1m-1-1h1v1h-1M9 6h1v1H9m0 1h1v1H9m0-2h1v1H9m1-1h1v1h-1'/%3E%3C/svg%3E");
+ }
+ ::-webkit-scrollbar-button:vertical:end:active {
+ background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='15' height='16' viewBox='0 0 15 16'%3E%3Cpath fill='%23fff' d='M5 6h1v1H5m6-1h1v1h-1m-1-1h1v1h-1M9 6h1v1H9M8 6h1v1H8M7 6h1v1H7M6 6h1v1H6m0 0h1v1H6m4-1h1v1h-1M9 7h1v1H9M8 7h1v1H8M7 7h1v1H7m0 0h1v1H7m2-1h1v1H9M8 9h1v1H8m0-2h1v1H8'/%3E%3C/svg%3E");
+ }
+ .cs-btn,
+ button:not(.default-btn),
+ input[type='submit']:not(.default-btn) {
+ background-color: var(--bg);
+ border: 1px solid;
+ border-color: var(--border-light) var(--border-dark) var(--border-dark)
+ var(--border-light);
+ color: #fff;
+ font-size: 16px;
+ line-height: 15px;
+ padding: 4px 5px 3px;
+ user-select: none;
+ &.close {
+ background: no-repeat 50%;
+ background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16'%3E%3Cpath fill='%238c9284' d='M3 3h1v1H3m1-1h1v1H4M3 4h1v1H3m1-1h1v1H4m0 0h1v1H4m1-1h1v1H5m0-2h1v1H5m0 1h1v1H5m1-1h1v1H6m0-2h1v1H6m0 1h1v1H6m0 0h1v1H6m1-1h1v1H7m0-2h1v1H7m0-2h1v1H7m1-1h1v1H8m0 0h1v1H8m0 0h1v1H8m0-4h1v1H8m1-1h1v1H9m0 0h1v1H9m0-3h1v1H9m1-1h1v1h-1m0 0h1v1h-1m0-3h1v1h-1m1-1h1v1h-1m0 0h1v1h-1M9 8h1v1H9m0 0h1v1H9M8 9h1v1H8m2-1h1v1h-1m0 0h1v1h-1m-1-1h1v1H9m2-1h1v1h-1m0 0h1v1h-1m-1-1h1v1h-1M5 8h1v1H5m0 0h1v1H5m1-1h1v1H6M4 9h1v1H4m0 0h1v1H4m1-1h1v1H5m-2-1h1v1H3m0 0h1v1H3m1-1h1v1H4'/%3E%3C/svg%3E");
+ height: 18px;
+ padding: 0;
+ width: 18px;
+ }
+ &:focus-visible {
+ outline: 1px solid var(--outline);
+ padding: 3px 4px 2px;
+ &.close {
+ outline: 0;
+ padding: 0;
+ }
+ }
+ &:active {
+ border-color: var(--border-dark) var(--border-light) var(--border-light)
+ var(--border-dark);
+ }
+ &:disabled {
+ color: var(--disabled-text);
+ pointer-events: none;
+ text-shadow: var(--disabled-text-shadow) 1px 1px;
+ }
+ }
+ hr:not(.default-hr) {
+ border-bottom-color: var(--border-light);
+ border-left: 0;
+ border-right: 0;
+ border-top-color: var(--border-dark);
+ }
+ .cs-checkbox:not(input) {
+ position: relative;
+ }
+ .cs-checkbox input,
+ input.cs-checkbox,
+ input[type='checkbox']:not(.default-checkbox) {
+ position: absolute;
+ clip: rect(1px, 1px, 1px, 1px);
+ border: 0;
+ height: 1px;
+ overflow: hidden;
+ padding: 0;
+ width: 1px;
+ &:focus:not(:focus-visible) {
+ outline: none;
+ }
+ &:focus-visible + .cs-checkbox__label,
+ &:focus-visible + label {
+ outline: dotted 2px var(--outline);
+ outline-offset: 3px;
+ }
+ &:checked + .cs-checkbox__label,
+ &:checked + label {
+ color: var(--accent);
+ &:before {
+ background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 10 10'%3E%3Cpath fill='%23c4b550' d='M2 6h1v1H2m1-2h1v1H3M2 5h1v1H2m0-2h1v1H2m1 1h1v1H3m0 0h1v1H3m1-2h1v1H4m0 0h1v1H4m0 0h1v1H4m1-2h1v1H5m0-2h1v1H5m0-2h1v1H5m1-2h1v1H6m0 0h1v1H6m0 0h1v1H6m1-2h1v1H7m0-2h1v1H7m0-2h1v1H7m1 0h1v1H8m0-2h1v1H8m0-2h1v1H8'/%3E%3C/svg%3E");
+ }
+ }
+ }
+ .cs-checkbox input + label,
+ .cs-checkbox__label,
+ input.cs-checkbox + label,
+ input[type='checkbox']:not(.default-checkbox) + label,
+ label.cs-checkbox:has(input),
+ label:has(.cs-checkbox),
+ label:not(.default-checkbox):has(
+ input[type='checkbox']:not(.default-checkbox)
+ ) {
+ color: var(--secondary--text);
+ cursor: pointer;
+ display: inline-block;
+ line-height: 15px;
+ user-select: none;
+ &:before {
+ background-color: var(--secondary-bg);
+ border: 1px solid;
+ border-color: var(--border-dark) var(--border-light) var(--border-light)
+ var(--border-dark);
+ content: '';
+ display: inline-block;
+ height: 12px;
+ margin-right: 7px;
+ vertical-align: middle;
+ width: 12px;
+ }
+ &:hover {
+ color: #fff;
+ }
+ }
+ label.cs-checkbox:has(input),
+ label:has(.cs-checkbox),
+ label:not(.default-checkbox):has(
+ input[type='checkbox']:not(.default-checkbox)
+ ) {
+ position: relative;
+ &:has(.cs-checkbox:focus-visible),
+ &:has(input:not(.default-checkbox):focus-visible) {
+ outline: dotted 2px var(--outline);
+ outline-offset: 3px;
+ }
+ &:before {
+ margin-right: 3px;
+ }
+ &:has(.cs-checkbox:checked),
+ &:has(input:not(.default-checkbox):checked) {
+ color: var(--accent);
+ &:before {
+ background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 10 10'%3E%3Cpath fill='%23c4b550' d='M2 6h1v1H2m1-2h1v1H3M2 5h1v1H2m0-2h1v1H2m1 1h1v1H3m0 0h1v1H3m1-2h1v1H4m0 0h1v1H4m0 0h1v1H4m1-2h1v1H5m0-2h1v1H5m0-2h1v1H5m1-2h1v1H6m0 0h1v1H6m0 0h1v1H6m1-2h1v1H7m0-2h1v1H7m0-2h1v1H7m1 0h1v1H8m0-2h1v1H8m0-2h1v1H8'/%3E%3C/svg%3E");
+ }
+ }
+ }
+ .cs-input,
+ input:is(
+ [type='text'],
+ [type='number'],
+ [type='email'],
+ [type='date'],
+ [type='datetime-local'],
+ [type='month'],
+ [type='password'],
+ [type='search'],
+ [type='tel'],
+ [type='url'],
+ [type='week'],
+ [type='datetime'],
+ [type='input']
+ ):not(.default-input) {
+ background-color: var(--secondary-bg);
+ border: 1px solid;
+ border-color: var(--border-dark) var(--border-light) var(--border-light)
+ var(--border-dark);
+ color: var(--secondary--text);
+ font-size: 1rem;
+ line-height: 1.0625rem;
+ outline: 0;
+ padding: 3px 2px 2px;
+ &:focus + .cs-input__label,
+ &:focus + label {
+ color: var(--accent);
+ }
+ &::-moz-selection {
+ background-color: var(--secondary-accent);
+ color: #fff;
+ }
+ &::selection {
+ background-color: var(--secondary-accent);
+ color: #fff;
+ }
+ &:disabled {
+ background-color: var(--bg);
+ color: var(--text-3);
+ pointer-events: none;
+ }
+ &:disabled + .cs-input__label,
+ &:disabled + label {
+ color: var(--disabled-text);
+ pointer-events: none;
+ text-shadow: var(--disabled-text-shadow) 1px 1px;
+ }
+ }
+ .cs-input__label,
+ label:has(
+ input:is(
+ [type='text'],
+ [type='number'],
+ [type='email'],
+ [type='date'],
+ [type='datetime-local'],
+ [type='month'],
+ [type='password'],
+ [type='search'],
+ [type='tel'],
+ [type='url'],
+ [type='week'],
+ [type='datetime'],
+ [type='input']
+ ):not(.default-input)
+ ):not(.default-input) {
+ color: var(--secondary--text);
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ user-select: none;
+ &:has(input:not(.default-input):focus) {
+ color: var(--accent);
+ }
+ &:has(input:not(.default-input):disabled) {
+ color: var(--disabled-text);
+ pointer-events: none;
+ text-shadow: var(--disabled-text-shadow) 1px 1px;
+ }
+ }
+ .cs-select,
+ select:not(.default-select) {
+ appearance: none;
+ background-color: var(--secondary-bg);
+ background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='7' height='4' viewBox='0 0 7 4'%3E%3Cpath fill='%23a0aa95' d='M0 0h1v1H0m1-1h1v1H1m0 0h1v1H1m1-1h1v1H2m0 0h1v1H2m1-1h1v1H3m0 0h1v1H3m0-3h1v1H3M2 0h1v1H2m1-1h1v1H3m1-1h1v1H4m0 1h1v1H4m0-2h1v1H4m1-1h1v1H5m0-2h1v1H5m1-1h1v1H6'/%3E%3C/svg%3E");
+ background-position: right 6px top 50%;
+ background-repeat: no-repeat;
+ background-size: 7px auto;
+ border: 1px solid;
+ border-color: var(--border-dark) var(--border-light) var(--border-light)
+ var(--border-dark);
+ border-radius: 0;
+ color: var(--secondary--text);
+ line-height: 15px;
+ min-width: 150px;
+ outline: 0;
+ padding: 5px 15px 5px 3px;
+ user-select: none;
+ &:focus-within,
+ &:hover {
+ background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='7' height='4' viewBox='0 0 7 4'%3E%3Cpath fill='%23fff' d='M0 0h1v1H0m1-1h1v1H1m0 0h1v1H1m1-1h1v1H2m0 0h1v1H2m1 0h1v1H3m0-2h1v1H3m0-2h1v1H3M2 0h1v1H2m1-1h1v1H3m1-1h1v1H4m0 1h1v1H4m0-2h1v1H4m1-1h1v1H5m0-2h1v1H5m1-1h1v1H6'/%3E%3C/svg%3E");
+ }
+ option {
+ background-color: var(--bg);
+ color: var(--text-3);
+ }
+ }
+ .cs-select__label,
+ label:has(select:not(.default-select)):not(.default-select-label) {
+ color: var(--secondary--text);
+ font-size: 16px;
+ line-height: 15px;
+ user-select: none;
+ }
+ .cs-fieldset,
+ fieldset:not(.default-fieldset) {
+ border: none;
+ user-select: none;
+ legend {
+ color: var(--secondary--text);
+ margin-bottom: 10px;
+ }
+ > div {
+ padding-left: 10px;
+ }
+ &:disabled {
+ input[type='radio'] {
+ + label {
+ color: var(--disabled-text);
+ pointer-events: none;
+ text-shadow: var(--disabled-text-shadow) 1px 1px;
+ }
+ }
+ legend {
+ color: var(--disabled-text);
+ pointer-events: none;
+ text-shadow: var(--disabled-text-shadow) 1px 1px;
+ }
+ }
+ input[type='radio'] {
+ opacity: 0;
+ + label {
+ color: var(--secondary--text);
+ cursor: pointer;
+ font-size: 16px;
+ line-height: 15px;
+ position: relative;
+ &:before {
+ background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%23889180' d='M10 2h1v1h-1m0 0h1v1h-1m1 0h1v1h-1m0 0h1v1h-1m0 0h1v1h-1m0 0h1v1h-1m-1 0h1v1h-1m0 0h1v1h-1m-2 0h1v1H8m1-1h1v1H9m-2 0h1v1H7m-1-1h1v1H6m-1-1h1v1H5m-3-2h1v1H2m1-1h1v1H3m1 0h1v1H4'/%3E%3Cpath fill='%23292c21' d='M1 2h1v1H1m0 0h1v1H1m1-3h1v1H2m1-1h1v1H3m1-2h1v1H4m1-1h1v1H5m1-1h1v1H6m1-1h1v1H7m1 0h1v1H8m1-1h1v1H9M0 4h1v1H0m0 0h1v1H0m0 0h1v1H0m0 0h1v1H0m1 0h1v1H1m0 0h1v1H1'/%3E%3Cpath fill='%233e4637' d='M4 1h1v1H4m1-1h1v1H5m1-1h1v1H6m1-1h1v1H7m1 0h1v1H8m1-1h1v1H9m0 0h1v1H9m0 0h1v1H9m1-1h1v1h-1m0 0h1v1h-1m0 0h1v1h-1m0 0h1v1h-1M9 7h1v1H9m0 0h1v1H9m0 0h1v1H9M8 9h1v1H8M7 9h1v1H7m0 0h1v1H7m-1-1h1v1H6m-1-1h1v1H5m-1-1h1v1H4m2-2h1v1H6M5 9h1v1H5M4 9h1v1H4M3 9h1v1H3M2 9h1v1H2m0-2h1v1H2M1 7h1v1H1m0-4h1v1H1m1-2h1v1H2m0-2h1v1H2m1-1h1v1H3m1-1h1v1H4m1-1h1v1H5m1-1h1v1H6m1-1h1v1H7M3 3h1v1H3M2 4h1v1H2m0 0h1v1H2M1 5h1v1H1m0 0h1v1H1m1-1h1v1H2m0 0h1v1H2m1 0h1v1H3m0-2h1v1H3m0-2h1v1H3m0-2h1v1H3m0-2h1v1H3m1-2h1v1H4m1-1h1v1H5m0 0h1v1H5M4 8h1v1H4m0-2h1v1H4m0-2h1v1H4m0-3h1v1H4m0 0h1v1H4m1-1h1v1H5m0 0h1v1H5m0 0h1v1H5m0 0h1v1H5m1-1h1v1H6m0-2h1v1H6m0-2h1v1H6m0-4h1v1H6m0 0h1v1H6m0 0h1v1H6m1 1h1v1H7m0 0h1v1H7m1-1h1v1H8m0-2h1v1H8M7 6h1v1H7m0-2h1v1H7m0-2h1v1H7m0-2h1v1H7m1-1h1v1H8m0 0h1v1H8m0 0h1v1H8m0 0h1v1H8m1-1h1v1H9m0-2h1v1H9'/%3E%3C/svg%3E");
+ height: 12px;
+ left: -25px;
+ top: 1px;
+ width: 12px;
+ }
+ &:after,
+ &:before {
+ content: '';
+ position: absolute;
+ }
+ &:after {
+ height: 6px;
+ left: -22px;
+ top: 4px;
+ width: 6px;
+ }
+ }
+ &:checked {
+ + label {
+ color: var(--accent);
+ }
+ + label:after {
+ background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='6' height='6' viewBox='0 0 6 6'%3E%3Cpath fill='%23c4b550' d='M1 0h1v1H1m2-1h1v1H3m1-1h1v1H4m0 0h1v1H4m1-1h1v1H5m0 0h1v1H5m0 0h1v1H5m0 0h1v1H5M4 5h1v1H4M3 5h1v1H3M2 5h1v1H2M1 5h1v1H1M0 4h1v1H0m0-2h1v1H0m0-2h1v1H0m1-1h1v1H1m0 0h1v1H1m0 0h1v1H1m1-1h1v1H2m0-2h1v1H2m0-4h1v1H2m0 0h1v1H2m1-1h1v1H3m0 1h1v1H3m0 0h1v1H3m1-1h1v1H4m0-2h1v1H4m0-2h1v1H4M3 2h1v1H3M2 2h1v1H2M1 1h1v1H1M0 1h1v1H0'/%3E%3C/svg%3E");
+ }
+ }
+ }
+ }
+ .cs-slider {
+ display: flex;
+ flex-direction: column-reverse;
+ user-select: none;
+ width: 150px;
+ input {
+ -webkit-appearance: none;
+ appearance: none;
+ background: var(--slider-bg);
+ border: 1px solid;
+ border-color: var(--border-dark) var(--border-light) var(--border-light)
+ var(--border-dark);
+ box-sizing: border-box;
+ height: 4px;
+ outline: none;
+ width: 150px;
+ }
+ input::-webkit-slider-thumb {
+ -webkit-appearance: none;
+ appearance: none;
+ background: var(--bg);
+ border: 1px solid;
+ border-color: var(--border-light) var(--border-dark) var(--border-dark)
+ var(--border-light);
+ border-radius: 0;
+ box-sizing: border-box;
+ cursor: pointer;
+ height: 16px;
+ width: 8px;
+ }
+ input::-moz-range-thumb {
+ -webkit-appearance: none;
+ appearance: none;
+ background: var(--bg);
+ border: 1px solid;
+ border-color: var(--border-light) var(--border-dark) var(--border-dark)
+ var(--border-light);
+ border-radius: 0;
+ box-sizing: border-box;
+ cursor: pointer;
+ height: 16px;
+ width: 8px;
+ }
+ label {
+ color: var(--secondary--text);
+ font-size: 16px;
+ line-height: 15px;
+ margin-bottom: 12px;
+ }
+ &:has(input:focus) label {
+ color: var(--accent);
+ }
+ .ruler {
+ background-image: linear-gradient(
+ to right,
+ var(--slider) 1px,
+ transparent 1px
+ );
+ background-size: 15px 5px;
+ height: 5px;
+ margin-left: 4px;
+ margin-top: 4px;
+ width: calc(100% + 5px);
+ z-index: -1;
+ }
+ .value {
+ align-items: center;
+ color: var(--slider);
+ display: flex;
+ font-size: 13px;
+ justify-content: space-between;
+ line-height: 15px;
+ }
+ }
+ .cs-dialog,
+ dialog:not(.default-dialog) {
+ background-color: var(--bg);
+ border: 1px solid;
+ border-color: var(--border-light) var(--border-dark) var(--border-dark)
+ var(--border-light);
+ color: var(--text);
+ margin: auto;
+ max-width: 510px;
+ min-width: 350px;
+ padding: 4px;
+ position: fixed;
+ right: 0;
+ top: 0;
+ user-select: none;
+ .heading {
+ align-items: center;
+ display: flex;
+ justify-content: space-between;
+ margin-top: 3px;
+ padding-left: 2px;
+ .wrapper {
+ align-items: center;
+ display: flex;
+ gap: 5px;
+ .icon {
+ background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='15' viewBox='0 0 16 15'%3E%3Cpath fill='%238c9284' d='M1 12h1v1H1m1 0h1v1H2m1-2h1v1H3m11-6h1v1h-1'/%3E%3Cpath fill='%23a5aa9c' d='M3 14h1v1H3'/%3E%3Cpath fill='%23bdbeb5' d='M0 11h1v1H0m10-9h1v1h-1m0 1h1v1h-1m2-3h1v1h-1m0 1h1v1h-1m0 2h1v1h-1'/%3E%3Cpath fill='%23fff' d='M0 10h1v1H0m0-2h1v1H0m0-2h1v1H0m1-1h1v1H1m0 0h1v1H1m0 0h1v1H1m1-1h1v1H2m0-2h1v1H2m1-1h1v1H3m0 0h1v1H3m1-2h1v1H4m0 0h1v1H4m1-1h1v1H5m-4 0h1v1H1m1-1h1v1H2m1-1h1v1H3m1-1h1v1H4m1-1h1v1H5m-2 1h1v1H3m3-6h1v1H6m0-2h1v1H6m1-1h1v1H7m0 0h1v1H7m1-2h1v1H8m0 0h1v1H8m1-2h1v1H9m0 0h1v1H9m1-2h1v1h-1m0 0h1v1h-1M7 9h1v1H7m1-1h1v1H8m1-1h1v1H9M7 6h1v1H7m1-1h1v1H8m0-2h1v1H8m0-2h1v1H8m0-2h1v1H8m-1 7h1v1H7m4-9h1v1h-1m0 0h1v1h-1m-1-1h1v1h-1m1 0h1v1h-1m1-2h1v1h-1M9 2h1v1H9m4-1h1v1h-1m0 4h1v1h-1m1-2h1v1h-1m0-2h1v1h-1m0-2h1v1h-1m0-2h1v1h-1m-4-3h1v1h-1m1-1h1v1h-1m1-1h1v1h-1'/%3E%3Cpath fill='%23848e84' d='M0 7h1v1H0m11-8h1v1h-1M7 4h1v1H7m1-4h1v1H8'/%3E%3Cpath fill='%239ca29c' d='M2 8h1v1H2m1-1h1v1H3m3 5h1v1H6m1-2h1v1H7m3-5h1v1h-1m5-6h1v1h-1m0 0h1v1h-1'/%3E%3Cpath fill='%23d6d7ce' d='M4 8h1v1H4m2 0h1v1H6'/%3E%3Cpath fill='%23dedfde' d='M4 14h1v1H4m1-1h1v1H5m3-5h1v1H8'/%3E%3Cpath fill='%23f7f7f7' d='M5 8h1v1H5m6-2h1v1h-1m1-1h1v1h-1m-1 0h1v1h-1'/%3E%3Cpath fill='%23efefef' d='M2 12h1v1H2m4 0h1v1H6m1-2h1v1H7m0-3h1v1H7m0-6h1v1H7'/%3E%3Cpath fill='%23cecfce' d='M4 12h1v1H4m1-1h1v1H5m4-7h1v1H9'/%3E%3Cpath fill='%23d6dbd6' d='M8 2h1v1H8m1-2h1v1H9m4-1h1v1h-1m1 0h1v1h-1'/%3E%3Cpath fill='%23949e94' d='M13 6h1v1h-1'/%3E%3Cpath fill='%235a6952' d='M5 9h1v1H5m1 0h1v1H6m0 0h1v1H6m0 0h1v1H6m-2 0h1v1H4m1-1h1v1H5m8-9h1v1h-1m0-3h1v1h-1m0 4h1v1h-1m-4 1h1v1H9m-2 3h1v1H7'/%3E%3Cpath fill='%23525d4a' d='M10 6h1v1h-1m1-1h1v1h-1m1-1h1v1h-1m1-3h1v1h-1m-1-3h1v1h-1m-1-1h1v1h-1m-1-1h1v1h-1M9 3h1v1H9m0 0h1v1H9m0 0h1v1H9M5 7h1v1H5m2-6h1v1H7m0 0h1v1H7m2-4h1v1H9m1-1h1v1h-1m2-1h1v1h-1m2 0h1v1h-1'/%3E%3Cpath fill='%23adb6ad' d='M6 6h1v1H6'/%3E%3C/svg%3E");
+ height: 15px;
+ width: 16px;
+ }
+ .text {
+ color: #fff;
+ font-size: 16px;
+ line-height: 15px;
+ }
+ }
+ }
+ .content {
+ padding: 10px;
+ }
+ .footer-btns {
+ float: right;
+ margin: 4px 8px 8px 0;
+ .cs-btn {
+ text-align: left;
+ width: 72px;
+ }
+ }
+ }
+ .cs-tooltip {
+ color: #fff;
+ display: inline-block;
+ line-height: 20px;
+ position: relative;
+ user-select: none;
+ &:hover .text {
+ visibility: visible;
+ }
+ .text {
+ background-color: var(--secondary-accent);
+ border: 1px solid var(--border-dark);
+ color: #000;
+ font-size: 16px;
+ line-height: 15px;
+ padding: 2px 2px 1px;
+ position: absolute;
+ text-align: center;
+ visibility: hidden;
+ width: max-content;
+ z-index: 1;
+ }
+ }
+ .cs-progress-bar {
+ background-color: var(--secondary-bg);
+ border: 1px solid;
+ border-color: var(--border-dark) var(--border-light) var(--border-light)
+ var(--border-dark);
+ height: 24px;
+ padding: 3px;
+ width: 260px;
+ .bars {
+ background-image: linear-gradient(
+ to right,
+ var(--accent) 8px,
+ transparent 2px
+ );
+ background-size: 12px 16px;
+ height: 100%;
+ }
+ }
+ progress:not(.default-progress) {
+ background-color: var(--secondary-bg);
+ border: 1px solid;
+ border-color: var(--border-dark) var(--border-light) var(--border-light)
+ var(--border-dark);
+ height: 24px;
+ padding: 3px;
+ position: relative;
+ width: 260px;
+ &::-moz-progress-bar {
+ background-color: var(--secondary-bg);
+ background-image: linear-gradient(
+ 90deg,
+ transparent 0,
+ var(--accent) 0.01px,
+ var(--accent) 7.99px,
+ transparent 8px
+ );
+ background-size: 12px 16px;
+ height: 100%;
+ }
+ &::-webkit-progress-bar,
+ &::-webkit-progress-value {
+ background-color: var(--secondary-bg);
+ }
+ &::-webkit-progress-value {
+ background-image: linear-gradient(
+ to right,
+ var(--accent) 8px,
+ transparent 2px
+ );
+ background-size: 12px 16px;
+ height: 100%;
+ }
+ }
+ .cs-tabs {
+ align-items: center;
+ display: flex;
+ flex-wrap: wrap;
+ user-select: none;
+ .radiotab {
+ opacity: 0;
+ position: absolute;
+ }
+ .label {
+ background-color: var(--bg);
+ border-bottom: none;
+ border-left: 1px solid var(--border-light);
+ border-right: 1px solid var(--border-dark);
+ border-top: 1px solid var(--border-light);
+ color: #fff;
+ cursor: pointer;
+ font-size: 16px;
+ height: 27px;
+ line-height: 15px;
+ margin-right: 1px;
+ min-width: 64px;
+ padding: 4px 5px;
+ position: relative;
+ text-align: left;
+ z-index: 10;
+ }
+ .radiotab:checked + .label {
+ background: var(--bg);
+ color: var(--accent);
+ height: 29px;
+ padding: 5px;
+ &:before {
+ background-color: var(--bg);
+ bottom: 0;
+ content: '';
+ height: 1px;
+ left: 0;
+ position: absolute;
+ width: 100%;
+ }
+ }
+ .panel {
+ background: var(--bg);
+ border-bottom: 1px solid var(--border-dark);
+ border-left: 1px solid var(--border-light);
+ border-right: 1px solid var(--border-dark);
+ border-top: 1px solid var(--border-light);
+ bottom: 1px;
+ color: var(--text);
+ display: none;
+ order: 99;
+ padding: 32px 39px 27px;
+ position: relative;
+ width: 100%;
+ }
+ .radiotab:checked + .label + .panel {
+ display: block;
+ position: relative;
+ }
+ }
+}
+body {
+ padding: 40px;
+ max-width: 800px;
+ margin: auto;
+ margin: 0 max(0px, round(50vw - (800px/2), 1px));
+}
+
+@media (max-width: 400px) {
+ body {
+ padding: 20px;
+ }
+}
diff --git a/static/robots.txt b/static/robots.txt
new file mode 100644
index 0000000..b6dd667
--- /dev/null
+++ b/static/robots.txt
@@ -0,0 +1,3 @@
+# allow crawling everything by default
+User-agent: *
+Disallow:
diff --git a/svelte.config.js b/svelte.config.js
new file mode 100644
index 0000000..4a423ba
--- /dev/null
+++ b/svelte.config.js
@@ -0,0 +1,12 @@
+import adapter from '@sveltejs/adapter-static';
+import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
+
+/** @type {import('@sveltejs/kit').Config} */
+const config = {
+ // Consult https://svelte.dev/docs/kit/integrations
+ // for more information about preprocessors
+ preprocess: vitePreprocess(),
+ kit: { adapter: adapter() }
+};
+
+export default config;
diff --git a/tsconfig.json b/tsconfig.json
new file mode 100644
index 0000000..a5567ee
--- /dev/null
+++ b/tsconfig.json
@@ -0,0 +1,19 @@
+{
+ "extends": "./.svelte-kit/tsconfig.json",
+ "compilerOptions": {
+ "allowJs": true,
+ "checkJs": true,
+ "esModuleInterop": true,
+ "forceConsistentCasingInFileNames": true,
+ "resolveJsonModule": true,
+ "skipLibCheck": true,
+ "sourceMap": true,
+ "strict": true,
+ "moduleResolution": "bundler"
+ }
+ // Path aliases are handled by https://svelte.dev/docs/kit/configuration#alias
+ // except $lib which is handled by https://svelte.dev/docs/kit/configuration#files
+ //
+ // To make changes to top-level options such as include and exclude, we recommend extending
+ // the generated config; see https://svelte.dev/docs/kit/configuration#typescript
+}
diff --git a/vite.config.ts b/vite.config.ts
new file mode 100644
index 0000000..bbf8c7d
--- /dev/null
+++ b/vite.config.ts
@@ -0,0 +1,6 @@
+import { sveltekit } from '@sveltejs/kit/vite';
+import { defineConfig } from 'vite';
+
+export default defineConfig({
+ plugins: [sveltekit()]
+});