From 30f2b4714d63557869c4c5ae96c6e6c6879f5302 Mon Sep 17 00:00:00 2001 From: mux Date: Mon, 27 Oct 2025 04:10:26 -0300 Subject: [PATCH] initial commit --- .gitignore | 14 + README.md | 17 + assets/favicon.png | Bin 0 -> 2185 bytes assets/styles.css | 552 ++++++++++++++++++ client.ts | 7 + components/Box.tsx | 22 + components/Footer.tsx | 29 + components/Header.tsx | 35 ++ components/Icon.tsx | 442 ++++++++++++++ components/Layout.tsx | 32 + components/Link.tsx | 24 + components/Tinted.tsx | 60 ++ components/Title.tsx | 29 + deno.json | 58 ++ deno.lock | 1123 ++++++++++++++++++++++++++++++++++++ islands/Code.tsx | 30 + islands/Meow.tsx | 19 + islands/Name.tsx | 37 ++ islands/Rain.tsx | 374 ++++++++++++ islands/Time.tsx | 49 ++ main.ts | 12 + routes/_app.tsx | 31 + routes/index.tsx | 308 ++++++++++ scripts/copyright.ts | 31 + static/88x31.gif | Bin 0 -> 2133 bytes static/88x31.png | Bin 0 -> 1612 bytes static/88x31/meow_d.webp | Bin 0 -> 2198 bytes static/88x31/paige.gif | Bin 0 -> 1021 bytes static/88x31@1000.gif | Bin 0 -> 23889 bytes static/88x31@1000.png | Bin 0 -> 5066 bytes static/bnuy.webp | Bin 0 -> 2792 bytes static/extra/mumengo.gif | Bin 0 -> 2780059 bytes static/extra/nenezil.gif | Bin 0 -> 2298843 bytes static/favicon.png | Bin 0 -> 1200 bytes static/fonts/jersey15.ttf | Bin 0 -> 103368 bytes static/fonts/m6x11.ttf | Bin 0 -> 13068 bytes static/fonts/m6x11plus.ttf | Bin 0 -> 18192 bytes static/fonts/str.ttf | Bin 0 -> 46596 bytes static/icons/smiley.gif | Bin 0 -> 37312 bytes static/logo.svg | 243 ++++++++ static/pgp-key.asc | 51 ++ utils.ts | 14 + vite.config.ts | 11 + 43 files changed, 3654 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 assets/favicon.png create mode 100644 assets/styles.css create mode 100644 client.ts create mode 100644 components/Box.tsx create mode 100644 components/Footer.tsx create mode 100644 components/Header.tsx create mode 100644 components/Icon.tsx create mode 100644 components/Layout.tsx create mode 100644 components/Link.tsx create mode 100644 components/Tinted.tsx create mode 100644 components/Title.tsx create mode 100644 deno.json create mode 100644 deno.lock create mode 100644 islands/Code.tsx create mode 100644 islands/Meow.tsx create mode 100644 islands/Name.tsx create mode 100644 islands/Rain.tsx create mode 100644 islands/Time.tsx create mode 100644 main.ts create mode 100644 routes/_app.tsx create mode 100644 routes/index.tsx create mode 100755 scripts/copyright.ts create mode 100644 static/88x31.gif create mode 100644 static/88x31.png create mode 100644 static/88x31/meow_d.webp create mode 100644 static/88x31/paige.gif create mode 100644 static/88x31@1000.gif create mode 100644 static/88x31@1000.png create mode 100644 static/bnuy.webp create mode 100644 static/extra/mumengo.gif create mode 100644 static/extra/nenezil.gif create mode 100644 static/favicon.png create mode 100644 static/fonts/jersey15.ttf create mode 100644 static/fonts/m6x11.ttf create mode 100644 static/fonts/m6x11plus.ttf create mode 100644 static/fonts/str.ttf create mode 100644 static/icons/smiley.gif create mode 100644 static/logo.svg create mode 100644 static/pgp-key.asc create mode 100644 utils.ts create mode 100644 vite.config.ts diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0b297d4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,14 @@ +# dotenv environment variable files +.env +.env.development.local +.env.test.local +.env.production.local +.env.local + +# Fresh build directory +_fresh/ +# npm + other dependencies +node_modules/ +vendor/ + +sync.sh diff --git a/README.md b/README.md new file mode 100644 index 0000000..b2e551f --- /dev/null +++ b/README.md @@ -0,0 +1,17 @@ +# Fresh project + +Your new Fresh project is ready to go. You can follow the Fresh "Getting +Started" guide here: https://fresh.deno.dev/docs/getting-started + +### Usage + +Make sure to install Deno: +https://docs.deno.com/runtime/getting_started/installation + +Then start the project in development mode: + +``` +deno task dev +``` + +This will watch the project directory and restart as necessary. diff --git a/assets/favicon.png b/assets/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..9cd636059e5285a2341934147ba04d32a3e82534 GIT binary patch literal 2185 zcmcgteN<9s9LDA**h+V_k69i2*om`N9{ZSmxY4GVnPjGsDao{DiAI)+kcc>PwaVp5 zEE{W1rf7a#OhYjgtY#ltX^KFCKpiziqH7^&+|WUF&T5tHkDcA~-t)fap8NiO&-*;T z=l3294GEm)?BNW9!KMXmM2Ep(4jHx={*m>|Z4Io=Iyt0-1^U6b?Q^v-7~DSy{p~i& zIlXdu5;J1Pj`{|E#R*>13pupobcic+ zaO7Z}j}L#7&NO8S+mb%NhLrk#QXNY3f>Y^db@&|4Imvg(KNe4xhi*6c!8Hxlo!|$vUhx`xK|+xk6NAI+Jdiu z#vioz^{l_`u2$__0#Gfb+8Mk%$_edgmw=7wUuQ4LpwA3xdfu>EQZ*4RIo3O?I-#0O z=}JqMp&zFT7st!CCopSd+-`i53K@^1jz1+5luaO1wP}i@+gqf)hCLpok7J}QuM-86 z=}9}SP#gVlYGG5&C9G{7cXXEunJjUC5Baa+pbs6t<+!Z)Q%wJMBMbA0Dm2$RUMHRwuS_ZOnRz+GnGCF&~!{N$lClezQs%2(_DNMirv|X@r%0T?8sOaWsk7#Ox zVGQFkB4T6mRkpH_nZbfmV7qOXmw7zdEK|smVaB&L`$JJe z#FA>cbyDU50$DOW?j=S%nLnK~2e9ufUHOFo@BGFDx~N$>V$6h!)A&d+&448~Z?g=? zlxcO?X#-yO*axmU!QW2)k2VoD!YTsHn*Q^ni-tY@pP?!s(K^Ddo;CKI=S_ed0I=di zRF&D6l@rKOa~hM%QtV}n?K0&&v~cBhr#Y(JyDggL@h<2S)DQ@YKnvUxt8_YwEL%xG zL+GVZQRn{dXYW2mixRqL=F0KRdP!^Rtx8U=ub`nj?Te7V zio}I4j2!XX&CQLF)L!31cjxyEx-BMpKK`oE@+YP<2_xbvHPt*wh3A(Bivf9u|(f_Q2S& .logo { + height: 1em; + margin-right: 0.5ch; + vertical-align: -4px; +} + +.centered { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + width: 100%; + height: 100%; + gap: 1em; +} + +.title { + color: var(--theme-accent-title); + padding-bottom: 0.25em; + border-bottom: 2px solid var(--theme-border); + text-align: center; + justify-content: center; + margin: 0px; + padding-bottom: 0.5rem; + display: flex; + align-items: center; + gap: 0.25em; +} + +.title-1 { + font-size: 1.25rem; +} + +.title-3 { + color: var(--theme-fg-alt); + padding-bottom: 0.16rem; + border-bottom: none; + font-size: 0.9rem; +} + +.title.title-3::after { + background-image: linear-gradient( + 90deg, + rgba(var(--theme-border-rgb), 0) 0, + rgba(var(--theme-fg-alt-rgb), 255) + ); +} + +.title::after { + background-image: linear-gradient( + 90deg, + rgba(var(--theme-accent-title-rgb), 0) 0, + rgba(var(--theme-accent-title-rgb), 255) + ); + content: ""; + display: block; + flex: 1; + margin-left: 0.5ch; + height: 0.3rem; + border-radius: 3px; +} + +.title .icon { + height: 24px; + width: 24px; + shape-rendering: crispEdges; +} + +.box { + background-color: var(--theme-accent-alt); + color: var(--theme-accent); + padding: 0.5rem 1rem; + line-height: 1; + box-sizing: border-box; + width: fit-content; + overflow: hidden; + text-overflow: ellipsis; + word-break: break-all; + clip-path: polygon( + 0px calc(100% - 6px), + 6px calc(100% - 6px), + 6px 100%, + calc(100% - 6px) 100%, + calc(100% - 6px) calc(100% - 6px), + 100% calc(100% - 6px), + 100% 6px, + calc(100% - 6px) 6px, + calc(100% - 6px) 0px, + 6px 0px, + 6px 6px, + 0px 6px + ); + display: flex; + align-items: center; + gap: 0.35rem; +} + +a, +a:visited, +a:active { + color: var(--theme-accent-third); + text-decoration: none; +} + +a:hover { + text-decoration: 2px underline; + text-underline-offset: 3px; +} + +#header { + position: relative; + display: flex; + flex-direction: row; + justify-content: space-between; + z-index: 1; +} + +#header, +#header #left, +#header #links { + flex-wrap: wrap; +} + +#header #left, +#header #links { + display: flex; + flex-direction: row; + align-items: center; + gap: 0.5rem; + margin: 0; + padding: 0; +} + +#header img { + width: auto; + height: 1.5em; +} + +nav .module { + clip-path: polygon( + 0px calc(100% - 6px), + 6px calc(100% - 6px), + 6px 100%, + calc(100% - 6px) 100%, + calc(100% - 6px) calc(100% - 6px), + 100% calc(100% - 6px), + 100% 6px, + calc(100% - 6px) 6px, + calc(100% - 6px) 0px, + 6px 0px, + 6px 6px, + 0px 6px + ); + padding: 0.5em 1.25em; + box-sizing: border-box; + background-color: var(--theme-bg-secondary); +} + +#logo { + display: flex; + align-items: center; + padding: 0.5em; +} + +.labeled-icons { + margin: 0; + padding: 0; + list-style: none; + display: flex; + flex-direction: row; + flex-wrap: wrap; + gap: 0.35rem; + margin-top: 0.25rem; +} + +.labeled-icons.full { + flex-direction: column; + & > * { + flex-grow: 1; + } + & .box { + width: 100%; + } +} + +.labeled-icons.b88x31 { + gap: 0.35rem; +} + +.labeled-icons.b88x31 a { + display: flex; + width: 88px; + height: 31px; + background: var(--theme-bg-tertiary); + color: var(--theme-fg-alt); + justify-content: center; +} + +.labeled-icons.b88x31 a, +#muxiepuff { + clip-path: polygon( + 0px calc(100% - 3px), + 3px calc(100% - 3px), + 3px 100%, + calc(100% - 3px) 100%, + calc(100% - 3px) calc(100% - 3px), + 100% calc(100% - 3px), + 100% 3px, + calc(100% - 3px) 3px, + calc(100% - 3px) 0px, + 3px 0px, + 3px 3px, + 0px 3px + ); +} + +.labeled-icons.b88x31 li { + transition: filter 0.2s ease; +} + +.labeled-icons.b88x31 li:hover { + filter: brightness(0.5); +} + +.labeled-icons.b88x31 img { + image-rendering: pixelated; +} + +.labeled-icons.b88x31 img { + image-rendering: pixelated; +} + +#extra { + display: flex; + list-style: none; + flex-wrap: wrap; + align-items: center; + justify-content: space-between; + padding: 0; +} + +#extra svg { + width: 15rem; + max-width: 100%; + height: 15rem; +} + +@media (max-width: 768px) { + html { + font-size: 18px; + } +} + +@media (max-width: 480px) { + html { + font-size: 16px; + } + + body { + padding: 8px; + } +} + +@media (max-width: 768px) { + .section { + padding: 1.5rem; + } +} + +@media (max-width: 480px) { + .section { + padding: 1rem; + } +} + +@media (max-width: 480px) { + .box { + padding: 0.4rem 0.8rem; + font-size: 0.9em; + } + + .box svg { + width: 20px; + height: 20px; + } +} + +@media (max-width: 480px) { + .title { + font-size: 1.1rem; + } +} + +@media (max-width: 768px) { + #extra { + justify-content: center; + gap: 1rem; + } + + #extra svg { + width: 8rem; + height: 8rem; + } +} + +@media (max-width: 480px) { + #extra svg { + width: 6rem; + height: 6rem; + } +} + +@media (max-width: 480px) { + .alt-font { + font-size: 14px; + } +} + +#muxiepuff { + display: flex; + padding: 0; + background: none; + outline: none; + border: none; + cursor: pointer; +} + +.name-scroller { + display: inline-block; + position: relative; + vertical-align: middle; + margin-top: -3px; + overflow: hidden; +} + +.name-wrapper { + transition: + transform 0.3s ease-in-out, + opacity 0.3s ease-in-out; + transform: translateY(0); + opacity: 1; +} + +.name-wrapper.animating { + transform: translateY(-100%); + opacity: 0; +} + +.name-wrapper:not(.animating) { + transform: translateY(0); + opacity: 1; +} + +.name-text { + position: relative; + display: inline-block; +} + +.name-underline { + position: absolute; + bottom: 2px; + left: 0; + width: 100%; + height: 2px; + background: currentColor; + box-shadow: 0 0 8px currentColor; + animation: pulse 2s ease-in-out infinite; +} + +@keyframes pulse { + 0%, + 100% { + opacity: 1; + } + 50% { + opacity: 0.5; + } +} + +.inline-code { + font-family: "Share Tech Mono", "Share Tech", monospace; + font-size: 0.75em; + background-color: var(--theme-border); + padding: 1px; + display: inline-block; + clip-path: polygon( + 0px calc(100% - 2px), + 2px calc(100% - 2px), + 2px 100%, + calc(100% - 2px) 100%, + calc(100% - 2px) calc(100% - 2px), + 100% calc(100% - 2px), + 100% 2px, + calc(100% - 2px) 2px, + calc(100% - 2px) 0px, + 2px 0px, + 2px 2px, + 0px 2px + ); + line-height: 1.6; + vertical-align: middle; +} + +.inline-code > span { + display: block; + background-color: var(--theme-bg-tertiary); + color: var(--theme-fg); + padding: 0.15em 0.4em; + clip-path: polygon( + 0px calc(100% - 2px), + 2px calc(100% - 2px), + 2px 100%, + calc(100% - 2px) 100%, + calc(100% - 2px) calc(100% - 2px), + 100% calc(100% - 2px), + 100% 2px, + calc(100% - 2px) 2px, + calc(100% - 2px) 0px, + 2px 0px, + 2px 2px, + 0px 2px + ); + font-weight: 500; +} + +p, +.title { + transform: translateZ(0px); + -webkit-transform: translateZ(0px); + will-change: transform; +} + +hr { + width: 100%; + border: none; + border-top: 2px solid var(--theme-border); +} + +footer.section { + display: flex; + align-items: center; + justify-content: center; + gap: 1ch; +} + +footer p { + text-align: center; + gap: 1ch; + margin: 0; + padding: 0; +} + +footer a { + overflow-wrap: anywhere; + word-break: break-word; +} + +footer #f-heart { + color: var(--theme-accent-third); + vertical-align: middle; +} diff --git a/client.ts b/client.ts new file mode 100644 index 0000000..d528f06 --- /dev/null +++ b/client.ts @@ -0,0 +1,7 @@ +/** + * Copyright (c) 2025 xwra + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +// Import CSS files here for hot module reloading to work. +import "./assets/styles.css"; diff --git a/components/Box.tsx b/components/Box.tsx new file mode 100644 index 0000000..11c2d53 --- /dev/null +++ b/components/Box.tsx @@ -0,0 +1,22 @@ +/** + * Copyright (c) 2025 xwra + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +import { ComponentChildren, h } from "preact"; +import { LinkIcon } from "./Icon.tsx"; + +interface PolygonBoxProps { + as?: keyof HTMLElementTagNameMap; + children?: ComponentChildren; + [key: string]: any; +} + +export default function Box( + { as: Tag = "span", class: className, children, ...props }: PolygonBoxProps, +) { + const content = Tag === "a" + ? [children, h(LinkIcon, { size: 16, class: "link-icon" })] + : children; + return h(Tag, { class: `box ${className || ""}`, ...props }, content); +} diff --git a/components/Footer.tsx b/components/Footer.tsx new file mode 100644 index 0000000..4d81208 --- /dev/null +++ b/components/Footer.tsx @@ -0,0 +1,29 @@ +/** + * Copyright (c) 2025 xwra + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +import { HeartFilledIcon } from "./Icon.tsx"; +import Link from "./Link.tsx"; + +export default function Footer() { + return ( +
+

