commit 66b9ea60540218a78424646bb68da4d24e18874a Author: Fi3w0 Date: Tue Aug 11 16:26:50 2026 +0200 chore: capture homepage baseline diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..613d739 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,10 @@ +.git +.gitignore +.idea +.cache +dist +node_modules +npm-debug.log* +.DS_Store +.env +DEPLOY.md diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..f29d257 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,11 @@ +# editorconfig.org + +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_size = 2 +indent_style = space +insert_final_newline = true +trim_trailing_whitespace = true diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..2e9729a --- /dev/null +++ b/.env.example @@ -0,0 +1,4 @@ +DOMAIN=fiwlabs.dev +TRAEFIK_NETWORK=proxy +TRAEFIK_HTTPS_ENTRYPOINT=websecure +TRAEFIK_CERT_RESOLVER=porkbun diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..c664a90 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,194 @@ +## GITATTRIBUTES FOR WEB PROJECTS +# +# These settings are for any web project. +# +# Details per file setting: +# text These files should be normalized (i.e. convert CRLF to LF). +# binary These files are binary and should be left untouched. +# +# Note that binary is a macro for -text -diff. +###################################################################### + +## AUTO-DETECT +## Handle line endings automatically for files detected as +## text and leave all files detected as binary untouched. +## This will handle all files NOT defined below. +* text=auto + +## SOURCE CODE +*.bat text eol=crlf +*.coffee text +*.css text +*.htm text +*.html text +*.inc text +*.ini text +*.js text +*.json text +*.jsx text +*.less text +*.od text +*.onlydata text +*.php text +*.pl text +*.py text +*.rb text +*.sass text +*.scm text +*.scss text +*.sh text eol=lf +*.sql text +*.styl text +*.tag text +*.ts text +*.tsx text +*.xml text +*.xhtml text + +## DOCKER +*.dockerignore text +Dockerfile text + +## DOCUMENTATION +*.markdown text +*.md text +*.mdwn text +*.mdown text +*.mkd text +*.mkdn text +*.mdtxt text +*.mdtext text +*.txt text +AUTHORS text +CHANGELOG text +CHANGES text +CONTRIBUTING text +COPYING text +copyright text +*COPYRIGHT* text +INSTALL text +license text +LICENSE text +NEWS text +readme text +*README* text +TODO text + +## TEMPLATES +*.dot text +*.ejs text +*.haml text +*.handlebars text +*.hbs text +*.hbt text +*.jade text +*.latte text +*.mustache text +*.njk text +*.phtml text +*.tmpl text +*.tpl text +*.twig text + +## LINTERS +.babelrc text +.csslintrc text +.eslintrc text +.htmlhintrc text +.jscsrc text +.jshintrc text +.jshintignore text +.prettierrc text +.stylelintrc text + +## CONFIGS +*.bowerrc text +*.cnf text +*.conf text +*.config text +.browserslistrc text +.editorconfig text +.gitattributes text +.gitconfig text +.gitignore text +.htaccess text +*.npmignore text +*.yaml text +*.yml text +browserslist text +Makefile text +makefile text + +## HEROKU +Procfile text +.slugignore text + +## GRAPHICS +*.ai binary +*.bmp binary +*.eps binary +*.gif binary +*.ico binary +*.jng binary +*.jp2 binary +*.jpg binary +*.jpeg binary +*.jpx binary +*.jxr binary +*.pdf binary +*.png binary +*.psb binary +*.psd binary +*.svg text +*.svgz binary +*.tif binary +*.tiff binary +*.wbmp binary +*.webp binary + +## AUDIO +*.kar binary +*.m4a binary +*.mid binary +*.midi binary +*.mp3 binary +*.ogg binary +*.ra binary + +## VIDEO +*.3gpp binary +*.3gp binary +*.as binary +*.asf binary +*.asx binary +*.fla binary +*.flv binary +*.m4v binary +*.mng binary +*.mov binary +*.mp4 binary +*.mpeg binary +*.mpg binary +*.ogv binary +*.swc binary +*.swf binary +*.webm binary + +## ARCHIVES +*.7z binary +*.gz binary +*.jar binary +*.rar binary +*.tar binary +*.zip binary + +## FONTS +*.ttf binary +*.eot binary +*.otf binary +*.woff binary +*.woff2 binary + +## EXECUTABLES +*.exe binary +*.pyc binary diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..888249e --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +node_modules +dist +.cache +.idea/ +*.iml +.DS_Store +.env diff --git a/404.html b/404.html new file mode 100644 index 0000000..dcbcdef --- /dev/null +++ b/404.html @@ -0,0 +1,28 @@ + + + + + + + 404 - Fi3w0 + + + + + + + + + + + + +
+

HTTP 404 / route not found

+

Wrong path. Good terminal.

+

The requested route is not running on this host. Return to the system index and try another direction.

