diff --git a/.github/workflows/deploy-pages.yml b/.github/workflows/deploy-pages.yml index b0884d3..b23ef57 100644 --- a/.github/workflows/deploy-pages.yml +++ b/.github/workflows/deploy-pages.yml @@ -1,4 +1,4 @@ -name: Deploy Astro to GitHub Pages +name: Deploy Static Site + Lab to GitHub Pages on: push: @@ -26,14 +26,35 @@ jobs: with: node-version: 22 cache: npm + cache-dependency-path: | + package-lock.json + apps/lab-interactif/package-lock.json - - name: Install dependencies + - name: Install root dependencies run: npm ci - - name: Build - run: npm run build - env: - PUBLIC_GTM_CONTAINER_ID: GTM-5SLM67QF + - name: Install lab dependencies + run: npm ci --prefix apps/lab-interactif + + - name: Build lab module + run: npm run lab:build + + - name: Prepare pages artifact + run: | + mkdir -p .pages-dist + cp index.html .pages-dist/ + cp styles.css .pages-dist/ + cp script.js .pages-dist/ + cp robots.txt .pages-dist/ + cp sitemap.xml .pages-dist/ + cp favicon.svg .pages-dist/ + cp favicon.ico .pages-dist/ + cp favicon-32x32.png .pages-dist/ + cp favicon-16x16.png .pages-dist/ + cp apple-touch-icon.png .pages-dist/ + cp -R assets .pages-dist/assets + cp -R lab .pages-dist/lab + if [ -f CNAME ]; then cp CNAME .pages-dist/; fi - name: Setup Pages uses: actions/configure-pages@v5 @@ -41,7 +62,7 @@ jobs: - name: Upload artifact uses: actions/upload-pages-artifact@v3 with: - path: ./dist + path: ./.pages-dist deploy: needs: build diff --git a/.gitignore b/.gitignore index b3550c9..652cb05 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,12 @@ dist/ storybook-static/ .astro/ .DS_Store + +# GH Pages / builds locaux (sorties CI ou previews locales) +.pages-dist/ + +# Artefacts locaux de workflow / QA +output/ +tmp/ +.tmp/ +.playwright-cli/ diff --git a/.storybook/preview.ts b/.storybook/preview.ts index fa12844..e5411bb 100644 --- a/.storybook/preview.ts +++ b/.storybook/preview.ts @@ -1,14 +1,20 @@ import type { Preview } from '@storybook/react-vite'; import '../src/styles/global.css'; +if (typeof document !== 'undefined') { + // Align Storybook rendering with the site default (atelier) theme. + document.documentElement.setAttribute('data-theme', 'light'); +} + const preview: Preview = { parameters: { layout: 'fullscreen', backgrounds: { - default: 'studio-dark', + default: 'atelier', values: [ - { name: 'studio-dark', value: '#0f0e17' }, - { name: 'studio-deep', value: '#151325' } + { name: 'atelier', value: '#f4eee3' }, + { name: 'atelier-soft', value: '#fbf7ef' }, + { name: 'ink', value: '#0b0a09' } ] } } diff --git a/apple-touch-icon.png b/apple-touch-icon.png new file mode 100644 index 0000000..d46a9ea Binary files /dev/null and b/apple-touch-icon.png differ diff --git a/apps/lab-interactif/index.html b/apps/lab-interactif/index.html new file mode 100644 index 0000000..3f69a06 --- /dev/null +++ b/apps/lab-interactif/index.html @@ -0,0 +1,15 @@ + + + + + + Lab interactif - L'electron rare + + + +
+ + + diff --git a/apps/lab-interactif/package-lock.json b/apps/lab-interactif/package-lock.json new file mode 100644 index 0000000..c61464b --- /dev/null +++ b/apps/lab-interactif/package-lock.json @@ -0,0 +1,1834 @@ +{ + "name": "lab-interactif", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "lab-interactif", + "version": "0.1.0", + "dependencies": { + "react": "^19.1.1", + "react-dom": "^19.1.1", + "react-router-dom": "^7.13.1" + }, + "devDependencies": { + "@vitejs/plugin-react": "^5.0.4", + "vite": "^7.3.1" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", + "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.28.5", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz", + "integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz", + "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-module-transforms": "^7.28.6", + "@babel/helpers": "^7.28.6", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/traverse": "^7.29.0", + "@babel/types": "^7.29.0", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.29.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz", + "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.0", + "@babel/types": "^7.29.0", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", + "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.28.6", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", + "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", + "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.28.6", + "@babel/helper-validator-identifier": "^7.28.5", + "@babel/traverse": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz", + "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.6.tgz", + "integrity": "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.0.tgz", + "integrity": "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.0" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz", + "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz", + "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", + "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.28.6", + "@babel/parser": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz", + "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/types": "^7.29.0", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.3.tgz", + "integrity": "sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.3.tgz", + "integrity": "sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.3.tgz", + "integrity": "sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.3.tgz", + "integrity": "sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.3.tgz", + "integrity": "sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.3.tgz", + "integrity": "sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.3.tgz", + "integrity": "sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.3.tgz", + "integrity": "sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.3.tgz", + "integrity": "sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.3.tgz", + "integrity": "sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.3.tgz", + "integrity": "sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.3.tgz", + "integrity": "sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.3.tgz", + "integrity": "sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.3.tgz", + "integrity": "sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.3.tgz", + "integrity": "sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.3.tgz", + "integrity": "sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.3.tgz", + "integrity": "sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.3.tgz", + "integrity": "sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.3.tgz", + "integrity": "sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.3.tgz", + "integrity": "sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.3.tgz", + "integrity": "sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.3.tgz", + "integrity": "sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.3.tgz", + "integrity": "sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.3.tgz", + "integrity": "sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.3.tgz", + "integrity": "sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.3.tgz", + "integrity": "sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-rc.3", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.3.tgz", + "integrity": "sha512-eybk3TjzzzV97Dlj5c+XrBFW57eTNhzod66y9HrBlzJ6NsCrWCp/2kaPS3K9wJmurBC0Tdw4yPjXKZqlznim3Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.59.0.tgz", + "integrity": "sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.59.0.tgz", + "integrity": "sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.59.0.tgz", + "integrity": "sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.59.0.tgz", + "integrity": "sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.59.0.tgz", + "integrity": "sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.59.0.tgz", + "integrity": "sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.59.0.tgz", + "integrity": "sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.59.0.tgz", + "integrity": "sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.59.0.tgz", + "integrity": "sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.59.0.tgz", + "integrity": "sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.59.0.tgz", + "integrity": "sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.59.0.tgz", + "integrity": "sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.59.0.tgz", + "integrity": "sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.59.0.tgz", + "integrity": "sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.59.0.tgz", + "integrity": "sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.59.0.tgz", + "integrity": "sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.59.0.tgz", + "integrity": "sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.59.0.tgz", + "integrity": "sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.59.0.tgz", + "integrity": "sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.59.0.tgz", + "integrity": "sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.59.0.tgz", + "integrity": "sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.59.0.tgz", + "integrity": "sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.59.0.tgz", + "integrity": "sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.59.0.tgz", + "integrity": "sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.59.0.tgz", + "integrity": "sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", + "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.2" + } + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@vitejs/plugin-react": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-5.1.4.tgz", + "integrity": "sha512-VIcFLdRi/VYRU8OL/puL7QXMYafHmqOnwTZY50U1JPlCNj30PxCMx65c494b1K9be9hX83KVt0+gTEwTWLqToA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.29.0", + "@babel/plugin-transform-react-jsx-self": "^7.27.1", + "@babel/plugin-transform-react-jsx-source": "^7.27.1", + "@rolldown/pluginutils": "1.0.0-rc.3", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.18.0" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "peerDependencies": { + "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" + } + }, + "node_modules/baseline-browser-mapping": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.0.tgz", + "integrity": "sha512-lIyg0szRfYbiy67j9KN8IyeD7q7hcmqnJ1ddWmNt19ItGpNN64mnllmxUNFIOdOm6by97jlL6wfpTTJrmnjWAA==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/browserslist": { + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", + "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "baseline-browser-mapping": "^2.9.0", + "caniuse-lite": "^1.0.30001759", + "electron-to-chromium": "^1.5.263", + "node-releases": "^2.0.27", + "update-browserslist-db": "^1.2.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001775", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001775.tgz", + "integrity": "sha512-s3Qv7Lht9zbVKE9XoTyRG6wVDCKdtOFIjBGg3+Yhn6JaytuNKPIjBMTMIY1AnOH3seL5mvF+x33oGAyK3hVt3A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cookie": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz", + "integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "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/electron-to-chromium": { + "version": "1.5.302", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.302.tgz", + "integrity": "sha512-sM6HAN2LyK82IyPBpznDRqlTQAtuSaO+ShzFiWTvoMJLHyZ+Y39r8VMfHzwbU8MVBzQ4Wdn85+wlZl2TLGIlwg==", + "dev": true, + "license": "ISC" + }, + "node_modules/esbuild": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.3.tgz", + "integrity": "sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.27.3", + "@esbuild/android-arm": "0.27.3", + "@esbuild/android-arm64": "0.27.3", + "@esbuild/android-x64": "0.27.3", + "@esbuild/darwin-arm64": "0.27.3", + "@esbuild/darwin-x64": "0.27.3", + "@esbuild/freebsd-arm64": "0.27.3", + "@esbuild/freebsd-x64": "0.27.3", + "@esbuild/linux-arm": "0.27.3", + "@esbuild/linux-arm64": "0.27.3", + "@esbuild/linux-ia32": "0.27.3", + "@esbuild/linux-loong64": "0.27.3", + "@esbuild/linux-mips64el": "0.27.3", + "@esbuild/linux-ppc64": "0.27.3", + "@esbuild/linux-riscv64": "0.27.3", + "@esbuild/linux-s390x": "0.27.3", + "@esbuild/linux-x64": "0.27.3", + "@esbuild/netbsd-arm64": "0.27.3", + "@esbuild/netbsd-x64": "0.27.3", + "@esbuild/openbsd-arm64": "0.27.3", + "@esbuild/openbsd-x64": "0.27.3", + "@esbuild/openharmony-arm64": "0.27.3", + "@esbuild/sunos-x64": "0.27.3", + "@esbuild/win32-arm64": "0.27.3", + "@esbuild/win32-ia32": "0.27.3", + "@esbuild/win32-x64": "0.27.3" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "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/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/node-releases": { + "version": "2.0.27", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", + "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/react": { + "version": "19.2.4", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz", + "integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "19.2.4", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.4.tgz", + "integrity": "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==", + "license": "MIT", + "dependencies": { + "scheduler": "^0.27.0" + }, + "peerDependencies": { + "react": "^19.2.4" + } + }, + "node_modules/react-refresh": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.18.0.tgz", + "integrity": "sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-router": { + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.13.1.tgz", + "integrity": "sha512-td+xP4X2/6BJvZoX6xw++A2DdEi++YypA69bJUV5oVvqf6/9/9nNlD70YO1e9d3MyamJEBQFEzk6mbfDYbqrSA==", + "license": "MIT", + "dependencies": { + "cookie": "^1.0.1", + "set-cookie-parser": "^2.6.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + } + } + }, + "node_modules/react-router-dom": { + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.13.1.tgz", + "integrity": "sha512-UJnV3Rxc5TgUPJt2KJpo1Jpy0OKQr0AjgbZzBFjaPJcFOb2Y8jA5H3LT8HUJAiRLlWrEXWHbF1Z4SCZaQjWDHw==", + "license": "MIT", + "dependencies": { + "react-router": "7.13.1" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + } + }, + "node_modules/rollup": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.59.0.tgz", + "integrity": "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.59.0", + "@rollup/rollup-android-arm64": "4.59.0", + "@rollup/rollup-darwin-arm64": "4.59.0", + "@rollup/rollup-darwin-x64": "4.59.0", + "@rollup/rollup-freebsd-arm64": "4.59.0", + "@rollup/rollup-freebsd-x64": "4.59.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.59.0", + "@rollup/rollup-linux-arm-musleabihf": "4.59.0", + "@rollup/rollup-linux-arm64-gnu": "4.59.0", + "@rollup/rollup-linux-arm64-musl": "4.59.0", + "@rollup/rollup-linux-loong64-gnu": "4.59.0", + "@rollup/rollup-linux-loong64-musl": "4.59.0", + "@rollup/rollup-linux-ppc64-gnu": "4.59.0", + "@rollup/rollup-linux-ppc64-musl": "4.59.0", + "@rollup/rollup-linux-riscv64-gnu": "4.59.0", + "@rollup/rollup-linux-riscv64-musl": "4.59.0", + "@rollup/rollup-linux-s390x-gnu": "4.59.0", + "@rollup/rollup-linux-x64-gnu": "4.59.0", + "@rollup/rollup-linux-x64-musl": "4.59.0", + "@rollup/rollup-openbsd-x64": "4.59.0", + "@rollup/rollup-openharmony-arm64": "4.59.0", + "@rollup/rollup-win32-arm64-msvc": "4.59.0", + "@rollup/rollup-win32-ia32-msvc": "4.59.0", + "@rollup/rollup-win32-x64-gnu": "4.59.0", + "@rollup/rollup-win32-x64-msvc": "4.59.0", + "fsevents": "~2.3.2" + } + }, + "node_modules/scheduler": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", + "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", + "license": "MIT" + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/set-cookie-parser": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.2.tgz", + "integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==", + "license": "MIT" + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/vite": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.1.tgz", + "integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.27.0", + "fdir": "^6.5.0", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.15" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "lightningcss": "^1.21.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + } + } +} diff --git a/apps/lab-interactif/package.json b/apps/lab-interactif/package.json new file mode 100644 index 0000000..7b18070 --- /dev/null +++ b/apps/lab-interactif/package.json @@ -0,0 +1,20 @@ +{ + "name": "lab-interactif", + "version": "0.1.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview" + }, + "dependencies": { + "react": "^19.1.1", + "react-dom": "^19.1.1", + "react-router-dom": "^7.13.1" + }, + "devDependencies": { + "@vitejs/plugin-react": "^5.0.4", + "vite": "^7.3.1" + } +} diff --git a/apps/lab-interactif/src/App.jsx b/apps/lab-interactif/src/App.jsx new file mode 100644 index 0000000..e383c85 --- /dev/null +++ b/apps/lab-interactif/src/App.jsx @@ -0,0 +1,41 @@ +import { NavLink, Route, Routes } from 'react-router-dom'; +import { LabHomePage } from './pages/LabHomePage'; +import { SignalsPage } from './pages/SignalsPage'; +import { PrototypesPage } from './pages/PrototypesPage'; + +export function App() { + return ( +
+
+
+ + Retour site principal + + +
+
+ +
+ + } /> + } /> + } /> + +
+
+ ); +} diff --git a/apps/lab-interactif/src/main.jsx b/apps/lab-interactif/src/main.jsx new file mode 100644 index 0000000..d19a8b0 --- /dev/null +++ b/apps/lab-interactif/src/main.jsx @@ -0,0 +1,13 @@ +import React from 'react'; +import { createRoot } from 'react-dom/client'; +import { HashRouter } from 'react-router-dom'; +import { App } from './App'; +import './styles.css'; + +createRoot(document.getElementById('root')).render( + + + + + +); diff --git a/apps/lab-interactif/src/pages/LabHomePage.jsx b/apps/lab-interactif/src/pages/LabHomePage.jsx new file mode 100644 index 0000000..0162d23 --- /dev/null +++ b/apps/lab-interactif/src/pages/LabHomePage.jsx @@ -0,0 +1,27 @@ +export function LabHomePage() { + return ( +
+

Module C

+

Lab interactif React Router

+

+ Cet espace accueille les experiences interactives qui demandent un routage client, + une logique d'etat plus riche et des iterations UI rapides. +

+
+
+

Pourquoi ce module

+

+ Conserver une base statique lisible pour la conversion, et isoler les zones + experimentales sans alourdir le site principal. +

+
+
+

Contrat d'integration

+

+ Chemin public: /lab/. Deploiement via build Vite, independent du template statique. +

+
+
+
+ ); +} diff --git a/apps/lab-interactif/src/pages/PrototypesPage.jsx b/apps/lab-interactif/src/pages/PrototypesPage.jsx new file mode 100644 index 0000000..a2b3a89 --- /dev/null +++ b/apps/lab-interactif/src/pages/PrototypesPage.jsx @@ -0,0 +1,37 @@ +const prototypes = [ + { + title: 'Flow mission brief', + status: 'In review', + desc: 'Wizard de cadrage mission avec sorties DA + tracking event map.' + }, + { + title: 'Interactive scene card', + status: 'Draft', + desc: 'Carte projet animable pour narration systeme et preuves live.' + }, + { + title: 'Lab telemetry shell', + status: 'Scaffolded', + desc: 'Base React Router prete pour brancher des donnees de suivi internes.' + } +]; + +export function PrototypesPage() { + return ( +
+

Prototypes

+

Backlog interactif

+ +
+ ); +} diff --git a/apps/lab-interactif/src/pages/SignalsPage.jsx b/apps/lab-interactif/src/pages/SignalsPage.jsx new file mode 100644 index 0000000..1815492 --- /dev/null +++ b/apps/lab-interactif/src/pages/SignalsPage.jsx @@ -0,0 +1,24 @@ +const signals = [ + { label: 'Interaction density', value: '74%', note: 'navigation testee sur 3 patterns' }, + { label: 'Prototype confidence', value: 'B+', note: 'gates a11y et perf a renforcer' }, + { label: 'Narrative coherence', value: '82%', note: 'DA premium respectee sur les vues clefs' } +]; + +export function SignalsPage() { + return ( +
+

Signals

+

Tableau de signaux

+

Vue rapide sur l'etat des experiments interactifs en cours.

+
+ {signals.map((signal) => ( +
+

{signal.label}

+ {signal.value} +

{signal.note}

+
+ ))} +
+
+ ); +} diff --git a/apps/lab-interactif/src/styles.css b/apps/lab-interactif/src/styles.css new file mode 100644 index 0000000..7658f81 --- /dev/null +++ b/apps/lab-interactif/src/styles.css @@ -0,0 +1,224 @@ +@import url('https://fonts.googleapis.com/css2?family=Manrope:wght@400;500;600;700;800&family=Prata&display=swap'); + +:root { + --lab-bg: #171a1e; + --lab-surface: #222830; + --lab-surface-soft: #2b3441; + --lab-line: #3d4b5d; + --lab-text: #f2f4f8; + --lab-muted: #b8c4d3; + --lab-accent: #f2a666; + --lab-accent-2: #7bd5cf; +} + +* { + box-sizing: border-box; +} + +html, +body, +#root { + min-height: 100%; +} + +body { + margin: 0; + font-family: 'Manrope', 'Segoe UI', sans-serif; + color: var(--lab-text); + background: + radial-gradient(1000px 500px at 15% -20%, rgba(242, 166, 102, 0.18), transparent 55%), + radial-gradient(800px 460px at 100% 0%, rgba(123, 213, 207, 0.2), transparent 55%), + var(--lab-bg); +} + +.lab-shell { + width: min(1080px, 92vw); + margin: 0 auto; +} + +.lab-header { + position: sticky; + top: 0; + z-index: 20; + border-bottom: 1px solid var(--lab-line); + background: color-mix(in oklab, var(--lab-bg) 86%, black 14%); + backdrop-filter: blur(8px); +} + +.lab-header .lab-shell { + min-height: 74px; + display: flex; + align-items: center; + justify-content: space-between; + gap: 1rem; +} + +.lab-brand { + display: inline-flex; + text-decoration: none; + color: var(--lab-accent); + font-weight: 700; +} + +.lab-header ul { + margin: 0; + padding: 0; + list-style: none; + display: flex; + gap: 0.5rem; + flex-wrap: wrap; +} + +.lab-header a { + min-height: 2.2rem; + display: inline-flex; + align-items: center; + text-decoration: none; + color: var(--lab-text); + border: 1px solid transparent; + border-radius: 999px; + padding: 0 0.85rem; + font-size: 0.9rem; + font-weight: 600; +} + +.lab-header a.active, +.lab-header a:hover, +.lab-header a:focus-visible { + border-color: var(--lab-line); + background: color-mix(in oklab, var(--lab-surface-soft) 80%, var(--lab-accent-2) 20%); +} + +main { + padding-block: 1.2rem 2.8rem; +} + +.lab-panel { + border: 1px solid var(--lab-line); + border-radius: 18px; + background: linear-gradient(180deg, var(--lab-surface), color-mix(in oklab, var(--lab-surface) 70%, black 30%)); + box-shadow: 0 16px 42px rgba(0, 0, 0, 0.28); + padding: 1rem; +} + +.lab-kicker { + margin: 0; + text-transform: uppercase; + letter-spacing: 0.14em; + font-size: 0.72rem; + color: var(--lab-accent-2); + font-weight: 700; +} + +h1, +h2 { + font-family: 'Prata', Georgia, serif; + margin: 0; + font-weight: 400; +} + +h1 { + margin-top: 0.5rem; + font-size: clamp(1.8rem, 5vw, 3rem); +} + +.lab-panel > p { + color: var(--lab-muted); + margin: 0.9rem 0 0; + max-width: 70ch; +} + +.lab-grid { + margin-top: 1rem; + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 0.6rem; +} + +.lab-grid article, +.signal-grid article, +.prototype-list li { + border: 1px solid var(--lab-line); + border-radius: 14px; + background: color-mix(in oklab, var(--lab-surface-soft) 82%, black 18%); + padding: 0.8rem; +} + +.signal-grid { + margin-top: 0.9rem; + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 0.6rem; +} + +.signal-grid strong { + display: block; + margin-top: 0.35rem; + color: var(--lab-accent); + font-size: 1.35rem; +} + +.signal-grid p, +.prototype-list p { + margin: 0.4rem 0 0; + color: var(--lab-muted); +} + +.prototype-list { + margin: 1rem 0 0; + padding: 0; + list-style: none; + display: grid; + gap: 0.58rem; +} + +.prototype-list li { + display: flex; + justify-content: space-between; + gap: 0.8rem; + align-items: flex-start; +} + +.prototype-list span { + border: 1px solid var(--lab-line); + border-radius: 999px; + min-height: 1.9rem; + display: inline-flex; + align-items: center; + padding: 0 0.66rem; + font-size: 0.72rem; + text-transform: uppercase; + letter-spacing: 0.06em; + color: var(--lab-accent-2); +} + +code { + font-family: ui-monospace, SFMono-Regular, Menlo, monospace; + background: rgba(0, 0, 0, 0.25); + border: 1px solid var(--lab-line); + border-radius: 6px; + padding: 0.14rem 0.3rem; +} + +@media (max-width: 900px) { + .signal-grid { + grid-template-columns: 1fr; + } + + .lab-grid { + grid-template-columns: 1fr; + } +} + +@media (max-width: 700px) { + .lab-header .lab-shell { + min-height: auto; + flex-direction: column; + align-items: flex-start; + padding-block: 0.7rem; + } + + .prototype-list li { + flex-direction: column; + } +} diff --git a/apps/lab-interactif/vite.config.js b/apps/lab-interactif/vite.config.js new file mode 100644 index 0000000..f394788 --- /dev/null +++ b/apps/lab-interactif/vite.config.js @@ -0,0 +1,11 @@ +import { defineConfig } from 'vite'; +import react from '@vitejs/plugin-react'; + +export default defineConfig({ + plugins: [react()], + base: '/lab/', + build: { + outDir: '../../lab', + emptyOutDir: true + } +}); diff --git a/artifacts/figma-capture/2026-03-02/da00-home-figma-capture-log.md b/artifacts/figma-capture/2026-03-02/da00-home-figma-capture-log.md new file mode 100644 index 0000000..7619e4a --- /dev/null +++ b/artifacts/figma-capture/2026-03-02/da00-home-figma-capture-log.md @@ -0,0 +1,70 @@ +# DA-00 — Home page Figma capture log (2026-03-02) + +## Scope exécuté +- Objectif: capturer la home page statique `index.html` avec style `styles.css` pour DA-00 (Desktop/Mobile) +- Branchement cible: `http://127.0.0.1:4174/` +- Typo/Palette: conforme aux tokens déjà en place dans : + - `notes-interne/creative-direction-brief.md` + - `specs/site-github-pages-spec.md` + +## Fichier créé (obligatoire) +1. Capture 390 (`newFile`) — Team utilisée: `team::1358840601337404242` (Full seat) + - `captureId`: `d42b3736-86a0-4317-aba3-db38e3fd8081` + - Viewport exécuté: `390x2600` + - Résultat: **completed** + - Claim URL: `https://www.figma.com/integrations/claim/fnqOdDOU97v7E27LxkV7cn` +2. Capture 390 de secours (réémission initiale) : + - `captureId`: `8e837489-b410-4fe6-bcd9-164cfc06ea28` + - Viewport exécuté: `390x2600` + - Résultat: **completed** + - Claim URL: `https://www.figma.com/integrations/claim/ZKgr7hsRPsU9FxZ1D3C9CC` +3. Capture 768 (`newFile`) : + - `captureId`: `a592d67e-df53-427a-bbc1-451b2cd00072` + - Viewport exécuté: `768x2600` + - Résultat: **completed** + - Claim URL: `https://www.figma.com/integrations/claim/zAedZvfZMYMxY1UfnKftGr` +4. Capture 1024 (`newFile`) : + - `captureId`: `e5039698-8d12-4fbb-b67c-556cc3af48be` + - Viewport exécuté: `1024x2600` + - Résultat: **completed** + - Claim URL: `https://www.figma.com/integrations/claim/6ZP1SHZVN5rgWrig10Lh9i` +5. Capture 1440 (`newFile`) : + - `captureId`: `b7aa2fbd-d715-4522-8b22-acdd6d058b28` + - Viewport exécuté: `1440x2600` + - Résultat: **completed** + - Claim URL: `https://www.figma.com/integrations/claim/ZMeMDAbbfYnDMgfXOeIDA4` + +## Etat actuel +- Le fichier Figma de base est bien créé. +- `existingFile` pour regrouper plusieurs tailles dans le même fichier reste bloqué côté accès MCP (message: `This figma file could not be accessed`) avec `fileKey` de claim. + +## Blocage détecté +- Les appels `existingFile` pour: + - `ZKgr7hsRPsU9FxZ1D3C9CC` + - `fnqOdDOU97v7E27LxkV7cn` + - `zAedZvfZMYMxY1UfnKftGr` + - `6ZP1SHZVN5rgWrig10Lh9i` + - `ZMeMDAbbfYnDMgfXOeIDA4` + retournent systématiquement: + - `This figma file could not be accessed.` +- Docs Figma: mode probable “claim non consommé / résolution du vrai fileKey et permissions” en cours. + +## TODO d’exécution prêt à lancer +1. Réclamer les 4 claims ci-dessus depuis la session Figma connectée (ou les ouvrir en parallèle). +2. Pour chaque claim, nommer l’artboard: + - `Home 390` + - `Home 768` + - `Home 1024` + - `Home 1440` +3. Fusionner les 4 captures dans un seul fichier Figma (ou en garder un fichier par breakpoint si la contrainte de claim persiste). +4. Structurer selon la logique DA-00: + - `Header` + - `Hero + Identité` + - `Systèmes` + - `Production` + - `Conversion` + - `Footer` +5. Vérifier `#a-propos`, `#projets`, `#contact` visuellement. +6. Ajouter composants + variantes (`default`, `hover`, `focus-visible`, état lab collapsed/expanded si utilisé). +7. QA finale visuelle: overflow, lisibilité mobile, contraste CTA. +8. Archiver la preuve (captures + noms d’artboards + lien final) dans `artifacts/figma-capture/2026-03-02`. diff --git a/artifacts/qa-test/2026-03-01/g3-verification-v8-da-polish.md b/artifacts/qa-test/2026-03-01/g3-verification-v8-da-polish.md new file mode 100644 index 0000000..8d79aca --- /dev/null +++ b/artifacts/qa-test/2026-03-01/g3-verification-v8-da-polish.md @@ -0,0 +1,36 @@ +# G3 — Vérification DA / Responsive / Accessibilité (v8) + +Date: 2026-03-01 + +## Scope +- Validation de la passe DA studio pour la page d'accueil Astro (`src/pages/index.astro` + sections). +- Vérification visuelle/UX locale (sans exécution de tests automatisés dans cette étape). + +## Changes appliqués +1. Consolidation tokens visuels globaux +- Nouveau tokenset électrique dans `src/styles/global.css`. +- Classes sémantiques studio (`studio-panel`, `studio-link`, `studio-chip*`, `studio-muted`, etc.). + +2. UI systémique alignée +- `src/components/ui/button.tsx` et `src/components/ui/card.tsx` sur tokens. +- Header/nav/footer dans `src/pages/index.astro`. +- Refonte visuelle et copy de toutes les sections: `Hero`, `About`, `Projects`, `Contact`. + +3. Gouvernance DA +- Conformité maintenue au brief interne (experimental/noise, électrique, priorité lisibilité/impact). + +## Vérifications documentées +- Aucune référence couleur violette dominante restante dans classes Tailwind des sections. +- Contrat tracking préservé (mêmes `data-track` et événements). +- `prefers-reduced-motion` conservé dans `global.css`. +- Classes d’accessibilité clavier conservées (focus-visible). + +## Checklist métier +- [x] Direction artistique visuelle uniforme (accroche hero + side card + sections). +- [x] CTA lisibles et conservés: projets, contact, profil. +- [x] Références externes conservées: LinkedIn / Malt / Bandcamp avec tracking. +- [ ] Revue responsive 390/768/1024/1440 (audit visuel à réaliser en session de dev). +- [ ] Revue accessibilité complète (focus order + contraste réel sur composants interactifs). + +## Prochaine action QA +- Exécuter Lighthouse prod + revue GA4/SS to close P2 sprint. diff --git a/artifacts/qa-test/2026-03-01/g3-verification-v9-production-readiness.md b/artifacts/qa-test/2026-03-01/g3-verification-v9-production-readiness.md new file mode 100644 index 0000000..b108732 --- /dev/null +++ b/artifacts/qa-test/2026-03-01/g3-verification-v9-production-readiness.md @@ -0,0 +1,24 @@ +# G3 Verification v9 - Production Readiness (local + external gates) + +Date: 2026-03-01 +Owner: QA/Test + +## Local gates +- [x] `npm run typecheck` passe (0 erreur) +- [x] `npm run build` passe (site statique genere) +- [x] `public/robots.txt` present et coherent +- [x] `public/sitemap.xml` present et coherent +- [x] Contrat tracking front present (`src/lib/tracking.ts`) +- [x] GTM default present (`GTM-5SLM67QF`) +- [x] Canonical + OG/Twitter tags presents (`src/layouts/BaseLayout.astro`) + +## External gates (a valider en prod) +- [ ] GA4 Realtime: events recus apres clic CTA +- [ ] GA4 DebugView: `event_category/event_label/destination` corrects +- [ ] GA4 conversions configurees (LinkedIn primaire, Malt secondaire) +- [ ] Search Console: propriete verifiee + sitemap soumis +- [ ] Social previews: LinkedIn/Facebook debug passes + +## Notes +- QA Playwright locale effectuee sur 390/768/1024/1440 avec themes dark/light/high-contrast. +- Pipeline logo prepare (`notes-interne/logo-prompts-electron-rare.md`, `tmp/imagegen/electron-rare-logo-batch.jsonl`), generation finale en attente de cle API. diff --git a/artifacts/qa-test/2026-03-02/g0-da00-brief-wireflow.md b/artifacts/qa-test/2026-03-02/g0-da00-brief-wireflow.md new file mode 100644 index 0000000..ea053f7 --- /dev/null +++ b/artifacts/qa-test/2026-03-02/g0-da00-brief-wireflow.md @@ -0,0 +1,34 @@ +# G0 DA-00 - Brief + Wireflow Conversion + +Date: 2026-03-02 +Owner: Codex +Status: READY FOR DA-01 + +## Scope covered +- Consolidation brief DA v2.0.0 +- Guidelines DA enrichies (zoning + matrice arbitrage) +- Spec projet alignee DA-00 +- Wireflow conversion documente (desktop 1440 + mobile 390 + user flow CTA) +- Backlog DA-01 decision-complet + +## Files delivered +- notes-interne/creative-direction-brief.md +- notes-interne/creative-direction-guidelines.md +- specs/site-github-pages-spec.md +- docs/wireflow-conversion-da00.md +- docs/da-01-implementation-backlog.md + +## Decisions locked +- readability_priority: balanced +- anchors core preserved: #a-propos, #projets, #contact +- DA axis: atelier premium (ivoire/encre/cuivre) + accents techniques mesurés +- CTA primary: LinkedIn; secondary: Malt + +## Validation notes +- Figma MCP not detected in this environment at planning time. +- Fallback applied: decision-complete wireflow documentation ready for manual Figma execution. + +## Next gate (DA-01) +- Implement full structural/UI refactor from wireflow +- Preserve tracking/SEO contracts +- Run QA responsive/accessibility/build gates diff --git a/artifacts/qa-test/2026-03-02/g1-logo-selection-integration.md b/artifacts/qa-test/2026-03-02/g1-logo-selection-integration.md new file mode 100644 index 0000000..0c82aeb --- /dev/null +++ b/artifacts/qa-test/2026-03-02/g1-logo-selection-integration.md @@ -0,0 +1,46 @@ +# G1 Logo Selection + Integration + +Date: 2026-03-02 +Status: PASS + +## Source and selection +- Source officielle: `output/VALIDE DA` +- Note de selection: `notes-interne/logo-selection-2026-03-02.md` +- Winner: `001-create-a-vector-logo-for-electron-rare-with-an-er-monogram-b.png` +- Backup A: `010-produce-a-favicon-first-hazard-signal-icon-for-electron-rare.png` +- Backup B: `005-generate-a-minimal-industrial-logo-with-telemetry-data-frame.png` + +## Freeze working set +- `tmp/brand-selection/001-create-a-vector-logo-for-electron-rare-with-an-er-monogram-b.png` +- `tmp/brand-selection/010-produce-a-favicon-first-hazard-signal-icon-for-electron-rare.png` +- `tmp/brand-selection/005-generate-a-minimal-industrial-logo-with-telemetry-data-frame.png` + +## Assets generated +- `public/assets/brand/logo-mark.png` (1024x1024) +- `public/assets/brand/logo-lockup.png` (1400x700) +- `public/assets/brand/logo-mark.svg` (derived) +- `public/assets/brand/logo-lockup.svg` (derived) +- `public/favicon.svg` +- `public/favicon.ico` +- `public/favicon-32x32.png` +- `public/favicon-16x16.png` +- `public/apple-touch-icon.png` +- `public/assets/og-cover.jpg` (1200x630) + +## Code integration +- `src/lib/site.ts`: BRAND_ASSETS paths -> final brand PNG assets +- `src/layouts/BaseLayout.astro`: favicon link set completed (svg/png/ico/apple) +- `src/styles/global.css`: header brand mark path updated to `/assets/brand/logo-mark.png` + +## Regression contract checks +- Anchors core unchanged: `#a-propos`, `#projets`, `#contact` +- Tracking contract untouched (events/params) +- SEO public resources preserved (`robots.txt`, `sitemap.xml`, canonical/OG/Twitter) + +## Build checks +- `npm run typecheck`: PASS (0 errors) +- `npm run build`: PASS + +## Notes +- SVG outputs are derived wrappers from PNG source (no native vector source available). +- Fallback behavior maintained: display relies on PNG quality; SVG kept for compatibility. diff --git a/artifacts/qa-test/2026-03-02/g2-da01-p0-layout-structure.md b/artifacts/qa-test/2026-03-02/g2-da01-p0-layout-structure.md new file mode 100644 index 0000000..4c1e57a --- /dev/null +++ b/artifacts/qa-test/2026-03-02/g2-da01-p0-layout-structure.md @@ -0,0 +1,35 @@ +# G2 DA-01 P0 — Structure layout control-room + +Date: 2026-03-02 +Scope: finalisation P0 layout/tokens pour structure `index.astro` (sans changement des contrats publics) + +## Changements appliques +- `src/styles/global.css` + - ajout des regles structurelles DA-01: + - `nav-main-row`, `nav-tools`, `nav-sub-row`, `nav-sub-chip` + - `studio-structure`, `structure-grid`, `structure-cell` + - variantes de grille: `--hero`, `--systems`, `--production`, `--conversion` + - `footer-grid`, `footer-title`, `footer-copy`, `footer-links`, `footer-link` + - ajout des breakpoints de composition: + - mobile `<768` + - tablette `>=768` + - desktop large `>=1140` + - micro-ajustements `<=390` + +## Contrats verifies (non modifies) +- Anchors core conserves: + - `#a-propos` + - `#projets` + - `#contact` +- Tracking conserve: + - events `TRACK_EVENTS` inchanges + - attributs `data-track` / `data-destination` inchanges +- SEO/GTM non touches dans ce lot. + +## Verification technique +- `npm run typecheck` -> OK (0 erreur) +- `npm run build` -> OK (build Astro statique complet) + +## Notes +- Ce lot couvre la stabilisation layout/tokens P0. +- Les validations visuelles navigables (390/768/1024/1440) et QA accessibilite fine restent dans P1 QA. diff --git a/artifacts/qa-test/2026-03-02/g3-da01-p1-sections-footer-references.md b/artifacts/qa-test/2026-03-02/g3-da01-p1-sections-footer-references.md new file mode 100644 index 0000000..7711e51 --- /dev/null +++ b/artifacts/qa-test/2026-03-02/g3-da01-p1-sections-footer-references.md @@ -0,0 +1,68 @@ +# G3 DA-01 P1 — Harmonisation sections + footer + references GitHub + +Date: 2026-03-02 +Scope: harmoniser les sections conversion-first et intégrer les references projets GitHub fournies. + +## Changements appliques + +- `src/components/sections/SystemPipeline.tsx` + - labels pipeline harmonises (framing pro/automatisme). + - ajout intro section + chips de signaux. + +- `src/components/sections/FlowDiagram.tsx` + - ajout intro section + chips narratifs du flux mission. + +- `src/components/sections/About.tsx` + - titre et lead alignes sur le positionnement "profil systeme". + +- `src/components/sections/Contact.tsx` + - ajout lead conversion orientee cadrage mission. + +- `src/components/sections/Projects.tsx` + - harmonisation du bloc projets. + - ajout panel de references GitHub: + - `KomplexKapharnaum/KXKM_ESP32_Audio_Battery_hardware` + - `KomplexKapharnaum/LEDcurtain_hardware` + - `KomplexKapharnaum/kxkm_Ve.direct` + - `KomplexKapharnaum/KXKM_Batterie_Parallelator` + - `KomplexKapharnaum/STM32_ESP32_firmware` + - `KomplexKapharnaum/LEDcurtain` + - `electron-rare/` + +- `src/components/sections/ProjectsTimeline.tsx` + - ajout entree timeline "Open repos references" vers GitHub. + - ajustement wording des liens de preuve. + +- `src/components/sections/LabNotes.tsx` + - ajout lead de debrief technique. + +- `src/components/sections/TrustStrip.tsx` + - enrichissement des preuves avec details et mention GitHub. + +- `src/pages/index.astro` + - footer passe en mode knowledge/protocoles/links externes (LinkedIn, Malt, Bandcamp, GitHub). + +- `src/styles/global.css` + - ajout classes de coherence P1: + - `section-lead`, `section-signal-row`, `section-signal-chip` + - `project-stage`, `project-reference-*` + - `trust-pill-detail` + - `footer-column-title`, `footer-protocol-list`, ajustements `footer-grid` + +## Contrats verifies (non modifies) + +- Anchors core conserves: + - `#a-propos` + - `#projets` + - `#contact` +- Contrat tracking conserve (events existants conserves; aucune suppression d'event). +- Contrat SEO/GTM conserve. + +## Verification technique + +- `npm run typecheck` -> OK (0 erreur) +- `npm run build` -> OK (build Astro statique complet) + +## Notes + +- QA responsive/accessibilite fine (visuelle cross-breakpoints) reste a confirmer en revue manuelle finale. diff --git a/artifacts/qa-test/2026-03-02/g4-uiux-da-research-and-qa.md b/artifacts/qa-test/2026-03-02/g4-uiux-da-research-and-qa.md new file mode 100644 index 0000000..f3a3edf --- /dev/null +++ b/artifacts/qa-test/2026-03-02/g4-uiux-da-research-and-qa.md @@ -0,0 +1,55 @@ +# G4 — Recherche UI/UX + QA responsive DA + +Date: 2026-03-02 +Owner: Design/QA + +## Decisions appliquees + +1. References GitHub dans Projets: +- mode retenu: **top 3 + lien "voir plus"** + +2. Tracking GitHub: +- events GA4 dedies ajoutes: + - `outbound_github_project` + - `outbound_github_contact` + +3. QA immediate: +- passe responsive effectuee en local sur 390/768/1024/1440 + +## Verifications locales + +### Build/qualite +- `npm run typecheck` -> OK +- `npm run build` -> OK + +### Captures responsive +- `artifacts/qa-test/2026-03-02/home-390.png` +- `artifacts/qa-test/2026-03-02/home-768.png` +- `artifacts/qa-test/2026-03-02/home-1024.png` +- `artifacts/qa-test/2026-03-02/home-1440.png` + +### Lighthouse (local preview) +- mobile: `artifacts/qa-test/2026-03-02/lighthouse-home-mobile-v5.json` + - Performance: **54** + - Accessibility: **100** + - Best Practices: **100** + - SEO: **100** +- desktop: `artifacts/qa-test/2026-03-02/lighthouse-home-desktop-v5.json` + - Performance: **90** + - Accessibility: **100** + - Best Practices: **100** + - SEO: **100** + +## Etat P1 + +- Harmonisation sections: OK +- Footer knowledge/protocoles: OK +- QA responsive/accessibilite/perf: **partiel** + - responsive + accessibilite: OK local + - perf mobile: sous cible (objectif >= 90 non atteint) + +## Prochain levier anti-blocage + +1. Reduire l'hydration client sur zones non critiques (objectif: baisse TBT mobile) +2. Confirmer en prod les mesures Lighthouse (environnement GitHub Pages) +3. Passer a Storybook P2 une fois perf mobile stabilisee diff --git a/artifacts/qa-test/2026-03-02/home-1024.png b/artifacts/qa-test/2026-03-02/home-1024.png new file mode 100644 index 0000000..030c224 Binary files /dev/null and b/artifacts/qa-test/2026-03-02/home-1024.png differ diff --git a/artifacts/qa-test/2026-03-02/home-1440.png b/artifacts/qa-test/2026-03-02/home-1440.png new file mode 100644 index 0000000..9b905b6 Binary files /dev/null and b/artifacts/qa-test/2026-03-02/home-1440.png differ diff --git a/artifacts/qa-test/2026-03-02/home-390.png b/artifacts/qa-test/2026-03-02/home-390.png new file mode 100644 index 0000000..94e15ea Binary files /dev/null and b/artifacts/qa-test/2026-03-02/home-390.png differ diff --git a/artifacts/qa-test/2026-03-02/home-768.png b/artifacts/qa-test/2026-03-02/home-768.png new file mode 100644 index 0000000..092045f Binary files /dev/null and b/artifacts/qa-test/2026-03-02/home-768.png differ diff --git a/artifacts/qa-test/2026-03-02/lighthouse-home-desktop-v2.json b/artifacts/qa-test/2026-03-02/lighthouse-home-desktop-v2.json new file mode 100644 index 0000000..ff6bab2 --- /dev/null +++ b/artifacts/qa-test/2026-03-02/lighthouse-home-desktop-v2.json @@ -0,0 +1,10828 @@ +{ + "lighthouseVersion": "13.0.3", + "requestedUrl": "http://127.0.0.1:4322/", + "mainDocumentUrl": "http://127.0.0.1:4322/", + "finalDisplayedUrl": "http://127.0.0.1:4322/", + "finalUrl": "http://127.0.0.1:4322/", + "fetchTime": "2026-03-02T00:20:45.810Z", + "gatherMode": "navigation", + "runWarnings": [ + "Clearing the browser cache timed out. Try auditing this page again and file a bug if the issue persists." + ], + "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/145.0.0.0 Safari/537.36", + "environment": { + "networkUserAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.0.0 Safari/537.36", + "hostUserAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/145.0.0.0 Safari/537.36", + "benchmarkIndex": 166, + "credits": { + "axe-core": "4.11.1" + } + }, + "audits": { + "is-on-https": { + "id": "is-on-https", + "title": "Uses HTTPS", + "description": "All sites should be protected with HTTPS, even ones that don't handle sensitive data. This includes avoiding [mixed content](https://developers.google.com/web/fundamentals/security/prevent-mixed-content/what-is-mixed-content), where some resources are loaded over HTTP despite the initial request being served over HTTPS. HTTPS prevents intruders from tampering with or passively listening in on the communications between your app and your users, and is a prerequisite for HTTP/2 and many new web platform APIs. [Learn more about HTTPS](https://developer.chrome.com/docs/lighthouse/pwa/is-on-https/).", + "score": 1, + "scoreDisplayMode": "binary", + "details": { + "type": "table", + "headings": [ + { + "key": "url", + "valueType": "url", + "label": "Insecure URL" + }, + { + "key": "resolution", + "valueType": "text", + "label": "Request Resolution" + } + ], + "items": [] + } + }, + "redirects-http": { + "id": "redirects-http", + "title": "Redirects HTTP traffic to HTTPS", + "description": "Make sure that you redirect all HTTP traffic to HTTPS in order to enable secure web features for all your users. [Learn more](https://developer.chrome.com/docs/lighthouse/pwa/redirects-http/).", + "score": null, + "scoreDisplayMode": "notApplicable" + }, + "first-contentful-paint": { + "id": "first-contentful-paint", + "title": "First Contentful Paint", + "description": "First Contentful Paint marks the time at which the first text or image is painted. [Learn more about the First Contentful Paint metric](https://developer.chrome.com/docs/lighthouse/performance/first-contentful-paint/).", + "score": 0.78, + "scoreDisplayMode": "numeric", + "numericValue": 1144.29925, + "numericUnit": "millisecond", + "displayValue": "1.1 s", + "scoringOptions": { + "p10": 934, + "median": 1600 + } + }, + "largest-contentful-paint": { + "id": "largest-contentful-paint", + "title": "Largest Contentful Paint", + "description": "Largest Contentful Paint marks the time at which the largest text or image is painted. [Learn more about the Largest Contentful Paint metric](https://developer.chrome.com/docs/lighthouse/performance/lighthouse-largest-contentful-paint/)", + "score": 0.87, + "scoreDisplayMode": "numeric", + "numericValue": 1280.8402499999997, + "numericUnit": "millisecond", + "displayValue": "1.3 s", + "scoringOptions": { + "p10": 1200, + "median": 2400 + } + }, + "speed-index": { + "id": "speed-index", + "title": "Speed Index", + "description": "Speed Index shows how quickly the contents of a page are visibly populated. [Learn more about the Speed Index metric](https://developer.chrome.com/docs/lighthouse/performance/speed-index/).", + "score": 0.87, + "scoreDisplayMode": "numeric", + "numericValue": 1390.0919864667349, + "numericUnit": "millisecond", + "displayValue": "1.4 s", + "scoringOptions": { + "p10": 1311, + "median": 2300 + } + }, + "total-blocking-time": { + "id": "total-blocking-time", + "title": "Total Blocking Time", + "description": "Sum of all time periods between FCP and Time to Interactive, when task length exceeded 50ms, expressed in milliseconds. [Learn more about the Total Blocking Time metric](https://developer.chrome.com/docs/lighthouse/performance/lighthouse-total-blocking-time/).", + "score": 1, + "scoreDisplayMode": "numeric", + "numericValue": 37, + "numericUnit": "millisecond", + "displayValue": "40 ms", + "scoringOptions": { + "p10": 150, + "median": 350 + } + }, + "max-potential-fid": { + "id": "max-potential-fid", + "title": "Max Potential First Input Delay", + "description": "The maximum potential First Input Delay that your users could experience is the duration of the longest task. [Learn more about the Maximum Potential First Input Delay metric](https://developer.chrome.com/docs/lighthouse/performance/lighthouse-max-potential-fid/).", + "score": 0.98, + "scoreDisplayMode": "numeric", + "numericValue": 87, + "numericUnit": "millisecond", + "displayValue": "90 ms" + }, + "cumulative-layout-shift": { + "id": "cumulative-layout-shift", + "title": "Cumulative Layout Shift", + "description": "Cumulative Layout Shift measures the movement of visible elements within the viewport. [Learn more about the Cumulative Layout Shift metric](https://web.dev/articles/cls).", + "score": 0.81, + "scoreDisplayMode": "numeric", + "numericValue": 0.13294318182835646, + "numericUnit": "unitless", + "displayValue": "0.133", + "scoringOptions": { + "p10": 0.1, + "median": 0.25 + }, + "details": { + "type": "debugdata", + "items": [ + { + "cumulativeLayoutShiftMainFrame": 0.13294318182835646, + "newEngineResult": { + "cumulativeLayoutShift": 0.13294318182835646, + "cumulativeLayoutShiftMainFrame": 0.13294318182835646 + }, + "newEngineResultDiffered": false + } + ] + } + }, + "errors-in-console": { + "id": "errors-in-console", + "title": "No browser errors logged to the console", + "description": "Errors logged to the console indicate unresolved problems. They can come from network request failures and other browser concerns. [Learn more about this errors in console diagnostic audit](https://developer.chrome.com/docs/lighthouse/best-practices/errors-in-console/)", + "score": 1, + "scoreDisplayMode": "binary", + "details": { + "type": "table", + "headings": [ + { + "key": "sourceLocation", + "valueType": "source-location", + "label": "Source" + }, + { + "key": "description", + "valueType": "code", + "label": "Description" + } + ], + "items": [] + } + }, + "server-response-time": { + "id": "server-response-time", + "title": "Initial server response time was short", + "description": "Keep the server response time for the main document short because all other requests depend on it. [Learn more about the Time to First Byte metric](https://developer.chrome.com/docs/lighthouse/performance/time-to-first-byte/).", + "score": 1, + "scoreDisplayMode": "metricSavings", + "numericValue": 38, + "numericUnit": "millisecond", + "displayValue": "Root document took 40 ms", + "metricSavings": { + "FCP": 0, + "LCP": 0 + }, + "details": { + "type": "opportunity", + "headings": [ + { + "key": "url", + "valueType": "url", + "label": "URL" + }, + { + "key": "responseTime", + "valueType": "timespanMs", + "label": "Time Spent" + } + ], + "items": [ + { + "url": "http://127.0.0.1:4322/", + "responseTime": 38 + } + ], + "overallSavingsMs": 0 + }, + "guidanceLevel": 1 + }, + "interactive": { + "id": "interactive", + "title": "Time to Interactive", + "description": "Time to Interactive is the amount of time it takes for the page to become fully interactive. [Learn more about the Time to Interactive metric](https://developer.chrome.com/docs/lighthouse/performance/interactive/).", + "score": 1, + "scoreDisplayMode": "numeric", + "numericValue": 1280.84025, + "numericUnit": "millisecond", + "displayValue": "1.3 s" + }, + "user-timings": { + "id": "user-timings", + "title": "User Timing marks and measures", + "description": "Consider instrumenting your app with the User Timing API to measure your app's real-world performance during key user experiences. [Learn more about User Timing marks](https://developer.chrome.com/docs/lighthouse/performance/user-timings/).", + "score": null, + "scoreDisplayMode": "notApplicable", + "details": { + "type": "table", + "headings": [ + { + "key": "name", + "valueType": "text", + "label": "Name" + }, + { + "key": "timingType", + "valueType": "text", + "label": "Type" + }, + { + "key": "startTime", + "valueType": "ms", + "granularity": 0.01, + "label": "Start Time" + }, + { + "key": "duration", + "valueType": "ms", + "granularity": 0.01, + "label": "Duration" + } + ], + "items": [] + }, + "guidanceLevel": 2 + }, + "redirects": { + "id": "redirects", + "title": "Avoid multiple page redirects", + "description": "Redirects introduce additional delays before the page can be loaded. [Learn how to avoid page redirects](https://developer.chrome.com/docs/lighthouse/performance/redirects/).", + "score": 1, + "scoreDisplayMode": "metricSavings", + "numericValue": 0, + "numericUnit": "millisecond", + "displayValue": "", + "metricSavings": { + "LCP": 0, + "FCP": 0 + }, + "details": { + "type": "opportunity", + "headings": [], + "items": [], + "overallSavingsMs": 0 + }, + "guidanceLevel": 2 + }, + "image-aspect-ratio": { + "id": "image-aspect-ratio", + "title": "Displays images with correct aspect ratio", + "description": "Image display dimensions should match natural aspect ratio. [Learn more about image aspect ratio](https://developer.chrome.com/docs/lighthouse/best-practices/image-aspect-ratio/).", + "score": 1, + "scoreDisplayMode": "binary", + "details": { + "type": "table", + "headings": [ + { + "key": "node", + "valueType": "node", + "label": "" + }, + { + "key": "url", + "valueType": "url", + "label": "URL" + }, + { + "key": "displayedAspectRatio", + "valueType": "text", + "label": "Aspect Ratio (Displayed)" + }, + { + "key": "actualAspectRatio", + "valueType": "text", + "label": "Aspect Ratio (Actual)" + } + ], + "items": [] + } + }, + "image-size-responsive": { + "id": "image-size-responsive", + "title": "Serves images with appropriate resolution", + "description": "Image natural dimensions should be proportional to the display size and the pixel ratio to maximize image clarity. [Learn how to provide responsive images](https://web.dev/articles/serve-responsive-images).", + "score": 1, + "scoreDisplayMode": "binary", + "details": { + "type": "table", + "headings": [ + { + "key": "node", + "valueType": "node", + "label": "" + }, + { + "key": "url", + "valueType": "url", + "label": "URL" + }, + { + "key": "displayedSize", + "valueType": "text", + "label": "Displayed size" + }, + { + "key": "actualSize", + "valueType": "text", + "label": "Actual size" + }, + { + "key": "expectedSize", + "valueType": "text", + "label": "Expected size" + } + ], + "items": [] + } + }, + "deprecations": { + "id": "deprecations", + "title": "Avoids deprecated APIs", + "description": "Deprecated APIs will eventually be removed from the browser. [Learn more about deprecated APIs](https://developer.chrome.com/docs/lighthouse/best-practices/deprecations/).", + "score": 1, + "scoreDisplayMode": "binary", + "details": { + "type": "table", + "headings": [ + { + "key": "value", + "valueType": "text", + "label": "Deprecation / Warning" + }, + { + "key": "source", + "valueType": "source-location", + "label": "Source" + } + ], + "items": [] + } + }, + "third-party-cookies": { + "id": "third-party-cookies", + "title": "Avoids third-party cookies", + "description": "Third-party cookies may be blocked in some contexts. [Learn more about preparing for third-party cookie restrictions](https://privacysandbox.google.com/cookies/prepare/overview).", + "score": 1, + "scoreDisplayMode": "binary", + "details": { + "type": "table", + "headings": [ + { + "key": "name", + "valueType": "text", + "label": "Name" + }, + { + "key": "url", + "valueType": "url", + "label": "URL" + } + ], + "items": [] + } + }, + "mainthread-work-breakdown": { + "id": "mainthread-work-breakdown", + "title": "Minimizes main-thread work", + "description": "Consider reducing the time spent parsing, compiling and executing JS. You may find delivering smaller JS payloads helps with this. [Learn how to minimize main-thread work](https://developer.chrome.com/docs/lighthouse/performance/mainthread-work-breakdown/)", + "score": 1, + "scoreDisplayMode": "metricSavings", + "numericValue": 1747.2229999999986, + "numericUnit": "millisecond", + "displayValue": "1.7 s", + "metricSavings": { + "TBT": 50 + }, + "details": { + "type": "table", + "headings": [ + { + "key": "groupLabel", + "valueType": "text", + "label": "Category" + }, + { + "key": "duration", + "valueType": "ms", + "granularity": 1, + "label": "Time Spent" + } + ], + "items": [ + { + "group": "styleLayout", + "groupLabel": "Style & Layout", + "duration": 877.911 + }, + { + "group": "scriptEvaluation", + "groupLabel": "Script Evaluation", + "duration": 464.66799999999853 + }, + { + "group": "other", + "groupLabel": "Other", + "duration": 261.8039999999995 + }, + { + "group": "paintCompositeRender", + "groupLabel": "Rendering", + "duration": 114.86700000000067 + }, + { + "group": "scriptParseCompile", + "groupLabel": "Script Parsing & Compilation", + "duration": 13.947 + }, + { + "group": "parseHTML", + "groupLabel": "Parse HTML & CSS", + "duration": 8.161 + }, + { + "group": "garbageCollection", + "groupLabel": "Garbage Collection", + "duration": 5.864999999999997 + } + ], + "sortedBy": [ + "duration" + ] + }, + "guidanceLevel": 1 + }, + "bootup-time": { + "id": "bootup-time", + "title": "JavaScript execution time", + "description": "Consider reducing the time spent parsing, compiling, and executing JS. You may find delivering smaller JS payloads helps with this. [Learn how to reduce Javascript execution time](https://developer.chrome.com/docs/lighthouse/performance/bootup-time/).", + "score": 1, + "scoreDisplayMode": "metricSavings", + "numericValue": 463.18899999999894, + "numericUnit": "millisecond", + "displayValue": "0.5 s", + "metricSavings": { + "TBT": 50 + }, + "details": { + "type": "table", + "headings": [ + { + "key": "url", + "valueType": "url", + "label": "URL" + }, + { + "key": "total", + "granularity": 1, + "valueType": "ms", + "label": "Total CPU Time" + }, + { + "key": "scripting", + "granularity": 1, + "valueType": "ms", + "label": "Script Evaluation" + }, + { + "key": "scriptParseCompile", + "granularity": 1, + "valueType": "ms", + "label": "Script Parse" + } + ], + "items": [ + { + "url": "http://127.0.0.1:4322/", + "total": 1049.7680000000003, + "scripting": 27.377999999999997, + "scriptParseCompile": 2.2669999999999995 + }, + { + "url": "http://127.0.0.1:4322/_astro/client.BnVIp5Iu.js", + "total": 442.9529999999988, + "scripting": 289.548999999999, + "scriptParseCompile": 0.338 + }, + { + "url": "https://www.googletagmanager.com/gtm.js?id=GTM-5SLM67QF", + "total": 135.48499999999993, + "scripting": 124.46899999999994, + "scriptParseCompile": 10.77 + }, + { + "url": "Unattributable", + "total": 59.173, + "scripting": 8.417999999999997, + "scriptParseCompile": 0 + } + ], + "summary": { + "wastedMs": 463.18899999999894 + }, + "sortedBy": [ + "total" + ] + }, + "guidanceLevel": 1 + }, + "diagnostics": { + "id": "diagnostics", + "title": "Diagnostics", + "description": "Collection of useful page vitals.", + "score": 1, + "scoreDisplayMode": "informative", + "details": { + "type": "debugdata", + "items": [ + { + "numRequests": 20, + "numScripts": 11, + "numStylesheets": 2, + "numFonts": 4, + "numTasks": 554, + "numTasksOver10ms": 13, + "numTasksOver25ms": 9, + "numTasksOver50ms": 8, + "numTasksOver100ms": 6, + "numTasksOver500ms": 0, + "rtt": 0.06075, + "throughput": 50121469.435067564, + "maxRtt": 81.686, + "maxServerLatency": 27.989999999999995, + "totalByteWeight": 653703, + "totalTaskTime": 1747.2229999999959, + "mainDocumentTransferSize": 12769 + } + ] + } + }, + "network-requests": { + "id": "network-requests", + "title": "Network Requests", + "description": "Lists the network requests that were made during page load.", + "score": 1, + "scoreDisplayMode": "informative", + "details": { + "type": "table", + "headings": [ + { + "key": "url", + "valueType": "url", + "label": "URL" + }, + { + "key": "protocol", + "valueType": "text", + "label": "Protocol" + }, + { + "key": "networkRequestTime", + "valueType": "ms", + "granularity": 1, + "label": "Network Request Time" + }, + { + "key": "networkEndTime", + "valueType": "ms", + "granularity": 1, + "label": "Network End Time" + }, + { + "key": "transferSize", + "valueType": "bytes", + "displayUnit": "kb", + "granularity": 1, + "label": "Transfer Size" + }, + { + "key": "resourceSize", + "valueType": "bytes", + "displayUnit": "kb", + "granularity": 1, + "label": "Resource Size" + }, + { + "key": "statusCode", + "valueType": "text", + "label": "Status Code" + }, + { + "key": "mimeType", + "valueType": "text", + "label": "MIME Type" + }, + { + "key": "resourceType", + "valueType": "text", + "label": "Resource Type" + } + ], + "items": [ + { + "url": "http://127.0.0.1:4322/", + "sessionTargetType": "page", + "protocol": "http/1.1", + "rendererStartTime": 0, + "networkRequestTime": 1.652999997138977, + "networkEndTime": 42.32000000029802, + "finished": true, + "transferSize": 12769, + "resourceSize": 61323, + "statusCode": 200, + "mimeType": "text/html", + "resourceType": "Document", + "priority": "VeryHigh", + "experimentalFromMainFrame": true, + "entity": "127.0.0.1" + }, + { + "url": "http://127.0.0.1:4322/_astro/index.Vx9wT9b4.css", + "sessionTargetType": "page", + "protocol": "http/1.1", + "rendererStartTime": 50.58799999952316, + "networkRequestTime": 52.44500000029802, + "networkEndTime": 67.3319999948144, + "finished": true, + "transferSize": 16023, + "resourceSize": 89788, + "statusCode": 200, + "mimeType": "text/css", + "resourceType": "Stylesheet", + "priority": "VeryHigh", + "experimentalFromMainFrame": true, + "entity": "127.0.0.1" + }, + { + "url": "https://www.googletagmanager.com/gtm.js?id=GTM-5SLM67QF", + "sessionTargetType": "page", + "protocol": "h2", + "rendererStartTime": 58.524999998509884, + "networkRequestTime": 59.4379999935627, + "networkEndTime": 174.58299999684095, + "finished": true, + "transferSize": 108471, + "resourceSize": 302204, + "statusCode": 200, + "mimeType": "application/javascript", + "resourceType": "Script", + "priority": "Low", + "experimentalFromMainFrame": true, + "entity": "Google Tag Manager" + }, + { + "url": "https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,500;9..144,700&family=IBM+Plex+Mono:wght@400;500;600&family=Manrope:wght@400;500;600;700&display=swap", + "sessionTargetType": "page", + "protocol": "h2", + "rendererStartTime": 67.90699999779463, + "networkRequestTime": 69.13099999725819, + "networkEndTime": 154.32799999415874, + "finished": true, + "transferSize": 1520, + "resourceSize": 17348, + "statusCode": 200, + "mimeType": "text/css", + "resourceType": "Stylesheet", + "priority": "VeryHigh", + "experimentalFromMainFrame": true, + "entity": "Google Fonts" + }, + { + "url": "http://127.0.0.1:4322/assets/brand/logo-mark.png", + "sessionTargetType": "page", + "protocol": "http/1.1", + "rendererStartTime": 160.3319999948144, + "networkRequestTime": 161.47999999672174, + "networkEndTime": 178.43100000172853, + "finished": true, + "transferSize": 243764, + "resourceSize": 243495, + "statusCode": 200, + "mimeType": "image/png", + "resourceType": "Image", + "priority": "High", + "experimentalFromMainFrame": true, + "entity": "127.0.0.1" + }, + { + "url": "https://fonts.gstatic.com/s/manrope/v20/xn7gYHE41ni1AdIRggexSvfedN4.woff2", + "sessionTargetType": "page", + "protocol": "h3", + "rendererStartTime": 162.98599999397993, + "networkRequestTime": 206.78199999779463, + "networkEndTime": 308.723999992013, + "finished": true, + "transferSize": 24605, + "resourceSize": 24576, + "statusCode": 200, + "mimeType": "font/woff2", + "resourceType": "Font", + "priority": "VeryHigh", + "experimentalFromMainFrame": true, + "entity": "Google Fonts" + }, + { + "url": "https://fonts.gstatic.com/s/ibmplexmono/v20/-F6qfjptAgt5VM-kVkqdyU8n3vAOwlBFgsAXHNk.woff2", + "sessionTargetType": "page", + "protocol": "h3", + "rendererStartTime": 163.21900000423193, + "networkRequestTime": 207.58099999278784, + "networkEndTime": 306.42300000041723, + "finished": true, + "transferSize": 10147, + "resourceSize": 10120, + "statusCode": 200, + "mimeType": "font/woff2", + "resourceType": "Font", + "priority": "VeryHigh", + "experimentalFromMainFrame": true, + "entity": "Google Fonts" + }, + { + "url": "https://fonts.gstatic.com/s/ibmplexmono/v20/-F63fjptAgt5VM-kVkqdyU8n1i8q131nj-o.woff2", + "sessionTargetType": "page", + "protocol": "h3", + "rendererStartTime": 163.36500000208616, + "networkRequestTime": 207.96099999547005, + "networkEndTime": 305.09899999946356, + "finished": true, + "transferSize": 10079, + "resourceSize": 10052, + "statusCode": 200, + "mimeType": "font/woff2", + "resourceType": "Font", + "priority": "VeryHigh", + "experimentalFromMainFrame": true, + "entity": "Google Fonts" + }, + { + "url": "http://127.0.0.1:4322/_astro/Hero.CWdFfU6a.js", + "sessionTargetType": "page", + "protocol": "http/1.1", + "rendererStartTime": 212.8069999963045, + "networkRequestTime": 213.50999999791384, + "networkEndTime": 238.71099999547005, + "finished": true, + "transferSize": 2250, + "resourceSize": 5542, + "statusCode": 200, + "mimeType": "text/javascript", + "resourceType": "Script", + "priority": "High", + "experimentalFromMainFrame": true, + "entity": "127.0.0.1" + }, + { + "url": "http://127.0.0.1:4322/_astro/client.BnVIp5Iu.js", + "sessionTargetType": "page", + "protocol": "http/1.1", + "rendererStartTime": 213.2009999975562, + "networkRequestTime": 214.26599999517202, + "networkEndTime": 264.3459999933839, + "finished": true, + "transferSize": 58877, + "resourceSize": 186619, + "statusCode": 200, + "mimeType": "text/javascript", + "resourceType": "Script", + "priority": "High", + "experimentalFromMainFrame": true, + "entity": "127.0.0.1" + }, + { + "url": "http://127.0.0.1:4322/_astro/FlowDiagram.rObCbwEq.js", + "sessionTargetType": "page", + "protocol": "http/1.1", + "rendererStartTime": 215.29799999296665, + "networkRequestTime": 216.06899999827147, + "networkEndTime": 246.0920000001788, + "finished": true, + "transferSize": 1619, + "resourceSize": 2931, + "statusCode": 200, + "mimeType": "text/javascript", + "resourceType": "Script", + "priority": "High", + "experimentalFromMainFrame": true, + "entity": "127.0.0.1" + }, + { + "url": "http://127.0.0.1:4322/_astro/Projects.DwnD_OPS.js", + "sessionTargetType": "page", + "protocol": "http/1.1", + "rendererStartTime": 217.36299999803305, + "networkRequestTime": 218.18800000101328, + "networkEndTime": 249.668999992311, + "finished": true, + "transferSize": 1980, + "resourceSize": 3928, + "statusCode": 200, + "mimeType": "text/javascript", + "resourceType": "Script", + "priority": "High", + "experimentalFromMainFrame": true, + "entity": "127.0.0.1" + }, + { + "url": "https://fonts.gstatic.com/s/fraunces/v38/6NU78FyLNQOQZAnv9bYEvDiIdE9Ea92uemAk_WBq8U_9v0c2Wa0KxC9TeP2Xz5c.woff2", + "sessionTargetType": "page", + "protocol": "h3", + "rendererStartTime": 243.5869999974966, + "networkRequestTime": 472.22199999541044, + "networkEndTime": 492.1849999949336, + "finished": true, + "transferSize": 67425, + "resourceSize": 67388, + "statusCode": 200, + "mimeType": "font/woff2", + "resourceType": "Font", + "priority": "VeryHigh", + "experimentalFromMainFrame": true, + "entity": "Google Fonts" + }, + { + "url": "http://127.0.0.1:4322/_astro/IdentityLab.CG225saZ.js", + "sessionTargetType": "page", + "protocol": "http/1.1", + "rendererStartTime": 1193.4530000016093, + "networkRequestTime": 1194.3439999967813, + "networkEndTime": 1240.3189999982715, + "finished": true, + "transferSize": 1566, + "resourceSize": 4277, + "statusCode": 200, + "mimeType": "text/javascript", + "resourceType": "Script", + "priority": "High", + "experimentalFromMainFrame": true, + "entity": "127.0.0.1" + }, + { + "url": "http://127.0.0.1:4322/_astro/proxy.DrdNLT3k.js", + "sessionTargetType": "page", + "protocol": "http/1.1", + "rendererStartTime": 1196.4890000000596, + "networkRequestTime": 1197.1560000032187, + "networkEndTime": 1249.7669999971986, + "finished": true, + "transferSize": 39679, + "resourceSize": 119539, + "statusCode": 200, + "mimeType": "text/javascript", + "resourceType": "Script", + "priority": "High", + "experimentalFromMainFrame": true, + "entity": "127.0.0.1" + }, + { + "url": "http://127.0.0.1:4322/_astro/cta-dual-rail.BsNvZaAg.js", + "sessionTargetType": "page", + "protocol": "http/1.1", + "rendererStartTime": 1196.9479999989271, + "networkRequestTime": 1197.6749999970198, + "networkEndTime": 1241.3420000001788, + "finished": true, + "transferSize": 10681, + "resourceSize": 31586, + "statusCode": 200, + "mimeType": "text/javascript", + "resourceType": "Script", + "priority": "High", + "experimentalFromMainFrame": true, + "entity": "127.0.0.1" + }, + { + "url": "http://127.0.0.1:4322/_astro/tracking.D1HldQGt.js", + "sessionTargetType": "page", + "protocol": "http/1.1", + "rendererStartTime": 1198.1349999979138, + "networkRequestTime": 1198.4959999993443, + "networkEndTime": 1223.2480000033975, + "finished": true, + "transferSize": 769, + "resourceSize": 448, + "statusCode": 200, + "mimeType": "text/javascript", + "resourceType": "Script", + "priority": "High", + "experimentalFromMainFrame": true, + "entity": "127.0.0.1" + }, + { + "url": "http://127.0.0.1:4322/_astro/index.DJ4e78gH.js", + "sessionTargetType": "page", + "protocol": "http/1.1", + "rendererStartTime": 1198.987999998033, + "networkRequestTime": 1199.4540000036359, + "networkEndTime": 1244.6229999959469, + "finished": true, + "transferSize": 3646, + "resourceSize": 8355, + "statusCode": 200, + "mimeType": "text/javascript", + "resourceType": "Script", + "priority": "High", + "experimentalFromMainFrame": true, + "entity": "127.0.0.1" + }, + { + "url": "http://127.0.0.1:4322/_astro/use-reduced-motion.ye2a724N.js", + "sessionTargetType": "page", + "protocol": "http/1.1", + "rendererStartTime": 1200.1939999982715, + "networkRequestTime": 1200.8589999973774, + "networkEndTime": 1237.1970000043511, + "finished": true, + "transferSize": 500, + "resourceSize": 179, + "statusCode": 200, + "mimeType": "text/javascript", + "resourceType": "Script", + "priority": "High", + "experimentalFromMainFrame": true, + "entity": "127.0.0.1" + }, + { + "url": "http://127.0.0.1:4322/favicon.ico", + "sessionTargetType": "page", + "protocol": "http/1.1", + "rendererStartTime": 1529.9499999955297, + "networkRequestTime": 1531.0319999977946, + "networkEndTime": 1534.0169999971986, + "finished": true, + "transferSize": 37333, + "resourceSize": 37063, + "statusCode": 200, + "mimeType": "image/x-icon", + "resourceType": "Other", + "priority": "High", + "experimentalFromMainFrame": true, + "entity": "127.0.0.1" + } + ], + "debugData": { + "type": "debugdata", + "networkStartTimeTs": 50739578516, + "initiators": [ + { + "type": "parser", + "url": "http://127.0.0.1:4322/", + "lineNumber": 15, + "columnNumber": 75 + }, + { + "type": "parser", + "url": "http://127.0.0.1:4322/_astro/index.Vx9wT9b4.css", + "lineNumber": 0, + "columnNumber": 0 + }, + { + "type": "parser", + "url": "http://127.0.0.1:4322/_astro/index.Vx9wT9b4.css" + }, + { + "type": "parser", + "url": "https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,500;9..144,700&family=IBM+Plex+Mono:wght@400;500;600&family=Manrope:wght@400;500;600;700&display=swap" + }, + { + "type": "parser", + "url": "https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,500;9..144,700&family=IBM+Plex+Mono:wght@400;500;600&family=Manrope:wght@400;500;600;700&display=swap" + }, + { + "type": "parser", + "url": "https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,500;9..144,700&family=IBM+Plex+Mono:wght@400;500;600&family=Manrope:wght@400;500;600;700&display=swap" + }, + { + "type": "parser", + "url": "https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,500;9..144,700&family=IBM+Plex+Mono:wght@400;500;600&family=Manrope:wght@400;500;600;700&display=swap" + }, + { + "type": "script", + "url": "http://127.0.0.1:4322/_astro/Hero.CWdFfU6a.js", + "lineNumber": 0, + "columnNumber": 25 + }, + { + "type": "script", + "url": "http://127.0.0.1:4322/_astro/Hero.CWdFfU6a.js", + "lineNumber": 0, + "columnNumber": 72 + }, + { + "type": "script", + "url": "http://127.0.0.1:4322/_astro/Hero.CWdFfU6a.js", + "lineNumber": 0, + "columnNumber": 122 + }, + { + "type": "script", + "url": "http://127.0.0.1:4322/_astro/Hero.CWdFfU6a.js", + "lineNumber": 0, + "columnNumber": 153 + }, + { + "type": "script", + "url": "http://127.0.0.1:4322/_astro/FlowDiagram.rObCbwEq.js", + "lineNumber": 0, + "columnNumber": 115 + } + ] + } + } + }, + "network-rtt": { + "id": "network-rtt", + "title": "Network Round Trip Times", + "description": "Network round trip times (RTT) have a large impact on performance. If the RTT to an origin is high, it's an indication that servers closer to the user could improve performance. [Learn more about the Round Trip Time](https://hpbn.co/primer-on-latency-and-bandwidth/).", + "score": 1, + "scoreDisplayMode": "informative", + "numericValue": 81.686, + "numericUnit": "millisecond", + "displayValue": "80 ms", + "details": { + "type": "table", + "headings": [ + { + "key": "origin", + "valueType": "text", + "label": "URL" + }, + { + "key": "rtt", + "valueType": "ms", + "granularity": 1, + "label": "Time Spent" + } + ], + "items": [ + { + "origin": "https://fonts.gstatic.com", + "rtt": 81.686 + }, + { + "origin": "https://www.googletagmanager.com", + "rtt": 8.753 + }, + { + "origin": "https://fonts.googleapis.com", + "rtt": 8.699 + }, + { + "origin": "http://127.0.0.1:4322", + "rtt": 0.06075 + } + ], + "sortedBy": [ + "rtt" + ] + } + }, + "network-server-latency": { + "id": "network-server-latency", + "title": "Server Backend Latencies", + "description": "Server latencies can impact web performance. If the server latency of an origin is high, it's an indication the server is overloaded or has poor backend performance. [Learn more about server response time](https://hpbn.co/primer-on-web-performance/#analyzing-the-resource-waterfall).", + "score": 1, + "scoreDisplayMode": "informative", + "numericValue": 27.989999999999995, + "numericUnit": "millisecond", + "displayValue": "30 ms", + "details": { + "type": "table", + "headings": [ + { + "key": "origin", + "valueType": "text", + "label": "URL" + }, + { + "key": "serverResponseTime", + "valueType": "ms", + "granularity": 1, + "label": "Time Spent" + } + ], + "items": [ + { + "origin": "https://fonts.googleapis.com", + "serverResponseTime": 27.989999999999995 + }, + { + "origin": "http://127.0.0.1:4322", + "serverResponseTime": 26.94675 + }, + { + "origin": "https://www.googletagmanager.com", + "serverResponseTime": 19.869 + }, + { + "origin": "https://fonts.gstatic.com", + "serverResponseTime": 0 + } + ], + "sortedBy": [ + "serverResponseTime" + ] + } + }, + "main-thread-tasks": { + "id": "main-thread-tasks", + "title": "Tasks", + "description": "Lists the toplevel main thread tasks that executed during page load.", + "score": 1, + "scoreDisplayMode": "informative", + "details": { + "type": "table", + "headings": [ + { + "key": "startTime", + "valueType": "ms", + "granularity": 1, + "label": "Start Time" + }, + { + "key": "duration", + "valueType": "ms", + "granularity": 1, + "label": "End Time" + } + ], + "items": [ + { + "duration": 9.855, + "startTime": 48.41 + }, + { + "duration": 50.165, + "startTime": 157.521 + }, + { + "duration": 25.57, + "startTime": 211.631 + }, + { + "duration": 232.876, + "startTime": 237.265 + }, + { + "duration": 441.152, + "startTime": 472.305 + }, + { + "duration": 264.476, + "startTime": 916.666 + }, + { + "duration": 8.837, + "startTime": 1184.774 + }, + { + "duration": 130.188, + "startTime": 1204.687 + }, + { + "duration": 14.344, + "startTime": 1346.972 + }, + { + "duration": 121.402, + "startTime": 1361.447 + }, + { + "duration": 24.761, + "startTime": 1482.873 + }, + { + "duration": 9.031, + "startTime": 1513.884 + }, + { + "duration": 6.666, + "startTime": 1524.801 + }, + { + "duration": 143.5, + "startTime": 1531.949 + }, + { + "duration": 8.946, + "startTime": 1677.616 + }, + { + "duration": 8.129, + "startTime": 1686.618 + }, + { + "duration": 87.449, + "startTime": 1698.849 + }, + { + "duration": 13.57, + "startTime": 3356.345 + }, + { + "duration": 15.273, + "startTime": 3380.999 + }, + { + "duration": 7.159, + "startTime": 3619.716 + }, + { + "duration": 6.446, + "startTime": 3635.609 + }, + { + "duration": 8.053, + "startTime": 3706.806 + }, + { + "duration": 7.836, + "startTime": 3740.591 + }, + { + "duration": 7.282, + "startTime": 3749.521 + }, + { + "duration": 7.844, + "startTime": 3844.628 + }, + { + "duration": 8.164, + "startTime": 3939.945 + } + ] + } + }, + "metrics": { + "id": "metrics", + "title": "Metrics", + "description": "Collects all available metrics.", + "score": 1, + "scoreDisplayMode": "informative", + "numericValue": 1281, + "numericUnit": "millisecond", + "details": { + "type": "debugdata", + "items": [ + { + "firstContentfulPaint": 1144, + "largestContentfulPaint": 1281, + "interactive": 1281, + "speedIndex": 1390, + "totalBlockingTime": 37, + "maxPotentialFID": 87, + "cumulativeLayoutShift": 0.13294318182835646, + "cumulativeLayoutShiftMainFrame": 0.13294318182835646, + "timeToFirstByte": 147, + "observedTimeOrigin": 0, + "observedTimeOriginTs": 50739576741, + "observedNavigationStart": 0, + "observedNavigationStartTs": 50739576741, + "observedFirstPaint": 349, + "observedFirstPaintTs": 50739926130, + "observedFirstContentfulPaint": 349, + "observedFirstContentfulPaintTs": 50739926130, + "observedFirstContentfulPaintAllFrames": 349, + "observedFirstContentfulPaintAllFramesTs": 50739926130, + "observedLargestContentfulPaint": 3843, + "observedLargestContentfulPaintTs": 50743419485, + "observedLargestContentfulPaintAllFrames": 3843, + "observedLargestContentfulPaintAllFramesTs": 50743419485, + "observedTraceEnd": 4035, + "observedTraceEndTs": 50743611670, + "observedLoad": 1337, + "observedLoadTs": 50740913269, + "observedDomContentLoaded": 1204, + "observedDomContentLoadedTs": 50740780607, + "observedCumulativeLayoutShift": 0.13294318182835646, + "observedCumulativeLayoutShiftMainFrame": 0.13294318182835646, + "observedFirstVisualChange": 12, + "observedFirstVisualChangeTs": 50739588741, + "observedLastVisualChange": 4018, + "observedLastVisualChangeTs": 50743594741, + "observedSpeedIndex": 1429, + "observedSpeedIndexTs": 50741005983 + }, + { + "lcpInvalidated": false + } + ] + } + }, + "resource-summary": { + "id": "resource-summary", + "title": "Resources Summary", + "description": "Aggregates all network requests and groups them by type", + "score": 1, + "scoreDisplayMode": "informative", + "details": { + "type": "table", + "headings": [ + { + "key": "label", + "valueType": "text", + "label": "Resource Type" + }, + { + "key": "requestCount", + "valueType": "numeric", + "label": "Requests" + }, + { + "key": "transferSize", + "valueType": "bytes", + "label": "Transfer Size" + } + ], + "items": [ + { + "resourceType": "total", + "label": "Total", + "requestCount": 19, + "transferSize": 616370 + }, + { + "resourceType": "image", + "label": "Image", + "requestCount": 1, + "transferSize": 243764 + }, + { + "resourceType": "script", + "label": "Script", + "requestCount": 11, + "transferSize": 230038 + }, + { + "resourceType": "font", + "label": "Font", + "requestCount": 4, + "transferSize": 112256 + }, + { + "resourceType": "stylesheet", + "label": "Stylesheet", + "requestCount": 2, + "transferSize": 17543 + }, + { + "resourceType": "document", + "label": "Document", + "requestCount": 1, + "transferSize": 12769 + }, + { + "resourceType": "media", + "label": "Media", + "requestCount": 0, + "transferSize": 0 + }, + { + "resourceType": "other", + "label": "Other", + "requestCount": 0, + "transferSize": 0 + }, + { + "resourceType": "third-party", + "label": "Third-party", + "requestCount": 6, + "transferSize": 222247 + } + ] + } + }, + "layout-shifts": { + "id": "layout-shifts", + "title": "Avoid large layout shifts", + "description": "These are the largest layout shifts observed on the page. Each table item represents a single layout shift, and shows the element that shifted the most. Below each item are possible root causes that led to the layout shift. Some of these layout shifts may not be included in the CLS metric value due to [windowing](https://web.dev/articles/cls#what_is_cls). [Learn how to improve CLS](https://web.dev/articles/optimize-cls)", + "score": 0, + "scoreDisplayMode": "metricSavings", + "displayValue": "2 layout shifts found", + "metricSavings": { + "CLS": 0.133 + }, + "details": { + "type": "table", + "headings": [ + { + "key": "node", + "valueType": "node", + "subItemsHeading": { + "key": "extra" + }, + "label": "Element" + }, + { + "key": "score", + "valueType": "numeric", + "subItemsHeading": { + "key": "cause", + "valueType": "text" + }, + "granularity": 0.001, + "label": "Layout shift score" + } + ], + "items": [ + { + "node": { + "type": "node", + "lhId": "page-1-MAIN", + "path": "1,HTML,1,BODY,3,MAIN", + "selector": "body > main.site-shell", + "boundingRect": { + "top": 107, + "bottom": 3915, + "left": 68, + "right": 1268, + "width": 1200, + "height": 3808 + }, + "snippet": "
", + "nodeLabel": "PRO • CODEUR CREATIF • ITERATEUR IA • SAVANT FOU\n\nClement Saillant, alias L'ele…" + }, + "score": 0.1286776778847144, + "subItems": { + "type": "subitems", + "items": [ + { + "extra": { + "type": "url", + "value": "https://fonts.gstatic.com/s/fraunces/v38/6NU78FyLNQOQZAnv9bYEvDiIdE9Ea92uemAk_WBq8U_9v0c2Wa0KxC9TeP2Xz5c.woff2" + }, + "cause": "Web font loaded" + } + ] + } + }, + { + "node": { + "type": "node", + "lhId": "page-1-MAIN", + "path": "1,HTML,1,BODY,3,MAIN", + "selector": "body > main.site-shell", + "boundingRect": { + "top": 107, + "bottom": 3915, + "left": 68, + "right": 1268, + "width": 1200, + "height": 3808 + }, + "snippet": "
", + "nodeLabel": "PRO • CODEUR CREATIF • ITERATEUR IA • SAVANT FOU\n\nClement Saillant, alias L'ele…" + }, + "score": 0.004265503943642047 + } + ] + }, + "guidanceLevel": 2 + }, + "long-tasks": { + "id": "long-tasks", + "title": "Avoid long main-thread tasks", + "description": "Lists the longest tasks on the main thread, useful for identifying worst contributors to input delay. [Learn how to avoid long main-thread tasks](https://web.dev/articles/optimize-long-tasks)", + "score": 1, + "scoreDisplayMode": "informative", + "displayValue": "7 long tasks found", + "metricSavings": { + "TBT": 50 + }, + "details": { + "type": "table", + "headings": [ + { + "key": "url", + "valueType": "url", + "label": "URL" + }, + { + "key": "startTime", + "valueType": "ms", + "granularity": 1, + "label": "Start Time" + }, + { + "key": "duration", + "valueType": "ms", + "granularity": 1, + "label": "Duration" + } + ], + "items": [ + { + "url": "http://127.0.0.1:4322/", + "duration": 220.99999999999994, + "startTime": 356.94675 + }, + { + "url": "http://127.0.0.1:4322/_astro/client.BnVIp5Iu.js", + "duration": 144, + "startTime": 869.9467499999998 + }, + { + "url": "http://127.0.0.1:4322/", + "duration": 131.9999999999999, + "startTime": 577.94675 + }, + { + "url": "https://www.googletagmanager.com/gtm.js?id=GTM-5SLM67QF", + "duration": 130, + "startTime": 1013.9467499999998 + }, + { + "url": "http://127.0.0.1:4322/_astro/client.BnVIp5Iu.js", + "duration": 121, + "startTime": 723.9467499999998 + }, + { + "url": "http://127.0.0.1:4322/", + "duration": 116, + "startTime": 240.94675 + }, + { + "url": "http://127.0.0.1:4322/_astro/client.BnVIp5Iu.js", + "duration": 87, + "startTime": 1147.9467499999998 + } + ], + "sortedBy": [ + "duration" + ], + "skipSumming": [ + "startTime" + ], + "debugData": { + "type": "debugdata", + "urls": [ + "http://127.0.0.1:4322/", + "http://127.0.0.1:4322/_astro/client.BnVIp5Iu.js", + "https://www.googletagmanager.com/gtm.js?id=GTM-5SLM67QF" + ], + "tasks": [ + { + "urlIndex": 0, + "startTime": 356.9, + "duration": 221, + "other": 221, + "parseHTML": 0 + }, + { + "urlIndex": 1, + "startTime": 869.9, + "duration": 144, + "other": 144 + }, + { + "urlIndex": 0, + "startTime": 577.9, + "duration": 132, + "other": 132, + "paintCompositeRender": 0, + "styleLayout": 0 + }, + { + "urlIndex": 2, + "startTime": 1013.9, + "duration": 130, + "other": 130, + "scriptEvaluation": 0 + }, + { + "urlIndex": 1, + "startTime": 723.9, + "duration": 121, + "other": 121, + "scriptEvaluation": 0 + }, + { + "urlIndex": 0, + "startTime": 240.9, + "duration": 116, + "other": 116, + "paintCompositeRender": 0, + "styleLayout": 0 + }, + { + "urlIndex": 1, + "startTime": 1147.9, + "duration": 87, + "other": 87 + } + ] + } + }, + "guidanceLevel": 1 + }, + "non-composited-animations": { + "id": "non-composited-animations", + "title": "Avoid non-composited animations", + "description": "Animations which are not composited can be janky and increase CLS. [Learn how to avoid non-composited animations](https://developer.chrome.com/docs/lighthouse/performance/non-composited-animations/)", + "score": 1, + "scoreDisplayMode": "informative", + "displayValue": "19 animated elements found", + "metricSavings": { + "CLS": 0 + }, + "details": { + "type": "table", + "headings": [ + { + "key": "node", + "valueType": "node", + "subItemsHeading": { + "key": "failureReason", + "valueType": "text" + }, + "label": "Element" + }, + { + "key": null, + "valueType": "text", + "subItemsHeading": { + "key": "animation", + "valueType": "text" + }, + "label": "Name" + } + ], + "items": [ + { + "node": { + "type": "node", + "lhId": "page-2-::before", + "path": "1,HTML,1,BODY,2,HEADER,0,::before", + "selector": "body > header.sticky > ::before", + "boundingRect": { + "top": 105, + "bottom": 107, + "left": 68, + "right": 68, + "width": 0, + "height": 2 + }, + "snippet": "<::before>", + "nodeLabel": "body > header.sticky > ::before" + }, + "subItems": { + "type": "subitems", + "items": [ + { + "failureReason": "Unsupported CSS Property: background-position-x", + "animation": "v3ProgressFlow" + } + ] + } + }, + { + "node": { + "type": "node", + "lhId": "page-7-SPAN", + "path": "1,HTML,1,BODY,2,HEADER,0,DIV,2,DIV,2,SPAN", + "selector": "header.sticky > div.site-shell > div.nav-tools > span.lab-pill", + "boundingRect": { + "top": 20, + "bottom": 52, + "left": 1138, + "right": 1268, + "width": 129, + "height": 32 + }, + "snippet": "", + "nodeLabel": "LAB MODE ACTIF" + }, + "subItems": { + "type": "subitems", + "items": [ + { + "failureReason": "Unsupported CSS Property: box-shadow", + "animation": "labPulse" + } + ] + } + }, + { + "node": { + "type": "node", + "lhId": "page-8-::before", + "path": "1,HTML,1,BODY,2,HEADER,0,DIV,0,A,0,::before", + "selector": "header.sticky > div.site-shell > a.site-brand > ::before", + "boundingRect": { + "top": 26, + "bottom": 46, + "left": 68, + "right": 87, + "width": 20, + "height": 20 + }, + "snippet": "<::before>", + "nodeLabel": "header.sticky > div.site-shell > a.site-brand > ::before" + }, + "subItems": { + "type": "subitems", + "items": [ + { + "failureReason": "Unsupported CSS Property: box-shadow", + "animation": "brandSpark" + } + ] + } + }, + { + "node": { + "type": "node", + "lhId": "page-9-::before", + "path": "1,HTML,1,BODY,3,MAIN,1,SECTION,1,DIV,0,ASTRO-ISLAND,0,SECTION,0,DIV,0,::before", + "selector": "astro-island > section.section-anchor > div.circuit-board > ::before", + "boundingRect": { + "top": 1000, + "bottom": 1467, + "left": 533, + "right": 900, + "width": 367, + "height": 467 + }, + "snippet": "<::before>", + "nodeLabel": "astro-island > section.section-anchor > div.circuit-board > ::before" + }, + "subItems": { + "type": "subitems", + "items": [ + { + "failureReason": "Unsupported CSS Properties: background-position-x, background-position-y", + "animation": "v3TraceDrift" + } + ] + } + }, + { + "node": { + "type": "node", + "lhId": "page-10-::before", + "path": "1,HTML,1,BODY,3,MAIN,0,SECTION,1,DIV,1,ASTRO-ISLAND,0,SECTION,0,DIV,0,::before", + "selector": "astro-island > section#identite > div.circuit-board > ::before", + "boundingRect": { + "top": 139, + "bottom": 711, + "left": 882, + "right": 1267, + "width": 386, + "height": 572 + }, + "snippet": "<::before>", + "nodeLabel": "astro-island > section#identite > div.circuit-board > ::before" + }, + "subItems": { + "type": "subitems", + "items": [ + { + "failureReason": "Unsupported CSS Properties: background-position-x, background-position-y", + "animation": "v3TraceDrift" + } + ] + } + }, + { + "node": { + "type": "node", + "lhId": "page-11-::before", + "path": "1,HTML,1,BODY,3,MAIN,1,SECTION,0,DIV,0,ASTRO-ISLAND,0,SECTION,0,DIV,3,OL,1,LI,0,::before", + "selector": "div.circuit-board > ol.flow-diagram > li.flow-edge > ::before", + "boundingRect": { + "top": 1284, + "bottom": 1285, + "left": 172, + "right": 172, + "width": 0, + "height": 1 + }, + "snippet": "<::before>", + "nodeLabel": "div.circuit-board > ol.flow-diagram > li.flow-edge > ::before" + }, + "subItems": { + "type": "subitems", + "items": [ + { + "failureReason": "Unsupported CSS Property: background-position-x", + "animation": "v3SignalTravel" + } + ] + } + }, + { + "node": { + "type": "node", + "lhId": "page-12-::before", + "path": "1,HTML,1,BODY,3,MAIN,1,SECTION,0,DIV,0,ASTRO-ISLAND,0,SECTION,0,DIV,3,OL,3,LI,0,::before", + "selector": "div.circuit-board > ol.flow-diagram > li.flow-edge > ::before", + "boundingRect": { + "top": 1284, + "bottom": 1285, + "left": 291, + "right": 291, + "width": 0, + "height": 1 + }, + "snippet": "<::before>", + "nodeLabel": "div.circuit-board > ol.flow-diagram > li.flow-edge > ::before" + }, + "subItems": { + "type": "subitems", + "items": [ + { + "failureReason": "Unsupported CSS Property: background-position-x", + "animation": "v3SignalTravel" + } + ] + } + }, + { + "node": { + "type": "node", + "lhId": "page-13-::before", + "path": "1,HTML,1,BODY,3,MAIN,0,SECTION,0,DIV,3,ASTRO-ISLAND,0,SECTION,2,DIV,1,ASIDE,0,::before", + "selector": "section#top > div.grid > aside.circuit-board > ::before", + "boundingRect": { + "top": 481, + "bottom": 964, + "left": 554, + "right": 864, + "width": 311, + "height": 484 + }, + "snippet": "<::before>", + "nodeLabel": "section#top > div.grid > aside.circuit-board > ::before" + }, + "subItems": { + "type": "subitems", + "items": [ + { + "failureReason": "Unsupported CSS Properties: background-position-x, background-position-y", + "animation": "v3TraceDrift" + } + ] + } + }, + { + "node": { + "type": "node", + "lhId": "page-14-::before", + "path": "1,HTML,1,BODY,3,MAIN,2,SECTION,0,DIV,0,ASTRO-ISLAND,0,SECTION,0,DIV,0,::before", + "selector": "astro-island > section#projets > div.circuit-board > ::before", + "boundingRect": { + "top": 1811, + "bottom": 3290, + "left": 68, + "right": 533, + "width": 466, + "height": 1479 + }, + "snippet": "<::before>", + "nodeLabel": "astro-island > section#projets > div.circuit-board > ::before" + }, + "subItems": { + "type": "subitems", + "items": [ + { + "failureReason": "Unsupported CSS Properties: background-position-x, background-position-y", + "animation": "v3TraceDrift" + } + ] + } + }, + { + "node": { + "type": "node", + "lhId": "page-15-path", + "path": "1,HTML,1,BODY,3,MAIN,0,SECTION,1,DIV,1,ASTRO-ISLAND,0,SECTION,0,DIV,2,DIV,0,ARTICLE,2,svg,1,path", + "selector": "div.identity-lab-grid > article.logo-lab-card > svg.logo-lab-svg > path.logo-lab-trace", + "boundingRect": { + "top": 563, + "bottom": 570, + "left": 933, + "right": 947, + "width": 15, + "height": 7 + }, + "snippet": "", + "nodeLabel": "div.identity-lab-grid > article.logo-lab-card > svg.logo-lab-svg > path.logo-lab-trace" + }, + "subItems": { + "type": "subitems", + "items": [ + { + "failureReason": "Unsupported CSS Property: stroke-dashoffset", + "animation": "traceRun" + } + ] + } + }, + { + "node": { + "type": "node", + "lhId": "page-16-path", + "path": "1,HTML,1,BODY,3,MAIN,0,SECTION,1,DIV,1,ASTRO-ISLAND,0,SECTION,0,DIV,2,DIV,0,ARTICLE,2,svg,2,path", + "selector": "div.identity-lab-grid > article.logo-lab-card > svg.logo-lab-svg > path.logo-lab-trace", + "boundingRect": { + "top": 563, + "bottom": 574, + "left": 952, + "right": 973, + "width": 20, + "height": 11 + }, + "snippet": "", + "nodeLabel": "div.identity-lab-grid > article.logo-lab-card > svg.logo-lab-svg > path.logo-lab-trace" + }, + "subItems": { + "type": "subitems", + "items": [ + { + "failureReason": "Unsupported CSS Property: stroke-dashoffset", + "animation": "traceRun" + } + ] + } + }, + { + "node": { + "type": "node", + "lhId": "page-17-::before", + "path": "1,HTML,1,BODY,3,MAIN,1,SECTION,0,DIV,0,ASTRO-ISLAND,0,SECTION,0,DIV,3,OL,5,LI,0,::before", + "selector": "div.circuit-board > ol.flow-diagram > li.flow-edge > ::before", + "boundingRect": { + "top": 1284, + "bottom": 1285, + "left": 411, + "right": 411, + "width": 0, + "height": 1 + }, + "snippet": "<::before>", + "nodeLabel": "div.circuit-board > ol.flow-diagram > li.flow-edge > ::before" + }, + "subItems": { + "type": "subitems", + "items": [ + { + "failureReason": "Unsupported CSS Property: background-position-x", + "animation": "v3SignalTravel" + } + ] + } + }, + { + "node": { + "type": "node", + "lhId": "page-18-::before", + "path": "1,HTML,1,BODY,3,MAIN,1,SECTION,0,DIV,0,ASTRO-ISLAND,0,SECTION,0,DIV,0,::before", + "selector": "astro-island > section.flow-diagram-shell > div.circuit-board > ::before", + "boundingRect": { + "top": 1000, + "bottom": 1414, + "left": 68, + "right": 516, + "width": 448, + "height": 414 + }, + "snippet": "<::before>", + "nodeLabel": "astro-island > section.flow-diagram-shell > div.circuit-board > ::before" + }, + "subItems": { + "type": "subitems", + "items": [ + { + "failureReason": "Unsupported CSS Properties: background-position-x, background-position-y", + "animation": "v3TraceDrift" + } + ] + } + }, + { + "node": { + "type": "node", + "lhId": "page-19-::before", + "path": "1,HTML,1,BODY,3,MAIN,1,SECTION,2,DIV,0,ASTRO-ISLAND,0,SECTION,0,DIV,0,::before", + "selector": "astro-island > section#a-propos > div.circuit-board > ::before", + "boundingRect": { + "top": 1016, + "bottom": 1791, + "left": 917, + "right": 1267, + "width": 350, + "height": 775 + }, + "snippet": "<::before>", + "nodeLabel": "astro-island > section#a-propos > div.circuit-board > ::before" + }, + "subItems": { + "type": "subitems", + "items": [ + { + "failureReason": "Unsupported CSS Properties: background-position-x, background-position-y", + "animation": "v3TraceDrift" + } + ] + } + }, + { + "node": { + "type": "node", + "lhId": "page-20-::before", + "path": "1,HTML,1,BODY,3,MAIN,3,SECTION,0,DIV,0,ASTRO-ISLAND,0,SECTION,0,DIV,0,::before", + "selector": "astro-island > section.section-anchor > div.circuit-board > ::before", + "boundingRect": { + "top": 3336, + "bottom": 3794, + "left": 68, + "right": 659, + "width": 591, + "height": 458 + }, + "snippet": "<::before>", + "nodeLabel": "astro-island > section.section-anchor > div.circuit-board > ::before" + }, + "subItems": { + "type": "subitems", + "items": [ + { + "failureReason": "Unsupported CSS Properties: background-position-x, background-position-y", + "animation": "v3TraceDrift" + } + ] + } + }, + { + "node": { + "type": "node", + "lhId": "page-21-::before", + "path": "1,HTML,1,BODY,3,MAIN,3,SECTION,1,DIV,0,ASTRO-ISLAND,0,SECTION,0,DIV,0,::before", + "selector": "astro-island > section#contact > div.circuit-board > ::before", + "boundingRect": { + "top": 3342, + "bottom": 3883, + "left": 676, + "right": 1268, + "width": 591, + "height": 541 + }, + "snippet": "<::before>", + "nodeLabel": "astro-island > section#contact > div.circuit-board > ::before" + }, + "subItems": { + "type": "subitems", + "items": [ + { + "failureReason": "Unsupported CSS Properties: background-position-x, background-position-y", + "animation": "v3TraceDrift" + } + ] + } + }, + { + "node": { + "type": "node", + "lhId": "page-22-::before", + "path": "1,HTML,1,BODY,3,MAIN,2,SECTION,1,DIV,0,ASTRO-ISLAND,0,SECTION,0,DIV,0,::before", + "selector": "astro-island > section.section-anchor > div.circuit-board > ::before", + "boundingRect": { + "top": 1811, + "bottom": 3211, + "left": 551, + "right": 862, + "width": 311, + "height": 1400 + }, + "snippet": "<::before>", + "nodeLabel": "astro-island > section.section-anchor > div.circuit-board > ::before" + }, + "subItems": { + "type": "subitems", + "items": [ + { + "failureReason": "Unsupported CSS Properties: background-position-x, background-position-y", + "animation": "v3TraceDrift" + } + ] + } + }, + { + "node": { + "type": "node", + "lhId": "page-23-::before", + "path": "1,HTML,1,BODY,3,MAIN,2,SECTION,2,DIV,0,ASTRO-ISLAND,0,SECTION,0,DIV,0,::before", + "selector": "astro-island > section#lab-notes > div.circuit-board > ::before", + "boundingRect": { + "top": 1811, + "bottom": 2991, + "left": 879, + "right": 1268, + "width": 388, + "height": 1181 + }, + "snippet": "<::before>", + "nodeLabel": "astro-island > section#lab-notes > div.circuit-board > ::before" + }, + "subItems": { + "type": "subitems", + "items": [ + { + "failureReason": "Unsupported CSS Properties: background-position-x, background-position-y", + "animation": "v3TraceDrift" + } + ] + } + }, + { + "node": { + "type": "node", + "lhId": "page-24-A", + "path": "1,HTML,1,BODY,2,HEADER,0,DIV,1,NAV,0,UL,1,LI,0,A", + "selector": "nav > ul.m-0 > li > a.site-navlink", + "boundingRect": { + "top": 20, + "bottom": 52, + "left": 413, + "right": 498, + "width": 86, + "height": 32 + }, + "snippet": "", + "nodeLabel": "IDENTITE" + }, + "subItems": { + "type": "subitems", + "items": [ + { + "failureReason": "Unsupported CSS Property: box-shadow", + "animation": "v3NavPulse" + }, + { + "failureReason": "Unsupported CSS Property: border-bottom-color", + "animation": "border-bottom-color" + }, + { + "failureReason": "Unsupported CSS Property: border-left-color", + "animation": "border-left-color" + }, + { + "failureReason": "Unsupported CSS Property: border-right-color", + "animation": "border-right-color" + }, + { + "failureReason": "Unsupported CSS Property: color", + "animation": "color" + }, + { + "failureReason": "Unsupported CSS Property: border-top-color", + "animation": "border-top-color" + } + ] + } + } + ] + }, + "guidanceLevel": 2 + }, + "unsized-images": { + "id": "unsized-images", + "title": "Image elements have explicit `width` and `height`", + "description": "Set an explicit width and height on image elements to reduce layout shifts and improve CLS. [Learn how to set image dimensions](https://web.dev/articles/optimize-cls#images_without_dimensions)", + "score": 1, + "scoreDisplayMode": "metricSavings", + "metricSavings": { + "CLS": 0 + }, + "details": { + "type": "table", + "headings": [ + { + "key": "node", + "valueType": "node", + "label": "" + }, + { + "key": "url", + "valueType": "url", + "label": "URL" + } + ], + "items": [] + }, + "guidanceLevel": 4 + }, + "valid-source-maps": { + "id": "valid-source-maps", + "title": "Page has valid source maps", + "description": "Source maps translate minified code to the original source code. This helps developers debug in production. In addition, Lighthouse is able to provide further insights. Consider deploying source maps to take advantage of these benefits. [Learn more about source maps](https://developer.chrome.com/docs/devtools/javascript/source-maps/).", + "score": 1, + "scoreDisplayMode": "binary", + "details": { + "type": "table", + "headings": [ + { + "key": "scriptUrl", + "valueType": "url", + "subItemsHeading": { + "key": "error" + }, + "label": "URL" + }, + { + "key": "sourceMapUrl", + "valueType": "url", + "label": "Map URL" + } + ], + "items": [] + } + }, + "csp-xss": { + "id": "csp-xss", + "title": "Ensure CSP is effective against XSS attacks", + "description": "A strong Content Security Policy (CSP) significantly reduces the risk of cross-site scripting (XSS) attacks. [Learn how to use a CSP to prevent XSS](https://developer.chrome.com/docs/lighthouse/best-practices/csp-xss/)", + "score": 1, + "scoreDisplayMode": "informative", + "details": { + "type": "table", + "headings": [ + { + "key": "description", + "valueType": "text", + "subItemsHeading": { + "key": "description" + }, + "label": "Description" + }, + { + "key": "directive", + "valueType": "code", + "subItemsHeading": { + "key": "directive" + }, + "label": "Directive" + }, + { + "key": "severity", + "valueType": "text", + "subItemsHeading": { + "key": "severity" + }, + "label": "Severity" + } + ], + "items": [ + { + "severity": "High", + "description": "No CSP found in enforcement mode" + } + ] + } + }, + "has-hsts": { + "id": "has-hsts", + "title": "Use a strong HSTS policy", + "description": "Deployment of the HSTS header significantly reduces the risk of downgrading HTTP connections and eavesdropping attacks. A rollout in stages, starting with a low max-age is recommended. [Learn more about using a strong HSTS policy.](https://developer.chrome.com/docs/lighthouse/best-practices/has-hsts)", + "score": 1, + "scoreDisplayMode": "informative", + "details": { + "type": "table", + "headings": [ + { + "key": "description", + "valueType": "text", + "subItemsHeading": { + "key": "description" + }, + "label": "Description" + }, + { + "key": "directive", + "valueType": "code", + "subItemsHeading": { + "key": "directive" + }, + "label": "Directive" + }, + { + "key": "severity", + "valueType": "text", + "subItemsHeading": { + "key": "severity" + }, + "label": "Severity" + } + ], + "items": [ + { + "severity": "High", + "description": "No HSTS header found" + } + ] + } + }, + "origin-isolation": { + "id": "origin-isolation", + "title": "Ensure proper origin isolation with COOP", + "description": "The Cross-Origin-Opener-Policy (COOP) can be used to isolate the top-level window from other documents such as pop-ups. [Learn more about deploying the COOP header.](https://web.dev/articles/why-coop-coep#coop)", + "score": 1, + "scoreDisplayMode": "informative", + "details": { + "type": "table", + "headings": [ + { + "key": "description", + "valueType": "text", + "subItemsHeading": { + "key": "description" + }, + "label": "Description" + }, + { + "key": "directive", + "valueType": "code", + "subItemsHeading": { + "key": "directive" + }, + "label": "Directive" + }, + { + "key": "severity", + "valueType": "text", + "subItemsHeading": { + "key": "severity" + }, + "label": "Severity" + } + ], + "items": [ + { + "description": "No COOP header found", + "severity": "High" + } + ] + } + }, + "clickjacking-mitigation": { + "id": "clickjacking-mitigation", + "title": "Mitigate clickjacking with XFO or CSP", + "description": "The `X-Frame-Options` (XFO) header or the `frame-ancestors` directive in the `Content-Security-Policy` (CSP) header control where a page can be embedded. These can mitigate clickjacking attacks by blocking some or all sites from embedding the page. [Learn more about mitigating clickjacking](https://developer.chrome.com/docs/lighthouse/best-practices/clickjacking-mitigation).", + "score": 1, + "scoreDisplayMode": "informative", + "details": { + "type": "table", + "headings": [ + { + "key": "description", + "valueType": "text", + "subItemsHeading": { + "key": "description" + }, + "label": "Description" + }, + { + "key": "severity", + "valueType": "text", + "subItemsHeading": { + "key": "severity" + }, + "label": "Severity" + } + ], + "items": [ + { + "severity": "High", + "description": "No frame control policy found" + } + ] + } + }, + "trusted-types-xss": { + "id": "trusted-types-xss", + "title": "Mitigate DOM-based XSS with Trusted Types", + "description": "The `require-trusted-types-for` directive in the `Content-Security-Policy` (CSP) header instructs user agents to control the data passed to DOM XSS sink functions. [Learn more about mitigating DOM-based XSS with Trusted Types](https://developer.chrome.com/docs/lighthouse/best-practices/trusted-types-xss).", + "score": 1, + "scoreDisplayMode": "informative", + "details": { + "type": "table", + "headings": [ + { + "key": "description", + "valueType": "text", + "subItemsHeading": { + "key": "description" + }, + "label": "Description" + }, + { + "key": "severity", + "valueType": "text", + "subItemsHeading": { + "key": "severity" + }, + "label": "Severity" + } + ], + "items": [ + { + "severity": "High", + "description": "No `Content-Security-Policy` header with Trusted Types directive found" + } + ] + } + }, + "script-treemap-data": { + "id": "script-treemap-data", + "title": "Script Treemap Data", + "description": "Used for treemap app", + "score": 1, + "scoreDisplayMode": "informative", + "details": { + "type": "treemap-data", + "nodes": [ + { + "name": "http://127.0.0.1:4322/", + "resourceBytes": 9867, + "encodedBytes": 2012, + "unusedBytes": 1599, + "children": [ + { + "name": "(inline) (function(){con…", + "resourceBytes": 610, + "unusedBytes": 0 + }, + { + "name": "(inline) (()=>{var e=asy…", + "resourceBytes": 130, + "unusedBytes": 0 + }, + { + "name": "(inline) (()=>{var A=Obj…", + "resourceBytes": 3462, + "unusedBytes": 499 + }, + { + "name": "(inline) (()=>{var a=(s,…", + "resourceBytes": 372, + "unusedBytes": 0 + }, + { + "name": "(inline) (function () {\n…", + "resourceBytes": 668, + "unusedBytes": 457 + }, + { + "name": "(inline) (function () {\n…", + "resourceBytes": 1927, + "unusedBytes": 239 + }, + { + "name": "(inline) (function () {\n…", + "resourceBytes": 2698, + "unusedBytes": 404 + } + ] + }, + { + "name": "https://www.googletagmanager.com/gtm.js?id=GTM-5SLM67QF", + "resourceBytes": 302204, + "encodedBytes": 108115, + "unusedBytes": 193287 + }, + { + "name": "http://127.0.0.1:4322/_astro/client.BnVIp5Iu.js", + "resourceBytes": 186619, + "encodedBytes": 58522, + "unusedBytes": 100175 + }, + { + "name": "http://127.0.0.1:4322/_astro/index.DJ4e78gH.js", + "resourceBytes": 8355, + "encodedBytes": 3293, + "unusedBytes": 2854 + }, + { + "name": "http://127.0.0.1:4322/_astro/Hero.CWdFfU6a.js", + "resourceBytes": 5535, + "encodedBytes": 1897, + "unusedBytes": 0 + }, + { + "name": "http://127.0.0.1:4322/_astro/proxy.DrdNLT3k.js", + "resourceBytes": 119539, + "encodedBytes": 39324, + "unusedBytes": 69267 + }, + { + "name": "http://127.0.0.1:4322/_astro/cta-dual-rail.BsNvZaAg.js", + "resourceBytes": 31586, + "encodedBytes": 10327, + "unusedBytes": 1575 + }, + { + "name": "http://127.0.0.1:4322/_astro/tracking.D1HldQGt.js", + "resourceBytes": 448, + "encodedBytes": 448, + "unusedBytes": 0 + }, + { + "name": "http://127.0.0.1:4322/_astro/Projects.DwnD_OPS.js", + "resourceBytes": 3927, + "encodedBytes": 1627, + "unusedBytes": 0 + }, + { + "name": "http://127.0.0.1:4322/_astro/FlowDiagram.rObCbwEq.js", + "resourceBytes": 2923, + "encodedBytes": 1266, + "unusedBytes": 0 + }, + { + "name": "http://127.0.0.1:4322/_astro/use-reduced-motion.ye2a724N.js", + "resourceBytes": 179, + "encodedBytes": 179, + "unusedBytes": 0 + }, + { + "name": "http://127.0.0.1:4322/_astro/IdentityLab.CG225saZ.js", + "resourceBytes": 4277, + "encodedBytes": 1213, + "unusedBytes": 0 + } + ] + } + }, + "accesskeys": { + "id": "accesskeys", + "title": "`[accesskey]` values are unique", + "description": "Access keys let users quickly focus a part of the page. For proper navigation, each access key must be unique. [Learn more about access keys](https://dequeuniversity.com/rules/axe/4.11/accesskeys).", + "score": null, + "scoreDisplayMode": "notApplicable" + }, + "aria-allowed-attr": { + "id": "aria-allowed-attr", + "title": "`[aria-*]` attributes match their roles", + "description": "Each ARIA `role` supports a specific subset of `aria-*` attributes. Mismatching these invalidates the `aria-*` attributes. [Learn how to match ARIA attributes to their roles](https://dequeuniversity.com/rules/axe/4.11/aria-allowed-attr).", + "score": 1, + "scoreDisplayMode": "binary", + "details": { + "type": "table", + "headings": [ + { + "key": "node", + "valueType": "node", + "subItemsHeading": { + "key": "relatedNode", + "valueType": "node" + }, + "label": "Failing Elements" + } + ], + "items": [] + } + }, + "aria-allowed-role": { + "id": "aria-allowed-role", + "title": "Uses ARIA roles only on compatible elements", + "description": "Many HTML elements can only be assigned certain ARIA roles. Using ARIA roles where they are not allowed can interfere with the accessibility of the web page. [Learn more about ARIA roles](https://dequeuniversity.com/rules/axe/4.11/aria-allowed-role).", + "score": 1, + "scoreDisplayMode": "informative", + "details": { + "type": "table", + "headings": [ + { + "key": "node", + "valueType": "node", + "subItemsHeading": { + "key": "relatedNode", + "valueType": "node" + }, + "label": "Failing Elements" + } + ], + "items": [ + { + "node": { + "type": "node", + "lhId": "1-0-ARTICLE", + "path": "1,HTML,1,BODY,3,MAIN,3,SECTION,0,DIV,0,ASTRO-ISLAND,0,SECTION,0,DIV,2,DIV,0,ARTICLE", + "selector": "section.section-anchor > div.circuit-board > div.trust-strip > article.trust-pill", + "boundingRect": { + "top": 3478, + "bottom": 3624, + "left": 93, + "right": 267, + "width": 174, + "height": 147 + }, + "snippet": "
", + "nodeLabel": "COLLABORATIONS\n\nStudio / design / audiovisuel\n\nApproche orientee systeme et liv…", + "explanation": "Fix any of the following:\n ARIA role listitem is not allowed for given element" + } + }, + { + "node": { + "type": "node", + "lhId": "1-1-ARTICLE", + "path": "1,HTML,1,BODY,3,MAIN,3,SECTION,0,DIV,0,ASTRO-ISLAND,0,SECTION,0,DIV,2,DIV,1,ARTICLE", + "selector": "section.section-anchor > div.circuit-board > div.trust-strip > article.trust-pill", + "boundingRect": { + "top": 3478, + "bottom": 3624, + "left": 276, + "right": 450, + "width": 174, + "height": 147 + }, + "snippet": "
", + "nodeLabel": "PROJETS ACTIFS\n\nR&D electronique + UX conversion\n\nChaîne complete: idee, protot…", + "explanation": "Fix any of the following:\n ARIA role listitem is not allowed for given element" + } + }, + { + "node": { + "type": "node", + "lhId": "1-2-ARTICLE", + "path": "1,HTML,1,BODY,3,MAIN,3,SECTION,0,DIV,0,ASTRO-ISLAND,0,SECTION,0,DIV,2,DIV,2,ARTICLE", + "selector": "section.section-anchor > div.circuit-board > div.trust-strip > article.trust-pill", + "boundingRect": { + "top": 3478, + "bottom": 3624, + "left": 459, + "right": 634, + "width": 174, + "height": 147 + }, + "snippet": "
", + "nodeLabel": "LIENS VERIFIABLES\n\nLinkedIn, Malt, Bandcamp, GitHub\n\nReferences hardware/firmwa…", + "explanation": "Fix any of the following:\n ARIA role listitem is not allowed for given element" + } + } + ], + "debugData": { + "type": "debugdata", + "impact": "minor", + "tags": [ + "cat.aria", + "best-practice" + ] + } + } + }, + "aria-command-name": { + "id": "aria-command-name", + "title": "`button`, `link`, and `menuitem` elements have accessible names", + "description": "When an element doesn't have an accessible name, screen readers announce it with a generic name, making it unusable for users who rely on screen readers. [Learn how to make command elements more accessible](https://dequeuniversity.com/rules/axe/4.11/aria-command-name).", + "score": null, + "scoreDisplayMode": "notApplicable" + }, + "aria-conditional-attr": { + "id": "aria-conditional-attr", + "title": "ARIA attributes are used as specified for the element's role", + "description": "Some ARIA attributes are only allowed on an element under certain conditions. [Learn more about conditional ARIA attributes](https://dequeuniversity.com/rules/axe/4.11/aria-conditional-attr).", + "score": 1, + "scoreDisplayMode": "binary", + "details": { + "type": "table", + "headings": [ + { + "key": "node", + "valueType": "node", + "subItemsHeading": { + "key": "relatedNode", + "valueType": "node" + }, + "label": "Failing Elements" + } + ], + "items": [] + } + }, + "aria-deprecated-role": { + "id": "aria-deprecated-role", + "title": "Deprecated ARIA roles were not used", + "description": "Deprecated ARIA roles may not be processed correctly by assistive technology. [Learn more about deprecated ARIA roles](https://dequeuniversity.com/rules/axe/4.11/aria-deprecated-role).", + "score": 1, + "scoreDisplayMode": "binary", + "details": { + "type": "table", + "headings": [ + { + "key": "node", + "valueType": "node", + "subItemsHeading": { + "key": "relatedNode", + "valueType": "node" + }, + "label": "Failing Elements" + } + ], + "items": [] + } + }, + "aria-dialog-name": { + "id": "aria-dialog-name", + "title": "Elements with `role=\"dialog\"` or `role=\"alertdialog\"` have accessible names.", + "description": "ARIA dialog elements without accessible names may prevent screen readers users from discerning the purpose of these elements. [Learn how to make ARIA dialog elements more accessible](https://dequeuniversity.com/rules/axe/4.11/aria-dialog-name).", + "score": null, + "scoreDisplayMode": "notApplicable" + }, + "aria-hidden-body": { + "id": "aria-hidden-body", + "title": "`[aria-hidden=\"true\"]` is not present on the document ``", + "description": "Assistive technologies, like screen readers, work inconsistently when `aria-hidden=\"true\"` is set on the document ``. [Learn how `aria-hidden` affects the document body](https://dequeuniversity.com/rules/axe/4.11/aria-hidden-body).", + "score": 1, + "scoreDisplayMode": "binary", + "details": { + "type": "table", + "headings": [ + { + "key": "node", + "valueType": "node", + "subItemsHeading": { + "key": "relatedNode", + "valueType": "node" + }, + "label": "Failing Elements" + } + ], + "items": [] + } + }, + "aria-hidden-focus": { + "id": "aria-hidden-focus", + "title": "`[aria-hidden=\"true\"]` elements do not contain focusable descendents", + "description": "Focusable descendents within an `[aria-hidden=\"true\"]` element prevent those interactive elements from being available to users of assistive technologies like screen readers. [Learn how `aria-hidden` affects focusable elements](https://dequeuniversity.com/rules/axe/4.11/aria-hidden-focus).", + "score": 1, + "scoreDisplayMode": "binary", + "details": { + "type": "table", + "headings": [ + { + "key": "node", + "valueType": "node", + "subItemsHeading": { + "key": "relatedNode", + "valueType": "node" + }, + "label": "Failing Elements" + } + ], + "items": [] + } + }, + "aria-input-field-name": { + "id": "aria-input-field-name", + "title": "ARIA input fields have accessible names", + "description": "When an input field doesn't have an accessible name, screen readers announce it with a generic name, making it unusable for users who rely on screen readers. [Learn more about input field labels](https://dequeuniversity.com/rules/axe/4.11/aria-input-field-name).", + "score": null, + "scoreDisplayMode": "notApplicable" + }, + "aria-meter-name": { + "id": "aria-meter-name", + "title": "ARIA `meter` elements have accessible names", + "description": "When a meter element doesn't have an accessible name, screen readers announce it with a generic name, making it unusable for users who rely on screen readers. [Learn how to name `meter` elements](https://dequeuniversity.com/rules/axe/4.11/aria-meter-name).", + "score": null, + "scoreDisplayMode": "notApplicable" + }, + "aria-progressbar-name": { + "id": "aria-progressbar-name", + "title": "ARIA `progressbar` elements have accessible names", + "description": "When a `progressbar` element doesn't have an accessible name, screen readers announce it with a generic name, making it unusable for users who rely on screen readers. [Learn how to label `progressbar` elements](https://dequeuniversity.com/rules/axe/4.11/aria-progressbar-name).", + "score": null, + "scoreDisplayMode": "notApplicable" + }, + "aria-prohibited-attr": { + "id": "aria-prohibited-attr", + "title": "Elements use only permitted ARIA attributes", + "description": "Using ARIA attributes in roles where they are prohibited can mean that important information is not communicated to users of assistive technologies. [Learn more about prohibited ARIA roles](https://dequeuniversity.com/rules/axe/4.11/aria-prohibited-attr).", + "score": 1, + "scoreDisplayMode": "binary", + "details": { + "type": "table", + "headings": [ + { + "key": "node", + "valueType": "node", + "subItemsHeading": { + "key": "relatedNode", + "valueType": "node" + }, + "label": "Failing Elements" + } + ], + "items": [] + } + }, + "aria-required-attr": { + "id": "aria-required-attr", + "title": "`[role]`s have all required `[aria-*]` attributes", + "description": "Some ARIA roles have required attributes that describe the state of the element to screen readers. [Learn more about roles and required attributes](https://dequeuniversity.com/rules/axe/4.11/aria-required-attr).", + "score": 1, + "scoreDisplayMode": "binary", + "details": { + "type": "table", + "headings": [ + { + "key": "node", + "valueType": "node", + "subItemsHeading": { + "key": "relatedNode", + "valueType": "node" + }, + "label": "Failing Elements" + } + ], + "items": [] + } + }, + "aria-required-children": { + "id": "aria-required-children", + "title": "Elements with an ARIA `[role]` that require children to contain a specific `[role]` have all required children.", + "description": "Some ARIA parent roles must contain specific child roles to perform their intended accessibility functions. [Learn more about roles and required children elements](https://dequeuniversity.com/rules/axe/4.11/aria-required-children).", + "score": 1, + "scoreDisplayMode": "binary", + "details": { + "type": "table", + "headings": [ + { + "key": "node", + "valueType": "node", + "subItemsHeading": { + "key": "relatedNode", + "valueType": "node" + }, + "label": "Failing Elements" + } + ], + "items": [] + } + }, + "aria-required-parent": { + "id": "aria-required-parent", + "title": "`[role]`s are contained by their required parent element", + "description": "Some ARIA child roles must be contained by specific parent roles to properly perform their intended accessibility functions. [Learn more about ARIA roles and required parent element](https://dequeuniversity.com/rules/axe/4.11/aria-required-parent).", + "score": 1, + "scoreDisplayMode": "binary", + "details": { + "type": "table", + "headings": [ + { + "key": "node", + "valueType": "node", + "subItemsHeading": { + "key": "relatedNode", + "valueType": "node" + }, + "label": "Failing Elements" + } + ], + "items": [] + } + }, + "aria-roles": { + "id": "aria-roles", + "title": "`[role]` values are valid", + "description": "ARIA roles must have valid values in order to perform their intended accessibility functions. [Learn more about valid ARIA roles](https://dequeuniversity.com/rules/axe/4.11/aria-roles).", + "score": 1, + "scoreDisplayMode": "binary", + "details": { + "type": "table", + "headings": [ + { + "key": "node", + "valueType": "node", + "subItemsHeading": { + "key": "relatedNode", + "valueType": "node" + }, + "label": "Failing Elements" + } + ], + "items": [] + } + }, + "aria-text": { + "id": "aria-text", + "title": "Elements with the `role=text` attribute do not have focusable descendents.", + "description": "Adding `role=text` around a text node split by markup enables VoiceOver to treat it as one phrase, but the element's focusable descendents will not be announced. [Learn more about the `role=text` attribute](https://dequeuniversity.com/rules/axe/4.11/aria-text).", + "score": null, + "scoreDisplayMode": "notApplicable" + }, + "aria-toggle-field-name": { + "id": "aria-toggle-field-name", + "title": "ARIA toggle fields have accessible names", + "description": "When a toggle field doesn't have an accessible name, screen readers announce it with a generic name, making it unusable for users who rely on screen readers. [Learn more about toggle fields](https://dequeuniversity.com/rules/axe/4.11/aria-toggle-field-name).", + "score": null, + "scoreDisplayMode": "notApplicable" + }, + "aria-tooltip-name": { + "id": "aria-tooltip-name", + "title": "ARIA `tooltip` elements have accessible names", + "description": "When a tooltip element doesn't have an accessible name, screen readers announce it with a generic name, making it unusable for users who rely on screen readers. [Learn how to name `tooltip` elements](https://dequeuniversity.com/rules/axe/4.11/aria-tooltip-name).", + "score": null, + "scoreDisplayMode": "notApplicable" + }, + "aria-treeitem-name": { + "id": "aria-treeitem-name", + "title": "ARIA `treeitem` elements have accessible names", + "description": "When a `treeitem` element doesn't have an accessible name, screen readers announce it with a generic name, making it unusable for users who rely on screen readers. [Learn more about labeling `treeitem` elements](https://dequeuniversity.com/rules/axe/4.11/aria-treeitem-name).", + "score": null, + "scoreDisplayMode": "notApplicable" + }, + "aria-valid-attr-value": { + "id": "aria-valid-attr-value", + "title": "`[aria-*]` attributes have valid values", + "description": "Assistive technologies, like screen readers, can't interpret ARIA attributes with invalid values. [Learn more about valid values for ARIA attributes](https://dequeuniversity.com/rules/axe/4.11/aria-valid-attr-value).", + "score": 1, + "scoreDisplayMode": "binary", + "details": { + "type": "table", + "headings": [ + { + "key": "node", + "valueType": "node", + "subItemsHeading": { + "key": "relatedNode", + "valueType": "node" + }, + "label": "Failing Elements" + } + ], + "items": [] + } + }, + "aria-valid-attr": { + "id": "aria-valid-attr", + "title": "`[aria-*]` attributes are valid and not misspelled", + "description": "Assistive technologies, like screen readers, can't interpret ARIA attributes with invalid names. [Learn more about valid ARIA attributes](https://dequeuniversity.com/rules/axe/4.11/aria-valid-attr).", + "score": 1, + "scoreDisplayMode": "binary", + "details": { + "type": "table", + "headings": [ + { + "key": "node", + "valueType": "node", + "subItemsHeading": { + "key": "relatedNode", + "valueType": "node" + }, + "label": "Failing Elements" + } + ], + "items": [] + } + }, + "button-name": { + "id": "button-name", + "title": "Buttons have an accessible name", + "description": "When a button doesn't have an accessible name, screen readers announce it as \"button\", making it unusable for users who rely on screen readers. [Learn how to make buttons more accessible](https://dequeuniversity.com/rules/axe/4.11/button-name).", + "score": 1, + "scoreDisplayMode": "binary", + "details": { + "type": "table", + "headings": [ + { + "key": "node", + "valueType": "node", + "subItemsHeading": { + "key": "relatedNode", + "valueType": "node" + }, + "label": "Failing Elements" + } + ], + "items": [] + } + }, + "bypass": { + "id": "bypass", + "title": "The page contains a heading, skip link, or landmark region", + "description": "Adding ways to bypass repetitive content lets keyboard users navigate the page more efficiently. [Learn more about bypass blocks](https://dequeuniversity.com/rules/axe/4.11/bypass).", + "score": null, + "scoreDisplayMode": "notApplicable" + }, + "color-contrast": { + "id": "color-contrast", + "title": "Background and foreground colors have a sufficient contrast ratio", + "description": "Low-contrast text is difficult or impossible for many users to read. [Learn how to provide sufficient color contrast](https://dequeuniversity.com/rules/axe/4.11/color-contrast).", + "score": 1, + "scoreDisplayMode": "binary", + "details": { + "type": "table", + "headings": [ + { + "key": "node", + "valueType": "node", + "subItemsHeading": { + "key": "relatedNode", + "valueType": "node" + }, + "label": "Failing Elements" + } + ], + "items": [] + } + }, + "definition-list": { + "id": "definition-list", + "title": "`
`'s contain only properly-ordered `
` and `
` groups, ` + + + + + + + + + + + + + +
+
+

Creative systems studio

+

+ Je construis des experiences electroniques qui connectent design, code et IA. +

+

+ De l'idee au prototype live: direction produit, architecture technique et execution visuelle pour + lancements, installations et projets experimentaux. +

+ +
    +
  • + Systemes + UX, hardware et logiciel alignes +
  • +
  • + IA appliquee + prototypage rapide et pipelines intelligents +
  • +
  • + Production + execution propre, mesurable, deployable +
  • +
+
+ +
+
+

Approche

+

Direction artistique + direction systeme

+
+

+ Mon role est de transformer une intention en systeme operationnel: narration visuelle, architecture, + instrumentation et decisions produit. J'interviens comme partenaire de conception et de livraison. +

+
+ Creative coding + Design produit + Systemes embarques + Automation IA + Tracking GA4/GTM +
+
+ +
+
+

Top projets

+

3 references GitHub prioritaires

+
+ +
+
+

Real-time embedded stack

+

RTC_BL_PHONE

+

+ Firmware ESP32 avec WebUI, audio, Bluetooth et orchestration multi-modules pour experiences de + communication temps reel. +

+ + Ouvrir le repo + +
+ +
+

Narrative UI and scene engine

+

Le Mystere Professeur Zacus

+

+ Pipeline scenes/screens, effets visuels et logique d'interaction pour experiences immersives sur + hardware contraint. +

+ + Ouvrir le repo + +
+ +
+

Portfolio and conversion stack

+

electron-rare.github.io

+

+ Site vitrine orienté conversion: message clair, preuves directes, instrumentation GA4 et gouvernance + DA continue. +

+ + Ouvrir le repo + +
+
+
+ +
+
+

GitHub Lab

+

Section dediee aux references techniques

+
+

+ Ici je centralise les depots de travail, prototypes secondaires et experiments en cours, avec suivi des + iterations. +

+ + Voir plus sur GitHub + + + Ouvrir le Lab interactif + +
+ +
+
+

Contact

+

Parlons lancement, prototype ou mission studio

+
+

+ Je prends des missions autour du design systeme, du prototypage produit et des experiences creatives + instrumentees. +

+ +
+
+ +
+ +
+ + + + diff --git a/lab/assets/index-7Y0vZRJY.css b/lab/assets/index-7Y0vZRJY.css new file mode 100644 index 0000000..7b37a47 --- /dev/null +++ b/lab/assets/index-7Y0vZRJY.css @@ -0,0 +1 @@ +@import"https://fonts.googleapis.com/css2?family=Manrope:wght@400;500;600;700;800&family=Prata&display=swap";:root{--lab-bg: #171a1e;--lab-surface: #222830;--lab-surface-soft: #2b3441;--lab-line: #3d4b5d;--lab-text: #f2f4f8;--lab-muted: #b8c4d3;--lab-accent: #f2a666;--lab-accent-2: #7bd5cf}*{box-sizing:border-box}html,body,#root{min-height:100%}body{margin:0;font-family:Manrope,Segoe UI,sans-serif;color:var(--lab-text);background:radial-gradient(1000px 500px at 15% -20%,rgba(242,166,102,.18),transparent 55%),radial-gradient(800px 460px at 100% 0%,rgba(123,213,207,.2),transparent 55%),var(--lab-bg)}.lab-shell{width:min(1080px,92vw);margin:0 auto}.lab-header{position:sticky;top:0;z-index:20;border-bottom:1px solid var(--lab-line);background:color-mix(in oklab,var(--lab-bg) 86%,black 14%);-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px)}.lab-header .lab-shell{min-height:74px;display:flex;align-items:center;justify-content:space-between;gap:1rem}.lab-brand{display:inline-flex;text-decoration:none;color:var(--lab-accent);font-weight:700}.lab-header ul{margin:0;padding:0;list-style:none;display:flex;gap:.5rem;flex-wrap:wrap}.lab-header a{min-height:2.2rem;display:inline-flex;align-items:center;text-decoration:none;color:var(--lab-text);border:1px solid transparent;border-radius:999px;padding:0 .85rem;font-size:.9rem;font-weight:600}.lab-header a.active,.lab-header a:hover,.lab-header a:focus-visible{border-color:var(--lab-line);background:color-mix(in oklab,var(--lab-surface-soft) 80%,var(--lab-accent-2) 20%)}main{padding-block:1.2rem 2.8rem}.lab-panel{border:1px solid var(--lab-line);border-radius:18px;background:linear-gradient(180deg,var(--lab-surface),color-mix(in oklab,var(--lab-surface) 70%,black 30%));box-shadow:0 16px 42px #00000047;padding:1rem}.lab-kicker{margin:0;text-transform:uppercase;letter-spacing:.14em;font-size:.72rem;color:var(--lab-accent-2);font-weight:700}h1,h2{font-family:Prata,Georgia,serif;margin:0;font-weight:400}h1{margin-top:.5rem;font-size:clamp(1.8rem,5vw,3rem)}.lab-panel>p{color:var(--lab-muted);margin:.9rem 0 0;max-width:70ch}.lab-grid{margin-top:1rem;display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:.6rem}.lab-grid article,.signal-grid article,.prototype-list li{border:1px solid var(--lab-line);border-radius:14px;background:color-mix(in oklab,var(--lab-surface-soft) 82%,black 18%);padding:.8rem}.signal-grid{margin-top:.9rem;display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:.6rem}.signal-grid strong{display:block;margin-top:.35rem;color:var(--lab-accent);font-size:1.35rem}.signal-grid p,.prototype-list p{margin:.4rem 0 0;color:var(--lab-muted)}.prototype-list{margin:1rem 0 0;padding:0;list-style:none;display:grid;gap:.58rem}.prototype-list li{display:flex;justify-content:space-between;gap:.8rem;align-items:flex-start}.prototype-list span{border:1px solid var(--lab-line);border-radius:999px;min-height:1.9rem;display:inline-flex;align-items:center;padding:0 .66rem;font-size:.72rem;text-transform:uppercase;letter-spacing:.06em;color:var(--lab-accent-2)}code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;background:#00000040;border:1px solid var(--lab-line);border-radius:6px;padding:.14rem .3rem}@media(max-width:900px){.signal-grid,.lab-grid{grid-template-columns:1fr}}@media(max-width:700px){.lab-header .lab-shell{min-height:auto;flex-direction:column;align-items:flex-start;padding-block:.7rem}.prototype-list li{flex-direction:column}} diff --git a/lab/assets/index-Zjyw1-5g.js b/lab/assets/index-Zjyw1-5g.js new file mode 100644 index 0000000..ed61b55 --- /dev/null +++ b/lab/assets/index-Zjyw1-5g.js @@ -0,0 +1,11 @@ +(function(){const o=document.createElement("link").relList;if(o&&o.supports&&o.supports("modulepreload"))return;for(const h of document.querySelectorAll('link[rel="modulepreload"]'))c(h);new MutationObserver(h=>{for(const m of h)if(m.type==="childList")for(const S of m.addedNodes)S.tagName==="LINK"&&S.rel==="modulepreload"&&c(S)}).observe(document,{childList:!0,subtree:!0});function s(h){const m={};return h.integrity&&(m.integrity=h.integrity),h.referrerPolicy&&(m.referrerPolicy=h.referrerPolicy),h.crossOrigin==="use-credentials"?m.credentials="include":h.crossOrigin==="anonymous"?m.credentials="omit":m.credentials="same-origin",m}function c(h){if(h.ep)return;h.ep=!0;const m=s(h);fetch(h.href,m)}})();function Iy(f){return f&&f.__esModule&&Object.prototype.hasOwnProperty.call(f,"default")?f.default:f}var Oc={exports:{}},Mu={};var wd;function Py(){if(wd)return Mu;wd=1;var f=Symbol.for("react.transitional.element"),o=Symbol.for("react.fragment");function s(c,h,m){var S=null;if(m!==void 0&&(S=""+m),h.key!==void 0&&(S=""+h.key),"key"in h){m={};for(var M in h)M!=="key"&&(m[M]=h[M])}else m=h;return h=m.ref,{$$typeof:f,type:c,key:S,ref:h!==void 0?h:null,props:m}}return Mu.Fragment=o,Mu.jsx=s,Mu.jsxs=s,Mu}var $d;function tv(){return $d||($d=1,Oc.exports=Py()),Oc.exports}var V=tv(),Mc={exports:{}},F={};var Wd;function ev(){if(Wd)return F;Wd=1;var f=Symbol.for("react.transitional.element"),o=Symbol.for("react.portal"),s=Symbol.for("react.fragment"),c=Symbol.for("react.strict_mode"),h=Symbol.for("react.profiler"),m=Symbol.for("react.consumer"),S=Symbol.for("react.context"),M=Symbol.for("react.forward_ref"),b=Symbol.for("react.suspense"),g=Symbol.for("react.memo"),N=Symbol.for("react.lazy"),A=Symbol.for("react.activity"),q=Symbol.iterator;function J(v){return v===null||typeof v!="object"?null:(v=q&&v[q]||v["@@iterator"],typeof v=="function"?v:null)}var Z={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},L=Object.assign,H={};function w(v,x,j){this.props=v,this.context=x,this.refs=H,this.updater=j||Z}w.prototype.isReactComponent={},w.prototype.setState=function(v,x){if(typeof v!="object"&&typeof v!="function"&&v!=null)throw Error("takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,v,x,"setState")},w.prototype.forceUpdate=function(v){this.updater.enqueueForceUpdate(this,v,"forceUpdate")};function I(){}I.prototype=w.prototype;function $(v,x,j){this.props=v,this.context=x,this.refs=H,this.updater=j||Z}var pt=$.prototype=new I;pt.constructor=$,L(pt,w.prototype),pt.isPureReactComponent=!0;var St=Array.isArray;function Rt(){}var k={H:null,A:null,T:null,S:null},Dt=Object.prototype.hasOwnProperty;function Jt(v,x,j){var G=j.ref;return{$$typeof:f,type:v,key:x,ref:G!==void 0?G:null,props:j}}function Ce(v,x){return Jt(v.type,x,v.props)}function me(v){return typeof v=="object"&&v!==null&&v.$$typeof===f}function wt(v){var x={"=":"=0",":":"=2"};return"$"+v.replace(/[=:]/g,function(j){return x[j]})}var Ne=/\/+/g;function ye(v,x){return typeof v=="object"&&v!==null&&v.key!=null?wt(""+v.key):x.toString(36)}function xt(v){switch(v.status){case"fulfilled":return v.value;case"rejected":throw v.reason;default:switch(typeof v.status=="string"?v.then(Rt,Rt):(v.status="pending",v.then(function(x){v.status==="pending"&&(v.status="fulfilled",v.value=x)},function(x){v.status==="pending"&&(v.status="rejected",v.reason=x)})),v.status){case"fulfilled":return v.value;case"rejected":throw v.reason}}throw v}function O(v,x,j,G,P){var lt=typeof v;(lt==="undefined"||lt==="boolean")&&(v=null);var st=!1;if(v===null)st=!0;else switch(lt){case"bigint":case"string":case"number":st=!0;break;case"object":switch(v.$$typeof){case f:case o:st=!0;break;case N:return st=v._init,O(st(v._payload),x,j,G,P)}}if(st)return P=P(v),st=G===""?"."+ye(v,0):G,St(P)?(j="",st!=null&&(j=st.replace(Ne,"$&/")+"/"),O(P,x,j,"",function(Ba){return Ba})):P!=null&&(me(P)&&(P=Ce(P,j+(P.key==null||v&&v.key===P.key?"":(""+P.key).replace(Ne,"$&/")+"/")+st)),x.push(P)),1;st=0;var Wt=G===""?".":G+":";if(St(v))for(var Ut=0;Ut>>1,bt=O[mt];if(0>>1;mth(j,W))Gh(P,j)?(O[mt]=P,O[G]=W,mt=G):(O[mt]=j,O[x]=W,mt=x);else if(Gh(P,W))O[mt]=P,O[G]=W,mt=G;else break t}}return B}function h(O,B){var W=O.sortIndex-B.sortIndex;return W!==0?W:O.id-B.id}if(f.unstable_now=void 0,typeof performance=="object"&&typeof performance.now=="function"){var m=performance;f.unstable_now=function(){return m.now()}}else{var S=Date,M=S.now();f.unstable_now=function(){return S.now()-M}}var b=[],g=[],N=1,A=null,q=3,J=!1,Z=!1,L=!1,H=!1,w=typeof setTimeout=="function"?setTimeout:null,I=typeof clearTimeout=="function"?clearTimeout:null,$=typeof setImmediate<"u"?setImmediate:null;function pt(O){for(var B=s(g);B!==null;){if(B.callback===null)c(g);else if(B.startTime<=O)c(g),B.sortIndex=B.expirationTime,o(b,B);else break;B=s(g)}}function St(O){if(L=!1,pt(O),!Z)if(s(b)!==null)Z=!0,Rt||(Rt=!0,wt());else{var B=s(g);B!==null&&xt(St,B.startTime-O)}}var Rt=!1,k=-1,Dt=5,Jt=-1;function Ce(){return H?!0:!(f.unstable_now()-JtO&&Ce());){var mt=A.callback;if(typeof mt=="function"){A.callback=null,q=A.priorityLevel;var bt=mt(A.expirationTime<=O);if(O=f.unstable_now(),typeof bt=="function"){A.callback=bt,pt(O),B=!0;break e}A===s(b)&&c(b),pt(O)}else c(b);A=s(b)}if(A!==null)B=!0;else{var v=s(g);v!==null&&xt(St,v.startTime-O),B=!1}}break t}finally{A=null,q=W,J=!1}B=void 0}}finally{B?wt():Rt=!1}}}var wt;if(typeof $=="function")wt=function(){$(me)};else if(typeof MessageChannel<"u"){var Ne=new MessageChannel,ye=Ne.port2;Ne.port1.onmessage=me,wt=function(){ye.postMessage(null)}}else wt=function(){w(me,0)};function xt(O,B){k=w(function(){O(f.unstable_now())},B)}f.unstable_IdlePriority=5,f.unstable_ImmediatePriority=1,f.unstable_LowPriority=4,f.unstable_NormalPriority=3,f.unstable_Profiling=null,f.unstable_UserBlockingPriority=2,f.unstable_cancelCallback=function(O){O.callback=null},f.unstable_forceFrameRate=function(O){0>O||125mt?(O.sortIndex=W,o(g,O),s(b)===null&&O===s(g)&&(L?(I(k),k=-1):L=!0,xt(St,W-mt))):(O.sortIndex=bt,o(b,O),Z||J||(Z=!0,Rt||(Rt=!0,wt()))),O},f.unstable_shouldYield=Ce,f.unstable_wrapCallback=function(O){var B=q;return function(){var W=q;q=B;try{return O.apply(this,arguments)}finally{q=W}}}})(Cc)),Cc}var Id;function uv(){return Id||(Id=1,Uc.exports=av()),Uc.exports}var Nc={exports:{}},$t={};var Pd;function nv(){if(Pd)return $t;Pd=1;var f=Yc();function o(b){var g="https://react.dev/errors/"+b;if(1"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(f)}catch(o){console.error(o)}}return f(),Nc.exports=nv(),Nc.exports}var eh;function fv(){if(eh)return Du;eh=1;var f=uv(),o=Yc(),s=iv();function c(t){var e="https://react.dev/errors/"+t;if(1bt||(t.current=mt[bt],mt[bt]=null,bt--)}function j(t,e){bt++,mt[bt]=t.current,t.current=e}var G=v(null),P=v(null),lt=v(null),st=v(null);function Wt(t,e){switch(j(lt,e),j(P,t),j(G,null),e.nodeType){case 9:case 11:t=(t=e.documentElement)&&(t=t.namespaceURI)?vd(t):0;break;default:if(t=e.tagName,e=e.namespaceURI)e=vd(e),t=gd(e,t);else switch(t){case"svg":t=1;break;case"math":t=2;break;default:t=0}}x(G),j(G,t)}function Ut(){x(G),x(P),x(lt)}function Ba(t){t.memoizedState!==null&&j(st,t);var e=G.current,l=gd(e,t.type);e!==l&&(j(P,t),j(G,l))}function Bu(t){P.current===t&&(x(G),x(P)),st.current===t&&(x(st),Au._currentValue=W)}var ci,Kc;function Ul(t){if(ci===void 0)try{throw Error()}catch(l){var e=l.stack.trim().match(/\n( *(at )?)/);ci=e&&e[1]||"",Kc=-1)":-1u||d[a]!==T[u]){var _=` +`+d[a].replace(" at new "," at ");return t.displayName&&_.includes("")&&(_=_.replace("",t.displayName)),_}while(1<=a&&0<=u);break}}}finally{ri=!1,Error.prepareStackTrace=l}return(l=t?t.displayName||t.name:"")?Ul(l):""}function Dh(t,e){switch(t.tag){case 26:case 27:case 5:return Ul(t.type);case 16:return Ul("Lazy");case 13:return t.child!==e&&e!==null?Ul("Suspense Fallback"):Ul("Suspense");case 19:return Ul("SuspenseList");case 0:case 15:return oi(t.type,!1);case 11:return oi(t.type.render,!1);case 1:return oi(t.type,!0);case 31:return Ul("Activity");default:return""}}function Jc(t){try{var e="",l=null;do e+=Dh(t,l),l=t,t=t.return;while(t);return e}catch(a){return` +Error generating stack: `+a.message+` +`+a.stack}}var si=Object.prototype.hasOwnProperty,di=f.unstable_scheduleCallback,hi=f.unstable_cancelCallback,Uh=f.unstable_shouldYield,Ch=f.unstable_requestPaint,ue=f.unstable_now,Nh=f.unstable_getCurrentPriorityLevel,wc=f.unstable_ImmediatePriority,$c=f.unstable_UserBlockingPriority,qu=f.unstable_NormalPriority,xh=f.unstable_LowPriority,Wc=f.unstable_IdlePriority,Hh=f.log,Bh=f.unstable_setDisableYieldValue,qa=null,ne=null;function ul(t){if(typeof Hh=="function"&&Bh(t),ne&&typeof ne.setStrictMode=="function")try{ne.setStrictMode(qa,t)}catch{}}var ie=Math.clz32?Math.clz32:Yh,qh=Math.log,jh=Math.LN2;function Yh(t){return t>>>=0,t===0?32:31-(qh(t)/jh|0)|0}var ju=256,Yu=262144,Lu=4194304;function Cl(t){var e=t&42;if(e!==0)return e;switch(t&-t){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:return 64;case 128:return 128;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:return t&261888;case 262144:case 524288:case 1048576:case 2097152:return t&3932160;case 4194304:case 8388608:case 16777216:case 33554432:return t&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return t}}function Gu(t,e,l){var a=t.pendingLanes;if(a===0)return 0;var u=0,n=t.suspendedLanes,i=t.pingedLanes;t=t.warmLanes;var r=a&134217727;return r!==0?(a=r&~n,a!==0?u=Cl(a):(i&=r,i!==0?u=Cl(i):l||(l=r&~t,l!==0&&(u=Cl(l))))):(r=a&~n,r!==0?u=Cl(r):i!==0?u=Cl(i):l||(l=a&~t,l!==0&&(u=Cl(l)))),u===0?0:e!==0&&e!==u&&(e&n)===0&&(n=u&-u,l=e&-e,n>=l||n===32&&(l&4194048)!==0)?e:u}function ja(t,e){return(t.pendingLanes&~(t.suspendedLanes&~t.pingedLanes)&e)===0}function Lh(t,e){switch(t){case 1:case 2:case 4:case 8:case 64:return e+250;case 16:case 32:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return e+5e3;case 4194304:case 8388608:case 16777216:case 33554432:return-1;case 67108864:case 134217728:case 268435456:case 536870912:case 1073741824:return-1;default:return-1}}function kc(){var t=Lu;return Lu<<=1,(Lu&62914560)===0&&(Lu=4194304),t}function mi(t){for(var e=[],l=0;31>l;l++)e.push(t);return e}function Ya(t,e){t.pendingLanes|=e,e!==268435456&&(t.suspendedLanes=0,t.pingedLanes=0,t.warmLanes=0)}function Gh(t,e,l,a,u,n){var i=t.pendingLanes;t.pendingLanes=l,t.suspendedLanes=0,t.pingedLanes=0,t.warmLanes=0,t.expiredLanes&=l,t.entangledLanes&=l,t.errorRecoveryDisabledLanes&=l,t.shellSuspendCounter=0;var r=t.entanglements,d=t.expirationTimes,T=t.hiddenUpdates;for(l=i&~l;0"u")return null;try{return t.activeElement||t.body}catch{return t.body}}var Jh=/[\n"\\]/g;function ge(t){return t.replace(Jh,function(e){return"\\"+e.charCodeAt(0).toString(16)+" "})}function bi(t,e,l,a,u,n,i,r){t.name="",i!=null&&typeof i!="function"&&typeof i!="symbol"&&typeof i!="boolean"?t.type=i:t.removeAttribute("type"),e!=null?i==="number"?(e===0&&t.value===""||t.value!=e)&&(t.value=""+ve(e)):t.value!==""+ve(e)&&(t.value=""+ve(e)):i!=="submit"&&i!=="reset"||t.removeAttribute("value"),e!=null?Ei(t,i,ve(e)):l!=null?Ei(t,i,ve(l)):a!=null&&t.removeAttribute("value"),u==null&&n!=null&&(t.defaultChecked=!!n),u!=null&&(t.checked=u&&typeof u!="function"&&typeof u!="symbol"),r!=null&&typeof r!="function"&&typeof r!="symbol"&&typeof r!="boolean"?t.name=""+ve(r):t.removeAttribute("name")}function rr(t,e,l,a,u,n,i,r){if(n!=null&&typeof n!="function"&&typeof n!="symbol"&&typeof n!="boolean"&&(t.type=n),e!=null||l!=null){if(!(n!=="submit"&&n!=="reset"||e!=null)){Si(t);return}l=l!=null?""+ve(l):"",e=e!=null?""+ve(e):l,r||e===t.value||(t.value=e),t.defaultValue=e}a=a??u,a=typeof a!="function"&&typeof a!="symbol"&&!!a,t.checked=r?t.checked:!!a,t.defaultChecked=!!a,i!=null&&typeof i!="function"&&typeof i!="symbol"&&typeof i!="boolean"&&(t.name=i),Si(t)}function Ei(t,e,l){e==="number"&&Zu(t.ownerDocument)===t||t.defaultValue===""+l||(t.defaultValue=""+l)}function ea(t,e,l,a){if(t=t.options,e){e={};for(var u=0;u"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),_i=!1;if(Ge)try{var Qa={};Object.defineProperty(Qa,"passive",{get:function(){_i=!0}}),window.addEventListener("test",Qa,Qa),window.removeEventListener("test",Qa,Qa)}catch{_i=!1}var il=null,Oi=null,Ku=null;function vr(){if(Ku)return Ku;var t,e=Oi,l=e.length,a,u="value"in il?il.value:il.textContent,n=u.length;for(t=0;t=Ka),Tr=" ",zr=!1;function Ar(t,e){switch(t){case"keyup":return bm.indexOf(e.keyCode)!==-1;case"keydown":return e.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function Rr(t){return t=t.detail,typeof t=="object"&&"data"in t?t.data:null}var na=!1;function Tm(t,e){switch(t){case"compositionend":return Rr(e);case"keypress":return e.which!==32?null:(zr=!0,Tr);case"textInput":return t=e.data,t===Tr&&zr?null:t;default:return null}}function zm(t,e){if(na)return t==="compositionend"||!Ni&&Ar(t,e)?(t=vr(),Ku=Oi=il=null,na=!1,t):null;switch(t){case"paste":return null;case"keypress":if(!(e.ctrlKey||e.altKey||e.metaKey)||e.ctrlKey&&e.altKey){if(e.char&&1=e)return{node:l,offset:e-t};t=a}t:{for(;l;){if(l.nextSibling){l=l.nextSibling;break t}l=l.parentNode}l=void 0}l=xr(l)}}function Br(t,e){return t&&e?t===e?!0:t&&t.nodeType===3?!1:e&&e.nodeType===3?Br(t,e.parentNode):"contains"in t?t.contains(e):t.compareDocumentPosition?!!(t.compareDocumentPosition(e)&16):!1:!1}function qr(t){t=t!=null&&t.ownerDocument!=null&&t.ownerDocument.defaultView!=null?t.ownerDocument.defaultView:window;for(var e=Zu(t.document);e instanceof t.HTMLIFrameElement;){try{var l=typeof e.contentWindow.location.href=="string"}catch{l=!1}if(l)t=e.contentWindow;else break;e=Zu(t.document)}return e}function Bi(t){var e=t&&t.nodeName&&t.nodeName.toLowerCase();return e&&(e==="input"&&(t.type==="text"||t.type==="search"||t.type==="tel"||t.type==="url"||t.type==="password")||e==="textarea"||t.contentEditable==="true")}var Cm=Ge&&"documentMode"in document&&11>=document.documentMode,ia=null,qi=null,Wa=null,ji=!1;function jr(t,e,l){var a=l.window===l?l.document:l.nodeType===9?l:l.ownerDocument;ji||ia==null||ia!==Zu(a)||(a=ia,"selectionStart"in a&&Bi(a)?a={start:a.selectionStart,end:a.selectionEnd}:(a=(a.ownerDocument&&a.ownerDocument.defaultView||window).getSelection(),a={anchorNode:a.anchorNode,anchorOffset:a.anchorOffset,focusNode:a.focusNode,focusOffset:a.focusOffset}),Wa&&$a(Wa,a)||(Wa=a,a=Ln(qi,"onSelect"),0>=i,u-=i,xe=1<<32-ie(e)+u|l<et?(it=X,X=null):it=X.sibling;var rt=z(p,X,E[et],D);if(rt===null){X===null&&(X=it);break}t&&X&&rt.alternate===null&&e(p,X),y=n(rt,y,et),ct===null?Q=rt:ct.sibling=rt,ct=rt,X=it}if(et===E.length)return l(p,X),ft&&Qe(p,et),Q;if(X===null){for(;etet?(it=X,X=null):it=X.sibling;var Ml=z(p,X,rt.value,D);if(Ml===null){X===null&&(X=it);break}t&&X&&Ml.alternate===null&&e(p,X),y=n(Ml,y,et),ct===null?Q=Ml:ct.sibling=Ml,ct=Ml,X=it}if(rt.done)return l(p,X),ft&&Qe(p,et),Q;if(X===null){for(;!rt.done;et++,rt=E.next())rt=C(p,rt.value,D),rt!==null&&(y=n(rt,y,et),ct===null?Q=rt:ct.sibling=rt,ct=rt);return ft&&Qe(p,et),Q}for(X=a(X);!rt.done;et++,rt=E.next())rt=R(X,p,et,rt.value,D),rt!==null&&(t&&rt.alternate!==null&&X.delete(rt.key===null?et:rt.key),y=n(rt,y,et),ct===null?Q=rt:ct.sibling=rt,ct=rt);return t&&X.forEach(function(Fy){return e(p,Fy)}),ft&&Qe(p,et),Q}function gt(p,y,E,D){if(typeof E=="object"&&E!==null&&E.type===L&&E.key===null&&(E=E.props.children),typeof E=="object"&&E!==null){switch(E.$$typeof){case J:t:{for(var Q=E.key;y!==null;){if(y.key===Q){if(Q=E.type,Q===L){if(y.tag===7){l(p,y.sibling),D=u(y,E.props.children),D.return=p,p=D;break t}}else if(y.elementType===Q||typeof Q=="object"&&Q!==null&&Q.$$typeof===Dt&&Ql(Q)===y.type){l(p,y.sibling),D=u(y,E.props),eu(D,E),D.return=p,p=D;break t}l(p,y);break}else e(p,y);y=y.sibling}E.type===L?(D=jl(E.props.children,p.mode,D,E.key),D.return=p,p=D):(D=en(E.type,E.key,E.props,null,p.mode,D),eu(D,E),D.return=p,p=D)}return i(p);case Z:t:{for(Q=E.key;y!==null;){if(y.key===Q)if(y.tag===4&&y.stateNode.containerInfo===E.containerInfo&&y.stateNode.implementation===E.implementation){l(p,y.sibling),D=u(y,E.children||[]),D.return=p,p=D;break t}else{l(p,y);break}else e(p,y);y=y.sibling}D=Vi(E,p.mode,D),D.return=p,p=D}return i(p);case Dt:return E=Ql(E),gt(p,y,E,D)}if(xt(E))return Y(p,y,E,D);if(wt(E)){if(Q=wt(E),typeof Q!="function")throw Error(c(150));return E=Q.call(E),K(p,y,E,D)}if(typeof E.then=="function")return gt(p,y,rn(E),D);if(E.$$typeof===$)return gt(p,y,un(p,E),D);on(p,E)}return typeof E=="string"&&E!==""||typeof E=="number"||typeof E=="bigint"?(E=""+E,y!==null&&y.tag===6?(l(p,y.sibling),D=u(y,E),D.return=p,p=D):(l(p,y),D=Zi(E,p.mode,D),D.return=p,p=D),i(p)):l(p,y)}return function(p,y,E,D){try{tu=0;var Q=gt(p,y,E,D);return ga=null,Q}catch(X){if(X===va||X===fn)throw X;var ct=ce(29,X,null,p.mode);return ct.lanes=D,ct.return=p,ct}}}var Vl=io(!0),fo=io(!1),sl=!1;function lf(t){t.updateQueue={baseState:t.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function af(t,e){t=t.updateQueue,e.updateQueue===t&&(e.updateQueue={baseState:t.baseState,firstBaseUpdate:t.firstBaseUpdate,lastBaseUpdate:t.lastBaseUpdate,shared:t.shared,callbacks:null})}function dl(t){return{lane:t,tag:0,payload:null,callback:null,next:null}}function hl(t,e,l){var a=t.updateQueue;if(a===null)return null;if(a=a.shared,(ot&2)!==0){var u=a.pending;return u===null?e.next=e:(e.next=u.next,u.next=e),a.pending=e,e=tn(t),Vr(t,null,l),e}return Pu(t,a,e,l),tn(t)}function lu(t,e,l){if(e=e.updateQueue,e!==null&&(e=e.shared,(l&4194048)!==0)){var a=e.lanes;a&=t.pendingLanes,l|=a,e.lanes=l,Ic(t,l)}}function uf(t,e){var l=t.updateQueue,a=t.alternate;if(a!==null&&(a=a.updateQueue,l===a)){var u=null,n=null;if(l=l.firstBaseUpdate,l!==null){do{var i={lane:l.lane,tag:l.tag,payload:l.payload,callback:null,next:null};n===null?u=n=i:n=n.next=i,l=l.next}while(l!==null);n===null?u=n=e:n=n.next=e}else u=n=e;l={baseState:a.baseState,firstBaseUpdate:u,lastBaseUpdate:n,shared:a.shared,callbacks:a.callbacks},t.updateQueue=l;return}t=l.lastBaseUpdate,t===null?l.firstBaseUpdate=e:t.next=e,l.lastBaseUpdate=e}var nf=!1;function au(){if(nf){var t=ya;if(t!==null)throw t}}function uu(t,e,l,a){nf=!1;var u=t.updateQueue;sl=!1;var n=u.firstBaseUpdate,i=u.lastBaseUpdate,r=u.shared.pending;if(r!==null){u.shared.pending=null;var d=r,T=d.next;d.next=null,i===null?n=T:i.next=T,i=d;var _=t.alternate;_!==null&&(_=_.updateQueue,r=_.lastBaseUpdate,r!==i&&(r===null?_.firstBaseUpdate=T:r.next=T,_.lastBaseUpdate=d))}if(n!==null){var C=u.baseState;i=0,_=T=d=null,r=n;do{var z=r.lane&-536870913,R=z!==r.lane;if(R?(nt&z)===z:(a&z)===z){z!==0&&z===ma&&(nf=!0),_!==null&&(_=_.next={lane:0,tag:r.tag,payload:r.payload,callback:null,next:null});t:{var Y=t,K=r;z=e;var gt=l;switch(K.tag){case 1:if(Y=K.payload,typeof Y=="function"){C=Y.call(gt,C,z);break t}C=Y;break t;case 3:Y.flags=Y.flags&-65537|128;case 0:if(Y=K.payload,z=typeof Y=="function"?Y.call(gt,C,z):Y,z==null)break t;C=A({},C,z);break t;case 2:sl=!0}}z=r.callback,z!==null&&(t.flags|=64,R&&(t.flags|=8192),R=u.callbacks,R===null?u.callbacks=[z]:R.push(z))}else R={lane:z,tag:r.tag,payload:r.payload,callback:r.callback,next:null},_===null?(T=_=R,d=C):_=_.next=R,i|=z;if(r=r.next,r===null){if(r=u.shared.pending,r===null)break;R=r,r=R.next,R.next=null,u.lastBaseUpdate=R,u.shared.pending=null}}while(!0);_===null&&(d=C),u.baseState=d,u.firstBaseUpdate=T,u.lastBaseUpdate=_,n===null&&(u.shared.lanes=0),pl|=i,t.lanes=i,t.memoizedState=C}}function co(t,e){if(typeof t!="function")throw Error(c(191,t));t.call(e)}function ro(t,e){var l=t.callbacks;if(l!==null)for(t.callbacks=null,t=0;tn?n:8;var i=O.T,r={};O.T=r,Rf(t,!1,e,l);try{var d=u(),T=O.S;if(T!==null&&T(r,d),d!==null&&typeof d=="object"&&typeof d.then=="function"){var _=Gm(d,a);fu(t,e,_,he(t))}else fu(t,e,a,he(t))}catch(C){fu(t,e,{then:function(){},status:"rejected",reason:C},he())}finally{B.p=n,i!==null&&r.types!==null&&(i.types=r.types),O.T=i}}function Jm(){}function zf(t,e,l,a){if(t.tag!==5)throw Error(c(476));var u=Qo(t).queue;Xo(t,u,e,W,l===null?Jm:function(){return Zo(t),l(a)})}function Qo(t){var e=t.memoizedState;if(e!==null)return e;e={memoizedState:W,baseState:W,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Je,lastRenderedState:W},next:null};var l={};return e.next={memoizedState:l,baseState:l,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Je,lastRenderedState:l},next:null},t.memoizedState=e,t=t.alternate,t!==null&&(t.memoizedState=e),e}function Zo(t){var e=Qo(t);e.next===null&&(e=t.alternate.memoizedState),fu(t,e.next.queue,{},he())}function Af(){return Zt(Au)}function Vo(){return Nt().memoizedState}function Ko(){return Nt().memoizedState}function wm(t){for(var e=t.return;e!==null;){switch(e.tag){case 24:case 3:var l=he();t=dl(l);var a=hl(e,t,l);a!==null&&(ae(a,e,l),lu(a,e,l)),e={cache:Ii()},t.payload=e;return}e=e.return}}function $m(t,e,l){var a=he();l={lane:a,revertLane:0,gesture:null,action:l,hasEagerState:!1,eagerState:null,next:null},bn(t)?wo(e,l):(l=Xi(t,e,l,a),l!==null&&(ae(l,t,a),$o(l,e,a)))}function Jo(t,e,l){var a=he();fu(t,e,l,a)}function fu(t,e,l,a){var u={lane:a,revertLane:0,gesture:null,action:l,hasEagerState:!1,eagerState:null,next:null};if(bn(t))wo(e,u);else{var n=t.alternate;if(t.lanes===0&&(n===null||n.lanes===0)&&(n=e.lastRenderedReducer,n!==null))try{var i=e.lastRenderedState,r=n(i,l);if(u.hasEagerState=!0,u.eagerState=r,fe(r,i))return Pu(t,e,u,0),Et===null&&Iu(),!1}catch{}if(l=Xi(t,e,u,a),l!==null)return ae(l,t,a),$o(l,e,a),!0}return!1}function Rf(t,e,l,a){if(a={lane:2,revertLane:ac(),gesture:null,action:a,hasEagerState:!1,eagerState:null,next:null},bn(t)){if(e)throw Error(c(479))}else e=Xi(t,l,a,2),e!==null&&ae(e,t,2)}function bn(t){var e=t.alternate;return t===tt||e!==null&&e===tt}function wo(t,e){Sa=hn=!0;var l=t.pending;l===null?e.next=e:(e.next=l.next,l.next=e),t.pending=e}function $o(t,e,l){if((l&4194048)!==0){var a=e.lanes;a&=t.pendingLanes,l|=a,e.lanes=l,Ic(t,l)}}var cu={readContext:Zt,use:vn,useCallback:Ot,useContext:Ot,useEffect:Ot,useImperativeHandle:Ot,useLayoutEffect:Ot,useInsertionEffect:Ot,useMemo:Ot,useReducer:Ot,useRef:Ot,useState:Ot,useDebugValue:Ot,useDeferredValue:Ot,useTransition:Ot,useSyncExternalStore:Ot,useId:Ot,useHostTransitionStatus:Ot,useFormState:Ot,useActionState:Ot,useOptimistic:Ot,useMemoCache:Ot,useCacheRefresh:Ot};cu.useEffectEvent=Ot;var Wo={readContext:Zt,use:vn,useCallback:function(t,e){return kt().memoizedState=[t,e===void 0?null:e],t},useContext:Zt,useEffect:No,useImperativeHandle:function(t,e,l){l=l!=null?l.concat([t]):null,pn(4194308,4,qo.bind(null,e,t),l)},useLayoutEffect:function(t,e){return pn(4194308,4,t,e)},useInsertionEffect:function(t,e){pn(4,2,t,e)},useMemo:function(t,e){var l=kt();e=e===void 0?null:e;var a=t();if(Kl){ul(!0);try{t()}finally{ul(!1)}}return l.memoizedState=[a,e],a},useReducer:function(t,e,l){var a=kt();if(l!==void 0){var u=l(e);if(Kl){ul(!0);try{l(e)}finally{ul(!1)}}}else u=e;return a.memoizedState=a.baseState=u,t={pending:null,lanes:0,dispatch:null,lastRenderedReducer:t,lastRenderedState:u},a.queue=t,t=t.dispatch=$m.bind(null,tt,t),[a.memoizedState,t]},useRef:function(t){var e=kt();return t={current:t},e.memoizedState=t},useState:function(t){t=pf(t);var e=t.queue,l=Jo.bind(null,tt,e);return e.dispatch=l,[t.memoizedState,l]},useDebugValue:Ef,useDeferredValue:function(t,e){var l=kt();return Tf(l,t,e)},useTransition:function(){var t=pf(!1);return t=Xo.bind(null,tt,t.queue,!0,!1),kt().memoizedState=t,[!1,t]},useSyncExternalStore:function(t,e,l){var a=tt,u=kt();if(ft){if(l===void 0)throw Error(c(407));l=l()}else{if(l=e(),Et===null)throw Error(c(349));(nt&127)!==0||vo(a,e,l)}u.memoizedState=l;var n={value:l,getSnapshot:e};return u.queue=n,No(po.bind(null,a,n,t),[t]),a.flags|=2048,Ea(9,{destroy:void 0},go.bind(null,a,n,l,e),null),l},useId:function(){var t=kt(),e=Et.identifierPrefix;if(ft){var l=He,a=xe;l=(a&~(1<<32-ie(a)-1)).toString(32)+l,e="_"+e+"R_"+l,l=mn++,0<\/script>",n=n.removeChild(n.firstChild);break;case"select":n=typeof a.is=="string"?i.createElement("select",{is:a.is}):i.createElement("select"),a.multiple?n.multiple=!0:a.size&&(n.size=a.size);break;default:n=typeof a.is=="string"?i.createElement(u,{is:a.is}):i.createElement(u)}}n[Xt]=e,n[Ft]=a;t:for(i=e.child;i!==null;){if(i.tag===5||i.tag===6)n.appendChild(i.stateNode);else if(i.tag!==4&&i.tag!==27&&i.child!==null){i.child.return=i,i=i.child;continue}if(i===e)break t;for(;i.sibling===null;){if(i.return===null||i.return===e)break t;i=i.return}i.sibling.return=i.return,i=i.sibling}e.stateNode=n;t:switch(Kt(n,u,a),u){case"button":case"input":case"select":case"textarea":a=!!a.autoFocus;break t;case"img":a=!0;break t;default:a=!1}a&&$e(e)}}return zt(e),Lf(e,e.type,t===null?null:t.memoizedProps,e.pendingProps,l),null;case 6:if(t&&e.stateNode!=null)t.memoizedProps!==a&&$e(e);else{if(typeof a!="string"&&e.stateNode===null)throw Error(c(166));if(t=lt.current,da(e)){if(t=e.stateNode,l=e.memoizedProps,a=null,u=Qt,u!==null)switch(u.tag){case 27:case 5:a=u.memoizedProps}t[Xt]=e,t=!!(t.nodeValue===l||a!==null&&a.suppressHydrationWarning===!0||md(t.nodeValue,l)),t||rl(e,!0)}else t=Gn(t).createTextNode(a),t[Xt]=e,e.stateNode=t}return zt(e),null;case 31:if(l=e.memoizedState,t===null||t.memoizedState!==null){if(a=da(e),l!==null){if(t===null){if(!a)throw Error(c(318));if(t=e.memoizedState,t=t!==null?t.dehydrated:null,!t)throw Error(c(557));t[Xt]=e}else Yl(),(e.flags&128)===0&&(e.memoizedState=null),e.flags|=4;zt(e),t=!1}else l=$i(),t!==null&&t.memoizedState!==null&&(t.memoizedState.hydrationErrors=l),t=!0;if(!t)return e.flags&256?(oe(e),e):(oe(e),null);if((e.flags&128)!==0)throw Error(c(558))}return zt(e),null;case 13:if(a=e.memoizedState,t===null||t.memoizedState!==null&&t.memoizedState.dehydrated!==null){if(u=da(e),a!==null&&a.dehydrated!==null){if(t===null){if(!u)throw Error(c(318));if(u=e.memoizedState,u=u!==null?u.dehydrated:null,!u)throw Error(c(317));u[Xt]=e}else Yl(),(e.flags&128)===0&&(e.memoizedState=null),e.flags|=4;zt(e),u=!1}else u=$i(),t!==null&&t.memoizedState!==null&&(t.memoizedState.hydrationErrors=u),u=!0;if(!u)return e.flags&256?(oe(e),e):(oe(e),null)}return oe(e),(e.flags&128)!==0?(e.lanes=l,e):(l=a!==null,t=t!==null&&t.memoizedState!==null,l&&(a=e.child,u=null,a.alternate!==null&&a.alternate.memoizedState!==null&&a.alternate.memoizedState.cachePool!==null&&(u=a.alternate.memoizedState.cachePool.pool),n=null,a.memoizedState!==null&&a.memoizedState.cachePool!==null&&(n=a.memoizedState.cachePool.pool),n!==u&&(a.flags|=2048)),l!==t&&l&&(e.child.flags|=8192),Rn(e,e.updateQueue),zt(e),null);case 4:return Ut(),t===null&&fc(e.stateNode.containerInfo),zt(e),null;case 10:return Ve(e.type),zt(e),null;case 19:if(x(Ct),a=e.memoizedState,a===null)return zt(e),null;if(u=(e.flags&128)!==0,n=a.rendering,n===null)if(u)ou(a,!1);else{if(Mt!==0||t!==null&&(t.flags&128)!==0)for(t=e.child;t!==null;){if(n=dn(t),n!==null){for(e.flags|=128,ou(a,!1),t=n.updateQueue,e.updateQueue=t,Rn(e,t),e.subtreeFlags=0,t=l,l=e.child;l!==null;)Kr(l,t),l=l.sibling;return j(Ct,Ct.current&1|2),ft&&Qe(e,a.treeForkCount),e.child}t=t.sibling}a.tail!==null&&ue()>Un&&(e.flags|=128,u=!0,ou(a,!1),e.lanes=4194304)}else{if(!u)if(t=dn(n),t!==null){if(e.flags|=128,u=!0,t=t.updateQueue,e.updateQueue=t,Rn(e,t),ou(a,!0),a.tail===null&&a.tailMode==="hidden"&&!n.alternate&&!ft)return zt(e),null}else 2*ue()-a.renderingStartTime>Un&&l!==536870912&&(e.flags|=128,u=!0,ou(a,!1),e.lanes=4194304);a.isBackwards?(n.sibling=e.child,e.child=n):(t=a.last,t!==null?t.sibling=n:e.child=n,a.last=n)}return a.tail!==null?(t=a.tail,a.rendering=t,a.tail=t.sibling,a.renderingStartTime=ue(),t.sibling=null,l=Ct.current,j(Ct,u?l&1|2:l&1),ft&&Qe(e,a.treeForkCount),t):(zt(e),null);case 22:case 23:return oe(e),cf(),a=e.memoizedState!==null,t!==null?t.memoizedState!==null!==a&&(e.flags|=8192):a&&(e.flags|=8192),a?(l&536870912)!==0&&(e.flags&128)===0&&(zt(e),e.subtreeFlags&6&&(e.flags|=8192)):zt(e),l=e.updateQueue,l!==null&&Rn(e,l.retryQueue),l=null,t!==null&&t.memoizedState!==null&&t.memoizedState.cachePool!==null&&(l=t.memoizedState.cachePool.pool),a=null,e.memoizedState!==null&&e.memoizedState.cachePool!==null&&(a=e.memoizedState.cachePool.pool),a!==l&&(e.flags|=2048),t!==null&&x(Xl),null;case 24:return l=null,t!==null&&(l=t.memoizedState.cache),e.memoizedState.cache!==l&&(e.flags|=2048),Ve(Ht),zt(e),null;case 25:return null;case 30:return null}throw Error(c(156,e.tag))}function Pm(t,e){switch(Ji(e),e.tag){case 1:return t=e.flags,t&65536?(e.flags=t&-65537|128,e):null;case 3:return Ve(Ht),Ut(),t=e.flags,(t&65536)!==0&&(t&128)===0?(e.flags=t&-65537|128,e):null;case 26:case 27:case 5:return Bu(e),null;case 31:if(e.memoizedState!==null){if(oe(e),e.alternate===null)throw Error(c(340));Yl()}return t=e.flags,t&65536?(e.flags=t&-65537|128,e):null;case 13:if(oe(e),t=e.memoizedState,t!==null&&t.dehydrated!==null){if(e.alternate===null)throw Error(c(340));Yl()}return t=e.flags,t&65536?(e.flags=t&-65537|128,e):null;case 19:return x(Ct),null;case 4:return Ut(),null;case 10:return Ve(e.type),null;case 22:case 23:return oe(e),cf(),t!==null&&x(Xl),t=e.flags,t&65536?(e.flags=t&-65537|128,e):null;case 24:return Ve(Ht),null;case 25:return null;default:return null}}function Ss(t,e){switch(Ji(e),e.tag){case 3:Ve(Ht),Ut();break;case 26:case 27:case 5:Bu(e);break;case 4:Ut();break;case 31:e.memoizedState!==null&&oe(e);break;case 13:oe(e);break;case 19:x(Ct);break;case 10:Ve(e.type);break;case 22:case 23:oe(e),cf(),t!==null&&x(Xl);break;case 24:Ve(Ht)}}function su(t,e){try{var l=e.updateQueue,a=l!==null?l.lastEffect:null;if(a!==null){var u=a.next;l=u;do{if((l.tag&t)===t){a=void 0;var n=l.create,i=l.inst;a=n(),i.destroy=a}l=l.next}while(l!==u)}}catch(r){ht(e,e.return,r)}}function vl(t,e,l){try{var a=e.updateQueue,u=a!==null?a.lastEffect:null;if(u!==null){var n=u.next;a=n;do{if((a.tag&t)===t){var i=a.inst,r=i.destroy;if(r!==void 0){i.destroy=void 0,u=e;var d=l,T=r;try{T()}catch(_){ht(u,d,_)}}}a=a.next}while(a!==n)}}catch(_){ht(e,e.return,_)}}function bs(t){var e=t.updateQueue;if(e!==null){var l=t.stateNode;try{ro(e,l)}catch(a){ht(t,t.return,a)}}}function Es(t,e,l){l.props=Jl(t.type,t.memoizedProps),l.state=t.memoizedState;try{l.componentWillUnmount()}catch(a){ht(t,e,a)}}function du(t,e){try{var l=t.ref;if(l!==null){switch(t.tag){case 26:case 27:case 5:var a=t.stateNode;break;case 30:a=t.stateNode;break;default:a=t.stateNode}typeof l=="function"?t.refCleanup=l(a):l.current=a}}catch(u){ht(t,e,u)}}function Be(t,e){var l=t.ref,a=t.refCleanup;if(l!==null)if(typeof a=="function")try{a()}catch(u){ht(t,e,u)}finally{t.refCleanup=null,t=t.alternate,t!=null&&(t.refCleanup=null)}else if(typeof l=="function")try{l(null)}catch(u){ht(t,e,u)}else l.current=null}function Ts(t){var e=t.type,l=t.memoizedProps,a=t.stateNode;try{t:switch(e){case"button":case"input":case"select":case"textarea":l.autoFocus&&a.focus();break t;case"img":l.src?a.src=l.src:l.srcSet&&(a.srcset=l.srcSet)}}catch(u){ht(t,t.return,u)}}function Gf(t,e,l){try{var a=t.stateNode;Ey(a,t.type,l,e),a[Ft]=e}catch(u){ht(t,t.return,u)}}function zs(t){return t.tag===5||t.tag===3||t.tag===26||t.tag===27&&zl(t.type)||t.tag===4}function Xf(t){t:for(;;){for(;t.sibling===null;){if(t.return===null||zs(t.return))return null;t=t.return}for(t.sibling.return=t.return,t=t.sibling;t.tag!==5&&t.tag!==6&&t.tag!==18;){if(t.tag===27&&zl(t.type)||t.flags&2||t.child===null||t.tag===4)continue t;t.child.return=t,t=t.child}if(!(t.flags&2))return t.stateNode}}function Qf(t,e,l){var a=t.tag;if(a===5||a===6)t=t.stateNode,e?(l.nodeType===9?l.body:l.nodeName==="HTML"?l.ownerDocument.body:l).insertBefore(t,e):(e=l.nodeType===9?l.body:l.nodeName==="HTML"?l.ownerDocument.body:l,e.appendChild(t),l=l._reactRootContainer,l!=null||e.onclick!==null||(e.onclick=Le));else if(a!==4&&(a===27&&zl(t.type)&&(l=t.stateNode,e=null),t=t.child,t!==null))for(Qf(t,e,l),t=t.sibling;t!==null;)Qf(t,e,l),t=t.sibling}function _n(t,e,l){var a=t.tag;if(a===5||a===6)t=t.stateNode,e?l.insertBefore(t,e):l.appendChild(t);else if(a!==4&&(a===27&&zl(t.type)&&(l=t.stateNode),t=t.child,t!==null))for(_n(t,e,l),t=t.sibling;t!==null;)_n(t,e,l),t=t.sibling}function As(t){var e=t.stateNode,l=t.memoizedProps;try{for(var a=t.type,u=e.attributes;u.length;)e.removeAttributeNode(u[0]);Kt(e,a,l),e[Xt]=t,e[Ft]=l}catch(n){ht(t,t.return,n)}}var We=!1,jt=!1,Zf=!1,Rs=typeof WeakSet=="function"?WeakSet:Set,Gt=null;function ty(t,e){if(t=t.containerInfo,oc=wn,t=qr(t),Bi(t)){if("selectionStart"in t)var l={start:t.selectionStart,end:t.selectionEnd};else t:{l=(l=t.ownerDocument)&&l.defaultView||window;var a=l.getSelection&&l.getSelection();if(a&&a.rangeCount!==0){l=a.anchorNode;var u=a.anchorOffset,n=a.focusNode;a=a.focusOffset;try{l.nodeType,n.nodeType}catch{l=null;break t}var i=0,r=-1,d=-1,T=0,_=0,C=t,z=null;e:for(;;){for(var R;C!==l||u!==0&&C.nodeType!==3||(r=i+u),C!==n||a!==0&&C.nodeType!==3||(d=i+a),C.nodeType===3&&(i+=C.nodeValue.length),(R=C.firstChild)!==null;)z=C,C=R;for(;;){if(C===t)break e;if(z===l&&++T===u&&(r=i),z===n&&++_===a&&(d=i),(R=C.nextSibling)!==null)break;C=z,z=C.parentNode}C=R}l=r===-1||d===-1?null:{start:r,end:d}}else l=null}l=l||{start:0,end:0}}else l=null;for(sc={focusedElem:t,selectionRange:l},wn=!1,Gt=e;Gt!==null;)if(e=Gt,t=e.child,(e.subtreeFlags&1028)!==0&&t!==null)t.return=e,Gt=t;else for(;Gt!==null;){switch(e=Gt,n=e.alternate,t=e.flags,e.tag){case 0:if((t&4)!==0&&(t=e.updateQueue,t=t!==null?t.events:null,t!==null))for(l=0;l title"))),Kt(n,a,l),n[Xt]=t,Lt(n),a=n;break t;case"link":var i=Cd("link","href",u).get(a+(l.href||""));if(i){for(var r=0;rgt&&(i=gt,gt=K,K=i);var p=Hr(r,K),y=Hr(r,gt);if(p&&y&&(R.rangeCount!==1||R.anchorNode!==p.node||R.anchorOffset!==p.offset||R.focusNode!==y.node||R.focusOffset!==y.offset)){var E=C.createRange();E.setStart(p.node,p.offset),R.removeAllRanges(),K>gt?(R.addRange(E),R.extend(y.node,y.offset)):(E.setEnd(y.node,y.offset),R.addRange(E))}}}}for(C=[],R=r;R=R.parentNode;)R.nodeType===1&&C.push({element:R,left:R.scrollLeft,top:R.scrollTop});for(typeof r.focus=="function"&&r.focus(),r=0;rl?32:l,O.T=null,l=kf,kf=null;var n=bl,i=tl;if(Yt=0,_a=bl=null,tl=0,(ot&6)!==0)throw Error(c(331));var r=ot;if(ot|=4,qs(n.current),xs(n,n.current,i,l),ot=r,pu(0,!1),ne&&typeof ne.onPostCommitFiberRoot=="function")try{ne.onPostCommitFiberRoot(qa,n)}catch{}return!0}finally{B.p=u,O.T=a,td(t,e)}}function ld(t,e,l){e=Se(l,e),e=Df(t.stateNode,e,2),t=hl(t,e,2),t!==null&&(Ya(t,2),qe(t))}function ht(t,e,l){if(t.tag===3)ld(t,t,l);else for(;e!==null;){if(e.tag===3){ld(e,t,l);break}else if(e.tag===1){var a=e.stateNode;if(typeof e.type.getDerivedStateFromError=="function"||typeof a.componentDidCatch=="function"&&(Sl===null||!Sl.has(a))){t=Se(l,t),l=as(2),a=hl(e,l,2),a!==null&&(us(l,a,e,t),Ya(a,2),qe(a));break}}e=e.return}}function tc(t,e,l){var a=t.pingCache;if(a===null){a=t.pingCache=new ay;var u=new Set;a.set(e,u)}else u=a.get(e),u===void 0&&(u=new Set,a.set(e,u));u.has(l)||(Jf=!0,u.add(l),t=cy.bind(null,t,e,l),e.then(t,t))}function cy(t,e,l){var a=t.pingCache;a!==null&&a.delete(e),t.pingedLanes|=t.suspendedLanes&l,t.warmLanes&=~l,Et===t&&(nt&l)===l&&(Mt===4||Mt===3&&(nt&62914560)===nt&&300>ue()-Dn?(ot&2)===0&&Oa(t,0):wf|=l,Ra===nt&&(Ra=0)),qe(t)}function ad(t,e){e===0&&(e=kc()),t=ql(t,e),t!==null&&(Ya(t,e),qe(t))}function ry(t){var e=t.memoizedState,l=0;e!==null&&(l=e.retryLane),ad(t,l)}function oy(t,e){var l=0;switch(t.tag){case 31:case 13:var a=t.stateNode,u=t.memoizedState;u!==null&&(l=u.retryLane);break;case 19:a=t.stateNode;break;case 22:a=t.stateNode._retryCache;break;default:throw Error(c(314))}a!==null&&a.delete(e),ad(t,l)}function sy(t,e){return di(t,e)}var qn=null,Da=null,ec=!1,jn=!1,lc=!1,Tl=0;function qe(t){t!==Da&&t.next===null&&(Da===null?qn=Da=t:Da=Da.next=t),jn=!0,ec||(ec=!0,hy())}function pu(t,e){if(!lc&&jn){lc=!0;do for(var l=!1,a=qn;a!==null;){if(t!==0){var u=a.pendingLanes;if(u===0)var n=0;else{var i=a.suspendedLanes,r=a.pingedLanes;n=(1<<31-ie(42|t)+1)-1,n&=u&~(i&~r),n=n&201326741?n&201326741|1:n?n|2:0}n!==0&&(l=!0,fd(a,n))}else n=nt,n=Gu(a,a===Et?n:0,a.cancelPendingCommit!==null||a.timeoutHandle!==-1),(n&3)===0||ja(a,n)||(l=!0,fd(a,n));a=a.next}while(l);lc=!1}}function dy(){ud()}function ud(){jn=ec=!1;var t=0;Tl!==0&&zy()&&(t=Tl);for(var e=ue(),l=null,a=qn;a!==null;){var u=a.next,n=nd(a,e);n===0?(a.next=null,l===null?qn=u:l.next=u,u===null&&(Da=l)):(l=a,(t!==0||(n&3)!==0)&&(jn=!0)),a=u}Yt!==0&&Yt!==5||pu(t),Tl!==0&&(Tl=0)}function nd(t,e){for(var l=t.suspendedLanes,a=t.pingedLanes,u=t.expirationTimes,n=t.pendingLanes&-62914561;0r)break;var _=d.transferSize,C=d.initiatorType;_&&yd(C)&&(d=d.responseEnd,i+=_*(d"u"?null:document;function Od(t,e,l){var a=Ua;if(a&&typeof e=="string"&&e){var u=ge(e);u='link[rel="'+t+'"][href="'+u+'"]',typeof l=="string"&&(u+='[crossorigin="'+l+'"]'),_d.has(u)||(_d.add(u),t={rel:t,crossOrigin:l,href:e},a.querySelector(u)===null&&(e=a.createElement("link"),Kt(e,"link",t),Lt(e),a.head.appendChild(e)))}}function Ny(t){el.D(t),Od("dns-prefetch",t,null)}function xy(t,e){el.C(t,e),Od("preconnect",t,e)}function Hy(t,e,l){el.L(t,e,l);var a=Ua;if(a&&t&&e){var u='link[rel="preload"][as="'+ge(e)+'"]';e==="image"&&l&&l.imageSrcSet?(u+='[imagesrcset="'+ge(l.imageSrcSet)+'"]',typeof l.imageSizes=="string"&&(u+='[imagesizes="'+ge(l.imageSizes)+'"]')):u+='[href="'+ge(t)+'"]';var n=u;switch(e){case"style":n=Ca(t);break;case"script":n=Na(t)}Re.has(n)||(t=A({rel:"preload",href:e==="image"&&l&&l.imageSrcSet?void 0:t,as:e},l),Re.set(n,t),a.querySelector(u)!==null||e==="style"&&a.querySelector(Tu(n))||e==="script"&&a.querySelector(zu(n))||(e=a.createElement("link"),Kt(e,"link",t),Lt(e),a.head.appendChild(e)))}}function By(t,e){el.m(t,e);var l=Ua;if(l&&t){var a=e&&typeof e.as=="string"?e.as:"script",u='link[rel="modulepreload"][as="'+ge(a)+'"][href="'+ge(t)+'"]',n=u;switch(a){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":n=Na(t)}if(!Re.has(n)&&(t=A({rel:"modulepreload",href:t},e),Re.set(n,t),l.querySelector(u)===null)){switch(a){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":if(l.querySelector(zu(n)))return}a=l.createElement("link"),Kt(a,"link",t),Lt(a),l.head.appendChild(a)}}}function qy(t,e,l){el.S(t,e,l);var a=Ua;if(a&&t){var u=Pl(a).hoistableStyles,n=Ca(t);e=e||"default";var i=u.get(n);if(!i){var r={loading:0,preload:null};if(i=a.querySelector(Tu(n)))r.loading=5;else{t=A({rel:"stylesheet",href:t,"data-precedence":e},l),(l=Re.get(n))&&pc(t,l);var d=i=a.createElement("link");Lt(d),Kt(d,"link",t),d._p=new Promise(function(T,_){d.onload=T,d.onerror=_}),d.addEventListener("load",function(){r.loading|=1}),d.addEventListener("error",function(){r.loading|=2}),r.loading|=4,Qn(i,e,a)}i={type:"stylesheet",instance:i,count:1,state:r},u.set(n,i)}}}function jy(t,e){el.X(t,e);var l=Ua;if(l&&t){var a=Pl(l).hoistableScripts,u=Na(t),n=a.get(u);n||(n=l.querySelector(zu(u)),n||(t=A({src:t,async:!0},e),(e=Re.get(u))&&Sc(t,e),n=l.createElement("script"),Lt(n),Kt(n,"link",t),l.head.appendChild(n)),n={type:"script",instance:n,count:1,state:null},a.set(u,n))}}function Yy(t,e){el.M(t,e);var l=Ua;if(l&&t){var a=Pl(l).hoistableScripts,u=Na(t),n=a.get(u);n||(n=l.querySelector(zu(u)),n||(t=A({src:t,async:!0,type:"module"},e),(e=Re.get(u))&&Sc(t,e),n=l.createElement("script"),Lt(n),Kt(n,"link",t),l.head.appendChild(n)),n={type:"script",instance:n,count:1,state:null},a.set(u,n))}}function Md(t,e,l,a){var u=(u=lt.current)?Xn(u):null;if(!u)throw Error(c(446));switch(t){case"meta":case"title":return null;case"style":return typeof l.precedence=="string"&&typeof l.href=="string"?(e=Ca(l.href),l=Pl(u).hoistableStyles,a=l.get(e),a||(a={type:"style",instance:null,count:0,state:null},l.set(e,a)),a):{type:"void",instance:null,count:0,state:null};case"link":if(l.rel==="stylesheet"&&typeof l.href=="string"&&typeof l.precedence=="string"){t=Ca(l.href);var n=Pl(u).hoistableStyles,i=n.get(t);if(i||(u=u.ownerDocument||u,i={type:"stylesheet",instance:null,count:0,state:{loading:0,preload:null}},n.set(t,i),(n=u.querySelector(Tu(t)))&&!n._p&&(i.instance=n,i.state.loading=5),Re.has(t)||(l={rel:"preload",as:"style",href:l.href,crossOrigin:l.crossOrigin,integrity:l.integrity,media:l.media,hrefLang:l.hrefLang,referrerPolicy:l.referrerPolicy},Re.set(t,l),n||Ly(u,t,l,i.state))),e&&a===null)throw Error(c(528,""));return i}if(e&&a!==null)throw Error(c(529,""));return null;case"script":return e=l.async,l=l.src,typeof l=="string"&&e&&typeof e!="function"&&typeof e!="symbol"?(e=Na(l),l=Pl(u).hoistableScripts,a=l.get(e),a||(a={type:"script",instance:null,count:0,state:null},l.set(e,a)),a):{type:"void",instance:null,count:0,state:null};default:throw Error(c(444,t))}}function Ca(t){return'href="'+ge(t)+'"'}function Tu(t){return'link[rel="stylesheet"]['+t+"]"}function Dd(t){return A({},t,{"data-precedence":t.precedence,precedence:null})}function Ly(t,e,l,a){t.querySelector('link[rel="preload"][as="style"]['+e+"]")?a.loading=1:(e=t.createElement("link"),a.preload=e,e.addEventListener("load",function(){return a.loading|=1}),e.addEventListener("error",function(){return a.loading|=2}),Kt(e,"link",l),Lt(e),t.head.appendChild(e))}function Na(t){return'[src="'+ge(t)+'"]'}function zu(t){return"script[async]"+t}function Ud(t,e,l){if(e.count++,e.instance===null)switch(e.type){case"style":var a=t.querySelector('style[data-href~="'+ge(l.href)+'"]');if(a)return e.instance=a,Lt(a),a;var u=A({},l,{"data-href":l.href,"data-precedence":l.precedence,href:null,precedence:null});return a=(t.ownerDocument||t).createElement("style"),Lt(a),Kt(a,"style",u),Qn(a,l.precedence,t),e.instance=a;case"stylesheet":u=Ca(l.href);var n=t.querySelector(Tu(u));if(n)return e.state.loading|=4,e.instance=n,Lt(n),n;a=Dd(l),(u=Re.get(u))&&pc(a,u),n=(t.ownerDocument||t).createElement("link"),Lt(n);var i=n;return i._p=new Promise(function(r,d){i.onload=r,i.onerror=d}),Kt(n,"link",a),e.state.loading|=4,Qn(n,l.precedence,t),e.instance=n;case"script":return n=Na(l.src),(u=t.querySelector(zu(n)))?(e.instance=u,Lt(u),u):(a=l,(u=Re.get(n))&&(a=A({},l),Sc(a,u)),t=t.ownerDocument||t,u=t.createElement("script"),Lt(u),Kt(u,"link",a),t.head.appendChild(u),e.instance=u);case"void":return null;default:throw Error(c(443,e.type))}else e.type==="stylesheet"&&(e.state.loading&4)===0&&(a=e.instance,e.state.loading|=4,Qn(a,l.precedence,t));return e.instance}function Qn(t,e,l){for(var a=l.querySelectorAll('link[rel="stylesheet"][data-precedence],style[data-precedence]'),u=a.length?a[a.length-1]:null,n=u,i=0;i title"):null)}function Gy(t,e,l){if(l===1||e.itemProp!=null)return!1;switch(t){case"meta":case"title":return!0;case"style":if(typeof e.precedence!="string"||typeof e.href!="string"||e.href==="")break;return!0;case"link":if(typeof e.rel!="string"||typeof e.href!="string"||e.href===""||e.onLoad||e.onError)break;return e.rel==="stylesheet"?(t=e.disabled,typeof e.precedence=="string"&&t==null):!0;case"script":if(e.async&&typeof e.async!="function"&&typeof e.async!="symbol"&&!e.onLoad&&!e.onError&&e.src&&typeof e.src=="string")return!0}return!1}function xd(t){return!(t.type==="stylesheet"&&(t.state.loading&3)===0)}function Xy(t,e,l,a){if(l.type==="stylesheet"&&(typeof a.media!="string"||matchMedia(a.media).matches!==!1)&&(l.state.loading&4)===0){if(l.instance===null){var u=Ca(a.href),n=e.querySelector(Tu(u));if(n){e=n._p,e!==null&&typeof e=="object"&&typeof e.then=="function"&&(t.count++,t=Vn.bind(t),e.then(t,t)),l.state.loading|=4,l.instance=n,Lt(n);return}n=e.ownerDocument||e,a=Dd(a),(u=Re.get(u))&&pc(a,u),n=n.createElement("link"),Lt(n);var i=n;i._p=new Promise(function(r,d){i.onload=r,i.onerror=d}),Kt(n,"link",a),l.instance=n}t.stylesheets===null&&(t.stylesheets=new Map),t.stylesheets.set(l,e),(e=l.state.preload)&&(l.state.loading&3)===0&&(t.count++,l=Vn.bind(t),e.addEventListener("load",l),e.addEventListener("error",l))}}var bc=0;function Qy(t,e){return t.stylesheets&&t.count===0&&Jn(t,t.stylesheets),0bc?50:800)+e);return t.unsuspend=l,function(){t.unsuspend=null,clearTimeout(a),clearTimeout(u)}}:null}function Vn(){if(this.count--,this.count===0&&(this.imgCount===0||!this.waitingForImages)){if(this.stylesheets)Jn(this,this.stylesheets);else if(this.unsuspend){var t=this.unsuspend;this.unsuspend=null,t()}}}var Kn=null;function Jn(t,e){t.stylesheets=null,t.unsuspend!==null&&(t.count++,Kn=new Map,e.forEach(Zy,t),Kn=null,Vn.call(t))}function Zy(t,e){if(!(e.state.loading&4)){var l=Kn.get(t);if(l)var a=l.get(null);else{l=new Map,Kn.set(t,l);for(var u=t.querySelectorAll("link[data-precedence],style[data-precedence]"),n=0;n"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(f)}catch(o){console.error(o)}}return f(),Dc.exports=fv(),Dc.exports}var rv=cv();var ah="popstate";function uh(f){return typeof f=="object"&&f!=null&&"pathname"in f&&"search"in f&&"hash"in f&&"state"in f&&"key"in f}function ov(f={}){function o(h,m){let{pathname:S="/",search:M="",hash:b=""}=Wl(h.location.hash.substring(1));return!S.startsWith("/")&&!S.startsWith(".")&&(S="/"+S),qc("",{pathname:S,search:M,hash:b},m.state&&m.state.usr||null,m.state&&m.state.key||"default")}function s(h,m){let S=h.document.querySelector("base"),M="";if(S&&S.getAttribute("href")){let b=h.location.href,g=b.indexOf("#");M=g===-1?b:b.slice(0,g)}return M+"#"+(typeof m=="string"?m:Cu(m))}function c(h,m){Ue(h.pathname.charAt(0)==="/",`relative pathnames are not supported in hash history.push(${JSON.stringify(m)})`)}return dv(o,s,c,f)}function _t(f,o){if(f===!1||f===null||typeof f>"u")throw new Error(o)}function Ue(f,o){if(!f){typeof console<"u"&&console.warn(o);try{throw new Error(o)}catch{}}}function sv(){return Math.random().toString(36).substring(2,10)}function nh(f,o){return{usr:f.state,key:f.key,idx:o,masked:f.unstable_mask?{pathname:f.pathname,search:f.search,hash:f.hash}:void 0}}function qc(f,o,s=null,c,h){return{pathname:typeof f=="string"?f:f.pathname,search:"",hash:"",...typeof o=="string"?Wl(o):o,state:s,key:o&&o.key||c||sv(),unstable_mask:h}}function Cu({pathname:f="/",search:o="",hash:s=""}){return o&&o!=="?"&&(f+=o.charAt(0)==="?"?o:"?"+o),s&&s!=="#"&&(f+=s.charAt(0)==="#"?s:"#"+s),f}function Wl(f){let o={};if(f){let s=f.indexOf("#");s>=0&&(o.hash=f.substring(s),f=f.substring(0,s));let c=f.indexOf("?");c>=0&&(o.search=f.substring(c),f=f.substring(0,c)),f&&(o.pathname=f)}return o}function dv(f,o,s,c={}){let{window:h=document.defaultView,v5Compat:m=!1}=c,S=h.history,M="POP",b=null,g=N();g==null&&(g=0,S.replaceState({...S.state,idx:g},""));function N(){return(S.state||{idx:null}).idx}function A(){M="POP";let H=N(),w=H==null?null:H-g;g=H,b&&b({action:M,location:L.location,delta:w})}function q(H,w){M="PUSH";let I=uh(H)?H:qc(L.location,H,w);s&&s(I,H),g=N()+1;let $=nh(I,g),pt=L.createHref(I.unstable_mask||I);try{S.pushState($,"",pt)}catch(St){if(St instanceof DOMException&&St.name==="DataCloneError")throw St;h.location.assign(pt)}m&&b&&b({action:M,location:L.location,delta:1})}function J(H,w){M="REPLACE";let I=uh(H)?H:qc(L.location,H,w);s&&s(I,H),g=N();let $=nh(I,g),pt=L.createHref(I.unstable_mask||I);S.replaceState($,"",pt),m&&b&&b({action:M,location:L.location,delta:0})}function Z(H){return hv(H)}let L={get action(){return M},get location(){return f(h,S)},listen(H){if(b)throw new Error("A history only accepts one active listener");return h.addEventListener(ah,A),b=H,()=>{h.removeEventListener(ah,A),b=null}},createHref(H){return o(h,H)},createURL:Z,encodeLocation(H){let w=Z(H);return{pathname:w.pathname,search:w.search,hash:w.hash}},push:q,replace:J,go(H){return S.go(H)}};return L}function hv(f,o=!1){let s="http://localhost";typeof window<"u"&&(s=window.location.origin!=="null"?window.location.origin:window.location.href),_t(s,"No window.location.(origin|href) available to create URL");let c=typeof f=="string"?f:Cu(f);return c=c.replace(/ $/,"%20"),!o&&c.startsWith("//")&&(c=s+c),new URL(c,s)}function oh(f,o,s="/"){return mv(f,o,s,!1)}function mv(f,o,s,c){let h=typeof o=="string"?Wl(o):o,m=ll(h.pathname||"/",s);if(m==null)return null;let S=sh(f);yv(S);let M=null;for(let b=0;M==null&&b{let N={relativePath:g===void 0?S.path||"":g,caseSensitive:S.caseSensitive===!0,childrenIndex:M,route:S};if(N.relativePath.startsWith("/")){if(!N.relativePath.startsWith(c)&&b)return;_t(N.relativePath.startsWith(c),`Absolute route path "${N.relativePath}" nested under path "${c}" is not valid. An absolute child route path must start with the combined path of all its parent routes.`),N.relativePath=N.relativePath.slice(c.length)}let A=je([c,N.relativePath]),q=s.concat(N);S.children&&S.children.length>0&&(_t(S.index!==!0,`Index routes must not have child routes. Please remove all child routes from route path "${A}".`),sh(S.children,o,q,A,b)),!(S.path==null&&!S.index)&&o.push({path:A,score:Tv(A,S.index),routesMeta:q})};return f.forEach((S,M)=>{if(S.path===""||!S.path?.includes("?"))m(S,M);else for(let b of dh(S.path))m(S,M,!0,b)}),o}function dh(f){let o=f.split("/");if(o.length===0)return[];let[s,...c]=o,h=s.endsWith("?"),m=s.replace(/\?$/,"");if(c.length===0)return h?[m,""]:[m];let S=dh(c.join("/")),M=[];return M.push(...S.map(b=>b===""?m:[m,b].join("/"))),h&&M.push(...S),M.map(b=>f.startsWith("/")&&b===""?"/":b)}function yv(f){f.sort((o,s)=>o.score!==s.score?s.score-o.score:zv(o.routesMeta.map(c=>c.childrenIndex),s.routesMeta.map(c=>c.childrenIndex)))}var vv=/^:[\w-]+$/,gv=3,pv=2,Sv=1,bv=10,Ev=-2,ih=f=>f==="*";function Tv(f,o){let s=f.split("/"),c=s.length;return s.some(ih)&&(c+=Ev),o&&(c+=pv),s.filter(h=>!ih(h)).reduce((h,m)=>h+(vv.test(m)?gv:m===""?Sv:bv),c)}function zv(f,o){return f.length===o.length&&f.slice(0,-1).every((c,h)=>c===o[h])?f[f.length-1]-o[o.length-1]:0}function Av(f,o,s=!1){let{routesMeta:c}=f,h={},m="/",S=[];for(let M=0;M{if(N==="*"){let Z=M[q]||"";S=m.slice(0,m.length-Z.length).replace(/(.)\/+$/,"$1")}const J=M[q];return A&&!J?g[N]=void 0:g[N]=(J||"").replace(/%2F/g,"/"),g},{}),pathname:m,pathnameBase:S,pattern:f}}function Rv(f,o=!1,s=!0){Ue(f==="*"||!f.endsWith("*")||f.endsWith("/*"),`Route path "${f}" will be treated as if it were "${f.replace(/\*$/,"/*")}" because the \`*\` character must always follow a \`/\` in the pattern. To get rid of this warning, please change the route path to "${f.replace(/\*$/,"/*")}".`);let c=[],h="^"+f.replace(/\/*\*?$/,"").replace(/^\/*/,"/").replace(/[\\.*+^${}|()[\]]/g,"\\$&").replace(/\/:([\w-]+)(\?)?/g,(S,M,b,g,N)=>{if(c.push({paramName:M,isOptional:b!=null}),b){let A=N.charAt(g+S.length);return A&&A!=="/"?"/([^\\/]*)":"(?:/([^\\/]*))?"}return"/([^\\/]+)"}).replace(/\/([\w-]+)\?(\/|$)/g,"(/$1)?$2");return f.endsWith("*")?(c.push({paramName:"*"}),h+=f==="*"||f==="/*"?"(.*)$":"(?:\\/(.+)|\\/*)$"):s?h+="\\/*$":f!==""&&f!=="/"&&(h+="(?:(?=\\/|$))"),[new RegExp(h,o?void 0:"i"),c]}function _v(f){try{return f.split("/").map(o=>decodeURIComponent(o).replace(/\//g,"%2F")).join("/")}catch(o){return Ue(!1,`The URL path "${f}" could not be decoded because it is a malformed URL segment. This is probably due to a bad percent encoding (${o}).`),f}}function ll(f,o){if(o==="/")return f;if(!f.toLowerCase().startsWith(o.toLowerCase()))return null;let s=o.endsWith("/")?o.length-1:o.length,c=f.charAt(s);return c&&c!=="/"?null:f.slice(s)||"/"}var Ov=/^(?:[a-z][a-z0-9+.-]*:|\/\/)/i;function Mv(f,o="/"){let{pathname:s,search:c="",hash:h=""}=typeof f=="string"?Wl(f):f,m;return s?(s=s.replace(/\/\/+/g,"/"),s.startsWith("/")?m=fh(s.substring(1),"/"):m=fh(s,o)):m=o,{pathname:m,search:Cv(c),hash:Nv(h)}}function fh(f,o){let s=o.replace(/\/+$/,"").split("/");return f.split("/").forEach(h=>{h===".."?s.length>1&&s.pop():h!=="."&&s.push(h)}),s.length>1?s.join("/"):"/"}function xc(f,o,s,c){return`Cannot include a '${f}' character in a manually specified \`to.${o}\` field [${JSON.stringify(c)}]. Please separate it out to the \`to.${s}\` field. Alternatively you may provide the full path as a string in and the router will parse it for you.`}function Dv(f){return f.filter((o,s)=>s===0||o.route.path&&o.route.path.length>0)}function hh(f){let o=Dv(f);return o.map((s,c)=>c===o.length-1?s.pathname:s.pathnameBase)}function Lc(f,o,s,c=!1){let h;typeof f=="string"?h=Wl(f):(h={...f},_t(!h.pathname||!h.pathname.includes("?"),xc("?","pathname","search",h)),_t(!h.pathname||!h.pathname.includes("#"),xc("#","pathname","hash",h)),_t(!h.search||!h.search.includes("#"),xc("#","search","hash",h)));let m=f===""||h.pathname==="",S=m?"/":h.pathname,M;if(S==null)M=s;else{let A=o.length-1;if(!c&&S.startsWith("..")){let q=S.split("/");for(;q[0]==="..";)q.shift(),A-=1;h.pathname=q.join("/")}M=A>=0?o[A]:"/"}let b=Mv(h,M),g=S&&S!=="/"&&S.endsWith("/"),N=(m||S===".")&&s.endsWith("/");return!b.pathname.endsWith("/")&&(g||N)&&(b.pathname+="/"),b}var je=f=>f.join("/").replace(/\/\/+/g,"/"),Uv=f=>f.replace(/\/+$/,"").replace(/^\/*/,"/"),Cv=f=>!f||f==="?"?"":f.startsWith("?")?f:"?"+f,Nv=f=>!f||f==="#"?"":f.startsWith("#")?f:"#"+f,xv=class{constructor(f,o,s,c=!1){this.status=f,this.statusText=o||"",this.internal=c,s instanceof Error?(this.data=s.toString(),this.error=s):this.data=s}};function Hv(f){return f!=null&&typeof f.status=="number"&&typeof f.statusText=="string"&&typeof f.internal=="boolean"&&"data"in f}function Bv(f){return f.map(o=>o.route.path).filter(Boolean).join("/").replace(/\/\/*/g,"/")||"/"}var mh=typeof window<"u"&&typeof window.document<"u"&&typeof window.document.createElement<"u";function yh(f,o){let s=f;if(typeof s!="string"||!Ov.test(s))return{absoluteURL:void 0,isExternal:!1,to:s};let c=s,h=!1;if(mh)try{let m=new URL(window.location.href),S=s.startsWith("//")?new URL(m.protocol+s):new URL(s),M=ll(S.pathname,o);S.origin===m.origin&&M!=null?s=M+S.search+S.hash:h=!0}catch{Ue(!1,` contains an invalid URL which will probably break when clicked - please update to a valid URL path.`)}return{absoluteURL:c,isExternal:h,to:s}}Object.getOwnPropertyNames(Object.prototype).sort().join("\0");var vh=["POST","PUT","PATCH","DELETE"];new Set(vh);var qv=["GET",...vh];new Set(qv);var Ha=U.createContext(null);Ha.displayName="DataRouter";var ii=U.createContext(null);ii.displayName="DataRouterState";var jv=U.createContext(!1),gh=U.createContext({isTransitioning:!1});gh.displayName="ViewTransition";var Yv=U.createContext(new Map);Yv.displayName="Fetchers";var Lv=U.createContext(null);Lv.displayName="Await";var _e=U.createContext(null);_e.displayName="Navigation";var Nu=U.createContext(null);Nu.displayName="Location";var al=U.createContext({outlet:null,matches:[],isDataRoute:!1});al.displayName="Route";var Gc=U.createContext(null);Gc.displayName="RouteError";var ph="REACT_ROUTER_ERROR",Gv="REDIRECT",Xv="ROUTE_ERROR_RESPONSE";function Qv(f){if(f.startsWith(`${ph}:${Gv}:{`))try{let o=JSON.parse(f.slice(28));if(typeof o=="object"&&o&&typeof o.status=="number"&&typeof o.statusText=="string"&&typeof o.location=="string"&&typeof o.reloadDocument=="boolean"&&typeof o.replace=="boolean")return o}catch{}}function Zv(f){if(f.startsWith(`${ph}:${Xv}:{`))try{let o=JSON.parse(f.slice(40));if(typeof o=="object"&&o&&typeof o.status=="number"&&typeof o.statusText=="string")return new xv(o.status,o.statusText,o.data)}catch{}}function Vv(f,{relative:o}={}){_t(xu(),"useHref() may be used only in the context of a component.");let{basename:s,navigator:c}=U.useContext(_e),{hash:h,pathname:m,search:S}=Hu(f,{relative:o}),M=m;return s!=="/"&&(M=m==="/"?s:je([s,m])),c.createHref({pathname:M,search:S,hash:h})}function xu(){return U.useContext(Nu)!=null}function Dl(){return _t(xu(),"useLocation() may be used only in the context of a component."),U.useContext(Nu).location}var Sh="You should call navigate() in a React.useEffect(), not when your component is first rendered.";function bh(f){U.useContext(_e).static||U.useLayoutEffect(f)}function Kv(){let{isDataRoute:f}=U.useContext(al);return f?u0():Jv()}function Jv(){_t(xu(),"useNavigate() may be used only in the context of a component.");let f=U.useContext(Ha),{basename:o,navigator:s}=U.useContext(_e),{matches:c}=U.useContext(al),{pathname:h}=Dl(),m=JSON.stringify(hh(c)),S=U.useRef(!1);return bh(()=>{S.current=!0}),U.useCallback((b,g={})=>{if(Ue(S.current,Sh),!S.current)return;if(typeof b=="number"){s.go(b);return}let N=Lc(b,JSON.parse(m),h,g.relative==="path");f==null&&o!=="/"&&(N.pathname=N.pathname==="/"?o:je([o,N.pathname])),(g.replace?s.replace:s.push)(N,g.state,g)},[o,s,m,h,f])}U.createContext(null);function Hu(f,{relative:o}={}){let{matches:s}=U.useContext(al),{pathname:c}=Dl(),h=JSON.stringify(hh(s));return U.useMemo(()=>Lc(f,JSON.parse(h),c,o==="path"),[f,h,c,o])}function wv(f,o){return Eh(f,o)}function Eh(f,o,s){_t(xu(),"useRoutes() may be used only in the context of a component.");let{navigator:c}=U.useContext(_e),{matches:h}=U.useContext(al),m=h[h.length-1],S=m?m.params:{},M=m?m.pathname:"/",b=m?m.pathnameBase:"/",g=m&&m.route;{let H=g&&g.path||"";zh(M,!g||H.endsWith("*")||H.endsWith("*?"),`You rendered descendant (or called \`useRoutes()\`) at "${M}" (under ) but the parent route path has no trailing "*". This means if you navigate deeper, the parent won't match anymore and therefore the child routes will never render. + +Please change the parent to .`)}let N=Dl(),A;if(o){let H=typeof o=="string"?Wl(o):o;_t(b==="/"||H.pathname?.startsWith(b),`When overriding the location using \`\` or \`useRoutes(routes, location)\`, the location pathname must begin with the portion of the URL pathname that was matched by all parent routes. The current pathname base is "${b}" but pathname "${H.pathname}" was given in the \`location\` prop.`),A=H}else A=N;let q=A.pathname||"/",J=q;if(b!=="/"){let H=b.replace(/^\//,"").split("/");J="/"+q.replace(/^\//,"").split("/").slice(H.length).join("/")}let Z=oh(f,{pathname:J});Ue(g||Z!=null,`No routes matched location "${A.pathname}${A.search}${A.hash}" `),Ue(Z==null||Z[Z.length-1].route.element!==void 0||Z[Z.length-1].route.Component!==void 0||Z[Z.length-1].route.lazy!==void 0,`Matched leaf route at location "${A.pathname}${A.search}${A.hash}" does not have an element or Component. This means it will render an with a null value by default resulting in an "empty" page.`);let L=Iv(Z&&Z.map(H=>Object.assign({},H,{params:Object.assign({},S,H.params),pathname:je([b,c.encodeLocation?c.encodeLocation(H.pathname.replace(/\?/g,"%3F").replace(/#/g,"%23")).pathname:H.pathname]),pathnameBase:H.pathnameBase==="/"?b:je([b,c.encodeLocation?c.encodeLocation(H.pathnameBase.replace(/\?/g,"%3F").replace(/#/g,"%23")).pathname:H.pathnameBase])})),h,s);return o&&L?U.createElement(Nu.Provider,{value:{location:{pathname:"/",search:"",hash:"",state:null,key:"default",unstable_mask:void 0,...A},navigationType:"POP"}},L):L}function $v(){let f=a0(),o=Hv(f)?`${f.status} ${f.statusText}`:f instanceof Error?f.message:JSON.stringify(f),s=f instanceof Error?f.stack:null,c="rgba(200,200,200, 0.5)",h={padding:"0.5rem",backgroundColor:c},m={padding:"2px 4px",backgroundColor:c},S=null;return console.error("Error handled by React Router default ErrorBoundary:",f),S=U.createElement(U.Fragment,null,U.createElement("p",null,"💿 Hey developer 👋"),U.createElement("p",null,"You can provide a way better UX than this when your app throws errors by providing your own ",U.createElement("code",{style:m},"ErrorBoundary")," or"," ",U.createElement("code",{style:m},"errorElement")," prop on your route.")),U.createElement(U.Fragment,null,U.createElement("h2",null,"Unexpected Application Error!"),U.createElement("h3",{style:{fontStyle:"italic"}},o),s?U.createElement("pre",{style:h},s):null,S)}var Wv=U.createElement($v,null),Th=class extends U.Component{constructor(f){super(f),this.state={location:f.location,revalidation:f.revalidation,error:f.error}}static getDerivedStateFromError(f){return{error:f}}static getDerivedStateFromProps(f,o){return o.location!==f.location||o.revalidation!=="idle"&&f.revalidation==="idle"?{error:f.error,location:f.location,revalidation:f.revalidation}:{error:f.error!==void 0?f.error:o.error,location:o.location,revalidation:f.revalidation||o.revalidation}}componentDidCatch(f,o){this.props.onError?this.props.onError(f,o):console.error("React Router caught the following error during render",f)}render(){let f=this.state.error;if(this.context&&typeof f=="object"&&f&&"digest"in f&&typeof f.digest=="string"){const s=Zv(f.digest);s&&(f=s)}let o=f!==void 0?U.createElement(al.Provider,{value:this.props.routeContext},U.createElement(Gc.Provider,{value:f,children:this.props.component})):this.props.children;return this.context?U.createElement(kv,{error:f},o):o}};Th.contextType=jv;var Hc=new WeakMap;function kv({children:f,error:o}){let{basename:s}=U.useContext(_e);if(typeof o=="object"&&o&&"digest"in o&&typeof o.digest=="string"){let c=Qv(o.digest);if(c){let h=Hc.get(o);if(h)throw h;let m=yh(c.location,s);if(mh&&!Hc.get(o))if(m.isExternal||c.reloadDocument)window.location.href=m.absoluteURL||m.to;else{const S=Promise.resolve().then(()=>window.__reactRouterDataRouter.navigate(m.to,{replace:c.replace}));throw Hc.set(o,S),S}return U.createElement("meta",{httpEquiv:"refresh",content:`0;url=${m.absoluteURL||m.to}`})}}return f}function Fv({routeContext:f,match:o,children:s}){let c=U.useContext(Ha);return c&&c.static&&c.staticContext&&(o.route.errorElement||o.route.ErrorBoundary)&&(c.staticContext._deepestRenderedBoundaryId=o.route.id),U.createElement(al.Provider,{value:f},s)}function Iv(f,o=[],s){let c=s?.state;if(f==null){if(!c)return null;if(c.errors)f=c.matches;else if(o.length===0&&!c.initialized&&c.matches.length>0)f=c.matches;else return null}let h=f,m=c?.errors;if(m!=null){let N=h.findIndex(A=>A.route.id&&m?.[A.route.id]!==void 0);_t(N>=0,`Could not find a matching route for errors on route IDs: ${Object.keys(m).join(",")}`),h=h.slice(0,Math.min(h.length,N+1))}let S=!1,M=-1;if(s&&c){S=c.renderFallback;for(let N=0;N=0?h=h.slice(0,M+1):h=[h[0]];break}}}}let b=s?.onError,g=c&&b?(N,A)=>{b(N,{location:c.location,params:c.matches?.[0]?.params??{},unstable_pattern:Bv(c.matches),errorInfo:A})}:void 0;return h.reduceRight((N,A,q)=>{let J,Z=!1,L=null,H=null;c&&(J=m&&A.route.id?m[A.route.id]:void 0,L=A.route.errorElement||Wv,S&&(M<0&&q===0?(zh("route-fallback",!1,"No `HydrateFallback` element provided to render during initial hydration"),Z=!0,H=null):M===q&&(Z=!0,H=A.route.hydrateFallbackElement||null)));let w=o.concat(h.slice(0,q+1)),I=()=>{let $;return J?$=L:Z?$=H:A.route.Component?$=U.createElement(A.route.Component,null):A.route.element?$=A.route.element:$=N,U.createElement(Fv,{match:A,routeContext:{outlet:N,matches:w,isDataRoute:c!=null},children:$})};return c&&(A.route.ErrorBoundary||A.route.errorElement||q===0)?U.createElement(Th,{location:c.location,revalidation:c.revalidation,component:L,error:J,children:I(),routeContext:{outlet:null,matches:w,isDataRoute:!0},onError:g}):I()},null)}function Xc(f){return`${f} must be used within a data router. See https://reactrouter.com/en/main/routers/picking-a-router.`}function Pv(f){let o=U.useContext(Ha);return _t(o,Xc(f)),o}function t0(f){let o=U.useContext(ii);return _t(o,Xc(f)),o}function e0(f){let o=U.useContext(al);return _t(o,Xc(f)),o}function Qc(f){let o=e0(f),s=o.matches[o.matches.length-1];return _t(s.route.id,`${f} can only be used on routes that contain a unique "id"`),s.route.id}function l0(){return Qc("useRouteId")}function a0(){let f=U.useContext(Gc),o=t0("useRouteError"),s=Qc("useRouteError");return f!==void 0?f:o.errors?.[s]}function u0(){let{router:f}=Pv("useNavigate"),o=Qc("useNavigate"),s=U.useRef(!1);return bh(()=>{s.current=!0}),U.useCallback(async(h,m={})=>{Ue(s.current,Sh),s.current&&(typeof h=="number"?await f.navigate(h):await f.navigate(h,{fromRouteId:o,...m}))},[f,o])}var ch={};function zh(f,o,s){!o&&!ch[f]&&(ch[f]=!0,Ue(!1,s))}U.memo(n0);function n0({routes:f,future:o,state:s,isStatic:c,onError:h}){return Eh(f,void 0,{state:s,isStatic:c,onError:h})}function ei(f){_t(!1,"A is only ever to be used as the child of element, never rendered directly. Please wrap your in a .")}function i0({basename:f="/",children:o=null,location:s,navigationType:c="POP",navigator:h,static:m=!1,unstable_useTransitions:S}){_t(!xu(),"You cannot render a inside another . You should never have more than one in your app.");let M=f.replace(/^\/*/,"/"),b=U.useMemo(()=>({basename:M,navigator:h,static:m,unstable_useTransitions:S,future:{}}),[M,h,m,S]);typeof s=="string"&&(s=Wl(s));let{pathname:g="/",search:N="",hash:A="",state:q=null,key:J="default",unstable_mask:Z}=s,L=U.useMemo(()=>{let H=ll(g,M);return H==null?null:{location:{pathname:H,search:N,hash:A,state:q,key:J,unstable_mask:Z},navigationType:c}},[M,g,N,A,q,J,c,Z]);return Ue(L!=null,` is not able to match the URL "${g}${N}${A}" because it does not start with the basename, so the won't render anything.`),L==null?null:U.createElement(_e.Provider,{value:b},U.createElement(Nu.Provider,{children:o,value:L}))}function f0({children:f,location:o}){return wv(jc(f),o)}function jc(f,o=[]){let s=[];return U.Children.forEach(f,(c,h)=>{if(!U.isValidElement(c))return;let m=[...o,h];if(c.type===U.Fragment){s.push.apply(s,jc(c.props.children,m));return}_t(c.type===ei,`[${typeof c.type=="string"?c.type:c.type.name}] is not a component. All component children of must be a or `),_t(!c.props.index||!c.props.children,"An index route cannot have child routes.");let S={id:c.props.id||m.join("-"),caseSensitive:c.props.caseSensitive,element:c.props.element,Component:c.props.Component,index:c.props.index,path:c.props.path,middleware:c.props.middleware,loader:c.props.loader,action:c.props.action,hydrateFallbackElement:c.props.hydrateFallbackElement,HydrateFallback:c.props.HydrateFallback,errorElement:c.props.errorElement,ErrorBoundary:c.props.ErrorBoundary,hasErrorBoundary:c.props.hasErrorBoundary===!0||c.props.ErrorBoundary!=null||c.props.errorElement!=null,shouldRevalidate:c.props.shouldRevalidate,handle:c.props.handle,lazy:c.props.lazy};c.props.children&&(S.children=jc(c.props.children,m)),s.push(S)}),s}var li="get",ai="application/x-www-form-urlencoded";function fi(f){return typeof HTMLElement<"u"&&f instanceof HTMLElement}function c0(f){return fi(f)&&f.tagName.toLowerCase()==="button"}function r0(f){return fi(f)&&f.tagName.toLowerCase()==="form"}function o0(f){return fi(f)&&f.tagName.toLowerCase()==="input"}function s0(f){return!!(f.metaKey||f.altKey||f.ctrlKey||f.shiftKey)}function d0(f,o){return f.button===0&&(!o||o==="_self")&&!s0(f)}var ti=null;function h0(){if(ti===null)try{new FormData(document.createElement("form"),0),ti=!1}catch{ti=!0}return ti}var m0=new Set(["application/x-www-form-urlencoded","multipart/form-data","text/plain"]);function Bc(f){return f!=null&&!m0.has(f)?(Ue(!1,`"${f}" is not a valid \`encType\` for \`
\`/\`\` and will default to "${ai}"`),null):f}function y0(f,o){let s,c,h,m,S;if(r0(f)){let M=f.getAttribute("action");c=M?ll(M,o):null,s=f.getAttribute("method")||li,h=Bc(f.getAttribute("enctype"))||ai,m=new FormData(f)}else if(c0(f)||o0(f)&&(f.type==="submit"||f.type==="image")){let M=f.form;if(M==null)throw new Error('Cannot submit a - - +

+

-
    -
  • Positionnement verifiable: concepteur, creation electronique et iteration IA
  • +
      +
    • Poste studio: conception electronique et design de systeme
    • Presence professionnelle active sur LinkedIn et Malt
    • Premier echange possible sous 24-48h selon disponibilite
    • -
    • Travaux publies et contact direct pour collaboration
    • +
    • Travaux publies et processus de co-conception vérifiables
    - + ); } diff --git a/src/components/sections/FlowDiagram.tsx b/src/components/sections/FlowDiagram.tsx new file mode 100644 index 0000000..670ae58 --- /dev/null +++ b/src/components/sections/FlowDiagram.tsx @@ -0,0 +1,124 @@ +import { TRACK_EVENTS, trackAttrs } from '@/lib/tracking'; +import type { CtaLink } from '@/lib/types'; +import { motion, useReducedMotion } from 'motion/react'; + +type FlowStep = { + label: string; + description: string; + href: string; + icon: 'pad' | 'hub' | 'cable'; + event: CtaLink['event']; + destination: string; +}; + +const steps: FlowStep[] = [ + { + label: 'Signal d’entrée', + description: 'Mesure du besoin, contraintes techniques et points de controle', + href: '#top', + icon: 'pad', + event: TRACK_EVENTS.ctaHeroProfile, + destination: '#top' + }, + { + label: 'Bus de contrôle', + description: 'Architecture systeme, mapping des flux et logique d automatisme', + href: '#a-propos', + icon: 'hub', + event: TRACK_EVENTS.ctaHeroProjects, + destination: '#a-propos' + }, + { + label: 'Automatisme', + description: 'Prototype operationnel, boucle test -> calibrage -> validation', + href: '#projets', + icon: 'cable', + event: TRACK_EVENTS.ctaHeroContact, + destination: '#projets' + }, + { + label: 'Lancement mission', + description: 'Activation de collaboration avec objectifs, delais et livrables', + href: '#contact', + icon: 'hub', + event: TRACK_EVENTS.outboundLinkedinContact, + destination: '#contact' + } +]; + +export function FlowDiagram() { + const prefersReducedMotion = useReducedMotion(); + + return ( +
    +
    +
    +
    + +

    + Sequence de pilotage studio: lecture du signal, architecture, automatisme puis activation collaboration. +

    + +
    + idee -> systeme + schema -> prototype + preuve -> mission +
    + +
      + {steps.flatMap((step, index) => { + const node = ( + + + + + ); + + if (index === steps.length - 1) { + return [node]; + } + + const edge = ( +
    +
    +
    + ); +} diff --git a/src/components/sections/Hero.tsx b/src/components/sections/Hero.tsx index b2f7899..a83bd16 100644 --- a/src/components/sections/Hero.tsx +++ b/src/components/sections/Hero.tsx @@ -1,5 +1,5 @@ -import { motion } from 'motion/react'; import { Button } from '@/components/ui/button'; +import { CtaDualRail } from '@/components/ui/cta-dual-rail'; import type { CtaLink } from '@/lib/types'; import { TRACK_EVENTS, trackAttrs } from '@/lib/tracking'; @@ -29,46 +29,54 @@ export function Hero() { return (
    +
    -

    +

    Pro • Codeur creatif • Iterateur IA • Savant fou

    - Clement Saillant, alias L'electron rare. - + - - Creation electronique, design de produit et invention de systemes audiovisuels. - J'assemble code, IA, materiaux sonores et narration visuelle pour concevoir des experiences - qui passent du prototype au live. - +

    + Laboratoire electronique et automatisme creatif: design produit, invention de systemes audiovisuels, + architecture de flux et calibration operationnelle. + J'assemble code, IA et protocoles de controle pour faire passer une idee du schema au live. +

    + +
    +

    +

    +

    +

    +

    +

    +
      -
    • - Creation electronique +
    • + Lab electronique
    • -
    • - Invention de systemes +
    • + Bus de controle
    • -
    • - Design produit +
    • + Automatisme creatif
    • -
    • - Lab IA +
    • + Boucle IA
    @@ -85,43 +93,29 @@ export function Hero() {
    -
    - Contact rapide - - LinkedIn DM - - - - Malt - -
    +
    - -
    -

    Carte rapide

    -

    L'electron rare

    -

    +

    ); diff --git a/src/components/sections/IdentityLab.tsx b/src/components/sections/IdentityLab.tsx new file mode 100644 index 0000000..644da6b --- /dev/null +++ b/src/components/sections/IdentityLab.tsx @@ -0,0 +1,78 @@ +export function IdentityLab() { + return ( +
    +
    +
    +
    + +

    + Direction provisoire en pur code: signatures visuelles electronics/automatisme avant integration des + variantes image_gen. +

    + +
    +
    +

    Option 01

    +

    ER monogramme PCB

    + + + + + + + + + ELECTRON RARE + + +

    Unstable by design

    +
    + +
    +

    Option 02

    +

    Boucle de controle

    + + + + + + + + + + ELECTRON RARE + + +

    Control signal / feedback / mission

    +
    + +
    +

    Option 03

    +

    Stamp technique

    + + + + + ELECTRON RARE + + + UNSTABLE BY DESIGN + + + +

    Label industriel / protocole studio

    +
    +
    +
    +
    + ); +} diff --git a/src/components/sections/LabNotes.tsx b/src/components/sections/LabNotes.tsx new file mode 100644 index 0000000..ac0937c --- /dev/null +++ b/src/components/sections/LabNotes.tsx @@ -0,0 +1,123 @@ +import { motion } from 'motion/react'; +import { TRACK_EVENTS, trackAttrs } from '@/lib/tracking'; +import { CtaDualRail } from '@/components/ui/cta-dual-rail'; + +type LabEntry = { + date: string; + title: string; + intent: string; + system: string; + build: string; + test: string; + result: string; + href: string; + event: (typeof TRACK_EVENTS)[keyof typeof TRACK_EVENTS]; + destination: string; + external?: boolean; +}; + +const entries: LabEntry[] = [ + { + date: '2026-02-25', + title: 'Automatisme de navigation active', + intent: 'Rendre la lecture de section instantanee pendant le scroll.', + system: 'Signal scroll -> section active -> etat nav.', + build: 'Header sticky + progress line + jitter controle.', + test: 'Verification 390/768/1024/1440 + clavier.', + result: 'Navigation plus lisible sans perte de contraste.', + href: '#top', + event: TRACK_EVENTS.ctaHeroProfile, + destination: '#top' + }, + { + date: '2026-02-27', + title: 'Boucle conversion dual CTA', + intent: 'Clarifier le chemin de contact professionnel.', + system: 'CTA primaire LinkedIn, secondaire Malt.', + build: 'Module CTA reutilisable sur sections cles.', + test: 'Controle tracking GA4 + focus visible.', + result: 'Parcours contact plus direct et mesurable.', + href: '#contact', + event: TRACK_EVENTS.ctaHeroContact, + destination: '#contact' + }, + { + date: '2026-03-01', + title: 'Research noise / Electron Fou', + intent: 'Connecter les travaux sonores au studio systeme.', + system: 'Carte projet + timeline + lien plateforme.', + build: 'Integration Bandcamp dans axe portfolio.', + test: 'Sortants verifies + ouverture nouvel onglet.', + result: 'Preuve publique du versant noise experimental.', + href: 'https://lelectron-fou.bandcamp.com/', + event: TRACK_EVENTS.outboundBandcampProject, + destination: 'bandcamp.com', + external: true + } +]; + +export function LabNotes() { + return ( +
    +
    +
    +
    + +

    + Debrief technique de sprint: hypotheses, implémentation, verification et impact operationnel. +

    + +

    + Journal de fabrication: chaque note suit le meme protocole + Intent -> System -> Build -> Test -> Result. +

    + +
    + {entries.map((entry, index) => ( + +

    {entry.date}

    +

    {entry.title}

    +
    +
    Intent
    +
    {entry.intent}
    +
    System
    +
    {entry.system}
    +
    Build
    +
    {entry.build}
    +
    Test
    +
    {entry.test}
    +
    Result
    +
    {entry.result}
    +
    +

    + + Ouvrir note reliee + +

    +
    + ))} +
    + + +
    +
    + ); +} diff --git a/src/components/sections/Projects.tsx b/src/components/sections/Projects.tsx index aac99c7..88e7e1d 100644 --- a/src/components/sections/Projects.tsx +++ b/src/components/sections/Projects.tsx @@ -1,10 +1,12 @@ import { motion } from 'motion/react'; import { Card } from '@/components/ui/card'; +import { CtaDualRail } from '@/components/ui/cta-dual-rail'; import type { CtaLink } from '@/lib/types'; import { TRACK_EVENTS, trackAttrs } from '@/lib/tracking'; type ProjectItem = { title: string; + stage: string; description: string; link?: CtaLink; }; @@ -12,6 +14,7 @@ type ProjectItem = { const projects: ProjectItem[] = [ { title: "L'électron rare", + stage: 'Studio core', description: 'Studio principal: creation electronique, prototypes d interactions audiovisuelles et systemes experimentaux.', link: { @@ -24,11 +27,13 @@ const projects: ProjectItem[] = [ }, { title: 'Bureau conception produit/systeme', + stage: 'Design produit', description: "Conception de dispositifs et parcours d'usage: du concept au prototype fonctionnel, avec approche studio et iteration rapide." }, { title: 'Electron Fou (noise)', + stage: 'R&D sonore', description: 'Volet noise: R&D sonore, textures radicales et sorties publiees sur plateformes audio.', link: { @@ -38,16 +43,39 @@ const projects: ProjectItem[] = [ destination: 'bandcamp.com', external: true } + }, + { + title: 'Hardware/Firmware references', + stage: 'Open source', + description: + 'Stack de references terrain: ESP32, STM32, LED curtain, energie batterie et automatisme de flux.' } ]; +const topReferences = [ + 'https://github.com/KomplexKapharnaum/KXKM_ESP32_Audio_Battery_hardware', + 'https://github.com/KomplexKapharnaum/LEDcurtain_hardware', + 'https://github.com/KomplexKapharnaum/kxkm_Ve.direct' +] as const; + +const referencesHub = 'https://github.com/electron-rare/?tab=repositories'; + export function Projects() { return (
    -
    -

    - Projets -

    +
    +
    +
    + +

    + Bloc projets oriente execution: conception systeme, preuve publique et references hardware/firmware reliees + au positionnement studio. +

    {projects.map((project, index) => ( @@ -59,9 +87,13 @@ export function Projects() { transition={{ duration: 0.42, delay: index * 0.06 }} whileHover={{ y: -5 }} > - -

    {project.title}

    -

    {project.description}

    + +

    {project.stage}

    +
    +
    +

    {project.description}

    {project.link && (

    {project.link.label} @@ -79,6 +111,38 @@ export function Projects() { ))}

    + +
    +

    References GitHub (stack source)

    + +

    + + Voir plus sur GitHub + +

    +
    + +
    ); diff --git a/src/components/sections/ProjectsTimeline.tsx b/src/components/sections/ProjectsTimeline.tsx new file mode 100644 index 0000000..af94951 --- /dev/null +++ b/src/components/sections/ProjectsTimeline.tsx @@ -0,0 +1,113 @@ +import { motion } from 'motion/react'; +import { TRACK_EVENTS, trackAttrs } from '@/lib/tracking'; +import type { TrackEventName } from '@/lib/tracking'; + +type TimelineItem = { + year: string; + title: string; + category: string; + summary: string; + href?: string; + event?: TrackEventName; + destination?: string; + external?: boolean; +}; + +const timeline: TimelineItem[] = [ + { + year: '2010', + title: 'VJ Clearscreen', + category: 'Video live / scenographie', + summary: 'Performances video et experimentations de diffusion autour du langage ecran.' + }, + { + year: '2016', + title: 'Electron Fou', + category: 'Noise / creation sonore', + summary: 'R&D de textures noise et sorties en ligne sur plateformes audio.', + href: 'https://lelectron-fou.bandcamp.com/', + event: TRACK_EVENTS.outboundBandcampProject, + destination: 'bandcamp.com', + external: true + }, + { + year: '2021', + title: "L'electron rare", + category: 'Design produit / systemes', + summary: 'Conception de dispositifs, automation creative et methodes studio.', + href: 'https://fr.linkedin.com/in/electron-rare', + event: TRACK_EVENTS.outboundLinkedinProject, + destination: 'linkedin.com', + external: true + }, + { + year: '2026', + title: 'Open repos references', + category: 'Hardware/Firmware', + summary: 'References GitHub: ESP32, STM32, LED, energie batterie et systemes de controle.', + href: 'https://github.com/electron-rare/', + event: TRACK_EVENTS.outboundGithubProject, + destination: 'github.com', + external: true + }, + { + year: '2026', + title: 'Studio acquisition', + category: 'SEO / CRO / tracking', + summary: 'Pipeline mesuree: CTA, analytics, indexation et iteration continue.', + href: '#contact', + event: TRACK_EVENTS.ctaHeroContact, + destination: '#contact' + } +]; + +export function ProjectsTimeline() { + return ( +
    +
    +
    +
    + +

    + Chronologie orientee preuves: evolution video/noise, design systeme puis references open source. +

    + +
      + {timeline.map((item, index) => ( + +

      {item.year}

      +
      +

      {item.category}

      +

      {item.title}

      +

      {item.summary}

      + {item.href && item.event && item.destination && ( + + {item.external ? 'Ouvrir preuve' : 'Voir detail'} + + )} +
      +
      + ))} +
    +
    +
    + ); +} diff --git a/src/components/sections/SystemPipeline.tsx b/src/components/sections/SystemPipeline.tsx new file mode 100644 index 0000000..548fde2 --- /dev/null +++ b/src/components/sections/SystemPipeline.tsx @@ -0,0 +1,93 @@ +import { motion, useReducedMotion } from 'motion/react'; +import { TRACK_EVENTS, trackAttrs } from '@/lib/tracking'; + +type PipelineStep = { + label: string; + detail: string; + href: string; + event: (typeof TRACK_EVENTS)[keyof typeof TRACK_EVENTS]; + destination: string; +}; + +const steps: PipelineStep[] = [ + { + label: 'Audit terrain', + detail: 'Contexte, objectifs, contraintes et signaux critiques', + href: '#a-propos', + event: TRACK_EVENTS.ctaHeroProfile, + destination: '#a-propos' + }, + { + label: 'Schema bus', + detail: 'Architecture systeme, flux, interfaces et points de mesure', + href: '#projets', + event: TRACK_EVENTS.ctaHeroProjects, + destination: '#projets' + }, + { + label: 'Prototype runtime', + detail: 'Calibration des automatismes, boucles test et QA', + href: '#projets', + event: TRACK_EVENTS.ctaHeroProjects, + destination: '#projets' + }, + { + label: 'Activation mission', + detail: 'Mise en production, suivi conversion et optimisation continue', + href: '#contact', + event: TRACK_EVENTS.ctaHeroContact, + destination: '#contact' + } +]; + +export function SystemPipeline() { + const prefersReducedMotion = useReducedMotion(); + + return ( +
    +
    +
    +
    + +

    + Pipeline d'execution studio: chaque etape garde une logique operationnelle mesurable, du cadrage a + l'activation mission. +

    + +
    + process orienté preuve + automatisme calibré + conversion traçable +
    + +
      + {steps.map((step, index) => ( + + + + + {step.label} + {step.detail} + + + + ))} +
    +
    +
    + ); +} diff --git a/src/components/sections/TrustStrip.tsx b/src/components/sections/TrustStrip.tsx new file mode 100644 index 0000000..9f51f7d --- /dev/null +++ b/src/components/sections/TrustStrip.tsx @@ -0,0 +1,62 @@ +import { motion } from 'motion/react'; +import { CtaDualRail } from '@/components/ui/cta-dual-rail'; + +const proofItems = [ + { + label: 'Collaborations', + value: 'Studio / design / audiovisuel', + detail: 'Approche orientee systeme et livraison.' + }, + { + label: 'Projets actifs', + value: 'R&D electronique + UX conversion', + detail: 'Chaîne complete: idee, prototype, QA, publication.' + }, + { + label: 'Liens verifiables', + value: 'LinkedIn, Malt, Bandcamp, GitHub', + detail: 'References hardware/firmware consultables.' + } +]; + +export function TrustStrip() { + return ( +
    + +
    +
    + +

    + Preuves de credibilite avant contact: execution, references publiques et capacite d'iteration. +

    + +
    + {proofItems.map((item) => ( +
    +

    {item.label}

    +

    {item.value}

    +

    {item.detail}

    +
    + ))} +
    + +

    + Bloc preuves place avant contact pour reduire la friction de decision. +

    + + +
    +
    + ); +} diff --git a/src/components/ui/button.tsx b/src/components/ui/button.tsx index fd6150f..74cc1ad 100644 --- a/src/components/ui/button.tsx +++ b/src/components/ui/button.tsx @@ -4,14 +4,14 @@ import { cva, type VariantProps } from 'class-variance-authority'; import { cn } from '@/lib/utils'; const buttonVariants = cva( - 'inline-flex min-h-11 items-center justify-center rounded-xl px-4 py-2 text-sm font-semibold transition-transform duration-150 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-cyan-300 disabled:pointer-events-none disabled:opacity-50', + 'inline-flex min-h-11 items-center justify-center rounded-[0.7rem] border px-4 py-2 text-sm font-semibold tracking-[0.01em] transition-all duration-150 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[var(--electric)] disabled:pointer-events-none disabled:opacity-50', { variants: { variant: { primary: - 'bg-cyan-400 text-slate-950 shadow-[0_0_0_1px_rgba(255,255,255,0.08)_inset,0_8px_22px_rgba(53,220,255,0.26)] hover:-translate-y-0.5 hover:bg-cyan-300', + 'bg-[var(--electric)] text-[var(--bg)] shadow-[0_0_0_1px_rgba(255,255,255,0.08)_inset,0_8px_26px_rgba(8,247,255,0.33)] hover:-translate-y-0.5 hover:bg-[var(--electric-strong)]', secondary: - 'border border-fuchsia-300/35 bg-fuchsia-950/16 text-violet-100 shadow-[0_0_0_1px_rgba(255,255,255,0.04)_inset] hover:-translate-y-0.5 hover:border-fuchsia-300/55' + 'border-[color:var(--trace-cyan)] bg-[rgba(10,22,43,0.82)] text-[var(--text)] shadow-[0_0_0_1px_rgba(255,255,255,0.06)_inset,0_0_0_1px_rgba(8,247,255,0.12)_inset] hover:-translate-y-0.5 hover:border-[var(--electric-strong)]' }, size: { md: 'h-11', diff --git a/src/components/ui/card.tsx b/src/components/ui/card.tsx index 2ac3b86..7f2b9c5 100644 --- a/src/components/ui/card.tsx +++ b/src/components/ui/card.tsx @@ -5,7 +5,7 @@ export function Card({ className, ...props }: React.HTMLAttributes +

    {label}

    + + + ); +} diff --git a/src/layouts/BaseLayout.astro b/src/layouts/BaseLayout.astro index 0e788b3..882b0cc 100644 --- a/src/layouts/BaseLayout.astro +++ b/src/layouts/BaseLayout.astro @@ -31,13 +31,18 @@ const personJsonLd = JSON.stringify({ --- - + {title} + + + + + @@ -73,6 +78,7 @@ const personJsonLd = JSON.stringify({ })(window, document, "script", "dataLayer", gtmId); } + { @@ -109,5 +115,146 @@ const personJsonLd = JSON.stringify({ } })(); + + + + diff --git a/src/lib/site.ts b/src/lib/site.ts index 2992e6e..468de19 100644 --- a/src/lib/site.ts +++ b/src/lib/site.ts @@ -1,4 +1,6 @@ -export const SITE_URL = 'https://electron-rare.github.io/'; +const normalizeUrl = (value: string) => (value.endsWith('/') ? value : `${value}/`); + +export const SITE_URL = normalizeUrl(import.meta.env.PUBLIC_SITE_URL || 'https://electron-rare.github.io/'); export const SITE_META = { title: "Clément Saillant — L'électron rare", @@ -9,9 +11,14 @@ export const SITE_META = { twitterDescription: "Creation electronique, invention de systemes et design produit sous l'identite L'electron rare.", ogImagePath: 'assets/og-cover.jpg', - themeColor: '#0f0e17' + themeColor: '#f4eee3' } as const; export const SITE_OG_IMAGE_URL = `${SITE_URL}${SITE_META.ogImagePath}`; export const GTM_CONTAINER_ID_DEFAULT = 'GTM-5SLM67QF'; + +export const BRAND_ASSETS = { + markPath: 'assets/brand/logo-mark.png', + lockupPath: 'assets/brand/logo-lockup.png' +} as const; diff --git a/src/lib/tracking.ts b/src/lib/tracking.ts index f3a8211..df24d49 100644 --- a/src/lib/tracking.ts +++ b/src/lib/tracking.ts @@ -6,7 +6,9 @@ export const TRACK_EVENTS = { outboundLinkedinContact: 'outbound_linkedin_contact', outboundMaltContact: 'outbound_malt_contact', outboundBandcampProject: 'outbound_bandcamp_project', - outboundBandcampContact: 'outbound_bandcamp_contact' + outboundBandcampContact: 'outbound_bandcamp_contact', + outboundGithubProject: 'outbound_github_project', + outboundGithubContact: 'outbound_github_contact' } as const; export type TrackEventName = (typeof TRACK_EVENTS)[keyof typeof TRACK_EVENTS]; diff --git a/src/pages/index.astro b/src/pages/index.astro index 8adc001..7aa9f47 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -2,41 +2,155 @@ import BaseLayout from '@/layouts/BaseLayout.astro'; import '@/styles/global.css'; import { Hero } from '@/components/sections/Hero'; +import { IdentityLab } from '@/components/sections/IdentityLab'; import { About } from '@/components/sections/About'; import { Projects } from '@/components/sections/Projects'; +import { FlowDiagram } from '@/components/sections/FlowDiagram'; +import { SystemPipeline } from '@/components/sections/SystemPipeline'; +import { ProjectsTimeline } from '@/components/sections/ProjectsTimeline'; +import { LabNotes } from '@/components/sections/LabNotes'; +import { TrustStrip } from '@/components/sections/TrustStrip'; import { Contact } from '@/components/sections/Contact'; +import { TRACK_EVENTS, trackAttrs } from '@/lib/tracking'; --- -
    -
    - + -
    - - - - +
    +
    +
    + +
    +
    + +
    +
    + +
    +
    + +
    +
    + +
    +
    + +
    +
    + +
    +
    + +
    +
    + +
    +
    + +
    +
    + +
    +
    + +
    +
    + +
    +
    -