+ Made with · Source code available at{" "} + git.acpi.at under the{" "} + + GNU Affero General Public License v3.0 + + , with all site content licensed under{" "} + + CC BY-SA 4.0 + + . +

+

+ © 2025 muxiepuff • Powered by FreeBSD and pixels +

+
+ ); +} diff --git a/components/Header.tsx b/components/Header.tsx new file mode 100644 index 0000000..3c71fb1 --- /dev/null +++ b/components/Header.tsx @@ -0,0 +1,35 @@ +/** + * Copyright (c) 2025 xwra + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +export default function Header() { + return ( + + ); +} diff --git a/components/Icon.tsx b/components/Icon.tsx new file mode 100644 index 0000000..cff513b --- /dev/null +++ b/components/Icon.tsx @@ -0,0 +1,442 @@ +/** + * Copyright (c) 2025 xwra + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +interface IconProps { + size?: number; + [key: string]: any; +} + +export function LinkIcon({ size = 24, ...props }: IconProps) { + return ( + + + + ); +} + +export function PersonIcon({ size = 24, ...props }: IconProps) { + return ( + + + + ); +} + +export function HeartIcon({ size = 24, ...props }: IconProps) { + return ( + + + + ); +} + +export function CommentIcon({ size = 24, ...props }: IconProps) { + return ( + + + + ); +} + +export function AttachmentIcon({ size = 24, ...props }: IconProps) { + return ( + + + + ); +} + +export function LabelIcon({ size = 24, ...props }: IconProps) { + return ( + + + + ); +} + +export function DiscordIcon({ size = 24, ...props }: IconProps) { + return ( + + Discord + + + ); +} +export function SignalIcon({ size = 24, ...props }: IconProps) { + return ( + + Signal + + + ); +} +export function LastfmIcon({ size = 24, ...props }: IconProps) { + return ( + + Last.fm + + + ); +} +export function BlueskyIcon({ size = 24, ...props }: IconProps) { + return ( + + Bluesky + + + ); +} + +export function MastodonIcon({ size = 24, ...props }: IconProps) { + return ( + + Mastodon / Fediverse + + + ); +} + +export function ForgejoIcon({ size = 24, ...props }: IconProps) { + return ( + + Forgejo + + + ); +} +export function CodebergIcon({ size = 24, ...props }: IconProps) { + return ( + + Codeberg + + + ); +} +export function GitHubIcon({ size = 24, ...props }: IconProps) { + return ( + + GitHub + + + ); +} + +export function MailIcon({ size = 24, ...props }: IconProps) { + return ( + + + + + ); +} + +export function TwitterIcon({ size = 24, ...props }: IconProps) { + return ( + + + + ); +} + +export function KofiIcon({ size = 24, ...props }: IconProps) { + return ( + + Ko-fi + + + ); +} + +export function BitcoinIcon({ size = 24, ...props }: IconProps) { + return ( + + Bitcoin + + + ); +} + +export function BitcoinCashIcon({ size = 24, ...props }: IconProps) { + return ( + + Bitcoin Cash + + + ); +} + +export function MoneroIcon({ size = 24, ...props }: IconProps) { + return ( + + Monero + + + ); +} + +export function NanoIcon({ size = 24, ...props }: IconProps) { + return ( + + Nano + + + ); +} + +export function LitecoinIcon({ size = 24, ...props }: IconProps) { + return ( + + Litecoin + + + ); +} + +export function EthereumIcon({ size = 24, ...props }: IconProps) { + return ( + + Ethereum + + + ); +} + +export function HeartFilledIcon({ size = 24, ...props }: IconProps) { + return ( + + + + ); +} diff --git a/components/Layout.tsx b/components/Layout.tsx new file mode 100644 index 0000000..1d1e586 --- /dev/null +++ b/components/Layout.tsx @@ -0,0 +1,32 @@ +/** + * Copyright (c) 2025 xwra + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +import { ComponentChildren } from "preact"; + +interface LayoutProps { + children: ComponentChildren; + [key: string]: any; +} + +export function Section({ children, class: className, ...props }: LayoutProps) { + return ( +
+ {children} +
+ ); +} + +export function Centered( + { children, class: className, ...props }: LayoutProps, +) { + return ( +
+ {children} +
+ ); +} diff --git a/components/Link.tsx b/components/Link.tsx new file mode 100644 index 0000000..636d545 --- /dev/null +++ b/components/Link.tsx @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2025 xwra + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +import { HTMLAttributes, JSX } from "preact"; +import { LinkIcon } from "./Icon.tsx"; + +interface LinkProps extends HTMLAttributes { + href: string; + children: JSX.Element | JSX.Element[] | string; + noIcon?: boolean; +} + +export default function Link( + { children, noIcon = false, ...props }: LinkProps, +) { + return ( + + {children} + {!noIcon && } + + ); +} diff --git a/components/Tinted.tsx b/components/Tinted.tsx new file mode 100644 index 0000000..85096d7 --- /dev/null +++ b/components/Tinted.tsx @@ -0,0 +1,60 @@ +/** + * Copyright (c) 2025 xwra + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +interface TintedImageProps { + src: string; + colour: string; + [key: string]: any; +} + +export default function TintedImage({ + colour, + src, + ...props +}: TintedImageProps) { + return ( + + + + + + + + + + + ); +} diff --git a/components/Title.tsx b/components/Title.tsx new file mode 100644 index 0000000..5246dfc --- /dev/null +++ b/components/Title.tsx @@ -0,0 +1,29 @@ +/** + * Copyright (c) 2025 xwra + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +import { ComponentChildren, h } from "preact"; + +interface TitleProps { + level?: 1 | 2 | 3 | 4 | 5 | 6; + children: ComponentChildren; + [key: string]: any; +} + +export default function Title({ + level = 1, + children, + class: className, + ...props +}: TitleProps) { + const Heading = `h${Math.min(Math.max(level, 1), 6)}`; + return h( + Heading, + { + class: `title title-${level} ${className || ""}`, + ...props, + }, + children, + ); +} diff --git a/deno.json b/deno.json new file mode 100644 index 0000000..e9072ef --- /dev/null +++ b/deno.json @@ -0,0 +1,58 @@ +{ + "nodeModulesDir": "auto", + "tasks": { + "check": "deno fmt --check . && deno lint . && deno check", + "dev": "vite", + "build": "vite build", + "start": "deno serve -A _fresh/server.js", + "update": "deno run -A -r jsr:@fresh/update ." + }, + "lint": { + "rules": { + "tags": [ + "fresh", + "recommended" + ], + "exclude": ["no-explicit-any", "no-window", "no-window-prefix"] + } + }, + "exclude": [ + "**/_fresh/*" + ], + "imports": { + "fresh": "jsr:@fresh/core@^2.1.2", + "preact": "npm:preact@^10.27.2", + "@preact/signals": "npm:@preact/signals@^2.3.1", + "@fresh/plugin-vite": "jsr:@fresh/plugin-vite@^1.0.5", + "vite": "npm:vite@^7.1.3" + }, + "compilerOptions": { + "lib": [ + "dom", + "dom.asynciterable", + "dom.iterable", + "deno.ns" + ], + "jsx": "precompile", + "jsxImportSource": "preact", + "jsxPrecompileSkipElements": [ + "a", + "img", + "source", + "body", + "html", + "head", + "title", + "meta", + "script", + "link", + "style", + "base", + "noscript", + "template" + ], + "types": [ + "vite/client" + ] + } +} diff --git a/deno.lock b/deno.lock new file mode 100644 index 0000000..de65da2 --- /dev/null +++ b/deno.lock @@ -0,0 +1,1123 @@ +{ + "version": "5", + "specifiers": { + "jsr:@deno/esbuild-plugin@^1.2.0": "1.2.0", + "jsr:@deno/loader@~0.3.2": "0.3.7", + "jsr:@deno/loader@~0.3.3": "0.3.7", + "jsr:@fresh/build-id@1": "1.0.1", + "jsr:@fresh/core@2": "2.1.2", + "jsr:@fresh/core@^2.1.2": "2.1.2", + "jsr:@fresh/plugin-vite@^1.0.5": "1.0.5", + "jsr:@std/bytes@^1.0.6": "1.0.6", + "jsr:@std/dotenv@~0.225.5": "0.225.5", + "jsr:@std/encoding@1": "1.0.10", + "jsr:@std/encoding@^1.0.10": "1.0.10", + "jsr:@std/fmt@^1.0.7": "1.0.8", + "jsr:@std/fmt@^1.0.8": "1.0.8", + "jsr:@std/fs@1": "1.0.19", + "jsr:@std/html@1": "1.0.5", + "jsr:@std/http@^1.0.15": "1.0.21", + "jsr:@std/internal@^1.0.10": "1.0.12", + "jsr:@std/json@^1.0.2": "1.0.2", + "jsr:@std/jsonc@1": "1.0.2", + "jsr:@std/media-types@1": "1.1.0", + "jsr:@std/path@1": "1.1.2", + "jsr:@std/path@^1.1.1": "1.1.2", + "jsr:@std/semver@1": "1.0.6", + "jsr:@std/uuid@^1.0.7": "1.0.9", + "npm:@babel/core@^7.28.0": "7.28.4", + "npm:@babel/preset-react@^7.27.1": "7.27.1_@babel+core@7.28.4", + "npm:@mjackson/node-fetch-server@0.7": "0.7.0", + "npm:@opentelemetry/api@^1.9.0": "1.9.0", + "npm:@preact/signals@^2.2.1": "2.3.2_preact@10.27.2", + "npm:@preact/signals@^2.3.1": "2.3.2_preact@10.27.2", + "npm:@prefresh/vite@^2.4.8": "2.4.10_preact@10.27.2_vite@7.1.11__picomatch@4.0.3_@types+node@24.2.0", + "npm:@types/node@*": "24.2.0", + "npm:esbuild-wasm@0.25.7": "0.25.7", + "npm:esbuild@0.25.7": "0.25.7", + "npm:esbuild@~0.25.5": "0.25.11", + "npm:preact-render-to-string@^6.5.11": "6.6.2_preact@10.27.2", + "npm:preact@^10.27.0": "10.27.2", + "npm:preact@^10.27.2": "10.27.2", + "npm:rollup@^4.50.0": "4.52.5", + "npm:vite@7.1.11": "7.1.11_picomatch@4.0.3_@types+node@24.2.0", + "npm:vite@^7.1.3": "7.1.11_picomatch@4.0.3_@types+node@24.2.0", + "npm:vite@^7.1.4": "7.1.11_picomatch@4.0.3_@types+node@24.2.0" + }, + "jsr": { + "@deno/esbuild-plugin@1.2.0": { + "integrity": "04ddd0fca9416d8a2866263928a53b9d5ed08dfca064d64504a0aaf9800c709e", + "dependencies": [ + "jsr:@deno/loader@~0.3.3", + "jsr:@std/path@^1.1.1", + "npm:esbuild@~0.25.5" + ] + }, + "@deno/loader@0.3.7": { + "integrity": "d93aad9ba95df02eafa949e550d85a0b360754321a7f79f3796911481aa6e202" + }, + "@fresh/build-id@1.0.1": { + "integrity": "12a2ec25fd52ae9ec68c26848a5696cd1c9b537f7c983c7e56e4fb1e7e816c20", + "dependencies": [ + "jsr:@std/encoding@^1.0.10" + ] + }, + "@fresh/core@2.1.2": { + "integrity": "ffa92d2306e39136cab53f51b6bb25391c9eea3d5fa989382003e4579101ca78", + "dependencies": [ + "jsr:@deno/esbuild-plugin", + "jsr:@fresh/build-id", + "jsr:@std/encoding@1", + "jsr:@std/fmt@^1.0.8", + "jsr:@std/fs", + "jsr:@std/html", + "jsr:@std/http", + "jsr:@std/jsonc", + "jsr:@std/media-types", + "jsr:@std/path@1", + "jsr:@std/semver", + "jsr:@std/uuid", + "npm:@opentelemetry/api", + "npm:@preact/signals@^2.2.1", + "npm:esbuild-wasm", + "npm:esbuild@0.25.7", + "npm:preact-render-to-string", + "npm:preact@^10.27.0" + ] + }, + "@fresh/plugin-vite@1.0.5": { + "integrity": "886da094ef00ee99ea938d644e297854cbfb77519fc2dd243480bc9a71a6df7e", + "dependencies": [ + "jsr:@deno/loader@~0.3.2", + "jsr:@fresh/core@2", + "jsr:@fresh/core@^2.1.2", + "jsr:@std/dotenv", + "jsr:@std/fmt@^1.0.7", + "jsr:@std/path@1", + "npm:@babel/core", + "npm:@babel/preset-react", + "npm:@mjackson/node-fetch-server", + "npm:@prefresh/vite", + "npm:rollup", + "npm:vite@^7.1.4" + ] + }, + "@std/bytes@1.0.6": { + "integrity": "f6ac6adbd8ccd99314045f5703e23af0a68d7f7e58364b47d2c7f408aeb5820a" + }, + "@std/dotenv@0.225.5": { + "integrity": "9ce6f9d0ec3311f74a32535aa1b8c62ed88b1ab91b7f0815797d77a6f60c922f" + }, + "@std/encoding@1.0.10": { + "integrity": "8783c6384a2d13abd5e9e87a7ae0520a30e9f56aeeaa3bdf910a3eaaf5c811a1" + }, + "@std/fmt@1.0.8": { + "integrity": "71e1fc498787e4434d213647a6e43e794af4fd393ef8f52062246e06f7e372b7" + }, + "@std/fs@1.0.19": { + "integrity": "051968c2b1eae4d2ea9f79a08a3845740ef6af10356aff43d3e2ef11ed09fb06", + "dependencies": [ + "jsr:@std/path@^1.1.1" + ] + }, + "@std/html@1.0.5": { + "integrity": "4e2d693f474cae8c16a920fa5e15a3b72267b94b84667f11a50c6dd1cb18d35e" + }, + "@std/http@1.0.21": { + "integrity": "abb5c747651ee6e3ea6139858fd9b1810d2c97f53a5e6722f3b6d27a6d263edc", + "dependencies": [ + "jsr:@std/encoding@^1.0.10" + ] + }, + "@std/internal@1.0.12": { + "integrity": "972a634fd5bc34b242024402972cd5143eac68d8dffaca5eaa4dba30ce17b027" + }, + "@std/json@1.0.2": { + "integrity": "d9e5497801c15fb679f55a2c01c7794ad7a5dfda4dd1bebab5e409cb5e0d34d4" + }, + "@std/jsonc@1.0.2": { + "integrity": "909605dae3af22bd75b1cbda8d64a32cf1fd2cf6efa3f9e224aba6d22c0f44c7", + "dependencies": [ + "jsr:@std/json" + ] + }, + "@std/media-types@1.1.0": { + "integrity": "c9d093f0c05c3512932b330e3cc1fe1d627b301db33a4c2c2185c02471d6eaa4" + }, + "@std/path@1.1.2": { + "integrity": "c0b13b97dfe06546d5e16bf3966b1cadf92e1cc83e56ba5476ad8b498d9e3038", + "dependencies": [ + "jsr:@std/internal" + ] + }, + "@std/semver@1.0.6": { + "integrity": "b7c98ae2843547cf3f7ac37f3995889e6e4cee0a97b57b57f17f62722843303c" + }, + "@std/uuid@1.0.9": { + "integrity": "44b627bf2d372fe1bd099e2ad41b2be41a777fc94e62a3151006895a037f1642", + "dependencies": [ + "jsr:@std/bytes" + ] + } + }, + "npm": { + "@babel/code-frame@7.27.1": { + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", + "dependencies": [ + "@babel/helper-validator-identifier", + "js-tokens", + "picocolors" + ] + }, + "@babel/compat-data@7.28.4": { + "integrity": "sha512-YsmSKC29MJwf0gF8Rjjrg5LQCmyh+j/nD8/eP7f+BeoQTKYqs9RoWbjGOdy0+1Ekr68RJZMUOPVQaQisnIo4Rw==" + }, + "@babel/core@7.28.4": { + "integrity": "sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==", + "dependencies": [ + "@babel/code-frame", + "@babel/generator", + "@babel/helper-compilation-targets", + "@babel/helper-module-transforms", + "@babel/helpers", + "@babel/parser", + "@babel/template", + "@babel/traverse", + "@babel/types", + "@jridgewell/remapping", + "convert-source-map", + "debug", + "gensync", + "json5", + "semver" + ] + }, + "@babel/generator@7.28.3": { + "integrity": "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==", + "dependencies": [ + "@babel/parser", + "@babel/types", + "@jridgewell/gen-mapping", + "@jridgewell/trace-mapping", + "jsesc" + ] + }, + "@babel/helper-annotate-as-pure@7.27.3": { + "integrity": "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==", + "dependencies": [ + "@babel/types" + ] + }, + "@babel/helper-compilation-targets@7.27.2": { + "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", + "dependencies": [ + "@babel/compat-data", + "@babel/helper-validator-option", + "browserslist", + "lru-cache", + "semver" + ] + }, + "@babel/helper-globals@7.28.0": { + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==" + }, + "@babel/helper-module-imports@7.27.1": { + "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", + "dependencies": [ + "@babel/traverse", + "@babel/types" + ] + }, + "@babel/helper-module-transforms@7.28.3_@babel+core@7.28.4": { + "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==", + "dependencies": [ + "@babel/core", + "@babel/helper-module-imports", + "@babel/helper-validator-identifier", + "@babel/traverse" + ] + }, + "@babel/helper-plugin-utils@7.27.1": { + "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==" + }, + "@babel/helper-string-parser@7.27.1": { + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==" + }, + "@babel/helper-validator-identifier@7.27.1": { + "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==" + }, + "@babel/helper-validator-option@7.27.1": { + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==" + }, + "@babel/helpers@7.28.4": { + "integrity": "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==", + "dependencies": [ + "@babel/template", + "@babel/types" + ] + }, + "@babel/parser@7.28.4": { + "integrity": "sha512-yZbBqeM6TkpP9du/I2pUZnJsRMGGvOuIrhjzC1AwHwW+6he4mni6Bp/m8ijn0iOuZuPI2BfkCoSRunpyjnrQKg==", + "dependencies": [ + "@babel/types" + ], + "bin": true + }, + "@babel/plugin-syntax-jsx@7.27.1_@babel+core@7.28.4": { + "integrity": "sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==", + "dependencies": [ + "@babel/core", + "@babel/helper-plugin-utils" + ] + }, + "@babel/plugin-transform-react-display-name@7.28.0_@babel+core@7.28.4": { + "integrity": "sha512-D6Eujc2zMxKjfa4Zxl4GHMsmhKKZ9VpcqIchJLvwTxad9zWIYulwYItBovpDOoNLISpcZSXoDJ5gaGbQUDqViA==", + "dependencies": [ + "@babel/core", + "@babel/helper-plugin-utils" + ] + }, + "@babel/plugin-transform-react-jsx-development@7.27.1_@babel+core@7.28.4": { + "integrity": "sha512-ykDdF5yI4f1WrAolLqeF3hmYU12j9ntLQl/AOG1HAS21jxyg1Q0/J/tpREuYLfatGdGmXp/3yS0ZA76kOlVq9Q==", + "dependencies": [ + "@babel/core", + "@babel/plugin-transform-react-jsx" + ] + }, + "@babel/plugin-transform-react-jsx@7.27.1_@babel+core@7.28.4": { + "integrity": "sha512-2KH4LWGSrJIkVf5tSiBFYuXDAoWRq2MMwgivCf+93dd0GQi8RXLjKA/0EvRnVV5G0hrHczsquXuD01L8s6dmBw==", + "dependencies": [ + "@babel/core", + "@babel/helper-annotate-as-pure", + "@babel/helper-module-imports", + "@babel/helper-plugin-utils", + "@babel/plugin-syntax-jsx", + "@babel/types" + ] + }, + "@babel/plugin-transform-react-pure-annotations@7.27.1_@babel+core@7.28.4": { + "integrity": "sha512-JfuinvDOsD9FVMTHpzA/pBLisxpv1aSf+OIV8lgH3MuWrks19R27e6a6DipIg4aX1Zm9Wpb04p8wljfKrVSnPA==", + "dependencies": [ + "@babel/core", + "@babel/helper-annotate-as-pure", + "@babel/helper-plugin-utils" + ] + }, + "@babel/preset-react@7.27.1_@babel+core@7.28.4": { + "integrity": "sha512-oJHWh2gLhU9dW9HHr42q0cI0/iHHXTLGe39qvpAZZzagHy0MzYLCnCVV0symeRvzmjHyVU7mw2K06E6u/JwbhA==", + "dependencies": [ + "@babel/core", + "@babel/helper-plugin-utils", + "@babel/helper-validator-option", + "@babel/plugin-transform-react-display-name", + "@babel/plugin-transform-react-jsx", + "@babel/plugin-transform-react-jsx-development", + "@babel/plugin-transform-react-pure-annotations" + ] + }, + "@babel/template@7.27.2": { + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", + "dependencies": [ + "@babel/code-frame", + "@babel/parser", + "@babel/types" + ] + }, + "@babel/traverse@7.28.4": { + "integrity": "sha512-YEzuboP2qvQavAcjgQNVgsvHIDv6ZpwXvcvjmyySP2DIMuByS/6ioU5G9pYrWHM6T2YDfc7xga9iNzYOs12CFQ==", + "dependencies": [ + "@babel/code-frame", + "@babel/generator", + "@babel/helper-globals", + "@babel/parser", + "@babel/template", + "@babel/types", + "debug" + ] + }, + "@babel/types@7.28.4": { + "integrity": "sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q==", + "dependencies": [ + "@babel/helper-string-parser", + "@babel/helper-validator-identifier" + ] + }, + "@esbuild/aix-ppc64@0.25.11": { + "integrity": "sha512-Xt1dOL13m8u0WE8iplx9Ibbm+hFAO0GsU2P34UNoDGvZYkY8ifSiy6Zuc1lYxfG7svWE2fzqCUmFp5HCn51gJg==", + "os": ["aix"], + "cpu": ["ppc64"] + }, + "@esbuild/aix-ppc64@0.25.7": { + "integrity": "sha512-uD0kKFHh6ETr8TqEtaAcV+dn/2qnYbH/+8wGEdY70Qf7l1l/jmBUbrmQqwiPKAQE6cOQ7dTj6Xr0HzQDGHyceQ==", + "os": ["aix"], + "cpu": ["ppc64"] + }, + "@esbuild/android-arm64@0.25.11": { + "integrity": "sha512-9slpyFBc4FPPz48+f6jyiXOx/Y4v34TUeDDXJpZqAWQn/08lKGeD8aDp9TMn9jDz2CiEuHwfhRmGBvpnd/PWIQ==", + "os": ["android"], + "cpu": ["arm64"] + }, + "@esbuild/android-arm64@0.25.7": { + "integrity": "sha512-p0ohDnwyIbAtztHTNUTzN5EGD/HJLs1bwysrOPgSdlIA6NDnReoVfoCyxG6W1d85jr2X80Uq5KHftyYgaK9LPQ==", + "os": ["android"], + "cpu": ["arm64"] + }, + "@esbuild/android-arm@0.25.11": { + "integrity": "sha512-uoa7dU+Dt3HYsethkJ1k6Z9YdcHjTrSb5NUy66ZfZaSV8hEYGD5ZHbEMXnqLFlbBflLsl89Zke7CAdDJ4JI+Gg==", + "os": ["android"], + "cpu": ["arm"] + }, + "@esbuild/android-arm@0.25.7": { + "integrity": "sha512-Jhuet0g1k9rAJHrXGIh7sFknFuT4sfytYZpZpuZl7YKDhnPByVAm5oy2LEBmMbuYf3ejWVYCc2seX81Mk+madA==", + "os": ["android"], + "cpu": ["arm"] + }, + "@esbuild/android-x64@0.25.11": { + "integrity": "sha512-Sgiab4xBjPU1QoPEIqS3Xx+R2lezu0LKIEcYe6pftr56PqPygbB7+szVnzoShbx64MUupqoE0KyRlN7gezbl8g==", + "os": ["android"], + "cpu": ["x64"] + }, + "@esbuild/android-x64@0.25.7": { + "integrity": "sha512-mMxIJFlSgVK23HSsII3ZX9T2xKrBCDGyk0qiZnIW10LLFFtZLkFD6imZHu7gUo2wkNZwS9Yj3mOtZD3ZPcjCcw==", + "os": ["android"], + "cpu": ["x64"] + }, + "@esbuild/darwin-arm64@0.25.11": { + "integrity": "sha512-VekY0PBCukppoQrycFxUqkCojnTQhdec0vevUL/EDOCnXd9LKWqD/bHwMPzigIJXPhC59Vd1WFIL57SKs2mg4w==", + "os": ["darwin"], + "cpu": ["arm64"] + }, + "@esbuild/darwin-arm64@0.25.7": { + "integrity": "sha512-jyOFLGP2WwRwxM8F1VpP6gcdIJc8jq2CUrURbbTouJoRO7XCkU8GdnTDFIHdcifVBT45cJlOYsZ1kSlfbKjYUQ==", + "os": ["darwin"], + "cpu": ["arm64"] + }, + "@esbuild/darwin-x64@0.25.11": { + "integrity": "sha512-+hfp3yfBalNEpTGp9loYgbknjR695HkqtY3d3/JjSRUyPg/xd6q+mQqIb5qdywnDxRZykIHs3axEqU6l1+oWEQ==", + "os": ["darwin"], + "cpu": ["x64"] + }, + "@esbuild/darwin-x64@0.25.7": { + "integrity": "sha512-m9bVWqZCwQ1BthruifvG64hG03zzz9gE2r/vYAhztBna1/+qXiHyP9WgnyZqHgGeXoimJPhAmxfbeU+nMng6ZA==", + "os": ["darwin"], + "cpu": ["x64"] + }, + "@esbuild/freebsd-arm64@0.25.11": { + "integrity": "sha512-CmKjrnayyTJF2eVuO//uSjl/K3KsMIeYeyN7FyDBjsR3lnSJHaXlVoAK8DZa7lXWChbuOk7NjAc7ygAwrnPBhA==", + "os": ["freebsd"], + "cpu": ["arm64"] + }, + "@esbuild/freebsd-arm64@0.25.7": { + "integrity": "sha512-Bss7P4r6uhr3kDzRjPNEnTm/oIBdTPRNQuwaEFWT/uvt6A1YzK/yn5kcx5ZxZ9swOga7LqeYlu7bDIpDoS01bA==", + "os": ["freebsd"], + "cpu": ["arm64"] + }, + "@esbuild/freebsd-x64@0.25.11": { + "integrity": "sha512-Dyq+5oscTJvMaYPvW3x3FLpi2+gSZTCE/1ffdwuM6G1ARang/mb3jvjxs0mw6n3Lsw84ocfo9CrNMqc5lTfGOw==", + "os": ["freebsd"], + "cpu": ["x64"] + }, + "@esbuild/freebsd-x64@0.25.7": { + "integrity": "sha512-S3BFyjW81LXG7Vqmr37ddbThrm3A84yE7ey/ERBlK9dIiaWgrjRlre3pbG7txh1Uaxz8N7wGGQXmC9zV+LIpBQ==", + "os": ["freebsd"], + "cpu": ["x64"] + }, + "@esbuild/linux-arm64@0.25.11": { + "integrity": "sha512-Qr8AzcplUhGvdyUF08A1kHU3Vr2O88xxP0Tm8GcdVOUm25XYcMPp2YqSVHbLuXzYQMf9Bh/iKx7YPqECs6ffLA==", + "os": ["linux"], + "cpu": ["arm64"] + }, + "@esbuild/linux-arm64@0.25.7": { + "integrity": "sha512-HfQZQqrNOfS1Okn7PcsGUqHymL1cWGBslf78dGvtrj8q7cN3FkapFgNA4l/a5lXDwr7BqP2BSO6mz9UremNPbg==", + "os": ["linux"], + "cpu": ["arm64"] + }, + "@esbuild/linux-arm@0.25.11": { + "integrity": "sha512-TBMv6B4kCfrGJ8cUPo7vd6NECZH/8hPpBHHlYI3qzoYFvWu2AdTvZNuU/7hsbKWqu/COU7NIK12dHAAqBLLXgw==", + "os": ["linux"], + "cpu": ["arm"] + }, + "@esbuild/linux-arm@0.25.7": { + "integrity": "sha512-JZMIci/1m5vfQuhKoFXogCKVYVfYQmoZJg8vSIMR4TUXbF+0aNlfXH3DGFEFMElT8hOTUF5hisdZhnrZO/bkDw==", + "os": ["linux"], + "cpu": ["arm"] + }, + "@esbuild/linux-ia32@0.25.11": { + "integrity": "sha512-TmnJg8BMGPehs5JKrCLqyWTVAvielc615jbkOirATQvWWB1NMXY77oLMzsUjRLa0+ngecEmDGqt5jiDC6bfvOw==", + "os": ["linux"], + "cpu": ["ia32"] + }, + "@esbuild/linux-ia32@0.25.7": { + "integrity": "sha512-9Jex4uVpdeofiDxnwHRgen+j6398JlX4/6SCbbEFEXN7oMO2p0ueLN+e+9DdsdPLUdqns607HmzEFnxwr7+5wQ==", + "os": ["linux"], + "cpu": ["ia32"] + }, + "@esbuild/linux-loong64@0.25.11": { + "integrity": "sha512-DIGXL2+gvDaXlaq8xruNXUJdT5tF+SBbJQKbWy/0J7OhU8gOHOzKmGIlfTTl6nHaCOoipxQbuJi7O++ldrxgMw==", + "os": ["linux"], + "cpu": ["loong64"] + }, + "@esbuild/linux-loong64@0.25.7": { + "integrity": "sha512-TG1KJqjBlN9IHQjKVUYDB0/mUGgokfhhatlay8aZ/MSORMubEvj/J1CL8YGY4EBcln4z7rKFbsH+HeAv0d471w==", + "os": ["linux"], + "cpu": ["loong64"] + }, + "@esbuild/linux-mips64el@0.25.11": { + "integrity": "sha512-Osx1nALUJu4pU43o9OyjSCXokFkFbyzjXb6VhGIJZQ5JZi8ylCQ9/LFagolPsHtgw6himDSyb5ETSfmp4rpiKQ==", + "os": ["linux"], + "cpu": ["mips64el"] + }, + "@esbuild/linux-mips64el@0.25.7": { + "integrity": "sha512-Ty9Hj/lx7ikTnhOfaP7ipEm/ICcBv94i/6/WDg0OZ3BPBHhChsUbQancoWYSO0WNkEiSW5Do4febTTy4x1qYQQ==", + "os": ["linux"], + "cpu": ["mips64el"] + }, + "@esbuild/linux-ppc64@0.25.11": { + "integrity": "sha512-nbLFgsQQEsBa8XSgSTSlrnBSrpoWh7ioFDUmwo158gIm5NNP+17IYmNWzaIzWmgCxq56vfr34xGkOcZ7jX6CPw==", + "os": ["linux"], + "cpu": ["ppc64"] + }, + "@esbuild/linux-ppc64@0.25.7": { + "integrity": "sha512-MrOjirGQWGReJl3BNQ58BLhUBPpWABnKrnq8Q/vZWWwAB1wuLXOIxS2JQ1LT3+5T+3jfPh0tyf5CpbyQHqnWIQ==", + "os": ["linux"], + "cpu": ["ppc64"] + }, + "@esbuild/linux-riscv64@0.25.11": { + "integrity": "sha512-HfyAmqZi9uBAbgKYP1yGuI7tSREXwIb438q0nqvlpxAOs3XnZ8RsisRfmVsgV486NdjD7Mw2UrFSw51lzUk1ww==", + "os": ["linux"], + "cpu": ["riscv64"] + }, + "@esbuild/linux-riscv64@0.25.7": { + "integrity": "sha512-9pr23/pqzyqIZEZmQXnFyqp3vpa+KBk5TotfkzGMqpw089PGm0AIowkUppHB9derQzqniGn3wVXgck19+oqiOw==", + "os": ["linux"], + "cpu": ["riscv64"] + }, + "@esbuild/linux-s390x@0.25.11": { + "integrity": "sha512-HjLqVgSSYnVXRisyfmzsH6mXqyvj0SA7pG5g+9W7ESgwA70AXYNpfKBqh1KbTxmQVaYxpzA/SvlB9oclGPbApw==", + "os": ["linux"], + "cpu": ["s390x"] + }, + "@esbuild/linux-s390x@0.25.7": { + "integrity": "sha512-4dP11UVGh9O6Y47m8YvW8eoA3r8qL2toVZUbBKyGta8j6zdw1cn9F/Rt59/Mhv0OgY68pHIMjGXWOUaykCnx+w==", + "os": ["linux"], + "cpu": ["s390x"] + }, + "@esbuild/linux-x64@0.25.11": { + "integrity": "sha512-HSFAT4+WYjIhrHxKBwGmOOSpphjYkcswF449j6EjsjbinTZbp8PJtjsVK1XFJStdzXdy/jaddAep2FGY+wyFAQ==", + "os": ["linux"], + "cpu": ["x64"] + }, + "@esbuild/linux-x64@0.25.7": { + "integrity": "sha512-ghJMAJTdw/0uhz7e7YnpdX1xVn7VqA0GrWrAO2qKMuqbvgHT2VZiBv1BQ//VcHsPir4wsL3P2oPggfKPzTKoCA==", + "os": ["linux"], + "cpu": ["x64"] + }, + "@esbuild/netbsd-arm64@0.25.11": { + "integrity": "sha512-hr9Oxj1Fa4r04dNpWr3P8QKVVsjQhqrMSUzZzf+LZcYjZNqhA3IAfPQdEh1FLVUJSiu6sgAwp3OmwBfbFgG2Xg==", + "os": ["netbsd"], + "cpu": ["arm64"] + }, + "@esbuild/netbsd-arm64@0.25.7": { + "integrity": "sha512-bwXGEU4ua45+u5Ci/a55B85KWaDSRS8NPOHtxy2e3etDjbz23wlry37Ffzapz69JAGGc4089TBo+dGzydQmydg==", + "os": ["netbsd"], + "cpu": ["arm64"] + }, + "@esbuild/netbsd-x64@0.25.11": { + "integrity": "sha512-u7tKA+qbzBydyj0vgpu+5h5AeudxOAGncb8N6C9Kh1N4n7wU1Xw1JDApsRjpShRpXRQlJLb9wY28ELpwdPcZ7A==", + "os": ["netbsd"], + "cpu": ["x64"] + }, + "@esbuild/netbsd-x64@0.25.7": { + "integrity": "sha512-tUZRvLtgLE5OyN46sPSYlgmHoBS5bx2URSrgZdW1L1teWPYVmXh+QN/sKDqkzBo/IHGcKcHLKDhBeVVkO7teEA==", + "os": ["netbsd"], + "cpu": ["x64"] + }, + "@esbuild/openbsd-arm64@0.25.11": { + "integrity": "sha512-Qq6YHhayieor3DxFOoYM1q0q1uMFYb7cSpLD2qzDSvK1NAvqFi8Xgivv0cFC6J+hWVw2teCYltyy9/m/14ryHg==", + "os": ["openbsd"], + "cpu": ["arm64"] + }, + "@esbuild/openbsd-arm64@0.25.7": { + "integrity": "sha512-bTJ50aoC+WDlDGBReWYiObpYvQfMjBNlKztqoNUL0iUkYtwLkBQQeEsTq/I1KyjsKA5tyov6VZaPb8UdD6ci6Q==", + "os": ["openbsd"], + "cpu": ["arm64"] + }, + "@esbuild/openbsd-x64@0.25.11": { + "integrity": "sha512-CN+7c++kkbrckTOz5hrehxWN7uIhFFlmS/hqziSFVWpAzpWrQoAG4chH+nN3Be+Kzv/uuo7zhX716x3Sn2Jduw==", + "os": ["openbsd"], + "cpu": ["x64"] + }, + "@esbuild/openbsd-x64@0.25.7": { + "integrity": "sha512-TA9XfJrgzAipFUU895jd9j2SyDh9bbNkK2I0gHcvqb/o84UeQkBpi/XmYX3cO1q/9hZokdcDqQxIi6uLVrikxg==", + "os": ["openbsd"], + "cpu": ["x64"] + }, + "@esbuild/openharmony-arm64@0.25.11": { + "integrity": "sha512-rOREuNIQgaiR+9QuNkbkxubbp8MSO9rONmwP5nKncnWJ9v5jQ4JxFnLu4zDSRPf3x4u+2VN4pM4RdyIzDty/wQ==", + "os": ["openharmony"], + "cpu": ["arm64"] + }, + "@esbuild/openharmony-arm64@0.25.7": { + "integrity": "sha512-5VTtExUrWwHHEUZ/N+rPlHDwVFQ5aME7vRJES8+iQ0xC/bMYckfJ0l2n3yGIfRoXcK/wq4oXSItZAz5wslTKGw==", + "os": ["openharmony"], + "cpu": ["arm64"] + }, + "@esbuild/sunos-x64@0.25.11": { + "integrity": "sha512-nq2xdYaWxyg9DcIyXkZhcYulC6pQ2FuCgem3LI92IwMgIZ69KHeY8T4Y88pcwoLIjbed8n36CyKoYRDygNSGhA==", + "os": ["sunos"], + "cpu": ["x64"] + }, + "@esbuild/sunos-x64@0.25.7": { + "integrity": "sha512-umkbn7KTxsexhv2vuuJmj9kggd4AEtL32KodkJgfhNOHMPtQ55RexsaSrMb+0+jp9XL4I4o2y91PZauVN4cH3A==", + "os": ["sunos"], + "cpu": ["x64"] + }, + "@esbuild/win32-arm64@0.25.11": { + "integrity": "sha512-3XxECOWJq1qMZ3MN8srCJ/QfoLpL+VaxD/WfNRm1O3B4+AZ/BnLVgFbUV3eiRYDMXetciH16dwPbbHqwe1uU0Q==", + "os": ["win32"], + "cpu": ["arm64"] + }, + "@esbuild/win32-arm64@0.25.7": { + "integrity": "sha512-j20JQGP/gz8QDgzl5No5Gr4F6hurAZvtkFxAKhiv2X49yi/ih8ECK4Y35YnjlMogSKJk931iNMcd35BtZ4ghfw==", + "os": ["win32"], + "cpu": ["arm64"] + }, + "@esbuild/win32-ia32@0.25.11": { + "integrity": "sha512-3ukss6gb9XZ8TlRyJlgLn17ecsK4NSQTmdIXRASVsiS2sQ6zPPZklNJT5GR5tE/MUarymmy8kCEf5xPCNCqVOA==", + "os": ["win32"], + "cpu": ["ia32"] + }, + "@esbuild/win32-ia32@0.25.7": { + "integrity": "sha512-4qZ6NUfoiiKZfLAXRsvFkA0hoWVM+1y2bSHXHkpdLAs/+r0LgwqYohmfZCi985c6JWHhiXP30mgZawn/XrqAkQ==", + "os": ["win32"], + "cpu": ["ia32"] + }, + "@esbuild/win32-x64@0.25.11": { + "integrity": "sha512-D7Hpz6A2L4hzsRpPaCYkQnGOotdUpDzSGRIv9I+1ITdHROSFUWW95ZPZWQmGka1Fg7W3zFJowyn9WGwMJ0+KPA==", + "os": ["win32"], + "cpu": ["x64"] + }, + "@esbuild/win32-x64@0.25.7": { + "integrity": "sha512-FaPsAHTwm+1Gfvn37Eg3E5HIpfR3i6x1AIcla/MkqAIupD4BW3MrSeUqfoTzwwJhk3WE2/KqUn4/eenEJC76VA==", + "os": ["win32"], + "cpu": ["x64"] + }, + "@jridgewell/gen-mapping@0.3.13": { + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dependencies": [ + "@jridgewell/sourcemap-codec", + "@jridgewell/trace-mapping" + ] + }, + "@jridgewell/remapping@2.3.5": { + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dependencies": [ + "@jridgewell/gen-mapping", + "@jridgewell/trace-mapping" + ] + }, + "@jridgewell/resolve-uri@3.1.2": { + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==" + }, + "@jridgewell/sourcemap-codec@1.5.5": { + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==" + }, + "@jridgewell/trace-mapping@0.3.31": { + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dependencies": [ + "@jridgewell/resolve-uri", + "@jridgewell/sourcemap-codec" + ] + }, + "@mjackson/node-fetch-server@0.7.0": { + "integrity": "sha512-un8diyEBKU3BTVj3GzlTPA1kIjCkGdD+AMYQy31Gf9JCkfoZzwgJ79GUtHrF2BN3XPNMLpubbzPcxys+a3uZEw==" + }, + "@opentelemetry/api@1.9.0": { + "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==" + }, + "@preact/signals-core@1.12.1": { + "integrity": "sha512-BwbTXpj+9QutoZLQvbttRg5x3l5468qaV2kufh+51yha1c53ep5dY4kTuZR35+3pAZxpfQerGJiQqg34ZNZ6uA==" + }, + "@preact/signals@2.3.2_preact@10.27.2": { + "integrity": "sha512-Q22avIn4z0BQnmFeo6Y5HCnJTo8VufN84zN51OtqeNgZOVCYgdwEOcJKVX1x/IrjRVxUnOy6Ubn7H5aVFujXaQ==", + "dependencies": [ + "@preact/signals-core", + "preact" + ] + }, + "@prefresh/babel-plugin@0.5.2": { + "integrity": "sha512-AOl4HG6dAxWkJ5ndPHBgBa49oo/9bOiJuRDKHLSTyH+Fd9x00shTXpdiTj1W41l6oQIwUOAgJeHMn4QwIDpHkA==" + }, + "@prefresh/core@1.5.8_preact@10.27.2": { + "integrity": "sha512-T7HMpakS1iPVCFZvfDLMGyrWAcO3toUN9/RkJUqqoRr/vNhQrZgHjidfhq3awDzAQtw1emDWH8dsOeu0DWqtgA==", + "dependencies": [ + "preact" + ] + }, + "@prefresh/utils@1.2.1": { + "integrity": "sha512-vq/sIuN5nYfYzvyayXI4C2QkprfNaHUQ9ZX+3xLD8nL3rWyzpxOm1+K7RtMbhd+66QcaISViK7amjnheQ/4WZw==" + }, + "@prefresh/vite@2.4.10_preact@10.27.2_vite@7.1.11__picomatch@4.0.3": { + "integrity": "sha512-lt+ODASOtXRWaPplp7/DlrgAaInnQYNvcpCglQBMx2OeJPyZ4IqPRaxsK77w96mWshjYwkqTsRSHoAM7aAn0ow==", + "dependencies": [ + "@babel/core", + "@prefresh/babel-plugin", + "@prefresh/core", + "@prefresh/utils", + "@rollup/pluginutils", + "preact", + "vite@7.1.11_picomatch@4.0.3" + ] + }, + "@prefresh/vite@2.4.10_preact@10.27.2_vite@7.1.11__picomatch@4.0.3_@types+node@24.2.0": { + "integrity": "sha512-lt+ODASOtXRWaPplp7/DlrgAaInnQYNvcpCglQBMx2OeJPyZ4IqPRaxsK77w96mWshjYwkqTsRSHoAM7aAn0ow==", + "dependencies": [ + "@babel/core", + "@prefresh/babel-plugin", + "@prefresh/core", + "@prefresh/utils", + "@rollup/pluginutils", + "preact", + "vite@7.1.11_picomatch@4.0.3_@types+node@24.2.0" + ] + }, + "@rollup/pluginutils@4.2.1": { + "integrity": "sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==", + "dependencies": [ + "estree-walker", + "picomatch@2.3.1" + ] + }, + "@rollup/rollup-android-arm-eabi@4.52.5": { + "integrity": "sha512-8c1vW4ocv3UOMp9K+gToY5zL2XiiVw3k7f1ksf4yO1FlDFQ1C2u72iACFnSOceJFsWskc2WZNqeRhFRPzv+wtQ==", + "os": ["android"], + "cpu": ["arm"] + }, + "@rollup/rollup-android-arm64@4.52.5": { + "integrity": "sha512-mQGfsIEFcu21mvqkEKKu2dYmtuSZOBMmAl5CFlPGLY94Vlcm+zWApK7F/eocsNzp8tKmbeBP8yXyAbx0XHsFNA==", + "os": ["android"], + "cpu": ["arm64"] + }, + "@rollup/rollup-darwin-arm64@4.52.5": { + "integrity": "sha512-takF3CR71mCAGA+v794QUZ0b6ZSrgJkArC+gUiG6LB6TQty9T0Mqh3m2ImRBOxS2IeYBo4lKWIieSvnEk2OQWA==", + "os": ["darwin"], + "cpu": ["arm64"] + }, + "@rollup/rollup-darwin-x64@4.52.5": { + "integrity": "sha512-W901Pla8Ya95WpxDn//VF9K9u2JbocwV/v75TE0YIHNTbhqUTv9w4VuQ9MaWlNOkkEfFwkdNhXgcLqPSmHy0fA==", + "os": ["darwin"], + "cpu": ["x64"] + }, + "@rollup/rollup-freebsd-arm64@4.52.5": { + "integrity": "sha512-QofO7i7JycsYOWxe0GFqhLmF6l1TqBswJMvICnRUjqCx8b47MTo46W8AoeQwiokAx3zVryVnxtBMcGcnX12LvA==", + "os": ["freebsd"], + "cpu": ["arm64"] + }, + "@rollup/rollup-freebsd-x64@4.52.5": { + "integrity": "sha512-jr21b/99ew8ujZubPo9skbrItHEIE50WdV86cdSoRkKtmWa+DDr6fu2c/xyRT0F/WazZpam6kk7IHBerSL7LDQ==", + "os": ["freebsd"], + "cpu": ["x64"] + }, + "@rollup/rollup-linux-arm-gnueabihf@4.52.5": { + "integrity": "sha512-PsNAbcyv9CcecAUagQefwX8fQn9LQ4nZkpDboBOttmyffnInRy8R8dSg6hxxl2Re5QhHBf6FYIDhIj5v982ATQ==", + "os": ["linux"], + "cpu": ["arm"] + }, + "@rollup/rollup-linux-arm-musleabihf@4.52.5": { + "integrity": "sha512-Fw4tysRutyQc/wwkmcyoqFtJhh0u31K+Q6jYjeicsGJJ7bbEq8LwPWV/w0cnzOqR2m694/Af6hpFayLJZkG2VQ==", + "os": ["linux"], + "cpu": ["arm"] + }, + "@rollup/rollup-linux-arm64-gnu@4.52.5": { + "integrity": "sha512-a+3wVnAYdQClOTlyapKmyI6BLPAFYs0JM8HRpgYZQO02rMR09ZcV9LbQB+NL6sljzG38869YqThrRnfPMCDtZg==", + "os": ["linux"], + "cpu": ["arm64"] + }, + "@rollup/rollup-linux-arm64-musl@4.52.5": { + "integrity": "sha512-AvttBOMwO9Pcuuf7m9PkC1PUIKsfaAJ4AYhy944qeTJgQOqJYJ9oVl2nYgY7Rk0mkbsuOpCAYSs6wLYB2Xiw0Q==", + "os": ["linux"], + "cpu": ["arm64"] + }, + "@rollup/rollup-linux-loong64-gnu@4.52.5": { + "integrity": "sha512-DkDk8pmXQV2wVrF6oq5tONK6UHLz/XcEVow4JTTerdeV1uqPeHxwcg7aFsfnSm9L+OO8WJsWotKM2JJPMWrQtA==", + "os": ["linux"], + "cpu": ["loong64"] + }, + "@rollup/rollup-linux-ppc64-gnu@4.52.5": { + "integrity": "sha512-W/b9ZN/U9+hPQVvlGwjzi+Wy4xdoH2I8EjaCkMvzpI7wJUs8sWJ03Rq96jRnHkSrcHTpQe8h5Tg3ZzUPGauvAw==", + "os": ["linux"], + "cpu": ["ppc64"] + }, + "@rollup/rollup-linux-riscv64-gnu@4.52.5": { + "integrity": "sha512-sjQLr9BW7R/ZiXnQiWPkErNfLMkkWIoCz7YMn27HldKsADEKa5WYdobaa1hmN6slu9oWQbB6/jFpJ+P2IkVrmw==", + "os": ["linux"], + "cpu": ["riscv64"] + }, + "@rollup/rollup-linux-riscv64-musl@4.52.5": { + "integrity": "sha512-hq3jU/kGyjXWTvAh2awn8oHroCbrPm8JqM7RUpKjalIRWWXE01CQOf/tUNWNHjmbMHg/hmNCwc/Pz3k1T/j/Lg==", + "os": ["linux"], + "cpu": ["riscv64"] + }, + "@rollup/rollup-linux-s390x-gnu@4.52.5": { + "integrity": "sha512-gn8kHOrku8D4NGHMK1Y7NA7INQTRdVOntt1OCYypZPRt6skGbddska44K8iocdpxHTMMNui5oH4elPH4QOLrFQ==", + "os": ["linux"], + "cpu": ["s390x"] + }, + "@rollup/rollup-linux-x64-gnu@4.52.5": { + "integrity": "sha512-hXGLYpdhiNElzN770+H2nlx+jRog8TyynpTVzdlc6bndktjKWyZyiCsuDAlpd+j+W+WNqfcyAWz9HxxIGfZm1Q==", + "os": ["linux"], + "cpu": ["x64"] + }, + "@rollup/rollup-linux-x64-musl@4.52.5": { + "integrity": "sha512-arCGIcuNKjBoKAXD+y7XomR9gY6Mw7HnFBv5Rw7wQRvwYLR7gBAgV7Mb2QTyjXfTveBNFAtPt46/36vV9STLNg==", + "os": ["linux"], + "cpu": ["x64"] + }, + "@rollup/rollup-openharmony-arm64@4.52.5": { + "integrity": "sha512-QoFqB6+/9Rly/RiPjaomPLmR/13cgkIGfA40LHly9zcH1S0bN2HVFYk3a1eAyHQyjs3ZJYlXvIGtcCs5tko9Cw==", + "os": ["openharmony"], + "cpu": ["arm64"] + }, + "@rollup/rollup-win32-arm64-msvc@4.52.5": { + "integrity": "sha512-w0cDWVR6MlTstla1cIfOGyl8+qb93FlAVutcor14Gf5Md5ap5ySfQ7R9S/NjNaMLSFdUnKGEasmVnu3lCMqB7w==", + "os": ["win32"], + "cpu": ["arm64"] + }, + "@rollup/rollup-win32-ia32-msvc@4.52.5": { + "integrity": "sha512-Aufdpzp7DpOTULJCuvzqcItSGDH73pF3ko/f+ckJhxQyHtp67rHw3HMNxoIdDMUITJESNE6a8uh4Lo4SLouOUg==", + "os": ["win32"], + "cpu": ["ia32"] + }, + "@rollup/rollup-win32-x64-gnu@4.52.5": { + "integrity": "sha512-UGBUGPFp1vkj6p8wCRraqNhqwX/4kNQPS57BCFc8wYh0g94iVIW33wJtQAx3G7vrjjNtRaxiMUylM0ktp/TRSQ==", + "os": ["win32"], + "cpu": ["x64"] + }, + "@rollup/rollup-win32-x64-msvc@4.52.5": { + "integrity": "sha512-TAcgQh2sSkykPRWLrdyy2AiceMckNf5loITqXxFI5VuQjS5tSuw3WlwdN8qv8vzjLAUTvYaH/mVjSFpbkFbpTg==", + "os": ["win32"], + "cpu": ["x64"] + }, + "@types/estree@1.0.8": { + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==" + }, + "@types/node@24.2.0": { + "integrity": "sha512-3xyG3pMCq3oYCNg7/ZP+E1ooTaGB4cG8JWRsqqOYQdbWNY4zbaV0Ennrd7stjiJEFZCaybcIgpTjJWHRfBSIDw==", + "dependencies": [ + "undici-types" + ] + }, + "baseline-browser-mapping@2.8.19": { + "integrity": "sha512-zoKGUdu6vb2jd3YOq0nnhEDQVbPcHhco3UImJrv5dSkvxTc2pl2WjOPsjZXDwPDSl5eghIMuY3R6J9NDKF3KcQ==", + "bin": true + }, + "browserslist@4.26.3": { + "integrity": "sha512-lAUU+02RFBuCKQPj/P6NgjlbCnLBMp4UtgTx7vNHd3XSIJF87s9a5rA3aH2yw3GS9DqZAUbOtZdCCiZeVRqt0w==", + "dependencies": [ + "baseline-browser-mapping", + "caniuse-lite", + "electron-to-chromium", + "node-releases", + "update-browserslist-db" + ], + "bin": true + }, + "caniuse-lite@1.0.30001751": { + "integrity": "sha512-A0QJhug0Ly64Ii3eIqHu5X51ebln3k4yTUkY1j8drqpWHVreg/VLijN48cZ1bYPiqOQuqpkIKnzr/Ul8V+p6Cw==" + }, + "convert-source-map@2.0.0": { + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" + }, + "debug@4.4.3": { + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dependencies": [ + "ms" + ] + }, + "electron-to-chromium@1.5.237": { + "integrity": "sha512-icUt1NvfhGLar5lSWH3tHNzablaA5js3HVHacQimfP8ViEBOQv+L7DKEuHdbTZ0SKCO1ogTJTIL1Gwk9S6Qvcg==" + }, + "esbuild-wasm@0.25.7": { + "integrity": "sha512-x3t1BlU59YOMtpwzayHxF4LPVujOvNKqm7y6jPvFKC13J8FmJRCdHPJwHq86er7ik+f7uwGcMbe+6KVzLGmsGw==", + "bin": true + }, + "esbuild@0.25.11": { + "integrity": "sha512-KohQwyzrKTQmhXDW1PjCv3Tyspn9n5GcY2RTDqeORIdIJY8yKIF7sTSopFmn/wpMPW4rdPXI0UE5LJLuq3bx0Q==", + "optionalDependencies": [ + "@esbuild/aix-ppc64@0.25.11", + "@esbuild/android-arm@0.25.11", + "@esbuild/android-arm64@0.25.11", + "@esbuild/android-x64@0.25.11", + "@esbuild/darwin-arm64@0.25.11", + "@esbuild/darwin-x64@0.25.11", + "@esbuild/freebsd-arm64@0.25.11", + "@esbuild/freebsd-x64@0.25.11", + "@esbuild/linux-arm@0.25.11", + "@esbuild/linux-arm64@0.25.11", + "@esbuild/linux-ia32@0.25.11", + "@esbuild/linux-loong64@0.25.11", + "@esbuild/linux-mips64el@0.25.11", + "@esbuild/linux-ppc64@0.25.11", + "@esbuild/linux-riscv64@0.25.11", + "@esbuild/linux-s390x@0.25.11", + "@esbuild/linux-x64@0.25.11", + "@esbuild/netbsd-arm64@0.25.11", + "@esbuild/netbsd-x64@0.25.11", + "@esbuild/openbsd-arm64@0.25.11", + "@esbuild/openbsd-x64@0.25.11", + "@esbuild/openharmony-arm64@0.25.11", + "@esbuild/sunos-x64@0.25.11", + "@esbuild/win32-arm64@0.25.11", + "@esbuild/win32-ia32@0.25.11", + "@esbuild/win32-x64@0.25.11" + ], + "scripts": true, + "bin": true + }, + "esbuild@0.25.7": { + "integrity": "sha512-daJB0q2dmTzo90L9NjRaohhRWrCzYxWNFTjEi72/h+p5DcY3yn4MacWfDakHmaBaDzDiuLJsCh0+6LK/iX+c+Q==", + "optionalDependencies": [ + "@esbuild/aix-ppc64@0.25.7", + "@esbuild/android-arm@0.25.7", + "@esbuild/android-arm64@0.25.7", + "@esbuild/android-x64@0.25.7", + "@esbuild/darwin-arm64@0.25.7", + "@esbuild/darwin-x64@0.25.7", + "@esbuild/freebsd-arm64@0.25.7", + "@esbuild/freebsd-x64@0.25.7", + "@esbuild/linux-arm@0.25.7", + "@esbuild/linux-arm64@0.25.7", + "@esbuild/linux-ia32@0.25.7", + "@esbuild/linux-loong64@0.25.7", + "@esbuild/linux-mips64el@0.25.7", + "@esbuild/linux-ppc64@0.25.7", + "@esbuild/linux-riscv64@0.25.7", + "@esbuild/linux-s390x@0.25.7", + "@esbuild/linux-x64@0.25.7", + "@esbuild/netbsd-arm64@0.25.7", + "@esbuild/netbsd-x64@0.25.7", + "@esbuild/openbsd-arm64@0.25.7", + "@esbuild/openbsd-x64@0.25.7", + "@esbuild/openharmony-arm64@0.25.7", + "@esbuild/sunos-x64@0.25.7", + "@esbuild/win32-arm64@0.25.7", + "@esbuild/win32-ia32@0.25.7", + "@esbuild/win32-x64@0.25.7" + ], + "scripts": true, + "bin": true + }, + "escalade@3.2.0": { + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==" + }, + "estree-walker@2.0.2": { + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" + }, + "fdir@6.5.0_picomatch@4.0.3": { + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dependencies": [ + "picomatch@4.0.3" + ], + "optionalPeers": [ + "picomatch@4.0.3" + ] + }, + "fsevents@2.3.3": { + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "os": ["darwin"], + "scripts": true + }, + "gensync@1.0.0-beta.2": { + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==" + }, + "js-tokens@4.0.0": { + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "jsesc@3.1.0": { + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "bin": true + }, + "json5@2.2.3": { + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "bin": true + }, + "lru-cache@5.1.1": { + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dependencies": [ + "yallist" + ] + }, + "ms@2.1.3": { + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "nanoid@3.3.11": { + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "bin": true + }, + "node-releases@2.0.26": { + "integrity": "sha512-S2M9YimhSjBSvYnlr5/+umAnPHE++ODwt5e2Ij6FoX45HA/s4vHdkDx1eax2pAPeAOqu4s9b7ppahsyEFdVqQA==" + }, + "picocolors@1.1.1": { + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" + }, + "picomatch@2.3.1": { + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" + }, + "picomatch@4.0.3": { + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==" + }, + "postcss@8.5.6": { + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "dependencies": [ + "nanoid", + "picocolors", + "source-map-js" + ] + }, + "preact-render-to-string@6.6.2_preact@10.27.2": { + "integrity": "sha512-VJ++Pkzv6+ZOmeN/9Qvx0mRdXqnei1Lo3uu9bGvYHhoMI1VUkDT44hcpGbiokl/kuuYTayYa3yvmYTLZMplfMA==", + "dependencies": [ + "preact" + ] + }, + "preact@10.27.2": { + "integrity": "sha512-5SYSgFKSyhCbk6SrXyMpqjb5+MQBgfvEKE/OC+PujcY34sOpqtr+0AZQtPYx5IA6VxynQ7rUPCtKzyovpj9Bpg==" + }, + "rollup@4.52.5": { + "integrity": "sha512-3GuObel8h7Kqdjt0gxkEzaifHTqLVW56Y/bjN7PSQtkKr0w3V/QYSdt6QWYtd7A1xUtYQigtdUfgj1RvWVtorw==", + "dependencies": [ + "@types/estree" + ], + "optionalDependencies": [ + "@rollup/rollup-android-arm-eabi", + "@rollup/rollup-android-arm64", + "@rollup/rollup-darwin-arm64", + "@rollup/rollup-darwin-x64", + "@rollup/rollup-freebsd-arm64", + "@rollup/rollup-freebsd-x64", + "@rollup/rollup-linux-arm-gnueabihf", + "@rollup/rollup-linux-arm-musleabihf", + "@rollup/rollup-linux-arm64-gnu", + "@rollup/rollup-linux-arm64-musl", + "@rollup/rollup-linux-loong64-gnu", + "@rollup/rollup-linux-ppc64-gnu", + "@rollup/rollup-linux-riscv64-gnu", + "@rollup/rollup-linux-riscv64-musl", + "@rollup/rollup-linux-s390x-gnu", + "@rollup/rollup-linux-x64-gnu", + "@rollup/rollup-linux-x64-musl", + "@rollup/rollup-openharmony-arm64", + "@rollup/rollup-win32-arm64-msvc", + "@rollup/rollup-win32-ia32-msvc", + "@rollup/rollup-win32-x64-gnu", + "@rollup/rollup-win32-x64-msvc", + "fsevents" + ], + "bin": true + }, + "semver@6.3.1": { + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": true + }, + "source-map-js@1.2.1": { + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==" + }, + "tinyglobby@0.2.15_picomatch@4.0.3": { + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "dependencies": [ + "fdir", + "picomatch@4.0.3" + ] + }, + "undici-types@7.10.0": { + "integrity": "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag==" + }, + "update-browserslist-db@1.1.3_browserslist@4.26.3": { + "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", + "dependencies": [ + "browserslist", + "escalade", + "picocolors" + ], + "bin": true + }, + "vite@7.1.11_picomatch@4.0.3": { + "integrity": "sha512-uzcxnSDVjAopEUjljkWh8EIrg6tlzrjFUfMcR1EVsRDGwf/ccef0qQPRyOrROwhrTDaApueq+ja+KLPlzR/zdg==", + "dependencies": [ + "esbuild@0.25.11", + "fdir", + "picomatch@4.0.3", + "postcss", + "rollup", + "tinyglobby" + ], + "optionalDependencies": [ + "fsevents" + ], + "bin": true + }, + "vite@7.1.11_picomatch@4.0.3_@types+node@24.2.0": { + "integrity": "sha512-uzcxnSDVjAopEUjljkWh8EIrg6tlzrjFUfMcR1EVsRDGwf/ccef0qQPRyOrROwhrTDaApueq+ja+KLPlzR/zdg==", + "dependencies": [ + "@types/node", + "esbuild@0.25.11", + "fdir", + "picomatch@4.0.3", + "postcss", + "rollup", + "tinyglobby" + ], + "optionalDependencies": [ + "fsevents" + ], + "optionalPeers": [ + "@types/node" + ], + "bin": true + }, + "yallist@3.1.1": { + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + } + }, + "redirects": { + "https://deno.land/std/fs/walk.ts": "https://deno.land/std@0.224.0/fs/walk.ts" + }, + "remote": { + "https://deno.land/std@0.224.0/assert/assert.ts": "09d30564c09de846855b7b071e62b5974b001bb72a4b797958fe0660e7849834", + "https://deno.land/std@0.224.0/assert/assertion_error.ts": "ba8752bd27ebc51f723702fac2f54d3e94447598f54264a6653d6413738a8917", + "https://deno.land/std@0.224.0/fs/_create_walk_entry.ts": "5d9d2aaec05bcf09a06748b1684224d33eba7a4de24cf4cf5599991ca6b5b412", + "https://deno.land/std@0.224.0/fs/_to_path_string.ts": "29bfc9c6c112254961d75cbf6ba814d6de5349767818eb93090cecfa9665591e", + "https://deno.land/std@0.224.0/fs/walk.ts": "cddf87d2705c0163bff5d7767291f05b0f46ba10b8b28f227c3849cace08d303", + "https://deno.land/std@0.224.0/path/_common/assert_path.ts": "dbdd757a465b690b2cc72fc5fb7698c51507dec6bfafce4ca500c46b76ff7bd8", + "https://deno.land/std@0.224.0/path/_common/basename.ts": "569744855bc8445f3a56087fd2aed56bdad39da971a8d92b138c9913aecc5fa2", + "https://deno.land/std@0.224.0/path/_common/constants.ts": "dc5f8057159f4b48cd304eb3027e42f1148cf4df1fb4240774d3492b5d12ac0c", + "https://deno.land/std@0.224.0/path/_common/from_file_url.ts": "d672bdeebc11bf80e99bf266f886c70963107bdd31134c4e249eef51133ceccf", + "https://deno.land/std@0.224.0/path/_common/normalize.ts": "684df4aa71a04bbcc346c692c8485594fc8a90b9408dfbc26ff32cf3e0c98cc8", + "https://deno.land/std@0.224.0/path/_common/normalize_string.ts": "33edef773c2a8e242761f731adeb2bd6d683e9c69e4e3d0092985bede74f4ac3", + "https://deno.land/std@0.224.0/path/_common/strip_trailing_separators.ts": "7024a93447efcdcfeaa9339a98fa63ef9d53de363f1fbe9858970f1bba02655a", + "https://deno.land/std@0.224.0/path/_os.ts": "8fb9b90fb6b753bd8c77cfd8a33c2ff6c5f5bc185f50de8ca4ac6a05710b2c15", + "https://deno.land/std@0.224.0/path/basename.ts": "7ee495c2d1ee516ffff48fb9a93267ba928b5a3486b550be73071bc14f8cc63e", + "https://deno.land/std@0.224.0/path/from_file_url.ts": "911833ae4fd10a1c84f6271f36151ab785955849117dc48c6e43b929504ee069", + "https://deno.land/std@0.224.0/path/join.ts": "ae2ec5ca44c7e84a235fd532e4a0116bfb1f2368b394db1c4fb75e3c0f26a33a", + "https://deno.land/std@0.224.0/path/normalize.ts": "4155743ccceeed319b350c1e62e931600272fad8ad00c417b91df093867a8352", + "https://deno.land/std@0.224.0/path/posix/_util.ts": "1e3937da30f080bfc99fe45d7ed23c47dd8585c5e473b2d771380d3a6937cf9d", + "https://deno.land/std@0.224.0/path/posix/basename.ts": "d2fa5fbbb1c5a3ab8b9326458a8d4ceac77580961b3739cd5bfd1d3541a3e5f0", + "https://deno.land/std@0.224.0/path/posix/from_file_url.ts": "951aee3a2c46fd0ed488899d024c6352b59154c70552e90885ed0c2ab699bc40", + "https://deno.land/std@0.224.0/path/posix/join.ts": "7fc2cb3716aa1b863e990baf30b101d768db479e70b7313b4866a088db016f63", + "https://deno.land/std@0.224.0/path/posix/normalize.ts": "baeb49816a8299f90a0237d214cef46f00ba3e95c0d2ceb74205a6a584b58a91", + "https://deno.land/std@0.224.0/path/windows/_util.ts": "d5f47363e5293fced22c984550d5e70e98e266cc3f31769e1710511803d04808", + "https://deno.land/std@0.224.0/path/windows/basename.ts": "6bbc57bac9df2cec43288c8c5334919418d784243a00bc10de67d392ab36d660", + "https://deno.land/std@0.224.0/path/windows/from_file_url.ts": "ced2d587b6dff18f963f269d745c4a599cf82b0c4007356bd957cb4cb52efc01", + "https://deno.land/std@0.224.0/path/windows/join.ts": "8d03530ab89195185103b7da9dfc6327af13eabdcd44c7c63e42e27808f50ecf", + "https://deno.land/std@0.224.0/path/windows/normalize.ts": "78126170ab917f0ca355a9af9e65ad6bfa5be14d574c5fb09bb1920f52577780" + }, + "workspace": { + "dependencies": [ + "jsr:@fresh/core@^2.1.2", + "jsr:@fresh/plugin-vite@^1.0.5", + "npm:@preact/signals@^2.3.1", + "npm:preact@^10.27.2", + "npm:vite@^7.1.3" + ] + } +} diff --git a/islands/Code.tsx b/islands/Code.tsx new file mode 100644 index 0000000..fae6439 --- /dev/null +++ b/islands/Code.tsx @@ -0,0 +1,30 @@ +/** + * Copyright (c) 2025 xwra + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +import { ComponentChildren } from "preact"; + +interface CodeProps { + children: ComponentChildren; + [key: string]: any; +} + +export default function Code({ children, ...props }: CodeProps) { + const handleClick = () => { + if (typeof children === "string") { + navigator.clipboard.writeText(children); + } + }; + return ( + + {children} + + ); +} diff --git a/islands/Meow.tsx b/islands/Meow.tsx new file mode 100644 index 0000000..101786e --- /dev/null +++ b/islands/Meow.tsx @@ -0,0 +1,19 @@ +/** + * Copyright (c) 2025 xwra + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +export default function Meow() { + return ( + + ); +} diff --git a/islands/Name.tsx b/islands/Name.tsx new file mode 100644 index 0000000..9e9ee88 --- /dev/null +++ b/islands/Name.tsx @@ -0,0 +1,37 @@ +/** + * Copyright (c) 2025 xwra + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +import { useEffect, useState } from "preact/hooks"; + +export default function Name() { + const names = ["muxiepuff", "lívia", "aury"]; + const ipas = ["/ˈmuˌksipʌf/", "/li.vjɐ/", "/ˈaʊ̯ˌɾi/"] + ; + const [currentIndex, setCurrentIndex] = useState(0); + const [isAnimating, setIsAnimating] = useState(false); + + useEffect(() => { + const interval = setInterval(() => { + setIsAnimating(true); + setTimeout(() => { + setCurrentIndex((prev) => (prev + 1) % names.length); + setIsAnimating(false); + }, 200); + }, 2000); + return () => clearInterval(interval); + }, []); + + return ( + + + + {names[currentIndex]} + + {" "} + ({ipas[currentIndex]}, she/her) + + + ); +} diff --git a/islands/Rain.tsx b/islands/Rain.tsx new file mode 100644 index 0000000..e7a26de --- /dev/null +++ b/islands/Rain.tsx @@ -0,0 +1,374 @@ +/** + * Copyright (c) 2025 xwra + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +import { useEffect, useRef } from "preact/hooks"; + +interface Particle { + offsetX: number; + offsetY: number; + velocityX: number; + velocityY: number; +} + +interface Raindrop { + x: number; + y: number; + length: number; + speed: number; + opacity: number; + floorHeight: number; +} + +interface Splash { + x: number; + y: number; + age: number; + maxAge: number; + particles: Particle[]; +} + +interface Star { + x: number; + y: number; + size: number; + brightness: number; + twinkleSpeed: number; + twinkleOffset: number; + age: number; + maxAge: number; + canVanish: boolean; + color: { r: number; g: number; b: number }; + colorIndex: number; +} + +const PIXEL_SIZE = 4; +const DROP_COUNT = 300; +const RAIN_COLOR = { r: 87, g: 97, b: 100 }; +const BACKGROUND_COLOUR = "#16191C"; +const STAR_COUNT = 150; +const RAIN_SPEED = 0.75; + +const SPLASH_CHANCE = 0.3; +const FLOOR_HEIGHT_MIN = 0.55; +const FLOOR_HEIGHT_RANGE = 0.95; + +const PARTICLE_OFFSET_RANGE = 4; +const PARTICLE_Y_RANGE = 2; +const PARTICLE_Y_MIN = 1; +const PARTICLE_VX_RANGE = 0.8; +const PARTICLE_VY_RANGE = 0.5; +const PARTICLE_VY_MIN = 0.3; +const PARTICLE_GRAVITY = 0.15; + +const STAR_BRIGHTNESS_MIN = 0.6; +const STAR_BRIGHTNESS_RANGE = 0.4; +const STAR_LARGE_THRESHOLD = 0.7; +const STAR_SIZE_SMALL = 4; +const STAR_SIZE_LARGE = 8; +const STAR_TWINKLE_MIN = 0.002; +const STAR_TWINKLE_RANGE = 0.005; +const STAR_AGE_MIN = 60; +const STAR_AGE_RANGE = 120; +const STAR_TWINKLE_AMPLITUDE = 0.3; +const STAR_TWINKLE_BASE = 0.7; +const STAR_GLOW_THRESHOLD = 0.7; +const STAR_GLOW_ALPHA = 0.5; + +const RAIN_COLORS: string[] = []; +const STAR_COLORS: string[] = []; +const ALPHA_STAR_COLORS: string[] = []; +const NUM_COLOR_VARIATIONS = 20; + +for (let i = 0; i < NUM_COLOR_VARIATIONS; i++) { + const brightness = 1 - (i / NUM_COLOR_VARIATIONS) * 0.5; + RAIN_COLORS.push( + `rgb(${Math.floor(RAIN_COLOR.r * brightness)},${ + Math.floor(RAIN_COLOR.g * brightness) + },${Math.floor(RAIN_COLOR.b * brightness)})`, + ); +} + +for (let i = 0; i < NUM_COLOR_VARIATIONS; i++) { + const brightness = STAR_BRIGHTNESS_MIN + + (i / NUM_COLOR_VARIATIONS) * STAR_BRIGHTNESS_RANGE; + STAR_COLORS.push( + `rgb(${Math.floor(RAIN_COLOR.r * brightness)},${ + Math.floor(RAIN_COLOR.g * brightness) + },${Math.floor(RAIN_COLOR.b * brightness)})`, + ); + ALPHA_STAR_COLORS.push( + `rgba(${Math.floor(RAIN_COLOR.r * brightness)},${ + Math.floor(RAIN_COLOR.g * brightness) + },${Math.floor(RAIN_COLOR.b * brightness)},`, + ); +} + +const SPLASH_PARTICLE_COLOR = `rgb(${RAIN_COLOR.r * 0.9},${ + RAIN_COLOR.g * 0.95 +},${RAIN_COLOR.b * 1.1})`; +const SPLASH_RIPPLE_COLOR = `rgb(${RAIN_COLOR.r * 0.7},${RAIN_COLOR.g * 0.8},${ + RAIN_COLOR.b * 0.95 +})`; + +function createParticle(): Particle { + return { + offsetX: (Math.random() - 0.5) * PARTICLE_OFFSET_RANGE, + offsetY: -(Math.random() * PARTICLE_Y_RANGE + PARTICLE_Y_MIN), + velocityX: (Math.random() - 0.5) * PARTICLE_VX_RANGE, + velocityY: -(Math.random() * PARTICLE_VY_RANGE + PARTICLE_VY_MIN), + }; +} + +function createSplash(x: number, y: number): Splash { + return { + x, + y, + age: 0, + maxAge: 12, + particles: Array.from( + { length: Math.floor(Math.random() * 3) + 3 }, + createParticle, + ), + }; +} + +function createRaindrop(gridWidth: number, gridHeight: number): Raindrop { + const bias = Math.random() * Math.random(); + return { + x: Math.floor(Math.random() * gridWidth), + y: Math.floor(Math.random() * gridHeight) - gridHeight, + length: Math.floor(Math.random() * 4) + 2, + speed: RAIN_SPEED * (Math.random() * 2 + 1), + opacity: Math.random() * 0.3 + 0.6, + floorHeight: window.innerHeight * + (FLOOR_HEIGHT_MIN + bias * FLOOR_HEIGHT_RANGE), + }; +} + +function createStar(): Star { + const brightness = Math.random() * STAR_BRIGHTNESS_RANGE + + STAR_BRIGHTNESS_MIN; + const colorIndex = Math.floor( + (brightness - STAR_BRIGHTNESS_MIN) / STAR_BRIGHTNESS_RANGE * + (NUM_COLOR_VARIATIONS - 1), + ); + + return { + x: Math.random() * window.innerWidth, + y: Math.random() * window.innerHeight, + size: Math.random() > STAR_LARGE_THRESHOLD + ? STAR_SIZE_LARGE + : STAR_SIZE_SMALL, + twinkleSpeed: Math.random() * STAR_TWINKLE_RANGE + STAR_TWINKLE_MIN, + twinkleOffset: Math.random() * Math.PI * 2, + brightness, + age: 0, + maxAge: STAR_AGE_MIN + Math.random() * STAR_AGE_RANGE, + canVanish: false, + colorIndex, + }; +} + +function updateParticle(p: Particle) { + p.offsetX += p.velocityX; + p.offsetY += p.velocityY; + p.velocityY += PARTICLE_GRAVITY; +} + +function updateSplash(splash: Splash) { + splash.age++; + splash.particles.forEach(updateParticle); +} + +function updateRaindrop( + drop: Raindrop, + splashes: Splash[], + gridWidth: number, + gridHeight: number, +) { + drop.y += drop.speed; + const dropY = drop.y * PIXEL_SIZE; + + if (dropY >= drop.floorHeight && Math.random() < SPLASH_CHANCE) { + splashes.push(createSplash(drop.x, Math.floor(dropY / PIXEL_SIZE))); + Object.assign(drop, createRaindrop(gridWidth, gridHeight)); + } else if (dropY > window.innerHeight) { + Object.assign(drop, createRaindrop(gridWidth, gridHeight)); + } +} + +function updateStar(star: Star): void { + star.age++; + const phase = (star.age * star.twinkleSpeed + star.twinkleOffset) % + (2 * Math.PI); + + if (!star.canVanish && phase < star.twinkleSpeed) { + star.canVanish = true; + } + + if (star.canVanish && star.age > star.maxAge) { + Object.assign(star, createStar()); + } else if (star.x > window.innerWidth || star.y > window.innerHeight) { + Object.assign(star, createStar()); + } +} + +const isSplashDead = (splash: Splash): boolean => splash.age >= splash.maxAge; + +const drawRaindrop = (ctx: CanvasRenderingContext2D, drop: Raindrop): void => { + ctx.globalAlpha = drop.opacity; + const xPos = drop.x * PIXEL_SIZE; + + for (let i = 0; i < drop.length; i++) { + const colorIndex = Math.floor( + (i / drop.length) * NUM_COLOR_VARIATIONS * 0.5, + ); + ctx.fillStyle = RAIN_COLORS[colorIndex]; + ctx.fillRect(xPos, (drop.y - i) * PIXEL_SIZE, PIXEL_SIZE, PIXEL_SIZE); + } + ctx.globalAlpha = 1; +}; + +function drawSplash(ctx: CanvasRenderingContext2D, splash: Splash) { + if (splash.age >= splash.maxAge) return; + + const progress = splash.age / splash.maxAge; + ctx.globalAlpha = 1 - progress; + + ctx.fillStyle = SPLASH_PARTICLE_COLOR; + splash.particles.forEach((p) => { + const px = Math.floor(splash.x + p.offsetX) * PIXEL_SIZE; + const py = Math.floor(splash.y + p.offsetY) * PIXEL_SIZE; + ctx.fillRect(px, py, PIXEL_SIZE, PIXEL_SIZE); + }); + + if (splash.age < 6) { + const rippleSize = Math.floor(splash.age / 2) + 1; + const splashY = splash.y * PIXEL_SIZE; + ctx.fillStyle = SPLASH_RIPPLE_COLOR; + ctx.fillRect( + (splash.x - rippleSize) * PIXEL_SIZE, + splashY, + PIXEL_SIZE, + PIXEL_SIZE, + ); + ctx.fillRect( + (splash.x + rippleSize) * PIXEL_SIZE, + splashY, + PIXEL_SIZE, + PIXEL_SIZE, + ); + } + + ctx.globalAlpha = 1; +} + +function drawStar( + ctx: CanvasRenderingContext2D, + star: Star, + time: number, +) { + const twinkle = Math.sin(time * star.twinkleSpeed + star.twinkleOffset) * + STAR_TWINKLE_AMPLITUDE + STAR_TWINKLE_BASE; + const alpha = star.brightness * twinkle; + + const x = Math.floor(star.x); + const y = Math.floor(star.y); + const color = ALPHA_STAR_COLORS[star.colorIndex]; + + ctx.fillStyle = color + alpha; + ctx.fillRect(x, y, star.size, star.size); + + if (star.size === STAR_SIZE_LARGE && alpha > STAR_GLOW_THRESHOLD) { + ctx.fillStyle = color + (alpha * STAR_GLOW_ALPHA); + ctx.fillRect(x - 4, y + 2, 4, 4); + ctx.fillRect(x + 8, y + 2, 4, 4); + ctx.fillRect(x + 2, y - 4, 4, 4); + ctx.fillRect(x + 2, y + 8, 4, 4); + } +} + +export default function Rain() { + const canvasRef = useRef(null); + + useEffect(() => { + const prefersReducedMotion = + window.matchMedia("(prefers-reduced-motion: reduce)").matches; + if (prefersReducedMotion) return; + + const canvas = canvasRef.current; + if (!canvas) return; + + const ctx = canvas.getContext("2d"); + if (!ctx) return; + + let gridWidth = 0; + let gridHeight = 0; + + const resizeCanvas = () => { + canvas.width = window.innerWidth; + canvas.height = window.innerHeight; + gridWidth = Math.floor(window.innerWidth / PIXEL_SIZE); + gridHeight = Math.floor(window.innerHeight / PIXEL_SIZE); + }; + + resizeCanvas(); + window.addEventListener("resize", resizeCanvas); + + const stars = Array.from({ length: STAR_COUNT }, createStar); + const raindrops = Array.from( + { length: DROP_COUNT }, + () => createRaindrop(gridWidth, gridHeight), + ); + const splashes: Splash[] = []; + + const startTime = performance.now(); + + const animate = (time: number) => { + ctx.fillStyle = BACKGROUND_COLOUR; + ctx.fillRect(0, 0, canvas.width, canvas.height); + + for (let i = 0; i < stars.length; i++) { + updateStar(stars[i]); + drawStar(ctx, stars[i], time - startTime); + } + raindrops.forEach((drop) => + updateRaindrop(drop, splashes, gridWidth, gridHeight) + ); + for (let i = splashes.length - 1; i >= 0; i--) { + updateSplash(splashes[i]); + if (isSplashDead(splashes[i])) { + splashes.splice(i, 1); + } + } + + for (let i = 0; i < stars.length; i++) { + updateStar(stars[i]); + drawStar(ctx, stars[i], performance.now() - startTime); + } + raindrops.forEach((drop) => drawRaindrop(ctx, drop)); + splashes.forEach((splash) => drawSplash(ctx, splash)); + + requestAnimationFrame(animate); + }; + + animate(0); + }, []); + + return ( + + ); +} diff --git a/islands/Time.tsx b/islands/Time.tsx new file mode 100644 index 0000000..42f6162 --- /dev/null +++ b/islands/Time.tsx @@ -0,0 +1,49 @@ +/** + * Copyright (c) 2025 xwra + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +import { useEffect, useState } from "preact/hooks"; +import Box from "../components/Box.tsx"; + +export default function Time() { + const formatter = new Intl.DateTimeFormat("en-US", { + hour: "numeric", + minute: "numeric", + hour12: true, + timeZone: "America/Sao_Paulo", + }); + + const now = new Date(); + const time = formatter.format(now); + const [offset, setOffset] = useState(""); + + useEffect(() => { + const br = new Date( + now.toLocaleString("en-US", { + timeZone: "America/Sao_Paulo", + }), + ); + const local = new Date(now.toLocaleString("en-US")); + const diff = br.getTime() - local.getTime(); + const ms = Math.abs(diff); + const hours = ~~(ms / 36e5); + const minutes = ~~((ms / 6e4) % 60); + + let output = " · "; + if (hours) output += `You're ${hours} hour${hours > 1 ? "s" : ""} `; + if (hours && minutes) output += "and "; + if (minutes) output += `${minutes} minute${minutes > 1 ? "s" : ""} `; + if (hours || minutes) output += diff > 0 ? "behind" : "ahead"; + else output = " · Hey, we're in the same time zone!"; + + setOffset(output); + }, []); + + return ( + + Brasília Time, {time} + {offset} + + ); +} diff --git a/main.ts b/main.ts new file mode 100644 index 0000000..18bb82c --- /dev/null +++ b/main.ts @@ -0,0 +1,12 @@ +/** + * Copyright (c) 2025 xwra + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +import { App, staticFiles } from "fresh"; +import { type State } from "./utils.ts"; + +export const app = new App(); + +app.use(staticFiles()); +app.fsRoutes(); diff --git a/routes/_app.tsx b/routes/_app.tsx new file mode 100644 index 0000000..ede27a7 --- /dev/null +++ b/routes/_app.tsx @@ -0,0 +1,31 @@ +/** + * Copyright (c) 2025 xwra + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +import { define } from "../utils.ts"; + +export default define.page(function App({ Component }) { + return ( + + + + + + + + + + + + mux's winterhouse + + + + + + ); +}); diff --git a/routes/index.tsx b/routes/index.tsx new file mode 100644 index 0000000..169f6e4 --- /dev/null +++ b/routes/index.tsx @@ -0,0 +1,308 @@ +/** + * Copyright (c) 2025 xwra + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +import { define } from "../utils.ts"; +import Time from "../islands/Time.tsx"; +import Rain from "../islands/Rain.tsx"; +import { Centered, Section } from "../components/Layout.tsx"; +import Title from "../components/Title.tsx"; +import TintedImage from "../components/Tinted.tsx"; +import Link from "../components/Link.tsx"; +import Header from "../components/Header.tsx"; +import Footer from "../components/Footer.tsx"; +import Box from "../components/Box.tsx"; +import Meow from "../islands/Meow.tsx"; +import Name from "../islands/Name.tsx"; +import Code from "../islands/Code.tsx"; +import { + AttachmentIcon, + BlueskyIcon, + CodebergIcon, + DiscordIcon, + ForgejoIcon, + GitHubIcon, + LabelIcon, + LastfmIcon, + MailIcon, + SignalIcon, + TwitterIcon, + CommentIcon, + HeartIcon, + KofiIcon, + BitcoinIcon, + BitcoinCashIcon, + MoneroIcon, + NanoIcon, + LitecoinIcon, + EthereumIcon, +} from "../components/Icon.tsx"; + +export default define.page(() => { + return ( + <> + + +
+
+ + <HeartIcon class="icon" /> + About me + +

+ + {" "} + muxiepuff{" "} + (/ˈmuˌksipʌf/, she/her) + {" · "} + + I'm just your average advocate for open access to information and + knowledge and aspiring electrical engineer with complementary + interests in systems programming and linguistics. Neurodivergent + student passionate about libre software. +

+

+ On the side, I maintain a modest FreeBSD server where I self-host + this website and various services. This is nothing particularly + impressive, just a growing curiosity about systems administration. + Service status and uptime available{" "} + here. +

+
+
+ + <LabelIcon class="icon" /> + Links + +
+ Social platforms +
    +
  • + + @acpi.at + +
  • +
  • + + @auwora + +
  • +
+
+
+ Software and code +
    +
  • + + mux + +
  • +
  • + + ex + +
  • +
  • + + xwra + +
  • +
+
+
+ Congenial folks + +
+
+
+ + <CommentIcon class="icon" /> + Contact + +

+ Feel free to reach out through any of the platforms listed above. + For email correspondence, you can reach me at{" "} + base64 -d <<< bXV4QGFjcGkuYXQK. +

+

+ Psst! When discussing sensitive matters over email or other insecure + communication channels, I'd really appreciate it if you could + encrypt your message with my PGP key{" "} + (fingerprint:{" "} + AC14 9A39 5013 C572 CA74 8799 BCD2 117C 99E6 9817). +

+
+ Communication +
    +
  • + + @muxiepuff + +
  • +
  • + + @mux.01 + +
  • +
+
+
+

+ If you enjoy throwing money at people on the internet, please + consider me! It keeps the server alive, fuels my tinkering with + esoteric technology, and helps me navigate some rough financial + patches and stay afloat while things are tight. +

+
+ Donations +
    +
  • + + west + +
  • +
  • + + {" "} + 456tmp4CU158sV95Pjh75QfMcANNsRCFTdpmc86G31eKg9urvcYunnuBVyUmazAbuihUXwRDVojkhFTbzg6X2GuAJ7t3MCT + +
  • +
  • + + ltc1ql30jtr2r0pkr0wshspf465rdupvlpmwacql7wp + +
  • +
  • + + {" "}nano_1qbbwrzxnutw53kuykdo6zcwteawf3befpbf95zrz66b33yxpz5ans6wrw4w + +
  • +
  • + + {" "} bc1qj3l6cpxz604vlfz5zqlnhzr7g0aq7xlslnmzcm + +
  • +
  • + + {" "}bitcoincash:qrs8y70dwzvz2kvxnv30c9k4pxa0vatzvudle5aaa3 + +
  • +
  • + + {" "}0x9bb671035Dde19C674769592AbC20E63f36b5Aa9 + +
  • +
+
+
+
+ + <AttachmentIcon class="icon" /> + Extra + +
    +
  • + +
  • +
  • + +
  • +
+
+