+ Back to fi3w0 +
+ + + diff --git a/DEPLOY.md b/DEPLOY.md new file mode 100644 index 0000000..c299dc5 --- /dev/null +++ b/DEPLOY.md @@ -0,0 +1,50 @@ +# Server deployment + +The production image builds the Webpack site with Node and serves the generated `dist/` directory with Nginx. The container does not publish a host port; Traefik reaches it over an external Docker network. + +## Defaults + +| Setting | Default | +| --- | --- | +| Domain | `fiwlabs.dev` | +| Traefik network | `proxy` | +| HTTPS entrypoint | `websecure` | +| Certificate resolver | `porkbun` | + +Compose reads overrides from `.env`. The available keys and defaults are documented in `.env.example`. + +## Prerequisites + +1. Point the `A` and optional `AAAA` records for `fiwlabs.dev` to the server. +2. Ensure Traefik has its Docker provider enabled. +3. Attach Traefik to the same external network configured by `TRAEFIK_NETWORK`. +4. Ensure the configured certificate resolver exists in Traefik. + +Create the default shared network once if the Traefik stack has not already created it: + +```sh +docker network create proxy +``` + +## Deploy + +Validate the resolved Compose configuration: + +```sh +docker compose -f docker-compose.yml config +``` + +Build and start the site: + +```sh +docker compose -f docker-compose.yml up --build -d +``` + +Check container health and logs: + +```sh +docker compose -f docker-compose.yml ps +docker compose -f docker-compose.yml logs -f fiws-page +``` + +The container exposes `/healthz` internally for Docker health checks. Traefik serves the site at `https://fiwlabs.dev`; the server's `web` entrypoint redirects HTTP requests to HTTPS globally. diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..20435c3 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,21 @@ +# syntax=docker/dockerfile:1.7 + +FROM node:22-alpine AS build + +WORKDIR /app + +COPY package.json package-lock.json ./ +RUN npm ci --ignore-scripts + +COPY . . +RUN npm run build + +FROM nginx:1.27-alpine AS runtime + +COPY deploy/nginx.conf /etc/nginx/conf.d/default.conf +COPY --from=build /app/dist /usr/share/nginx/html + +EXPOSE 80 + +HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ + CMD wget -q -O /dev/null http://127.0.0.1/healthz || exit 1 diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..294e91d --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,19 @@ +Copyright (c) HTML5 Boilerplate + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/css/editorial.css b/css/editorial.css new file mode 100644 index 0000000..54239a9 --- /dev/null +++ b/css/editorial.css @@ -0,0 +1,1816 @@ +:root { + --bg: #101a21; + --bg-soft: #17252e; + --surface: #1e2e38; + --surface-2: #283b46; + --paper: #e9e5da; + --paper-deep: #d8d2c3; + --ink: #11171a; + --text: #edf1e9; + --muted: #b2bfbd; + --muted-dark: #5c6665; + --line: #66767c; + --line-dark: #8d918a; + --coral: #f0996e; + --coral-bright: #ffad82; + --cyan: #8fd4d0; + --lime: #c8ee80; + --yellow: #f3d277; + --display: "Archivo Black", "Arial Black", sans-serif; + --mono: "IBM Plex Mono", "Courier New", monospace; + --page-pad: clamp(1.25rem, 4vw, 4rem); + --max-width: 92rem; + --radius-sm: 0; + --radius-md: 0; + --radius-lg: 0; +} + +body { + background: var(--bg); + font-size: clamp(1rem, 1.05vw, 1.08rem); + line-height: 1.62; +} + +.terminal-card::before, +.current-project::before, +.project-visual::after { + display: none; +} + +body::before { + opacity: 0.8; +} + +.page-grid { + display: block; + opacity: 0.26; +} + +h1, +h2, +h3 { + font-weight: 400; + letter-spacing: -0.055em; +} + +code { + border-width: 2px; + border-radius: 0; +} + +:focus-visible { + outline: 4px solid var(--lime); + outline-offset: 3px; +} + +.site-header { + top: 0; + left: 0; + width: 100%; + min-height: 4.5rem; + padding: 0.65rem var(--page-pad); + transform: none; + border: 0; + border-bottom: 2px solid var(--line); + border-radius: 0; + background: var(--bg); + box-shadow: none; + backdrop-filter: none; +} + +.brand { + gap: 0.8rem; + font-family: var(--mono); + font-size: 1rem; + font-weight: 600; + letter-spacing: 0.04em; + text-transform: uppercase; +} + +.brand-mark { + width: 2.55rem; + height: 2.55rem; + border: 2px solid var(--coral); + border-radius: 0; + background: transparent; + color: var(--coral); +} + +.site-nav { + gap: clamp(1rem, 2.7vw, 2.8rem); +} + +.site-nav a { + font-size: 0.75rem; + font-weight: 600; +} + +.site-nav > a:not(.nav-pill)::after { + bottom: -0.25rem; + height: 3px; +} + +.nav-pill { + padding: 0.45rem 0 0.45rem 1.1rem; + border: 0; + border-left: 2px solid var(--line); + border-radius: 0; +} + +.nav-pill:hover { + border-color: var(--line); + background: transparent; + color: var(--lime); +} + +.hero { + position: relative; + min-height: 48rem; + padding-top: clamp(8rem, 13vh, 10rem); + padding-bottom: clamp(5rem, 8vh, 7rem); + grid-template-columns: minmax(0, 7fr) minmax(24rem, 4fr); + align-items: center; + gap: clamp(3rem, 7vw, 7rem); +} + +.hero::after { + position: absolute; + z-index: 0; + top: 16%; + right: -0.08em; + color: rgba(143, 212, 208, 0.065); + content: "/SYS"; + font-family: var(--display); + font-size: clamp(10rem, 23vw, 23rem); + letter-spacing: -0.1em; + line-height: 0.75; + pointer-events: none; +} + +/* Liquid ASCII — a hand-built ripple/height-field simulation (no external + registry, no CDN), filling the whole hero as a body of "water" visitors + can stir with a cursor or finger. Sits behind hero-copy/terminal-card; + calm water renders almost blank, so ripples read as bright disturbance + rather than a flat gray texture. */ +.hero-liquid { + position: absolute; + z-index: 0; + top: 0; + bottom: 0; + left: 50%; + width: 100vw; + overflow: hidden; + cursor: crosshair; + transform: translateX(-50%); +} + +.hero-liquid-pre { + position: absolute; + inset: 0; + margin: 0; + padding: 0; + overflow: hidden; + color: rgba(143, 212, 208, 0.55); + line-height: 1em; + mix-blend-mode: screen; + white-space: pre; + user-select: none; +} + +.hero-liquid-hint { + position: absolute; + right: 0.9rem; + bottom: 0.7rem; + margin: 0; + color: rgba(143, 212, 208, 0.4); + font-family: var(--mono); + font-size: 0.62rem; + letter-spacing: 0.06em; + text-transform: uppercase; + pointer-events: none; +} + +@media (max-width: 40rem), (pointer: coarse) { + .hero-liquid-hint { + display: none; + } +} + +@media (prefers-reduced-motion: reduce) { + .hero-liquid { + display: none; + } +} + +.eyebrow, +.section-index, +.project-kicker, +.stack-label { + margin-bottom: 1.25rem; + font-size: 0.76rem; + font-weight: 600; + letter-spacing: 0.08em; +} + +.eyebrow { + color: var(--cyan); +} + +.status-dot { + width: 0.65rem; + height: 0.65rem; + border: 2px solid var(--lime); + border-radius: 0; + background: transparent; + box-shadow: none; +} + +.status-dot::after { + display: block; +} + +.hero h1 { + max-width: none; + margin-bottom: 2.4rem; + font-size: clamp(5rem, 9.8vw, 9.6rem); + line-height: 0.83; + letter-spacing: -0.075em; +} + +.hero h1 span { + color: var(--coral); +} + +.hero-intro { + max-width: 47rem; + margin-bottom: 2rem; + color: var(--text); + font-size: clamp(1.05rem, 1.35vw, 1.25rem); + line-height: 1.55; +} + +.hero-actions { + gap: 2.4rem; + margin-bottom: 3.2rem; +} + +.button { + min-height: auto; + padding: 0.6rem 0 0.4rem; + border: 0; + border-bottom: 3px solid currentColor; + border-radius: 0; + font-size: 0.8rem; + transition: color 120ms ease; +} + +.button:hover { + transform: translateY(-2px); + color: var(--lime); +} + +.button-primary, +.button-primary:hover, +.button-ghost:hover { + border-color: currentColor; + background: transparent; + color: inherit; +} + +.button-primary { + color: var(--coral); +} + +.button-primary:hover, +.button-ghost:hover { + color: var(--lime); +} + +.hero-signals { + max-width: 48rem; + border-top: 3px solid var(--line); + border-bottom: 1px solid var(--line); +} + +.hero-signals li { + padding: 0.85rem 0.8rem 0.85rem 0; + color: var(--muted); + font-size: 0.7rem; +} + +.hero-signals li + li { + padding-left: 0.8rem; + border-left: 1px solid var(--line); +} + +.hero-signals span { + color: var(--coral); +} + +.terminal-card { + overflow: visible; + border: 2px solid rgba(143, 212, 208, 0.35); + border-radius: 0; + background: var(--bg-soft); + box-shadow: none; + transform: rotate(1deg); + transition: transform 220ms ease, border-color 220ms ease; +} + +.terminal-card:hover { + transform: rotate(0.35deg) translateY(-0.3rem); + border-color: rgba(143, 212, 208, 0.7); +} + +.terminal-chrome { + display: flex; + min-height: 3.3rem; + justify-content: space-between; + padding: 0 1.2rem; + border-bottom: 2px solid rgba(143, 212, 208, 0.25); + color: var(--muted); + font-size: 0.72rem; +} + +.terminal-state { + color: var(--lime); +} + +.terminal-body { + min-height: 25rem; + padding: 2rem; + font-size: 0.86rem; +} + +.terminal-body > p { + margin-bottom: 0.65rem; +} + +.terminal-output { + margin: 0 0 1.5rem 1.5rem; + color: var(--muted); +} + +.terminal-output span, +.prompt { + color: var(--coral); +} + +.terminal-note { + margin-top: 2rem; + color: var(--lime); + font-style: italic; +} + +.profile-chip { + right: -1.4rem; + bottom: -3.5rem; + width: min(18rem, 80%); + min-height: 5rem; + padding: 0.6rem; + border: 2px solid rgba(240, 153, 110, 0.55); + border-radius: 0; + background: var(--bg-soft); + color: var(--text); + box-shadow: none; + grid-template-columns: 4rem 1fr; + transform: rotate(-3deg); + backdrop-filter: none; + transition: transform 220ms ease, border-color 220ms ease; +} + +.profile-chip:hover { + transform: rotate(-1deg) translateY(-0.2rem); + border-color: var(--coral); +} + +.profile-chip img { + width: 4rem; + height: 4rem; + border: 1px solid var(--line); + border-radius: 0; +} + +.profile-chip strong { + font-family: var(--mono); + font-size: 0.85rem; +} + +.profile-chip div span { + color: var(--muted); + font-size: 0.62rem; +} + +.signal-strip { + border-top: 3px solid var(--ink); + border-bottom: 3px solid var(--ink); + background: var(--coral); +} + +.signal-track { + min-height: 3.7rem; +} + +.signal-set { + gap: clamp(0.9rem, 2.2vw, 2rem); + padding-right: clamp(0.9rem, 2.2vw, 2rem); +} + +.signal-item { + font-family: var(--mono); + font-size: 0.72rem; + font-weight: 600; +} + +.signal-track i { + width: 2px; + height: 1rem; + transform: rotate(18deg); +} + +.section { + padding-top: clamp(4.5rem, 7vw, 6.5rem); + padding-bottom: clamp(4.5rem, 7vw, 6.5rem); +} + +.section-heading { + margin-bottom: clamp(3.5rem, 6vw, 5.5rem); + padding-top: 1.3rem; + border-top: 5px solid currentColor; + grid-template-columns: minmax(9rem, 2fr) minmax(0, 10fr); +} + +.section-index { + color: var(--coral); +} + +.section-heading h2 { + max-width: 14ch; + font-size: clamp(3.4rem, 6.5vw, 6.4rem); + line-height: 0.94; +} + +.section-heading-row { + grid-template-columns: minmax(0, 8fr) minmax(18rem, 4fr); +} + +.section-heading-row > p { + margin-top: 0.25rem; + color: var(--muted); + font-size: 0.9rem; +} + +.about-section, +.archive-section { + background: var(--paper); + box-shadow: 0 0 0 100vmax var(--paper); +} + +.work-section { + position: relative; +} + +.about-section::before, +.archive-section::before, +.work-section::before, +.stack-section::after { + position: absolute; + z-index: 0; + right: -0.04em; + font-family: var(--display); + font-size: clamp(12rem, 25vw, 25rem); + letter-spacing: -0.1em; + line-height: 0.75; + pointer-events: none; +} + +.about-section::before { + top: 2.5rem; + color: rgba(17, 23, 26, 0.035); + content: "01"; +} + +.archive-section::before { + top: 2.5rem; + color: rgba(17, 23, 26, 0.035); + content: "03"; +} + +.work-section::before { + top: 4rem; + color: rgba(240, 153, 110, 0.055); + content: "02"; +} + +.stack-section::after { + right: 0; + bottom: 2rem; + color: rgba(143, 212, 208, 0.055); + content: "04"; +} + +.about-section > *, +.archive-section > *, +.work-section > *, +.stack-section > * { + position: relative; + z-index: 1; +} + +.about-section .section-index, +.archive-section .section-index { + color: #a74b2c; +} + +.about-layout { + gap: clamp(3rem, 7vw, 7rem); + grid-template-columns: minmax(18rem, 5fr) minmax(0, 7fr); +} + +.about-quote { + padding: 1.2rem 0 0 1.8rem; + border-top: 0; + border-left: 0.7rem solid var(--coral); +} + +.quote-mark { + display: none; +} + +.about-quote p { + margin-bottom: 2rem; + font-size: clamp(2rem, 3.4vw, 3.5rem); + line-height: 1.05; +} + +.about-quote footer { + color: var(--muted-dark); + font-size: 0.78rem; +} + +.about-copy p { + color: #3f4848; + font-size: 1rem; +} + +.about-copy .lead { + font-family: var(--mono); + font-size: clamp(1.2rem, 1.7vw, 1.6rem); + font-weight: 600; + letter-spacing: -0.02em; + line-height: 1.45; +} + +.language-line { + gap: 1.4rem; + margin-top: 2.5rem; +} + +.language-line span { + padding: 0.25rem 0; + border: 0; + border-bottom: 3px solid var(--ink); + border-radius: 0; + font-size: 0.68rem; +} + +.method-grid { + margin-top: clamp(4rem, 7vw, 7rem); + border-top: 5px solid var(--ink); + border-bottom: 2px solid var(--ink); + grid-template-columns: 5fr 4fr 3fr; +} + +.method-card { + min-height: 18rem; + padding: 1.5rem clamp(1rem, 2.5vw, 2.2rem) 2rem; +} + +.method-card + .method-card { + border-left: 2px solid var(--ink); +} + +.method-card > span { + color: #a74b2c; + font-size: 0.75rem; + font-weight: 600; +} + +.method-card h3 { + margin-top: 3.6rem; + font-size: clamp(1.5rem, 2.5vw, 2.4rem); +} + +.method-card p { + color: var(--muted-dark); + font-size: 0.8rem; +} + +.current-project { + min-height: 35rem; + margin: 0 0 4rem; + overflow: hidden; + border: 2px solid rgba(17, 23, 26, 0.28); + border-radius: 0; + background: var(--cyan); + grid-template-columns: minmax(0, 7fr) minmax(22rem, 5fr); + transition: transform 220ms ease, border-color 220ms ease; +} + +.current-project:hover { + transform: translateY(-0.3rem); + border-color: rgba(17, 23, 26, 0.62); +} + +.current-project-main, +.current-roadmap { + padding: clamp(2rem, 4vw, 3.5rem); +} + +.current-meta { + padding-bottom: 0.8rem; + border-bottom: 2px solid rgba(23, 20, 15, 0.4); + font-size: 0.66rem; +} + +.current-meta i { + width: 0.55rem; + height: 0.55rem; + border-radius: 0; + background: var(--ink); + box-shadow: none; +} + +.current-kicker { + margin-top: auto; + font-size: 0.72rem; +} + +.current-project h3 { + margin-bottom: 1.5rem; + font-size: clamp(4.5rem, 8.5vw, 8.5rem); + line-height: 0.85; +} + +.current-project-main > p:not(.current-kicker) { + max-width: 43rem; + font-size: 0.9rem; +} + +.tag-row { + gap: 0; +} + +.tag-row span { + padding: 0; + border: 0; + border-radius: 0; + font-size: 0.62rem; +} + +.tag-row span + span::before { + margin: 0 0.65rem; + content: "/"; +} + +.current-roadmap { + border-left: 3px solid rgba(23, 20, 15, 0.7); + background: transparent; + backdrop-filter: none; +} + +.current-roadmap > p { + font-size: 0.7rem; +} + +.current-roadmap ol { + border-top: 3px solid var(--ink); +} + +.current-roadmap li { + min-height: 6rem; + border-bottom: 1px solid rgba(23, 20, 15, 0.55); +} + +.current-roadmap strong { + font-family: var(--mono); + font-size: 0.9rem; +} + +.current-roadmap li > span, +.current-roadmap li > b, +.current-roadmap small { + font-size: 0.6rem; +} + +.current-roadmap li > b { + border: 0; + border-radius: 0; + background: var(--ink); + color: var(--cyan); +} + +.current-roadmap small a { + color: var(--ink); + text-decoration: underline; + text-decoration-thickness: 1px; + text-underline-offset: 0.15em; +} + +.current-watermark { + bottom: -0.18em; + color: rgba(255, 255, 255, 0.13); + font-size: clamp(9rem, 19vw, 18rem); + transition: transform 700ms cubic-bezier(0.2, 0.75, 0.25, 1), opacity 500ms ease; +} + +.current-project:hover .current-watermark { + transform: translateX(1.2rem); +} + +.current-project.has-tide-ascii .current-watermark { + opacity: 0; +} + +/* ASCIIText, ported from React Bits to vanilla JS/three.js. Lazily mounted + (see app.js) to replace the flat "TIDE" watermark with a rippling, + wave-distorted ASCII render — a nod to the compositor's water theme. + Falls back to the plain watermark above if WebGL/three.js is unavailable. */ +.tide-ascii { + position: absolute; + z-index: 1; + bottom: -9%; + left: -6%; + width: min(82rem, 126%); + height: 55%; + opacity: 0; + pointer-events: none; + transition: opacity 900ms ease; +} + +.tide-ascii.is-ready { + opacity: 0.6; +} + +.tide-ascii-inner { + position: absolute; + inset: 0; +} + +.tide-ascii-canvas { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + opacity: 0.7; + filter: saturate(1.4); + image-rendering: pixelated; +} + +.tide-ascii-pre { + position: absolute; + top: 0; + left: 0; + z-index: 2; + margin: 0; + padding: 0; + overflow: hidden; + color: rgba(17, 23, 26, 0.86); + line-height: 1em; + mix-blend-mode: multiply; + white-space: pre; + user-select: none; +} + +@media (max-width: 68rem) { + .tide-ascii { + display: none; + } + + .current-project.has-tide-ascii .current-watermark { + opacity: 1; + } +} + +.project-visual-flux.has-flux-ascii .flux-watermark { + opacity: 0; +} + +.flux-ascii { + position: absolute; + z-index: 1; + bottom: 34%; + left: -14%; + width: min(58rem, 118%); + height: 88%; + opacity: 0; + pointer-events: none; + transition: opacity 900ms ease; +} + +.flux-ascii.is-ready { + opacity: 0.85; +} + +@media (max-width: 64rem) { + .flux-ascii { + display: none; + } + + .project-visual-flux.has-flux-ascii .flux-watermark { + opacity: 1; + } +} + +.project-feature { + min-height: 38rem; + margin-bottom: 4rem; + overflow: visible; + border: 0; + border-radius: 0; + background: transparent; + grid-template-columns: minmax(0, 8fr) minmax(20rem, 4fr); + gap: 2rem; +} + +.project-visual { + min-height: 34rem; + border: 2px solid var(--line); +} + +.project-visual img { + filter: saturate(0.88) contrast(1.05); + transition: transform 700ms cubic-bezier(0.2, 0.7, 0.2, 1), filter 300ms ease; +} + +.project-visual:hover img { + transform: scale(1.025); + filter: saturate(1) contrast(1.04); +} + +.image-label { + bottom: 1rem; + left: 1.2rem; + padding: 0.55rem 0.8rem; + border: 1px solid var(--line); + border-radius: 0; + background: var(--bg); + color: var(--text); + font-size: 0.63rem; + backdrop-filter: none; +} + +.project-feature-copy { + padding: 2rem 0 0; + border-top: 3px solid var(--line); +} + +.project-meta { + color: var(--cyan); + font-size: 0.65rem; +} + +.project-feature-copy h3 { + margin-top: auto; + font-size: clamp(3rem, 5vw, 5rem); +} + +.project-feature-copy > p { + color: var(--text); + font-size: 0.86rem; +} + +.project-facts { + border-top-width: 3px; + border-bottom-width: 2px; +} + +.project-facts strong { + color: var(--lime); +} + +.project-facts span { + font-size: 0.62rem; +} + +/* Flux visual card — bring the glassy/rounded chrome in line with the + flat, bordered, no-blur language used by the rest of the site + (image-label, current-roadmap badges, tag-row). */ +.flux-chrome i { + border-radius: 50%; + box-shadow: inset 0 0 0 1px rgba(11, 16, 20, 0.5); +} + +.flux-icon { + box-shadow: 0 0.6rem 1.6rem rgba(4, 9, 13, 0.4); +} + +.project-visual-flux:hover .flux-icon { + box-shadow: 0 0.9rem 2rem rgba(4, 9, 13, 0.45); +} + +.flux-tags span { + border: 1px solid var(--line); + border-radius: 0; + background: rgba(11, 16, 20, 0.72); + color: var(--text); + backdrop-filter: none; + -webkit-backdrop-filter: none; +} + +.flux-stack { + border: 1px solid var(--line); + border-radius: 0; + background: rgba(11, 16, 20, 0.78); + backdrop-filter: none; + -webkit-backdrop-filter: none; +} + +.flux-stack > b { + border-bottom: 1px solid rgba(237, 241, 233, 0.2); + color: var(--muted); +} + +.flux-stack-row + .flux-stack-row { + border-top: 1px solid rgba(237, 241, 233, 0.12); +} + +.flux-stack-row > span:first-child { + color: var(--cyan); +} + +.flux-stack-row > span:last-child { + color: var(--text); +} + +.flux-stack-row small { + color: var(--muted); +} + +.flux-status { + color: var(--text); +} + +.flux-status i { + border-radius: 50%; + box-shadow: none; +} + +.flux-watermark { + color: rgba(255, 255, 255, 0.22); +} + +.text-link { + border-bottom-width: 3px; + font-size: 0.74rem; +} + +.project-grid { + gap: 1.5rem; + margin-bottom: 3.5rem; + grid-template-columns: minmax(0, 7fr) minmax(20rem, 5fr); + align-items: start; +} + +.project-card { + min-height: 31rem; + overflow: hidden; + border: 3px solid var(--ink); + border-radius: 0; + transition: transform 220ms ease, box-shadow 220ms ease; +} + +.project-card:hover { + transform: translate(-0.35rem, -0.35rem); + box-shadow: 0.55rem 0.55rem 0 rgba(237, 241, 233, 0.24); +} + +.project-card-warm { + background: var(--coral); +} + +.project-card-cool { + margin-top: 5rem; + background: var(--cyan); +} + +.project-card h3 { + font-size: clamp(3rem, 5.5vw, 5.6rem); +} + +.project-card p:last-child { + font-size: 0.88rem; +} + +.card-footer > a { + width: auto; + height: auto; + padding: 0.35rem 0; + border: 0; + border-bottom: 3px solid var(--ink); + border-radius: 0; +} + +.card-footer > a:hover { + transform: none; + background: transparent; + color: var(--ink); +} + +.project-list { + margin-bottom: 4rem; + border-top: 5px solid var(--text); +} + +.project-row { + min-height: 8.5rem; + border-bottom: 2px solid var(--line); + grid-template-columns: 2.5rem minmax(12rem, 0.65fr) minmax(16rem, 1fr) minmax(8rem, auto) 2rem; +} + +.project-row:hover { + padding-right: 0; + padding-left: 1rem; + background: transparent; + box-shadow: inset 0.45rem 0 var(--coral); +} + +.row-index, +.row-tech, +.project-row > div > p { + font-size: 0.66rem; +} + +.project-row h3 { + font-size: clamp(1.55rem, 2.5vw, 2.35rem); +} + +.project-row > p { + font-size: 0.8rem; +} + +.modrinth-panel { + margin-top: 0; + padding: clamp(2rem, 4vw, 3.5rem); + border: 4px solid #68dc91; + border-radius: 0; + background: #14251b; +} + +.modrinth-heading { + margin-bottom: 3.5rem; + align-items: start; +} + +.modrinth-label { + font-size: 0.7rem; +} + +.modrinth-label span { + width: 0.65rem; + height: 0.65rem; + border-radius: 0; + box-shadow: none; +} + +.modrinth-heading h3 { + font-size: clamp(2.8rem, 5vw, 5rem); +} + +.modrinth-grid { + display: block; + border-top: 4px solid #68dc91; +} + +.modrinth-item, +.modrinth-item:nth-child(odd), +.modrinth-item:nth-child(even) { + min-height: 6.4rem; + padding: 1rem 0; + border-right: 0; + border-bottom: 1px solid rgba(99, 220, 138, 0.45); + grid-template-columns: 3rem minmax(12rem, 1fr) minmax(11rem, 1fr) minmax(12rem, auto); +} + +.modrinth-item:hover { + padding-right: 0; + padding-left: 0.75rem; + background: transparent; + box-shadow: inset 0.35rem 0 #68dc91; +} + +.modrinth-item strong { + font-family: var(--mono); + font-size: 1rem; +} + +.modrinth-item small { + display: block; +} + +.modrinth-item small, +.modrinth-item b { + font-size: 0.66rem; +} + +.modrinth-summary { + border-top-width: 3px; + border-top-color: rgba(104, 220, 145, 0.4); + font-size: 0.9rem; +} + +.modrinth-stats strong { + font-size: clamp(2.2rem, 4.5vw, 3.2rem); +} + +.archive-section .section-heading { + margin-bottom: 3rem; +} + +.archive-grid { + display: block; + border-top: 5px solid var(--ink); + counter-reset: archive-index; +} + +.archive-item, +.archive-item:nth-child(odd), +.archive-item:nth-child(even) { + position: relative; + min-height: 5.25rem; + padding: 0.9rem 0 0.9rem 3rem; + border-right: 0; + border-bottom: 1px solid var(--line-dark); + grid-template-columns: minmax(13rem, 0.75fr) 1fr auto; + transition: padding 180ms ease, background 180ms ease; +} + +.archive-item::before { + position: absolute; + top: 50%; + left: 0.9rem; + color: var(--muted-dark); + counter-increment: archive-index; + content: counter(archive-index, decimal-leading-zero); + transform: translateY(-50%); + font-family: var(--mono); + font-size: 0.62rem; + font-weight: 600; + letter-spacing: 0.02em; +} + +.archive-item::after { + position: absolute; + top: 0.7rem; + bottom: 0.7rem; + left: 0; + width: 3px; + background: var(--coral); + opacity: 0.55; + content: ""; + transition: opacity 180ms ease, width 180ms ease; +} + +.archive-item:nth-child(4n + 2)::after { + background: var(--cyan); +} + +.archive-item:nth-child(4n + 3)::after { + background: var(--lime); +} + +.archive-item:nth-child(4n)::after { + background: var(--yellow); +} + +.archive-item:hover { + padding-right: 0; + padding-left: 3.4rem; + background: rgba(17, 23, 26, 0.045); +} + +.archive-item:hover::after { + width: 4px; + opacity: 1; +} + +.archive-item span { + font-family: var(--mono); + font-size: 1rem; + font-weight: 600; +} + +.archive-item small { + font-size: 0.7rem; +} + +.stack-layout { + gap: 0; + border-top: 5px solid var(--text); + grid-template-columns: repeat(3, minmax(0, 1fr)); +} + +.stack-section { + padding-bottom: 4rem; +} + +.stack-card, +.stack-card-main, +.stack-card:not(.stack-card-main, .stack-card-learning) { + min-height: 24rem; + padding: 2rem 2rem 2rem 0; + border: 0; + border-right: 2px solid var(--line); + border-radius: 0; + background: transparent; + grid-column: auto; + grid-row: auto; +} + +.stack-card:nth-child(2), +.stack-card:nth-child(3) { + padding-left: 2rem; +} + +.stack-card:nth-child(3) { + border-right: 0; +} + +.stack-card h3 { + min-height: 2.2em; + font-size: clamp(2rem, 3.2vw, 3.4rem); +} + +.stack-tags { + display: block; +} + +.stack-tags span { + display: block; + padding: 0.5rem 0; + border: 0; + border-bottom: 1px dashed var(--line); + border-radius: 0; + background: transparent; + color: var(--text); + font-size: 0.72rem; + transition: padding 160ms ease, color 160ms ease; +} + +.stack-tags span:hover { + padding-left: 0.65rem; + color: var(--cyan); +} + +.stack-tags span.tag-strong { + border-bottom: 1px solid var(--coral); + font-weight: 600; +} + +.stack-tags span.tag-strong:hover { + background-position: 100% 50%; +} + +.stack-intro { + margin-top: 1rem; + font-size: 0.82rem; +} + +.stack-card-learning { + display: grid; + min-height: auto; + margin-top: 1.5rem; + padding: 2rem; + border: 3px solid var(--ink); + background: var(--lime); + grid-column: 1 / -1; + grid-template-columns: 0.3fr 1fr 1fr; + transition: transform 220ms ease; +} + +.stack-card-learning:hover { + transform: translateX(0.4rem); +} + +.stack-card-learning h3 { + min-height: 0; +} + +.stack-card-learning p { + font-size: 0.82rem; +} + +.contact-section { + padding-top: clamp(4.5rem, 7vw, 7rem); + padding-bottom: clamp(4.5rem, 7vw, 7rem); + background: var(--coral); + box-shadow: 0 0 0 100vmax var(--coral); +} + +.contact-section h2 { + max-width: none; + margin-bottom: 2rem; + font-size: clamp(5rem, 12vw, 11rem); + line-height: 0.82; +} + +.contact-orbit { + display: block; + opacity: 0.62; + pointer-events: none; + animation: orbit-rotate 36s linear infinite; +} + +.contact-copy { + max-width: 50rem; + margin-bottom: 3rem; + font-size: 1rem; +} + +.contact-links { + border-top: 5px solid var(--ink); + border-bottom: 2px solid var(--ink); +} + +.contact-links a, +.contact-links button { + min-height: 7rem; + border-bottom: 0; +} + +.contact-links > * + * { + border-left: 2px solid var(--ink); +} + +.contact-links a:hover, +.contact-links button:hover { + padding-right: 1.3rem; + padding-left: 1.3rem; + background: transparent; + color: var(--ink); + box-shadow: inset 0 -0.55rem var(--yellow); +} + +.contact-links span { + font-size: clamp(1.4rem, 2.3vw, 2.2rem); +} + +.site-footer { + min-height: 7rem; + border-top: 2px solid var(--line); +} + +.site-footer p { + font-size: 0.66rem; +} + +.error-shell { + border: 4px solid var(--paper); + border-radius: 0; + background: var(--bg); + box-shadow: 0.75rem 0.75rem 0 var(--coral); +} + +.js .reveal { + opacity: 0; + transform: translateY(1rem); + transition: opacity 480ms ease, transform 480ms cubic-bezier(0.2, 0.75, 0.25, 1); +} + +.js .reveal.is-visible { + opacity: 1; + transform: translateY(0); +} + +#glitch-name { + position: relative; + width: fit-content; + cursor: crosshair; + isolation: isolate; + transition: color 150ms ease; + will-change: transform; +} + +#glitch-name::before, +#glitch-name::after { + position: absolute; + z-index: -1; + inset: 0; + display: block; + opacity: 0; + content: attr(data-text); + pointer-events: none; +} + +.glitch-active #glitch-name { + color: var(--coral-bright); + animation: glitch-float 900ms steps(2, end) infinite; +} + +.glitch-active #glitch-name::before { + opacity: 0.72; + color: var(--cyan); + clip-path: inset(8% 0 56% 0); + animation: glitch-slice-a 420ms steps(2, end) infinite; +} + +.glitch-active #glitch-name::after { + opacity: 0.68; + color: var(--lime); + clip-path: inset(58% 0 5% 0); + animation: glitch-slice-b 570ms steps(2, end) infinite reverse; +} + +.glitch-active .page-grid { + opacity: 0.4; +} + +.glitch-field { + position: fixed; + z-index: 90; + inset: 0; + overflow: hidden; + contain: strict; + pointer-events: none; +} + +.glitch-glyph { + position: absolute; + top: var(--y); + left: var(--x); + color: var(--coral); + font: 600 var(--size) var(--mono); + line-height: 1; + opacity: 0; + text-shadow: 2px 0 var(--bg); + animation: glyph-escape var(--life) steps(9, end) forwards; + will-change: transform, opacity; +} + +.glitch-glyph.is-cyan { + color: var(--cyan); +} + +.glitch-glyph.is-lime { + color: var(--lime); +} + +.glitch-glyph.is-paper { + color: var(--paper); +} + +@keyframes glitch-float { + 0%, 100% { transform: translate(0, 0) rotate(0); } + 20% { transform: translate(0.08em, -0.04em) rotate(0.25deg); } + 42% { transform: translate(-0.035em, 0.025em) rotate(-0.2deg); } + 68% { transform: translate(0.025em, -0.06em) rotate(0.15deg); } + 82% { transform: translate(-0.06em, 0.015em) rotate(-0.15deg); } +} + +@keyframes glitch-slice-a { + 0%, 100% { transform: translate(-0.055em, -0.015em); } + 35% { transform: translate(0.09em, 0.02em); } + 70% { transform: translate(-0.02em, 0.045em); } +} + +@keyframes glitch-slice-b { + 0%, 100% { transform: translate(0.065em, 0.025em); } + 45% { transform: translate(-0.08em, -0.02em); } + 75% { transform: translate(0.025em, -0.05em); } +} + +@keyframes glyph-escape { + 0% { + opacity: 0; + transform: translate(-50%, -50%) scale(0.55) rotate(0); + } + 14%, 62% { + opacity: 0.9; + } + 100% { + opacity: 0; + transform: translate(calc(-50% + var(--dx)), calc(-50% + var(--dy))) scale(1.15) rotate(var(--rot)); + } +} + +@keyframes orbit-rotate { + to { + transform: rotate(1turn); + } +} + +@media (max-width: 68rem) { + .hero { + min-height: auto; + grid-template-columns: 1fr; + } + + .hero-copy { + max-width: 70rem; + } + + .terminal-card { + width: min(100%, 44rem); + margin: 1rem auto 2rem; + } + + .section-heading, + .section-heading-row { + grid-template-columns: 1fr; + } + + .section-heading h2 { + grid-column: 1; + } + + .section-heading-row > p, + .archive-section .section-heading-row > .text-link { + margin: 1.5rem 0 0; + } + + .current-project { + grid-template-columns: 1fr; + } + + .current-roadmap { + border-top: 3px solid rgba(23, 20, 15, 0.7); + border-left: 0; + } + + .project-feature { + grid-template-columns: 1fr; + } + + .project-feature-copy h3 { + margin-top: 4rem; + } + + .project-grid { + grid-template-columns: 1fr; + } + + .project-card-cool { + width: 86%; + margin: 0 0 0 auto; + } + + .project-row { + grid-template-columns: 2rem minmax(11rem, 0.6fr) minmax(15rem, 1fr) 2rem; + } + + .row-tech { + display: none; + } + + .modrinth-item, + .modrinth-item:nth-child(odd), + .modrinth-item:nth-child(even) { + grid-template-columns: 2.5rem minmax(10rem, 1fr) minmax(10rem, 1fr) auto; + } +} + +@media (max-width: 52rem) { + .site-header { + top: 0; + width: 100%; + padding-right: 1rem; + padding-left: 1rem; + } + + .nav-pill { + padding-left: 0.8rem; + } + + .hero { + padding-top: 7.5rem; + padding-bottom: 4.5rem; + } + + .hero h1 { + font-size: clamp(3.7rem, 17vw, 6rem); + } + + .hero-signals { + grid-template-columns: 1fr; + } + + .hero-signals li, + .hero-signals li + li { + padding: 0.65rem 0; + border-top: 1px solid var(--line); + border-left: 0; + } + + .hero-signals span { + display: inline; + margin-right: 0.7rem; + } + + .terminal-card { + box-shadow: none; + transform: none; + } + + .terminal-body { + min-height: 22rem; + padding: 1.4rem; + } + + .profile-chip { + position: relative; + right: auto; + bottom: auto; + width: calc(100% - 1.4rem); + margin: 0.7rem 0.7rem -2.4rem; + transform: rotate(-1deg); + } + + .signal-track { + width: max-content; + justify-content: flex-start; + } + + .section-heading h2 { + font-size: clamp(2.8rem, 13vw, 4.8rem); + } + + .about-layout { + grid-template-columns: 1fr; + } + + .method-grid { + grid-template-columns: 1fr; + } + + .method-card { + min-height: auto; + padding: 1.5rem 0 2rem; + } + + .method-card + .method-card { + border-top: 2px solid var(--ink); + border-left: 0; + } + + .method-card h3 { + margin-top: 2rem; + } + + .current-project { + border-width: 2px; + } + + .current-project h3 { + font-size: clamp(3.1rem, 16.5vw, 6rem); + } + + .current-kicker { + margin-top: 4rem; + } + + .project-visual { + min-height: 20rem; + } + + .project-card-cool { + width: 94%; + } + + .project-row { + grid-template-columns: 2rem 1fr 2rem; + } + + .project-row > p, + .row-tech { + display: none; + } + + .modrinth-heading { + display: block; + } + + .modrinth-heading .text-link { + margin-top: 2rem; + } + + .modrinth-item, + .modrinth-item:nth-child(odd), + .modrinth-item:nth-child(even) { + grid-template-columns: 2.2rem minmax(0, 1fr); + } + + .modrinth-item small { + display: none; + } + + .modrinth-item b { + grid-column: 2; + justify-self: start; + text-align: left; + } + + .archive-item, + .archive-item:nth-child(odd), + .archive-item:nth-child(even) { + grid-template-columns: 1fr auto; + } + + .archive-item small { + grid-column: 1; + grid-row: 2; + } + + .archive-item b { + grid-column: 2; + grid-row: 1 / 3; + } + + .stack-layout { + display: block; + } + + .stack-card, + .stack-card-main, + .stack-card:not(.stack-card-main, .stack-card-learning) { + min-height: auto; + padding: 2rem 0; + border-right: 0; + border-bottom: 2px solid var(--line); + } + + .stack-card:nth-child(2), + .stack-card:nth-child(3) { + padding-left: 0; + } + + .stack-card h3 { + min-height: 0; + } + + .stack-card-learning { + display: block; + margin-top: 2rem; + padding: 1.5rem; + } + + .stack-card-learning h3 { + margin-bottom: 1.5rem; + } + + .contact-section h2 { + font-size: clamp(4rem, 22vw, 7rem); + } + + .contact-links { + grid-template-columns: 1fr; + } + + .contact-links a, + .contact-links button { + min-height: 5.5rem; + padding-left: 0; + border-bottom: 2px solid var(--ink); + } + + .contact-links > * + * { + padding-left: 0; + border-left: 0; + } + + .site-footer { + grid-template-columns: 1fr auto; + } +} + +@media (max-width: 36rem) { + .hero-actions { + display: flex; + } + + .button { + width: auto; + } + + .current-project-main, + .current-roadmap, + .project-card, + .modrinth-panel { + padding: 1.35rem; + } + + .current-project h3 { + font-size: clamp(3rem, 16vw, 5rem); + } + + .project-card h3 { + font-size: clamp(2.7rem, 14vw, 4.5rem); + } +} + +@media print { + .site-header, + .signal-strip { + display: none; + } +} diff --git a/css/style.css b/css/style.css new file mode 100644 index 0000000..9682d26 --- /dev/null +++ b/css/style.css @@ -0,0 +1,2747 @@ +:root { + --bg: #0b1014; + --bg-soft: #11191f; + --surface: #152029; + --surface-2: #1b2831; + --paper: #e9e5da; + --paper-deep: #d8d2c3; + --ink: #11171a; + --text: #edf1e9; + --muted: #9ba7a5; + --muted-dark: #5c6665; + --line: rgba(237, 241, 233, 0.16); + --line-dark: rgba(17, 23, 26, 0.18); + --coral: #f0996e; + --coral-bright: #ffad82; + --cyan: #8fd4d0; + --lime: #c8ee80; + --yellow: #f3d277; + --display: "Syne", "Avenir Next", sans-serif; + --mono: "IBM Plex Mono", "Courier New", monospace; + --page-pad: clamp(1.25rem, 4vw, 4.5rem); + --max-width: 96rem; + --radius-sm: 0.5rem; + --radius-md: 1rem; + --radius-lg: 1.5rem; +} + +*, +*::before, +*::after { + box-sizing: border-box; +} + +html { + overflow-x: clip; + scroll-behavior: smooth; + scroll-padding-top: 7rem; +} + +body { + min-width: 20rem; + margin: 0; + overflow-x: clip; + background: var(--bg); + color: var(--text); + font-family: var(--mono); + font-size: 1rem; + line-height: 1.65; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; +} + +body::before { + position: fixed; + z-index: -2; + inset: 0; + background: + radial-gradient(circle at 82% 10%, rgba(143, 212, 208, 0.11), transparent 28rem), + radial-gradient(circle at 9% 36%, rgba(240, 153, 110, 0.09), transparent 25rem), + var(--bg); + content: ""; + pointer-events: none; +} + +::selection { + background: var(--coral); + color: var(--ink); +} + +img, +svg { + display: block; + max-width: 100%; +} + +a { + color: inherit; + text-decoration: none; +} + +button { + color: inherit; + font: inherit; +} + +p, +h1, +h2, +h3, +blockquote, +ul { + margin-top: 0; +} + +h1, +h2, +h3 { + font-family: var(--display); + line-height: 0.98; +} + +code { + padding: 0.08em 0.35em; + border: 1px solid currentColor; + border-radius: 0.3rem; + font: 0.85em var(--mono); +} + +:focus-visible { + outline: 3px solid var(--lime); + outline-offset: 4px; +} + +.skip-link { + position: fixed; + z-index: 1000; + top: 1rem; + left: 1rem; + padding: 0.75rem 1rem; + transform: translateY(-160%); + background: var(--lime); + color: var(--ink); + font-weight: 600; + transition: transform 180ms ease; +} + +.skip-link:focus { + transform: translateY(0); +} + +.page-grid { + position: fixed; + z-index: -1; + inset: 0; + opacity: 0.3; + background-image: + linear-gradient(rgba(255, 255, 255, 0.025) 1px, transparent 1px), + linear-gradient(90deg, rgba(255, 255, 255, 0.025) 1px, transparent 1px); + background-size: 4rem 4rem; + pointer-events: none; + mask-image: linear-gradient(to bottom, black, transparent 72%); +} + +.site-header { + position: fixed; + z-index: 100; + top: 1rem; + left: 50%; + display: flex; + width: min(calc(100% - 2rem), var(--max-width)); + min-height: 4rem; + align-items: center; + justify-content: space-between; + padding: 0.55rem 0.65rem 0.55rem 1rem; + transform: translateX(-50%); + border: 1px solid rgba(237, 241, 233, 0.14); + border-radius: 0.8rem; + background: rgba(11, 16, 20, 0.78); + box-shadow: 0 1rem 3rem rgba(0, 0, 0, 0.16); + backdrop-filter: blur(18px); +} + +.brand { + display: inline-flex; + align-items: center; + gap: 0.65rem; + font-family: var(--display); + font-size: 1.05rem; + font-weight: 700; + letter-spacing: -0.02em; +} + +/* ShinyText-style sweep, ported to plain CSS (no motion/JS dependency). + A blended highlight bar sweeps across the wordmark rather than animating + background-clip:text, which is unreliable across engines at small sizes. */ +.brand > span:last-child { + position: relative; + display: inline-block; + overflow: hidden; +} + +.brand > span:last-child::after { + position: absolute; + inset: -20% -10%; + background: linear-gradient(100deg, transparent 42%, rgba(255, 255, 255, 0.9) 50%, transparent 58%); + content: ""; + mix-blend-mode: overlay; + pointer-events: none; + transform: translateX(-140%); + animation: brand-shine 5.5s ease-in-out infinite; +} + +@media (prefers-reduced-motion: reduce) { + .brand > span:last-child::after { + display: none; + } +} + +@keyframes brand-shine { + 0%, 18% { + transform: translateX(-140%); + } + 55%, 100% { + transform: translateX(140%); + } +} + +.brand-mark { + display: grid; + width: 2.45rem; + height: 2.45rem; + place-items: center; + border-radius: 0.45rem; + background: var(--coral); + color: var(--ink); + font: 600 0.85rem var(--mono); +} + +.site-nav { + position: relative; + display: flex; + align-items: center; + gap: clamp(0.8rem, 2vw, 2rem); +} + +/* GooeyNav-style hover highlight, ported to vanilla JS/CSS (no gsap + dependency). A solid coral pill snaps to the hovered nav item with a + springy squash/stretch, matching the site's flat, opaque badge language + (roadmap chips, image labels) instead of a soft blurred glow. */ +.nav-gooey { + position: absolute; + z-index: 0; + top: 0; + left: 0; + width: 0; + height: 0; + opacity: 0; + pointer-events: none; + transition: opacity 180ms ease; +} + +.nav-gooey.is-active { + opacity: 1; +} + +.nav-gooey-blob { + position: absolute; + top: 0; + left: 0; + border-radius: 100vw; + background: var(--coral); + transition: + left 320ms cubic-bezier(0.22, 1, 0.36, 1), + top 320ms cubic-bezier(0.22, 1, 0.36, 1), + width 320ms cubic-bezier(0.22, 1, 0.36, 1), + height 320ms cubic-bezier(0.22, 1, 0.36, 1), + transform 320ms cubic-bezier(0.34, 1.56, 0.64, 1); +} + +.nav-gooey.is-jumping .nav-gooey-blob { + transform: scaleX(1.18) scaleY(0.86); +} + +.nav-gooey-blob--trail { + display: none; +} + +.site-nav > a { + position: relative; + z-index: 1; + transition: color 180ms ease; +} + +.site-nav > a.is-lit { + color: var(--ink) !important; +} + +@media (prefers-reduced-motion: reduce) { + .nav-gooey { + display: none; + } +} + +.site-nav a { + font-size: 0.78rem; + font-weight: 500; + letter-spacing: 0.04em; + text-transform: uppercase; +} + +.site-nav > a:not(.nav-pill) { + position: relative; + color: var(--muted); + transition: color 180ms ease; +} + +.site-nav > a:not(.nav-pill)::after { + position: absolute; + right: 0; + bottom: -0.4rem; + left: 0; + height: 1px; + transform: scaleX(0); + transform-origin: right; + background: var(--coral); + content: ""; + transition: transform 180ms ease; +} + +.site-nav > a:not(.nav-pill):hover { + color: var(--text); +} + +.site-nav > a:not(.nav-pill):hover::after { + transform: scaleX(1); + transform-origin: left; +} + +.nav-pill { + display: inline-flex; + align-items: center; + gap: 0.65rem; + padding: 0.72rem 0.9rem; + border: 1px solid var(--line); + border-radius: 0.45rem; + transition: background 180ms ease, color 180ms ease, border-color 180ms ease; +} + +.nav-pill:hover { + border-color: var(--lime); + background: var(--lime); + color: var(--ink); +} + +.hero { + display: grid; + width: min(100%, var(--max-width)); + min-height: 100svh; + margin: 0 auto; + padding: clamp(8.5rem, 14vh, 11rem) var(--page-pad) clamp(4.5rem, 8vh, 7rem); + grid-template-columns: minmax(0, 1.05fr) minmax(30rem, 0.95fr); + align-items: center; + gap: clamp(3rem, 7vw, 8rem); +} + +.hero-copy { + position: relative; + z-index: 2; + min-width: 0; +} + +.eyebrow, +.section-index, +.project-kicker, +.stack-label { + margin-bottom: 1.4rem; + font-size: 0.72rem; + font-weight: 600; + letter-spacing: 0.13em; + text-transform: uppercase; +} + +.eyebrow { + display: flex; + align-items: center; + color: var(--cyan); +} + +.status-dot { + position: relative; + width: 0.52rem; + height: 0.52rem; + margin-right: 0.7rem; + border-radius: 50%; + background: var(--lime); + box-shadow: 0 0 0 0.3rem rgba(200, 238, 128, 0.11); +} + +.status-dot::after { + position: absolute; + inset: -0.4rem; + border: 1px solid rgba(200, 238, 128, 0.35); + border-radius: 50%; + content: ""; + animation: status-pulse 2.4s ease-out infinite; +} + +.hero h1 { + max-width: 11ch; + margin-bottom: 2rem; + font-size: clamp(3.4rem, 6.5vw, 7.25rem); + font-weight: 700; + letter-spacing: -0.075em; +} + +.hero h1 span { + display: block; + color: var(--coral); +} + +.hero-intro { + max-width: 43rem; + margin-bottom: 2.1rem; + color: var(--muted); + font-size: clamp(0.93rem, 1.25vw, 1.08rem); +} + +.hero-actions { + display: flex; + flex-wrap: wrap; + gap: 0.8rem; + margin-bottom: 3rem; +} + +.button { + display: inline-flex; + min-height: 3.2rem; + align-items: center; + justify-content: space-between; + gap: 1.5rem; + padding: 0.8rem 1.1rem; + border: 1px solid var(--line); + border-radius: 0.45rem; + font-size: 0.78rem; + font-weight: 600; + letter-spacing: 0.03em; + text-transform: uppercase; + transition: transform 180ms ease, background 180ms ease, color 180ms ease; +} + +.button:hover { + transform: translateY(-3px); +} + +.button-primary { + border-color: var(--coral); + background: var(--coral); + color: var(--ink); +} + +.button-primary:hover { + background: var(--coral-bright); +} + +.button-ghost:hover { + background: var(--text); + color: var(--ink); +} + +.hero-signals { + display: flex; + max-width: 44rem; + margin-bottom: 0; + padding: 0; + border-top: 1px solid var(--line); + list-style: none; +} + +.hero-signals li { + flex: 1; + padding: 1rem 1rem 0 0; + color: var(--muted); + font-size: 0.67rem; + letter-spacing: 0.06em; + text-transform: uppercase; +} + +.hero-signals li + li { + padding-left: 1rem; + border-left: 1px solid var(--line); +} + +.hero-signals span { + display: block; + margin-bottom: 0.2rem; + color: var(--coral); +} + +.terminal-card { + position: relative; + z-index: 1; + min-width: 0; + align-self: center; + border: 1px solid rgba(143, 212, 208, 0.25); + border-radius: var(--radius-lg); + background: linear-gradient(145deg, rgba(25, 38, 47, 0.96), rgba(12, 19, 24, 0.98)); + box-shadow: 0 2rem 7rem rgba(0, 0, 0, 0.36), inset 0 1px rgba(255, 255, 255, 0.04); + transform: rotate(1.5deg); +} + +.terminal-card::before { + position: absolute; + z-index: -1; + inset: 10% -10% -8% 14%; + border-radius: 50%; + background: rgba(143, 212, 208, 0.12); + filter: blur(4rem); + content: ""; +} + +.terminal-chrome { + display: grid; + min-height: 3.6rem; + padding: 0 1.2rem; + border-bottom: 1px solid var(--line); + grid-template-columns: 1fr auto 1fr; + align-items: center; + color: var(--muted); + font-size: 0.7rem; +} + +.window-dots { + display: flex; + gap: 0.35rem; +} + +.window-dots i { + width: 0.48rem; + height: 0.48rem; + border-radius: 50%; + background: #58636a; +} + +.window-dots i:first-child { + background: var(--coral); +} + +.window-dots i:nth-child(2) { + background: var(--yellow); +} + +.window-dots i:last-child { + background: var(--lime); +} + +.terminal-state { + display: flex; + align-items: center; + justify-self: end; + gap: 0.45rem; + color: var(--lime); +} + +.terminal-state i, +.repo-live i { + width: 0.4rem; + height: 0.4rem; + border-radius: 50%; + background: currentColor; +} + +.terminal-body { + padding: clamp(1.35rem, 3vw, 2.2rem); + font-size: clamp(0.73rem, 1vw, 0.86rem); +} + +.terminal-body > p { + margin-bottom: 0.25rem; +} + +.terminal-output { + margin-left: 1.4rem; + color: var(--muted); +} + +.prompt { + margin-right: 0.65rem; + color: var(--coral); +} + +.terminal-ok { + color: var(--lime); +} + +.infra-map { + display: grid; + margin-top: 2rem; + padding: 1.25rem; + border: 1px solid rgba(143, 212, 208, 0.18); + border-radius: 0.8rem; + background: rgba(0, 0, 0, 0.18); + grid-template-columns: auto 1fr auto 1fr auto; + align-items: center; +} + +.infra-node { + position: relative; + z-index: 2; + min-width: 4.8rem; + padding: 0.65rem; + border: 1px solid var(--line); + border-radius: 0.45rem; + background: var(--surface); + text-align: center; +} + +.infra-node small, +.infra-node strong { + display: block; +} + +.infra-node small { + margin-bottom: 0.15rem; + color: var(--muted); + font-size: 0.52rem; + font-weight: 400; + letter-spacing: 0.08em; + text-transform: uppercase; +} + +.infra-node strong { + color: var(--text); + font-size: 0.7rem; + font-weight: 500; +} + +.node-router { + border-color: rgba(240, 153, 110, 0.55); +} + +.node-host { + border-color: rgba(200, 238, 128, 0.5); +} + +.infra-line { + position: relative; + height: 1px; + overflow: hidden; + background: var(--line); +} + +.infra-line span { + position: absolute; + top: -1px; + left: -0.4rem; + width: 0.4rem; + height: 3px; + border-radius: 1rem; + background: var(--cyan); + box-shadow: 0 0 0.5rem var(--cyan); + animation: packet 2s linear infinite; +} + +.service-row { + display: grid; + grid-column: 1 / -1; + gap: 0.5rem; + margin-top: 0.9rem; + grid-template-columns: repeat(4, 1fr); +} + +.service-row span { + padding: 0.4rem; + border-radius: 0.3rem; + background: rgba(143, 212, 208, 0.08); + color: var(--muted); + font-size: 0.55rem; + text-align: center; +} + +.profile-chip { + position: absolute; + right: -1.5rem; + bottom: -3.3rem; + display: grid; + width: min(23rem, 76%); + min-height: 5.5rem; + padding: 0.7rem 1rem 0.7rem 0.7rem; + border: 1px solid rgba(240, 153, 110, 0.35); + border-radius: 1rem; + background: rgba(13, 19, 23, 0.95); + box-shadow: 0 1.3rem 3rem rgba(0, 0, 0, 0.38); + grid-template-columns: 4.1rem 1fr auto; + align-items: center; + gap: 0.85rem; + transform: rotate(-3deg); + backdrop-filter: blur(12px); +} + +.profile-chip img { + width: 4.1rem; + height: 4.1rem; + border-radius: 0.65rem; + background: var(--paper); + object-fit: contain; +} + +.profile-chip strong, +.profile-chip span { + display: block; +} + +.profile-chip strong { + font-family: var(--display); + font-size: 0.92rem; +} + +.profile-chip div span { + margin-top: 0.2rem; + color: var(--muted); + font-size: 0.6rem; + letter-spacing: 0.03em; +} + +.profile-arrow { + color: var(--coral); + font-size: 1.15rem; +} + +.signal-strip { + position: relative; + z-index: 3; + overflow: hidden; + border-top: 1px solid var(--ink); + border-bottom: 1px solid var(--ink); + background: var(--coral); + color: var(--ink); +} + +.signal-track { + display: flex; + width: max-content; + min-height: 3.6rem; + align-items: center; + animation: marquee 38s linear infinite; +} + +.signal-strip:hover .signal-track { + animation-play-state: paused; +} + +.signal-set { + display: flex; + flex-shrink: 0; + align-items: center; + gap: 1.4rem; + padding-right: 1.4rem; +} + +.signal-item { + display: inline-flex; + align-items: center; + gap: 0.5rem; + font-family: var(--display); + font-size: 0.82rem; + font-weight: 700; + letter-spacing: 0.06em; + text-transform: uppercase; + white-space: nowrap; +} + +.signal-icon { + width: 1rem; + height: 1rem; + flex-shrink: 0; + object-fit: contain; +} + +.signal-track i { + width: 0.42rem; + height: 0.42rem; + flex-shrink: 0; + transform: rotate(45deg); + background: var(--ink); +} + +@media (prefers-reduced-motion: reduce) { + .signal-track { + animation: none; + } +} + +.section { + width: min(100%, var(--max-width)); + margin: 0 auto; + padding: clamp(5.5rem, 10vw, 10rem) var(--page-pad); +} + +.section-heading { + display: grid; + margin-bottom: clamp(3.5rem, 7vw, 6rem); + grid-template-columns: minmax(10rem, 0.38fr) minmax(0, 1fr); + align-items: start; +} + +.section-index { + color: var(--coral); +} + +.section-heading h2 { + margin-bottom: 0; + font-size: clamp(3rem, 6.4vw, 6.6rem); + font-weight: 700; + letter-spacing: -0.065em; +} + +.section-heading-row { + grid-template-columns: minmax(0, 1fr) minmax(18rem, 0.35fr); + gap: 3rem; +} + +.section-heading-row .section-index { + margin-bottom: 1.2rem; +} + +.section-heading-row > p { + max-width: 28rem; + margin: 1.4rem 0 0 auto; + color: var(--muted); + font-size: 0.86rem; +} + +.section-heading-row > p strong { + color: var(--text); +} + +.about-section, +.archive-section { + position: relative; + background: var(--paper); + box-shadow: 0 0 0 100vmax var(--paper); + color: var(--ink); + clip-path: inset(0 -100vmax); +} + +.about-section .section-index, +.archive-section .section-index { + color: #a74b2c; +} + +.about-layout { + display: grid; + gap: clamp(3rem, 8vw, 8rem); + grid-template-columns: minmax(17rem, 0.7fr) minmax(0, 1fr); +} + +.about-quote { + position: relative; + margin-bottom: 0; + padding-top: 5.5rem; + border-top: 1px solid var(--line-dark); +} + +.quote-mark { + position: absolute; + top: 0; + left: 0; + color: var(--coral); + font-family: var(--display); + font-size: 6rem; + line-height: 1; +} + +.about-quote p { + margin-bottom: 1.7rem; + font-family: var(--display); + font-size: clamp(2rem, 4vw, 4rem); + font-weight: 600; + letter-spacing: -0.055em; + line-height: 1.05; +} + +.about-quote footer { + max-width: 30rem; + color: var(--muted-dark); + font-size: 0.72rem; +} + +.about-copy { + max-width: 48rem; +} + +.about-copy p { + color: #3f4848; + font-size: 0.92rem; +} + +.about-copy .lead { + margin-bottom: 1.8rem; + color: var(--ink); + font-family: var(--display); + font-size: clamp(1.35rem, 2.2vw, 2rem); + font-weight: 600; + letter-spacing: -0.035em; + line-height: 1.25; +} + +.language-line { + display: flex; + flex-wrap: wrap; + gap: 0.5rem; + margin-top: 2rem; +} + +.language-line span { + padding: 0.5rem 0.7rem; + border: 1px solid var(--line-dark); + border-radius: 100vw; + font-size: 0.62rem; + font-weight: 600; + letter-spacing: 0.04em; + text-transform: uppercase; +} + +.method-grid { + display: grid; + margin-top: clamp(4rem, 8vw, 8rem); + border-top: 1px solid var(--line-dark); + border-bottom: 1px solid var(--line-dark); + grid-template-columns: repeat(3, 1fr); +} + +.method-card { + min-height: 17rem; + padding: 1.5rem clamp(1rem, 3vw, 2.5rem) 2rem; +} + +.method-card + .method-card { + border-left: 1px solid var(--line-dark); +} + +.method-card > span { + color: #a74b2c; + font-size: 0.66rem; +} + +.method-card h3 { + max-width: 10ch; + margin: 4rem 0 1rem; + font-size: clamp(1.55rem, 2.8vw, 2.5rem); + letter-spacing: -0.045em; +} + +.method-card p { + max-width: 25rem; + margin-bottom: 0; + color: var(--muted-dark); + font-size: 0.74rem; +} + +.work-section { + padding-bottom: clamp(6rem, 10vw, 10rem); +} + +.current-project { + position: relative; + display: grid; + min-height: 36rem; + overflow: hidden; + margin-bottom: 1rem; + border: 1px solid rgba(17, 23, 26, 0.22); + border-radius: var(--radius-lg); + background: + radial-gradient(circle at 8% 0, rgba(255, 255, 255, 0.9), transparent 19rem), + linear-gradient(135deg, #bcebf1 0%, #9bd5e4 47%, #9ebce9 100%); + color: var(--ink); + grid-template-columns: minmax(0, 1.15fr) minmax(22rem, 0.7fr); +} + +.current-project::before { + position: absolute; + top: -65%; + left: -10%; + width: 115%; + height: 85%; + transform: rotate(-5deg); + border-radius: 50%; + background: rgba(255, 255, 255, 0.24); + content: ""; + filter: blur(0.2rem); +} + +.current-project-main, +.current-roadmap { + position: relative; + z-index: 2; + padding: clamp(1.7rem, 4vw, 3.4rem); +} + +.current-project-main { + display: flex; + flex-direction: column; +} + +.current-meta { + display: flex; + align-items: center; + justify-content: space-between; + gap: 1rem; + font-size: 0.6rem; + font-weight: 600; + letter-spacing: 0.07em; + text-transform: uppercase; +} + +.current-meta > span:first-child { + display: flex; + align-items: center; + gap: 0.5rem; +} + +.current-meta i { + width: 0.45rem; + height: 0.45rem; + border-radius: 50%; + background: #167e72; + box-shadow: 0 0 0 0.3rem rgba(22, 126, 114, 0.12); +} + +.current-kicker { + margin: auto 0 0.8rem; + font-size: 0.68rem; + font-weight: 600; + letter-spacing: 0.1em; + text-transform: uppercase; +} + +.current-project h3 { + margin-bottom: 1.3rem; + font-size: clamp(4.5rem, 10vw, 10rem); + letter-spacing: -0.085em; +} + +.tide-heading { + display: flex; + align-items: center; + gap: 1rem; +} + +.current-project .tide-heading h3 { + margin-bottom: 0; +} + +.tide-mark { + width: clamp(2.2rem, 3.4vw, 2.8rem); + height: clamp(2.2rem, 3.4vw, 2.8rem); + flex-shrink: 0; + transition: transform 320ms cubic-bezier(0.2, 0.8, 0.2, 1), filter 320ms ease; + will-change: transform; +} + +.tide-mark:hover { + transform: scale(1.18) rotate(-6deg); + filter: drop-shadow(0 0.4rem 0.6rem rgba(17, 23, 26, 0.28)); +} + +.current-repo-link { + margin-top: 0.4rem; +} + +.current-project-main > p:not(.current-kicker) { + max-width: 45rem; + margin-bottom: 2rem; + font-size: 0.8rem; +} + +.current-tags span { + border-color: rgba(17, 23, 26, 0.35); +} + +.current-roadmap { + display: flex; + border-left: 1px solid rgba(17, 23, 26, 0.18); + background: rgba(236, 252, 253, 0.24); + flex-direction: column; + justify-content: center; + backdrop-filter: blur(1rem); +} + +.current-roadmap > p { + margin-bottom: 1.4rem; + font-size: 0.64rem; + font-weight: 600; + letter-spacing: 0.1em; + text-transform: uppercase; +} + +.current-roadmap ol { + margin: 0; + padding: 0; + border-top: 1px solid rgba(17, 23, 26, 0.2); + list-style: none; +} + +.current-roadmap li { + display: grid; + min-height: 5.4rem; + padding: 0.9rem 0; + border-bottom: 1px solid rgba(17, 23, 26, 0.2); + grid-template-columns: 2rem 1fr auto; + align-items: center; + gap: 0.8rem; +} + +.current-roadmap li > span, +.current-roadmap li > b, +.current-roadmap small { + font-size: 0.55rem; +} + +.current-roadmap li > span { + color: #326570; +} + +.current-roadmap strong, +.current-roadmap small { + display: block; +} + +.current-roadmap strong { + margin-bottom: 0.15rem; + font-family: var(--display); + font-size: 0.85rem; +} + +.current-roadmap small { + color: #3c5d63; +} + +.current-roadmap li > b { + padding: 0.3rem 0.45rem; + border: 1px solid rgba(17, 23, 26, 0.24); + border-radius: 100vw; + font-weight: 500; + letter-spacing: 0.04em; + text-transform: uppercase; +} + +.current-watermark { + position: absolute; + z-index: 1; + bottom: -0.28em; + left: 0.25em; + color: rgba(255, 255, 255, 0.13); + font-family: var(--display); + font-size: clamp(8rem, 20vw, 20rem); + font-weight: 800; + letter-spacing: -0.1em; + line-height: 0.7; + pointer-events: none; +} + +.project-feature { + display: grid; + overflow: hidden; + min-height: 42rem; + margin-bottom: 1rem; + border: 1px solid var(--line); + border-radius: var(--radius-lg); + background: var(--bg-soft); + grid-template-columns: minmax(0, 1.5fr) minmax(22rem, 0.62fr); +} + +.project-visual { + position: relative; + min-height: 35rem; + overflow: hidden; +} + +.project-visual::after { + position: absolute; + inset: 0; + background: linear-gradient(90deg, transparent 70%, rgba(17, 25, 31, 0.76)), linear-gradient(0deg, rgba(11, 16, 20, 0.35), transparent 40%); + content: ""; + transition: opacity 300ms ease; +} + +.project-visual:hover::after { + opacity: 0.45; +} + +.project-visual img { + width: 100%; + height: 100%; + transition: transform 700ms cubic-bezier(0.2, 0.7, 0.2, 1); + object-fit: cover; +} + +.project-visual:hover img { + transform: scale(1.025); +} + +.image-label { + position: absolute; + z-index: 2; + bottom: 1rem; + left: 1rem; + padding: 0.55rem 0.7rem; + border: 1px solid rgba(255, 255, 255, 0.2); + border-radius: 0.35rem; + background: rgba(11, 16, 20, 0.72); + font-size: 0.58rem; + letter-spacing: 0.08em; + text-transform: uppercase; + backdrop-filter: blur(10px); +} + +.flux-frost { + display: none; +} + +.project-visual-flux { + background: + radial-gradient(circle at 8% 0, rgba(255, 255, 255, 0.85), transparent 19rem), + linear-gradient(135deg, #ddd1f6 0%, #c0aeee 50%, #aabbe9 100%); +} + +.project-visual-flux::after { + background: linear-gradient(0deg, rgba(17, 23, 26, 0.08), transparent 30%); +} + +.project-visual .flux-icon { + position: absolute; + z-index: 2; + top: 50%; + left: 50%; + width: clamp(5.5rem, 9vw, 8rem); + height: auto; + border-radius: 22%; + box-shadow: 0 1.2rem 2.8rem rgba(4, 9, 13, 0.55); + filter: none; + object-fit: contain; + transform: translate(-50%, -50%); + transition: transform 400ms cubic-bezier(0.2, 0.8, 0.2, 1), box-shadow 400ms ease; +} + +.project-visual-flux:hover .flux-icon { + box-shadow: 0 1.6rem 3.4rem rgba(4, 9, 13, 0.6); + transform: translate(-50%, -50%) scale(1.06) rotate(-2deg); +} + +.flux-watermark { + position: absolute; + z-index: 1; + bottom: -0.16em; + left: 0.22em; + color: rgba(255, 255, 255, 0.34); + font-family: var(--display); + font-size: clamp(6rem, 13vw, 13rem); + font-weight: 800; + letter-spacing: -0.06em; + line-height: 0.8; + pointer-events: none; + transition: transform 700ms cubic-bezier(0.2, 0.75, 0.25, 1); +} + +.project-visual-flux:hover .flux-watermark { + transform: translateX(1.2rem); +} + +.flux-chrome { + position: absolute; + z-index: 2; + top: 1rem; + left: 1.2rem; + display: flex; + gap: 0.45rem; +} + +.flux-chrome i { + width: 0.7rem; + height: 0.7rem; + border-radius: 50%; + background: rgba(237, 241, 233, 0.28); + box-shadow: inset 0 0 0 1px rgba(11, 16, 20, 0.35); +} + +.flux-chrome i:nth-child(1) { background: rgba(240, 153, 110, 0.85); } +.flux-chrome i:nth-child(2) { background: rgba(243, 210, 119, 0.85); } +.flux-chrome i:nth-child(3) { background: rgba(200, 238, 128, 0.85); } + +.flux-tags { + position: absolute; + z-index: 2; + top: calc(50% + 4.6rem); + left: 50%; + display: flex; + gap: 0.4rem; + transform: translateX(-50%); +} + +.flux-tags span { + padding: 0.32rem 0.6rem; + border: 1px solid rgba(17, 23, 26, 0.32); + border-radius: 100vw; + background: rgba(255, 255, 255, 0.22); + color: var(--ink); + font-family: var(--mono); + font-size: 0.55rem; + letter-spacing: 0.08em; + text-transform: uppercase; + backdrop-filter: blur(8px); + -webkit-backdrop-filter: blur(8px); +} + +.flux-stack { + position: absolute; + z-index: 2; + top: 50%; + right: 1.2rem; + width: 12.5rem; + padding: 1rem 1.1rem; + border: 1px solid rgba(17, 23, 26, 0.2); + background: rgba(255, 255, 255, 0.26); + backdrop-filter: blur(12px); + -webkit-backdrop-filter: blur(12px); + transform: translateY(-50%); +} + +.flux-stack > b { + display: block; + margin-bottom: 0.7rem; + padding-bottom: 0.6rem; + border-bottom: 1px solid rgba(17, 23, 26, 0.2); + color: #3c5d63; + font-family: var(--mono); + font-size: 0.58rem; + font-weight: 600; + letter-spacing: 0.1em; + text-transform: uppercase; +} + +.flux-stack-row { + display: grid; + padding: 0.4rem 0; + grid-template-columns: 1.6rem 1fr; + align-items: baseline; + gap: 0.4rem; +} + +.flux-stack-row + .flux-stack-row { + border-top: 1px solid rgba(17, 23, 26, 0.12); +} + +.flux-stack-row > span:first-child { + color: #326570; + font-family: var(--mono); + font-size: 0.55rem; +} + +.flux-stack-row > span:last-child { + color: var(--ink); + font-family: var(--mono); + font-size: 0.62rem; + letter-spacing: 0.04em; +} + +.flux-stack-row small { + display: block; + margin-top: 0.1rem; + color: #3c5d63; + font-size: 0.55rem; +} + +.flux-status { + position: absolute; + z-index: 2; + right: 1.2rem; + bottom: 1rem; + display: inline-flex; + align-items: center; + gap: 0.45rem; + color: #2f4a44; + font-family: var(--mono); + font-size: 0.58rem; + letter-spacing: 0.08em; + text-transform: uppercase; +} + +.flux-status i { + width: 0.45rem; + height: 0.45rem; + border-radius: 50%; + background: #167e72; + box-shadow: 0 0 0 0.3rem rgba(22, 126, 114, 0.14); + animation: flux-pulse 2.4s ease-in-out infinite; +} + +@keyframes flux-pulse { + 0%, 100% { opacity: 1; } + 50% { opacity: 0.35; } +} + +@media (max-width: 64rem) { + .flux-stack { + display: none; + } +} + +@media (max-width: 52rem) { + .flux-status { + display: none; + } +} + +@media (max-width: 40rem) { + .flux-tags { + display: none; + } +} + +.project-feature-copy { + display: flex; + padding: clamp(1.8rem, 4vw, 3.5rem); + flex-direction: column; +} + +.project-meta { + display: flex; + justify-content: space-between; + gap: 1rem; + color: var(--cyan); + font-size: 0.61rem; + letter-spacing: 0.07em; + text-transform: uppercase; +} + +.project-feature-copy h3 { + max-width: 7ch; + margin: auto 0 1.4rem; + font-size: clamp(2.8rem, 5vw, 5rem); + letter-spacing: -0.06em; +} + +.project-feature-copy > p { + color: var(--muted); + font-size: 0.78rem; +} + +.project-facts { + display: grid; + margin: 1.7rem 0 2rem; + padding: 1.3rem 0; + border-top: 1px solid var(--line); + border-bottom: 1px solid var(--line); + list-style: none; + grid-template-columns: repeat(3, 1fr); +} + +.project-facts strong, +.project-facts span { + display: block; +} + +.project-facts strong { + color: var(--coral); + font-family: var(--display); + font-size: 1.5rem; +} + +.project-facts span { + margin-top: 0.15rem; + color: var(--muted); + font-size: 0.55rem; +} + +.text-link { + display: inline-flex; + width: fit-content; + align-items: center; + gap: 0.8rem; + border-bottom: 1px solid currentColor; + font-size: 0.7rem; + font-weight: 600; + letter-spacing: 0.03em; + text-transform: uppercase; +} + +.text-link span { + transition: transform 180ms ease; +} + +.text-link:hover span { + transform: translate(0.2rem, -0.2rem); +} + +.project-grid { + display: grid; + gap: 1rem; + margin-bottom: 1rem; + grid-template-columns: repeat(2, 1fr); +} + +.project-card { + position: relative; + display: flex; + min-height: 31rem; + overflow: hidden; + padding: clamp(1.5rem, 4vw, 3rem); + border-radius: var(--radius-lg); + color: var(--ink); + flex-direction: column; + justify-content: space-between; +} + +.project-card::after { + position: absolute; + right: -5rem; + bottom: -8rem; + width: 19rem; + height: 19rem; + border: 1px solid rgba(17, 23, 26, 0.22); + border-radius: 50%; + box-shadow: 0 0 0 3rem rgba(17, 23, 26, 0.05), 0 0 0 6rem rgba(17, 23, 26, 0.035); + content: ""; + transition: transform 500ms ease; +} + +.project-card:hover::after { + transform: scale(1.12); +} + +.project-card-warm { + background: var(--coral); +} + +.project-card-cool { + background: var(--cyan); +} + +.project-card-top, +.card-footer { + position: relative; + z-index: 2; + display: flex; + align-items: center; + justify-content: space-between; +} + +.project-number { + font-size: 0.7rem; +} + +.repo-live { + display: flex; + align-items: center; + gap: 0.45rem; + font-size: 0.6rem; + letter-spacing: 0.08em; + text-transform: uppercase; +} + +.project-card > div:nth-child(2) { + position: relative; + z-index: 2; + max-width: 39rem; +} + +.project-kicker { + margin-bottom: 0.9rem; +} + +.project-card h3 { + max-width: 10ch; + margin-bottom: 1.5rem; + font-size: clamp(3rem, 6vw, 6rem); + letter-spacing: -0.065em; +} + +.project-card p:last-child { + max-width: 39rem; + margin-bottom: 0; + font-size: 0.8rem; +} + +.tag-row { + display: flex; + flex-wrap: wrap; + gap: 0.4rem; +} + +.tag-row span { + padding: 0.42rem 0.58rem; + border: 1px solid rgba(17, 23, 26, 0.3); + border-radius: 100vw; + font-size: 0.54rem; + font-weight: 600; + text-transform: uppercase; +} + +.card-footer > a { + position: relative; + z-index: 3; + display: grid; + width: 3.1rem; + height: 3.1rem; + place-items: center; + border: 1px solid var(--ink); + border-radius: 50%; + transition: transform 200ms ease, background 200ms ease, color 200ms ease; +} + +.card-footer > a:hover { + transform: rotate(45deg); + background: var(--ink); + color: var(--text); +} + +.project-list { + border-top: 1px solid var(--line); +} + +.project-row { + display: grid; + min-height: 9.4rem; + padding: 1.4rem 0; + border-bottom: 1px solid var(--line); + grid-template-columns: 3rem minmax(12rem, 0.5fr) minmax(16rem, 1fr) minmax(8rem, auto) 3rem; + align-items: center; + gap: clamp(1rem, 3vw, 3rem); + transition: background 180ms ease, padding 180ms ease; +} + +.project-row:hover { + padding-right: 1rem; + padding-left: 1rem; + background: rgba(255, 255, 255, 0.035); +} + +.row-index, +.row-tech, +.project-row > div > p { + color: var(--muted); + font-size: 0.61rem; + letter-spacing: 0.06em; + text-transform: uppercase; +} + +.project-row > div > p { + margin-bottom: 0.4rem; +} + +.project-row h3 { + margin-bottom: 0; + font-size: clamp(1.45rem, 2.4vw, 2.2rem); + letter-spacing: -0.04em; +} + +.project-row > p { + margin-bottom: 0; + color: var(--muted); + font-size: 0.73rem; +} + +.project-row > a { + font-size: 1.2rem; + text-align: right; + transition: color 180ms ease, transform 180ms ease; +} + +.project-row:hover > a { + transform: translate(0.2rem, -0.2rem); + color: var(--coral); +} + +.modrinth-panel { + margin-top: 1rem; + padding: clamp(1.5rem, 4vw, 3rem); + border: 1px solid rgba(96, 222, 139, 0.25); + border-radius: var(--radius-lg); + background: + radial-gradient(circle at 90% 0, rgba(96, 222, 139, 0.12), transparent 24rem), + #101814; +} + +.modrinth-heading { + display: flex; + align-items: end; + justify-content: space-between; + gap: 2rem; + margin-bottom: 3rem; +} + +.modrinth-label { + display: flex; + align-items: center; + gap: 0.65rem; + margin-bottom: 1rem; + color: #68dc91; + font-size: 0.65rem; + font-weight: 600; + letter-spacing: 0.1em; + text-transform: uppercase; +} + +.modrinth-label span { + width: 0.55rem; + height: 0.55rem; + border-radius: 50%; + background: #68dc91; + box-shadow: 0 0 0 0.3rem rgba(104, 220, 145, 0.1); +} + +.modrinth-heading h3 { + max-width: 14ch; + margin-bottom: 0; + font-size: clamp(2.2rem, 4.5vw, 4.6rem); + letter-spacing: -0.055em; +} + +.modrinth-heading .text-link { + margin-bottom: 0.4rem; + color: #68dc91; +} + +.modrinth-grid { + display: grid; + border-top: 1px solid rgba(237, 241, 233, 0.14); + grid-template-columns: repeat(2, 1fr); +} + +.modrinth-item { + display: grid; + min-height: 7.8rem; + padding: 1.25rem 1.25rem 1.25rem 0; + border-bottom: 1px solid rgba(237, 241, 233, 0.14); + grid-template-columns: 2.5rem minmax(10rem, 0.75fr) minmax(9rem, 1fr); + align-items: center; + gap: 1rem; + transition: padding 180ms ease, background 180ms ease; +} + +.modrinth-item:nth-child(odd) { + padding-right: 2rem; + border-right: 1px solid rgba(237, 241, 233, 0.14); +} + +.modrinth-item:nth-child(even) { + padding-left: 2rem; +} + +.modrinth-item:hover { + padding-right: 1.4rem; + padding-left: 1.4rem; + background: rgba(104, 220, 145, 0.055); +} + +.catalog-index { + color: #68dc91; + font-size: 0.62rem; +} + +.modrinth-item strong { + font-family: var(--display); + font-size: 1.12rem; + letter-spacing: -0.025em; +} + +.modrinth-item small, +.modrinth-item b { + color: var(--muted); + font-size: 0.58rem; + font-weight: 400; +} + +.modrinth-item small { + display: none; +} + +.modrinth-item b { + justify-self: end; + text-align: right; +} + +.modrinth-summary { + max-width: 42rem; + margin: 0; + padding-top: 2rem; + border-top: 1px solid rgba(237, 241, 233, 0.14); + color: var(--muted); + font-size: 0.86rem; +} + +.modrinth-stats { + display: flex; + flex-wrap: wrap; + gap: clamp(2rem, 6vw, 4rem); + margin-top: 2rem; +} + +.modrinth-stats div { + display: flex; + flex-direction: column; + gap: 0.3rem; +} + +.modrinth-stats strong { + color: #68dc91; + font-family: var(--display); + font-size: clamp(2rem, 4vw, 2.8rem); + letter-spacing: -0.03em; +} + +.modrinth-stats span { + color: var(--muted); + font-size: 0.68rem; + letter-spacing: 0.04em; + text-transform: uppercase; +} + +.archive-section .section-heading { + margin-bottom: 4rem; +} + +.archive-section .section-heading-row > .text-link { + margin: 1.4rem 0 0 auto; +} + +.archive-grid { + display: grid; + border-top: 1px solid var(--line-dark); + grid-template-columns: repeat(2, 1fr); +} + +.archive-item { + display: grid; + min-height: 6rem; + padding: 1.15rem 1rem 1.15rem 0; + border-bottom: 1px solid var(--line-dark); + grid-template-columns: minmax(9rem, 0.8fr) 1fr auto; + align-items: center; + gap: 1rem; + transition: padding 180ms ease, background 180ms ease; +} + +.archive-item:nth-child(odd) { + padding-right: 2rem; + border-right: 1px solid var(--line-dark); +} + +.archive-item:nth-child(even) { + padding-left: 2rem; +} + +.archive-item:hover { + padding-right: 1.5rem; + padding-left: 1.5rem; + background: rgba(17, 23, 26, 0.055); +} + +.archive-item span { + font-family: var(--display); + font-size: 1.1rem; + font-weight: 700; + letter-spacing: -0.025em; +} + +.archive-item small { + color: var(--muted-dark); + font-size: 0.62rem; +} + +.archive-item b { + color: #a74b2c; + font-weight: 400; +} + +.archive-item-paused { + opacity: 0.7; +} + +.stack-section { + position: relative; +} + +.stack-section::before { + position: absolute; + z-index: -1; + top: 15%; + right: -15%; + width: 40rem; + height: 40rem; + border: 1px solid rgba(143, 212, 208, 0.08); + border-radius: 50%; + box-shadow: 0 0 0 7rem rgba(143, 212, 208, 0.025), 0 0 0 14rem rgba(143, 212, 208, 0.015); + content: ""; +} + +.stack-layout { + display: grid; + gap: 1rem; + grid-template-columns: repeat(12, minmax(0, 1fr)); +} + +.stack-card { + min-width: 0; + min-height: 18rem; + padding: clamp(1.4rem, 3vw, 2.5rem); + border: 1px solid var(--line); + border-radius: var(--radius-lg); + background: linear-gradient(145deg, var(--surface), rgba(17, 25, 31, 0.75)); + grid-column: span 5; +} + +.stack-card-main { + min-height: 37rem; + background: + linear-gradient(145deg, rgba(240, 153, 110, 0.18), transparent 60%), + var(--surface); + grid-row: span 2; + grid-column: span 7; +} + +.stack-card-learning { + display: grid; + min-height: 15rem; + background: var(--lime); + color: var(--ink); + grid-column: span 12; + grid-template-columns: 0.25fr 0.9fr 1fr; + align-items: end; + gap: 2rem; +} + +.stack-label { + margin-bottom: 1rem; + color: var(--coral); +} + +.stack-card-learning .stack-label { + color: #496017; +} + +.stack-card h3 { + max-width: 15ch; + margin: 0 0 2rem; + font-size: clamp(2rem, 4vw, 4rem); + letter-spacing: -0.05em; +} + +.stack-card-learning h3, +.stack-card-learning p { + margin-bottom: 0; +} + +/* GradientText-style animated sweep, ported to plain CSS. Stays in dark + tones (ink/rust) so it holds contrast against the lime card. */ +.stack-card-learning h3 { + position: relative; + display: inline-block; + overflow: hidden; +} + +.stack-card-learning h3::after { + position: absolute; + inset: -20% -10%; + background: linear-gradient(100deg, transparent 40%, rgba(167, 75, 44, 0.8) 50%, transparent 60%); + content: ""; + mix-blend-mode: multiply; + pointer-events: none; + transform: translateX(-140%); + animation: learning-gradient 7s ease-in-out infinite; +} + +@media (prefers-reduced-motion: reduce) { + .stack-card-learning h3::after { + display: none; + } +} + +@keyframes learning-gradient { + 0%, 15% { + transform: translateX(-140%); + } + 60%, 100% { + transform: translateX(140%); + } +} + +.stack-card-learning p { + color: #435020; + font-size: 0.76rem; +} + +.stack-tags { + display: flex; + flex-wrap: wrap; + align-content: flex-start; + gap: 0.5rem; +} + +.stack-tags span { + padding: 0.55rem 0.72rem; + border: 1px solid var(--line); + border-radius: 0.4rem; + background: rgba(0, 0, 0, 0.08); + color: var(--muted); + font-size: 0.62rem; +} + +/* Small callout for the tools the person is strongest in — a marker plus an + animated gradient sweeping through the text fill (ported from React + Bits' GradientText, tuned to the coral/yellow/cyan editorial palette). */ +.stack-tags span.tag-strong { + position: relative; + overflow: visible; + border-color: var(--coral); + font-weight: 600; + background-image: linear-gradient(90deg, var(--coral), var(--yellow), var(--cyan), var(--coral-bright), var(--coral)); + background-size: 300% 100%; + background-position: 0% 50%; + background-clip: text; + -webkit-background-clip: text; + color: transparent; + -webkit-text-fill-color: transparent; + animation: tag-gradient 6s ease-in-out infinite alternate; +} + +.stack-tags span.tag-strong::before { + margin-right: 0.4em; + background: none; + color: var(--coral); + content: "\2726"; + font-size: 0.85em; + -webkit-text-fill-color: var(--coral); +} + +.stack-tags span.tag-strong:nth-of-type(3n) { + animation-delay: -2s; +} + +.stack-tags span.tag-strong:nth-of-type(3n + 1) { + animation-delay: -4s; +} + +@keyframes tag-gradient { + 0% { + background-position: 0% 50%; + } + + 100% { + background-position: 100% 50%; + } +} + +@media (prefers-reduced-motion: reduce) { + .stack-tags span.tag-strong { + animation: none; + background-position: 30% 50%; + } +} + +.stack-intro { + grid-column: 2; + max-width: 36rem; + margin: 1.2rem 0 0; + color: var(--muted); + font-size: 0.86rem; +} + +.stack-meter { + margin-top: 5rem; +} + +.stack-meter span { + display: block; + margin-bottom: 0.6rem; + color: var(--muted); + font-size: 0.61rem; +} + +.stack-meter > i { + display: block; + height: 0.28rem; + overflow: hidden; + border-radius: 1rem; + background: rgba(255, 255, 255, 0.08); +} + +.stack-meter b { + display: block; + height: 100%; + border-radius: inherit; + background: var(--coral); +} + +.contact-section { + position: relative; + width: min(100%, var(--max-width)); + margin: 0 auto; + overflow: hidden; + padding: clamp(5.5rem, 10vw, 10rem) var(--page-pad); + background: var(--coral); + box-shadow: 0 0 0 100vmax var(--coral); + color: var(--ink); + clip-path: inset(0 -100vmax); +} + +.contact-section .section-index { + color: #71351f; +} + +.contact-section h2 { + position: relative; + z-index: 2; + max-width: 11ch; + margin-bottom: 2.5rem; + font-size: clamp(3.3rem, 8.8vw, 9rem); + letter-spacing: -0.075em; +} + +.contact-section h2 span { + color: var(--paper); +} + +.contact-copy { + position: relative; + z-index: 2; + max-width: 44rem; + margin-bottom: 4rem; + font-size: clamp(0.85rem, 1.5vw, 1rem); +} + +.contact-orbit { + position: absolute; + top: 6rem; + right: -7rem; + width: min(44vw, 41rem); + aspect-ratio: 1; + border: 1px solid rgba(17, 23, 26, 0.22); + border-radius: 50%; +} + +.contact-orbit::before, +.contact-orbit::after { + position: absolute; + border: 1px solid rgba(17, 23, 26, 0.15); + border-radius: 50%; + content: ""; +} + +.contact-orbit::before { + inset: 18%; +} + +.contact-orbit::after { + inset: 36%; + background: rgba(233, 229, 218, 0.12); +} + +.contact-orbit span { + position: absolute; + z-index: 2; + width: 0.75rem; + height: 0.75rem; + border-radius: 50%; + background: var(--ink); +} + +.contact-orbit span:first-child { + top: 10%; + left: 19%; +} + +.contact-orbit span:nth-child(2) { + right: 14%; + bottom: 17%; + background: var(--paper); +} + +.contact-orbit span:last-child { + top: 48%; + left: 48%; + width: 1rem; + height: 1rem; +} + +.contact-links { + position: relative; + z-index: 2; + display: grid; + border-top: 1px solid rgba(17, 23, 26, 0.3); + grid-template-columns: repeat(3, 1fr); +} + +.contact-links a, +.contact-links button { + display: grid; + min-height: 8.5rem; + padding: 1.3rem 1.3rem 1.3rem 0; + border: 0; + border-bottom: 1px solid rgba(17, 23, 26, 0.3); + background: transparent; + color: var(--ink); + grid-template-columns: 1fr auto; + align-content: center; + text-align: left; + cursor: pointer; + transition: padding 180ms ease, background 180ms ease; +} + +.contact-links > * + * { + padding-left: 1.5rem; + border-left: 1px solid rgba(17, 23, 26, 0.3); +} + +.contact-links a:hover, +.contact-links button:hover { + padding-right: 1.2rem; + padding-left: 1.2rem; + background: var(--ink); + color: var(--coral); +} + +.contact-links span, +.contact-links small { + display: block; +} + +.contact-links span { + font-family: var(--display); + font-size: clamp(1.4rem, 2.5vw, 2.2rem); + font-weight: 700; +} + +.contact-links small { + margin-top: 0.35rem; + color: currentColor; + font-size: 0.58rem; + opacity: 0.68; +} + +.contact-links b { + font-size: 1.3rem; + font-weight: 400; + grid-column: 2; + grid-row: 1 / 3; + align-self: center; +} + +.copy-status { + min-height: 1.5rem; + margin: 1rem 0 0; + font-size: 0.65rem; +} + +.site-footer { + display: grid; + width: min(100%, var(--max-width)); + min-height: 8rem; + margin: 0 auto; + padding: 2rem var(--page-pad); + grid-template-columns: 1fr auto auto auto; + align-items: center; + gap: 3rem; +} + +.site-footer p { + margin-bottom: 0; + color: var(--muted); + font-size: 0.62rem; +} + +.footer-prompt { + font-family: var(--mono); + letter-spacing: 0.02em; +} + +.footer-prompt .prompt { + color: var(--coral); +} + +.cursor-blink { + display: inline-block; + margin-left: 0.15em; + animation: cursor-blink 1.1s steps(1, end) infinite; +} + +@keyframes cursor-blink { + 0%, 49% { opacity: 1; } + 50%, 100% { opacity: 0; } +} + +.error-page { + display: grid; + min-height: 100svh; + place-items: center; + padding: 2rem; +} + +.error-shell { + width: min(100%, 56rem); + padding: clamp(2rem, 6vw, 5rem); + border: 1px solid var(--line); + border-radius: var(--radius-lg); + background: var(--bg-soft); + box-shadow: 0 2rem 6rem rgba(0, 0, 0, 0.32); +} + +.error-code { + margin-bottom: 1.5rem; + color: var(--coral); + font-size: 0.72rem; + letter-spacing: 0.12em; + text-transform: uppercase; +} + +.error-shell h1 { + max-width: 9ch; + margin-bottom: 1.5rem; + font-size: clamp(3.2rem, 9vw, 7rem); + letter-spacing: -0.07em; +} + +.error-shell p { + max-width: 38rem; + margin-bottom: 2rem; + color: var(--muted); +} + +.js .reveal { + opacity: 0; + transform: translateY(1.8rem); + transition: opacity 700ms ease, transform 700ms cubic-bezier(0.2, 0.75, 0.25, 1); +} + +.js .reveal.is-visible { + opacity: 1; + transform: translateY(0); +} + +.js .method-card:nth-child(2), +.js .project-grid > :nth-child(2), +.js .archive-item:nth-child(even) { + transition-delay: 80ms; +} + +.js .method-card:nth-child(3) { + transition-delay: 160ms; +} + +@keyframes status-pulse { + 0% { + transform: scale(0.55); + opacity: 0.8; + } + 75%, + 100% { + transform: scale(1.4); + opacity: 0; + } +} + +@keyframes packet { + from { left: -0.4rem; } + to { left: 100%; } +} + +@keyframes marquee { + from { transform: translateX(0); } + to { transform: translateX(-50%); } +} + +@media (max-width: 74rem) { + .hero { + min-height: auto; + padding-top: 9rem; + padding-bottom: 8rem; + grid-template-columns: minmax(0, 1fr); + } + + .hero-copy { + max-width: 68rem; + } + + .hero h1 { + max-width: 12ch; + } + + .terminal-card { + width: min(100%, 48rem); + margin: 0 auto; + transform: rotate(0.7deg); + } + + .section-heading, + .section-heading-row { + grid-template-columns: 1fr; + } + + .section-heading .section-index { + margin-bottom: 1.5rem; + } + + .section-heading-row > p, + .archive-section .section-heading-row > .text-link { + margin: 1.5rem 0 0; + } + + .project-feature { + grid-template-columns: 1fr; + } + + .current-project { + grid-template-columns: 1fr; + } + + .current-roadmap { + border-top: 1px solid rgba(17, 23, 26, 0.18); + border-left: 0; + } + + .project-visual { + min-height: 31rem; + } + + .project-visual::after { + background: linear-gradient(0deg, rgba(17, 25, 31, 0.75), transparent 28%); + } + + .project-feature-copy h3 { + margin-top: 4rem; + } + + .project-row { + grid-template-columns: 2rem minmax(11rem, 0.5fr) minmax(15rem, 1fr) 2rem; + } + + .modrinth-item { + grid-template-columns: 2rem minmax(9rem, 1fr) minmax(8rem, auto); + } + + .row-tech { + display: none; + } + + .stack-card-main { + grid-column: span 12; + } + + .stack-card:not(.stack-card-main, .stack-card-learning) { + grid-column: span 6; + } + + .stack-card-learning { + grid-template-columns: 0.3fr 1fr 1fr; + } +} + +@media (max-width: 52rem) { + .site-header { + top: 0.6rem; + width: calc(100% - 1.2rem); + } + + .site-nav > a:not(.nav-pill) { + display: none; + } + + .hero { + padding-top: 8.5rem; + } + + .hero-signals { + display: grid; + grid-template-columns: repeat(3, 1fr); + } + + .hero-signals li { + padding-right: 0.5rem; + } + + .profile-chip { + right: 0.6rem; + width: min(23rem, 88%); + } + + .about-layout { + grid-template-columns: 1fr; + } + + .about-copy { + max-width: none; + } + + .method-grid, + .project-grid, + .archive-grid, + .contact-links { + grid-template-columns: 1fr; + } + + .method-card { + min-height: auto; + padding: 1.5rem 0 2rem; + } + + .method-card + .method-card { + border-top: 1px solid var(--line-dark); + border-left: 0; + } + + .method-card h3 { + margin-top: 2rem; + } + + .project-card { + min-height: 27rem; + } + + .current-project h3 { + font-size: clamp(3.2rem, 16.5vw, 7rem); + } + + .current-kicker { + margin-top: 5rem; + } + + .project-row { + padding: 1.5rem 0; + grid-template-columns: 2rem 1fr 2rem; + } + + .project-row > p, + .row-tech { + display: none; + } + + .modrinth-heading { + display: grid; + align-items: start; + } + + .modrinth-grid { + grid-template-columns: 1fr; + } + + .modrinth-item:nth-child(odd), + .modrinth-item:nth-child(even) { + padding-right: 0; + padding-left: 0; + border-right: 0; + } + + .modrinth-item:hover { + padding-right: 0.8rem; + padding-left: 0.8rem; + } + + .modrinth-item { + grid-template-columns: 2rem minmax(0, 1fr); + } + + .modrinth-item b { + grid-column: 2; + justify-self: start; + text-align: left; + } + + .archive-item:nth-child(odd), + .archive-item:nth-child(even) { + padding-right: 0; + padding-left: 0; + border-right: 0; + } + + .archive-item:hover { + padding-right: 0.8rem; + padding-left: 0.8rem; + } + + .stack-card, + .stack-card-main, + .stack-card:not(.stack-card-main, .stack-card-learning), + .stack-card-learning { + min-height: auto; + grid-column: span 12; + } + + .stack-card-main { + min-height: 31rem; + } + + .stack-card-learning { + display: block; + } + + .stack-card-learning h3 { + margin-bottom: 1.5rem; + } + + .contact-orbit { + top: 3rem; + right: -12rem; + width: 26rem; + } + + .contact-links > * + * { + padding-left: 0; + border-left: 0; + } + + .contact-links a:hover, + .contact-links button:hover { + padding-left: 1rem; + } + + .site-footer { + grid-template-columns: 1fr auto; + gap: 1rem; + } + + .site-footer p:first-of-type { + display: none; + } + + .footer-prompt { + display: none; + } +} + +@media (max-width: 36rem) { + .hero h1 { + font-size: clamp(3rem, 14vw, 4.2rem); + } + + .hero-actions { + display: grid; + } + + .button { + width: 100%; + } + + .hero-signals { + grid-template-columns: 1fr; + } + + .hero-signals li { + padding: 0.7rem 0; + } + + .hero-signals li + li { + padding-left: 0; + border-top: 1px solid var(--line); + border-left: 0; + } + + .hero-signals span { + display: inline; + margin-right: 0.7rem; + } + + .terminal-chrome { + grid-template-columns: 1fr auto; + } + + .terminal-chrome > span:nth-child(2) { + display: none; + } + + .infra-map { + grid-template-columns: 1fr; + gap: 0.55rem; + } + + .infra-line { + width: 1px; + height: 0.8rem; + margin: 0 auto; + } + + .infra-line span { + display: none; + } + + .service-row { + grid-template-columns: repeat(2, 1fr); + } + + .profile-chip { + position: relative; + right: auto; + bottom: auto; + width: calc(100% - 2rem); + margin: 0 1rem -2rem; + transform: rotate(-1deg); + } + + .project-visual { + min-height: 19rem; + } + + .project-meta { + display: grid; + } + + .project-facts { + grid-template-columns: repeat(3, 1fr); + } + + .archive-item { + grid-template-columns: 1fr auto; + } + + .archive-item small { + grid-column: 1; + grid-row: 2; + } + + .archive-item b { + grid-column: 2; + grid-row: 1 / 3; + } +} + +@media (prefers-reduced-motion: reduce) { + html { + scroll-behavior: auto; + } + + *, + *::before, + *::after { + animation-duration: 0.01ms !important; + animation-iteration-count: 1 !important; + scroll-behavior: auto !important; + transition-duration: 0.01ms !important; + } + + .signal-track { + animation: none; + } +} + +@media print { + .site-header, + .signal-strip, + .contact-orbit, + .page-grid { + display: none; + } + + body, + .about-section, + .archive-section, + .contact-section { + background: white; + box-shadow: none; + color: black; + } + + .hero { + min-height: auto; + padding-top: 2rem; + } +} diff --git a/deploy/nginx.conf b/deploy/nginx.conf new file mode 100644 index 0000000..2c7245d --- /dev/null +++ b/deploy/nginx.conf @@ -0,0 +1,47 @@ +server { + listen 80 default_server; + listen [::]:80 default_server; + server_name _; + + root /usr/share/nginx/html; + index index.html; + charset utf-8; + server_tokens off; + + add_header X-Content-Type-Options "nosniff" always; + add_header X-Frame-Options "DENY" always; + add_header Referrer-Policy "strict-origin-when-cross-origin" always; + add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always; + add_header Content-Security-Policy "default-src 'self'; base-uri 'self'; form-action 'none'; frame-ancestors 'none'; script-src 'self'; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com; img-src 'self' data:; connect-src 'self'" always; + + gzip on; + gzip_vary on; + gzip_min_length 1024; + gzip_types text/plain text/css application/javascript application/json application/manifest+json image/svg+xml; + + location = /healthz { + access_log off; + default_type text/plain; + return 200 "ok\n"; + } + + location = /index.html { + expires -1; + try_files $uri =404; + } + + location ~* \.(?:css|js|png|jpe?g|gif|svg|ico|webmanifest)$ { + expires 1h; + try_files $uri =404; + } + + location / { + try_files $uri $uri/ =404; + } + + error_page 404 /404.html; + + location = /404.html { + internal; + } +} diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..030efcf --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,39 @@ +name: fiws-page + +services: + fiws-page: + image: fiws-page:latest + container_name: fiws-page + build: + context: . + dockerfile: Dockerfile + target: runtime + restart: unless-stopped + init: true + read_only: true + security_opt: + - no-new-privileges:true + tmpfs: + - /var/cache/nginx + - /var/run + - /tmp + expose: + - "80" + networks: + - proxy + labels: + traefik.enable: "true" + traefik.docker.network: "${TRAEFIK_NETWORK:-proxy}" + + traefik.http.services.fiws-page.loadbalancer.server.port: "80" + + traefik.http.routers.fiws-page.rule: "Host(`${DOMAIN:-fiwlabs.dev}`)" + traefik.http.routers.fiws-page.entrypoints: "${TRAEFIK_HTTPS_ENTRYPOINT:-websecure}" + traefik.http.routers.fiws-page.service: "fiws-page" + traefik.http.routers.fiws-page.tls: "true" + traefik.http.routers.fiws-page.tls.certresolver: "${TRAEFIK_CERT_RESOLVER:-porkbun}" + +networks: + proxy: + external: true + name: "${TRAEFIK_NETWORK:-proxy}" diff --git a/favicon.ico b/favicon.ico new file mode 100644 index 0000000..1704723 Binary files /dev/null and b/favicon.ico differ diff --git a/icon.png b/icon.png new file mode 100644 index 0000000..826d893 Binary files /dev/null and b/icon.png differ diff --git a/icon.svg b/icon.svg new file mode 100644 index 0000000..01ff40e --- /dev/null +++ b/icon.svg @@ -0,0 +1,8 @@ + + Fi3w0 terminal mark + + + + + + diff --git a/img/avatar.png b/img/avatar.png new file mode 100644 index 0000000..b9c2c87 Binary files /dev/null and b/img/avatar.png differ diff --git a/img/flux-icon.png b/img/flux-icon.png new file mode 100644 index 0000000..bb3bb92 Binary files /dev/null and b/img/flux-icon.png differ diff --git a/img/flux-overview.jpg b/img/flux-overview.jpg new file mode 100644 index 0000000..f354a78 Binary files /dev/null and b/img/flux-overview.jpg differ diff --git a/img/moonlit-shell.jpg b/img/moonlit-shell.jpg new file mode 100644 index 0000000..f9323dd Binary files /dev/null and b/img/moonlit-shell.jpg differ diff --git a/img/tidewm-logo.png b/img/tidewm-logo.png new file mode 100644 index 0000000..0297dd6 Binary files /dev/null and b/img/tidewm-logo.png differ diff --git a/index.html b/index.html new file mode 100644 index 0000000..a83a5de --- /dev/null +++ b/index.html @@ -0,0 +1,420 @@ + + + + + + + Fi3w0 / Alex - Systems Builder + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+

