Revert to static JS site (Svelte built, but no CSR); Optimize images
@@ -5,7 +5,7 @@ This file helps LLM agents work with the Armandine codebase without introducing
|
||||
## Stack and goals
|
||||
|
||||
- **Svelte 5** + **SvelteKit** with **TypeScript**. The site is a **single pre-rendered page** (no SSR, no backend).
|
||||
- **adapter-static**: the app is built to static HTML/JS/CSS in `build/`. The gallery is **rendered at build time** from `src/lib/media.ts`; the HTML already contains the full gallery. Lightbox and theme toggle are handled by a **client script** (`static/assets/js/script.js`) that binds to the pre-rendered DOM.
|
||||
- **adapter-static**: the app is built to static HTML/JS/CSS in `build/`. **CSR is disabled** (`csr = false` in `+layout.ts`), so no Svelte runtime or app JS is loaded in the browser. The gallery and shell (header, empty lightbox dialog) are **rendered at build time** from Svelte components and `src/lib/media.ts`. Lightbox, theme toggle, and “show video” are implemented in **`static/assets/js/script.js`** only; they bind to the pre-rendered DOM.
|
||||
- **PostCSS**: nesting and CSS level 2; component-scoped `<style>` in Svelte where possible; global styles in `src/app.css`.
|
||||
- **Critical CSS**: after `vite build`, `scripts/critical-css.js` runs Beasties to inline critical CSS into the built HTML.
|
||||
|
||||
@@ -26,7 +26,7 @@ This file helps LLM agents work with the Armandine codebase without introducing
|
||||
|
||||
- Use **Svelte 5** patterns (e.g. `$props()`, runes). Use **TypeScript** for `src/lib` and route logic.
|
||||
- **Gallery**: Rendered at build time via `GalleryFigure` and `data.mediaItems` from `+page.ts`. Do not move gallery rendering to the client.
|
||||
- **Lightbox and theme**: Implemented in `static/assets/js/script.js`; they rely on the pre-rendered DOM (e.g. `.gallery-item`, `#lightbox`, `#lb-content`). Keep them in that script; do not reimplement in Svelte for “consistency” (the plan keeps them in JS for optimal loading and preload).
|
||||
- **Lightbox and theme**: Implemented only in `static/assets/js/script.js` (no client-side Svelte). They rely on the pre-rendered DOM (e.g. `.gallery-item[data-name]`, `dialog.lightbox`, `#show_video`, `#theme-toggle`). The Svelte `Lightbox` component is still used at build time to output the empty `<dialog class="lightbox">`; script.js creates the inner structure (header, .lb-content, #lb-caption) on first open. Keep all runtime behavior in script.js.
|
||||
- **Head**: Metadata, JSON-LD, favicons, preload of `script.js`, and GA scripts are set in `+page.svelte`’s `<svelte:head>`.
|
||||
- **CSS**: Prefer component-scoped `<style>` in Svelte components; use `src/app.css` only for `:root`, `body`, and shared/global rules (e.g. lightbox, which is targeted by the client script).
|
||||
- **Build**: `pnpm build` = `vite build` then `node scripts/critical-css.js`. Output is `build/`. Dockerfile copies `build/` into the image.
|
||||
|
||||
@@ -10,7 +10,7 @@ services:
|
||||
- "traefik.docker.network=marina-net"
|
||||
- "traefik.http.routers.armandine-gallery.rule=Host(`armandine.mifi.holdings`)"
|
||||
- "traefik.http.routers.armandine-gallery.entrypoints=websecure"
|
||||
- "traefik.http.routers.armandine-gallery.middlewares=security-supermax-with-analytics@file"
|
||||
- "traefik.http.routers.armandine-gallery.middlewares=gzip@file,security-supermax-with-analytics@file"
|
||||
- "traefik.http.routers.armandine-gallery.tls=true"
|
||||
- "traefik.http.routers.armandine-gallery.tls.certresolver=letsencrypt"
|
||||
- "traefik.http.services.armandine-gallery.loadbalancer.server.port=80"
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
"scripts": {
|
||||
"dev": "vite dev",
|
||||
"build": "vite build && node scripts/critical-css.js && node scripts/externalize-bootstrap.js",
|
||||
"preview": "vite preview",
|
||||
"preview": "serve build",
|
||||
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
||||
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
||||
"format": "prettier --write \"src/**/*.{ts,js,svelte,css,json}\" \"static/**/*.js\"",
|
||||
@@ -29,6 +29,7 @@
|
||||
"@sveltejs/kit": "^2.0.0",
|
||||
"@sveltejs/vite-plugin-svelte": "^6.2.4",
|
||||
"beasties": "^0.4.1",
|
||||
"serve": "^14.2.5",
|
||||
"@eslint/js": "^10.0.1",
|
||||
"eslint": "^10.0.0",
|
||||
"eslint-config-prettier": "^10.1.8",
|
||||
|
||||
476
pnpm-lock.yaml
generated
@@ -47,6 +47,9 @@ importers:
|
||||
prettier-plugin-svelte:
|
||||
specifier: ^3.2.0
|
||||
version: 3.4.1(prettier@3.8.1)(svelte@5.51.2)
|
||||
serve:
|
||||
specifier: ^14.2.5
|
||||
version: 14.2.5
|
||||
stylelint:
|
||||
specifier: ^17.3.0
|
||||
version: 17.3.0(typescript@5.9.3)
|
||||
@@ -918,6 +921,9 @@ packages:
|
||||
resolution: {integrity: sha512-AxNRwEie8Nn4eFS1FzDMJWIISMGoXMb037sgCBJ3UR6o0fQTzr2tqN9WT+DkWJPhIdQCfV7T6D387566VtnCJA==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
|
||||
'@zeit/schemas@2.36.0':
|
||||
resolution: {integrity: sha512-7kjMwcChYEzMKjeex9ZFXkt1AyNov9R5HZtjBKVsmVpw7pa7ZtlCGvCBC2vnnXctaYN+aRI61HjIqeetZW5ROg==}
|
||||
|
||||
acorn-jsx@5.3.2:
|
||||
resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
|
||||
peerDependencies:
|
||||
@@ -931,9 +937,15 @@ packages:
|
||||
ajv@6.12.6:
|
||||
resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==}
|
||||
|
||||
ajv@8.12.0:
|
||||
resolution: {integrity: sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==}
|
||||
|
||||
ajv@8.17.1:
|
||||
resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==}
|
||||
|
||||
ansi-align@3.0.1:
|
||||
resolution: {integrity: sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==}
|
||||
|
||||
ansi-regex@5.0.1:
|
||||
resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
|
||||
engines: {node: '>=8'}
|
||||
@@ -946,6 +958,16 @@ packages:
|
||||
resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
ansi-styles@6.2.3:
|
||||
resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
arch@2.2.0:
|
||||
resolution: {integrity: sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==}
|
||||
|
||||
arg@5.0.2:
|
||||
resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==}
|
||||
|
||||
argparse@2.0.1:
|
||||
resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
|
||||
|
||||
@@ -997,6 +1019,13 @@ packages:
|
||||
boolbase@1.0.0:
|
||||
resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==}
|
||||
|
||||
boxen@7.0.0:
|
||||
resolution: {integrity: sha512-j//dBVuyacJbvW+tvZ9HuH03fZ46QcaKvvhZickZqtB271DxJ7SNRSNxrV/dZX0085m7hISRZWbzWlJvx/rHSg==}
|
||||
engines: {node: '>=14.16'}
|
||||
|
||||
brace-expansion@1.1.12:
|
||||
resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==}
|
||||
|
||||
brace-expansion@2.0.2:
|
||||
resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==}
|
||||
|
||||
@@ -1016,6 +1045,14 @@ packages:
|
||||
buffer-from@1.1.2:
|
||||
resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
|
||||
|
||||
bytes@3.0.0:
|
||||
resolution: {integrity: sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==}
|
||||
engines: {node: '>= 0.8'}
|
||||
|
||||
bytes@3.1.2:
|
||||
resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==}
|
||||
engines: {node: '>= 0.8'}
|
||||
|
||||
cacheable@2.3.2:
|
||||
resolution: {integrity: sha512-w+ZuRNmex9c1TR9RcsxbfTKCjSL0rh1WA5SABbrWprIHeNBdmyQLSYonlDy9gpD+63XT8DgZ/wNh1Smvc9WnJA==}
|
||||
|
||||
@@ -1023,13 +1060,37 @@ packages:
|
||||
resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
camelcase@7.0.1:
|
||||
resolution: {integrity: sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==}
|
||||
engines: {node: '>=14.16'}
|
||||
|
||||
caniuse-lite@1.0.30001770:
|
||||
resolution: {integrity: sha512-x/2CLQ1jHENRbHg5PSId2sXq1CIO1CISvwWAj027ltMVG2UNgW+w9oH2+HzgEIRFembL8bUlXtfbBHR1fCg2xw==}
|
||||
|
||||
chalk-template@0.4.0:
|
||||
resolution: {integrity: sha512-/ghrgmhfY8RaSdeo43hNXxpoHAtxdbskUHjPpfqUWGttFgycUhYPGx3YZBCnUCvOa7Doivn1IZec3DEGFoMgLg==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
chalk@4.1.2:
|
||||
resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
chalk@5.0.1:
|
||||
resolution: {integrity: sha512-Fo07WOYGqMfCWHOzSXOt2CxDbC6skS/jO9ynEcmpANMoPrD+W1r1K6Vx7iNm+AQmETU1Xr2t+n8nzkV9t6xh3w==}
|
||||
engines: {node: ^12.17.0 || ^14.13 || >=16.0.0}
|
||||
|
||||
chokidar@4.0.3:
|
||||
resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==}
|
||||
engines: {node: '>= 14.16.0'}
|
||||
|
||||
cli-boxes@3.0.0:
|
||||
resolution: {integrity: sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
clipboardy@3.0.0:
|
||||
resolution: {integrity: sha512-Su+uU5sr1jkUy1sGRpLKjKrvEOVXgSgiSInwa/qeID6aJ07yh+5NWc3h2QfjHjBnfX4LhtFcuAWKUsJ3r+fjbg==}
|
||||
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
||||
|
||||
cliui@7.0.4:
|
||||
resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==}
|
||||
|
||||
@@ -1050,9 +1111,24 @@ packages:
|
||||
commander@2.20.3:
|
||||
resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==}
|
||||
|
||||
compressible@2.0.18:
|
||||
resolution: {integrity: sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==}
|
||||
engines: {node: '>= 0.6'}
|
||||
|
||||
compression@1.8.1:
|
||||
resolution: {integrity: sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==}
|
||||
engines: {node: '>= 0.8.0'}
|
||||
|
||||
concat-map@0.0.1:
|
||||
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
|
||||
|
||||
consola@2.15.3:
|
||||
resolution: {integrity: sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==}
|
||||
|
||||
content-disposition@0.5.2:
|
||||
resolution: {integrity: sha512-kRGRZw3bLlFISDBgwTSA1TMBFN6J6GWDeubmDE3AF+3+yXL8hTWv8r5rkLbqYXY4RjPk/EzHnClI3zQf1cFmHA==}
|
||||
engines: {node: '>= 0.6'}
|
||||
|
||||
cookie@0.6.0:
|
||||
resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==}
|
||||
engines: {node: '>= 0.6'}
|
||||
@@ -1111,6 +1187,14 @@ packages:
|
||||
engines: {node: '>=4'}
|
||||
hasBin: true
|
||||
|
||||
debug@2.6.9:
|
||||
resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==}
|
||||
peerDependencies:
|
||||
supports-color: '*'
|
||||
peerDependenciesMeta:
|
||||
supports-color:
|
||||
optional: true
|
||||
|
||||
debug@4.4.3:
|
||||
resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==}
|
||||
engines: {node: '>=6.0'}
|
||||
@@ -1120,6 +1204,10 @@ packages:
|
||||
supports-color:
|
||||
optional: true
|
||||
|
||||
deep-extend@0.6.0:
|
||||
resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==}
|
||||
engines: {node: '>=4.0.0'}
|
||||
|
||||
deep-is@0.1.4:
|
||||
resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
|
||||
|
||||
@@ -1147,12 +1235,18 @@ packages:
|
||||
domutils@3.2.2:
|
||||
resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==}
|
||||
|
||||
eastasianwidth@0.2.0:
|
||||
resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
|
||||
|
||||
electron-to-chromium@1.5.286:
|
||||
resolution: {integrity: sha512-9tfDXhJ4RKFNerfjdCcZfufu49vg620741MNs26a9+bhLThdB+plgMeou98CAaHu/WATj2iHOOHTp1hWtABj2A==}
|
||||
|
||||
emoji-regex@8.0.0:
|
||||
resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
|
||||
|
||||
emoji-regex@9.2.2:
|
||||
resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
|
||||
|
||||
entities@4.5.0:
|
||||
resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==}
|
||||
engines: {node: '>=0.12'}
|
||||
@@ -1239,6 +1333,10 @@ packages:
|
||||
resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
execa@5.1.1:
|
||||
resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
fast-deep-equal@3.1.3:
|
||||
resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
|
||||
|
||||
@@ -1312,6 +1410,10 @@ packages:
|
||||
resolution: {integrity: sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
get-stream@6.0.1:
|
||||
resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
glob-parent@5.1.2:
|
||||
resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
|
||||
engines: {node: '>= 6'}
|
||||
@@ -1339,6 +1441,10 @@ packages:
|
||||
globjoin@0.1.4:
|
||||
resolution: {integrity: sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==}
|
||||
|
||||
has-flag@4.0.0:
|
||||
resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
has-flag@5.0.1:
|
||||
resolution: {integrity: sha512-CsNUt5x9LUdx6hnk/E2SZLsDyvfqANZSUq4+D3D8RzDJ2M+HDTIkF60ibS1vHaK55vzgiZw1bEPFG9yH7l33wA==}
|
||||
engines: {node: '>=12'}
|
||||
@@ -1357,6 +1463,10 @@ packages:
|
||||
htmlparser2@10.1.0:
|
||||
resolution: {integrity: sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ==}
|
||||
|
||||
human-signals@2.1.0:
|
||||
resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==}
|
||||
engines: {node: '>=10.17.0'}
|
||||
|
||||
ignore@5.3.2:
|
||||
resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==}
|
||||
engines: {node: '>= 4'}
|
||||
@@ -1386,6 +1496,11 @@ packages:
|
||||
is-arrayish@0.2.1:
|
||||
resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==}
|
||||
|
||||
is-docker@2.2.1:
|
||||
resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==}
|
||||
engines: {node: '>=8'}
|
||||
hasBin: true
|
||||
|
||||
is-extglob@2.1.1:
|
||||
resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@@ -1410,9 +1525,21 @@ packages:
|
||||
resolution: {integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
is-port-reachable@4.0.0:
|
||||
resolution: {integrity: sha512-9UoipoxYmSk6Xy7QFgRv2HDyaysmgSG75TFQs6S+3pDM7ZhKTF/bskZV+0UlABHzKjNVhPjYCLfeZUEg1wXxig==}
|
||||
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
||||
|
||||
is-reference@3.0.3:
|
||||
resolution: {integrity: sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==}
|
||||
|
||||
is-stream@2.0.1:
|
||||
resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
is-wsl@2.2.0:
|
||||
resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
isexe@2.0.0:
|
||||
resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
|
||||
|
||||
@@ -1493,6 +1620,9 @@ packages:
|
||||
resolution: {integrity: sha512-JhC3R1f6dbspVtmF3vKjAWz1EVIvwFrGGPLSdU6rK79xBwHWTuHoLnRX/t1/zHS1Ch1Y2UtIrih7DAHuH9JFJA==}
|
||||
engines: {node: '>=20'}
|
||||
|
||||
merge-stream@2.0.0:
|
||||
resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==}
|
||||
|
||||
merge2@1.4.1:
|
||||
resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
|
||||
engines: {node: '>= 8'}
|
||||
@@ -1501,14 +1631,36 @@ packages:
|
||||
resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==}
|
||||
engines: {node: '>=8.6'}
|
||||
|
||||
mime-db@1.33.0:
|
||||
resolution: {integrity: sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==}
|
||||
engines: {node: '>= 0.6'}
|
||||
|
||||
mime-db@1.54.0:
|
||||
resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==}
|
||||
engines: {node: '>= 0.6'}
|
||||
|
||||
mime-types@2.1.18:
|
||||
resolution: {integrity: sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==}
|
||||
engines: {node: '>= 0.6'}
|
||||
|
||||
mimic-fn@2.1.0:
|
||||
resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
minimatch@10.2.0:
|
||||
resolution: {integrity: sha512-ugkC31VaVg9cF0DFVoADH12k6061zNZkZON+aX8AWsR9GhPcErkcMBceb6znR8wLERM2AkkOxy2nWRLpT9Jq5w==}
|
||||
engines: {node: 20 || >=22}
|
||||
|
||||
minimatch@3.1.2:
|
||||
resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
|
||||
|
||||
minimatch@9.0.5:
|
||||
resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==}
|
||||
engines: {node: '>=16 || 14 >=14.17'}
|
||||
|
||||
minimist@1.2.8:
|
||||
resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
|
||||
|
||||
mri@1.2.0:
|
||||
resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==}
|
||||
engines: {node: '>=4'}
|
||||
@@ -1517,6 +1669,9 @@ packages:
|
||||
resolution: {integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
ms@2.0.0:
|
||||
resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==}
|
||||
|
||||
ms@2.1.3:
|
||||
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
|
||||
|
||||
@@ -1532,6 +1687,10 @@ packages:
|
||||
resolution: {integrity: sha512-p2cfF+B3XXacQdswUYWZ0w6Vld0832A/tuqjLBu3H1sfUcby4N2oVbGhyuCkZv+t3iY3aiFEj7gZGqax9Q2c1w==}
|
||||
engines: {node: '>= 0.4.0'}
|
||||
|
||||
negotiator@0.6.4:
|
||||
resolution: {integrity: sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==}
|
||||
engines: {node: '>= 0.6'}
|
||||
|
||||
node-releases@2.0.27:
|
||||
resolution: {integrity: sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==}
|
||||
|
||||
@@ -1539,12 +1698,24 @@ packages:
|
||||
resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
npm-run-path@4.0.1:
|
||||
resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
nth-check@2.1.1:
|
||||
resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==}
|
||||
|
||||
obug@2.1.1:
|
||||
resolution: {integrity: sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==}
|
||||
|
||||
on-headers@1.1.0:
|
||||
resolution: {integrity: sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==}
|
||||
engines: {node: '>= 0.8'}
|
||||
|
||||
onetime@5.1.2:
|
||||
resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
optionator@0.9.4:
|
||||
resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==}
|
||||
engines: {node: '>= 0.8.0'}
|
||||
@@ -1569,10 +1740,16 @@ packages:
|
||||
resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
path-is-inside@1.0.2:
|
||||
resolution: {integrity: sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w==}
|
||||
|
||||
path-key@3.1.1:
|
||||
resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
path-to-regexp@3.3.0:
|
||||
resolution: {integrity: sha512-qyCH421YQPS2WFDxDjftfc1ZR5WKQzVzqsp4n9M2kQhVOo/ByahFoUNJfl58kOcEGfQ//7weFTDhm+ss8Ecxgw==}
|
||||
|
||||
path-type@4.0.0:
|
||||
resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==}
|
||||
engines: {node: '>=8'}
|
||||
@@ -1805,10 +1982,25 @@ packages:
|
||||
queue-microtask@1.2.3:
|
||||
resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
|
||||
|
||||
range-parser@1.2.0:
|
||||
resolution: {integrity: sha512-kA5WQoNVo4t9lNx2kQNFCxKeBl5IbbSNBl1M/tLkw9WCn+hxNBAW5Qh8gdhs63CJnhjJ2zQWFoqPJP2sK1AV5A==}
|
||||
engines: {node: '>= 0.6'}
|
||||
|
||||
rc@1.2.8:
|
||||
resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==}
|
||||
hasBin: true
|
||||
|
||||
readdirp@4.1.2:
|
||||
resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==}
|
||||
engines: {node: '>= 14.18.0'}
|
||||
|
||||
registry-auth-token@3.3.2:
|
||||
resolution: {integrity: sha512-JL39c60XlzCVgNrO+qq68FoNb56w/m7JYvGR2jT5iR1xBrUA3Mfx5Twk5rqTThPmQKMWydGmq8oFtDlxfrmxnQ==}
|
||||
|
||||
registry-url@3.1.0:
|
||||
resolution: {integrity: sha512-ZbgR5aZEdf4UKZVBPYIgaglBmSF2Hi94s2PcIHhRGFjKYu+chjJdYfHn4rt3hB6eCKLJ8giVIIfgMa1ehDfZKA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
require-directory@2.1.1:
|
||||
resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@@ -1837,6 +2029,9 @@ packages:
|
||||
resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
safe-buffer@5.2.1:
|
||||
resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
|
||||
|
||||
secure-keys@1.0.0:
|
||||
resolution: {integrity: sha512-nZi59hW3Sl5P3+wOO89eHBAAGwmCPd2aE1+dLZV5MO+ItQctIvAqihzaAXIQhvtH4KJPxM080HsnqltR2y8cWg==}
|
||||
|
||||
@@ -1845,6 +2040,14 @@ packages:
|
||||
engines: {node: '>=10'}
|
||||
hasBin: true
|
||||
|
||||
serve-handler@6.1.6:
|
||||
resolution: {integrity: sha512-x5RL9Y2p5+Sh3D38Fh9i/iQ5ZK+e4xuXRd/pGbM4D13tgo/MGwbttUk8emytcr1YYzBYs+apnUngBDFYfpjPuQ==}
|
||||
|
||||
serve@14.2.5:
|
||||
resolution: {integrity: sha512-Qn/qMkzCcMFVPb60E/hQy+iRLpiU8PamOfOSYoAHmmF+fFFmpPpqa6Oci2iWYpTdOUM3VF+TINud7CfbQnsZbA==}
|
||||
engines: {node: '>= 14'}
|
||||
hasBin: true
|
||||
|
||||
set-cookie-parser@3.0.1:
|
||||
resolution: {integrity: sha512-n7Z7dXZhJbwuAHhNzkTti6Aw9QDDjZtm3JTpTGATIdNzdQz5GuFs22w90BcvF4INfnrL5xrX3oGsuqO5Dx3A1Q==}
|
||||
|
||||
@@ -1856,6 +2059,9 @@ packages:
|
||||
resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
signal-exit@3.0.7:
|
||||
resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==}
|
||||
|
||||
signal-exit@4.1.0:
|
||||
resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
|
||||
engines: {node: '>=14'}
|
||||
@@ -1891,6 +2097,10 @@ packages:
|
||||
resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
string-width@5.1.2:
|
||||
resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
string-width@8.1.1:
|
||||
resolution: {integrity: sha512-KpqHIdDL9KwYk22wEOg/VIqYbrnLeSApsKT/bSj6Ez7pn3CftUiLAv2Lccpq1ALcpLV9UX1Ppn92npZWu2w/aw==}
|
||||
engines: {node: '>=20'}
|
||||
@@ -1903,6 +2113,14 @@ packages:
|
||||
resolution: {integrity: sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
strip-final-newline@2.0.0:
|
||||
resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
strip-json-comments@2.0.1:
|
||||
resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
stylelint-config-recommended@18.0.0:
|
||||
resolution: {integrity: sha512-mxgT2XY6YZ3HWWe3Di8umG6aBmWmHTblTgu/f10rqFXnyWxjKWwNdjSWkgkwCtxIKnqjSJzvFmPT5yabVIRxZg==}
|
||||
engines: {node: '>=20.19.0'}
|
||||
@@ -1924,6 +2142,10 @@ packages:
|
||||
resolution: {integrity: sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
supports-color@7.2.0:
|
||||
resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
supports-hyperlinks@4.4.0:
|
||||
resolution: {integrity: sha512-UKbpT93hN5Nr9go5UY7bopIB9YQlMz9nm/ct4IXt/irb5YRkn9WaqrOBJGZ5Pwvsd5FQzSVeYlGdXoCAPQZrPg==}
|
||||
engines: {node: '>=20'}
|
||||
@@ -1974,6 +2196,10 @@ packages:
|
||||
resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==}
|
||||
engines: {node: '>= 0.8.0'}
|
||||
|
||||
type-fest@2.19.0:
|
||||
resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==}
|
||||
engines: {node: '>=12.20'}
|
||||
|
||||
typescript-eslint@8.55.0:
|
||||
resolution: {integrity: sha512-HE4wj+r5lmDVS9gdaN0/+iqNvPZwGfnJ5lZuz7s5vLlg9ODw0bIiiETaios9LvFI1U94/VBXGm3CB2Y5cNFMpw==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
@@ -1996,12 +2222,19 @@ packages:
|
||||
peerDependencies:
|
||||
browserslist: '>= 4.21.0'
|
||||
|
||||
update-check@1.5.4:
|
||||
resolution: {integrity: sha512-5YHsflzHP4t1G+8WGPlvKbJEbAJGCgw+Em+dGR1KmBUbr1J36SJBqlHLjR7oob7sco5hWHGQVcr9B2poIVDDTQ==}
|
||||
|
||||
uri-js@4.4.1:
|
||||
resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
|
||||
|
||||
util-deprecate@1.0.2:
|
||||
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
|
||||
|
||||
vary@1.1.2:
|
||||
resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==}
|
||||
engines: {node: '>= 0.8'}
|
||||
|
||||
vite@7.3.1:
|
||||
resolution: {integrity: sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
@@ -2059,6 +2292,10 @@ packages:
|
||||
engines: {node: '>= 8'}
|
||||
hasBin: true
|
||||
|
||||
widest-line@4.0.1:
|
||||
resolution: {integrity: sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
word-wrap@1.2.5:
|
||||
resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@@ -2067,6 +2304,10 @@ packages:
|
||||
resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
wrap-ansi@8.1.0:
|
||||
resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
write-file-atomic@7.0.0:
|
||||
resolution: {integrity: sha512-YnlPC6JqnZl6aO4uRc+dx5PHguiR9S6WeoLtpxNT9wIG+BDya7ZNE1q7KOjVgaA73hKhKLpVPgJ5QA9THQ5BRg==}
|
||||
engines: {node: ^20.17.0 || >=22.9.0}
|
||||
@@ -2830,6 +3071,8 @@ snapshots:
|
||||
'@typescript-eslint/types': 8.55.0
|
||||
eslint-visitor-keys: 4.2.1
|
||||
|
||||
'@zeit/schemas@2.36.0': {}
|
||||
|
||||
acorn-jsx@5.3.2(acorn@8.15.0):
|
||||
dependencies:
|
||||
acorn: 8.15.0
|
||||
@@ -2843,6 +3086,13 @@ snapshots:
|
||||
json-schema-traverse: 0.4.1
|
||||
uri-js: 4.4.1
|
||||
|
||||
ajv@8.12.0:
|
||||
dependencies:
|
||||
fast-deep-equal: 3.1.3
|
||||
json-schema-traverse: 1.0.0
|
||||
require-from-string: 2.0.2
|
||||
uri-js: 4.4.1
|
||||
|
||||
ajv@8.17.1:
|
||||
dependencies:
|
||||
fast-deep-equal: 3.1.3
|
||||
@@ -2850,6 +3100,10 @@ snapshots:
|
||||
json-schema-traverse: 1.0.0
|
||||
require-from-string: 2.0.2
|
||||
|
||||
ansi-align@3.0.1:
|
||||
dependencies:
|
||||
string-width: 4.2.3
|
||||
|
||||
ansi-regex@5.0.1: {}
|
||||
|
||||
ansi-regex@6.2.2: {}
|
||||
@@ -2858,6 +3112,12 @@ snapshots:
|
||||
dependencies:
|
||||
color-convert: 2.0.1
|
||||
|
||||
ansi-styles@6.2.3: {}
|
||||
|
||||
arch@2.2.0: {}
|
||||
|
||||
arg@5.0.2: {}
|
||||
|
||||
argparse@2.0.1: {}
|
||||
|
||||
aria-query@5.3.2: {}
|
||||
@@ -2903,6 +3163,22 @@ snapshots:
|
||||
|
||||
boolbase@1.0.0: {}
|
||||
|
||||
boxen@7.0.0:
|
||||
dependencies:
|
||||
ansi-align: 3.0.1
|
||||
camelcase: 7.0.1
|
||||
chalk: 5.0.1
|
||||
cli-boxes: 3.0.0
|
||||
string-width: 5.1.2
|
||||
type-fest: 2.19.0
|
||||
widest-line: 4.0.1
|
||||
wrap-ansi: 8.1.0
|
||||
|
||||
brace-expansion@1.1.12:
|
||||
dependencies:
|
||||
balanced-match: 1.0.2
|
||||
concat-map: 0.0.1
|
||||
|
||||
brace-expansion@2.0.2:
|
||||
dependencies:
|
||||
balanced-match: 1.0.2
|
||||
@@ -2925,6 +3201,10 @@ snapshots:
|
||||
|
||||
buffer-from@1.1.2: {}
|
||||
|
||||
bytes@3.0.0: {}
|
||||
|
||||
bytes@3.1.2: {}
|
||||
|
||||
cacheable@2.3.2:
|
||||
dependencies:
|
||||
'@cacheable/memory': 2.0.7
|
||||
@@ -2935,12 +3215,33 @@ snapshots:
|
||||
|
||||
callsites@3.1.0: {}
|
||||
|
||||
camelcase@7.0.1: {}
|
||||
|
||||
caniuse-lite@1.0.30001770: {}
|
||||
|
||||
chalk-template@0.4.0:
|
||||
dependencies:
|
||||
chalk: 4.1.2
|
||||
|
||||
chalk@4.1.2:
|
||||
dependencies:
|
||||
ansi-styles: 4.3.0
|
||||
supports-color: 7.2.0
|
||||
|
||||
chalk@5.0.1: {}
|
||||
|
||||
chokidar@4.0.3:
|
||||
dependencies:
|
||||
readdirp: 4.1.2
|
||||
|
||||
cli-boxes@3.0.0: {}
|
||||
|
||||
clipboardy@3.0.0:
|
||||
dependencies:
|
||||
arch: 2.2.0
|
||||
execa: 5.1.1
|
||||
is-wsl: 2.2.0
|
||||
|
||||
cliui@7.0.4:
|
||||
dependencies:
|
||||
string-width: 4.2.3
|
||||
@@ -2959,8 +3260,28 @@ snapshots:
|
||||
|
||||
commander@2.20.3: {}
|
||||
|
||||
compressible@2.0.18:
|
||||
dependencies:
|
||||
mime-db: 1.54.0
|
||||
|
||||
compression@1.8.1:
|
||||
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
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
concat-map@0.0.1: {}
|
||||
|
||||
consola@2.15.3: {}
|
||||
|
||||
content-disposition@0.5.2: {}
|
||||
|
||||
cookie@0.6.0: {}
|
||||
|
||||
cosmiconfig@9.0.0(typescript@5.9.3):
|
||||
@@ -3015,10 +3336,16 @@ snapshots:
|
||||
|
||||
cssesc@3.0.0: {}
|
||||
|
||||
debug@2.6.9:
|
||||
dependencies:
|
||||
ms: 2.0.0
|
||||
|
||||
debug@4.4.3:
|
||||
dependencies:
|
||||
ms: 2.1.3
|
||||
|
||||
deep-extend@0.6.0: {}
|
||||
|
||||
deep-is@0.1.4: {}
|
||||
|
||||
deepmerge@4.3.1: {}
|
||||
@@ -3047,10 +3374,14 @@ snapshots:
|
||||
domelementtype: 2.3.0
|
||||
domhandler: 5.0.3
|
||||
|
||||
eastasianwidth@0.2.0: {}
|
||||
|
||||
electron-to-chromium@1.5.286: {}
|
||||
|
||||
emoji-regex@8.0.0: {}
|
||||
|
||||
emoji-regex@9.2.2: {}
|
||||
|
||||
entities@4.5.0: {}
|
||||
|
||||
entities@7.0.1: {}
|
||||
@@ -3170,6 +3501,18 @@ snapshots:
|
||||
|
||||
esutils@2.0.3: {}
|
||||
|
||||
execa@5.1.1:
|
||||
dependencies:
|
||||
cross-spawn: 7.0.6
|
||||
get-stream: 6.0.1
|
||||
human-signals: 2.1.0
|
||||
is-stream: 2.0.1
|
||||
merge-stream: 2.0.0
|
||||
npm-run-path: 4.0.1
|
||||
onetime: 5.1.2
|
||||
signal-exit: 3.0.7
|
||||
strip-final-newline: 2.0.0
|
||||
|
||||
fast-deep-equal@3.1.3: {}
|
||||
|
||||
fast-glob@3.3.3:
|
||||
@@ -3235,6 +3578,8 @@ snapshots:
|
||||
|
||||
get-east-asian-width@1.4.0: {}
|
||||
|
||||
get-stream@6.0.1: {}
|
||||
|
||||
glob-parent@5.1.2:
|
||||
dependencies:
|
||||
is-glob: 4.0.3
|
||||
@@ -3273,6 +3618,8 @@ snapshots:
|
||||
|
||||
globjoin@0.1.4: {}
|
||||
|
||||
has-flag@4.0.0: {}
|
||||
|
||||
has-flag@5.0.1: {}
|
||||
|
||||
hashery@1.4.0:
|
||||
@@ -3290,6 +3637,8 @@ snapshots:
|
||||
domutils: 3.2.2
|
||||
entities: 7.0.1
|
||||
|
||||
human-signals@2.1.0: {}
|
||||
|
||||
ignore@5.3.2: {}
|
||||
|
||||
ignore@7.0.5: {}
|
||||
@@ -3309,6 +3658,8 @@ snapshots:
|
||||
|
||||
is-arrayish@0.2.1: {}
|
||||
|
||||
is-docker@2.2.1: {}
|
||||
|
||||
is-extglob@2.1.1: {}
|
||||
|
||||
is-fullwidth-code-point@3.0.0: {}
|
||||
@@ -3323,10 +3674,18 @@ snapshots:
|
||||
|
||||
is-plain-object@5.0.0: {}
|
||||
|
||||
is-port-reachable@4.0.0: {}
|
||||
|
||||
is-reference@3.0.3:
|
||||
dependencies:
|
||||
'@types/estree': 1.0.8
|
||||
|
||||
is-stream@2.0.1: {}
|
||||
|
||||
is-wsl@2.2.0:
|
||||
dependencies:
|
||||
is-docker: 2.2.1
|
||||
|
||||
isexe@2.0.0: {}
|
||||
|
||||
jackspeak@4.2.3:
|
||||
@@ -3390,6 +3749,8 @@ snapshots:
|
||||
|
||||
meow@14.0.0: {}
|
||||
|
||||
merge-stream@2.0.0: {}
|
||||
|
||||
merge2@1.4.1: {}
|
||||
|
||||
micromatch@4.0.8:
|
||||
@@ -3397,18 +3758,36 @@ snapshots:
|
||||
braces: 3.0.3
|
||||
picomatch: 2.3.1
|
||||
|
||||
mime-db@1.33.0: {}
|
||||
|
||||
mime-db@1.54.0: {}
|
||||
|
||||
mime-types@2.1.18:
|
||||
dependencies:
|
||||
mime-db: 1.33.0
|
||||
|
||||
mimic-fn@2.1.0: {}
|
||||
|
||||
minimatch@10.2.0:
|
||||
dependencies:
|
||||
brace-expansion: 5.0.2
|
||||
|
||||
minimatch@3.1.2:
|
||||
dependencies:
|
||||
brace-expansion: 1.1.12
|
||||
|
||||
minimatch@9.0.5:
|
||||
dependencies:
|
||||
brace-expansion: 2.0.2
|
||||
|
||||
minimist@1.2.8: {}
|
||||
|
||||
mri@1.2.0: {}
|
||||
|
||||
mrmime@2.0.1: {}
|
||||
|
||||
ms@2.0.0: {}
|
||||
|
||||
ms@2.1.3: {}
|
||||
|
||||
nanoid@3.3.11: {}
|
||||
@@ -3422,16 +3801,28 @@ snapshots:
|
||||
secure-keys: 1.0.0
|
||||
yargs: 16.2.0
|
||||
|
||||
negotiator@0.6.4: {}
|
||||
|
||||
node-releases@2.0.27: {}
|
||||
|
||||
normalize-path@3.0.0: {}
|
||||
|
||||
npm-run-path@4.0.1:
|
||||
dependencies:
|
||||
path-key: 3.1.1
|
||||
|
||||
nth-check@2.1.1:
|
||||
dependencies:
|
||||
boolbase: 1.0.0
|
||||
|
||||
obug@2.1.1: {}
|
||||
|
||||
on-headers@1.1.0: {}
|
||||
|
||||
onetime@5.1.2:
|
||||
dependencies:
|
||||
mimic-fn: 2.1.0
|
||||
|
||||
optionator@0.9.4:
|
||||
dependencies:
|
||||
deep-is: 0.1.4
|
||||
@@ -3462,8 +3853,12 @@ snapshots:
|
||||
|
||||
path-exists@4.0.0: {}
|
||||
|
||||
path-is-inside@1.0.2: {}
|
||||
|
||||
path-key@3.1.1: {}
|
||||
|
||||
path-to-regexp@3.3.0: {}
|
||||
|
||||
path-type@4.0.0: {}
|
||||
|
||||
picocolors@1.1.1: {}
|
||||
@@ -3735,8 +4130,26 @@ snapshots:
|
||||
|
||||
queue-microtask@1.2.3: {}
|
||||
|
||||
range-parser@1.2.0: {}
|
||||
|
||||
rc@1.2.8:
|
||||
dependencies:
|
||||
deep-extend: 0.6.0
|
||||
ini: 1.3.8
|
||||
minimist: 1.2.8
|
||||
strip-json-comments: 2.0.1
|
||||
|
||||
readdirp@4.1.2: {}
|
||||
|
||||
registry-auth-token@3.3.2:
|
||||
dependencies:
|
||||
rc: 1.2.8
|
||||
safe-buffer: 5.2.1
|
||||
|
||||
registry-url@3.1.0:
|
||||
dependencies:
|
||||
rc: 1.2.8
|
||||
|
||||
require-directory@2.1.1: {}
|
||||
|
||||
require-from-string@2.0.2: {}
|
||||
@@ -3784,10 +4197,38 @@ snapshots:
|
||||
dependencies:
|
||||
mri: 1.2.0
|
||||
|
||||
safe-buffer@5.2.1: {}
|
||||
|
||||
secure-keys@1.0.0: {}
|
||||
|
||||
semver@7.7.4: {}
|
||||
|
||||
serve-handler@6.1.6:
|
||||
dependencies:
|
||||
bytes: 3.0.0
|
||||
content-disposition: 0.5.2
|
||||
mime-types: 2.1.18
|
||||
minimatch: 3.1.2
|
||||
path-is-inside: 1.0.2
|
||||
path-to-regexp: 3.3.0
|
||||
range-parser: 1.2.0
|
||||
|
||||
serve@14.2.5:
|
||||
dependencies:
|
||||
'@zeit/schemas': 2.36.0
|
||||
ajv: 8.12.0
|
||||
arg: 5.0.2
|
||||
boxen: 7.0.0
|
||||
chalk: 5.0.1
|
||||
chalk-template: 0.4.0
|
||||
clipboardy: 3.0.0
|
||||
compression: 1.8.1
|
||||
is-port-reachable: 4.0.0
|
||||
serve-handler: 6.1.6
|
||||
update-check: 1.5.4
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
set-cookie-parser@3.0.1: {}
|
||||
|
||||
shebang-command@2.0.0:
|
||||
@@ -3796,6 +4237,8 @@ snapshots:
|
||||
|
||||
shebang-regex@3.0.0: {}
|
||||
|
||||
signal-exit@3.0.7: {}
|
||||
|
||||
signal-exit@4.1.0: {}
|
||||
|
||||
sirv@3.0.2:
|
||||
@@ -3829,6 +4272,12 @@ snapshots:
|
||||
is-fullwidth-code-point: 3.0.0
|
||||
strip-ansi: 6.0.1
|
||||
|
||||
string-width@5.1.2:
|
||||
dependencies:
|
||||
eastasianwidth: 0.2.0
|
||||
emoji-regex: 9.2.2
|
||||
strip-ansi: 7.1.2
|
||||
|
||||
string-width@8.1.1:
|
||||
dependencies:
|
||||
get-east-asian-width: 1.4.0
|
||||
@@ -3842,6 +4291,10 @@ snapshots:
|
||||
dependencies:
|
||||
ansi-regex: 6.2.2
|
||||
|
||||
strip-final-newline@2.0.0: {}
|
||||
|
||||
strip-json-comments@2.0.1: {}
|
||||
|
||||
stylelint-config-recommended@18.0.0(stylelint@17.3.0(typescript@5.9.3)):
|
||||
dependencies:
|
||||
stylelint: 17.3.0(typescript@5.9.3)
|
||||
@@ -3898,6 +4351,10 @@ snapshots:
|
||||
|
||||
supports-color@10.2.2: {}
|
||||
|
||||
supports-color@7.2.0:
|
||||
dependencies:
|
||||
has-flag: 4.0.0
|
||||
|
||||
supports-hyperlinks@4.4.0:
|
||||
dependencies:
|
||||
has-flag: 5.0.1
|
||||
@@ -3970,6 +4427,8 @@ snapshots:
|
||||
dependencies:
|
||||
prelude-ls: 1.2.1
|
||||
|
||||
type-fest@2.19.0: {}
|
||||
|
||||
typescript-eslint@8.55.0(eslint@10.0.0)(typescript@5.9.3):
|
||||
dependencies:
|
||||
'@typescript-eslint/eslint-plugin': 8.55.0(@typescript-eslint/parser@8.55.0(eslint@10.0.0)(typescript@5.9.3))(eslint@10.0.0)(typescript@5.9.3)
|
||||
@@ -3991,12 +4450,19 @@ snapshots:
|
||||
escalade: 3.2.0
|
||||
picocolors: 1.1.1
|
||||
|
||||
update-check@1.5.4:
|
||||
dependencies:
|
||||
registry-auth-token: 3.3.2
|
||||
registry-url: 3.1.0
|
||||
|
||||
uri-js@4.4.1:
|
||||
dependencies:
|
||||
punycode: 2.3.1
|
||||
|
||||
util-deprecate@1.0.2: {}
|
||||
|
||||
vary@1.1.2: {}
|
||||
|
||||
vite@7.3.1(terser@5.46.0):
|
||||
dependencies:
|
||||
esbuild: 0.27.3
|
||||
@@ -4021,6 +4487,10 @@ snapshots:
|
||||
dependencies:
|
||||
isexe: 2.0.0
|
||||
|
||||
widest-line@4.0.1:
|
||||
dependencies:
|
||||
string-width: 5.1.2
|
||||
|
||||
word-wrap@1.2.5: {}
|
||||
|
||||
wrap-ansi@7.0.0:
|
||||
@@ -4029,6 +4499,12 @@ snapshots:
|
||||
string-width: 4.2.3
|
||||
strip-ansi: 6.0.1
|
||||
|
||||
wrap-ansi@8.1.0:
|
||||
dependencies:
|
||||
ansi-styles: 6.2.3
|
||||
string-width: 5.1.2
|
||||
strip-ansi: 7.1.2
|
||||
|
||||
write-file-atomic@7.0.0:
|
||||
dependencies:
|
||||
imurmurhash: 0.1.4
|
||||
|
||||
@@ -22,8 +22,10 @@ function getFiles(dir, ext, files = []) {
|
||||
const beasties = new Beasties({
|
||||
path: buildDir,
|
||||
preload: 'default',
|
||||
logLevel: 'warn'
|
||||
});
|
||||
logLevel: 'warn',
|
||||
inlineThreshold: 50 * 1024, // inline any stylesheet < 50KB
|
||||
minimumExternalSize: 50 * 1024 // inline any leftover < 50KB
|
||||
});
|
||||
|
||||
async function main() {
|
||||
const htmlFiles = getFiles(buildDir, '.html');
|
||||
|
||||
60
src/app.css
@@ -44,6 +44,66 @@ body {
|
||||
color: var(--fg);
|
||||
}
|
||||
|
||||
/* Lightbox (structure may be created by script.js; ensures styles apply to injected content) */
|
||||
.lightbox {
|
||||
align-items: stretch;
|
||||
background: var(--surface-elevated);
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
box-shadow: var(--lightbox-shadow);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5rem;
|
||||
justify-content: center;
|
||||
max-width: 90vw;
|
||||
padding: 0.5rem 1rem;
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s;
|
||||
}
|
||||
|
||||
.lightbox::backdrop {
|
||||
background: var(--lightbox-backdrop);
|
||||
}
|
||||
|
||||
.lightbox[open] {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.lightbox header {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
padding: 0.25rem 0.25rem 0 0;
|
||||
}
|
||||
|
||||
.lightbox .lb-close {
|
||||
background: none;
|
||||
border: none;
|
||||
font-size: 2rem;
|
||||
color: var(--fg);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.lightbox .lb-content {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.lightbox .lb-content img,
|
||||
.lightbox .lb-content video {
|
||||
max-width: 90vw;
|
||||
max-height: 80vh;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.lightbox .lb-caption {
|
||||
color: var(--fg);
|
||||
margin-top: 0.5rem;
|
||||
text-align: center;
|
||||
max-width: 90vw;
|
||||
}
|
||||
|
||||
.lightbox-open {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
@@ -4,25 +4,18 @@
|
||||
interface Props {
|
||||
index?: number;
|
||||
item: MediaItem;
|
||||
showLightbox: (item: MediaItem) => void;
|
||||
}
|
||||
|
||||
let { item, index, showLightbox }: Props = $props();
|
||||
let { item, index }: Props = $props();
|
||||
</script>
|
||||
|
||||
<button
|
||||
class={`gallery-item ${item.type === 'video' ? ' video' : ''}`}
|
||||
type="button"
|
||||
tabindex="0"
|
||||
data-name={item.name}
|
||||
data-type={item.type}
|
||||
data-caption={item.caption}
|
||||
onclick={() => showLightbox(item)}
|
||||
onkeydown={(e) => {
|
||||
if (e.key === 'Enter' || e.key === ' ') {
|
||||
e.preventDefault();
|
||||
showLightbox(item);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<figure>
|
||||
<picture>
|
||||
|
||||
@@ -1,77 +1,20 @@
|
||||
<script lang="ts">
|
||||
import type { MediaItem } from '$lib/media';
|
||||
|
||||
interface Props {
|
||||
item: MediaItem | null;
|
||||
onClose: () => void;
|
||||
}
|
||||
|
||||
let { item, onClose }: Props = $props();
|
||||
|
||||
let ref = $state<HTMLDialogElement | null>(null);
|
||||
|
||||
$effect(() => {
|
||||
if (ref && item) {
|
||||
document.body.style.overflow = 'hidden';
|
||||
ref.showModal();
|
||||
} else {
|
||||
document.body.style.overflow = 'auto';
|
||||
ref?.close();
|
||||
}
|
||||
});
|
||||
/**
|
||||
* Structure-only lightbox shell. Content is injected by static/assets/js/script.js
|
||||
* (no client-side Svelte; csr = false). Keeps HTML/CSS in one place.
|
||||
*/
|
||||
</script>
|
||||
|
||||
<dialog
|
||||
class="lightbox"
|
||||
aria-hidden="true"
|
||||
onclose={onClose}
|
||||
closedby="any"
|
||||
aria-describedby="lb-caption"
|
||||
bind:this={ref}
|
||||
>
|
||||
{#if item}
|
||||
<header>
|
||||
<button
|
||||
class="lb-close"
|
||||
aria-label="Close"
|
||||
onclick={() => ref?.close()}
|
||||
onkeydown={(e) => {
|
||||
if (e.key === 'Enter') ref?.close();
|
||||
}}>×</button
|
||||
>
|
||||
</header>
|
||||
<div class="lb-content">
|
||||
{#if item?.type === 'video'}
|
||||
<video
|
||||
src={`/assets/media/videos/${item?.name}.mp4`}
|
||||
controls
|
||||
autoplay
|
||||
>
|
||||
<track
|
||||
kind="captions"
|
||||
src={`/assets/media/videos/${item?.name}-captions.vtt`}
|
||||
default
|
||||
/>
|
||||
</video>
|
||||
{:else}
|
||||
<picture>
|
||||
{#each [{ bp: 'desktop', minWidth: 1024 }, { bp: 'tablet', minWidth: 768 }, { bp: 'mobile', minWidth: 0 }] as breakpoint}
|
||||
<source
|
||||
media="(min-width:{breakpoint.minWidth}px)"
|
||||
srcset={item?.type === 'image'
|
||||
? `/assets/media/${breakpoint.bp}/${item?.name}@1x.webp 1x, /assets/media/${breakpoint.bp}/${item?.name}.webp 2x`
|
||||
: `/assets/media/${breakpoint.bp}/${item?.name}_still@1x.webp 1x, /assets/media/${breakpoint.bp}/${item?.name}_still.webp 2x`}
|
||||
/>
|
||||
{/each}
|
||||
<img
|
||||
src="/assets/media/thumbnail/{item?.name}.webp"
|
||||
alt={item?.alt.replace(/['']/g, '')}
|
||||
/>
|
||||
</picture>
|
||||
{/if}
|
||||
</div>
|
||||
<p id="lb-caption" class="lb-caption">{item?.caption}</p>
|
||||
{/if}
|
||||
<dialog class="lightbox" aria-hidden="true" aria-describedby="lb-caption" closedby="any">
|
||||
<header>
|
||||
<button type="button" class="lb-close" aria-label="Close"
|
||||
>×</button
|
||||
>
|
||||
</header>
|
||||
<div class="lb-content">
|
||||
<!-- script.js injects image or video here -->
|
||||
</div>
|
||||
<p id="lb-caption" class="lb-caption"></p>
|
||||
</dialog>
|
||||
|
||||
<style>
|
||||
@@ -98,8 +41,9 @@
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
& img,
|
||||
& video {
|
||||
/* Injected by script.js */
|
||||
:global(img),
|
||||
:global(video) {
|
||||
max-width: 90vw;
|
||||
max-height: 80vh;
|
||||
border-radius: 8px;
|
||||
@@ -117,6 +61,7 @@
|
||||
border: none;
|
||||
font-size: 2rem;
|
||||
color: var(--fg);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.lb-content {
|
||||
@@ -125,7 +70,8 @@
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
& img {
|
||||
/* Injected by script.js */
|
||||
:global(img) {
|
||||
max-width: 90vw;
|
||||
max-height: 80vh;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<script lang="ts">
|
||||
import { theme } from '$lib/stores/theme.svelte.js';
|
||||
|
||||
const toggleTheme = () => {
|
||||
theme.set(theme.get() === 'light' ? 'dark' : 'light');
|
||||
};
|
||||
interface Props {
|
||||
/** Caption for the tour video (used by script.js for lightbox); from media data */
|
||||
tourCaption?: string;
|
||||
}
|
||||
let { tourCaption }: Props = $props();
|
||||
</script>
|
||||
|
||||
<header class="site-header">
|
||||
@@ -13,6 +13,9 @@
|
||||
id="show_video"
|
||||
class="emoji-button"
|
||||
aria-label="Show video tour"
|
||||
data-name="tour"
|
||||
data-type="video"
|
||||
data-caption={tourCaption}
|
||||
>
|
||||
🎥
|
||||
</button>
|
||||
@@ -20,7 +23,6 @@
|
||||
id="theme-toggle"
|
||||
class="emoji-button"
|
||||
aria-label="Toggle light/dark theme"
|
||||
onclick={toggleTheme}
|
||||
>
|
||||
🌓
|
||||
</button>
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
export const prerender = true;
|
||||
export const ssr = true;
|
||||
export const csr = false;
|
||||
|
||||
@@ -29,16 +29,6 @@
|
||||
addressCountry: 'US',
|
||||
},
|
||||
};
|
||||
|
||||
let showPicture = $state<MediaItem | null>(null);
|
||||
|
||||
const showLightbox = (item: MediaItem) => {
|
||||
showPicture = item;
|
||||
};
|
||||
|
||||
const onClose = () => {
|
||||
showPicture = null;
|
||||
};
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
@@ -77,12 +67,14 @@
|
||||
{@html `<script type="application/ld+json">${JSON.stringify(jsonLd)}</script>`}
|
||||
</svelte:head>
|
||||
|
||||
<SiteHeader />
|
||||
<SiteHeader
|
||||
tourCaption={data.mediaItems.find((m) => m.name === 'tour')?.caption}
|
||||
/>
|
||||
<main>
|
||||
<section id="gallery" class="gallery-grid">
|
||||
{#each data.mediaItems as item, index (item.name)}
|
||||
<GalleryFigure {item} {index} {showLightbox} />
|
||||
<GalleryFigure {item} {index} />
|
||||
{/each}
|
||||
</section>
|
||||
</main>
|
||||
<Lightbox item={showPicture} {onClose} />
|
||||
<Lightbox />
|
||||
|
||||
@@ -11,3 +11,108 @@ if (saved) {
|
||||
root.setAttribute('data-theme', 'light');
|
||||
}
|
||||
}
|
||||
|
||||
// Theme toggle
|
||||
const themeToggle = document.getElementById('theme-toggle');
|
||||
if (themeToggle) {
|
||||
themeToggle.addEventListener('click', () => {
|
||||
const current = root.getAttribute('data-theme') || 'light';
|
||||
const next = current === 'light' ? 'dark' : 'light';
|
||||
root.setAttribute('data-theme', next);
|
||||
try {
|
||||
localStorage.setItem('theme', next);
|
||||
} catch (_) {}
|
||||
});
|
||||
}
|
||||
|
||||
// Lightbox (structure from Lightbox.svelte; we fill content and handle open/close)
|
||||
const dialog = document.querySelector('dialog.lightbox');
|
||||
const lbContent = dialog?.querySelector('.lb-content');
|
||||
const lbCaption = dialog?.querySelector('#lb-caption, .lb-caption');
|
||||
|
||||
function openLightbox(name, type, caption) {
|
||||
if (!dialog || !lbContent || !lbCaption) return;
|
||||
document.body.style.overflow = 'hidden';
|
||||
|
||||
if (type === 'video') {
|
||||
lbContent.innerHTML = `<video src="/assets/media/videos/${name}.mp4" controls autoplay><track kind="captions" src="/assets/media/videos/${name}-captions.vtt" default></video>`;
|
||||
} else {
|
||||
const srcset = (bp) =>
|
||||
type === 'image'
|
||||
? `/assets/media/${bp}/${name}@1x.webp 1x, /assets/media/${bp}/${name}.webp 2x`
|
||||
: `/assets/media/${bp}/${name}_still@1x.webp 1x, /assets/media/${bp}/${name}_still.webp 2x`;
|
||||
lbContent.innerHTML = `<picture>
|
||||
<source media="(min-width:1024px)" srcset="${srcset('desktop')}">
|
||||
<source media="(min-width:768px)" srcset="${srcset('tablet')}">
|
||||
<source media="(min-width:0px)" srcset="${srcset('mobile')}">
|
||||
<img src="/assets/media/thumbnail/${name}.webp" alt="">
|
||||
</picture>`;
|
||||
}
|
||||
lbCaption.textContent = caption || '';
|
||||
dialog.setAttribute('aria-hidden', 'false');
|
||||
dialog.showModal();
|
||||
}
|
||||
|
||||
function closeLightbox() {
|
||||
if (!dialog) return;
|
||||
document.body.style.overflow = '';
|
||||
if (lbContent) lbContent.innerHTML = '';
|
||||
if (lbCaption) lbCaption.textContent = '';
|
||||
dialog.setAttribute('aria-hidden', 'true');
|
||||
dialog.close();
|
||||
}
|
||||
|
||||
if (dialog) {
|
||||
// Add event handlers
|
||||
dialog.querySelector('.lb-close').addEventListener('click', closeLightbox);
|
||||
dialog.querySelector('.lb-close').addEventListener('keydown', (e) => {
|
||||
if (e.key === 'Enter' || e.key === ' ') {
|
||||
e.preventDefault();
|
||||
closeLightbox();
|
||||
}
|
||||
});
|
||||
dialog.addEventListener('close', closeLightbox);
|
||||
dialog.addEventListener('cancel', closeLightbox);
|
||||
dialog.addEventListener('click', () => {
|
||||
if (e.target === dialog) dialog.close();
|
||||
});
|
||||
}
|
||||
|
||||
// Gallery items
|
||||
document.querySelectorAll('.gallery-item[data-name]').forEach((el) => {
|
||||
el.addEventListener('click', () => {
|
||||
const name = el.getAttribute('data-name');
|
||||
const type = el.getAttribute('data-type') || 'image';
|
||||
const caption = el.getAttribute('data-caption') || '';
|
||||
if (name) openLightbox(name, type, caption);
|
||||
});
|
||||
el.addEventListener('keydown', (e) => {
|
||||
if (e.key === 'Enter' || e.key === ' ') {
|
||||
e.preventDefault();
|
||||
const name = el.getAttribute('data-name');
|
||||
const type = el.getAttribute('data-type') || 'image';
|
||||
const caption = el.getAttribute('data-caption') || '';
|
||||
if (name) openLightbox(name, type, caption);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Show video button (open lightbox with tour)
|
||||
const showVideoBtn = document.getElementById('show_video');
|
||||
if (showVideoBtn) {
|
||||
const openTour = () => {
|
||||
const name = showVideoBtn.getAttribute('data-name') || 'tour';
|
||||
const type = showVideoBtn.getAttribute('data-type') || 'video';
|
||||
const caption =
|
||||
showVideoBtn.getAttribute('data-caption') ||
|
||||
"Take the scenic route—explore your the home's highlights with a virtual walkthrough.";
|
||||
openLightbox(name, type, caption);
|
||||
};
|
||||
showVideoBtn.addEventListener('click', openTour);
|
||||
showVideoBtn.addEventListener('keydown', (e) => {
|
||||
if (e.key === 'Enter' || e.key === ' ') {
|
||||
e.preventDefault();
|
||||
openTour();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 1.2 MiB After Width: | Height: | Size: 812 KiB |
|
Before Width: | Height: | Size: 347 KiB After Width: | Height: | Size: 217 KiB |
|
Before Width: | Height: | Size: 826 KiB After Width: | Height: | Size: 452 KiB |
|
Before Width: | Height: | Size: 130 KiB After Width: | Height: | Size: 69 KiB |
|
Before Width: | Height: | Size: 903 KiB After Width: | Height: | Size: 474 KiB |
|
Before Width: | Height: | Size: 146 KiB After Width: | Height: | Size: 86 KiB |
|
Before Width: | Height: | Size: 637 KiB After Width: | Height: | Size: 328 KiB |
|
Before Width: | Height: | Size: 100 KiB After Width: | Height: | Size: 54 KiB |
|
Before Width: | Height: | Size: 630 KiB After Width: | Height: | Size: 372 KiB |
|
Before Width: | Height: | Size: 92 KiB After Width: | Height: | Size: 48 KiB |
|
Before Width: | Height: | Size: 494 KiB After Width: | Height: | Size: 320 KiB |
|
Before Width: | Height: | Size: 135 KiB After Width: | Height: | Size: 90 KiB |
|
Before Width: | Height: | Size: 618 KiB After Width: | Height: | Size: 362 KiB |
|
Before Width: | Height: | Size: 167 KiB After Width: | Height: | Size: 110 KiB |
|
Before Width: | Height: | Size: 294 KiB After Width: | Height: | Size: 188 KiB |
|
Before Width: | Height: | Size: 142 KiB After Width: | Height: | Size: 88 KiB |
|
Before Width: | Height: | Size: 315 KiB After Width: | Height: | Size: 154 KiB |
|
Before Width: | Height: | Size: 85 KiB After Width: | Height: | Size: 51 KiB |
|
Before Width: | Height: | Size: 373 KiB After Width: | Height: | Size: 134 KiB |
|
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 1005 KiB After Width: | Height: | Size: 581 KiB |
|
Before Width: | Height: | Size: 188 KiB After Width: | Height: | Size: 114 KiB |
|
Before Width: | Height: | Size: 538 KiB After Width: | Height: | Size: 261 KiB |
|
Before Width: | Height: | Size: 113 KiB After Width: | Height: | Size: 72 KiB |
|
Before Width: | Height: | Size: 748 KiB After Width: | Height: | Size: 423 KiB |
|
Before Width: | Height: | Size: 144 KiB After Width: | Height: | Size: 89 KiB |
|
Before Width: | Height: | Size: 800 KiB After Width: | Height: | Size: 424 KiB |
|
Before Width: | Height: | Size: 129 KiB After Width: | Height: | Size: 70 KiB |
|
Before Width: | Height: | Size: 770 KiB After Width: | Height: | Size: 362 KiB |
|
Before Width: | Height: | Size: 115 KiB After Width: | Height: | Size: 65 KiB |
|
Before Width: | Height: | Size: 826 KiB After Width: | Height: | Size: 442 KiB |
|
Before Width: | Height: | Size: 126 KiB After Width: | Height: | Size: 70 KiB |
|
Before Width: | Height: | Size: 688 KiB After Width: | Height: | Size: 344 KiB |
|
Before Width: | Height: | Size: 97 KiB After Width: | Height: | Size: 57 KiB |
|
Before Width: | Height: | Size: 423 KiB After Width: | Height: | Size: 204 KiB |
|
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 41 KiB |
|
Before Width: | Height: | Size: 176 KiB After Width: | Height: | Size: 91 KiB |
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 127 KiB After Width: | Height: | Size: 84 KiB |
|
Before Width: | Height: | Size: 59 KiB After Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 96 KiB After Width: | Height: | Size: 60 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 74 KiB After Width: | Height: | Size: 49 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 6.6 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 36 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 60 KiB After Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 8.7 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 9.4 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 8.1 KiB |
|
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 5.6 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 388 KiB After Width: | Height: | Size: 242 KiB |
|
Before Width: | Height: | Size: 102 KiB After Width: | Height: | Size: 63 KiB |
|
Before Width: | Height: | Size: 152 KiB After Width: | Height: | Size: 80 KiB |
|
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 170 KiB After Width: | Height: | Size: 97 KiB |
|
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 116 KiB After Width: | Height: | Size: 61 KiB |
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 102 KiB After Width: | Height: | Size: 55 KiB |
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 150 KiB After Width: | Height: | Size: 100 KiB |
|
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 187 KiB After Width: | Height: | Size: 123 KiB |
|
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 152 KiB After Width: | Height: | Size: 99 KiB |
|
Before Width: | Height: | Size: 60 KiB After Width: | Height: | Size: 39 KiB |
|
Before Width: | Height: | Size: 94 KiB After Width: | Height: | Size: 57 KiB |
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 71 KiB After Width: | Height: | Size: 45 KiB |
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 215 KiB After Width: | Height: | Size: 129 KiB |
|
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 126 KiB After Width: | Height: | Size: 79 KiB |