wip first
This commit is contained in:
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
node_modules
|
||||
dist
|
||||
12
index.html
Normal file
12
index.html
Normal file
@@ -0,0 +1,12 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Canopy</title>
|
||||
<script type="module" src="/src/main.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
</body>
|
||||
</html>
|
||||
987
package-lock.json
generated
Normal file
987
package-lock.json
generated
Normal file
@@ -0,0 +1,987 @@
|
||||
{
|
||||
"name": "canopy-game",
|
||||
"version": "0.0.1",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "canopy-game",
|
||||
"version": "0.0.1",
|
||||
"devDependencies": {
|
||||
"vite": "^5.4.19"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/aix-ppc64": {
|
||||
"version": "0.21.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz",
|
||||
"integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"aix"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/android-arm": {
|
||||
"version": "0.21.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz",
|
||||
"integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/android-arm64": {
|
||||
"version": "0.21.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz",
|
||||
"integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/android-x64": {
|
||||
"version": "0.21.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz",
|
||||
"integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/darwin-arm64": {
|
||||
"version": "0.21.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz",
|
||||
"integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/darwin-x64": {
|
||||
"version": "0.21.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz",
|
||||
"integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/freebsd-arm64": {
|
||||
"version": "0.21.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz",
|
||||
"integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/freebsd-x64": {
|
||||
"version": "0.21.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz",
|
||||
"integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-arm": {
|
||||
"version": "0.21.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz",
|
||||
"integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-arm64": {
|
||||
"version": "0.21.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz",
|
||||
"integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-ia32": {
|
||||
"version": "0.21.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz",
|
||||
"integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-loong64": {
|
||||
"version": "0.21.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz",
|
||||
"integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==",
|
||||
"cpu": [
|
||||
"loong64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-mips64el": {
|
||||
"version": "0.21.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz",
|
||||
"integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==",
|
||||
"cpu": [
|
||||
"mips64el"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-ppc64": {
|
||||
"version": "0.21.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz",
|
||||
"integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-riscv64": {
|
||||
"version": "0.21.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz",
|
||||
"integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-s390x": {
|
||||
"version": "0.21.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz",
|
||||
"integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==",
|
||||
"cpu": [
|
||||
"s390x"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-x64": {
|
||||
"version": "0.21.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz",
|
||||
"integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/netbsd-x64": {
|
||||
"version": "0.21.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz",
|
||||
"integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"netbsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/openbsd-x64": {
|
||||
"version": "0.21.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz",
|
||||
"integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"openbsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/sunos-x64": {
|
||||
"version": "0.21.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz",
|
||||
"integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"sunos"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/win32-arm64": {
|
||||
"version": "0.21.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz",
|
||||
"integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/win32-ia32": {
|
||||
"version": "0.21.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz",
|
||||
"integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/win32-x64": {
|
||||
"version": "0.21.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz",
|
||||
"integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@rollup/rollup-android-arm-eabi": {
|
||||
"version": "4.60.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.1.tgz",
|
||||
"integrity": "sha512-d6FinEBLdIiK+1uACUttJKfgZREXrF0Qc2SmLII7W2AD8FfiZ9Wjd+rD/iRuf5s5dWrr1GgwXCvPqOuDquOowA==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-android-arm64": {
|
||||
"version": "4.60.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.60.1.tgz",
|
||||
"integrity": "sha512-YjG/EwIDvvYI1YvYbHvDz/BYHtkY4ygUIXHnTdLhG+hKIQFBiosfWiACWortsKPKU/+dUwQQCKQM3qrDe8c9BA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-darwin-arm64": {
|
||||
"version": "4.60.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.60.1.tgz",
|
||||
"integrity": "sha512-mjCpF7GmkRtSJwon+Rq1N8+pI+8l7w5g9Z3vWj4T7abguC4Czwi3Yu/pFaLvA3TTeMVjnu3ctigusqWUfjZzvw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-darwin-x64": {
|
||||
"version": "4.60.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.60.1.tgz",
|
||||
"integrity": "sha512-haZ7hJ1JT4e9hqkoT9R/19XW2QKqjfJVv+i5AGg57S+nLk9lQnJ1F/eZloRO3o9Scy9CM3wQ9l+dkXtcBgN5Ew==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-freebsd-arm64": {
|
||||
"version": "4.60.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.60.1.tgz",
|
||||
"integrity": "sha512-czw90wpQq3ZsAVBlinZjAYTKduOjTywlG7fEeWKUA7oCmpA8xdTkxZZlwNJKWqILlq0wehoZcJYfBvOyhPTQ6w==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-freebsd-x64": {
|
||||
"version": "4.60.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.60.1.tgz",
|
||||
"integrity": "sha512-KVB2rqsxTHuBtfOeySEyzEOB7ltlB/ux38iu2rBQzkjbwRVlkhAGIEDiiYnO2kFOkJp+Z7pUXKyrRRFuFUKt+g==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
|
||||
"version": "4.60.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.60.1.tgz",
|
||||
"integrity": "sha512-L+34Qqil+v5uC0zEubW7uByo78WOCIrBvci69E7sFASRl0X7b/MB6Cqd1lky/CtcSVTydWa2WZwFuWexjS5o6g==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
|
||||
"version": "4.60.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.60.1.tgz",
|
||||
"integrity": "sha512-n83O8rt4v34hgFzlkb1ycniJh7IR5RCIqt6mz1VRJD6pmhRi0CXdmfnLu9dIUS6buzh60IvACM842Ffb3xd6Gg==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm64-gnu": {
|
||||
"version": "4.60.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.60.1.tgz",
|
||||
"integrity": "sha512-Nql7sTeAzhTAja3QXeAI48+/+GjBJ+QmAH13snn0AJSNL50JsDqotyudHyMbO2RbJkskbMbFJfIJKWA6R1LCJQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm64-musl": {
|
||||
"version": "4.60.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.60.1.tgz",
|
||||
"integrity": "sha512-+pUymDhd0ys9GcKZPPWlFiZ67sTWV5UU6zOJat02M1+PiuSGDziyRuI/pPue3hoUwm2uGfxdL+trT6Z9rxnlMA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-loong64-gnu": {
|
||||
"version": "4.60.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.60.1.tgz",
|
||||
"integrity": "sha512-VSvgvQeIcsEvY4bKDHEDWcpW4Yw7BtlKG1GUT4FzBUlEKQK0rWHYBqQt6Fm2taXS+1bXvJT6kICu5ZwqKCnvlQ==",
|
||||
"cpu": [
|
||||
"loong64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-loong64-musl": {
|
||||
"version": "4.60.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.60.1.tgz",
|
||||
"integrity": "sha512-4LqhUomJqwe641gsPp6xLfhqWMbQV04KtPp7/dIp0nzPxAkNY1AbwL5W0MQpcalLYk07vaW9Kp1PBhdpZYYcEw==",
|
||||
"cpu": [
|
||||
"loong64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-ppc64-gnu": {
|
||||
"version": "4.60.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.60.1.tgz",
|
||||
"integrity": "sha512-tLQQ9aPvkBxOc/EUT6j3pyeMD6Hb8QF2BTBnCQWP/uu1lhc9AIrIjKnLYMEroIz/JvtGYgI9dF3AxHZNaEH0rw==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-ppc64-musl": {
|
||||
"version": "4.60.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.60.1.tgz",
|
||||
"integrity": "sha512-RMxFhJwc9fSXP6PqmAz4cbv3kAyvD1etJFjTx4ONqFP9DkTkXsAMU4v3Vyc5BgzC+anz7nS/9tp4obsKfqkDHg==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
|
||||
"version": "4.60.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.60.1.tgz",
|
||||
"integrity": "sha512-QKgFl+Yc1eEk6MmOBfRHYF6lTxiiiV3/z/BRrbSiW2I7AFTXoBFvdMEyglohPj//2mZS4hDOqeB0H1ACh3sBbg==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-riscv64-musl": {
|
||||
"version": "4.60.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.60.1.tgz",
|
||||
"integrity": "sha512-RAjXjP/8c6ZtzatZcA1RaQr6O1TRhzC+adn8YZDnChliZHviqIjmvFwHcxi4JKPSDAt6Uhf/7vqcBzQJy0PDJg==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-s390x-gnu": {
|
||||
"version": "4.60.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.60.1.tgz",
|
||||
"integrity": "sha512-wcuocpaOlaL1COBYiA89O6yfjlp3RwKDeTIA0hM7OpmhR1Bjo9j31G1uQVpDlTvwxGn2nQs65fBFL5UFd76FcQ==",
|
||||
"cpu": [
|
||||
"s390x"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-x64-gnu": {
|
||||
"version": "4.60.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.60.1.tgz",
|
||||
"integrity": "sha512-77PpsFQUCOiZR9+LQEFg9GClyfkNXj1MP6wRnzYs0EeWbPcHs02AXu4xuUbM1zhwn3wqaizle3AEYg5aeoohhg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-x64-musl": {
|
||||
"version": "4.60.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.60.1.tgz",
|
||||
"integrity": "sha512-5cIATbk5vynAjqqmyBjlciMJl1+R/CwX9oLk/EyiFXDWd95KpHdrOJT//rnUl4cUcskrd0jCCw3wpZnhIHdD9w==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-openbsd-x64": {
|
||||
"version": "4.60.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.60.1.tgz",
|
||||
"integrity": "sha512-cl0w09WsCi17mcmWqqglez9Gk8isgeWvoUZ3WiJFYSR3zjBQc2J5/ihSjpl+VLjPqjQ/1hJRcqBfLjssREQILw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"openbsd"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-openharmony-arm64": {
|
||||
"version": "4.60.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.60.1.tgz",
|
||||
"integrity": "sha512-4Cv23ZrONRbNtbZa37mLSueXUCtN7MXccChtKpUnQNgF010rjrjfHx3QxkS2PI7LqGT5xXyYs1a7LbzAwT0iCA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"openharmony"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-arm64-msvc": {
|
||||
"version": "4.60.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.60.1.tgz",
|
||||
"integrity": "sha512-i1okWYkA4FJICtr7KpYzFpRTHgy5jdDbZiWfvny21iIKky5YExiDXP+zbXzm3dUcFpkEeYNHgQ5fuG236JPq0g==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-ia32-msvc": {
|
||||
"version": "4.60.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.60.1.tgz",
|
||||
"integrity": "sha512-u09m3CuwLzShA0EYKMNiFgcjjzwqtUMLmuCJLeZWjjOYA3IT2Di09KaxGBTP9xVztWyIWjVdsB2E9goMjZvTQg==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-x64-gnu": {
|
||||
"version": "4.60.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.60.1.tgz",
|
||||
"integrity": "sha512-k+600V9Zl1CM7eZxJgMyTUzmrmhB/0XZnF4pRypKAlAgxmedUA+1v9R+XOFv56W4SlHEzfeMtzujLJD22Uz5zg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-x64-msvc": {
|
||||
"version": "4.60.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.60.1.tgz",
|
||||
"integrity": "sha512-lWMnixq/QzxyhTV6NjQJ4SFo1J6PvOX8vUx5Wb4bBPsEb+8xZ89Bz6kOXpfXj9ak9AHTQVQzlgzBEc1SyM27xQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
]
|
||||
},
|
||||
"node_modules/@types/estree": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
|
||||
"integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/esbuild": {
|
||||
"version": "0.21.5",
|
||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz",
|
||||
"integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"esbuild": "bin/esbuild"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@esbuild/aix-ppc64": "0.21.5",
|
||||
"@esbuild/android-arm": "0.21.5",
|
||||
"@esbuild/android-arm64": "0.21.5",
|
||||
"@esbuild/android-x64": "0.21.5",
|
||||
"@esbuild/darwin-arm64": "0.21.5",
|
||||
"@esbuild/darwin-x64": "0.21.5",
|
||||
"@esbuild/freebsd-arm64": "0.21.5",
|
||||
"@esbuild/freebsd-x64": "0.21.5",
|
||||
"@esbuild/linux-arm": "0.21.5",
|
||||
"@esbuild/linux-arm64": "0.21.5",
|
||||
"@esbuild/linux-ia32": "0.21.5",
|
||||
"@esbuild/linux-loong64": "0.21.5",
|
||||
"@esbuild/linux-mips64el": "0.21.5",
|
||||
"@esbuild/linux-ppc64": "0.21.5",
|
||||
"@esbuild/linux-riscv64": "0.21.5",
|
||||
"@esbuild/linux-s390x": "0.21.5",
|
||||
"@esbuild/linux-x64": "0.21.5",
|
||||
"@esbuild/netbsd-x64": "0.21.5",
|
||||
"@esbuild/openbsd-x64": "0.21.5",
|
||||
"@esbuild/sunos-x64": "0.21.5",
|
||||
"@esbuild/win32-arm64": "0.21.5",
|
||||
"@esbuild/win32-ia32": "0.21.5",
|
||||
"@esbuild/win32-x64": "0.21.5"
|
||||
}
|
||||
},
|
||||
"node_modules/fsevents": {
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
|
||||
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/nanoid": {
|
||||
"version": "3.3.11",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
|
||||
"integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/ai"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"nanoid": "bin/nanoid.cjs"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/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/postcss": {
|
||||
"version": "8.5.9",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.9.tgz",
|
||||
"integrity": "sha512-7a70Nsot+EMX9fFU3064K/kdHWZqGVY+BADLyXc8Dfv+mTLLVl6JzJpPaCZ2kQL9gIJvKXSLMHhqdRRjwQeFtw==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/postcss/"
|
||||
},
|
||||
{
|
||||
"type": "tidelift",
|
||||
"url": "https://tidelift.com/funding/github/npm/postcss"
|
||||
},
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/ai"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"nanoid": "^3.3.11",
|
||||
"picocolors": "^1.1.1",
|
||||
"source-map-js": "^1.2.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^10 || ^12 || >=14"
|
||||
}
|
||||
},
|
||||
"node_modules/rollup": {
|
||||
"version": "4.60.1",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.60.1.tgz",
|
||||
"integrity": "sha512-VmtB2rFU/GroZ4oL8+ZqXgSA38O6GR8KSIvWmEFv63pQ0G6KaBH9s07PO8XTXP4vI+3UJUEypOfjkGfmSBBR0w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/estree": "1.0.8"
|
||||
},
|
||||
"bin": {
|
||||
"rollup": "dist/bin/rollup"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0",
|
||||
"npm": ">=8.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@rollup/rollup-android-arm-eabi": "4.60.1",
|
||||
"@rollup/rollup-android-arm64": "4.60.1",
|
||||
"@rollup/rollup-darwin-arm64": "4.60.1",
|
||||
"@rollup/rollup-darwin-x64": "4.60.1",
|
||||
"@rollup/rollup-freebsd-arm64": "4.60.1",
|
||||
"@rollup/rollup-freebsd-x64": "4.60.1",
|
||||
"@rollup/rollup-linux-arm-gnueabihf": "4.60.1",
|
||||
"@rollup/rollup-linux-arm-musleabihf": "4.60.1",
|
||||
"@rollup/rollup-linux-arm64-gnu": "4.60.1",
|
||||
"@rollup/rollup-linux-arm64-musl": "4.60.1",
|
||||
"@rollup/rollup-linux-loong64-gnu": "4.60.1",
|
||||
"@rollup/rollup-linux-loong64-musl": "4.60.1",
|
||||
"@rollup/rollup-linux-ppc64-gnu": "4.60.1",
|
||||
"@rollup/rollup-linux-ppc64-musl": "4.60.1",
|
||||
"@rollup/rollup-linux-riscv64-gnu": "4.60.1",
|
||||
"@rollup/rollup-linux-riscv64-musl": "4.60.1",
|
||||
"@rollup/rollup-linux-s390x-gnu": "4.60.1",
|
||||
"@rollup/rollup-linux-x64-gnu": "4.60.1",
|
||||
"@rollup/rollup-linux-x64-musl": "4.60.1",
|
||||
"@rollup/rollup-openbsd-x64": "4.60.1",
|
||||
"@rollup/rollup-openharmony-arm64": "4.60.1",
|
||||
"@rollup/rollup-win32-arm64-msvc": "4.60.1",
|
||||
"@rollup/rollup-win32-ia32-msvc": "4.60.1",
|
||||
"@rollup/rollup-win32-x64-gnu": "4.60.1",
|
||||
"@rollup/rollup-win32-x64-msvc": "4.60.1",
|
||||
"fsevents": "~2.3.2"
|
||||
}
|
||||
},
|
||||
"node_modules/source-map-js": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
|
||||
"integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/vite": {
|
||||
"version": "5.4.21",
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz",
|
||||
"integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"esbuild": "^0.21.3",
|
||||
"postcss": "^8.4.43",
|
||||
"rollup": "^4.20.0"
|
||||
},
|
||||
"bin": {
|
||||
"vite": "bin/vite.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.0.0 || >=20.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/vitejs/vite?sponsor=1"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"fsevents": "~2.3.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/node": "^18.0.0 || >=20.0.0",
|
||||
"less": "*",
|
||||
"lightningcss": "^1.21.0",
|
||||
"sass": "*",
|
||||
"sass-embedded": "*",
|
||||
"stylus": "*",
|
||||
"sugarss": "*",
|
||||
"terser": "^5.4.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/node": {
|
||||
"optional": true
|
||||
},
|
||||
"less": {
|
||||
"optional": true
|
||||
},
|
||||
"lightningcss": {
|
||||
"optional": true
|
||||
},
|
||||
"sass": {
|
||||
"optional": true
|
||||
},
|
||||
"sass-embedded": {
|
||||
"optional": true
|
||||
},
|
||||
"stylus": {
|
||||
"optional": true
|
||||
},
|
||||
"sugarss": {
|
||||
"optional": true
|
||||
},
|
||||
"terser": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
14
package.json
Normal file
14
package.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"name": "canopy-game",
|
||||
"private": true,
|
||||
"version": "0.0.1",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"devDependencies": {
|
||||
"vite": "^5.4.19"
|
||||
}
|
||||
}
|
||||
504
plan.md
Normal file
504
plan.md
Normal file
@@ -0,0 +1,504 @@
|
||||
# Canopy Refactor And Rules Expansion Plan
|
||||
|
||||
## Goals
|
||||
|
||||
- Convert the game from JavaScript to TypeScript.
|
||||
- Refactor the single-file implementation into small rules and UI modules.
|
||||
- Fix the turn-order leverage problem with a public initiative seat draft.
|
||||
- Add a public weather/effect card draft-ban phase to break symmetry.
|
||||
- Add an alternate per-turn income mode with extra positional costs for balance.
|
||||
|
||||
## Recommended Foundation
|
||||
|
||||
- Use plain TypeScript with typed domain models and pure rules modules.
|
||||
- Do not migrate to a board-game framework during this feature pass.
|
||||
- Keep rendering simple and browser-native for now.
|
||||
- Treat the game as a deterministic rules engine with DOM rendering layered on top.
|
||||
|
||||
Why this approach:
|
||||
|
||||
- The game is turn-based and rules-heavy, not entity-heavy.
|
||||
- ECS-style libraries are a poor fit for this problem.
|
||||
- `boardgame.io` is the main browser board-game framework, but it would expand scope too much for this refactor.
|
||||
- If formal phase handling becomes painful later, `XState` is the best follow-up addition.
|
||||
|
||||
## Card System Goals
|
||||
|
||||
The weather/effect cards should:
|
||||
|
||||
- be readable from a TV screen
|
||||
- be resolved with perfect information
|
||||
- create asymmetric incentives each round
|
||||
- be strong enough to disrupt mirror play
|
||||
- avoid too much arithmetic or long text
|
||||
- mostly modify incentives, not replace the core game
|
||||
|
||||
## Card Market Structure
|
||||
|
||||
Recommended round flow:
|
||||
|
||||
1. Determine round initiative order.
|
||||
2. Reveal `playerCount + 2` public cards.
|
||||
3. In initiative order, each player takes exactly one action:
|
||||
- draft one card for the round, or
|
||||
- ban one card from the row
|
||||
4. Drafted cards become active global rules for the round.
|
||||
5. Banned cards are removed.
|
||||
6. Undrafted cards are discarded.
|
||||
|
||||
Recommended limits:
|
||||
|
||||
- Start with 8 to 14 total cards.
|
||||
- Keep active cards per round low, ideally 1 to 3.
|
||||
- Prefer cards with one sentence and one number.
|
||||
|
||||
## Candidate Weather / Effect Cards
|
||||
|
||||
These are written to fit a large shared screen. The title should be the main thing players read; the rule text should stay short.
|
||||
|
||||
### Economy / Position Cards
|
||||
|
||||
- **Leaf Surge**: Each leaf gains `+1` energy.
|
||||
- **Branching Season**: Each branch beyond your first gives `+1` energy.
|
||||
- **West Light**: Left third columns give `+1` energy.
|
||||
- **East Light**: Right third columns give `+1` energy.
|
||||
- **High Noon**: Center third columns give `+1` energy.
|
||||
- **Sun Ladder**: Straight-up growth costs `-1` once per turn.
|
||||
- **Storehouse**: Banking is enabled this round.
|
||||
- **Shade Cloth**: Your covered nodes still count for `1` energy.
|
||||
|
||||
### Conflict / Interaction Cards
|
||||
|
||||
- **Sap Theft**: When your branch crosses an opponent branch, gain `+1` energy.
|
||||
- **Hedge Trimmer**: Branches above the lowest player height are cut down before scoring.
|
||||
- **Disease Sweep**: Before each turn, that player loses `1` energy.
|
||||
- **Stalemate**: Contested columns give no energy.
|
||||
- **Split Light**: Contested columns give half energy to each tied player.
|
||||
- **Shared Light**: Contested columns give full energy to every tied player.
|
||||
|
||||
### Additional Cards Worth Considering
|
||||
|
||||
- **Root Pulse**: Root shifts cost `0` this round.
|
||||
- **Still Soil**: Root shifts are disabled this round.
|
||||
- **Thin Air**: Diagonal growth costs `+1`.
|
||||
- **Tailwind**: Diagonal growth costs `-1` once per turn.
|
||||
- **Canopy Tax**: The tallest branch of each player costs `+1` to extend.
|
||||
- **Undergrowth**: The first growth each turn costs `0`.
|
||||
- **Dry Season**: Banking loses `1` energy when used.
|
||||
- **Tall Reward**: Your tallest leaf gains `+2` energy.
|
||||
- **Wide Reward**: If you control the most columns, gain `+2` energy.
|
||||
- **Twig Bloom**: New leaves created this round gain `+1` energy when scored.
|
||||
- **Heavy Shade**: Columns with 2 or more players present count as contested.
|
||||
- **Sunbreak**: Empty columns next to your branch give `+1` energy.
|
||||
|
||||
## Best Initial Card Set
|
||||
|
||||
For the first implementation, avoid the cards that require the most new geometry or crossing logic. Start with cards that reuse existing board evaluation.
|
||||
|
||||
### Phase 1 card set
|
||||
|
||||
- **Leaf Surge**: Each leaf gains `+1` energy.
|
||||
- **Branching Season**: Each branch beyond your first gives `+1` energy.
|
||||
- **West Light**: Left third columns give `+1` energy.
|
||||
- **East Light**: Right third columns give `+1` energy.
|
||||
- **High Noon**: Center third columns give `+1` energy.
|
||||
- **Sun Ladder**: Straight-up growth costs `-1` once per turn.
|
||||
- **Storehouse**: Banking is enabled this round.
|
||||
- **Stalemate**: Contested columns give no energy.
|
||||
- **Split Light**: Contested columns give half energy to each tied player.
|
||||
- **Shared Light**: Contested columns give full energy to every tied player.
|
||||
|
||||
### Phase 2 card set
|
||||
|
||||
Add later after the rules core is stable:
|
||||
|
||||
- **Shade Cloth**
|
||||
- **Sap Theft**
|
||||
- **Hedge Trimmer**
|
||||
- **Disease Sweep**
|
||||
- **Root Pulse**
|
||||
- **Still Soil**
|
||||
|
||||
Why split it this way:
|
||||
|
||||
- Phase 1 mostly changes scoring and move costs.
|
||||
- Phase 2 needs new concepts like coverage protection, branch crossing checks, pruning, or per-turn drain.
|
||||
|
||||
## Rules Clarifications To Lock Down
|
||||
|
||||
### Initiative seat draft
|
||||
|
||||
- Players use a pure seat-selection token, not growth bidding.
|
||||
- Players choose specific seat numbers.
|
||||
- Seats are drafted publicly in bidding order, so no seat conflict resolution is needed.
|
||||
- Bidding order is determined by setup rule:
|
||||
- rotating from a random starting anchor, or
|
||||
- lowest lifetime growth income first
|
||||
|
||||
### Lifetime growth income
|
||||
|
||||
Track all growth ever gained.
|
||||
|
||||
This should include:
|
||||
|
||||
- starting growth at game start
|
||||
- round-end sunlight income
|
||||
- per-turn sunlight income
|
||||
- seat bonus growth
|
||||
- card-generated growth
|
||||
- random event growth like sunbeam bonuses
|
||||
- recovered or protected growth if the game records that as gain
|
||||
|
||||
This should not double-count:
|
||||
|
||||
- banked energy carried into a later round after it was already counted when first gained
|
||||
|
||||
Implementation note:
|
||||
|
||||
- Add a dedicated `lifetimeGrowthIncome` stat to each player.
|
||||
- Update it only at the moment growth is awarded.
|
||||
|
||||
### Banking
|
||||
|
||||
Current open issue:
|
||||
|
||||
- Banking should likely become conditional on a round card rather than always-on.
|
||||
|
||||
Recommended rule:
|
||||
|
||||
- By default, banking is disabled.
|
||||
- `Storehouse` enables banking for that round.
|
||||
|
||||
Why:
|
||||
|
||||
- This helps reduce the economy snowball.
|
||||
- It gives the weather deck a meaningful strategic lever.
|
||||
|
||||
### Contested columns
|
||||
|
||||
The current game reads column ownership by the top intercepting node. Weather cards that talk about contested columns require a clear definition.
|
||||
|
||||
Recommended definition:
|
||||
|
||||
- A column is contested if 2 or more players have a node in that column and they are tied under the active contest rule.
|
||||
|
||||
Open design task:
|
||||
|
||||
- Decide whether contest is based on equal top row, any shared presence, or special card-defined presence.
|
||||
|
||||
Recommended default:
|
||||
|
||||
- Contest means two or more players share the best topmost position for that column.
|
||||
|
||||
This keeps the rule closest to current sunlight logic.
|
||||
|
||||
### Leaves and branches
|
||||
|
||||
These terms need firm technical definitions before implementation.
|
||||
|
||||
Recommended definitions:
|
||||
|
||||
- `leaf`: a node with no children
|
||||
- `branch`: a root-to-leaf path, or more simply for scoring, each leaf represents one branch
|
||||
|
||||
Recommended implementation simplification:
|
||||
|
||||
- Use `leaf count` instead of true branch count in the first pass.
|
||||
- Rename card text if needed to match the actual rule.
|
||||
|
||||
Example:
|
||||
|
||||
- Instead of `Branching Season: Each branch beyond your first gives +1 energy`, consider `Leaf Burst: Each leaf after your first gives +1 energy`.
|
||||
|
||||
This is much easier to explain and compute.
|
||||
|
||||
### Branch crossing
|
||||
|
||||
`Sap Theft` needs a precise crossing rule.
|
||||
|
||||
Risk:
|
||||
|
||||
- The current data model stores branch segments, but crossing detection between diagonal edges is new logic.
|
||||
|
||||
Recommendation:
|
||||
|
||||
- Do not include crossing-based cards in phase 1.
|
||||
- If added later, count only actual geometric edge intersections between different players' segments.
|
||||
|
||||
### Hedge Trimmer
|
||||
|
||||
This card is flavorful but potentially destructive and swingy.
|
||||
|
||||
Risks:
|
||||
|
||||
- Requires pruning nodes and edges from the board.
|
||||
- Can invalidate pending move assumptions.
|
||||
- Needs a clear “same level” definition.
|
||||
|
||||
Recommendation:
|
||||
|
||||
- Delay to phase 2.
|
||||
- Define it as: `Before scoring, all nodes above the shortest tallest-player height are removed.`
|
||||
- Only apply between turns or at round end, never mid-turn.
|
||||
|
||||
### Disease Sweep
|
||||
|
||||
This can be implemented in more than one way.
|
||||
|
||||
Choices:
|
||||
|
||||
- lose growth before each turn
|
||||
- lose sunlight before end-of-round tally
|
||||
- kill twigs as the current disease event does
|
||||
|
||||
Recommendation:
|
||||
|
||||
- For a card, use the simple economy version: `Before each turn, that player loses 1 energy.`
|
||||
- Keep the existing random disease event separate.
|
||||
|
||||
## Implementation Risks
|
||||
|
||||
### Player identity and turn order are currently coupled
|
||||
|
||||
Current risk:
|
||||
|
||||
- `player.id` is treated as both a stable identity and an array index.
|
||||
|
||||
Plan:
|
||||
|
||||
- Keep `players` in stable id order.
|
||||
- Introduce `turnOrder: PlayerId[]` for seats and active order.
|
||||
- Update turn flow and render helpers to use `turnOrder` where needed.
|
||||
|
||||
### The game needs explicit phases
|
||||
|
||||
Current risk:
|
||||
|
||||
- The code uses ad hoc flow control plus animation locks.
|
||||
|
||||
Plan:
|
||||
|
||||
- Add a typed phase model:
|
||||
- `initiative_bid`
|
||||
- `weather_draft`
|
||||
- `turn`
|
||||
- `round_end`
|
||||
- `game_over`
|
||||
|
||||
### The code is currently one large file
|
||||
|
||||
Current risk:
|
||||
|
||||
- Rules, state, rendering, and DOM events are tightly mixed.
|
||||
|
||||
Plan:
|
||||
|
||||
- Convert to TypeScript first.
|
||||
- Extract pure rules before feature work.
|
||||
|
||||
### Per-turn income changes the economy deeply
|
||||
|
||||
Current risk:
|
||||
|
||||
- Existing logic assumes income is only awarded between rounds.
|
||||
|
||||
Plan:
|
||||
|
||||
- Keep `round_end` income as the stable default.
|
||||
- Add `per_turn` as an alternate rules path after the initiative and weather phases are working.
|
||||
- Add positional surcharges to slow runaway chaining.
|
||||
|
||||
### TV readability
|
||||
|
||||
Current risk:
|
||||
|
||||
- Too many active modifiers will be hard to track.
|
||||
|
||||
Plan:
|
||||
|
||||
- Cap active cards per round.
|
||||
- Keep card titles short.
|
||||
- Show active effects in one compact panel with icons or one-line summaries.
|
||||
|
||||
### Banking may conflict with weather cards
|
||||
|
||||
Current risk:
|
||||
|
||||
- If banking is always available and also appears on a card, the card has no value.
|
||||
|
||||
Plan:
|
||||
|
||||
- Make banking conditional on round effects, or convert the card into a banking bonus instead of availability.
|
||||
|
||||
### Randomness vs strategy
|
||||
|
||||
Current risk:
|
||||
|
||||
- Too much randomness in the weather row can obscure good play.
|
||||
|
||||
Plan:
|
||||
|
||||
- Start with a small curated deck.
|
||||
- Reveal a modest row each round.
|
||||
- Consider a rotating deck instead of full shuffle if needed after testing.
|
||||
|
||||
## Proposed TypeScript Module Structure
|
||||
|
||||
- `src/main.ts`
|
||||
- `src/constants.ts`
|
||||
- `src/state/types.ts`
|
||||
- `src/state/createGame.ts`
|
||||
- `src/state/reducer.ts`
|
||||
- `src/rules/board.ts`
|
||||
- `src/rules/moves.ts`
|
||||
- `src/rules/scoring.ts`
|
||||
- `src/rules/initiative.ts`
|
||||
- `src/rules/weather.ts`
|
||||
- `src/rules/turnFlow.ts`
|
||||
- `src/ui/renderBoard.ts`
|
||||
- `src/ui/renderSidebar.ts`
|
||||
- `src/ui/renderScoreboard.ts`
|
||||
- `src/ui/renderModals.ts`
|
||||
- `src/app/events.ts`
|
||||
|
||||
## Proposed Type Model
|
||||
|
||||
Core types to introduce early:
|
||||
|
||||
- `PlayerId`
|
||||
- `NodeKey`
|
||||
- `Setup`
|
||||
- `GameState`
|
||||
- `Player`
|
||||
- `Phase`
|
||||
- `TurnMove`
|
||||
- `WeatherCardId`
|
||||
- `WeatherCardDefinition`
|
||||
- `ActiveRoundEffect`
|
||||
|
||||
New setup fields:
|
||||
|
||||
- `initiativeMode: "fixed" | "bid"`
|
||||
- `biddingOrderRule: "rotating" | "lowest_growth_income"`
|
||||
- `incomeTiming: "round_end" | "per_turn"`
|
||||
- `weatherDraftEnabled: boolean`
|
||||
|
||||
New player fields:
|
||||
|
||||
- `lifetimeGrowthIncome: number`
|
||||
|
||||
New game state fields:
|
||||
|
||||
- `phase`
|
||||
- `turnOrder`
|
||||
- `seatChoices`
|
||||
- `initiativeAnchorPlayerId`
|
||||
- `weatherRow`
|
||||
- `draftedWeather`
|
||||
- `bannedWeather`
|
||||
- `activeRoundEffects`
|
||||
|
||||
## Execution Order
|
||||
|
||||
### Milestone 1: TypeScript conversion and safe refactor
|
||||
|
||||
1. Add TypeScript and config.
|
||||
2. Convert `src/main.js` to `src/main.ts` without changing behavior.
|
||||
3. Extract constants and types.
|
||||
4. Extract pure board, move, and scoring helpers.
|
||||
5. Keep current gameplay working exactly as-is.
|
||||
|
||||
### Milestone 2: Turn-order refactor
|
||||
|
||||
1. Separate stable player identity from seat order.
|
||||
2. Introduce `turnOrder`.
|
||||
3. Update active-player logic to walk `turnOrder`.
|
||||
4. Add explicit `phase` handling.
|
||||
|
||||
### Milestone 3: Initiative draft phase
|
||||
|
||||
1. Add setup controls for initiative mode and bidding-order rule.
|
||||
2. Add lifetime growth income tracking.
|
||||
3. Implement rotating bid order.
|
||||
4. Implement lowest-growth-income bid order.
|
||||
5. Add public seat selection modal.
|
||||
6. Apply seat growth bonuses.
|
||||
|
||||
### Milestone 4: Weather draft-ban phase
|
||||
|
||||
1. Define weather card data in `rules/weather.ts`.
|
||||
2. Add setup toggle for weather phase.
|
||||
3. Implement weather row generation.
|
||||
4. Implement draft-or-ban action in seat order.
|
||||
5. Render active effects clearly.
|
||||
6. Apply phase 1 weather cards in scoring and move cost logic.
|
||||
|
||||
### Milestone 5: Per-turn income mode
|
||||
|
||||
1. Add setup control for income timing.
|
||||
2. Implement payout to the active player immediately after their turn.
|
||||
3. Keep round-end mode intact.
|
||||
4. Verify banking and pass logic still make sense.
|
||||
|
||||
### Milestone 6: Distance-based balancing
|
||||
|
||||
1. Add root-distance surcharge support.
|
||||
2. Start with a simple formula such as:
|
||||
- `extraCost = floor((abs(dx) + abs(dy)) / 4)`
|
||||
3. Apply only in `per_turn` mode at first.
|
||||
4. Tune after playtesting.
|
||||
|
||||
### Milestone 7: Phase 2 weather cards
|
||||
|
||||
1. Add crossing-based cards if still desired.
|
||||
2. Add hedge-trimming/pruning cards.
|
||||
3. Add disease drain cards.
|
||||
4. Rebalance text and values based on playtests.
|
||||
|
||||
## Testing Plan
|
||||
|
||||
Add rule-level tests as soon as the core logic is modularized.
|
||||
|
||||
Priority coverage:
|
||||
|
||||
- legal growth moves
|
||||
- root shift legality
|
||||
- scoring by column
|
||||
- contested column resolution modes
|
||||
- seat draft ordering
|
||||
- lifetime growth income tracking
|
||||
- weather draft resolution
|
||||
- weather effect application
|
||||
- per-turn payout behavior
|
||||
- distance surcharge cost calculation
|
||||
|
||||
## Recommended First Shipping Configuration
|
||||
|
||||
- initiative mode: `bid`
|
||||
- bidding order rule: `rotating`
|
||||
- income timing: `round_end`
|
||||
- weather draft: `enabled`
|
||||
- banking: enabled only through `Storehouse`
|
||||
- weather deck: only phase 1 cards
|
||||
|
||||
Why this first:
|
||||
|
||||
- It directly attacks the symmetry problem.
|
||||
- It fixes turn-order leverage without also changing all economy timing at once.
|
||||
- It keeps the new concepts readable for group play.
|
||||
|
||||
## Summary
|
||||
|
||||
The most important design shift is this:
|
||||
|
||||
- turn order becomes a public seat draft
|
||||
- each round gains a public asymmetric card market
|
||||
- mirror play is no longer automatically safe because players can deny and reshape incentives before growth begins
|
||||
|
||||
The best implementation strategy is:
|
||||
|
||||
- TypeScript first
|
||||
- modular rules second
|
||||
- initiative phase third
|
||||
- weather card system fourth
|
||||
- per-turn economy mode after the game flow is stable
|
||||
1508
src/main.js
Normal file
1508
src/main.js
Normal file
File diff suppressed because it is too large
Load Diff
684
src/styles.css
Normal file
684
src/styles.css
Normal file
@@ -0,0 +1,684 @@
|
||||
:root {
|
||||
color-scheme: dark;
|
||||
font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
||||
background:
|
||||
radial-gradient(circle at top, rgba(48, 72, 104, 0.35), transparent 42%),
|
||||
linear-gradient(180deg, #0b1220 0%, #070b13 100%);
|
||||
color: #f4f7fb;
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
min-height: 100vh;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
button,
|
||||
input {
|
||||
font: inherit;
|
||||
}
|
||||
|
||||
input[type="number"],
|
||||
input[type="text"] {
|
||||
width: 100%;
|
||||
min-height: 2.8rem;
|
||||
padding: 0.7rem 0.85rem;
|
||||
border-radius: 0.9rem;
|
||||
border: 1px solid rgba(255, 255, 255, 0.12);
|
||||
background: rgba(255, 255, 255, 0.05);
|
||||
color: #f4f7fb;
|
||||
}
|
||||
|
||||
button {
|
||||
border: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#app {
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.layout {
|
||||
min-height: 100vh;
|
||||
padding: 1rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.85rem;
|
||||
}
|
||||
|
||||
.scoreboard {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
.scoreboard--bottom {
|
||||
align-items: end;
|
||||
}
|
||||
|
||||
.score-card {
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
border-radius: 1.25rem;
|
||||
padding: 0.8rem 1rem;
|
||||
background: linear-gradient(180deg, rgba(255, 255, 255, 0.08), rgba(255, 255, 255, 0.02));
|
||||
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06);
|
||||
}
|
||||
|
||||
.score-card.active {
|
||||
border-color: color-mix(in srgb, var(--player-color) 55%, white);
|
||||
box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.08), 0 0 24px var(--player-glow);
|
||||
}
|
||||
|
||||
.score-card__head,
|
||||
.score-card__numbers,
|
||||
.panel__title-row,
|
||||
.button-row,
|
||||
.setup-grid,
|
||||
.toggle-row,
|
||||
.active-turn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.score-card__head,
|
||||
.panel__title-row,
|
||||
.button-row,
|
||||
.toggle-row {
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.score-card__head h2,
|
||||
.panel h1,
|
||||
.panel h2,
|
||||
.active-turn h2 {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.score-card__numbers {
|
||||
margin-top: 0.65rem;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.score-card__numbers div {
|
||||
display: grid;
|
||||
gap: 0.15rem;
|
||||
}
|
||||
|
||||
.score-card__numbers span,
|
||||
.eyebrow,
|
||||
label span,
|
||||
.log-list p,
|
||||
.status-panel p,
|
||||
.active-turn p {
|
||||
color: rgba(231, 238, 247, 0.72);
|
||||
}
|
||||
|
||||
.score-card__numbers strong {
|
||||
font-size: 1.35rem;
|
||||
}
|
||||
|
||||
.score-value {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.score-value.changed {
|
||||
animation: score-pop 0.7s ease;
|
||||
}
|
||||
|
||||
.player-dot {
|
||||
width: 0.95rem;
|
||||
height: 0.95rem;
|
||||
border-radius: 999px;
|
||||
background: var(--player-color);
|
||||
box-shadow: 0 0 18px var(--player-glow);
|
||||
}
|
||||
|
||||
.game-area {
|
||||
flex: 1;
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1.9fr) minmax(320px, 0.85fr);
|
||||
gap: 0.85rem;
|
||||
min-height: 0;
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
.board-shell,
|
||||
.panel {
|
||||
border-radius: 1.5rem;
|
||||
border: 1px solid rgba(255, 255, 255, 0.08);
|
||||
background: rgba(9, 16, 29, 0.72);
|
||||
backdrop-filter: blur(20px);
|
||||
}
|
||||
|
||||
.board-shell {
|
||||
min-height: 0;
|
||||
padding: 0.8rem;
|
||||
}
|
||||
|
||||
.board {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
max-height: calc(100vh - 10.5rem);
|
||||
aspect-ratio: var(--board-columns) / var(--board-rows);
|
||||
display: grid;
|
||||
gap: 0.32rem;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.board__lines {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
pointer-events: none;
|
||||
filter: drop-shadow(0 0 8px rgba(255, 255, 255, 0.18));
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.board__fx {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
pointer-events: none;
|
||||
z-index: 4;
|
||||
}
|
||||
|
||||
.cell {
|
||||
position: relative;
|
||||
background: rgba(255, 255, 255, 0.03);
|
||||
border-radius: 0.8rem;
|
||||
border: 1px solid rgba(255, 255, 255, 0.05);
|
||||
overflow: hidden;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.cell__shade {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: linear-gradient(180deg, rgba(255, 255, 255, 0.03), var(--column-tint));
|
||||
}
|
||||
|
||||
.cell__root-ring {
|
||||
position: absolute;
|
||||
inset: 18% 18%;
|
||||
border: 1px dashed rgba(255, 255, 255, 0.28);
|
||||
border-radius: 999px;
|
||||
}
|
||||
|
||||
.cell__node,
|
||||
.cell__target-label {
|
||||
position: absolute;
|
||||
inset: 50% auto auto 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
.cell__node {
|
||||
width: min(2.5vw, 1.6rem);
|
||||
height: min(2.5vw, 1.6rem);
|
||||
min-width: 1rem;
|
||||
min-height: 1rem;
|
||||
border-radius: 50%;
|
||||
background: var(--node-color);
|
||||
box-shadow: 0 0 0 0.2rem rgba(255, 255, 255, 0.06), 0 0 1.2rem var(--node-glow);
|
||||
}
|
||||
|
||||
.cell.selected {
|
||||
border-color: rgba(255, 255, 255, 0.55);
|
||||
box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.22);
|
||||
}
|
||||
|
||||
.cell.pending {
|
||||
border-color: rgba(255, 255, 255, 0.28);
|
||||
box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.12), 0 0 18px rgba(255, 255, 255, 0.08);
|
||||
}
|
||||
|
||||
.cell.pending .cell__node {
|
||||
box-shadow: 0 0 0 0.22rem rgba(255, 255, 255, 0.08), 0 0 1.4rem var(--node-glow), 0 0 2rem rgba(255, 255, 255, 0.08);
|
||||
}
|
||||
|
||||
.board__drop-layer {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
pointer-events: none;
|
||||
overflow: hidden;
|
||||
z-index: 5;
|
||||
}
|
||||
|
||||
.board__energy-layer {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
pointer-events: none;
|
||||
z-index: 4;
|
||||
}
|
||||
|
||||
.board__energy-cell {
|
||||
position: absolute;
|
||||
border-radius: 0.8rem;
|
||||
background:
|
||||
radial-gradient(circle at 50% 50%, rgba(255, 255, 255, 0.95), color-mix(in srgb, var(--flash-color) 70%, #ffe08a) 34%, rgba(255, 224, 138, 0.18) 72%, transparent 100%),
|
||||
linear-gradient(180deg, rgba(255, 255, 255, 0.18), transparent);
|
||||
box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.12), 0 0 18px color-mix(in srgb, var(--flash-color) 55%, #ffe08a);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.board__energy-cell--sunlight {
|
||||
inset: 12%;
|
||||
background:
|
||||
linear-gradient(180deg, rgba(255, 244, 214, 0.05), rgba(255, 244, 214, 0.008)),
|
||||
radial-gradient(circle at 50% 50%, rgba(255, 242, 196, 0.11), color-mix(in srgb, var(--flash-color) 10%, #ffe3a3) 42%, rgba(255, 221, 128, 0.03) 72%, transparent 100%);
|
||||
box-shadow: inset 0 0 0 1px rgba(255, 245, 224, 0.02), 0 0 6px color-mix(in srgb, var(--flash-color) 8%, #ffe3a3);
|
||||
}
|
||||
|
||||
.board--sunlight .board__energy-cell--sunlight,
|
||||
.board--branches .board__energy-cell,
|
||||
.board--bonus .board__energy-cell--bonus {
|
||||
animation: energy-cell-flash 0.48s ease forwards;
|
||||
animation-delay: var(--flash-delay, 0ms);
|
||||
}
|
||||
|
||||
.board__energy-cell--bonus {
|
||||
box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.18), 0 0 22px rgba(255, 216, 94, 0.9);
|
||||
}
|
||||
|
||||
.board--bonus .board__drop--bonus {
|
||||
animation: sunlight-drop 0.85s cubic-bezier(0.2, 0.7, 0.2, 1) forwards;
|
||||
}
|
||||
|
||||
.board__drop-core,
|
||||
.board__drop-spark {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
border-radius: 999px;
|
||||
}
|
||||
|
||||
.board__drop-core {
|
||||
background: radial-gradient(circle at 35% 30%, rgba(255, 255, 255, 0.98), color-mix(in srgb, var(--drop-color) 72%, #ffe38a) 45%, rgba(255, 227, 138, 0.18) 100%);
|
||||
box-shadow: 0 0 18px color-mix(in srgb, var(--drop-color) 40%, #ffe38a), 0 0 32px rgba(255, 236, 174, 0.65);
|
||||
}
|
||||
|
||||
.board__drop-spark {
|
||||
inset: 35%;
|
||||
border: 1px solid rgba(255, 248, 220, 0.95);
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.board__drop-spark--a { transform: translate(-0.8rem, -0.15rem) scale(0.55); }
|
||||
.board__drop-spark--b { transform: translate(0.75rem, -0.1rem) scale(0.45); }
|
||||
.board__drop-spark--c { transform: translate(0.1rem, -0.75rem) scale(0.35); }
|
||||
|
||||
.board__root-burst,
|
||||
.board__disease-mark,
|
||||
.board__sunbeam-burst {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.board__root-burst circle,
|
||||
.board__sunbeam-burst {
|
||||
fill: color-mix(in srgb, var(--burst-color, #ffd85e) 70%, white);
|
||||
stroke: rgba(255, 255, 255, 0.65);
|
||||
stroke-width: 0.35;
|
||||
}
|
||||
|
||||
.board__root-burst text {
|
||||
fill: #08111c;
|
||||
font-size: 2.1px;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.board__disease-mark circle {
|
||||
fill: rgba(162, 255, 142, 0.2);
|
||||
stroke: rgba(162, 255, 142, 0.9);
|
||||
stroke-width: 0.35;
|
||||
}
|
||||
|
||||
.board__disease-mark path {
|
||||
stroke: rgba(162, 255, 142, 1);
|
||||
stroke-width: 0.5;
|
||||
stroke-linecap: round;
|
||||
}
|
||||
|
||||
.board--branches .board__root-burst,
|
||||
.board--events .board__root-burst,
|
||||
.board--events .board__disease-mark,
|
||||
.board--bonus .board__sunbeam-burst,
|
||||
.board--events .board__sunbeam-burst {
|
||||
animation: pop-fade 0.8s ease forwards;
|
||||
animation-delay: var(--trace-delay, 0ms);
|
||||
}
|
||||
|
||||
.board__sunbeam-burst text {
|
||||
fill: #08111c;
|
||||
font-size: 2.1px;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.cell.target {
|
||||
border-color: rgba(255, 255, 255, 0.22);
|
||||
background: rgba(255, 255, 255, 0.05);
|
||||
}
|
||||
|
||||
.cell.target:hover {
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.cell__target-label {
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
border-radius: 999px;
|
||||
background: rgba(255, 255, 255, 0.09);
|
||||
border: 1px solid rgba(255, 255, 255, 0.18);
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.panel {
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.controls-panel {
|
||||
display: grid;
|
||||
gap: 0.8rem;
|
||||
}
|
||||
|
||||
.panel__actions {
|
||||
display: flex;
|
||||
gap: 0.55rem;
|
||||
}
|
||||
|
||||
.modal-backdrop {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
padding: 1.25rem;
|
||||
background: rgba(3, 8, 16, 0.72);
|
||||
backdrop-filter: blur(14px);
|
||||
z-index: 20;
|
||||
}
|
||||
|
||||
.modal {
|
||||
width: min(1180px, 100%);
|
||||
max-height: min(92vh, 980px);
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.modal-setup-grid,
|
||||
.modal-grid {
|
||||
display: grid;
|
||||
gap: 0.9rem;
|
||||
}
|
||||
|
||||
.modal-setup-grid {
|
||||
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
|
||||
}
|
||||
|
||||
.modal-grid {
|
||||
margin-top: 0.9rem;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.modal-actions {
|
||||
margin-top: 0.9rem;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.eyebrow {
|
||||
margin: 0 0 0.3rem;
|
||||
font-size: 0.82rem;
|
||||
letter-spacing: 0.12em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.setup-grid {
|
||||
gap: 1rem;
|
||||
align-items: end;
|
||||
}
|
||||
|
||||
.setup-grid label {
|
||||
flex: 1;
|
||||
display: grid;
|
||||
gap: 0.35rem;
|
||||
}
|
||||
|
||||
.seed-editor {
|
||||
display: grid;
|
||||
gap: 0.65rem;
|
||||
padding: 0.8rem;
|
||||
border-radius: 1rem;
|
||||
background: rgba(255, 255, 255, 0.03);
|
||||
border: 1px solid rgba(255, 255, 255, 0.06);
|
||||
}
|
||||
|
||||
.seed-row {
|
||||
display: grid;
|
||||
gap: 0.35rem;
|
||||
}
|
||||
|
||||
.order-row,
|
||||
.order-row__label,
|
||||
.order-row__actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.order-row {
|
||||
justify-content: space-between;
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
.order-row__label {
|
||||
gap: 0.6rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.order-row__actions {
|
||||
gap: 0.4rem;
|
||||
}
|
||||
|
||||
.mini-button {
|
||||
min-height: 2rem;
|
||||
padding: 0.35rem 0.65rem;
|
||||
border-radius: 0.7rem;
|
||||
background: rgba(255, 255, 255, 0.08);
|
||||
color: #f4f7fb;
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.seed-help {
|
||||
margin: 0;
|
||||
color: rgba(231, 238, 247, 0.72);
|
||||
}
|
||||
|
||||
.randomize-button {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
input[type="range"] {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.active-turn {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: 0.35rem;
|
||||
padding: 0.8rem;
|
||||
border-radius: 1rem;
|
||||
background: linear-gradient(135deg, color-mix(in srgb, var(--player-color) 22%, rgba(255, 255, 255, 0.04)), rgba(255, 255, 255, 0.04));
|
||||
border: 1px solid color-mix(in srgb, var(--player-color) 35%, rgba(255, 255, 255, 0.08));
|
||||
}
|
||||
|
||||
.root-shift-row {
|
||||
display: flex;
|
||||
gap: 0.55rem;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.root-shift-button {
|
||||
min-height: 2.2rem;
|
||||
}
|
||||
|
||||
.button-row {
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
.button-row button,
|
||||
.ghost-button {
|
||||
min-height: 2.7rem;
|
||||
padding: 0.65rem 0.9rem;
|
||||
border-radius: 0.95rem;
|
||||
background: #f4f7fb;
|
||||
color: #0a1020;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.ghost-button,
|
||||
#finish-game {
|
||||
background: rgba(255, 255, 255, 0.08);
|
||||
color: #f4f7fb;
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
button:disabled {
|
||||
opacity: 0.45;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.log-list {
|
||||
display: grid;
|
||||
gap: 0.55rem;
|
||||
max-height: 18vh;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.log-list p,
|
||||
.status-panel p,
|
||||
.active-turn p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.event-note {
|
||||
color: #ffd577;
|
||||
}
|
||||
|
||||
@keyframes sunlight-drop {
|
||||
0% {
|
||||
opacity: 0;
|
||||
top: -0.9rem;
|
||||
transform: scale(0.65);
|
||||
}
|
||||
|
||||
12% {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
85% {
|
||||
opacity: 1;
|
||||
top: calc(var(--drop-end) - 0.55rem);
|
||||
transform: scale(1);
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 0;
|
||||
top: calc(var(--drop-end) - 0.55rem);
|
||||
transform: scale(1.25);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes pop-fade {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: scale(0.65);
|
||||
}
|
||||
|
||||
25% {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes energy-cell-flash {
|
||||
0% {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
20% {
|
||||
opacity: 0.98;
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes score-pop {
|
||||
0% {
|
||||
transform: scale(0.88);
|
||||
color: #fff7d6;
|
||||
text-shadow: 0 0 0 rgba(255, 235, 153, 0);
|
||||
}
|
||||
|
||||
35% {
|
||||
transform: scale(1.18);
|
||||
color: #ffe480;
|
||||
text-shadow: 0 0 16px rgba(255, 228, 128, 0.9);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: scale(1);
|
||||
color: inherit;
|
||||
text-shadow: 0 0 0 rgba(255, 235, 153, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 1100px) {
|
||||
.game-area {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.modal-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.board {
|
||||
max-height: none;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 720px) {
|
||||
.layout {
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.scoreboard {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.score-card__numbers {
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.cell__node {
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user