alex@fiw:~ $ cat about.txt

+

Alex / Fi3w0

+

+ I make Linux and macOS desktop tools, run a homelab, and publish Minecraft server mods. + Most of my projects start as something I wanted for my own machine or server, + then grow until they are useful to somebody else too. +

+ + + +
    +
  • 01 Arch at the desk
  • +
  • 02 Ubuntu on the server
  • +
  • 03 break it, learn, repeat
  • +
+
+ + +
+ +
+
+
+ Arch Linux + Ubuntu Server + Docker + Minecraft tooling + Wayland + Self-hosting + Things configured with JSON + Bash + Rust + Go + Lua + Kotlin + TypeScript + GitHub Actions + FFmpeg + macOS +
+ +
+
+ +
+
+

01 / About

+

What I actually do.

+
+ +
+
+ +

I care more about the whole machine than winning an argument about one language.

+
Design it, configure it, deploy it, then fix the boring parts.
+
+ +
+

+ Some weeks I am building a Minecraft framework. Other weeks I replace half my desktop + shell or add something unnecessary to the mini PC under my desk. +

+

+ My projects jump between low-level desktop work and data-driven server tools, but the part I enjoy + is the same: turning rough pieces into something I can run and maintain myself. +

+

+ Linux, systemd, Docker, Traefik, backups, and CI pipelines are familiar territory. I like + hot reload, readable config files, updates that can fail safely, and logs that say what went wrong. +

