diff --git a/CLAUDE.md b/CLAUDE.md index 4d00c09..ffd8046 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -127,6 +127,10 @@ Upload screen includes hidden folder visibility instructions per OS (macOS: Cmd+ - `npm run build:tui` — esbuild bundle (runs automatically via `prepublishOnly`) - `npm run setup:command` — install /ccrewind slash command from local build - `"files": ["dist/"]` in package.json overrides .gitignore so dist/ is included in npm publish +- npm package: published as `ccrewind`, bin entry `ccrewind` → `dist/ccrewind-tui.mjs` + - `npm run build:tui` — esbuild bundle (runs automatically via `prepublishOnly`) + - `npm run setup:command` — install /ccrewind slash command from local build + - `"files": ["dist/"]` in package.json overrides .gitignore so dist/ is included in npm publish ### Project name normalisation (important) diff --git a/README.md b/README.md index 41bcf1b..b8f523a 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # Claude Code Rewind +![Claude standing on business](public/claude_standing_on_business.png) + > There's no way to see your Claude Code usage. We changed that. Your developer archetype. Your token costs. Your Claude ELO. Nobody else has touched this data. Find out where you actually stand. Upload your `~/.claude` folder. Get a personalised story of your usage. Find out your archetype. Get your Claude Elo. Everything runs in the browser - zero data leaves your machine. diff --git a/next.config.ts b/next.config.ts index cb651cd..fa67b35 100644 --- a/next.config.ts +++ b/next.config.ts @@ -1,5 +1,9 @@ import type { NextConfig } from "next"; -const nextConfig: NextConfig = {}; +const nextConfig: NextConfig = { + turbopack: { + root: __dirname, + }, +}; export default nextConfig; diff --git a/package-lock.json b/package-lock.json index 047c723..dcf5d9c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,34 +8,33 @@ "name": "ccrewind", "version": "1.0.0", "license": "ISC", - "dependencies": { + "bin": { + "ccrewind": "dist/ccrewind-tui.mjs" + }, + "devDependencies": { "@tailwindcss/postcss": "^4.2.2", + "@types/d3": "^7.4.3", + "@types/jest": "^30.0.0", "@types/node": "^25.5.0", "@types/react": "^19.2.14", "@types/react-dom": "^19.2.3", "d3": "^7.9.0", + "esbuild": "^0.28.0", + "eslint": "^9.39.4", + "eslint-config-next": "^16.2.1", "framer-motion": "^12.38.0", "html-to-image": "^1.11.13", "html2canvas": "^1.4.1", + "jest": "^30.3.0", + "jimp": "^1.6.0", "next": "^16.2.1", "postcss": "^8.5.8", + "prettier": "^3.8.1", "react": "^19.2.4", "react-dom": "^19.2.4", "tailwindcss": "^4.2.2", - "typescript": "^5.8.3" - }, - "bin": { - "ccrewind": "dist/ccrewind-tui.mjs" - }, - "devDependencies": { - "@types/d3": "^7.4.3", - "@types/jest": "^30.0.0", - "esbuild": "^0.28.0", - "eslint": "^9.39.4", - "eslint-config-next": "^16.2.1", - "jest": "^30.3.0", - "prettier": "^3.8.1", "ts-jest": "^29.4.6", + "typescript": "^5.8.3", "typescript-eslint": "^8.57.2" }, "engines": { @@ -46,6 +45,7 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "dev": true, "license": "MIT", "engines": { "node": ">=10" @@ -85,7 +85,6 @@ "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", @@ -575,6 +574,7 @@ "version": "1.9.1", "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.9.1.tgz", "integrity": "sha512-mukuNALVsoix/w1BJwFzwXBN/dHeejQtuVzcDsfOEsdpCumXb/E9j8w11h5S54tT1xhifGfbbSm/ICrObRb3KA==", + "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -586,6 +586,7 @@ "version": "1.9.1", "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.9.1.tgz", "integrity": "sha512-VYi5+ZVLhpgK4hQ0TAjiQiZ6ol0oe4mBx7mVv7IflsiEp0OWoVsp/+f9Vc1hOhE0TtkORVrI1GvzyreqpgWtkA==", + "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -596,6 +597,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.0.tgz", "integrity": "sha512-N10dEJNSsUx41Z6pZsXU8FjPjpBEplgH24sfkmITrBED1/U2Esum9F3lfLrMjKHHjmi557zQn7kR9R+XWXu5Rg==", + "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -1257,6 +1259,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz", "integrity": "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==", + "dev": true, "license": "MIT", "optional": true, "engines": { @@ -1270,6 +1273,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "Apache-2.0", "optional": true, "os": [ @@ -1292,6 +1296,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "Apache-2.0", "optional": true, "os": [ @@ -1314,6 +1319,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -1330,6 +1336,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -1346,6 +1353,7 @@ "cpu": [ "arm" ], + "dev": true, "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -1362,6 +1370,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -1378,6 +1387,7 @@ "cpu": [ "ppc64" ], + "dev": true, "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -1394,6 +1404,7 @@ "cpu": [ "riscv64" ], + "dev": true, "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -1410,6 +1421,7 @@ "cpu": [ "s390x" ], + "dev": true, "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -1426,6 +1438,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -1442,6 +1455,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -1458,6 +1472,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -1474,6 +1489,7 @@ "cpu": [ "arm" ], + "dev": true, "license": "Apache-2.0", "optional": true, "os": [ @@ -1496,6 +1512,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "Apache-2.0", "optional": true, "os": [ @@ -1518,6 +1535,7 @@ "cpu": [ "ppc64" ], + "dev": true, "license": "Apache-2.0", "optional": true, "os": [ @@ -1540,6 +1558,7 @@ "cpu": [ "riscv64" ], + "dev": true, "license": "Apache-2.0", "optional": true, "os": [ @@ -1562,6 +1581,7 @@ "cpu": [ "s390x" ], + "dev": true, "license": "Apache-2.0", "optional": true, "os": [ @@ -1584,6 +1604,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "Apache-2.0", "optional": true, "os": [ @@ -1606,6 +1627,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "Apache-2.0", "optional": true, "os": [ @@ -1628,6 +1650,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "Apache-2.0", "optional": true, "os": [ @@ -1650,6 +1673,7 @@ "cpu": [ "wasm32" ], + "dev": true, "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", "optional": true, "dependencies": { @@ -1669,6 +1693,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "Apache-2.0 AND LGPL-3.0-or-later", "optional": true, "os": [ @@ -1688,6 +1713,7 @@ "cpu": [ "ia32" ], + "dev": true, "license": "Apache-2.0 AND LGPL-3.0-or-later", "optional": true, "os": [ @@ -1707,6 +1733,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "Apache-2.0 AND LGPL-3.0-or-later", "optional": true, "os": [ @@ -2124,131 +2151,732 @@ } } }, - "node_modules/@jest/schemas": { - "version": "30.0.5", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.0.5.tgz", - "integrity": "sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA==", + "node_modules/@jest/schemas": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.0.5.tgz", + "integrity": "sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.34.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/snapshot-utils": { + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/snapshot-utils/-/snapshot-utils-30.3.0.tgz", + "integrity": "sha512-ORbRN9sf5PP82v3FXNSwmO1OTDR2vzR2YTaR+E3VkSBZ8zadQE6IqYdYEeFH1NIkeB2HIGdF02dapb6K0Mj05g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "30.3.0", + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "natural-compare": "^1.4.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/source-map": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-30.0.1.tgz", + "integrity": "sha512-MIRWMUUR3sdbP36oyNyhbThLHyJ2eEDClPCiHVbrYAe5g3CHRArIVpBw7cdSB5fr+ofSfIb2Tnsw8iEHL0PYQg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.25", + "callsites": "^3.1.0", + "graceful-fs": "^4.2.11" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/test-result": { + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-30.3.0.tgz", + "integrity": "sha512-e/52nJGuD74AKTSe0P4y5wFRlaXP0qmrS17rqOMHeSwm278VyNyXE3gFO/4DTGF9w+65ra3lo3VKj0LBrzmgdQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "30.3.0", + "@jest/types": "30.3.0", + "@types/istanbul-lib-coverage": "^2.0.6", + "collect-v8-coverage": "^1.0.2" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/test-sequencer": { + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-30.3.0.tgz", + "integrity": "sha512-dgbWy9b8QDlQeRZcv7LNF+/jFiiYHTKho1xirauZ7kVwY7avjFF6uTT0RqlgudB5OuIPagFdVtfFMosjVbk1eA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/test-result": "30.3.0", + "graceful-fs": "^4.2.11", + "jest-haste-map": "30.3.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/transform": { + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-30.3.0.tgz", + "integrity": "sha512-TLKY33fSLVd/lKB2YI1pH69ijyUblO/BQvCj566YvnwuzoTNr648iE0j22vRvVNk2HsPwByPxATg3MleS3gf5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.27.4", + "@jest/types": "30.3.0", + "@jridgewell/trace-mapping": "^0.3.25", + "babel-plugin-istanbul": "^7.0.1", + "chalk": "^4.1.2", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.11", + "jest-haste-map": "30.3.0", + "jest-regex-util": "30.0.1", + "jest-util": "30.3.0", + "pirates": "^4.0.7", + "slash": "^3.0.0", + "write-file-atomic": "^5.0.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/types": { + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.3.0.tgz", + "integrity": "sha512-JHm87k7bA33hpBngtU8h6UBub/fqqA9uXfw+21j5Hmk7ooPHlboRNxHq0JcMtC+n8VJGP1mcfnD3Mk+XKe1oSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/pattern": "30.0.1", + "@jest/schemas": "30.0.5", + "@types/istanbul-lib-coverage": "^2.0.6", + "@types/istanbul-reports": "^3.0.4", + "@types/node": "*", + "@types/yargs": "^17.0.33", + "chalk": "^4.1.2" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jimp/core": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/core/-/core-1.6.0.tgz", + "integrity": "sha512-EQQlKU3s9QfdJqiSrZWNTxBs3rKXgO2W+GxNXDtwchF3a4IqxDheFX1ti+Env9hdJXDiYLp2jTRjlxhPthsk8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jimp/file-ops": "1.6.0", + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0", + "await-to-js": "^3.0.0", + "exif-parser": "^0.1.12", + "file-type": "^16.0.0", + "mime": "3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/diff": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/diff/-/diff-1.6.0.tgz", + "integrity": "sha512-+yUAQ5gvRC5D1WHYxjBHZI7JBRusGGSLf8AmPRPCenTzh4PA+wZ1xv2+cYqQwTfQHU5tXYOhA0xDytfHUf1Zyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jimp/plugin-resize": "1.6.0", + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0", + "pixelmatch": "^5.3.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/file-ops": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/file-ops/-/file-ops-1.6.0.tgz", + "integrity": "sha512-Dx/bVDmgnRe1AlniRpCKrGRm5YvGmUwbDzt+MAkgmLGf+jvBT75hmMEZ003n9HQI/aPnm/YKnXjg/hOpzNCpHQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/js-bmp": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/js-bmp/-/js-bmp-1.6.0.tgz", + "integrity": "sha512-FU6Q5PC/e3yzLyBDXupR3SnL3htU7S3KEs4e6rjDP6gNEOXRFsWs6YD3hXuXd50jd8ummy+q2WSwuGkr8wi+Gw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jimp/core": "1.6.0", + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0", + "bmp-ts": "^1.0.9" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/js-gif": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/js-gif/-/js-gif-1.6.0.tgz", + "integrity": "sha512-N9CZPHOrJTsAUoWkWZstLPpwT5AwJ0wge+47+ix3++SdSL/H2QzyMqxbcDYNFe4MoI5MIhATfb0/dl/wmX221g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jimp/core": "1.6.0", + "@jimp/types": "1.6.0", + "gifwrap": "^0.10.1", + "omggif": "^1.0.10" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/js-jpeg": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/js-jpeg/-/js-jpeg-1.6.0.tgz", + "integrity": "sha512-6vgFDqeusblf5Pok6B2DUiMXplH8RhIKAryj1yn+007SIAQ0khM1Uptxmpku/0MfbClx2r7pnJv9gWpAEJdMVA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jimp/core": "1.6.0", + "@jimp/types": "1.6.0", + "jpeg-js": "^0.4.4" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/js-png": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/js-png/-/js-png-1.6.0.tgz", + "integrity": "sha512-AbQHScy3hDDgMRNfG0tPjL88AV6qKAILGReIa3ATpW5QFjBKpisvUaOqhzJ7Reic1oawx3Riyv152gaPfqsBVg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jimp/core": "1.6.0", + "@jimp/types": "1.6.0", + "pngjs": "^7.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/js-tiff": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/js-tiff/-/js-tiff-1.6.0.tgz", + "integrity": "sha512-zhReR8/7KO+adijj3h0ZQUOiun3mXUv79zYEAKvE0O+rP7EhgtKvWJOZfRzdZSNv0Pu1rKtgM72qgtwe2tFvyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jimp/core": "1.6.0", + "@jimp/types": "1.6.0", + "utif2": "^4.1.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-blit": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-blit/-/plugin-blit-1.6.0.tgz", + "integrity": "sha512-M+uRWl1csi7qilnSK8uxK4RJMSuVeBiO1AY0+7APnfUbQNZm6hCe0CCFv1Iyw1D/Dhb8ph8fQgm5mwM0eSxgVA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-blit/node_modules/zod": { + "version": "3.25.76", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/@jimp/plugin-blur": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-blur/-/plugin-blur-1.6.0.tgz", + "integrity": "sha512-zrM7iic1OTwUCb0g/rN5y+UnmdEsT3IfuCXCJJNs8SZzP0MkZ1eTvuwK9ZidCuMo4+J3xkzCidRwYXB5CyGZTw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jimp/core": "1.6.0", + "@jimp/utils": "1.6.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-circle": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-circle/-/plugin-circle-1.6.0.tgz", + "integrity": "sha512-xt1Gp+LtdMKAXfDp3HNaG30SPZW6AQ7dtAtTnoRKorRi+5yCJjKqXRgkewS5bvj8DEh87Ko1ydJfzqS3P2tdWw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jimp/types": "1.6.0", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-circle/node_modules/zod": { + "version": "3.25.76", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/@jimp/plugin-color": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-color/-/plugin-color-1.6.0.tgz", + "integrity": "sha512-J5q8IVCpkBsxIXM+45XOXTrsyfblyMZg3a9eAo0P7VPH4+CrvyNQwaYatbAIamSIN1YzxmO3DkIZXzRjFSz1SA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jimp/core": "1.6.0", + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0", + "tinycolor2": "^1.6.0", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-color/node_modules/zod": { + "version": "3.25.76", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/@jimp/plugin-contain": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-contain/-/plugin-contain-1.6.0.tgz", + "integrity": "sha512-oN/n+Vdq/Qg9bB4yOBOxtY9IPAtEfES8J1n9Ddx+XhGBYT1/QTU/JYkGaAkIGoPnyYvmLEDqMz2SGihqlpqfzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jimp/core": "1.6.0", + "@jimp/plugin-blit": "1.6.0", + "@jimp/plugin-resize": "1.6.0", + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-contain/node_modules/zod": { + "version": "3.25.76", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/@jimp/plugin-cover": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-cover/-/plugin-cover-1.6.0.tgz", + "integrity": "sha512-Iow0h6yqSC269YUJ8HC3Q/MpCi2V55sMlbkkTTx4zPvd8mWZlC0ykrNDeAy9IJegrQ7v5E99rJwmQu25lygKLA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jimp/core": "1.6.0", + "@jimp/plugin-crop": "1.6.0", + "@jimp/plugin-resize": "1.6.0", + "@jimp/types": "1.6.0", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-cover/node_modules/zod": { + "version": "3.25.76", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/@jimp/plugin-crop": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-crop/-/plugin-crop-1.6.0.tgz", + "integrity": "sha512-KqZkEhvs+21USdySCUDI+GFa393eDIzbi1smBqkUPTE+pRwSWMAf01D5OC3ZWB+xZsNla93BDS9iCkLHA8wang==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jimp/core": "1.6.0", + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-crop/node_modules/zod": { + "version": "3.25.76", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/@jimp/plugin-displace": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-displace/-/plugin-displace-1.6.0.tgz", + "integrity": "sha512-4Y10X9qwr5F+Bo5ME356XSACEF55485j5nGdiyJ9hYzjQP9nGgxNJaZ4SAOqpd+k5sFaIeD7SQ0Occ26uIng5Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-displace/node_modules/zod": { + "version": "3.25.76", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/@jimp/plugin-dither": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-dither/-/plugin-dither-1.6.0.tgz", + "integrity": "sha512-600d1RxY0pKwgyU0tgMahLNKsqEcxGdbgXadCiVCoGd6V6glyCvkNrnnwC0n5aJ56Htkj88PToSdF88tNVZEEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jimp/types": "1.6.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-fisheye": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-fisheye/-/plugin-fisheye-1.6.0.tgz", + "integrity": "sha512-E5QHKWSCBFtpgZarlmN3Q6+rTQxjirFqo44ohoTjzYVrDI6B6beXNnPIThJgPr0Y9GwfzgyarKvQuQuqCnnfbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-fisheye/node_modules/zod": { + "version": "3.25.76", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/@jimp/plugin-flip": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-flip/-/plugin-flip-1.6.0.tgz", + "integrity": "sha512-/+rJVDuBIVOgwoyVkBjUFHtP+wmW0r+r5OQ2GpatQofToPVbJw1DdYWXlwviSx7hvixTWLKVgRWQ5Dw862emDg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jimp/types": "1.6.0", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-flip/node_modules/zod": { + "version": "3.25.76", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/@jimp/plugin-hash": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-hash/-/plugin-hash-1.6.0.tgz", + "integrity": "sha512-wWzl0kTpDJgYVbZdajTf+4NBSKvmI3bRI8q6EH9CVeIHps9VWVsUvEyb7rpbcwVLWYuzDtP2R0lTT6WeBNQH9Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jimp/core": "1.6.0", + "@jimp/js-bmp": "1.6.0", + "@jimp/js-jpeg": "1.6.0", + "@jimp/js-png": "1.6.0", + "@jimp/js-tiff": "1.6.0", + "@jimp/plugin-color": "1.6.0", + "@jimp/plugin-resize": "1.6.0", + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0", + "any-base": "^1.1.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-mask": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-mask/-/plugin-mask-1.6.0.tgz", + "integrity": "sha512-Cwy7ExSJMZszvkad8NV8o/Z92X2kFUFM8mcDAhNVxU0Q6tA0op2UKRJY51eoK8r6eds/qak3FQkXakvNabdLnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jimp/types": "1.6.0", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-mask/node_modules/zod": { + "version": "3.25.76", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/@jimp/plugin-print": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-print/-/plugin-print-1.6.0.tgz", + "integrity": "sha512-zarTIJi8fjoGMSI/M3Xh5yY9T65p03XJmPsuNet19K/Q7mwRU6EV2pfj+28++2PV2NJ+htDF5uecAlnGyxFN2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jimp/core": "1.6.0", + "@jimp/js-jpeg": "1.6.0", + "@jimp/js-png": "1.6.0", + "@jimp/plugin-blit": "1.6.0", + "@jimp/types": "1.6.0", + "parse-bmfont-ascii": "^1.0.6", + "parse-bmfont-binary": "^1.0.6", + "parse-bmfont-xml": "^1.1.6", + "simple-xml-to-json": "^1.2.2", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-print/node_modules/zod": { + "version": "3.25.76", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/@jimp/plugin-quantize": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-quantize/-/plugin-quantize-1.6.0.tgz", + "integrity": "sha512-EmzZ/s9StYQwbpG6rUGBCisc3f64JIhSH+ncTJd+iFGtGo0YvSeMdAd+zqgiHpfZoOL54dNavZNjF4otK+mvlg==", + "dev": true, + "license": "MIT", + "dependencies": { + "image-q": "^4.0.0", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-quantize/node_modules/zod": { + "version": "3.25.76", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/@jimp/plugin-resize": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-resize/-/plugin-resize-1.6.0.tgz", + "integrity": "sha512-uSUD1mqXN9i1SGSz5ov3keRZ7S9L32/mAQG08wUwZiEi5FpbV0K8A8l1zkazAIZi9IJzLlTauRNU41Mi8IF9fA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jimp/core": "1.6.0", + "@jimp/types": "1.6.0", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-resize/node_modules/zod": { + "version": "3.25.76", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/@jimp/plugin-rotate": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-rotate/-/plugin-rotate-1.6.0.tgz", + "integrity": "sha512-JagdjBLnUZGSG4xjCLkIpQOZZ3Mjbg8aGCCi4G69qR+OjNpOeGI7N2EQlfK/WE8BEHOW5vdjSyglNqcYbQBWRw==", "dev": true, "license": "MIT", "dependencies": { - "@sinclair/typebox": "^0.34.0" + "@jimp/core": "1.6.0", + "@jimp/plugin-crop": "1.6.0", + "@jimp/plugin-resize": "1.6.0", + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0", + "zod": "^3.23.8" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=18" } }, - "node_modules/@jest/snapshot-utils": { - "version": "30.3.0", - "resolved": "https://registry.npmjs.org/@jest/snapshot-utils/-/snapshot-utils-30.3.0.tgz", - "integrity": "sha512-ORbRN9sf5PP82v3FXNSwmO1OTDR2vzR2YTaR+E3VkSBZ8zadQE6IqYdYEeFH1NIkeB2HIGdF02dapb6K0Mj05g==", + "node_modules/@jimp/plugin-rotate/node_modules/zod": { + "version": "3.25.76", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", "dev": true, "license": "MIT", - "dependencies": { - "@jest/types": "30.3.0", - "chalk": "^4.1.2", - "graceful-fs": "^4.2.11", - "natural-compare": "^1.4.0" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "funding": { + "url": "https://github.com/sponsors/colinhacks" } }, - "node_modules/@jest/source-map": { - "version": "30.0.1", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-30.0.1.tgz", - "integrity": "sha512-MIRWMUUR3sdbP36oyNyhbThLHyJ2eEDClPCiHVbrYAe5g3CHRArIVpBw7cdSB5fr+ofSfIb2Tnsw8iEHL0PYQg==", + "node_modules/@jimp/plugin-threshold": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-threshold/-/plugin-threshold-1.6.0.tgz", + "integrity": "sha512-M59m5dzLoHOVWdM41O8z9SyySzcDn43xHseOH0HavjsfQsT56GGCC4QzU1banJidbUrePhzoEdS42uFE8Fei8w==", "dev": true, "license": "MIT", "dependencies": { - "@jridgewell/trace-mapping": "^0.3.25", - "callsites": "^3.1.0", - "graceful-fs": "^4.2.11" + "@jimp/core": "1.6.0", + "@jimp/plugin-color": "1.6.0", + "@jimp/plugin-hash": "1.6.0", + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0", + "zod": "^3.23.8" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=18" } }, - "node_modules/@jest/test-result": { - "version": "30.3.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-30.3.0.tgz", - "integrity": "sha512-e/52nJGuD74AKTSe0P4y5wFRlaXP0qmrS17rqOMHeSwm278VyNyXE3gFO/4DTGF9w+65ra3lo3VKj0LBrzmgdQ==", + "node_modules/@jimp/plugin-threshold/node_modules/zod": { + "version": "3.25.76", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", "dev": true, "license": "MIT", - "dependencies": { - "@jest/console": "30.3.0", - "@jest/types": "30.3.0", - "@types/istanbul-lib-coverage": "^2.0.6", - "collect-v8-coverage": "^1.0.2" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "funding": { + "url": "https://github.com/sponsors/colinhacks" } }, - "node_modules/@jest/test-sequencer": { - "version": "30.3.0", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-30.3.0.tgz", - "integrity": "sha512-dgbWy9b8QDlQeRZcv7LNF+/jFiiYHTKho1xirauZ7kVwY7avjFF6uTT0RqlgudB5OuIPagFdVtfFMosjVbk1eA==", + "node_modules/@jimp/types": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/types/-/types-1.6.0.tgz", + "integrity": "sha512-7UfRsiKo5GZTAATxm2qQ7jqmUXP0DxTArztllTcYdyw6Xi5oT4RaoXynVtCD4UyLK5gJgkZJcwonoijrhYFKfg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/test-result": "30.3.0", - "graceful-fs": "^4.2.11", - "jest-haste-map": "30.3.0", - "slash": "^3.0.0" + "zod": "^3.23.8" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=18" } }, - "node_modules/@jest/transform": { - "version": "30.3.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-30.3.0.tgz", - "integrity": "sha512-TLKY33fSLVd/lKB2YI1pH69ijyUblO/BQvCj566YvnwuzoTNr648iE0j22vRvVNk2HsPwByPxATg3MleS3gf5A==", + "node_modules/@jimp/types/node_modules/zod": { + "version": "3.25.76", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", "dev": true, "license": "MIT", - "dependencies": { - "@babel/core": "^7.27.4", - "@jest/types": "30.3.0", - "@jridgewell/trace-mapping": "^0.3.25", - "babel-plugin-istanbul": "^7.0.1", - "chalk": "^4.1.2", - "convert-source-map": "^2.0.0", - "fast-json-stable-stringify": "^2.1.0", - "graceful-fs": "^4.2.11", - "jest-haste-map": "30.3.0", - "jest-regex-util": "30.0.1", - "jest-util": "30.3.0", - "pirates": "^4.0.7", - "slash": "^3.0.0", - "write-file-atomic": "^5.0.1" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "funding": { + "url": "https://github.com/sponsors/colinhacks" } }, - "node_modules/@jest/types": { - "version": "30.3.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.3.0.tgz", - "integrity": "sha512-JHm87k7bA33hpBngtU8h6UBub/fqqA9uXfw+21j5Hmk7ooPHlboRNxHq0JcMtC+n8VJGP1mcfnD3Mk+XKe1oSw==", + "node_modules/@jimp/utils": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-1.6.0.tgz", + "integrity": "sha512-gqFTGEosKbOkYF/WFj26jMHOI5OH2jeP1MmC/zbK6BF6VJBf8rIC5898dPfSzZEbSA0wbbV5slbntWVc5PKLFA==", "dev": true, "license": "MIT", "dependencies": { - "@jest/pattern": "30.0.1", - "@jest/schemas": "30.0.5", - "@types/istanbul-lib-coverage": "^2.0.6", - "@types/istanbul-reports": "^3.0.4", - "@types/node": "*", - "@types/yargs": "^17.0.33", - "chalk": "^4.1.2" + "@jimp/types": "1.6.0", + "tinycolor2": "^1.6.0" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "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", @@ -2259,6 +2887,7 @@ "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", @@ -2269,6 +2898,7 @@ "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" @@ -2278,12 +2908,14 @@ "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", @@ -2294,6 +2926,7 @@ "version": "0.2.12", "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz", "integrity": "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==", + "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -2306,6 +2939,7 @@ "version": "16.2.1", "resolved": "https://registry.npmjs.org/@next/env/-/env-16.2.1.tgz", "integrity": "sha512-n8P/HCkIWW+gVal2Z8XqXJ6aB3J0tuM29OcHpCsobWlChH/SITBs1DFBk/HajgrwDkqqBXPbuUuzgDvUekREPg==", + "dev": true, "license": "MIT" }, "node_modules/@next/eslint-plugin-next": { @@ -2325,6 +2959,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2341,6 +2976,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2357,6 +2993,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2373,6 +3010,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2389,6 +3027,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2405,6 +3044,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2421,6 +3061,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2437,6 +3078,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2556,6 +3198,7 @@ "version": "0.5.15", "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz", "integrity": "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==", + "dev": true, "license": "Apache-2.0", "dependencies": { "tslib": "^2.8.0" @@ -2565,6 +3208,7 @@ "version": "4.2.2", "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.2.2.tgz", "integrity": "sha512-pXS+wJ2gZpVXqFaUEjojq7jzMpTGf8rU6ipJz5ovJV6PUGmlJ+jvIwGrzdHdQ80Sg+wmQxUFuoW1UAAwHNEdFA==", + "dev": true, "license": "MIT", "dependencies": { "@jridgewell/remapping": "^2.3.5", @@ -2580,6 +3224,7 @@ "version": "4.2.2", "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.2.2.tgz", "integrity": "sha512-qEUA07+E5kehxYp9BVMpq9E8vnJuBHfJEC0vPC5e7iL/hw7HR61aDKoVoKzrG+QKp56vhNZe4qwkRmMC0zDLvg==", + "dev": true, "license": "MIT", "engines": { "node": ">= 20" @@ -2606,6 +3251,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2622,6 +3268,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2638,6 +3285,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2654,6 +3302,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2670,6 +3319,7 @@ "cpu": [ "arm" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2686,6 +3336,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2702,6 +3353,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2718,6 +3370,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2734,6 +3387,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2758,6 +3412,7 @@ "cpu": [ "wasm32" ], + "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -2779,6 +3434,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2795,6 +3451,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2808,6 +3465,7 @@ "version": "4.2.2", "resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.2.2.tgz", "integrity": "sha512-n4goKQbW8RVXIbNKRB/45LzyUqN451deQK0nzIeauVEqjlI49slUlgKYJM2QyUzap/PcpnS7kzSUmPb1sCRvYQ==", + "dev": true, "license": "MIT", "dependencies": { "@alloc/quick-lru": "^5.2.0", @@ -2817,10 +3475,18 @@ "tailwindcss": "4.2.2" } }, + "node_modules/@tokenizer/token": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz", + "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==", + "dev": true, + "license": "MIT" + }, "node_modules/@tybys/wasm-util": { "version": "0.10.1", "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", "integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==", + "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -3226,6 +3892,7 @@ "version": "25.5.0", "resolved": "https://registry.npmjs.org/@types/node/-/node-25.5.0.tgz", "integrity": "sha512-jp2P3tQMSxWugkCUKLRPVUpGaL5MVFwF8RDuSRztfwgN1wmqJeMSbKlnEtQqU8UrhTmzEmZdu2I6v2dpp7XIxw==", + "dev": true, "license": "MIT", "dependencies": { "undici-types": "~7.18.0" @@ -3235,8 +3902,8 @@ "version": "19.2.14", "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz", "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==", + "dev": true, "license": "MIT", - "peer": true, "dependencies": { "csstype": "^3.2.2" } @@ -3245,6 +3912,7 @@ "version": "19.2.3", "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz", "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", + "dev": true, "license": "MIT", "peerDependencies": { "@types/react": "^19.2.0" @@ -3319,7 +3987,6 @@ "integrity": "sha512-30ScMRHIAD33JJQkgfGW1t8CURZtjc2JpTrq5n2HFhOefbAhb7ucc7xJwdWcrEtqUIYJ73Nybpsggii6GtAHjA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.57.2", "@typescript-eslint/types": "8.57.2", @@ -3833,13 +4500,25 @@ "win32" ] }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "dev": true, + "license": "MIT", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, "node_modules/acorn": { "version": "8.16.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", "dev": true, "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -3919,6 +4598,13 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/any-base": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/any-base/-/any-base-1.1.0.tgz", + "integrity": "sha512-uMgjozySS8adZZYePpaWs8cxB9/kdzmpX6SgJZ+wbz1K5eYk5QMYDVJaZKhxyIHUdnnJkfR7SVgStgH7LkGUyg==", + "dev": true, + "license": "MIT" + }, "node_modules/anymatch": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", @@ -4143,6 +4829,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/await-to-js": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/await-to-js/-/await-to-js-3.0.0.tgz", + "integrity": "sha512-zJAaP9zxTcvTHRlejau3ZOY4V7SRpiByf3/dxx2uyKxxor19tpmpV2QRsTKikckwhaPmr2dVpxxMr7jOCYVp5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/axe-core": { "version": "4.11.1", "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.11.1.tgz", @@ -4273,15 +4969,38 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", "integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==", + "dev": true, "license": "MIT", "engines": { "node": ">= 0.6.0" } }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, "node_modules/baseline-browser-mapping": { "version": "2.10.11", "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.11.tgz", "integrity": "sha512-DAKrHphkJyiGuau/cFieRYhcTFeK/lBuD++C7cZ6KZHbMhBrisoi+EvhQ5RZrIfV5qwsW8kgQ07JIC+MDJRAhg==", + "dev": true, "license": "Apache-2.0", "bin": { "baseline-browser-mapping": "dist/cli.cjs" @@ -4290,6 +5009,13 @@ "node": ">=6.0.0" } }, + "node_modules/bmp-ts": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/bmp-ts/-/bmp-ts-1.0.9.tgz", + "integrity": "sha512-cTEHk2jLrPyi+12M3dhpEbnnPOsaZuq7C45ylbbQIiWgDFZq4UVYPEY5mlqjvsj/6gJv9qX5sa+ebDzLXT28Vw==", + "dev": true, + "license": "MIT" + }, "node_modules/brace-expansion": { "version": "1.1.13", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.13.tgz", @@ -4334,7 +5060,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", @@ -4372,6 +5097,31 @@ "node-int64": "^0.4.0" } }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", @@ -4453,6 +5203,7 @@ "version": "1.0.30001781", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001781.tgz", "integrity": "sha512-RdwNCyMsNBftLjW6w01z8bKEvT6e/5tpPVEgtn22TiLGlstHOVecsX2KHFkD5e/vRnIE4EGzpuIODb3mtswtkw==", + "dev": true, "funding": [ { "type": "opencollective", @@ -4523,6 +5274,7 @@ "version": "0.0.1", "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", + "dev": true, "license": "MIT" }, "node_modules/cliui": { @@ -4645,6 +5397,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "dev": true, "license": "MIT", "engines": { "node": ">= 10" @@ -4683,6 +5436,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/css-line-break/-/css-line-break-2.1.0.tgz", "integrity": "sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==", + "dev": true, "license": "MIT", "dependencies": { "utrie": "^1.0.2" @@ -4692,12 +5446,14 @@ "version": "3.2.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "dev": true, "license": "MIT" }, "node_modules/d3": { "version": "7.9.0", "resolved": "https://registry.npmjs.org/d3/-/d3-7.9.0.tgz", "integrity": "sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA==", + "dev": true, "license": "ISC", "dependencies": { "d3-array": "3", @@ -4739,6 +5495,7 @@ "version": "3.2.4", "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", + "dev": true, "license": "ISC", "dependencies": { "internmap": "1 - 2" @@ -4751,6 +5508,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-3.0.0.tgz", "integrity": "sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==", + "dev": true, "license": "ISC", "engines": { "node": ">=12" @@ -4760,6 +5518,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-3.0.0.tgz", "integrity": "sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==", + "dev": true, "license": "ISC", "dependencies": { "d3-dispatch": "1 - 3", @@ -4776,6 +5535,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-3.0.1.tgz", "integrity": "sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==", + "dev": true, "license": "ISC", "dependencies": { "d3-path": "1 - 3" @@ -4788,6 +5548,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", + "dev": true, "license": "ISC", "engines": { "node": ">=12" @@ -4797,6 +5558,7 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-4.0.2.tgz", "integrity": "sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==", + "dev": true, "license": "ISC", "dependencies": { "d3-array": "^3.2.0" @@ -4809,6 +5571,7 @@ "version": "6.0.4", "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-6.0.4.tgz", "integrity": "sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==", + "dev": true, "license": "ISC", "dependencies": { "delaunator": "5" @@ -4821,6 +5584,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==", + "dev": true, "license": "ISC", "engines": { "node": ">=12" @@ -4830,6 +5594,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz", "integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==", + "dev": true, "license": "ISC", "dependencies": { "d3-dispatch": "1 - 3", @@ -4843,6 +5608,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-3.0.1.tgz", "integrity": "sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==", + "dev": true, "license": "ISC", "dependencies": { "commander": "7", @@ -4868,6 +5634,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", + "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=12" @@ -4877,6 +5644,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-3.0.1.tgz", "integrity": "sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==", + "dev": true, "license": "ISC", "dependencies": { "d3-dsv": "1 - 3" @@ -4889,6 +5657,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-3.0.0.tgz", "integrity": "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==", + "dev": true, "license": "ISC", "dependencies": { "d3-dispatch": "1 - 3", @@ -4903,6 +5672,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.2.tgz", "integrity": "sha512-AJDdYOdnyRDV5b6ArilzCPPwc1ejkHcoyFarqlPqT7zRYjhavcT3uSrqcMvsgh2CgoPbK3RCwyHaVyxYcP2Arg==", + "dev": true, "license": "ISC", "engines": { "node": ">=12" @@ -4912,6 +5682,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.1.1.tgz", "integrity": "sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q==", + "dev": true, "license": "ISC", "dependencies": { "d3-array": "2.5.0 - 3" @@ -4924,6 +5695,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz", "integrity": "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==", + "dev": true, "license": "ISC", "engines": { "node": ">=12" @@ -4933,6 +5705,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", + "dev": true, "license": "ISC", "dependencies": { "d3-color": "1 - 3" @@ -4945,6 +5718,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", + "dev": true, "license": "ISC", "engines": { "node": ">=12" @@ -4954,6 +5728,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-3.0.1.tgz", "integrity": "sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==", + "dev": true, "license": "ISC", "engines": { "node": ">=12" @@ -4963,6 +5738,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz", "integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==", + "dev": true, "license": "ISC", "engines": { "node": ">=12" @@ -4972,6 +5748,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-3.0.1.tgz", "integrity": "sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==", + "dev": true, "license": "ISC", "engines": { "node": ">=12" @@ -4981,6 +5758,7 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", + "dev": true, "license": "ISC", "dependencies": { "d3-array": "2.10.0 - 3", @@ -4997,6 +5775,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz", "integrity": "sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==", + "dev": true, "license": "ISC", "dependencies": { "d3-color": "1 - 3", @@ -5010,8 +5789,8 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", + "dev": true, "license": "ISC", - "peer": true, "engines": { "node": ">=12" } @@ -5020,6 +5799,7 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", + "dev": true, "license": "ISC", "dependencies": { "d3-path": "^3.1.0" @@ -5032,6 +5812,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", + "dev": true, "license": "ISC", "dependencies": { "d3-array": "2 - 3" @@ -5044,6 +5825,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", + "dev": true, "license": "ISC", "dependencies": { "d3-time": "1 - 3" @@ -5056,6 +5838,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", + "dev": true, "license": "ISC", "engines": { "node": ">=12" @@ -5065,6 +5848,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz", "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==", + "dev": true, "license": "ISC", "dependencies": { "d3-color": "1 - 3", @@ -5084,6 +5868,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz", "integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==", + "dev": true, "license": "ISC", "dependencies": { "d3-dispatch": "1 - 3", @@ -5247,6 +6032,7 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.1.0.tgz", "integrity": "sha512-AGrQ4QSgssa1NGmWmLPqN5NY2KajF5MqxetNEO+o0n3ZwZZeTmt7bBnvzHWrmkZFxGgr4HdyFgelzgi06otLuQ==", + "dev": true, "license": "ISC", "dependencies": { "robust-predicates": "^3.0.2" @@ -5256,6 +6042,7 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "dev": true, "license": "Apache-2.0", "engines": { "node": ">=8" @@ -5337,6 +6124,7 @@ "version": "5.20.1", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.20.1.tgz", "integrity": "sha512-Qohcme7V1inbAfvjItgw0EaxVX5q2rdVEZHRBrEQdRZTssLDGsL8Lwrznl8oQ/6kuTJONLaDcGjkNP247XEhcA==", + "dev": true, "license": "MIT", "dependencies": { "graceful-fs": "^4.2.4", @@ -5605,7 +6393,6 @@ "integrity": "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -5778,7 +6565,6 @@ "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@rtsao/scc": "^1.1.0", "array-includes": "^3.1.9", @@ -6052,6 +6838,26 @@ "node": ">=0.10.0" } }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.x" + } + }, "node_modules/execa": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", @@ -6083,6 +6889,12 @@ "dev": true, "license": "ISC" }, + "node_modules/exif-parser": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/exif-parser/-/exif-parser-0.1.12.tgz", + "integrity": "sha512-c2bQfLNbMzLPmzQuOr8fy0csy84WmwnER81W88DzTp9CYNPJ6yzOj2EZAh9pywYpqHnshVLHQJ8WzldAyfY+Iw==", + "dev": true + }, "node_modules/exit-x": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/exit-x/-/exit-x-0.2.2.tgz", @@ -6195,6 +7007,24 @@ "node": ">=16.0.0" } }, + "node_modules/file-type": { + "version": "16.5.4", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-16.5.4.tgz", + "integrity": "sha512-/yFHK0aGjFEgDJjEKP0pWCplsPFPhwyfwevf/pVxiN0tmE4L9LmwWxWukdJSHdoCli4VgQLehjJtwQBnqmsKcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "readable-web-to-node-stream": "^3.0.0", + "strtok3": "^6.2.4", + "token-types": "^4.1.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/file-type?sponsor=1" + } + }, "node_modules/fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", @@ -6283,6 +7113,7 @@ "version": "12.38.0", "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.38.0.tgz", "integrity": "sha512-rFYkY/pigbcswl1XQSb7q424kSTQ8q6eAC+YUsSKooHQYuLdzdHjrt6uxUC+PRAO++q5IS7+TamgIw1AphxR+g==", + "dev": true, "license": "MIT", "dependencies": { "motion-dom": "^12.38.0", @@ -6492,6 +7323,17 @@ "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" } }, + "node_modules/gifwrap": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/gifwrap/-/gifwrap-0.10.1.tgz", + "integrity": "sha512-2760b1vpJHNmLzZ/ubTtNnEx5WApN/PYWJvXvgS+tL1egTTthayFYIQQNi136FLEDcN/IyEY2EcGpIITD6eYUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "image-q": "^4.0.0", + "omggif": "^1.0.10" + } + }, "node_modules/glob": { "version": "10.5.0", "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", @@ -6600,6 +7442,7 @@ "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, "license": "ISC" }, "node_modules/handlebars": { @@ -6746,12 +7589,14 @@ "version": "1.11.13", "resolved": "https://registry.npmjs.org/html-to-image/-/html-to-image-1.11.13.tgz", "integrity": "sha512-cuOPoI7WApyhBElTTb9oqsawRvZ0rHhaHwghRLlTuffoD1B2aDemlCruLeZrUIIdvG7gs9xeELEPm6PhuASqrg==", + "dev": true, "license": "MIT" }, "node_modules/html2canvas": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/html2canvas/-/html2canvas-1.4.1.tgz", "integrity": "sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==", + "dev": true, "license": "MIT", "dependencies": { "css-line-break": "^2.1.0", @@ -6775,6 +7620,7 @@ "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" @@ -6783,6 +7629,27 @@ "node": ">=0.10.0" } }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, "node_modules/ignore": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", @@ -6793,6 +7660,23 @@ "node": ">= 4" } }, + "node_modules/image-q": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/image-q/-/image-q-4.0.0.tgz", + "integrity": "sha512-PfJGVgIfKQJuq3s0tTDOKtztksibuUEbJQIYT3by6wctQo+Rdlh7ef4evJ5NCdxY4CfMbvFkocEwbl4BF8RlJw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "16.9.1" + } + }, + "node_modules/image-q/node_modules/@types/node": { + "version": "16.9.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.9.1.tgz", + "integrity": "sha512-QpLcX9ZSsq3YYUUnD3nFDY8H7wctAhQj/TFKL8Ya8v5fMm3CFXxo8zStsLAl780ltoYoo1WvKUVGBQK+1ifr7g==", + "dev": true, + "license": "MIT" + }, "node_modules/import-fresh": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", @@ -6878,6 +7762,7 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", + "dev": true, "license": "ISC", "engines": { "node": ">=12" @@ -7450,7 +8335,6 @@ "integrity": "sha512-AkXIIFcaazymvey2i/+F94XRnM6TsVLZDhBMLsd1Sf/W0wzsvvpjeyUrCZD6HGG4SDYPgDJDBKeiJTBb10WzMg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@jest/core": "30.3.0", "@jest/types": "30.3.0", @@ -8073,15 +8957,62 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, + "node_modules/jimp": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/jimp/-/jimp-1.6.0.tgz", + "integrity": "sha512-YcwCHw1kiqEeI5xRpDlPPBGL2EOpBKLwO4yIBJcXWHPj5PnA5urGq0jbyhM5KoNpypQ6VboSoxc9D8HyfvngSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jimp/core": "1.6.0", + "@jimp/diff": "1.6.0", + "@jimp/js-bmp": "1.6.0", + "@jimp/js-gif": "1.6.0", + "@jimp/js-jpeg": "1.6.0", + "@jimp/js-png": "1.6.0", + "@jimp/js-tiff": "1.6.0", + "@jimp/plugin-blit": "1.6.0", + "@jimp/plugin-blur": "1.6.0", + "@jimp/plugin-circle": "1.6.0", + "@jimp/plugin-color": "1.6.0", + "@jimp/plugin-contain": "1.6.0", + "@jimp/plugin-cover": "1.6.0", + "@jimp/plugin-crop": "1.6.0", + "@jimp/plugin-displace": "1.6.0", + "@jimp/plugin-dither": "1.6.0", + "@jimp/plugin-fisheye": "1.6.0", + "@jimp/plugin-flip": "1.6.0", + "@jimp/plugin-hash": "1.6.0", + "@jimp/plugin-mask": "1.6.0", + "@jimp/plugin-print": "1.6.0", + "@jimp/plugin-quantize": "1.6.0", + "@jimp/plugin-resize": "1.6.0", + "@jimp/plugin-rotate": "1.6.0", + "@jimp/plugin-threshold": "1.6.0", + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/jiti": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", + "dev": true, "license": "MIT", "bin": { "jiti": "lib/jiti-cli.mjs" } }, + "node_modules/jpeg-js": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.4.tgz", + "integrity": "sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==", + "dev": true, + "license": "BSD-3-Clause" + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -8230,6 +9161,7 @@ "version": "1.32.0", "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", + "dev": true, "license": "MPL-2.0", "dependencies": { "detect-libc": "^2.0.3" @@ -8262,6 +9194,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MPL-2.0", "optional": true, "os": [ @@ -8282,6 +9215,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MPL-2.0", "optional": true, "os": [ @@ -8302,6 +9236,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MPL-2.0", "optional": true, "os": [ @@ -8322,6 +9257,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MPL-2.0", "optional": true, "os": [ @@ -8342,6 +9278,7 @@ "cpu": [ "arm" ], + "dev": true, "license": "MPL-2.0", "optional": true, "os": [ @@ -8362,6 +9299,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MPL-2.0", "optional": true, "os": [ @@ -8382,6 +9320,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MPL-2.0", "optional": true, "os": [ @@ -8402,6 +9341,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MPL-2.0", "optional": true, "os": [ @@ -8422,6 +9362,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MPL-2.0", "optional": true, "os": [ @@ -8442,6 +9383,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MPL-2.0", "optional": true, "os": [ @@ -8462,6 +9404,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MPL-2.0", "optional": true, "os": [ @@ -8539,6 +9482,7 @@ "version": "0.30.21", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dev": true, "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" @@ -8618,6 +9562,19 @@ "node": ">=8.6" } }, + "node_modules/mime": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", + "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", + "dev": true, + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/mimic-fn": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", @@ -8665,6 +9622,7 @@ "version": "12.38.0", "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.38.0.tgz", "integrity": "sha512-pdkHLD8QYRp8VfiNLb8xIBJis1byQ9gPT3Jnh2jqfFtAsWUA3dEepDlsWe/xMpO8McV+VdpKVcp+E+TGJEtOoA==", + "dev": true, "license": "MIT", "dependencies": { "motion-utils": "^12.36.0" @@ -8674,6 +9632,7 @@ "version": "12.36.0", "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.36.0.tgz", "integrity": "sha512-eHWisygbiwVvf6PZ1vhaHCLamvkSbPIeAYxWUuL3a2PD/TROgE7FvfHWTIH4vMl798QLfMw15nRqIaRDXTlYRg==", + "dev": true, "license": "MIT" }, "node_modules/ms": { @@ -8687,6 +9646,7 @@ "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", @@ -8735,6 +9695,7 @@ "version": "16.2.1", "resolved": "https://registry.npmjs.org/next/-/next-16.2.1.tgz", "integrity": "sha512-VaChzNL7o9rbfdt60HUj8tev4m6d7iC1igAy157526+cJlXOQu5LzsBXNT+xaJnTP/k+utSX5vMv7m0G+zKH+Q==", + "dev": true, "license": "MIT", "dependencies": { "@next/env": "16.2.1", @@ -8788,6 +9749,7 @@ "version": "8.4.31", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", + "dev": true, "funding": [ { "type": "opencollective", @@ -9001,6 +9963,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/omggif": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/omggif/-/omggif-1.0.10.tgz", + "integrity": "sha512-LMJTtvgc/nugXj0Vcrrs68Mn2D1r0zf630VNtqtpI1FEO7e+O9FP4gqs9AcnBaSEeoHIPm28u6qgPR0oyEpGSw==", + "dev": true, + "license": "MIT" + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -9112,6 +10081,13 @@ "dev": true, "license": "BlueOak-1.0.0" }, + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "dev": true, + "license": "(MIT AND Zlib)" + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -9125,6 +10101,31 @@ "node": ">=6" } }, + "node_modules/parse-bmfont-ascii": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/parse-bmfont-ascii/-/parse-bmfont-ascii-1.0.6.tgz", + "integrity": "sha512-U4RrVsUFCleIOBsIGYOMKjn9PavsGOXxbvYGtMOEfnId0SVNsgehXh1DxUdVPLoxd5mvcEtvmKs2Mmf0Mpa1ZA==", + "dev": true, + "license": "MIT" + }, + "node_modules/parse-bmfont-binary": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/parse-bmfont-binary/-/parse-bmfont-binary-1.0.6.tgz", + "integrity": "sha512-GxmsRea0wdGdYthjuUeWTMWPqm2+FAd4GI8vCvhgJsFnoGhTrLhXDDupwTo7rXVAgaLIGoVHDZS9p/5XbSqeWA==", + "dev": true, + "license": "MIT" + }, + "node_modules/parse-bmfont-xml": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/parse-bmfont-xml/-/parse-bmfont-xml-1.1.6.tgz", + "integrity": "sha512-0cEliVMZEhrFDwMh4SxIyVJpqYoOWDJ9P895tFuS+XuNzI5UBmBk5U5O4KuJdTnZpSBI4LFA2+ZiJaiwfSwlMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "xml-parse-from-string": "^1.0.0", + "xml2js": "^0.5.0" + } + }, "node_modules/parse-json": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", @@ -9205,10 +10206,25 @@ "dev": true, "license": "ISC" }, + "node_modules/peek-readable": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-4.1.0.tgz", + "integrity": "sha512-ZI3LnwUv5nOGbQzD9c2iDG6toheuXSZP5esSHBjopsXH4dg19soufvpUGA3uohi5anFtGb2lhAVdHzH6R/Evvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, "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": { @@ -9234,6 +10250,29 @@ "node": ">= 6" } }, + "node_modules/pixelmatch": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/pixelmatch/-/pixelmatch-5.3.0.tgz", + "integrity": "sha512-o8mkY4E/+LNUf6LzX96ht6k6CEDi65k9G2rjMtBe9Oo+VPKSvl+0GKHuH/AlG+GA5LPG/i5hrekkxUc3s2HU+Q==", + "dev": true, + "license": "ISC", + "dependencies": { + "pngjs": "^6.0.0" + }, + "bin": { + "pixelmatch": "bin/pixelmatch" + } + }, + "node_modules/pixelmatch/node_modules/pngjs": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-6.0.0.tgz", + "integrity": "sha512-TRzzuFRRmEoSW/p1KVAmiOgPco2Irlah+bGFCeNfJXxxYGwSw7YwAOAcd7X28K/m5bjBWKsC29KyoMfHbypayg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.13.0" + } + }, "node_modules/pkg-dir": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", @@ -9303,6 +10342,16 @@ "node": ">=8" } }, + "node_modules/pngjs": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-7.0.0.tgz", + "integrity": "sha512-LKWqWJRhstyYo9pGvgor/ivk2w94eSjE3RGVuzLGlr3NmD8bf7RcYGze1mNdEHRP6TRP6rMuDHk5t44hnTRyow==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.19.0" + } + }, "node_modules/possible-typed-array-names": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", @@ -9317,6 +10366,7 @@ "version": "8.5.8", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.8.tgz", "integrity": "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==", + "dev": true, "funding": [ { "type": "opencollective", @@ -9402,6 +10452,16 @@ "dev": true, "license": "MIT" }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6.0" + } + }, "node_modules/prop-types": { "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", @@ -9466,8 +10526,8 @@ "version": "19.2.4", "resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz", "integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==", + "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=0.10.0" } @@ -9476,8 +10536,8 @@ "version": "19.2.4", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.4.tgz", "integrity": "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==", + "dev": true, "license": "MIT", - "peer": true, "dependencies": { "scheduler": "^0.27.0" }, @@ -9492,6 +10552,40 @@ "dev": true, "license": "MIT" }, + "node_modules/readable-stream": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", + "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", + "dev": true, + "license": "MIT", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/readable-web-to-node-stream": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.4.tgz", + "integrity": "sha512-9nX56alTf5bwXQ3ZDipHJhusu9NTQJ/CVPtb/XHAJCXihZeitfJvIRS4GqQ/mfIoOE3IelHMrpayVrosdHBuLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "readable-stream": "^4.7.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, "node_modules/reflect.getprototypeof": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", @@ -9625,6 +10719,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.3.tgz", "integrity": "sha512-NS3levdsRIUOmiJ8FZWCP7LG3QpJyrs/TE0Zpf1yvZu8cAJJ6QMW92H1c7kWpdIHo8RvmLxN/o2JXTKHp74lUA==", + "dev": true, "license": "Unlicense" }, "node_modules/run-parallel": { @@ -9655,6 +10750,7 @@ "version": "1.3.3", "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==", + "dev": true, "license": "BSD-3-Clause" }, "node_modules/safe-array-concat": { @@ -9677,6 +10773,27 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, "node_modules/safe-push-apply": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", @@ -9716,19 +10833,31 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true, "license": "MIT" }, + "node_modules/sax": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.6.0.tgz", + "integrity": "sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=11.0.0" + } + }, "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==", + "dev": true, "license": "MIT" }, "node_modules/semver": { "version": "7.7.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", - "devOptional": true, + "dev": true, "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -9790,6 +10919,7 @@ "version": "0.34.5", "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz", "integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==", + "dev": true, "hasInstallScript": true, "license": "Apache-2.0", "optional": true, @@ -9943,6 +11073,16 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/simple-xml-to-json": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/simple-xml-to-json/-/simple-xml-to-json-1.2.5.tgz", + "integrity": "sha512-ZyRpOE39EtJcTA3eL7qkHXKtZSNrDm3PkttECKBfaFTDuEvnXQA/Sq0mPMxdNfMLrCkMcJT4nEgGStceP73Ihg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.12.2" + } + }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -9967,6 +11107,7 @@ "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" @@ -10034,6 +11175,16 @@ "node": ">= 0.4" } }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, "node_modules/string-length": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", @@ -10321,10 +11472,29 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/strtok3": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-6.3.0.tgz", + "integrity": "sha512-fZtbhtvI9I48xDSywd/somNqgUHl2L2cstmXCCif0itOf96jeW18MBSyrLuNicYQVkvpOxkZtkzujiTJ9LW5Jw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@tokenizer/token": "^0.3.0", + "peek-readable": "^4.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, "node_modules/styled-jsx": { "version": "5.1.6", "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz", "integrity": "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==", + "dev": true, "license": "MIT", "dependencies": { "client-only": "0.0.1" @@ -10390,12 +11560,14 @@ "version": "4.2.2", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.2.2.tgz", "integrity": "sha512-KWBIxs1Xb6NoLdMVqhbhgwZf2PGBpPEiwOqgI4pFIYbNTfBXiKYyWoTsXgBQ9WFg/OlhnvHaY+AEpW7wSmFo2Q==", + "dev": true, "license": "MIT" }, "node_modules/tapable": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.2.tgz", "integrity": "sha512-1MOpMXuhGzGL5TTCZFItxCc0AARf1EZFQkGqMm7ERKj8+Hgr5oLvJOVFcC+lRmR8hCe2S3jC4T5D7Vg/d7/fhA==", + "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -10446,11 +11618,19 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/text-segmentation/-/text-segmentation-1.0.3.tgz", "integrity": "sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==", + "dev": true, "license": "MIT", "dependencies": { "utrie": "^1.0.2" } }, + "node_modules/tinycolor2": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.6.0.tgz", + "integrity": "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==", + "dev": true, + "license": "MIT" + }, "node_modules/tinyglobby": { "version": "0.2.15", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", @@ -10492,7 +11672,6 @@ "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -10520,6 +11699,24 @@ "node": ">=8.0" } }, + "node_modules/token-types": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/token-types/-/token-types-4.2.1.tgz", + "integrity": "sha512-6udB24Q737UD/SDsKAHI9FCRP7Bqc9D/MQUV02ORQg5iskjtLJlZJNdN4kKtcdtwCeWIwIHDGaUsTsCCAa8sFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@tokenizer/token": "^0.3.0", + "ieee754": "^1.2.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, "node_modules/ts-api-utils": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz", @@ -10629,6 +11826,7 @@ "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, "license": "0BSD" }, "node_modules/type-check": { @@ -10749,8 +11947,8 @@ "version": "5.9.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -10820,6 +12018,7 @@ "version": "7.18.2", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz", "integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==", + "dev": true, "license": "MIT" }, "node_modules/unrs-resolver": { @@ -10898,10 +12097,21 @@ "punycode": "^2.1.0" } }, + "node_modules/utif2": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/utif2/-/utif2-4.1.0.tgz", + "integrity": "sha512-+oknB9FHrJ7oW7A2WZYajOcv4FcDR4CfoGB0dPNfxbi4GO05RRnFmt5oa23+9w32EanrYcSJWspUiJkLMs+37w==", + "dev": true, + "license": "MIT", + "dependencies": { + "pako": "^1.0.11" + } + }, "node_modules/utrie": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/utrie/-/utrie-1.0.2.tgz", "integrity": "sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==", + "dev": true, "license": "MIT", "dependencies": { "base64-arraybuffer": "^1.0.2" @@ -11170,6 +12380,37 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/xml-parse-from-string": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/xml-parse-from-string/-/xml-parse-from-string-1.0.1.tgz", + "integrity": "sha512-ErcKwJTF54uRzzNMXq2X5sMIy88zJvfN2DmdoQvy7PAFJ+tPRU6ydWuOKNMyfmOjdyBQTFREi60s0Y0SyI0G0g==", + "dev": true, + "license": "MIT" + }, + "node_modules/xml2js": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz", + "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4.0" + } + }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", @@ -11280,7 +12521,6 @@ "integrity": "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==", "dev": true, "license": "MIT", - "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" } diff --git a/package.json b/package.json index 17e8ff8..e157e00 100644 --- a/package.json +++ b/package.json @@ -49,6 +49,7 @@ "html-to-image": "^1.11.13", "html2canvas": "^1.4.1", "jest": "^30.3.0", + "jimp": "^1.6.0", "next": "^16.2.1", "postcss": "^8.5.8", "prettier": "^3.8.1", diff --git a/public/claude_standing_on_business.png b/public/claude_standing_on_business.png new file mode 100644 index 0000000..cd79669 Binary files /dev/null and b/public/claude_standing_on_business.png differ diff --git a/scripts/ccrewind-tui.ts b/scripts/ccrewind-tui.ts index ddbabdf..2f00b87 100644 --- a/scripts/ccrewind-tui.ts +++ b/scripts/ccrewind-tui.ts @@ -7,6 +7,7 @@ import fs from "fs/promises"; import path from "path"; import os from "os"; import { fileURLToPath } from "url"; +import { MASCOT_ART } from "./mascots-ansi"; // ── ANSI helpers ────────────────────────────────────────── @@ -27,8 +28,31 @@ const gray = (s: string) => `${GRAY}${s}${RESET}`; const gold = (s: string) => `${GOLD}${s}${RESET}`; const green = (s: string) => `${GREEN}${s}${RESET}`; +const COL_WIDTH = Math.max(60, process.stdout.columns || 80); + // ── Formatting helpers ──────────────────────────────────── +function visibleLen(s: string): number { + return s.replace(/\x1b\[[0-9;]*m/g, "").length; +} + +function wrapLine(text: string, maxWidth: number, indent: string = ""): string[] { + const words = text.split(" "); + const lines: string[] = []; + let cur = ""; + for (const word of words) { + const test = cur ? `${cur} ${word}` : word; + if (visibleLen(test) > maxWidth && cur) { + lines.push(indent + cur); + cur = word; + } else { + cur = test; + } + } + if (cur) lines.push(indent + cur); + return lines.length ? lines : [indent]; +} + function formatNumber(n: number): string { if (n >= 1_000_000_000) return `${(n / 1_000_000_000).toFixed(1)}B`; if (n >= 1_000_000) return `${(n / 1_000_000).toFixed(1)}M`; @@ -89,11 +113,11 @@ function renderCalendar(activeDates: string[]): string[] { const dateStr = date.toISOString().split("T")[0]; if (date > today) { - line += " "; + line += " "; } else if (activeSet.has(dateStr)) { - line += orange("\u2593"); + line += orange("\u2593") + " "; } else { - line += gray("\u2591"); + line += gray("\u2591") + " "; } } lines.push(line); @@ -102,27 +126,28 @@ function renderCalendar(activeDates: string[]): string[] { } function renderEloBar(score: number, max: number = 1000): string { - const filled = Math.round((score / max) * 20); - return orange("\u25B0".repeat(filled)) + gray("\u25B1".repeat(20 - filled)); + const width = Math.max(10, COL_WIDTH - 4); + const filled = Math.round((score / max) * width); + return orange("\u25B0".repeat(filled)) + gray("\u25B1".repeat(width - filled)); } // ── Section renderers ───────────────────────────────────── function sectionHeader(title: string): string { - const dashes = "\u2500".repeat(Math.max(1, 44 - title.length - 5)); + const dashes = "\u2500".repeat(Math.max(1, COL_WIDTH - title.length - 5)); return orange(`\u2500\u2500\u2500 ${title} ${dashes}`); } function renderHeader(): string { + const inner = COL_WIDTH - 2; + const title = "\u27E1 CC REWIND \u27E1"; + const lpad = Math.floor((inner - title.length) / 2); + const rpad = inner - title.length - lpad; return [ "", - orange( - "\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557" - ), - orange("\u2551") + bold(white(" \u27E1 CC REWIND \u27E1 ")) + orange("\u2551"), - orange( - "\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D" - ), + orange("\u2554" + "\u2550".repeat(inner) + "\u2557"), + orange("\u2551") + bold(white(" ".repeat(lpad) + title + " ".repeat(rpad))) + orange("\u2551"), + orange("\u255A" + "\u2550".repeat(inner) + "\u255D"), dim(" \uD83D\uDD12 All data stays on your machine."), "", ].join("\n"); @@ -142,15 +167,15 @@ function renderTopTools(stats: ComputedStats): string { const tools = stats.topTools.slice(0, 7); if (tools.length === 0) return ""; const maxCount = tools[0].count; - const maxNameLen = Math.max(...tools.map((t) => t.name.length)); + const maxNameLen = COL_WIDTH - 2; + const BAR_WIDTH = Math.max(10, COL_WIDTH - 14); const lines = [sectionHeader("TOP TOOLS")]; for (const tool of tools) { - const name = pad(white(tool.name), maxNameLen + 8); - const bar = orange(renderBar(tool.count, maxCount, 20)); - const count = white(formatNumber(tool.count).padStart(7)); - lines.push(` ${name} ${bar} ${count}`); + const name = tool.name.length > maxNameLen ? tool.name.slice(0, maxNameLen - 1) + "…" : tool.name; + lines.push(` ${white(name)}`); + lines.push(` ${orange(renderBar(tool.count, maxCount, BAR_WIDTH))} ${white(formatNumber(tool.count))}`); + lines.push(""); } - lines.push(""); return lines.join("\n"); } @@ -171,17 +196,20 @@ function renderCostAndModels(stats: ComputedStats): string { if (allModels.length === 0) return ""; const maxCount = Math.max(...allModels.map((m) => m.count)); - const maxNameLen = Math.max(...allModels.map((m) => m.model.length)); + const maxNameLen = COL_WIDTH - 2; + // 4 indent + bar + 2 + 4 pct + 2 + 8 cost = 20 overhead + const BAR_WIDTH = Math.max(10, COL_WIDTH - 20); const lines = [sectionHeader("COST & MODELS")]; lines.push(` ${bold(orange(`$${stats.estimatedCostUSD.toFixed(2)}`))} ${dim("estimated total spend")}`); lines.push(""); for (const { model, count, cost } of allModels) { const pct = modelUsageTotal > 0 ? Math.round((count / modelUsageTotal) * 100) : 0; - const name = pad(white(model), maxNameLen + 8); - const bar = orange(renderBar(count, maxCount, 16)); + const name = model.length > maxNameLen ? model.slice(0, maxNameLen - 1) + "…" : model; + const bar = orange(renderBar(count, maxCount, BAR_WIDTH)); const costStr = cost >= 0.01 ? orange(`$${cost.toFixed(2)}`) : dim("< $0.01"); - lines.push(` ${name} ${bar} ${dim(`${pct}%`)} ${costStr}`); + lines.push(` ${white(name)}`); + lines.push(` ${bar} ${dim(`${pct}%`)} ${costStr}`); } lines.push(""); return lines.join("\n"); @@ -198,20 +226,22 @@ function renderTokenUsage(stats: ComputedStats): string { const pct = (v: number) => (total > 0 ? `(${Math.round((v / total) * 100)}%)` : ""); + // 2 + 12 name + 1 + bar + 2 + 7 count + 2 + 6 pct = 32 overhead + const BAR_WIDTH = Math.max(10, COL_WIDTH - 32); const lines = [sectionHeader("TOKEN USAGE")]; lines.push(dim(` Total: ${formatNumber(total)} tokens`)); lines.push(""); lines.push( - ` ${pad(white("Input"), 14)} ${orange(renderBar(stats.totalInputTokens, maxToken, 20))} ${white(formatNumber(stats.totalInputTokens))} ${dim(pct(stats.totalInputTokens))}` + ` ${pad(white("Input"), 12)} ${orange(renderBar(stats.totalInputTokens, maxToken, BAR_WIDTH))} ${white(formatNumber(stats.totalInputTokens))} ${dim(pct(stats.totalInputTokens))}` ); lines.push( - ` ${pad(white("Output"), 14)} ${orange(renderBar(stats.totalOutputTokens, maxToken, 20))} ${white(formatNumber(stats.totalOutputTokens))} ${dim(pct(stats.totalOutputTokens))}` + ` ${pad(white("Output"), 12)} ${orange(renderBar(stats.totalOutputTokens, maxToken, BAR_WIDTH))} ${white(formatNumber(stats.totalOutputTokens))} ${dim(pct(stats.totalOutputTokens))}` ); lines.push( - ` ${pad(gold("Cache Read"), 14)} ${gold(renderBar(stats.totalCacheReadTokens, maxToken, 20))} ${gold(formatNumber(stats.totalCacheReadTokens))} ${dim(pct(stats.totalCacheReadTokens))}` + ` ${pad(gold("Cache Read"), 12)} ${gold(renderBar(stats.totalCacheReadTokens, maxToken, BAR_WIDTH))} ${gold(formatNumber(stats.totalCacheReadTokens))} ${dim(pct(stats.totalCacheReadTokens))}` ); lines.push( - ` ${pad(gold("Cache Write"), 14)} ${gold(renderBar(stats.totalCacheCreationTokens, maxToken, 20))} ${gold(formatNumber(stats.totalCacheCreationTokens))} ${dim(pct(stats.totalCacheCreationTokens))}` + ` ${pad(gold("Cache Write"), 12)} ${gold(renderBar(stats.totalCacheCreationTokens, maxToken, BAR_WIDTH))} ${gold(formatNumber(stats.totalCacheCreationTokens))} ${dim(pct(stats.totalCacheCreationTokens))}` ); lines.push(""); return lines.join("\n"); @@ -230,12 +260,13 @@ function renderTopProjects(stats: ComputedStats): string { })) .sort((a, b) => b.estimatedCost - a.estimatedCost); - const maxNameLen = Math.max(...projects.map((p) => p.shortName.length)); + const maxNameLen = COL_WIDTH - 2; const lines = [sectionHeader("TOP PROJECTS")]; for (const p of projects) { - const name = pad(white(p.shortName), maxNameLen + 8); + const name = p.shortName.length > maxNameLen ? p.shortName.slice(0, maxNameLen - 1) + "…" : p.shortName; const cost = p.estimatedCost >= 0.01 ? orange(`$${p.estimatedCost.toFixed(2)}`) : dim("< $0.01"); - lines.push(` ${name} ${cost} ${dim(`${formatNumber(p.messages)} msgs`)} ${dim(`${p.sessions} sessions`)}`); + lines.push(` ${white(name)}`); + lines.push(` ${cost} ${dim(`${formatNumber(p.messages)} msgs`)} ${dim(`${p.sessions} sessions`)}`); } lines.push(""); return lines.join("\n"); @@ -268,25 +299,43 @@ function renderStreak(stats: ComputedStats): string { } function renderCharacterReveal(_stats: ComputedStats, elo: EloBreakdown, character: Character): string { - return [ + const lines: string[] = [ sectionHeader("YOUR CHARACTER"), "", ` ${orange("\u2726")} ${bold(white(character.name))} ${orange("\u2726")}`, - ` ${dim('"')}${white(character.oneLiner)}${dim('"')}`, + ...(() => { + const wrapped = wrapLine(character.oneLiner, COL_WIDTH - 4, " "); + return wrapped.map((line, i) => { + const text = line.trimStart(); + if (wrapped.length === 1) return ` ${dim('"')}${white(text)}${dim('"')}`; + if (i === 0) return ` ${dim('"')}${white(text)}`; + if (i === wrapped.length - 1) return ` ${white(text)}${dim('"')}`; + return ` ${white(text)}`; + }); + })(), "", + ]; + + const art = MASCOT_ART[character.name]; + if (art) { + art.split("\n").forEach((l) => lines.push(" " + l)); + lines.push(""); + } + + lines.push( ` Claude Elo: ${bold(orange(String(elo.total)))} / 1000`, ` ${renderEloBar(elo.total)}`, "", ` ${dim(character.endingLine)}`, - "", - ].join("\n"); + "" + ); + + return lines.join("\n"); } function renderFooter(): string { return [ - orange( - "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500" - ), + orange("\u2500".repeat(COL_WIDTH)), ` ${dim("Full visual experience \u2192")} ${orange("ccrewind.com")}`, "", ].join("\n"); diff --git a/scripts/generate-mascot-art.ts b/scripts/generate-mascot-art.ts new file mode 100644 index 0000000..5da8cd4 --- /dev/null +++ b/scripts/generate-mascot-art.ts @@ -0,0 +1,251 @@ +/** + * Generate true-color ANSI half-block art for all character mascots and write to + * scripts/mascots-ansi.ts. Run from repo root: + * + * npx tsx scripts/generate-mascot-art.ts + * + * Requires: jimp (devDependency) + */ + +import { Jimp, intToRGBA } from "jimp"; +import fs from "fs"; +import path from "path"; +import { fileURLToPath } from "url"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +const REPO_ROOT = path.dirname(__dirname); +const MASCOTS_DIR = path.join(REPO_ROOT, "public", "mascots"); +const OUTPUT_FILE = path.join(REPO_ROOT, "scripts", "mascots-ansi.ts"); + +const WIDTH = 30; +const HEIGHT = 15; +const BG_THRESH = 35; + +const CHAR_MAP: Record = { + "The Intern": "char-the-intern.png", + "The Degen": "char-the-degen.png", + "The SBF": "char-the-ghost.png", + "The Sama": "char-the-operator.png", + "The Quant": "char-the-quant.png", + "The Musk": "char-the-chaos-agent.png", + "The Dario": "char-the-visionary.png", + "The Karpathy": "char-the-night-shift-engineer.png", + "Slough Boy": "char-the-researcher.png", +}; + +const ESC = "\x1b"; +const RESET = `${ESC}[0m`; + +type RGB = { r: number; g: number; b: number }; + +function colorDist(a: RGB, b: RGB): number { + return Math.sqrt((a.r - b.r) ** 2 + (a.g - b.g) ** 2 + (a.b - b.b) ** 2); +} + +function getPixel(img: InstanceType, x: number, y: number): RGB { + const rgba = intToRGBA(img.getPixelColor(x, y)); + return { r: rgba.r, g: rgba.g, b: rgba.b }; +} + +function detectBg(img: InstanceType): RGB { + const w = img.width; + const h = img.height; + const samples = [ + getPixel(img, 0, 0), + getPixel(img, w - 1, 0), + getPixel(img, 0, h - 1), + getPixel(img, w - 1, h - 1), + getPixel(img, Math.floor(w / 2), 0), + getPixel(img, 0, Math.floor(h / 2)), + ]; + return { + r: Math.floor(samples.reduce((s, p) => s + p.r, 0) / samples.length), + g: Math.floor(samples.reduce((s, p) => s + p.g, 0) / samples.length), + b: Math.floor(samples.reduce((s, p) => s + p.b, 0) / samples.length), + }; +} + +function makeBgMask(img: InstanceType, bg: RGB, thresh: number): boolean[][] { + const w = img.width; + const h = img.height; + const visited: boolean[][] = Array.from({ length: w }, () => + new Array(h).fill(false) + ); + const queue: [number, number][] = []; + + const seed = (x: number, y: number) => { + if (!visited[x][y] && colorDist(getPixel(img, x, y), bg) < thresh) { + visited[x][y] = true; + queue.push([x, y]); + } + }; + + for (let x = 0; x < w; x++) { + seed(x, 0); + seed(x, h - 1); + } + for (let y = 0; y < h; y++) { + seed(0, y); + seed(w - 1, y); + } + + let i = 0; + while (i < queue.length) { + const [x, y] = queue[i++]; + for (const [nx, ny] of [ + [x - 1, y], + [x + 1, y], + [x, y - 1], + [x, y + 1], + ] as [number, number][]) { + if (nx >= 0 && nx < w && ny >= 0 && ny < h && !visited[nx][ny]) { + if (colorDist(getPixel(img, nx, ny), bg) < thresh) { + visited[nx][ny] = true; + queue.push([nx, ny]); + } + } + } + } + + return visited; +} + +async function imgToAnsi(filePath: string): Promise { + const orig = await Jimp.read(filePath); + const origW = orig.width; + const origH = orig.height; + const bg = detectBg(orig); + const mask = makeBgMask(orig, bg, BG_THRESH); + + const img = orig.clone(); + img.resize({ w: WIDTH, h: HEIGHT * 2 }); + + const scaleX = origW / WIDTH; + const scaleY = origH / (HEIGHT * 2); + + const isBg = (col: number, prow: number): boolean => { + const ox = Math.min(Math.floor(col * scaleX), origW - 1); + const oy = Math.min(Math.floor(prow * scaleY), origH - 1); + return mask[ox][oy]; + }; + + const lines: string[] = []; + + for (let row = 0; row < HEIGHT; row++) { + const parts: string[] = []; + let curFg: RGB | null = null; + let curBg: RGB | null = null; + + for (let col = 0; col < WIDTH; col++) { + const tp = getPixel(img, col, row * 2); + const bp = getPixel(img, col, row * 2 + 1); + const tc = isBg(col, row * 2) ? null : tp; + const bc = isBg(col, row * 2 + 1) ? null : bp; + + if (tc === null && bc === null) { + if (curFg !== null || curBg !== null) { + parts.push(RESET); + curFg = curBg = null; + } + parts.push(" "); + continue; + } + + let newFg: RGB, newBg: RGB | null, char: string; + if (tc !== null && bc !== null) { + newFg = bc; + newBg = tc; + char = "▄"; + } else if (tc !== null) { + newFg = tc; + newBg = null; + char = "▀"; + } else { + newFg = bc!; + newBg = null; + char = "▄"; + } + + let seq = ""; + if ( + newBg?.r !== curBg?.r || + newBg?.g !== curBg?.g || + newBg?.b !== curBg?.b + ) { + seq += + newBg === null + ? `${ESC}[49m` + : `${ESC}[48;2;${newBg.r};${newBg.g};${newBg.b}m`; + curBg = newBg; + } + if ( + newFg.r !== curFg?.r || + newFg.g !== curFg?.g || + newFg.b !== curFg?.b + ) { + seq += `${ESC}[38;2;${newFg.r};${newFg.g};${newFg.b}m`; + curFg = newFg; + } + parts.push(seq + char); + } + + parts.push(RESET); + lines.push(parts.join("")); + } + + const isBlank = (line: string) => + line.replace(/\x1b\[[0-9;]*m/g, "").trim() === ""; + while (lines.length && isBlank(lines[0])) lines.shift(); + while (lines.length && isBlank(lines[lines.length - 1])) lines.pop(); + + return lines.join("\n"); +} + +async function main() { + const results: Record = {}; + let totalBytes = 0; + + for (const [name, filename] of Object.entries(CHAR_MAP)) { + const filePath = path.join(MASCOTS_DIR, filename); + if (!fs.existsSync(filePath)) { + console.warn(` WARNING: missing ${filePath}`); + continue; + } + process.stdout.write(` Processing ${name}...`); + const art = await imgToAnsi(filePath); + results[name] = art; + const size = Buffer.byteLength(art, "utf8"); + totalBytes += size; + console.log(` → ${Math.floor(size / 1024)}KB`); + } + + console.log(`\nTotal: ${Math.floor(totalBytes / 1024)}KB`); + + const tsLines = [ + "// AUTO-GENERATED by scripts/generate-mascot-art.ts — do not edit manually", + "// Pre-rendered true-color ANSI half-block art (30×15, flood-fill transparent bg)", + "// To regenerate: npx tsx scripts/generate-mascot-art.ts", + "", + "export const MASCOT_ART: Record = {", + ]; + + for (const [name, art] of Object.entries(results)) { + const escaped = art + .replace(/\\/g, "\\\\") + .replace(/`/g, "\\`") + .replace(/\$\{/g, "\\${"); + tsLines.push(` ${JSON.stringify(name)}: \`${escaped}\`,`); + tsLines.push(""); + } + + tsLines.push("};\n"); + fs.writeFileSync(OUTPUT_FILE, tsLines.join("\n"), "utf8"); + console.log(`Written: ${OUTPUT_FILE}`); +} + +main().catch((err) => { + console.error(err); + process.exit(1); +}); diff --git a/scripts/generate-variants.ts b/scripts/generate-variants.ts new file mode 100644 index 0000000..ab14c8e --- /dev/null +++ b/scripts/generate-variants.ts @@ -0,0 +1,614 @@ +import fs from "fs"; +import path from "path"; +import { fileURLToPath } from "url"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +const srcPath = path.join(__dirname, "../src/components/upload/UploadScreen.tsx"); +const originalSource = fs.readFileSync(srcPath, "utf8"); + +const previewCardsMatch = originalSource.match( + /\/\* ─── Stacked preview cards ─── \*\/\s*function PreviewCards\(\) \{[\s\S]*?return \([\s\S]*? \);\n\}/ +); +const previewCardsCode = previewCardsMatch ? previewCardsMatch[0] : ""; + +const generateTemplate = (vNum: string, chromeCode: string, wrapperClass: string, rightColClass: string) => ` +"use client"; + +import { useState, useCallback, useRef, useEffect } from "react"; +import { motion, AnimatePresence } from "framer-motion"; +import { parseClaudeFolder } from "@/lib/parser"; +import { generateDemoData } from "@/lib/demo"; +import { ParsedData } from "@/types"; + +interface UploadScreenProps { + onDataParsed: (data: ParsedData) => void; +} + +const LOADING_MESSAGES = [ + "Reading your .claude folder...", + "Scanning session transcripts...", + "Crunching the numbers...", + "Analyzing your habits...", + "Building your story...", +]; + +${previewCardsCode} + +function TabContentNPM({ active }: { active: boolean }) { + const [lines, setLines] = useState(0); + useEffect(() => { + if (!active) { + setLines(0); + return; + } + const timeouts = [ + setTimeout(() => setLines(1), 50), + setTimeout(() => setLines(2), 100), + setTimeout(() => setLines(3), 150), + setTimeout(() => setLines(4), 200), + setTimeout(() => setLines(5), 250), + ]; + return () => timeouts.forEach(clearTimeout); + }, [active]); + + return ( +
+
+
+
+
+
+
+

$ npx ccrewind

+ {lines >= 1 &&

◆ CC REWIND ◆

} + {lines >= 2 &&

Reading ~/.claude...

} + {lines >= 3 &&

Your character: The Quant

} + {lines >= 4 &&

Claude Elo: 847 / 1000

} + {lines >= 5 &&

→ ccrewind.com for the full story

} +
+ +
+ ); +} + +function TabContentClaude() { + const [copied, setCopied] = useState(false); + const copyCmd = () => { + navigator.clipboard.writeText("npx ccrewind --setup"); + setCopied(true); + setTimeout(() => setCopied(false), 1500); + }; + return ( +
+

Run inside Claude Code

+
+ npx ccrewind --setup + +
+
+
+ /ccrewind + Terminal stats report +
+
+ /ccrewind-ui + Opens web UI with auto-detected data +
+
+

Registers slash commands in your Claude Code session

+
+ ); +} + +export default function UploadScreenV${vNum}({ onDataParsed }: UploadScreenProps) { + const [isDragging, setIsDragging] = useState(false); + const [isLoading, setIsLoading] = useState(false); + const [loadingText, setLoadingText] = useState(LOADING_MESSAGES[0]); + const [error, setError] = useState(null); + const [localAvailable, setLocalAvailable] = useState(false); + const [showHiddenHelp, setShowHiddenHelp] = useState(false); + const inputRef = useRef(null); + + const [activeTab, setActiveTab] = useState<"npm" | "web" | "claude">("web"); + + useEffect(() => { + fetch("/api/local-data/status") + .then((r) => r.json()) + .then((d: { available: boolean }) => { + if (d.available) setLocalAvailable(true); + }) + .catch(() => {}); + }, []); + + const startLoadingCycle = () => { + let idx = 0; + const interval = setInterval(() => { + idx = (idx + 1) % LOADING_MESSAGES.length; + setLoadingText(LOADING_MESSAGES[idx]); + }, 1500); + return interval; + }; + + const handleLocalData = useCallback(async () => { + setIsLoading(true); + setError(null); + setLoadingText(LOADING_MESSAGES[0]); + const interval = startLoadingCycle(); + try { + const res = await fetch("/api/local-data"); + if (!res.ok) throw new Error("Failed to load local data"); + const data: ParsedData = await res.json(); + if (!data.statsCache && data.history.length === 0 && data.sessions.length === 0) { + throw new Error("No Claude data found in ~/.claude"); + } + clearInterval(interval); + setLoadingText("Ready."); + await new Promise((r) => setTimeout(r, 500)); + onDataParsed(data); + } catch (e) { + clearInterval(interval); + setIsLoading(false); + setError(e instanceof Error ? e.message : "Failed to load local data"); + } + }, [onDataParsed]); + + const handleFiles = useCallback( + async (files: FileList) => { + setIsLoading(true); + setError(null); + setLoadingText(LOADING_MESSAGES[0]); + const interval = startLoadingCycle(); + try { + const data = await parseClaudeFolder(files); + if (!data.statsCache && data.history.length === 0 && data.sessions.length === 0) { + throw new Error("No Claude data found. Make sure you selected your ~/.claude folder."); + } + clearInterval(interval); + setLoadingText("Ready."); + await new Promise((r) => setTimeout(r, 500)); + onDataParsed(data); + } catch (e) { + clearInterval(interval); + setIsLoading(false); + setError(e instanceof Error ? e.message : "Failed to parse data"); + } + }, + [onDataParsed] + ); + + const handleDemo = useCallback(() => { + setIsLoading(true); + setLoadingText("Loading demo data..."); + fetch("/demo-data.json") + .then((r) => r.json()) + .then((data) => { + setLoadingText("Ready."); + setTimeout(() => onDataParsed(data), 400); + }) + .catch(() => { + const demoData = generateDemoData(); + setLoadingText("Ready."); + setTimeout(() => onDataParsed(demoData), 400); + }); + }, [onDataParsed]); + + const handleDrop = useCallback( + (e: React.DragEvent) => { + e.preventDefault(); + setIsDragging(false); + if (e.dataTransfer.files.length > 0) handleFiles(e.dataTransfer.files); + }, + [handleFiles] + ); + + const handleDragOver = useCallback((e: React.DragEvent) => { + e.preventDefault(); + setIsDragging(true); + }, []); + const handleDragLeave = useCallback((e: React.DragEvent) => { + e.preventDefault(); + setIsDragging(false); + }, []); + + const handleInputChange = (e: React.ChangeEvent) => { + if (e.target.files && e.target.files.length > 0) handleFiles(e.target.files); + }; + + const TabContentWeb = () => ( +
+ {localAvailable ? ( + + ) : ( + + )} + +
+ {localAvailable && ( + + )} + +
+ +
+ + + + + + + Your data stays local + + +
+ +
+
+ + + {showHiddenHelp && ( + +
+

+ Show hidden files first: +

+ {[ + { os: "macOS", hint: "Cmd + Shift + .", note: "in Finder" }, + { os: "Windows", hint: "View → Show → Hidden items", note: "" }, + { os: "Linux", hint: "Ctrl + H", note: "in file manager" }, + ].map(({ os, hint, note }) => ( +
+ {os} + + {hint} + + {note && {note}} +
+ ))} +
+
+ )} +
+
+ ); + + return ( +
+
+
+
+ + + {isLoading ? ( + +
+ + + +
+ + + {loadingText} + + +
+ ) : ( + +
+ +

+ Claude Code
+ Rewind. +

+

+ Connect your data. Get your character. Share your stats. +

+
+ + ${chromeCode} + +
+ + + + +
+ )} +
+ + + {isDragging && ( + +
+

Drop it like it's hot

+

release to upload your ~/.claude folder

+
+
+ )} +
+ + + {error && ( + +

{error}

+
+ )} +
+ + +
+ ); +} +`; + +const v1Chrome = ` +
+
+ {(["npm", "web", "claude"] as const).map((t) => ( + + ))} +
+
+ {activeTab === "npm" && } + {activeTab === "web" && } + {activeTab === "claude" && } +
+
+`; + +const v2Chrome = ` +
+
+ {(["npm", "web", "claude"] as const).map((t) => ( + + ))} +
+
+ {activeTab === "npm" && } + {activeTab === "web" && } + {activeTab === "claude" && } +
+
+`; + +const v3Chrome = ` +
+
+ {(["npm", "web", "claude"] as const).map((t, idx) => ( + + ))} +
+
+ {activeTab === "npm" && } + {activeTab === "web" && } + {activeTab === "claude" && } +
+
+`; + +const v4Chrome = ` +
+
+ {(["npm", "web", "claude"] as const).map((t) => ( + + ))} +
+
+ {activeTab === "npm" && } + {activeTab === "web" && } + {activeTab === "claude" && } +
+
+`; + +const v5Chrome = ` +
+
+ {(["npm", "web", "claude"] as const).map((t) => ( + + ))} +
+
+ {activeTab === "npm" && } + {activeTab === "web" && } + {activeTab === "claude" && } +
+
+`; + +fs.writeFileSync( + path.join(__dirname, "../src/components/upload/UploadScreenV1.tsx"), + generateTemplate( + "1", + v1Chrome, + "flex-1 flex flex-col items-center md:items-start w-full max-w-lg", + "shrink-0 hidden md:block" + ) +); +fs.writeFileSync( + path.join(__dirname, "../src/components/upload/UploadScreenV2.tsx"), + generateTemplate( + "2", + v2Chrome, + "flex-1 flex flex-col items-center md:items-start w-full max-w-lg", + "shrink-0 hidden md:block" + ) +); +fs.writeFileSync( + path.join(__dirname, "../src/components/upload/UploadScreenV3.tsx"), + generateTemplate( + "3", + v3Chrome, + "flex-1 flex flex-col items-center md:items-start w-full max-w-lg", + "shrink-0 hidden md:block" + ) +); +fs.writeFileSync( + path.join(__dirname, "../src/components/upload/UploadScreenV4.tsx"), + generateTemplate( + "4", + v4Chrome, + "flex-1 flex flex-col items-center md:items-start w-full max-w-lg", + "shrink-0 hidden md:block" + ) +); +fs.writeFileSync( + path.join(__dirname, "../src/components/upload/UploadScreenV5.tsx"), + generateTemplate( + "5", + v5Chrome, + "flex-1 flex flex-col items-center md:items-start w-full max-w-lg", + "shrink-0 hidden md:block" + ) +); + +console.log("Successfully generated 5 variants (fixed Next.js TS issues)."); diff --git a/scripts/mascots-ansi.ts b/scripts/mascots-ansi.ts new file mode 100644 index 0000000..363df90 --- /dev/null +++ b/scripts/mascots-ansi.ts @@ -0,0 +1,94 @@ +// AUTO-GENERATED by scripts/generate-mascot-art.ts — do not edit manually +// Pre-rendered true-color ANSI half-block art (90×45, flood-fill transparent bg) +// To regenerate: npx tsx scripts/generate-mascot-art.ts + +export const MASCOT_ART: Record = { + "The Intern": ` ▄▄▄▄▄▄▄▄▄  + ▄ ▄▄▄▄▄▄▄▄▄  + ▄▄▄▄▄▄▄▄▄▄▄▄▄▄  + ▄▄▄▄▄▄▄▄▄▀▀▀▀▀  + ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄  + ▀▄▀▀▀▀▀▀▀▄▄▄▄▄▄▄▄▄▀▀▀▀▀▀▀▄▀  + ▄ ▄▄▄▄▄▄▄▄▄ ▄  + ▄ ▄ ▀ ▀ ▀ ▀ ▄ ▄  + ▄ ▀ ▀ ▄ ▀ ▀ ▄ `, + + "The Degen": ` ▄▄▄▄▄▄▄▄▄  + ▄▀▄▄▄▄▄▄▄▄▀  + ▄▄▄▄▄▄▄▄▄▄▄▄  + ▄▄▄▄▄▄▄▄▄▄▄▄▀  + ▄▄▀▀▄▄▄▄▄▄▄▀ ▀▄  + ▀▄ ▄▄▄▄ ▄▀▄▄▀▄ ▄▀▄  + ▄▄▀ ▄▄▄ ▄▄▄▄▀▄▄ ▀▄▄  + ▄▄ ▄▄▄▄▄▄▄▄▄▄▄▄▄  + ▄▄▄▄▄▄ ▀▄▄▀ ▄▄▀ ▄▄▄▄  + ▀▀▀▄▄▄▄▄▀▀▀ ▀▀▀▄▄▄▄▄▀▀  + ▀▀▀▀ ▀▀▀ `, + + "The SBF": ` ▄ ▄▄▄▄▄  + ▄▄▄▄▄▄▄▄▄▄ ▄▄▄▄▄▄  + ▄▄▄▄▄▄▄▄▄▄▄▄ ▀  + ▄▄▄▄▄▄▄▄▄▄▄▄▄▄  + ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄  + ▀▀▄▄▄▄▄▄▄▄▄▄▄▄▄▄  + ▀▄▄▄▄▀▀▄▄▄▄  + ▀ ▀ `, + + "The Sama": ` ▄▄▄▄▄▄▄▄▄▄▄▄▄  + ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄  + ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄  + ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄  + ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄  + ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄  + ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄  + ▄▄▀▄▄▄▄▄▄▄▄▄▄▄▄▄▄▀▀▀  + ▄▄▄▄ ▄▄▄▄▄ `, + + "The Quant": ` ▄ ▄ ▄ ▄ ▄▄▄ ▄▄  + ▄▄ ▄ ▄▄▄▄▄ ▀▄▄▄ ▀  + ▄ ▄▄▄▀▀▀▀▄▀▀▀ ▄ ▄  + ▀▀ ▀▄▄▄▄▄▄▄▄▄▄▄▀▀▀▀▀  + ▄▄▄▄▄▄▄▄▄▄▄▄ ▄  + ▄ ▄ ▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ▄▄▀▄  + ▀▀▀▄ ▀▄▄▄▄▄▄▄▄▄▄▄▀▀▄▀▀▄▄  + ▄▀ ▄▄▄▄▄▄▄▄▄▄▄ ▄▄  + ▄▄▄▄▄▄▄▄▄▄▄  + ▀▄▀▄ ▄▀▄▀ `, + + "The Musk": ` ▄▄ ▄▄▄▄▄▄▄▄▄▄  + ▄▄▄▄▄▄▄▄▄▄▄▄▄  + ▀▄▄▀ ▀▄▄▄ ▄▄▀  + ▀▀  +  +  + ▄▄▄▄▄ ▄▄▄▄▄  + ▀▄▀▄▀ ▀▀▀▄▀ `, + + "The Dario": ` ▄▄▄▄▄▄▄▄▄  + ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄  + ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▀  + ▀▄ ▀▀▄▄▄▄▄▄▄▄▄▄▄▄▄▄  + ▄▄▄ ▄▄▄▄▄▄▄▄▄▄▄▄▄▄  + ▀▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄  + ▀▀▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄  + ▀▄▄▄▄▄▄▄▄▄▄▄▄▄▀▀  + ▄▄▄▄ ▀▄▄▄ `, + + "The Karpathy": ` ▄▄ ▄▄▄▄▄▄▄▄▄▄▄▄  + ▄▄▄▄▄ ▄▄▄▄▄▄▄▄▄▄▄▄  + ▀▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄  + ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▀ ▄▄  + ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ▄▄▄  + ▄▄▄▄▄▄▀ ▀▀ ▀ ▀ ▄▄▄▄ `, + + "Slough Boy": ` ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄  + ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄  + ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄  + ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄  + ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄  + ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄  + ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄  + ▄▄▄▄▄▄▄▄▀  + ▄▄ ▀▀▄▄▀  + ▀▀ ▀▀ `, +}; diff --git a/src/components/upload/UploadScreen.tsx b/src/components/upload/UploadScreen.tsx index c7cbee8..59a5ffe 100644 --- a/src/components/upload/UploadScreen.tsx +++ b/src/components/upload/UploadScreen.tsx @@ -160,111 +160,61 @@ function PreviewCards() { } function TabContentNPM({ active }: { active: boolean }) { - const [copied, setCopied] = useState(false); - const copyCmd = () => { - navigator.clipboard.writeText("npx ccrewind"); - setCopied(true); - setTimeout(() => setCopied(false), 1500); - }; - - const hourBars = [40, 30, 25, 20, 10, 10, 10, 15, 20, 30, 35, 45, 60, 70, 80, 95, 75, 30, 15, 50, 55, 65, 50, 45]; + const [lines, setLines] = useState(0); + useEffect(() => { + if (!active) { + setLines(0); + return; + } + const timeouts = [ + setTimeout(() => setLines(1), 50), + setTimeout(() => setLines(2), 100), + setTimeout(() => setLines(3), 150), + setTimeout(() => setLines(4), 200), + setTimeout(() => setLines(5), 250), + ]; + return () => timeouts.forEach(clearTimeout); + }, [active]); return ( -
-
-
-
-
-
-
- -
- - $ npx ccrewind - - -
- -

⟡ CC REWIND ⟡

- -
-
-

$361

-

cost

-
-
-

585M

-

tokens

-
-
-

8.4K

-

messages

-
-
- -

- ─── ACTIVITY BY HOUR ─── +

+
+
+
+
+
+
+

+ $ npx ccrewind

-
- {hourBars.map((h, i) => ( -
= 70 ? "#ff6b35" : h >= 40 ? "rgba(255,107,53,0.5)" : "rgba(255,107,53,0.2)", - opacity: active ? 1 : 0, - transition: `opacity 0.2s ease ${i * 0.02}s`, - }} - /> - ))} -
-

peak: 3pm (736 messages)

- - + {lines >= 1 &&

◆ CC REWIND ◆

} + {lines >= 2 &&

Reading ~/.claude...

} + {lines >= 3 && ( +

+ Your character: The Quant +

+ )} + {lines >= 4 && ( +

+ Claude Elo: 847 / 1000 +

+ )} + {lines >= 5 &&

→ ccrewind.com for the full story

} +
+
); @@ -278,15 +228,16 @@ function TabContentClaude() { setTimeout(() => setCopied(false), 1500); }; return ( -
-
+
+

Run inside Claude Code

+
npx ccrewind --setup - - # sets up ccrewind as a native slash command + + # registers slash commands
-
+
/ccrewind - inline report
-
+
/ccrewind-ui - open web UI
-

Run these directly inside Claude Code!

); } @@ -347,35 +295,9 @@ export default function UploadScreen({ onDataParsed }: UploadScreenProps) { const [showHiddenHelp, setShowHiddenHelp] = useState(false); const inputRef = useRef(null); - const [activeTab, setActiveTab] = useState<"npm" | "web" | "claude">("npm"); + const [activeTab, setActiveTab] = useState<"npm" | "web" | "claude">("web"); + const [everExpandedNpm, setEverExpandedNpm] = useState(false); const [hasInteracted, setHasInteracted] = useState(false); - const [cycleKey, setCycleKey] = useState(0); - const [cycleActive, setCycleActive] = useState(true); - const TABS = ["npm", "web", "claude"] as const; - const CYCLE_MS = 6000; - - useEffect(() => { - if (!cycleActive) return; - const timer = setInterval(() => { - setActiveTab((prev) => { - const idx = TABS.indexOf(prev); - return TABS[(idx + 1) % TABS.length]; - }); - setCycleKey((k) => k + 1); - }, CYCLE_MS); - return () => clearInterval(timer); - }, [cycleKey, cycleActive]); - - useEffect(() => { - const stop = () => setCycleActive(false); - window.addEventListener("click", stop, { once: true }); - return () => window.removeEventListener("click", stop); - }, []); - - const handleTabClick = (t: "npm" | "web" | "claude") => { - setActiveTab(t); - setCycleActive(false); - }; useEffect(() => { fetch("/api/local-data/status") @@ -484,7 +406,7 @@ export default function UploadScreen({ onDataParsed }: UploadScreenProps) { }; const TabContentWeb = () => ( -
+
{localAvailable ? ( ))}
- -
+ {activeTab === "npm" && ( )} -
-
+ +
+ + + + )} - {/* Preview cards — fixed to viewport center, independent of tab height */} - {!isLoading && ( - -
-
- -
-
-
- )} - {isDragging && (