diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 0000000..1cc91bb
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,47 @@
+# Dependencies
+node_modules/
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+
+# Development files
+*.md
+.git/
+.gitignore
+
+# OS generated files
+.DS_Store
+.DS_Store?
+._*
+.Spotlight-V100
+.Trashes
+ehthumbs.db
+Thumbs.db
+
+# Editor files
+.vscode/
+.idea/
+*.swp
+*.swo
+
+# Logs
+logs
+*.log
+
+# Environment files
+.env
+.env.local
+.env.development.local
+.env.test.local
+.env.production.local
+
+# CI/CD
+.forgejo/
+.github/
+
+# Other
+coverage/
+.nyc_output/
+
+# Built files (will be built inside Docker)
+dist/
diff --git a/.editorconfig b/.editorconfig
deleted file mode 100644
index 5f346e1..0000000
--- a/.editorconfig
+++ /dev/null
@@ -1,10 +0,0 @@
-root = true
-
-[*]
-end_of_line = lf
-insert_final_newline = true
-
-[*.{js,json,.yml}]
-charset = utf-8
-indent_style = space
-indent_size = 2
diff --git a/.env.example b/.env.example
new file mode 100644
index 0000000..d5ac2d5
--- /dev/null
+++ b/.env.example
@@ -0,0 +1,8 @@
+# Copy to .env and fill in your secrets
+# These are used by the Bun/Elysia server to fetch your current/last played track from Last.fm
+LASTFM_API_KEY=
+LASTFM_USERNAME=
+
+# Optional
+PORT=3000
+NODE_ENV=development
diff --git a/.forgejo/workflows/build-and-dockerise.yml b/.forgejo/workflows/build-and-dockerise.yml
index bada351..223f232 100644
--- a/.forgejo/workflows/build-and-dockerise.yml
+++ b/.forgejo/workflows/build-and-dockerise.yml
@@ -3,7 +3,7 @@ name: Build and Push Docker Image
on:
push:
branches:
- - main # Adjust if your main branch is different
+ - turquoise
tags:
- 'v*.*.*' # Trigger on version tags
@@ -26,14 +26,6 @@ jobs:
with:
fetch-depth: 0 # Recommended for metadata action
- - name: Install pnpm dependencies
- run: pnpm i
- shell: sh
-
- - name: Build project
- run: pnpm run build
- shell: sh
-
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v3
@@ -55,7 +47,7 @@ jobs:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_BASE_NAME }}
tags: |
# Use 'github.ref' for branch/tag detection
- type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', 'main') }} # Adjust 'main' if needed
+ type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', 'turquoise') }}
type=ref,event=branch
type=ref,event=tag
type=sha,format=short # Tag with short Git SHA
@@ -65,11 +57,11 @@ jobs:
org.opencontainers.image.revision=${{ github.sha }}
org.opencontainers.image.ref.name=${{ github.ref_name }}
- - name: Build and push Docker image
+ - name: Build and push minimal Docker image
uses: docker/build-push-action@v5
with:
context: .
- file: ./Dockerfile
+ file: ./Dockerfile # Uses the Alpine-based minimal container
push: true
tags: ${{ steps.meta.outputs.tags }} # Use tags from metadata step
labels: ${{ steps.meta.outputs.labels }} # Use labels from metadata step
diff --git a/.gitattributes b/.gitattributes
deleted file mode 100644
index 6777c93..0000000
--- a/.gitattributes
+++ /dev/null
@@ -1 +0,0 @@
-/.yarn/** linguist-vendored
diff --git a/.gitignore b/.gitignore
index af4cecd..4abe73e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,27 @@
-node_modules
-docker-compose.yml
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
-www/extra
-www/css/style.css
\ No newline at end of file
+node_modules
+dist
+dist-ssr
+*.local
+
+# Editor directories and files
+.vscode/*
+!.vscode/extensions.json
+.idea
+.DS_Store
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
+
+# Environment variables
+.env
diff --git a/.yarn/cache/@alloc-quick-lru-npm-5.2.0-eb83517088-48e6d9607b.zip b/.yarn/cache/@alloc-quick-lru-npm-5.2.0-eb83517088-48e6d9607b.zip
deleted file mode 100644
index 488032c..0000000
Binary files a/.yarn/cache/@alloc-quick-lru-npm-5.2.0-eb83517088-48e6d9607b.zip and /dev/null differ
diff --git a/.yarn/cache/@isaacs-cliui-npm-8.0.2-f4364666d5-1b9b20d02b.zip b/.yarn/cache/@isaacs-cliui-npm-8.0.2-f4364666d5-1b9b20d02b.zip
deleted file mode 100644
index eca199f..0000000
Binary files a/.yarn/cache/@isaacs-cliui-npm-8.0.2-f4364666d5-1b9b20d02b.zip and /dev/null differ
diff --git a/.yarn/cache/@jridgewell-gen-mapping-npm-0.3.3-1815eba94c-3023bf63bc.zip b/.yarn/cache/@jridgewell-gen-mapping-npm-0.3.3-1815eba94c-3023bf63bc.zip
deleted file mode 100644
index 24d714f..0000000
Binary files a/.yarn/cache/@jridgewell-gen-mapping-npm-0.3.3-1815eba94c-3023bf63bc.zip and /dev/null differ
diff --git a/.yarn/cache/@jridgewell-resolve-uri-npm-3.1.1-aa2de3f210-874cf20998.zip b/.yarn/cache/@jridgewell-resolve-uri-npm-3.1.1-aa2de3f210-874cf20998.zip
deleted file mode 100644
index cf5c8e2..0000000
Binary files a/.yarn/cache/@jridgewell-resolve-uri-npm-3.1.1-aa2de3f210-874cf20998.zip and /dev/null differ
diff --git a/.yarn/cache/@jridgewell-set-array-npm-1.1.2-45b82d7fb6-1013d30769.zip b/.yarn/cache/@jridgewell-set-array-npm-1.1.2-45b82d7fb6-1013d30769.zip
deleted file mode 100644
index 87d6da6..0000000
Binary files a/.yarn/cache/@jridgewell-set-array-npm-1.1.2-45b82d7fb6-1013d30769.zip and /dev/null differ
diff --git a/.yarn/cache/@jridgewell-sourcemap-codec-npm-1.4.15-a055fb62cf-6d731b4d60.zip b/.yarn/cache/@jridgewell-sourcemap-codec-npm-1.4.15-a055fb62cf-6d731b4d60.zip
deleted file mode 100644
index 0d74194..0000000
Binary files a/.yarn/cache/@jridgewell-sourcemap-codec-npm-1.4.15-a055fb62cf-6d731b4d60.zip and /dev/null differ
diff --git a/.yarn/cache/@jridgewell-trace-mapping-npm-0.3.20-d90f282910-e719e9de55.zip b/.yarn/cache/@jridgewell-trace-mapping-npm-0.3.20-d90f282910-e719e9de55.zip
deleted file mode 100644
index f3101f4..0000000
Binary files a/.yarn/cache/@jridgewell-trace-mapping-npm-0.3.20-d90f282910-e719e9de55.zip and /dev/null differ
diff --git a/.yarn/cache/@nodelib-fs.scandir-npm-2.1.5-89c67370dd-91b3de88d9.zip b/.yarn/cache/@nodelib-fs.scandir-npm-2.1.5-89c67370dd-91b3de88d9.zip
deleted file mode 100644
index d74044f..0000000
Binary files a/.yarn/cache/@nodelib-fs.scandir-npm-2.1.5-89c67370dd-91b3de88d9.zip and /dev/null differ
diff --git a/.yarn/cache/@nodelib-fs.stat-npm-2.0.5-01f4dd3030-a4fcf7408f.zip b/.yarn/cache/@nodelib-fs.stat-npm-2.0.5-01f4dd3030-a4fcf7408f.zip
deleted file mode 100644
index 47ba89a..0000000
Binary files a/.yarn/cache/@nodelib-fs.stat-npm-2.0.5-01f4dd3030-a4fcf7408f.zip and /dev/null differ
diff --git a/.yarn/cache/@nodelib-fs.walk-npm-1.2.8-b4a89da548-f7870cf3f1.zip b/.yarn/cache/@nodelib-fs.walk-npm-1.2.8-b4a89da548-f7870cf3f1.zip
deleted file mode 100644
index 2c375e5..0000000
Binary files a/.yarn/cache/@nodelib-fs.walk-npm-1.2.8-b4a89da548-f7870cf3f1.zip and /dev/null differ
diff --git a/.yarn/cache/@npmcli-agent-npm-2.2.0-cf04e8a830-87d91ddf05.zip b/.yarn/cache/@npmcli-agent-npm-2.2.0-cf04e8a830-87d91ddf05.zip
deleted file mode 100644
index 1156c88..0000000
Binary files a/.yarn/cache/@npmcli-agent-npm-2.2.0-cf04e8a830-87d91ddf05.zip and /dev/null differ
diff --git a/.yarn/cache/@npmcli-fs-npm-3.1.0-0844a57978-b96d3a91f6.zip b/.yarn/cache/@npmcli-fs-npm-3.1.0-0844a57978-b96d3a91f6.zip
deleted file mode 100644
index c5fd618..0000000
Binary files a/.yarn/cache/@npmcli-fs-npm-3.1.0-0844a57978-b96d3a91f6.zip and /dev/null differ
diff --git a/.yarn/cache/@pkgjs-parseargs-npm-0.11.0-cd2a3fe948-dfe6befa02.zip b/.yarn/cache/@pkgjs-parseargs-npm-0.11.0-cd2a3fe948-dfe6befa02.zip
deleted file mode 100644
index 60d1547..0000000
Binary files a/.yarn/cache/@pkgjs-parseargs-npm-0.11.0-cd2a3fe948-dfe6befa02.zip and /dev/null differ
diff --git a/.yarn/cache/abbrev-npm-2.0.0-0eb38a17e5-a82907e52c.zip b/.yarn/cache/abbrev-npm-2.0.0-0eb38a17e5-a82907e52c.zip
deleted file mode 100644
index 62b6e68..0000000
Binary files a/.yarn/cache/abbrev-npm-2.0.0-0eb38a17e5-a82907e52c.zip and /dev/null differ
diff --git a/.yarn/cache/agent-base-npm-7.1.0-4b12ba5111-e80384a4b4.zip b/.yarn/cache/agent-base-npm-7.1.0-4b12ba5111-e80384a4b4.zip
deleted file mode 100644
index 19d93f4..0000000
Binary files a/.yarn/cache/agent-base-npm-7.1.0-4b12ba5111-e80384a4b4.zip and /dev/null differ
diff --git a/.yarn/cache/aggregate-error-npm-3.1.0-415a406f4e-704d2001a3.zip b/.yarn/cache/aggregate-error-npm-3.1.0-415a406f4e-704d2001a3.zip
deleted file mode 100644
index a616171..0000000
Binary files a/.yarn/cache/aggregate-error-npm-3.1.0-415a406f4e-704d2001a3.zip and /dev/null differ
diff --git a/.yarn/cache/ansi-regex-npm-5.0.1-c963a48615-c944e1229f.zip b/.yarn/cache/ansi-regex-npm-5.0.1-c963a48615-c944e1229f.zip
deleted file mode 100644
index a0e7204..0000000
Binary files a/.yarn/cache/ansi-regex-npm-5.0.1-c963a48615-c944e1229f.zip and /dev/null differ
diff --git a/.yarn/cache/ansi-regex-npm-6.0.1-8d663a607d-5a4e4cd709.zip b/.yarn/cache/ansi-regex-npm-6.0.1-8d663a607d-5a4e4cd709.zip
deleted file mode 100644
index da215e6..0000000
Binary files a/.yarn/cache/ansi-regex-npm-6.0.1-8d663a607d-5a4e4cd709.zip and /dev/null differ
diff --git a/.yarn/cache/ansi-styles-npm-4.3.0-245c7d42c7-ea02c0179f.zip b/.yarn/cache/ansi-styles-npm-4.3.0-245c7d42c7-ea02c0179f.zip
deleted file mode 100644
index 909670c..0000000
Binary files a/.yarn/cache/ansi-styles-npm-4.3.0-245c7d42c7-ea02c0179f.zip and /dev/null differ
diff --git a/.yarn/cache/ansi-styles-npm-6.2.1-d43647018c-285ec4b6dc.zip b/.yarn/cache/ansi-styles-npm-6.2.1-d43647018c-285ec4b6dc.zip
deleted file mode 100644
index 13c7f3c..0000000
Binary files a/.yarn/cache/ansi-styles-npm-6.2.1-d43647018c-285ec4b6dc.zip and /dev/null differ
diff --git a/.yarn/cache/any-promise-npm-1.3.0-f34eeaa7e7-e829425e4a.zip b/.yarn/cache/any-promise-npm-1.3.0-f34eeaa7e7-e829425e4a.zip
deleted file mode 100644
index 23093fd..0000000
Binary files a/.yarn/cache/any-promise-npm-1.3.0-f34eeaa7e7-e829425e4a.zip and /dev/null differ
diff --git a/.yarn/cache/anymatch-npm-3.1.3-bc81d103b1-7191d13e13.zip b/.yarn/cache/anymatch-npm-3.1.3-bc81d103b1-7191d13e13.zip
deleted file mode 100644
index cb53e17..0000000
Binary files a/.yarn/cache/anymatch-npm-3.1.3-bc81d103b1-7191d13e13.zip and /dev/null differ
diff --git a/.yarn/cache/arg-npm-5.0.2-2f5805a547-2fe52bbdfa.zip b/.yarn/cache/arg-npm-5.0.2-2f5805a547-2fe52bbdfa.zip
deleted file mode 100644
index d945284..0000000
Binary files a/.yarn/cache/arg-npm-5.0.2-2f5805a547-2fe52bbdfa.zip and /dev/null differ
diff --git a/.yarn/cache/balanced-match-npm-1.0.2-a53c126459-690643f300.zip b/.yarn/cache/balanced-match-npm-1.0.2-a53c126459-690643f300.zip
deleted file mode 100644
index cf4290e..0000000
Binary files a/.yarn/cache/balanced-match-npm-1.0.2-a53c126459-690643f300.zip and /dev/null differ
diff --git a/.yarn/cache/binary-extensions-npm-2.2.0-180c33fec7-0f5f5685f3.zip b/.yarn/cache/binary-extensions-npm-2.2.0-180c33fec7-0f5f5685f3.zip
deleted file mode 100644
index f748daf..0000000
Binary files a/.yarn/cache/binary-extensions-npm-2.2.0-180c33fec7-0f5f5685f3.zip and /dev/null differ
diff --git a/.yarn/cache/brace-expansion-npm-1.1.11-fb95eb05ad-4c878e25e4.zip b/.yarn/cache/brace-expansion-npm-1.1.11-fb95eb05ad-4c878e25e4.zip
deleted file mode 100644
index 67819e1..0000000
Binary files a/.yarn/cache/brace-expansion-npm-1.1.11-fb95eb05ad-4c878e25e4.zip and /dev/null differ
diff --git a/.yarn/cache/brace-expansion-npm-2.0.1-17aa2616f9-c499787968.zip b/.yarn/cache/brace-expansion-npm-2.0.1-17aa2616f9-c499787968.zip
deleted file mode 100644
index eb60682..0000000
Binary files a/.yarn/cache/brace-expansion-npm-2.0.1-17aa2616f9-c499787968.zip and /dev/null differ
diff --git a/.yarn/cache/braces-npm-3.0.2-782240b28a-f3493181c3.zip b/.yarn/cache/braces-npm-3.0.2-782240b28a-f3493181c3.zip
deleted file mode 100644
index 9f5e780..0000000
Binary files a/.yarn/cache/braces-npm-3.0.2-782240b28a-f3493181c3.zip and /dev/null differ
diff --git a/.yarn/cache/cacache-npm-18.0.0-32582cfebc-1c3947050d.zip b/.yarn/cache/cacache-npm-18.0.0-32582cfebc-1c3947050d.zip
deleted file mode 100644
index 87626ae..0000000
Binary files a/.yarn/cache/cacache-npm-18.0.0-32582cfebc-1c3947050d.zip and /dev/null differ
diff --git a/.yarn/cache/camelcase-css-npm-2.0.1-90d1b6df08-3d557da914.zip b/.yarn/cache/camelcase-css-npm-2.0.1-90d1b6df08-3d557da914.zip
deleted file mode 100644
index f4c7b43..0000000
Binary files a/.yarn/cache/camelcase-css-npm-2.0.1-90d1b6df08-3d557da914.zip and /dev/null differ
diff --git a/.yarn/cache/chokidar-npm-3.5.3-c5f9b0a56a-ea6636f22d.zip b/.yarn/cache/chokidar-npm-3.5.3-c5f9b0a56a-ea6636f22d.zip
deleted file mode 100644
index 39598f1..0000000
Binary files a/.yarn/cache/chokidar-npm-3.5.3-c5f9b0a56a-ea6636f22d.zip and /dev/null differ
diff --git a/.yarn/cache/chownr-npm-2.0.0-638f1c9c61-b06ba0bf42.zip b/.yarn/cache/chownr-npm-2.0.0-638f1c9c61-b06ba0bf42.zip
deleted file mode 100644
index 5b643d7..0000000
Binary files a/.yarn/cache/chownr-npm-2.0.0-638f1c9c61-b06ba0bf42.zip and /dev/null differ
diff --git a/.yarn/cache/clean-stack-npm-2.2.0-a8ce435a5c-e291ce2b8c.zip b/.yarn/cache/clean-stack-npm-2.2.0-a8ce435a5c-e291ce2b8c.zip
deleted file mode 100644
index 8fabe8f..0000000
Binary files a/.yarn/cache/clean-stack-npm-2.2.0-a8ce435a5c-e291ce2b8c.zip and /dev/null differ
diff --git a/.yarn/cache/color-convert-npm-2.0.1-79730e935b-3d5d8a011a.zip b/.yarn/cache/color-convert-npm-2.0.1-79730e935b-3d5d8a011a.zip
deleted file mode 100644
index c5520e7..0000000
Binary files a/.yarn/cache/color-convert-npm-2.0.1-79730e935b-3d5d8a011a.zip and /dev/null differ
diff --git a/.yarn/cache/color-name-npm-1.1.4-025792b0ea-3e1c9a4dee.zip b/.yarn/cache/color-name-npm-1.1.4-025792b0ea-3e1c9a4dee.zip
deleted file mode 100644
index 62ad58d..0000000
Binary files a/.yarn/cache/color-name-npm-1.1.4-025792b0ea-3e1c9a4dee.zip and /dev/null differ
diff --git a/.yarn/cache/commander-npm-4.1.1-22a0fe921b-448585071b.zip b/.yarn/cache/commander-npm-4.1.1-22a0fe921b-448585071b.zip
deleted file mode 100644
index dea96a9..0000000
Binary files a/.yarn/cache/commander-npm-4.1.1-22a0fe921b-448585071b.zip and /dev/null differ
diff --git a/.yarn/cache/concat-map-npm-0.0.1-85a921b7ee-554e28d9ee.zip b/.yarn/cache/concat-map-npm-0.0.1-85a921b7ee-554e28d9ee.zip
deleted file mode 100644
index dd651d0..0000000
Binary files a/.yarn/cache/concat-map-npm-0.0.1-85a921b7ee-554e28d9ee.zip and /dev/null differ
diff --git a/.yarn/cache/cross-spawn-npm-7.0.3-e4ff3e65b3-51f10036f5.zip b/.yarn/cache/cross-spawn-npm-7.0.3-e4ff3e65b3-51f10036f5.zip
deleted file mode 100644
index e74d069..0000000
Binary files a/.yarn/cache/cross-spawn-npm-7.0.3-e4ff3e65b3-51f10036f5.zip and /dev/null differ
diff --git a/.yarn/cache/cssesc-npm-3.0.0-15ec56f86f-673783eda1.zip b/.yarn/cache/cssesc-npm-3.0.0-15ec56f86f-673783eda1.zip
deleted file mode 100644
index a6c0288..0000000
Binary files a/.yarn/cache/cssesc-npm-3.0.0-15ec56f86f-673783eda1.zip and /dev/null differ
diff --git a/.yarn/cache/debug-npm-4.3.4-4513954577-7d71c93be2.zip b/.yarn/cache/debug-npm-4.3.4-4513954577-7d71c93be2.zip
deleted file mode 100644
index 22cf2c6..0000000
Binary files a/.yarn/cache/debug-npm-4.3.4-4513954577-7d71c93be2.zip and /dev/null differ
diff --git a/.yarn/cache/didyoumean-npm-1.2.2-fd568ec571-808a1e4855.zip b/.yarn/cache/didyoumean-npm-1.2.2-fd568ec571-808a1e4855.zip
deleted file mode 100644
index 6487bee..0000000
Binary files a/.yarn/cache/didyoumean-npm-1.2.2-fd568ec571-808a1e4855.zip and /dev/null differ
diff --git a/.yarn/cache/dlv-npm-1.1.3-187c903a21-3ed2cd5054.zip b/.yarn/cache/dlv-npm-1.1.3-187c903a21-3ed2cd5054.zip
deleted file mode 100644
index fddbfd1..0000000
Binary files a/.yarn/cache/dlv-npm-1.1.3-187c903a21-3ed2cd5054.zip and /dev/null differ
diff --git a/.yarn/cache/eastasianwidth-npm-0.2.0-c37eb16bd1-436391b865.zip b/.yarn/cache/eastasianwidth-npm-0.2.0-c37eb16bd1-436391b865.zip
deleted file mode 100644
index f7cd95f..0000000
Binary files a/.yarn/cache/eastasianwidth-npm-0.2.0-c37eb16bd1-436391b865.zip and /dev/null differ
diff --git a/.yarn/cache/emoji-regex-npm-8.0.0-213764015c-87cf3f89ef.zip b/.yarn/cache/emoji-regex-npm-8.0.0-213764015c-87cf3f89ef.zip
deleted file mode 100644
index 37a8db7..0000000
Binary files a/.yarn/cache/emoji-regex-npm-8.0.0-213764015c-87cf3f89ef.zip and /dev/null differ
diff --git a/.yarn/cache/emoji-regex-npm-9.2.2-e6fac8d058-f3029ec432.zip b/.yarn/cache/emoji-regex-npm-9.2.2-e6fac8d058-f3029ec432.zip
deleted file mode 100644
index 8752d8b..0000000
Binary files a/.yarn/cache/emoji-regex-npm-9.2.2-e6fac8d058-f3029ec432.zip and /dev/null differ
diff --git a/.yarn/cache/encoding-npm-0.1.13-82a1837d30-282d5696a4.zip b/.yarn/cache/encoding-npm-0.1.13-82a1837d30-282d5696a4.zip
deleted file mode 100644
index 69ce31a..0000000
Binary files a/.yarn/cache/encoding-npm-0.1.13-82a1837d30-282d5696a4.zip and /dev/null differ
diff --git a/.yarn/cache/env-paths-npm-2.2.1-7c7577428c-9579868bc7.zip b/.yarn/cache/env-paths-npm-2.2.1-7c7577428c-9579868bc7.zip
deleted file mode 100644
index 982ed60..0000000
Binary files a/.yarn/cache/env-paths-npm-2.2.1-7c7577428c-9579868bc7.zip and /dev/null differ
diff --git a/.yarn/cache/err-code-npm-2.0.3-082e0ff9a7-14e09e9990.zip b/.yarn/cache/err-code-npm-2.0.3-082e0ff9a7-14e09e9990.zip
deleted file mode 100644
index 0a1f588..0000000
Binary files a/.yarn/cache/err-code-npm-2.0.3-082e0ff9a7-14e09e9990.zip and /dev/null differ
diff --git a/.yarn/cache/exponential-backoff-npm-3.1.1-04df458b30-369725ac55.zip b/.yarn/cache/exponential-backoff-npm-3.1.1-04df458b30-369725ac55.zip
deleted file mode 100644
index 1aa0130..0000000
Binary files a/.yarn/cache/exponential-backoff-npm-3.1.1-04df458b30-369725ac55.zip and /dev/null differ
diff --git a/.yarn/cache/fast-glob-npm-3.3.2-0a8cb4f2ca-76c8f75492.zip b/.yarn/cache/fast-glob-npm-3.3.2-0a8cb4f2ca-76c8f75492.zip
deleted file mode 100644
index 8d8450d..0000000
Binary files a/.yarn/cache/fast-glob-npm-3.3.2-0a8cb4f2ca-76c8f75492.zip and /dev/null differ
diff --git a/.yarn/cache/fastq-npm-1.15.0-1013f6514e-fe2a63a4d6.zip b/.yarn/cache/fastq-npm-1.15.0-1013f6514e-fe2a63a4d6.zip
deleted file mode 100644
index 6b90aa5..0000000
Binary files a/.yarn/cache/fastq-npm-1.15.0-1013f6514e-fe2a63a4d6.zip and /dev/null differ
diff --git a/.yarn/cache/fill-range-npm-7.0.1-b8b1817caa-efca43d59b.zip b/.yarn/cache/fill-range-npm-7.0.1-b8b1817caa-efca43d59b.zip
deleted file mode 100644
index 3ef9993..0000000
Binary files a/.yarn/cache/fill-range-npm-7.0.1-b8b1817caa-efca43d59b.zip and /dev/null differ
diff --git a/.yarn/cache/foreground-child-npm-3.1.1-77e78ed774-8b7a1db35a.zip b/.yarn/cache/foreground-child-npm-3.1.1-77e78ed774-8b7a1db35a.zip
deleted file mode 100644
index 6ec2faf..0000000
Binary files a/.yarn/cache/foreground-child-npm-3.1.1-77e78ed774-8b7a1db35a.zip and /dev/null differ
diff --git a/.yarn/cache/fs-minipass-npm-2.1.0-501ef87306-e14a490658.zip b/.yarn/cache/fs-minipass-npm-2.1.0-501ef87306-e14a490658.zip
deleted file mode 100644
index 77b7a6c..0000000
Binary files a/.yarn/cache/fs-minipass-npm-2.1.0-501ef87306-e14a490658.zip and /dev/null differ
diff --git a/.yarn/cache/fs-minipass-npm-3.0.3-d148d6ac19-28f0078906.zip b/.yarn/cache/fs-minipass-npm-3.0.3-d148d6ac19-28f0078906.zip
deleted file mode 100644
index b167702..0000000
Binary files a/.yarn/cache/fs-minipass-npm-3.0.3-d148d6ac19-28f0078906.zip and /dev/null differ
diff --git a/.yarn/cache/fs.realpath-npm-1.0.0-c8f05d8126-698a91b169.zip b/.yarn/cache/fs.realpath-npm-1.0.0-c8f05d8126-698a91b169.zip
deleted file mode 100644
index fb74b58..0000000
Binary files a/.yarn/cache/fs.realpath-npm-1.0.0-c8f05d8126-698a91b169.zip and /dev/null differ
diff --git a/.yarn/cache/fsevents-npm-2.3.3-ce9fb0ffae-f22d0a854b.zip b/.yarn/cache/fsevents-npm-2.3.3-ce9fb0ffae-f22d0a854b.zip
deleted file mode 100644
index 0a430fb..0000000
Binary files a/.yarn/cache/fsevents-npm-2.3.3-ce9fb0ffae-f22d0a854b.zip and /dev/null differ
diff --git a/.yarn/cache/fsevents-patch-8036bb578f-b4a5cd7915.zip b/.yarn/cache/fsevents-patch-8036bb578f-b4a5cd7915.zip
deleted file mode 100644
index 06cfa4b..0000000
Binary files a/.yarn/cache/fsevents-patch-8036bb578f-b4a5cd7915.zip and /dev/null differ
diff --git a/.yarn/cache/function-bind-npm-1.1.2-7a55be9b03-0d0c3d1dbe.zip b/.yarn/cache/function-bind-npm-1.1.2-7a55be9b03-0d0c3d1dbe.zip
deleted file mode 100644
index 87767a5..0000000
Binary files a/.yarn/cache/function-bind-npm-1.1.2-7a55be9b03-0d0c3d1dbe.zip and /dev/null differ
diff --git a/.yarn/cache/glob-npm-10.3.10-da1ef8b112-07706025e0.zip b/.yarn/cache/glob-npm-10.3.10-da1ef8b112-07706025e0.zip
deleted file mode 100644
index 2b4bbe8..0000000
Binary files a/.yarn/cache/glob-npm-10.3.10-da1ef8b112-07706025e0.zip and /dev/null differ
diff --git a/.yarn/cache/glob-npm-7.1.6-1ce3a5189a-789977b524.zip b/.yarn/cache/glob-npm-7.1.6-1ce3a5189a-789977b524.zip
deleted file mode 100644
index aa99358..0000000
Binary files a/.yarn/cache/glob-npm-7.1.6-1ce3a5189a-789977b524.zip and /dev/null differ
diff --git a/.yarn/cache/glob-parent-npm-5.1.2-021ab32634-82fcaa4ce1.zip b/.yarn/cache/glob-parent-npm-5.1.2-021ab32634-82fcaa4ce1.zip
deleted file mode 100644
index 646a5a7..0000000
Binary files a/.yarn/cache/glob-parent-npm-5.1.2-021ab32634-82fcaa4ce1.zip and /dev/null differ
diff --git a/.yarn/cache/glob-parent-npm-6.0.2-2cbef12738-226293dc9d.zip b/.yarn/cache/glob-parent-npm-6.0.2-2cbef12738-226293dc9d.zip
deleted file mode 100644
index b39b34e..0000000
Binary files a/.yarn/cache/glob-parent-npm-6.0.2-2cbef12738-226293dc9d.zip and /dev/null differ
diff --git a/.yarn/cache/graceful-fs-npm-4.2.11-24bb648a68-99533f7c73.zip b/.yarn/cache/graceful-fs-npm-4.2.11-24bb648a68-99533f7c73.zip
deleted file mode 100644
index fd7f50f..0000000
Binary files a/.yarn/cache/graceful-fs-npm-4.2.11-24bb648a68-99533f7c73.zip and /dev/null differ
diff --git a/.yarn/cache/hasown-npm-2.0.0-78b794ceef-5d9c0e10b4.zip b/.yarn/cache/hasown-npm-2.0.0-78b794ceef-5d9c0e10b4.zip
deleted file mode 100644
index 8732d2c..0000000
Binary files a/.yarn/cache/hasown-npm-2.0.0-78b794ceef-5d9c0e10b4.zip and /dev/null differ
diff --git a/.yarn/cache/http-cache-semantics-npm-4.1.1-1120131375-ea193328de.zip b/.yarn/cache/http-cache-semantics-npm-4.1.1-1120131375-ea193328de.zip
deleted file mode 100644
index 1f122b1..0000000
Binary files a/.yarn/cache/http-cache-semantics-npm-4.1.1-1120131375-ea193328de.zip and /dev/null differ
diff --git a/.yarn/cache/http-proxy-agent-npm-7.0.0-106a57cc8c-bc12e49a3b.zip b/.yarn/cache/http-proxy-agent-npm-7.0.0-106a57cc8c-bc12e49a3b.zip
deleted file mode 100644
index fa416d1..0000000
Binary files a/.yarn/cache/http-proxy-agent-npm-7.0.0-106a57cc8c-bc12e49a3b.zip and /dev/null differ
diff --git a/.yarn/cache/https-proxy-agent-npm-7.0.2-83ea6a5d42-607c61a4c9.zip b/.yarn/cache/https-proxy-agent-npm-7.0.2-83ea6a5d42-607c61a4c9.zip
deleted file mode 100644
index e164fcb..0000000
Binary files a/.yarn/cache/https-proxy-agent-npm-7.0.2-83ea6a5d42-607c61a4c9.zip and /dev/null differ
diff --git a/.yarn/cache/iconv-lite-npm-0.6.3-24b8aae27e-9b4f24db66.zip b/.yarn/cache/iconv-lite-npm-0.6.3-24b8aae27e-9b4f24db66.zip
deleted file mode 100644
index 5e543a5..0000000
Binary files a/.yarn/cache/iconv-lite-npm-0.6.3-24b8aae27e-9b4f24db66.zip and /dev/null differ
diff --git a/.yarn/cache/imurmurhash-npm-0.1.4-610c5068a0-34d414d789.zip b/.yarn/cache/imurmurhash-npm-0.1.4-610c5068a0-34d414d789.zip
deleted file mode 100644
index e9c177b..0000000
Binary files a/.yarn/cache/imurmurhash-npm-0.1.4-610c5068a0-34d414d789.zip and /dev/null differ
diff --git a/.yarn/cache/indent-string-npm-4.0.0-7b717435b2-3e54996c6e.zip b/.yarn/cache/indent-string-npm-4.0.0-7b717435b2-3e54996c6e.zip
deleted file mode 100644
index 9dfd833..0000000
Binary files a/.yarn/cache/indent-string-npm-4.0.0-7b717435b2-3e54996c6e.zip and /dev/null differ
diff --git a/.yarn/cache/inflight-npm-1.0.6-ccedb4b908-17c53fc42c.zip b/.yarn/cache/inflight-npm-1.0.6-ccedb4b908-17c53fc42c.zip
deleted file mode 100644
index 8b43e84..0000000
Binary files a/.yarn/cache/inflight-npm-1.0.6-ccedb4b908-17c53fc42c.zip and /dev/null differ
diff --git a/.yarn/cache/inherits-npm-2.0.4-c66b3957a0-98426da247.zip b/.yarn/cache/inherits-npm-2.0.4-c66b3957a0-98426da247.zip
deleted file mode 100644
index fd9d5ae..0000000
Binary files a/.yarn/cache/inherits-npm-2.0.4-c66b3957a0-98426da247.zip and /dev/null differ
diff --git a/.yarn/cache/ip-npm-2.0.0-204facb3cc-046f0487ff.zip b/.yarn/cache/ip-npm-2.0.0-204facb3cc-046f0487ff.zip
deleted file mode 100644
index 027b5e2..0000000
Binary files a/.yarn/cache/ip-npm-2.0.0-204facb3cc-046f0487ff.zip and /dev/null differ
diff --git a/.yarn/cache/is-binary-path-npm-2.1.0-e61d46f557-49a1446a3c.zip b/.yarn/cache/is-binary-path-npm-2.1.0-e61d46f557-49a1446a3c.zip
deleted file mode 100644
index e599d38..0000000
Binary files a/.yarn/cache/is-binary-path-npm-2.1.0-e61d46f557-49a1446a3c.zip and /dev/null differ
diff --git a/.yarn/cache/is-core-module-npm-2.13.1-36e17434f9-a19e63cd9a.zip b/.yarn/cache/is-core-module-npm-2.13.1-36e17434f9-a19e63cd9a.zip
deleted file mode 100644
index bdff56c..0000000
Binary files a/.yarn/cache/is-core-module-npm-2.13.1-36e17434f9-a19e63cd9a.zip and /dev/null differ
diff --git a/.yarn/cache/is-extglob-npm-2.1.1-0870ea68b5-ca623e2c56.zip b/.yarn/cache/is-extglob-npm-2.1.1-0870ea68b5-ca623e2c56.zip
deleted file mode 100644
index 502658e..0000000
Binary files a/.yarn/cache/is-extglob-npm-2.1.1-0870ea68b5-ca623e2c56.zip and /dev/null differ
diff --git a/.yarn/cache/is-fullwidth-code-point-npm-3.0.0-1ecf4ebee5-a01a19ecac.zip b/.yarn/cache/is-fullwidth-code-point-npm-3.0.0-1ecf4ebee5-a01a19ecac.zip
deleted file mode 100644
index b81f8cf..0000000
Binary files a/.yarn/cache/is-fullwidth-code-point-npm-3.0.0-1ecf4ebee5-a01a19ecac.zip and /dev/null differ
diff --git a/.yarn/cache/is-glob-npm-4.0.3-cb87bf1bdb-8f6b4c42b7.zip b/.yarn/cache/is-glob-npm-4.0.3-cb87bf1bdb-8f6b4c42b7.zip
deleted file mode 100644
index 005921b..0000000
Binary files a/.yarn/cache/is-glob-npm-4.0.3-cb87bf1bdb-8f6b4c42b7.zip and /dev/null differ
diff --git a/.yarn/cache/is-lambda-npm-1.0.1-7ab55bc8a8-669ea37e8f.zip b/.yarn/cache/is-lambda-npm-1.0.1-7ab55bc8a8-669ea37e8f.zip
deleted file mode 100644
index 3a00275..0000000
Binary files a/.yarn/cache/is-lambda-npm-1.0.1-7ab55bc8a8-669ea37e8f.zip and /dev/null differ
diff --git a/.yarn/cache/is-number-npm-7.0.0-060086935c-eec6e506c6.zip b/.yarn/cache/is-number-npm-7.0.0-060086935c-eec6e506c6.zip
deleted file mode 100644
index 0234594..0000000
Binary files a/.yarn/cache/is-number-npm-7.0.0-060086935c-eec6e506c6.zip and /dev/null differ
diff --git a/.yarn/cache/isexe-npm-2.0.0-b58870bd2e-7b437980bb.zip b/.yarn/cache/isexe-npm-2.0.0-b58870bd2e-7b437980bb.zip
deleted file mode 100644
index b7bb40b..0000000
Binary files a/.yarn/cache/isexe-npm-2.0.0-b58870bd2e-7b437980bb.zip and /dev/null differ
diff --git a/.yarn/cache/isexe-npm-3.1.1-9c0061eead-9220579164.zip b/.yarn/cache/isexe-npm-3.1.1-9c0061eead-9220579164.zip
deleted file mode 100644
index 5280eb1..0000000
Binary files a/.yarn/cache/isexe-npm-3.1.1-9c0061eead-9220579164.zip and /dev/null differ
diff --git a/.yarn/cache/jackspeak-npm-2.3.6-42e1233172-4e1113feef.zip b/.yarn/cache/jackspeak-npm-2.3.6-42e1233172-4e1113feef.zip
deleted file mode 100644
index e338bfa..0000000
Binary files a/.yarn/cache/jackspeak-npm-2.3.6-42e1233172-4e1113feef.zip and /dev/null differ
diff --git a/.yarn/cache/jiti-npm-1.21.0-baebd5985a-6dda596de2.zip b/.yarn/cache/jiti-npm-1.21.0-baebd5985a-6dda596de2.zip
deleted file mode 100644
index a65029b..0000000
Binary files a/.yarn/cache/jiti-npm-1.21.0-baebd5985a-6dda596de2.zip and /dev/null differ
diff --git a/.yarn/cache/lilconfig-npm-2.1.0-a179261924-8a6e47a6ad.zip b/.yarn/cache/lilconfig-npm-2.1.0-a179261924-8a6e47a6ad.zip
deleted file mode 100644
index 9557b5d..0000000
Binary files a/.yarn/cache/lilconfig-npm-2.1.0-a179261924-8a6e47a6ad.zip and /dev/null differ
diff --git a/.yarn/cache/lilconfig-npm-3.0.0-6931a31ed7-927fff6d2a.zip b/.yarn/cache/lilconfig-npm-3.0.0-6931a31ed7-927fff6d2a.zip
deleted file mode 100644
index b4298d3..0000000
Binary files a/.yarn/cache/lilconfig-npm-3.0.0-6931a31ed7-927fff6d2a.zip and /dev/null differ
diff --git a/.yarn/cache/lines-and-columns-npm-1.2.4-d6c7cc5799-a1d22dcb6f.zip b/.yarn/cache/lines-and-columns-npm-1.2.4-d6c7cc5799-a1d22dcb6f.zip
deleted file mode 100644
index 08cbb94..0000000
Binary files a/.yarn/cache/lines-and-columns-npm-1.2.4-d6c7cc5799-a1d22dcb6f.zip and /dev/null differ
diff --git a/.yarn/cache/lru-cache-npm-10.0.3-1c2f93d565-7e46eaebd1.zip b/.yarn/cache/lru-cache-npm-10.0.3-1c2f93d565-7e46eaebd1.zip
deleted file mode 100644
index 92a65ad..0000000
Binary files a/.yarn/cache/lru-cache-npm-10.0.3-1c2f93d565-7e46eaebd1.zip and /dev/null differ
diff --git a/.yarn/cache/lru-cache-npm-6.0.0-b4c8668fe1-b8b78353d2.zip b/.yarn/cache/lru-cache-npm-6.0.0-b4c8668fe1-b8b78353d2.zip
deleted file mode 100644
index e0ac235..0000000
Binary files a/.yarn/cache/lru-cache-npm-6.0.0-b4c8668fe1-b8b78353d2.zip and /dev/null differ
diff --git a/.yarn/cache/make-fetch-happen-npm-13.0.0-f87a92bb87-08ed8f6464.zip b/.yarn/cache/make-fetch-happen-npm-13.0.0-f87a92bb87-08ed8f6464.zip
deleted file mode 100644
index 51e2aac..0000000
Binary files a/.yarn/cache/make-fetch-happen-npm-13.0.0-f87a92bb87-08ed8f6464.zip and /dev/null differ
diff --git a/.yarn/cache/merge2-npm-1.4.1-a2507bd06c-7ad40d8b14.zip b/.yarn/cache/merge2-npm-1.4.1-a2507bd06c-7ad40d8b14.zip
deleted file mode 100644
index ae8944e..0000000
Binary files a/.yarn/cache/merge2-npm-1.4.1-a2507bd06c-7ad40d8b14.zip and /dev/null differ
diff --git a/.yarn/cache/micromatch-npm-4.0.5-cfab5d7669-af3dc46b9d.zip b/.yarn/cache/micromatch-npm-4.0.5-cfab5d7669-af3dc46b9d.zip
deleted file mode 100644
index 9844b63..0000000
Binary files a/.yarn/cache/micromatch-npm-4.0.5-cfab5d7669-af3dc46b9d.zip and /dev/null differ
diff --git a/.yarn/cache/minimatch-npm-3.1.2-9405269906-1a7584a6de.zip b/.yarn/cache/minimatch-npm-3.1.2-9405269906-1a7584a6de.zip
deleted file mode 100644
index 78f277a..0000000
Binary files a/.yarn/cache/minimatch-npm-3.1.2-9405269906-1a7584a6de.zip and /dev/null differ
diff --git a/.yarn/cache/minimatch-npm-9.0.3-69d7d6fad5-fb6dc6e08f.zip b/.yarn/cache/minimatch-npm-9.0.3-69d7d6fad5-fb6dc6e08f.zip
deleted file mode 100644
index 6248036..0000000
Binary files a/.yarn/cache/minimatch-npm-9.0.3-69d7d6fad5-fb6dc6e08f.zip and /dev/null differ
diff --git a/.yarn/cache/minipass-collect-npm-1.0.2-3b4676eab5-529ef62123.zip b/.yarn/cache/minipass-collect-npm-1.0.2-3b4676eab5-529ef62123.zip
deleted file mode 100644
index 28646fa..0000000
Binary files a/.yarn/cache/minipass-collect-npm-1.0.2-3b4676eab5-529ef62123.zip and /dev/null differ
diff --git a/.yarn/cache/minipass-fetch-npm-3.0.4-200ac7c66d-920b4b454a.zip b/.yarn/cache/minipass-fetch-npm-3.0.4-200ac7c66d-920b4b454a.zip
deleted file mode 100644
index 94f1f1a..0000000
Binary files a/.yarn/cache/minipass-fetch-npm-3.0.4-200ac7c66d-920b4b454a.zip and /dev/null differ
diff --git a/.yarn/cache/minipass-flush-npm-1.0.5-efe79d9826-d354ca0da8.zip b/.yarn/cache/minipass-flush-npm-1.0.5-efe79d9826-d354ca0da8.zip
deleted file mode 100644
index bcc49f5..0000000
Binary files a/.yarn/cache/minipass-flush-npm-1.0.5-efe79d9826-d354ca0da8.zip and /dev/null differ
diff --git a/.yarn/cache/minipass-npm-3.3.6-b8d93a945b-3cc3a75860.zip b/.yarn/cache/minipass-npm-3.3.6-b8d93a945b-3cc3a75860.zip
deleted file mode 100644
index 705882d..0000000
Binary files a/.yarn/cache/minipass-npm-3.3.6-b8d93a945b-3cc3a75860.zip and /dev/null differ
diff --git a/.yarn/cache/minipass-npm-5.0.0-c64fb63c92-f9d89ca516.zip b/.yarn/cache/minipass-npm-5.0.0-c64fb63c92-f9d89ca516.zip
deleted file mode 100644
index b07b099..0000000
Binary files a/.yarn/cache/minipass-npm-5.0.0-c64fb63c92-f9d89ca516.zip and /dev/null differ
diff --git a/.yarn/cache/minipass-npm-7.0.4-eacb4e042e-27e7007235.zip b/.yarn/cache/minipass-npm-7.0.4-eacb4e042e-27e7007235.zip
deleted file mode 100644
index ad8e9aa..0000000
Binary files a/.yarn/cache/minipass-npm-7.0.4-eacb4e042e-27e7007235.zip and /dev/null differ
diff --git a/.yarn/cache/minipass-pipeline-npm-1.2.4-5924cb077f-001d5a4a0c.zip b/.yarn/cache/minipass-pipeline-npm-1.2.4-5924cb077f-001d5a4a0c.zip
deleted file mode 100644
index a9396f6..0000000
Binary files a/.yarn/cache/minipass-pipeline-npm-1.2.4-5924cb077f-001d5a4a0c.zip and /dev/null differ
diff --git a/.yarn/cache/minipass-sized-npm-1.0.3-306d86f432-747cb22e8a.zip b/.yarn/cache/minipass-sized-npm-1.0.3-306d86f432-747cb22e8a.zip
deleted file mode 100644
index 27486e6..0000000
Binary files a/.yarn/cache/minipass-sized-npm-1.0.3-306d86f432-747cb22e8a.zip and /dev/null differ
diff --git a/.yarn/cache/minizlib-npm-2.1.2-ea89cd0cfb-5a45b57b34.zip b/.yarn/cache/minizlib-npm-2.1.2-ea89cd0cfb-5a45b57b34.zip
deleted file mode 100644
index b15a5fc..0000000
Binary files a/.yarn/cache/minizlib-npm-2.1.2-ea89cd0cfb-5a45b57b34.zip and /dev/null differ
diff --git a/.yarn/cache/mkdirp-npm-1.0.4-37f6ef56b9-1aa3a6a2d7.zip b/.yarn/cache/mkdirp-npm-1.0.4-37f6ef56b9-1aa3a6a2d7.zip
deleted file mode 100644
index 4d2896d..0000000
Binary files a/.yarn/cache/mkdirp-npm-1.0.4-37f6ef56b9-1aa3a6a2d7.zip and /dev/null differ
diff --git a/.yarn/cache/ms-npm-2.1.2-ec0c1512ff-9b65fb709b.zip b/.yarn/cache/ms-npm-2.1.2-ec0c1512ff-9b65fb709b.zip
deleted file mode 100644
index c4fe244..0000000
Binary files a/.yarn/cache/ms-npm-2.1.2-ec0c1512ff-9b65fb709b.zip and /dev/null differ
diff --git a/.yarn/cache/mz-npm-2.7.0-ec3cef4ec2-063966dd8e.zip b/.yarn/cache/mz-npm-2.7.0-ec3cef4ec2-063966dd8e.zip
deleted file mode 100644
index 82234e1..0000000
Binary files a/.yarn/cache/mz-npm-2.7.0-ec3cef4ec2-063966dd8e.zip and /dev/null differ
diff --git a/.yarn/cache/nanoid-npm-3.3.7-98824ba130-cf385d8457.zip b/.yarn/cache/nanoid-npm-3.3.7-98824ba130-cf385d8457.zip
deleted file mode 100644
index 059d7cf..0000000
Binary files a/.yarn/cache/nanoid-npm-3.3.7-98824ba130-cf385d8457.zip and /dev/null differ
diff --git a/.yarn/cache/negotiator-npm-0.6.3-9d50e36171-5899e1bf5c.zip b/.yarn/cache/negotiator-npm-0.6.3-9d50e36171-5899e1bf5c.zip
deleted file mode 100644
index a533027..0000000
Binary files a/.yarn/cache/negotiator-npm-0.6.3-9d50e36171-5899e1bf5c.zip and /dev/null differ
diff --git a/.yarn/cache/node-gyp-npm-10.0.1-48708ce70b-7b92a3c50c.zip b/.yarn/cache/node-gyp-npm-10.0.1-48708ce70b-7b92a3c50c.zip
deleted file mode 100644
index 06ca2c4..0000000
Binary files a/.yarn/cache/node-gyp-npm-10.0.1-48708ce70b-7b92a3c50c.zip and /dev/null differ
diff --git a/.yarn/cache/nopt-npm-7.2.0-dd734b678d-1ee27d90ba.zip b/.yarn/cache/nopt-npm-7.2.0-dd734b678d-1ee27d90ba.zip
deleted file mode 100644
index c0bb6e6..0000000
Binary files a/.yarn/cache/nopt-npm-7.2.0-dd734b678d-1ee27d90ba.zip and /dev/null differ
diff --git a/.yarn/cache/normalize-path-npm-3.0.0-658ba7d77f-215a701b47.zip b/.yarn/cache/normalize-path-npm-3.0.0-658ba7d77f-215a701b47.zip
deleted file mode 100644
index 8d5e845..0000000
Binary files a/.yarn/cache/normalize-path-npm-3.0.0-658ba7d77f-215a701b47.zip and /dev/null differ
diff --git a/.yarn/cache/object-assign-npm-4.1.1-1004ad6dec-66cf021898.zip b/.yarn/cache/object-assign-npm-4.1.1-1004ad6dec-66cf021898.zip
deleted file mode 100644
index e4ce2e1..0000000
Binary files a/.yarn/cache/object-assign-npm-4.1.1-1004ad6dec-66cf021898.zip and /dev/null differ
diff --git a/.yarn/cache/object-hash-npm-3.0.0-d941e0cabe-f12c80d588.zip b/.yarn/cache/object-hash-npm-3.0.0-d941e0cabe-f12c80d588.zip
deleted file mode 100644
index fa61c0d..0000000
Binary files a/.yarn/cache/object-hash-npm-3.0.0-d941e0cabe-f12c80d588.zip and /dev/null differ
diff --git a/.yarn/cache/once-npm-1.4.0-ccf03ef07a-57afc24653.zip b/.yarn/cache/once-npm-1.4.0-ccf03ef07a-57afc24653.zip
deleted file mode 100644
index 14dee7d..0000000
Binary files a/.yarn/cache/once-npm-1.4.0-ccf03ef07a-57afc24653.zip and /dev/null differ
diff --git a/.yarn/cache/p-map-npm-4.0.0-4677ae07c7-d51e630d72.zip b/.yarn/cache/p-map-npm-4.0.0-4677ae07c7-d51e630d72.zip
deleted file mode 100644
index dbc9626..0000000
Binary files a/.yarn/cache/p-map-npm-4.0.0-4677ae07c7-d51e630d72.zip and /dev/null differ
diff --git a/.yarn/cache/path-is-absolute-npm-1.0.1-31bc695ffd-907e1e3e6a.zip b/.yarn/cache/path-is-absolute-npm-1.0.1-31bc695ffd-907e1e3e6a.zip
deleted file mode 100644
index 42f2376..0000000
Binary files a/.yarn/cache/path-is-absolute-npm-1.0.1-31bc695ffd-907e1e3e6a.zip and /dev/null differ
diff --git a/.yarn/cache/path-key-npm-3.1.1-0e66ea8321-e44aa3ca9f.zip b/.yarn/cache/path-key-npm-3.1.1-0e66ea8321-e44aa3ca9f.zip
deleted file mode 100644
index 28ec147..0000000
Binary files a/.yarn/cache/path-key-npm-3.1.1-0e66ea8321-e44aa3ca9f.zip and /dev/null differ
diff --git a/.yarn/cache/path-parse-npm-1.0.7-09564527b7-6de0bfa37b.zip b/.yarn/cache/path-parse-npm-1.0.7-09564527b7-6de0bfa37b.zip
deleted file mode 100644
index cb35624..0000000
Binary files a/.yarn/cache/path-parse-npm-1.0.7-09564527b7-6de0bfa37b.zip and /dev/null differ
diff --git a/.yarn/cache/path-scurry-npm-1.10.1-52bd946f2e-7a2ca28cda.zip b/.yarn/cache/path-scurry-npm-1.10.1-52bd946f2e-7a2ca28cda.zip
deleted file mode 100644
index d434688..0000000
Binary files a/.yarn/cache/path-scurry-npm-1.10.1-52bd946f2e-7a2ca28cda.zip and /dev/null differ
diff --git a/.yarn/cache/picocolors-npm-1.0.0-d81e0b1927-6616d34dd0.zip b/.yarn/cache/picocolors-npm-1.0.0-d81e0b1927-6616d34dd0.zip
deleted file mode 100644
index 2bb490e..0000000
Binary files a/.yarn/cache/picocolors-npm-1.0.0-d81e0b1927-6616d34dd0.zip and /dev/null differ
diff --git a/.yarn/cache/picomatch-npm-2.3.1-c782cfd986-5e3bbbf6a7.zip b/.yarn/cache/picomatch-npm-2.3.1-c782cfd986-5e3bbbf6a7.zip
deleted file mode 100644
index b962307..0000000
Binary files a/.yarn/cache/picomatch-npm-2.3.1-c782cfd986-5e3bbbf6a7.zip and /dev/null differ
diff --git a/.yarn/cache/pify-npm-2.3.0-8b63310934-d5758aa570.zip b/.yarn/cache/pify-npm-2.3.0-8b63310934-d5758aa570.zip
deleted file mode 100644
index d6a8926..0000000
Binary files a/.yarn/cache/pify-npm-2.3.0-8b63310934-d5758aa570.zip and /dev/null differ
diff --git a/.yarn/cache/pirates-npm-4.0.6-a8ec571a43-1c8546420a.zip b/.yarn/cache/pirates-npm-4.0.6-a8ec571a43-1c8546420a.zip
deleted file mode 100644
index 1ec0444..0000000
Binary files a/.yarn/cache/pirates-npm-4.0.6-a8ec571a43-1c8546420a.zip and /dev/null differ
diff --git a/.yarn/cache/postcss-import-npm-15.1.0-8b9e86f900-234c4d23eb.zip b/.yarn/cache/postcss-import-npm-15.1.0-8b9e86f900-234c4d23eb.zip
deleted file mode 100644
index aab2cae..0000000
Binary files a/.yarn/cache/postcss-import-npm-15.1.0-8b9e86f900-234c4d23eb.zip and /dev/null differ
diff --git a/.yarn/cache/postcss-js-npm-4.0.1-2c4ee70bf3-9991f86f05.zip b/.yarn/cache/postcss-js-npm-4.0.1-2c4ee70bf3-9991f86f05.zip
deleted file mode 100644
index a4665e9..0000000
Binary files a/.yarn/cache/postcss-js-npm-4.0.1-2c4ee70bf3-9991f86f05.zip and /dev/null differ
diff --git a/.yarn/cache/postcss-load-config-npm-4.0.2-319bcff9ca-efbe2cf7bd.zip b/.yarn/cache/postcss-load-config-npm-4.0.2-319bcff9ca-efbe2cf7bd.zip
deleted file mode 100644
index 90970d0..0000000
Binary files a/.yarn/cache/postcss-load-config-npm-4.0.2-319bcff9ca-efbe2cf7bd.zip and /dev/null differ
diff --git a/.yarn/cache/postcss-nested-npm-6.0.1-5cdc427fe8-287630cd56.zip b/.yarn/cache/postcss-nested-npm-6.0.1-5cdc427fe8-287630cd56.zip
deleted file mode 100644
index 4da892d..0000000
Binary files a/.yarn/cache/postcss-nested-npm-6.0.1-5cdc427fe8-287630cd56.zip and /dev/null differ
diff --git a/.yarn/cache/postcss-npm-8.4.31-385051a82b-dac8611c6d.zip b/.yarn/cache/postcss-npm-8.4.31-385051a82b-dac8611c6d.zip
deleted file mode 100644
index 959b9c8..0000000
Binary files a/.yarn/cache/postcss-npm-8.4.31-385051a82b-dac8611c6d.zip and /dev/null differ
diff --git a/.yarn/cache/postcss-selector-parser-npm-6.0.13-f732d92326-556a437939.zip b/.yarn/cache/postcss-selector-parser-npm-6.0.13-f732d92326-556a437939.zip
deleted file mode 100644
index d7efaa3..0000000
Binary files a/.yarn/cache/postcss-selector-parser-npm-6.0.13-f732d92326-556a437939.zip and /dev/null differ
diff --git a/.yarn/cache/postcss-value-parser-npm-4.2.0-3cef602a6a-9f66285b98.zip b/.yarn/cache/postcss-value-parser-npm-4.2.0-3cef602a6a-9f66285b98.zip
deleted file mode 100644
index 236a4a5..0000000
Binary files a/.yarn/cache/postcss-value-parser-npm-4.2.0-3cef602a6a-9f66285b98.zip and /dev/null differ
diff --git a/.yarn/cache/proc-log-npm-3.0.0-a8c21c2f0f-f1e721cbbb.zip b/.yarn/cache/proc-log-npm-3.0.0-a8c21c2f0f-f1e721cbbb.zip
deleted file mode 100644
index f4db796..0000000
Binary files a/.yarn/cache/proc-log-npm-3.0.0-a8c21c2f0f-f1e721cbbb.zip and /dev/null differ
diff --git a/.yarn/cache/promise-retry-npm-2.0.1-871f0b01b7-325e99d059.zip b/.yarn/cache/promise-retry-npm-2.0.1-871f0b01b7-325e99d059.zip
deleted file mode 100644
index dd2b04f..0000000
Binary files a/.yarn/cache/promise-retry-npm-2.0.1-871f0b01b7-325e99d059.zip and /dev/null differ
diff --git a/.yarn/cache/queue-microtask-npm-1.2.3-fcc98e4e2d-0f88d794d4.zip b/.yarn/cache/queue-microtask-npm-1.2.3-fcc98e4e2d-0f88d794d4.zip
deleted file mode 100644
index 1809973..0000000
Binary files a/.yarn/cache/queue-microtask-npm-1.2.3-fcc98e4e2d-0f88d794d4.zip and /dev/null differ
diff --git a/.yarn/cache/read-cache-npm-1.0.0-00fa89ed05-17a1996977.zip b/.yarn/cache/read-cache-npm-1.0.0-00fa89ed05-17a1996977.zip
deleted file mode 100644
index f2d0731..0000000
Binary files a/.yarn/cache/read-cache-npm-1.0.0-00fa89ed05-17a1996977.zip and /dev/null differ
diff --git a/.yarn/cache/readdirp-npm-3.6.0-f950cc74ab-7da2fe8d5a.zip b/.yarn/cache/readdirp-npm-3.6.0-f950cc74ab-7da2fe8d5a.zip
deleted file mode 100644
index 973cfd1..0000000
Binary files a/.yarn/cache/readdirp-npm-3.6.0-f950cc74ab-7da2fe8d5a.zip and /dev/null differ
diff --git a/.yarn/cache/resolve-npm-1.22.8-098f379dfe-87b03ea191.zip b/.yarn/cache/resolve-npm-1.22.8-098f379dfe-87b03ea191.zip
deleted file mode 100644
index 5ff3589..0000000
Binary files a/.yarn/cache/resolve-npm-1.22.8-098f379dfe-87b03ea191.zip and /dev/null differ
diff --git a/.yarn/cache/resolve-patch-6ba30f2f2c-798a84fbca.zip b/.yarn/cache/resolve-patch-6ba30f2f2c-798a84fbca.zip
deleted file mode 100644
index 14ca4f7..0000000
Binary files a/.yarn/cache/resolve-patch-6ba30f2f2c-798a84fbca.zip and /dev/null differ
diff --git a/.yarn/cache/retry-npm-0.12.0-72ac7fb4cc-51f2fddddb.zip b/.yarn/cache/retry-npm-0.12.0-72ac7fb4cc-51f2fddddb.zip
deleted file mode 100644
index 562b651..0000000
Binary files a/.yarn/cache/retry-npm-0.12.0-72ac7fb4cc-51f2fddddb.zip and /dev/null differ
diff --git a/.yarn/cache/reusify-npm-1.0.4-95ac4aec11-08ef02ed05.zip b/.yarn/cache/reusify-npm-1.0.4-95ac4aec11-08ef02ed05.zip
deleted file mode 100644
index cd80993..0000000
Binary files a/.yarn/cache/reusify-npm-1.0.4-95ac4aec11-08ef02ed05.zip and /dev/null differ
diff --git a/.yarn/cache/run-parallel-npm-1.2.0-3f47ff2034-3d12f0251a.zip b/.yarn/cache/run-parallel-npm-1.2.0-3f47ff2034-3d12f0251a.zip
deleted file mode 100644
index aa7c07c..0000000
Binary files a/.yarn/cache/run-parallel-npm-1.2.0-3f47ff2034-3d12f0251a.zip and /dev/null differ
diff --git a/.yarn/cache/safer-buffer-npm-2.1.2-8d5c0b705e-549ba83f5b.zip b/.yarn/cache/safer-buffer-npm-2.1.2-8d5c0b705e-549ba83f5b.zip
deleted file mode 100644
index e120db3..0000000
Binary files a/.yarn/cache/safer-buffer-npm-2.1.2-8d5c0b705e-549ba83f5b.zip and /dev/null differ
diff --git a/.yarn/cache/semver-npm-7.5.4-c4ad957fcd-9bc02fd8e2.zip b/.yarn/cache/semver-npm-7.5.4-c4ad957fcd-9bc02fd8e2.zip
deleted file mode 100644
index 0cf952c..0000000
Binary files a/.yarn/cache/semver-npm-7.5.4-c4ad957fcd-9bc02fd8e2.zip and /dev/null differ
diff --git a/.yarn/cache/shebang-command-npm-2.0.0-eb2b01921d-85aa394d8c.zip b/.yarn/cache/shebang-command-npm-2.0.0-eb2b01921d-85aa394d8c.zip
deleted file mode 100644
index 5dbbd04..0000000
Binary files a/.yarn/cache/shebang-command-npm-2.0.0-eb2b01921d-85aa394d8c.zip and /dev/null differ
diff --git a/.yarn/cache/shebang-regex-npm-3.0.0-899a0cd65e-ea18044ffa.zip b/.yarn/cache/shebang-regex-npm-3.0.0-899a0cd65e-ea18044ffa.zip
deleted file mode 100644
index 6b227ae..0000000
Binary files a/.yarn/cache/shebang-regex-npm-3.0.0-899a0cd65e-ea18044ffa.zip and /dev/null differ
diff --git a/.yarn/cache/signal-exit-npm-4.1.0-61fb957687-a9175b0697.zip b/.yarn/cache/signal-exit-npm-4.1.0-61fb957687-a9175b0697.zip
deleted file mode 100644
index dd170f5..0000000
Binary files a/.yarn/cache/signal-exit-npm-4.1.0-61fb957687-a9175b0697.zip and /dev/null differ
diff --git a/.yarn/cache/smart-buffer-npm-4.2.0-5ac3f668bb-644e012e31.zip b/.yarn/cache/smart-buffer-npm-4.2.0-5ac3f668bb-644e012e31.zip
deleted file mode 100644
index ca86502..0000000
Binary files a/.yarn/cache/smart-buffer-npm-4.2.0-5ac3f668bb-644e012e31.zip and /dev/null differ
diff --git a/.yarn/cache/socks-npm-2.7.1-17f2b53052-412b254d32.zip b/.yarn/cache/socks-npm-2.7.1-17f2b53052-412b254d32.zip
deleted file mode 100644
index 1245644..0000000
Binary files a/.yarn/cache/socks-npm-2.7.1-17f2b53052-412b254d32.zip and /dev/null differ
diff --git a/.yarn/cache/socks-proxy-agent-npm-8.0.2-df165543cf-3ff2970563.zip b/.yarn/cache/socks-proxy-agent-npm-8.0.2-df165543cf-3ff2970563.zip
deleted file mode 100644
index 303f2c9..0000000
Binary files a/.yarn/cache/socks-proxy-agent-npm-8.0.2-df165543cf-3ff2970563.zip and /dev/null differ
diff --git a/.yarn/cache/source-map-js-npm-1.0.2-ee4f9f9b30-3bb232796a.zip b/.yarn/cache/source-map-js-npm-1.0.2-ee4f9f9b30-3bb232796a.zip
deleted file mode 100644
index c2a6ff1..0000000
Binary files a/.yarn/cache/source-map-js-npm-1.0.2-ee4f9f9b30-3bb232796a.zip and /dev/null differ
diff --git a/.yarn/cache/ssri-npm-10.0.5-1a7557d04d-3d1f6a4aa5.zip b/.yarn/cache/ssri-npm-10.0.5-1a7557d04d-3d1f6a4aa5.zip
deleted file mode 100644
index ed9b4a0..0000000
Binary files a/.yarn/cache/ssri-npm-10.0.5-1a7557d04d-3d1f6a4aa5.zip and /dev/null differ
diff --git a/.yarn/cache/string-width-npm-4.2.3-2c27177bae-748c979889.zip b/.yarn/cache/string-width-npm-4.2.3-2c27177bae-748c979889.zip
deleted file mode 100644
index f5c9c6d..0000000
Binary files a/.yarn/cache/string-width-npm-4.2.3-2c27177bae-748c979889.zip and /dev/null differ
diff --git a/.yarn/cache/string-width-npm-5.1.2-bf60531341-4da7e3d5d6.zip b/.yarn/cache/string-width-npm-5.1.2-bf60531341-4da7e3d5d6.zip
deleted file mode 100644
index bd90081..0000000
Binary files a/.yarn/cache/string-width-npm-5.1.2-bf60531341-4da7e3d5d6.zip and /dev/null differ
diff --git a/.yarn/cache/strip-ansi-npm-6.0.1-caddc7cb40-9d3061240b.zip b/.yarn/cache/strip-ansi-npm-6.0.1-caddc7cb40-9d3061240b.zip
deleted file mode 100644
index 4321145..0000000
Binary files a/.yarn/cache/strip-ansi-npm-6.0.1-caddc7cb40-9d3061240b.zip and /dev/null differ
diff --git a/.yarn/cache/strip-ansi-npm-7.1.0-7453b80b79-23e0a12a07.zip b/.yarn/cache/strip-ansi-npm-7.1.0-7453b80b79-23e0a12a07.zip
deleted file mode 100644
index 7554c12..0000000
Binary files a/.yarn/cache/strip-ansi-npm-7.1.0-7453b80b79-23e0a12a07.zip and /dev/null differ
diff --git a/.yarn/cache/sucrase-npm-3.34.0-434160cdf2-b04543bc2c.zip b/.yarn/cache/sucrase-npm-3.34.0-434160cdf2-b04543bc2c.zip
deleted file mode 100644
index d6ebf98..0000000
Binary files a/.yarn/cache/sucrase-npm-3.34.0-434160cdf2-b04543bc2c.zip and /dev/null differ
diff --git a/.yarn/cache/supports-preserve-symlinks-flag-npm-1.0.0-f17c4d0028-a0f3140423.zip b/.yarn/cache/supports-preserve-symlinks-flag-npm-1.0.0-f17c4d0028-a0f3140423.zip
deleted file mode 100644
index 58bb4f6..0000000
Binary files a/.yarn/cache/supports-preserve-symlinks-flag-npm-1.0.0-f17c4d0028-a0f3140423.zip and /dev/null differ
diff --git a/.yarn/cache/tailwindcss-npm-3.3.5-a3fffa234c-655b7b26d2.zip b/.yarn/cache/tailwindcss-npm-3.3.5-a3fffa234c-655b7b26d2.zip
deleted file mode 100644
index c4c0f6b..0000000
Binary files a/.yarn/cache/tailwindcss-npm-3.3.5-a3fffa234c-655b7b26d2.zip and /dev/null differ
diff --git a/.yarn/cache/tar-npm-6.2.0-3eb25205a7-5f68e53e31.zip b/.yarn/cache/tar-npm-6.2.0-3eb25205a7-5f68e53e31.zip
deleted file mode 100644
index 20ab1a3..0000000
Binary files a/.yarn/cache/tar-npm-6.2.0-3eb25205a7-5f68e53e31.zip and /dev/null differ
diff --git a/.yarn/cache/thenify-all-npm-1.6.0-96309bbc8b-22775c13a1.zip b/.yarn/cache/thenify-all-npm-1.6.0-96309bbc8b-22775c13a1.zip
deleted file mode 100644
index 1eb1e3a..0000000
Binary files a/.yarn/cache/thenify-all-npm-1.6.0-96309bbc8b-22775c13a1.zip and /dev/null differ
diff --git a/.yarn/cache/thenify-npm-3.3.1-030bedb22c-c3cbda4f5f.zip b/.yarn/cache/thenify-npm-3.3.1-030bedb22c-c3cbda4f5f.zip
deleted file mode 100644
index 86d5007..0000000
Binary files a/.yarn/cache/thenify-npm-3.3.1-030bedb22c-c3cbda4f5f.zip and /dev/null differ
diff --git a/.yarn/cache/to-regex-range-npm-5.0.1-f1e8263b00-2b6001e314.zip b/.yarn/cache/to-regex-range-npm-5.0.1-f1e8263b00-2b6001e314.zip
deleted file mode 100644
index 933c228..0000000
Binary files a/.yarn/cache/to-regex-range-npm-5.0.1-f1e8263b00-2b6001e314.zip and /dev/null differ
diff --git a/.yarn/cache/ts-interface-checker-npm-0.1.13-0c7b064494-df3e240963.zip b/.yarn/cache/ts-interface-checker-npm-0.1.13-0c7b064494-df3e240963.zip
deleted file mode 100644
index 296df54..0000000
Binary files a/.yarn/cache/ts-interface-checker-npm-0.1.13-0c7b064494-df3e240963.zip and /dev/null differ
diff --git a/.yarn/cache/unique-filename-npm-3.0.0-77d68e0a45-9310efd64c.zip b/.yarn/cache/unique-filename-npm-3.0.0-77d68e0a45-9310efd64c.zip
deleted file mode 100644
index 0303147..0000000
Binary files a/.yarn/cache/unique-filename-npm-3.0.0-77d68e0a45-9310efd64c.zip and /dev/null differ
diff --git a/.yarn/cache/unique-slug-npm-4.0.0-e6b08f28aa-aabf6e1d22.zip b/.yarn/cache/unique-slug-npm-4.0.0-e6b08f28aa-aabf6e1d22.zip
deleted file mode 100644
index f1cf9da..0000000
Binary files a/.yarn/cache/unique-slug-npm-4.0.0-e6b08f28aa-aabf6e1d22.zip and /dev/null differ
diff --git a/.yarn/cache/util-deprecate-npm-1.0.2-e3fe1a219c-73c2b1cf02.zip b/.yarn/cache/util-deprecate-npm-1.0.2-e3fe1a219c-73c2b1cf02.zip
deleted file mode 100644
index 237a2ff..0000000
Binary files a/.yarn/cache/util-deprecate-npm-1.0.2-e3fe1a219c-73c2b1cf02.zip and /dev/null differ
diff --git a/.yarn/cache/which-npm-2.0.2-320ddf72f7-ea9b1db126.zip b/.yarn/cache/which-npm-2.0.2-320ddf72f7-ea9b1db126.zip
deleted file mode 100644
index 2e9d763..0000000
Binary files a/.yarn/cache/which-npm-2.0.2-320ddf72f7-ea9b1db126.zip and /dev/null differ
diff --git a/.yarn/cache/which-npm-4.0.0-dd31cd4928-143a8b3d74.zip b/.yarn/cache/which-npm-4.0.0-dd31cd4928-143a8b3d74.zip
deleted file mode 100644
index 7daf2f0..0000000
Binary files a/.yarn/cache/which-npm-4.0.0-dd31cd4928-143a8b3d74.zip and /dev/null differ
diff --git a/.yarn/cache/wrap-ansi-npm-7.0.0-ad6e1a0554-09939dd775.zip b/.yarn/cache/wrap-ansi-npm-7.0.0-ad6e1a0554-09939dd775.zip
deleted file mode 100644
index cbe3a0d..0000000
Binary files a/.yarn/cache/wrap-ansi-npm-7.0.0-ad6e1a0554-09939dd775.zip and /dev/null differ
diff --git a/.yarn/cache/wrap-ansi-npm-8.1.0-26a4e6ae28-f75c2443bd.zip b/.yarn/cache/wrap-ansi-npm-8.1.0-26a4e6ae28-f75c2443bd.zip
deleted file mode 100644
index 92be2a2..0000000
Binary files a/.yarn/cache/wrap-ansi-npm-8.1.0-26a4e6ae28-f75c2443bd.zip and /dev/null differ
diff --git a/.yarn/cache/wrappy-npm-1.0.2-916de4d4b3-519fcda0fc.zip b/.yarn/cache/wrappy-npm-1.0.2-916de4d4b3-519fcda0fc.zip
deleted file mode 100644
index fb3bf59..0000000
Binary files a/.yarn/cache/wrappy-npm-1.0.2-916de4d4b3-519fcda0fc.zip and /dev/null differ
diff --git a/.yarn/cache/yallist-npm-4.0.0-b493d9e907-a2960ef879.zip b/.yarn/cache/yallist-npm-4.0.0-b493d9e907-a2960ef879.zip
deleted file mode 100644
index ef0d9e2..0000000
Binary files a/.yarn/cache/yallist-npm-4.0.0-b493d9e907-a2960ef879.zip and /dev/null differ
diff --git a/.yarn/cache/yaml-npm-2.3.4-8bb6dc2c0d-c5f378790e.zip b/.yarn/cache/yaml-npm-2.3.4-8bb6dc2c0d-c5f378790e.zip
deleted file mode 100644
index ea47b2a..0000000
Binary files a/.yarn/cache/yaml-npm-2.3.4-8bb6dc2c0d-c5f378790e.zip and /dev/null differ
diff --git a/Dockerfile b/Dockerfile
index d521c19..b387eee 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,11 +1,35 @@
-FROM nginx:latest
+# Build stage
+FROM oven/bun:latest as builder
-COPY www /usr/share/nginx/html
-COPY entrypoint.sh /entrypoint.sh
+WORKDIR /app
-RUN chmod +x /entrypoint.sh
+# Copy package files
+COPY package.json bun.lock* ./
-ENTRYPOINT ["/entrypoint.sh"]
+# Install all dependencies (including devDependencies for building)
+RUN bun install --frozen-lockfile
-STOPSIGNAL SIGQUIT
-CMD ["nginx", "-g", "daemon off;"]
\ No newline at end of file
+# Copy source code and configuration files
+COPY . .
+
+# Build the frontend with Vite and compile the server to executable
+RUN bun run build
+
+# Minimal production stage using distroless debian
+FROM gcr.io/distroless/cc-debian12
+
+WORKDIR /app
+
+# Copy the built assets
+COPY --from=builder /app/dist/server /app/server
+COPY --from=builder /app/dist/ /app/dist/
+COPY --from=builder /app/dist/assets /app/dist/assets
+
+# Expose the port
+EXPOSE 3000
+
+# Set environment to production
+ENV NODE_ENV=production
+
+# Start the application using the compiled executable
+CMD ["/app/server"]
diff --git a/README.md b/README.md
deleted file mode 100644
index 369177c..0000000
--- a/README.md
+++ /dev/null
@@ -1 +0,0 @@
-# public
diff --git a/bun.lock b/bun.lock
new file mode 100644
index 0000000..2b9d8dc
--- /dev/null
+++ b/bun.lock
@@ -0,0 +1,406 @@
+{
+ "lockfileVersion": 1,
+ "workspaces": {
+ "": {
+ "name": "homepage",
+ "dependencies": {
+ "@elysiajs/eden": "^1.3.2",
+ "@elysiajs/static": "^1.3.0",
+ "@fontsource-variable/exo-2": "^5.2.6",
+ "@fontsource-variable/inter": "^5.2.6",
+ "@tailwindcss/vite": "^4.1.11",
+ "elysia": "^1.3.8",
+ "tailwindcss": "^4.1.11",
+ },
+ "devDependencies": {
+ "@iconify/json": "^2.2.367",
+ "bun-types": "latest",
+ "concurrently": "^9.2.0",
+ "unplugin-icons": "^22.2.0",
+ "vite": "^7.1.0",
+ },
+ },
+ },
+ "trustedDependencies": [
+ "@tailwindcss/oxide",
+ ],
+ "packages": {
+ "@ampproject/remapping": ["@ampproject/remapping@2.3.0", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw=="],
+
+ "@antfu/install-pkg": ["@antfu/install-pkg@1.1.0", "", { "dependencies": { "package-manager-detector": "^1.3.0", "tinyexec": "^1.0.1" } }, "sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ=="],
+
+ "@antfu/utils": ["@antfu/utils@8.1.1", "", {}, "sha512-Mex9nXf9vR6AhcXmMrlz/HVgYYZpVGJ6YlPgwl7UnaFpnshXs6EK/oa5Gpf3CzENMjkvEx2tQtntGnb7UtSTOQ=="],
+
+ "@elysiajs/eden": ["@elysiajs/eden@1.3.2", "", { "peerDependencies": { "elysia": ">= 1.3.0" } }, "sha512-0bCU5DO7J7hQfS2y3O3399GtoxMWRDMgQNMTHOnf70/F2nF8SwGHvzwh3+wO62Ko5FMF7EYqTN9Csw/g/Q7qwg=="],
+
+ "@elysiajs/static": ["@elysiajs/static@1.3.0", "", { "dependencies": { "node-cache": "^5.1.2" }, "peerDependencies": { "elysia": ">= 1.3.0" } }, "sha512-7mWlj2U/AZvH27IfRKqpUjDP1W9ZRldF9NmdnatFEtx0AOy7YYgyk0rt5hXrH6wPcR//2gO2Qy+k5rwswpEhJA=="],
+
+ "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.8", "", { "os": "aix", "cpu": "ppc64" }, "sha512-urAvrUedIqEiFR3FYSLTWQgLu5tb+m0qZw0NBEasUeo6wuqatkMDaRT+1uABiGXEu5vqgPd7FGE1BhsAIy9QVA=="],
+
+ "@esbuild/android-arm": ["@esbuild/android-arm@0.25.8", "", { "os": "android", "cpu": "arm" }, "sha512-RONsAvGCz5oWyePVnLdZY/HHwA++nxYWIX1atInlaW6SEkwq6XkP3+cb825EUcRs5Vss/lGh/2YxAb5xqc07Uw=="],
+
+ "@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.8", "", { "os": "android", "cpu": "arm64" }, "sha512-OD3p7LYzWpLhZEyATcTSJ67qB5D+20vbtr6vHlHWSQYhKtzUYrETuWThmzFpZtFsBIxRvhO07+UgVA9m0i/O1w=="],
+
+ "@esbuild/android-x64": ["@esbuild/android-x64@0.25.8", "", { "os": "android", "cpu": "x64" }, "sha512-yJAVPklM5+4+9dTeKwHOaA+LQkmrKFX96BM0A/2zQrbS6ENCmxc4OVoBs5dPkCCak2roAD+jKCdnmOqKszPkjA=="],
+
+ "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.8", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Jw0mxgIaYX6R8ODrdkLLPwBqHTtYHJSmzzd+QeytSugzQ0Vg4c5rDky5VgkoowbZQahCbsv1rT1KW72MPIkevw=="],
+
+ "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.8", "", { "os": "darwin", "cpu": "x64" }, "sha512-Vh2gLxxHnuoQ+GjPNvDSDRpoBCUzY4Pu0kBqMBDlK4fuWbKgGtmDIeEC081xi26PPjn+1tct+Bh8FjyLlw1Zlg=="],
+
+ "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.8", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-YPJ7hDQ9DnNe5vxOm6jaie9QsTwcKedPvizTVlqWG9GBSq+BuyWEDazlGaDTC5NGU4QJd666V0yqCBL2oWKPfA=="],
+
+ "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.8", "", { "os": "freebsd", "cpu": "x64" }, "sha512-MmaEXxQRdXNFsRN/KcIimLnSJrk2r5H8v+WVafRWz5xdSVmWLoITZQXcgehI2ZE6gioE6HirAEToM/RvFBeuhw=="],
+
+ "@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.8", "", { "os": "linux", "cpu": "arm" }, "sha512-FuzEP9BixzZohl1kLf76KEVOsxtIBFwCaLupVuk4eFVnOZfU+Wsn+x5Ryam7nILV2pkq2TqQM9EZPsOBuMC+kg=="],
+
+ "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.8", "", { "os": "linux", "cpu": "arm64" }, "sha512-WIgg00ARWv/uYLU7lsuDK00d/hHSfES5BzdWAdAig1ioV5kaFNrtK8EqGcUBJhYqotlUByUKz5Qo6u8tt7iD/w=="],
+
+ "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.8", "", { "os": "linux", "cpu": "ia32" }, "sha512-A1D9YzRX1i+1AJZuFFUMP1E9fMaYY+GnSQil9Tlw05utlE86EKTUA7RjwHDkEitmLYiFsRd9HwKBPEftNdBfjg=="],
+
+ "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.8", "", { "os": "linux", "cpu": "none" }, "sha512-O7k1J/dwHkY1RMVvglFHl1HzutGEFFZ3kNiDMSOyUrB7WcoHGf96Sh+64nTRT26l3GMbCW01Ekh/ThKM5iI7hQ=="],
+
+ "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.8", "", { "os": "linux", "cpu": "none" }, "sha512-uv+dqfRazte3BzfMp8PAQXmdGHQt2oC/y2ovwpTteqrMx2lwaksiFZ/bdkXJC19ttTvNXBuWH53zy/aTj1FgGw=="],
+
+ "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.8", "", { "os": "linux", "cpu": "ppc64" }, "sha512-GyG0KcMi1GBavP5JgAkkstMGyMholMDybAf8wF5A70CALlDM2p/f7YFE7H92eDeH/VBtFJA5MT4nRPDGg4JuzQ=="],
+
+ "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.8", "", { "os": "linux", "cpu": "none" }, "sha512-rAqDYFv3yzMrq7GIcen3XP7TUEG/4LK86LUPMIz6RT8A6pRIDn0sDcvjudVZBiiTcZCY9y2SgYX2lgK3AF+1eg=="],
+
+ "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.8", "", { "os": "linux", "cpu": "s390x" }, "sha512-Xutvh6VjlbcHpsIIbwY8GVRbwoviWT19tFhgdA7DlenLGC/mbc3lBoVb7jxj9Z+eyGqvcnSyIltYUrkKzWqSvg=="],
+
+ "@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.8", "", { "os": "linux", "cpu": "x64" }, "sha512-ASFQhgY4ElXh3nDcOMTkQero4b1lgubskNlhIfJrsH5OKZXDpUAKBlNS0Kx81jwOBp+HCeZqmoJuihTv57/jvQ=="],
+
+ "@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.8", "", { "os": "none", "cpu": "arm64" }, "sha512-d1KfruIeohqAi6SA+gENMuObDbEjn22olAR7egqnkCD9DGBG0wsEARotkLgXDu6c4ncgWTZJtN5vcgxzWRMzcw=="],
+
+ "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.8", "", { "os": "none", "cpu": "x64" }, "sha512-nVDCkrvx2ua+XQNyfrujIG38+YGyuy2Ru9kKVNyh5jAys6n+l44tTtToqHjino2My8VAY6Lw9H7RI73XFi66Cg=="],
+
+ "@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.8", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-j8HgrDuSJFAujkivSMSfPQSAa5Fxbvk4rgNAS5i3K+r8s1X0p1uOO2Hl2xNsGFppOeHOLAVgYwDVlmxhq5h+SQ=="],
+
+ "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.8", "", { "os": "openbsd", "cpu": "x64" }, "sha512-1h8MUAwa0VhNCDp6Af0HToI2TJFAn1uqT9Al6DJVzdIBAd21m/G0Yfc77KDM3uF3T/YaOgQq3qTJHPbTOInaIQ=="],
+
+ "@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.25.8", "", { "os": "none", "cpu": "arm64" }, "sha512-r2nVa5SIK9tSWd0kJd9HCffnDHKchTGikb//9c7HX+r+wHYCpQrSgxhlY6KWV1nFo1l4KFbsMlHk+L6fekLsUg=="],
+
+ "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.8", "", { "os": "sunos", "cpu": "x64" }, "sha512-zUlaP2S12YhQ2UzUfcCuMDHQFJyKABkAjvO5YSndMiIkMimPmxA+BYSBikWgsRpvyxuRnow4nS5NPnf9fpv41w=="],
+
+ "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.8", "", { "os": "win32", "cpu": "arm64" }, "sha512-YEGFFWESlPva8hGL+zvj2z/SaK+pH0SwOM0Nc/d+rVnW7GSTFlLBGzZkuSU9kFIGIo8q9X3ucpZhu8PDN5A2sQ=="],
+
+ "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.8", "", { "os": "win32", "cpu": "ia32" }, "sha512-hiGgGC6KZ5LZz58OL/+qVVoZiuZlUYlYHNAmczOm7bs2oE1XriPFi5ZHHrS8ACpV5EjySrnoCKmcbQMN+ojnHg=="],
+
+ "@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.8", "", { "os": "win32", "cpu": "x64" }, "sha512-cn3Yr7+OaaZq1c+2pe+8yxC8E144SReCQjN6/2ynubzYjvyqZjTXfQJpAcQpsdJq3My7XADANiYGHoFC69pLQw=="],
+
+ "@fontsource-variable/exo-2": ["@fontsource-variable/exo-2@5.2.6", "", {}, "sha512-9wFQ7oEhQa0S6xgcuCQHj7twrLNkQ+y3gS+u/hsyCF8tqRVSMgXJBF294aF/Xc6WTjNZU+eeWpntycQzb1guVQ=="],
+
+ "@fontsource-variable/inter": ["@fontsource-variable/inter@5.2.6", "", {}, "sha512-jks/bficUPQ9nn7GvXvHtlQIPudW7Wx8CrlZoY8bhxgeobNxlQan8DclUJuYF2loYRrGpfrhCIZZspXYysiVGg=="],
+
+ "@iconify/json": ["@iconify/json@2.2.367", "", { "dependencies": { "@iconify/types": "*", "pathe": "^1.1.2" } }, "sha512-8ngsYOcvrfVbNq/9vp74FsnqPcmVcmS+v3mgzkcsex3IvGNOg3dvLOEukSfTRoq1kpkVYlwy6FkTwCqfSnSK7A=="],
+
+ "@iconify/types": ["@iconify/types@2.0.0", "", {}, "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg=="],
+
+ "@iconify/utils": ["@iconify/utils@2.3.0", "", { "dependencies": { "@antfu/install-pkg": "^1.0.0", "@antfu/utils": "^8.1.0", "@iconify/types": "^2.0.0", "debug": "^4.4.0", "globals": "^15.14.0", "kolorist": "^1.8.0", "local-pkg": "^1.0.0", "mlly": "^1.7.4" } }, "sha512-GmQ78prtwYW6EtzXRU1rY+KwOKfz32PD7iJh6Iyqw68GiKuoZ2A6pRtzWONz5VQJbp50mEjXh/7NkumtrAgRKA=="],
+
+ "@isaacs/fs-minipass": ["@isaacs/fs-minipass@4.0.1", "", { "dependencies": { "minipass": "^7.0.4" } }, "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w=="],
+
+ "@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.12", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg=="],
+
+ "@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="],
+
+ "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.4", "", {}, "sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw=="],
+
+ "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.29", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ=="],
+
+ "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.46.2", "", { "os": "android", "cpu": "arm" }, "sha512-Zj3Hl6sN34xJtMv7Anwb5Gu01yujyE/cLBDB2gnHTAHaWS1Z38L7kuSG+oAh0giZMqG060f/YBStXtMH6FvPMA=="],
+
+ "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.46.2", "", { "os": "android", "cpu": "arm64" }, "sha512-nTeCWY83kN64oQ5MGz3CgtPx8NSOhC5lWtsjTs+8JAJNLcP3QbLCtDDgUKQc/Ro/frpMq4SHUaHN6AMltcEoLQ=="],
+
+ "@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.46.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-HV7bW2Fb/F5KPdM/9bApunQh68YVDU8sO8BvcW9OngQVN3HHHkw99wFupuUJfGR9pYLLAjcAOA6iO+evsbBaPQ=="],
+
+ "@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.46.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-SSj8TlYV5nJixSsm/y3QXfhspSiLYP11zpfwp6G/YDXctf3Xkdnk4woJIF5VQe0of2OjzTt8EsxnJDCdHd2xMA=="],
+
+ "@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.46.2", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-ZyrsG4TIT9xnOlLsSSi9w/X29tCbK1yegE49RYm3tu3wF1L/B6LVMqnEWyDB26d9Ecx9zrmXCiPmIabVuLmNSg=="],
+
+ "@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.46.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-pCgHFoOECwVCJ5GFq8+gR8SBKnMO+xe5UEqbemxBpCKYQddRQMgomv1104RnLSg7nNvgKy05sLsY51+OVRyiVw=="],
+
+ "@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.46.2", "", { "os": "linux", "cpu": "arm" }, "sha512-EtP8aquZ0xQg0ETFcxUbU71MZlHaw9MChwrQzatiE8U/bvi5uv/oChExXC4mWhjiqK7azGJBqU0tt5H123SzVA=="],
+
+ "@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.46.2", "", { "os": "linux", "cpu": "arm" }, "sha512-qO7F7U3u1nfxYRPM8HqFtLd+raev2K137dsV08q/LRKRLEc7RsiDWihUnrINdsWQxPR9jqZ8DIIZ1zJJAm5PjQ=="],
+
+ "@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.46.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-3dRaqLfcOXYsfvw5xMrxAk9Lb1f395gkoBYzSFcc/scgRFptRXL9DOaDpMiehf9CO8ZDRJW2z45b6fpU5nwjng=="],
+
+ "@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.46.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-fhHFTutA7SM+IrR6lIfiHskxmpmPTJUXpWIsBXpeEwNgZzZZSg/q4i6FU4J8qOGyJ0TR+wXBwx/L7Ho9z0+uDg=="],
+
+ "@rollup/rollup-linux-loongarch64-gnu": ["@rollup/rollup-linux-loongarch64-gnu@4.46.2", "", { "os": "linux", "cpu": "none" }, "sha512-i7wfGFXu8x4+FRqPymzjD+Hyav8l95UIZ773j7J7zRYc3Xsxy2wIn4x+llpunexXe6laaO72iEjeeGyUFmjKeA=="],
+
+ "@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.46.2", "", { "os": "linux", "cpu": "ppc64" }, "sha512-B/l0dFcHVUnqcGZWKcWBSV2PF01YUt0Rvlurci5P+neqY/yMKchGU8ullZvIv5e8Y1C6wOn+U03mrDylP5q9Yw=="],
+
+ "@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.46.2", "", { "os": "linux", "cpu": "none" }, "sha512-32k4ENb5ygtkMwPMucAb8MtV8olkPT03oiTxJbgkJa7lJ7dZMr0GCFJlyvy+K8iq7F/iuOr41ZdUHaOiqyR3iQ=="],
+
+ "@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.46.2", "", { "os": "linux", "cpu": "none" }, "sha512-t5B2loThlFEauloaQkZg9gxV05BYeITLvLkWOkRXogP4qHXLkWSbSHKM9S6H1schf/0YGP/qNKtiISlxvfmmZw=="],
+
+ "@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.46.2", "", { "os": "linux", "cpu": "s390x" }, "sha512-YKjekwTEKgbB7n17gmODSmJVUIvj8CX7q5442/CK80L8nqOUbMtf8b01QkG3jOqyr1rotrAnW6B/qiHwfcuWQA=="],
+
+ "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.46.2", "", { "os": "linux", "cpu": "x64" }, "sha512-Jj5a9RUoe5ra+MEyERkDKLwTXVu6s3aACP51nkfnK9wJTraCC8IMe3snOfALkrjTYd2G1ViE1hICj0fZ7ALBPA=="],
+
+ "@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.46.2", "", { "os": "linux", "cpu": "x64" }, "sha512-7kX69DIrBeD7yNp4A5b81izs8BqoZkCIaxQaOpumcJ1S/kmqNFjPhDu1LHeVXv0SexfHQv5cqHsxLOjETuqDuA=="],
+
+ "@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.46.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-wiJWMIpeaak/jsbaq2HMh/rzZxHVW1rU6coyeNNpMwk5isiPjSTx0a4YLSlYDwBH/WBvLz+EtsNqQScZTLJy3g=="],
+
+ "@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.46.2", "", { "os": "win32", "cpu": "ia32" }, "sha512-gBgaUDESVzMgWZhcyjfs9QFK16D8K6QZpwAaVNJxYDLHWayOta4ZMjGm/vsAEy3hvlS2GosVFlBlP9/Wb85DqQ=="],
+
+ "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.46.2", "", { "os": "win32", "cpu": "x64" }, "sha512-CvUo2ixeIQGtF6WvuB87XWqPQkoFAFqW+HUo/WzHwuHDvIwZCtjdWXoYCcr06iKGydiqTclC4jU/TNObC/xKZg=="],
+
+ "@sinclair/typebox": ["@sinclair/typebox@0.34.38", "", {}, "sha512-HpkxMmc2XmZKhvaKIZZThlHmx1L0I/V1hWK1NubtlFnr6ZqdiOpV72TKudZUNQjZNsyDBay72qFEhEvb+bcwcA=="],
+
+ "@tailwindcss/node": ["@tailwindcss/node@4.1.11", "", { "dependencies": { "@ampproject/remapping": "^2.3.0", "enhanced-resolve": "^5.18.1", "jiti": "^2.4.2", "lightningcss": "1.30.1", "magic-string": "^0.30.17", "source-map-js": "^1.2.1", "tailwindcss": "4.1.11" } }, "sha512-yzhzuGRmv5QyU9qLNg4GTlYI6STedBWRE7NjxP45CsFYYq9taI0zJXZBMqIC/c8fViNLhmrbpSFS57EoxUmD6Q=="],
+
+ "@tailwindcss/oxide": ["@tailwindcss/oxide@4.1.11", "", { "dependencies": { "detect-libc": "^2.0.4", "tar": "^7.4.3" }, "optionalDependencies": { "@tailwindcss/oxide-android-arm64": "4.1.11", "@tailwindcss/oxide-darwin-arm64": "4.1.11", "@tailwindcss/oxide-darwin-x64": "4.1.11", "@tailwindcss/oxide-freebsd-x64": "4.1.11", "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.11", "@tailwindcss/oxide-linux-arm64-gnu": "4.1.11", "@tailwindcss/oxide-linux-arm64-musl": "4.1.11", "@tailwindcss/oxide-linux-x64-gnu": "4.1.11", "@tailwindcss/oxide-linux-x64-musl": "4.1.11", "@tailwindcss/oxide-wasm32-wasi": "4.1.11", "@tailwindcss/oxide-win32-arm64-msvc": "4.1.11", "@tailwindcss/oxide-win32-x64-msvc": "4.1.11" } }, "sha512-Q69XzrtAhuyfHo+5/HMgr1lAiPP/G40OMFAnws7xcFEYqcypZmdW8eGXaOUIeOl1dzPJBPENXgbjsOyhg2nkrg=="],
+
+ "@tailwindcss/oxide-android-arm64": ["@tailwindcss/oxide-android-arm64@4.1.11", "", { "os": "android", "cpu": "arm64" }, "sha512-3IfFuATVRUMZZprEIx9OGDjG3Ou3jG4xQzNTvjDoKmU9JdmoCohQJ83MYd0GPnQIu89YoJqvMM0G3uqLRFtetg=="],
+
+ "@tailwindcss/oxide-darwin-arm64": ["@tailwindcss/oxide-darwin-arm64@4.1.11", "", { "os": "darwin", "cpu": "arm64" }, "sha512-ESgStEOEsyg8J5YcMb1xl8WFOXfeBmrhAwGsFxxB2CxY9evy63+AtpbDLAyRkJnxLy2WsD1qF13E97uQyP1lfQ=="],
+
+ "@tailwindcss/oxide-darwin-x64": ["@tailwindcss/oxide-darwin-x64@4.1.11", "", { "os": "darwin", "cpu": "x64" }, "sha512-EgnK8kRchgmgzG6jE10UQNaH9Mwi2n+yw1jWmof9Vyg2lpKNX2ioe7CJdf9M5f8V9uaQxInenZkOxnTVL3fhAw=="],
+
+ "@tailwindcss/oxide-freebsd-x64": ["@tailwindcss/oxide-freebsd-x64@4.1.11", "", { "os": "freebsd", "cpu": "x64" }, "sha512-xdqKtbpHs7pQhIKmqVpxStnY1skuNh4CtbcyOHeX1YBE0hArj2romsFGb6yUmzkq/6M24nkxDqU8GYrKrz+UcA=="],
+
+ "@tailwindcss/oxide-linux-arm-gnueabihf": ["@tailwindcss/oxide-linux-arm-gnueabihf@4.1.11", "", { "os": "linux", "cpu": "arm" }, "sha512-ryHQK2eyDYYMwB5wZL46uoxz2zzDZsFBwfjssgB7pzytAeCCa6glsiJGjhTEddq/4OsIjsLNMAiMlHNYnkEEeg=="],
+
+ "@tailwindcss/oxide-linux-arm64-gnu": ["@tailwindcss/oxide-linux-arm64-gnu@4.1.11", "", { "os": "linux", "cpu": "arm64" }, "sha512-mYwqheq4BXF83j/w75ewkPJmPZIqqP1nhoghS9D57CLjsh3Nfq0m4ftTotRYtGnZd3eCztgbSPJ9QhfC91gDZQ=="],
+
+ "@tailwindcss/oxide-linux-arm64-musl": ["@tailwindcss/oxide-linux-arm64-musl@4.1.11", "", { "os": "linux", "cpu": "arm64" }, "sha512-m/NVRFNGlEHJrNVk3O6I9ggVuNjXHIPoD6bqay/pubtYC9QIdAMpS+cswZQPBLvVvEF6GtSNONbDkZrjWZXYNQ=="],
+
+ "@tailwindcss/oxide-linux-x64-gnu": ["@tailwindcss/oxide-linux-x64-gnu@4.1.11", "", { "os": "linux", "cpu": "x64" }, "sha512-YW6sblI7xukSD2TdbbaeQVDysIm/UPJtObHJHKxDEcW2exAtY47j52f8jZXkqE1krdnkhCMGqP3dbniu1Te2Fg=="],
+
+ "@tailwindcss/oxide-linux-x64-musl": ["@tailwindcss/oxide-linux-x64-musl@4.1.11", "", { "os": "linux", "cpu": "x64" }, "sha512-e3C/RRhGunWYNC3aSF7exsQkdXzQ/M+aYuZHKnw4U7KQwTJotnWsGOIVih0s2qQzmEzOFIJ3+xt7iq67K/p56Q=="],
+
+ "@tailwindcss/oxide-wasm32-wasi": ["@tailwindcss/oxide-wasm32-wasi@4.1.11", "", { "dependencies": { "@emnapi/core": "^1.4.3", "@emnapi/runtime": "^1.4.3", "@emnapi/wasi-threads": "^1.0.2", "@napi-rs/wasm-runtime": "^0.2.11", "@tybys/wasm-util": "^0.9.0", "tslib": "^2.8.0" }, "cpu": "none" }, "sha512-Xo1+/GU0JEN/C/dvcammKHzeM6NqKovG+6921MR6oadee5XPBaKOumrJCXvopJ/Qb5TH7LX/UAywbqrP4lax0g=="],
+
+ "@tailwindcss/oxide-win32-arm64-msvc": ["@tailwindcss/oxide-win32-arm64-msvc@4.1.11", "", { "os": "win32", "cpu": "arm64" }, "sha512-UgKYx5PwEKrac3GPNPf6HVMNhUIGuUh4wlDFR2jYYdkX6pL/rn73zTq/4pzUm8fOjAn5L8zDeHp9iXmUGOXZ+w=="],
+
+ "@tailwindcss/oxide-win32-x64-msvc": ["@tailwindcss/oxide-win32-x64-msvc@4.1.11", "", { "os": "win32", "cpu": "x64" }, "sha512-YfHoggn1j0LK7wR82TOucWc5LDCguHnoS879idHekmmiR7g9HUtMw9MI0NHatS28u/Xlkfi9w5RJWgz2Dl+5Qg=="],
+
+ "@tailwindcss/vite": ["@tailwindcss/vite@4.1.11", "", { "dependencies": { "@tailwindcss/node": "4.1.11", "@tailwindcss/oxide": "4.1.11", "tailwindcss": "4.1.11" }, "peerDependencies": { "vite": "^5.2.0 || ^6 || ^7" } }, "sha512-RHYhrR3hku0MJFRV+fN2gNbDNEh3dwKvY8XJvTxCSXeMOsCRSr+uKvDWQcbizrHgjML6ZmTE5OwMrl5wKcujCw=="],
+
+ "@tokenizer/inflate": ["@tokenizer/inflate@0.2.7", "", { "dependencies": { "debug": "^4.4.0", "fflate": "^0.8.2", "token-types": "^6.0.0" } }, "sha512-MADQgmZT1eKjp06jpI2yozxaU9uVs4GzzgSL+uEq7bVcJ9V1ZXQkeGNql1fsSI0gMy1vhvNTNbUqrx+pZfJVmg=="],
+
+ "@tokenizer/token": ["@tokenizer/token@0.3.0", "", {}, "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A=="],
+
+ "@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="],
+
+ "@types/node": ["@types/node@24.2.0", "", { "dependencies": { "undici-types": "~7.10.0" } }, "sha512-3xyG3pMCq3oYCNg7/ZP+E1ooTaGB4cG8JWRsqqOYQdbWNY4zbaV0Ennrd7stjiJEFZCaybcIgpTjJWHRfBSIDw=="],
+
+ "@types/react": ["@types/react@19.1.9", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-WmdoynAX8Stew/36uTSVMcLJJ1KRh6L3IZRx1PZ7qJtBqT3dYTgyDTx8H1qoRghErydW7xw9mSJ3wS//tCRpFA=="],
+
+ "acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="],
+
+ "ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
+
+ "ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
+
+ "bun-types": ["bun-types@1.2.19", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-uAOTaZSPuYsWIXRpj7o56Let0g/wjihKCkeRqUBhlLVM/Bt+Fj9xTo+LhC1OV1XDaGkz4hNC80et5xgy+9KTHQ=="],
+
+ "chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
+
+ "chownr": ["chownr@3.0.0", "", {}, "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g=="],
+
+ "cliui": ["cliui@8.0.1", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" } }, "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ=="],
+
+ "clone": ["clone@2.1.2", "", {}, "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w=="],
+
+ "color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="],
+
+ "color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="],
+
+ "concurrently": ["concurrently@9.2.0", "", { "dependencies": { "chalk": "^4.1.2", "lodash": "^4.17.21", "rxjs": "^7.8.1", "shell-quote": "^1.8.1", "supports-color": "^8.1.1", "tree-kill": "^1.2.2", "yargs": "^17.7.2" }, "bin": { "concurrently": "dist/bin/concurrently.js", "conc": "dist/bin/concurrently.js" } }, "sha512-IsB/fiXTupmagMW4MNp2lx2cdSN2FfZq78vF90LBB+zZHArbIQZjQtzXCiXnvTxCZSvXanTqFLWBjw2UkLx1SQ=="],
+
+ "confbox": ["confbox@0.2.2", "", {}, "sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ=="],
+
+ "cookie": ["cookie@1.0.2", "", {}, "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA=="],
+
+ "csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="],
+
+ "debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="],
+
+ "detect-libc": ["detect-libc@2.0.4", "", {}, "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA=="],
+
+ "elysia": ["elysia@1.3.8", "", { "dependencies": { "cookie": "^1.0.2", "exact-mirror": "0.1.3", "fast-decode-uri-component": "^1.0.1" }, "optionalDependencies": { "@sinclair/typebox": "^0.34.33", "openapi-types": "^12.1.3" }, "peerDependencies": { "file-type": ">= 20.0.0", "typescript": ">= 5.0.0" } }, "sha512-kxYFhegJbUEf5otzmisEvGt3R7d/dPBNVERO2nHo0kFqKBHyj5slArc90mSRKLfi1vamMtPcz67rL6Zeg5F2yg=="],
+
+ "emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
+
+ "enhanced-resolve": ["enhanced-resolve@5.18.3", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" } }, "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww=="],
+
+ "esbuild": ["esbuild@0.25.8", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.8", "@esbuild/android-arm": "0.25.8", "@esbuild/android-arm64": "0.25.8", "@esbuild/android-x64": "0.25.8", "@esbuild/darwin-arm64": "0.25.8", "@esbuild/darwin-x64": "0.25.8", "@esbuild/freebsd-arm64": "0.25.8", "@esbuild/freebsd-x64": "0.25.8", "@esbuild/linux-arm": "0.25.8", "@esbuild/linux-arm64": "0.25.8", "@esbuild/linux-ia32": "0.25.8", "@esbuild/linux-loong64": "0.25.8", "@esbuild/linux-mips64el": "0.25.8", "@esbuild/linux-ppc64": "0.25.8", "@esbuild/linux-riscv64": "0.25.8", "@esbuild/linux-s390x": "0.25.8", "@esbuild/linux-x64": "0.25.8", "@esbuild/netbsd-arm64": "0.25.8", "@esbuild/netbsd-x64": "0.25.8", "@esbuild/openbsd-arm64": "0.25.8", "@esbuild/openbsd-x64": "0.25.8", "@esbuild/openharmony-arm64": "0.25.8", "@esbuild/sunos-x64": "0.25.8", "@esbuild/win32-arm64": "0.25.8", "@esbuild/win32-ia32": "0.25.8", "@esbuild/win32-x64": "0.25.8" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-vVC0USHGtMi8+R4Kz8rt6JhEWLxsv9Rnu/lGYbPR8u47B+DCBksq9JarW0zOO7bs37hyOK1l2/oqtbciutL5+Q=="],
+
+ "escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="],
+
+ "exact-mirror": ["exact-mirror@0.1.3", "", { "peerDependencies": { "@sinclair/typebox": "^0.34.15" }, "optionalPeers": ["@sinclair/typebox"] }, "sha512-yI62LpSby0ItzPJF05C4DRycVAoknRiCIDOLOCCs9zaEKylOXQtOFM3flX54S44swpRz584vk3P70yWQodsLlg=="],
+
+ "exsolve": ["exsolve@1.0.7", "", {}, "sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw=="],
+
+ "fast-decode-uri-component": ["fast-decode-uri-component@1.0.1", "", {}, "sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg=="],
+
+ "fdir": ["fdir@6.4.6", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w=="],
+
+ "fflate": ["fflate@0.8.2", "", {}, "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A=="],
+
+ "file-type": ["file-type@21.0.0", "", { "dependencies": { "@tokenizer/inflate": "^0.2.7", "strtok3": "^10.2.2", "token-types": "^6.0.0", "uint8array-extras": "^1.4.0" } }, "sha512-ek5xNX2YBYlXhiUXui3D/BXa3LdqPmoLJ7rqEx2bKJ7EAUEfmXgW0Das7Dc6Nr9MvqaOnIqiPV0mZk/r/UpNAg=="],
+
+ "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
+
+ "get-caller-file": ["get-caller-file@2.0.5", "", {}, "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="],
+
+ "globals": ["globals@15.15.0", "", {}, "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg=="],
+
+ "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="],
+
+ "has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="],
+
+ "ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="],
+
+ "is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="],
+
+ "jiti": ["jiti@2.5.1", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w=="],
+
+ "kolorist": ["kolorist@1.8.0", "", {}, "sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ=="],
+
+ "lightningcss": ["lightningcss@1.30.1", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-darwin-arm64": "1.30.1", "lightningcss-darwin-x64": "1.30.1", "lightningcss-freebsd-x64": "1.30.1", "lightningcss-linux-arm-gnueabihf": "1.30.1", "lightningcss-linux-arm64-gnu": "1.30.1", "lightningcss-linux-arm64-musl": "1.30.1", "lightningcss-linux-x64-gnu": "1.30.1", "lightningcss-linux-x64-musl": "1.30.1", "lightningcss-win32-arm64-msvc": "1.30.1", "lightningcss-win32-x64-msvc": "1.30.1" } }, "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg=="],
+
+ "lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.30.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ=="],
+
+ "lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.30.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA=="],
+
+ "lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.30.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig=="],
+
+ "lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.30.1", "", { "os": "linux", "cpu": "arm" }, "sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q=="],
+
+ "lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.30.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw=="],
+
+ "lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.30.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ=="],
+
+ "lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.30.1", "", { "os": "linux", "cpu": "x64" }, "sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw=="],
+
+ "lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.30.1", "", { "os": "linux", "cpu": "x64" }, "sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ=="],
+
+ "lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.30.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA=="],
+
+ "lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.30.1", "", { "os": "win32", "cpu": "x64" }, "sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg=="],
+
+ "local-pkg": ["local-pkg@1.1.1", "", { "dependencies": { "mlly": "^1.7.4", "pkg-types": "^2.0.1", "quansync": "^0.2.8" } }, "sha512-WunYko2W1NcdfAFpuLUoucsgULmgDBRkdxHxWQ7mK0cQqwPiy8E1enjuRBrhLtZkB5iScJ1XIPdhVEFK8aOLSg=="],
+
+ "lodash": ["lodash@4.17.21", "", {}, "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="],
+
+ "magic-string": ["magic-string@0.30.17", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0" } }, "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA=="],
+
+ "minipass": ["minipass@7.1.2", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="],
+
+ "minizlib": ["minizlib@3.0.2", "", { "dependencies": { "minipass": "^7.1.2" } }, "sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA=="],
+
+ "mkdirp": ["mkdirp@3.0.1", "", { "bin": { "mkdirp": "dist/cjs/src/bin.js" } }, "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg=="],
+
+ "mlly": ["mlly@1.7.4", "", { "dependencies": { "acorn": "^8.14.0", "pathe": "^2.0.1", "pkg-types": "^1.3.0", "ufo": "^1.5.4" } }, "sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw=="],
+
+ "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
+
+ "nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
+
+ "node-cache": ["node-cache@5.1.2", "", { "dependencies": { "clone": "2.x" } }, "sha512-t1QzWwnk4sjLWaQAS8CHgOJ+RAfmHpxFWmc36IWTiWHQfs0w5JDMBS1b1ZxQteo0vVVuWJvIUKHDkkeK7vIGCg=="],
+
+ "openapi-types": ["openapi-types@12.1.3", "", {}, "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw=="],
+
+ "package-manager-detector": ["package-manager-detector@1.3.0", "", {}, "sha512-ZsEbbZORsyHuO00lY1kV3/t72yp6Ysay6Pd17ZAlNGuGwmWDLCJxFpRs0IzfXfj1o4icJOkUEioexFHzyPurSQ=="],
+
+ "pathe": ["pathe@1.1.2", "", {}, "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ=="],
+
+ "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
+
+ "picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="],
+
+ "pkg-types": ["pkg-types@2.2.0", "", { "dependencies": { "confbox": "^0.2.2", "exsolve": "^1.0.7", "pathe": "^2.0.3" } }, "sha512-2SM/GZGAEkPp3KWORxQZns4M+WSeXbC2HEvmOIJe3Cmiv6ieAJvdVhDldtHqM5J1Y7MrR1XhkBT/rMlhh9FdqQ=="],
+
+ "postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="],
+
+ "quansync": ["quansync@0.2.10", "", {}, "sha512-t41VRkMYbkHyCYmOvx/6URnN80H7k4X0lLdBMGsz+maAwrJQYB1djpV6vHrQIBE0WBSGqhtEHrK9U3DWWH8v7A=="],
+
+ "require-directory": ["require-directory@2.1.1", "", {}, "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="],
+
+ "rollup": ["rollup@4.46.2", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.46.2", "@rollup/rollup-android-arm64": "4.46.2", "@rollup/rollup-darwin-arm64": "4.46.2", "@rollup/rollup-darwin-x64": "4.46.2", "@rollup/rollup-freebsd-arm64": "4.46.2", "@rollup/rollup-freebsd-x64": "4.46.2", "@rollup/rollup-linux-arm-gnueabihf": "4.46.2", "@rollup/rollup-linux-arm-musleabihf": "4.46.2", "@rollup/rollup-linux-arm64-gnu": "4.46.2", "@rollup/rollup-linux-arm64-musl": "4.46.2", "@rollup/rollup-linux-loongarch64-gnu": "4.46.2", "@rollup/rollup-linux-ppc64-gnu": "4.46.2", "@rollup/rollup-linux-riscv64-gnu": "4.46.2", "@rollup/rollup-linux-riscv64-musl": "4.46.2", "@rollup/rollup-linux-s390x-gnu": "4.46.2", "@rollup/rollup-linux-x64-gnu": "4.46.2", "@rollup/rollup-linux-x64-musl": "4.46.2", "@rollup/rollup-win32-arm64-msvc": "4.46.2", "@rollup/rollup-win32-ia32-msvc": "4.46.2", "@rollup/rollup-win32-x64-msvc": "4.46.2", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-WMmLFI+Boh6xbop+OAGo9cQ3OgX9MIg7xOQjn+pTCwOkk+FNDAeAemXkJ3HzDJrVXleLOFVa1ipuc1AmEx1Dwg=="],
+
+ "rxjs": ["rxjs@7.8.2", "", { "dependencies": { "tslib": "^2.1.0" } }, "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA=="],
+
+ "shell-quote": ["shell-quote@1.8.3", "", {}, "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw=="],
+
+ "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
+
+ "string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
+
+ "strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
+
+ "strtok3": ["strtok3@10.3.4", "", { "dependencies": { "@tokenizer/token": "^0.3.0" } }, "sha512-KIy5nylvC5le1OdaaoCJ07L+8iQzJHGH6pWDuzS+d07Cu7n1MZ2x26P8ZKIWfbK02+XIL8Mp4RkWeqdUCrDMfg=="],
+
+ "supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="],
+
+ "tailwindcss": ["tailwindcss@4.1.11", "", {}, "sha512-2E9TBm6MDD/xKYe+dvJZAmg3yxIEDNRc0jwlNyDg/4Fil2QcSLjFKGVff0lAf1jjeaArlG/M75Ey/EYr/OJtBA=="],
+
+ "tapable": ["tapable@2.2.2", "", {}, "sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg=="],
+
+ "tar": ["tar@7.4.3", "", { "dependencies": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", "minipass": "^7.1.2", "minizlib": "^3.0.1", "mkdirp": "^3.0.1", "yallist": "^5.0.0" } }, "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw=="],
+
+ "tinyexec": ["tinyexec@1.0.1", "", {}, "sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw=="],
+
+ "tinyglobby": ["tinyglobby@0.2.14", "", { "dependencies": { "fdir": "^6.4.4", "picomatch": "^4.0.2" } }, "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ=="],
+
+ "token-types": ["token-types@6.0.4", "", { "dependencies": { "@tokenizer/token": "^0.3.0", "ieee754": "^1.2.1" } }, "sha512-MD9MjpVNhVyH4fyd5rKphjvt/1qj+PtQUz65aFqAZA6XniWAuSFRjLk3e2VALEFlh9OwBpXUN7rfeqSnT/Fmkw=="],
+
+ "tree-kill": ["tree-kill@1.2.2", "", { "bin": { "tree-kill": "cli.js" } }, "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A=="],
+
+ "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
+
+ "typescript": ["typescript@5.9.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A=="],
+
+ "ufo": ["ufo@1.6.1", "", {}, "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA=="],
+
+ "uint8array-extras": ["uint8array-extras@1.4.0", "", {}, "sha512-ZPtzy0hu4cZjv3z5NW9gfKnNLjoz4y6uv4HlelAjDK7sY/xOkKZv9xK/WQpcsBB3jEybChz9DPC2U/+cusjJVQ=="],
+
+ "undici-types": ["undici-types@7.10.0", "", {}, "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag=="],
+
+ "unplugin": ["unplugin@2.3.5", "", { "dependencies": { "acorn": "^8.14.1", "picomatch": "^4.0.2", "webpack-virtual-modules": "^0.6.2" } }, "sha512-RyWSb5AHmGtjjNQ6gIlA67sHOsWpsbWpwDokLwTcejVdOjEkJZh7QKu14J00gDDVSh8kGH4KYC/TNBceXFZhtw=="],
+
+ "unplugin-icons": ["unplugin-icons@22.2.0", "", { "dependencies": { "@antfu/install-pkg": "^1.1.0", "@iconify/utils": "^2.3.0", "debug": "^4.4.1", "local-pkg": "^1.1.1", "unplugin": "^2.3.5" }, "peerDependencies": { "@svgr/core": ">=7.0.0", "@svgx/core": "^1.0.1", "@vue/compiler-sfc": "^3.0.2 || ^2.7.0", "svelte": "^3.0.0 || ^4.0.0 || ^5.0.0", "vue-template-compiler": "^2.6.12", "vue-template-es2015-compiler": "^1.9.0" }, "optionalPeers": ["@svgr/core", "@svgx/core", "@vue/compiler-sfc", "svelte", "vue-template-compiler", "vue-template-es2015-compiler"] }, "sha512-OdrXCiXexC1rFd0QpliAgcd4cMEEEQtoCf2WIrRIGu4iW6auBPpQKMCBeWxoe55phYdRyZLUWNOtzyTX+HOFSA=="],
+
+ "vite": ["vite@7.1.1", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.6", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.14" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-yJ+Mp7OyV+4S+afWo+QyoL9jFWD11QFH0i5i7JypnfTcA1rmgxCbiA8WwAICDEtZ1Z1hzrVhN8R8rGTqkTY8ZQ=="],
+
+ "webpack-virtual-modules": ["webpack-virtual-modules@0.6.2", "", {}, "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ=="],
+
+ "wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="],
+
+ "y18n": ["y18n@5.0.8", "", {}, "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="],
+
+ "yallist": ["yallist@5.0.0", "", {}, "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw=="],
+
+ "yargs": ["yargs@17.7.2", "", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="],
+
+ "yargs-parser": ["yargs-parser@21.1.1", "", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="],
+
+ "@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.4.5", "", { "dependencies": { "@emnapi/wasi-threads": "1.0.4", "tslib": "^2.4.0" }, "bundled": true }, "sha512-XsLw1dEOpkSX/WucdqUhPWP7hDxSvZiY+fsUC14h+FtQ2Ifni4znbBt8punRX+Uj2JG/uDb8nEHVKvrVlvdZ5Q=="],
+
+ "@tailwindcss/oxide-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.4.5", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-++LApOtY0pEEz1zrd9vy1/zXVaVJJ/EbAF3u0fXIzPJEDtnITsBGbbK0EkM72amhl/R5b+5xx0Y/QhcVOpuulg=="],
+
+ "@tailwindcss/oxide-wasm32-wasi/@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.0.4", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-PJR+bOmMOPH8AtcTGAyYNiuJ3/Fcoj2XN/gBEWzDIKh254XO+mM9XoXHk5GNEhodxeMznbg7BlRojVbKN+gC6g=="],
+
+ "@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@0.2.12", "", { "dependencies": { "@emnapi/core": "^1.4.3", "@emnapi/runtime": "^1.4.3", "@tybys/wasm-util": "^0.10.0" }, "bundled": true }, "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ=="],
+
+ "@tailwindcss/oxide-wasm32-wasi/@tybys/wasm-util": ["@tybys/wasm-util@0.9.0", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw=="],
+
+ "@tailwindcss/oxide-wasm32-wasi/tslib": ["tslib@2.8.1", "", { "bundled": true }, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
+
+ "chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="],
+
+ "mlly/pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="],
+
+ "mlly/pkg-types": ["pkg-types@1.3.1", "", { "dependencies": { "confbox": "^0.1.8", "mlly": "^1.7.4", "pathe": "^2.0.1" } }, "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ=="],
+
+ "pkg-types/pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="],
+
+ "@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime/@tybys/wasm-util": ["@tybys/wasm-util@0.10.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-VyyPYFlOMNylG45GoAe0xDoLwWuowvf92F9kySqzYh8vmYm7D2u4iUJKa1tOUpS70Ku13ASrOkS4ScXFsTaCNQ=="],
+
+ "mlly/pkg-types/confbox": ["confbox@0.1.8", "", {}, "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w=="],
+ }
+}
diff --git a/entrypoint.sh b/entrypoint.sh
deleted file mode 100644
index e25a903..0000000
--- a/entrypoint.sh
+++ /dev/null
@@ -1,54 +0,0 @@
-#!/bin/sh
-# vim:sw=4:ts=4:et
-
-set -e
-
-entrypoint_log() {
- if [ -z "${NGINX_ENTRYPOINT_QUIET_LOGS:-}" ]; then
- echo "$@"
- fi
-}
-
-if [ "$1" = "nginx" ] || [ "$1" = "nginx-debug" ]; then
- if /usr/bin/find "/docker-entrypoint.d/" -mindepth 1 -maxdepth 1 -type f -print -quit 2>/dev/null | read v; then
- entrypoint_log "$0: /docker-entrypoint.d/ is not empty, will attempt to perform configuration"
-
- entrypoint_log "$0: Looking for shell scripts in /docker-entrypoint.d/"
- find "/docker-entrypoint.d/" -follow -type f -print | sort -V | while read -r f; do
- case "$f" in
- *.envsh)
- if [ -x "$f" ]; then
- entrypoint_log "$0: Sourcing $f";
- . "$f"
- else
- # warn on shell scripts without exec bit
- entrypoint_log "$0: Ignoring $f, not executable";
- fi
- ;;
- *.sh)
- if [ -x "$f" ]; then
- entrypoint_log "$0: Launching $f";
- "$f"
- else
- # warn on shell scripts without exec bit
- entrypoint_log "$0: Ignoring $f, not executable";
- fi
- ;;
- *) entrypoint_log "$0: Ignoring $f";;
- esac
- done
-
- entrypoint_log "$0: Configuration complete; ready for start up"
- else
- entrypoint_log "$0: No files found in /docker-entrypoint.d/, skipping configuration"
- fi
-fi
-
-# Check if the folder /extra exists, if so, copy all files from /extra to /usr/share/nginx/html
-if [ -d "/extra" ]; then
- echo "Copying files from /extra to /usr/share/nginx/html"
- cp -r /extra/* /usr/share/nginx/html/
-fi
-
-echo "Executing command: $@"
-exec "$@"
\ No newline at end of file
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..b4234e0
--- /dev/null
+++ b/index.html
@@ -0,0 +1,191 @@
+
+
+
+
+
+
+ Cameron B. R. Redmore - Software Developer
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Loading music data...
+
+
+
+
+
+
+
+
+
Cameron B. R. Redmore
+
+
Software Developer from Kingston-Upon-Hull, UK
+
+
+ With 8 years of professional experience and over 15 years of passion-driven coding, I build
+ robust and efficient software solutions. My journey has taken me from recreational projects
+ to
+ developing complex professional applications.
+
+
+
+
+
Interests & Hobbies
+
+ Beyond my core work, I have a deep interest in the broader field of computing and
+ programming. I'm particularly passionate about the AI and Machine Learning space,
+ focusing
+ on integrating Large Language Models (LLMs) in novel ways. In my spare time, I also
+ enjoy
+ the logical challenge of puzzles like Sudoku and Nonograms.
+
+
+
+
+
Programming Skills
+
+ HTML
+ CSS
+ JavaScript
+ TypeScript
+ C#
+ C++
+ C
+ Java
+
+
+
+
+
+
+
+
+
Music
+
+
+
+ Loading music data...
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Save Pattern
+
+
+ Load Pattern
+
+
+
+
+
+ Simulation Speed:
+
+ 10 Hz
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/package.json b/package.json
index 230fca8..1b4bf8e 100644
--- a/package.json
+++ b/package.json
@@ -1,10 +1,35 @@
{
- "name": "public",
- "dependencies": {
- "tailwindcss": "^3.4.17"
- },
+ "name": "homepage",
+ "private": true,
+ "version": "0.0.0",
+ "type": "module",
"scripts": {
- "build": "tailwind -c tailwind.config.js -i www/css/input.css -o www/css/style.css --minify",
- "watch": "tailwind -c tailwind.config.js -i www/css/input.css -o www/css/style.css --minify --watch"
- }
+ "start": "bun src/server.ts",
+ "dev": "concurrently \"bun run --hot src/server.ts\" \"vite\"",
+ "build": "vite build && bun build src/server.ts --compile --outfile dist/server",
+ "build:frontend": "vite build",
+ "build:server": "bun build src/server.ts --compile --outfile dist/server",
+ "test:executable": "npm run build && NODE_ENV=production ./dist/server.exe",
+ "preview": "vite preview",
+ "prod": "NODE_ENV=production bun src/server.ts"
+ },
+ "devDependencies": {
+ "@iconify/json": "^2.2.367",
+ "bun-types": "latest",
+ "concurrently": "^9.2.0",
+ "unplugin-icons": "^22.2.0",
+ "vite": "^7.1.0"
+ },
+ "dependencies": {
+ "@elysiajs/eden": "^1.3.2",
+ "@elysiajs/static": "^1.3.0",
+ "@fontsource-variable/exo-2": "^5.2.6",
+ "@fontsource-variable/inter": "^5.2.6",
+ "@tailwindcss/vite": "^4.1.11",
+ "elysia": "^1.3.8",
+ "tailwindcss": "^4.1.11"
+ },
+ "trustedDependencies": [
+ "@tailwindcss/oxide"
+ ]
}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
deleted file mode 100644
index 2b20b9b..0000000
--- a/pnpm-lock.yaml
+++ /dev/null
@@ -1,837 +0,0 @@
-lockfileVersion: '9.0'
-
-settings:
- autoInstallPeers: true
- excludeLinksFromLockfile: false
-
-importers:
-
- .:
- dependencies:
- tailwindcss:
- specifier: ^3.4.17
- version: 3.4.17
-
-packages:
-
- '@alloc/quick-lru@5.2.0':
- resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==}
- engines: {node: '>=10'}
-
- '@isaacs/cliui@8.0.2':
- resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==}
- engines: {node: '>=12'}
-
- '@jridgewell/gen-mapping@0.3.8':
- resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==}
- engines: {node: '>=6.0.0'}
-
- '@jridgewell/resolve-uri@3.1.2':
- resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
- engines: {node: '>=6.0.0'}
-
- '@jridgewell/set-array@1.2.1':
- resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==}
- engines: {node: '>=6.0.0'}
-
- '@jridgewell/sourcemap-codec@1.5.0':
- resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==}
-
- '@jridgewell/trace-mapping@0.3.25':
- resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==}
-
- '@nodelib/fs.scandir@2.1.5':
- resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
- engines: {node: '>= 8'}
-
- '@nodelib/fs.stat@2.0.5':
- resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==}
- engines: {node: '>= 8'}
-
- '@nodelib/fs.walk@1.2.8':
- resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
- engines: {node: '>= 8'}
-
- '@pkgjs/parseargs@0.11.0':
- resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
- engines: {node: '>=14'}
-
- ansi-regex@5.0.1:
- resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
- engines: {node: '>=8'}
-
- ansi-regex@6.1.0:
- resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==}
- engines: {node: '>=12'}
-
- ansi-styles@4.3.0:
- resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
- engines: {node: '>=8'}
-
- ansi-styles@6.2.1:
- resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==}
- engines: {node: '>=12'}
-
- any-promise@1.3.0:
- resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==}
-
- anymatch@3.1.3:
- resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==}
- engines: {node: '>= 8'}
-
- arg@5.0.2:
- resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==}
-
- balanced-match@1.0.2:
- resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
-
- binary-extensions@2.3.0:
- resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==}
- engines: {node: '>=8'}
-
- brace-expansion@2.0.1:
- resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==}
-
- braces@3.0.3:
- resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==}
- engines: {node: '>=8'}
-
- camelcase-css@2.0.1:
- resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==}
- engines: {node: '>= 6'}
-
- chokidar@3.6.0:
- resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==}
- engines: {node: '>= 8.10.0'}
-
- color-convert@2.0.1:
- resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
- engines: {node: '>=7.0.0'}
-
- color-name@1.1.4:
- resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
-
- commander@4.1.1:
- resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==}
- engines: {node: '>= 6'}
-
- cross-spawn@7.0.6:
- resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
- engines: {node: '>= 8'}
-
- cssesc@3.0.0:
- resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==}
- engines: {node: '>=4'}
- hasBin: true
-
- didyoumean@1.2.2:
- resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==}
-
- dlv@1.1.3:
- resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==}
-
- eastasianwidth@0.2.0:
- resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
-
- emoji-regex@8.0.0:
- resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
-
- emoji-regex@9.2.2:
- resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
-
- fast-glob@3.3.3:
- resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==}
- engines: {node: '>=8.6.0'}
-
- fastq@1.19.1:
- resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==}
-
- fill-range@7.1.1:
- resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
- engines: {node: '>=8'}
-
- foreground-child@3.3.1:
- resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==}
- engines: {node: '>=14'}
-
- fsevents@2.3.3:
- resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
- engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
- os: [darwin]
-
- function-bind@1.1.2:
- resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
-
- glob-parent@5.1.2:
- resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
- engines: {node: '>= 6'}
-
- glob-parent@6.0.2:
- resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==}
- engines: {node: '>=10.13.0'}
-
- glob@10.4.5:
- resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==}
- hasBin: true
-
- hasown@2.0.2:
- resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
- engines: {node: '>= 0.4'}
-
- is-binary-path@2.1.0:
- resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
- engines: {node: '>=8'}
-
- is-core-module@2.16.1:
- resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==}
- engines: {node: '>= 0.4'}
-
- is-extglob@2.1.1:
- resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
- engines: {node: '>=0.10.0'}
-
- is-fullwidth-code-point@3.0.0:
- resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
- engines: {node: '>=8'}
-
- is-glob@4.0.3:
- resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
- engines: {node: '>=0.10.0'}
-
- is-number@7.0.0:
- resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
- engines: {node: '>=0.12.0'}
-
- isexe@2.0.0:
- resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
-
- jackspeak@3.4.3:
- resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==}
-
- jiti@1.21.7:
- resolution: {integrity: sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==}
- hasBin: true
-
- lilconfig@3.1.3:
- resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==}
- engines: {node: '>=14'}
-
- lines-and-columns@1.2.4:
- resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
-
- lru-cache@10.4.3:
- resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==}
-
- merge2@1.4.1:
- resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
- engines: {node: '>= 8'}
-
- micromatch@4.0.8:
- resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==}
- engines: {node: '>=8.6'}
-
- minimatch@9.0.5:
- resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==}
- engines: {node: '>=16 || 14 >=14.17'}
-
- minipass@7.1.2:
- resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==}
- engines: {node: '>=16 || 14 >=14.17'}
-
- mz@2.7.0:
- resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==}
-
- nanoid@3.3.11:
- resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==}
- engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
- hasBin: true
-
- normalize-path@3.0.0:
- resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
- engines: {node: '>=0.10.0'}
-
- object-assign@4.1.1:
- resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
- engines: {node: '>=0.10.0'}
-
- object-hash@3.0.0:
- resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==}
- engines: {node: '>= 6'}
-
- package-json-from-dist@1.0.1:
- resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==}
-
- path-key@3.1.1:
- resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
- engines: {node: '>=8'}
-
- path-parse@1.0.7:
- resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
-
- path-scurry@1.11.1:
- resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==}
- engines: {node: '>=16 || 14 >=14.18'}
-
- picocolors@1.1.1:
- resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
-
- picomatch@2.3.1:
- resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
- engines: {node: '>=8.6'}
-
- pify@2.3.0:
- resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==}
- engines: {node: '>=0.10.0'}
-
- pirates@4.0.7:
- resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==}
- engines: {node: '>= 6'}
-
- postcss-import@15.1.0:
- resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==}
- engines: {node: '>=14.0.0'}
- peerDependencies:
- postcss: ^8.0.0
-
- postcss-js@4.0.1:
- resolution: {integrity: sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==}
- engines: {node: ^12 || ^14 || >= 16}
- peerDependencies:
- postcss: ^8.4.21
-
- postcss-load-config@4.0.2:
- resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==}
- engines: {node: '>= 14'}
- peerDependencies:
- postcss: '>=8.0.9'
- ts-node: '>=9.0.0'
- peerDependenciesMeta:
- postcss:
- optional: true
- ts-node:
- optional: true
-
- postcss-nested@6.2.0:
- resolution: {integrity: sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==}
- engines: {node: '>=12.0'}
- peerDependencies:
- postcss: ^8.2.14
-
- postcss-selector-parser@6.1.2:
- resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==}
- engines: {node: '>=4'}
-
- postcss-value-parser@4.2.0:
- resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==}
-
- postcss@8.5.3:
- resolution: {integrity: sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==}
- engines: {node: ^10 || ^12 || >=14}
-
- queue-microtask@1.2.3:
- resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
-
- read-cache@1.0.0:
- resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==}
-
- readdirp@3.6.0:
- resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
- engines: {node: '>=8.10.0'}
-
- resolve@1.22.10:
- resolution: {integrity: sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==}
- engines: {node: '>= 0.4'}
- hasBin: true
-
- reusify@1.1.0:
- resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==}
- engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
-
- run-parallel@1.2.0:
- resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
-
- shebang-command@2.0.0:
- resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
- engines: {node: '>=8'}
-
- shebang-regex@3.0.0:
- resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
- engines: {node: '>=8'}
-
- signal-exit@4.1.0:
- resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
- engines: {node: '>=14'}
-
- source-map-js@1.2.1:
- resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
- engines: {node: '>=0.10.0'}
-
- string-width@4.2.3:
- resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
- engines: {node: '>=8'}
-
- string-width@5.1.2:
- resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==}
- engines: {node: '>=12'}
-
- strip-ansi@6.0.1:
- resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
- engines: {node: '>=8'}
-
- strip-ansi@7.1.0:
- resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==}
- engines: {node: '>=12'}
-
- sucrase@3.35.0:
- resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==}
- engines: {node: '>=16 || 14 >=14.17'}
- hasBin: true
-
- supports-preserve-symlinks-flag@1.0.0:
- resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
- engines: {node: '>= 0.4'}
-
- tailwindcss@3.4.17:
- resolution: {integrity: sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==}
- engines: {node: '>=14.0.0'}
- hasBin: true
-
- thenify-all@1.6.0:
- resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==}
- engines: {node: '>=0.8'}
-
- thenify@3.3.1:
- resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==}
-
- to-regex-range@5.0.1:
- resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
- engines: {node: '>=8.0'}
-
- ts-interface-checker@0.1.13:
- resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==}
-
- util-deprecate@1.0.2:
- resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
-
- which@2.0.2:
- resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
- engines: {node: '>= 8'}
- hasBin: true
-
- wrap-ansi@7.0.0:
- resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
- engines: {node: '>=10'}
-
- wrap-ansi@8.1.0:
- resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==}
- engines: {node: '>=12'}
-
- yaml@2.7.1:
- resolution: {integrity: sha512-10ULxpnOCQXxJvBgxsn9ptjq6uviG/htZKk9veJGhlqn3w/DxQ631zFF+nlQXLwmImeS5amR2dl2U8sg6U9jsQ==}
- engines: {node: '>= 14'}
- hasBin: true
-
-snapshots:
-
- '@alloc/quick-lru@5.2.0': {}
-
- '@isaacs/cliui@8.0.2':
- dependencies:
- string-width: 5.1.2
- string-width-cjs: string-width@4.2.3
- strip-ansi: 7.1.0
- strip-ansi-cjs: strip-ansi@6.0.1
- wrap-ansi: 8.1.0
- wrap-ansi-cjs: wrap-ansi@7.0.0
-
- '@jridgewell/gen-mapping@0.3.8':
- dependencies:
- '@jridgewell/set-array': 1.2.1
- '@jridgewell/sourcemap-codec': 1.5.0
- '@jridgewell/trace-mapping': 0.3.25
-
- '@jridgewell/resolve-uri@3.1.2': {}
-
- '@jridgewell/set-array@1.2.1': {}
-
- '@jridgewell/sourcemap-codec@1.5.0': {}
-
- '@jridgewell/trace-mapping@0.3.25':
- dependencies:
- '@jridgewell/resolve-uri': 3.1.2
- '@jridgewell/sourcemap-codec': 1.5.0
-
- '@nodelib/fs.scandir@2.1.5':
- dependencies:
- '@nodelib/fs.stat': 2.0.5
- run-parallel: 1.2.0
-
- '@nodelib/fs.stat@2.0.5': {}
-
- '@nodelib/fs.walk@1.2.8':
- dependencies:
- '@nodelib/fs.scandir': 2.1.5
- fastq: 1.19.1
-
- '@pkgjs/parseargs@0.11.0':
- optional: true
-
- ansi-regex@5.0.1: {}
-
- ansi-regex@6.1.0: {}
-
- ansi-styles@4.3.0:
- dependencies:
- color-convert: 2.0.1
-
- ansi-styles@6.2.1: {}
-
- any-promise@1.3.0: {}
-
- anymatch@3.1.3:
- dependencies:
- normalize-path: 3.0.0
- picomatch: 2.3.1
-
- arg@5.0.2: {}
-
- balanced-match@1.0.2: {}
-
- binary-extensions@2.3.0: {}
-
- brace-expansion@2.0.1:
- dependencies:
- balanced-match: 1.0.2
-
- braces@3.0.3:
- dependencies:
- fill-range: 7.1.1
-
- camelcase-css@2.0.1: {}
-
- chokidar@3.6.0:
- dependencies:
- anymatch: 3.1.3
- braces: 3.0.3
- glob-parent: 5.1.2
- is-binary-path: 2.1.0
- is-glob: 4.0.3
- normalize-path: 3.0.0
- readdirp: 3.6.0
- optionalDependencies:
- fsevents: 2.3.3
-
- color-convert@2.0.1:
- dependencies:
- color-name: 1.1.4
-
- color-name@1.1.4: {}
-
- commander@4.1.1: {}
-
- cross-spawn@7.0.6:
- dependencies:
- path-key: 3.1.1
- shebang-command: 2.0.0
- which: 2.0.2
-
- cssesc@3.0.0: {}
-
- didyoumean@1.2.2: {}
-
- dlv@1.1.3: {}
-
- eastasianwidth@0.2.0: {}
-
- emoji-regex@8.0.0: {}
-
- emoji-regex@9.2.2: {}
-
- fast-glob@3.3.3:
- dependencies:
- '@nodelib/fs.stat': 2.0.5
- '@nodelib/fs.walk': 1.2.8
- glob-parent: 5.1.2
- merge2: 1.4.1
- micromatch: 4.0.8
-
- fastq@1.19.1:
- dependencies:
- reusify: 1.1.0
-
- fill-range@7.1.1:
- dependencies:
- to-regex-range: 5.0.1
-
- foreground-child@3.3.1:
- dependencies:
- cross-spawn: 7.0.6
- signal-exit: 4.1.0
-
- fsevents@2.3.3:
- optional: true
-
- function-bind@1.1.2: {}
-
- glob-parent@5.1.2:
- dependencies:
- is-glob: 4.0.3
-
- glob-parent@6.0.2:
- dependencies:
- is-glob: 4.0.3
-
- glob@10.4.5:
- dependencies:
- foreground-child: 3.3.1
- jackspeak: 3.4.3
- minimatch: 9.0.5
- minipass: 7.1.2
- package-json-from-dist: 1.0.1
- path-scurry: 1.11.1
-
- hasown@2.0.2:
- dependencies:
- function-bind: 1.1.2
-
- is-binary-path@2.1.0:
- dependencies:
- binary-extensions: 2.3.0
-
- is-core-module@2.16.1:
- dependencies:
- hasown: 2.0.2
-
- is-extglob@2.1.1: {}
-
- is-fullwidth-code-point@3.0.0: {}
-
- is-glob@4.0.3:
- dependencies:
- is-extglob: 2.1.1
-
- is-number@7.0.0: {}
-
- isexe@2.0.0: {}
-
- jackspeak@3.4.3:
- dependencies:
- '@isaacs/cliui': 8.0.2
- optionalDependencies:
- '@pkgjs/parseargs': 0.11.0
-
- jiti@1.21.7: {}
-
- lilconfig@3.1.3: {}
-
- lines-and-columns@1.2.4: {}
-
- lru-cache@10.4.3: {}
-
- merge2@1.4.1: {}
-
- micromatch@4.0.8:
- dependencies:
- braces: 3.0.3
- picomatch: 2.3.1
-
- minimatch@9.0.5:
- dependencies:
- brace-expansion: 2.0.1
-
- minipass@7.1.2: {}
-
- mz@2.7.0:
- dependencies:
- any-promise: 1.3.0
- object-assign: 4.1.1
- thenify-all: 1.6.0
-
- nanoid@3.3.11: {}
-
- normalize-path@3.0.0: {}
-
- object-assign@4.1.1: {}
-
- object-hash@3.0.0: {}
-
- package-json-from-dist@1.0.1: {}
-
- path-key@3.1.1: {}
-
- path-parse@1.0.7: {}
-
- path-scurry@1.11.1:
- dependencies:
- lru-cache: 10.4.3
- minipass: 7.1.2
-
- picocolors@1.1.1: {}
-
- picomatch@2.3.1: {}
-
- pify@2.3.0: {}
-
- pirates@4.0.7: {}
-
- postcss-import@15.1.0(postcss@8.5.3):
- dependencies:
- postcss: 8.5.3
- postcss-value-parser: 4.2.0
- read-cache: 1.0.0
- resolve: 1.22.10
-
- postcss-js@4.0.1(postcss@8.5.3):
- dependencies:
- camelcase-css: 2.0.1
- postcss: 8.5.3
-
- postcss-load-config@4.0.2(postcss@8.5.3):
- dependencies:
- lilconfig: 3.1.3
- yaml: 2.7.1
- optionalDependencies:
- postcss: 8.5.3
-
- postcss-nested@6.2.0(postcss@8.5.3):
- dependencies:
- postcss: 8.5.3
- postcss-selector-parser: 6.1.2
-
- postcss-selector-parser@6.1.2:
- dependencies:
- cssesc: 3.0.0
- util-deprecate: 1.0.2
-
- postcss-value-parser@4.2.0: {}
-
- postcss@8.5.3:
- dependencies:
- nanoid: 3.3.11
- picocolors: 1.1.1
- source-map-js: 1.2.1
-
- queue-microtask@1.2.3: {}
-
- read-cache@1.0.0:
- dependencies:
- pify: 2.3.0
-
- readdirp@3.6.0:
- dependencies:
- picomatch: 2.3.1
-
- resolve@1.22.10:
- dependencies:
- is-core-module: 2.16.1
- path-parse: 1.0.7
- supports-preserve-symlinks-flag: 1.0.0
-
- reusify@1.1.0: {}
-
- run-parallel@1.2.0:
- dependencies:
- queue-microtask: 1.2.3
-
- shebang-command@2.0.0:
- dependencies:
- shebang-regex: 3.0.0
-
- shebang-regex@3.0.0: {}
-
- signal-exit@4.1.0: {}
-
- source-map-js@1.2.1: {}
-
- string-width@4.2.3:
- dependencies:
- emoji-regex: 8.0.0
- is-fullwidth-code-point: 3.0.0
- strip-ansi: 6.0.1
-
- string-width@5.1.2:
- dependencies:
- eastasianwidth: 0.2.0
- emoji-regex: 9.2.2
- strip-ansi: 7.1.0
-
- strip-ansi@6.0.1:
- dependencies:
- ansi-regex: 5.0.1
-
- strip-ansi@7.1.0:
- dependencies:
- ansi-regex: 6.1.0
-
- sucrase@3.35.0:
- dependencies:
- '@jridgewell/gen-mapping': 0.3.8
- commander: 4.1.1
- glob: 10.4.5
- lines-and-columns: 1.2.4
- mz: 2.7.0
- pirates: 4.0.7
- ts-interface-checker: 0.1.13
-
- supports-preserve-symlinks-flag@1.0.0: {}
-
- tailwindcss@3.4.17:
- dependencies:
- '@alloc/quick-lru': 5.2.0
- arg: 5.0.2
- chokidar: 3.6.0
- didyoumean: 1.2.2
- dlv: 1.1.3
- fast-glob: 3.3.3
- glob-parent: 6.0.2
- is-glob: 4.0.3
- jiti: 1.21.7
- lilconfig: 3.1.3
- micromatch: 4.0.8
- normalize-path: 3.0.0
- object-hash: 3.0.0
- picocolors: 1.1.1
- postcss: 8.5.3
- postcss-import: 15.1.0(postcss@8.5.3)
- postcss-js: 4.0.1(postcss@8.5.3)
- postcss-load-config: 4.0.2(postcss@8.5.3)
- postcss-nested: 6.2.0(postcss@8.5.3)
- postcss-selector-parser: 6.1.2
- resolve: 1.22.10
- sucrase: 3.35.0
- transitivePeerDependencies:
- - ts-node
-
- thenify-all@1.6.0:
- dependencies:
- thenify: 3.3.1
-
- thenify@3.3.1:
- dependencies:
- any-promise: 1.3.0
-
- to-regex-range@5.0.1:
- dependencies:
- is-number: 7.0.0
-
- ts-interface-checker@0.1.13: {}
-
- util-deprecate@1.0.2: {}
-
- which@2.0.2:
- dependencies:
- isexe: 2.0.0
-
- wrap-ansi@7.0.0:
- dependencies:
- ansi-styles: 4.3.0
- string-width: 4.2.3
- strip-ansi: 6.0.1
-
- wrap-ansi@8.1.0:
- dependencies:
- ansi-styles: 6.2.1
- string-width: 5.1.2
- strip-ansi: 7.1.0
-
- yaml@2.7.1: {}
diff --git a/public/apple-touch-icon.png b/public/apple-touch-icon.png
new file mode 100644
index 0000000..746388b
Binary files /dev/null and b/public/apple-touch-icon.png differ
diff --git a/public/avatar.webp b/public/avatar.webp
new file mode 100644
index 0000000..15032e3
Binary files /dev/null and b/public/avatar.webp differ
diff --git a/public/favicon-96x96.png b/public/favicon-96x96.png
new file mode 100644
index 0000000..3f37d9c
Binary files /dev/null and b/public/favicon-96x96.png differ
diff --git a/public/favicon.ico b/public/favicon.ico
new file mode 100644
index 0000000..892eaeb
Binary files /dev/null and b/public/favicon.ico differ
diff --git a/public/favicon.svg b/public/favicon.svg
new file mode 100644
index 0000000..fe1cdbd
--- /dev/null
+++ b/public/favicon.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/public/site.webmanifest b/public/site.webmanifest
new file mode 100644
index 0000000..fcc13c3
--- /dev/null
+++ b/public/site.webmanifest
@@ -0,0 +1,21 @@
+{
+ "name": "cmzi.uk",
+ "short_name": "cmzi.uk",
+ "icons": [
+ {
+ "src": "/web-app-manifest-192x192.png",
+ "sizes": "192x192",
+ "type": "image/png",
+ "purpose": "maskable"
+ },
+ {
+ "src": "/web-app-manifest-512x512.png",
+ "sizes": "512x512",
+ "type": "image/png",
+ "purpose": "maskable"
+ }
+ ],
+ "theme_color": "#1171e9",
+ "background_color": "#1171e9",
+ "display": "standalone"
+}
\ No newline at end of file
diff --git a/public/web-app-manifest-192x192.png b/public/web-app-manifest-192x192.png
new file mode 100644
index 0000000..d99e43d
Binary files /dev/null and b/public/web-app-manifest-192x192.png differ
diff --git a/public/web-app-manifest-512x512.png b/public/web-app-manifest-512x512.png
new file mode 100644
index 0000000..b110a12
Binary files /dev/null and b/public/web-app-manifest-512x512.png differ
diff --git a/src/client.ts b/src/client.ts
new file mode 100644
index 0000000..46813de
--- /dev/null
+++ b/src/client.ts
@@ -0,0 +1,329 @@
+import { treaty } from '@elysiajs/eden';
+import type { App } from './server';
+import './gameoflife';
+
+// Create Eden Treaty client using current page origin
+const client = treaty(window.location.origin);
+
+interface LastSongImage {
+ size: 'small' | 'medium' | 'large' | 'extralarge';
+ '#text': string;
+}
+
+interface LastSong {
+ name: string;
+ artist: string;
+ album: string;
+ url: string;
+ nowPlaying: boolean;
+ image: LastSongImage[];
+ playedAt?: number;
+}
+
+// WebSocket connection
+let musicWebSocket: any = null;
+let connected = false;
+let hasInitialized = false;
+
+// Function to connect to WebSocket for real-time updates
+function connectMusicWebSocket(): void {
+ try {
+ connected = false;
+
+ // Subscribe to the music WebSocket endpoint
+ musicWebSocket = client.music.subscribe();
+
+ musicWebSocket.on('open', () => {
+ console.log('Connected to music WebSocket');
+ connected = true;
+ });
+
+ musicWebSocket.subscribe((evt: any) => {
+ const { data } = evt;
+ if (!data) return;
+ if (data.type === 'song-update') {
+ const history: HistoryEntry[] = Array.isArray(data.history) ? data.history : [];
+ updateLastSongDisplay(data.data, undefined, history);
+ }
+ });
+
+ musicWebSocket.on('close', () => {
+ if (!connected) {
+ return;
+ }
+ console.log('Music WebSocket disconnected, attempting to reconnect...');
+ updateLastSongDisplay(null, 'Connection lost, reconnecting...');
+ // Attempt to reconnect after a delay
+ setTimeout(connectMusicWebSocket, 3000);
+ });
+
+ musicWebSocket.on('error', (error: any) => {
+ if (!connected) {
+ return;
+ }
+ console.error('Music WebSocket error:', error);
+ updateLastSongDisplay(null, 'Connection error occurred');
+ });
+
+ } catch (error) {
+ console.error('Failed to connect to music WebSocket:', error);
+ updateLastSongDisplay(null, 'Failed to connect to music service');
+ // Retry connection after delay
+ setTimeout(connectMusicWebSocket, 5000);
+ }
+}
+
+// Function to select appropriate image size based on screen width
+function getOptimalImageUrl(images: LastSongImage[]): string {
+ if (!images || images.length === 0) return '';
+
+ const screenWidth = window.innerWidth;
+
+ // Select image size based on screen width and device pixel ratio
+ const pixelRatio = window.devicePixelRatio || 1;
+ const effectiveWidth = screenWidth * pixelRatio;
+
+ let targetSize: string;
+
+ if (effectiveWidth <= 400) {
+ targetSize = 'small'; // 34px
+ } else if (effectiveWidth <= 800) {
+ targetSize = 'medium'; // 64px
+ } else if (effectiveWidth <= 1400) {
+ targetSize = 'large'; // 174px
+ } else {
+ targetSize = 'extralarge'; // 300px
+ }
+
+ // Find the target size, fallback to largest available
+ const targetImage = images.find(img => img.size === targetSize);
+ if (targetImage) return targetImage['#text'];
+
+ // Fallback: return the largest available image
+ const fallbackOrder = ['extralarge', 'large', 'medium', 'small'];
+ for (const size of fallbackOrder) {
+ const image = images.find(img => img.size === size);
+ if (image) return image['#text'];
+ }
+
+ return '';
+}
+
+// Function to preload an image and return a promise
+function preloadImage(url: string): Promise {
+ return new Promise((resolve, reject) => {
+ const img = new Image();
+ img.onload = () => resolve(img);
+ img.onerror = reject;
+ img.src = url;
+ });
+}
+
+// Function to update the UI with song information
+async function updateLastSongDisplay(song: LastSong | null, errorMessage?: string, history: HistoryEntry[] = []): Promise {
+ console.log('Updating last song display:', song, errorMessage);
+ const containers = [
+ document.getElementById('last-song-container'),
+ document.getElementById('last-song-container-mobile')
+ ];
+
+ for (const container of containers) {
+ if (!container) continue;
+
+ if (errorMessage || !song) {
+ container.innerHTML = `
+
+
+
${errorMessage || 'Loading music data...'}
+
+ `;
+ continue;
+ }
+
+ const statusText = song.nowPlaying ? 'Now Playing' : 'Last Played';
+ const imageUrl = getOptimalImageUrl(song.image);
+
+ // Create tooltip content for music
+ const tooltipContent = `
+ ${song.name}
+ by ${song.artist}
+ ${song.album ? `from "${song.album}"
` : ''}
+ `;
+
+ let imageElement: string;
+
+ // If there's an image URL, preload it before updating the display
+ if (imageUrl) {
+ try {
+ // Show loading state while preloading
+ const loadingElement = `
+
+ `;
+
+ // Temporarily show loading state
+ container.innerHTML = `
+
+ `;
+
+ // Preload the image
+ await preloadImage(imageUrl);
+
+ // Now set the actual image
+ imageElement = ` `;
+ } catch (error) {
+ console.warn('Failed to preload image:', imageUrl, error);
+ // Fallback to default icon if image fails to load
+ imageElement = `
+
+ `;
+ }
+ } else {
+ // No image URL, use default icon
+ imageElement = `
+
+ `;
+ }
+
+ // Equalizer animation when live
+ const eq = song.nowPlaying ? `
+
+
+
+ ` : '';
+
+ const artistLink = `https://www.last.fm/music/${encodeURIComponent(song.artist)}`;
+ const albumLink = song.album ? `https://www.last.fm/music/${encodeURIComponent(song.artist)}/${encodeURIComponent(song.album)}` : '';
+
+ // Final update with the actual image and history dropdown
+ container.innerHTML = `
+
+ `;
+ const listEl = container.querySelector('#history-list') as HTMLElement | null;
+ if (listEl) {
+ renderHistory(listEl, history);
+ }
+ }
+}
+
+// Initialize when DOM is loaded
+document.addEventListener('DOMContentLoaded', () => {
+ // Card flip logic - attach to orbit buttons
+ const cardContainer = document.querySelector('.card-container');
+ const flipButtons = document.querySelectorAll('icon-mdi-orbit-variant');
+
+ flipButtons.forEach(button => {
+ button.addEventListener('click', (event) => {
+ event.stopPropagation();
+ if (cardContainer) {
+ cardContainer.classList.toggle('is-flipped');
+ }
+ });
+ });
+
+ // Lazy-load: observe the desktop and mobile containers
+ const targets = [
+ document.getElementById('last-song-container'),
+ document.getElementById('last-song-container-mobile')
+ ].filter(Boolean) as HTMLElement[];
+
+ if (!targets.length) {
+ connectMusicWebSocket();
+ return;
+ }
+
+ const observer = new IntersectionObserver((entries) => {
+ for (const entry of entries) {
+ if (entry.isIntersecting && !hasInitialized) {
+ hasInitialized = true;
+ connectMusicWebSocket();
+ observer.disconnect();
+ break;
+ }
+ }
+ }, { rootMargin: '100px' });
+
+ targets.forEach((t) => observer.observe(t));
+});
+
+// Clean up on page unload
+window.addEventListener('beforeunload', () => {
+ if (musicWebSocket) {
+ musicWebSocket.close();
+ }
+});
+
+// Hook to receive history from WS subscribe and render it
+type HistoryEntry = LastSong;
+function renderHistory(listEl: HTMLElement, history: HistoryEntry[]) {
+ const fmt = (ts: number) => new Date(ts * 1000).toLocaleString();
+ listEl.innerHTML = history.slice(0, 5).map((h) => {
+ const playedAt = h.playedAt ? fmt(h.playedAt) : '';
+ const tooltipContent = `
+ ${h.name}
+ by ${h.artist}
+ ${h.album ? `from \"${h.album}\"
` : ''}
+ ${playedAt ? `played ${playedAt}
` : ''}
+ `;
+ return `
+
+
+
+ `;
+ }).join('');
+}
+
+// Export functions for manual control if needed
+export { connectMusicWebSocket };
\ No newline at end of file
diff --git a/src/gameoflife.ts b/src/gameoflife.ts
new file mode 100644
index 0000000..8bec9d5
--- /dev/null
+++ b/src/gameoflife.ts
@@ -0,0 +1,573 @@
+// File to implement Game of Life using stored co-ordinates.
+document.addEventListener('DOMContentLoaded', () => {
+ const canvas = document.getElementById('game-of-life-canvas') as HTMLCanvasElement;
+
+ const gameOfLife = new GameOfLife(canvas);
+
+ gameOfLife.start();
+});
+
+interface Cell {
+ x: number;
+ y: number;
+}
+
+class GameOfLife {
+ private canvas: HTMLCanvasElement;
+ private ctx: CanvasRenderingContext2D;
+
+ // Define sets of cells (much more efficient for large grids than 2D array)
+ private activeCells: Set = new Set(); // Cells that are currently alive
+ private activeCellsNext: Set = new Set(); // Cells that will be alive in the next generation
+
+ private potentialCells: Set = new Set(); // Cells that could potentially become alive in the next generation
+ private potentialCellsNext: Set = new Set(); // Cells that will be alive in the next generation
+
+ // Viewport and interaction state
+ private offsetX: number = 0;
+ private offsetY: number = 0;
+ private zoomLevel: number = 1;
+ private isPaused: boolean = true;
+
+ private isDragging: boolean = false;
+ private lastMouseX: number = 0;
+ private lastMouseY: number = 0;
+
+ private targetFrameRate: number = 144;
+ private targetSimulationRate: number = 10;
+
+ constructor(canvas: HTMLCanvasElement) {
+ this.canvas = canvas;
+ this.ctx = canvas.getContext('2d')!;
+
+ // Set canvas size
+ this.canvas.width = 800;
+ this.canvas.height = 550;
+
+ this.setupEventListeners();
+ this.setupSimulationSpeedSlider();
+ this.setupSaveLoadButtons();
+ this.seedInitialPattern();
+ }
+
+ start() {
+ this.update();
+ this.drawCells();
+ }
+
+ private setupEventListeners() {
+ // Click to add cells
+ this.canvas.addEventListener('click', (e) => {
+ if (!this.isDragging) {
+ this.handleCellClick(e);
+ }
+ });
+
+ // Right click to fill area with random cells
+ this.canvas.addEventListener('contextmenu', (e) => {
+ e.preventDefault(); // Prevent context menu
+ if (!this.isDragging) {
+ this.handleRightClick(e);
+ }
+ });
+
+ // Mouse events for panning
+ this.canvas.addEventListener('mousedown', (e) => {
+ this.isDragging = false;
+ this.lastMouseX = e.clientX;
+ this.lastMouseY = e.clientY;
+ });
+
+ this.canvas.addEventListener('mousemove', (e) => {
+ if (e.buttons === 1) { // Left mouse button pressed
+ const deltaX = e.clientX - this.lastMouseX;
+ const deltaY = e.clientY - this.lastMouseY;
+
+ if (Math.abs(deltaX) > 3 || Math.abs(deltaY) > 3) {
+ this.isDragging = true;
+ this.offsetX -= deltaX;
+ this.offsetY -= deltaY;
+ }
+
+ this.lastMouseX = e.clientX;
+ this.lastMouseY = e.clientY;
+ }
+ });
+
+ // Zoom with mouse wheel
+ this.canvas.addEventListener('wheel', (e) => {
+ e.preventDefault();
+ const rect = this.canvas.getBoundingClientRect();
+ const mouseX = e.clientX - rect.left;
+ const mouseY = e.clientY - rect.top;
+
+ // Calculate world coordinates of mouse position before zoom
+ const worldX = (mouseX + this.offsetX) / this.zoomLevel;
+ const worldY = (mouseY + this.offsetY) / this.zoomLevel;
+
+ const zoomFactor = e.deltaY > 0 ? 0.9 : 1.1;
+ const newZoomLevel = Math.max(0.1, Math.min(5, this.zoomLevel * zoomFactor));
+
+ // Calculate new offset to keep the mouse position at the same world coordinates
+ this.offsetX = (worldX * newZoomLevel) - mouseX;
+ this.offsetY = (worldY * newZoomLevel) - mouseY;
+
+ this.zoomLevel = newZoomLevel;
+ });
+
+ // Keyboard controls
+ document.addEventListener('keydown', (e) => {
+ if (e.code === 'Space') {
+ e.preventDefault();
+ this.isPaused = !this.isPaused;
+ }
+ });
+ }
+
+ private setupSimulationSpeedSlider() {
+ const speedSlider = document.getElementById('simulation-speed') as HTMLInputElement;
+ const speedDisplay = document.getElementById('speed-display') as HTMLSpanElement;
+
+ if (speedSlider && speedDisplay) {
+ // Update display with initial value
+ speedDisplay.textContent = `${speedSlider.value} Hz`;
+
+ // Listen for slider changes
+ speedSlider.addEventListener('input', (e) => {
+ const target = e.target as HTMLInputElement;
+ const newSpeed = parseInt(target.value);
+ this.targetSimulationRate = newSpeed;
+ speedDisplay.textContent = `${newSpeed} Hz`;
+ });
+ }
+ }
+
+ private setupSaveLoadButtons() {
+ const saveButton = document.getElementById('save-pattern') as HTMLButtonElement;
+ const loadButton = document.getElementById('load-pattern') as HTMLButtonElement;
+ const fileInput = document.getElementById('pattern-file') as HTMLInputElement;
+
+ if (saveButton && loadButton) {
+ saveButton.addEventListener('click', async () => {
+ try {
+ const patternBlob = await this.savePattern();
+
+ // Create a download link
+ const url = URL.createObjectURL(patternBlob);
+ const a = document.createElement('a');
+ a.href = url;
+ a.download = `game-of-life-pattern-${Date.now()}.gol.zz`;
+ document.body.appendChild(a);
+ a.click();
+ document.body.removeChild(a);
+ URL.revokeObjectURL(url);
+
+ // Show success feedback
+ saveButton.textContent = 'Downloaded!';
+ setTimeout(() => {
+ saveButton.textContent = 'Save Pattern';
+ }, 1000);
+ } catch (error) {
+ console.error('Failed to save pattern:', error);
+ saveButton.textContent = 'Save Failed';
+ setTimeout(() => {
+ saveButton.textContent = 'Save Pattern';
+ }, 1000);
+ }
+ });
+
+ loadButton.addEventListener('click', () => {
+ // Trigger the file input
+ if (fileInput) {
+ fileInput.click();
+ } else {
+ // Create a temporary file input if none exists
+ const tempInput = document.createElement('input');
+ tempInput.type = 'file';
+ tempInput.accept = '.gol.zz,.zz';
+ tempInput.addEventListener('change', async (e) => {
+ const file = (e.target as HTMLInputElement).files?.[0];
+ if (file) {
+ await this.handleFileLoad(file, loadButton);
+ }
+ });
+ tempInput.click();
+ }
+ });
+
+ // Set up file input if it exists
+ if (fileInput) {
+ fileInput.addEventListener('change', async (e) => {
+ const file = (e.target as HTMLInputElement).files?.[0];
+ if (file) {
+ await this.handleFileLoad(file, loadButton);
+ }
+ });
+ }
+ }
+ }
+
+ private async handleFileLoad(file: File, loadButton: HTMLButtonElement) {
+ try {
+ await this.loadPattern(file);
+ loadButton.textContent = 'Loaded!';
+ setTimeout(() => {
+ loadButton.textContent = 'Load Pattern';
+ }, 1000);
+ } catch (error) {
+ console.error('Failed to load pattern:', error);
+ loadButton.textContent = 'Load Failed';
+ setTimeout(() => {
+ loadButton.textContent = 'Load Pattern';
+ }, 1000);
+ }
+ }
+
+ private cellToString(cell: Cell): string {
+ return `${cell.x},${cell.y}`;
+ }
+
+ private stringToCell(str: string): Cell {
+ const [x, y] = str.split(',').map(Number);
+ return { x, y };
+ }
+
+ private async savePattern(): Promise {
+ // Convert active cells to an array of coordinates
+ const cells = Array.from(this.activeCells).map(cellKey => {
+ const cell = this.stringToCell(cellKey);
+ return [cell.x, cell.y];
+ });
+
+ // Convert to JSON
+ const jsonData = JSON.stringify(cells);
+ const encoder = new TextEncoder();
+ const jsonBytes = encoder.encode(jsonData);
+
+ // Compress using deflate
+ const compressionStream = new CompressionStream('deflate-raw');
+ const writer = compressionStream.writable.getWriter();
+ const reader = compressionStream.readable.getReader();
+
+ // Write the data to the compression stream
+ writer.write(jsonBytes);
+ writer.close();
+
+ // Read the compressed data
+ const compressedChunks: Uint8Array[] = [];
+ let done = false;
+
+ while (!done) {
+ const { value, done: readerDone } = await reader.read();
+ done = readerDone;
+ if (value) {
+ compressedChunks.push(value);
+ }
+ }
+
+ // Combine all chunks into a single blob
+ const combinedArray = new Uint8Array(
+ compressedChunks.reduce((totalLength, chunk) => totalLength + chunk.length, 0)
+ );
+ let offset = 0;
+ for (const chunk of compressedChunks) {
+ combinedArray.set(chunk, offset);
+ offset += chunk.length;
+ }
+
+ return new Blob([combinedArray], { type: 'application/deflate' });
+ }
+
+ private async loadPattern(file: File): Promise {
+ try {
+ // Read the file as array buffer
+ const compressedData = await file.arrayBuffer();
+
+ // Decompress using deflate
+ const decompressionStream = new DecompressionStream('deflate-raw');
+ const writer = decompressionStream.writable.getWriter();
+ const reader = decompressionStream.readable.getReader();
+
+ // Write the compressed data to the decompression stream
+ writer.write(new Uint8Array(compressedData));
+ writer.close();
+
+ // Read the decompressed data
+ const decompressedChunks: Uint8Array[] = [];
+ let done = false;
+
+ while (!done) {
+ const { value, done: readerDone } = await reader.read();
+ done = readerDone;
+ if (value) {
+ decompressedChunks.push(value);
+ }
+ }
+
+ // Combine chunks and decode to string
+ const totalLength = decompressedChunks.reduce((sum, chunk) => sum + chunk.length, 0);
+ const combinedArray = new Uint8Array(totalLength);
+ let offset = 0;
+
+ for (const chunk of decompressedChunks) {
+ combinedArray.set(chunk, offset);
+ offset += chunk.length;
+ }
+
+ const decoder = new TextDecoder();
+ const jsonData = decoder.decode(combinedArray);
+ const cells = JSON.parse(jsonData) as number[][];
+
+ // Clear current pattern
+ this.activeCells.clear();
+ this.activeCellsNext.clear();
+ this.potentialCells.clear();
+ this.potentialCellsNext.clear();
+
+ // Load new pattern
+ for (const [x, y] of cells) {
+ const cellKey = this.cellToString({ x, y });
+ this.activeCells.add(cellKey);
+ this.potentialCells.add(cellKey);
+
+ // Add neighbors to potential cells
+ const neighbors = this.getNeighbors({ x, y });
+ for (const neighbor of neighbors) {
+ this.potentialCells.add(this.cellToString(neighbor));
+ }
+ }
+
+ // Initialize next generation sets
+ this.activeCellsNext = new Set(this.activeCells);
+ this.potentialCellsNext = new Set(this.potentialCells);
+
+ } catch (error) {
+ throw new Error('Invalid pattern file or decompression failed');
+ }
+ }
+
+ private handleCellClick(e: MouseEvent) {
+ const rect = this.canvas.getBoundingClientRect();
+ const x = e.clientX - rect.left;
+ const y = e.clientY - rect.top;
+
+ // Convert screen coordinates to grid coordinates
+ const cellSize = 10 * this.zoomLevel;
+ const gridX = Math.floor((x + this.offsetX) / cellSize);
+ const gridY = Math.floor((y + this.offsetY) / cellSize);
+
+ const cellKey = this.cellToString({ x: gridX, y: gridY });
+
+ // Toggle cell state
+ if (this.activeCells.has(cellKey)) {
+ this.activeCells.delete(cellKey);
+ this.activeCellsNext.delete(cellKey);
+ this.potentialCellsNext.add(cellKey);
+
+ const neighbors = this.getNeighbors({ x: gridX, y: gridY });
+ for (const neighbor of neighbors) {
+ this.potentialCellsNext.add(this.cellToString(neighbor));
+ }
+ } else {
+ this.activeCells.add(cellKey);
+ this.activeCellsNext.add(cellKey);
+ this.potentialCellsNext.add(cellKey);
+
+ // Add neighbors to potential cells
+ const neighbors = this.getNeighbors({ x: gridX, y: gridY });
+ for (const neighbor of neighbors) {
+ this.potentialCellsNext.add(this.cellToString(neighbor));
+ }
+ }
+ }
+
+ private handleRightClick(e: MouseEvent) {
+ const rect = this.canvas.getBoundingClientRect();
+ const x = e.clientX - rect.left;
+ const y = e.clientY - rect.top;
+
+ // Convert screen coordinates to grid coordinates
+ const cellSize = 10 * this.zoomLevel;
+ const centerX = Math.floor((x + this.offsetX) / cellSize);
+ const centerY = Math.floor((y + this.offsetY) / cellSize);
+
+ // Define the area size (radius around the cursor) - scale inversely with zoom level
+ // Base radius of 5 at zoom level 1, scales up when zoomed out
+ const areaRadius = Math.max(2, Math.round(5 / this.zoomLevel));
+ const fillDensity = 0.3; // 30% chance for each cell to be filled
+
+ // Fill random cells in the area
+ for (let dx = -areaRadius; dx <= areaRadius; dx++) {
+ for (let dy = -areaRadius; dy <= areaRadius; dy++) {
+ // Only fill cells within a circular area
+ if (dx * dx + dy * dy <= areaRadius * areaRadius) {
+ if (Math.random() < fillDensity) {
+ const gridX = centerX + dx;
+ const gridY = centerY + dy;
+ const cellKey = this.cellToString({ x: gridX, y: gridY });
+
+ // Add the cell if it's not already alive
+ if (!this.activeCells.has(cellKey)) {
+ this.activeCells.add(cellKey);
+ this.activeCellsNext.add(cellKey);
+ this.potentialCellsNext.add(cellKey);
+
+ // Add neighbors to potential cells
+ const neighbors = this.getNeighbors({ x: gridX, y: gridY });
+ for (const neighbor of neighbors) {
+ this.potentialCellsNext.add(this.cellToString(neighbor));
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private update() {
+ if (!this.isPaused) {
+ this.updateCells();
+ }
+
+ setTimeout(() => requestAnimationFrame(this.update.bind(this)), 1000 / this.targetSimulationRate);
+ }
+
+ private updateCells() {
+ //Check if the card is currently flipped, otherwise do not update cells.
+ const isFlipped = document.querySelector('main')?.classList.contains('is-flipped');
+ if (!isFlipped) {
+ return;
+ }
+
+ this.activeCells = new Set(this.activeCellsNext);
+ this.activeCellsNext = new Set();
+
+ this.potentialCells = new Set(this.potentialCellsNext);
+
+ // Each current cell has the potential to cause change on this update.
+ this.potentialCellsNext = new Set(this.activeCells);
+
+ for (const cellKey of this.potentialCells) {
+ const cell = this.stringToCell(cellKey);
+ const neighbors = this.getNeighbors(cell);
+ const aliveNeighbors = neighbors.filter(n => this.activeCells.has(this.cellToString(n))).length;
+
+ if (this.activeCells.has(cellKey)) {
+ // Cell is currently alive
+ if (aliveNeighbors < 2 || aliveNeighbors > 3) {
+ // Cell dies, so we don't add it to the next generation
+
+ // However, this means the surrounding cells could change on the next generation.
+ for (const neighbor of neighbors) {
+ // Add neighbors to potential cells for next generation
+ this.potentialCellsNext.add(this.cellToString(neighbor));
+ }
+ this.potentialCellsNext.add(cellKey);
+ continue;
+ } else {
+ // Cell stays alive
+ this.activeCellsNext.add(cellKey);
+ }
+ } else {
+ // Cell is currently dead
+ if (aliveNeighbors === 3) {
+ // Cell becomes alive
+ this.activeCellsNext.add(cellKey);
+ this.potentialCellsNext.add(cellKey);
+
+ for (const neighbor of neighbors) {
+ // Add neighbors to potential cells for next generation
+ this.potentialCellsNext.add(this.cellToString(neighbor));
+ }
+ }
+ }
+ }
+ }
+
+ private getNeighbors(cell: Cell): Cell[] {
+ const neighbors: Cell[] = [];
+ for (let x = -1; x <= 1; x++) {
+ for (let y = -1; y <= 1; y++) {
+ // Ignore the cell itself.
+ if (x === 0 && y === 0)
+ {
+ continue;
+ }
+ neighbors.push({ x: cell.x + x, y: cell.y + y });
+ }
+ }
+ return neighbors;
+ }
+
+ private drawCells() {
+ const isFlipped = document.querySelector('main')?.classList.contains('is-flipped');
+ if (!isFlipped) {
+ setTimeout(() => requestAnimationFrame(this.drawCells.bind(this)), 1000 / this.targetFrameRate);
+ return;
+ }
+
+ // Draw the cells, taking into account viewport offset and zoom level.
+ this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
+
+ // Find what range of cells are currently visible based on the canvas size and zoom level.
+ let cellSize = 10; // Default size of each cell in pixels
+
+ // Adjust size by zoom level
+ cellSize *= this.zoomLevel;
+
+ // Calculate the visible range of cells
+ const startX = Math.floor(this.offsetX / cellSize);
+ const startY = Math.floor(this.offsetY / cellSize);
+ const endX = Math.ceil((this.offsetX + this.canvas.width) / cellSize);
+ const endY = Math.ceil((this.offsetY + this.canvas.height) / cellSize);
+
+ // Draw grid lines for better visibility
+ this.ctx.strokeStyle = 'rgba(255, 255, 255, 0.1)';
+ this.ctx.lineWidth = 1;
+
+ for (let x = startX; x <= endX; x++) {
+ const screenX = (x * cellSize) - this.offsetX;
+ this.ctx.beginPath();
+ this.ctx.moveTo(screenX, 0);
+ this.ctx.lineTo(screenX, this.canvas.height);
+ this.ctx.stroke();
+ }
+
+ for (let y = startY; y <= endY; y++) {
+ const screenY = (y * cellSize) - this.offsetY;
+ this.ctx.beginPath();
+ this.ctx.moveTo(0, screenY);
+ this.ctx.lineTo(this.canvas.width, screenY);
+ this.ctx.stroke();
+ }
+
+ this.ctx.fillStyle = '#67e8f9'; // cyan color to match theme
+
+ // Draw active cells
+ for (let x = startX; x < endX; x++) {
+ for (let y = startY; y < endY; y++) {
+ const cellKey = this.cellToString({ x, y });
+ if (this.activeCells.has(cellKey)) {
+ const screenX = (x * cellSize) - this.offsetX;
+ const screenY = (y * cellSize) - this.offsetY;
+ this.ctx.fillRect(screenX, screenY, cellSize - 1, cellSize - 1);
+ }
+ }
+ }
+
+ this.ctx.fillStyle = 'rgba(255, 255, 255, 0.8)';
+ this.ctx.font = '20px Exo 2 Variable, sans-serif';
+
+ // Draw pause indicator
+ if (this.isPaused) {
+ this.ctx.fillText('PAUSED - Press SPACE to resume', 10, 30);
+ }
+
+ // Draw current X, Y and zoom level along with total number of active cells in bottom left
+ this.ctx.fillText(`X: ${Math.floor(this.offsetX / cellSize)}, Y: ${Math.floor(this.offsetY / cellSize)}, Zoom: ${this.zoomLevel.toFixed(2)}`, 10, this.canvas.height - 10);
+ this.ctx.fillText(`Active Cells: ${this.activeCells.size}`, 10, this.canvas.height - 30);
+
+
+ setTimeout(() => requestAnimationFrame(this.drawCells.bind(this)), 1000 / this.targetFrameRate);
+ }
+}
\ No newline at end of file
diff --git a/src/server.ts b/src/server.ts
new file mode 100644
index 0000000..ce69554
--- /dev/null
+++ b/src/server.ts
@@ -0,0 +1,175 @@
+import { Elysia } from 'elysia';
+import { staticPlugin } from '@elysiajs/static';
+import path from 'path';
+
+// Song data interface
+interface LastSongImage {
+ size: 'small' | 'medium' | 'large' | 'extralarge';
+ '#text': string;
+}
+
+interface LastSong {
+ name: string;
+ artist: string;
+ album: string;
+ url: string;
+ nowPlaying: boolean;
+ image: LastSongImage[];
+ playedAt?: number; // epoch seconds from Last.fm for history entries
+}
+
+// Current song state
+let currentSong: LastSong | null = null;
+let lastSongId: string | null = null;
+let history: LastSong[] = []; // last 5 tracks (most recent first)
+let pollTimer: ReturnType | null = null;
+
+// Minimal shape we need for a WS connection
+type WSLike = { send: (data: string | Uint8Array) => void };
+// WebSocket connections
+const connections = new Set();
+
+// Function to fetch song from Last.fm
+async function fetchLastFmSongAndHistory(): Promise<{ current: LastSong | null; recent: LastSong[] }> {
+ const apiKey = Bun.env.LASTFM_API_KEY;
+ const username = Bun.env.LASTFM_USERNAME;
+
+ if (!apiKey || !username) {
+ console.error('Last.fm API key or username not configured');
+ return { current: null, recent: [] };
+ }
+
+ const url = `https://ws.audioscrobbler.com/2.0/?method=user.getrecenttracks&user=${username}&api_key=${apiKey}&format=json&limit=5`;
+
+ try {
+ const response = await fetch(url);
+ if (!response.ok) {
+ console.error('Last.fm response not OK:', response.status, response.statusText);
+ return { current: null, recent: [] };
+ }
+ const data = await response.json().catch(() => null as any);
+ const tracks = Array.isArray(data?.recenttracks?.track) ? data.recenttracks.track : [];
+ if (!tracks.length) return { current: null, recent: [] };
+
+ const mapped: LastSong[] = tracks.map((t: any) => ({
+ name: t?.name ?? '',
+ artist: t?.artist?.['#text'] ?? '',
+ album: t?.album?.['#text'] ?? '',
+ url: t?.url ?? '',
+ nowPlaying: t?.['@attr']?.nowplaying === 'true',
+ image: Array.isArray(t?.image) ? t.image : [],
+ playedAt: t?.date?.uts ? Number(t.date.uts) : undefined,
+ }));
+
+ const current = mapped[0] ?? null;
+ // History is the next items that have a playedAt (exclude the currently playing item)
+ const recent = mapped.filter((s) => !!s.playedAt).slice(0, 5);
+ return { current, recent };
+ } catch (error) {
+ console.error('Error fetching from Last.fm:', error);
+ return { current: null, recent: [] };
+ }
+}
+
+// Function to check for song changes and notify clients
+async function checkAndUpdateSong(): Promise {
+ const { current: newSong, recent } = await fetchLastFmSongAndHistory();
+
+ // Default to not currently playing if we couldn't fetch anything
+ let nowPlaying = false;
+
+ if (newSong) {
+ // Create a unique identifier for the song (include nowPlaying state)
+ const newSongId = `${newSong.artist}-${newSong.name}-${newSong.nowPlaying}`;
+
+ // Check if song has changed
+ if (newSongId !== lastSongId) {
+ console.log('Song changed:', newSong.name, 'by', newSong.artist);
+ // Update state and notify clients
+ currentSong = newSong;
+ lastSongId = newSongId;
+ history = recent;
+
+ const message = JSON.stringify({
+ type: 'song-update',
+ data: newSong,
+ history
+ });
+
+ connections.forEach(ws => {
+ try {
+ ws.send(message);
+ } catch (error) {
+ console.error('Error sending to WebSocket client:', error);
+ connections.delete(ws);
+ }
+ });
+ } else {
+ // Keep currentSong updated even if no change to ID (e.g., image/url may vary)
+ currentSong = newSong;
+ history = recent;
+ }
+
+ nowPlaying = !!newSong.nowPlaying;
+ } else {
+ // If fetch failed, keep existing currentSong and fall back to slower polling
+ nowPlaying = currentSong?.nowPlaying ?? false;
+ }
+
+ // Schedule next poll based on whether a track is currently playing
+ const delayMs = nowPlaying ? 5000 : 30000;
+ if (pollTimer) clearTimeout(pollTimer);
+ pollTimer = setTimeout(checkAndUpdateSong, delayMs);
+}
+
+// Kick off adaptive polling with an immediate check
+checkAndUpdateSong();
+
+// Determine static assets path - adjust for compiled executable
+const assetsPath = Bun.env.NODE_ENV === 'production'
+ ? path.join(path.dirname(process.execPath || __dirname), 'dist')
+ : 'dist';
+
+console.log('Serving static assets from:', assetsPath);
+
+const app = new Elysia()
+ .use(staticPlugin({
+ assets: assetsPath,
+ prefix: ''
+ }))
+ // Simple health check endpoint for uptime checks and Docker
+ .get('/healthz', () => ({ status: 'ok', now: Date.now() }))
+ .ws('/music', {
+ message(ws, message) {
+ // Handle incoming messages if needed
+ console.log('Received message from client:', message);
+ },
+ open(ws) {
+ console.log('WebSocket client connected');
+ connections.add(ws);
+
+ // Send current song to new client immediately
+ if (currentSong) {
+ const message = JSON.stringify({
+ type: 'song-update',
+ data: currentSong,
+ history
+ });
+ ws.send(message);
+ }
+ },
+ close(ws) {
+ console.log('WebSocket client disconnected');
+ connections.delete(ws);
+ },
+ })
+ .listen({
+ port: Bun.env.PORT || 3000,
+ hostname: Bun.env.NODE_ENV === 'production' ? '0.0.0.0' : 'localhost'
+ });
+
+console.log(
+ `🦊 Elysia is running at http://${app.server?.hostname}:${app.server?.port}`
+);
+
+export type App = typeof app;
diff --git a/src/style.css b/src/style.css
new file mode 100644
index 0000000..a5468ee
--- /dev/null
+++ b/src/style.css
@@ -0,0 +1,303 @@
+@import "tailwindcss";
+@import "@fontsource-variable/exo-2";
+
+/* Custom styles for the glassmorphism effect and background */
+html {
+ font-family: 'Exo 2 Variable', sans-serif;
+ /* Deep blue theme */
+ background: linear-gradient(135deg, #2c3e50 0%, #4ca1af 100%);
+ padding: 0;
+ margin: 0;
+}
+
+body {
+ overflow-x: hidden;
+ margin: 0;
+ padding: 0;
+}
+
+/* Skeleton shimmer */
+.skeleton {
+ position: relative;
+ background: linear-gradient(90deg, rgba(255,255,255,0.08), rgba(255,255,255,0.18), rgba(255,255,255,0.08));
+ background-size: 200% 100%;
+ animation: skeleton-loading 1.2s ease-in-out infinite;
+}
+
+@keyframes skeleton-loading {
+ 0% { background-position: 200% 0; }
+ 100% { background-position: -200% 0; }
+}
+
+/* The main card with the glass effect */
+.glass-card {
+ background: rgba(255, 255, 255, 0.1);
+ backdrop-filter: blur(25px);
+ -webkit-backdrop-filter: blur(25px);
+ border: 1px solid rgba(255, 255, 255, 0.2);
+ box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.2);
+}
+
+/* Decorative background shapes */
+.shape {
+ position: absolute;
+ border-radius: 50%;
+ filter: blur(100px);
+ z-index: -1;
+ animation: float 20s infinite ease-in-out alternate;
+ pointer-events: none;
+}
+
+.shape-1 {
+ width: 300px;
+ height: 300px;
+ background: rgba(76, 161, 175, 0.4);
+ top: 0;
+ left: 0;
+ transform: translate(-25%, -25%);
+ animation-duration: 25s;
+}
+
+.shape-2 {
+ width: 400px;
+ height: 400px;
+ background: rgba(108, 99, 255, 0.3);
+ bottom: 0;
+ right: 0;
+ transform: translate(25%, 25%);
+ animation-duration: 20s;
+}
+
+.shape-3 {
+ width: 250px;
+ height: 250px;
+ background: rgba(67, 209, 217, 0.3);
+ bottom: 20%;
+ left: 10%;
+ animation-duration: 30s;
+}
+
+@keyframes float {
+ 0% {
+ transform: translateY(0px) translateX(0px);
+ }
+
+ 50% {
+ transform: translateY(-40px) translateX(20px);
+ }
+
+ 100% {
+ transform: translateY(0px) translateX(0px);
+ }
+}
+
+/* Custom styling for hoverable elements */
+.hover-glass {
+ background: rgba(255, 255, 255, 0.15);
+ box-shadow: 0 2px 10px rgba(0, 0, 0, 0);
+ transition: background 0.3s ease, transform 0.3s ease, box-shadow 0.3s ease, color 0.3s ease;
+}
+
+.hover-glass:hover {
+ background: rgba(255, 255, 255, 0.3);
+ box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
+ transform: translateY(-2px);
+}
+
+/* Equalizer animation */
+.eq {
+ display: inline-flex;
+ gap: 2px;
+ align-items: flex-end;
+ margin-right: 4px;
+}
+.eq span {
+ width: 3px;
+ height: 8px;
+ background-color: #67e8f9; /* cyan-300 */
+ display: inline-block;
+ animation: eq-bounce 0.9s infinite ease-in-out;
+}
+.eq span:nth-child(2) { animation-delay: 0.15s; }
+.eq span:nth-child(3) { animation-delay: 0.3s; }
+
+@keyframes eq-bounce {
+ 0%, 100% { height: 4px; opacity: 0.8; }
+ 50% { height: 12px; opacity: 1; }
+}
+
+/* History list styling */
+details.history {
+ width: 100%;
+}
+details.history[open] summary {
+ color: #a5f3fc; /* cyan-200 */
+}
+details.history ul li {
+ border-left: 2px solid rgba(255,255,255,0.1);
+ padding-left: 6px;
+}
+
+/* Animated gradient for text */
+.animated-gradient {
+ background: linear-gradient(90deg, #4dd0e1, #818cf8, #a5f3fc, #4dd0e1);
+ background-size: 200% auto;
+ -webkit-background-clip: text;
+ background-clip: text;
+ color: transparent;
+ animation: gradient-animation 5s ease infinite;
+}
+
+@keyframes gradient-animation {
+ 0% {
+ background-position: 0% 50%;
+ }
+ 50% {
+ background-position: 100% 50%;
+ }
+ 100% {
+ background-position: 0% 50%;
+ }
+}
+
+/* Tooltip styles */
+.tooltip {
+ position: relative;
+ display: inline-block;
+}
+
+.tooltip .tooltip-text {
+ visibility: hidden;
+ opacity: 0;
+ width: max-content;
+ max-width: 200px;
+ background: rgba(43, 85, 131, 0.9);
+ color: #fff;
+ text-align: center;
+ border-radius: 8px;
+ padding: 8px 12px;
+ position: absolute;
+ z-index: 1000;
+ top: 50%;
+ left: 100%;
+ transform: translateX(50%) translateY(-50%);
+ font-size: 14px;
+ font-weight: 500;
+ white-space: nowrap;
+ backdrop-filter: blur(10px);
+ -webkit-backdrop-filter: blur(10px);
+ border: 1px solid rgba(255, 255, 255, 0.1);
+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
+ transition: opacity 0.3s ease, visibility 0.3s ease, transform 0.3s ease;
+}
+
+.tooltip:hover .tooltip-text {
+ visibility: visible;
+ opacity: 1;
+ transform: translateX(0%) translateY(-50%);
+}
+
+/* Music tooltip specific styling */
+.music-tooltip .tooltip-text {
+ white-space: normal;
+ line-height: 1.4;
+}
+
+.music-tooltip .tooltip-text .song-name {
+ font-weight: 600;
+ color: #4dd0e1;
+ margin-bottom: 2px;
+}
+
+.music-tooltip .tooltip-text .artist-name {
+ font-weight: 500;
+ color: #e2e8f0;
+ margin-bottom: 1px;
+}
+
+.music-tooltip .tooltip-text .album-name {
+ font-weight: 400;
+ color: #cbd5e0;
+ font-size: 12px;
+}
+
+/* Card flip styles */
+.card-container {
+ perspective: 1500px;
+}
+
+.card-flipper {
+ position: relative;
+ width: 100%;
+ min-height: 720px;
+ transform-style: preserve-3d;
+ transition: transform 0.8s cubic-bezier(0.175, 0.885, 0.32, 1.275);
+}
+
+.card-container.is-flipped .card-flipper {
+ transform: rotateY(-180deg);
+}
+
+.card-front,
+.card-back {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ backface-visibility: hidden;
+ -webkit-backface-visibility: hidden;
+}
+
+.card-front {
+ z-index: 2;
+ transform: rotateY(0deg);
+}
+
+.card-back {
+ transform: rotateY(-180deg);
+ z-index: 1;
+}
+
+/* Slider styles for simulation speed control */
+.slider {
+ background: rgba(255, 255, 255, 0.2);
+ outline: none;
+ -webkit-appearance: none;
+ appearance: none;
+}
+
+.slider::-webkit-slider-thumb {
+ appearance: none;
+ width: 20px;
+ height: 20px;
+ border-radius: 50%;
+ background: #67e8f9;
+ cursor: pointer;
+ border: 2px solid rgba(255, 255, 255, 0.3);
+ box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
+ transition: all 0.3s ease;
+}
+
+.slider::-webkit-slider-thumb:hover {
+ background: #4dd0e1;
+ transform: scale(1.1);
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4);
+}
+
+.slider::-moz-range-thumb {
+ width: 20px;
+ height: 20px;
+ border-radius: 50%;
+ background: #67e8f9;
+ cursor: pointer;
+ border: 2px solid rgba(255, 255, 255, 0.3);
+ box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
+ transition: all 0.3s ease;
+}
+
+.slider::-moz-range-thumb:hover {
+ background: #4dd0e1;
+ transform: scale(1.1);
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4);
+}
\ No newline at end of file
diff --git a/tailwind.config.js b/tailwind.config.js
deleted file mode 100644
index 7cd1abf..0000000
--- a/tailwind.config.js
+++ /dev/null
@@ -1,10 +0,0 @@
-/** @type {import('tailwindcss').Config} */
-module.exports = {
- content: ["./www/**/*.{html,js}"],
- theme: {
- darkMode: 'media',
- extend: {},
- },
- plugins: [],
-}
-
diff --git a/tsconfig.json b/tsconfig.json
new file mode 100644
index 0000000..1bf46ff
--- /dev/null
+++ b/tsconfig.json
@@ -0,0 +1,21 @@
+{
+ "compilerOptions": {
+ "target": "ES2022",
+ "module": "ESNext",
+ "moduleResolution": "Bundler",
+ "strict": true,
+ "noEmit": true,
+ "skipLibCheck": true,
+ "types": [
+ "bun-types",
+ "vite/client"
+ ],
+ "jsx": "react-jsx",
+ "allowJs": true,
+ "resolveJsonModule": true
+ },
+ "include": [
+ "src",
+ "vite.config.*"
+ ]
+}
diff --git a/vite.config.js b/vite.config.js
new file mode 100644
index 0000000..6959824
--- /dev/null
+++ b/vite.config.js
@@ -0,0 +1,28 @@
+import { defineConfig } from 'vite'
+import tailwindcss from '@tailwindcss/vite'
+import Icons from 'unplugin-icons/vite'
+
+
+export default defineConfig({
+ plugins: [
+ tailwindcss(),
+ Icons({
+ compiler: 'web-components',
+ webComponents: {
+ autoDefine: true,
+ },
+ })
+ ],
+ server: {
+ port: 5173,
+ host: 'localhost',
+ proxy: {
+ // Proxy the backend WebSocket/API on /music to the Bun server
+ '/music': {
+ target: 'http://localhost:3000',
+ changeOrigin: true,
+ ws: true,
+ },
+ },
+ },
+})
\ No newline at end of file
diff --git a/www/css/custom.css b/www/css/custom.css
deleted file mode 100644
index 5dd6aeb..0000000
--- a/www/css/custom.css
+++ /dev/null
@@ -1,9 +0,0 @@
-* {
- box-sizing: border-box;
-
- font-family: 'Chakra Petch', sans-serif;
-}
-
-html, body {
- min-height: 100% !important;
-}
\ No newline at end of file
diff --git a/www/css/input.css b/www/css/input.css
deleted file mode 100644
index bd6213e..0000000
--- a/www/css/input.css
+++ /dev/null
@@ -1,3 +0,0 @@
-@tailwind base;
-@tailwind components;
-@tailwind utilities;
\ No newline at end of file
diff --git a/www/demos/filters.html b/www/demos/filters.html
deleted file mode 100644
index d775c8b..0000000
--- a/www/demos/filters.html
+++ /dev/null
@@ -1,608 +0,0 @@
-
-
-
-
-
-
- Search Example
-
-
-
-
-
- Search Filter Example
-
- Please note, this is still *very* early. It is a proof of concept, not attached to any real data, and is designed to allow experimentation with a *potential* filtering method.
-
-
- This example is still missing dynamic filters entirely, and sort and pagination are yet to be implemented. It is also not yet wholly responsive.
-
- Additionally, the counts on the category and brand buttons are not yet implemented, and filter chips are not sorted in any way.
-
-
-
-
-
-
-
-
Category (X)
-
Brand (X)
-
-
Sort
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/www/favicon.ico b/www/favicon.ico
deleted file mode 100644
index cd440da..0000000
Binary files a/www/favicon.ico and /dev/null differ
diff --git a/www/index.html b/www/index.html
deleted file mode 100644
index 64d601a..0000000
--- a/www/index.html
+++ /dev/null
@@ -1,148 +0,0 @@
-
-
-
- Cameron's Corner
-
-
-
-
-
-
-
-
-
-
-
- Cameron's Corner
-
- Welcome to Cameron's Corner, my own little slice of the Internet.
-
-
-
- Current Projects
- Looking for things I've done? Check out some of my projects!
-
-
-
-
- Socials
- Want to get in touch? You can find me at all of these places!
-
-
-
- Copyright © Cameron Redmore 2023
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/www/js/main.js b/www/js/main.js
deleted file mode 100644
index e69de29..0000000
diff --git a/www/js/obf.js b/www/js/obf.js
deleted file mode 100644
index 7d12ae5..0000000
--- a/www/js/obf.js
+++ /dev/null
@@ -1 +0,0 @@
-function _0x52c7(_0x2c81f6,_0x37a3cb){const _0x5562fd=_0x1abb();return _0x52c7=function(_0x4d3a20,_0x383560){_0x4d3a20=_0x4d3a20-(-0x1e1c+0x2*0x789+0xffe);let _0x41d4ac=_0x5562fd[_0x4d3a20];if(_0x52c7['\x57\x51\x7a\x6c\x64\x48']===undefined){var _0x4e2868=function(_0x21e7d0){const _0x1f7123='\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x2b\x2f\x3d';let _0x4667bd='',_0x2ca6b3='',_0x4bbfc1=_0x4667bd+_0x4e2868;for(let _0x1aa531=-0xca2+-0xc*-0x293+-0x1242,_0x5c5c57,_0x5b04eb,_0x245923=-0x1*-0x25d9+-0x40*-0x73+-0x4299*0x1;_0x5b04eb=_0x21e7d0['\x63\x68\x61\x72\x41\x74'](_0x245923++);~_0x5b04eb&&(_0x5c5c57=_0x1aa531%(0x4*0x167+0x493*-0x4+0xcb4)?_0x5c5c57*(-0x1687+-0xf*-0xd3+0xa6a)+_0x5b04eb:_0x5b04eb,_0x1aa531++%(-0xf8b*0x1+0x4*0x6c5+-0xb85))?_0x4667bd+=_0x4bbfc1['\x63\x68\x61\x72\x43\x6f\x64\x65\x41\x74'](_0x245923+(0x2253+-0x23*0x11c+-0x48b*-0x1))-(-0x15cb+0x248e*0x1+-0xeb9)!==0x11b*0x17+0x1aff+0xdc*-0x3d?String['\x66\x72\x6f\x6d\x43\x68\x61\x72\x43\x6f\x64\x65'](-0xf63*-0x1+0x1b8e+-0x1*0x29f2&_0x5c5c57>>(-(0x2b*-0xdf+0x1d98+0x7df)*_0x1aa531&-0x43e*-0x9+0x1e40+-0x18e*0x2c)):_0x1aa531:0x1*0x23f3+0x91f+-0x2d12){_0x5b04eb=_0x1f7123['\x69\x6e\x64\x65\x78\x4f\x66'](_0x5b04eb);}for(let _0xd23709=0x324+0x1*0x7ed+-0xb11,_0xc5f2cb=_0x4667bd['\x6c\x65\x6e\x67\x74\x68'];_0xd23709<_0xc5f2cb;_0xd23709++){_0x2ca6b3+='\x25'+('\x30\x30'+_0x4667bd['\x63\x68\x61\x72\x43\x6f\x64\x65\x41\x74'](_0xd23709)['\x74\x6f\x53\x74\x72\x69\x6e\x67'](-0x1f*-0xfb+0x2092+-0x1*0x3ee7))['\x73\x6c\x69\x63\x65'](-(-0x2*0xfaa+-0xb8c+0x2ae2*0x1));}return decodeURIComponent(_0x2ca6b3);};_0x52c7['\x71\x55\x4b\x47\x41\x7a']=_0x4e2868,_0x2c81f6=arguments,_0x52c7['\x57\x51\x7a\x6c\x64\x48']=!![];}const _0x1db3c7=_0x5562fd[-0x1*-0xff5+0x15b*-0x17+-0x8*-0x1e7],_0x341968=_0x4d3a20+_0x1db3c7,_0x26a0bf=_0x2c81f6[_0x341968];if(!_0x26a0bf){const _0x330d48=function(_0x547f9b){this['\x49\x74\x52\x67\x66\x4e']=_0x547f9b,this['\x74\x66\x70\x6d\x6c\x44']=[-0x6a*0x59+-0x43*-0x7+-0x1*-0x2306,-0x1c*0xa1+0x26ad*-0x1+-0x9*-0x641,0x2b6*-0x6+-0x377+-0x13bb*-0x1],this['\x6e\x4d\x54\x58\x79\x53']=function(){return'\x6e\x65\x77\x53\x74\x61\x74\x65';},this['\x51\x49\x44\x58\x54\x52']='\x5c\x77\x2b\x20\x2a\x5c\x28\x5c\x29\x20\x2a\x7b\x5c\x77\x2b\x20\x2a',this['\x64\x68\x6b\x53\x6c\x4d']='\x5b\x27\x7c\x22\x5d\x2e\x2b\x5b\x27\x7c\x22\x5d\x3b\x3f\x20\x2a\x7d';};_0x330d48['\x70\x72\x6f\x74\x6f\x74\x79\x70\x65']['\x59\x6d\x5a\x4b\x50\x57']=function(){const _0x1006a4=new RegExp(this['\x51\x49\x44\x58\x54\x52']+this['\x64\x68\x6b\x53\x6c\x4d']),_0x13917c=_0x1006a4['\x74\x65\x73\x74'](this['\x6e\x4d\x54\x58\x79\x53']['\x74\x6f\x53\x74\x72\x69\x6e\x67']())?--this['\x74\x66\x70\x6d\x6c\x44'][-0x237f+0x1b37+-0x849*-0x1]:--this['\x74\x66\x70\x6d\x6c\x44'][0x15f9+0x55*0x41+-0x2b8e];return this['\x70\x6d\x43\x45\x75\x79'](_0x13917c);},_0x330d48['\x70\x72\x6f\x74\x6f\x74\x79\x70\x65']['\x70\x6d\x43\x45\x75\x79']=function(_0x3af4af){if(!Boolean(~_0x3af4af))return _0x3af4af;return this['\x72\x4d\x43\x72\x49\x73'](this['\x49\x74\x52\x67\x66\x4e']);},_0x330d48['\x70\x72\x6f\x74\x6f\x74\x79\x70\x65']['\x72\x4d\x43\x72\x49\x73']=function(_0x3c090b){for(let _0x40e030=-0xc43+0x1260+-0x5*0x139,_0x3be523=this['\x74\x66\x70\x6d\x6c\x44']['\x6c\x65\x6e\x67\x74\x68'];_0x40e030<_0x3be523;_0x40e030++){this['\x74\x66\x70\x6d\x6c\x44']['\x70\x75\x73\x68'](Math['\x72\x6f\x75\x6e\x64'](Math['\x72\x61\x6e\x64\x6f\x6d']())),_0x3be523=this['\x74\x66\x70\x6d\x6c\x44']['\x6c\x65\x6e\x67\x74\x68'];}return _0x3c090b(this['\x74\x66\x70\x6d\x6c\x44'][-0x86+0x12f1+-0xcd*0x17]);},new _0x330d48(_0x52c7)['\x59\x6d\x5a\x4b\x50\x57'](),_0x41d4ac=_0x52c7['\x71\x55\x4b\x47\x41\x7a'](_0x41d4ac),_0x2c81f6[_0x341968]=_0x41d4ac;}else _0x41d4ac=_0x26a0bf;return _0x41d4ac;},_0x52c7(_0x2c81f6,_0x37a3cb);}function _0x3689(_0x5c96ce,_0x31a26b){const _0x155443=_0x1abb();return _0x3689=function(_0xf68c3f,_0x1e3cf1){_0xf68c3f=_0xf68c3f-(-0x1e1c+0x2*0x789+0xffe);let _0x214c77=_0x155443[_0xf68c3f];if(_0x3689['\x7a\x4f\x73\x6c\x50\x6f']===undefined){var _0x29ffe9=function(_0x155c2c){const _0x5d4cde='\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x2b\x2f\x3d';let _0x23814e='',_0xc44014='',_0x50426e=_0x23814e+_0x29ffe9;for(let _0x30bdb9=-0xca2+-0xc*-0x293+-0x1242,_0x2eaa37,_0x39f5ee,_0x58d1fb=-0x1*-0x25d9+-0x40*-0x73+-0x4299*0x1;_0x39f5ee=_0x155c2c['\x63\x68\x61\x72\x41\x74'](_0x58d1fb++);~_0x39f5ee&&(_0x2eaa37=_0x30bdb9%(0x4*0x167+0x493*-0x4+0xcb4)?_0x2eaa37*(-0x1687+-0xf*-0xd3+0xa6a)+_0x39f5ee:_0x39f5ee,_0x30bdb9++%(-0xf8b*0x1+0x4*0x6c5+-0xb85))?_0x23814e+=_0x50426e['\x63\x68\x61\x72\x43\x6f\x64\x65\x41\x74'](_0x58d1fb+(0x2253+-0x23*0x11c+-0x48b*-0x1))-(-0x15cb+0x248e*0x1+-0xeb9)!==0x11b*0x17+0x1aff+0xdc*-0x3d?String['\x66\x72\x6f\x6d\x43\x68\x61\x72\x43\x6f\x64\x65'](-0xf63*-0x1+0x1b8e+-0x1*0x29f2&_0x2eaa37>>(-(0x2b*-0xdf+0x1d98+0x7df)*_0x30bdb9&-0x43e*-0x9+0x1e40+-0x18e*0x2c)):_0x30bdb9:0x1*0x23f3+0x91f+-0x2d12){_0x39f5ee=_0x5d4cde['\x69\x6e\x64\x65\x78\x4f\x66'](_0x39f5ee);}for(let _0x1475c4=0x324+0x1*0x7ed+-0xb11,_0x230252=_0x23814e['\x6c\x65\x6e\x67\x74\x68'];_0x1475c4<_0x230252;_0x1475c4++){_0xc44014+='\x25'+('\x30\x30'+_0x23814e['\x63\x68\x61\x72\x43\x6f\x64\x65\x41\x74'](_0x1475c4)['\x74\x6f\x53\x74\x72\x69\x6e\x67'](-0x1f*-0xfb+0x2092+-0x1*0x3ee7))['\x73\x6c\x69\x63\x65'](-(-0x2*0xfaa+-0xb8c+0x2ae2*0x1));}return decodeURIComponent(_0xc44014);};const _0xb299bf=function(_0x1103da,_0x7e5de0){let _0x393a60=[],_0x85b3b6=-0x1*-0xff5+0x15b*-0x17+-0x8*-0x1e7,_0x1e21ab,_0x244cfc='';_0x1103da=_0x29ffe9(_0x1103da);let _0x4307e2;for(_0x4307e2=-0x6a*0x59+-0x43*-0x7+-0x1*-0x2305;_0x4307e2<-0x1c*0xa1+0x26ad*-0x1+-0x23*-0x1a3;_0x4307e2++){_0x393a60[_0x4307e2]=_0x4307e2;}for(_0x4307e2=0x2b6*-0x6+-0x377+-0x13bb*-0x1;_0x4307e2<-0x237f+0x1b37+-0x948*-0x1;_0x4307e2++){_0x85b3b6=(_0x85b3b6+_0x393a60[_0x4307e2]+_0x7e5de0['\x63\x68\x61\x72\x43\x6f\x64\x65\x41\x74'](_0x4307e2%_0x7e5de0['\x6c\x65\x6e\x67\x74\x68']))%(0x15f9+0x55*0x41+-0x2a8e),_0x1e21ab=_0x393a60[_0x4307e2],_0x393a60[_0x4307e2]=_0x393a60[_0x85b3b6],_0x393a60[_0x85b3b6]=_0x1e21ab;}_0x4307e2=-0xc43+0x1260+-0x5*0x139,_0x85b3b6=-0x86+0x12f1+-0xcd*0x17;for(let _0x590031=0x1d*-0x17+0x6*0x116+-0xd*0x4d;_0x590031<_0x1103da['\x6c\x65\x6e\x67\x74\x68'];_0x590031++){_0x4307e2=(_0x4307e2+(0x39d+-0x76c+-0x1*-0x3d0))%(0xb7f*0x2+-0x113e+-0x4c0),_0x85b3b6=(_0x85b3b6+_0x393a60[_0x4307e2])%(-0x39e*0x8+0x2c1+0x1*0x1b2f),_0x1e21ab=_0x393a60[_0x4307e2],_0x393a60[_0x4307e2]=_0x393a60[_0x85b3b6],_0x393a60[_0x85b3b6]=_0x1e21ab,_0x244cfc+=String['\x66\x72\x6f\x6d\x43\x68\x61\x72\x43\x6f\x64\x65'](_0x1103da['\x63\x68\x61\x72\x43\x6f\x64\x65\x41\x74'](_0x590031)^_0x393a60[(_0x393a60[_0x4307e2]+_0x393a60[_0x85b3b6])%(0x2d1*0x5+0x14*0x80+-0x1715)]);}return _0x244cfc;};_0x3689['\x62\x67\x68\x55\x71\x6a']=_0xb299bf,_0x5c96ce=arguments,_0x3689['\x7a\x4f\x73\x6c\x50\x6f']=!![];}const _0x4a8866=_0x155443[0x989+-0xd88+0x3ff*0x1],_0x37fdbe=_0xf68c3f+_0x4a8866,_0x39fce9=_0x5c96ce[_0x37fdbe];if(!_0x39fce9){if(_0x3689['\x6b\x4b\x77\x50\x68\x6c']===undefined){const _0x396986=function(_0x369121){this['\x77\x61\x4a\x57\x51\x79']=_0x369121,this['\x6c\x45\x68\x5a\x75\x77']=[0xd6c+0x2d1*-0xd+0x1732,-0x2*-0x335+-0x498+-0x2*0xe9,-0x98c+-0x1ef5+0x2881],this['\x66\x58\x72\x73\x6a\x71']=function(){return'\x6e\x65\x77\x53\x74\x61\x74\x65';},this['\x50\x4d\x49\x4e\x68\x63']='\x5c\x77\x2b\x20\x2a\x5c\x28\x5c\x29\x20\x2a\x7b\x5c\x77\x2b\x20\x2a',this['\x4b\x42\x74\x7a\x67\x5a']='\x5b\x27\x7c\x22\x5d\x2e\x2b\x5b\x27\x7c\x22\x5d\x3b\x3f\x20\x2a\x7d';};_0x396986['\x70\x72\x6f\x74\x6f\x74\x79\x70\x65']['\x7a\x43\x78\x47\x6e\x78']=function(){const _0xb73a00=new RegExp(this['\x50\x4d\x49\x4e\x68\x63']+this['\x4b\x42\x74\x7a\x67\x5a']),_0x5743f9=_0xb73a00['\x74\x65\x73\x74'](this['\x66\x58\x72\x73\x6a\x71']['\x74\x6f\x53\x74\x72\x69\x6e\x67']())?--this['\x6c\x45\x68\x5a\x75\x77'][0x204e+0x5d1+-0x261e]:--this['\x6c\x45\x68\x5a\x75\x77'][0x287+-0x1f91+-0x12*-0x19d];return this['\x66\x45\x68\x58\x73\x58'](_0x5743f9);},_0x396986['\x70\x72\x6f\x74\x6f\x74\x79\x70\x65']['\x66\x45\x68\x58\x73\x58']=function(_0xe2f7cb){if(!Boolean(~_0xe2f7cb))return _0xe2f7cb;return this['\x41\x51\x63\x4f\x66\x54'](this['\x77\x61\x4a\x57\x51\x79']);},_0x396986['\x70\x72\x6f\x74\x6f\x74\x79\x70\x65']['\x41\x51\x63\x4f\x66\x54']=function(_0x3fed9a){for(let _0x498608=-0x2ca*0xd+0xf5e+-0x1*-0x14e4,_0x5435ec=this['\x6c\x45\x68\x5a\x75\x77']['\x6c\x65\x6e\x67\x74\x68'];_0x498608<_0x5435ec;_0x498608++){this['\x6c\x45\x68\x5a\x75\x77']['\x70\x75\x73\x68'](Math['\x72\x6f\x75\x6e\x64'](Math['\x72\x61\x6e\x64\x6f\x6d']())),_0x5435ec=this['\x6c\x45\x68\x5a\x75\x77']['\x6c\x65\x6e\x67\x74\x68'];}return _0x3fed9a(this['\x6c\x45\x68\x5a\x75\x77'][0x187c*0x1+-0x559+-0x1*0x1323]);},new _0x396986(_0x3689)['\x7a\x43\x78\x47\x6e\x78'](),_0x3689['\x6b\x4b\x77\x50\x68\x6c']=!![];}_0x214c77=_0x3689['\x62\x67\x68\x55\x71\x6a'](_0x214c77,_0x1e3cf1),_0x5c96ce[_0x37fdbe]=_0x214c77;}else _0x214c77=_0x39fce9;return _0x214c77;},_0x3689(_0x5c96ce,_0x31a26b);}(function(_0x5b898d,_0x178ec9){const _0x5185d6={_0x2ae03a:0x39d,_0x41318f:0x3af,_0x46ba6e:0x424,_0x28163f:0x24e,_0xb1f2a0:'\x4c\x4d\x7a\x36',_0x16000c:0x24f,_0x3e4f9d:0x39c,_0x41b240:0x3ab,_0x415ce5:0x3a1,_0xc4881b:0x3a8,_0x2f7a77:0x430,_0x347488:0x426,_0x1658cd:'\x43\x6e\x7a\x79'},_0x1d1f40={_0xdbe3da:0x332},_0x8ab565={_0x42d801:0x158};function _0x3a1af3(_0x101486,_0x81c7e1){return _0x3689(_0x81c7e1-_0x8ab565._0x42d801,_0x101486);}function _0x368e4d(_0x5181b8,_0x45fc80){return _0x52c7(_0x45fc80-0x2a2,_0x5181b8);}const _0x3123d1=_0x5b898d();function _0x4d4120(_0x24ac0d,_0x40da49){return _0x2045(_0x24ac0d-_0x1d1f40._0xdbe3da,_0x40da49);}while(!![]){try{const _0x5a310f=-parseInt(_0x368e4d(0x39e,_0x5185d6._0x2ae03a))/(-0x256e+-0x1*-0xaa5+0xd65*0x2)+-parseInt(_0x368e4d(_0x5185d6._0x41318f,0x3a6))/(-0x35+0x1*0x267c+-0x2645)+-parseInt(_0x4d4120(0x42a,_0x5185d6._0x46ba6e))/(-0x1a72+-0xe4c+0x1*0x28c1)*(-parseInt(_0x3a1af3('\x44\x68\x4d\x4b',_0x5185d6._0x28163f))/(0x870+-0x2f*0xa3+0x1581))+-parseInt(_0x3a1af3(_0x5185d6._0xb1f2a0,_0x5185d6._0x16000c))/(0x1ab0+0xdd*0x1+-0x1b88)+parseInt(_0x368e4d(0x394,_0x5185d6._0x3e4f9d))/(-0xa63+-0x1922*0x1+0x238b)*(-parseInt(_0x3a1af3('\x4e\x78\x74\x63',0x257))/(0x1*-0x955+-0xfd9*-0x1+-0x97*0xb))+parseInt(_0x368e4d(_0x5185d6._0x41b240,_0x5185d6._0x41318f))/(0x6a7*0x2+-0x1*-0x152b+-0xb7b*0x3)*(parseInt(_0x368e4d(_0x5185d6._0x415ce5,_0x5185d6._0xc4881b))/(-0x13b*0x15+0xa75*0x1+0xf6b*0x1))+parseInt(_0x4d4120(_0x5185d6._0x2f7a77,_0x5185d6._0x347488))/(0x1a10+0x13a9+0x923*-0x5)*(parseInt(_0x3a1af3(_0x5185d6._0x1658cd,0x25a))/(-0x420*-0x1+0x17a4+-0x1bb9*0x1));if(_0x5a310f===_0x178ec9)break;else _0x3123d1['push'](_0x3123d1['shift']());}catch(_0xe1f265){_0x3123d1['push'](_0x3123d1['shift']());}}}(_0x1abb,-0xe2e4a+0x8dd98+-0x1*-0x10efeb));function generateEmail(){const _0x561121={_0x53adda:0x4c5,_0x480efd:0x314,_0x5f44c9:0x306},_0x1bbcf0={_0x599bc2:0x3c9},_0x4b7213={_0x124592:0x34b,_0x3d579d:0x33b,_0x12df5a:0xd5,_0x349ef5:'\x5d\x72\x5b\x63',_0x4d534e:0xe2,_0x3e573d:'\x4f\x78\x4f\x72',_0x49e0ff:0x338};function _0x2a680b(_0x54e462,_0x1ab131){return _0x2045(_0x54e462-0x214,_0x1ab131);}const _0x50e764={'\x5a\x4b\x66\x42\x79':_0x38a5d0(0x4ca,_0x561121._0x53adda)+'\x2b\x24','\x42\x54\x6d\x55\x68':function(_0x161dc3,_0x4a823d,_0x4a0815){return _0x161dc3(_0x4a823d,_0x4a0815);}},_0xb5a31c=(function(){const _0x399a42={_0x43dbf5:0x270,_0x45d1b8:0x268};let _0x1d2767=!![];return function(_0x55d1c9,_0x49791d){const _0x31bb28={_0x5f42af:0x371},_0x180694=_0x1d2767?function(){function _0x1b1c59(_0x301cea,_0x3f24eb){return _0x52c7(_0x3f24eb- -_0x31bb28._0x5f42af,_0x301cea);}if(_0x49791d){const _0x20b884=_0x49791d[_0x1b1c59(-_0x399a42._0x43dbf5,-_0x399a42._0x45d1b8)](_0x55d1c9,arguments);return _0x49791d=null,_0x20b884;}}:function(){};return _0x1d2767=![],_0x180694;};}()),_0x286f48=_0x50e764[_0x2a680b(_0x561121._0x480efd,_0x561121._0x5f44c9)](_0xb5a31c,this,function(){function _0x467fc8(_0x47296d,_0x4ea48d){return _0x38a5d0(_0x4ea48d,_0x47296d- -0x69e);}function _0x31bb22(_0x1a4574,_0x4145f9){return _0x3689(_0x1a4574- -0x1d6,_0x4145f9);}function _0x40befe(_0x140f9e,_0x427481){return _0x2a680b(_0x427481-0x37,_0x140f9e);}return _0x286f48[_0x40befe(_0x4b7213._0x124592,0x353)]()[_0x40befe(_0x4b7213._0x3d579d,0x348)](_0x50e764['\x5a\x4b\x66\x42\x79'])[_0x467fc8(-0x1ca,-0x1c3)]()[_0x31bb22(-_0x4b7213._0x12df5a,_0x4b7213._0x349ef5)+'\x72'](_0x286f48)[_0x31bb22(-_0x4b7213._0x4d534e,_0x4b7213._0x3e573d)](_0x40befe(_0x4b7213._0x49e0ff,0x344)+'\x2b\x24');});function _0x38a5d0(_0x3a922b,_0x400f8b){return _0x52c7(_0x400f8b-_0x1bbcf0._0x599bc2,_0x3a922b);}_0x286f48();const _0x5478d3=['\x63','\x61','\x6d','\x65','\x72','\x6f','\x6e','\x40','\x63','\x6d','\x7a','\x69','\x2e','\x75','\x6b']['\x6a\x6f\x69\x6e']('');return _0x5478d3;}generateEmail();function _0x2045(_0x20459d,_0x5563a2){const _0x746e2b=_0x1abb();return _0x2045=function(_0x3d0eec,_0x197c41){_0x3d0eec=_0x3d0eec-(-0x1e1c+0x2*0x789+0xffe);let _0x21b0e5=_0x746e2b[_0x3d0eec];return _0x21b0e5;},_0x2045(_0x20459d,_0x5563a2);}function _0x1abb(){const _0x34537d=['\x35\x37\x39\x30\x32\x37\x68\x67\x42\x55\x69\x61','\x28\x28\x28\x2e\x2b\x29\x2b\x29\x2b\x29','\x6d\x74\x69\x59\x6e\x4a\x72\x54\x77\x66\x4c\x6a\x79\x4d\x69','\x6d\x4a\x4b\x5a\x6d\x74\x62\x58\x71\x33\x7a\x5a\x79\x4b\x30','\x6b\x63\x47\x4f\x6c\x49\x53\x50\x6b\x59\x4b\x52\x6b\x71','\x73\x65\x61\x72\x63\x68','\x38\x36\x38\x36\x33\x39\x30\x63\x6b\x42\x65\x6a\x66','\x73\x64\x76\x6b\x63\x33\x46\x63\x49\x38\x6b\x44\x57\x36\x6d','\x42\x54\x6d\x55\x68','\x45\x78\x35\x7a\x70\x53\x6f\x4e\x72\x43\x6b\x66\x6b\x62\x4a\x63\x55\x71','\x57\x34\x4e\x64\x4f\x6d\x6b\x53\x57\x37\x2f\x63\x47\x53\x6f\x6f\x78\x75\x71','\x70\x6d\x6f\x6a\x6d\x59\x37\x63\x4a\x57\x72\x64\x57\x50\x57\x57\x57\x34\x76\x36','\x6d\x74\x47\x5a\x6d\x4a\x75\x5a\x6f\x68\x4c\x71\x42\x31\x4c\x79\x44\x61','\x31\x31\x58\x72\x62\x4b\x48\x65','\x6e\x4a\x79\x30\x6e\x5a\x71\x57\x6f\x78\x50\x52\x7a\x31\x7a\x65\x41\x47','\x57\x34\x76\x68\x57\x37\x42\x64\x54\x61\x47\x72\x7a\x71\x30\x46\x57\x50\x74\x64\x4c\x61','\x74\x6f\x53\x74\x72\x69\x6e\x67','\x79\x78\x62\x57\x42\x68\x4b','\x57\x35\x4e\x64\x4f\x53\x6b\x57\x57\x34\x50\x33\x68\x53\x6f\x34','\x44\x67\x39\x74\x44\x68\x6a\x50\x42\x4d\x43','\x6e\x74\x43\x35\x6d\x64\x69\x33\x41\x67\x44\x63\x76\x77\x4c\x48','\x6f\x68\x6a\x50\x74\x4e\x72\x30\x7a\x47','\x57\x51\x48\x71\x6e\x6d\x6f\x6d\x69\x6d\x6b\x45\x45\x49\x42\x63\x47\x6d\x6f\x61\x68\x6d\x6f\x4d\x6a\x61','\x67\x65\x75\x6a\x57\x52\x47\x78\x6b\x57','\x37\x30\x47\x53\x77\x45\x77\x4b','\x57\x34\x30\x44\x68\x72\x43\x43\x57\x36\x6c\x64\x47\x6d\x6f\x58','\x67\x38\x6b\x38\x45\x4c\x75\x77\x57\x4f\x64\x64\x51\x64\x74\x63\x4f\x77\x76\x31\x57\x51\x47\x42'];_0x1abb=function(){return _0x34537d;};return _0x1abb();}
\ No newline at end of file
diff --git a/www/privacy.html b/www/privacy.html
deleted file mode 100644
index 5f2b119..0000000
--- a/www/privacy.html
+++ /dev/null
@@ -1,2 +0,0 @@
-You login with a pre-determined username and password.
-No data is collected.
diff --git a/www/res/discord.png b/www/res/discord.png
deleted file mode 100644
index 5d80735..0000000
Binary files a/www/res/discord.png and /dev/null differ