+

+ I write Bash, Go, Lua, and modify Java directly. For Rust, Swift, and larger Kotlin, TypeScript, Python, + and QML builds, I use AI agents heavily, then review, test, and integrate the result myself. +

+
+ Ukrainian + RussianSpanishEnglish C1 +
+
+
+ +
+
+ 01

Start with the mess

Work out the data, failure cases, and who has to maintain it before choosing the clever part.

+
+
+ 02

Automate repeats

If I have to do it twice, it probably needs a script, an installer, or a CI job.

+
+
+ 03

Make it recoverable

Reboots, bad input, old versions, and my own mistakes are normal operating conditions.

+
+
+
+ +
+
+

02 / Work

Projects, tools, experiments.

+

Public repositories, installable mods, and rougher ideas that started on my own machines.

+
+ +
+
+
Daily-driver compositorAI-assisted / evolving
+

Wayland compositor / Rust

+
+ +

TideWM

+
+

A water-themed Wayland compositor built on Smithay, made because I wanted to see how far I could take it. Tiling (BSP and master/stack), multi-monitor, XWayland, workspaces, and IPC already run as my daily driver; the signature aqua render effects are next.

+
AI-assistedSmithayRustWayland
+ View repository +
+
+

Project shape

+
    +
  1. 01
    FoundationRust compositor built directly on Smithay
    base
  2. +
  3. 02
    Tiling & compatBSP/master-stack layouts, multi-monitor, XWayland
    done
  4. +
  5. 03
    Visual directionWater/aqua render effects, still pending
    next
  6. +
  7. 04
    Development methodAI-assisted implementation, tested and reviewed by me
    method
  8. +
