diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..604feb7 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,75 @@ +# Standard, org-uniform Dependabot configuration template. +# +# Each repo should drop this file at .github/dependabot.yml and uncomment the +# ecosystem entries that apply. Keep weekly cadence so review backlogs stay +# manageable. Auto-assigning all PRs to a single triage owner (@srpatcha) +# prevents the "ten people CC'd, no one acts" failure mode. +# +# Reference template lives at embeddedos-org/.github/.github/dependabot-template.yml. + +version: 2 +updates: + # GitHub Actions — every repo should keep this enabled. + - package-ecosystem: github-actions + directory: / + schedule: + interval: weekly + day: monday + open-pull-requests-limit: 5 + assignees: + - srpatcha + labels: + - dependencies + - github-actions + + # Python — uncomment in repos with pyproject.toml or requirements.txt. + # - package-ecosystem: pip + # directory: / + # schedule: + # interval: weekly + # day: monday + # open-pull-requests-limit: 5 + # assignees: + # - srpatcha + # labels: + # - dependencies + # - python + + # Node.js — uncomment in repos with package.json. + # - package-ecosystem: npm + # directory: / + # schedule: + # interval: weekly + # day: monday + # open-pull-requests-limit: 5 + # assignees: + # - srpatcha + # labels: + # - dependencies + # - npm + + # Go — uncomment in repos with go.mod. + # - package-ecosystem: gomod + # directory: / + # schedule: + # interval: weekly + # day: monday + # open-pull-requests-limit: 5 + # assignees: + # - srpatcha + # labels: + # - dependencies + # - go + + # Docker — uncomment in repos with Dockerfile. + # - package-ecosystem: docker + # directory: / + # schedule: + # interval: weekly + # day: monday + # open-pull-requests-limit: 3 + # assignees: + # - srpatcha + # labels: + # - dependencies + # - docker diff --git a/.github/workflows/health-check.yml b/.github/workflows/health-check.yml new file mode 100644 index 0000000..4c0717d --- /dev/null +++ b/.github/workflows/health-check.yml @@ -0,0 +1,39 @@ +name: health-check + +on: + schedule: + # Weekly — Mondays 06:00 UTC + - cron: '0 6 * * 1' + workflow_dispatch: {} + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: false + +jobs: + linkinator: + name: Crawl live sites for broken links + runs-on: ubuntu-latest + steps: + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version: '20' + + - name: Crawl developer portal + run: | + npx --yes linkinator@6 https://embeddedos-org.github.io \ + --recurse \ + --skip 'github.com|googletagmanager|fonts.googleapis' \ + --timeout 10000 \ + --retry \ + --retry-errors-count 2 + + - name: Crawl org profile + run: | + npx --yes linkinator@6 https://github.com/embeddedos-org \ + --skip 'login|signup|sponsors' \ + --timeout 10000 diff --git a/.github/workflows/lint-readme.yml b/.github/workflows/lint-readme.yml new file mode 100644 index 0000000..d475ac7 --- /dev/null +++ b/.github/workflows/lint-readme.yml @@ -0,0 +1,42 @@ +name: lint-readme + +on: + push: + paths: + - '**/*.md' + pull_request: + paths: + - '**/*.md' + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: false + +jobs: + markdownlint: + name: markdownlint + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-node@v4 + with: + node-version: '20' + + - name: Run markdownlint + run: npx --yes markdownlint-cli '**/*.md' --ignore node_modules + + lychee: + name: lychee link check (offline) + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: lychee --offline + uses: lycheeverse/lychee-action@v2 + with: + args: --offline --no-progress --verbose './**/*.md' + fail: true diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml index 57f7afc..5831e7c 100644 --- a/.github/workflows/pr-check.yml +++ b/.github/workflows/pr-check.yml @@ -20,7 +20,7 @@ jobs: with: node-version: 20 - run: npm install - - run: npx playwright install --with-deps chromium + - run: npx playwright install --with-deps chromium firefox webkit - name: HTML validation run: | diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..63140b7 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,1960 @@ +{ + "name": "embeddedos-website", + "version": "3.0.1", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "embeddedos-website", + "version": "3.0.1", + "devDependencies": { + "@playwright/test": "^1.42.0", + "html-validate": "^11.10.0", + "http-server": "^14.1.0", + "linkinator": "^6.0.0", + "wait-on": "^7.2.0" + } + }, + "node_modules/@hapi/hoek": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", + "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@hapi/topo": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", + "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@hapi/hoek": "^9.0.0" + } + }, + "node_modules/@html-validate/stylish": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@html-validate/stylish/-/stylish-6.0.0.tgz", + "integrity": "sha512-d1/lI3qIXhGVJF3+MmKEBn1dRX6U4Z+BDaOdDI3E6SXcO+OQ7hC/3mSo6BIjwQlcuV6NdDOKm6QCrzIQL1EezQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^22.16.0 || >= 24.0.0" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@playwright/test": { + "version": "1.62.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.62.1.tgz", + "integrity": "sha512-DTcUc8qii+cpHvtOwggMtBRMjKZHXYWdw8syRYu2vtzuq4Wxphqq4NfCs5Zt44L6mA8rfDfj+PHnxFc/FeK6mQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright": "1.62.1" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@sideway/address": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.5.tgz", + "integrity": "sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@hapi/hoek": "^9.0.0" + } + }, + "node_modules/@sideway/formula": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz", + "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@sideway/pinpoint": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", + "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@sidvind/better-ajv-errors": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@sidvind/better-ajv-errors/-/better-ajv-errors-7.0.0.tgz", + "integrity": "sha512-imVsp5D3KxJ8+uUmu2dsLKnFg3qdX952v/L1gZoCa0NO2ivhQWHMpYM2KmpFrRXHWFjlqkNZ/935nxiTqXEi1A==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^22.12 || >= 24.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + } + }, + "node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "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/ansi-regex": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.3.0.tgz", + "integrity": "sha512-WpDfL7NO6j7tH88IDBNVdUJxDh9nmCteAVW9dsep846XdwF4naCBK+/tGLX3KJgcpgMRXCFlTM2hKGoK9FsdrQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "dev": true, + "license": "MIT" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/axios": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.19.0.tgz", + "integrity": "sha512-ht/iuYZXEjFxLH/Hkezgd7m6JKlHHXEUSneaDz8uZe1Gj5QZtCnpyDsckvAiEnT89OEbCLmnte4R4sn7P0EKFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.16.0", + "form-data": "^4.0.6", + "https-proxy-agent": "^5.0.1", + "proxy-from-env": "^2.1.0" + } + }, + "node_modules/axios/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/axios/node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/basic-auth": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "5.1.2" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/brace-expansion": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.4.tgz", + "integrity": "sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.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/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/corser": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/corser/-/corser-2.0.1.tgz", + "integrity": "sha512-utCYNzRSQIZNPIcGZdQc92UVJYAhtGAteCFg0yRaFm8f0P+CPtyGyHXJcGXnffjCybUCEx3FQ2G7U3/o9eIkVQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "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/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/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "dev": true, + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/dom-serializer/node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?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": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", + "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "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/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true, + "license": "MIT" + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT" + }, + "node_modules/entities": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz", + "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "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-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/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "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/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/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true, + "license": "MIT" + }, + "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-uri": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.7.tgz", + "integrity": "sha512-dOvZVzjdZdz7phd9v6jCbwxrBW3fK6n8Rc0CtdmM4bumzMnxywBYhuph6J819RRw/ku+rLbelwfMunktuzVVHg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, + "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/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "dev": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/form-data": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz", + "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.4", + "mime-types": "^2.1.35" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "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/gaxios": { + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-6.7.1.tgz", + "integrity": "sha512-LDODD4TMYx7XXdpwxAVRAIAuB0bzv0s+ywFonY46k126qzQHT9ygyoa9tncmOiQmmDrik65UYsEkv3lbfqQ3yQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "extend": "^3.0.2", + "https-proxy-agent": "^7.0.1", + "is-stream": "^2.0.0", + "node-fetch": "^2.6.9", + "uuid": "^9.0.1" + }, + "engines": { + "node": ">=14" + } + }, + "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": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "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/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/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "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/html-encoding-sniffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", + "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==", + "dev": true, + "license": "MIT", + "dependencies": { + "whatwg-encoding": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/html-validate": { + "version": "11.15.0", + "resolved": "https://registry.npmjs.org/html-validate/-/html-validate-11.15.0.tgz", + "integrity": "sha512-h9KaylhlNg6F1UliMJQr0W5vBCK5AppCLfOKTxLqiiL/B2n/9lPyvYJTKlwliHbyPTNzKYYp0Dhs0sZyI1osnA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/html-validate" + } + ], + "license": "MIT", + "dependencies": { + "@html-validate/stylish": "^6.0.0", + "@sidvind/better-ajv-errors": "7.0.0", + "ajv": "^8.0.0", + "kleur": "^4.1.0", + "prompts": "^2.0.0", + "semver": "^7.0.0" + }, + "bin": { + "html-validate": "bin/html-validate.mjs" + }, + "engines": { + "node": "^22.22.0 || >= 24.8.0" + }, + "peerDependencies": { + "@jest/globals": "^29.0.3 || ^30.0.0", + "@vitest/expect": "^3.2.0 || ^4.0.1 || ^5.0.0", + "jest": "^29.0.3 || ^30.0.0", + "jest-snapshot": "^29.0.3 || ^30.0.0", + "vitest": "^3.2.0 || ^4.0.1 || ^5.0.0" + }, + "peerDependenciesMeta": { + "@jest/globals": { + "optional": true + }, + "@vitest/expect": { + "optional": true + }, + "jest": { + "optional": true + }, + "jest-snapshot": { + "optional": true + }, + "vitest": { + "optional": true + } + } + }, + "node_modules/htmlparser2": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-10.1.0.tgz", + "integrity": "sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ==", + "dev": true, + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.2.2", + "entities": "^7.0.1" + } + }, + "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-server": { + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/http-server/-/http-server-14.1.1.tgz", + "integrity": "sha512-+cbxadF40UXd9T01zUHgA+rlo2Bg1Srer4+B4NwIHdaGxAGGv59nYRnGGDJ9LBk7alpS0US+J+bLLdQOOkJq4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "basic-auth": "^2.0.1", + "chalk": "^4.1.2", + "corser": "^2.0.1", + "he": "^1.2.0", + "html-encoding-sniffer": "^3.0.0", + "http-proxy": "^1.18.1", + "mime": "^1.6.0", + "minimist": "^1.2.6", + "opener": "^1.5.1", + "portfinder": "^1.0.28", + "secure-compare": "3.0.1", + "union": "~0.5.0", + "url-join": "^4.0.1" + }, + "bin": { + "http-server": "bin/http-server" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/joi": { + "version": "17.13.6", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.13.6.tgz", + "integrity": "sha512-ImNZaq/LSysofih+xIGYfR0WUXMA9GLUNB//YTCSrZptoRmVgaNAdJyi6K1kXi9pkLEoSkoI8I4UwtNiu/D7nw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@hapi/hoek": "^9.3.0", + "@hapi/topo": "^5.1.0", + "@sideway/address": "^4.1.5", + "@sideway/formula": "^3.0.1", + "@sideway/pinpoint": "^2.0.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/kleur": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", + "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/linkinator": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/linkinator/-/linkinator-6.3.0.tgz", + "integrity": "sha512-MRKxkkIK5XlK+IKzIhJydJBF72TpygT7atR9CCUZrKl9hpEPVkm3Kcu66M38HJUvUBg4iskzCQENwas7HIiJeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^5.0.0", + "escape-html": "^1.0.3", + "gaxios": "^6.0.0", + "glob": "^10.3.10", + "htmlparser2": "^10.0.0", + "marked": "^13.0.0", + "meow": "^13.0.0", + "mime": "^4.0.0", + "server-destroy": "^1.0.1", + "srcset": "^5.0.0" + }, + "bin": { + "linkinator": "build/src/cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/linkinator/node_modules/chalk": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/linkinator/node_modules/mime": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-4.1.0.tgz", + "integrity": "sha512-X5ju04+cAzsojXKes0B/S4tcYtFAJ6tTMuSPBEn9CPGlrWr8Fiw7qYeLT0XyH80HSoAoqWCaz+MWKh22P7G1cw==", + "dev": true, + "funding": [ + "https://github.com/sponsors/broofa" + ], + "license": "MIT", + "bin": { + "mime": "bin/cli.js" + }, + "engines": { + "node": ">=16" + } + }, + "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/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/marked": { + "version": "13.0.3", + "resolved": "https://registry.npmjs.org/marked/-/marked-13.0.3.tgz", + "integrity": "sha512-rqRix3/TWzE9rIoFGIn8JmsVfhiuC8VIQ8IdX5TfzmeBucdY05/0UlzKaw0eVtpcN/OdVFpBk7CjKGo9iHJ/zA==", + "dev": true, + "license": "MIT", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 18" + } + }, + "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/meow": { + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-13.2.0.tgz", + "integrity": "sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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.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/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/minimatch": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.2" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "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/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "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/opener": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", + "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", + "dev": true, + "license": "(WTFPL OR MIT)", + "bin": { + "opener": "bin/opener-bin.js" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true, + "license": "BlueOak-1.0.0" + }, + "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-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/playwright": { + "version": "1.62.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.62.1.tgz", + "integrity": "sha512-0M+L3LAD8/nm554LOla9Ayx0j0tmFZ0FBcoQ7F1VuVHpM/XpiC8RcDzBQB8W5+hA8L22THxELzeF+2WcUzvcLg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright-core": "1.62.1" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=20" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.62.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.62.1.tgz", + "integrity": "sha512-wPYSwEBJY9GHraISXqyqtx0na0LpO3XEX7jNDhntbex7tzUS7kLnZsOlFruFJB4Hi/rhDMjXGqHewDZ68nYZVw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/portfinder": { + "version": "1.0.38", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.38.tgz", + "integrity": "sha512-rEwq/ZHlJIKw++XtLAO8PPuOQA/zaPJOZJ37BVuN97nLpMJeuDVLVGRwbFoBgLudgdTMP2hdRJP++H+8QOA3vg==", + "dev": true, + "license": "MIT", + "dependencies": { + "async": "^3.2.6", + "debug": "^4.3.6" + }, + "engines": { + "node": ">= 10.12" + } + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/prompts/node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/proxy-from-env": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz", + "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "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/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/rxjs": { + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", + "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "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/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/secure-compare": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/secure-compare/-/secure-compare-3.0.1.tgz", + "integrity": "sha512-AckIIV90rPDcBcglUwXPF3kg0P0qmPsPXAj6BBEENQE1p5yA1xfmDJzfi1Tappj37Pv2mVbKpL3Z1T+Nn7k1Qw==", + "dev": true, + "license": "MIT" + }, + "node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/server-destroy": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/server-destroy/-/server-destroy-1.0.1.tgz", + "integrity": "sha512-rb+9B5YBIEzYcD6x2VKidaa+cqYBJQKnU4oe4E3ANwRRN56yk/ua1YCJT1n21NTS8w6CcOclAKNP3PhdCXKYtQ==", + "dev": true, + "license": "ISC" + }, + "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/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/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true, + "license": "MIT" + }, + "node_modules/srcset": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/srcset/-/srcset-5.0.3.tgz", + "integrity": "sha512-AZswtOXIsu0LeHdo6YY7d0r2pCH2Rl1D8ae1utvXUX4GxG3RggsVUAOFX1r8RI4YHFMYb4g89+UBPBv3mNUU2g==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/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/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/string-width-cjs/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/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "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/strip-ansi-cjs/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/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dev": true, + "license": "MIT" + }, + "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/union": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/union/-/union-0.5.0.tgz", + "integrity": "sha512-N6uOhuW6zO95P3Mel2I2zMsbsanvvtgn6jVqJv4vbVcz/JN0OkL9suomjQGmWtxJQXOCqUJvquc1sMeNz/IwlA==", + "dev": true, + "dependencies": { + "qs": "^6.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/url-join": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", + "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==", + "dev": true, + "license": "MIT" + }, + "node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "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, + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/wait-on": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/wait-on/-/wait-on-7.2.0.tgz", + "integrity": "sha512-wCQcHkRazgjG5XoAq9jbTMLpNIjoSlZslrJ2+N9MxDsGEv1HnFoVjOCexL0ESva7Y9cu350j+DWADdk54s4AFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "axios": "^1.6.1", + "joi": "^17.11.0", + "lodash": "^4.17.21", + "minimist": "^1.2.8", + "rxjs": "^7.8.1" + }, + "bin": { + "wait-on": "bin/wait-on" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/whatwg-encoding": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", + "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", + "deprecated": "Use @exodus/bytes instead for a more spec-conformant and faster implementation", + "dev": true, + "license": "MIT", + "dependencies": { + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dev": true, + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.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/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/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/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/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/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + } + } +} diff --git a/package.json b/package.json index 29236b5..0360981 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,8 @@ "check:links": "npx linkinator http://localhost:8080 --recurse --skip 'github.com|googletagmanager' --timeout 10000", "lint:html": "npx html-validate '*.html' 'docs/*.html' || true", "lighthouse": "npx @lhci/cli collect --url=http://localhost:8080/index.html --settings.preset=desktop", - "audit": "npm run test && npm run check:links" + "audit": "npm run test && npm run check:links", + "build": "python3 scripts/build-deploy.py" }, "devDependencies": { "@playwright/test": "^1.42.0", diff --git a/scripts/build-deploy.py b/scripts/build-deploy.py new file mode 100644 index 0000000..0d12eb8 --- /dev/null +++ b/scripts/build-deploy.py @@ -0,0 +1,34 @@ +#!/usr/bin/env python3 +"""Build the static deployment tree without modifying tracked sources.""" + +from __future__ import annotations + +import shutil +from pathlib import Path + +ROOT = Path(__file__).resolve().parent.parent +OUT = ROOT / "dist" +SOURCE_ONLY = {"tests", "test-screenshots", ".github", "scripts", "dist", ".git", "node_modules"} +def stage_tree() -> None: + """Copy publishable files into OUT while leaving the checkout untouched.""" + if OUT.exists(): + shutil.rmtree(OUT) + + def ignore(directory: str, names: list[str]) -> set[str]: + if Path(directory).resolve() == ROOT: + return SOURCE_ONLY.intersection(names) + return {"node_modules"}.intersection(names) + + shutil.copytree(ROOT, OUT, ignore=ignore) + + +def build() -> None: + # HTML, JavaScript, and CSS all contain contexts where whitespace and + # comment-looking text are significant. Preserve source bytes until the + # project adopts syntax-aware minifiers for each language. + stage_tree() + print(f"Deploy tree written to {OUT.relative_to(ROOT)}/ (source tree untouched)") + + +if __name__ == "__main__": + build() diff --git a/style.css.bak b/style.css.bak deleted file mode 100644 index d9bf72b..0000000 --- a/style.css.bak +++ /dev/null @@ -1,986 +0,0 @@ -:root { - --bg-primary: #0d1117; - --bg-secondary: #161b22; - --bg-tertiary: #1c2128; - --bg-card: #21262d; - --bg-hover: #292e36; - --text-primary: #e6edf3; - --text-secondary: #8b949e; - --text-muted: #6e7681; - --border-color: #30363d; - --border-light: #21262d; - --blue: #58a6ff; - --green: #3fb950; - --purple: #bc8cff; - --orange: #f0883e; - --cyan: #79c0ff; - --pink: #f778ba; - --yellow: #e3b341; - --red: #f85149; - --blue-dim: rgba(88,166,255,0.15); - --green-dim: rgba(63,185,80,0.15); - --purple-dim: rgba(188,140,255,0.15); - --orange-dim: rgba(240,136,62,0.15); - --cyan-dim: rgba(121,192,255,0.15); - --pink-dim: rgba(247,120,186,0.15); - --yellow-dim: rgba(227,179,65,0.15); - --red-dim: rgba(248,81,73,0.15); - --gradient-hero: linear-gradient(135deg, #0d1117 0%, #0f1a35 25%, #1a1040 55%, #0d1117 100%); - --shadow-sm: 0 1px 3px rgba(0,0,0,0.3); - --shadow-md: 0 4px 12px rgba(0,0,0,0.4); - --shadow-lg: 0 8px 24px rgba(0,0,0,0.5); - --radius-sm: 6px; - --radius-md: 10px; - --radius-lg: 16px; - --radius-xl: 24px; - --font-sans: 'Inter', 'Segoe UI', -apple-system, BlinkMacSystemFont, sans-serif; - --font-mono: 'Fira Code', 'Cascadia Code', Consolas, monospace; - --sidebar-width: 260px; - --nav-height: 64px; -} -*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } -html { scroll-behavior: smooth; font-size: 16px; overflow-x: hidden; } -body { font-family: var(--font-sans); background: var(--bg-primary); color: var(--text-primary); line-height: 1.7; overflow-x: hidden; -webkit-font-smoothing: antialiased; } -a { color: var(--cyan); text-decoration: none; transition: color 0.2s; } -a:hover { color: var(--blue); text-decoration: underline; } -img { max-width: 100%; } -ul, ol { padding-left: 1.5em; } -h1, h2, h3, h4, h5, h6 { line-height: 1.3; } -h2 { font-size: 1.6rem; margin: 2.5rem 0 1rem; padding-bottom: 0.5rem; border-bottom: 1px solid var(--border-color); } -h3 { font-size: 1.25rem; margin: 2rem 0 0.75rem; } - -.navbar { position: sticky; top: 0; z-index: 1000; background: rgba(13,17,23,0.85); backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px); border-bottom: 1px solid var(--border-color); height: var(--nav-height); display: flex; align-items: center; padding: 0 2rem; } -.navbar .nav-inner { max-width: 1400px; width: 100%; margin: 0 auto; display: flex; align-items: center; justify-content: space-between; } -.navbar .logo { display: flex; align-items: center; gap: 10px; font-size: 1.25rem; font-weight: 700; color: var(--text-primary); text-decoration: none; } -.navbar .logo:hover { text-decoration: none; color: var(--text-primary); } -.navbar .logo-icon { width: 36px; height: 36px; background: linear-gradient(135deg, #1158a6, #58a6ff); border-radius: var(--radius-sm); display: flex; align-items: center; justify-content: center; font-weight: 900; font-size: 0.9rem; color: #fff; } -.navbar .nav-links { display: flex; align-items: center; gap: 0.25rem; list-style: none; padding: 0; } -.navbar .nav-links a { padding: 0.5rem 1rem; border-radius: var(--radius-sm); color: var(--text-secondary); font-size: 0.9rem; font-weight: 500; transition: all 0.2s; } -.navbar .nav-links a:hover { color: var(--text-primary); background: var(--bg-tertiary); text-decoration: none; } -.navbar .nav-links a.active { color: var(--blue); background: var(--blue-dim); } -.nav-version { font-size: 0.7rem; padding: 2px 8px; background: var(--green-dim); color: var(--green); border-radius: 20px; font-weight: 600; } -.nav-github { display: inline-flex; align-items: center; gap: 6px; padding: 0.4rem 1rem; background: var(--bg-tertiary); border: 1px solid var(--border-color); border-radius: var(--radius-sm); color: var(--text-secondary); font-size: 0.85rem; transition: all 0.2s; } -.nav-github:hover { background: var(--bg-hover); color: var(--text-primary); border-color: var(--text-muted); text-decoration: none; } -.hero { background: var(--gradient-hero); padding: 6rem 2rem 5rem; text-align: center; position: relative; overflow: hidden; } -.hero::before { content: ''; position: absolute; top: -50%; left: -50%; width: 200%; height: 200%; background: radial-gradient(circle at 30% 50%, rgba(88,166,255,0.10) 0%, transparent 50%), radial-gradient(circle at 70% 50%, rgba(188,140,255,0.10) 0%, transparent 50%), radial-gradient(circle at 50% 80%, rgba(63,185,80,0.05) 0%, transparent 40%); animation: heroGlow 8s ease-in-out infinite alternate; } -@keyframes heroGlow { 0% { transform: translate(0, 0); } 100% { transform: translate(-3%, 3%); } } -.hero-content { position: relative; z-index: 1; max-width: 900px; margin: 0 auto; } -.hero h1 { font-size: 3.5rem; font-weight: 800; line-height: 1.2; margin-bottom: 1rem; background: linear-gradient(135deg, var(--blue), var(--purple), var(--pink)); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; } -.hero .subtitle { font-size: 1.3rem; color: var(--text-secondary); margin-bottom: 2rem; max-width: 600px; margin-left: auto; margin-right: auto; } -.hero-buttons { display: flex; gap: 1rem; justify-content: center; flex-wrap: wrap; } -.hero-stats { display: flex; gap: 3rem; justify-content: center; margin-top: 3rem; flex-wrap: wrap; } -.stat { text-align: center; } -.stat-number { font-size: 2.5rem; font-weight: 800; display: block; } -.stat-label { font-size: 0.85rem; color: var(--text-secondary); text-transform: uppercase; letter-spacing: 1px; } - -.btn { display: inline-flex; align-items: center; gap: 8px; padding: 0.7rem 1.5rem; border-radius: var(--radius-sm); font-weight: 600; font-size: 0.95rem; cursor: pointer; transition: all 0.25s ease; border: none; text-decoration: none !important; } -.btn-primary { background: var(--blue); color: #fff !important; } -.btn-primary:hover { background: #79b8ff; box-shadow: 0 0 24px rgba(88,166,255,0.4); transform: translateY(-2px); } -.btn:active { transform: scale(0.97) !important; transition: transform 0.12s ease-out !important; } -.btn-secondary { background: var(--bg-tertiary); color: var(--text-primary) !important; border: 1px solid var(--border-color); } -.btn-secondary:hover { background: var(--bg-hover); border-color: var(--text-muted); transform: translateY(-2px); } -.btn-green { background: var(--green); color: #fff !important; } -.btn-green:hover { background: #56d364; box-shadow: 0 0 20px rgba(63,185,80,0.3); transform: translateY(-2px); } -.btn-purple { background: var(--purple); color: #fff !important; } -.btn-purple:hover { box-shadow: 0 0 20px rgba(188,140,255,0.3); transform: translateY(-2px); } -.btn-sm { padding: 0.4rem 0.9rem; font-size: 0.8rem; } -.btn-outline { background: transparent; border: 1px solid var(--border-color); color: var(--text-secondary) !important; } -.btn-outline:hover { border-color: var(--blue); color: var(--blue) !important; background: var(--blue-dim); } - -.product-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1.5rem; max-width: 1400px; margin: 0 auto; padding: 0 2rem; } -.product-card { background: var(--bg-card); border: 1px solid var(--border-color); border-radius: var(--radius-md); padding: 1.5rem; transition: all 0.3s ease; position: relative; overflow: hidden; } -.product-card::before { content: ''; position: absolute; top: 0; left: 0; right: 0; height: 3px; } -.product-card:hover { transform: translateY(-5px); box-shadow: 0 12px 32px rgba(0,0,0,0.6); border-color: var(--text-muted); } -.card-icon { width: 48px; height: 48px; border-radius: var(--radius-sm); display: flex; align-items: center; justify-content: center; font-weight: 800; font-size: 1.1rem; margin-bottom: 1rem; } -.product-card h3 { font-size: 1.15rem; font-weight: 700; margin-bottom: 0.5rem; border: none; padding: 0; margin-top: 0; } -.product-card p { color: var(--text-secondary); font-size: 0.9rem; margin-bottom: 1rem; line-height: 1.5; } -.card-tags { display: flex; flex-wrap: wrap; gap: 0.4rem; margin-bottom: 1rem; } -.card-buttons { display: flex; gap: 0.5rem; } - -.card-eos::before { background: var(--blue); } -.card-eos .card-icon { background: var(--blue-dim); color: var(--blue); } -.card-eos:hover { border-color: var(--blue); box-shadow: 0 8px 24px rgba(88,166,255,0.15); } -.card-eboot::before { background: var(--green); } -.card-eboot .card-icon { background: var(--green-dim); color: var(--green); } -.card-eboot:hover { border-color: var(--green); box-shadow: 0 8px 24px rgba(63,185,80,0.15); } -.card-ebuild::before { background: var(--orange); } -.card-ebuild .card-icon { background: var(--orange-dim); color: var(--orange); } -.card-ebuild:hover { border-color: var(--orange); box-shadow: 0 8px 24px rgba(240,136,62,0.15); } -.card-eipc::before { background: var(--cyan); } -.card-eipc .card-icon { background: var(--cyan-dim); color: var(--cyan); } -.card-eipc:hover { border-color: var(--cyan); box-shadow: 0 8px 24px rgba(121,192,255,0.15); } -.card-eai::before { background: var(--purple); } -.card-eai .card-icon { background: var(--purple-dim); color: var(--purple); } -.card-eai:hover { border-color: var(--purple); box-shadow: 0 8px 24px rgba(188,140,255,0.15); } -.card-eni::before { background: var(--pink); } -.card-eni .card-icon { background: var(--pink-dim); color: var(--pink); } -.card-eni:hover { border-color: var(--pink); box-shadow: 0 8px 24px rgba(247,120,186,0.15); } -.card-eosuite::before { background: var(--yellow); } -.card-eosuite .card-icon { background: var(--yellow-dim); color: var(--yellow); } -.card-eosuite:hover { border-color: var(--yellow); box-shadow: 0 8px 24px rgba(227,179,65,0.15); } -.card-eosim::before { background: var(--red); } -.card-eosim .card-icon { background: var(--red-dim); color: var(--red); } -.card-eosim:hover { border-color: var(--red); box-shadow: 0 8px 24px rgba(248,81,73,0.15); } -.badge { display: inline-flex; align-items: center; padding: 2px 10px; border-radius: 20px; font-size: 0.72rem; font-weight: 600; letter-spacing: 0.3px; text-transform: uppercase; } -.badge-blue { background: var(--blue-dim); color: var(--blue); } -.badge-green { background: var(--green-dim); color: var(--green); } -.badge-purple { background: var(--purple-dim); color: var(--purple); } -.badge-orange { background: var(--orange-dim); color: var(--orange); } -.badge-cyan { background: var(--cyan-dim); color: var(--cyan); } -.badge-pink { background: var(--pink-dim); color: var(--pink); } -.badge-yellow { background: var(--yellow-dim); color: var(--yellow); } -.badge-red { background: var(--red-dim); color: var(--red); } -.version-badge { display: inline-flex; align-items: center; gap: 4px; padding: 3px 12px; border-radius: 20px; font-size: 0.8rem; font-weight: 600; background: var(--green-dim); color: var(--green); } - -.section { padding: 5rem 2rem; max-width: 1400px; margin: 0 auto; } -.section-full { padding: 5rem 2rem; } -.section-alt { background: var(--bg-secondary); } -.section-title { font-size: 2rem; font-weight: 800; margin-bottom: 0.5rem; text-align: center; border: none; } -.section-subtitle { color: var(--text-secondary); text-align: center; margin-bottom: 3rem; font-size: 1.1rem; } -.section-divider { height: 3px; border-radius: 2px; margin: 0 auto 3rem; max-width: 80px; border: none; } - -.doc-layout { display: grid; grid-template-columns: var(--sidebar-width) 1fr; max-width: 1400px; margin: 0 auto; min-height: calc(100vh - var(--nav-height)); overflow: hidden; } -.doc-sidebar { position: sticky; top: var(--nav-height); height: calc(100vh - var(--nav-height)); overflow-y: auto; padding: 1.5rem; border-right: 1px solid var(--border-color); background: var(--bg-secondary); scrollbar-width: thin; scrollbar-color: var(--border-color) transparent; z-index: 1; } -.doc-sidebar h4 { font-size: 0.75rem; text-transform: uppercase; letter-spacing: 1.5px; color: var(--text-muted); margin-bottom: 0.75rem; padding-left: 0.5rem; } -.doc-sidebar ul { list-style: none; padding: 0; margin-bottom: 1.5rem; } -.doc-sidebar li a { display: block; padding: 0.35rem 0.75rem; color: var(--text-secondary); font-size: 0.85rem; border-radius: var(--radius-sm); border-left: 2px solid transparent; transition: all 0.2s; } -.doc-sidebar li a:hover { color: var(--text-primary); background: var(--bg-tertiary); text-decoration: none; } -.doc-sidebar li a.active { color: var(--blue); background: var(--blue-dim); border-left-color: var(--blue); } -.sidebar-green li a.active { color: var(--green) !important; background: var(--green-dim) !important; border-left-color: var(--green) !important; } -.sidebar-orange li a.active { color: var(--orange) !important; background: var(--orange-dim) !important; border-left-color: var(--orange) !important; } -.sidebar-cyan li a.active { color: var(--cyan) !important; background: var(--cyan-dim) !important; border-left-color: var(--cyan) !important; } -.sidebar-purple li a.active { color: var(--purple) !important; background: var(--purple-dim) !important; border-left-color: var(--purple) !important; } -.sidebar-pink li a.active { color: var(--pink) !important; background: var(--pink-dim) !important; border-left-color: var(--pink) !important; } -.sidebar-yellow li a.active { color: var(--yellow) !important; background: var(--yellow-dim) !important; border-left-color: var(--yellow) !important; } -.sidebar-red li a.active { color: var(--red) !important; background: var(--red-dim) !important; border-left-color: var(--red) !important; } -.doc-content { padding: 2rem 3rem; max-width: 960px; position: relative; z-index: 0; } -.doc-content p { margin-bottom: 1rem; } - -.breadcrumb { display: flex; align-items: center; gap: 0.5rem; font-size: 0.85rem; color: var(--text-muted); margin-bottom: 1.5rem; flex-wrap: wrap; } -.breadcrumb a { color: var(--text-secondary); } -.breadcrumb a:hover { color: var(--blue); } -.breadcrumb .sep { color: var(--text-muted); } - -.doc-hero { padding: 2rem; border-radius: var(--radius-md); margin-bottom: 2rem; border: 1px solid var(--border-color); } -.doc-hero h1 { font-size: 2.2rem; font-weight: 800; margin-bottom: 0.5rem; border: none; } -.doc-hero p { color: var(--text-secondary); font-size: 1.05rem; margin-bottom: 0; } -.doc-hero-meta { display: flex; align-items: center; gap: 1rem; margin-top: 1rem; flex-wrap: wrap; } -.doc-hero-blue { background: linear-gradient(135deg, rgba(88,166,255,0.1), rgba(88,166,255,0.02)); border-color: rgba(88,166,255,0.3); } -.doc-hero-green { background: linear-gradient(135deg, rgba(63,185,80,0.1), rgba(63,185,80,0.02)); border-color: rgba(63,185,80,0.3); } -.doc-hero-orange { background: linear-gradient(135deg, rgba(240,136,62,0.1), rgba(240,136,62,0.02)); border-color: rgba(240,136,62,0.3); } -.doc-hero-cyan { background: linear-gradient(135deg, rgba(121,192,255,0.1), rgba(121,192,255,0.02)); border-color: rgba(121,192,255,0.3); } -.doc-hero-purple { background: linear-gradient(135deg, rgba(188,140,255,0.1), rgba(188,140,255,0.02)); border-color: rgba(188,140,255,0.3); } -.doc-hero-pink { background: linear-gradient(135deg, rgba(247,120,186,0.1), rgba(247,120,186,0.02)); border-color: rgba(247,120,186,0.3); } -.doc-hero-yellow { background: linear-gradient(135deg, rgba(227,179,65,0.1), rgba(227,179,65,0.02)); border-color: rgba(227,179,65,0.3); } -.doc-hero-red { background: linear-gradient(135deg, rgba(248,81,73,0.1), rgba(248,81,73,0.02)); border-color: rgba(248,81,73,0.3); } -pre { background: var(--bg-secondary); border: 1px solid var(--border-color); border-radius: var(--radius-md); padding: 1.2rem 1.5rem; overflow-x: auto; font-family: var(--font-mono); font-size: 0.85rem; line-height: 1.7; margin: 1rem 0; position: relative; } -code { font-family: var(--font-mono); font-size: 0.85em; } -:not(pre) > code { background: var(--bg-tertiary); padding: 2px 7px; border-radius: 4px; color: var(--cyan); font-size: 0.85em; } -pre .copy-hint { position: absolute; top: 0.5rem; right: 0.75rem; font-size: 0.7rem; color: var(--text-muted); background: var(--bg-tertiary); padding: 2px 8px; border-radius: 4px; font-family: var(--font-sans); opacity: 0; transition: opacity 0.2s; } -pre:hover .copy-hint { opacity: 1; } -.kw { color: var(--purple); font-weight: 600; } -.fn { color: var(--blue); } -.str { color: var(--green); } -.cm { color: var(--text-muted); font-style: italic; } -.ty { color: var(--cyan); } -.num { color: var(--orange); } -.op { color: var(--text-secondary); } -.pp { color: var(--pink); } - -.api-block { background: var(--bg-card); border: 1px solid var(--border-color); border-radius: var(--radius-md); margin: 1rem 0; overflow: hidden; } -.api-header { padding: 0.75rem 1.2rem; background: var(--bg-tertiary); border-bottom: 1px solid var(--border-color); font-family: var(--font-mono); font-size: 0.85rem; } -.api-body { padding: 1rem 1.2rem; color: var(--text-secondary); font-size: 0.9rem; } -.api-body p { margin-bottom: 0.5rem; } -.api-params dt { font-family: var(--font-mono); color: var(--cyan); font-size: 0.82rem; margin-top: 0.4rem; } -.api-params dd { color: var(--text-secondary); font-size: 0.82rem; padding-left: 1rem; margin-bottom: 0.2rem; } - -table { width: 100%; border-collapse: collapse; margin: 1rem 0; font-size: 0.9rem; } -th { background: var(--bg-tertiary); padding: 0.75rem 1rem; text-align: left; font-weight: 600; font-size: 0.82rem; text-transform: uppercase; letter-spacing: 0.5px; border-bottom: 2px solid var(--border-color); } -td { padding: 0.6rem 1rem; border-bottom: 1px solid var(--border-light); } -tr:nth-child(even) { background: rgba(255,255,255,0.02); } -tr:hover { background: rgba(255,255,255,0.04); } -.table-blue th { color: var(--blue); border-bottom-color: var(--blue); } -.table-green th { color: var(--green); border-bottom-color: var(--green); } -.table-orange th { color: var(--orange); border-bottom-color: var(--orange); } -.table-cyan th { color: var(--cyan); border-bottom-color: var(--cyan); } -.table-purple th { color: var(--purple); border-bottom-color: var(--purple); } -.table-pink th { color: var(--pink); border-bottom-color: var(--pink); } -.table-yellow th { color: var(--yellow); border-bottom-color: var(--yellow); } -.table-red th { color: var(--red); border-bottom-color: var(--red); } - -.callout { padding: 1rem 1.25rem; border-radius: var(--radius-sm); margin: 1rem 0; border-left: 4px solid; font-size: 0.9rem; } -.callout-title { font-weight: 700; font-size: 0.85rem; text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 0.3rem; } -.callout-tip { background: var(--green-dim); border-color: var(--green); } -.callout-tip .callout-title { color: var(--green); } -.callout-warning { background: var(--orange-dim); border-color: var(--orange); } -.callout-warning .callout-title { color: var(--orange); } -.callout-info { background: var(--blue-dim); border-color: var(--blue); } -.callout-info .callout-title { color: var(--blue); } -.callout-danger { background: var(--red-dim); border-color: var(--red); } -.callout-danger .callout-title { color: var(--red); } - -.steps { counter-reset: step-counter; padding-left: 0; list-style: none; } -.step { position: relative; padding-left: 3.5rem; margin-bottom: 2rem; counter-increment: step-counter; } -.step::before { content: counter(step-counter); position: absolute; left: 0; top: 0; width: 2.2rem; height: 2.2rem; border-radius: 50%; background: var(--blue); color: #fff; display: flex; align-items: center; justify-content: center; font-weight: 700; font-size: 0.9rem; } -.step h3 { font-size: 1.1rem; margin-bottom: 0.5rem; margin-top: 0; border: none; } -.step-green .step::before { background: var(--green); } -.step-orange .step::before { background: var(--orange); } -.step-purple .step::before { background: var(--purple); } -.step-cyan .step::before { background: var(--cyan); } -.step-pink .step::before { background: var(--pink); } -.step-yellow .step::before { background: var(--yellow); } -.step-red .step::before { background: var(--red); } - -details { background: var(--bg-card); border: 1px solid var(--border-color); border-radius: var(--radius-sm); margin: 0.75rem 0; } -summary { padding: 0.75rem 1rem; cursor: pointer; font-weight: 600; color: var(--text-primary); transition: background 0.2s; list-style: none; } -summary::-webkit-details-marker { display: none; } -summary::before { content: '\25B6'; display: inline-block; margin-right: 0.5rem; font-size: 0.7rem; transition: transform 0.2s; } -details[open] summary::before { transform: rotate(90deg); } -summary:hover { background: var(--bg-hover); } -details[open] summary { border-bottom: 1px solid var(--border-color); } -.details-content { padding: 1rem; } - -.arch-diagram { display: flex; flex-direction: column; gap: 1rem; padding: 2rem; background: var(--bg-secondary); border-radius: var(--radius-lg); border: 1px solid var(--border-color); margin: 2rem 0; } -.arch-row { display: flex; gap: 1rem; justify-content: center; flex-wrap: wrap; } -.arch-box { padding: 0.75rem 1.5rem; border-radius: var(--radius-sm); border: 2px solid; font-weight: 600; font-size: 0.85rem; text-align: center; min-width: 100px; transition: all 0.2s; background: var(--bg-card); } -.arch-box:hover { transform: scale(1.05); } -.arch-arrow { text-align: center; font-size: 1.5rem; color: var(--text-muted); padding: 0.25rem 0; } - -.footer { background: var(--bg-secondary); border-top: 1px solid var(--border-color); padding: 3rem 2rem; margin-top: 4rem; } -.footer-inner { max-width: 1400px; margin: 0 auto; display: grid; grid-template-columns: 2fr 1fr 1fr 1fr 1fr; gap: 2rem; } -.footer h4 { font-size: 0.85rem; text-transform: uppercase; letter-spacing: 1px; color: var(--text-muted); margin-bottom: 1rem; } -.footer ul { list-style: none; padding: 0; } -.footer li { margin-bottom: 0.4rem; } -.footer li a { color: var(--text-secondary); font-size: 0.9rem; } -.footer li a:hover { color: var(--blue); } -.footer-brand p { color: var(--text-secondary); font-size: 0.9rem; margin-bottom: 1rem; } -.footer-bottom { max-width: 1400px; margin: 2rem auto 0; padding-top: 1.5rem; border-top: 1px solid var(--border-color); text-align: center; color: var(--text-muted); font-size: 0.82rem; } - -.search-box { position: relative; max-width: 500px; margin: 0 auto 2rem; } -.search-box input { width: 100%; padding: 0.8rem 1.2rem 0.8rem 3rem; background: var(--bg-card); border: 1px solid var(--border-color); border-radius: var(--radius-lg); color: var(--text-primary); font-size: 0.95rem; outline: none; transition: all 0.2s; font-family: var(--font-sans); } -.search-box input:focus { border-color: var(--blue); box-shadow: 0 0 0 3px var(--blue-dim); } -.search-box input::placeholder { color: var(--text-muted); } -.search-icon { position: absolute; left: 1rem; top: 50%; transform: translateY(-50%); color: var(--text-muted); } - -.checklist { list-style: none; padding: 0; } -.checklist li { padding: 0.5rem 0 0.5rem 2rem; position: relative; font-size: 0.95rem; } -.checklist li::before { content: '\2713'; position: absolute; left: 0; width: 1.4rem; height: 1.4rem; background: var(--green-dim); color: var(--green); border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 0.7rem; font-weight: 700; top: 0.6rem; } - -.quick-links { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 1rem; margin: 1rem 0; } -.quick-link { display: flex; align-items: center; gap: 0.75rem; padding: 1rem; background: var(--bg-card); border: 1px solid var(--border-color); border-radius: var(--radius-sm); transition: all 0.2s; color: var(--text-primary); } -.quick-link:hover { border-color: var(--blue); transform: translateY(-2px); text-decoration: none; } -.ql-icon { width: 36px; height: 36px; border-radius: var(--radius-sm); display: flex; align-items: center; justify-content: center; font-weight: 700; font-size: 0.85rem; flex-shrink: 0; } -.ql-text { font-size: 0.9rem; font-weight: 500; } - -.popular { position: relative; } -.popular::after { content: 'POPULAR'; position: absolute; top: 0.75rem; right: 0.75rem; font-size: 0.6rem; padding: 2px 8px; background: var(--orange-dim); color: var(--orange); border-radius: 10px; font-weight: 700; letter-spacing: 0.5px; } - -.doc-nav { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; margin-top: 3rem; padding-top: 2rem; border-top: 1px solid var(--border-color); } -.doc-nav a { display: block; padding: 1rem 1.5rem; background: var(--bg-card); border: 1px solid var(--border-color); border-radius: var(--radius-sm); transition: all 0.2s; } -.doc-nav a:hover { border-color: var(--blue); background: var(--blue-dim); text-decoration: none; } -.nav-label { font-size: 0.75rem; color: var(--text-muted); text-transform: uppercase; letter-spacing: 1px; } -.nav-title { font-size: 1rem; font-weight: 600; color: var(--text-primary); } -.doc-nav .next { text-align: right; } - -.edit-link { display: inline-flex; align-items: center; gap: 6px; font-size: 0.82rem; color: var(--text-muted); padding: 4px 10px; border: 1px solid var(--border-light); border-radius: var(--radius-sm); transition: all 0.2s; float: right; } -.edit-link:hover { color: var(--blue); border-color: var(--blue); background: var(--blue-dim); text-decoration: none; } - -.hw-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 1rem; margin: 1rem 0; } -.hw-item { background: var(--bg-card); border: 1px solid var(--border-color); border-radius: var(--radius-sm); padding: 1rem; transition: all 0.2s; } -.hw-item:hover { border-color: var(--text-muted); transform: translateY(-2px); } -.hw-item h4 { font-size: 0.95rem; margin-bottom: 0.25rem; } -.hw-item p { font-size: 0.8rem; color: var(--text-secondary); margin-bottom: 0; } - -.content-wrapper { max-width: 900px; margin: 0 auto; padding: 2rem; } - -@media (max-width: 1024px) { - .product-grid { grid-template-columns: repeat(2, 1fr); } - .footer-inner { grid-template-columns: repeat(2, 1fr); } - .doc-layout { grid-template-columns: 1fr; } - .doc-sidebar { position: relative; top: 0; height: auto; border-right: none; border-bottom: 1px solid var(--border-color); } - .doc-content { padding: 1.5rem; } -} -@media (max-width: 768px) { - .product-grid { grid-template-columns: 1fr; } - .hero h1 { font-size: 2.2rem; } - .hero-stats { gap: 1.5rem; } - .footer-inner { grid-template-columns: 1fr; } - .doc-nav { grid-template-columns: 1fr; } - .arch-row { flex-direction: column; align-items: center; } - .section { padding: 3rem 1rem; } - .hero { padding: 4rem 1rem 3rem; } - table { display: block; overflow-x: auto; max-width: 100%; } - .api-card { margin: 1rem 0; padding: 1rem; } - .navbar { padding: 0 1rem; } -} -@media print { - .navbar, .doc-sidebar, .edit-link, .doc-nav { display: none; } - body { background: #fff; color: #000; } - .doc-content { max-width: 100%; padding: 0; } - a { color: #000; text-decoration: underline; } - pre { border: 1px solid #ccc; } -} -/* === API Documentation Card Styles === */ -.api-card { background: #161b22; border: 1px solid #30363d; border-radius: 8px; margin: 1.5rem 0; padding: 1.5rem; border-left: 4px solid var(--blue); } -.api-card.accent-green { border-left-color: var(--green); } -.api-card.accent-purple { border-left-color: var(--purple); } -.api-card.accent-orange { border-left-color: var(--orange); } -.api-card.accent-cyan { border-left-color: var(--cyan); } -.api-card.accent-pink { border-left-color: var(--pink); } -.api-signature { font-size: 1.05rem; font-family: var(--font-mono); background: #0d1117; padding: 0.5rem 1rem; border-radius: 4px; display: block; overflow-x: auto; } -.api-signature .ret { color: #3fb950; } -.api-signature .fn { color: #58a6ff; font-weight: bold; } -.api-signature .param { color: #79c0ff; } -.api-desc { color: #e6edf3; margin: 1rem 0; line-height: 1.6; font-size: 0.92rem; } -.api-params table { width: 100%; border-collapse: collapse; } -.api-params td { padding: 0.5rem; border-bottom: 1px solid #21262d; font-size: 0.88rem; } -.api-params td:first-child { font-weight: bold; color: #f0883e; width: 130px; } -.api-params td:nth-child(2) { color: #bc8cff; width: 200px; font-family: var(--font-mono); font-size: 0.82rem; } -.api-returns { margin: 0.5rem 0; font-size: 0.92rem; } -.api-example pre { background: #0d1117; border: 1px solid #30363d; border-radius: 6px; padding: 1rem; overflow-x: auto; font-size: 0.82rem; } -.api-params h5, .api-returns h5, .api-example h5 { color: #8b949e; font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.05em; margin: 0.75rem 0 0.25rem; } -.version-badge { background: #1f6feb; color: white; padding: 0.2rem 0.6rem; border-radius: 12px; font-size: 0.75rem; font-weight: 600; vertical-align: middle; } -.struct-card { background: #0d1117; border: 1px solid #30363d; border-radius: 8px; padding: 1.2rem; margin: 1rem 0; } -.struct-card h4 { color: #3fb950; font-family: var(--font-mono); margin-bottom: 0.5rem; } -.struct-card table td { padding: 0.35rem 0.5rem; font-size: 0.85rem; } -.module-section { margin: 3rem 0 1rem; padding: 1rem 0; border-top: 2px solid #30363d; } -.module-section h3 { font-size: 1.3rem; margin-bottom: 0.3rem; } -.module-section .module-desc { color: #8b949e; font-size: 0.9rem; } -/* Mobile hamburger menu */ -.nav-toggle { display: none; background: none; border: 1px solid var(--border-color); color: var(--text-primary); font-size: 1.5rem; padding: 0.3rem 0.6rem; border-radius: var(--radius-sm); cursor: pointer; line-height: 1; } -.nav-toggle:hover { background: var(--bg-tertiary); } -@media (max-width: 768px) { - .nav-toggle { display: block; } - .navbar .nav-links { display: none; position: absolute; top: var(--nav-height); left: 0; right: 0; background: var(--bg-secondary); border-bottom: 1px solid var(--border-color); flex-direction: column; padding: 1rem; z-index: 999; box-shadow: var(--shadow-md); } - .navbar .nav-links.open { display: flex; } - .navbar .nav-links a { padding: 0.75rem 1rem; border-radius: var(--radius-sm); width: 100%; } - .navbar .nav-inner { flex-wrap: wrap; gap: 0.5rem; } - .hero h1 { font-size: 2rem; } - .hero .subtitle { font-size: 1rem; } - .product-grid { grid-template-columns: 1fr; } - .footer-inner { grid-template-columns: 1fr; } - .doc-layout { grid-template-columns: 1fr; } - .doc-sidebar { position: relative; top: 0; height: auto; border-right: none; border-bottom: 1px solid var(--border-color); max-height: 250px; overflow-y: auto; } - .doc-content { padding: 1rem; } - .kid-grid, .editor-grid { grid-template-columns: 1fr; } - .board-nav { grid-template-columns: repeat(2, 1fr); } - .path-selector { grid-template-columns: repeat(2, 1fr); } - .quick-links { grid-template-columns: 1fr; } - .hw-grid { grid-template-columns: 1fr; } - .hero-stats { gap: 1rem; } - .hero-buttons { flex-direction: column; align-items: center; } - .arch-row { flex-direction: column; align-items: center; } - .doc-nav { grid-template-columns: 1fr; } - table { font-size: 0.8rem; } - th, td { padding: 0.4rem 0.5rem; } - .svg-icon svg { max-height: 60px; } - .svg-icon-lg svg { max-height: 80px; } - .hero-illustration { flex: 0 0 auto !important; max-width: 200px; } - .hero-content { flex-direction: column !important; text-align: center !important; } - .hero-text { text-align: center !important; } - .hero-text .hero-buttons { justify-content: center; } - .svg-isometric { transform: perspective(600px) rotateX(8deg) rotateY(-8deg); } - .hw-item .board-svg { max-height: 50px; } -} - -/* ═══════════════════════════════════════════════════════════════ - SVG Illustrations — Animations, Utilities & Layout - ═══════════════════════════════════════════════════════════════ */ - -@keyframes svg-float { - 0% { transform: translateY(0px); } - 100% { transform: translateY(-8px); } -} -@keyframes svg-pulse-glow { - 0%, 100% { opacity: 0.5; } - 50% { opacity: 1; } -} -@keyframes svg-spin-slow { - from { transform: rotate(0deg); } - to { transform: rotate(360deg); } -} -@keyframes svg-bob { - 0%, 100% { transform: translateY(0) rotate(0deg); } - 50% { transform: translateY(-4px) rotate(2deg); } -} -@keyframes svg-draw { - to { stroke-dashoffset: 0; } -} - -.svg-icon { - display: flex; - align-items: center; - justify-content: center; - margin-bottom: 0.75rem; -} -.svg-icon svg { - width: 100%; - height: auto; - max-height: 80px; -} -.svg-icon-sm svg { max-height: 48px; } -.svg-icon-lg svg { max-height: 110px; } - -.svg-isometric { - transform: perspective(800px) rotateX(12deg) rotateY(-12deg); - transform-style: preserve-3d; -} -.svg-float { animation: svg-float 3s ease-in-out infinite alternate; } -.svg-bob { animation: svg-bob 3s ease-in-out infinite; } -.svg-glow-hover:hover svg { filter: drop-shadow(0 0 8px currentColor); transition: filter 0.3s; } - -.card-icon svg { width: 32px; height: 32px; } -.hw-item .svg-icon { margin-bottom: 0.5rem; } -.hw-item .svg-icon svg { max-height: 60px; } -.hw-item .board-svg { max-height: 60px; width: 100%; } - -/* Hero side-by-side layout */ -.hero-content { display: flex; align-items: center; gap: 3rem; text-align: left; } -.hero-text { flex: 1; } -.hero-text h1 { text-align: left; } -.hero-text .subtitle { margin-left: 0; } -.hero-illustration { flex: 0 0 300px; } -.hero-illustration svg { - width: 100%; - height: auto; - filter: drop-shadow(0 8px 32px rgba(88,166,255,0.2)); -} - -/* Project card illustrations */ -.project-card .svg-icon { margin-bottom: 0.5rem; } -.project-card .svg-icon svg { max-height: 70px; } - -/* Kid card illustrations */ -.kid-card .svg-icon { margin-bottom: 0.5rem; } -.kid-card .svg-icon svg { max-height: 64px; } - -/* Search button in navbar */ -.nav-search-btn { - background: none; - border: 1px solid var(--border-color); - color: var(--text-secondary); - cursor: pointer; - padding: 4px 8px; - border-radius: var(--radius-sm); - font-size: 1rem; - transition: all 0.2s; - margin-left: 4px; -} -.nav-search-btn:hover { - color: var(--text-primary); - border-color: var(--blue); - background: var(--blue-dim); -} - -/* Search overlay */ -.search-overlay[hidden] { display: none; } -.search-overlay { - position: fixed; - inset: 0; - z-index: 9999; - background: rgba(0, 0, 0, 0.6); - display: flex; - align-items: flex-start; - justify-content: center; - padding-top: 15vh; - backdrop-filter: blur(4px); -} -.search-modal { - background: var(--bg-secondary); - border: 1px solid var(--border-color); - border-radius: var(--radius-lg); - width: 90%; - max-width: 560px; - box-shadow: 0 16px 48px rgba(0, 0, 0, 0.4); - overflow: hidden; -} -.search-header { - display: flex; - align-items: center; - gap: 8px; - padding: 12px 16px; - border-bottom: 1px solid var(--border-color); -} -.search-header .search-icon { - font-size: 1.1rem; - color: var(--text-secondary); -} -.search-input { - flex: 1; - background: none; - border: none; - color: var(--text-primary); - font-size: 1rem; - outline: none; -} -.search-input::placeholder { color: var(--text-muted); } -.search-kbd { - background: var(--bg-tertiary); - border: 1px solid var(--border-color); - border-radius: 4px; - padding: 2px 6px; - font-size: 0.75rem; - color: var(--text-secondary); - font-family: inherit; -} -.search-results { - list-style: none; - margin: 0; - padding: 8px; - max-height: 340px; - overflow-y: auto; -} -.search-result-item a { - display: block; - padding: 8px 12px; - border-radius: var(--radius-sm); - text-decoration: none; - color: var(--text-primary); - transition: background 0.15s; -} -.search-result-item a:hover { - background: var(--bg-hover); -} -.search-result-item a strong { - display: block; - font-size: 0.92rem; -} -.search-result-item a span { - display: block; - font-size: 0.82rem; - color: var(--text-secondary); - margin-top: 2px; -} - -/* Scroll-to-top button */ -.scroll-top-btn { - position: fixed; - bottom: 2rem; - right: 2rem; - width: 40px; - height: 40px; - border-radius: 50%; - background: var(--bg-card); - border: 1px solid var(--border-color); - color: var(--text-primary); - font-size: 1.2rem; - cursor: pointer; - display: none; - align-items: center; - justify-content: center; - transition: all 0.2s; - z-index: 100; -} -.scroll-top-btn:hover { - background: var(--blue-dim); - border-color: var(--blue); -} - -/* ═══════════════════════════════════════════════════════════════ - Scroll Reveal Animations - ═══════════════════════════════════════════════════════════════ */ -.eos-reveal { - opacity: 0; - transform: translateY(24px); - transition: opacity 0.6s ease-out, transform 0.6s ease-out; -} -.eos-reveal.eos-visible { - opacity: 1; - transform: translateY(0); -} -@media (prefers-reduced-motion: reduce) { - .eos-reveal { opacity: 1; transform: none; transition: none; } - .svg-float, .svg-bob { animation: none; } - * { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; } -} - -/* ═══════════════════════════════════════════════════════════════ - Skip-to-content & Focus Styles - ═══════════════════════════════════════════════════════════════ */ -.skip-to-content { - position: absolute; - top: -100px; - left: 50%; - transform: translateX(-50%); - padding: 0.75rem 1.5rem; - background: var(--blue); - color: #fff; - border-radius: 0 0 var(--radius-sm) var(--radius-sm); - z-index: 10000; - font-weight: 600; - transition: top 0.3s; -} -.skip-to-content:focus { - top: 0; - text-decoration: none; - color: #fff; -} -:focus-visible { - outline: 2px solid var(--blue); - outline-offset: 2px; -} -a:focus-visible, button:focus-visible { - outline: 2px solid var(--blue); - outline-offset: 2px; - border-radius: 2px; -} - -/* ═══════════════════════════════════════════════════════════════ - eBot AI Chat Widget - ═══════════════════════════════════════════════════════════════ */ -#ebot-fab { - position: fixed; - bottom: 1.5rem; - right: 5rem; - width: 52px; - height: 52px; - border-radius: 50%; - background: linear-gradient(135deg, var(--blue), var(--purple)); - border: none; - color: #fff; - cursor: pointer; - display: flex; - align-items: center; - justify-content: center; - box-shadow: 0 4px 16px rgba(88,166,255,0.4); - z-index: 9990; - transition: all 0.3s; -} -#ebot-fab:hover { - transform: scale(1.1); - box-shadow: 0 6px 24px rgba(88,166,255,0.5); -} -#ebot-fab.active { - background: linear-gradient(135deg, var(--purple), var(--pink)); -} -#ebot-panel { - position: fixed; - bottom: 5.5rem; - right: 1.5rem; - width: 380px; - max-height: 520px; - background: var(--bg-secondary); - border: 1px solid var(--border-color); - border-radius: var(--radius-lg); - box-shadow: 0 16px 48px rgba(0,0,0,0.5); - z-index: 9991; - display: flex; - flex-direction: column; - overflow: hidden; -} -#ebot-panel[hidden] { display: none; } -.ebot-header { - display: flex; - align-items: center; - justify-content: space-between; - padding: 0.75rem 1rem; - background: linear-gradient(135deg, rgba(88,166,255,0.15), rgba(188,140,255,0.15)); - border-bottom: 1px solid var(--border-color); -} -.ebot-title { - display: flex; - align-items: center; - gap: 8px; - font-weight: 700; - font-size: 0.9rem; - color: var(--text-primary); -} -.ebot-dot { - width: 8px; - height: 8px; - background: var(--green); - border-radius: 50%; - animation: pulse 2s infinite; -} -@keyframes pulse { 0%,100%{opacity:1}50%{opacity:0.4} } -.ebot-close { - background: none; - border: none; - color: var(--text-secondary); - font-size: 1.4rem; - cursor: pointer; - padding: 0 4px; - line-height: 1; -} -.ebot-close:hover { color: var(--text-primary); } -.ebot-messages { - flex: 1; - overflow-y: auto; - padding: 1rem; - display: flex; - flex-direction: column; - gap: 0.75rem; - max-height: 320px; - scrollbar-width: thin; - scrollbar-color: var(--border-color) transparent; -} -.ebot-msg { display: flex; } -.ebot-bot { justify-content: flex-start; } -.ebot-user { justify-content: flex-end; } -.ebot-bubble { - max-width: 85%; - padding: 0.6rem 0.9rem; - border-radius: 12px; - font-size: 0.85rem; - line-height: 1.5; - word-wrap: break-word; -} -.ebot-bot .ebot-bubble { - background: var(--bg-card); - border: 1px solid var(--border-color); - color: var(--text-primary); - border-bottom-left-radius: 4px; -} -.ebot-user .ebot-bubble { - background: linear-gradient(135deg, var(--blue), var(--purple)); - color: #fff; - border-bottom-right-radius: 4px; -} -.ebot-typing { - color: var(--text-muted); - font-style: italic; -} -.ebot-suggestions { - display: flex; - gap: 0.4rem; - padding: 0.5rem 1rem; - flex-wrap: wrap; - border-top: 1px solid var(--border-color); -} -.ebot-suggest-btn { - padding: 4px 10px; - background: var(--bg-card); - border: 1px solid var(--border-color); - border-radius: 100px; - color: var(--text-secondary); - font-size: 0.75rem; - cursor: pointer; - transition: all 0.2s; -} -.ebot-suggest-btn:hover { - background: var(--blue-dim); - border-color: var(--blue); - color: var(--blue); -} -.ebot-input-area { - display: flex; - gap: 0.5rem; - padding: 0.75rem; - border-top: 1px solid var(--border-color); - background: var(--bg-primary); -} -.ebot-input { - flex: 1; - padding: 0.5rem 0.75rem; - background: var(--bg-card); - border: 1px solid var(--border-color); - border-radius: var(--radius-sm); - color: var(--text-primary); - font-size: 0.85rem; - outline: none; - font-family: var(--font-sans); -} -.ebot-input:focus { - border-color: var(--blue); - box-shadow: 0 0 0 2px var(--blue-dim); -} -.ebot-input::placeholder { color: var(--text-muted); } -.ebot-send { - padding: 0.5rem 0.75rem; - background: var(--blue); - border: none; - border-radius: var(--radius-sm); - color: #fff; - cursor: pointer; - font-size: 1rem; - transition: background 0.2s; -} -.ebot-send:hover { background: #79b8ff; } - -@media (max-width: 480px) { - #ebot-panel { - right: 0.5rem; - left: 0.5rem; - width: auto; - bottom: 4.5rem; - max-height: 70vh; - } - #ebot-fab { bottom: 1rem; right: 1rem; } -} - -/* ═══════════════════════════════════════════════════════════════ - Colourful Refresh — Additive Visual Polish - All rules below are purely additive: they extend existing - selectors, add new pseudo-elements, or add new keyframes. - No existing CSS variable values are modified, and the - prefers-reduced-motion block above (line ~590) already - disables animations via the universal `*` selector. - ═══════════════════════════════════════════════════════════════ */ - -/* 1. Rainbow strip — fixed 3px bar at the very top of every page */ -body::before { - content: ''; - position: fixed; - top: 0; - left: 0; - right: 0; - height: 3px; - background: linear-gradient( - 90deg, - var(--blue), var(--green), var(--purple), var(--orange), - var(--cyan), var(--pink), var(--yellow), var(--red), var(--blue) - ); - background-size: 200% 100%; - z-index: 10000; - pointer-events: none; - animation: rainbowSlide 12s linear infinite; -} -@keyframes rainbowSlide { - 0% { background-position: 0% 50%; } - 100% { background-position: 200% 50%; } -} - -/* 2. Section-divider underline gradient under every H2 - (skip section-title which is centered & borderless by design) */ -h2:not(.section-title) { - position: relative; - border-bottom-color: transparent; -} -h2:not(.section-title)::after { - content: ''; - position: absolute; - left: 0; - right: 0; - bottom: -1px; - height: 2px; - background: linear-gradient( - 90deg, - var(--blue), var(--green), var(--purple), var(--orange), - var(--cyan), var(--pink), var(--yellow), var(--red) - ); - border-radius: 2px; - opacity: 0.85; -} - -/* 3. Brighter card-hover glow — colour-matched per accent */ -.card-eos:hover { box-shadow: 0 10px 32px rgba(88,166,255,0.40), 0 0 16px rgba(88,166,255,0.25); } -.card-eboot:hover { box-shadow: 0 10px 32px rgba(63,185,80,0.40), 0 0 16px rgba(63,185,80,0.25); } -.card-ebuild:hover { box-shadow: 0 10px 32px rgba(240,136,62,0.40), 0 0 16px rgba(240,136,62,0.25); } -.card-eipc:hover { box-shadow: 0 10px 32px rgba(121,192,255,0.40), 0 0 16px rgba(121,192,255,0.25); } -.card-eai:hover { box-shadow: 0 10px 32px rgba(188,140,255,0.40), 0 0 16px rgba(188,140,255,0.25); } -.card-eni:hover { box-shadow: 0 10px 32px rgba(247,120,186,0.40), 0 0 16px rgba(247,120,186,0.25); } -.card-eosuite:hover { box-shadow: 0 10px 32px rgba(227,179,65,0.40), 0 0 16px rgba(227,179,65,0.25); } -.card-eosim:hover { box-shadow: 0 10px 32px rgba(248,81,73,0.40), 0 0 16px rgba(248,81,73,0.25); } - -/* book-card / sim-card / project-card / kid-card / path-btn — generic colourful lift */ -.book-card:hover, -.sim-card:hover, -.project-card:hover, -.kid-card:hover, -.path-btn:hover { - transform: translateY(-4px); - box-shadow: 0 10px 32px rgba(188,140,255,0.30), 0 0 16px rgba(88,166,255,0.20); - transition: transform 0.25s ease, box-shadow 0.25s ease; -} - -/* 4. Hero aurora — slow hue-rotate layer over the existing radial glows */ -.hero::after { - content: ''; - position: absolute; - inset: 0; - background: - radial-gradient(circle at 20% 30%, rgba(247,120,186,0.08) 0%, transparent 55%), - radial-gradient(circle at 80% 70%, rgba(63,185,80,0.06) 0%, transparent 55%); - mix-blend-mode: screen; - pointer-events: none; - animation: heroAurora 8s linear infinite alternate; - z-index: 0; -} -@keyframes heroAurora { - 0% { filter: hue-rotate(0deg) saturate(1.0); opacity: 0.85; } - 100% { filter: hue-rotate(30deg) saturate(1.2); opacity: 1.00; } -} - -/* 5. Nav-pill colourful underline on hover */ -.navbar .nav-links li { position: relative; } -.navbar .nav-links li a { position: relative; } -.navbar .nav-links li a::after { - content: ''; - position: absolute; - left: 1rem; - right: 1rem; - bottom: 4px; - height: 2px; - opacity: 0; - border-radius: 2px; - transition: opacity 0.2s ease; - pointer-events: none; -} -.navbar .nav-links li:nth-child(8n+1) a::after { background: var(--blue); } -.navbar .nav-links li:nth-child(8n+2) a::after { background: var(--green); } -.navbar .nav-links li:nth-child(8n+3) a::after { background: var(--purple); } -.navbar .nav-links li:nth-child(8n+4) a::after { background: var(--orange); } -.navbar .nav-links li:nth-child(8n+5) a::after { background: var(--cyan); } -.navbar .nav-links li:nth-child(8n+6) a::after { background: var(--pink); } -.navbar .nav-links li:nth-child(8n+7) a::after { background: var(--yellow); } -.navbar .nav-links li:nth-child(8n) a::after { background: var(--red); } -.navbar .nav-links li a:hover::after, -.navbar .nav-links li a.active::after { opacity: 1; } - -/* 6. Footer accent bar — gradient stripe on top edge */ -.footer { position: relative; } -.footer::before { - content: ''; - position: absolute; - top: 0; - left: 0; - right: 0; - height: 3px; - background: linear-gradient( - 90deg, - var(--blue), var(--green), var(--purple), var(--orange), - var(--cyan), var(--pink), var(--yellow), var(--red) - ); - background-size: 200% 100%; - animation: rainbowSlide 18s linear infinite; - pointer-events: none; -} - -/* 7. Social-media link pills (footer "Connect" column) */ -.social-list { list-style: none; padding: 0; } -.social-list li { margin-bottom: 0.5rem; } -.social-link { - display: inline-flex; - align-items: center; - gap: 0.55rem; - padding: 0.4rem 0.75rem; - border-radius: 999px; - background: var(--bg-card); - border: 1px solid var(--border-color); - color: var(--text-secondary) !important; - font-size: 0.85rem; - font-weight: 500; - transition: all 0.2s ease; - text-decoration: none !important; -} -.social-link:hover { transform: translateY(-2px); color: var(--text-primary) !important; } -.social-icon { - display: inline-flex; - align-items: center; - justify-content: center; - width: 22px; - height: 22px; - border-radius: 50%; - font-weight: 800; - font-size: 0.8rem; - font-family: var(--font-sans); - line-height: 1; -} -.social-youtube .social-icon { background: var(--red-dim); color: var(--red); } -.social-linkedin .social-icon { background: var(--blue-dim); color: var(--blue); font-style: italic; } -.social-x .social-icon { background: var(--bg-tertiary); color: var(--text-primary); } -.social-facebook .social-icon { background: var(--purple-dim); color: var(--purple); font-family: Georgia, serif; font-style: italic; } -.social-youtube:hover { border-color: var(--red); box-shadow: 0 6px 18px rgba(248,81,73,0.30); } -.social-linkedin:hover { border-color: var(--blue); box-shadow: 0 6px 18px rgba(88,166,255,0.30); } -.social-x:hover { border-color: var(--text-primary); box-shadow: 0 6px 18px rgba(230,237,243,0.20); } -.social-facebook:hover { border-color: var(--purple); box-shadow: 0 6px 18px rgba(188,140,255,0.30); } diff --git a/tests/seo.spec.js b/tests/seo.spec.js index a2012c6..eca2a2e 100644 --- a/tests/seo.spec.js +++ b/tests/seo.spec.js @@ -143,13 +143,9 @@ test.describe('SEO: Robots & Sitemap', () => { await ctx.close(); }); - test('sitemap.xml is valid', async ({ browser }) => { - const ctx = await browser.newContext(); - const p = await ctx.newPage(); - const response = await p.goto(`${BASE}/sitemap.xml`); + test('sitemap.xml is valid', async ({ request }) => { + const response = await request.get(`${BASE}/sitemap.xml`); expect(response.status()).toBe(200); - const text = await p.textContent('body'); - expect(text).toContain('embeddedos-org.github.io'); - await ctx.close(); + expect(await response.text()).toContain('embeddedos-org.github.io'); }); });