diff --git a/.dockerignore b/.dockerignore
deleted file mode 100644
index 1cc91bb..0000000
--- a/.dockerignore
+++ /dev/null
@@ -1,47 +0,0 @@
-# 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
new file mode 100644
index 0000000..5f346e1
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,10 @@
+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
deleted file mode 100644
index d5ac2d5..0000000
--- a/.env.example
+++ /dev/null
@@ -1,8 +0,0 @@
-# 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 223f232..bada351 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:
- - turquoise
+ - main # Adjust if your main branch is different
tags:
- 'v*.*.*' # Trigger on version tags
@@ -26,6 +26,14 @@ 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
@@ -47,7 +55,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}', 'turquoise') }}
+ type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', 'main') }} # Adjust 'main' if needed
type=ref,event=branch
type=ref,event=tag
type=sha,format=short # Tag with short Git SHA
@@ -57,11 +65,11 @@ jobs:
org.opencontainers.image.revision=${{ github.sha }}
org.opencontainers.image.ref.name=${{ github.ref_name }}
- - name: Build and push minimal Docker image
+ - name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: .
- file: ./Dockerfile # Uses the Alpine-based minimal container
+ file: ./Dockerfile
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
new file mode 100644
index 0000000..6777c93
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1 @@
+/.yarn/** linguist-vendored
diff --git a/.gitignore b/.gitignore
index 4abe73e..af4cecd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,27 +1,5 @@
-# Logs
-logs
-*.log
-npm-debug.log*
-yarn-debug.log*
-yarn-error.log*
-pnpm-debug.log*
-lerna-debug.log*
-
node_modules
-dist
-dist-ssr
-*.local
+docker-compose.yml
-# Editor directories and files
-.vscode/*
-!.vscode/extensions.json
-.idea
-.DS_Store
-*.suo
-*.ntvs*
-*.njsproj
-*.sln
-*.sw?
-
-# Environment variables
-.env
+www/extra
+www/css/style.css
\ No newline at end of file
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
new file mode 100644
index 0000000..488032c
Binary files /dev/null and b/.yarn/cache/@alloc-quick-lru-npm-5.2.0-eb83517088-48e6d9607b.zip 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
new file mode 100644
index 0000000..eca199f
Binary files /dev/null and b/.yarn/cache/@isaacs-cliui-npm-8.0.2-f4364666d5-1b9b20d02b.zip 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
new file mode 100644
index 0000000..24d714f
Binary files /dev/null and b/.yarn/cache/@jridgewell-gen-mapping-npm-0.3.3-1815eba94c-3023bf63bc.zip 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
new file mode 100644
index 0000000..cf5c8e2
Binary files /dev/null and b/.yarn/cache/@jridgewell-resolve-uri-npm-3.1.1-aa2de3f210-874cf20998.zip 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
new file mode 100644
index 0000000..87d6da6
Binary files /dev/null and b/.yarn/cache/@jridgewell-set-array-npm-1.1.2-45b82d7fb6-1013d30769.zip 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
new file mode 100644
index 0000000..0d74194
Binary files /dev/null and b/.yarn/cache/@jridgewell-sourcemap-codec-npm-1.4.15-a055fb62cf-6d731b4d60.zip 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
new file mode 100644
index 0000000..f3101f4
Binary files /dev/null and b/.yarn/cache/@jridgewell-trace-mapping-npm-0.3.20-d90f282910-e719e9de55.zip 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
new file mode 100644
index 0000000..d74044f
Binary files /dev/null and b/.yarn/cache/@nodelib-fs.scandir-npm-2.1.5-89c67370dd-91b3de88d9.zip 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
new file mode 100644
index 0000000..47ba89a
Binary files /dev/null and b/.yarn/cache/@nodelib-fs.stat-npm-2.0.5-01f4dd3030-a4fcf7408f.zip 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
new file mode 100644
index 0000000..2c375e5
Binary files /dev/null and b/.yarn/cache/@nodelib-fs.walk-npm-1.2.8-b4a89da548-f7870cf3f1.zip 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
new file mode 100644
index 0000000..1156c88
Binary files /dev/null and b/.yarn/cache/@npmcli-agent-npm-2.2.0-cf04e8a830-87d91ddf05.zip 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
new file mode 100644
index 0000000..c5fd618
Binary files /dev/null and b/.yarn/cache/@npmcli-fs-npm-3.1.0-0844a57978-b96d3a91f6.zip 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
new file mode 100644
index 0000000..60d1547
Binary files /dev/null and b/.yarn/cache/@pkgjs-parseargs-npm-0.11.0-cd2a3fe948-dfe6befa02.zip 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
new file mode 100644
index 0000000..62b6e68
Binary files /dev/null and b/.yarn/cache/abbrev-npm-2.0.0-0eb38a17e5-a82907e52c.zip 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
new file mode 100644
index 0000000..19d93f4
Binary files /dev/null and b/.yarn/cache/agent-base-npm-7.1.0-4b12ba5111-e80384a4b4.zip 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
new file mode 100644
index 0000000..a616171
Binary files /dev/null and b/.yarn/cache/aggregate-error-npm-3.1.0-415a406f4e-704d2001a3.zip 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
new file mode 100644
index 0000000..a0e7204
Binary files /dev/null and b/.yarn/cache/ansi-regex-npm-5.0.1-c963a48615-c944e1229f.zip 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
new file mode 100644
index 0000000..da215e6
Binary files /dev/null and b/.yarn/cache/ansi-regex-npm-6.0.1-8d663a607d-5a4e4cd709.zip 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
new file mode 100644
index 0000000..909670c
Binary files /dev/null and b/.yarn/cache/ansi-styles-npm-4.3.0-245c7d42c7-ea02c0179f.zip 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
new file mode 100644
index 0000000..13c7f3c
Binary files /dev/null and b/.yarn/cache/ansi-styles-npm-6.2.1-d43647018c-285ec4b6dc.zip 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
new file mode 100644
index 0000000..23093fd
Binary files /dev/null and b/.yarn/cache/any-promise-npm-1.3.0-f34eeaa7e7-e829425e4a.zip 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
new file mode 100644
index 0000000..cb53e17
Binary files /dev/null and b/.yarn/cache/anymatch-npm-3.1.3-bc81d103b1-7191d13e13.zip 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
new file mode 100644
index 0000000..d945284
Binary files /dev/null and b/.yarn/cache/arg-npm-5.0.2-2f5805a547-2fe52bbdfa.zip 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
new file mode 100644
index 0000000..cf4290e
Binary files /dev/null and b/.yarn/cache/balanced-match-npm-1.0.2-a53c126459-690643f300.zip 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
new file mode 100644
index 0000000..f748daf
Binary files /dev/null and b/.yarn/cache/binary-extensions-npm-2.2.0-180c33fec7-0f5f5685f3.zip 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
new file mode 100644
index 0000000..67819e1
Binary files /dev/null and b/.yarn/cache/brace-expansion-npm-1.1.11-fb95eb05ad-4c878e25e4.zip 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
new file mode 100644
index 0000000..eb60682
Binary files /dev/null and b/.yarn/cache/brace-expansion-npm-2.0.1-17aa2616f9-c499787968.zip 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
new file mode 100644
index 0000000..9f5e780
Binary files /dev/null and b/.yarn/cache/braces-npm-3.0.2-782240b28a-f3493181c3.zip 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
new file mode 100644
index 0000000..87626ae
Binary files /dev/null and b/.yarn/cache/cacache-npm-18.0.0-32582cfebc-1c3947050d.zip 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
new file mode 100644
index 0000000..f4c7b43
Binary files /dev/null and b/.yarn/cache/camelcase-css-npm-2.0.1-90d1b6df08-3d557da914.zip 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
new file mode 100644
index 0000000..39598f1
Binary files /dev/null and b/.yarn/cache/chokidar-npm-3.5.3-c5f9b0a56a-ea6636f22d.zip 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
new file mode 100644
index 0000000..5b643d7
Binary files /dev/null and b/.yarn/cache/chownr-npm-2.0.0-638f1c9c61-b06ba0bf42.zip 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
new file mode 100644
index 0000000..8fabe8f
Binary files /dev/null and b/.yarn/cache/clean-stack-npm-2.2.0-a8ce435a5c-e291ce2b8c.zip 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
new file mode 100644
index 0000000..c5520e7
Binary files /dev/null and b/.yarn/cache/color-convert-npm-2.0.1-79730e935b-3d5d8a011a.zip 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
new file mode 100644
index 0000000..62ad58d
Binary files /dev/null and b/.yarn/cache/color-name-npm-1.1.4-025792b0ea-3e1c9a4dee.zip 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
new file mode 100644
index 0000000..dea96a9
Binary files /dev/null and b/.yarn/cache/commander-npm-4.1.1-22a0fe921b-448585071b.zip 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
new file mode 100644
index 0000000..dd651d0
Binary files /dev/null and b/.yarn/cache/concat-map-npm-0.0.1-85a921b7ee-554e28d9ee.zip 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
new file mode 100644
index 0000000..e74d069
Binary files /dev/null and b/.yarn/cache/cross-spawn-npm-7.0.3-e4ff3e65b3-51f10036f5.zip 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
new file mode 100644
index 0000000..a6c0288
Binary files /dev/null and b/.yarn/cache/cssesc-npm-3.0.0-15ec56f86f-673783eda1.zip 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
new file mode 100644
index 0000000..22cf2c6
Binary files /dev/null and b/.yarn/cache/debug-npm-4.3.4-4513954577-7d71c93be2.zip 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
new file mode 100644
index 0000000..6487bee
Binary files /dev/null and b/.yarn/cache/didyoumean-npm-1.2.2-fd568ec571-808a1e4855.zip 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
new file mode 100644
index 0000000..fddbfd1
Binary files /dev/null and b/.yarn/cache/dlv-npm-1.1.3-187c903a21-3ed2cd5054.zip 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
new file mode 100644
index 0000000..f7cd95f
Binary files /dev/null and b/.yarn/cache/eastasianwidth-npm-0.2.0-c37eb16bd1-436391b865.zip 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
new file mode 100644
index 0000000..37a8db7
Binary files /dev/null and b/.yarn/cache/emoji-regex-npm-8.0.0-213764015c-87cf3f89ef.zip 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
new file mode 100644
index 0000000..8752d8b
Binary files /dev/null and b/.yarn/cache/emoji-regex-npm-9.2.2-e6fac8d058-f3029ec432.zip 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
new file mode 100644
index 0000000..69ce31a
Binary files /dev/null and b/.yarn/cache/encoding-npm-0.1.13-82a1837d30-282d5696a4.zip 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
new file mode 100644
index 0000000..982ed60
Binary files /dev/null and b/.yarn/cache/env-paths-npm-2.2.1-7c7577428c-9579868bc7.zip 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
new file mode 100644
index 0000000..0a1f588
Binary files /dev/null and b/.yarn/cache/err-code-npm-2.0.3-082e0ff9a7-14e09e9990.zip 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
new file mode 100644
index 0000000..1aa0130
Binary files /dev/null and b/.yarn/cache/exponential-backoff-npm-3.1.1-04df458b30-369725ac55.zip 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
new file mode 100644
index 0000000..8d8450d
Binary files /dev/null and b/.yarn/cache/fast-glob-npm-3.3.2-0a8cb4f2ca-76c8f75492.zip 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
new file mode 100644
index 0000000..6b90aa5
Binary files /dev/null and b/.yarn/cache/fastq-npm-1.15.0-1013f6514e-fe2a63a4d6.zip 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
new file mode 100644
index 0000000..3ef9993
Binary files /dev/null and b/.yarn/cache/fill-range-npm-7.0.1-b8b1817caa-efca43d59b.zip 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
new file mode 100644
index 0000000..6ec2faf
Binary files /dev/null and b/.yarn/cache/foreground-child-npm-3.1.1-77e78ed774-8b7a1db35a.zip 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
new file mode 100644
index 0000000..77b7a6c
Binary files /dev/null and b/.yarn/cache/fs-minipass-npm-2.1.0-501ef87306-e14a490658.zip 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
new file mode 100644
index 0000000..b167702
Binary files /dev/null and b/.yarn/cache/fs-minipass-npm-3.0.3-d148d6ac19-28f0078906.zip 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
new file mode 100644
index 0000000..fb74b58
Binary files /dev/null and b/.yarn/cache/fs.realpath-npm-1.0.0-c8f05d8126-698a91b169.zip 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
new file mode 100644
index 0000000..0a430fb
Binary files /dev/null and b/.yarn/cache/fsevents-npm-2.3.3-ce9fb0ffae-f22d0a854b.zip differ
diff --git a/.yarn/cache/fsevents-patch-8036bb578f-b4a5cd7915.zip b/.yarn/cache/fsevents-patch-8036bb578f-b4a5cd7915.zip
new file mode 100644
index 0000000..06cfa4b
Binary files /dev/null and b/.yarn/cache/fsevents-patch-8036bb578f-b4a5cd7915.zip 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
new file mode 100644
index 0000000..87767a5
Binary files /dev/null and b/.yarn/cache/function-bind-npm-1.1.2-7a55be9b03-0d0c3d1dbe.zip 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
new file mode 100644
index 0000000..2b4bbe8
Binary files /dev/null and b/.yarn/cache/glob-npm-10.3.10-da1ef8b112-07706025e0.zip 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
new file mode 100644
index 0000000..aa99358
Binary files /dev/null and b/.yarn/cache/glob-npm-7.1.6-1ce3a5189a-789977b524.zip 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
new file mode 100644
index 0000000..646a5a7
Binary files /dev/null and b/.yarn/cache/glob-parent-npm-5.1.2-021ab32634-82fcaa4ce1.zip 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
new file mode 100644
index 0000000..b39b34e
Binary files /dev/null and b/.yarn/cache/glob-parent-npm-6.0.2-2cbef12738-226293dc9d.zip 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
new file mode 100644
index 0000000..fd7f50f
Binary files /dev/null and b/.yarn/cache/graceful-fs-npm-4.2.11-24bb648a68-99533f7c73.zip 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
new file mode 100644
index 0000000..8732d2c
Binary files /dev/null and b/.yarn/cache/hasown-npm-2.0.0-78b794ceef-5d9c0e10b4.zip 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
new file mode 100644
index 0000000..1f122b1
Binary files /dev/null and b/.yarn/cache/http-cache-semantics-npm-4.1.1-1120131375-ea193328de.zip 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
new file mode 100644
index 0000000..fa416d1
Binary files /dev/null and b/.yarn/cache/http-proxy-agent-npm-7.0.0-106a57cc8c-bc12e49a3b.zip 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
new file mode 100644
index 0000000..e164fcb
Binary files /dev/null and b/.yarn/cache/https-proxy-agent-npm-7.0.2-83ea6a5d42-607c61a4c9.zip 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
new file mode 100644
index 0000000..5e543a5
Binary files /dev/null and b/.yarn/cache/iconv-lite-npm-0.6.3-24b8aae27e-9b4f24db66.zip 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
new file mode 100644
index 0000000..e9c177b
Binary files /dev/null and b/.yarn/cache/imurmurhash-npm-0.1.4-610c5068a0-34d414d789.zip 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
new file mode 100644
index 0000000..9dfd833
Binary files /dev/null and b/.yarn/cache/indent-string-npm-4.0.0-7b717435b2-3e54996c6e.zip 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
new file mode 100644
index 0000000..8b43e84
Binary files /dev/null and b/.yarn/cache/inflight-npm-1.0.6-ccedb4b908-17c53fc42c.zip 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
new file mode 100644
index 0000000..fd9d5ae
Binary files /dev/null and b/.yarn/cache/inherits-npm-2.0.4-c66b3957a0-98426da247.zip 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
new file mode 100644
index 0000000..027b5e2
Binary files /dev/null and b/.yarn/cache/ip-npm-2.0.0-204facb3cc-046f0487ff.zip 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
new file mode 100644
index 0000000..e599d38
Binary files /dev/null and b/.yarn/cache/is-binary-path-npm-2.1.0-e61d46f557-49a1446a3c.zip 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
new file mode 100644
index 0000000..bdff56c
Binary files /dev/null and b/.yarn/cache/is-core-module-npm-2.13.1-36e17434f9-a19e63cd9a.zip 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
new file mode 100644
index 0000000..502658e
Binary files /dev/null and b/.yarn/cache/is-extglob-npm-2.1.1-0870ea68b5-ca623e2c56.zip 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
new file mode 100644
index 0000000..b81f8cf
Binary files /dev/null and b/.yarn/cache/is-fullwidth-code-point-npm-3.0.0-1ecf4ebee5-a01a19ecac.zip 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
new file mode 100644
index 0000000..005921b
Binary files /dev/null and b/.yarn/cache/is-glob-npm-4.0.3-cb87bf1bdb-8f6b4c42b7.zip 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
new file mode 100644
index 0000000..3a00275
Binary files /dev/null and b/.yarn/cache/is-lambda-npm-1.0.1-7ab55bc8a8-669ea37e8f.zip 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
new file mode 100644
index 0000000..0234594
Binary files /dev/null and b/.yarn/cache/is-number-npm-7.0.0-060086935c-eec6e506c6.zip 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
new file mode 100644
index 0000000..b7bb40b
Binary files /dev/null and b/.yarn/cache/isexe-npm-2.0.0-b58870bd2e-7b437980bb.zip 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
new file mode 100644
index 0000000..5280eb1
Binary files /dev/null and b/.yarn/cache/isexe-npm-3.1.1-9c0061eead-9220579164.zip 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
new file mode 100644
index 0000000..e338bfa
Binary files /dev/null and b/.yarn/cache/jackspeak-npm-2.3.6-42e1233172-4e1113feef.zip 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
new file mode 100644
index 0000000..a65029b
Binary files /dev/null and b/.yarn/cache/jiti-npm-1.21.0-baebd5985a-6dda596de2.zip 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
new file mode 100644
index 0000000..9557b5d
Binary files /dev/null and b/.yarn/cache/lilconfig-npm-2.1.0-a179261924-8a6e47a6ad.zip 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
new file mode 100644
index 0000000..b4298d3
Binary files /dev/null and b/.yarn/cache/lilconfig-npm-3.0.0-6931a31ed7-927fff6d2a.zip 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
new file mode 100644
index 0000000..08cbb94
Binary files /dev/null and b/.yarn/cache/lines-and-columns-npm-1.2.4-d6c7cc5799-a1d22dcb6f.zip 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
new file mode 100644
index 0000000..92a65ad
Binary files /dev/null and b/.yarn/cache/lru-cache-npm-10.0.3-1c2f93d565-7e46eaebd1.zip 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
new file mode 100644
index 0000000..e0ac235
Binary files /dev/null and b/.yarn/cache/lru-cache-npm-6.0.0-b4c8668fe1-b8b78353d2.zip 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
new file mode 100644
index 0000000..51e2aac
Binary files /dev/null and b/.yarn/cache/make-fetch-happen-npm-13.0.0-f87a92bb87-08ed8f6464.zip 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
new file mode 100644
index 0000000..ae8944e
Binary files /dev/null and b/.yarn/cache/merge2-npm-1.4.1-a2507bd06c-7ad40d8b14.zip 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
new file mode 100644
index 0000000..9844b63
Binary files /dev/null and b/.yarn/cache/micromatch-npm-4.0.5-cfab5d7669-af3dc46b9d.zip 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
new file mode 100644
index 0000000..78f277a
Binary files /dev/null and b/.yarn/cache/minimatch-npm-3.1.2-9405269906-1a7584a6de.zip 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
new file mode 100644
index 0000000..6248036
Binary files /dev/null and b/.yarn/cache/minimatch-npm-9.0.3-69d7d6fad5-fb6dc6e08f.zip 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
new file mode 100644
index 0000000..28646fa
Binary files /dev/null and b/.yarn/cache/minipass-collect-npm-1.0.2-3b4676eab5-529ef62123.zip 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
new file mode 100644
index 0000000..94f1f1a
Binary files /dev/null and b/.yarn/cache/minipass-fetch-npm-3.0.4-200ac7c66d-920b4b454a.zip 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
new file mode 100644
index 0000000..bcc49f5
Binary files /dev/null and b/.yarn/cache/minipass-flush-npm-1.0.5-efe79d9826-d354ca0da8.zip 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
new file mode 100644
index 0000000..705882d
Binary files /dev/null and b/.yarn/cache/minipass-npm-3.3.6-b8d93a945b-3cc3a75860.zip 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
new file mode 100644
index 0000000..b07b099
Binary files /dev/null and b/.yarn/cache/minipass-npm-5.0.0-c64fb63c92-f9d89ca516.zip 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
new file mode 100644
index 0000000..ad8e9aa
Binary files /dev/null and b/.yarn/cache/minipass-npm-7.0.4-eacb4e042e-27e7007235.zip 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
new file mode 100644
index 0000000..a9396f6
Binary files /dev/null and b/.yarn/cache/minipass-pipeline-npm-1.2.4-5924cb077f-001d5a4a0c.zip 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
new file mode 100644
index 0000000..27486e6
Binary files /dev/null and b/.yarn/cache/minipass-sized-npm-1.0.3-306d86f432-747cb22e8a.zip 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
new file mode 100644
index 0000000..b15a5fc
Binary files /dev/null and b/.yarn/cache/minizlib-npm-2.1.2-ea89cd0cfb-5a45b57b34.zip 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
new file mode 100644
index 0000000..4d2896d
Binary files /dev/null and b/.yarn/cache/mkdirp-npm-1.0.4-37f6ef56b9-1aa3a6a2d7.zip 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
new file mode 100644
index 0000000..c4fe244
Binary files /dev/null and b/.yarn/cache/ms-npm-2.1.2-ec0c1512ff-9b65fb709b.zip 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
new file mode 100644
index 0000000..82234e1
Binary files /dev/null and b/.yarn/cache/mz-npm-2.7.0-ec3cef4ec2-063966dd8e.zip 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
new file mode 100644
index 0000000..059d7cf
Binary files /dev/null and b/.yarn/cache/nanoid-npm-3.3.7-98824ba130-cf385d8457.zip 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
new file mode 100644
index 0000000..a533027
Binary files /dev/null and b/.yarn/cache/negotiator-npm-0.6.3-9d50e36171-5899e1bf5c.zip 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
new file mode 100644
index 0000000..06ca2c4
Binary files /dev/null and b/.yarn/cache/node-gyp-npm-10.0.1-48708ce70b-7b92a3c50c.zip 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
new file mode 100644
index 0000000..c0bb6e6
Binary files /dev/null and b/.yarn/cache/nopt-npm-7.2.0-dd734b678d-1ee27d90ba.zip 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
new file mode 100644
index 0000000..8d5e845
Binary files /dev/null and b/.yarn/cache/normalize-path-npm-3.0.0-658ba7d77f-215a701b47.zip 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
new file mode 100644
index 0000000..e4ce2e1
Binary files /dev/null and b/.yarn/cache/object-assign-npm-4.1.1-1004ad6dec-66cf021898.zip 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
new file mode 100644
index 0000000..fa61c0d
Binary files /dev/null and b/.yarn/cache/object-hash-npm-3.0.0-d941e0cabe-f12c80d588.zip 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
new file mode 100644
index 0000000..14dee7d
Binary files /dev/null and b/.yarn/cache/once-npm-1.4.0-ccf03ef07a-57afc24653.zip 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
new file mode 100644
index 0000000..dbc9626
Binary files /dev/null and b/.yarn/cache/p-map-npm-4.0.0-4677ae07c7-d51e630d72.zip 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
new file mode 100644
index 0000000..42f2376
Binary files /dev/null and b/.yarn/cache/path-is-absolute-npm-1.0.1-31bc695ffd-907e1e3e6a.zip 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
new file mode 100644
index 0000000..28ec147
Binary files /dev/null and b/.yarn/cache/path-key-npm-3.1.1-0e66ea8321-e44aa3ca9f.zip 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
new file mode 100644
index 0000000..cb35624
Binary files /dev/null and b/.yarn/cache/path-parse-npm-1.0.7-09564527b7-6de0bfa37b.zip 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
new file mode 100644
index 0000000..d434688
Binary files /dev/null and b/.yarn/cache/path-scurry-npm-1.10.1-52bd946f2e-7a2ca28cda.zip 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
new file mode 100644
index 0000000..2bb490e
Binary files /dev/null and b/.yarn/cache/picocolors-npm-1.0.0-d81e0b1927-6616d34dd0.zip 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
new file mode 100644
index 0000000..b962307
Binary files /dev/null and b/.yarn/cache/picomatch-npm-2.3.1-c782cfd986-5e3bbbf6a7.zip 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
new file mode 100644
index 0000000..d6a8926
Binary files /dev/null and b/.yarn/cache/pify-npm-2.3.0-8b63310934-d5758aa570.zip 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
new file mode 100644
index 0000000..1ec0444
Binary files /dev/null and b/.yarn/cache/pirates-npm-4.0.6-a8ec571a43-1c8546420a.zip 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
new file mode 100644
index 0000000..aab2cae
Binary files /dev/null and b/.yarn/cache/postcss-import-npm-15.1.0-8b9e86f900-234c4d23eb.zip 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
new file mode 100644
index 0000000..a4665e9
Binary files /dev/null and b/.yarn/cache/postcss-js-npm-4.0.1-2c4ee70bf3-9991f86f05.zip 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
new file mode 100644
index 0000000..90970d0
Binary files /dev/null and b/.yarn/cache/postcss-load-config-npm-4.0.2-319bcff9ca-efbe2cf7bd.zip 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
new file mode 100644
index 0000000..4da892d
Binary files /dev/null and b/.yarn/cache/postcss-nested-npm-6.0.1-5cdc427fe8-287630cd56.zip 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
new file mode 100644
index 0000000..959b9c8
Binary files /dev/null and b/.yarn/cache/postcss-npm-8.4.31-385051a82b-dac8611c6d.zip 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
new file mode 100644
index 0000000..d7efaa3
Binary files /dev/null and b/.yarn/cache/postcss-selector-parser-npm-6.0.13-f732d92326-556a437939.zip 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
new file mode 100644
index 0000000..236a4a5
Binary files /dev/null and b/.yarn/cache/postcss-value-parser-npm-4.2.0-3cef602a6a-9f66285b98.zip 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
new file mode 100644
index 0000000..f4db796
Binary files /dev/null and b/.yarn/cache/proc-log-npm-3.0.0-a8c21c2f0f-f1e721cbbb.zip 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
new file mode 100644
index 0000000..dd2b04f
Binary files /dev/null and b/.yarn/cache/promise-retry-npm-2.0.1-871f0b01b7-325e99d059.zip 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
new file mode 100644
index 0000000..1809973
Binary files /dev/null and b/.yarn/cache/queue-microtask-npm-1.2.3-fcc98e4e2d-0f88d794d4.zip 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
new file mode 100644
index 0000000..f2d0731
Binary files /dev/null and b/.yarn/cache/read-cache-npm-1.0.0-00fa89ed05-17a1996977.zip 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
new file mode 100644
index 0000000..973cfd1
Binary files /dev/null and b/.yarn/cache/readdirp-npm-3.6.0-f950cc74ab-7da2fe8d5a.zip 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
new file mode 100644
index 0000000..5ff3589
Binary files /dev/null and b/.yarn/cache/resolve-npm-1.22.8-098f379dfe-87b03ea191.zip differ
diff --git a/.yarn/cache/resolve-patch-6ba30f2f2c-798a84fbca.zip b/.yarn/cache/resolve-patch-6ba30f2f2c-798a84fbca.zip
new file mode 100644
index 0000000..14ca4f7
Binary files /dev/null and b/.yarn/cache/resolve-patch-6ba30f2f2c-798a84fbca.zip 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
new file mode 100644
index 0000000..562b651
Binary files /dev/null and b/.yarn/cache/retry-npm-0.12.0-72ac7fb4cc-51f2fddddb.zip 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
new file mode 100644
index 0000000..cd80993
Binary files /dev/null and b/.yarn/cache/reusify-npm-1.0.4-95ac4aec11-08ef02ed05.zip 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
new file mode 100644
index 0000000..aa7c07c
Binary files /dev/null and b/.yarn/cache/run-parallel-npm-1.2.0-3f47ff2034-3d12f0251a.zip 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
new file mode 100644
index 0000000..e120db3
Binary files /dev/null and b/.yarn/cache/safer-buffer-npm-2.1.2-8d5c0b705e-549ba83f5b.zip 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
new file mode 100644
index 0000000..0cf952c
Binary files /dev/null and b/.yarn/cache/semver-npm-7.5.4-c4ad957fcd-9bc02fd8e2.zip 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
new file mode 100644
index 0000000..5dbbd04
Binary files /dev/null and b/.yarn/cache/shebang-command-npm-2.0.0-eb2b01921d-85aa394d8c.zip 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
new file mode 100644
index 0000000..6b227ae
Binary files /dev/null and b/.yarn/cache/shebang-regex-npm-3.0.0-899a0cd65e-ea18044ffa.zip 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
new file mode 100644
index 0000000..dd170f5
Binary files /dev/null and b/.yarn/cache/signal-exit-npm-4.1.0-61fb957687-a9175b0697.zip 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
new file mode 100644
index 0000000..ca86502
Binary files /dev/null and b/.yarn/cache/smart-buffer-npm-4.2.0-5ac3f668bb-644e012e31.zip 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
new file mode 100644
index 0000000..1245644
Binary files /dev/null and b/.yarn/cache/socks-npm-2.7.1-17f2b53052-412b254d32.zip 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
new file mode 100644
index 0000000..303f2c9
Binary files /dev/null and b/.yarn/cache/socks-proxy-agent-npm-8.0.2-df165543cf-3ff2970563.zip 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
new file mode 100644
index 0000000..c2a6ff1
Binary files /dev/null and b/.yarn/cache/source-map-js-npm-1.0.2-ee4f9f9b30-3bb232796a.zip 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
new file mode 100644
index 0000000..ed9b4a0
Binary files /dev/null and b/.yarn/cache/ssri-npm-10.0.5-1a7557d04d-3d1f6a4aa5.zip 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
new file mode 100644
index 0000000..f5c9c6d
Binary files /dev/null and b/.yarn/cache/string-width-npm-4.2.3-2c27177bae-748c979889.zip 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
new file mode 100644
index 0000000..bd90081
Binary files /dev/null and b/.yarn/cache/string-width-npm-5.1.2-bf60531341-4da7e3d5d6.zip 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
new file mode 100644
index 0000000..4321145
Binary files /dev/null and b/.yarn/cache/strip-ansi-npm-6.0.1-caddc7cb40-9d3061240b.zip 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
new file mode 100644
index 0000000..7554c12
Binary files /dev/null and b/.yarn/cache/strip-ansi-npm-7.1.0-7453b80b79-23e0a12a07.zip 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
new file mode 100644
index 0000000..d6ebf98
Binary files /dev/null and b/.yarn/cache/sucrase-npm-3.34.0-434160cdf2-b04543bc2c.zip 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
new file mode 100644
index 0000000..58bb4f6
Binary files /dev/null and b/.yarn/cache/supports-preserve-symlinks-flag-npm-1.0.0-f17c4d0028-a0f3140423.zip 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
new file mode 100644
index 0000000..c4c0f6b
Binary files /dev/null and b/.yarn/cache/tailwindcss-npm-3.3.5-a3fffa234c-655b7b26d2.zip 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
new file mode 100644
index 0000000..20ab1a3
Binary files /dev/null and b/.yarn/cache/tar-npm-6.2.0-3eb25205a7-5f68e53e31.zip 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
new file mode 100644
index 0000000..1eb1e3a
Binary files /dev/null and b/.yarn/cache/thenify-all-npm-1.6.0-96309bbc8b-22775c13a1.zip 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
new file mode 100644
index 0000000..86d5007
Binary files /dev/null and b/.yarn/cache/thenify-npm-3.3.1-030bedb22c-c3cbda4f5f.zip 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
new file mode 100644
index 0000000..933c228
Binary files /dev/null and b/.yarn/cache/to-regex-range-npm-5.0.1-f1e8263b00-2b6001e314.zip 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
new file mode 100644
index 0000000..296df54
Binary files /dev/null and b/.yarn/cache/ts-interface-checker-npm-0.1.13-0c7b064494-df3e240963.zip 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
new file mode 100644
index 0000000..0303147
Binary files /dev/null and b/.yarn/cache/unique-filename-npm-3.0.0-77d68e0a45-9310efd64c.zip 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
new file mode 100644
index 0000000..f1cf9da
Binary files /dev/null and b/.yarn/cache/unique-slug-npm-4.0.0-e6b08f28aa-aabf6e1d22.zip 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
new file mode 100644
index 0000000..237a2ff
Binary files /dev/null and b/.yarn/cache/util-deprecate-npm-1.0.2-e3fe1a219c-73c2b1cf02.zip 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
new file mode 100644
index 0000000..2e9d763
Binary files /dev/null and b/.yarn/cache/which-npm-2.0.2-320ddf72f7-ea9b1db126.zip 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
new file mode 100644
index 0000000..7daf2f0
Binary files /dev/null and b/.yarn/cache/which-npm-4.0.0-dd31cd4928-143a8b3d74.zip 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
new file mode 100644
index 0000000..cbe3a0d
Binary files /dev/null and b/.yarn/cache/wrap-ansi-npm-7.0.0-ad6e1a0554-09939dd775.zip 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
new file mode 100644
index 0000000..92be2a2
Binary files /dev/null and b/.yarn/cache/wrap-ansi-npm-8.1.0-26a4e6ae28-f75c2443bd.zip 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
new file mode 100644
index 0000000..fb3bf59
Binary files /dev/null and b/.yarn/cache/wrappy-npm-1.0.2-916de4d4b3-519fcda0fc.zip 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
new file mode 100644
index 0000000..ef0d9e2
Binary files /dev/null and b/.yarn/cache/yallist-npm-4.0.0-b493d9e907-a2960ef879.zip 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
new file mode 100644
index 0000000..ea47b2a
Binary files /dev/null and b/.yarn/cache/yaml-npm-2.3.4-8bb6dc2c0d-c5f378790e.zip differ
diff --git a/Dockerfile b/Dockerfile
index b387eee..d521c19 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,35 +1,11 @@
-# Build stage
-FROM oven/bun:latest as builder
+FROM nginx:latest
-WORKDIR /app
+COPY www /usr/share/nginx/html
+COPY entrypoint.sh /entrypoint.sh
-# Copy package files
-COPY package.json bun.lock* ./
+RUN chmod +x /entrypoint.sh
-# Install all dependencies (including devDependencies for building)
-RUN bun install --frozen-lockfile
+ENTRYPOINT ["/entrypoint.sh"]
-# 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"]
+STOPSIGNAL SIGQUIT
+CMD ["nginx", "-g", "daemon off;"]
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..369177c
--- /dev/null
+++ b/README.md
@@ -0,0 +1 @@
+# public
diff --git a/bun.lock b/bun.lock
deleted file mode 100644
index 2b9d8dc..0000000
--- a/bun.lock
+++ /dev/null
@@ -1,406 +0,0 @@
-{
- "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
new file mode 100644
index 0000000..e25a903
--- /dev/null
+++ b/entrypoint.sh
@@ -0,0 +1,54 @@
+#!/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
deleted file mode 100644
index b4234e0..0000000
--- a/index.html
+++ /dev/null
@@ -1,191 +0,0 @@
-
-
-
-
-
-
- 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 1b4bf8e..230fca8 100644
--- a/package.json
+++ b/package.json
@@ -1,35 +1,10 @@
{
- "name": "homepage",
- "private": true,
- "version": "0.0.0",
- "type": "module",
- "scripts": {
- "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"
- },
+ "name": "public",
"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"
+ "tailwindcss": "^3.4.17"
},
- "trustedDependencies": [
- "@tailwindcss/oxide"
- ]
+ "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"
+ }
}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
new file mode 100644
index 0000000..2b20b9b
--- /dev/null
+++ b/pnpm-lock.yaml
@@ -0,0 +1,837 @@
+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
deleted file mode 100644
index 746388b..0000000
Binary files a/public/apple-touch-icon.png and /dev/null differ
diff --git a/public/avatar.webp b/public/avatar.webp
deleted file mode 100644
index 15032e3..0000000
Binary files a/public/avatar.webp and /dev/null differ
diff --git a/public/favicon-96x96.png b/public/favicon-96x96.png
deleted file mode 100644
index 3f37d9c..0000000
Binary files a/public/favicon-96x96.png and /dev/null differ
diff --git a/public/favicon.ico b/public/favicon.ico
deleted file mode 100644
index 892eaeb..0000000
Binary files a/public/favicon.ico and /dev/null differ
diff --git a/public/favicon.svg b/public/favicon.svg
deleted file mode 100644
index fe1cdbd..0000000
--- a/public/favicon.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/public/site.webmanifest b/public/site.webmanifest
deleted file mode 100644
index fcc13c3..0000000
--- a/public/site.webmanifest
+++ /dev/null
@@ -1,21 +0,0 @@
-{
- "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
deleted file mode 100644
index d99e43d..0000000
Binary files a/public/web-app-manifest-192x192.png and /dev/null differ
diff --git a/public/web-app-manifest-512x512.png b/public/web-app-manifest-512x512.png
deleted file mode 100644
index b110a12..0000000
Binary files a/public/web-app-manifest-512x512.png and /dev/null differ
diff --git a/src/client.ts b/src/client.ts
deleted file mode 100644
index 46813de..0000000
--- a/src/client.ts
+++ /dev/null
@@ -1,329 +0,0 @@
-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
deleted file mode 100644
index 8bec9d5..0000000
--- a/src/gameoflife.ts
+++ /dev/null
@@ -1,573 +0,0 @@
-// 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
deleted file mode 100644
index ce69554..0000000
--- a/src/server.ts
+++ /dev/null
@@ -1,175 +0,0 @@
-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
deleted file mode 100644
index a5468ee..0000000
--- a/src/style.css
+++ /dev/null
@@ -1,303 +0,0 @@
-@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
new file mode 100644
index 0000000..7cd1abf
--- /dev/null
+++ b/tailwind.config.js
@@ -0,0 +1,10 @@
+/** @type {import('tailwindcss').Config} */
+module.exports = {
+ content: ["./www/**/*.{html,js}"],
+ theme: {
+ darkMode: 'media',
+ extend: {},
+ },
+ plugins: [],
+}
+
diff --git a/tsconfig.json b/tsconfig.json
deleted file mode 100644
index 1bf46ff..0000000
--- a/tsconfig.json
+++ /dev/null
@@ -1,21 +0,0 @@
-{
- "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
deleted file mode 100644
index 6959824..0000000
--- a/vite.config.js
+++ /dev/null
@@ -1,28 +0,0 @@
-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
new file mode 100644
index 0000000..5dd6aeb
--- /dev/null
+++ b/www/css/custom.css
@@ -0,0 +1,9 @@
+* {
+ 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
new file mode 100644
index 0000000..bd6213e
--- /dev/null
+++ b/www/css/input.css
@@ -0,0 +1,3 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
\ No newline at end of file
diff --git a/www/demos/filters.html b/www/demos/filters.html
new file mode 100644
index 0000000..d775c8b
--- /dev/null
+++ b/www/demos/filters.html
@@ -0,0 +1,608 @@
+
+
+
+
+
+
+ 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
new file mode 100644
index 0000000..cd440da
Binary files /dev/null and b/www/favicon.ico differ
diff --git a/www/index.html b/www/index.html
new file mode 100644
index 0000000..64d601a
--- /dev/null
+++ b/www/index.html
@@ -0,0 +1,148 @@
+
+
+
+ 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
new file mode 100644
index 0000000..e69de29
diff --git a/www/js/obf.js b/www/js/obf.js
new file mode 100644
index 0000000..7d12ae5
--- /dev/null
+++ b/www/js/obf.js
@@ -0,0 +1 @@
+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
new file mode 100644
index 0000000..5f2b119
--- /dev/null
+++ b/www/privacy.html
@@ -0,0 +1,2 @@
+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
new file mode 100644
index 0000000..5d80735
Binary files /dev/null and b/www/res/discord.png differ