+
+ + +
+ +
+ + + + + + + + + macOS Tahoe / Apple silicon + +
+
Latest projectSwiftUI / AppKit / macOS
+

Flux

+

A native macOS media workbench: convert, download, edit, and compose media in one focused app. FFmpeg, yt-dlp, and Apple Vision underneath, pre-flight checks that explain failures before a job ever starts, and everything processed locally.

+
    +
  • 7media engines
  • +
  • 0telemetry
  • +
  • 100%local processing
  • +
+ View repository +
+
+ +
+ + Moonlit Shell desktop with its top bar over a nocturnal landscape + Daily driver / ThinkPad T14 + +
+
Featured systemQML / Go / Linux
+

Moonlit Shell

+

This is the desktop I actually use: Arch, Hyprland, and Quickshell with twelve panels, a live settings app, safe dotfile updates, and no monitoring daemon between the UI and /proc.

+
    +
  • 12native panels
  • +
  • 1live config
  • +
  • 0glue daemons
  • +
+ View repository +
+
+ +
+
+
01 published
+
+

Framework / Java

+

FIW Bosses

+

A JSON-driven, multi-loader boss framework with HP phases, custom minions, dialogue, loot, hot reload, and more than 50 configurable abilities.

+
+ +
+ +
+
02 published
+
+

Framework / Kotlin

+

FIW Custom Items

+

Server-side custom weapons, armor, crafting, curses, set bonuses, charges, and abilities built entirely through JSON. Vanilla clients can connect.

+
+ +
+
+ +
+
+ 03 +

Security tooling

FIW AntiCheat

+

Nonce challenges, mod signatures, resource-pack auditing, and honest limits across six loader/version targets.

+ Java / SHA-256 + +
+
+ 04 +

Reliability

FIW Graves

+

Packet-only grave markers, world-native persistence, rollback history, and a second loot safety net.

+ Java / Packets + +
+
+ 05 +

Server operations

FIW Admin Utilities

+

Maintenance mode, lag watchdog, entity sweeping, vanish, freeze, and item bans in one lightweight admin mod.

+ Fabric / NeoForge + +
+
+ +
+
+
+

Published on Modrinth

+

Mods people can install.

+
+ View creator profile +
+ +

Every mod above (plus Warp, Graves, and Tickwatch from the archive) ships through one Modrinth profile — same JSON-config philosophy, same hot reload, across Fabric, Forge, and NeoForge.

+ +
+
7mods published
+
3loaders supported
+
1creator profile
+
+
+
+ +
+
+

03 / Repositories

Other things I made.

+ All repositories +
+ + +
+ +
+
+

04 / Tools

+

What is usually open in my terminal.

+

Kitty as the daily emulator, running on a MacBook (macOS) — my main device — SSH'd out to the Arch desktop and the Ubuntu server for everything else.

+
+ +
+
+

Home turf

+

Linux / systems

+
Arch LinuxBashUbuntu ServersystemdSSHNetworking
+
+
+

Ship + operate

+

Infrastructure

+
DockerComposeTraefikPortainerGitHub ActionsBackups
+
+
+

Build surface

+

Code + config

+
GoLuaRust / AI-assistedJavaKotlinTypeScriptQMLJSON
+
+
+

Learning next

+

Kubernetes, Terraform, Ansible

+

I am learning these when a real problem gives me a reason, not just to collect more logos.

+
+
+
+ +
+ +

05 / Contact

+

Say hello.

+

Linux, infrastructure, self-hosting, Minecraft tooling, or a strange project you cannot stop thinking about are all good reasons to message me.

+ +

+
+
+ + + + + + + diff --git a/js/app.js b/js/app.js new file mode 100644 index 0000000..fdf5e16 --- /dev/null +++ b/js/app.js @@ -0,0 +1,1354 @@ +const root = document.documentElement; +root.classList.remove("no-js"); +root.classList.add("js"); + +const reducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches; +const revealItems = document.querySelectorAll(".reveal"); + +if (reducedMotion || !("IntersectionObserver" in window)) { + revealItems.forEach((item) => item.classList.add("is-visible")); +} else { + const revealObserver = new IntersectionObserver( + (entries, observer) => { + entries.forEach((entry) => { + if (!entry.isIntersecting) return; + entry.target.classList.add("is-visible"); + observer.unobserve(entry.target); + }); + }, + { rootMargin: "0px 0px -8%", threshold: 0.08 }, + ); + + revealItems.forEach((item) => revealObserver.observe(item)); +} + +const year = document.querySelector("#year"); +if (year) year.textContent = new Date().getFullYear().toString(); + +const glitchName = document.querySelector("#glitch-name"); +const finePointer = window.matchMedia("(hover: hover) and (pointer: fine)").matches; + +if (glitchName && finePointer && !reducedMotion) { + const glyphField = document.createElement("div"); + const glyphs = "01ABCDEFGHIJKLMNOPQRSTUVWXYZ{}[]<>/\\#$%&*+?=;:"; + const colorClasses = ["", "is-cyan", "is-lime", "is-paper"]; + let active = false; + let intervalId; + let lastSpawn = 0; + let pointerX = window.innerWidth * 0.5; + let pointerY = window.innerHeight * 0.5; + + glyphField.className = "glitch-field"; + glyphField.setAttribute("aria-hidden", "true"); + document.body.append(glyphField); + + const randomBetween = (min, max) => min + Math.random() * (max - min); + + const spawnGlyph = (origin) => { + if (glyphField.childElementCount >= 64) glyphField.firstElementChild?.remove(); + + const glyph = document.createElement("span"); + const nearPointer = Boolean(origin); + const x = nearPointer ? origin.x + randomBetween(-44, 44) : randomBetween(20, window.innerWidth - 20); + const y = nearPointer ? origin.y + randomBetween(-30, 30) : randomBetween(40, window.innerHeight - 30); + const travel = nearPointer ? 150 : 90; + + glyph.className = `glitch-glyph ${colorClasses[Math.floor(Math.random() * colorClasses.length)]}`.trim(); + glyph.textContent = glyphs[Math.floor(Math.random() * glyphs.length)]; + glyph.style.setProperty("--x", `${x}px`); + glyph.style.setProperty("--y", `${y}px`); + glyph.style.setProperty("--dx", `${randomBetween(-travel, travel)}px`); + glyph.style.setProperty("--dy", `${randomBetween(-travel, travel)}px`); + glyph.style.setProperty("--rot", `${randomBetween(-80, 80)}deg`); + glyph.style.setProperty("--size", `${randomBetween(0.65, 1.45)}rem`); + glyph.style.setProperty("--life", `${randomBetween(650, 1350)}ms`); + glyph.addEventListener("animationend", () => glyph.remove(), { once: true }); + glyphField.append(glyph); + }; + + const burst = (count) => { + const rect = glitchName.getBoundingClientRect(); + const origin = { x: rect.left + rect.width * 0.5, y: rect.top + rect.height * 0.55 }; + for (let index = 0; index < count; index += 1) spawnGlyph(origin); + }; + + const startGlitch = (event) => { + if (active) return; + active = true; + pointerX = event.clientX; + pointerY = event.clientY; + document.body.classList.add("glitch-active"); + burst(18); + intervalId = window.setInterval(() => { + if (!active) return; + spawnGlyph({ x: pointerX, y: pointerY }); + spawnGlyph(); + }, 115); + }; + + const moveGlitch = (event) => { + pointerX = event.clientX; + pointerY = event.clientY; + const now = performance.now(); + if (now - lastSpawn < 42) return; + lastSpawn = now; + spawnGlyph({ x: pointerX, y: pointerY }); + }; + + const stopGlitch = () => { + active = false; + document.body.classList.remove("glitch-active"); + window.clearInterval(intervalId); + }; + + glitchName.addEventListener("pointerenter", startGlitch); + glitchName.addEventListener("pointermove", moveGlitch); + glitchName.addEventListener("pointerleave", stopGlitch); + glitchName.addEventListener("pointercancel", stopGlitch); + document.addEventListener("visibilitychange", () => { + if (document.hidden) stopGlitch(); + }); +} + +const scrambleHeadings = document.querySelectorAll(".section-heading h2, #contact-title"); +const scrambleGlyphs = "01ABCDEFGHIJKLMNOPQRSTUVWXYZ{}[]<>/\\#$%&*+?=;:"; + +if (scrambleHeadings.length && !reducedMotion && "IntersectionObserver" in window) { + scrambleHeadings.forEach((heading) => { + heading.dataset.finalText = heading.textContent ?? ""; + }); + + const decryptHeading = (heading, duration = 600, steps = 14) => { + const finalText = heading.dataset.finalText ?? ""; + const totalChars = finalText.length; + let frame = 0; + + const timer = window.setInterval(() => { + frame += 1; + const revealCount = Math.floor((frame / steps) * totalChars); + heading.textContent = finalText + .split("") + .map((char, index) => { + if (char === " " || index < revealCount) return char; + return scrambleGlyphs[Math.floor(Math.random() * scrambleGlyphs.length)]; + }) + .join(""); + + if (frame >= steps) { + heading.textContent = finalText; + window.clearInterval(timer); + } + }, duration / steps); + }; + + const scrambleObserver = new IntersectionObserver( + (entries, observer) => { + entries.forEach((entry) => { + if (!entry.isIntersecting) return; + decryptHeading(entry.target); + observer.unobserve(entry.target); + }); + }, + { rootMargin: "0px 0px -10%", threshold: 0.4 }, + ); + + scrambleHeadings.forEach((heading) => scrambleObserver.observe(heading)); +} + +const gooeyNav = document.querySelector(".nav-gooey"); +const gooeyLinks = document.querySelectorAll(".site-nav > a:not(.nav-pill)"); + +if (gooeyNav && gooeyLinks.length && !reducedMotion) { + const navEl = gooeyNav.parentElement; + const blob = gooeyNav.querySelector(".nav-gooey-blob--lead"); + const pad = 10; + let litLink = null; + let jumpTimeout; + + const moveBlob = (target) => { + const navRect = navEl.getBoundingClientRect(); + const rect = target.getBoundingClientRect(); + + blob.style.left = `${rect.left - navRect.left - pad}px`; + blob.style.top = `${rect.top - navRect.top - pad}px`; + blob.style.width = `${rect.width + pad * 2}px`; + blob.style.height = `${rect.height + pad * 2}px`; + + gooeyNav.classList.add("is-active", "is-jumping"); + window.clearTimeout(jumpTimeout); + jumpTimeout = window.setTimeout(() => gooeyNav.classList.remove("is-jumping"), 220); + + litLink?.classList.remove("is-lit"); + litLink = target; + litLink.classList.add("is-lit"); + }; + + gooeyLinks.forEach((link) => { + link.addEventListener("pointerenter", () => moveBlob(link)); + link.addEventListener("focus", () => moveBlob(link)); + }); + + const clear = () => { + gooeyNav.classList.remove("is-active"); + litLink?.classList.remove("is-lit"); + litLink = null; + }; + + navEl.addEventListener("pointerleave", clear); + + navEl.addEventListener("focusout", (event) => { + if (!navEl.contains(event.relatedTarget)) clear(); + }); +} + +// --- ASCIIText, ported from React Bits (vanilla JS, three.js loaded on +// demand). Replaces the flat "TIDE" watermark on the TideWM card with a +// rippling, wave-distorted ASCII render once the card scrolls into view. +// The plain-text watermark stays in the DOM as the fallback if WebGL or the +// three.js CDN load ever fails. --- +(() => { + const targets = [ + { + host: document.querySelector("#tide-ascii"), + ancestorSelector: ".current-project", + readyClass: "has-tide-ascii", + text: "TIDE", + enableWaves: true, + asciiFontSize: 11, + textFontSize: 220, + }, + { + // Flux is a media-editing tool, not a water compositor — keep its + // watermark shape still and crisp (no mesh ripple), but let the + // glyphs themselves flicker/decode for a "processing feed" feel. + host: document.querySelector("#flux-ascii"), + ancestorSelector: ".project-visual-flux", + readyClass: "has-flux-ascii", + text: "FLUX", + enableWaves: false, + charJitter: true, + asciiFontSize: 8, + textFontSize: 240, + }, + ] + .map((t) => ({ ...t, ancestor: t.host?.closest(t.ancestorSelector) })) + .filter((t) => t.host && t.ancestor); + + if (!targets.length || reducedMotion) return; + + let hasWebGL = false; + try { + const testCanvas = document.createElement("canvas"); + hasWebGL = Boolean(testCanvas.getContext("webgl") || testCanvas.getContext("experimental-webgl")); + } catch { + hasWebGL = false; + } + if (!hasWebGL) return; + + const THREE_CDN_URL = "https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"; + let threeLoadPromise = null; + + const loadThree = () => { + if (window.THREE) return Promise.resolve(); + if (!threeLoadPromise) { + threeLoadPromise = new Promise((resolve, reject) => { + const script = document.createElement("script"); + script.src = THREE_CDN_URL; + script.onload = () => resolve(); + script.onerror = () => reject(new Error("three.js failed to load")); + document.head.append(script); + }); + } + return threeLoadPromise; + }; + + const mapRange = (n, start, stop, start2, stop2) => ((n - start) / (stop - start)) * (stop2 - start2) + start2; + + const vertexShader = ` + varying vec2 vUv; + uniform float uTime; + uniform float uEnableWaves; + void main() { + vUv = uv; + float time = uTime * 5.0; + float waveFactor = uEnableWaves; + vec3 transformed = position; + transformed.x += sin(time + position.y) * 0.5 * waveFactor; + transformed.y += cos(time + position.z) * 0.15 * waveFactor; + transformed.z += sin(time + position.x) * waveFactor; + gl_Position = projectionMatrix * modelViewMatrix * vec4(transformed, 1.0); + } + `; + + const fragmentShader = ` + varying vec2 vUv; + uniform float uTime; + uniform float uEnableWaves; + uniform sampler2D uTexture; + void main() { + float time = uTime; + vec2 pos = vUv; + float amount = mix(0.006, 0.01, uEnableWaves); + float r = texture2D(uTexture, pos + cos(time * 2.0 - time + pos.x) * amount).r; + float g = texture2D(uTexture, pos + tan(time * 0.5 + pos.x - time) * amount).g; + float b = texture2D(uTexture, pos - cos(time * 2.0 + time + pos.y) * amount).b; + float a = texture2D(uTexture, pos).a; + gl_FragColor = vec4(r, g, b, a); + } + `; + + class AsciiFilter { + constructor(renderer, { fontSize, fontFamily, charset, charJitter } = {}) { + this.renderer = renderer; + this.domElement = document.createElement("div"); + this.domElement.className = "tide-ascii-inner"; + this.pre = document.createElement("pre"); + this.pre.className = "tide-ascii-pre"; + this.domElement.append(this.pre); + this.canvas = document.createElement("canvas"); + this.canvas.className = "tide-ascii-canvas"; + this.context = this.canvas.getContext("2d"); + this.domElement.append(this.canvas); + this.fontSize = fontSize ?? 8; + this.fontFamily = fontFamily ?? "'IBM Plex Mono', monospace"; + this.charset = charset ?? " .'`^\",:;Il!i~+_-?][}{1)(|/tfjrxnuvczXYUJCLQ0OZmwqpdbkhao*#MW&8%B@$"; + // Optional per-cell character flicker — a subtle "decoding" glitch + // where a handful of glyphs jump to a denser/lighter char and settle + // back, independent of any mesh/wave motion. + this.charJitter = charJitter ?? false; + this.context.imageSmoothingEnabled = false; + } + + setSize(width, height) { + if (!width || !height) return; + this.width = width; + this.height = height; + this.renderer.setSize(width, height); + this.reset(); + } + + reset() { + this.context.font = `${this.fontSize}px ${this.fontFamily}`; + const charWidth = this.context.measureText("A").width; + this.cols = Math.max(1, Math.floor(this.width / (this.fontSize * (charWidth / this.fontSize)))); + this.rows = Math.max(1, Math.floor(this.height / this.fontSize)); + this.canvas.width = this.cols; + this.canvas.height = this.rows; + this.pre.style.fontFamily = this.fontFamily; + this.pre.style.fontSize = `${this.fontSize}px`; + } + + render(scene, camera, time) { + this.renderer.render(scene, camera); + const w = this.canvas.width; + const h = this.canvas.height; + this.context.clearRect(0, 0, w, h); + if (this.context && w && h) this.context.drawImage(this.renderer.domElement, 0, 0, w, h); + this.asciify(this.context, w, h, time ?? 0); + } + + asciify(ctx, w, h, time = 0) { + if (!w || !h) return; + const imgData = ctx.getImageData(0, 0, w, h).data; + const jitter = this.charJitter; + const frameBucket = Math.floor(time * 7); + const last = this.charset.length - 1; + let str = ""; + for (let y = 0; y < h; y += 1) { + for (let x = 0; x < w; x += 1) { + const i = x * 4 + y * 4 * w; + const [r, g, b, a] = [imgData[i], imgData[i + 1], imgData[i + 2], imgData[i + 3]]; + if (a === 0) { + str += " "; + continue; + } + const gray = (0.3 * r + 0.6 * g + 0.1 * b) / 255; + let idx = this.charset.length - Math.floor((1 - gray) * last) - 1; + if (jitter) { + const seed = Math.sin(x * 12.9898 + y * 78.233 + frameBucket * 37.719) * 43758.5453; + const rnd = seed - Math.floor(seed); + if (rnd > 0.85) { + const swing = Math.floor(((rnd - 0.85) / 0.15) * 8) - 4; + idx = Math.min(last, Math.max(0, idx + swing)); + } + } + str += this.charset[idx]; + } + str += "\n"; + } + this.pre.textContent = str; + } + + dispose() {} + } + + class CanvasTxt { + constructor(txt, { fontSize = 200, fontFamily = "Arial", color = "#fdf9f3" } = {}) { + this.canvas = document.createElement("canvas"); + this.context = this.canvas.getContext("2d"); + this.txt = txt; + this.font = `600 ${fontSize}px ${fontFamily}`; + this.color = color; + } + + resize() { + this.context.font = this.font; + const metrics = this.context.measureText(this.txt); + this.canvas.width = Math.ceil(metrics.width) + 20; + this.canvas.height = Math.ceil((metrics.actualBoundingBoxAscent || 0) + (metrics.actualBoundingBoxDescent || 0)) + 20; + } + + render() { + this.context.clearRect(0, 0, this.canvas.width, this.canvas.height); + this.context.fillStyle = this.color; + this.context.font = this.font; + const metrics = this.context.measureText(this.txt); + this.context.fillText(this.txt, 10, 10 + metrics.actualBoundingBoxAscent); + } + + get width() { + return this.canvas.width; + } + + get height() { + return this.canvas.height; + } + + get texture() { + return this.canvas; + } + } + + class CanvAscii { + constructor({ text, asciiFontSize, textFontSize, textColor, planeBaseHeight, enableWaves, charJitter }, container, width, height) { + this.textString = text; + this.asciiFontSize = asciiFontSize; + this.textFontSize = textFontSize; + this.textColor = textColor; + this.planeBaseHeight = planeBaseHeight; + this.container = container; + this.width = width; + this.height = height; + this.enableWaves = enableWaves; + this.charJitter = charJitter; + this.camera = new window.THREE.PerspectiveCamera(45, this.width / this.height, 1, 1000); + this.camera.position.z = 30; + this.scene = new window.THREE.Scene(); + } + + async init() { + try { + await document.fonts.load(`600 200px "IBM Plex Mono"`); + } catch { + // fall back to default font metrics if the webfont isn't ready yet + } + this.setMesh(); + this.setRenderer(); + } + + setMesh() { + const THREE = window.THREE; + this.textCanvas = new CanvasTxt(this.textString, { + fontSize: this.textFontSize, + fontFamily: "IBM Plex Mono", + color: this.textColor, + }); + this.textCanvas.resize(); + this.textCanvas.render(); + this.texture = new THREE.CanvasTexture(this.textCanvas.texture); + this.texture.minFilter = THREE.NearestFilter; + const textAspect = this.textCanvas.width / this.textCanvas.height; + const planeW = this.planeBaseHeight * textAspect; + this.geometry = new THREE.PlaneGeometry(planeW, this.planeBaseHeight, 36, 36); + this.material = new THREE.ShaderMaterial({ + vertexShader, + fragmentShader, + transparent: true, + uniforms: { + uTime: { value: 0 }, + uTexture: { value: this.texture }, + uEnableWaves: { value: this.enableWaves ? 1 : 0 }, + }, + }); + this.mesh = new THREE.Mesh(this.geometry, this.material); + this.scene.add(this.mesh); + } + + setRenderer() { + const THREE = window.THREE; + this.renderer = new THREE.WebGLRenderer({ antialias: false, alpha: true }); + this.renderer.setPixelRatio(1); + this.renderer.setClearColor(0x000000, 0); + this.filter = new AsciiFilter(this.renderer, { fontSize: this.asciiFontSize, charJitter: this.charJitter }); + this.container.append(this.filter.domElement); + this.setSize(this.width, this.height); + } + + setSize(w, h) { + if (!w || !h) return; + this.width = w; + this.height = h; + this.camera.aspect = w / h; + this.camera.updateProjectionMatrix(); + this.filter.setSize(w, h); + } + + animate() { + const frame = () => { + this.animationFrameId = requestAnimationFrame(frame); + this.renderFrame(); + }; + frame(); + } + + renderFrame() { + const time = Date.now() * 0.001; + this.mesh.material.uniforms.uTime.value = Math.sin(time); + this.filter.render(this.scene, this.camera, time); + } + + dispose() { + if (this.animationFrameId) cancelAnimationFrame(this.animationFrameId); + this.filter?.dispose(); + this.filter?.domElement?.remove(); + this.renderer?.dispose(); + } + } + + const mount = async ({ host, ancestor, readyClass, text, enableWaves, charJitter, asciiFontSize, textFontSize }) => { + try { + await loadThree(); + } catch { + return; + } + if (!window.THREE) return; + + const rect = host.getBoundingClientRect(); + if (rect.width < 20 || rect.height < 20) return; + + let instance; + try { + instance = new CanvAscii( + { + text, + asciiFontSize: asciiFontSize ?? 11, + textFontSize: textFontSize ?? 220, + textColor: "#eaf9f7", + planeBaseHeight: 8, + enableWaves: enableWaves ?? true, + charJitter: charJitter ?? false, + }, + host, + rect.width, + rect.height, + ); + await instance.init(); + instance.animate(); + } catch { + instance?.dispose(); + return; + } + + host.classList.add("is-ready"); + ancestor.classList.add(readyClass); + + if ("ResizeObserver" in window) { + const resizeObserver = new ResizeObserver((entries) => { + const entry = entries[0]; + if (!entry) return; + const { width, height } = entry.contentRect; + if (width > 20 && height > 20) instance.setSize(width, height); + }); + resizeObserver.observe(host); + } + }; + + targets.forEach((target) => { + const observer = new IntersectionObserver( + (entries, obs) => { + entries.forEach((entry) => { + if (!entry.isIntersecting) return; + obs.disconnect(); + mount(target); + }); + }, + { rootMargin: "200px" }, + ); + observer.observe(target.host); + }); +})(); + +// --- Liquid ASCII: a real FLIP/PIC fluid simulation (grid + particles, +// incompressible pressure solve, particle-particle separation) rendered as +// ASCII. No React, no registry, no CDN. Ported by hand from +// javierbyte/fluid-triangle (MIT), whose solver is itself ported from +// Matthias Müller's "Ten Minute Physics" FLIP fluid tutorial (MIT) — see +// license text below, preserved per the MIT terms of both sources. The +// obstacle's particle collider was a triangle in that fork; it's a circle +// here (matches the original Ten Minute Physics demo, and is what actually +// runs — the fork's grid-level triangle carving never mutated the fluid). +// +// Copyright 2022 Matthias Müller - Ten Minute Physics, +// www.youtube.com/c/TenMinutePhysics, www.matthiasMueller.info/tenMinutePhysics +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: the above copyright notice and this permission +// notice shall be included in all copies or substantial portions of the +// Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND. +(() => { + const host = document.querySelector("#hero-liquid"); + const pre = host?.querySelector(".hero-liquid-pre"); + const heroSection = host?.closest(".hero") || host; + if (!host || !pre || reducedMotion) return; + + const FLUID_CELL = 0; + const AIR_CELL = 1; + const SOLID_CELL = 2; + + const clamp = (x, lo, hi) => (x < lo ? lo : x > hi ? hi : x); + + // Letter ramps spelling "FLUID" across brightness bands, cycling + // diagonally across the grid — the fluid-triangle demo's signature + // touch, kept as-is since it's a genuinely nice detail for a water sim. + const BASE = [ + ["~", 12198], + [":", 6921], + ["-", 5589], + ["·", 3267], + [" ", 0], + [" ", 0], + ]; + const RENDER_CHARS = [ + [["F", 26574], ["F", 26574], ["f", 17490], ...BASE], + [["L", 21327], ["L", 21327], ["l", 14019], ...BASE], + [["U", 32973], ["U", 32973], ["u", 24093], ...BASE], + [["I", 14883], ["I", 14883], ["i", 13638], ...BASE], + [["D", 36198], ["D", 36198], ["d", 30762], ...BASE], + ].map((set) => + set + .slice() + .sort((a, b) => a[1] - b[1]) + .map(([char]) => char) + .join(""), + ); + + class FlipFluid { + constructor(density, width, height, spacing, particleRadius, maxParticles) { + this.density = density; + this.fNumX = Math.floor(width / spacing); + this.fNumY = Math.floor(height / spacing); + this.h = Math.max(width / this.fNumX, height / this.fNumY); + this.fInvSpacing = 1.0 / this.h; + this.fNumCells = this.fNumX * this.fNumY; + + this.u = new Float32Array(this.fNumCells); + this.v = new Float32Array(this.fNumCells); + this.du = new Float32Array(this.fNumCells); + this.dv = new Float32Array(this.fNumCells); + this.prevU = new Float32Array(this.fNumCells); + this.prevV = new Float32Array(this.fNumCells); + this.p = new Float32Array(this.fNumCells); + this.s = new Float32Array(this.fNumCells); + this.cellType = new Int32Array(this.fNumCells); + this.cellColor = new Float32Array(3 * this.fNumCells); + + this.maxParticles = maxParticles; + this.particlePos = new Float32Array(2 * this.maxParticles); + this.particleVel = new Float32Array(2 * this.maxParticles); + this.particleDensity = new Float32Array(this.fNumCells); + this.particleRestDensity = 0.0; + + this.particleRadius = particleRadius; + this.pInvSpacing = 1.0 / (2.2 * particleRadius); + this.pNumX = Math.floor(width * this.pInvSpacing) + 1; + this.pNumY = Math.floor(height * this.pInvSpacing) + 1; + this.pNumCells = this.pNumX * this.pNumY; + + this.numCellParticles = new Int32Array(this.pNumCells); + this.firstCellParticle = new Int32Array(this.pNumCells + 1); + this.cellParticleIds = new Int32Array(maxParticles); + + this.numParticles = 0; + } + + integrateParticles(dt, gravity) { + for (let i = 0; i < this.numParticles; i += 1) { + this.particleVel[2 * i + 1] += dt * gravity; + this.particlePos[2 * i] += this.particleVel[2 * i] * dt; + this.particlePos[2 * i + 1] += this.particleVel[2 * i + 1] * dt; + } + } + + pushParticlesApart(numIters) { + this.numCellParticles.fill(0); + for (let i = 0; i < this.numParticles; i += 1) { + const xi = clamp(Math.floor(this.particlePos[2 * i] * this.pInvSpacing), 0, this.pNumX - 1); + const yi = clamp(Math.floor(this.particlePos[2 * i + 1] * this.pInvSpacing), 0, this.pNumY - 1); + this.numCellParticles[xi * this.pNumY + yi] += 1; + } + let first = 0; + for (let i = 0; i < this.pNumCells; i += 1) { + first += this.numCellParticles[i]; + this.firstCellParticle[i] = first; + } + this.firstCellParticle[this.pNumCells] = first; + + for (let i = 0; i < this.numParticles; i += 1) { + const xi = clamp(Math.floor(this.particlePos[2 * i] * this.pInvSpacing), 0, this.pNumX - 1); + const yi = clamp(Math.floor(this.particlePos[2 * i + 1] * this.pInvSpacing), 0, this.pNumY - 1); + const cellNr = xi * this.pNumY + yi; + this.firstCellParticle[cellNr] -= 1; + this.cellParticleIds[this.firstCellParticle[cellNr]] = i; + } + + const minDist = 2.0 * this.particleRadius; + const minDist2 = minDist * minDist; + + for (let iter = 0; iter < numIters; iter += 1) { + for (let i = 0; i < this.numParticles; i += 1) { + const px = this.particlePos[2 * i]; + const py = this.particlePos[2 * i + 1]; + const pxi = Math.floor(px * this.pInvSpacing); + const pyi = Math.floor(py * this.pInvSpacing); + const x0 = Math.max(pxi - 1, 0); + const y0 = Math.max(pyi - 1, 0); + const x1 = Math.min(pxi + 1, this.pNumX - 1); + const y1 = Math.min(pyi + 1, this.pNumY - 1); + + for (let xi = x0; xi <= x1; xi += 1) { + for (let yi = y0; yi <= y1; yi += 1) { + const cellNr = xi * this.pNumY + yi; + const first = this.firstCellParticle[cellNr]; + const last = this.firstCellParticle[cellNr + 1]; + for (let j = first; j < last; j += 1) { + const id = this.cellParticleIds[j]; + if (id === i) continue; + let dx = this.particlePos[2 * id] - px; + let dy = this.particlePos[2 * id + 1] - py; + const d2 = dx * dx + dy * dy; + if (d2 > minDist2 || d2 === 0.0) continue; + const d = Math.sqrt(d2); + const s = (0.5 * (minDist - d)) / d; + dx *= s; + dy *= s; + this.particlePos[2 * i] -= dx; + this.particlePos[2 * i + 1] -= dy; + this.particlePos[2 * id] += dx; + this.particlePos[2 * id + 1] += dy; + } + } + } + } + } + } + + // Circular obstacle collider — the fork's triangle, deleted, restored + // to a plain circle (and given the obstacle's own velocity on contact + // for a real "push" instead of just clamping to zero). + handleParticleCollisions(obstacleX, obstacleY, obstacleRadius, obstacleVelX, obstacleVelY) { + const h = this.h; + const r = this.particleRadius; + const minDist = obstacleRadius + r; + const minDist2 = minDist * minDist; + + const minX = h + r; + const maxX = (this.fNumX - 1) * h - r; + const minY = h + r; + const maxY = (this.fNumY - 1) * h - r; + + for (let i = 0; i < this.numParticles; i += 1) { + let x = this.particlePos[2 * i]; + let y = this.particlePos[2 * i + 1]; + + if (obstacleRadius > 0) { + const dx = x - obstacleX; + const dy = y - obstacleY; + const d2 = dx * dx + dy * dy; + if (d2 < minDist2) { + const d = Math.sqrt(d2) || 0.0001; + x = obstacleX + (dx / d) * minDist; + y = obstacleY + (dy / d) * minDist; + this.particleVel[2 * i] = obstacleVelX; + this.particleVel[2 * i + 1] = obstacleVelY; + } + } + + if (x < minX) { + x = minX; + this.particleVel[2 * i] = 0.0; + } + if (x > maxX) { + x = maxX; + this.particleVel[2 * i] = 0.0; + } + if (y < minY) { + y = minY; + this.particleVel[2 * i + 1] = 0.0; + } + if (y > maxY) { + y = maxY; + this.particleVel[2 * i + 1] = 0.0; + } + this.particlePos[2 * i] = x; + this.particlePos[2 * i + 1] = y; + } + } + + updateParticleDensity() { + const n = this.fNumY; + const h = this.h; + const h1 = this.fInvSpacing; + const h2 = 0.5 * h; + const d = this.particleDensity; + d.fill(0.0); + + for (let i = 0; i < this.numParticles; i += 1) { + let x = clamp(this.particlePos[2 * i], h, (this.fNumX - 1) * h); + let y = clamp(this.particlePos[2 * i + 1], h, (this.fNumY - 1) * h); + + const x0 = Math.floor((x - h2) * h1); + const tx = (x - h2 - x0 * h) * h1; + const x1 = Math.min(x0 + 1, this.fNumX - 2); + const y0 = Math.floor((y - h2) * h1); + const ty = (y - h2 - y0 * h) * h1; + const y1 = Math.min(y0 + 1, this.fNumY - 2); + const sx = 1.0 - tx; + const sy = 1.0 - ty; + + if (x0 < this.fNumX && y0 < this.fNumY) d[x0 * n + y0] += sx * sy; + if (x1 < this.fNumX && y0 < this.fNumY) d[x1 * n + y0] += tx * sy; + if (x1 < this.fNumX && y1 < this.fNumY) d[x1 * n + y1] += tx * ty; + if (x0 < this.fNumX && y1 < this.fNumY) d[x0 * n + y1] += sx * ty; + } + + if (this.particleRestDensity === 0.0) { + let sum = 0.0; + let numFluidCells = 0; + for (let i = 0; i < this.fNumCells; i += 1) { + if (this.cellType[i] === FLUID_CELL) { + sum += d[i]; + numFluidCells += 1; + } + } + if (numFluidCells > 0) this.particleRestDensity = sum / numFluidCells; + } + } + + transferVelocities(toGrid, flipRatio) { + const n = this.fNumY; + const h = this.h; + const h1 = this.fInvSpacing; + const h2 = 0.5 * h; + + if (toGrid) { + this.prevU.set(this.u); + this.prevV.set(this.v); + this.du.fill(0.0); + this.dv.fill(0.0); + this.u.fill(0.0); + this.v.fill(0.0); + + for (let i = 0; i < this.fNumCells; i += 1) { + this.cellType[i] = this.s[i] === 0.0 ? SOLID_CELL : AIR_CELL; + } + for (let i = 0; i < this.numParticles; i += 1) { + const xi = clamp(Math.floor(this.particlePos[2 * i] * h1), 0, this.fNumX - 1); + const yi = clamp(Math.floor(this.particlePos[2 * i + 1] * h1), 0, this.fNumY - 1); + const cellNr = xi * n + yi; + if (this.cellType[cellNr] === AIR_CELL) this.cellType[cellNr] = FLUID_CELL; + } + } + + for (let component = 0; component < 2; component += 1) { + const dx = component === 0 ? 0.0 : h2; + const dy = component === 0 ? h2 : 0.0; + const f = component === 0 ? this.u : this.v; + const prevF = component === 0 ? this.prevU : this.prevV; + const d = component === 0 ? this.du : this.dv; + + for (let i = 0; i < this.numParticles; i += 1) { + let x = clamp(this.particlePos[2 * i], h, (this.fNumX - 1) * h); + let y = clamp(this.particlePos[2 * i + 1], h, (this.fNumY - 1) * h); + + const x0 = Math.min(Math.floor((x - dx) * h1), this.fNumX - 2); + const tx = (x - dx - x0 * h) * h1; + const x1 = Math.min(x0 + 1, this.fNumX - 2); + const y0 = Math.min(Math.floor((y - dy) * h1), this.fNumY - 2); + const ty = (y - dy - y0 * h) * h1; + const y1 = Math.min(y0 + 1, this.fNumY - 2); + const sx = 1.0 - tx; + const sy = 1.0 - ty; + + const d0 = sx * sy; + const d1 = tx * sy; + const d2 = tx * ty; + const d3 = sx * ty; + const nr0 = x0 * n + y0; + const nr1 = x1 * n + y0; + const nr2 = x1 * n + y1; + const nr3 = x0 * n + y1; + + if (toGrid) { + const pv = this.particleVel[2 * i + component]; + f[nr0] += pv * d0; + d[nr0] += d0; + f[nr1] += pv * d1; + d[nr1] += d1; + f[nr2] += pv * d2; + d[nr2] += d2; + f[nr3] += pv * d3; + d[nr3] += d3; + } else { + const offset = component === 0 ? n : 1; + const valid0 = this.cellType[nr0] !== AIR_CELL || this.cellType[nr0 - offset] !== AIR_CELL ? 1.0 : 0.0; + const valid1 = this.cellType[nr1] !== AIR_CELL || this.cellType[nr1 - offset] !== AIR_CELL ? 1.0 : 0.0; + const valid2 = this.cellType[nr2] !== AIR_CELL || this.cellType[nr2 - offset] !== AIR_CELL ? 1.0 : 0.0; + const valid3 = this.cellType[nr3] !== AIR_CELL || this.cellType[nr3 - offset] !== AIR_CELL ? 1.0 : 0.0; + + const v = this.particleVel[2 * i + component]; + const dSum = valid0 * d0 + valid1 * d1 + valid2 * d2 + valid3 * d3; + + if (dSum > 0.0) { + const picV = (valid0 * d0 * f[nr0] + valid1 * d1 * f[nr1] + valid2 * d2 * f[nr2] + valid3 * d3 * f[nr3]) / dSum; + const corr = + (valid0 * d0 * (f[nr0] - prevF[nr0]) + + valid1 * d1 * (f[nr1] - prevF[nr1]) + + valid2 * d2 * (f[nr2] - prevF[nr2]) + + valid3 * d3 * (f[nr3] - prevF[nr3])) / + dSum; + const flipV = v + corr; + this.particleVel[2 * i + component] = (1.0 - flipRatio) * picV + flipRatio * flipV; + } + } + } + + if (toGrid) { + for (let i = 0; i < f.length; i += 1) { + if (d[i] > 0.0) f[i] /= d[i]; + } + for (let i = 0; i < this.fNumX; i += 1) { + for (let j = 0; j < this.fNumY; j += 1) { + const solid = this.cellType[i * n + j] === SOLID_CELL; + if (solid || (i > 0 && this.cellType[(i - 1) * n + j] === SOLID_CELL)) this.u[i * n + j] = this.prevU[i * n + j]; + if (solid || (j > 0 && this.cellType[i * n + j - 1] === SOLID_CELL)) this.v[i * n + j] = this.prevV[i * n + j]; + } + } + } + } + } + + solveIncompressibility(numIters, dt, overRelaxation, compensateDrift) { + this.p.fill(0.0); + this.prevU.set(this.u); + this.prevV.set(this.v); + + const n = this.fNumY; + const cp = (this.density * this.h) / dt; + + for (let iter = 0; iter < numIters; iter += 1) { + for (let i = 1; i < this.fNumX - 1; i += 1) { + for (let j = 1; j < this.fNumY - 1; j += 1) { + if (this.cellType[i * n + j] !== FLUID_CELL) continue; + + const center = i * n + j; + const left = (i - 1) * n + j; + const right = (i + 1) * n + j; + const bottom = i * n + j - 1; + const top = i * n + j + 1; + + const sx0 = this.s[left]; + const sx1 = this.s[right]; + const sy0 = this.s[bottom]; + const sy1 = this.s[top]; + const s = sx0 + sx1 + sy0 + sy1; + if (s === 0.0) continue; + + let div = this.u[right] - this.u[center] + this.v[top] - this.v[center]; + + if (this.particleRestDensity > 0.0 && compensateDrift) { + const compression = this.particleDensity[center] - this.particleRestDensity; + if (compression > 0.0) div -= compression; + } + + let p = (-div / s) * overRelaxation; + this.p[center] += cp * p; + + this.u[center] -= sx0 * p; + this.u[right] += sx1 * p; + this.v[center] -= sy0 * p; + this.v[top] += sy1 * p; + } + } + } + } + + setSciColor(cellNr, val, minVal, maxVal) { + val = Math.min(Math.max(val, minVal), maxVal - 0.0001); + const d = maxVal - minVal; + val = d === 0.0 ? 0.5 : (val - minVal) / d; + const m = 0.25; + const num = Math.floor(val / m); + const s = (val - num * m) / m; + const shade = num === 0 || num === 2 ? s : 1.0 - s; + this.cellColor[3 * cellNr] = shade; + this.cellColor[3 * cellNr + 1] = shade; + this.cellColor[3 * cellNr + 2] = shade; + } + + updateCellColors() { + this.cellColor.fill(0.0); + for (let i = 0; i < this.fNumCells; i += 1) { + if (this.cellType[i] === FLUID_CELL) { + let d = this.particleDensity[i]; + if (this.particleRestDensity > 0.0) d /= this.particleRestDensity; + this.setSciColor(i, d, 0.0, 2.0); + } + } + } + + // Carves the circular obstacle into the pressure grid (s + solid-face + // velocities) — this is the part the fork's numX/numY typo silently + // disabled; done properly here so the fluid actually parts around it. + // + // Only touches a small box around the obstacle (this frame's + last + // frame's), instead of every interior cell in the grid — cells far + // from the obstacle are always s=1 and were being redundantly reset to + // that same value every single frame. Same numeric result, far less + // work: this was the single biggest avoidable per-frame cost. + applyObstacle(obstacleX, obstacleY, obstacleRadius, obstacleVelX, obstacleVelY) { + const n = this.fNumY; + const h = this.h; + const r2 = obstacleRadius * obstacleRadius; + const rCells = Math.max(1, Math.ceil(obstacleRadius / h) + 1); + const ci = clamp(Math.round(obstacleX / h), 1, this.fNumX - 2); + const cj = clamp(Math.round(obstacleY / h), 1, this.fNumY - 2); + const i0 = Math.max(1, ci - rCells); + const i1 = Math.min(this.fNumX - 2, ci + rCells); + const j0 = Math.max(1, cj - rCells); + const j1 = Math.min(this.fNumY - 2, cj + rCells); + + const prev = this._obstacleBox; + if (prev) { + for (let i = prev.i0; i <= prev.i1; i += 1) { + for (let j = prev.j0; j <= prev.j1; j += 1) { + this.s[i * n + j] = 1.0; + } + } + } + + for (let i = i0; i <= i1; i += 1) { + for (let j = j0; j <= j1; j += 1) { + const idx = i * n + j; + if (obstacleRadius <= 0) { + this.s[idx] = 1.0; + continue; + } + const dx = (i + 0.5) * h - obstacleX; + const dy = (j + 0.5) * h - obstacleY; + if (dx * dx + dy * dy < r2) { + this.s[idx] = 0.0; + this.u[idx] = obstacleVelX; + this.u[(i + 1) * n + j] = obstacleVelX; + this.v[idx] = obstacleVelY; + this.v[i * n + j + 1] = obstacleVelY; + } else { + this.s[idx] = 1.0; + } + } + } + + if (this._obstacleBox) { + this._obstacleBox.i0 = i0; + this._obstacleBox.i1 = i1; + this._obstacleBox.j0 = j0; + this._obstacleBox.j1 = j1; + } else { + this._obstacleBox = { i0, i1, j0, j1 }; + } + } + + simulate(dt, gravity, flipRatio, numPressureIters, numParticleIters, overRelaxation, compensateDrift, separateParticles, obstacleX, obstacleY, obstacleRadius, obstacleVelX, obstacleVelY) { + this.integrateParticles(dt, gravity); + if (separateParticles) this.pushParticlesApart(numParticleIters); + this.handleParticleCollisions(obstacleX, obstacleY, obstacleRadius, obstacleVelX, obstacleVelY); + this.applyObstacle(obstacleX, obstacleY, obstacleRadius, obstacleVelX, obstacleVelY); + this.transferVelocities(true); + this.updateParticleDensity(); + this.solveIncompressibility(numPressureIters, dt, overRelaxation, compensateDrift); + this.transferVelocities(false, flipRatio); + this.updateCellColors(); + } + } + + const CELL = 10; // px per ascii cell + const CROP_X = 1; + const CROP_Y = 1; + const SIM_HEIGHT = 2.0; + const DT_START = 1.0 / 60 / 16; // very slow the instant the obstacle appears/jumps — keeps the solve stable + const DT_BASE = 1.0 / 60 / 3; // resting speed + const DT_RELEASE = 1.0 / 60 / 1.25; // a bit livelier while settling after a drag + + const scene = { + gravity: -9.81, + dt: DT_BASE, + flipRatio: 0.9, + numPressureIters: 24, + numParticleIters: 2, + overRelaxation: 1.9, + compensateDrift: true, + separateParticles: true, + obstacleX: 0, + obstacleY: 0, + obstacleRadius: 0, + obstacleTargetRadius: 0, + obstacleVelX: 0, + obstacleVelY: 0, + fluid: null, + }; + + let fCols = 0; + let fRows = 0; + let maxRadius = 0.26; + let rafId = null; + let visible = false; + let isDown = false; + let renderTick = 0; + + // Monospace glyph *advance width* is narrower than the font-size (for + // IBM Plex Mono, roughly 0.6x) — assuming 1 character == CELL px wide + // under-filled the row by the same margin, which is why the water + // stopped a good way short of the right edge even though the box itself + // was full width. Measure the real rendered glyph box instead of + // guessing. + const measureGlyph = () => { + const probe = document.createElement("span"); + probe.style.whiteSpace = "pre"; + probe.style.position = "absolute"; + probe.style.visibility = "hidden"; + probe.textContent = "MMMMMMMMMM"; + pre.appendChild(probe); + const box = probe.getBoundingClientRect(); + pre.removeChild(probe); + return { w: box.width / 10, h: box.height || CELL }; + }; + + const setupScene = () => { + const rect = host.getBoundingClientRect(); + pre.style.fontFamily = "var(--mono)"; + pre.style.fontSize = `${CELL}px`; + pre.style.lineHeight = "1em"; + const glyph = measureGlyph(); + fCols = clamp(Math.floor(rect.width / glyph.w), 40, 520); + fRows = clamp(Math.floor(rect.height / glyph.h), 16, 160); + + maxRadius = rect.width > rect.height ? 0.26 : 0.34; + + // The physics grid uses square cells, but ASCII glyphs are much + // narrower than they are tall — so the box's raw pixel aspect ratio + // (rect.width/rect.height) is the WRONG ratio to build the sim on. On + // a wide screen that under-sized the grid's width by roughly half, + // which is exactly the "water stops partway across" line: the fluid + // grid was square-cell-correct but never had enough columns to reach + // the right edge of a wide, short box. Building simWidth off the + // character-grid ratio (fCols/fRows) instead makes fNumX land on the + // actual column count the box needs. + const simWidth = SIM_HEIGHT * (fCols / fRows); + const h = SIM_HEIGHT / fRows; + const density = 1000.0; + const relWaterHeight = 0.62; + const relWaterWidth = 1.0; + + const r = 0.3 * h; + const dx = 2.0 * r; + const dy = (Math.sqrt(3.0) / 2.0) * dx; + + const numX = Math.max(1, Math.floor((relWaterWidth * simWidth - 2.0 * h - 2.0 * r) / dx)); + const numY = Math.max(1, Math.floor((relWaterHeight * SIM_HEIGHT - 2.0 * h - 2.0 * r) / dy)); + const maxParticles = numX * numY; + + const f = new FlipFluid(density, simWidth, SIM_HEIGHT, h, r, maxParticles); + f.numParticles = numX * numY; + + const xOffset = (simWidth - numX * dx) / 2; + const yOffset = (SIM_HEIGHT - numY * dy) * -0.5; + let p = 0; + for (let i = 0; i < numX; i += 1) { + for (let j = 0; j < numY; j += 1) { + f.particlePos[p] = h + r + dx * i + (j % 2 === 0 ? 0.0 : r) + xOffset; + f.particlePos[p + 1] = h + r + dy * j + yOffset; + p += 2; + } + } + + const n = f.fNumY; + for (let i = 0; i < f.fNumX; i += 1) { + for (let j = 0; j < f.fNumY; j += 1) { + f.s[i * n + j] = i === 0 || i === f.fNumX - 1 || j === 0 ? 0.0 : 1.0; + } + } + + scene.fluid = f; + scene.obstacleX = simWidth / 2; + scene.obstacleY = SIM_HEIGHT * 0.55; + scene.obstacleRadius = 0; + scene.obstacleTargetRadius = 0; + }; + + const simCoordsFromEvent = (event) => { + const rect = host.getBoundingClientRect(); + const point = event.touches ? event.touches[0] : event; + const px = point.clientX - rect.left; + const py = point.clientY - rect.top; + const cScale = rect.height / SIM_HEIGHT; + return { x: px / cScale, y: (rect.height - py) / cScale }; + }; + + const onPointerDown = (event) => { + isDown = true; + scene.dt = DT_START; + scene.obstacleTargetRadius = maxRadius; + const p = simCoordsFromEvent(event); + scene.obstacleX = p.x; + scene.obstacleY = p.y; + scene.obstacleVelX = 0; + scene.obstacleVelY = 0; + }; + + const onPointerMove = (event) => { + if (!isDown) return; + const p = simCoordsFromEvent(event); + scene.obstacleVelX = (p.x - scene.obstacleX) / scene.dt; + scene.obstacleVelY = (p.y - scene.obstacleY) / scene.dt; + scene.obstacleX = p.x; + scene.obstacleY = p.y; + }; + + const onPointerUp = () => { + if (!isDown) return; + isDown = false; + scene.dt = DT_RELEASE; + scene.obstacleTargetRadius = 0; + scene.obstacleVelX = 0; + scene.obstacleVelY = 0; + }; + + host.addEventListener("pointerdown", onPointerDown, { passive: true }); + host.addEventListener("pointermove", onPointerMove, { passive: true }); + window.addEventListener("pointerup", onPointerUp, { passive: true }); + host.addEventListener("pointerleave", onPointerUp, { passive: true }); + + const render = () => { + const f = scene.fluid; + const dictLen = RENDER_CHARS[0].length; + const n = f.fNumY; + const rows = []; + for (let i = f.fNumY - CROP_Y; i > CROP_Y; i -= 1) { + const chars = new Array(f.fNumX - 2 * CROP_X); + let k = 0; + for (let j = CROP_X; j < f.fNumX - CROP_X; j += 1) { + const dict = RENDER_CHARS[(i + j + 1) % RENDER_CHARS.length]; + const shade = f.cellColor[3 * (j * n + i)]; + chars[k] = dict[Math.min(dictLen - 1, Math.floor(shade * dictLen))]; + k += 1; + } + rows.push(chars.join("")); + } + pre.textContent = rows.join("\n"); + }; + + const frame = () => { + rafId = null; + if (!visible) return; + + scene.obstacleRadius = (scene.obstacleRadius * 3 + scene.obstacleTargetRadius) / 4; + scene.fluid.simulate( + scene.dt, + scene.gravity, + scene.flipRatio, + scene.numPressureIters, + scene.numParticleIters, + scene.overRelaxation, + scene.compensateDrift, + scene.separateParticles, + scene.obstacleX, + scene.obstacleY, + scene.obstacleRadius, + scene.obstacleVelX, + scene.obstacleVelY, + ); + + renderTick += 1; + if (renderTick % 2 === 0) render(); + + rafId = requestAnimationFrame(frame); + }; + + setupScene(); + render(); + + // The glyph measurement above can happen before the real @font-face has + // loaded (using a fallback font's metrics instead) — redo it once the + // real font is active so the column count settles at the right value. + if (document.fonts && document.fonts.ready) { + document.fonts.ready.then(() => { + setupScene(); + render(); + }); + } + + if ("ResizeObserver" in window) { + let resizeTimer = null; + const resizeObserver = new ResizeObserver(() => { + clearTimeout(resizeTimer); + resizeTimer = setTimeout(() => { + setupScene(); + render(); + }, 200); + }); + resizeObserver.observe(host); + } + + // Only real "free" saving: don't run the sim at all while it's scrolled + // out of view — costs nothing visually since it can't be seen anyway. + if ("IntersectionObserver" in window) { + const observer = new IntersectionObserver( + (entries) => { + entries.forEach((entry) => { + visible = entry.isIntersecting; + if (visible && !rafId) rafId = requestAnimationFrame(frame); + }); + }, + { threshold: 0.05 }, + ); + observer.observe(host); + } else { + visible = true; + rafId = requestAnimationFrame(frame); + } +})(); + +const copyButton = document.querySelector("#copy-discord"); +const copyLabel = document.querySelector("#discord-label"); +const copyStatus = document.querySelector("#copy-status"); + +if (copyButton && copyLabel && copyStatus) { + copyButton.addEventListener("click", async () => { + try { + await navigator.clipboard.writeText("fi3w0"); + copyLabel.textContent = "copied: fi3w0"; + copyStatus.textContent = "Discord username copied to clipboard."; + } catch { + copyLabel.textContent = "username: fi3w0"; + copyStatus.textContent = "Clipboard access was blocked. The username is fi3w0."; + } + + window.setTimeout(() => { + copyLabel.textContent = "fi3w0 - click to copy"; + copyStatus.textContent = ""; + }, 2600); + }); +} diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..b0cfe69 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,5116 @@ +{ + "name": "fi3w0-portfolio", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "fi3w0-portfolio", + "version": "1.0.0", + "license": "MIT", + "devDependencies": { + "copy-webpack-plugin": "^11.0.0", + "html-webpack-plugin": "^5.6.0", + "webpack": "^5.91.0", + "webpack-cli": "^5.1.4", + "webpack-dev-server": "^5.0.4", + "webpack-merge": "^5.10.0" + } + }, + "node_modules/@discoveryjs/json-ext": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", + "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.11", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz", + "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jsonjoy.com/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-q6XAnWQDIMA3+FTiOYajoYqySkO+JSat0ytXGSuRdq9uXE7o92gzuQwQM14xaCRlBLGq3v5miDGC4vkVTn54xA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/buffers": { + "version": "17.67.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/buffers/-/buffers-17.67.0.tgz", + "integrity": "sha512-tfExRpYxBvi32vPs9ZHaTjSP4fHAfzSmcahOfNxtvGHcyJel+aibkPlGeBB+7AoC6hL7lXIE++8okecBxx7lcw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/codegen": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/codegen/-/codegen-1.0.0.tgz", + "integrity": "sha512-E8Oy+08cmCf0EK/NMxpaJZmOxPqM+6iSe2S4nlSBrPZOORoDJILxtbSUEDKQyTamm/BVAhIGllOBNU79/dwf0g==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-core": { + "version": "4.64.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-core/-/fs-core-4.64.0.tgz", + "integrity": "sha512-zs2TAq7Six5jgMuoMNjpspAvOP3mhtgq/k1UyQodEzCtQi/N83y2/y+zcvnZSGp/Rxq96DBN+bValOBQAyn/ew==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/fs-node-builtins": "4.64.0", + "@jsonjoy.com/fs-node-utils": "4.64.0", + "thingies": "^2.5.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-fsa": { + "version": "4.64.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-fsa/-/fs-fsa-4.64.0.tgz", + "integrity": "sha512-nMWOVbkLFyEgmXZih3wyvxA9XpgyyqyfrINMHvEFqhi7uqfRl7c9ERJt6yX7vgMPrB9Uo+OJO+Spa0cFzPD01w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/fs-core": "4.64.0", + "@jsonjoy.com/fs-node-builtins": "4.64.0", + "@jsonjoy.com/fs-node-utils": "4.64.0", + "thingies": "^2.5.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-node": { + "version": "4.64.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node/-/fs-node-4.64.0.tgz", + "integrity": "sha512-dO+NNkODbUli4uV42bcNrrLvq5rE7SNpdZ5TNd0dtbLsAaNK3MDiIC9lUi+brboGoIjW6vd2fB1qao60nrk5xA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/fs-core": "4.64.0", + "@jsonjoy.com/fs-node-builtins": "4.64.0", + "@jsonjoy.com/fs-node-utils": "4.64.0", + "@jsonjoy.com/fs-print": "4.64.0", + "@jsonjoy.com/fs-snapshot": "4.64.0", + "glob-to-regex.js": "^1.0.0", + "thingies": "^2.5.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-node-builtins": { + "version": "4.64.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node-builtins/-/fs-node-builtins-4.64.0.tgz", + "integrity": "sha512-/o7WRFhUWaM/fOrslwLZGnzn4RmRILykn+lAL+mNObqqRNw+CQSiij6hpCeZ+C7buhdoVo7go/OYqzaSUfDYmA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-node-to-fsa": { + "version": "4.64.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node-to-fsa/-/fs-node-to-fsa-4.64.0.tgz", + "integrity": "sha512-WDD9WVs0hb7UAEKTgZW2f66WDrbj7gIIWwpP3spbLyXa0rghtUaFTB8L4gdR3ZCWwiKIsj38/CNijpVmpnuPUw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/fs-fsa": "4.64.0", + "@jsonjoy.com/fs-node-builtins": "4.64.0", + "@jsonjoy.com/fs-node-utils": "4.64.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-node-utils": { + "version": "4.64.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node-utils/-/fs-node-utils-4.64.0.tgz", + "integrity": "sha512-k5Indsx9hWW9xSF7Y6oSKKwtCUNhzZxadub3owhIlitc+iMRVlPPdX2duTKQWBL3qNWpXya8jykgaaWpheeS4w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/fs-node-builtins": "4.64.0", + "glob-to-regex.js": "^1.0.1" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-print": { + "version": "4.64.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-print/-/fs-print-4.64.0.tgz", + "integrity": "sha512-PHZFccchvkhWrwPWHjmVAhbC3vSHCtyZvlZfJJ3ho2bnzl450hXri6/8e6pbkWdH+SkmLXNml0sV8e5HDAfxKw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/fs-node-utils": "4.64.0", + "tree-dump": "^1.1.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-snapshot": { + "version": "4.64.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-snapshot/-/fs-snapshot-4.64.0.tgz", + "integrity": "sha512-oM7UDeL83q6NBzzsfKAsYKXKVXlykKFqqOLh4xZZKAzzROTlInkPbc6LTDGThEOnPiFiUzA7tYziHG9xavd76Q==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/buffers": "^17.65.0", + "@jsonjoy.com/fs-node-utils": "4.64.0", + "@jsonjoy.com/json-pack": "^17.65.0", + "@jsonjoy.com/util": "^17.65.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-snapshot/node_modules/@jsonjoy.com/base64": { + "version": "17.67.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/base64/-/base64-17.67.0.tgz", + "integrity": "sha512-5SEsJGsm15aP8TQGkDfJvz9axgPwAEm98S5DxOuYe8e1EbfajcDmgeXXzccEjh+mLnjqEKrkBdjHWS5vFNwDdw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-snapshot/node_modules/@jsonjoy.com/codegen": { + "version": "17.67.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/codegen/-/codegen-17.67.0.tgz", + "integrity": "sha512-idnkUplROpdBOV0HMcwhsCUS5TRUi9poagdGs70A6S4ux9+/aPuKbh8+UYRTLYQHtXvAdNfQWXDqZEx5k4Dj2Q==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-snapshot/node_modules/@jsonjoy.com/json-pack": { + "version": "17.67.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pack/-/json-pack-17.67.0.tgz", + "integrity": "sha512-t0ejURcGaZsn1ClbJ/3kFqSOjlryd92eQY465IYrezsXmPcfHPE/av4twRSxf6WE+TkZgLY+71vCZbiIiFKA/w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/base64": "17.67.0", + "@jsonjoy.com/buffers": "17.67.0", + "@jsonjoy.com/codegen": "17.67.0", + "@jsonjoy.com/json-pointer": "17.67.0", + "@jsonjoy.com/util": "17.67.0", + "hyperdyperid": "^1.2.0", + "thingies": "^2.5.0", + "tree-dump": "^1.1.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-snapshot/node_modules/@jsonjoy.com/json-pointer": { + "version": "17.67.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pointer/-/json-pointer-17.67.0.tgz", + "integrity": "sha512-+iqOFInH+QZGmSuaybBUNdh7yvNrXvqR+h3wjXm0N/3JK1EyyFAeGJvqnmQL61d1ARLlk/wJdFKSL+LHJ1eaUA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/util": "17.67.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-snapshot/node_modules/@jsonjoy.com/util": { + "version": "17.67.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/util/-/util-17.67.0.tgz", + "integrity": "sha512-6+8xBaz1rLSohlGh68D1pdw3AwDi9xydm8QNlAFkvnavCJYSze+pxoW2VKP8p308jtlMRLs5NTHfPlZLd4w7ew==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/buffers": "17.67.0", + "@jsonjoy.com/codegen": "17.67.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/json-pack": { + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pack/-/json-pack-1.21.0.tgz", + "integrity": "sha512-+AKG+R2cfZMShzrF2uQw34v3zbeDYUqnQ+jg7ORic3BGtfw9p/+N6RJbq/kkV8JmYZaINknaEQ2m0/f693ZPpg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/base64": "^1.1.2", + "@jsonjoy.com/buffers": "^1.2.0", + "@jsonjoy.com/codegen": "^1.0.0", + "@jsonjoy.com/json-pointer": "^1.0.2", + "@jsonjoy.com/util": "^1.9.0", + "hyperdyperid": "^1.2.0", + "thingies": "^2.5.0", + "tree-dump": "^1.1.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/json-pack/node_modules/@jsonjoy.com/buffers": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/buffers/-/buffers-1.2.1.tgz", + "integrity": "sha512-12cdlDwX4RUM3QxmUbVJWqZ/mrK6dFQH4Zxq6+r1YXKXYBNgZXndx2qbCJwh3+WWkCSn67IjnlG3XYTvmvYtgA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/json-pointer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pointer/-/json-pointer-1.0.2.tgz", + "integrity": "sha512-Fsn6wM2zlDzY1U+v4Nc8bo3bVqgfNTGcn6dMgs6FjrEnt4ZCe60o6ByKRjOGlI2gow0aE/Q41QOigdTqkyK5fg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/codegen": "^1.0.0", + "@jsonjoy.com/util": "^1.9.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/util": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/util/-/util-1.9.0.tgz", + "integrity": "sha512-pLuQo+VPRnN8hfPqUTLTHk126wuYdXVxE6aDmjSeV4NCAgyxWbiOIeNJVtID3h1Vzpoi9m4jXezf73I6LgabgQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/buffers": "^1.0.0", + "@jsonjoy.com/codegen": "^1.0.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/util/node_modules/@jsonjoy.com/buffers": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/buffers/-/buffers-1.2.1.tgz", + "integrity": "sha512-12cdlDwX4RUM3QxmUbVJWqZ/mrK6dFQH4Zxq6+r1YXKXYBNgZXndx2qbCJwh3+WWkCSn67IjnlG3XYTvmvYtgA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@leichtgewicht/ip-codec": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz", + "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@noble/hashes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", + "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@peculiar/asn1-cms": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-cms/-/asn1-cms-2.8.0.tgz", + "integrity": "sha512-NgekZOrSJFSBFLFoLfwePguAWAx7z1+f2TEsWFUMyiqqfntZ4+S/S5hzqME3q4pCA0iOsFKdwiQ35dwY24eVqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@peculiar/asn1-schema": "^2.8.0", + "@peculiar/asn1-x509": "^2.8.0", + "@peculiar/asn1-x509-attr": "^2.8.0", + "asn1js": "^3.0.10", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-csr": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-csr/-/asn1-csr-2.8.0.tgz", + "integrity": "sha512-akbF8+uvleHs8sejNPQxwmVFuInAg6FMNHOwMILXfP518YfFJwdR3jr6oNUPOaEJfuEhn/vkNOCIT6ASUd4mbg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@peculiar/asn1-schema": "^2.8.0", + "@peculiar/asn1-x509": "^2.8.0", + "asn1js": "^3.0.10", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-ecc": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-ecc/-/asn1-ecc-2.8.0.tgz", + "integrity": "sha512-ohwlk+u9Rv2NOAY1c6MfHj45ATVF8R1DUN/WCgABiRtLi2ZftlZWZX7KvpAbU8v9xPcmoILfELeEABj/rn18AQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@peculiar/asn1-schema": "^2.8.0", + "@peculiar/asn1-x509": "^2.8.0", + "asn1js": "^3.0.10", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-pfx": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-pfx/-/asn1-pfx-2.8.0.tgz", + "integrity": "sha512-5yof1ytoB++RQtaFbqSUJ8pxDJtZT6vbVqZ8XoJ61ph7UjNVvfFwAilnCodqkNsAodpy13gDhoxZXw00pghnyg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@peculiar/asn1-cms": "^2.8.0", + "@peculiar/asn1-pkcs8": "^2.8.0", + "@peculiar/asn1-rsa": "^2.8.0", + "@peculiar/asn1-schema": "^2.8.0", + "asn1js": "^3.0.10", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-pkcs8": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-pkcs8/-/asn1-pkcs8-2.8.0.tgz", + "integrity": "sha512-qAKXtLpBEw9LqhKpjw3ajZSXlBur+ipW+y2ivVBQAG6F6qRx94yO+1ZR4mvw+YaCfKSaOzLeYEzsPaBp4SJELA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@peculiar/asn1-schema": "^2.8.0", + "@peculiar/asn1-x509": "^2.8.0", + "asn1js": "^3.0.10", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-pkcs9": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-pkcs9/-/asn1-pkcs9-2.8.0.tgz", + "integrity": "sha512-b5nDWCnkV60+cQ141D6sVVwK9nz64R5n3zSVnklGd+ECdkW2Ol3U1a6yYFlalpSOaD557yuJB64A+q42jG7lUQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@peculiar/asn1-cms": "^2.8.0", + "@peculiar/asn1-pfx": "^2.8.0", + "@peculiar/asn1-pkcs8": "^2.8.0", + "@peculiar/asn1-schema": "^2.8.0", + "@peculiar/asn1-x509": "^2.8.0", + "@peculiar/asn1-x509-attr": "^2.8.0", + "asn1js": "^3.0.10", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-rsa": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-rsa/-/asn1-rsa-2.8.0.tgz", + "integrity": "sha512-zHEUlCqB2mk7x2lxDwHHJy7hWZOPdGHVlsmITWKB5/PbQo61atbu9PJ/0r9dQNMwFzbKPXZ8uK8/91eUhRznSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@peculiar/asn1-schema": "^2.8.0", + "@peculiar/asn1-x509": "^2.8.0", + "asn1js": "^3.0.10", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-schema": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-schema/-/asn1-schema-2.8.0.tgz", + "integrity": "sha512-7YT0U/ze0tF2QOBbE15gKZwy5tvgGyLRiRHLzhlbOpf7BT032oBSd0haZqXn5W6l26WLlu3dyxzjM+2638/z2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@peculiar/utils": "^2.0.2", + "asn1js": "^3.0.10", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-x509": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-x509/-/asn1-x509-2.8.0.tgz", + "integrity": "sha512-N0CMuhWUzsWEVq6F1q9X6+VKUnWzSW+cSVg+aPaGGwDdbFoFWTYgin5MHwXgpWd6y9COMBxnfy/Qc+Xc7F0Zwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@peculiar/asn1-schema": "^2.8.0", + "@peculiar/utils": "^2.0.2", + "asn1js": "^3.0.10", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-x509-attr": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-x509-attr/-/asn1-x509-attr-2.8.0.tgz", + "integrity": "sha512-tHjkfS/qhMnmrlB2J9NhflQlQ7In3khO3CfmVrriOlpTeErY9ZIKOso1hQ5JQiyrJ7ShvqVPk7E5fQmbclkSKA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@peculiar/asn1-schema": "^2.8.0", + "@peculiar/asn1-x509": "^2.8.0", + "asn1js": "^3.0.10", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@peculiar/utils/-/utils-2.0.3.tgz", + "integrity": "sha512-+oL3HPFRIZ1St2K50lWCXiioIgSoxzz7R1J3uF6neO2yl1sgmpgY6XXJH4BdpoDkMWznQTeYF6oWNDZLCdQ4eQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/x509": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/@peculiar/x509/-/x509-1.14.3.tgz", + "integrity": "sha512-C2Xj8FZ0uHWeCXXqX5B4/gVFQmtSkiuOolzAgutjTfseNOHT3pUjljDZsTSxXFGgio54bCzVFqmEOUrIVk8RDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@peculiar/asn1-cms": "^2.6.0", + "@peculiar/asn1-csr": "^2.6.0", + "@peculiar/asn1-ecc": "^2.6.0", + "@peculiar/asn1-pkcs9": "^2.6.0", + "@peculiar/asn1-rsa": "^2.6.0", + "@peculiar/asn1-schema": "^2.6.0", + "@peculiar/asn1-x509": "^2.6.0", + "pvtsutils": "^1.3.6", + "reflect-metadata": "^0.2.2", + "tslib": "^2.8.1", + "tsyringe": "^4.10.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.6", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz", + "integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/bonjour": { + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.13.tgz", + "integrity": "sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/connect-history-api-fallback": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.4.tgz", + "integrity": "sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/express-serve-static-core": "*", + "@types/node": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/express": { + "version": "4.17.25", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.25.tgz", + "integrity": "sha512-dVd04UKsfpINUnK0yBoYHDF3xu7xVH4BuDotC/xGuycx4CgbP48X/KF/586bcObxT0HENHXEU8Nqtu6NR+eKhw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "^1" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.19.9", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.9.tgz", + "integrity": "sha512-QP2ESEe/ImWY0HDwNAnK9PvEffUyhLTnWkk7KXzHfyeWAnlrDe1fN77bXl6ia8KT3wPlmA7t9/VPRpnf4Ex9sg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/http-errors": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz", + "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/http-proxy": { + "version": "1.17.17", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.17.tgz", + "integrity": "sha512-ED6LB+Z1AVylNTu7hdzuBqOgMnvG/ld6wGCG8wFnAzKX5uyW2K3WD52v0gnLCTK/VLpXtKckgWuyScYK6cSPaw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "26.1.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-26.1.1.tgz", + "integrity": "sha512-nxAkRSVkN1Y0JC1W8ky/fTfkGsMmcrRsbx+3XoZE+rMOX71kLYTV7fLXpqud1GpbpP5TuffXFqfX7fH2GgZREw==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~8.3.0" + } + }, + "node_modules/@types/qs": { + "version": "6.15.1", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.15.1.tgz", + "integrity": "sha512-GZHUBZR9hckSUhrxmp1nG6NwdpM9fCunJwyThLW1X3AyHgd9IlHb6VANpQQqDr2o/qQp6McZ3y/IA2rVzKzSbw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/retry": { + "version": "0.12.2", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.2.tgz", + "integrity": "sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/send": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@types/send/-/send-1.2.1.tgz", + "integrity": "sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/serve-index": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.4.tgz", + "integrity": "sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.10", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.10.tgz", + "integrity": "sha512-tRs1dB+g8Itk72rlSI2ZrW6vZg0YrLI81iQSTkMmOqnqCaNr/8Ek4VwWcN5vZgCYWbg/JJSGBlUaYGAOP73qBw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/http-errors": "*", + "@types/node": "*", + "@types/send": "<1" + } + }, + "node_modules/@types/serve-static/node_modules/@types/send": { + "version": "0.17.6", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.6.tgz", + "integrity": "sha512-Uqt8rPBE8SY0RK8JB1EzVOIZ32uqy8HwdxCnoCOsYrvnswqmFZ/k+9Ikidlk/ImhsdvBsloHbAlewb2IEBV/Og==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/sockjs": { + "version": "0.3.36", + "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.36.tgz", + "integrity": "sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/ws": { + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", + "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@webassemblyjs/ast": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", + "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/helper-numbers": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", + "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", + "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", + "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz", + "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.13.2", + "@webassemblyjs/helper-api-error": "1.13.2", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz", + "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz", + "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/wasm-gen": "1.14.1" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz", + "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz", + "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz", + "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz", + "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/helper-wasm-section": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-opt": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1", + "@webassemblyjs/wast-printer": "1.14.1" + } + }, + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz", + "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" + } + }, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz", + "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz", + "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-api-error": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" + } + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz", + "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webpack-cli/configtest": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-2.1.1.tgz", + "integrity": "sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.15.0" + }, + "peerDependencies": { + "webpack": "5.x.x", + "webpack-cli": "5.x.x" + } + }, + "node_modules/@webpack-cli/info": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-2.0.2.tgz", + "integrity": "sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.15.0" + }, + "peerDependencies": { + "webpack": "5.x.x", + "webpack-cli": "5.x.x" + } + }, + "node_modules/@webpack-cli/serve": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-2.0.5.tgz", + "integrity": "sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.15.0" + }, + "peerDependencies": { + "webpack": "5.x.x", + "webpack-cli": "5.x.x" + }, + "peerDependenciesMeta": { + "webpack-dev-server": { + "optional": true + } + } + }, + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/accepts/node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.17.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.17.0.tgz", + "integrity": "sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-import-phases": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/acorn-import-phases/-/acorn-import-phases-1.0.4.tgz", + "integrity": "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.13.0" + }, + "peerDependencies": { + "acorn": "^8.14.0" + } + }, + "node_modules/ajv": { + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/ansi-html-community": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", + "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", + "dev": true, + "engines": [ + "node >= 0.8.0" + ], + "license": "Apache-2.0", + "bin": { + "ansi-html": "bin/ansi-html" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/asn1js": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/asn1js/-/asn1js-3.0.10.tgz", + "integrity": "sha512-S2s3aOytiKdFRdulw2qPE51MzjzVOisppcVv7jVFR+Kw0kxwvFrDcYA0h7Ndqbmj0HkMIXYWaoj7fli8kgx1eg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "pvtsutils": "^1.3.6", + "pvutils": "^1.1.5", + "tslib": "^2.8.1" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/baseline-browser-mapping": { + "version": "2.10.43", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.43.tgz", + "integrity": "sha512-AjYpR78kDWAY3Efj+cDTFH9t9SCoL7OoTp1BOb0mQV7S+6CiLwnWM3FyxhJtdPufDFKzmCSFoUncKjWgJEZTCQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==", + "dev": true, + "license": "MIT" + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/body-parser": { + "version": "1.20.6", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.6.tgz", + "integrity": "sha512-p5tAzS57i5MV9fZFDj9LeIiTZEufbSe2eDozP+ElheSUq1m74CRq1jI4mYNDdVs9vQztXFLuk/Gd6BWTdwRJ5g==", + "dev": true, + "license": "MIT", + "dependencies": { + "bytes": "~3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "~1.2.0", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "on-finished": "~2.4.1", + "qs": "~6.15.1", + "raw-body": "~2.5.3", + "type-is": "~1.6.18", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/bonjour-service": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.4.3.tgz", + "integrity": "sha512-2Kd5UYlFUVgAKMTyuBLl6w49wqfOnbxHqmuH0oCl/n7TfAikR0zoowNOP5BU4dfXmm+Vr9JyEN370auSMx+CNg==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "multicast-dns": "^7.2.5" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true, + "license": "ISC" + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.28.6", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.6.tgz", + "integrity": "sha512-FQBYNK15VMslhLHpA7+n+n1GOlF1kId2xcCg7/j95f24AOF6VDYMNH4mFxF7KuaTdv627faazpOAjFzMrfJOUw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "baseline-browser-mapping": "^2.10.42", + "caniuse-lite": "^1.0.30001803", + "electron-to-chromium": "^1.5.389", + "node-releases": "^2.0.51", + "update-browserslist-db": "^1.2.3" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/bundle-name": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", + "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "run-applescript": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/bytestreamjs": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/bytestreamjs/-/bytestreamjs-2.0.1.tgz", + "integrity": "sha512-U1Z/ob71V/bXfVABvNr/Kumf5VyeQRBEm6Txb0PQ6S7V5GpBM3w4Cbqz/xPDicR5tN0uvDifng8C+5qECeGwyQ==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/camel-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", + "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "pascal-case": "^3.1.2", + "tslib": "^2.0.3" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001806", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001806.tgz", + "integrity": "sha512-72Cuvd95zbSYPKq6Fhg8eDJRlzgWDf7/mtoZv6Qe/DYNCEBdNxoA3+rZAU2ZhGCpZlns3EssFavaZomckT5Uuw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/chrome-trace-event": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", + "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0" + } + }, + "node_modules/clean-css": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.3.tgz", + "integrity": "sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==", + "dev": true, + "license": "MIT", + "dependencies": { + "source-map": "~0.6.0" + }, + "engines": { + "node": ">= 10.0" + } + }, + "node_modules/clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true, + "license": "MIT" + }, + "node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": ">= 1.43.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compression": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.8.1.tgz", + "integrity": "sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "compressible": "~2.0.18", + "debug": "2.6.9", + "negotiator": "~0.6.4", + "on-headers": "~1.1.0", + "safe-buffer": "5.2.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/connect-history-api-fallback": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", + "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz", + "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==", + "dev": true, + "license": "MIT" + }, + "node_modules/copy-webpack-plugin": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-11.0.0.tgz", + "integrity": "sha512-fX2MWpamkW0hZxMEg0+mYnA40LTosOSa5TqZ9GYIBzyJa9C3QUaMPSE2xAi/buNr8u89SfD9wHSQVBzrRa/SOQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-glob": "^3.2.11", + "glob-parent": "^6.0.1", + "globby": "^13.1.1", + "normalize-path": "^3.0.0", + "schema-utils": "^4.0.0", + "serialize-javascript": "^6.0.0" + }, + "engines": { + "node": ">= 14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + } + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/css-select": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", + "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.0.1", + "domhandler": "^4.3.1", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-what": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz", + "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/default-browser": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.5.0.tgz", + "integrity": "sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "bundle-name": "^4.1.0", + "default-browser-id": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser-id": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.1.tgz", + "integrity": "sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/define-lazy-prop": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", + "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detect-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", + "dev": true, + "license": "MIT" + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dns-packet": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", + "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@leichtgewicht/ip-codec": "^2.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/dom-converter": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", + "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", + "dev": true, + "license": "MIT", + "dependencies": { + "utila": "~0.4" + } + }, + "node_modules/dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "dev": true, + "license": "MIT", + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "BSD-2-Clause" + }, + "node_modules/domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "domelementtype": "^2.2.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "dev": true, + "license": "MIT", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "dev": true, + "license": "MIT" + }, + "node_modules/electron-to-chromium": { + "version": "1.5.393", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.393.tgz", + "integrity": "sha512-kiDJdIUawuEIcp9XoICKp1iTYDEbgguIPq526N1Q7jIQDeQ3CqoMx71025PI/7E48Ddtw2HuWsVjY7afEgNxmg==", + "dev": true, + "license": "ISC" + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/enhanced-resolve": { + "version": "5.24.2", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.24.2.tgz", + "integrity": "sha512-rpsZEGT1jFuve6QlpyRp9ckQ+kN61hvF9BzCPyMdaKTm8UJce96KBn3sorXOFXlzjPrs3Vc4T1NsSroZ3PxlFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.3.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "dev": true, + "license": "BSD-2-Clause", + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/envinfo": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.21.0.tgz", + "integrity": "sha512-Lw7I8Zp5YKHFCXL7+Dz95g4CcbMEpgvqZNNq3AmlT5XAV6CgAAk6gyAMqn2zjw08K9BHfcNuKrMiCPLByGafow==", + "dev": true, + "license": "MIT", + "bin": { + "envinfo": "dist/cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-module-lexer": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.3.1.tgz", + "integrity": "sha512-shc1dbU90Yl/xq1QrC7QRtfcwURZuVRfPhZbDoldJ1cn1gzDvBaBWlv0eFolj5+0znnPJz5TXLxsN77X/12KTA==", + "dev": true, + "license": "MIT" + }, + "node_modules/es-object-atoms": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "dev": true, + "license": "MIT" + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "dev": true, + "license": "MIT" + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/express": { + "version": "4.22.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.22.2.tgz", + "integrity": "sha512-IuL+Elrou2ZvCFHs18/CIzy2Nzvo25nZ1/D2eIZlz7c+QUayAcYoiM2BthCjs+EBHVpjYjcuLDAiCWgeIX3X1Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "~1.20.5", + "content-disposition": "~0.5.4", + "content-type": "~1.0.4", + "cookie": "~0.7.1", + "cookie-signature": "~1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.3.1", + "fresh": "~0.5.2", + "http-errors": "~2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "~2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "~0.1.12", + "proxy-addr": "~2.0.7", + "qs": "~6.15.1", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "~0.19.0", + "serve-static": "~1.16.2", + "setprototypeof": "1.2.0", + "statuses": "~2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-uri": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.3.tgz", + "integrity": "sha512-i70LwGWUduXqzicKXWshooq+sWL1K3WUU5rKZNG/0i3a1OSoX3HqhH5WbWwTmqWfor4urUakGPiRQcleRZTwOg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/fastest-levenshtein": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", + "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4.9.1" + } + }, + "node_modules/fastq": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", + "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/faye-websocket": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "websocket-driver": ">=0.5.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz", + "integrity": "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "~2.4.1", + "parseurl": "~1.3.3", + "statuses": "~2.0.2", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "license": "BSD-3-Clause", + "bin": { + "flat": "cli.js" + } + }, + "node_modules/follow-redirects": { + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz", + "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/glob-to-regex.js": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/glob-to-regex.js/-/glob-to-regex.js-1.2.0.tgz", + "integrity": "sha512-QMwlOQKU/IzqMUOAZWubUOT8Qft+Y0KQWnX9nK3ch0CJg0tTp4TvGZsTfudYKv2NzoQSyPcnA6TYeIQ3jGichQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/globby": { + "version": "13.2.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-13.2.2.tgz", + "integrity": "sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "dir-glob": "^3.0.1", + "fast-glob": "^3.3.0", + "ignore": "^5.2.4", + "merge2": "^1.4.1", + "slash": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/handle-thing": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", + "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", + "dev": true, + "license": "MIT" + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "license": "MIT", + "bin": { + "he": "bin/he" + } + }, + "node_modules/hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.1", + "obuf": "^1.0.0", + "readable-stream": "^2.0.1", + "wbuf": "^1.1.0" + } + }, + "node_modules/hpack.js/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/hpack.js/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "license": "MIT" + }, + "node_modules/hpack.js/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==", + "dev": true, + "license": "MIT", + "dependencies": { + "camel-case": "^4.1.2", + "clean-css": "^5.2.2", + "commander": "^8.3.0", + "he": "^1.2.0", + "param-case": "^3.0.4", + "relateurl": "^0.2.7", + "terser": "^5.10.0" + }, + "bin": { + "html-minifier-terser": "cli.js" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/html-webpack-plugin": { + "version": "5.6.7", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.6.7.tgz", + "integrity": "sha512-md+vXtdCAe60s1k6AU3dUyMJnDxUyQAwfwPKoLisvgUF1IXjtlLsk2se54+qfL9Mdm26bbwvjJybpNx48NKRLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/html-minifier-terser": "^6.0.0", + "html-minifier-terser": "^6.0.2", + "lodash": "^4.17.21", + "pretty-error": "^4.0.0", + "tapable": "^2.0.0" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/html-webpack-plugin" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "webpack": "^5.20.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/htmlparser2": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", + "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "dev": true, + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "MIT", + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.5.2", + "entities": "^2.0.0" + } + }, + "node_modules/http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==", + "dev": true, + "license": "MIT" + }, + "node_modules/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/http-parser-js": { + "version": "0.5.10", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.10.tgz", + "integrity": "sha512-Pysuw9XpUq5dVc/2SMHpuTY01RFl8fttgcyunjL7eEMhGM3cI4eOmiCycJDVCo/7O7ClfQD3SaI6ftDzqOXYMA==", + "dev": true, + "license": "MIT" + }, + "node_modules/http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/http-proxy-middleware": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.10.tgz", + "integrity": "sha512-RKzRWNPxUZqbuk3BC5mGVJbBnWgr+diEnjJexIOytFbBzDy88Fbh/YvBr3DsNrl1jYAfjWfpATEv0NO35FDuPQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/http-proxy": "^1.17.8", + "http-proxy": "^1.18.1", + "is-glob": "^4.0.1", + "is-plain-obj": "^3.0.0", + "micromatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "@types/express": "^4.17.13" + }, + "peerDependenciesMeta": { + "@types/express": { + "optional": true + } + } + }, + "node_modules/hyperdyperid": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/hyperdyperid/-/hyperdyperid-1.2.0.tgz", + "integrity": "sha512-Y93lCzHYgGWdrJ66yIktxiaGULYc6oGiABxhcO5AufBeOyoIdZF7bIfLaOrbM0iGIOXQQgxxRrFEnb+Y6w1n4A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.18" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-local": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", + "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/interpret": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz", + "integrity": "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/ipaddr.js": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.4.0.tgz", + "integrity": "sha512-9VGk3HGanVE6JoZXHiCpnGy5X0jYDnN4EA4lntFPj+1vIWlFhIylq2CrrCOJH9EAhc5CYhq18F2Av2tgoAPsYQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-core-module": { + "version": "2.16.2", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.2.tgz", + "integrity": "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-docker": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", + "dev": true, + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-inside-container": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-docker": "^3.0.0" + }, + "bin": { + "is-inside-container": "cli.js" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-network-error": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/is-network-error/-/is-network-error-1.3.2.tgz", + "integrity": "sha512-PhBY86zaxNZUuWP6h13Vu5oFe0XY6/UlKzQnYFELzGVHygP3MxmvTfYSG7GN3aIab/iWudSMgjSnG9Dq+nHrgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-plain-obj": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", + "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "license": "MIT", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-wsl": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.1.tgz", + "integrity": "sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-inside-container": "^1.0.0" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT" + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/launch-editor": { + "version": "2.14.1", + "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.14.1.tgz", + "integrity": "sha512-QWBrQsMpH7gPr965dsKD/3cKWiNoTjpATQf++Xq63N6sKRGMwlVXz41O1IZTMfZQgBctD/K5Zt06+/I6pP6+HA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picocolors": "^1.1.1", + "shell-quote": "^1.8.4" + } + }, + "node_modules/loader-runner": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.2.tgz", + "integrity": "sha512-DFEqQ3ihfS9blba08cLfYf1NRAIEm+dDjic073DRDc3/JspI/8wYmtDsHwd3+4hwvdxSK7PGaElfTmm0awWJ4w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.11.5" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lodash": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.0.3" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/memfs": { + "version": "4.64.0", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.64.0.tgz", + "integrity": "sha512-Kw72fgY7Wn+sD8KmtNWSafl1dz0UvAsE/PHs3YVfLiaZuA3HxNm9sRLqAu0ATiBGJvME1PxZXbBZPv5GycDeAw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/fs-core": "4.64.0", + "@jsonjoy.com/fs-fsa": "4.64.0", + "@jsonjoy.com/fs-node": "4.64.0", + "@jsonjoy.com/fs-node-builtins": "4.64.0", + "@jsonjoy.com/fs-node-to-fsa": "4.64.0", + "@jsonjoy.com/fs-node-utils": "4.64.0", + "@jsonjoy.com/fs-print": "4.64.0", + "@jsonjoy.com/fs-snapshot": "4.64.0", + "@jsonjoy.com/json-pack": "^1.11.0", + "@jsonjoy.com/util": "^1.9.0", + "glob-to-regex.js": "^1.0.1", + "thingies": "^2.5.0", + "tree-dump": "^1.0.3", + "tslib": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true, + "license": "MIT" + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true, + "license": "ISC" + }, + "node_modules/minimizer-webpack-plugin": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/minimizer-webpack-plugin/-/minimizer-webpack-plugin-5.6.1.tgz", + "integrity": "sha512-DoeAZz8Q1C1znwsUzej1fdoi4jCf7/+Em27ouLqfK/+3m8G+D7yDhUwrc3CNhjSzGUN1kn7Iv4sWmjflQHenpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.25", + "jest-worker": "^27.4.5", + "schema-utils": "^4.3.0", + "terser": "^5.31.1" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@minify-html/node": { + "optional": true + }, + "@swc/core": { + "optional": true + }, + "@swc/css": { + "optional": true + }, + "@swc/html": { + "optional": true + }, + "clean-css": { + "optional": true + }, + "cssnano": { + "optional": true + }, + "csso": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "html-minifier-terser": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "postcss": { + "optional": true + }, + "uglify-js": { + "optional": true + } + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, + "node_modules/multicast-dns": { + "version": "7.2.5", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", + "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", + "dev": true, + "license": "MIT", + "dependencies": { + "dns-packet": "^5.2.2", + "thunky": "^1.0.2" + }, + "bin": { + "multicast-dns": "cli.js" + } + }, + "node_modules/negotiator": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", + "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true, + "license": "MIT" + }, + "node_modules/no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "dev": true, + "license": "MIT", + "dependencies": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, + "node_modules/node-releases": { + "version": "2.0.51", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.51.tgz", + "integrity": "sha512-wRNIrw4DmVLKQlbgOMdkMx27Wrpzes2hh5Jtbi2bjPd+4wJstWIqP5A+lscnqbm0xxmT5Bpg8Lec5ItEBwx6BQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", + "dev": true, + "license": "MIT" + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-headers": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz", + "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/open": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/open/-/open-10.2.0.tgz", + "integrity": "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "default-browser": "^5.2.1", + "define-lazy-prop": "^3.0.0", + "is-inside-container": "^1.0.0", + "wsl-utils": "^0.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-retry": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-6.2.1.tgz", + "integrity": "sha512-hEt02O4hUct5wtwg4H4KcWgDdm+l1bOaEy/hWzd8xtXB9BqxTWBBhb+2ImAtH4Cv4rPjV76xN3Zumqk3k3AhhQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/retry": "0.12.2", + "is-network-error": "^1.0.0", + "retry": "^0.13.1" + }, + "engines": { + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/param-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", + "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", + "dev": true, + "license": "MIT", + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/pascal-case": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", + "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", + "dev": true, + "license": "MIT", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-to-regexp": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.13.tgz", + "integrity": "sha512-A/AGNMFN3c8bOlvV9RreMdrv7jsmF9XIfDeCd87+I8RNg6s78BhJxMu69NEMHBSJFxKidViTEdruRwEk/WIKqA==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkijs": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/pkijs/-/pkijs-3.4.0.tgz", + "integrity": "sha512-emEcLuomt2j03vxD54giVB4SxTjnsqkU692xZOZXHDVoYyypEm+b3jpiTcc+Cf+myooc+/Ly0z01jqeNHVgJGw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@noble/hashes": "1.4.0", + "asn1js": "^3.0.6", + "bytestreamjs": "^2.0.1", + "pvtsutils": "^1.3.6", + "pvutils": "^1.1.3", + "tslib": "^2.8.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/pretty-error": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", + "integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==", + "dev": true, + "license": "MIT", + "dependencies": { + "lodash": "^4.17.20", + "renderkid": "^3.0.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true, + "license": "MIT" + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-addr/node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/pvtsutils": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/pvtsutils/-/pvtsutils-1.3.6.tgz", + "integrity": "sha512-PLgQXQ6H2FWCaeRak8vvk1GW462lMxB5s3Jm673N82zI4vqtVUPuZdffdZbPDFRoU8kAhItWFtPCWiPpp4/EDg==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.8.1" + } + }, + "node_modules/pvutils": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/pvutils/-/pvutils-1.1.5.tgz", + "integrity": "sha512-KTqnxsgGiQ6ZAzZCVlJH5eOjSnvlyEgx1m8bkRJfOhmGRqfo5KLvmAlACQkrjEtOQ4B7wF9TdSLIs9O90MX9xA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/qs": { + "version": "6.15.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.3.tgz", + "integrity": "sha512-O9gl3zCl5h5blw1KGUzQKhA5oUXSl8rwUIM5o0S3nCXMliSvy5Dzx7/DJcI+SwgICv+IneSZwhBh1oSyEHA71A==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "es-define-property": "^1.0.1", + "side-channel": "^1.1.1" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz", + "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", + "dev": true, + "license": "MIT", + "dependencies": { + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/rechoir": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", + "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve": "^1.20.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/reflect-metadata": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz", + "integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", + "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/renderkid": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", + "integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==", + "dev": true, + "license": "MIT", + "dependencies": { + "css-select": "^4.1.3", + "dom-converter": "^0.2.0", + "htmlparser2": "^6.1.0", + "lodash": "^4.17.21", + "strip-ansi": "^6.0.1" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/resolve": { + "version": "1.22.12", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz", + "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/run-applescript": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.1.0.tgz", + "integrity": "sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true, + "license": "MIT" + }, + "node_modules/schema-utils": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.3.tgz", + "integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==", + "dev": true, + "license": "MIT" + }, + "node_modules/selfsigned": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-5.5.0.tgz", + "integrity": "sha512-ftnu3TW4+3eBfLRFnDEkzGxSF/10BJBkaLJuBHZX0kiPS7bRdlpZGu6YGt4KngMkdTwJE6MbjavFpqHvqVt+Ew==", + "dev": true, + "license": "MIT", + "dependencies": { + "@peculiar/x509": "^1.14.2", + "pkijs": "^3.3.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/send": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.2.tgz", + "integrity": "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "~0.5.2", + "http-errors": "~2.0.1", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "~2.4.1", + "range-parser": "~1.2.1", + "statuses": "~2.0.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/serve-index": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.2.tgz", + "integrity": "sha512-KDj11HScOaLmrPxl70KYNW1PksP4Nb/CLL2yvC+Qd2kHMPEEpfc4Re2e4FOay+bC/+XQl/7zAcWON3JVo5v3KQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "accepts": "~1.3.8", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.8.0", + "mime-types": "~2.1.35", + "parseurl": "~1.3.3" + }, + "engines": { + "node": ">= 0.8.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/serve-index/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-index/node_modules/http-errors": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", + "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-index/node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-static": { + "version": "1.16.3", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.3.tgz", + "integrity": "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "~0.19.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "dev": true, + "license": "ISC" + }, + "node_modules/shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dev": true, + "license": "MIT", + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/shell-quote": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.10.0.tgz", + "integrity": "sha512-w1aiOKwKuRgtwAReIIj89puqg+I7GvX4IbLrvmhXbzQsj1+Zwi4VO3+fa6ZF91TWSjIxoEkKnMeHcLEODK5ZXA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.1.tgz", + "integrity": "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4", + "side-channel-list": "^1.0.1", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", + "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/slash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", + "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/sockjs": { + "version": "0.3.24", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", + "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "faye-websocket": "^0.11.3", + "uuid": "^8.3.2", + "websocket-driver": "^0.7.4" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/spdy": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", + "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.1.0", + "handle-thing": "^2.0.0", + "http-deceiver": "^1.2.7", + "select-hose": "^2.0.0", + "spdy-transport": "^3.0.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/spdy-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", + "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.1.0", + "detect-node": "^2.0.4", + "hpack.js": "^2.1.6", + "obuf": "^1.1.2", + "readable-stream": "^3.0.6", + "wbuf": "^1.7.3" + } + }, + "node_modules/spdy-transport/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/spdy-transport/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/spdy/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/spdy/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tapable": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz", + "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/terser": { + "version": "5.49.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.49.0.tgz", + "integrity": "sha512-SNiDnXyHSrxVcIOtVbULzcTmniUiwcV7Nwdyj1twVubeTmbjoa8p69KKDpfkdoOavuM4/GRm1+ykI8qqnavHoA==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.15.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/thingies": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/thingies/-/thingies-2.6.0.tgz", + "integrity": "sha512-rMHRjmlFLM1R96UYPvpmnc3LYtdFrT33JIB7L9hetGue1qAPfn1N2LJeEjxUSidu1Iku+haLZXDuEXUHNGO/lg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "^2" + } + }, + "node_modules/thunky": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", + "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", + "dev": true, + "license": "MIT" + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tree-dump": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/tree-dump/-/tree-dump-1.1.0.tgz", + "integrity": "sha512-rMuvhU4MCDbcbnleZTFezWsaZXRFemSqAM+7jPnzUl1fo9w3YEKOxAeui0fz3OI4EU4hf23iyA7uQRVko+UaBA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD" + }, + "node_modules/tsyringe": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/tsyringe/-/tsyringe-4.10.0.tgz", + "integrity": "sha512-axr3IdNuVIxnaK5XGEUFTu3YmAQ6lllgrvqfEoR16g/HGnYY/6We4oWENtAnzK6/LpJ2ur9PAb80RBt7/U4ugw==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^1.9.3" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/tsyringe/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true, + "license": "0BSD" + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/undici-types": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-8.3.0.tgz", + "integrity": "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/utila": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", + "integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==", + "dev": true, + "license": "MIT" + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).", + "dev": true, + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/watchpack": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.5.2.tgz", + "integrity": "sha512-6i/00NBjP4yGPs+caKSyRfpTF/8Torsu0MOW3mMzIbhgISFder8i7xbqgHlLMwJrdiN8ndBV3UA1/AfzPSr+jg==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/wbuf": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", + "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/webpack": { + "version": "5.108.4", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.108.4.tgz", + "integrity": "sha512-yur8LyJoeiWh47dErD+Ok7vlbmDsJ3UbbRPAoxbGJ54WpE2y5yVo5G/inUzujnYgw3tPmBRdn+G7PoxXaYC33w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.8", + "@types/json-schema": "^7.0.15", + "@webassemblyjs/ast": "^1.14.1", + "@webassemblyjs/wasm-edit": "^1.14.1", + "@webassemblyjs/wasm-parser": "^1.14.1", + "acorn": "^8.16.0", + "acorn-import-phases": "^1.0.3", + "browserslist": "^4.28.1", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.22.2", + "es-module-lexer": "^2.1.0", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "graceful-fs": "^4.2.11", + "loader-runner": "^4.3.2", + "mime-db": "^1.54.0", + "minimizer-webpack-plugin": "^5.6.1", + "neo-async": "^2.6.2", + "schema-utils": "^4.3.3", + "tapable": "^2.3.0", + "watchpack": "^2.5.2", + "webpack-sources": "^3.5.0" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-cli": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-5.1.4.tgz", + "integrity": "sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@discoveryjs/json-ext": "^0.5.0", + "@webpack-cli/configtest": "^2.1.1", + "@webpack-cli/info": "^2.0.2", + "@webpack-cli/serve": "^2.0.5", + "colorette": "^2.0.14", + "commander": "^10.0.1", + "cross-spawn": "^7.0.3", + "envinfo": "^7.7.3", + "fastest-levenshtein": "^1.0.12", + "import-local": "^3.0.2", + "interpret": "^3.1.1", + "rechoir": "^0.8.0", + "webpack-merge": "^5.7.3" + }, + "bin": { + "webpack-cli": "bin/cli.js" + }, + "engines": { + "node": ">=14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "5.x.x" + }, + "peerDependenciesMeta": { + "@webpack-cli/generators": { + "optional": true + }, + "webpack-bundle-analyzer": { + "optional": true + }, + "webpack-dev-server": { + "optional": true + } + } + }, + "node_modules/webpack-cli/node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/webpack-dev-middleware": { + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-7.4.5.tgz", + "integrity": "sha512-uxQ6YqGdE4hgDKNf7hUiPXOdtkXvBJXrfEGYSx7P7LC8hnUYGK70X6xQXUvXeNyBDDcsiQXpG2m3G9vxowaEuA==", + "dev": true, + "license": "MIT", + "dependencies": { + "colorette": "^2.0.10", + "memfs": "^4.43.1", + "mime-types": "^3.0.1", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + } + } + }, + "node_modules/webpack-dev-middleware/node_modules/mime-types": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", + "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": "^1.54.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/webpack-dev-server": { + "version": "5.2.6", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-5.2.6.tgz", + "integrity": "sha512-HNLRmamRvVavZQ+avceZifmv8hmdUjg43t6MI4SqJDwFdW7RPQwH5vzGhDRZSX59SgfbeHhLnq3g+uooWo7pVw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/bonjour": "^3.5.13", + "@types/connect-history-api-fallback": "^1.5.4", + "@types/express": "^4.17.25", + "@types/express-serve-static-core": "^4.17.21", + "@types/serve-index": "^1.9.4", + "@types/serve-static": "^1.15.5", + "@types/sockjs": "^0.3.36", + "@types/ws": "^8.5.10", + "ansi-html-community": "^0.0.8", + "bonjour-service": "^1.2.1", + "chokidar": "^3.6.0", + "colorette": "^2.0.10", + "compression": "^1.8.1", + "connect-history-api-fallback": "^2.0.0", + "express": "^4.22.1", + "graceful-fs": "^4.2.6", + "http-proxy-middleware": "^2.0.9", + "ipaddr.js": "^2.1.0", + "launch-editor": "^2.14.1", + "open": "^10.0.3", + "p-retry": "^6.2.0", + "schema-utils": "^4.2.0", + "selfsigned": "^5.5.0", + "serve-index": "^1.9.1", + "sockjs": "^0.3.24", + "spdy": "^4.0.2", + "webpack-dev-middleware": "^7.4.2", + "ws": "^8.18.0" + }, + "bin": { + "webpack-dev-server": "bin/webpack-dev-server.js" + }, + "engines": { + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + }, + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-merge": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", + "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "clone-deep": "^4.0.1", + "flat": "^5.0.2", + "wildcard": "^2.0.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/webpack-sources": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.5.1.tgz", + "integrity": "sha512-jyuiGJdtvY434z5bUZrjz67v76/ePNvFZTp9Mdz29IlH4+GPsgyGjiv0fKI+M7BdkU6ADjulUcKAd3tUK3WlEw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/websocket-driver": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.5.tgz", + "integrity": "sha512-ZL2+3c7kMBdIRCMz6l8jQMHyGVxj+UL+xVk74Ombiciboca8rHa15L86B19E5oh1pL9Ii/uj54gtsIrZGMo6zA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wildcard": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", + "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/ws": { + "version": "8.21.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.1.tgz", + "integrity": "sha512-+0NTnW77fFN/DjQi6k/Sq/Yvk4Sgajw7urW8V+asjXnRgDs9gyGkdb7EzgfhA4goXsRIZKE28fzIXBHEzhuiWw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/wsl-utils": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/wsl-utils/-/wsl-utils-0.1.0.tgz", + "integrity": "sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-wsl": "^3.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..cb6a6d2 --- /dev/null +++ b/package.json @@ -0,0 +1,26 @@ +{ + "name": "fi3w0-portfolio", + "version": "1.0.0", + "description": "Personal systems and development portfolio for Alex (Fi3w0).", + "private": true, + "keywords": [ + "portfolio", + "devops", + "systems", + "homelab" + ], + "license": "MIT", + "author": "Alex (Fi3w0)", + "scripts": { + "start": "webpack serve --open --config webpack.config.dev.js", + "build": "webpack --config webpack.config.prod.js" + }, + "devDependencies": { + "copy-webpack-plugin": "^11.0.0", + "html-webpack-plugin": "^5.6.0", + "webpack": "^5.91.0", + "webpack-cli": "^5.1.4", + "webpack-dev-server": "^5.0.4", + "webpack-merge": "^5.10.0" + } +} diff --git a/robots.txt b/robots.txt new file mode 100644 index 0000000..d0e5f1b --- /dev/null +++ b/robots.txt @@ -0,0 +1,5 @@ +# www.robotstxt.org/ + +# Allow crawling of all content +User-agent: * +Disallow: diff --git a/site.webmanifest b/site.webmanifest new file mode 100644 index 0000000..3543883 --- /dev/null +++ b/site.webmanifest @@ -0,0 +1,15 @@ +{ + "short_name": "Fi3w0", + "name": "Fi3w0 / Alex - Systems Builder", + "icons": [ + { + "src": "icon.png", + "type": "image/png", + "sizes": "192x192" + } + ], + "start_url": "/", + "display": "standalone", + "background_color": "#101a21", + "theme_color": "#101a21" +} diff --git a/webpack.common.js b/webpack.common.js new file mode 100644 index 0000000..b502ea9 --- /dev/null +++ b/webpack.common.js @@ -0,0 +1,12 @@ +const path = require('path'); + +module.exports = { + entry: { + app: './js/app.js', + }, + output: { + path: path.resolve(__dirname, 'dist'), + clean: true, + filename: './js/app.js', + }, +}; diff --git a/webpack.config.dev.js b/webpack.config.dev.js new file mode 100644 index 0000000..5953807 --- /dev/null +++ b/webpack.config.dev.js @@ -0,0 +1,13 @@ +const { merge } = require('webpack-merge'); +const common = require('./webpack.common.js'); + +module.exports = merge(common, { + mode: 'development', + devtool: 'inline-source-map', + devServer: { + liveReload: true, + hot: true, + open: true, + static: ['./'], + }, +}); diff --git a/webpack.config.prod.js b/webpack.config.prod.js new file mode 100644 index 0000000..96b3fde --- /dev/null +++ b/webpack.config.prod.js @@ -0,0 +1,26 @@ +const { merge } = require('webpack-merge'); +const common = require('./webpack.common.js'); +const HtmlWebpackPlugin = require('html-webpack-plugin'); +const CopyPlugin = require('copy-webpack-plugin'); + +module.exports = merge(common, { + mode: 'production', + plugins: [ + new HtmlWebpackPlugin({ + template: './index.html', + inject: false, + }), + new CopyPlugin({ + patterns: [ + { from: 'img', to: 'img' }, + { from: 'css', to: 'css' }, + { from: 'icon.svg', to: 'icon.svg' }, + { from: 'favicon.ico', to: 'favicon.ico' }, + { from: 'robots.txt', to: 'robots.txt' }, + { from: 'icon.png', to: 'icon.png' }, + { from: '404.html', to: '404.html' }, + { from: 'site.webmanifest', to: 'site.webmanifest' }, + ], + }), + ], +});