diff --git a/.gitignore b/.gitignore index bf7510b..aa6e3bd 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,28 @@ dist server/public vite.config.ts.* *.tar.gz - .local -.env \ No newline at end of file +.env + +# Test/debug artifacts +*.png +!client/public/**/*.png +!screenshots/*.png +coverage/ +.playwright-mcp/ + +# IDE +.idea/ +.vscode/ +*.swp +*.swo + +# Logs +*.log +firebase-debug.log + +# OS +Thumbs.db + +# Claude worktrees +.claude/worktrees/ diff --git a/.playwright-mcp/console-2026-02-12T19-26-49-011Z.log b/.playwright-mcp/console-2026-02-12T19-26-49-011Z.log deleted file mode 100644 index bc4aae6..0000000 --- a/.playwright-mcp/console-2026-02-12T19-26-49-011Z.log +++ /dev/null @@ -1,122 +0,0 @@ -[ 560ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:196 -[ 561ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:250 -[ 755ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 -[ 496642ms] [ERROR] Warning: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons: -1. You might have mismatching versions of React and the renderer (such as React DOM) -2. You might be breaking the Rules of Hooks -3. You might have more than one copy of React in the same app -See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem. @ http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-3TFVT2CW.js?v=b243a4a6:135 -[ 496643ms] [ERROR] Warning: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons: -1. You might have mismatching versions of React and the renderer (such as React DOM) -2. You might be breaking the Rules of Hooks -3. You might have more than one copy of React in the same app -See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem. @ http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-3TFVT2CW.js?v=b243a4a6:135 -[ 496643ms] [ERROR] Global error caught: ErrorEvent @ http://localhost:5000/src/components/game/HuntersPath.tsx:883 -[ 496653ms] [ERROR] Warning: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons: -1. You might have mismatching versions of React and the renderer (such as React DOM) -2. You might be breaking the Rules of Hooks -3. You might have more than one copy of React in the same app -See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem. @ http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-3TFVT2CW.js?v=b243a4a6:135 -[ 496653ms] [ERROR] Warning: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons: -1. You might have mismatching versions of React and the renderer (such as React DOM) -2. You might be breaking the Rules of Hooks -3. You might have more than one copy of React in the same app -See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem. @ http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-3TFVT2CW.js?v=b243a4a6:135 -[ 496653ms] [ERROR] Global error caught: ErrorEvent @ http://localhost:5000/src/components/game/HuntersPath.tsx:883 -[ 496656ms] [ERROR] TypeError: Cannot read properties of null (reading 'useMemo') - at useMemo (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-3TFVT2CW.js?v=b243a4a6:1094:29) - at AnimatePresence (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/framer-motion.js?v=05c08439:7802:54) - at renderWithHooks (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=7a4c9bf8:11548:26) - at mountIndeterminateComponent (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=7a4c9bf8:14926:21) - at beginWork (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=7a4c9bf8:15914:22) - at beginWork$1 (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=7a4c9bf8:19753:22) - at performUnitOfWork (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=7a4c9bf8:19198:20) - at workLoopSync (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=7a4c9bf8:19137:13) - at renderRootSync (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=7a4c9bf8:19116:15) - at recoverFromConcurrentError (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=7a4c9bf8:18736:28) @ http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=7a4c9bf8:14019 -[ 496657ms] [ERROR] The above error occurred in the component: - - at AnimatePresence (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/framer-motion.js?v=05c08439:7800:26) - at ParticleLayer - at div - at div - at Card (http://localhost:5000/src/components/game/HuntersPath.tsx:448:3) - at section - at div - at div - at div - at HuntersPath (http://localhost:5000/src/components/game/HuntersPath.tsx:796:56) - at Provider (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-NNSJBSER.js?v=7a4c9bf8:25:15) - at TooltipProvider (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/@radix-ui_react-tooltip.js?v=b93c5cd0:2240:5) - at QueryClientProvider (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/@tanstack_react-query.js?v=f64daa61:2805:3) - at App - -Consider adding an error boundary to your tree to customize error handling behavior. -Visit https://reactjs.org/link/error-boundaries to learn more about error boundaries. @ http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=7a4c9bf8:14031 -[ 496657ms] [ERROR] Global error caught: ErrorEvent @ http://localhost:5000/src/components/game/HuntersPath.tsx:883 -[ 544571ms] [ERROR] WebSocket connection to 'ws://localhost:5000/?token=bdjYrlr_lPJI' failed: Error during WebSocket handshake: Unexpected response code: 400 @ http://localhost:5000/@vite/client:535 -[ 544575ms] SyntaxError: Failed to construct 'WebSocket': The URL 'ws://localhost:undefined/?token=bdjYrlr_lPJI' is invalid. - at setupWebSocket (http://localhost:5000/@vite/client:536:19) - at fallback (http://localhost:5000/@vite/client:509:16) - at WebSocket. (http://localhost:5000/@vite/client:555:7) -[ 544796ms] [ERROR] Warning: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons: -1. You might have mismatching versions of React and the renderer (such as React DOM) -2. You might be breaking the Rules of Hooks -3. You might have more than one copy of React in the same app -See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem. @ http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-3TFVT2CW.js?v=b243a4a6:135 -[ 544797ms] [ERROR] Warning: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons: -1. You might have mismatching versions of React and the renderer (such as React DOM) -2. You might be breaking the Rules of Hooks -3. You might have more than one copy of React in the same app -See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem. @ http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-3TFVT2CW.js?v=b243a4a6:135 -[ 544802ms] TypeError: Cannot read properties of null (reading 'useEffect') - at Object.useEffect (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-3TFVT2CW.js?v=b243a4a6:1078:29) - at QueryClientProvider (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/@tanstack_react-query.js?v=f23cd135:2808:9) - at renderWithHooks (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:11548:26) - at mountIndeterminateComponent (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:14926:21) - at beginWork (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:15914:22) - at HTMLUnknownElement.callCallback2 (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:3674:22) - at Object.invokeGuardedCallbackDev (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:3699:24) - at invokeGuardedCallback (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:3733:39) - at beginWork$1 (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:19765:15) - at performUnitOfWork (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:19198:20) -[ 544799ms] [ERROR] Warning: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons: -1. You might have mismatching versions of React and the renderer (such as React DOM) -2. You might be breaking the Rules of Hooks -3. You might have more than one copy of React in the same app -See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem. @ http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-3TFVT2CW.js?v=b243a4a6:135 -[ 544799ms] [ERROR] Warning: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons: -1. You might have mismatching versions of React and the renderer (such as React DOM) -2. You might be breaking the Rules of Hooks -3. You might have more than one copy of React in the same app -See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem. @ http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-3TFVT2CW.js?v=b243a4a6:135 -[ 544803ms] TypeError: Cannot read properties of null (reading 'useEffect') - at Object.useEffect (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-3TFVT2CW.js?v=b243a4a6:1078:29) - at QueryClientProvider (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/@tanstack_react-query.js?v=f23cd135:2808:9) - at renderWithHooks (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:11548:26) - at mountIndeterminateComponent (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:14926:21) - at beginWork (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:15914:22) - at HTMLUnknownElement.callCallback2 (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:3674:22) - at Object.invokeGuardedCallbackDev (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:3699:24) - at invokeGuardedCallback (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:3733:39) - at beginWork$1 (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:19765:15) - at performUnitOfWork (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:19198:20) -[ 544800ms] [ERROR] The above error occurred in the component: - - at QueryClientProvider (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/@tanstack_react-query.js?v=f23cd135:2805:3) - at App - -Consider adding an error boundary to your tree to customize error handling behavior. -Visit https://reactjs.org/link/error-boundaries to learn more about error boundaries. @ http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:14031 -[ 544804ms] TypeError: Cannot read properties of null (reading 'useEffect') - at Object.useEffect (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-3TFVT2CW.js?v=b243a4a6:1078:29) - at QueryClientProvider (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/@tanstack_react-query.js?v=f23cd135:2808:9) - at renderWithHooks (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:11548:26) - at mountIndeterminateComponent (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:14926:21) - at beginWork (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:15914:22) - at beginWork$1 (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:19753:22) - at performUnitOfWork (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:19198:20) - at workLoopSync (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:19137:13) - at renderRootSync (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:19116:15) - at recoverFromConcurrentError (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:18736:28) -[ 544834ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 diff --git a/.playwright-mcp/console-2026-02-12T19-37-53-327Z.log b/.playwright-mcp/console-2026-02-12T19-37-53-327Z.log deleted file mode 100644 index 3cd44d2..0000000 --- a/.playwright-mcp/console-2026-02-12T19-37-53-327Z.log +++ /dev/null @@ -1,127 +0,0 @@ -[ 24ms] [ERROR] WebSocket connection to 'ws://localhost:5000/?token=bdjYrlr_lPJI' failed: Error during WebSocket handshake: Unexpected response code: 400 @ http://localhost:5000/@vite/client:535 -[ 67ms] SyntaxError: Failed to construct 'WebSocket': The URL 'ws://localhost:undefined/?token=bdjYrlr_lPJI' is invalid. - at setupWebSocket (http://localhost:5000/@vite/client:536:19) - at fallback (http://localhost:5000/@vite/client:509:16) - at WebSocket. (http://localhost:5000/@vite/client:555:7) -[ 49ms] [ERROR] Warning: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons: -1. You might have mismatching versions of React and the renderer (such as React DOM) -2. You might be breaking the Rules of Hooks -3. You might have more than one copy of React in the same app -See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem. @ http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-3TFVT2CW.js?v=b243a4a6:135 -[ 49ms] [ERROR] Warning: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons: -1. You might have mismatching versions of React and the renderer (such as React DOM) -2. You might be breaking the Rules of Hooks -3. You might have more than one copy of React in the same app -See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem. @ http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-3TFVT2CW.js?v=b243a4a6:135 -[ 90ms] TypeError: Cannot read properties of null (reading 'useEffect') - at Object.useEffect (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-3TFVT2CW.js?v=b243a4a6:1078:29) - at QueryClientProvider (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/@tanstack_react-query.js?v=f23cd135:2808:9) - at renderWithHooks (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:11548:26) - at mountIndeterminateComponent (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:14926:21) - at beginWork (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:15914:22) - at HTMLUnknownElement.callCallback2 (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:3674:22) - at Object.invokeGuardedCallbackDev (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:3699:24) - at invokeGuardedCallback (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:3733:39) - at beginWork$1 (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:19765:15) - at performUnitOfWork (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:19198:20) -[ 50ms] [ERROR] Warning: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons: -1. You might have mismatching versions of React and the renderer (such as React DOM) -2. You might be breaking the Rules of Hooks -3. You might have more than one copy of React in the same app -See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem. @ http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-3TFVT2CW.js?v=b243a4a6:135 -[ 50ms] [ERROR] Warning: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons: -1. You might have mismatching versions of React and the renderer (such as React DOM) -2. You might be breaking the Rules of Hooks -3. You might have more than one copy of React in the same app -See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem. @ http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-3TFVT2CW.js?v=b243a4a6:135 -[ 96ms] TypeError: Cannot read properties of null (reading 'useEffect') - at Object.useEffect (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-3TFVT2CW.js?v=b243a4a6:1078:29) - at QueryClientProvider (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/@tanstack_react-query.js?v=f23cd135:2808:9) - at renderWithHooks (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:11548:26) - at mountIndeterminateComponent (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:14926:21) - at beginWork (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:15914:22) - at HTMLUnknownElement.callCallback2 (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:3674:22) - at Object.invokeGuardedCallbackDev (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:3699:24) - at invokeGuardedCallback (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:3733:39) - at beginWork$1 (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:19765:15) - at performUnitOfWork (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:19198:20) -[ 50ms] [ERROR] The above error occurred in the component: - - at QueryClientProvider (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/@tanstack_react-query.js?v=f23cd135:2805:3) - at App - -Consider adding an error boundary to your tree to customize error handling behavior. -Visit https://reactjs.org/link/error-boundaries to learn more about error boundaries. @ http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:14031 -[ 97ms] TypeError: Cannot read properties of null (reading 'useEffect') - at Object.useEffect (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-3TFVT2CW.js?v=b243a4a6:1078:29) - at QueryClientProvider (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/@tanstack_react-query.js?v=f23cd135:2808:9) - at renderWithHooks (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:11548:26) - at mountIndeterminateComponent (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:14926:21) - at beginWork (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:15914:22) - at beginWork$1 (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:19753:22) - at performUnitOfWork (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:19198:20) - at workLoopSync (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:19137:13) - at renderRootSync (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:19116:15) - at recoverFromConcurrentError (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:18736:28) -[ 74ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 -[ 299308ms] [ERROR] Warning: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons: -1. You might have mismatching versions of React and the renderer (such as React DOM) -2. You might be breaking the Rules of Hooks -3. You might have more than one copy of React in the same app -See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem. @ http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-3TFVT2CW.js?v=b243a4a6:135 -[ 299308ms] [ERROR] Warning: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons: -1. You might have mismatching versions of React and the renderer (such as React DOM) -2. You might be breaking the Rules of Hooks -3. You might have more than one copy of React in the same app -See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem. @ http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-3TFVT2CW.js?v=b243a4a6:135 -[ 299343ms] TypeError: Cannot read properties of null (reading 'useEffect') - at Object.useEffect (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-3TFVT2CW.js?v=b243a4a6:1078:29) - at QueryClientProvider (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/@tanstack_react-query.js?v=f23cd135:2808:9) - at renderWithHooks (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:11548:26) - at mountIndeterminateComponent (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:14926:21) - at beginWork (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:15914:22) - at HTMLUnknownElement.callCallback2 (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:3674:22) - at Object.invokeGuardedCallbackDev (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:3699:24) - at invokeGuardedCallback (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:3733:39) - at beginWork$1 (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:19765:15) - at performUnitOfWork (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:19198:20) -[ 299309ms] [ERROR] Warning: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons: -1. You might have mismatching versions of React and the renderer (such as React DOM) -2. You might be breaking the Rules of Hooks -3. You might have more than one copy of React in the same app -See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem. @ http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-3TFVT2CW.js?v=b243a4a6:135 -[ 299309ms] [ERROR] Warning: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons: -1. You might have mismatching versions of React and the renderer (such as React DOM) -2. You might be breaking the Rules of Hooks -3. You might have more than one copy of React in the same app -See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem. @ http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-3TFVT2CW.js?v=b243a4a6:135 -[ 299344ms] TypeError: Cannot read properties of null (reading 'useEffect') - at Object.useEffect (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-3TFVT2CW.js?v=b243a4a6:1078:29) - at QueryClientProvider (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/@tanstack_react-query.js?v=f23cd135:2808:9) - at renderWithHooks (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:11548:26) - at mountIndeterminateComponent (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:14926:21) - at beginWork (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:15914:22) - at HTMLUnknownElement.callCallback2 (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:3674:22) - at Object.invokeGuardedCallbackDev (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:3699:24) - at invokeGuardedCallback (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:3733:39) - at beginWork$1 (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:19765:15) - at performUnitOfWork (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:19198:20) -[ 299309ms] [ERROR] The above error occurred in the component: - - at QueryClientProvider (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/@tanstack_react-query.js?v=f23cd135:2805:3) - at App - -Consider adding an error boundary to your tree to customize error handling behavior. -Visit https://reactjs.org/link/error-boundaries to learn more about error boundaries. @ http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:14031 -[ 299345ms] TypeError: Cannot read properties of null (reading 'useEffect') - at Object.useEffect (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-3TFVT2CW.js?v=b243a4a6:1078:29) - at QueryClientProvider (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/@tanstack_react-query.js?v=f23cd135:2808:9) - at renderWithHooks (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:11548:26) - at mountIndeterminateComponent (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:14926:21) - at beginWork (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:15914:22) - at beginWork$1 (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:19753:22) - at performUnitOfWork (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:19198:20) - at workLoopSync (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:19137:13) - at renderRootSync (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:19116:15) - at recoverFromConcurrentError (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:18736:28) -[ 299313ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 diff --git a/.playwright-mcp/console-2026-02-12T19-43-27-564Z.log b/.playwright-mcp/console-2026-02-12T19-43-27-564Z.log deleted file mode 100644 index a1a8ea6..0000000 --- a/.playwright-mcp/console-2026-02-12T19-43-27-564Z.log +++ /dev/null @@ -1,127 +0,0 @@ -[ 42ms] [ERROR] Warning: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons: -1. You might have mismatching versions of React and the renderer (such as React DOM) -2. You might be breaking the Rules of Hooks -3. You might have more than one copy of React in the same app -See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem. @ http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-3TFVT2CW.js?v=b243a4a6:135 -[ 42ms] [ERROR] Warning: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons: -1. You might have mismatching versions of React and the renderer (such as React DOM) -2. You might be breaking the Rules of Hooks -3. You might have more than one copy of React in the same app -See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem. @ http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-3TFVT2CW.js?v=b243a4a6:135 -[ 78ms] TypeError: Cannot read properties of null (reading 'useEffect') - at Object.useEffect (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-3TFVT2CW.js?v=b243a4a6:1078:29) - at QueryClientProvider (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/@tanstack_react-query.js?v=f23cd135:2808:9) - at renderWithHooks (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:11548:26) - at mountIndeterminateComponent (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:14926:21) - at beginWork (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:15914:22) - at HTMLUnknownElement.callCallback2 (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:3674:22) - at Object.invokeGuardedCallbackDev (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:3699:24) - at invokeGuardedCallback (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:3733:39) - at beginWork$1 (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:19765:15) - at performUnitOfWork (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:19198:20) -[ 43ms] [ERROR] Warning: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons: -1. You might have mismatching versions of React and the renderer (such as React DOM) -2. You might be breaking the Rules of Hooks -3. You might have more than one copy of React in the same app -See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem. @ http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-3TFVT2CW.js?v=b243a4a6:135 -[ 43ms] [ERROR] Warning: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons: -1. You might have mismatching versions of React and the renderer (such as React DOM) -2. You might be breaking the Rules of Hooks -3. You might have more than one copy of React in the same app -See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem. @ http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-3TFVT2CW.js?v=b243a4a6:135 -[ 79ms] TypeError: Cannot read properties of null (reading 'useEffect') - at Object.useEffect (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-3TFVT2CW.js?v=b243a4a6:1078:29) - at QueryClientProvider (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/@tanstack_react-query.js?v=f23cd135:2808:9) - at renderWithHooks (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:11548:26) - at mountIndeterminateComponent (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:14926:21) - at beginWork (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:15914:22) - at HTMLUnknownElement.callCallback2 (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:3674:22) - at Object.invokeGuardedCallbackDev (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:3699:24) - at invokeGuardedCallback (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:3733:39) - at beginWork$1 (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:19765:15) - at performUnitOfWork (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:19198:20) -[ 44ms] [ERROR] The above error occurred in the component: - - at QueryClientProvider (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/@tanstack_react-query.js?v=f23cd135:2805:3) - at App - -Consider adding an error boundary to your tree to customize error handling behavior. -Visit https://reactjs.org/link/error-boundaries to learn more about error boundaries. @ http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:14031 -[ 80ms] TypeError: Cannot read properties of null (reading 'useEffect') - at Object.useEffect (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-3TFVT2CW.js?v=b243a4a6:1078:29) - at QueryClientProvider (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/@tanstack_react-query.js?v=f23cd135:2808:9) - at renderWithHooks (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:11548:26) - at mountIndeterminateComponent (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:14926:21) - at beginWork (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:15914:22) - at beginWork$1 (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:19753:22) - at performUnitOfWork (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:19198:20) - at workLoopSync (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:19137:13) - at renderRootSync (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:19116:15) - at recoverFromConcurrentError (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:18736:28) -[ 47ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 -[ 465179ms] [ERROR] WebSocket connection to 'ws://localhost:5000/?token=bdjYrlr_lPJI' failed: Error during WebSocket handshake: Unexpected response code: 400 @ http://localhost:5000/@vite/client:535 -[ 465211ms] SyntaxError: Failed to construct 'WebSocket': The URL 'ws://localhost:undefined/?token=bdjYrlr_lPJI' is invalid. - at setupWebSocket (http://localhost:5000/@vite/client:536:19) - at fallback (http://localhost:5000/@vite/client:509:16) - at WebSocket. (http://localhost:5000/@vite/client:555:7) -[ 465203ms] [ERROR] Warning: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons: -1. You might have mismatching versions of React and the renderer (such as React DOM) -2. You might be breaking the Rules of Hooks -3. You might have more than one copy of React in the same app -See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem. @ http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-3TFVT2CW.js?v=b243a4a6:135 -[ 465204ms] [ERROR] Warning: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons: -1. You might have mismatching versions of React and the renderer (such as React DOM) -2. You might be breaking the Rules of Hooks -3. You might have more than one copy of React in the same app -See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem. @ http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-3TFVT2CW.js?v=b243a4a6:135 -[ 465237ms] TypeError: Cannot read properties of null (reading 'useEffect') - at Object.useEffect (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-3TFVT2CW.js?v=b243a4a6:1078:29) - at QueryClientProvider (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/@tanstack_react-query.js?v=f23cd135:2808:9) - at renderWithHooks (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:11548:26) - at mountIndeterminateComponent (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:14926:21) - at beginWork (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:15914:22) - at HTMLUnknownElement.callCallback2 (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:3674:22) - at Object.invokeGuardedCallbackDev (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:3699:24) - at invokeGuardedCallback (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:3733:39) - at beginWork$1 (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:19765:15) - at performUnitOfWork (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:19198:20) -[ 465204ms] [ERROR] Warning: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons: -1. You might have mismatching versions of React and the renderer (such as React DOM) -2. You might be breaking the Rules of Hooks -3. You might have more than one copy of React in the same app -See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem. @ http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-3TFVT2CW.js?v=b243a4a6:135 -[ 465204ms] [ERROR] Warning: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons: -1. You might have mismatching versions of React and the renderer (such as React DOM) -2. You might be breaking the Rules of Hooks -3. You might have more than one copy of React in the same app -See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem. @ http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-3TFVT2CW.js?v=b243a4a6:135 -[ 465238ms] TypeError: Cannot read properties of null (reading 'useEffect') - at Object.useEffect (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-3TFVT2CW.js?v=b243a4a6:1078:29) - at QueryClientProvider (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/@tanstack_react-query.js?v=f23cd135:2808:9) - at renderWithHooks (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:11548:26) - at mountIndeterminateComponent (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:14926:21) - at beginWork (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:15914:22) - at HTMLUnknownElement.callCallback2 (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:3674:22) - at Object.invokeGuardedCallbackDev (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:3699:24) - at invokeGuardedCallback (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:3733:39) - at beginWork$1 (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:19765:15) - at performUnitOfWork (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:19198:20) -[ 465205ms] [ERROR] The above error occurred in the component: - - at QueryClientProvider (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/@tanstack_react-query.js?v=f23cd135:2805:3) - at App - -Consider adding an error boundary to your tree to customize error handling behavior. -Visit https://reactjs.org/link/error-boundaries to learn more about error boundaries. @ http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:14031 -[ 465239ms] TypeError: Cannot read properties of null (reading 'useEffect') - at Object.useEffect (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-3TFVT2CW.js?v=b243a4a6:1078:29) - at QueryClientProvider (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/@tanstack_react-query.js?v=f23cd135:2808:9) - at renderWithHooks (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:11548:26) - at mountIndeterminateComponent (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:14926:21) - at beginWork (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:15914:22) - at beginWork$1 (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:19753:22) - at performUnitOfWork (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:19198:20) - at workLoopSync (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:19137:13) - at renderRootSync (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:19116:15) - at recoverFromConcurrentError (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:18736:28) -[ 465209ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 diff --git a/.playwright-mcp/console-2026-02-12T19-51-14-914Z.log b/.playwright-mcp/console-2026-02-12T19-51-14-914Z.log deleted file mode 100644 index 78aef28..0000000 --- a/.playwright-mcp/console-2026-02-12T19-51-14-914Z.log +++ /dev/null @@ -1,66 +0,0 @@ -[ 14ms] [ERROR] WebSocket connection to 'ws://localhost:5000/?token=bdjYrlr_lPJI' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/@vite/client:535 -[ 36ms] SyntaxError: Failed to construct 'WebSocket': The URL 'ws://localhost:undefined/?token=bdjYrlr_lPJI' is invalid. - at setupWebSocket (http://localhost:5000/@vite/client:536:19) - at fallback (http://localhost:5000/@vite/client:509:16) - at WebSocket. (http://localhost:5000/@vite/client:555:7) -[ 36ms] [ERROR] Warning: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons: -1. You might have mismatching versions of React and the renderer (such as React DOM) -2. You might be breaking the Rules of Hooks -3. You might have more than one copy of React in the same app -See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem. @ http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-3TFVT2CW.js?v=b243a4a6:135 -[ 37ms] [ERROR] Warning: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons: -1. You might have mismatching versions of React and the renderer (such as React DOM) -2. You might be breaking the Rules of Hooks -3. You might have more than one copy of React in the same app -See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem. @ http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-3TFVT2CW.js?v=b243a4a6:135 -[ 73ms] TypeError: Cannot read properties of null (reading 'useEffect') - at Object.useEffect (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-3TFVT2CW.js?v=b243a4a6:1078:29) - at QueryClientProvider (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/@tanstack_react-query.js?v=f23cd135:2808:9) - at renderWithHooks (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:11548:26) - at mountIndeterminateComponent (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:14926:21) - at beginWork (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:15914:22) - at HTMLUnknownElement.callCallback2 (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:3674:22) - at Object.invokeGuardedCallbackDev (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:3699:24) - at invokeGuardedCallback (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:3733:39) - at beginWork$1 (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:19765:15) - at performUnitOfWork (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:19198:20) -[ 37ms] [ERROR] Warning: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons: -1. You might have mismatching versions of React and the renderer (such as React DOM) -2. You might be breaking the Rules of Hooks -3. You might have more than one copy of React in the same app -See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem. @ http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-3TFVT2CW.js?v=b243a4a6:135 -[ 37ms] [ERROR] Warning: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons: -1. You might have mismatching versions of React and the renderer (such as React DOM) -2. You might be breaking the Rules of Hooks -3. You might have more than one copy of React in the same app -See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem. @ http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-3TFVT2CW.js?v=b243a4a6:135 -[ 74ms] TypeError: Cannot read properties of null (reading 'useEffect') - at Object.useEffect (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-3TFVT2CW.js?v=b243a4a6:1078:29) - at QueryClientProvider (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/@tanstack_react-query.js?v=f23cd135:2808:9) - at renderWithHooks (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:11548:26) - at mountIndeterminateComponent (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:14926:21) - at beginWork (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:15914:22) - at HTMLUnknownElement.callCallback2 (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:3674:22) - at Object.invokeGuardedCallbackDev (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:3699:24) - at invokeGuardedCallback (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:3733:39) - at beginWork$1 (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:19765:15) - at performUnitOfWork (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:19198:20) -[ 37ms] [ERROR] The above error occurred in the component: - - at QueryClientProvider (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/@tanstack_react-query.js?v=f23cd135:2805:3) - at App - -Consider adding an error boundary to your tree to customize error handling behavior. -Visit https://reactjs.org/link/error-boundaries to learn more about error boundaries. @ http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:14031 -[ 74ms] TypeError: Cannot read properties of null (reading 'useEffect') - at Object.useEffect (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-3TFVT2CW.js?v=b243a4a6:1078:29) - at QueryClientProvider (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/@tanstack_react-query.js?v=f23cd135:2808:9) - at renderWithHooks (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:11548:26) - at mountIndeterminateComponent (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:14926:21) - at beginWork (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:15914:22) - at beginWork$1 (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:19753:22) - at performUnitOfWork (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:19198:20) - at workLoopSync (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:19137:13) - at renderRootSync (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:19116:15) - at recoverFromConcurrentError (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=699444b2:18736:28) -[ 40ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 diff --git a/.playwright-mcp/console-2026-02-12T19-53-31-072Z.log b/.playwright-mcp/console-2026-02-12T19-53-31-072Z.log deleted file mode 100644 index e15b48e..0000000 --- a/.playwright-mcp/console-2026-02-12T19-53-31-072Z.log +++ /dev/null @@ -1,3 +0,0 @@ -[ 223ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:196 -[ 224ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:250 -[ 233ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 diff --git a/.playwright-mcp/console-2026-02-13T20-26-16-786Z.log b/.playwright-mcp/console-2026-02-13T20-26-16-786Z.log deleted file mode 100644 index 6fcf466..0000000 --- a/.playwright-mcp/console-2026-02-13T20-26-16-786Z.log +++ /dev/null @@ -1,3 +0,0 @@ -[ 387ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:196 -[ 388ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:250 -[ 391ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 diff --git a/.playwright-mcp/console-2026-02-13T20-35-43-777Z.log b/.playwright-mcp/console-2026-02-13T20-35-43-777Z.log deleted file mode 100644 index cf01a71..0000000 --- a/.playwright-mcp/console-2026-02-13T20-35-43-777Z.log +++ /dev/null @@ -1,3 +0,0 @@ -[ 157ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:196 -[ 158ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:250 -[ 166ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 diff --git a/.playwright-mcp/console-2026-02-13T20-50-41-249Z.log b/.playwright-mcp/console-2026-02-13T20-50-41-249Z.log deleted file mode 100644 index 88bc709..0000000 --- a/.playwright-mcp/console-2026-02-13T20-50-41-249Z.log +++ /dev/null @@ -1,3 +0,0 @@ -[ 138ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:196 -[ 138ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:250 -[ 145ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 diff --git a/.playwright-mcp/console-2026-02-13T20-50-46-350Z.log b/.playwright-mcp/console-2026-02-13T20-50-46-350Z.log deleted file mode 100644 index c96bdfd..0000000 --- a/.playwright-mcp/console-2026-02-13T20-50-46-350Z.log +++ /dev/null @@ -1,3 +0,0 @@ -[ 115ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:196 -[ 116ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:250 -[ 122ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 diff --git a/.playwright-mcp/console-2026-02-13T21-41-16-193Z.log b/.playwright-mcp/console-2026-02-13T21-41-16-193Z.log deleted file mode 100644 index 3801e97..0000000 --- a/.playwright-mcp/console-2026-02-13T21-41-16-193Z.log +++ /dev/null @@ -1,3 +0,0 @@ -[ 393ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ https://jesserweigel.github.io/HunterPath/assets/index-CyaD21z5.js:95 -[ 394ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ https://jesserweigel.github.io/HunterPath/assets/index-CyaD21z5.js:95 -[ 405ms] [ERROR] Failed to load resource: the server responded with a status of 404 () @ https://jesserweigel.github.io/assets/ui/player.svg:0 diff --git a/.playwright-mcp/console-2026-02-13T21-41-28-454Z.log b/.playwright-mcp/console-2026-02-13T21-41-28-454Z.log deleted file mode 100644 index edd1745..0000000 --- a/.playwright-mcp/console-2026-02-13T21-41-28-454Z.log +++ /dev/null @@ -1,5 +0,0 @@ -[ 73ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ https://jesserweigel.github.io/HunterPath/assets/index-CyaD21z5.js:95 -[ 74ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ https://jesserweigel.github.io/HunterPath/assets/index-CyaD21z5.js:95 -[ 86ms] [ERROR] Failed to load resource: the server responded with a status of 404 () @ https://jesserweigel.github.io/assets/ui/player.svg:0 -[ 13380ms] [ERROR] Failed to load resource: the server responded with a status of 404 () @ https://jesserweigel.github.io/assets/ui/player.svg:0 -[ 13394ms] [ERROR] Failed to load resource: the server responded with a status of 404 () @ https://jesserweigel.github.io/assets/bosses/boss_e.svg:0 diff --git a/.playwright-mcp/console-2026-02-13T21-45-01-763Z.log b/.playwright-mcp/console-2026-02-13T21-45-01-763Z.log deleted file mode 100644 index f8a7bd2..0000000 --- a/.playwright-mcp/console-2026-02-13T21-45-01-763Z.log +++ /dev/null @@ -1,3 +0,0 @@ -[ 65ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ https://jesserweigel.github.io/HunterPath/assets/index-CyaD21z5.js:95 -[ 65ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ https://jesserweigel.github.io/HunterPath/assets/index-CyaD21z5.js:95 -[ 82ms] [ERROR] Failed to load resource: the server responded with a status of 404 () @ https://jesserweigel.github.io/assets/ui/player.svg:0 diff --git a/.playwright-mcp/console-2026-02-13T21-45-11-424Z.log b/.playwright-mcp/console-2026-02-13T21-45-11-424Z.log deleted file mode 100644 index a5a2e78..0000000 --- a/.playwright-mcp/console-2026-02-13T21-45-11-424Z.log +++ /dev/null @@ -1,5 +0,0 @@ -[ 55ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ https://jesserweigel.github.io/HunterPath/assets/index-CyaD21z5.js:95 -[ 55ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ https://jesserweigel.github.io/HunterPath/assets/index-CyaD21z5.js:95 -[ 70ms] [ERROR] Failed to load resource: the server responded with a status of 404 () @ https://jesserweigel.github.io/assets/ui/player.svg:0 -[ 9016ms] [ERROR] Failed to load resource: the server responded with a status of 404 () @ https://jesserweigel.github.io/assets/ui/player.svg:0 -[ 9024ms] [ERROR] Failed to load resource: the server responded with a status of 404 () @ https://jesserweigel.github.io/assets/bosses/boss_e.svg:0 diff --git a/.playwright-mcp/console-2026-02-13T21-46-00-365Z.log b/.playwright-mcp/console-2026-02-13T21-46-00-365Z.log deleted file mode 100644 index 95c3255..0000000 --- a/.playwright-mcp/console-2026-02-13T21-46-00-365Z.log +++ /dev/null @@ -1,2 +0,0 @@ -[ 235ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ https://jesserweigel.github.io/HunterPath/assets/index-BWknHgMY.js:95 -[ 236ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ https://jesserweigel.github.io/HunterPath/assets/index-BWknHgMY.js:95 diff --git a/.playwright-mcp/console-2026-02-23T15-37-02-405Z.log b/.playwright-mcp/console-2026-02-23T15-37-02-405Z.log deleted file mode 100644 index cc781da..0000000 --- a/.playwright-mcp/console-2026-02-23T15-37-02-405Z.log +++ /dev/null @@ -1,10 +0,0 @@ -[ 435ms] [ERROR] WebSocket connection to 'ws://localhost:5000/?token=laQUEN_OVGs6' failed: Error during WebSocket handshake: Unexpected response code: 400 @ http://localhost:5000/@vite/client:535 -[ 443ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:196 -[ 444ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:250 -[ 446ms] [ERROR] WebSocket connection to 'ws://localhost:5000/?token=laQUEN_OVGs6' failed: Error during WebSocket handshake: Unexpected response code: 400 @ http://localhost:5000/@vite/client:535 -[ 446ms] [ERROR] [vite] failed to connect to websocket. -your current setup: - (browser) localhost:5000/ <--[HTTP]--> localhost:5000/ (server) - (browser) localhost:5000/ <--[WebSocket (failing)]--> localhost:5000/ (server) -Check out your Vite / network configuration and https://vite.dev/config/server-options.html#server-hmr . @ http://localhost:5000/@vite/client:511 -[ 451ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 diff --git a/.playwright-mcp/console-2026-02-23T15-37-08-551Z.log b/.playwright-mcp/console-2026-02-23T15-37-08-551Z.log deleted file mode 100644 index 23c034e..0000000 --- a/.playwright-mcp/console-2026-02-23T15-37-08-551Z.log +++ /dev/null @@ -1,10 +0,0 @@ -[ 20ms] [ERROR] WebSocket connection to 'ws://localhost:5000/?token=laQUEN_OVGs6' failed: Error during WebSocket handshake: Unexpected response code: 400 @ http://localhost:5000/@vite/client:535 -[ 112ms] [ERROR] WebSocket connection to 'ws://localhost:5000/?token=laQUEN_OVGs6' failed: Error during WebSocket handshake: Unexpected response code: 400 @ http://localhost:5000/@vite/client:535 -[ 117ms] [ERROR] [vite] failed to connect to websocket. -your current setup: - (browser) localhost:5000/ <--[HTTP]--> localhost:5000/ (server) - (browser) localhost:5000/ <--[WebSocket (failing)]--> localhost:5000/ (server) -Check out your Vite / network configuration and https://vite.dev/config/server-options.html#server-hmr . @ http://localhost:5000/@vite/client:511 -[ 118ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:196 -[ 119ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:250 -[ 122ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 diff --git a/.playwright-mcp/console-2026-02-23T19-05-05-011Z.log b/.playwright-mcp/console-2026-02-23T19-05-05-011Z.log deleted file mode 100644 index 4fbb288..0000000 --- a/.playwright-mcp/console-2026-02-23T19-05-05-011Z.log +++ /dev/null @@ -1,10 +0,0 @@ -[ 50ms] [ERROR] WebSocket connection to 'ws://localhost:5000/?token=laQUEN_OVGs6' failed: Error during WebSocket handshake: Unexpected response code: 400 @ http://localhost:5000/@vite/client:535 -[ 239ms] [ERROR] WebSocket connection to 'ws://localhost:5000/?token=laQUEN_OVGs6' failed: Error during WebSocket handshake: Unexpected response code: 400 @ http://localhost:5000/@vite/client:535 -[ 254ms] [ERROR] [vite] failed to connect to websocket. -your current setup: - (browser) localhost:5000/ <--[HTTP]--> localhost:5000/ (server) - (browser) localhost:5000/ <--[WebSocket (failing)]--> localhost:5000/ (server) -Check out your Vite / network configuration and https://vite.dev/config/server-options.html#server-hmr . @ http://localhost:5000/@vite/client:511 -[ 258ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:196 -[ 259ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:250 -[ 268ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 diff --git a/.playwright-mcp/console-2026-02-23T19-06-10-577Z.log b/.playwright-mcp/console-2026-02-23T19-06-10-577Z.log deleted file mode 100644 index ad9a6e6..0000000 --- a/.playwright-mcp/console-2026-02-23T19-06-10-577Z.log +++ /dev/null @@ -1,26 +0,0 @@ -[ 29ms] [ERROR] WebSocket connection to 'ws://localhost:5000/?token=laQUEN_OVGs6' failed: Error during WebSocket handshake: Unexpected response code: 400 @ http://localhost:5000/@vite/client:535 -[ 134ms] [ERROR] WebSocket connection to 'ws://localhost:5000/?token=laQUEN_OVGs6' failed: Error during WebSocket handshake: Unexpected response code: 400 @ http://localhost:5000/@vite/client:535 -[ 138ms] [ERROR] [vite] failed to connect to websocket. -your current setup: - (browser) localhost:5000/ <--[HTTP]--> localhost:5000/ (server) - (browser) localhost:5000/ <--[WebSocket (failing)]--> localhost:5000/ (server) -Check out your Vite / network configuration and https://vite.dev/config/server-options.html#server-hmr . @ http://localhost:5000/@vite/client:511 -[ 139ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:196 -[ 140ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:250 -[ 149ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 -[ 19440ms] [ERROR] WebSocket connection to 'ws://localhost:5000/?token=laQUEN_OVGs6' failed: Error during WebSocket handshake: Unexpected response code: 400 @ http://localhost:5000/@vite/client:535 -[ 19521ms] [ERROR] WebSocket connection to 'ws://localhost:5000/?token=laQUEN_OVGs6' failed: Error during WebSocket handshake: Unexpected response code: 400 @ http://localhost:5000/@vite/client:535 -[ 19533ms] [ERROR] [vite] failed to connect to websocket. -your current setup: - (browser) localhost:5000/ <--[HTTP]--> localhost:5000/ (server) - (browser) localhost:5000/ <--[WebSocket (failing)]--> localhost:5000/ (server) -Check out your Vite / network configuration and https://vite.dev/config/server-options.html#server-hmr . @ http://localhost:5000/@vite/client:511 -[ 19535ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 -[ 31500ms] [ERROR] WebSocket connection to 'ws://localhost:5000/?token=BoEzBs8UHcdu' failed: Error during WebSocket handshake: Unexpected response code: 400 @ http://localhost:5000/@vite/client:535 -[ 31534ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:196 -[ 31535ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:250 -[ 31539ms] [ERROR] Unhandled promise rejection: SyntaxError: Failed to construct 'WebSocket': The URL 'ws://localhost:undefined/?token=BoEzBs8UHcdu' is invalid. - at setupWebSocket (http://localhost:5000/@vite/client:536:19) - at fallback (http://localhost:5000/@vite/client:509:16) - at WebSocket. (http://localhost:5000/@vite/client:555:7) @ http://localhost:5000/src/components/game/HuntersPath.tsx?t=1771873558745&v=gCFZ5y_oOq-bBolY5elVe:893 -[ 31556ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 diff --git a/.playwright-mcp/console-2026-02-23T19-13-16-347Z.log b/.playwright-mcp/console-2026-02-23T19-13-16-347Z.log deleted file mode 100644 index ba2ace9..0000000 --- a/.playwright-mcp/console-2026-02-23T19-13-16-347Z.log +++ /dev/null @@ -1,3 +0,0 @@ -[ 448ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:196 -[ 449ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:250 -[ 465ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 diff --git a/.playwright-mcp/console-2026-02-23T19-13-49-079Z.log b/.playwright-mcp/console-2026-02-23T19-13-49-079Z.log deleted file mode 100644 index e0975f9..0000000 --- a/.playwright-mcp/console-2026-02-23T19-13-49-079Z.log +++ /dev/null @@ -1 +0,0 @@ -[ 689ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 diff --git a/.playwright-mcp/console-2026-02-23T19-14-26-638Z.log b/.playwright-mcp/console-2026-02-23T19-14-26-638Z.log deleted file mode 100644 index 2b5b84d..0000000 --- a/.playwright-mcp/console-2026-02-23T19-14-26-638Z.log +++ /dev/null @@ -1 +0,0 @@ -[ 311ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 diff --git a/.playwright-mcp/console-2026-02-23T19-18-39-369Z.log b/.playwright-mcp/console-2026-02-23T19-18-39-369Z.log deleted file mode 100644 index e40b904..0000000 --- a/.playwright-mcp/console-2026-02-23T19-18-39-369Z.log +++ /dev/null @@ -1,8 +0,0 @@ -[ 182ms] [ERROR] WebSocket connection to 'ws://localhost:5000/?token=UWwUHPKdepNM' failed: Error during WebSocket handshake: Unexpected response code: 400 @ http://localhost:5000/@vite/client:535 -[ 184ms] SyntaxError: Failed to construct 'WebSocket': The URL 'ws://localhost:undefined/?token=UWwUHPKdepNM' is invalid. - at setupWebSocket (http://localhost:5000/@vite/client:536:19) - at fallback (http://localhost:5000/@vite/client:509:16) - at WebSocket. (http://localhost:5000/@vite/client:555:7) -[ 440ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:196 -[ 441ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:250 -[ 475ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 diff --git a/.playwright-mcp/console-2026-02-23T19-20-24-086Z.log b/.playwright-mcp/console-2026-02-23T19-20-24-086Z.log deleted file mode 100644 index a911e50..0000000 --- a/.playwright-mcp/console-2026-02-23T19-20-24-086Z.log +++ /dev/null @@ -1,6 +0,0 @@ -[ 32ms] [ERROR] WebSocket connection to 'ws://localhost:5000/?token=ruKP92VJEZoy' failed: Error during WebSocket handshake: Unexpected response code: 400 @ http://localhost:5000/@vite/client:535 -[ 35ms] SyntaxError: Failed to construct 'WebSocket': The URL 'ws://localhost:undefined/?token=ruKP92VJEZoy' is invalid. - at setupWebSocket (http://localhost:5000/@vite/client:536:19) - at fallback (http://localhost:5000/@vite/client:509:16) - at WebSocket. (http://localhost:5000/@vite/client:555:7) -[ 2092ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 diff --git a/.playwright-mcp/console-2026-02-23T19-21-54-560Z.log b/.playwright-mcp/console-2026-02-23T19-21-54-560Z.log deleted file mode 100644 index 6d1125f..0000000 --- a/.playwright-mcp/console-2026-02-23T19-21-54-560Z.log +++ /dev/null @@ -1,6 +0,0 @@ -[ 24ms] [ERROR] WebSocket connection to 'ws://localhost:5000/?token=ArOgeVMZYOeF' failed: Error during WebSocket handshake: Unexpected response code: 400 @ http://localhost:5000/@vite/client:535 -[ 27ms] SyntaxError: Failed to construct 'WebSocket': The URL 'ws://localhost:undefined/?token=ArOgeVMZYOeF' is invalid. - at setupWebSocket (http://localhost:5000/@vite/client:536:19) - at fallback (http://localhost:5000/@vite/client:509:16) - at WebSocket. (http://localhost:5000/@vite/client:555:7) -[ 652ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 diff --git a/.playwright-mcp/console-2026-02-23T19-28-42-143Z.log b/.playwright-mcp/console-2026-02-23T19-28-42-143Z.log deleted file mode 100644 index 6e8a957..0000000 --- a/.playwright-mcp/console-2026-02-23T19-28-42-143Z.log +++ /dev/null @@ -1,8 +0,0 @@ -[ 28ms] [ERROR] WebSocket connection to 'ws://localhost:5000/?token=ArOgeVMZYOeF' failed: Error during WebSocket handshake: Unexpected response code: 400 @ http://localhost:5000/@vite/client:535 -[ 37ms] SyntaxError: Failed to construct 'WebSocket': The URL 'ws://localhost:undefined/?token=ArOgeVMZYOeF' is invalid. - at setupWebSocket (http://localhost:5000/@vite/client:536:19) - at fallback (http://localhost:5000/@vite/client:509:16) - at WebSocket. (http://localhost:5000/@vite/client:555:7) -[ 442ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:196 -[ 442ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:250 -[ 459ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 diff --git a/.playwright-mcp/console-2026-02-23T19-28-50-924Z.log b/.playwright-mcp/console-2026-02-23T19-28-50-924Z.log deleted file mode 100644 index 4390f93..0000000 --- a/.playwright-mcp/console-2026-02-23T19-28-50-924Z.log +++ /dev/null @@ -1,8 +0,0 @@ -[ 29ms] [ERROR] WebSocket connection to 'ws://localhost:5000/?token=UWwUHPKdepNM' failed: Error during WebSocket handshake: Unexpected response code: 400 @ http://localhost:5000/@vite/client:535 -[ 38ms] SyntaxError: Failed to construct 'WebSocket': The URL 'ws://localhost:undefined/?token=UWwUHPKdepNM' is invalid. - at setupWebSocket (http://localhost:5000/@vite/client:536:19) - at fallback (http://localhost:5000/@vite/client:509:16) - at WebSocket. (http://localhost:5000/@vite/client:555:7) -[ 396ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:196 -[ 397ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:250 -[ 412ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 diff --git a/.playwright-mcp/console-2026-02-23T19-29-03-576Z.log b/.playwright-mcp/console-2026-02-23T19-29-03-576Z.log deleted file mode 100644 index e8ca930..0000000 --- a/.playwright-mcp/console-2026-02-23T19-29-03-576Z.log +++ /dev/null @@ -1,6 +0,0 @@ -[ 98ms] [ERROR] WebSocket connection to 'ws://localhost:5000/?token=UWwUHPKdepNM' failed: Error during WebSocket handshake: Unexpected response code: 400 @ http://localhost:5000/@vite/client:535 -[ 100ms] SyntaxError: Failed to construct 'WebSocket': The URL 'ws://localhost:undefined/?token=UWwUHPKdepNM' is invalid. - at setupWebSocket (http://localhost:5000/@vite/client:536:19) - at fallback (http://localhost:5000/@vite/client:509:16) - at WebSocket. (http://localhost:5000/@vite/client:555:7) -[ 408ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 diff --git a/.playwright-mcp/console-2026-02-23T19-29-19-126Z.log b/.playwright-mcp/console-2026-02-23T19-29-19-126Z.log deleted file mode 100644 index 8e3b933..0000000 --- a/.playwright-mcp/console-2026-02-23T19-29-19-126Z.log +++ /dev/null @@ -1,6 +0,0 @@ -[ 26ms] [ERROR] WebSocket connection to 'ws://localhost:5000/?token=fkAS5C_-shpN' failed: Error during WebSocket handshake: Unexpected response code: 400 @ http://localhost:5000/@vite/client:535 -[ 45ms] SyntaxError: Failed to construct 'WebSocket': The URL 'ws://localhost:undefined/?token=fkAS5C_-shpN' is invalid. - at setupWebSocket (http://localhost:5000/@vite/client:536:19) - at fallback (http://localhost:5000/@vite/client:509:16) - at WebSocket. (http://localhost:5000/@vite/client:555:7) -[ 360ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 diff --git a/.playwright-mcp/console-2026-02-23T19-29-36-024Z.log b/.playwright-mcp/console-2026-02-23T19-29-36-024Z.log deleted file mode 100644 index 538afca..0000000 --- a/.playwright-mcp/console-2026-02-23T19-29-36-024Z.log +++ /dev/null @@ -1,8 +0,0 @@ -[ 27ms] [ERROR] WebSocket connection to 'ws://localhost:5000/?token=ArOgeVMZYOeF' failed: Error during WebSocket handshake: Unexpected response code: 400 @ http://localhost:5000/@vite/client:535 -[ 56ms] SyntaxError: Failed to construct 'WebSocket': The URL 'ws://localhost:undefined/?token=ArOgeVMZYOeF' is invalid. - at setupWebSocket (http://localhost:5000/@vite/client:536:19) - at fallback (http://localhost:5000/@vite/client:509:16) - at WebSocket. (http://localhost:5000/@vite/client:555:7) -[ 111ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:196 -[ 111ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:250 -[ 125ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 diff --git a/.playwright-mcp/console-2026-02-23T19-33-41-934Z.log b/.playwright-mcp/console-2026-02-23T19-33-41-934Z.log deleted file mode 100644 index 23fab54..0000000 --- a/.playwright-mcp/console-2026-02-23T19-33-41-934Z.log +++ /dev/null @@ -1,6 +0,0 @@ -[ 31ms] [ERROR] WebSocket connection to 'ws://localhost:5000/?token=ruKP92VJEZoy' failed: Error during WebSocket handshake: Unexpected response code: 400 @ http://localhost:5000/@vite/client:535 -[ 43ms] SyntaxError: Failed to construct 'WebSocket': The URL 'ws://localhost:undefined/?token=ruKP92VJEZoy' is invalid. - at setupWebSocket (http://localhost:5000/@vite/client:536:19) - at fallback (http://localhost:5000/@vite/client:509:16) - at WebSocket. (http://localhost:5000/@vite/client:555:7) -[ 447ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 diff --git a/.playwright-mcp/console-2026-02-23T19-39-54-534Z.log b/.playwright-mcp/console-2026-02-23T19-39-54-534Z.log deleted file mode 100644 index b9fe0cf..0000000 --- a/.playwright-mcp/console-2026-02-23T19-39-54-534Z.log +++ /dev/null @@ -1,30 +0,0 @@ -[ 171ms] [ERROR] WebSocket connection to 'ws://localhost:5000/?token=BoEzBs8UHcdu' failed: Error during WebSocket handshake: Unexpected response code: 400 @ http://localhost:5000/@vite/client:535 -[ 173ms] SyntaxError: Failed to construct 'WebSocket': The URL 'ws://localhost:undefined/?token=BoEzBs8UHcdu' is invalid. - at setupWebSocket (http://localhost:5000/@vite/client:536:19) - at fallback (http://localhost:5000/@vite/client:509:16) - at WebSocket. (http://localhost:5000/@vite/client:555:7) -[ 466ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 -[ 9541ms] [ERROR] Global error caught: ErrorEvent @ http://localhost:5000/src/components/game/HuntersPath.tsx?t=1771875586925:984 -[ 9543ms] [ERROR] Global error caught: ErrorEvent @ http://localhost:5000/src/components/game/HuntersPath.tsx?t=1771875586925:984 -[ 9545ms] [ERROR] TypeError: mod.applyToCombat is not a function - at http://localhost:5000/src/components/game/HuntersPath.tsx?t=1771875586925:1246:30 - at basicStateReducer (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=964d8f76:11703:49) - at updateReducer (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=964d8f76:11794:30) - at updateState (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=964d8f76:12021:18) - at Object.useState (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=964d8f76:12753:24) - at useState (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-3TFVT2CW.js?v=964d8f76:1066:29) - at HuntersPath (http://localhost:5000/src/components/game/HuntersPath.tsx?t=1771875586925:894:33) - at renderWithHooks (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=964d8f76:11548:26) - at updateFunctionComponent (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=964d8f76:14582:28) - at beginWork (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=964d8f76:15924:22) @ http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=964d8f76:14019 -[ 9545ms] [ERROR] The above error occurred in the component: - - at HuntersPath (http://localhost:5000/src/components/game/HuntersPath.tsx?t=1771875586925:883:62) - at Provider (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-YB5KI4Z7.js?v=964d8f76:88:15) - at TooltipProvider (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/@radix-ui_react-tooltip.js?v=964d8f76:2242:5) - at QueryClientProvider (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/@tanstack_react-query.js?v=964d8f76:2805:3) - at App - -Consider adding an error boundary to your tree to customize error handling behavior. -Visit https://reactjs.org/link/error-boundaries to learn more about error boundaries. @ http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=964d8f76:14031 -[ 9546ms] [ERROR] Global error caught: ErrorEvent @ http://localhost:5000/src/components/game/HuntersPath.tsx?t=1771875586925:984 diff --git a/.playwright-mcp/console-2026-02-23T19-40-17-406Z.log b/.playwright-mcp/console-2026-02-23T19-40-17-406Z.log deleted file mode 100644 index a49e2db..0000000 --- a/.playwright-mcp/console-2026-02-23T19-40-17-406Z.log +++ /dev/null @@ -1,32 +0,0 @@ -[ 25ms] [ERROR] WebSocket connection to 'ws://localhost:5000/?token=fkAS5C_-shpN' failed: Error during WebSocket handshake: Unexpected response code: 400 @ http://localhost:5000/@vite/client:535 -[ 41ms] SyntaxError: Failed to construct 'WebSocket': The URL 'ws://localhost:undefined/?token=fkAS5C_-shpN' is invalid. - at setupWebSocket (http://localhost:5000/@vite/client:536:19) - at fallback (http://localhost:5000/@vite/client:509:16) - at WebSocket. (http://localhost:5000/@vite/client:555:7) -[ 118ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:196 -[ 118ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:250 -[ 128ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 -[ 9115ms] [ERROR] Global error caught: ErrorEvent @ http://localhost:5000/src/components/game/HuntersPath.tsx?t=1771875586925:984 -[ 9115ms] [ERROR] Global error caught: ErrorEvent @ http://localhost:5000/src/components/game/HuntersPath.tsx?t=1771875586925:984 -[ 9117ms] [ERROR] TypeError: mod.applyToCombat is not a function - at http://localhost:5000/src/components/game/HuntersPath.tsx?t=1771875586925:1246:30 - at basicStateReducer (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=964d8f76:11703:49) - at updateReducer (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=964d8f76:11794:30) - at updateState (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=964d8f76:12021:18) - at Object.useState (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=964d8f76:12753:24) - at useState (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-3TFVT2CW.js?v=964d8f76:1066:29) - at HuntersPath (http://localhost:5000/src/components/game/HuntersPath.tsx?t=1771875586925:894:33) - at renderWithHooks (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=964d8f76:11548:26) - at updateFunctionComponent (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=964d8f76:14582:28) - at beginWork (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=964d8f76:15924:22) @ http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=964d8f76:14019 -[ 9117ms] [ERROR] The above error occurred in the component: - - at HuntersPath (http://localhost:5000/src/components/game/HuntersPath.tsx?t=1771875586925:883:62) - at Provider (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-YB5KI4Z7.js?v=964d8f76:88:15) - at TooltipProvider (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/@radix-ui_react-tooltip.js?v=964d8f76:2242:5) - at QueryClientProvider (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/@tanstack_react-query.js?v=964d8f76:2805:3) - at App - -Consider adding an error boundary to your tree to customize error handling behavior. -Visit https://reactjs.org/link/error-boundaries to learn more about error boundaries. @ http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=964d8f76:14031 -[ 9117ms] [ERROR] Global error caught: ErrorEvent @ http://localhost:5000/src/components/game/HuntersPath.tsx?t=1771875586925:984 diff --git a/.playwright-mcp/console-2026-02-23T19-41-04-381Z.log b/.playwright-mcp/console-2026-02-23T19-41-04-381Z.log deleted file mode 100644 index 169826f..0000000 --- a/.playwright-mcp/console-2026-02-23T19-41-04-381Z.log +++ /dev/null @@ -1,8 +0,0 @@ -[ 172ms] [ERROR] WebSocket connection to 'ws://localhost:5000/?token=fkAS5C_-shpN' failed: Error during WebSocket handshake: Unexpected response code: 400 @ http://localhost:5000/@vite/client:535 -[ 184ms] SyntaxError: Failed to construct 'WebSocket': The URL 'ws://localhost:undefined/?token=fkAS5C_-shpN' is invalid. - at setupWebSocket (http://localhost:5000/@vite/client:536:19) - at fallback (http://localhost:5000/@vite/client:509:16) - at WebSocket. (http://localhost:5000/@vite/client:555:7) -[ 287ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:196 -[ 288ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:250 -[ 299ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 diff --git a/.playwright-mcp/console-2026-02-23T19-47-50-716Z.log b/.playwright-mcp/console-2026-02-23T19-47-50-716Z.log deleted file mode 100644 index 75b00fd..0000000 --- a/.playwright-mcp/console-2026-02-23T19-47-50-716Z.log +++ /dev/null @@ -1,6 +0,0 @@ -[ 30ms] [ERROR] WebSocket connection to 'ws://localhost:5000/?token=UWwUHPKdepNM' failed: Error during WebSocket handshake: Unexpected response code: 400 @ http://localhost:5000/@vite/client:535 -[ 36ms] SyntaxError: Failed to construct 'WebSocket': The URL 'ws://localhost:undefined/?token=UWwUHPKdepNM' is invalid. - at setupWebSocket (http://localhost:5000/@vite/client:536:19) - at fallback (http://localhost:5000/@vite/client:509:16) - at WebSocket. (http://localhost:5000/@vite/client:555:7) -[ 446ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 diff --git a/.playwright-mcp/console-2026-02-23T19-48-07-301Z.log b/.playwright-mcp/console-2026-02-23T19-48-07-301Z.log deleted file mode 100644 index e409562..0000000 --- a/.playwright-mcp/console-2026-02-23T19-48-07-301Z.log +++ /dev/null @@ -1,8 +0,0 @@ -[ 29ms] [ERROR] WebSocket connection to 'ws://localhost:5000/?token=fkAS5C_-shpN' failed: Error during WebSocket handshake: Unexpected response code: 400 @ http://localhost:5000/@vite/client:535 -[ 55ms] SyntaxError: Failed to construct 'WebSocket': The URL 'ws://localhost:undefined/?token=fkAS5C_-shpN' is invalid. - at setupWebSocket (http://localhost:5000/@vite/client:536:19) - at fallback (http://localhost:5000/@vite/client:509:16) - at WebSocket. (http://localhost:5000/@vite/client:555:7) -[ 335ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:196 -[ 336ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:250 -[ 348ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 diff --git a/.playwright-mcp/console-2026-02-23T19-48-15-016Z.log b/.playwright-mcp/console-2026-02-23T19-48-15-016Z.log deleted file mode 100644 index dd66916..0000000 --- a/.playwright-mcp/console-2026-02-23T19-48-15-016Z.log +++ /dev/null @@ -1,3 +0,0 @@ -[ 124ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:196 -[ 125ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:250 -[ 135ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 diff --git a/.playwright-mcp/console-2026-02-23T19-51-09-572Z.log b/.playwright-mcp/console-2026-02-23T19-51-09-572Z.log deleted file mode 100644 index 4c7be0c..0000000 --- a/.playwright-mcp/console-2026-02-23T19-51-09-572Z.log +++ /dev/null @@ -1,16 +0,0 @@ -[ 30ms] [ERROR] WebSocket connection to 'ws://localhost:5000/?token=UWwUHPKdepNM' failed: Error during WebSocket handshake: Unexpected response code: 400 @ http://localhost:5000/@vite/client:535 -[ 59ms] SyntaxError: Failed to construct 'WebSocket': The URL 'ws://localhost:undefined/?token=UWwUHPKdepNM' is invalid. - at setupWebSocket (http://localhost:5000/@vite/client:536:19) - at fallback (http://localhost:5000/@vite/client:509:16) - at WebSocket. (http://localhost:5000/@vite/client:555:7) -[ 345ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:196 -[ 346ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:250 -[ 357ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 -[ 582316ms] [ERROR] WebSocket connection to 'ws://localhost:5000/?token=UWwUHPKdepNM' failed: Error during WebSocket handshake: Unexpected response code: 400 @ http://localhost:5000/@vite/client:535 -[ 582330ms] SyntaxError: Failed to construct 'WebSocket': The URL 'ws://localhost:undefined/?token=UWwUHPKdepNM' is invalid. - at setupWebSocket (http://localhost:5000/@vite/client:536:19) - at fallback (http://localhost:5000/@vite/client:509:16) - at WebSocket. (http://localhost:5000/@vite/client:555:7) -[ 582695ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:196 -[ 582696ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:250 -[ 582704ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 diff --git a/.playwright-mcp/console-2026-02-23T20-10-55-971Z.log b/.playwright-mcp/console-2026-02-23T20-10-55-971Z.log deleted file mode 100644 index 66bd9c9..0000000 --- a/.playwright-mcp/console-2026-02-23T20-10-55-971Z.log +++ /dev/null @@ -1,6 +0,0 @@ -[ 38ms] [ERROR] WebSocket connection to 'ws://localhost:5000/?token=BoEzBs8UHcdu' failed: Error during WebSocket handshake: Unexpected response code: 400 @ http://localhost:5000/@vite/client:535 -[ 58ms] SyntaxError: Failed to construct 'WebSocket': The URL 'ws://localhost:undefined/?token=BoEzBs8UHcdu' is invalid. - at setupWebSocket (http://localhost:5000/@vite/client:536:19) - at fallback (http://localhost:5000/@vite/client:509:16) - at WebSocket. (http://localhost:5000/@vite/client:555:7) -[ 373ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 diff --git a/.playwright-mcp/console-2026-02-23T20-14-00-467Z.log b/.playwright-mcp/console-2026-02-23T20-14-00-467Z.log deleted file mode 100644 index cb76bd1..0000000 --- a/.playwright-mcp/console-2026-02-23T20-14-00-467Z.log +++ /dev/null @@ -1,73 +0,0 @@ -[ 28ms] [ERROR] WebSocket connection to 'ws://localhost:5000/?token=BoEzBs8UHcdu' failed: Error during WebSocket handshake: Unexpected response code: 400 @ http://localhost:5000/@vite/client:535 -[ 35ms] SyntaxError: Failed to construct 'WebSocket': The URL 'ws://localhost:undefined/?token=BoEzBs8UHcdu' is invalid. - at setupWebSocket (http://localhost:5000/@vite/client:536:19) - at fallback (http://localhost:5000/@vite/client:509:16) - at WebSocket. (http://localhost:5000/@vite/client:555:7) -[ 178ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:196 -[ 178ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:250 -[ 197ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 -[ 5534145ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_RESET @ http://localhost:5000/src/components/ui/tooltip.tsx:0 -[ 5534145ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/src/components/PWAInstallPrompt.tsx:0 -[ 5534145ms] [ERROR] Failed to load resource: net::ERR_EMPTY_RESPONSE @ http://localhost:5000/src/components/ui/toaster.tsx:0 -[ 5534145ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/src/lib/queryClient.ts:0 -[ 5534145ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/src/components/game/HuntersPath.tsx:0 -[ 5534145ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/src/components/ErrorBoundary.tsx:0 -[ 5534147ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[ 5534148ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/icon-192x192.png:0 -[ 5534149ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/HunterPath/icon-192x192.png:0 -[ 5534149ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/icon-512x512.png:0 -[ 5534149ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 -[ 5535148ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[ 5536150ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[ 5537151ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[ 5538152ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[ 5539154ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[ 5540155ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[ 5541157ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[ 5542158ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[ 5543160ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[ 5544161ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[ 5545162ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[ 5546164ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[ 5547166ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[ 5548167ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[ 5549168ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[ 5550170ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[ 5551171ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[ 5552173ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[ 5553175ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[ 5554177ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[ 5555178ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[ 5556180ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[ 5557185ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[ 5558189ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[ 5559191ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[ 5560194ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[ 5561195ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[ 5562197ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[ 5563198ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[ 5564200ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[ 5565202ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[ 5566203ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[ 5567205ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[ 5568207ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[ 5569208ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[ 5570210ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[ 5571211ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[ 5572212ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[ 5573214ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[ 5574215ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[ 5575217ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[ 5576218ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[ 5577220ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[ 5578222ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[ 5579224ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[ 5580226ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[ 5581227ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[ 5582229ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[ 5583230ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[ 5584232ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[ 5585233ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[ 5587372ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:196 -[ 5587373ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:250 -[ 5587507ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 diff --git a/.playwright-mcp/console-2026-02-23T21-47-13-905Z.log b/.playwright-mcp/console-2026-02-23T21-47-13-905Z.log deleted file mode 100644 index 0feac48..0000000 --- a/.playwright-mcp/console-2026-02-23T21-47-13-905Z.log +++ /dev/null @@ -1,1808 +0,0 @@ -[ 130ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:196 -[ 131ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:250 -[ 136ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 -[ 551319ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 -[71407424ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71408426ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71409427ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71410428ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71411429ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71412430ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71413432ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71414433ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71415434ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71416436ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71417437ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71418439ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71419440ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71420442ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71421443ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71422444ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71423445ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71424447ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71425448ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71426450ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71427451ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71428452ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71433037ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71434038ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71435039ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71436041ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71437042ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71438044ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71439045ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71440046ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71441048ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71442049ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71443050ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71444051ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71445053ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71446054ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71447055ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71448056ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71449058ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71450059ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71451060ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71452062ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71453063ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71454065ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71455066ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71456067ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71457068ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71458070ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71459071ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71460072ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71461074ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71462075ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71463076ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71464077ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71468666ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71469667ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71470669ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71471670ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71472671ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71473673ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71474674ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71475675ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71476677ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71477679ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71478680ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71479681ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71480682ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71481685ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71482686ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71483687ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71484689ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71485690ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71486691ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71487692ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71488694ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71489695ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71490696ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71491697ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71492699ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71493700ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71494701ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71495702ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71496704ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71497706ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71498707ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71499708ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71500709ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71505292ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71506293ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71507294ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71508295ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71509296ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71510297ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71511299ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71512300ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71513301ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71514302ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71515303ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71516305ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71517306ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71518307ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71519309ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71520310ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71521311ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71522312ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71523313ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71524315ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71525316ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71526318ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71527319ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71528320ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71529321ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71530323ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71531324ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71532325ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71533326ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71534327ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71535329ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71536330ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71540916ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71541917ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71542918ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71543919ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71544920ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71545922ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71546923ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71547924ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71548925ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71549927ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71550928ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71551930ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71552931ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71553932ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71554933ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71555935ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71556936ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71557937ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71558938ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71559939ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71560941ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71561942ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71562943ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71563944ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71564946ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71565947ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71566948ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71567949ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71568951ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71569952ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71570953ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71571954ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71576546ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71577547ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71578548ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71579550ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71580551ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71581553ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71582555ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71583556ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71584557ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71585558ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71586560ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71587561ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71588562ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71589563ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71590564ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71591566ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71592567ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71593568ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71594569ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71595570ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71596572ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71597573ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71598574ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71599575ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71600577ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71601578ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71602579ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71603581ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71604582ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71605583ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71606585ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71607586ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71612167ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71613169ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71614170ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71615171ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71616172ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71617174ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71618175ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71619177ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71620180ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71621182ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71622184ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71623187ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71624189ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71625190ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71626192ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71627193ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71628194ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71629195ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71630197ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71631198ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71632199ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71633201ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71634202ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71635204ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71636205ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71637206ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71638208ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71639209ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71640210ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71641212ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71642213ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71643215ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71647801ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71648802ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71649803ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71650805ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71651806ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71652807ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71653809ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71654810ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71655811ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71656812ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71657813ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71658815ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71659816ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71660818ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71661819ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71662820ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71663822ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71664823ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71665824ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71666826ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71667828ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71668829ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71669830ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71670832ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71671833ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71672835ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71673836ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71674837ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71675838ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71676840ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71677841ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71678842ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71679844ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71684431ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71685432ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71686434ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71687435ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71688437ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71689438ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71690439ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71691441ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71692443ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71693444ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71694445ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71695446ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71696448ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71697449ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71698450ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71699452ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71700453ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71701455ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71702456ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71703457ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71704458ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71705460ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71706461ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71707462ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71708464ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71709465ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71710467ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71711469ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71712471ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71713472ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71714473ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71715475ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71720059ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71721061ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71722062ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71723063ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71724064ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71725065ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71726067ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71727068ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71728069ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71729070ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71730072ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71731073ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71732074ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71733076ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71734077ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71735078ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71736079ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71737081ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71738083ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71739084ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71740086ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71741087ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71742088ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71743089ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71744090ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71745092ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71746093ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71747094ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71748095ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71749096ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71750098ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71751099ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71755696ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71756697ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71757698ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71758700ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71759701ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71760702ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71761704ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71762705ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71763706ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71764708ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71765709ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71766711ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71767712ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71768713ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71769714ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71770716ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71771717ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71772718ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71773719ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71774721ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71775722ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71776723ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71777724ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71778726ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71779727ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71780728ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71781730ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71782731ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71783732ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71784734ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71785736ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71786738ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71791312ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71792313ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71793314ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71794316ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71795317ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71796318ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71797319ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71798320ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71799322ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71800323ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71801324ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71802326ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71803327ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71804328ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71805329ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71806331ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71807332ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71808333ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71809335ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71810336ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71811338ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71812340ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71813341ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71814342ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71815343ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71816345ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71817346ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71818347ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71819348ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71820350ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71821351ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71822352ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71823354ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71827940ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71828941ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71829943ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71830944ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71831945ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71832946ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71833948ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71834949ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71835951ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71836952ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71837953ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71838956ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71839957ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71840959ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71841961ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71842962ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71843963ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71844964ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71845966ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71846967ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71847969ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71848970ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71849971ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71850973ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71851974ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71852975ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71853977ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71854978ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71855980ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71856981ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71857982ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71858984ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71863572ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71864573ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71865574ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71866576ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71867577ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71868579ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71869580ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71870581ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71871582ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71872587ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71873588ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71874589ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71875591ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71876592ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71877593ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71878595ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71879596ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71880597ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71881598ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71882599ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71883601ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71884602ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71885603ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71886604ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71887605ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71888607ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71889608ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71890609ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71891610ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71892611ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71893613ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71894614ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71899202ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71900204ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71901205ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71902207ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71903210ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71904211ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71905212ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71906213ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71907215ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71908216ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71909217ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71910219ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71911220ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71912221ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71913222ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71914224ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71915225ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71916226ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71917228ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71918229ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71919230ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71920231ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71921233ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71922234ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71923236ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71924237ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71925238ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71926244ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71927246ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71928248ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71929250ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71930251ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71934832ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71935833ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71936835ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71937836ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71938837ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71939839ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71940840ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71941841ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71942843ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71943844ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71944846ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71945847ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71946848ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71947849ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71948850ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71949851ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71950852ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71951854ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71952856ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71953857ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71954859ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71955860ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71956861ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71957863ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71958864ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71959865ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71960866ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71961868ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71962869ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71963871ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71964872ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71965874ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71970435ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71971436ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71972437ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71973439ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71974440ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71975441ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71976442ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71977443ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71978445ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71979446ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71980447ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71981448ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71982450ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71983451ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71984452ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71985453ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71986455ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71987456ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71988457ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71989458ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71990460ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71991461ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71992462ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71993464ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71994465ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71995466ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71996467ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71997468ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71998469ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[71999471ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72000472ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72001473ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72002475ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72007085ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72008086ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72009087ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72010088ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72011090ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72012091ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72013092ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72014093ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72015095ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72016096ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72017097ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72018098ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72019100ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72020101ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72021102ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72022104ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72023105ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72024106ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72025107ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72026108ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72027110ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72028111ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72029112ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72030113ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72031114ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72032115ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72033117ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72034118ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72035119ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72036120ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72037122ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72038123ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72042713ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72043714ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72044716ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72045717ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72046718ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72047720ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72048722ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72049723ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72050724ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72051725ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72052727ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72053728ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72054729ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72055730ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72056732ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72057733ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72058734ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72059736ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72060737ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72061739ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72062740ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72063743ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72064744ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72065746ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72066747ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72067749ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72068750ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72069751ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72070752ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72071754ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72072755ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72073756ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72078340ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72079341ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72080343ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72081344ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72082345ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72083346ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72084348ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72085349ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72086350ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72087351ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72088352ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72089353ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72090355ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72091356ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72092358ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72093359ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72094360ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72095362ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72096363ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72097365ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72098366ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72099367ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72100368ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72101370ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72102372ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72103373ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72104374ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72105376ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72106378ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72107379ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72108381ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72109383ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72113973ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72114974ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72115976ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72116977ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72117978ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72118979ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72119981ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72120982ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72121983ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72122984ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72123986ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72124988ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72125989ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72126990ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72127991ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72128992ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72129994ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72130995ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72131996ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72132998ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72133999ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72135000ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72136001ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72137003ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72138004ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72139005ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72140007ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72141008ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72142009ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72143011ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72144012ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72145013ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72149593ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72150594ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72151595ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72152597ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72153598ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72154599ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72155600ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72156601ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72157603ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72158604ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72159606ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72160607ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72161608ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72162609ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72163611ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72164613ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72165615ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72166616ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72167617ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72168619ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72169620ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72170622ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72171623ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72172624ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72173626ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72174627ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72175628ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72176629ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72177630ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72178632ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72179633ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72180634ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72181636ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72186224ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72187225ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72188227ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72189229ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72190230ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72191232ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72192233ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72193234ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72194235ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72195236ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72196238ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72197239ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72198240ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72199241ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72200243ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72201244ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72202245ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72203246ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72204248ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72205249ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72206250ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72207252ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72208253ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72209254ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72210256ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72211257ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72212258ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72213259ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72214261ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72215262ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72216263ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72217264ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72221851ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72222853ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72223854ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72224855ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72225856ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72226857ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72227859ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72228861ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72229862ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72230863ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72231865ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72232867ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72233869ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72234870ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72235872ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72236873ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72237875ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72238877ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72239878ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72240879ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72241881ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72242882ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72243884ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72244885ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72245886ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72246887ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72247889ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72248890ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72249892ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72250893ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72251895ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72252896ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72257493ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72258495ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72259496ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72260497ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72261498ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72262500ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72263502ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72264503ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72265504ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72266506ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72267507ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72268509ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72269510ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72270511ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72271513ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72272514ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72273515ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72274517ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72275518ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72276520ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72277522ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72278523ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72279524ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72280526ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72281527ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72282529ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72283530ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72284531ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72285533ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72286534ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72287535ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72288537ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72293114ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72294116ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72295118ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72296119ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72297121ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72298122ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72299123ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72300125ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72301128ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72302129ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72303131ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72304133ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72305134ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72306136ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72307137ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72308138ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72309140ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72310141ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72311142ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72312144ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72313145ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72314147ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72315149ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72316150ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72317152ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72318154ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72319156ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72320157ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72321158ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72322160ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72323161ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72324163ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72328742ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72329744ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72330745ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72331747ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72332748ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72333750ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72334751ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72335754ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72336756ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72337757ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72338758ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72339760ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72340761ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72341762ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72342763ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72343766ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72344768ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72345769ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72346770ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72347772ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72348774ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72349775ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72350777ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72351778ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72352780ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72353782ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72354784ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72355785ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72356786ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72357788ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72358789ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72359790ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72360792ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72365369ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72366370ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72367371ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72368372ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72369374ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72370376ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72371377ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72372378ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72373380ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72374382ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72375383ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72376386ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72377388ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72378389ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72379391ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72380392ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72381393ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72382394ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72383396ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72384398ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72385399ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72386400ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72387402ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72388403ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72389405ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72390406ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72391408ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72392409ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72393411ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72394413ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72395414ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72396415ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72400709ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72401711ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72402712ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72403713ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72404714ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72405716ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72406717ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72407718ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72408720ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72409721ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72410722ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72411723ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72412725ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72413726ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72414728ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72415729ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72416730ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72417732ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72418733ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72419734ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72420736ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72421737ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72422738ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72423739ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72424740ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72425742ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72426743ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72427744ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72428746ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72429747ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72430748ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72431750ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72436192ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72437194ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72438197ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72439198ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72440199ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72441200ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72442203ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72443204ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72444205ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72445207ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72446208ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72447209ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72448210ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72449212ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72450213ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72451214ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72452215ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72453217ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72454218ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72455220ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72456221ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72457222ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72458224ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72459225ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72460226ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72461227ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72462229ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72463230ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72464232ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72465233ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72466234ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72467235ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72471824ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72472826ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72473829ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72474830ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72475831ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72476833ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72477834ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72478836ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72479837ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72480838ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72481840ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72482841ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72483842ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72484844ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72485845ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72486847ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72487848ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72488849ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72489851ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72490852ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72491853ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72492855ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72493856ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72494857ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72495859ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72496860ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72497861ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72498863ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72499864ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72500865ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72501867ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72502868ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72507452ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72508453ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72509455ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72510457ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72511458ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72512459ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72513460ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72514462ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72515463ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72516464ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72517465ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72518467ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72519468ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72520469ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72521471ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72522472ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72523473ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72524474ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72525476ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72526477ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72527479ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72528480ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72529482ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72530483ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72531485ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72532486ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72533487ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72534489ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72535490ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72536492ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72537493ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72538494ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72539496ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72544082ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72545083ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72546085ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72547086ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72548087ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72549088ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72550090ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72551092ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72552094ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72553095ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72554098ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72555099ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72556101ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72557103ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72558105ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72559107ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72560108ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72561110ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72562111ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72563112ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72564114ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72565115ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72566116ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72567119ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72568120ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72569122ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72570123ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72571125ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72572126ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72573127ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72574129ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72575130ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72579717ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72580718ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72581720ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72582723ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72583725ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72584726ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72585727ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72586728ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72587730ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72588731ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72589733ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72590734ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72591735ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72592737ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72593738ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72594739ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72595741ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72596743ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72597744ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72598745ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72599746ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72600748ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72601749ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72602751ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72603752ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72604754ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72605755ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72606756ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72607758ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72608759ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72609760ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72610762ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72615348ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72616349ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72617350ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72618351ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72619353ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72620354ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72621356ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72622357ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72623358ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72624360ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72625361ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72626363ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72627364ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72628368ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72629369ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72630370ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72631372ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72632374ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72633375ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72634376ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72635377ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72636378ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72637380ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72638381ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72639382ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72640384ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72641385ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72642387ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72643388ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72644389ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72645391ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72646392ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72650978ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72651979ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72652980ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72653982ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72654983ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72655985ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72656987ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72657988ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72658989ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72659990ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72660991ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72661993ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72662994ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72663995ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72664997ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72665999ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72667000ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72668002ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72669003ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72670004ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72671006ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72672007ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72673008ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72674010ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72675012ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72676013ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72677014ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72678015ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72679016ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72680018ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72681019ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72682021ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72686607ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72687608ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72688610ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72689611ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72690612ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72691614ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72692615ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72693616ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72694618ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72695619ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72696620ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72697622ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72698624ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72699626ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72700627ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72701628ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72702630ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72703631ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72704632ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72705633ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72706635ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72707636ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72708637ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72709639ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72710640ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72711642ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72712644ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72713645ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72714647ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72715648ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72716649ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72717651ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72718652ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72723243ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72724244ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72725246ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72726247ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72727248ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72728249ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72729252ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72730253ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72731255ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72732256ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72733257ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72734259ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72735261ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72736262ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72737264ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72738265ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72739267ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72740268ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72741270ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72742271ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72743272ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72744273ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72745274ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72746276ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72747277ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72748279ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72749280ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72750282ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72751283ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72752285ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72753286ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72754288ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72758880ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72759882ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72760883ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72761884ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72762887ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72763889ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72764890ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72765891ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72766892ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72767894ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72768896ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72769897ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72770898ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72771900ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72772901ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72773903ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72774905ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72775906ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72776908ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72777909ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72778910ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72779912ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72780914ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72781916ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72782917ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72783918ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72784920ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72785921ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72786922ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72787924ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72788925ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72789927ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72794503ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72795504ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72796506ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72797508ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72798509ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72799511ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72800512ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72801514ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72802515ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72803517ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72804518ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72805520ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72806522ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72807523ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72808524ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72809526ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72810527ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72811529ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72812531ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72813532ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72814534ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72815536ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72816538ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72817541ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72818542ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72819544ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72820545ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72821546ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72822548ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72823549ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72824550ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72825552ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72830138ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72831139ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72832141ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72833142ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72834144ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72835145ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72836147ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72837148ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72838150ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72839152ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72840153ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72841158ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72842159ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72843160ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72844162ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72845163ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72846165ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72847166ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72848167ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72849169ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72850170ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72851171ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72852173ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72853174ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72854176ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72855178ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72856179ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72857181ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72858182ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72859183ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72860184ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72861186ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72865775ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72866777ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72867778ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72868779ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72869781ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72870782ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72871784ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72872785ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72873787ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72874788ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72875791ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72876792ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72877794ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72878795ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72879796ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72880798ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72881799ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72882800ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72883802ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72884803ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72885804ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72886806ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72887807ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72888808ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72889810ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72890811ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72891813ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72892814ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72893815ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72894816ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72895817ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72896819ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72897821ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72902403ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72903404ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72904406ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72905407ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72906408ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72907410ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72908411ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72909412ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72910414ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72911415ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72912416ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72913417ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72914419ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72915420ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72916421ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72917423ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72918424ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72919426ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72920428ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72921430ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72922431ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72923433ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72924434ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72925436ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72926437ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72927438ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72928440ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72929441ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72930442ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72931443ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72932445ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72933446ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72938033ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72939034ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72940035ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72941037ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72942038ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72943040ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72944042ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72945043ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72946045ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72947046ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72948047ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72949051ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72950052ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72951053ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72952054ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72953055ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72954056ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72955058ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72956059ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72957060ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72958062ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72959063ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72960065ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72961066ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72962069ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72963070ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72964071ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72965073ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72966074ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72967075ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72968076ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72969077ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72973661ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72974662ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72975664ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72976665ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72977666ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72978668ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72979669ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72980670ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72981671ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72982673ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72983674ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72984676ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72985677ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72986678ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72987681ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72988682ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72989684ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72990685ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72991688ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72992689ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72993690ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72994692ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72995693ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72996694ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72997696ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72998697ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[72999699ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73000700ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73001701ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73002702ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73003704ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73004706ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73009298ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73010299ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73011300ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73012301ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73013302ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73014303ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73015305ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73016306ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73017307ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73018308ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73019310ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73020311ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73021312ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73022313ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73023315ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73024316ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73025317ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73026318ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73027320ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73028321ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73029323ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73030324ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73031326ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73032328ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73033329ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73034330ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73035331ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73036332ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73037334ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73038335ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73039336ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73040338ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73044921ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73045922ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73046923ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73047924ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73048926ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73049927ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73050929ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73051930ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73052932ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73053934ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73054935ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73055937ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73056938ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73057941ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73058942ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73059943ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73060944ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73061946ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73062947ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73063948ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73064949ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73065950ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73066952ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73067954ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73068955ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73069957ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73070958ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73071960ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73072962ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73073964ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73074965ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73075966ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73076967ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73081559ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73082560ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73083562ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73084563ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73085564ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73086566ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73087567ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73088568ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73089569ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73090571ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73091572ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73092573ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73093574ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73094576ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73095578ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73096580ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73097582ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73098583ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73099585ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73100587ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73101588ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73102589ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73103591ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73104592ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73105593ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73106594ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73107596ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73108597ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73109598ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73110599ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73111600ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73112602ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73117182ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73118183ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73119185ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73120187ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73121188ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73122189ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73123190ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73124192ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73125193ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73126194ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73127196ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73128197ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73129198ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73130199ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73131200ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73132202ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73133203ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73134204ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73135206ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73136208ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73137209ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73138210ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73139212ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73140214ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73141216ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73142217ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73143219ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73144221ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73145222ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73146223ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73147225ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73148227ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73152812ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73153815ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73154816ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73155817ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73156819ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73157820ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73158822ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73159824ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73160825ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73161826ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73162828ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73163829ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73164830ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73165832ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73166833ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73167834ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73168835ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73169836ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73170837ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73171839ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73172840ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73173841ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73174842ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73175844ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73176846ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73177847ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73178848ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73179849ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73180851ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73181853ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73182854ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73183859ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73188448ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73189449ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73190451ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73191452ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73192454ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73193455ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73194456ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73195457ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73196460ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73197461ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73198463ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73199464ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73200466ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73201468ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73202469ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73203470ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73204472ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73205473ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73206474ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73207476ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73208477ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73209478ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73210480ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73211481ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73212482ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73213484ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73214486ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73215487ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73216488ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73217491ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73218493ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73219494ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73224078ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73225080ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73226081ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73227083ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73228084ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73229085ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73230087ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73231088ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73232089ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73233091ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73234093ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73235094ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73236095ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73237097ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73238098ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73239101ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73240102ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73241104ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73242105ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73243106ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73244107ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73245109ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73246110ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73247111ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73248112ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73249114ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73250115ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73251116ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73252117ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73253118ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73254120ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73255121ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73256123ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73260710ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73261711ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73262714ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73263716ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73264717ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73265719ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73266720ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73267721ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73268723ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73269724ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73270725ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73271726ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73272728ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73273730ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73274731ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73275733ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73276734ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73277736ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73278737ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73279738ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73280740ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73281741ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73282743ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73283744ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73284746ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73285747ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73286748ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73287749ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73288751ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73289752ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73290753ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73291755ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73296340ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73297341ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73298342ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73299344ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73300345ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73301349ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73302350ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73303352ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73304354ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73305355ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73306357ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73307358ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73308359ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73309361ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73310362ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73311363ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73312364ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73313366ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73314367ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73315368ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73316370ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73317371ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73318372ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73319374ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73320375ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73321376ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73322378ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73323380ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73324381ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73325383ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73326384ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73327385ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73331972ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73332973ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73333975ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73334976ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73335978ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73336979ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73337980ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73338982ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73339984ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73340985ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73341987ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73342988ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73343989ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73344991ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73345993ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73346994ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73347996ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73348997ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73349998ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73351000ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73352002ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73353003ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73354004ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73355005ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73356006ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73357007ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73358009ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73359010ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73360011ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73361013ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73362014ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73363016ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73367602ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73368603ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73369605ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73370607ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73371608ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73372609ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73373610ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73374612ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73375613ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73376614ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73377615ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73378616ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73379618ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73380619ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73381621ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73382622ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73383623ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73384625ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73385626ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73386627ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73387629ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73388630ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73389631ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73390633ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73391635ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73392636ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73393637ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73394638ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73395640ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73396641ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73397642ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73398643ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73399645ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73404233ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73405234ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73406236ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73407237ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73408239ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73409240ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73410241ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73411243ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73412244ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 -[73413246ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/:0 diff --git a/.playwright-mcp/console-2026-02-25T13-03-51-198Z.log b/.playwright-mcp/console-2026-02-25T13-03-51-198Z.log deleted file mode 100644 index 714967a..0000000 --- a/.playwright-mcp/console-2026-02-25T13-03-51-198Z.log +++ /dev/null @@ -1,3 +0,0 @@ -[ 1186ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:196 -[ 1187ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:250 -[ 1296ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 diff --git a/.playwright-mcp/console-2026-02-25T14-37-54-061Z.log b/.playwright-mcp/console-2026-02-25T14-37-54-061Z.log deleted file mode 100644 index 40b6dd6..0000000 --- a/.playwright-mcp/console-2026-02-25T14-37-54-061Z.log +++ /dev/null @@ -1,3 +0,0 @@ -[ 513ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:196 -[ 514ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:250 -[ 525ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 diff --git a/.playwright-mcp/console-2026-02-25T14-55-16-288Z.log b/.playwright-mcp/console-2026-02-25T14-55-16-288Z.log deleted file mode 100644 index 17f9de4..0000000 --- a/.playwright-mcp/console-2026-02-25T14-55-16-288Z.log +++ /dev/null @@ -1,3 +0,0 @@ -[ 160ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:196 -[ 160ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:250 -[ 170ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 diff --git a/.playwright-mcp/console-2026-02-25T15-00-24-812Z.log b/.playwright-mcp/console-2026-02-25T15-00-24-812Z.log deleted file mode 100644 index 9b25dcf..0000000 --- a/.playwright-mcp/console-2026-02-25T15-00-24-812Z.log +++ /dev/null @@ -1,3 +0,0 @@ -[ 131ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:196 -[ 131ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:250 -[ 141ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 diff --git a/.playwright-mcp/console-2026-02-25T15-01-42-160Z.log b/.playwright-mcp/console-2026-02-25T15-01-42-160Z.log deleted file mode 100644 index e1041fe..0000000 --- a/.playwright-mcp/console-2026-02-25T15-01-42-160Z.log +++ /dev/null @@ -1,18 +0,0 @@ -[ 107ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:196 -[ 108ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:250 -[ 113ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 -[ 161607ms] [ERROR] Global error caught: ErrorEvent @ http://localhost:5000/src/components/game/HuntersPath.tsx?t=1772031772425:1138 -[ 161612ms] [ERROR] Global error caught: ErrorEvent @ http://localhost:5000/src/components/game/HuntersPath.tsx?t=1772031772425:1138 -[ 161613ms] [ERROR] Game crashed: ReferenceError: CombatResultScreen is not defined - at CombatTab (http://localhost:5000/src/components/game/mobile/CombatTab.tsx?t=1772031863653:163:7) - at renderWithHooks (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=964d8f76:11548:26) - at updateFunctionComponent (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=964d8f76:14582:28) - at beginWork (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=964d8f76:15924:22) - at beginWork$1 (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=964d8f76:19753:22) - at performUnitOfWork (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=964d8f76:19198:20) - at workLoopSync (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=964d8f76:19137:13) - at renderRootSync (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=964d8f76:19116:15) - at recoverFromConcurrentError (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=964d8f76:18736:28) - at performSyncWorkOnRoot (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=964d8f76:18879:28) {componentStack: - at CombatTab (http://localhost:5000/src/compo…/src/components/ErrorBoundary.tsx:7:5) - at App} @ http://localhost:5000/src/components/ErrorBoundary.tsx:13 diff --git a/.playwright-mcp/console-2026-02-25T15-05-19-556Z.log b/.playwright-mcp/console-2026-02-25T15-05-19-556Z.log deleted file mode 100644 index 3c85c98..0000000 --- a/.playwright-mcp/console-2026-02-25T15-05-19-556Z.log +++ /dev/null @@ -1,3 +0,0 @@ -[ 115ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:196 -[ 115ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:250 -[ 123ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 diff --git a/.playwright-mcp/console-2026-02-25T15-08-26-293Z.log b/.playwright-mcp/console-2026-02-25T15-08-26-293Z.log deleted file mode 100644 index 5c2f35b..0000000 --- a/.playwright-mcp/console-2026-02-25T15-08-26-293Z.log +++ /dev/null @@ -1,6 +0,0 @@ -[ 92ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:196 -[ 93ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:250 -[ 97ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 -[ 1141696ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:196 -[ 1141697ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:250 -[ 1141708ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 diff --git a/.playwright-mcp/console-2026-02-25T15-55-36-677Z.log b/.playwright-mcp/console-2026-02-25T15-55-36-677Z.log deleted file mode 100644 index 3c906d7..0000000 --- a/.playwright-mcp/console-2026-02-25T15-55-36-677Z.log +++ /dev/null @@ -1,3 +0,0 @@ -[ 142ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:196 -[ 142ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:250 -[ 155ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 diff --git a/.playwright-mcp/console-2026-02-25T16-02-04-199Z.log b/.playwright-mcp/console-2026-02-25T16-02-04-199Z.log deleted file mode 100644 index 7eb5f42..0000000 --- a/.playwright-mcp/console-2026-02-25T16-02-04-199Z.log +++ /dev/null @@ -1,3 +0,0 @@ -[ 135ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:196 -[ 136ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:250 -[ 150ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 diff --git a/.playwright-mcp/console-2026-02-25T16-06-50-451Z.log b/.playwright-mcp/console-2026-02-25T16-06-50-451Z.log deleted file mode 100644 index a8cac71..0000000 --- a/.playwright-mcp/console-2026-02-25T16-06-50-451Z.log +++ /dev/null @@ -1,3 +0,0 @@ -[ 158ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:196 -[ 159ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:250 -[ 168ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 diff --git a/.playwright-mcp/console-2026-02-25T16-08-06-938Z.log b/.playwright-mcp/console-2026-02-25T16-08-06-938Z.log deleted file mode 100644 index ef8711c..0000000 --- a/.playwright-mcp/console-2026-02-25T16-08-06-938Z.log +++ /dev/null @@ -1,3 +0,0 @@ -[ 86ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:196 -[ 87ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:250 -[ 91ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 diff --git a/.playwright-mcp/console-2026-02-25T16-11-43-555Z.log b/.playwright-mcp/console-2026-02-25T16-11-43-555Z.log deleted file mode 100644 index 70dda9a..0000000 --- a/.playwright-mcp/console-2026-02-25T16-11-43-555Z.log +++ /dev/null @@ -1,6 +0,0 @@ -[ 86ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:196 -[ 86ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:250 -[ 91ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 -[ 757524ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:196 -[ 757525ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:250 -[ 757529ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 diff --git a/.playwright-mcp/console-2026-02-25T16-29-19-103Z.log b/.playwright-mcp/console-2026-02-25T16-29-19-103Z.log deleted file mode 100644 index 4c649a5..0000000 --- a/.playwright-mcp/console-2026-02-25T16-29-19-103Z.log +++ /dev/null @@ -1,3 +0,0 @@ -[ 128ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:196 -[ 128ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:250 -[ 137ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 diff --git a/.playwright-mcp/console-2026-02-25T16-40-03-188Z.log b/.playwright-mcp/console-2026-02-25T16-40-03-188Z.log deleted file mode 100644 index 9f0cf8d..0000000 --- a/.playwright-mcp/console-2026-02-25T16-40-03-188Z.log +++ /dev/null @@ -1,3 +0,0 @@ -[ 104ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:196 -[ 105ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:250 -[ 111ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 diff --git a/.playwright-mcp/console-2026-02-25T17-58-30-783Z.log b/.playwright-mcp/console-2026-02-25T17-58-30-783Z.log deleted file mode 100644 index 2608366..0000000 --- a/.playwright-mcp/console-2026-02-25T17-58-30-783Z.log +++ /dev/null @@ -1,3 +0,0 @@ -[ 156ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:196 -[ 157ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:250 -[ 166ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 diff --git a/.playwright-mcp/console-2026-02-25T18-00-50-679Z.log b/.playwright-mcp/console-2026-02-25T18-00-50-679Z.log deleted file mode 100644 index 76e1df8..0000000 --- a/.playwright-mcp/console-2026-02-25T18-00-50-679Z.log +++ /dev/null @@ -1,3 +0,0 @@ -[ 116ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:196 -[ 116ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:250 -[ 128ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 diff --git a/.playwright-mcp/console-2026-02-25T18-02-05-753Z.log b/.playwright-mcp/console-2026-02-25T18-02-05-753Z.log deleted file mode 100644 index 22134fd..0000000 --- a/.playwright-mcp/console-2026-02-25T18-02-05-753Z.log +++ /dev/null @@ -1,3 +0,0 @@ -[ 117ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:196 -[ 118ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:250 -[ 123ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 diff --git a/.playwright-mcp/console-2026-02-25T18-23-53-560Z.log b/.playwright-mcp/console-2026-02-25T18-23-53-560Z.log deleted file mode 100644 index 7f9fd2e..0000000 --- a/.playwright-mcp/console-2026-02-25T18-23-53-560Z.log +++ /dev/null @@ -1,8 +0,0 @@ -[ 114ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:196 -[ 115ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:250 -[ 119ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 -[ 361146ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 -[ 362081ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 -[ 573589ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:196 -[ 573589ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:250 -[ 573593ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 diff --git a/.playwright-mcp/console-2026-03-14T20-31-30-436Z.log b/.playwright-mcp/console-2026-03-14T20-31-30-436Z.log deleted file mode 100644 index bdc5e58..0000000 --- a/.playwright-mcp/console-2026-03-14T20-31-30-436Z.log +++ /dev/null @@ -1,23 +0,0 @@ -[ 1318ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:196 -[ 1319ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ http://localhost:5000/src/lib/audioManager.ts:250 -[ 1546ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 -[155932278ms] [ERROR] SyntaxError: The requested module '/src/lib/game/gameLogic.ts?t=1773676222642' does not provide an export named 'calcExtractionChance' @ http://localhost:5000/@vite/client:173 -[155932279ms] [ERROR] [hmr] Failed to reload /src/components/game/HuntersPath.tsx. This could be due to syntax errors or importing non-existent modules. (see errors above) @ http://localhost:5000/@vite/client:175 -[155932469ms] The requested module '/src/lib/game/gameLogic.ts?t=1773676222642' does not provide an export named 'calcExtractionChance' -[155932446ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 -[155945355ms] The requested module '/src/lib/game/gameLogic.ts?t=1773676222642' does not provide an export named 'calcExtractionChance' -[155945316ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 -[155973067ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 -[156033044ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 -[156046531ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 -[156233462ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_RESET @ http://localhost:5000/manifest.json:0 -[156233462ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_RESET @ http://localhost:5000/src/components/ui/toaster.tsx:0 -[156233462ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_RESET @ http://localhost:5000/src/components/ui/tooltip.tsx:0 -[156233462ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_RESET @ http://localhost:5000/src/components/PWAInstallPrompt.tsx:0 -[156233462ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/src/components/game/HuntersPath.tsx?t=1773676523555:0 -[156233462ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/src/lib/queryClient.ts:0 -[156233462ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/src/components/ErrorBoundary.tsx:0 -[156233462ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/vite/dist/client/env.mjs:0 -[156233463ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/manifest.json:0 -[156233464ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/icon-192x192.png:0 -[156233465ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:5000/icon-512x512.png:0 diff --git a/.playwright-mcp/console-2026-03-16T16-17-39-487Z.log b/.playwright-mcp/console-2026-03-16T16-17-39-487Z.log deleted file mode 100644 index 1fe4a25..0000000 --- a/.playwright-mcp/console-2026-03-16T16-17-39-487Z.log +++ /dev/null @@ -1,69 +0,0 @@ -[ 1598ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 -[ 2234ms] [ERROR] WebSocket connection to 'ws://localhost:5000/?token=vbu1h2iDFGun' failed: Error during WebSocket handshake: Unexpected response code: 400 @ http://localhost:5000/@vite/client:535 -[ 2240ms] SyntaxError: Failed to construct 'WebSocket': The URL 'ws://localhost:undefined/?token=vbu1h2iDFGun' is invalid. - at setupWebSocket (http://localhost:5000/@vite/client:536:19) - at fallback (http://localhost:5000/@vite/client:509:16) - at WebSocket. (http://localhost:5000/@vite/client:555:7) -[ 2650ms] [ERROR] Warning: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons: -1. You might have mismatching versions of React and the renderer (such as React DOM) -2. You might be breaking the Rules of Hooks -3. You might have more than one copy of React in the same app -See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem. @ http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-3TFVT2CW.js?v=81747235:135 -[ 2651ms] [ERROR] Warning: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons: -1. You might have mismatching versions of React and the renderer (such as React DOM) -2. You might be breaking the Rules of Hooks -3. You might have more than one copy of React in the same app -See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem. @ http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-3TFVT2CW.js?v=81747235:135 -[ 2664ms] TypeError: Cannot read properties of null (reading 'useEffect') - at Object.useEffect (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-3TFVT2CW.js?v=81747235:1078:29) - at QueryClientProvider (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/@tanstack_react-query.js?v=81747235:2808:9) - at renderWithHooks (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=81747235:11548:26) - at mountIndeterminateComponent (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=81747235:14926:21) - at beginWork (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=81747235:15914:22) - at HTMLUnknownElement.callCallback2 (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=81747235:3674:22) - at Object.invokeGuardedCallbackDev (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=81747235:3699:24) - at invokeGuardedCallback (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=81747235:3733:39) - at beginWork$1 (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=81747235:19765:15) - at performUnitOfWork (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=81747235:19198:20) -[ 2655ms] [ERROR] Warning: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons: -1. You might have mismatching versions of React and the renderer (such as React DOM) -2. You might be breaking the Rules of Hooks -3. You might have more than one copy of React in the same app -See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem. @ http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-3TFVT2CW.js?v=81747235:135 -[ 2655ms] [ERROR] Warning: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons: -1. You might have mismatching versions of React and the renderer (such as React DOM) -2. You might be breaking the Rules of Hooks -3. You might have more than one copy of React in the same app -See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem. @ http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-3TFVT2CW.js?v=81747235:135 -[ 2664ms] TypeError: Cannot read properties of null (reading 'useEffect') - at Object.useEffect (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-3TFVT2CW.js?v=81747235:1078:29) - at QueryClientProvider (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/@tanstack_react-query.js?v=81747235:2808:9) - at renderWithHooks (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=81747235:11548:26) - at mountIndeterminateComponent (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=81747235:14926:21) - at beginWork (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=81747235:15914:22) - at HTMLUnknownElement.callCallback2 (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=81747235:3674:22) - at Object.invokeGuardedCallbackDev (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=81747235:3699:24) - at invokeGuardedCallback (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=81747235:3733:39) - at beginWork$1 (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=81747235:19765:15) - at performUnitOfWork (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=81747235:19198:20) -[ 2657ms] [ERROR] The above error occurred in the component: - - at QueryClientProvider (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/@tanstack_react-query.js?v=81747235:2805:3) - at ErrorBoundary (http://localhost:5000/src/components/ErrorBoundary.tsx?v=wI5rEhypPWMiFIHcKLNxU:7:5) - at App - -React will try to recreate this component tree from scratch using the error boundary you provided, ErrorBoundary. @ http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=81747235:14031 -[ 2657ms] [ERROR] Game crashed: TypeError: Cannot read properties of null (reading 'useEffect') - at Object.useEffect (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-3TFVT2CW.js?v=81747235:1078:29) - at QueryClientProvider (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/@tanstack_react-query.js?v=81747235:2808:9) - at renderWithHooks (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=81747235:11548:26) - at mountIndeterminateComponent (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=81747235:14926:21) - at beginWork (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=81747235:15914:22) - at beginWork$1 (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=81747235:19753:22) - at performUnitOfWork (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=81747235:19198:20) - at workLoopSync (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=81747235:19137:13) - at renderRootSync (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=81747235:19116:15) - at recoverFromConcurrentError (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=81747235:18736:28) {componentStack: - at QueryClientProvider (http://localhost:5000…ndary.tsx?v=wI5rEhypPWMiFIHcKLNxU:7:5) - at App} @ http://localhost:5000/src/components/ErrorBoundary.tsx?v=wI5rEhypPWMiFIHcKLNxU:13 -[ 2678ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 diff --git a/.playwright-mcp/console-2026-03-16T16-18-38-860Z.log b/.playwright-mcp/console-2026-03-16T16-18-38-860Z.log deleted file mode 100644 index 09c0611..0000000 --- a/.playwright-mcp/console-2026-03-16T16-18-38-860Z.log +++ /dev/null @@ -1,7 +0,0 @@ -[ 204ms] [ERROR] WebSocket connection to 'ws://localhost:5000/?token=TLtGS6gmtqlS' failed: Error during WebSocket handshake: Unexpected response code: 400 @ http://localhost:5000/@vite/client:535 -[ 205ms] SyntaxError: Failed to construct 'WebSocket': The URL 'ws://localhost:undefined/?token=TLtGS6gmtqlS' is invalid. - at setupWebSocket (http://localhost:5000/@vite/client:536:19) - at fallback (http://localhost:5000/@vite/client:509:16) - at WebSocket. (http://localhost:5000/@vite/client:555:7) -[ 554ms] [ERROR] Failed to load resource: the server responded with a status of 504 (Outdated Optimize Dep) @ http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/lucide-react.js?v=c65628ff:0 -[ 559ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 diff --git a/.playwright-mcp/console-2026-03-16T16-19-41-530Z.log b/.playwright-mcp/console-2026-03-16T16-19-41-530Z.log deleted file mode 100644 index d2208ab..0000000 --- a/.playwright-mcp/console-2026-03-16T16-19-41-530Z.log +++ /dev/null @@ -1,8 +0,0 @@ -[ 108ms] [ERROR] WebSocket connection to 'ws://localhost:5000/?token=iib6WFvyIos_' failed: Error during WebSocket handshake: Unexpected response code: 400 @ http://localhost:5000/@vite/client:535 -[ 109ms] SyntaxError: Failed to construct 'WebSocket': The URL 'ws://localhost:undefined/?token=iib6WFvyIos_' is invalid. - at setupWebSocket (http://localhost:5000/@vite/client:536:19) - at fallback (http://localhost:5000/@vite/client:509:16) - at WebSocket. (http://localhost:5000/@vite/client:555:7) -[ 156ms] [ERROR] Failed to load resource: the server responded with a status of 504 (Outdated Optimize Dep) @ http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/react.js?v=51e68e9a:0 -[ 156ms] [ERROR] Failed to load resource: the server responded with a status of 504 (Outdated Optimize Dep) @ http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/@radix-ui_react-tooltip.js?v=fcb29685:0 -[ 161ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 diff --git a/.playwright-mcp/console-2026-03-16T16-20-09-341Z.log b/.playwright-mcp/console-2026-03-16T16-20-09-341Z.log deleted file mode 100644 index 945dd3d..0000000 --- a/.playwright-mcp/console-2026-03-16T16-20-09-341Z.log +++ /dev/null @@ -1,3 +0,0 @@ -[ 13ms] [ERROR] Failed to load module script: Expected a JavaScript-or-Wasm module script but the server responded with a MIME type of "text/html". Strict MIME type checking is enforced for module scripts per HTML spec. @ http://localhost:5000/HunterPath/assets/index-BEE1FI9S.js:0 -[ 160ms] [ERROR] Failed to load resource: the server responded with a status of 500 (Internal Server Error) @ http://localhost:5000/HunterPath/manifest.json:0 -[ 160ms] [ERROR] Manifest fetch from http://localhost:5000/HunterPath/manifest.json failed, code 500 @ http://localhost:5000/:0 diff --git a/.playwright-mcp/console-2026-03-16T16-20-35-847Z.log b/.playwright-mcp/console-2026-03-16T16-20-35-847Z.log deleted file mode 100644 index 5269389..0000000 --- a/.playwright-mcp/console-2026-03-16T16-20-35-847Z.log +++ /dev/null @@ -1,68 +0,0 @@ -[ 24ms] [ERROR] WebSocket connection to 'ws://localhost:5000/?token=TLtGS6gmtqlS' failed: Error during WebSocket handshake: Unexpected response code: 400 @ http://localhost:5000/@vite/client:535 -[ 60ms] SyntaxError: Failed to construct 'WebSocket': The URL 'ws://localhost:undefined/?token=TLtGS6gmtqlS' is invalid. - at setupWebSocket (http://localhost:5000/@vite/client:536:19) - at fallback (http://localhost:5000/@vite/client:509:16) - at WebSocket. (http://localhost:5000/@vite/client:555:7) -[ 380ms] [ERROR] Warning: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons: -1. You might have mismatching versions of React and the renderer (such as React DOM) -2. You might be breaking the Rules of Hooks -3. You might have more than one copy of React in the same app -See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem. @ http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-3TFVT2CW.js?v=81747235:135 -[ 381ms] [ERROR] Warning: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons: -1. You might have mismatching versions of React and the renderer (such as React DOM) -2. You might be breaking the Rules of Hooks -3. You might have more than one copy of React in the same app -See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem. @ http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-3TFVT2CW.js?v=81747235:135 -[ 386ms] TypeError: Cannot read properties of null (reading 'useEffect') - at Object.useEffect (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-3TFVT2CW.js?v=81747235:1078:29) - at QueryClientProvider (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/@tanstack_react-query.js?v=81747235:2808:9) - at renderWithHooks (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=81747235:11548:26) - at mountIndeterminateComponent (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=81747235:14926:21) - at beginWork (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=81747235:15914:22) - at HTMLUnknownElement.callCallback2 (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=81747235:3674:22) - at Object.invokeGuardedCallbackDev (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=81747235:3699:24) - at invokeGuardedCallback (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=81747235:3733:39) - at beginWork$1 (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=81747235:19765:15) - at performUnitOfWork (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=81747235:19198:20) -[ 383ms] [ERROR] Warning: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons: -1. You might have mismatching versions of React and the renderer (such as React DOM) -2. You might be breaking the Rules of Hooks -3. You might have more than one copy of React in the same app -See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem. @ http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-3TFVT2CW.js?v=81747235:135 -[ 383ms] [ERROR] Warning: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons: -1. You might have mismatching versions of React and the renderer (such as React DOM) -2. You might be breaking the Rules of Hooks -3. You might have more than one copy of React in the same app -See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem. @ http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-3TFVT2CW.js?v=81747235:135 -[ 387ms] TypeError: Cannot read properties of null (reading 'useEffect') - at Object.useEffect (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-3TFVT2CW.js?v=81747235:1078:29) - at QueryClientProvider (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/@tanstack_react-query.js?v=81747235:2808:9) - at renderWithHooks (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=81747235:11548:26) - at mountIndeterminateComponent (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=81747235:14926:21) - at beginWork (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=81747235:15914:22) - at HTMLUnknownElement.callCallback2 (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=81747235:3674:22) - at Object.invokeGuardedCallbackDev (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=81747235:3699:24) - at invokeGuardedCallback (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=81747235:3733:39) - at beginWork$1 (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=81747235:19765:15) - at performUnitOfWork (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=81747235:19198:20) -[ 384ms] [ERROR] The above error occurred in the component: - - at QueryClientProvider (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/@tanstack_react-query.js?v=81747235:2805:3) - at ErrorBoundary (http://localhost:5000/src/components/ErrorBoundary.tsx:7:5) - at App - -React will try to recreate this component tree from scratch using the error boundary you provided, ErrorBoundary. @ http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=81747235:14031 -[ 384ms] [ERROR] Game crashed: TypeError: Cannot read properties of null (reading 'useEffect') - at Object.useEffect (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-3TFVT2CW.js?v=81747235:1078:29) - at QueryClientProvider (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/@tanstack_react-query.js?v=81747235:2808:9) - at renderWithHooks (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=81747235:11548:26) - at mountIndeterminateComponent (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=81747235:14926:21) - at beginWork (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=81747235:15914:22) - at beginWork$1 (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=81747235:19753:22) - at performUnitOfWork (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=81747235:19198:20) - at workLoopSync (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=81747235:19137:13) - at renderRootSync (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=81747235:19116:15) - at recoverFromConcurrentError (http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-WERSD76P.js?v=81747235:18736:28) {componentStack: - at QueryClientProvider (http://localhost:5000…/src/components/ErrorBoundary.tsx:7:5) - at App} @ http://localhost:5000/src/components/ErrorBoundary.tsx:13 -[ 428ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 diff --git a/.playwright-mcp/console-2026-03-16T16-21-30-064Z.log b/.playwright-mcp/console-2026-03-16T16-21-30-064Z.log deleted file mode 100644 index cc89605..0000000 --- a/.playwright-mcp/console-2026-03-16T16-21-30-064Z.log +++ /dev/null @@ -1,3 +0,0 @@ -[ 25ms] [ERROR] Failed to load module script: Expected a JavaScript-or-Wasm module script but the server responded with a MIME type of "text/html". Strict MIME type checking is enforced for module scripts per HTML spec. @ http://localhost:5000/src/lib/queryClient.ts:0 -[ 30ms] [ERROR] Failed to load module script: Expected a JavaScript-or-Wasm module script but the server responded with a MIME type of "text/html". Strict MIME type checking is enforced for module scripts per HTML spec. @ http://localhost:5000/src/components/PWAInstallPrompt.tsx:0 -[ 216ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 diff --git a/.playwright-mcp/console-2026-03-16T16-23-11-335Z.log b/.playwright-mcp/console-2026-03-16T16-23-11-335Z.log deleted file mode 100644 index c6de47e..0000000 --- a/.playwright-mcp/console-2026-03-16T16-23-11-335Z.log +++ /dev/null @@ -1,7 +0,0 @@ -[ 167ms] [ERROR] Failed to load resource: the server responded with a status of 504 (Outdated Optimize Dep) @ http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/react-dom_client.js?v=1972285c:0 -[ 416ms] [ERROR] WebSocket connection to 'ws://localhost:5000/?token=fzkfsZJGY3Gu' failed: Error during WebSocket handshake: Unexpected response code: 400 @ http://localhost:5000/@vite/client:535 -[ 420ms] SyntaxError: Failed to construct 'WebSocket': The URL 'ws://localhost:undefined/?token=fzkfsZJGY3Gu' is invalid. - at setupWebSocket (http://localhost:5000/@vite/client:536:19) - at fallback (http://localhost:5000/@vite/client:509:16) - at WebSocket. (http://localhost:5000/@vite/client:555:7) -[ 791ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 diff --git a/.playwright-mcp/console-2026-03-16T16-24-12-943Z.log b/.playwright-mcp/console-2026-03-16T16-24-12-943Z.log deleted file mode 100644 index b121371..0000000 --- a/.playwright-mcp/console-2026-03-16T16-24-12-943Z.log +++ /dev/null @@ -1,8 +0,0 @@ -[ 24ms] [ERROR] Failed to load module script: Expected a JavaScript-or-Wasm module script but the server responded with a MIME type of "text/html". Strict MIME type checking is enforced for module scripts per HTML spec. @ http://localhost:5000/src/App.tsx?v=TRhvMRR2iboygoNT0Zp6H:0 -[ 26ms] [ERROR] Failed to load module script: Expected a JavaScript-or-Wasm module script but the server responded with a MIME type of "text/html". Strict MIME type checking is enforced for module scripts per HTML spec. @ http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-4MBMRILA.js?v=af667bd8:0 -[ 29ms] [ERROR] WebSocket connection to 'ws://localhost:5000/?token=7t_hzXgXbd75' failed: Error during WebSocket handshake: Unexpected response code: 400 @ http://localhost:5000/@vite/client:535 -[ 47ms] SyntaxError: Failed to construct 'WebSocket': The URL 'ws://localhost:undefined/?token=7t_hzXgXbd75' is invalid. - at setupWebSocket (http://localhost:5000/@vite/client:536:19) - at fallback (http://localhost:5000/@vite/client:509:16) - at WebSocket. (http://localhost:5000/@vite/client:555:7) -[ 35ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 diff --git a/.playwright-mcp/console-2026-03-16T16-25-31-725Z.log b/.playwright-mcp/console-2026-03-16T16-25-31-725Z.log deleted file mode 100644 index 9406a6f..0000000 --- a/.playwright-mcp/console-2026-03-16T16-25-31-725Z.log +++ /dev/null @@ -1,7 +0,0 @@ -[ 181ms] [ERROR] WebSocket connection to 'ws://localhost:5000/?token=wQuBwDeW8eue' failed: Error during WebSocket handshake: Unexpected response code: 400 @ http://localhost:5000/@vite/client:535 -[ 182ms] SyntaxError: Failed to construct 'WebSocket': The URL 'ws://localhost:undefined/?token=wQuBwDeW8eue' is invalid. - at setupWebSocket (http://localhost:5000/@vite/client:536:19) - at fallback (http://localhost:5000/@vite/client:509:16) - at WebSocket. (http://localhost:5000/@vite/client:555:7) -[ 295ms] [ERROR] Failed to load resource: the server responded with a status of 504 (Outdated Optimize Dep) @ http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/@tanstack_react-query.js?v=9f874701:0 -[ 305ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 diff --git a/.playwright-mcp/console-2026-03-16T16-25-57-076Z.log b/.playwright-mcp/console-2026-03-16T16-25-57-076Z.log deleted file mode 100644 index dbcf1ef..0000000 --- a/.playwright-mcp/console-2026-03-16T16-25-57-076Z.log +++ /dev/null @@ -1,11 +0,0 @@ -[ 23ms] [ERROR] WebSocket connection to 'ws://localhost:5000/?token=wQuBwDeW8eue' failed: Error during WebSocket handshake: Unexpected response code: 400 @ http://localhost:5000/@vite/client:535 -[ 41ms] SyntaxError: Failed to construct 'WebSocket': The URL 'ws://localhost:undefined/?token=wQuBwDeW8eue' is invalid. - at setupWebSocket (http://localhost:5000/@vite/client:536:19) - at fallback (http://localhost:5000/@vite/client:509:16) - at WebSocket. (http://localhost:5000/@vite/client:555:7) -[ 46ms] [ERROR] Failed to load resource: the server responded with a status of 504 (Outdated Optimize Dep) @ http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-35HU7BGO.js?v=9e7792eb:0 -[ 47ms] [ERROR] Failed to load resource: the server responded with a status of 504 (Outdated Optimize Dep) @ http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-RD5JEI3L.js?v=9e7792eb:0 -[ 48ms] [ERROR] Failed to load resource: the server responded with a status of 504 (Outdated Optimize Dep) @ http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-FRSLF2YA.js?v=9e7792eb:0 -[ 49ms] [ERROR] Failed to load resource: the server responded with a status of 504 (Outdated Optimize Dep) @ http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-6AYMNNR7.js?v=9e7792eb:0 -[ 53ms] [ERROR] Failed to load resource: the server responded with a status of 504 (Outdated Optimize Dep) @ http://localhost:5000/@fs/home/jesse/Projects/HunterPath/node_modules/.vite/deps/chunk-ZOBI3TMJ.js?v=9e7792eb:0 -[ 62ms] [WARNING] Error while trying to use the following icon from the Manifest: http://localhost:5000/HunterPath/icon-192x192.png (Download error or resource isn't a valid image) @ http://localhost:5000/:0 diff --git a/.playwright-mcp/console-2026-03-16T16-32-19-789Z.log b/.playwright-mcp/console-2026-03-16T16-32-19-789Z.log deleted file mode 100644 index 09daa6e..0000000 --- a/.playwright-mcp/console-2026-03-16T16-32-19-789Z.log +++ /dev/null @@ -1,3 +0,0 @@ -[ 227ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ https://jesserweigel.github.io/HunterPath/assets/index-L69KfJBq.js:159 -[ 228ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ https://jesserweigel.github.io/HunterPath/assets/index-L69KfJBq.js:159 -[ 2436919ms] [WARNING] The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://developer.chrome.com/blog/autoplay/#web_audio @ https://jesserweigel.github.io/HunterPath/assets/index-BEE1FI9S.js:149 diff --git a/.playwright-mcp/page-2026-02-23T21-47-18-670Z.png b/.playwright-mcp/page-2026-02-23T21-47-18-670Z.png deleted file mode 100644 index c7e4afb..0000000 Binary files a/.playwright-mcp/page-2026-02-23T21-47-18-670Z.png and /dev/null differ diff --git a/.playwright-mcp/page-2026-02-23T21-47-29-006Z.png b/.playwright-mcp/page-2026-02-23T21-47-29-006Z.png deleted file mode 100644 index e209763..0000000 Binary files a/.playwright-mcp/page-2026-02-23T21-47-29-006Z.png and /dev/null differ diff --git a/auto-dungeon-story.png b/auto-dungeon-story.png deleted file mode 100644 index 94eacf4..0000000 Binary files a/auto-dungeon-story.png and /dev/null differ diff --git a/boss-intro-e-rank.png b/boss-intro-e-rank.png deleted file mode 100644 index bc768eb..0000000 Binary files a/boss-intro-e-rank.png and /dev/null differ diff --git a/boss-intro-test.png b/boss-intro-test.png deleted file mode 100644 index c1fbe79..0000000 Binary files a/boss-intro-test.png and /dev/null differ diff --git a/boss-svg-direct.png b/boss-svg-direct.png deleted file mode 100644 index a119f9b..0000000 Binary files a/boss-svg-direct.png and /dev/null differ diff --git a/check-broken-icons.png b/check-broken-icons.png deleted file mode 100644 index e73753f..0000000 Binary files a/check-broken-icons.png and /dev/null differ diff --git a/check-inventory-icons.png b/check-inventory-icons.png deleted file mode 100644 index f0f4bae..0000000 Binary files a/check-inventory-icons.png and /dev/null differ diff --git a/check-log-icons.png b/check-log-icons.png deleted file mode 100644 index 490e29f..0000000 Binary files a/check-log-icons.png and /dev/null differ diff --git a/check-manage-icons.png b/check-manage-icons.png deleted file mode 100644 index e2124c3..0000000 Binary files a/check-manage-icons.png and /dev/null differ diff --git a/check-spirits-icons.png b/check-spirits-icons.png deleted file mode 100644 index 304022a..0000000 Binary files a/check-spirits-icons.png and /dev/null differ diff --git a/client/src/components/game/HuntersPath.tsx b/client/src/components/game/HuntersPath.tsx index cfefd46..4b80e02 100644 --- a/client/src/components/game/HuntersPath.tsx +++ b/client/src/components/game/HuntersPath.tsx @@ -1301,44 +1301,27 @@ export default function HuntersPath() { {/* Level-Up Celebration Modal */} {levelUpState.isActive && ( -
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
- +
+
+
+
-

+

LEVEL UP!

-
+
Level {levelUpState.newLevel}
-
+
+{levelUpState.statPointsGained} Stat Points Available!
{levelUpState.showStatAllocation && ( diff --git a/combat-result-test.png b/combat-result-test.png deleted file mode 100644 index bb787a4..0000000 Binary files a/combat-result-test.png and /dev/null differ diff --git a/combat-zone.png b/combat-zone.png deleted file mode 100644 index 80f769b..0000000 Binary files a/combat-zone.png and /dev/null differ diff --git a/coverage/base.css b/coverage/base.css deleted file mode 100644 index f418035..0000000 --- a/coverage/base.css +++ /dev/null @@ -1,224 +0,0 @@ -body, html { - margin:0; padding: 0; - height: 100%; -} -body { - font-family: Helvetica Neue, Helvetica, Arial; - font-size: 14px; - color:#333; -} -.small { font-size: 12px; } -*, *:after, *:before { - -webkit-box-sizing:border-box; - -moz-box-sizing:border-box; - box-sizing:border-box; - } -h1 { font-size: 20px; margin: 0;} -h2 { font-size: 14px; } -pre { - font: 12px/1.4 Consolas, "Liberation Mono", Menlo, Courier, monospace; - margin: 0; - padding: 0; - -moz-tab-size: 2; - -o-tab-size: 2; - tab-size: 2; -} -a { color:#0074D9; text-decoration:none; } -a:hover { text-decoration:underline; } -.strong { font-weight: bold; } -.space-top1 { padding: 10px 0 0 0; } -.pad2y { padding: 20px 0; } -.pad1y { padding: 10px 0; } -.pad2x { padding: 0 20px; } -.pad2 { padding: 20px; } -.pad1 { padding: 10px; } -.space-left2 { padding-left:55px; } -.space-right2 { padding-right:20px; } -.center { text-align:center; } -.clearfix { display:block; } -.clearfix:after { - content:''; - display:block; - height:0; - clear:both; - visibility:hidden; - } -.fl { float: left; } -@media only screen and (max-width:640px) { - .col3 { width:100%; max-width:100%; } - .hide-mobile { display:none!important; } -} - -.quiet { - color: #7f7f7f; - color: rgba(0,0,0,0.5); -} -.quiet a { opacity: 0.7; } - -.fraction { - font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; - font-size: 10px; - color: #555; - background: #E8E8E8; - padding: 4px 5px; - border-radius: 3px; - vertical-align: middle; -} - -div.path a:link, div.path a:visited { color: #333; } -table.coverage { - border-collapse: collapse; - margin: 10px 0 0 0; - padding: 0; -} - -table.coverage td { - margin: 0; - padding: 0; - vertical-align: top; -} -table.coverage td.line-count { - text-align: right; - padding: 0 5px 0 20px; -} -table.coverage td.line-coverage { - text-align: right; - padding-right: 10px; - min-width:20px; -} - -table.coverage td span.cline-any { - display: inline-block; - padding: 0 5px; - width: 100%; -} -.missing-if-branch { - display: inline-block; - margin-right: 5px; - border-radius: 3px; - position: relative; - padding: 0 4px; - background: #333; - color: yellow; -} - -.skip-if-branch { - display: none; - margin-right: 10px; - position: relative; - padding: 0 4px; - background: #ccc; - color: white; -} -.missing-if-branch .typ, .skip-if-branch .typ { - color: inherit !important; -} -.coverage-summary { - border-collapse: collapse; - width: 100%; -} -.coverage-summary tr { border-bottom: 1px solid #bbb; } -.keyline-all { border: 1px solid #ddd; } -.coverage-summary td, .coverage-summary th { padding: 10px; } -.coverage-summary tbody { border: 1px solid #bbb; } -.coverage-summary td { border-right: 1px solid #bbb; } -.coverage-summary td:last-child { border-right: none; } -.coverage-summary th { - text-align: left; - font-weight: normal; - white-space: nowrap; -} -.coverage-summary th.file { border-right: none !important; } -.coverage-summary th.pct { } -.coverage-summary th.pic, -.coverage-summary th.abs, -.coverage-summary td.pct, -.coverage-summary td.abs { text-align: right; } -.coverage-summary td.file { white-space: nowrap; } -.coverage-summary td.pic { min-width: 120px !important; } -.coverage-summary tfoot td { } - -.coverage-summary .sorter { - height: 10px; - width: 7px; - display: inline-block; - margin-left: 0.5em; - background: url(sort-arrow-sprite.png) no-repeat scroll 0 0 transparent; -} -.coverage-summary .sorted .sorter { - background-position: 0 -20px; -} -.coverage-summary .sorted-desc .sorter { - background-position: 0 -10px; -} -.status-line { height: 10px; } -/* yellow */ -.cbranch-no { background: yellow !important; color: #111; } -/* dark red */ -.red.solid, .status-line.low, .low .cover-fill { background:#C21F39 } -.low .chart { border:1px solid #C21F39 } -.highlighted, -.highlighted .cstat-no, .highlighted .fstat-no, .highlighted .cbranch-no{ - background: #C21F39 !important; -} -/* medium red */ -.cstat-no, .fstat-no, .cbranch-no, .cbranch-no { background:#F6C6CE } -/* light red */ -.low, .cline-no { background:#FCE1E5 } -/* light green */ -.high, .cline-yes { background:rgb(230,245,208) } -/* medium green */ -.cstat-yes { background:rgb(161,215,106) } -/* dark green */ -.status-line.high, .high .cover-fill { background:rgb(77,146,33) } -.high .chart { border:1px solid rgb(77,146,33) } -/* dark yellow (gold) */ -.status-line.medium, .medium .cover-fill { background: #f9cd0b; } -.medium .chart { border:1px solid #f9cd0b; } -/* light yellow */ -.medium { background: #fff4c2; } - -.cstat-skip { background: #ddd; color: #111; } -.fstat-skip { background: #ddd; color: #111 !important; } -.cbranch-skip { background: #ddd !important; color: #111; } - -span.cline-neutral { background: #eaeaea; } - -.coverage-summary td.empty { - opacity: .5; - padding-top: 4px; - padding-bottom: 4px; - line-height: 1; - color: #888; -} - -.cover-fill, .cover-empty { - display:inline-block; - height: 12px; -} -.chart { - line-height: 0; -} -.cover-empty { - background: white; -} -.cover-full { - border-right: none !important; -} -pre.prettyprint { - border: none !important; - padding: 0 !important; - margin: 0 !important; -} -.com { color: #999 !important; } -.ignore-none { color: #999; font-weight: normal; } - -.wrapper { - min-height: 100%; - height: auto !important; - height: 100%; - margin: 0 auto -48px; -} -.footer, .push { - height: 48px; -} diff --git a/coverage/block-navigation.js b/coverage/block-navigation.js deleted file mode 100644 index 530d1ed..0000000 --- a/coverage/block-navigation.js +++ /dev/null @@ -1,87 +0,0 @@ -/* eslint-disable */ -var jumpToCode = (function init() { - // Classes of code we would like to highlight in the file view - var missingCoverageClasses = ['.cbranch-no', '.cstat-no', '.fstat-no']; - - // Elements to highlight in the file listing view - var fileListingElements = ['td.pct.low']; - - // We don't want to select elements that are direct descendants of another match - var notSelector = ':not(' + missingCoverageClasses.join('):not(') + ') > '; // becomes `:not(a):not(b) > ` - - // Selector that finds elements on the page to which we can jump - var selector = - fileListingElements.join(', ') + - ', ' + - notSelector + - missingCoverageClasses.join(', ' + notSelector); // becomes `:not(a):not(b) > a, :not(a):not(b) > b` - - // The NodeList of matching elements - var missingCoverageElements = document.querySelectorAll(selector); - - var currentIndex; - - function toggleClass(index) { - missingCoverageElements - .item(currentIndex) - .classList.remove('highlighted'); - missingCoverageElements.item(index).classList.add('highlighted'); - } - - function makeCurrent(index) { - toggleClass(index); - currentIndex = index; - missingCoverageElements.item(index).scrollIntoView({ - behavior: 'smooth', - block: 'center', - inline: 'center' - }); - } - - function goToPrevious() { - var nextIndex = 0; - if (typeof currentIndex !== 'number' || currentIndex === 0) { - nextIndex = missingCoverageElements.length - 1; - } else if (missingCoverageElements.length > 1) { - nextIndex = currentIndex - 1; - } - - makeCurrent(nextIndex); - } - - function goToNext() { - var nextIndex = 0; - - if ( - typeof currentIndex === 'number' && - currentIndex < missingCoverageElements.length - 1 - ) { - nextIndex = currentIndex + 1; - } - - makeCurrent(nextIndex); - } - - return function jump(event) { - if ( - document.getElementById('fileSearch') === document.activeElement && - document.activeElement != null - ) { - // if we're currently focused on the search input, we don't want to navigate - return; - } - - switch (event.which) { - case 78: // n - case 74: // j - goToNext(); - break; - case 66: // b - case 75: // k - case 80: // p - goToPrevious(); - break; - } - }; -})(); -window.addEventListener('keydown', jumpToCode); diff --git a/coverage/client/src/components/ErrorBoundary.tsx.html b/coverage/client/src/components/ErrorBoundary.tsx.html deleted file mode 100644 index 710f940..0000000 --- a/coverage/client/src/components/ErrorBoundary.tsx.html +++ /dev/null @@ -1,280 +0,0 @@ - - - - - - Code coverage report for client/src/components/ErrorBoundary.tsx - - - - - - - - - -
-
-

All files / client/src/components ErrorBoundary.tsx

-
- -
- 85.71% - Statements - 6/7 -
- - -
- 75% - Branches - 3/4 -
- - -
- 75% - Functions - 3/4 -
- - -
- 85.71% - Lines - 6/7 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63 -64 -65 -66  -  -  -  -  -  -  -  -  -  -  -  -8x -  -  -6x -  -  -  -3x -  -  -  -13x -6x -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -7x -  -  - 
import { Component, ErrorInfo, ReactNode } from "react";
- 
-interface Props {
-  children: ReactNode;
-}
- 
-interface State {
-  hasError: boolean;
-  error: Error | null;
-}
- 
-export class ErrorBoundary extends Component<Props, State> {
-  state: State = { hasError: false, error: null };
- 
-  static getDerivedStateFromError(error: Error): State {
-    return { hasError: true, error };
-  }
- 
-  componentDidCatch(error: Error, info: ErrorInfo) {
-    console.error("Game crashed:", error, info);
-  }
- 
-  render() {
-    if (this.state.hasError) {
-      return (
-        <div
-          style={{
-            display: "flex",
-            flexDirection: "column",
-            alignItems: "center",
-            justifyContent: "center",
-            height: "100vh",
-            background: "#0f0f0f",
-            color: "#a78bfa",
-            fontFamily: "system-ui, sans-serif",
-            gap: "1rem",
-            padding: "2rem",
-            textAlign: "center",
-          }}
-        >
-          <div style={{ fontSize: "3rem" }}>⚠️</div>
-          <h1 style={{ fontSize: "1.5rem", margin: 0 }}>Something went wrong</h1>
-          <p style={{ color: "#6b7280", margin: 0 }}>
-            {this.state.error?.message ?? "Unknown error"}
-          </p>
-          <button
-            onClick={() => window.location.reload()}
-            style={{
-              padding: "0.75rem 2rem",
-              background: "#7c3aed",
-              color: "white",
-              border: "none",
-              borderRadius: "0.5rem",
-              cursor: "pointer",
-              fontSize: "1rem",
-            }}
-          >
-            Reload Game
-          </button>
-        </div>
-      );
-    }
-    return this.props.children;
-  }
-}
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/client/src/components/PWAInstallPrompt.tsx.html b/coverage/client/src/components/PWAInstallPrompt.tsx.html deleted file mode 100644 index 9171f91..0000000 --- a/coverage/client/src/components/PWAInstallPrompt.tsx.html +++ /dev/null @@ -1,343 +0,0 @@ - - - - - - Code coverage report for client/src/components/PWAInstallPrompt.tsx - - - - - - - - - -
-
-

All files / client/src/components PWAInstallPrompt.tsx

-
- -
- 0% - Statements - 0/24 -
- - -
- 0% - Branches - 0/8 -
- - -
- 0% - Functions - 0/7 -
- - -
- 0% - Lines - 0/24 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63 -64 -65 -66 -67 -68 -69 -70 -71 -72 -73 -74 -75 -76 -77 -78 -79 -80 -81 -82 -83 -84 -85 -86 -87  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 
import React, { useEffect, useState } from "react";
-import {
-  checkInstallable,
-  setInstallPrompt,
-  showInstallPrompt,
-} from "../sw-register";
- 
-export default function PWAInstallPrompt() {
-  const [showPrompt, setShowPrompt] = useState(false);
-  const [canInstall, setCanInstall] = useState(false);
- 
-  useEffect(() => {
-    const handleBeforeInstallPrompt = (e: Event) => {
-      e.preventDefault();
-      setInstallPrompt(e);
-      setCanInstall(true);
-      setShowPrompt(true);
-    };
- 
-    const checkInstallability = async () => {
-      const installable = await checkInstallable();
-      if (installable) {
-        window.addEventListener(
-          "beforeinstallprompt",
-          handleBeforeInstallPrompt
-        );
-      }
-    };
- 
-    checkInstallability();
- 
-    return () => {
-      window.removeEventListener(
-        "beforeinstallprompt",
-        handleBeforeInstallPrompt
-      );
-    };
-  }, []);
- 
-  const handleInstall = async () => {
-    const installed = await showInstallPrompt();
-    if (installed) {
-      setShowPrompt(false);
-    }
-  };
- 
-  const handleDismiss = () => {
-    setShowPrompt(false);
-  };
- 
-  if (!showPrompt || !canInstall) {
-    return null;
-  }
- 
-  return (
-    <div className="fixed top-4 right-4 z-50 bg-zinc-800 border border-purple-500 rounded-lg p-4 shadow-lg max-w-sm">
-      <div className="flex items-center justify-between mb-2">
-        <h3 className="text-white font-semibold">Install Hunter's Path</h3>
-        <button
-          onClick={handleDismiss}
-          className="text-zinc-400 hover:text-white"
-        >
-          ✕
-        </button>
-      </div>
-      <p className="text-zinc-300 text-sm mb-3">
-        Install this app on your device for quick and easy access when you're on
-        the go.
-      </p>
-      <div className="flex gap-2">
-        <button
-          onClick={handleInstall}
-          className="bg-purple-600 hover:bg-purple-700 text-white px-4 py-2 rounded text-sm font-medium transition-colors"
-        >
-          Install
-        </button>
-        <button
-          onClick={handleDismiss}
-          className="bg-zinc-700 hover:bg-zinc-600 text-white px-4 py-2 rounded text-sm font-medium transition-colors"
-        >
-          Not now
-        </button>
-      </div>
-    </div>
-  );
-}
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/client/src/components/game/HuntersPath.tsx.html b/coverage/client/src/components/game/HuntersPath.tsx.html deleted file mode 100644 index e44ee94..0000000 --- a/coverage/client/src/components/game/HuntersPath.tsx.html +++ /dev/null @@ -1,18961 +0,0 @@ - - - - - - Code coverage report for client/src/components/game/HuntersPath.tsx - - - - - - - - - -
-
-

All files / client/src/components/game HuntersPath.tsx

-
- -
- 0% - Statements - 0/1359 -
- - -
- 0% - Branches - 0/1056 -
- - -
- 0% - Functions - 0/361 -
- - -
- 0% - Lines - 0/1199 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63 -64 -65 -66 -67 -68 -69 -70 -71 -72 -73 -74 -75 -76 -77 -78 -79 -80 -81 -82 -83 -84 -85 -86 -87 -88 -89 -90 -91 -92 -93 -94 -95 -96 -97 -98 -99 -100 -101 -102 -103 -104 -105 -106 -107 -108 -109 -110 -111 -112 -113 -114 -115 -116 -117 -118 -119 -120 -121 -122 -123 -124 -125 -126 -127 -128 -129 -130 -131 -132 -133 -134 -135 -136 -137 -138 -139 -140 -141 -142 -143 -144 -145 -146 -147 -148 -149 -150 -151 -152 -153 -154 -155 -156 -157 -158 -159 -160 -161 -162 -163 -164 -165 -166 -167 -168 -169 -170 -171 -172 -173 -174 -175 -176 -177 -178 -179 -180 -181 -182 -183 -184 -185 -186 -187 -188 -189 -190 -191 -192 -193 -194 -195 -196 -197 -198 -199 -200 -201 -202 -203 -204 -205 -206 -207 -208 -209 -210 -211 -212 -213 -214 -215 -216 -217 -218 -219 -220 -221 -222 -223 -224 -225 -226 -227 -228 -229 -230 -231 -232 -233 -234 -235 -236 -237 -238 -239 -240 -241 -242 -243 -244 -245 -246 -247 -248 -249 -250 -251 -252 -253 -254 -255 -256 -257 -258 -259 -260 -261 -262 -263 -264 -265 -266 -267 -268 -269 -270 -271 -272 -273 -274 -275 -276 -277 -278 -279 -280 -281 -282 -283 -284 -285 -286 -287 -288 -289 -290 -291 -292 -293 -294 -295 -296 -297 -298 -299 -300 -301 -302 -303 -304 -305 -306 -307 -308 -309 -310 -311 -312 -313 -314 -315 -316 -317 -318 -319 -320 -321 -322 -323 -324 -325 -326 -327 -328 -329 -330 -331 -332 -333 -334 -335 -336 -337 -338 -339 -340 -341 -342 -343 -344 -345 -346 -347 -348 -349 -350 -351 -352 -353 -354 -355 -356 -357 -358 -359 -360 -361 -362 -363 -364 -365 -366 -367 -368 -369 -370 -371 -372 -373 -374 -375 -376 -377 -378 -379 -380 -381 -382 -383 -384 -385 -386 -387 -388 -389 -390 -391 -392 -393 -394 -395 -396 -397 -398 -399 -400 -401 -402 -403 -404 -405 -406 -407 -408 -409 -410 -411 -412 -413 -414 -415 -416 -417 -418 -419 -420 -421 -422 -423 -424 -425 -426 -427 -428 -429 -430 -431 -432 -433 -434 -435 -436 -437 -438 -439 -440 -441 -442 -443 -444 -445 -446 -447 -448 -449 -450 -451 -452 -453 -454 -455 -456 -457 -458 -459 -460 -461 -462 -463 -464 -465 -466 -467 -468 -469 -470 -471 -472 -473 -474 -475 -476 -477 -478 -479 -480 -481 -482 -483 -484 -485 -486 -487 -488 -489 -490 -491 -492 -493 -494 -495 -496 -497 -498 -499 -500 -501 -502 -503 -504 -505 -506 -507 -508 -509 -510 -511 -512 -513 -514 -515 -516 -517 -518 -519 -520 -521 -522 -523 -524 -525 -526 -527 -528 -529 -530 -531 -532 -533 -534 -535 -536 -537 -538 -539 -540 -541 -542 -543 -544 -545 -546 -547 -548 -549 -550 -551 -552 -553 -554 -555 -556 -557 -558 -559 -560 -561 -562 -563 -564 -565 -566 -567 -568 -569 -570 -571 -572 -573 -574 -575 -576 -577 -578 -579 -580 -581 -582 -583 -584 -585 -586 -587 -588 -589 -590 -591 -592 -593 -594 -595 -596 -597 -598 -599 -600 -601 -602 -603 -604 -605 -606 -607 -608 -609 -610 -611 -612 -613 -614 -615 -616 -617 -618 -619 -620 -621 -622 -623 -624 -625 -626 -627 -628 -629 -630 -631 -632 -633 -634 -635 -636 -637 -638 -639 -640 -641 -642 -643 -644 -645 -646 -647 -648 -649 -650 -651 -652 -653 -654 -655 -656 -657 -658 -659 -660 -661 -662 -663 -664 -665 -666 -667 -668 -669 -670 -671 -672 -673 -674 -675 -676 -677 -678 -679 -680 -681 -682 -683 -684 -685 -686 -687 -688 -689 -690 -691 -692 -693 -694 -695 -696 -697 -698 -699 -700 -701 -702 -703 -704 -705 -706 -707 -708 -709 -710 -711 -712 -713 -714 -715 -716 -717 -718 -719 -720 -721 -722 -723 -724 -725 -726 -727 -728 -729 -730 -731 -732 -733 -734 -735 -736 -737 -738 -739 -740 -741 -742 -743 -744 -745 -746 -747 -748 -749 -750 -751 -752 -753 -754 -755 -756 -757 -758 -759 -760 -761 -762 -763 -764 -765 -766 -767 -768 -769 -770 -771 -772 -773 -774 -775 -776 -777 -778 -779 -780 -781 -782 -783 -784 -785 -786 -787 -788 -789 -790 -791 -792 -793 -794 -795 -796 -797 -798 -799 -800 -801 -802 -803 -804 -805 -806 -807 -808 -809 -810 -811 -812 -813 -814 -815 -816 -817 -818 -819 -820 -821 -822 -823 -824 -825 -826 -827 -828 -829 -830 -831 -832 -833 -834 -835 -836 -837 -838 -839 -840 -841 -842 -843 -844 -845 -846 -847 -848 -849 -850 -851 -852 -853 -854 -855 -856 -857 -858 -859 -860 -861 -862 -863 -864 -865 -866 -867 -868 -869 -870 -871 -872 -873 -874 -875 -876 -877 -878 -879 -880 -881 -882 -883 -884 -885 -886 -887 -888 -889 -890 -891 -892 -893 -894 -895 -896 -897 -898 -899 -900 -901 -902 -903 -904 -905 -906 -907 -908 -909 -910 -911 -912 -913 -914 -915 -916 -917 -918 -919 -920 -921 -922 -923 -924 -925 -926 -927 -928 -929 -930 -931 -932 -933 -934 -935 -936 -937 -938 -939 -940 -941 -942 -943 -944 -945 -946 -947 -948 -949 -950 -951 -952 -953 -954 -955 -956 -957 -958 -959 -960 -961 -962 -963 -964 -965 -966 -967 -968 -969 -970 -971 -972 -973 -974 -975 -976 -977 -978 -979 -980 -981 -982 -983 -984 -985 -986 -987 -988 -989 -990 -991 -992 -993 -994 -995 -996 -997 -998 -999 -1000 -1001 -1002 -1003 -1004 -1005 -1006 -1007 -1008 -1009 -1010 -1011 -1012 -1013 -1014 -1015 -1016 -1017 -1018 -1019 -1020 -1021 -1022 -1023 -1024 -1025 -1026 -1027 -1028 -1029 -1030 -1031 -1032 -1033 -1034 -1035 -1036 -1037 -1038 -1039 -1040 -1041 -1042 -1043 -1044 -1045 -1046 -1047 -1048 -1049 -1050 -1051 -1052 -1053 -1054 -1055 -1056 -1057 -1058 -1059 -1060 -1061 -1062 -1063 -1064 -1065 -1066 -1067 -1068 -1069 -1070 -1071 -1072 -1073 -1074 -1075 -1076 -1077 -1078 -1079 -1080 -1081 -1082 -1083 -1084 -1085 -1086 -1087 -1088 -1089 -1090 -1091 -1092 -1093 -1094 -1095 -1096 -1097 -1098 -1099 -1100 -1101 -1102 -1103 -1104 -1105 -1106 -1107 -1108 -1109 -1110 -1111 -1112 -1113 -1114 -1115 -1116 -1117 -1118 -1119 -1120 -1121 -1122 -1123 -1124 -1125 -1126 -1127 -1128 -1129 -1130 -1131 -1132 -1133 -1134 -1135 -1136 -1137 -1138 -1139 -1140 -1141 -1142 -1143 -1144 -1145 -1146 -1147 -1148 -1149 -1150 -1151 -1152 -1153 -1154 -1155 -1156 -1157 -1158 -1159 -1160 -1161 -1162 -1163 -1164 -1165 -1166 -1167 -1168 -1169 -1170 -1171 -1172 -1173 -1174 -1175 -1176 -1177 -1178 -1179 -1180 -1181 -1182 -1183 -1184 -1185 -1186 -1187 -1188 -1189 -1190 -1191 -1192 -1193 -1194 -1195 -1196 -1197 -1198 -1199 -1200 -1201 -1202 -1203 -1204 -1205 -1206 -1207 -1208 -1209 -1210 -1211 -1212 -1213 -1214 -1215 -1216 -1217 -1218 -1219 -1220 -1221 -1222 -1223 -1224 -1225 -1226 -1227 -1228 -1229 -1230 -1231 -1232 -1233 -1234 -1235 -1236 -1237 -1238 -1239 -1240 -1241 -1242 -1243 -1244 -1245 -1246 -1247 -1248 -1249 -1250 -1251 -1252 -1253 -1254 -1255 -1256 -1257 -1258 -1259 -1260 -1261 -1262 -1263 -1264 -1265 -1266 -1267 -1268 -1269 -1270 -1271 -1272 -1273 -1274 -1275 -1276 -1277 -1278 -1279 -1280 -1281 -1282 -1283 -1284 -1285 -1286 -1287 -1288 -1289 -1290 -1291 -1292 -1293 -1294 -1295 -1296 -1297 -1298 -1299 -1300 -1301 -1302 -1303 -1304 -1305 -1306 -1307 -1308 -1309 -1310 -1311 -1312 -1313 -1314 -1315 -1316 -1317 -1318 -1319 -1320 -1321 -1322 -1323 -1324 -1325 -1326 -1327 -1328 -1329 -1330 -1331 -1332 -1333 -1334 -1335 -1336 -1337 -1338 -1339 -1340 -1341 -1342 -1343 -1344 -1345 -1346 -1347 -1348 -1349 -1350 -1351 -1352 -1353 -1354 -1355 -1356 -1357 -1358 -1359 -1360 -1361 -1362 -1363 -1364 -1365 -1366 -1367 -1368 -1369 -1370 -1371 -1372 -1373 -1374 -1375 -1376 -1377 -1378 -1379 -1380 -1381 -1382 -1383 -1384 -1385 -1386 -1387 -1388 -1389 -1390 -1391 -1392 -1393 -1394 -1395 -1396 -1397 -1398 -1399 -1400 -1401 -1402 -1403 -1404 -1405 -1406 -1407 -1408 -1409 -1410 -1411 -1412 -1413 -1414 -1415 -1416 -1417 -1418 -1419 -1420 -1421 -1422 -1423 -1424 -1425 -1426 -1427 -1428 -1429 -1430 -1431 -1432 -1433 -1434 -1435 -1436 -1437 -1438 -1439 -1440 -1441 -1442 -1443 -1444 -1445 -1446 -1447 -1448 -1449 -1450 -1451 -1452 -1453 -1454 -1455 -1456 -1457 -1458 -1459 -1460 -1461 -1462 -1463 -1464 -1465 -1466 -1467 -1468 -1469 -1470 -1471 -1472 -1473 -1474 -1475 -1476 -1477 -1478 -1479 -1480 -1481 -1482 -1483 -1484 -1485 -1486 -1487 -1488 -1489 -1490 -1491 -1492 -1493 -1494 -1495 -1496 -1497 -1498 -1499 -1500 -1501 -1502 -1503 -1504 -1505 -1506 -1507 -1508 -1509 -1510 -1511 -1512 -1513 -1514 -1515 -1516 -1517 -1518 -1519 -1520 -1521 -1522 -1523 -1524 -1525 -1526 -1527 -1528 -1529 -1530 -1531 -1532 -1533 -1534 -1535 -1536 -1537 -1538 -1539 -1540 -1541 -1542 -1543 -1544 -1545 -1546 -1547 -1548 -1549 -1550 -1551 -1552 -1553 -1554 -1555 -1556 -1557 -1558 -1559 -1560 -1561 -1562 -1563 -1564 -1565 -1566 -1567 -1568 -1569 -1570 -1571 -1572 -1573 -1574 -1575 -1576 -1577 -1578 -1579 -1580 -1581 -1582 -1583 -1584 -1585 -1586 -1587 -1588 -1589 -1590 -1591 -1592 -1593 -1594 -1595 -1596 -1597 -1598 -1599 -1600 -1601 -1602 -1603 -1604 -1605 -1606 -1607 -1608 -1609 -1610 -1611 -1612 -1613 -1614 -1615 -1616 -1617 -1618 -1619 -1620 -1621 -1622 -1623 -1624 -1625 -1626 -1627 -1628 -1629 -1630 -1631 -1632 -1633 -1634 -1635 -1636 -1637 -1638 -1639 -1640 -1641 -1642 -1643 -1644 -1645 -1646 -1647 -1648 -1649 -1650 -1651 -1652 -1653 -1654 -1655 -1656 -1657 -1658 -1659 -1660 -1661 -1662 -1663 -1664 -1665 -1666 -1667 -1668 -1669 -1670 -1671 -1672 -1673 -1674 -1675 -1676 -1677 -1678 -1679 -1680 -1681 -1682 -1683 -1684 -1685 -1686 -1687 -1688 -1689 -1690 -1691 -1692 -1693 -1694 -1695 -1696 -1697 -1698 -1699 -1700 -1701 -1702 -1703 -1704 -1705 -1706 -1707 -1708 -1709 -1710 -1711 -1712 -1713 -1714 -1715 -1716 -1717 -1718 -1719 -1720 -1721 -1722 -1723 -1724 -1725 -1726 -1727 -1728 -1729 -1730 -1731 -1732 -1733 -1734 -1735 -1736 -1737 -1738 -1739 -1740 -1741 -1742 -1743 -1744 -1745 -1746 -1747 -1748 -1749 -1750 -1751 -1752 -1753 -1754 -1755 -1756 -1757 -1758 -1759 -1760 -1761 -1762 -1763 -1764 -1765 -1766 -1767 -1768 -1769 -1770 -1771 -1772 -1773 -1774 -1775 -1776 -1777 -1778 -1779 -1780 -1781 -1782 -1783 -1784 -1785 -1786 -1787 -1788 -1789 -1790 -1791 -1792 -1793 -1794 -1795 -1796 -1797 -1798 -1799 -1800 -1801 -1802 -1803 -1804 -1805 -1806 -1807 -1808 -1809 -1810 -1811 -1812 -1813 -1814 -1815 -1816 -1817 -1818 -1819 -1820 -1821 -1822 -1823 -1824 -1825 -1826 -1827 -1828 -1829 -1830 -1831 -1832 -1833 -1834 -1835 -1836 -1837 -1838 -1839 -1840 -1841 -1842 -1843 -1844 -1845 -1846 -1847 -1848 -1849 -1850 -1851 -1852 -1853 -1854 -1855 -1856 -1857 -1858 -1859 -1860 -1861 -1862 -1863 -1864 -1865 -1866 -1867 -1868 -1869 -1870 -1871 -1872 -1873 -1874 -1875 -1876 -1877 -1878 -1879 -1880 -1881 -1882 -1883 -1884 -1885 -1886 -1887 -1888 -1889 -1890 -1891 -1892 -1893 -1894 -1895 -1896 -1897 -1898 -1899 -1900 -1901 -1902 -1903 -1904 -1905 -1906 -1907 -1908 -1909 -1910 -1911 -1912 -1913 -1914 -1915 -1916 -1917 -1918 -1919 -1920 -1921 -1922 -1923 -1924 -1925 -1926 -1927 -1928 -1929 -1930 -1931 -1932 -1933 -1934 -1935 -1936 -1937 -1938 -1939 -1940 -1941 -1942 -1943 -1944 -1945 -1946 -1947 -1948 -1949 -1950 -1951 -1952 -1953 -1954 -1955 -1956 -1957 -1958 -1959 -1960 -1961 -1962 -1963 -1964 -1965 -1966 -1967 -1968 -1969 -1970 -1971 -1972 -1973 -1974 -1975 -1976 -1977 -1978 -1979 -1980 -1981 -1982 -1983 -1984 -1985 -1986 -1987 -1988 -1989 -1990 -1991 -1992 -1993 -1994 -1995 -1996 -1997 -1998 -1999 -2000 -2001 -2002 -2003 -2004 -2005 -2006 -2007 -2008 -2009 -2010 -2011 -2012 -2013 -2014 -2015 -2016 -2017 -2018 -2019 -2020 -2021 -2022 -2023 -2024 -2025 -2026 -2027 -2028 -2029 -2030 -2031 -2032 -2033 -2034 -2035 -2036 -2037 -2038 -2039 -2040 -2041 -2042 -2043 -2044 -2045 -2046 -2047 -2048 -2049 -2050 -2051 -2052 -2053 -2054 -2055 -2056 -2057 -2058 -2059 -2060 -2061 -2062 -2063 -2064 -2065 -2066 -2067 -2068 -2069 -2070 -2071 -2072 -2073 -2074 -2075 -2076 -2077 -2078 -2079 -2080 -2081 -2082 -2083 -2084 -2085 -2086 -2087 -2088 -2089 -2090 -2091 -2092 -2093 -2094 -2095 -2096 -2097 -2098 -2099 -2100 -2101 -2102 -2103 -2104 -2105 -2106 -2107 -2108 -2109 -2110 -2111 -2112 -2113 -2114 -2115 -2116 -2117 -2118 -2119 -2120 -2121 -2122 -2123 -2124 -2125 -2126 -2127 -2128 -2129 -2130 -2131 -2132 -2133 -2134 -2135 -2136 -2137 -2138 -2139 -2140 -2141 -2142 -2143 -2144 -2145 -2146 -2147 -2148 -2149 -2150 -2151 -2152 -2153 -2154 -2155 -2156 -2157 -2158 -2159 -2160 -2161 -2162 -2163 -2164 -2165 -2166 -2167 -2168 -2169 -2170 -2171 -2172 -2173 -2174 -2175 -2176 -2177 -2178 -2179 -2180 -2181 -2182 -2183 -2184 -2185 -2186 -2187 -2188 -2189 -2190 -2191 -2192 -2193 -2194 -2195 -2196 -2197 -2198 -2199 -2200 -2201 -2202 -2203 -2204 -2205 -2206 -2207 -2208 -2209 -2210 -2211 -2212 -2213 -2214 -2215 -2216 -2217 -2218 -2219 -2220 -2221 -2222 -2223 -2224 -2225 -2226 -2227 -2228 -2229 -2230 -2231 -2232 -2233 -2234 -2235 -2236 -2237 -2238 -2239 -2240 -2241 -2242 -2243 -2244 -2245 -2246 -2247 -2248 -2249 -2250 -2251 -2252 -2253 -2254 -2255 -2256 -2257 -2258 -2259 -2260 -2261 -2262 -2263 -2264 -2265 -2266 -2267 -2268 -2269 -2270 -2271 -2272 -2273 -2274 -2275 -2276 -2277 -2278 -2279 -2280 -2281 -2282 -2283 -2284 -2285 -2286 -2287 -2288 -2289 -2290 -2291 -2292 -2293 -2294 -2295 -2296 -2297 -2298 -2299 -2300 -2301 -2302 -2303 -2304 -2305 -2306 -2307 -2308 -2309 -2310 -2311 -2312 -2313 -2314 -2315 -2316 -2317 -2318 -2319 -2320 -2321 -2322 -2323 -2324 -2325 -2326 -2327 -2328 -2329 -2330 -2331 -2332 -2333 -2334 -2335 -2336 -2337 -2338 -2339 -2340 -2341 -2342 -2343 -2344 -2345 -2346 -2347 -2348 -2349 -2350 -2351 -2352 -2353 -2354 -2355 -2356 -2357 -2358 -2359 -2360 -2361 -2362 -2363 -2364 -2365 -2366 -2367 -2368 -2369 -2370 -2371 -2372 -2373 -2374 -2375 -2376 -2377 -2378 -2379 -2380 -2381 -2382 -2383 -2384 -2385 -2386 -2387 -2388 -2389 -2390 -2391 -2392 -2393 -2394 -2395 -2396 -2397 -2398 -2399 -2400 -2401 -2402 -2403 -2404 -2405 -2406 -2407 -2408 -2409 -2410 -2411 -2412 -2413 -2414 -2415 -2416 -2417 -2418 -2419 -2420 -2421 -2422 -2423 -2424 -2425 -2426 -2427 -2428 -2429 -2430 -2431 -2432 -2433 -2434 -2435 -2436 -2437 -2438 -2439 -2440 -2441 -2442 -2443 -2444 -2445 -2446 -2447 -2448 -2449 -2450 -2451 -2452 -2453 -2454 -2455 -2456 -2457 -2458 -2459 -2460 -2461 -2462 -2463 -2464 -2465 -2466 -2467 -2468 -2469 -2470 -2471 -2472 -2473 -2474 -2475 -2476 -2477 -2478 -2479 -2480 -2481 -2482 -2483 -2484 -2485 -2486 -2487 -2488 -2489 -2490 -2491 -2492 -2493 -2494 -2495 -2496 -2497 -2498 -2499 -2500 -2501 -2502 -2503 -2504 -2505 -2506 -2507 -2508 -2509 -2510 -2511 -2512 -2513 -2514 -2515 -2516 -2517 -2518 -2519 -2520 -2521 -2522 -2523 -2524 -2525 -2526 -2527 -2528 -2529 -2530 -2531 -2532 -2533 -2534 -2535 -2536 -2537 -2538 -2539 -2540 -2541 -2542 -2543 -2544 -2545 -2546 -2547 -2548 -2549 -2550 -2551 -2552 -2553 -2554 -2555 -2556 -2557 -2558 -2559 -2560 -2561 -2562 -2563 -2564 -2565 -2566 -2567 -2568 -2569 -2570 -2571 -2572 -2573 -2574 -2575 -2576 -2577 -2578 -2579 -2580 -2581 -2582 -2583 -2584 -2585 -2586 -2587 -2588 -2589 -2590 -2591 -2592 -2593 -2594 -2595 -2596 -2597 -2598 -2599 -2600 -2601 -2602 -2603 -2604 -2605 -2606 -2607 -2608 -2609 -2610 -2611 -2612 -2613 -2614 -2615 -2616 -2617 -2618 -2619 -2620 -2621 -2622 -2623 -2624 -2625 -2626 -2627 -2628 -2629 -2630 -2631 -2632 -2633 -2634 -2635 -2636 -2637 -2638 -2639 -2640 -2641 -2642 -2643 -2644 -2645 -2646 -2647 -2648 -2649 -2650 -2651 -2652 -2653 -2654 -2655 -2656 -2657 -2658 -2659 -2660 -2661 -2662 -2663 -2664 -2665 -2666 -2667 -2668 -2669 -2670 -2671 -2672 -2673 -2674 -2675 -2676 -2677 -2678 -2679 -2680 -2681 -2682 -2683 -2684 -2685 -2686 -2687 -2688 -2689 -2690 -2691 -2692 -2693 -2694 -2695 -2696 -2697 -2698 -2699 -2700 -2701 -2702 -2703 -2704 -2705 -2706 -2707 -2708 -2709 -2710 -2711 -2712 -2713 -2714 -2715 -2716 -2717 -2718 -2719 -2720 -2721 -2722 -2723 -2724 -2725 -2726 -2727 -2728 -2729 -2730 -2731 -2732 -2733 -2734 -2735 -2736 -2737 -2738 -2739 -2740 -2741 -2742 -2743 -2744 -2745 -2746 -2747 -2748 -2749 -2750 -2751 -2752 -2753 -2754 -2755 -2756 -2757 -2758 -2759 -2760 -2761 -2762 -2763 -2764 -2765 -2766 -2767 -2768 -2769 -2770 -2771 -2772 -2773 -2774 -2775 -2776 -2777 -2778 -2779 -2780 -2781 -2782 -2783 -2784 -2785 -2786 -2787 -2788 -2789 -2790 -2791 -2792 -2793 -2794 -2795 -2796 -2797 -2798 -2799 -2800 -2801 -2802 -2803 -2804 -2805 -2806 -2807 -2808 -2809 -2810 -2811 -2812 -2813 -2814 -2815 -2816 -2817 -2818 -2819 -2820 -2821 -2822 -2823 -2824 -2825 -2826 -2827 -2828 -2829 -2830 -2831 -2832 -2833 -2834 -2835 -2836 -2837 -2838 -2839 -2840 -2841 -2842 -2843 -2844 -2845 -2846 -2847 -2848 -2849 -2850 -2851 -2852 -2853 -2854 -2855 -2856 -2857 -2858 -2859 -2860 -2861 -2862 -2863 -2864 -2865 -2866 -2867 -2868 -2869 -2870 -2871 -2872 -2873 -2874 -2875 -2876 -2877 -2878 -2879 -2880 -2881 -2882 -2883 -2884 -2885 -2886 -2887 -2888 -2889 -2890 -2891 -2892 -2893 -2894 -2895 -2896 -2897 -2898 -2899 -2900 -2901 -2902 -2903 -2904 -2905 -2906 -2907 -2908 -2909 -2910 -2911 -2912 -2913 -2914 -2915 -2916 -2917 -2918 -2919 -2920 -2921 -2922 -2923 -2924 -2925 -2926 -2927 -2928 -2929 -2930 -2931 -2932 -2933 -2934 -2935 -2936 -2937 -2938 -2939 -2940 -2941 -2942 -2943 -2944 -2945 -2946 -2947 -2948 -2949 -2950 -2951 -2952 -2953 -2954 -2955 -2956 -2957 -2958 -2959 -2960 -2961 -2962 -2963 -2964 -2965 -2966 -2967 -2968 -2969 -2970 -2971 -2972 -2973 -2974 -2975 -2976 -2977 -2978 -2979 -2980 -2981 -2982 -2983 -2984 -2985 -2986 -2987 -2988 -2989 -2990 -2991 -2992 -2993 -2994 -2995 -2996 -2997 -2998 -2999 -3000 -3001 -3002 -3003 -3004 -3005 -3006 -3007 -3008 -3009 -3010 -3011 -3012 -3013 -3014 -3015 -3016 -3017 -3018 -3019 -3020 -3021 -3022 -3023 -3024 -3025 -3026 -3027 -3028 -3029 -3030 -3031 -3032 -3033 -3034 -3035 -3036 -3037 -3038 -3039 -3040 -3041 -3042 -3043 -3044 -3045 -3046 -3047 -3048 -3049 -3050 -3051 -3052 -3053 -3054 -3055 -3056 -3057 -3058 -3059 -3060 -3061 -3062 -3063 -3064 -3065 -3066 -3067 -3068 -3069 -3070 -3071 -3072 -3073 -3074 -3075 -3076 -3077 -3078 -3079 -3080 -3081 -3082 -3083 -3084 -3085 -3086 -3087 -3088 -3089 -3090 -3091 -3092 -3093 -3094 -3095 -3096 -3097 -3098 -3099 -3100 -3101 -3102 -3103 -3104 -3105 -3106 -3107 -3108 -3109 -3110 -3111 -3112 -3113 -3114 -3115 -3116 -3117 -3118 -3119 -3120 -3121 -3122 -3123 -3124 -3125 -3126 -3127 -3128 -3129 -3130 -3131 -3132 -3133 -3134 -3135 -3136 -3137 -3138 -3139 -3140 -3141 -3142 -3143 -3144 -3145 -3146 -3147 -3148 -3149 -3150 -3151 -3152 -3153 -3154 -3155 -3156 -3157 -3158 -3159 -3160 -3161 -3162 -3163 -3164 -3165 -3166 -3167 -3168 -3169 -3170 -3171 -3172 -3173 -3174 -3175 -3176 -3177 -3178 -3179 -3180 -3181 -3182 -3183 -3184 -3185 -3186 -3187 -3188 -3189 -3190 -3191 -3192 -3193 -3194 -3195 -3196 -3197 -3198 -3199 -3200 -3201 -3202 -3203 -3204 -3205 -3206 -3207 -3208 -3209 -3210 -3211 -3212 -3213 -3214 -3215 -3216 -3217 -3218 -3219 -3220 -3221 -3222 -3223 -3224 -3225 -3226 -3227 -3228 -3229 -3230 -3231 -3232 -3233 -3234 -3235 -3236 -3237 -3238 -3239 -3240 -3241 -3242 -3243 -3244 -3245 -3246 -3247 -3248 -3249 -3250 -3251 -3252 -3253 -3254 -3255 -3256 -3257 -3258 -3259 -3260 -3261 -3262 -3263 -3264 -3265 -3266 -3267 -3268 -3269 -3270 -3271 -3272 -3273 -3274 -3275 -3276 -3277 -3278 -3279 -3280 -3281 -3282 -3283 -3284 -3285 -3286 -3287 -3288 -3289 -3290 -3291 -3292 -3293 -3294 -3295 -3296 -3297 -3298 -3299 -3300 -3301 -3302 -3303 -3304 -3305 -3306 -3307 -3308 -3309 -3310 -3311 -3312 -3313 -3314 -3315 -3316 -3317 -3318 -3319 -3320 -3321 -3322 -3323 -3324 -3325 -3326 -3327 -3328 -3329 -3330 -3331 -3332 -3333 -3334 -3335 -3336 -3337 -3338 -3339 -3340 -3341 -3342 -3343 -3344 -3345 -3346 -3347 -3348 -3349 -3350 -3351 -3352 -3353 -3354 -3355 -3356 -3357 -3358 -3359 -3360 -3361 -3362 -3363 -3364 -3365 -3366 -3367 -3368 -3369 -3370 -3371 -3372 -3373 -3374 -3375 -3376 -3377 -3378 -3379 -3380 -3381 -3382 -3383 -3384 -3385 -3386 -3387 -3388 -3389 -3390 -3391 -3392 -3393 -3394 -3395 -3396 -3397 -3398 -3399 -3400 -3401 -3402 -3403 -3404 -3405 -3406 -3407 -3408 -3409 -3410 -3411 -3412 -3413 -3414 -3415 -3416 -3417 -3418 -3419 -3420 -3421 -3422 -3423 -3424 -3425 -3426 -3427 -3428 -3429 -3430 -3431 -3432 -3433 -3434 -3435 -3436 -3437 -3438 -3439 -3440 -3441 -3442 -3443 -3444 -3445 -3446 -3447 -3448 -3449 -3450 -3451 -3452 -3453 -3454 -3455 -3456 -3457 -3458 -3459 -3460 -3461 -3462 -3463 -3464 -3465 -3466 -3467 -3468 -3469 -3470 -3471 -3472 -3473 -3474 -3475 -3476 -3477 -3478 -3479 -3480 -3481 -3482 -3483 -3484 -3485 -3486 -3487 -3488 -3489 -3490 -3491 -3492 -3493 -3494 -3495 -3496 -3497 -3498 -3499 -3500 -3501 -3502 -3503 -3504 -3505 -3506 -3507 -3508 -3509 -3510 -3511 -3512 -3513 -3514 -3515 -3516 -3517 -3518 -3519 -3520 -3521 -3522 -3523 -3524 -3525 -3526 -3527 -3528 -3529 -3530 -3531 -3532 -3533 -3534 -3535 -3536 -3537 -3538 -3539 -3540 -3541 -3542 -3543 -3544 -3545 -3546 -3547 -3548 -3549 -3550 -3551 -3552 -3553 -3554 -3555 -3556 -3557 -3558 -3559 -3560 -3561 -3562 -3563 -3564 -3565 -3566 -3567 -3568 -3569 -3570 -3571 -3572 -3573 -3574 -3575 -3576 -3577 -3578 -3579 -3580 -3581 -3582 -3583 -3584 -3585 -3586 -3587 -3588 -3589 -3590 -3591 -3592 -3593 -3594 -3595 -3596 -3597 -3598 -3599 -3600 -3601 -3602 -3603 -3604 -3605 -3606 -3607 -3608 -3609 -3610 -3611 -3612 -3613 -3614 -3615 -3616 -3617 -3618 -3619 -3620 -3621 -3622 -3623 -3624 -3625 -3626 -3627 -3628 -3629 -3630 -3631 -3632 -3633 -3634 -3635 -3636 -3637 -3638 -3639 -3640 -3641 -3642 -3643 -3644 -3645 -3646 -3647 -3648 -3649 -3650 -3651 -3652 -3653 -3654 -3655 -3656 -3657 -3658 -3659 -3660 -3661 -3662 -3663 -3664 -3665 -3666 -3667 -3668 -3669 -3670 -3671 -3672 -3673 -3674 -3675 -3676 -3677 -3678 -3679 -3680 -3681 -3682 -3683 -3684 -3685 -3686 -3687 -3688 -3689 -3690 -3691 -3692 -3693 -3694 -3695 -3696 -3697 -3698 -3699 -3700 -3701 -3702 -3703 -3704 -3705 -3706 -3707 -3708 -3709 -3710 -3711 -3712 -3713 -3714 -3715 -3716 -3717 -3718 -3719 -3720 -3721 -3722 -3723 -3724 -3725 -3726 -3727 -3728 -3729 -3730 -3731 -3732 -3733 -3734 -3735 -3736 -3737 -3738 -3739 -3740 -3741 -3742 -3743 -3744 -3745 -3746 -3747 -3748 -3749 -3750 -3751 -3752 -3753 -3754 -3755 -3756 -3757 -3758 -3759 -3760 -3761 -3762 -3763 -3764 -3765 -3766 -3767 -3768 -3769 -3770 -3771 -3772 -3773 -3774 -3775 -3776 -3777 -3778 -3779 -3780 -3781 -3782 -3783 -3784 -3785 -3786 -3787 -3788 -3789 -3790 -3791 -3792 -3793 -3794 -3795 -3796 -3797 -3798 -3799 -3800 -3801 -3802 -3803 -3804 -3805 -3806 -3807 -3808 -3809 -3810 -3811 -3812 -3813 -3814 -3815 -3816 -3817 -3818 -3819 -3820 -3821 -3822 -3823 -3824 -3825 -3826 -3827 -3828 -3829 -3830 -3831 -3832 -3833 -3834 -3835 -3836 -3837 -3838 -3839 -3840 -3841 -3842 -3843 -3844 -3845 -3846 -3847 -3848 -3849 -3850 -3851 -3852 -3853 -3854 -3855 -3856 -3857 -3858 -3859 -3860 -3861 -3862 -3863 -3864 -3865 -3866 -3867 -3868 -3869 -3870 -3871 -3872 -3873 -3874 -3875 -3876 -3877 -3878 -3879 -3880 -3881 -3882 -3883 -3884 -3885 -3886 -3887 -3888 -3889 -3890 -3891 -3892 -3893 -3894 -3895 -3896 -3897 -3898 -3899 -3900 -3901 -3902 -3903 -3904 -3905 -3906 -3907 -3908 -3909 -3910 -3911 -3912 -3913 -3914 -3915 -3916 -3917 -3918 -3919 -3920 -3921 -3922 -3923 -3924 -3925 -3926 -3927 -3928 -3929 -3930 -3931 -3932 -3933 -3934 -3935 -3936 -3937 -3938 -3939 -3940 -3941 -3942 -3943 -3944 -3945 -3946 -3947 -3948 -3949 -3950 -3951 -3952 -3953 -3954 -3955 -3956 -3957 -3958 -3959 -3960 -3961 -3962 -3963 -3964 -3965 -3966 -3967 -3968 -3969 -3970 -3971 -3972 -3973 -3974 -3975 -3976 -3977 -3978 -3979 -3980 -3981 -3982 -3983 -3984 -3985 -3986 -3987 -3988 -3989 -3990 -3991 -3992 -3993 -3994 -3995 -3996 -3997 -3998 -3999 -4000 -4001 -4002 -4003 -4004 -4005 -4006 -4007 -4008 -4009 -4010 -4011 -4012 -4013 -4014 -4015 -4016 -4017 -4018 -4019 -4020 -4021 -4022 -4023 -4024 -4025 -4026 -4027 -4028 -4029 -4030 -4031 -4032 -4033 -4034 -4035 -4036 -4037 -4038 -4039 -4040 -4041 -4042 -4043 -4044 -4045 -4046 -4047 -4048 -4049 -4050 -4051 -4052 -4053 -4054 -4055 -4056 -4057 -4058 -4059 -4060 -4061 -4062 -4063 -4064 -4065 -4066 -4067 -4068 -4069 -4070 -4071 -4072 -4073 -4074 -4075 -4076 -4077 -4078 -4079 -4080 -4081 -4082 -4083 -4084 -4085 -4086 -4087 -4088 -4089 -4090 -4091 -4092 -4093 -4094 -4095 -4096 -4097 -4098 -4099 -4100 -4101 -4102 -4103 -4104 -4105 -4106 -4107 -4108 -4109 -4110 -4111 -4112 -4113 -4114 -4115 -4116 -4117 -4118 -4119 -4120 -4121 -4122 -4123 -4124 -4125 -4126 -4127 -4128 -4129 -4130 -4131 -4132 -4133 -4134 -4135 -4136 -4137 -4138 -4139 -4140 -4141 -4142 -4143 -4144 -4145 -4146 -4147 -4148 -4149 -4150 -4151 -4152 -4153 -4154 -4155 -4156 -4157 -4158 -4159 -4160 -4161 -4162 -4163 -4164 -4165 -4166 -4167 -4168 -4169 -4170 -4171 -4172 -4173 -4174 -4175 -4176 -4177 -4178 -4179 -4180 -4181 -4182 -4183 -4184 -4185 -4186 -4187 -4188 -4189 -4190 -4191 -4192 -4193 -4194 -4195 -4196 -4197 -4198 -4199 -4200 -4201 -4202 -4203 -4204 -4205 -4206 -4207 -4208 -4209 -4210 -4211 -4212 -4213 -4214 -4215 -4216 -4217 -4218 -4219 -4220 -4221 -4222 -4223 -4224 -4225 -4226 -4227 -4228 -4229 -4230 -4231 -4232 -4233 -4234 -4235 -4236 -4237 -4238 -4239 -4240 -4241 -4242 -4243 -4244 -4245 -4246 -4247 -4248 -4249 -4250 -4251 -4252 -4253 -4254 -4255 -4256 -4257 -4258 -4259 -4260 -4261 -4262 -4263 -4264 -4265 -4266 -4267 -4268 -4269 -4270 -4271 -4272 -4273 -4274 -4275 -4276 -4277 -4278 -4279 -4280 -4281 -4282 -4283 -4284 -4285 -4286 -4287 -4288 -4289 -4290 -4291 -4292 -4293 -4294 -4295 -4296 -4297 -4298 -4299 -4300 -4301 -4302 -4303 -4304 -4305 -4306 -4307 -4308 -4309 -4310 -4311 -4312 -4313 -4314 -4315 -4316 -4317 -4318 -4319 -4320 -4321 -4322 -4323 -4324 -4325 -4326 -4327 -4328 -4329 -4330 -4331 -4332 -4333 -4334 -4335 -4336 -4337 -4338 -4339 -4340 -4341 -4342 -4343 -4344 -4345 -4346 -4347 -4348 -4349 -4350 -4351 -4352 -4353 -4354 -4355 -4356 -4357 -4358 -4359 -4360 -4361 -4362 -4363 -4364 -4365 -4366 -4367 -4368 -4369 -4370 -4371 -4372 -4373 -4374 -4375 -4376 -4377 -4378 -4379 -4380 -4381 -4382 -4383 -4384 -4385 -4386 -4387 -4388 -4389 -4390 -4391 -4392 -4393 -4394 -4395 -4396 -4397 -4398 -4399 -4400 -4401 -4402 -4403 -4404 -4405 -4406 -4407 -4408 -4409 -4410 -4411 -4412 -4413 -4414 -4415 -4416 -4417 -4418 -4419 -4420 -4421 -4422 -4423 -4424 -4425 -4426 -4427 -4428 -4429 -4430 -4431 -4432 -4433 -4434 -4435 -4436 -4437 -4438 -4439 -4440 -4441 -4442 -4443 -4444 -4445 -4446 -4447 -4448 -4449 -4450 -4451 -4452 -4453 -4454 -4455 -4456 -4457 -4458 -4459 -4460 -4461 -4462 -4463 -4464 -4465 -4466 -4467 -4468 -4469 -4470 -4471 -4472 -4473 -4474 -4475 -4476 -4477 -4478 -4479 -4480 -4481 -4482 -4483 -4484 -4485 -4486 -4487 -4488 -4489 -4490 -4491 -4492 -4493 -4494 -4495 -4496 -4497 -4498 -4499 -4500 -4501 -4502 -4503 -4504 -4505 -4506 -4507 -4508 -4509 -4510 -4511 -4512 -4513 -4514 -4515 -4516 -4517 -4518 -4519 -4520 -4521 -4522 -4523 -4524 -4525 -4526 -4527 -4528 -4529 -4530 -4531 -4532 -4533 -4534 -4535 -4536 -4537 -4538 -4539 -4540 -4541 -4542 -4543 -4544 -4545 -4546 -4547 -4548 -4549 -4550 -4551 -4552 -4553 -4554 -4555 -4556 -4557 -4558 -4559 -4560 -4561 -4562 -4563 -4564 -4565 -4566 -4567 -4568 -4569 -4570 -4571 -4572 -4573 -4574 -4575 -4576 -4577 -4578 -4579 -4580 -4581 -4582 -4583 -4584 -4585 -4586 -4587 -4588 -4589 -4590 -4591 -4592 -4593 -4594 -4595 -4596 -4597 -4598 -4599 -4600 -4601 -4602 -4603 -4604 -4605 -4606 -4607 -4608 -4609 -4610 -4611 -4612 -4613 -4614 -4615 -4616 -4617 -4618 -4619 -4620 -4621 -4622 -4623 -4624 -4625 -4626 -4627 -4628 -4629 -4630 -4631 -4632 -4633 -4634 -4635 -4636 -4637 -4638 -4639 -4640 -4641 -4642 -4643 -4644 -4645 -4646 -4647 -4648 -4649 -4650 -4651 -4652 -4653 -4654 -4655 -4656 -4657 -4658 -4659 -4660 -4661 -4662 -4663 -4664 -4665 -4666 -4667 -4668 -4669 -4670 -4671 -4672 -4673 -4674 -4675 -4676 -4677 -4678 -4679 -4680 -4681 -4682 -4683 -4684 -4685 -4686 -4687 -4688 -4689 -4690 -4691 -4692 -4693 -4694 -4695 -4696 -4697 -4698 -4699 -4700 -4701 -4702 -4703 -4704 -4705 -4706 -4707 -4708 -4709 -4710 -4711 -4712 -4713 -4714 -4715 -4716 -4717 -4718 -4719 -4720 -4721 -4722 -4723 -4724 -4725 -4726 -4727 -4728 -4729 -4730 -4731 -4732 -4733 -4734 -4735 -4736 -4737 -4738 -4739 -4740 -4741 -4742 -4743 -4744 -4745 -4746 -4747 -4748 -4749 -4750 -4751 -4752 -4753 -4754 -4755 -4756 -4757 -4758 -4759 -4760 -4761 -4762 -4763 -4764 -4765 -4766 -4767 -4768 -4769 -4770 -4771 -4772 -4773 -4774 -4775 -4776 -4777 -4778 -4779 -4780 -4781 -4782 -4783 -4784 -4785 -4786 -4787 -4788 -4789 -4790 -4791 -4792 -4793 -4794 -4795 -4796 -4797 -4798 -4799 -4800 -4801 -4802 -4803 -4804 -4805 -4806 -4807 -4808 -4809 -4810 -4811 -4812 -4813 -4814 -4815 -4816 -4817 -4818 -4819 -4820 -4821 -4822 -4823 -4824 -4825 -4826 -4827 -4828 -4829 -4830 -4831 -4832 -4833 -4834 -4835 -4836 -4837 -4838 -4839 -4840 -4841 -4842 -4843 -4844 -4845 -4846 -4847 -4848 -4849 -4850 -4851 -4852 -4853 -4854 -4855 -4856 -4857 -4858 -4859 -4860 -4861 -4862 -4863 -4864 -4865 -4866 -4867 -4868 -4869 -4870 -4871 -4872 -4873 -4874 -4875 -4876 -4877 -4878 -4879 -4880 -4881 -4882 -4883 -4884 -4885 -4886 -4887 -4888 -4889 -4890 -4891 -4892 -4893 -4894 -4895 -4896 -4897 -4898 -4899 -4900 -4901 -4902 -4903 -4904 -4905 -4906 -4907 -4908 -4909 -4910 -4911 -4912 -4913 -4914 -4915 -4916 -4917 -4918 -4919 -4920 -4921 -4922 -4923 -4924 -4925 -4926 -4927 -4928 -4929 -4930 -4931 -4932 -4933 -4934 -4935 -4936 -4937 -4938 -4939 -4940 -4941 -4942 -4943 -4944 -4945 -4946 -4947 -4948 -4949 -4950 -4951 -4952 -4953 -4954 -4955 -4956 -4957 -4958 -4959 -4960 -4961 -4962 -4963 -4964 -4965 -4966 -4967 -4968 -4969 -4970 -4971 -4972 -4973 -4974 -4975 -4976 -4977 -4978 -4979 -4980 -4981 -4982 -4983 -4984 -4985 -4986 -4987 -4988 -4989 -4990 -4991 -4992 -4993 -4994 -4995 -4996 -4997 -4998 -4999 -5000 -5001 -5002 -5003 -5004 -5005 -5006 -5007 -5008 -5009 -5010 -5011 -5012 -5013 -5014 -5015 -5016 -5017 -5018 -5019 -5020 -5021 -5022 -5023 -5024 -5025 -5026 -5027 -5028 -5029 -5030 -5031 -5032 -5033 -5034 -5035 -5036 -5037 -5038 -5039 -5040 -5041 -5042 -5043 -5044 -5045 -5046 -5047 -5048 -5049 -5050 -5051 -5052 -5053 -5054 -5055 -5056 -5057 -5058 -5059 -5060 -5061 -5062 -5063 -5064 -5065 -5066 -5067 -5068 -5069 -5070 -5071 -5072 -5073 -5074 -5075 -5076 -5077 -5078 -5079 -5080 -5081 -5082 -5083 -5084 -5085 -5086 -5087 -5088 -5089 -5090 -5091 -5092 -5093 -5094 -5095 -5096 -5097 -5098 -5099 -5100 -5101 -5102 -5103 -5104 -5105 -5106 -5107 -5108 -5109 -5110 -5111 -5112 -5113 -5114 -5115 -5116 -5117 -5118 -5119 -5120 -5121 -5122 -5123 -5124 -5125 -5126 -5127 -5128 -5129 -5130 -5131 -5132 -5133 -5134 -5135 -5136 -5137 -5138 -5139 -5140 -5141 -5142 -5143 -5144 -5145 -5146 -5147 -5148 -5149 -5150 -5151 -5152 -5153 -5154 -5155 -5156 -5157 -5158 -5159 -5160 -5161 -5162 -5163 -5164 -5165 -5166 -5167 -5168 -5169 -5170 -5171 -5172 -5173 -5174 -5175 -5176 -5177 -5178 -5179 -5180 -5181 -5182 -5183 -5184 -5185 -5186 -5187 -5188 -5189 -5190 -5191 -5192 -5193 -5194 -5195 -5196 -5197 -5198 -5199 -5200 -5201 -5202 -5203 -5204 -5205 -5206 -5207 -5208 -5209 -5210 -5211 -5212 -5213 -5214 -5215 -5216 -5217 -5218 -5219 -5220 -5221 -5222 -5223 -5224 -5225 -5226 -5227 -5228 -5229 -5230 -5231 -5232 -5233 -5234 -5235 -5236 -5237 -5238 -5239 -5240 -5241 -5242 -5243 -5244 -5245 -5246 -5247 -5248 -5249 -5250 -5251 -5252 -5253 -5254 -5255 -5256 -5257 -5258 -5259 -5260 -5261 -5262 -5263 -5264 -5265 -5266 -5267 -5268 -5269 -5270 -5271 -5272 -5273 -5274 -5275 -5276 -5277 -5278 -5279 -5280 -5281 -5282 -5283 -5284 -5285 -5286 -5287 -5288 -5289 -5290 -5291 -5292 -5293 -5294 -5295 -5296 -5297 -5298 -5299 -5300 -5301 -5302 -5303 -5304 -5305 -5306 -5307 -5308 -5309 -5310 -5311 -5312 -5313 -5314 -5315 -5316 -5317 -5318 -5319 -5320 -5321 -5322 -5323 -5324 -5325 -5326 -5327 -5328 -5329 -5330 -5331 -5332 -5333 -5334 -5335 -5336 -5337 -5338 -5339 -5340 -5341 -5342 -5343 -5344 -5345 -5346 -5347 -5348 -5349 -5350 -5351 -5352 -5353 -5354 -5355 -5356 -5357 -5358 -5359 -5360 -5361 -5362 -5363 -5364 -5365 -5366 -5367 -5368 -5369 -5370 -5371 -5372 -5373 -5374 -5375 -5376 -5377 -5378 -5379 -5380 -5381 -5382 -5383 -5384 -5385 -5386 -5387 -5388 -5389 -5390 -5391 -5392 -5393 -5394 -5395 -5396 -5397 -5398 -5399 -5400 -5401 -5402 -5403 -5404 -5405 -5406 -5407 -5408 -5409 -5410 -5411 -5412 -5413 -5414 -5415 -5416 -5417 -5418 -5419 -5420 -5421 -5422 -5423 -5424 -5425 -5426 -5427 -5428 -5429 -5430 -5431 -5432 -5433 -5434 -5435 -5436 -5437 -5438 -5439 -5440 -5441 -5442 -5443 -5444 -5445 -5446 -5447 -5448 -5449 -5450 -5451 -5452 -5453 -5454 -5455 -5456 -5457 -5458 -5459 -5460 -5461 -5462 -5463 -5464 -5465 -5466 -5467 -5468 -5469 -5470 -5471 -5472 -5473 -5474 -5475 -5476 -5477 -5478 -5479 -5480 -5481 -5482 -5483 -5484 -5485 -5486 -5487 -5488 -5489 -5490 -5491 -5492 -5493 -5494 -5495 -5496 -5497 -5498 -5499 -5500 -5501 -5502 -5503 -5504 -5505 -5506 -5507 -5508 -5509 -5510 -5511 -5512 -5513 -5514 -5515 -5516 -5517 -5518 -5519 -5520 -5521 -5522 -5523 -5524 -5525 -5526 -5527 -5528 -5529 -5530 -5531 -5532 -5533 -5534 -5535 -5536 -5537 -5538 -5539 -5540 -5541 -5542 -5543 -5544 -5545 -5546 -5547 -5548 -5549 -5550 -5551 -5552 -5553 -5554 -5555 -5556 -5557 -5558 -5559 -5560 -5561 -5562 -5563 -5564 -5565 -5566 -5567 -5568 -5569 -5570 -5571 -5572 -5573 -5574 -5575 -5576 -5577 -5578 -5579 -5580 -5581 -5582 -5583 -5584 -5585 -5586 -5587 -5588 -5589 -5590 -5591 -5592 -5593 -5594 -5595 -5596 -5597 -5598 -5599 -5600 -5601 -5602 -5603 -5604 -5605 -5606 -5607 -5608 -5609 -5610 -5611 -5612 -5613 -5614 -5615 -5616 -5617 -5618 -5619 -5620 -5621 -5622 -5623 -5624 -5625 -5626 -5627 -5628 -5629 -5630 -5631 -5632 -5633 -5634 -5635 -5636 -5637 -5638 -5639 -5640 -5641 -5642 -5643 -5644 -5645 -5646 -5647 -5648 -5649 -5650 -5651 -5652 -5653 -5654 -5655 -5656 -5657 -5658 -5659 -5660 -5661 -5662 -5663 -5664 -5665 -5666 -5667 -5668 -5669 -5670 -5671 -5672 -5673 -5674 -5675 -5676 -5677 -5678 -5679 -5680 -5681 -5682 -5683 -5684 -5685 -5686 -5687 -5688 -5689 -5690 -5691 -5692 -5693 -5694 -5695 -5696 -5697 -5698 -5699 -5700 -5701 -5702 -5703 -5704 -5705 -5706 -5707 -5708 -5709 -5710 -5711 -5712 -5713 -5714 -5715 -5716 -5717 -5718 -5719 -5720 -5721 -5722 -5723 -5724 -5725 -5726 -5727 -5728 -5729 -5730 -5731 -5732 -5733 -5734 -5735 -5736 -5737 -5738 -5739 -5740 -5741 -5742 -5743 -5744 -5745 -5746 -5747 -5748 -5749 -5750 -5751 -5752 -5753 -5754 -5755 -5756 -5757 -5758 -5759 -5760 -5761 -5762 -5763 -5764 -5765 -5766 -5767 -5768 -5769 -5770 -5771 -5772 -5773 -5774 -5775 -5776 -5777 -5778 -5779 -5780 -5781 -5782 -5783 -5784 -5785 -5786 -5787 -5788 -5789 -5790 -5791 -5792 -5793 -5794 -5795 -5796 -5797 -5798 -5799 -5800 -5801 -5802 -5803 -5804 -5805 -5806 -5807 -5808 -5809 -5810 -5811 -5812 -5813 -5814 -5815 -5816 -5817 -5818 -5819 -5820 -5821 -5822 -5823 -5824 -5825 -5826 -5827 -5828 -5829 -5830 -5831 -5832 -5833 -5834 -5835 -5836 -5837 -5838 -5839 -5840 -5841 -5842 -5843 -5844 -5845 -5846 -5847 -5848 -5849 -5850 -5851 -5852 -5853 -5854 -5855 -5856 -5857 -5858 -5859 -5860 -5861 -5862 -5863 -5864 -5865 -5866 -5867 -5868 -5869 -5870 -5871 -5872 -5873 -5874 -5875 -5876 -5877 -5878 -5879 -5880 -5881 -5882 -5883 -5884 -5885 -5886 -5887 -5888 -5889 -5890 -5891 -5892 -5893 -5894 -5895 -5896 -5897 -5898 -5899 -5900 -5901 -5902 -5903 -5904 -5905 -5906 -5907 -5908 -5909 -5910 -5911 -5912 -5913 -5914 -5915 -5916 -5917 -5918 -5919 -5920 -5921 -5922 -5923 -5924 -5925 -5926 -5927 -5928 -5929 -5930 -5931 -5932 -5933 -5934 -5935 -5936 -5937 -5938 -5939 -5940 -5941 -5942 -5943 -5944 -5945 -5946 -5947 -5948 -5949 -5950 -5951 -5952 -5953 -5954 -5955 -5956 -5957 -5958 -5959 -5960 -5961 -5962 -5963 -5964 -5965 -5966 -5967 -5968 -5969 -5970 -5971 -5972 -5973 -5974 -5975 -5976 -5977 -5978 -5979 -5980 -5981 -5982 -5983 -5984 -5985 -5986 -5987 -5988 -5989 -5990 -5991 -5992 -5993 -5994 -5995 -5996 -5997 -5998 -5999 -6000 -6001 -6002 -6003 -6004 -6005 -6006 -6007 -6008 -6009 -6010 -6011 -6012 -6013 -6014 -6015 -6016 -6017 -6018 -6019 -6020 -6021 -6022 -6023 -6024 -6025 -6026 -6027 -6028 -6029 -6030 -6031 -6032 -6033 -6034 -6035 -6036 -6037 -6038 -6039 -6040 -6041 -6042 -6043 -6044 -6045 -6046 -6047 -6048 -6049 -6050 -6051 -6052 -6053 -6054 -6055 -6056 -6057 -6058 -6059 -6060 -6061 -6062 -6063 -6064 -6065 -6066 -6067 -6068 -6069 -6070 -6071 -6072 -6073 -6074 -6075 -6076 -6077 -6078 -6079 -6080 -6081 -6082 -6083 -6084 -6085 -6086 -6087 -6088 -6089 -6090 -6091 -6092 -6093 -6094 -6095 -6096 -6097 -6098 -6099 -6100 -6101 -6102 -6103 -6104 -6105 -6106 -6107 -6108 -6109 -6110 -6111 -6112 -6113 -6114 -6115 -6116 -6117 -6118 -6119 -6120 -6121 -6122 -6123 -6124 -6125 -6126 -6127 -6128 -6129 -6130 -6131 -6132 -6133 -6134 -6135 -6136 -6137 -6138 -6139 -6140 -6141 -6142 -6143 -6144 -6145 -6146 -6147 -6148 -6149 -6150 -6151 -6152 -6153 -6154 -6155 -6156 -6157 -6158 -6159 -6160 -6161 -6162 -6163 -6164 -6165 -6166 -6167 -6168 -6169 -6170 -6171 -6172 -6173 -6174 -6175 -6176 -6177 -6178 -6179 -6180 -6181 -6182 -6183 -6184 -6185 -6186 -6187 -6188 -6189 -6190 -6191 -6192 -6193 -6194 -6195 -6196 -6197 -6198 -6199 -6200 -6201 -6202 -6203 -6204 -6205 -6206 -6207 -6208 -6209 -6210 -6211 -6212 -6213 -6214 -6215 -6216 -6217 -6218 -6219 -6220 -6221 -6222 -6223 -6224 -6225 -6226 -6227 -6228 -6229 -6230 -6231 -6232 -6233 -6234 -6235 -6236 -6237 -6238 -6239 -6240 -6241 -6242 -6243 -6244 -6245 -6246 -6247 -6248 -6249 -6250 -6251 -6252 -6253 -6254 -6255 -6256 -6257 -6258 -6259 -6260 -6261 -6262 -6263 -6264 -6265 -6266 -6267 -6268 -6269 -6270 -6271 -6272 -6273 -6274 -6275 -6276 -6277 -6278 -6279 -6280 -6281 -6282 -6283 -6284 -6285 -6286 -6287 -6288 -6289 -6290 -6291 -6292 -6293  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 
import React, { useEffect, useMemo, useRef, useState } from "react";
-import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "@/components/ui/accordion";
-import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter } from "@/components/ui/dialog";
-import { motion, AnimatePresence } from "framer-motion";
-import { audioManager } from "@/lib/audioManager";
-import type { SoundName, MusicName } from "@/lib/audioManager";
-import { hapticLight, hapticMedium, hapticHeavy, hapticSuccess, hapticWarning, hapticRumble } from "@/lib/haptics";
-import { useParticles, ParticleLayer } from "@/lib/particles";
-import type { ParticlePreset } from "@/lib/particles";
-import { RebirthModal } from "./sections/RebirthModal";
-import { PlayerAvatar, BossE, BossD, BossC, BossB, BossA, BossS } from "./bosses";
-import { useIsMobile } from "../../hooks/useIsMobile";
-import { MobileLayout } from "./mobile/MobileLayout";
-import { createInitialPlayer, playerPower, spiritUpkeep, calcExtractionChance, gainExpGoldFromGate } from "@/lib/game/gameLogic";
-import { createSpirit, getRarityColor, getRarityBorder, SPIRIT_TYPES, SPIRIT_ABILITIES, SPIRIT_DESCRIPTIONS } from "@/lib/game/spiritSystem";
-import { RANKS, RANK_COLORS as GAME_RANK_COLORS, DUNGEON_MODIFIERS, generateGatePool, makeGate, rollDrop } from "@/lib/game/gateSystem";
-export const RANK_COLORS = GAME_RANK_COLORS;
-import { formatGameTime, getCurrentGameDate, initialGameTime, generateDailyQuests, getDifficultyColor, getDifficultyBgColor } from "@/lib/game/questSystem";
- 
-// Hunter's Path — An idle/roguelite RPG built for Canvas preview
-// Notes:
-// - Mechanics: Gates/Dungeons, Daily Quests with penalties,
-//   stat allocation on level-up, fatigue, spirit binding (post-boss), instant dungeons.
-// - An original IP idle/roguelite RPG.
-//
-// Play tips:
-// 1) Complete Daily Quest before running a dungeon to avoid penalties.
-// 2) Allocate stat points after leveling up (top-right panel).
-// 3) Beat a dungeon boss to attempt Spirit Binding — your INT and LUCK matter.
-// 4) Fatigue rises with runs; high fatigue reduces damage and raises failure risk.
-// 5) Instant Dungeon Keys drop sometimes; use them for a bonus run.
- 
-// ---------- Utility ----------
-const clamp = (n: number, a: number, b: number) => Math.max(a, Math.min(b, n));
-const rand = (min: number, max: number) =>
-  Math.floor(Math.random() * (max - min + 1)) + min;
-const uid = () => Math.random().toString(36).slice(2, 9);
-const fmt = (n: number) => new Intl.NumberFormat().format(Math.floor(n));
- 
-const STAT_ICONS = {
-  STR: "fas fa-fist-raised",
-  AGI: "fas fa-running",
-  INT: "fas fa-brain",
-  VIT: "fas fa-heart",
-  LUCK: "fas fa-dice",
-};
- 
-const STAT_COLORS = {
-  STR: "bg-red-600",
-  AGI: "bg-green-600",
-  INT: "bg-blue-600",
-  VIT: "bg-orange-600",
-  LUCK: "bg-yellow-600",
-};
- 
-interface Boss {
-  name: string;
-  maxHp: number;
-  hp: number;
-  atk: number;
-  def: number;
-}
- 
-interface DungeonModifier {
-  id: string;
-  name: string;
-  description: string;
-  icon: string;
-  type: "buff" | "debuff" | "neutral";
-  applyToRewards: (expMult: number, goldMult: number) => { expMult: number; goldMult: number };
-  applyToCombat: (playerDmgMult: number, bossDmgMult: number) => { playerDmgMult: number; bossDmgMult: number };
-}
- 
-interface Gate {
-  id: string;
-  name: string;
-  rank: string;
-  rankIdx: number;
-  recommended: number;
-  power: number;
-  boss: Boss;
-  modifiers: DungeonModifier[];
-}
- 
-interface Spirit {
-  id: string;
-  name: string;
-  power: number;
-  rarity: "common" | "uncommon" | "rare" | "epic" | "legendary";
-  abilities: SpiritAbility[];
-  level: number;
-  exp: number;
-  expToNext: number;
-  type: "warrior" | "mage" | "rogue" | "tank" | "support";
-  description: string;
-}
- 
-interface SpiritAbility {
-  id: string;
-  name: string;
-  description: string;
-  type: "passive" | "active";
-  effect: string;
-  cooldown?: number;
-}
- 
-interface Item {
-  id: string;
-  name: string;
-  type: string;
-  rarity: "common" | "uncommon" | "rare" | "epic" | "legendary";
-  quality: number; // 1-100, affects effectiveness
-  description?: string;
-  stats?: {
-    STR?: number;
-    AGI?: number;
-    INT?: number;
-    VIT?: number;
-    LUCK?: number;
-    HP?: number;
-    MP?: number;
-  };
-  equipmentSlot?: "weapon" | "armor" | "accessory" | null;
-  sellValue?: number;
-}
- 
-interface Equipment {
-  weapon?: Item;
-  armor?: Item;
-  accessory?: Item;
-}
- 
-interface Player {
-  level: number;
-  exp: number;
-  expNext: number;
-  hp: number;
-  mp: number;
-  maxHp: number;
-  maxMp: number;
-  fatigue: number;
-  points: number;
-  stats: {
-    STR: number;
-    AGI: number;
-    INT: number;
-    VIT: number;
-    LUCK: number;
-  };
-  spirits: Spirit[];
-  inv: Item[];
-  keys: number;
-  equipment: Equipment;
-  rebirths: number;        // Number of times rebirthing
-  prestigePoints: number;  // Total prestige points earned
-  clearedRanks?: string[]; // Ranks cleared for first time (E, D, C, B, A, S)
-}
- 
-interface DailyTask {
-  id: string;
-  name: string;
-  description: string;
-  type: "combat" | "exploration" | "collection" | "skill" | "challenge";
-  difficulty: "easy" | "medium" | "hard" | "epic";
-  need: number;
-  have: number;
-  expReward: number;
-  goldReward: number;
-  bonusRewards?: {
-    items?: Item[];
-    statPoints?: number;
-  };
-}
- 
-interface Daily {
-  active: boolean;
-  availableQuests: DailyTask[];
-  completedQuests: string[]; // IDs of completed quests
-  completed: boolean;
-  penaltyArmed: boolean;
-  completedDate?: string; // Track when it was completed to allow reset
-  questReputation: number; // New: tracks quest completion reputation
-  lastResetDate?: string; // Track when daily quests were last reset
-}
- 
-interface GameTime {
-  day: number;
-  currentDate: string;
-  lastReset: string;
-}
- 
-interface RunningState {
-  gate: Gate;
-  boss: Boss;
-  hpEnemy: number;
-  tick: number;
-}
- 
-interface CombatResult {
-  victory: boolean;
-  gate: Gate;
-  boss: Boss;
-  expGained: number;
-  goldGained: number;
-  drops: Item[];
-  spiritBound?: Spirit;
-  combatLog: string[];
-}
- 
-// Simple statistics interfaces for Phase 1
-interface PlayerStatistics {
-  totalGatesCompleted: number;
-  totalGatesFailed: number;
-  totalExpGained: number;
-  totalGoldGained: number;
-  totalSpiritsBound: number;
-  highestGateRank: string;
-  lastUpdated: string;
-}
- 
-interface Achievement {
-  id: string;
-  name: string;
-  description: string;
-  unlockedAt: string;
-}
- 
-interface PrestigeUpgrade {
-  id: string;
-  name: string;
-  description: string;
-  costPer: number;
-  maxLevel: number;
-}
- 
-const PRESTIGE_UPGRADES: PrestigeUpgrade[] = [
-  { id: "exp_boost", name: "Eternal Scholar", description: "+5% EXP gain per level", costPer: 50, maxLevel: 10 },
-  { id: "gold_boost", name: "Fortune's Heir", description: "+5% gold gain per level", costPer: 50, maxLevel: 10 },
-  { id: "spirit_power", name: "Legion Master", description: "+2% spirit power bonus per level", costPer: 100, maxLevel: 10 },
-  { id: "start_gold", name: "Head Start", description: "+100 starting gold per rebirth level", costPer: 75, maxLevel: 5 },
-  { id: "fatigue_resist", name: "Ironwill", description: "-5% fatigue accumulation per level", costPer: 75, maxLevel: 5 },
-  { id: "bind_chance", name: "Spirit Whisperer", description: "+3% spirit bind chance per level", costPer: 150, maxLevel: 5 },
-];
- 
-// Core combat, gate, spirit, and progression logic lives in @/lib/game modules.
- 
-// ---------- React UI Components ----------
-function Card({
-  children,
-  className = "",
-  glow,
-}: {
-  children: React.ReactNode;
-  className?: string;
-  glow?: "purple" | "red" | "green" | "gold";
-}) {
-  const glowCls = glow
-    ? {
-        purple: "border-violet-500/40 shadow-violet-500/10",
-        red: "border-red-500/40 shadow-red-500/10",
-        green: "border-green-500/40 shadow-green-500/10",
-        gold: "border-yellow-500/40 shadow-yellow-500/10",
-      }[glow]
-    : "";
-  return (
-    <div
-      className={`game-card rounded-xl border p-6 ${glowCls} ${className}`}
-    >
-      {children}
-    </div>
-  );
-}
- 
-function Btn({
-  children,
-  onClick,
-  disabled,
-  sm,
-  theme = "default",
-  className = "",
-}: {
-  children: React.ReactNode;
-  onClick?: () => void;
-  disabled?: boolean;
-  sm?: boolean;
-  theme?: string;
-  className?: string;
-}) {
-  const base =
-    "rounded-xl px-4 py-2 font-bold font-display tracking-wide transition-all duration-200 active:scale-95 disabled:opacity-40 disabled:cursor-not-allowed hover:scale-105 select-none touch-manipulation";
-  const size = sm ? "px-3 py-1 text-sm" : "text-sm";
-  const themeCls =
-    theme === "danger"
-      ? "bg-gradient-to-r from-red-600 to-red-500 hover:from-red-500 hover:to-red-400 text-white shadow-lg shadow-red-500/20"
-      : "bg-gradient-to-r from-violet-600 to-purple-500 hover:from-violet-500 hover:to-purple-400 text-white shadow-lg shadow-violet-500/20";
-  return (
-    <button
-      className={`${base} ${size} ${themeCls} ${className}`}
-      onClick={() => {
-        hapticLight();
-        onClick?.();
-      }}
-      disabled={disabled}
-    >
-      {children}
-    </button>
-  );
-}
- 
-function Bar({
-  label,
-  value,
-  max,
-  color = "progress-hp",
-}: {
-  label: string;
-  value: number;
-  max: number;
-  color?: string;
-}) {
-  const pct = Math.round((value / max) * 100);
-  return (
-    <div className="mt-3">
-      <div className="flex justify-between text-sm opacity-90 mb-1">
-        <span className="font-medium">{label}</span>
-        <span className="tabular-nums">
-          {fmt(value)} / {fmt(max)} ({pct}%)
-        </span>
-      </div>
-      <div className="w-full h-3 bg-zinc-800/80 rounded-full overflow-hidden border border-zinc-700/50">
-        <div
-          className={`h-full rounded-full transition-all duration-500 ease-out progress-shimmer ${color}`}
-          style={{ width: `${pct}%` }}
-        />
-      </div>
-    </div>
-  );
-}
- 
-function BarMini({
-  value,
-  max,
-  color = "bg-emerald-500",
-}: {
-  value: number;
-  max: number;
-  color?: string;
-}) {
-  const pct = Math.round((value / max) * 100);
-  return (
-    <div className="w-full h-2 bg-zinc-800 rounded-full overflow-hidden">
-      <div
-        className={`h-2 rounded-full transition-all duration-300 ${color}`}
-        style={{ width: `${pct}%` }}
-      />
-    </div>
-  );
-}
- 
-// ─── Framer Motion combat components ──────────────────────────
- 
-// Animated health bar with spring physics
-function CombatBar({
-  value,
-  max,
-  color,
-  label,
-}: {
-  value: number;
-  max: number;
-  color: string;
-  label: string;
-}) {
-  const pct = max > 0 ? Math.round((value / max) * 100) : 0;
-  return (
-    <div>
-      <div className="flex justify-between text-sm mb-1">
-        <span className={color}>{label}</span>
-        <span className="text-zinc-300 tabular-nums">
-          {fmt(value)}/{fmt(max)}
-        </span>
-      </div>
-      <div className="w-full bg-zinc-700/80 rounded-full h-3 overflow-hidden border border-zinc-600/40">
-        <motion.div
-          className={`h-full rounded-full progress-shimmer ${
-            label === "HP" && color.includes("green")
-              ? "bg-gradient-to-r from-green-600 to-green-500 shadow-green-500/40"
-              : label === "MP"
-              ? "bg-gradient-to-r from-blue-600 to-blue-500 shadow-blue-500/40"
-              : "bg-gradient-to-r from-red-600 to-red-500 shadow-red-500/40"
-          }`}
-          style={{ boxShadow: "0 0 6px currentColor" }}
-          initial={false}
-          animate={{ width: `${pct}%` }}
-          transition={{ type: "spring", stiffness: 120, damping: 20 }}
-        />
-      </div>
-    </div>
-  );
-}
- 
-// Floating damage/heal numbers
-function DamageNumber({
-  amount,
-  type,
-  id,
-}: {
-  amount: number;
-  type: "damage" | "heal" | "critical" | "block";
-  id: string;
-}) {
-  const colorMap = {
-    damage: "text-red-400",
-    heal: "text-green-400",
-    critical: "text-yellow-300 text-lg font-black",
-    block: "text-zinc-400",
-  };
-  const prefix = type === "heal" ? "+" : type === "block" ? "" : "-";
-  const label = type === "block" ? "BLOCKED" : `${prefix}${fmt(amount)}`;
- 
-  return (
-    <motion.div
-      key={id}
-      className={`absolute font-bold pointer-events-none z-20 ${colorMap[type]}`}
-      initial={{ opacity: 1, y: 0, scale: type === "critical" ? 1.4 : 1 }}
-      animate={{ opacity: 0, y: -40, scale: type === "critical" ? 1.8 : 1.1 }}
-      exit={{ opacity: 0 }}
-      transition={{ duration: 1, ease: "easeOut" }}
-    >
-      {label}
-    </motion.div>
-  );
-}
- 
-// Monster data for immersive experience
-const MONSTER_DATA = {
-  E: {
-    name: "Goblin Warrior",
-    description:
-      "A small but fierce goblin with crude weapons. Though weak individually, they fight with surprising ferocity.",
-    icon: "fas fa-user-ninja",
-    color: "text-green-400",
-    bgColor: "bg-green-900/30",
-    borderColor: "border-green-500/30",
-    environment:
-      "A dimly lit cave with moss-covered walls and scattered bones.",
-    sound: "High-pitched screeches echo through the cavern...",
-  },
-  D: {
-    name: "Orc Berserker",
-    description:
-      "A muscular orc warrior with blood-red eyes. Their rage makes them unpredictable and dangerous.",
-    icon: "fas fa-user-shield",
-    color: "text-blue-400",
-    bgColor: "bg-blue-900/30",
-    borderColor: "border-blue-500/30",
-    environment: "A torch-lit dungeon with iron bars and the stench of battle.",
-    sound: "Deep roars shake the dungeon walls...",
-  },
-  C: {
-    name: "Dark Elf Assassin",
-    description:
-      "A shadowy figure with deadly precision. Their movements are like liquid darkness.",
-    icon: "fas fa-user-secret",
-    color: "text-purple-400",
-    bgColor: "bg-purple-900/30",
-    borderColor: "border-purple-500/30",
-    environment:
-      "A moonlit forest clearing with twisted trees and mysterious shadows.",
-    sound: "Whispers of ancient magic fill the air...",
-  },
-  B: {
-    name: "Troll Chieftain",
-    description:
-      "A massive troll with stone-like skin. Their club can crush bones with a single swing.",
-    icon: "fas fa-user-graduate",
-    color: "text-red-400",
-    bgColor: "bg-red-900/30",
-    borderColor: "border-red-500/30",
-    environment: "A rocky mountain pass with jagged peaks and howling winds.",
-    sound: "Thunderous footsteps echo across the mountains...",
-  },
-  A: {
-    name: "Dragon Knight",
-    description:
-      "A legendary warrior clad in dragon-scale armor. Their sword burns with ancient fire.",
-    icon: "fas fa-crown",
-    color: "text-orange-400",
-    bgColor: "bg-orange-900/30",
-    borderColor: "border-orange-500/30",
-    environment: "A grand hall with towering pillars and dragon banners.",
-    sound: "The clash of steel and roar of dragons fills the hall...",
-  },
-  S: {
-    name: "Void Lord",
-    description:
-      "A being of pure darkness and malice. Their very presence corrupts the air around them.",
-    icon: "fas fa-user-tie",
-    color: "text-yellow-400",
-    bgColor: "bg-yellow-900/30",
-    borderColor: "border-yellow-500/30",
-    environment:
-      "A void of absolute darkness where reality itself seems to bend.",
-    sound: "The fabric of space itself seems to tear...",
-  },
-};
- 
-// Thematic gate names by rank
-const GATE_NAMES: Record<string, string[]> = {
-  E: [
-    "Goblin Burrow", "Mushroom Grotto", "Rat Warren", "Slime Pit",
-    "Mossy Tunnel", "Abandoned Mine", "Shallow Cave", "Dusty Cellar",
-  ],
-  D: [
-    "Orc Stronghold", "Cursed Mines", "Swamp Depths", "Iron Crypt",
-    "Bandit Hideout", "Troll Bridge", "Dark Hollow", "Bone Quarry",
-  ],
-  C: [
-    "Shadow Forest", "Moonlit Ruins", "Phantom Keep", "Crimson Marsh",
-    "Spider Nest", "Haunted Chapel", "Witch's Glade", "Twilight Gorge",
-  ],
-  B: [
-    "Troll Citadel", "Thunder Peak", "Frozen Fortress", "Magma Cavern",
-    "War Bastion", "Storm Spire", "Obsidian Vault", "Siege Grounds",
-  ],
-  A: [
-    "Dragon's Lair", "Inferno Sanctum", "Sky Fortress", "Ashen Throne",
-    "Blazing Halls", "Wyrm's Den", "Phoenix Roost", "Flame Citadel",
-  ],
-  S: [
-    "Void Nexus", "Abyssal Gate", "Reality Fracture", "Chaos Rift",
-    "World's Edge", "Dimensional Tear", "Oblivion Core", "Shattered Plane",
-  ],
-};
- 
-// Combat log flavor text
-const PLAYER_ATTACK_MSGS = [
-  (dmg: number) => `Hunter strikes for ${dmg} damage!`,
-  (dmg: number) => `Hunter lands a solid blow — ${dmg} damage!`,
-  (dmg: number) => `Hunter slashes through for ${dmg} damage!`,
-  (dmg: number) => `Hunter charges in — ${dmg} damage dealt!`,
-  (dmg: number) => `A swift strike connects — ${dmg} damage!`,
-  (dmg: number) => `Hunter finds an opening — ${dmg} damage!`,
-];
-const BOSS_ATTACK_MSGS: Record<string, ((name: string, dmg: number) => string)[]> = {
-  E: [
-    (n, d) => `${n} swings wildly — ${d} damage!`,
-    (n, d) => `${n} lunges with a crude blade — ${d} damage!`,
-  ],
-  D: [
-    (n, d) => `${n} roars and smashes down — ${d} damage!`,
-    (n, d) => `${n} charges with brute force — ${d} damage!`,
-  ],
-  C: [
-    (n, d) => `${n} strikes from the shadows — ${d} damage!`,
-    (n, d) => `${n} vanishes and reappears — ${d} damage!`,
-  ],
-  B: [
-    (n, d) => `${n} slams their weapon down — ${d} damage!`,
-    (n, d) => `${n} hurls a massive blow — ${d} damage!`,
-  ],
-  A: [
-    (n, d) => `${n} unleashes dragonfire — ${d} damage!`,
-    (n, d) => `${n} swings a blazing sword — ${d} damage!`,
-  ],
-  S: [
-    (n, d) => `${n} tears through reality — ${d} damage!`,
-    (n, d) => `${n} channels the void — ${d} damage!`,
-  ],
-};
-const BOSS_BLOCK_MSGS = [
-  (name: string) => `${name}'s attack is deflected!`,
-  (name: string) => `Hunter dodges ${name}'s strike!`,
-  (name: string) => `${name}'s blow glances off!`,
-];
-const CRIT_MSGS = [
-  (dmg: number) => `💥 Critical hit! ${dmg} damage!`,
-  (dmg: number) => `💥 Devastating blow — ${dmg} damage!`,
-  (dmg: number) => `💥 Hunter finds a weak spot — ${dmg} critical damage!`,
-];
-const SPIRIT_ABILITY_MSGS: Record<string, string[]> = {
-  berserker_rage: [
-    "⚔️ Berserker Rage surges — damage increased!",
-    "⚔️ Rage takes hold — striking harder!",
-  ],
-  shadow_step: [
-    "🌑 Shadow Step — enhanced strike!",
-    "🌑 Slipping through shadows for a precise hit!",
-  ],
-  ethereal_shield: [
-    "🛡️ Ethereal Shield shimmers into place!",
-  ],
-  vitality_aura: [
-    "💚 Vitality Aura pulses with healing energy",
-  ],
-  mana_shield: [
-    "🔮 Mana Shield absorbs incoming damage",
-  ],
-};
-const BOSS_PHASE_MSGS: Record<string, string[]> = {
-  "75": [
-    "The boss staggers but fights on!",
-    "Blood drips — the boss grows desperate!",
-  ],
-  "50": [
-    "The boss is wounded — halfway down!",
-    "⚠️ The boss enters a frenzy!",
-  ],
-  "25": [
-    "The boss is near death — finish it!",
-    "💀 The boss makes a last stand!",
-  ],
-};
-function pick<T>(arr: T[]): T { return arr[Math.floor(Math.random() * arr.length)]; }
- 
-// Story progression — rank-up milestones (triggered on level-up)
-const RANK_MILESTONES: { level: number; title: string; message: string; color: string }[] = [
-  { level: 1,  title: "The Awakening",           message: "You awaken to find a shimmering gate before you. A strange instinct compels you forward. Your journey as a Hunter begins.", color: "violet" },
-  { level: 3,  title: "D-Rank Certified",         message: "The Hunter's Guild acknowledges your skill. D-Rank gates now open to you. The creatures within are fiercer — prepare yourself.", color: "green" },
-  { level: 6,  title: "C-Rank Hunter",            message: "Your reputation grows. Shadows in C-Rank gates whisper of a Hunter who fights without fear. Darker dungeons beckon.", color: "blue" },
-  { level: 10, title: "B-Rank Breakthrough",       message: "Few Hunters reach B-Rank. The Guild Commander nods with respect. \"The gates are getting worse,\" she warns. \"Something stirs beyond them.\"", color: "orange" },
-  { level: 20, title: "A-Rank — Elite Hunter",     message: "A-Rank. The world watches. Dragons and ancient knights guard these gates. You stand among the strongest Hunters alive.", color: "red" },
-  { level: 35, title: "S-Rank — Legend",           message: "S-Rank gates tear at the fabric of reality itself. You are one of the few who dares enter. The void beyond these gates holds secrets older than the world.", color: "purple" },
-  { level: 50, title: "Transcendence",            message: "You have reached the pinnacle. The gates themselves seem to respond to your power. Perhaps it is time to be reborn — stronger than before.", color: "amber" },
-];
- 
-// First-clear celebration text per rank
-const FIRST_CLEAR_TEXT: Record<string, { title: string; message: string }> = {
-  E: { title: "First Gate Cleared", message: "You emerge from your first gate, shaking but alive. The Hunter's Guild takes notice — a new Hunter has begun their journey." },
-  D: { title: "D-Rank Conquered", message: "The shadows of D-Rank gates no longer frighten you. You've proven you can handle what lurks in the dark. The Guild marks your file: 'Promising.'" },
-  C: { title: "C-Rank Vanquished", message: "C-Rank bosses fall before you. Other Hunters whisper your name in the guild halls. The path ahead grows darker — but so does your resolve." },
-  B: { title: "B-Rank Breakthrough!", message: "You've done what most Hunters never will — cleared a B-Rank gate. The Guild Commander summons you personally. \"We need Hunters like you. The worst is yet to come.\"" },
-  A: { title: "A-Rank Conquered!", message: "Dragons and ancient knights — the guardians of A-Rank gates — have fallen to your blade. The world trembles. You stand among the elite, the chosen few who dare face the abyss." },
-  S: { title: "S-Rank — The Impossible", message: "Reality itself bends around you as you emerge from an S-Rank gate. No one believed it possible. The fabric of dimensions whispers your name. You are legend." },
-};
- 
-// Boss dialogue shown at combat start
-const BOSS_DIALOGUE: Record<string, string[]> = {
-  E: [
-    "\"You dare enter my burrow? You'll regret this!\"",
-    "\"Another Hunter? They never learn...\"",
-  ],
-  D: [
-    "\"I've crushed a dozen Hunters. You're next!\"",
-    "\"This dungeon is MY territory!\"",
-  ],
-  C: [
-    "\"You can feel it, can't you? The darkness here is alive.\"",
-    "\"Most Hunters flee at this point. Will you?\"",
-  ],
-  B: [
-    "\"I've been waiting for a real challenge. Step forward.\"",
-    "\"The mountain itself trembles at my rage.\"",
-  ],
-  A: [
-    "\"Few mortals have stood before me and lived.\"",
-    "\"The dragon's flame burns eternal. Can you endure it?\"",
-  ],
-  S: [
-    "\"You stand at the edge of oblivion. Turn back.\"",
-    "\"Reality bends. Time fractures. And still you come.\"",
-  ],
-};
- 
-// Unlockable lore entries keyed by player level
-const LORE_ENTRIES: { level: number; title: string; text: string }[] = [
-  { level: 1,  title: "What Are Gates?",            text: "Dimensional rifts that appeared across the world without warning. Inside lie monsters, treasure, and mysteries. Hunters are those brave enough to enter." },
-  { level: 5,  title: "The Hunter's Guild",          text: "Formed to organize Hunters and manage gate clearance. They rank both Hunters and gates from E (weakest) to S (catastrophic). Guild support keeps cities safe." },
-  { level: 10, title: "Spirit Binding",              text: "Some Hunters develop the ability to bind the essence of defeated bosses, creating spirit allies that fight alongside them. The mechanism is poorly understood." },
-  { level: 15, title: "The Fatigue Problem",         text: "Prolonged exposure to gate energy causes fatigue — a dulling of the senses that weakens even the strongest Hunters. Rest is not optional; it is survival." },
-  { level: 20, title: "Gate Ranks Explained",        text: "E-Rank gates are manageable. D through C require real skill. B-Rank gates have leveled entire city blocks when left unchecked. A and S-Rank gates are existential threats." },
-  { level: 30, title: "The Origin of Gates",         text: "No one knows why gates appeared. Some theories suggest a weakening barrier between dimensions. Others point to an ancient experiment gone wrong. The truth remains buried." },
-  { level: 40, title: "Rebirth",                    text: "A handful of Hunters have discovered a way to shed their accumulated power and start anew — emerging stronger each time. They call it Rebirth. The cost is everything you've built." },
-  { level: 50, title: "Beyond S-Rank",               text: "Rumors persist of gates beyond S-Rank — tears in reality so vast they could swallow nations. If they exist, only a reborn Hunter could hope to survive them." },
-];
- 
-type BossRank = (typeof RANKS)[number];
-const BOSS_COMPONENTS: Record<BossRank, React.ComponentType<{ className?: string }>> = {
-  E: BossE,
-  D: BossD,
-  C: BossC,
-  B: BossB,
-  A: BossA,
-  S: BossS,
-};
- 
-export default function HuntersPath() {
-  // Particle effects system
-  const { trigger: triggerParticles, bursts, removeBurst } = useParticles();
-  const isMobile = useIsMobile();
- 
-  const [player, setPlayer] = useState<Player>(createInitialPlayer);
-  const [rebirthModalOpen, setRebirthModalOpen] = useState(false);
-  const [offlineGains, setOfflineGains] = useState<{
-    show: boolean;
-    exp: number;
-    gold: number;
-    hours: number;
-  } | null>(null);
-  const [log, setLog] = useState<string[]>([
-    "Welcome, Hunter. Complete your Daily Quest, then clear a Gate.",
-  ]);
-  const [combatLog, setCombatLog] = useState<string[]>([]);
-  const [gates, setGates] = useState<Gate[]>(() => generateGatePool(1));
-  const [running, setRunning] = useState<RunningState | null>(null); // { gate, boss, tick, inBoss, hpEnemy }
-  const [combatResult, setCombatResult] = useState<CombatResult | null>(null);
-  const [visualEffects, setVisualEffects] = useState<{
-    damageFlash: boolean;
-    healFlash: boolean;
-    criticalHit: boolean;
-    screenShake: boolean;
-    levelUp: boolean;
-    statAllocation: boolean;
-  }>({
-    damageFlash: false,
-    healFlash: false,
-    criticalHit: false,
-    screenShake: false,
-    levelUp: false,
-    statAllocation: false,
-  });
-  // Floating damage numbers for combat
-  const [damageNumbers, setDamageNumbers] = useState<
-    { id: string; amount: number; type: "damage" | "heal" | "critical" | "block"; side: "player" | "enemy" }[]
-  >([]);
- 
-  const addDamageNumber = (amount: number, type: "damage" | "heal" | "critical" | "block", side: "player" | "enemy") => {
-    const id = uid();
-    setDamageNumbers((prev) => [...prev.slice(-5), { id, amount, type, side }]);
-    setTimeout(() => setDamageNumbers((prev) => prev.filter((d) => d.id !== id)), 1100);
-  };
- 
-  const [gold, setGold] = useState(50); // Start with some gold for gate refreshes
-  const [gameTime, setGameTime] = useState<GameTime>(initialGameTime);
-  const [daily, setDaily] = useState<Daily>(() => {
-    // Check if we need to reset daily quests based on real date
-    const today = new Date().toDateString();
-    const savedDaily = localStorage.getItem("hunters-path-daily");
- 
-    if (savedDaily) {
-      const parsedDaily = JSON.parse(savedDaily);
-      if (parsedDaily.lastResetDate === today) {
-        // Same day, restore saved state
-        return parsedDaily;
-      }
-    }
- 
-    // New day or no saved data, generate fresh daily quests
-    const initialQuests = generateDailyQuests(1, 0);
-    const newDaily = {
-      active: true, // Auto-start daily quests
-      availableQuests: initialQuests,
-      completedQuests: [],
-      completed: false,
-      penaltyArmed: false,
-      questReputation: 0,
-      lastResetDate: today,
-    };
- 
-    // Save the new daily state
-    localStorage.setItem("hunters-path-daily", JSON.stringify(newDaily));
-    return newDaily;
-  });
- 
-  // Sound management state — delegates to audioManager singleton
-  const [soundEnabled, setSoundEnabled] = useState(true);
-  const [musicEnabled, setMusicEnabled] = useState(true);
-  const [volume, setVolume] = useState(0.7);
- 
-  // Simple statistics state for Phase 1
-  const [playerStats, setPlayerStats] = useState<PlayerStatistics>({
-    totalGatesCompleted: 0,
-    totalGatesFailed: 0,
-    totalExpGained: 0,
-    totalGoldGained: 0,
-    totalSpiritsBound: 0,
-    highestGateRank: "E",
-    lastUpdated: new Date().toISOString(),
-  });
-  const [achievements, setAchievements] = useState<Achievement[]>([]);
-  const [showStats, setShowStats] = useState(false);
- 
-  const [prestigeUpgrades, setPrestigeUpgrades] = useState<Record<string, number>>(
-    () => {
-      try {
-        const saved = localStorage.getItem("hunters-path-prestige-upgrades");
-        return saved ? JSON.parse(saved) : {};
-      } catch { return {}; }
-    }
-  );
- 
-  const tickRef = useRef<NodeJS.Timeout | null>(null);
-  const timeRef = useRef<NodeJS.Timeout | null>(null);
-  const [autoDungeon, setAutoDungeon] = useState(false);
-  const autoDungeonRef = useRef<boolean>(false);
- 
-  const pPower = useMemo(() => playerPower(player, prestigeUpgrades["spirit_power"] || 0), [player, prestigeUpgrades]);
- 
-  const inRun = Boolean(running);
- 
-  // Spirit binding sequence state
-  const [spiritBindingState, setSpiritBindingState] = useState<{
-    isActive: boolean;
-    phase: "preparing" | "extracting" | "success" | "failure" | null;
-    progress: number;
-    bossName: string;
-    bossRank: string;
-  }>({
-    isActive: false,
-    phase: null,
-    progress: 0,
-    bossName: "",
-    bossRank: "",
-  });
- 
-  // Level-up celebration state
-  const [levelUpState, setLevelUpState] = useState({
-    isActive: false,
-    newLevel: 0,
-    statPointsGained: 0,
-    showStatAllocation: false,
-  });
- 
-  // Story event modal — shown for rank milestones & first clears
-  const [storyEvent, setStoryEvent] = useState<{
-    title: string;
-    message: string;
-    rankColor?: string;
-  } | null>(null);
-  const pendingStoryEvents = useRef<{ title: string; message: string; rankColor?: string }[]>([]);
-  const [storyQueueTrigger, setStoryQueueTrigger] = useState(0);
- 
-  function queueStoryEvent(event: { title: string; message: string; rankColor?: string }) {
-    pendingStoryEvents.current.push(event);
-    setStoryQueueTrigger(n => n + 1);
-  }
- 
-  // Show pending story events when level-up and spirit binding are both done
-  useEffect(() => {
-    if (levelUpState.isActive || spiritBindingState.isActive || storyEvent) return;
-    if (pendingStoryEvents.current.length > 0) {
-      const next = pendingStoryEvents.current.shift()!;
-      // Small delay so it doesn't flash immediately during transitions
-      const timer = setTimeout(() => setStoryEvent(next), 500);
-      return () => clearTimeout(timer);
-    }
-  }, [levelUpState.isActive, spiritBindingState.isActive, storyEvent, storyQueueTrigger]);
- 
-  // Boss intro sequence — shown before combat starts
-  const [bossIntro, setBossIntro] = useState<{
-    gate: Gate;
-    boss: Boss;
-    dialogue: string;
-  } | null>(null);
- 
-  // Stat progression tracking
-  const [statHistory, setStatHistory] = useState<
-    {
-      level: number;
-      stats: Player["stats"];
-      power: number;
-      timestamp: string;
-    }[]
-  >([]);
- 
-  // Daily login streak state
-  const [loginStreak, setLoginStreak] = useState<{
-    streak: number;
-    lastLogin: string;
-  }>(() => {
-    try {
-      const saved = localStorage.getItem("hunters-path-login-streak");
-      return saved ? JSON.parse(saved) : { streak: 0, lastLogin: "" };
-    } catch { return { streak: 0, lastLogin: "" }; }
-  });
- 
-  const [loginReward, setLoginReward] = useState<{
-    show: boolean;
-    gold: number;
-    exp: number;
-    streak: number;
-    bonus?: string;
-  } | null>(null);
- 
-  // Global error handler for mobile PWA compatibility
-  useEffect(() => {
-    const handleError = (error: ErrorEvent) => {
-      console.error("Global error caught:", error);
-      // Prevent the app from crashing completely
-      error.preventDefault();
-    };
- 
-    const handleUnhandledRejection = (event: PromiseRejectionEvent) => {
-      console.error("Unhandled promise rejection:", event.reason);
-      // Prevent the app from crashing completely
-      event.preventDefault();
-    };
- 
-    window.addEventListener("error", handleError);
-    window.addEventListener("unhandledrejection", handleUnhandledRejection);
- 
-    return () => {
-      window.removeEventListener("error", handleError);
-      window.removeEventListener(
-        "unhandledrejection",
-        handleUnhandledRejection
-      );
-    };
-  }, []);
- 
-  // Daily login reward — runs once on mount
-  useEffect(() => {
-    const timer = setTimeout(() => {
-      const today = new Date().toDateString();
-      const saved = localStorage.getItem("hunters-path-login-streak");
-      const streakData = saved ? JSON.parse(saved) : { streak: 0, lastLogin: "" };
- 
-      if (streakData.lastLogin === today) return; // already claimed today
- 
-      const yesterday = new Date(Date.now() - 86400000).toDateString();
-      const isConsecutive = streakData.lastLogin === yesterday;
-      const newStreak = isConsecutive ? streakData.streak + 1 : 1;
- 
-      const gold = 50 + newStreak * 25;
-      const exp = 100 + newStreak * 50;
-      let bonus: string | undefined;
- 
-      // Apply milestone bonus items
-      if (newStreak >= 30) {
-        bonus = "+5 Prestige Points!";
-        setPlayer(p => ({ ...p, prestigePoints: p.prestigePoints + 5 }));
-      } else if (newStreak >= 14) {
-        bonus = "Epic gear drop!";
-        const epicItem: Item = {
-          id: uid(), name: "Champion's Relic", type: "equipment",
-          rarity: "epic", quality: 90, description: "A powerful artifact earned through dedication",
-          stats: { STR: 5, AGI: 5, INT: 5, VIT: 5, LUCK: 5 },
-          equipmentSlot: "accessory", sellValue: 500,
-        };
-        setPlayer(p => ({ ...p, inv: [...p.inv, epicItem] }));
-      } else if (newStreak >= 7) {
-        bonus = "Rare rune!";
-        const rareRune: Item = {
-          id: uid(), name: "Rune of Power", type: "rune",
-          rarity: "rare", quality: 75, description: "A rare rune filled with magical energy",
-          stats: { STR: 3, AGI: 3, INT: 3 }, sellValue: 150,
-        };
-        setPlayer(p => ({ ...p, inv: [...p.inv, rareRune] }));
-      } else if (newStreak >= 3) {
-        bonus = "Instant Dungeon Key!";
-        setPlayer(p => ({ ...p, keys: p.keys + 1 }));
-      }
- 
-      // Apply EXP and gold
-      setGold(g => g + gold);
-      setPlayer(p => {
-        let newExp = p.exp + exp;
-        let level = p.level; let expNext = p.expNext;
-        let points = p.points; let maxHp = p.maxHp; let maxMp = p.maxMp;
-        while (newExp >= expNext) {
-          newExp -= expNext; level += 1;
-          expNext = Math.floor(expNext * 1.35); points += 5; maxHp += 10; maxMp += 5;
-        }
-        return { ...p, exp: newExp, level, expNext, points, maxHp, maxMp };
-      });
- 
-      // Update streak in state and localStorage
-      const newStreakData = { streak: newStreak, lastLogin: today };
-      setLoginStreak(newStreakData);
-      localStorage.setItem("hunters-path-login-streak", JSON.stringify(newStreakData));
- 
-      // Show modal
-      setLoginReward({ show: true, gold, exp, streak: newStreak, bonus });
-    }, 1500);
- 
-    return () => clearTimeout(timer);
-  }, []); // Only run once on mount
- 
-  // Periodic save for ancillary data (daily quests, statistics, prestige)
-  useEffect(() => {
-    const autoSaveInterval = setInterval(() => {
-      localStorage.setItem("hunters-path-daily", JSON.stringify(daily));
-      localStorage.setItem("hunters-path-stats", JSON.stringify({
-        playerStats, achievements, lastSaved: new Date().toISOString(),
-      }));
-      localStorage.setItem("hunters-path-prestige-upgrades", JSON.stringify(prestigeUpgrades));
-    }, 30000);
- 
-    return () => clearInterval(autoSaveInterval);
-  }, [daily, playerStats, achievements, prestigeUpgrades]);
- 
-  // Auto-trigger stat allocation after level-up celebration
-  useEffect(() => {
-    if (levelUpState.isActive && !levelUpState.showStatAllocation) {
-      const timer = setTimeout(() => {
-        setLevelUpState((prev) => ({ ...prev, showStatAllocation: true }));
-      }, 3000);
-      return () => clearTimeout(timer);
-    }
-  }, [levelUpState.isActive, levelUpState.showStatAllocation]);
- 
-  // Load statistics on component mount
-  useEffect(() => {
-    try {
-      const savedStats = localStorage.getItem("hunters-path-stats");
-      if (savedStats) {
-        const stats = JSON.parse(savedStats);
-        if (stats.playerStats) {
-          setPlayerStats(stats.playerStats);
-        }
-        if (stats.achievements) {
-          setAchievements(stats.achievements);
-        }
-      }
-    } catch (error) {
-      console.error("Failed to load statistics:", error);
-    }
-  }, []);
- 
-  // Sync audioManager with React state
-  useEffect(() => {
-    audioManager.soundEnabled = soundEnabled;
-  }, [soundEnabled]);
-  useEffect(() => {
-    audioManager.musicEnabled = musicEnabled;
-  }, [musicEnabled]);
-  useEffect(() => {
-    audioManager.volume = volume;
-  }, [volume]);
- 
-  // Load game on startup
-  useEffect(() => {
-    const saved = localStorage.getItem("hunters-path-autosave");
-    if (saved) {
-      try {
-        const gameState = JSON.parse(saved);
- 
-        // Migrate old spirits to new format (also initialise missing field)
-        gameState.player.spirits = (gameState.player.spirits || []).map(
-          (spirit: any) => {
-            // If spirit already has new format, return as is
-            if (spirit.rarity && spirit.abilities && spirit.type) {
-              return spirit;
-            }
- 
-            // Migrate old spirit format to new format
-            const type = SPIRIT_TYPES[rand(0, SPIRIT_TYPES.length - 1)];
-            const rarity = "common"; // Default to common for old spirits
-            const availableAbilities = SPIRIT_ABILITIES[type];
-            const abilities = availableAbilities.slice(0, 1); // Give 1 ability to old spirits
- 
-            return {
-              id: spirit.id,
-              name: spirit.name,
-              power: spirit.power,
-              rarity,
-              abilities,
-              level: 1,
-              exp: 0,
-              expToNext: 100,
-              type,
-              description: SPIRIT_DESCRIPTIONS[type],
-            };
-          }
-        );
- 
-        // Strip debug spirits from save data
-        gameState.player.spirits = (gameState.player.spirits || []).filter(
-          (s: any) => !s.id?.startsWith("debug_") && !s.name?.startsWith("Debug ")
-        );
- 
-        // Fix maxHp/maxMp if they're lower than expected for the player's level
-        const expectedMaxHp = 100 + ((gameState.player.level || 1) - 1) * 10;
-        const expectedMaxMp = 50 + ((gameState.player.level || 1) - 1) * 5;
-        if ((gameState.player.maxHp || 0) < expectedMaxHp) {
-          gameState.player.maxHp = expectedMaxHp;
-          gameState.player.hp = Math.min(gameState.player.hp ?? expectedMaxHp, expectedMaxHp);
-        }
-        if ((gameState.player.maxMp || 0) < expectedMaxMp) {
-          gameState.player.maxMp = expectedMaxMp;
-          gameState.player.mp = Math.min(gameState.player.mp ?? expectedMaxMp, expectedMaxMp);
-        }
- 
-        setPlayer(gameState.player);
-        // Migrate old gate names to thematic names
-        const loadedGates = gameState.gates || generateGatePool(gameState.player?.level || 1);
-        for (const g of loadedGates) {
-          if (/^[A-Z]-Rank Gate/.test(g.name)) {
-            const pool = GATE_NAMES[g.rank] ?? GATE_NAMES["E"];
-            g.name = pool[Math.floor(Math.random() * pool.length)];
-          }
-        }
-        setGates(loadedGates);
-        setGold(gameState.gold || 50);
-        setGameTime(gameState.gameTime || initialGameTime());
-        // Load daily state - the daily state initialization will handle the real-time reset logic
-        setDaily(
-          gameState.daily || {
-            active: true,
-            availableQuests: generateDailyQuests(
-              gameState.player?.level || 1,
-              0
-            ),
-            completedQuests: [],
-            completed: false,
-            penaltyArmed: false,
-            questReputation: 0,
-          }
-        );
-        // Calculate offline progress
-        if (gameState.lastSaved) {
-          const msElapsed = Date.now() - new Date(gameState.lastSaved).getTime();
-          const hoursElapsed = Math.min(8, msElapsed / (1000 * 60 * 60));
- 
-          if (hoursElapsed >= 0.1) { // at least 6 minutes offline
-            const level = gameState.player?.level || 1;
-            const offlineExpPerHour = 20 + level * 5;
-            const offlineGoldPerHour = 10 + level * 3;
-            const offlineExp = Math.floor(offlineExpPerHour * hoursElapsed);
-            const offlineGold = Math.floor(offlineGoldPerHour * hoursElapsed);
- 
-            // Apply gold immediately
-            setGold(g => g + offlineGold);
- 
-            // Apply EXP with leveling (inline version of handleLevelGain)
-            setPlayer(p => {
-              let exp = p.exp + offlineExp;
-              let level = p.level;
-              let expNext = p.expNext;
-              let points = p.points;
-              let maxHp = p.maxHp;
-              let maxMp = p.maxMp;
- 
-              while (exp >= expNext) {
-                exp -= expNext;
-                level += 1;
-                expNext = Math.floor(expNext * 1.35);
-                points += 5;
-                maxHp += 10;
-                maxMp += 5;
-              }
- 
-              return { ...p, exp, level, expNext, points, maxHp, maxMp };
-            });
- 
-            setOfflineGains({
-              show: true,
-              exp: offlineExp,
-              gold: offlineGold,
-              hours: hoursElapsed,
-            });
-          }
-        }
- 
-        setLog(["Game loaded from auto-save. Welcome back, Hunter!"]);
-      } catch (error) {
-        console.error("Failed to load auto-save:", error);
-      }
-    }
-  }, []);
- 
-  // Real-time daily quest reset system - check every minute
-  useEffect(() => {
-    const checkDailyReset = () => {
-      const today = new Date().toDateString();
- 
-      setDaily((prevDaily) => {
-        // If it's a new day and we haven't reset yet
-        if (prevDaily.lastResetDate !== today) {
-          setLog((l) => [
-            `New day begins! Daily quests have been refreshed.`,
-            ...l,
-          ]);
- 
-          const newQuests = generateDailyQuests(
-            player.level,
-            prevDaily.questReputation
-          );
- 
-          const newDaily = {
-            active: true, // Auto-start daily quests
-            availableQuests: newQuests,
-            completedQuests: [],
-            completed: false,
-            penaltyArmed: false,
-            questReputation: prevDaily.questReputation, // Preserve reputation
-            lastResetDate: today,
-          };
- 
-          // Save the new daily state
-          localStorage.setItem("hunters-path-daily", JSON.stringify(newDaily));
-          return newDaily;
-        }
-        return prevDaily;
-      });
-    };
- 
-    // Check immediately on mount
-    checkDailyReset();
- 
-    // Then check every minute
-    const interval = setInterval(checkDailyReset, 60000); // 1 minute
- 
-    return () => {
-      clearInterval(interval);
-    };
-  }, [player.level]);
- 
-  // Game time system - advance time every 30 seconds (1 game hour) - simplified without daily reset
-  useEffect(() => {
-    if (timeRef.current) clearInterval(timeRef.current);
-    timeRef.current = setInterval(() => {
-      setGameTime((prevTime) => {
-        const currentRealDate = getCurrentGameDate();
-        const shouldAdvanceDay =
-          currentRealDate !== prevTime.currentDate || Math.random() < 0.1; // 10% chance per hour or real day change
- 
-        if (shouldAdvanceDay) {
-          const newDay = prevTime.day + 1;
-          setLog((l) => [`Day ${newDay} begins.`, ...l]);
- 
-          // Passive experience gain for surviving another day
-          const passiveExp = Math.floor(10 + newDay * 2);
-          setPlayer((p) => ({ ...p, exp: p.exp + passiveExp }));
-          setLog((l) => [`+${passiveExp} EXP for surviving another day`, ...l]);
- 
-          return {
-            day: newDay,
-            currentDate: currentRealDate,
-            lastReset: currentRealDate,
-          };
-        }
-        return prevTime;
-      });
-    }, 30000); // 30 seconds = 1 game hour
- 
-    return () => {
-      if (timeRef.current) clearInterval(timeRef.current);
-    };
-  }, []);
- 
-  // Dungeon tick loop
-  useEffect(() => {
-    if (!inRun) return;
-    if (tickRef.current) clearInterval(tickRef.current);
-    tickRef.current = setInterval(() => {
-      setRunning((prev) => {
-        if (!prev) return prev;
-        let { boss, hpEnemy, tick } = prev;
- 
-        // Apply spirit passive abilities
-        let spiritDmgBonus = 0;
-        let spiritBlockChance = 0;
-        let spiritHealPerTick = 0;
- 
-        for (const spirit of player.spirits) {
-          for (const ability of (spirit.abilities || [])) {
-            if (ability.type !== "passive") continue;
-            switch (ability.id) {
-              case "berserker_rage":
-                if (player.hp < player.maxHp * 0.5) spiritDmgBonus += 0.25;
-                break;
-              case "ethereal_shield":
-                spiritBlockChance += 0.15;
-                break;
-              case "shadow_step":
-                if (tick % 3 === 0) spiritDmgBonus += 0.10;
-                break;
-              case "vitality_aura":
-                spiritHealPerTick += 2;
-                break;
-              case "mana_shield":
-                // Converts some mana damage to reduced physical: handled implicitly by MP upkeep
-                break;
-            }
-          }
-        }
- 
-        // Cap combined block chance at 75% max
-        spiritBlockChance = Math.min(spiritBlockChance, 0.75);
-        // Cap spirit damage bonus at 100% max
-        spiritDmgBonus = Math.min(spiritDmgBonus, 1.0);
- 
-        // Apply dungeon modifiers to combat
-        // Re-look up modifier by ID to restore functions lost during serialization
-        let playerDmgMult = 1 + spiritDmgBonus;
-        let bossDmgMult = 1;
-        for (const mod of (prev.gate.modifiers || [])) {
-          const liveMod = DUNGEON_MODIFIERS.find(m => m.id === mod.id) ?? mod;
-          if (typeof liveMod.applyToCombat !== "function") continue;
-          const result = liveMod.applyToCombat(playerDmgMult, bossDmgMult);
-          playerDmgMult = result.playerDmgMult;
-          bossDmgMult = result.bossDmgMult;
-        }
- 
-        // Player attack - increased base damage (with spirit bonuses and dungeon modifiers)
-        const dmgPlayer = Math.max(
-          1,
-          Math.floor(pPower * 1.2 * playerDmgMult - boss.def * 0.3 + rand(0, 6))
-        );
-        const oldHpEnemy = hpEnemy;
-        hpEnemy = clamp(hpEnemy - dmgPlayer, 0, boss.maxHp);
- 
-        // Boss attack - slightly reduced boss damage (with spirit block chance and dungeon modifiers)
-        const blocked = spiritBlockChance > 0 && Math.random() < spiritBlockChance;
-        const dmgBoss = blocked ? 0 : Math.max(
-          0,
-          Math.floor(boss.atk * 0.8 * bossDmgMult - player.stats.VIT * 0.7 + rand(0, 3))
-        );
-        const oldHp = player.hp;
-        let newHp = clamp(player.hp - dmgBoss, 0, player.maxHp);
- 
-        // Spirit healing
-        if (spiritHealPerTick > 0 && newHp > 0) {
-          const healAmount = Math.min(spiritHealPerTick, player.maxHp - newHp);
-          if (healAmount > 0) {
-            newHp = Math.min(newHp + healAmount, player.maxHp);
-            addDamageNumber(healAmount, "heal", "player");
-          }
-        }
- 
-        // Trigger visual effects, sounds, haptics, particles, and floating damage numbers
-        if (dmgPlayer > 0) {
-          triggerVisualEffect("screenShake");
-          playSound("attack");
-          const isCrit = dmgPlayer > pPower * 1.5;
-          if (isCrit) {
-            triggerVisualEffect("criticalHit");
-            playSound("critical");
-            hapticHeavy();
-            triggerParticles("critical-hit", "75%", "40%");
-            addDamageNumber(dmgPlayer, "critical", "enemy");
-          } else {
-            hapticMedium();
-            triggerParticles("combat-hit", "75%", "40%");
-            addDamageNumber(dmgPlayer, "damage", "enemy");
-          }
-        }
-        if (dmgBoss > 0) {
-          triggerVisualEffect("damageFlash");
-          playSound("damage");
-          hapticWarning();
-          triggerParticles("combat-hit", "25%", "40%");
-          addDamageNumber(dmgBoss, "damage", "player");
-        } else {
-          playSound("block");
-          addDamageNumber(0, "block", "player");
-        }
- 
-        // MP upkeep
-        const upkeep = spiritUpkeep(player);
-        const newMp = clamp(player.mp - upkeep, 0, player.maxMp);
- 
-        // Fatigue gain
-        const fatigueGainMult = 1 - (prestigeUpgrades["fatigue_resist"] || 0) * 0.05;
-        const newFatigue = clamp(player.fatigue + 0.5 * fatigueGainMult, 0, 100);
- 
-        // Add combat log entries
-        const rank = prev.gate?.rank ?? "E";
-        const oldBossHpPct = boss.maxHp > 0 ? (oldHpEnemy / boss.maxHp) * 100 : 0;
-        const newBossHpPct = boss.maxHp > 0 ? (hpEnemy / boss.maxHp) * 100 : 0;
-        setCombatLog((log) => {
-          const newEntries: string[] = [];
-          const isCrit = dmgPlayer > pPower * 1.5;
- 
-          // Player attack
-          if (dmgPlayer > 0) {
-            if (isCrit) {
-              newEntries.push(pick(CRIT_MSGS)(dmgPlayer));
-            } else {
-              newEntries.push(pick(PLAYER_ATTACK_MSGS)(dmgPlayer));
-            }
-          }
- 
-          // Boss attack
-          if (dmgBoss > 0) {
-            const rankMsgs = BOSS_ATTACK_MSGS[rank] ?? BOSS_ATTACK_MSGS["E"];
-            newEntries.push(pick(rankMsgs)(boss.name, dmgBoss));
-          } else {
-            newEntries.push(pick(BOSS_BLOCK_MSGS)(boss.name));
-          }
- 
-          // Boss HP phase transitions
-          for (const threshold of [75, 50, 25]) {
-            if (oldBossHpPct > threshold && newBossHpPct <= threshold) {
-              newEntries.push(pick(BOSS_PHASE_MSGS[String(threshold)]));
-            }
-          }
- 
-          // Spirit ability procs (throttled to avoid spam)
-          if (spiritDmgBonus > 0 && tick % 3 === 0) {
-            // Find which spirit abilities are active for flavor
-            for (const spirit of player.spirits) {
-              for (const ab of (spirit.abilities || [])) {
-                if (ab.type !== "passive") continue;
-                if (ab.id === "berserker_rage" && player.hp < player.maxHp * 0.5) {
-                  newEntries.push(pick(SPIRIT_ABILITY_MSGS["berserker_rage"]));
-                  break;
-                }
-                if (ab.id === "shadow_step" && tick % 3 === 0) {
-                  newEntries.push(pick(SPIRIT_ABILITY_MSGS["shadow_step"]));
-                  break;
-                }
-              }
-            }
-          }
-          if (blocked) {
-            newEntries.push(pick(SPIRIT_ABILITY_MSGS["ethereal_shield"]));
-          }
-          if (spiritHealPerTick > 0 && tick % 3 === 0) {
-            newEntries.push(pick(SPIRIT_ABILITY_MSGS["vitality_aura"]));
-          }
- 
-          // Keep only last 8 entries
-          return [...log, ...newEntries].slice(-8);
-        });
- 
-        setPlayer((pp) => ({
-          ...pp,
-          hp: newHp,
-          mp: newMp,
-          fatigue: newFatigue,
-        }));
- 
-        if (hpEnemy <= 0) {
-          // Victory
-          clearInterval(tickRef.current!);
-          playSound("victory");
-          playMusic("victory_music", false);
-          hapticSuccess();
- 
-          const { exp: rawExp, gold: rawGold } = gainExpGoldFromGate(prev.gate);
-          const expBoost = 1 + (prestigeUpgrades["exp_boost"] || 0) * 0.05;
-          const goldBoostMult = 1 + (prestigeUpgrades["gold_boost"] || 0) * 0.05;
- 
-          // Apply dungeon modifiers to rewards
-          // Re-look up modifier by ID to restore functions lost during serialization
-          let expMult = expBoost;
-          let goldMult = goldBoostMult;
-          for (const mod of (prev.gate.modifiers || [])) {
-            const liveMod = DUNGEON_MODIFIERS.find(m => m.id === mod.id) ?? mod;
-            if (typeof liveMod.applyToRewards !== "function") continue;
-            const result = liveMod.applyToRewards(expMult, goldMult);
-            expMult = result.expMult;
-            goldMult = result.goldMult;
-          }
-          const exp = Math.floor(rawExp * expMult);
-          const goldGain = Math.floor(rawGold * goldMult);
-          const drop = rollDrop(prev.gate);
-          const drops = drop ? [drop] : [];
- 
-          // Track quest progress
-          trackQuestProgress("monster_defeated");
-          if (drop) {
-            trackQuestProgress("item_gained");
-          }
-          // Check if player took no damage for challenge quests
-          if (player.hp === player.maxHp) {
-            trackQuestProgress("gate_completed_no_damage");
-          }
- 
-          // Show combat result screen first
-          setCombatResult({
-            victory: true,
-            gate: prev.gate,
-            boss: boss,
-            expGained: exp,
-            goldGained: goldGain,
-            drops,
-            combatLog: [...combatLog, `Victory! ${boss.name} is defeated! 🎉`],
-          });
- 
-          // Apply rewards
-          setGold((g) => g + goldGain);
-          setLog((l) => [
-            `Cleared ${prev.gate.name}! +${fmt(exp)} EXP, +${fmt(goldGain)}₲`,
-            ...l,
-          ]);
-          handleLevelGain(exp);
- 
-          // Apply drops
-          if (drop) {
-            if (drop.type === "key")
-              setPlayer((pp) => ({ ...pp, keys: pp.keys + 1 }));
-            else setPlayer((pp) => ({ ...pp, inv: [...pp.inv, drop] }));
-            setLog((l) => [`Found: ${drop.name}`, ...l]);
-          }
- 
-          // Heal to full on victory
-          setPlayer((pp) => ({
-            ...pp,
-            hp: pp.maxHp,
-            mp: Math.min(pp.mp + Math.floor(pp.maxMp * 0.3), pp.maxMp),
-          }));
- 
-          // First-clear celebration — queue story modal for new rank clears
-          const rank = prev.gate.rank;
-          const alreadyCleared = player.clearedRanks ?? [];
-          if (!alreadyCleared.includes(rank)) {
-            setPlayer((pp) => ({
-              ...pp,
-              clearedRanks: [...(pp.clearedRanks ?? []), rank],
-            }));
-            const firstClear = FIRST_CLEAR_TEXT[rank];
-            if (firstClear) {
-              queueStoryEvent({ title: firstClear.title, message: firstClear.message });
-            }
-          }
- 
-          // Update statistics
-          updateStats(true, exp, goldGain, prev.gate.rank);
-          checkAchievements();
- 
-          // Automatically attempt spirit binding with visual sequence
-          const bindBoost = (prestigeUpgrades["bind_chance"] || 0) * 0.03;
-          const extractionChance = calcExtractionChance(
-            player,
-            prev.gate.rankIdx
-          ) + bindBoost;
-          if (Math.random() < extractionChance) {
-            // Start the visual extraction sequence
-            startSpiritBindingSequence(
-              boss.name,
-              prev.gate.rank,
-              prev.gate.power
-            );
-          }
- 
-          // Keep the combat UI visible - don't set running to null yet
-          // Remove cleared gate and potentially refresh pool
-          setGates((gs) => {
-            const filtered = gs.filter((g) => g.id !== prev.gate.id);
- 
-            // If we have fewer than 3 gates total, generate a new pool
-            if (filtered.length < 3) {
-              return generateGatePool(player.level);
-            }
- 
-            return filtered;
-          });
-          return null;
-        }
-        if (newHp <= 0) {
-          // Defeat
-          clearInterval(tickRef.current!);
-          playSound("defeat");
-          playMusic("defeat_music", false);
-          hapticWarning();
- 
-          // Show combat result screen
-          setCombatResult({
-            victory: false,
-            gate: prev.gate,
-            boss: boss,
-            expGained: 0,
-            goldGained: -10,
-            drops: [],
-            combatLog: [...combatLog, `Defeat! Hunter falls in battle... 💀`],
-          });
- 
-          setLog((l) => [
-            `You were defeated in ${prev.gate.name}. Rest and try again.`,
-            ...l,
-          ]);
-          // defeat penalty: lose some gold; recover to 30% HP
-          setGold((g) => Math.max(0, g - 10));
-          setPlayer((pp) => ({
-            ...pp,
-            hp: Math.max(5, Math.floor(pp.maxHp * 0.3)),
-            mp: Math.min(pp.mp + Math.floor(pp.maxMp * 0.2), pp.maxMp),
-          }));
- 
-          // Update statistics
-          updateStats(false, 0, -10, prev.gate.rank);
- 
-          // Keep the combat UI visible - don't set running to null yet
-          return null;
-        }
- 
-        // Continue ticking
-        return { ...prev, hpEnemy, tick: tick + 1 };
-      });
-    }, 2500); // Slowed down from 1500ms to 2500ms for much better visibility
-    return () => {
-      if (tickRef.current) clearInterval(tickRef.current);
-    };
-  }, [inRun, pPower, player.stats.VIT, player.maxHp, player.mp, player.hp, player.spirits]);
- 
-  function handleLevelGain(addExp: number) {
-    setPlayer((p) => {
-      let exp = p.exp + addExp;
-      let level = p.level;
-      let expNext = p.expNext;
-      let points = p.points;
-      let maxHp = p.maxHp;
-      let maxMp = p.maxMp;
-      let leveledUp = false;
-      let levelsGained = 0;
- 
-      while (exp >= expNext) {
-        exp -= expNext;
-        level += 1;
-        leveledUp = true;
-        levelsGained += 1;
-        expNext = Math.floor(expNext * 1.35);
-        points += 5;
-        maxHp += 10;
-        maxMp += 5;
- 
-        logPush(`Level Up! Welcome to level ${level}. +5 stat points!`);
-        playSound("level_up");
-        hapticHeavy();
-        triggerParticles("level-up", "50%", "50%");
- 
-        // Check for rank milestone story event — queue modal to show after level-up
-        const milestone = RANK_MILESTONES.find(m => m.level === level);
-        if (milestone) {
-          logPush(`--- ${milestone.title} ---`);
-          logPush(milestone.message);
-          queueStoryEvent({ title: milestone.title, message: milestone.message, rankColor: milestone.color });
-        }
-      }
- 
-      // If player leveled up, refresh gates to unlock new tiers
-      if (leveledUp) {
-        // Record stat history before level up
-        setStatHistory((prev) => [
-          ...prev,
-          {
-            level: p.level,
-            stats: p.stats,
-            power: playerPower(p),
-            timestamp: new Date().toISOString(),
-          },
-        ]);
- 
-        // Trigger level-up celebration
-        setLevelUpState({
-          isActive: true,
-          newLevel: level,
-          statPointsGained: levelsGained * 5,
-          showStatAllocation: false,
-        });
- 
-        // Trigger visual effects
-        triggerVisualEffect("levelUp");
- 
-        setTimeout(() => {
-          setGates(generateGatePool(level));
-          logPush(
-            `New gates appeared! Higher tier dungeons are now available.`
-          );
-        }, 1000);
-      }
- 
-      return {
-        ...p,
-        exp,
-        level,
-        expNext,
-        points,
-        maxHp,
-        maxMp,
-        hp: Math.max(p.hp, Math.floor(maxHp * 0.6)),
-        mp: Math.max(p.mp, Math.floor(maxMp * 0.5)),
-      };
-    });
-  }
- 
-  function logPush(msg: string) {
-    setLog((l) => [msg, ...l].slice(0, 120));
-  }
- 
-  function handleRebirth() {
-    const earnedPoints = Math.floor(
-      player.level * 10 * (1 + player.rebirths * 0.5)
-    );
-    const fresh = createInitialPlayer();
-    setPlayer({
-      ...fresh,
-      level: player.level,
-      exp: 0,
-      expNext: player.expNext,
-      stats: { ...player.stats },
-      spirits: [...player.spirits],
-      equipment: { ...player.equipment },
-      inv: [],
-      keys: 0,
-      fatigue: 0,
-      hp: player.maxHp,
-      maxHp: player.maxHp,
-      mp: player.maxMp,
-      maxMp: player.maxMp,
-      points: player.points,
-      rebirths: player.rebirths + 1,
-      prestigePoints: player.prestigePoints + earnedPoints,
-    });
-    const startGold = 50 + (prestigeUpgrades["start_gold"] || 0) * 100;
-    setGold(startGold);
-    setGates(generateGatePool(player.level));
-    setRebirthModalOpen(false);
-    setLog((prev) => [
-      `⚡ REBIRTH ${player.rebirths + 1}! +${earnedPoints} Prestige Points. Power bonus: +${(player.rebirths + 1) * 15}%`,
-      ...prev,
-    ]);
-  }
- 
-  function buyPrestigeUpgrade(upgradeId: string) {
-    const upgrade = PRESTIGE_UPGRADES.find(u => u.id === upgradeId);
-    if (!upgrade) return;
-    const currentLevel = prestigeUpgrades[upgradeId] || 0;
-    if (currentLevel >= upgrade.maxLevel) {
-      logPush(`${upgrade.name} is already at max level!`);
-      return;
-    }
-    const cost = upgrade.costPer * (currentLevel + 1);
-    if (player.prestigePoints < cost) {
-      logPush(`Not enough Prestige Points. Need ${cost} PP.`);
-      return;
-    }
-    setPlayer(p => ({ ...p, prestigePoints: p.prestigePoints - cost }));
-    setPrestigeUpgrades(prev => {
-      const next = { ...prev, [upgradeId]: (prev[upgradeId] || 0) + 1 };
-      localStorage.setItem("hunters-path-prestige-upgrades", JSON.stringify(next));
-      return next;
-    });
-    logPush(`Upgraded ${upgrade.name} to level ${currentLevel + 1}!`);
-  }
- 
-  // Simple statistics tracking functions
-  function updateStats(
-    victory: boolean,
-    expGained: number,
-    goldGained: number,
-    gateRank: string
-  ) {
-    setPlayerStats((stats) => {
-      const newStats = { ...stats };
- 
-      if (victory) {
-        newStats.totalGatesCompleted += 1;
-      } else {
-        newStats.totalGatesFailed += 1;
-      }
- 
-      newStats.totalExpGained += expGained;
-      newStats.totalGoldGained += goldGained;
- 
-      // Update highest gate rank
-      const rankOrder = ["E", "D", "C", "B", "A", "S"];
-      const currentRankIdx = rankOrder.indexOf(stats.highestGateRank);
-      const newRankIdx = rankOrder.indexOf(gateRank);
-      if (newRankIdx > currentRankIdx) {
-        newStats.highestGateRank = gateRank;
-      }
- 
-      newStats.lastUpdated = new Date().toISOString();
-      return newStats;
-    });
-  }
- 
-  function recordSpiritBinding() {
-    setPlayerStats((stats) => ({
-      ...stats,
-      totalSpiritsBound: stats.totalSpiritsBound + 1,
-      lastUpdated: new Date().toISOString(),
-    }));
-  }
- 
-  function checkAchievements() {
-    const newAchievements: Achievement[] = [];
- 
-    // First victory achievement
-    if (
-      playerStats.totalGatesCompleted === 1 &&
-      achievements &&
-      !achievements.some((a) => a.name === "First Blood")
-    ) {
-      newAchievements.push({
-        id: uid(),
-        name: "First Blood",
-        description: "Win your first gate battle",
-        unlockedAt: new Date().toISOString(),
-      });
-    }
- 
-    // Gate master achievement
-    if (
-      playerStats.totalGatesCompleted === 10 &&
-      achievements &&
-      !achievements.some((a) => a.name === "Gate Master")
-    ) {
-      newAchievements.push({
-        id: uid(),
-        name: "Gate Master",
-        description: "Complete 10 gates",
-        unlockedAt: new Date().toISOString(),
-      });
-    }
- 
-    // Spirit caller achievement
-    if (
-      playerStats.totalSpiritsBound === 1 &&
-      achievements &&
-      !achievements.some((a) => a.name === "Spirit Caller")
-    ) {
-      newAchievements.push({
-        id: uid(),
-        name: "Spirit Caller",
-        description: "Bind your first spirit",
-        unlockedAt: new Date().toISOString(),
-      });
-    }
- 
-    // Add new achievements
-    if (newAchievements.length > 0) {
-      setAchievements((current) => [...current, ...newAchievements]);
- 
-      // Show achievement notifications
-      newAchievements.forEach((achievement) => {
-        logPush(`🏆 Achievement Unlocked: ${achievement.name}!`);
-      });
-    }
-  }
- 
-  // Spirit binding sequence functions
-  function startSpiritBindingSequence(
-    bossName: string,
-    bossRank: string,
-    gatePower: number
-  ) {
-    setSpiritBindingState({
-      isActive: true,
-      phase: "preparing",
-      progress: 0,
-      bossName,
-      bossRank,
-    });
- 
-    // Play extraction start sound
-    playSound("extraction_start");
- 
-    // Phase 1: Preparing (2 seconds)
-    setTimeout(() => {
-      setSpiritBindingState((prev) => ({
-        ...prev,
-        phase: "extracting",
-        progress: 0,
-      }));
- 
-      // Play extraction loop sound
-      playSound("extraction_loop");
- 
-      // Phase 2: Extracting (3 seconds with progress animation)
-      const extractionInterval = setInterval(() => {
-        setSpiritBindingState((prev) => {
-          if (prev.progress >= 100) {
-            clearInterval(extractionInterval);
-            return prev;
-          }
-          return { ...prev, progress: prev.progress + 2 };
-        });
-      }, 60); // Update every 60ms for smooth animation
- 
-      // After 3 seconds, determine success/failure
-      setTimeout(() => {
-        const chance = calcExtractionChance(player, RANKS.indexOf(bossRank as BossRank));
-        const success = Math.random() < chance;
- 
-        setSpiritBindingState((prev) => ({
-          ...prev,
-          phase: success ? "success" : "failure",
-          progress: 100,
-        }));
- 
-        // Play success/failure sound + haptics + particles
-        if (success) {
-          playSound("extraction_success");
-          hapticSuccess();
-          triggerParticles("spirit-bind", "50%", "50%");
- 
-          // Create the spirit and update player state
-          const spiritBound = createSpirit(
-            gatePower,
-            RANKS.indexOf(bossRank as BossRank)
-          );
- 
-          setPlayer((pp) => ({
-            ...pp,
-            spirits: [...pp.spirits, spiritBound],
-          }));
- 
-          recordSpiritBinding();
-          setLog((l) => [
-            `${spiritBound.rarity.toUpperCase()} spirit bound: ${
-              spiritBound.name
-            }! (${spiritBound.type})`,
-            ...l,
-          ]);
- 
-          // Update combat result with the bound spirit
-          setCombatResult((prev) =>
-            prev
-              ? {
-                  ...prev,
-                  spiritBound,
-                }
-              : prev
-          );
-        } else {
-          playSound("extraction_failure");
-          hapticWarning();
-        }
- 
-        // End sequence after 2 seconds
-        setTimeout(() => {
-          setSpiritBindingState({
-            isActive: false,
-            phase: null,
-            progress: 0,
-            bossName: "",
-            bossRank: "",
-          });
-        }, 2000);
-      }, 3000);
-    }, 2000);
-  }
- 
-  function getExtractionSequenceText() {
-    const { phase, bossName, progress } = spiritBindingState;
- 
-    switch (phase) {
-      case "preparing":
-        return {
-          title: "Spirit Binding Initiated",
-          subtitle: `Preparing to bind spirit from ${bossName}...`,
-          description: "Gathering magical energy and focusing your will...",
-        };
-      case "extracting":
-        return {
-          title: "Binding Spirit",
-          subtitle: `${progress}% Complete`,
-          description: "The spirit essence is being drawn forth...",
-        };
-      case "success":
-        return {
-          title: "Extraction Successful!",
-          subtitle: `${bossName}'s spirit joins you!`,
-          description: "A new spirit ally has been bound to your will.",
-        };
-      case "failure":
-        return {
-          title: "Extraction Failed",
-          subtitle: "The spirit crumbles to dust...",
-          description: "The essence was too weak or your focus wavered.",
-        };
-      default:
-        return { title: "", subtitle: "", description: "" };
-    }
-  }
- 
-  // Quest Progress Tracking Functions
-  function trackQuestProgress(action: string, count: number = 1) {
-    if (!daily.active || daily.completed) return;
- 
-    daily.availableQuests.forEach((quest) => {
-      if (daily.completedQuests.includes(quest.id)) return; // Skip already completed quests
- 
-      let shouldProgress = false;
- 
-      switch (quest.type) {
-        case "combat":
-          if (action === "monster_defeated") shouldProgress = true;
-          break;
-        case "exploration":
-          if (action === "gate_entered") shouldProgress = true;
-          break;
-        case "collection":
-          if (action === "item_gained") shouldProgress = true;
-          break;
-        case "skill":
-          if (action === "potion_used" || action === "rune_used")
-            shouldProgress = true;
-          break;
-        case "challenge":
-          if (action === "gate_completed_no_damage") shouldProgress = true;
-          break;
-      }
- 
-      if (shouldProgress) {
-        progressDaily(quest.id);
-      }
-    });
-  }
- 
-  function startGate(g: Gate) {
-    if (inRun || bossIntro) return;
- 
-    // Track gate entry for exploration quests
-    trackQuestProgress("gate_entered");
- 
-    const dialogue = BOSS_DIALOGUE[g.rank];
-    const line = dialogue ? pick(dialogue) : "";
- 
-    // Play gate entry sound + haptic rumble
-    playSound("gate_enter");
-    hapticRumble();
-    logPush(`Entered ${g.name} (${g.rank}-Rank)`);
- 
-    // Skip boss intro during auto-dungeon — go straight to combat
-    if (autoDungeonRef.current) {
-      beginCombat(g, line);
-      return;
-    }
- 
-    // Show boss intro sequence first
-    setBossIntro({ gate: g, boss: g.boss, dialogue: line });
- 
-    // Auto-proceed to combat after 2.5s
-    setTimeout(() => {
-      beginCombat(g, line);
-    }, 2500);
-  }
- 
-  const beginCombatRef = useRef(false);
-  function beginCombat(g: Gate, dialogueLine: string) {
-    // Guard against double-call (timeout + tap)
-    if (beginCombatRef.current) return;
-    beginCombatRef.current = true;
-    setBossIntro(null);
- 
-    setRunning({
-      gate: g,
-      boss: g.boss,
-      hpEnemy: g.boss.hp,
-      tick: 0,
-    });
-    const initLog = dialogueLine ? [dialogueLine] : [];
-    setCombatLog(initLog);
-    setCombatResult(null);
- 
-    // Clear any existing spirit binding state
-    setSpiritBindingState({
-      isActive: false,
-      phase: null,
-      progress: 0,
-      bossName: "",
-      bossRank: "",
-    });
- 
-    // Reset guard after a tick
-    setTimeout(() => { beginCombatRef.current = false; }, 100);
-  }
- 
-  function skipBossIntro() {
-    if (!bossIntro) return;
-    beginCombat(bossIntro.gate, bossIntro.dialogue);
-  }
- 
-  function rest() {
-    if (inRun) return;
-    const heal = Math.floor(player.maxHp * 0.6);
-    const mp = Math.floor(player.maxMp * 0.5);
-    setPlayer((p) => ({
-      ...p,
-      hp: clamp(p.hp + heal, 0, p.maxHp),
-      mp: clamp(p.mp + mp, 0, p.maxMp),
-      fatigue: clamp(p.fatigue - 20, 0, 100),
-    }));
-    logPush("You took a rest. Deus reficit — you feel renewed.");
-    playSound("rest");
-    playMusic("ambient_music");
-  }
- 
-  function allocate(stat: keyof Player["stats"], amount: number = 1) {
-    if (player.points <= 0) return;
-    const actual = Math.min(amount, player.points);
-    setPlayer((p) => ({
-      ...p,
-      points: p.points - actual,
-      stats: { ...p.stats, [stat]: p.stats[stat] + actual },
-    }));
-  }
- 
-  function progressDaily(id: string) {
-    if (!daily.active || daily.completed) return;
- 
-    setDaily((d) => {
-      const updatedQuests = d.availableQuests.map((t) =>
-        t.id === id ? { ...t, have: clamp(t.have + 1, 0, t.need) } : t
-      );
- 
-      // Check if any quests are completed
-      const completedQuests = updatedQuests.filter(
-        (q) => !d.completedQuests.includes(q.id) && q.have >= q.need
-      );
- 
-      const newCompletedQuests = [...d.completedQuests];
-      let totalExpGained = 0;
-      let totalGoldGained = 0;
-      let bonusItems: Item[] = [];
-      let bonusStatPoints = 0;
- 
-      completedQuests.forEach((quest) => {
-        newCompletedQuests.push(quest.id);
-        totalExpGained += quest.expReward;
-        totalGoldGained += quest.goldReward;
- 
-        if (quest.bonusRewards) {
-          if (quest.bonusRewards.items) {
-            bonusItems.push(...quest.bonusRewards.items);
-          }
-          if (quest.bonusRewards.statPoints) {
-            bonusStatPoints += quest.bonusRewards.statPoints;
-          }
-        }
- 
-        // Log individual quest completion
-        logPush(
-          `Quest completed: ${quest.name}! +${quest.expReward} EXP, +${quest.goldReward} Gold`
-        );
-        if (quest.bonusRewards) {
-          if (quest.bonusRewards.statPoints) {
-            logPush(
-              `+${quest.bonusRewards.statPoints} Stat Points from epic quest!`
-            );
-          }
-          if (quest.bonusRewards.items) {
-            logPush(`Received ${quest.bonusRewards.items.length} bonus items!`);
-          }
-        }
-      });
- 
-      // Check if all quests are completed
-      const allCompleted = updatedQuests.every((quest) =>
-        newCompletedQuests.includes(quest.id)
-      );
- 
-      if (allCompleted && !d.completed) {
-        // Award reputation points
-        const reputationGain = Math.floor(totalExpGained / 10);
- 
-        // Update player stats
-        setPlayer((p) => ({
-          ...p,
-          exp: p.exp + totalExpGained,
-          points: p.points + bonusStatPoints,
-          inv: [...p.inv, ...bonusItems],
-        }));
- 
-        setGold((g) => g + totalGoldGained);
- 
-        logPush(`All daily quests completed! +${reputationGain} Reputation`);
- 
-        return {
-          ...d,
-          availableQuests: updatedQuests,
-          completedQuests: newCompletedQuests,
-          completed: true,
-          completedDate: getCurrentGameDate(),
-          questReputation: d.questReputation + reputationGain,
-        };
-      }
- 
-      // Apply rewards for individual quest completions
-      if (completedQuests.length > 0) {
-        setPlayer((p) => ({
-          ...p,
-          exp: p.exp + totalExpGained,
-          points: p.points + bonusStatPoints,
-          inv: [...p.inv, ...bonusItems],
-        }));
- 
-        setGold((g) => g + totalGoldGained);
-      }
- 
-      return {
-        ...d,
-        availableQuests: updatedQuests,
-        completedQuests: newCompletedQuests,
-      };
-    });
-  }
- 
-  function forfeitDaily() {
-    if (!daily.active) return;
- 
-    setDaily({
-      active: false,
-      availableQuests: [],
-      completedQuests: [],
-      completed: false,
-      penaltyArmed: true,
-      questReputation: daily.questReputation,
-    });
- 
-    logPush("Daily quests forfeited.");
-  }
- 
-  function applyPenaltyZone() {
-    // In the source logic, failure triggers a Penalty Zone. We'll simulate a harsh debuff.
-    setPlayer((p) => ({
-      ...p,
-      hp: Math.max(1, Math.floor(p.maxHp * 0.1)),
-      fatigue: clamp(p.fatigue + 25, 0, 100),
-    }));
-    logPush(
-      "Penalty Zone: You pushed boulders for hours. HP to a sliver; Fatigue up."
-    );
-  }
- 
-  function tryExtraction(bossRankIdx: number) {
-    const chance = calcExtractionChance(player, bossRankIdx);
-    const cost = 10;
-    if (player.mp < cost) {
-      logPush("Not enough MP to attempt extraction.");
-      return;
-    }
- 
-    // Get boss info for the sequence
-    const bossRank = RANKS[bossRankIdx];
-    const bossName = running?.boss.name || "Unknown Boss";
- 
-    // Start the visual extraction sequence
-    startSpiritBindingSequence(
-      bossName,
-      bossRank,
-      running?.gate.power || 100
-    );
- 
-    // Consume MP immediately
-    setPlayer((p) => ({ ...p, mp: Math.max(0, p.mp - cost) }));
- 
-    // The actual extraction logic will be handled in the sequence
-    // We'll update the player and stats when the sequence completes
-    setTimeout(() => {
-      if (Math.random() < chance) {
-        const pow = Math.floor(
-          5 + player.stats.INT * 0.8 + bossRankIdx * 6 + rand(0, 8)
-        );
-        const s = createSpirit(pow, bossRankIdx);
-        setPlayer((p) => ({ ...p, spirits: [...p.spirits, s] }));
-        logPush(
-          `${s.rarity.toUpperCase()} spirit bound: ${s.name}! (${
-            s.type
-          }) - +${s.power} power`
-        );
- 
-        // Update statistics
-        recordSpiritBinding();
-        checkAchievements();
-      } else {
-        logPush("Extraction failed. The shade crumbles to dust.");
-      }
-    }, 7000); // Wait for the full sequence to complete
-  }
- 
-  // Test function for spirit binding (for easier testing)
-  function testSpiritBinding() {
-    // Function removed for production
-  }
- 
-  function usePotion(itemId: string) {
-    const idx = player.inv.findIndex((i) => i.id === itemId);
-    if (idx === -1) return;
-    const item = player.inv[idx];
-    if (item.type !== "potion") return;
- 
-    const oldHp = player.hp;
-    const oldMp = player.mp;
- 
-    // Use the potion's own HP stat if available; fall back to 50% maxHp
-    const hpHeal = item.stats?.HP ?? Math.floor(player.maxHp * 0.5);
-    const mpHeal = Math.floor(player.maxMp * 0.3);
- 
-    setPlayer((p) => ({
-      ...p,
-      hp: clamp(p.hp + hpHeal, 0, p.maxHp),
-      mp: clamp(p.mp + mpHeal, 0, p.maxMp),
-      inv: p.inv.filter((i: Item) => i.id !== itemId),
-    }));
- 
-    // Trigger heal visual effect + particles
-    triggerVisualEffect("healFlash");
-    playSound("heal");
-    triggerParticles("heal", "25%", "40%");
- 
-    // Add combat log entry if in combat
-    if (inRun && running) {
-      setCombatLog((log) => [
-        ...log.slice(-7),
-        `Hunter uses a potion! +${hpHeal} HP, +${mpHeal} MP`,
-      ]);
-    }
- 
-    logPush(
-      "You used a potion. 体力回復 (tairyoku kaifuku): vitality restored."
-    );
- 
-    // Progress Resource Manager quest
-    if (daily.active && !daily.completed) {
-      const resourceQuest = daily.availableQuests.find(
-        (q) => q.type === "skill" && q.name.includes("Resource Manager")
-      );
-      if (resourceQuest) {
-        progressDaily(resourceQuest.id);
-      }
-    }
-  }
- 
-  function useRune(itemId: string) {
-    const idx = player.inv.findIndex((i) => i.id === itemId);
-    if (idx === -1) return;
-    const item = player.inv[idx];
-    if (item.type !== "rune") return;
- 
-    // Parse rune name to get rank and type
-    const runeName = item.name;
-    const rankMatch = runeName.match(/([A-Z])-grade/);
-    const typeMatch = runeName.match(/([A-Z]+)-grade/);
- 
-    if (!rankMatch || !typeMatch) {
-      logPush("Invalid rune format. Cannot use this rune.");
-      return;
-    }
- 
-    const rank = rankMatch[1];
-    const rankIdx = RANKS.indexOf(rank as BossRank);
-    if (rankIdx === -1) {
-      logPush("Unknown rune rank. Cannot use this rune.");
-      return;
-    }
- 
-    // Determine stat type from rune name
-    let statType: keyof Player["stats"] | null = null;
-    if (runeName.includes("STR")) statType = "STR";
-    else if (runeName.includes("AGI")) statType = "AGI";
-    else if (runeName.includes("INT")) statType = "INT";
-    else if (runeName.includes("VIT")) statType = "VIT";
-    else if (runeName.includes("LUCK")) statType = "LUCK";
-    else {
-      // Random stat if not specified
-      const statKeys: (keyof Player["stats"])[] = [
-        "STR",
-        "AGI",
-        "INT",
-        "VIT",
-        "LUCK",
-      ];
-      statType = statKeys[rand(0, statKeys.length - 1)];
-    }
- 
-    // Calculate stat boost based on rank
-    const baseBoost = rankIdx + 1; // E=1, D=2, C=3, B=4, A=5, S=6
-    const variance = rand(-1, 1); // Small variance
-    const statBoost = Math.max(1, baseBoost + variance);
- 
-    // Apply stat boost
-    setPlayer((p) => ({
-      ...p,
-      stats: {
-        ...p.stats,
-        [statType!]: p.stats[statType!] + statBoost,
-      },
-      inv: p.inv.filter((i: Item) => i.id !== itemId),
-    }));
- 
-    logPush(
-      `Used ${item.name}! +${statBoost} ${statType} permanently. 魔力強化 (maryoku kyōka): magical enhancement.`
-    );
-    playSound("rune_use");
- 
-    // Progress Resource Manager quest
-    if (daily.active && !daily.completed) {
-      const resourceQuest = daily.availableQuests.find(
-        (q) => q.type === "skill" && q.name.includes("Resource Manager")
-      );
-      if (resourceQuest) {
-        progressDaily(resourceQuest.id);
-      }
-    }
-  }
- 
-  function useKey() {
-    if (player.keys <= 0 || inRun) return;
-    const rankIdx = clamp(rand(1, 3), 0, RANKS.length - 1);
-    const g = makeGate(rankIdx);
-    setPlayer((p) => ({ ...p, keys: p.keys - 1 }));
-    startGate({ ...g, name: `Instant Dungeon: ${g.name}` });
-  }
- 
-  function dismissCombatResult() {
-    setCombatResult(null);
-    setRunning(null); // Clear the combat state
-    setCombatLog([]); // Clear the combat log
-  }
- 
-  function triggerVisualEffect(effect: keyof typeof visualEffects) {
-    setVisualEffects((prev) => ({ ...prev, [effect]: true }));
-    setTimeout(() => {
-      setVisualEffects((prev) => ({ ...prev, [effect]: false }));
-    }, 300);
-  }
- 
-  // Additional training activities for more EXP
-  function doTraining(type: "physical" | "mental" | "meditation") {
-    if (inRun) return;
- 
-    let expGain = 0;
-    let fatigueGain = 0;
-    let message = "";
- 
-    switch (type) {
-      case "physical":
-        expGain = rand(8, 15);
-        fatigueGain = rand(5, 10);
-        message = "Physical training complete. Your body grows stronger.";
-        break;
-      case "mental":
-        expGain = rand(6, 12);
-        fatigueGain = rand(3, 7);
-        message = "Mental training sharpens your focus.";
-        break;
-      case "meditation":
-        expGain = rand(4, 8);
-        fatigueGain = -rand(5, 12); // Meditation reduces fatigue
-        message = "Meditation brings clarity and peace.";
-        break;
-    }
- 
-    setPlayer((p) => ({
-      ...p,
-      exp: p.exp + expGain,
-      fatigue: clamp(p.fatigue + fatigueGain, 0, 100),
-    }));
- 
-    handleLevelGain(expGain);
-    logPush(`${message} +${expGain} EXP`);
-  }
- 
-  // Work for gold and small EXP
-  function doWork() {
-    if (inRun) return;
- 
-    const goldGain = rand(15, 35);
-    const expGain = rand(3, 8);
-    const fatigueGain = rand(8, 15);
- 
-    setGold((g) => g + goldGain);
-    setPlayer((p) => ({
-      ...p,
-      exp: p.exp + expGain,
-      fatigue: clamp(p.fatigue + fatigueGain, 0, 100),
-    }));
- 
-    handleLevelGain(expGain);
-    logPush(`Work complete. +${goldGain}₲, +${expGain} EXP (but more fatigue)`);
-  }
- 
-  // Shop functions
-  function buyPotion() {
-    const cost = 25;
-    if (gold < cost) {
-      logPush(`Not enough gold. Need ${cost}₲ for a potion.`);
-      return;
-    }
- 
-    const quality = rand(40, 60);
-    // Shop potions scale with player level so they stay useful
-    const levelBonus = Math.floor((player.level ?? 1) * 1.5);
-    const healAmount = Math.floor((quality / 100) * 50 + 25 + levelBonus);
- 
-    setGold((g) => g - cost);
-    setPlayer((p) => ({
-      ...p,
-      inv: [
-        ...p.inv,
-        {
-          id: uid(),
-          name: "Health Potion",
-          type: "potion",
-          rarity: "common",
-          quality,
-          description: `Restores ${healAmount} HP`,
-          stats: { HP: healAmount },
-          sellValue: Math.floor(quality * 1.2),
-        },
-      ],
-    }));
-    logPush(`Purchased a Health Potion for ${cost}₲`);
-  }
- 
-  function buyUpgrade(type: "weapon" | "armor" | "accessory") {
-    let cost = 0;
-    let bonus = 0;
-    let statType = "";
- 
-    switch (type) {
-      case "weapon":
-        cost = 100 + player.level * 25;
-        bonus = 3 + Math.floor(player.level / 3);
-        statType = "STR";
-        break;
-      case "armor":
-        cost = 80 + player.level * 20;
-        bonus = 2 + Math.floor(player.level / 4);
-        statType = "VIT";
-        break;
-      case "accessory":
-        cost = 120 + player.level * 30;
-        bonus = 2 + Math.floor(player.level / 5);
-        statType = "LUCK";
-        break;
-    }
- 
-    if (gold < cost) {
-      logPush(`Not enough gold. Need ${cost}₲ for ${type} upgrade.`);
-      return;
-    }
- 
-    setGold((g) => g - cost);
-    setPlayer((p) => ({
-      ...p,
-      stats: {
-        ...p.stats,
-        [statType]: p.stats[statType as keyof Player["stats"]] + bonus,
-      },
-    }));
-    logPush(`Purchased ${type} upgrade! +${bonus} ${statType} for ${cost}₲`);
-  }
- 
-  // Refresh gate pool
-  function refreshGates() {
-    if (inRun) return;
-    const cost = Math.max(10, player.level * 5);
-    if (gold < cost) {
-      logPush(`Not enough gold. Need ${cost}₲ to refresh gates.`);
-      return;
-    }
- 
-    setGold((g) => g - cost);
-    setGates(generateGatePool(player.level));
-    logPush(`Gates refreshed! (-${cost}₲)`);
-  }
- 
-  // Silent auto-save (no log message) — call after important mutations
-  function silentSave() {
-    const gameState = {
-      player,
-      gates,
-      gold,
-      gameTime,
-      daily,
-      lastSaved: new Date().toISOString(),
-    };
-    localStorage.setItem("hunters-path-autosave", JSON.stringify(gameState));
-    localStorage.setItem("hunters-path-save", JSON.stringify(gameState));
-  }
- 
-  // Save/Load functions
-  function saveGame() {
-    silentSave();
-    logPush("Game saved successfully!");
-  }
- 
-  function loadGame() {
-    try {
-      const saved = localStorage.getItem("hunters-path-save");
-      if (!saved) {
-        logPush("No save file found.");
-        return;
-      }
- 
-      const gameState = JSON.parse(saved);
- 
-      // Ensure equipment property exists for old save data
-      if (!gameState.player.equipment) {
-        gameState.player.equipment = {};
-      }
- 
-      // Handle old daily quest structure
-      if (gameState.daily) {
-        // If old structure, generate new quests
-        if (!gameState.daily.questReputation) {
-          gameState.daily.questReputation = 0;
-        }
-        if (
-          !gameState.daily.availableQuests ||
-          gameState.daily.availableQuests.length === 0
-        ) {
-          gameState.daily.availableQuests = generateDailyQuests(
-            gameState.player.level,
-            gameState.daily.questReputation
-          );
-          gameState.daily.active = true;
-        }
-      }
- 
-      // Migrate old spirits to new format (also initialise missing field)
-      gameState.player.spirits = (gameState.player.spirits || []).map(
-        (spirit: any) => {
-          // If spirit already has new format, return as is
-          if (spirit.rarity && spirit.abilities && spirit.type) {
-            return spirit;
-          }
- 
-          // Migrate old spirit format to new format
-          const type = SPIRIT_TYPES[rand(0, SPIRIT_TYPES.length - 1)];
-          const rarity = "common"; // Default to common for old spirits
-          const availableAbilities = SPIRIT_ABILITIES[type];
-          const abilities = availableAbilities.slice(0, 1); // Give 1 ability to old spirits
- 
-          return {
-            id: spirit.id,
-            name: spirit.name,
-            power: spirit.power,
-            rarity,
-            abilities,
-            level: 1,
-            exp: 0,
-            expToNext: 100,
-            type,
-            description: SPIRIT_DESCRIPTIONS[type],
-          };
-        }
-      );
- 
-      // Strip debug spirits from save data
-      gameState.player.spirits = (gameState.player.spirits || []).filter(
-        (s: any) => !s.id?.startsWith("debug_") && !s.name?.startsWith("Debug ")
-      );
- 
-      setPlayer(gameState.player);
-      setGates(gameState.gates);
-      setGold(gameState.gold);
-      setGameTime(gameState.gameTime);
-      setDaily(gameState.daily);
-      logPush("Game loaded successfully!");
-    } catch (error) {
-      logPush("Failed to load game. Save file may be corrupted.");
-    }
-  }
- 
-  function resetGame() {
-    if (
-      confirm(
-        "Are you sure you want to reset your progress? This cannot be undone."
-      )
-    ) {
-      setPlayer(createInitialPlayer());
-      setGates(generateGatePool(1));
-      setGold(50);
-      setGameTime(initialGameTime());
- 
-      // Generate new daily quests for level 1
-      const newQuests = generateDailyQuests(1, 0);
-      setDaily({
-        active: true,
-        availableQuests: newQuests,
-        completedQuests: [],
-        completed: false,
-        penaltyArmed: false,
-        questReputation: 0,
-      });
- 
-      setLog(["Game reset. Welcome back, Hunter!"]);
-      localStorage.removeItem("hunters-path-save");
-    }
-  }
- 
-  // Arm penalty if player enters dungeon mid-daily and then completes after — simulate auto-trigger at end of fight
-  useEffect(() => {
-    if (!inRun && daily.penaltyArmed) {
-      setDaily((d) => ({ ...d, penaltyArmed: false }));
-      applyPenaltyZone();
-    }
-    // eslint-disable-next-line react-hooks/exhaustive-deps
-  }, [inRun]);
- 
-  // Keep autoDungeonRef in sync with autoDungeon state (for stale closure safety)
-  useEffect(() => {
-    autoDungeonRef.current = autoDungeon;
-  }, [autoDungeon]);
- 
-  // Auto-dungeon logic: after each run ends (or combatResult appears), queue next run
-  useEffect(() => {
-    if (!autoDungeon || inRun || player.fatigue > 80) return;
- 
-    // Auto-rest if HP is low before entering next gate
-    if (player.hp < player.maxHp * 0.5) {
-      const timer = setTimeout(() => {
-        if (!autoDungeonRef.current) return;
-        if (combatResult) setCombatResult(null);
-        rest();
-        logPush("Auto-dungeon: Resting before next gate...");
-      }, 1500);
-      return () => clearTimeout(timer);
-    }
- 
-    const timer = setTimeout(() => {
-      if (!autoDungeonRef.current) return; // user turned it off during delay
- 
-      // Auto-dismiss combat result if one is showing
-      if (combatResult) setCombatResult(null);
- 
-      // Pick gates the player can comfortably clear (power >= actual gate power)
-      const clearable = gates.filter(g => pPower >= g.power);
-      if (clearable.length === 0) {
-        logPush("Auto-dungeon: No suitable gates found. Disabling.");
-        setAutoDungeon(false);
-        return;
-      }
- 
-      // Pick highest rank available
-      const target = clearable.sort((a, b) => b.rankIdx - a.rankIdx)[0];
-      startGate(target);
-    }, 3000); // 3 second pause between runs
- 
-    return () => clearTimeout(timer);
-  // eslint-disable-next-line react-hooks/exhaustive-deps
-  }, [autoDungeon, inRun, gates, pPower, player.fatigue, player.hp, player.maxHp, combatResult]);
- 
-  // Auto-disable when fatigue > 80
-  useEffect(() => {
-    if (player.fatigue > 80 && autoDungeon) {
-      setAutoDungeon(false);
-      logPush("Auto-dungeon disabled: too fatigued. Rest first!");
-    }
-  // eslint-disable-next-line react-hooks/exhaustive-deps
-  }, [player.fatigue, autoDungeon]);
- 
-  // Debounced auto-save: persists within 1s of any state change.
-  // Catches spirit binding, equipping, level-ups, etc. before a pull-to-refresh.
-  useEffect(() => {
-    const timer = setTimeout(() => {
-      const gameState = {
-        player, gates, gold, gameTime, daily,
-        lastSaved: new Date().toISOString(),
-      };
-      localStorage.setItem("hunters-path-autosave", JSON.stringify(gameState));
-      localStorage.setItem("hunters-path-save", JSON.stringify(gameState));
-    }, 1000);
-    return () => clearTimeout(timer);
-  }, [player, gates, gold, daily, gameTime]);
- 
-  // Also save immediately when user switches away or closes the PWA
-  useEffect(() => {
-    const onHide = () => {
-      if (document.visibilityState === "hidden") saveGame();
-    };
-    document.addEventListener("visibilitychange", onHide);
-    return () => document.removeEventListener("visibilitychange", onHide);
-  }, [player, gates, gold, daily, gameTime]);
- 
-  // Sound management — thin wrappers around audioManager singleton
-  function playSound(soundName: string, volumeOverride?: number) {
-    audioManager.playSound(soundName as SoundName, volumeOverride);
-  }
- 
-  function playMusic(musicName: string, loop: boolean = true) {
-    // Map legacy names to new MusicName type
-    const nameMap: Record<string, MusicName> = {
-      ambient_music: "ambient",
-      combat_music: "combat",
-      victory_music: "victory_music",
-      defeat_music: "defeat_music",
-    };
-    audioManager.playMusic(nameMap[musicName] ?? (musicName as MusicName), loop);
-  }
- 
-  function stopMusic() {
-    audioManager.stopMusic(true);
-  }
- 
-  function updateVolume(newVolume: number) {
-    setVolume(newVolume);
-  }
- 
-  function toggleSound() {
-    setSoundEnabled((prev) => !prev);
-  }
- 
-  function toggleMusic() {
-    setMusicEnabled((prev) => !prev);
-  }
- 
-  // Stat progression visualization component
-  function StatProgressionChart() {
-    if (statHistory.length < 2) return null;
- 
-    const maxStats = {
-      STR: Math.max(...statHistory.map((h) => h.stats.STR)),
-      AGI: Math.max(...statHistory.map((h) => h.stats.AGI)),
-      INT: Math.max(...statHistory.map((h) => h.stats.INT)),
-      VIT: Math.max(...statHistory.map((h) => h.stats.VIT)),
-      LUCK: Math.max(...statHistory.map((h) => h.stats.LUCK)),
-    };
- 
-    const totalMax = Math.max(...Object.values(maxStats));
- 
-    return (
-      <div className="bg-zinc-800/30 rounded-lg p-4 border border-zinc-600/30">
-        <h4 className="text-lg font-bold text-zinc-100 mb-4">
-          <i className="fas fa-chart-line mr-2 text-blue-400"></i>
-          Stat Progression
-        </h4>
- 
-        <div className="space-y-3">
-          {Object.entries(maxStats).map(([stat, maxValue]) => {
-            const currentValue = player.stats[stat as keyof Player["stats"]];
-            const percentage =
-              totalMax > 0 ? (currentValue / totalMax) * 100 : 0;
- 
-            return (
-              <div key={stat} className="flex items-center space-x-3">
-                <div className="w-12 text-sm text-zinc-400 font-bold">
-                  {stat}
-                </div>
-                <div className="flex-1 bg-zinc-700 rounded-full h-3 overflow-hidden">
-                  <div
-                    className="h-full bg-gradient-to-r from-blue-500 to-purple-500 transition-all duration-500"
-                    style={{ width: `${percentage}%` }}
-                  ></div>
-                </div>
-                <div className="w-12 text-sm text-zinc-300 font-bold text-right">
-                  {currentValue}
-                </div>
-              </div>
-            );
-          })}
-        </div>
- 
-        <div className="mt-4 text-xs text-zinc-500 text-center">
-          Showing progression over {statHistory.length} recorded points
-        </div>
-      </div>
-    );
-  }
- 
-  function completeLevelUp() {
-    setLevelUpState({
-      isActive: false,
-      newLevel: 0,
-      statPointsGained: 0,
-      showStatAllocation: false,
-    });
-  }
- 
-  function allocateStatWithFeedback(stat: keyof Player["stats"]) {
-    if (player.points <= 0) return;
- 
-    // Trigger visual feedback
-    triggerVisualEffect("statAllocation");
- 
-    setPlayer((p) => ({
-      ...p,
-      points: p.points - 1,
-      stats: { ...p.stats, [stat]: p.stats[stat] + 1 },
-    }));
- 
-    // Play stat allocation sound
-    playSound("rune_use"); // Reuse rune sound for stat allocation
- 
-    // Record stat change
-    setStatHistory((prev) => [
-      ...prev,
-      {
-        level: player.level,
-        stats: { ...player.stats, [stat]: player.stats[stat] + 1 },
-        power: playerPower({
-          ...player,
-          stats: { ...player.stats, [stat]: player.stats[stat] + 1 },
-        }),
-        timestamp: new Date().toISOString(),
-      },
-    ]);
-  }
- 
-  // Enhanced Inventory System State
-  const [inventoryFilter, setInventoryFilter] = useState<
-    "all" | "potion" | "rune" | "key" | "equipment"
-  >("all");
-  const [inventorySort, setInventorySort] = useState<
-    "name" | "rarity" | "quality" | "type"
-  >("type");
-  const [showItemDetails, setShowItemDetails] = useState<string | null>(null);
- 
-  // Collapsible Sections State for Mobile
-  const [collapsedSections, setCollapsedSections] = useState<{
-    player: boolean;
-    inventory: boolean;
-    training: boolean;
-    shop: boolean;
-    spirits: boolean;
-  }>({
-    player: false,
-    inventory: false,
-    training: false,
-    shop: false,
-    spirits: false,
-  });
- 
-  // Mobile menu state
-  const [showMobileMenu, setShowMobileMenu] = useState(false);
- 
-  // Enhanced Inventory Utility Functions
-  function equipItem(itemId: string) {
-    try {
-      console.log("Equipping item:", itemId);
- 
-      const item = player.inv.find((i) => i.id === itemId);
-      if (!item || item.type !== "equipment" || !item.equipmentSlot) {
-        console.log("Cannot equip item:", { item, itemId });
-        return;
-      }
- 
-      // Validate item structure
-      if (!item.id || !item.name || !item.equipmentSlot) {
-        console.error("Invalid item structure:", item);
-        logPush("Invalid item. Cannot equip.");
-        return;
-      }
- 
-      setPlayer((p) => {
-        try {
-          // Create defensive copies to prevent mutation issues
-          const newInv = [...p.inv].filter((i) => i.id !== itemId);
-          const oldItem = item.equipmentSlot
-            ? p.equipment[item.equipmentSlot]
-            : undefined;
- 
-          // Add old item back to inventory if it exists
-          if (oldItem) {
-            newInv.push({ ...oldItem }); // Create copy to prevent reference issues
-          }
- 
-          // Create new equipment object with explicit copying
-          const newEquipment = {
-            weapon: p.equipment.weapon ? { ...p.equipment.weapon } : undefined,
-            armor: p.equipment.armor ? { ...p.equipment.armor } : undefined,
-            accessory: p.equipment.accessory
-              ? { ...p.equipment.accessory }
-              : undefined,
-          };
- 
-          // Set the new item
-          if (item.equipmentSlot === "weapon") {
-            newEquipment.weapon = { ...item };
-          } else if (item.equipmentSlot === "armor") {
-            newEquipment.armor = { ...item };
-          } else if (item.equipmentSlot === "accessory") {
-            newEquipment.accessory = { ...item };
-          }
- 
-          const newPlayer = {
-            ...p,
-            inv: newInv,
-            equipment: newEquipment,
-          };
- 
-          console.log("New player state:", newPlayer);
-          return newPlayer;
-        } catch (setPlayerError) {
-          console.error("Error in setPlayer callback:", setPlayerError);
-          // Return unchanged state if there's an error
-          return p;
-        }
-      });
- 
-      logPush(`Equipped ${item.name}!`);
- 
-      // Force a small delay and re-render for mobile PWA compatibility
-      setTimeout(() => {
-        // Trigger a small state update to ensure re-render
-        setPlayer((p) => ({ ...p }));
-      }, 100);
-    } catch (error) {
-      console.error("Error equipping item:", error);
-      logPush("Error equipping item. Please try again.");
-    }
-  }
- 
-  function unequipItem(slot: keyof Equipment) {
-    try {
-      console.log("Unequipping item from slot:", slot);
- 
-      const item = player.equipment[slot];
-      if (!item) {
-        console.log("No item to unequip in slot:", slot);
-        return;
-      }
- 
-      // Validate item structure
-      if (!item.id || !item.name) {
-        console.error("Invalid item structure:", item);
-        logPush("Invalid item. Cannot unequip.");
-        return;
-      }
- 
-      setPlayer((p) => {
-        try {
-          // Create defensive copies
-          const newInv = [...p.inv, { ...item }]; // Create copy to prevent reference issues
-          const newEquipment = { ...p.equipment };
-          newEquipment[slot] = undefined;
- 
-          const newPlayer = {
-            ...p,
-            inv: newInv,
-            equipment: newEquipment,
-          };
- 
-          console.log("New player state after unequip:", newPlayer);
-          return newPlayer;
-        } catch (setPlayerError) {
-          console.error(
-            "Error in setPlayer callback (unequip):",
-            setPlayerError
-          );
-          // Return unchanged state if there's an error
-          return p;
-        }
-      });
- 
-      logPush(`Unequipped ${item.name}!`);
- 
-      // Force a small delay and re-render for mobile PWA compatibility
-      setTimeout(() => {
-        // Trigger a small state update to ensure re-render
-        setPlayer((p) => ({ ...p }));
-      }, 100);
-    } catch (error) {
-      console.error("Error unequipping item:", error);
-      logPush("Error unequipping item. Please try again.");
-    }
-  }
- 
-  function getRarityColor(rarity: string): string {
-    switch (rarity) {
-      case "common":
-        return "text-gray-400";
-      case "uncommon":
-        return "text-green-400";
-      case "rare":
-        return "text-blue-400";
-      case "epic":
-        return "text-purple-400";
-      case "legendary":
-        return "text-yellow-400";
-      default:
-        return "text-gray-400";
-    }
-  }
- 
-  function getRarityBgColor(rarity: string): string {
-    switch (rarity) {
-      case "common":
-        return "bg-gray-600";
-      case "uncommon":
-        return "bg-green-600";
-      case "rare":
-        return "bg-blue-600";
-      case "epic":
-        return "bg-purple-600";
-      case "legendary":
-        return "bg-yellow-600";
-      default:
-        return "bg-gray-600";
-    }
-  }
- 
-  function getFilteredAndSortedItems() {
-    let filtered = player.inv;
- 
-    // Apply filter
-    if (inventoryFilter !== "all") {
-      filtered = filtered.filter((item) => {
-        if (inventoryFilter === "equipment") {
-          return item.type === "equipment";
-        }
-        return item.type === inventoryFilter;
-      });
-    }
- 
-    // Apply sort
-    filtered.sort((a, b) => {
-      switch (inventorySort) {
-        case "name":
-          return a.name.localeCompare(b.name);
-        case "rarity":
-          const rarityOrder = {
-            common: 0,
-            uncommon: 1,
-            rare: 2,
-            epic: 3,
-            legendary: 4,
-          };
-          return (
-            (rarityOrder[a.rarity || "common"] || 0) -
-            (rarityOrder[b.rarity || "common"] || 0)
-          );
-        case "quality":
-          return (b.quality || 50) - (a.quality || 50);
-        case "type":
-          return a.type.localeCompare(b.type);
-        default:
-          return 0;
-      }
-    });
- 
-    return filtered;
-  }
- 
-  // Enhanced Inventory Component
-  function EnhancedInventory() {
-    const filteredItems = getFilteredAndSortedItems();
-    const equipmentSlots = [
-      { key: "weapon" as const, name: "Weapon", icon: "fas fa-hand-fist" },
-      { key: "armor" as const, name: "Armor", icon: "fas fa-shield-alt" },
-      { key: "accessory" as const, name: "Accessory", icon: "fas fa-ring" },
-    ];
- 
-    // Safety check for equipment
-    const equipment = player.equipment || {};
- 
-    return (
-      <div>
-        {/* Filter and Sort Controls */}
-        <div className="flex flex-col sm:flex-row items-start sm:items-center space-y-2 sm:space-y-0 sm:space-x-2 mb-4">
-          <select
-            value={inventoryFilter}
-            onChange={(e: React.ChangeEvent<HTMLSelectElement>) =>
-              setInventoryFilter(e.target.value as any)
-            }
-            className="bg-zinc-800 text-zinc-300 text-xs px-2 py-1 rounded border border-zinc-600 flex-1"
-          >
-            <option value="all">All Items</option>
-            <option value="potion">Potions</option>
-            <option value="rune">Runes</option>
-            <option value="key">Keys</option>
-            <option value="equipment">Equipment</option>
-          </select>
- 
-          <select
-            value={inventorySort}
-            onChange={(e: React.ChangeEvent<HTMLSelectElement>) =>
-              setInventorySort(e.target.value as any)
-            }
-            className="bg-zinc-800 text-zinc-300 text-xs px-2 py-1 rounded border border-zinc-600 flex-1"
-          >
-            <option value="type">Sort by Type</option>
-            <option value="rarity">Sort by Rarity</option>
-            <option value="quality">Sort by Quality</option>
-            <option value="name">Sort by Name</option>
-          </select>
-        </div>
- 
-        {/* Equipment Slots */}
-        <div className="mb-4 p-2 bg-zinc-800/30 rounded border border-zinc-600/30">
-          <h4 className="text-sm font-bold text-zinc-300 mb-2 flex items-center">
-            <i className="fas fa-user-shield mr-2"></i>
-            Equipment
-          </h4>
-          <div className="grid grid-cols-3 gap-1">
-            {equipmentSlots.map((slot) => {
-              const equippedItem = equipment[slot.key];
-              return (
-                <div key={slot.key} className="text-center">
-                  <div className="text-xs text-zinc-400 mb-1">{slot.name}</div>
-                  <div className="w-8 h-8 mx-auto border-2 border-dashed border-zinc-600 rounded flex items-center justify-center">
-                    {equippedItem ? (
-                      <div className="w-6 h-6 rounded-full flex items-center justify-center bg-purple-600">
-                        <i className="fas fa-check text-white text-xs"></i>
-                      </div>
-                    ) : (
-                      <i className={`${slot.icon} text-zinc-500 text-xs`}></i>
-                    )}
-                  </div>
-                  {equippedItem && (
-                    <button
-                      onClick={() => {
-                        try {
-                          unequipItem(slot.key);
-                        } catch (error) {
-                          console.error(
-                            "Unequip error caught in button:",
-                            error
-                          );
-                          logPush("Unequip failed. Please try again.");
-                        }
-                      }}
-                      className="text-xs text-red-400 hover:text-red-300 mt-1"
-                    >
-                      Unequip
-                    </button>
-                  )}
-                </div>
-              );
-            })}
-          </div>
-        </div>
- 
-        {/* Inventory Items */}
-        {player.inv.length === 0 ? (
-          <div className="opacity-70 text-sm text-center py-6">
-            <i className="fas fa-box-open text-2xl text-zinc-600 mb-2"></i>
-            <div>Empty inventory</div>
-          </div>
-        ) : (
-          <div className="space-y-1 max-h-80 overflow-y-auto custom-scrollbar">
-            {filteredItems.map((item) => (
-              <div
-                key={item.id}
-                className={`relative bg-zinc-800/30 rounded p-2 border transition-all hover:bg-zinc-700/40 ${
-                  showItemDetails === item.id
-                    ? "border-zinc-500"
-                    : "border-zinc-600/30"
-                }`}
-                onClick={(e) => {
-                  // Don't toggle details if clicking on a button
-                  if ((e.target as HTMLElement).closest("button")) {
-                    return;
-                  }
-                  setShowItemDetails(
-                    showItemDetails === item.id ? null : item.id
-                  );
-                }}
-              >
-                <div className="flex items-center justify-between">
-                  <div className="flex items-center space-x-2 min-w-0 flex-1">
-                    <div
-                      className={`w-6 h-6 rounded-full flex items-center justify-center flex-shrink-0 ${getRarityBgColor(
-                        item.rarity || "common"
-                      )}`}
-                    >
-                      <i
-                        className={`text-white text-xs ${
-                          item.type === "potion"
-                            ? "fas fa-flask"
-                            : item.type === "rune"
-                            ? "fas fa-gem"
-                            : item.type === "key"
-                            ? "fas fa-key"
-                            : item.type === "equipment"
-                            ? "fas fa-hand-fist"
-                            : "fas fa-question"
-                        }`}
-                      ></i>
-                    </div>
-                    <div className="flex flex-col min-w-0 flex-1">
-                      <div className="flex items-center space-x-1">
-                        <span
-                          className={`text-zinc-300 font-medium text-sm truncate ${getRarityColor(
-                            item.rarity || "common"
-                          )}`}
-                        >
-                          {item.name}
-                        </span>
-                        <span className="text-xs text-zinc-500 flex-shrink-0">
-                          Q{item.quality || 50}
-                        </span>
-                      </div>
-                      {item.description && (
-                        <span className="text-xs text-zinc-500 truncate">
-                          {item.description}
-                        </span>
-                      )}
-                    </div>
-                  </div>
- 
-                  <div className="flex items-center space-x-1 flex-shrink-0">
-                    {item.type === "potion" && (
-                      <Btn sm onClick={() => usePotion(item.id)}>
-                        Use
-                      </Btn>
-                    )}
-                    {item.type === "rune" && (
-                      <Btn sm onClick={() => useRune(item.id)}>
-                        Use
-                      </Btn>
-                    )}
-                    {item.type === "equipment" && (
-                      <Btn
-                        sm
-                        onClick={() => {
-                          try {
-                            equipItem(item.id);
-                          } catch (error) {
-                            console.error(
-                              "Equipment error caught in button:",
-                              error
-                            );
-                            logPush("Equipment failed. Please try again.");
-                          }
-                        }}
-                      >
-                        Equip
-                      </Btn>
-                    )}
-                    <button
-                      onClick={() => {}}
-                      className="text-zinc-400 hover:text-zinc-300 text-xs"
-                    >
-                      <i className="fas fa-info-circle"></i>
-                    </button>
-                  </div>
-                </div>
- 
-                {/* Expanded Item Details */}
-                {showItemDetails === item.id && (
-                  <div className="mt-2 pt-2 border-t border-zinc-600/30">
-                    <div className="text-xs text-zinc-400 space-y-1">
-                      {item.description && (
-                        <div>
-                          <strong>Description:</strong> {item.description}
-                        </div>
-                      )}
-                      {item.stats && Object.keys(item.stats).length > 0 && (
-                        <div>
-                          <strong>Stats:</strong>
-                          {Object.entries(item.stats).map(([stat, value]) => (
-                            <span key={stat} className="ml-2 text-blue-400">
-                              +{value} {stat}
-                            </span>
-                          ))}
-                        </div>
-                      )}
-                      {item.sellValue && (
-                        <div>
-                          <strong>Sell Value:</strong> {item.sellValue}₲
-                        </div>
-                      )}
-                      <div>
-                        <strong>Rarity:</strong>{" "}
-                        <span
-                          className={getRarityColor(item.rarity || "common")}
-                        >
-                          {item.rarity || "common"}
-                        </span>
-                      </div>
-                      <div>
-                        <strong>Quality:</strong> {item.quality || 50}/100
-                      </div>
-                    </div>
-                  </div>
-                )}
-              </div>
-            ))}
-          </div>
-        )}
-      </div>
-    );
-  }
- 
-  // Debug mode state
-  const [debugMode, setDebugMode] = useState(false);
-  const [showDebugPanel, setShowDebugPanel] = useState(false);
- 
-  // Debug Functions
-  function addDebugItem(
-    type: "potion" | "rune" | "key" | "equipment",
-    rarity: "common" | "uncommon" | "rare" | "epic" | "legendary" = "common"
-  ) {
-    const quality =
-      rarity === "common"
-        ? 50
-        : rarity === "uncommon"
-        ? 60
-        : rarity === "rare"
-        ? 75
-        : rarity === "epic"
-        ? 85
-        : 95;
- 
-    let item: Item;
- 
-    switch (type) {
-      case "potion":
-        item = {
-          id: uid(),
-          name: `${
-            rarity.charAt(0).toUpperCase() + rarity.slice(1)
-          } Health Potion`,
-          type: "potion",
-          rarity,
-          quality,
-          description: `Restores ${Math.floor((quality / 100) * 50 + 25)} HP`,
-          stats: { HP: Math.floor((quality / 100) * 50 + 25) },
-          sellValue: Math.floor(quality * 1.2),
-        };
-        break;
-      case "rune":
-        const statTypes = ["STR", "AGI", "INT", "VIT", "LUCK"];
-        const runeStatType =
-          statTypes[Math.floor(Math.random() * statTypes.length)];
-        const runeStatBonus = Math.floor((quality / 100) * 5);
-        item = {
-          id: uid(),
-          name: `${
-            rarity.charAt(0).toUpperCase() + rarity.slice(1)
-          } ${runeStatType} Rune`,
-          type: "rune",
-          rarity,
-          quality,
-          description: `Boosts ${runeStatType} by ${runeStatBonus}`,
-          stats: { [runeStatType]: runeStatBonus },
-          sellValue: Math.floor(quality * 1.5),
-        };
-        break;
-      case "key":
-        item = {
-          id: uid(),
-          name: `${
-            rarity.charAt(0).toUpperCase() + rarity.slice(1)
-          } Dungeon Key`,
-          type: "key",
-          rarity,
-          quality,
-          description: "Opens a special dungeon with enhanced rewards",
-          sellValue: Math.floor(quality * 2),
-        };
-        break;
-      case "equipment":
-        const equipmentTypes = ["weapon", "armor", "accessory"];
-        const equipmentType =
-          equipmentTypes[Math.floor(Math.random() * equipmentTypes.length)];
-        const equipStatBonus = Math.floor((quality / 100) * 10);
-        const equipStatType =
-          equipmentType === "weapon"
-            ? "STR"
-            : equipmentType === "armor"
-            ? "VIT"
-            : "LUCK";
-        const equipmentNames = {
-          weapon: `${rarity.charAt(0).toUpperCase() + rarity.slice(1)} Blade`,
-          armor: `${rarity.charAt(0).toUpperCase() + rarity.slice(1)} Armor`,
-          accessory: `${
-            rarity.charAt(0).toUpperCase() + rarity.slice(1)
-          } Charm`,
-        };
-        item = {
-          id: uid(),
-          name: equipmentNames[equipmentType as keyof typeof equipmentNames],
-          type: "equipment",
-          rarity,
-          quality,
-          description: `Provides ${equipStatBonus} ${equipStatType}`,
-          stats: { [equipStatType]: equipStatBonus },
-          equipmentSlot: equipmentType as "weapon" | "armor" | "accessory",
-          sellValue: Math.floor(quality * 3),
-        };
-        break;
-    }
- 
-    setPlayer((p) => ({
-      ...p,
-      inv: [...p.inv, item],
-    }));
- 
-    logPush(`Added ${item.name} to inventory!`);
-  }
- 
-  function setDebugPlayerLevel(level: number) {
-    const expNeeded = level * 100; // Simple formula for testing
-    setPlayer((p) => ({
-      ...p,
-      level,
-      exp: expNeeded - 1, // Just below the level threshold
-      expNext: expNeeded,
-    }));
-    logPush(`Set player level to ${level}!`);
-  }
- 
-  function addDebugGold(amount: number) {
-    setGold((g) => g + amount);
-    logPush(`Added ${amount} gold!`);
-  }
- 
-  function generateDebugGates() {
-    const debugGates = [
-      makeGate(0), // E-rank
-      makeGate(1), // D-rank
-      makeGate(2), // C-rank
-      makeGate(3), // B-rank
-      makeGate(4), // A-rank
-      makeGate(5), // S-rank
-    ];
-    setGates(debugGates);
-    logPush("Generated debug gates (E through S rank)!");
-  }
- 
-  function clearDebugData() {
-    setPlayer((p) => ({
-      ...p,
-      inv: [],
-      equipment: {},
-    }));
-    setGold(0);
-    logPush("Cleared all items and gold!");
-  }
- 
-  const BossComp = running ? BOSS_COMPONENTS[running.gate.rank as BossRank] : null;
- 
- 
- 
-  if (isMobile) {
-    return (
-      <MobileLayout
-        player={player}
-        playerPower={pPower}
-        gates={gates}
-        gold={gold}
-        daily={daily}
-        log={log}
-        running={running}
-        combatResult={combatResult}
-        combatLog={combatLog}
-        autoDungeon={autoDungeon}
-        soundEnabled={soundEnabled}
-        musicEnabled={musicEnabled}
-        volume={volume}
-        onStartGate={startGate}
-        onRest={rest}
-        onUseKey={useKey}
-        onRefreshGates={refreshGates}
-        onUsePotion={usePotion}
-        onDismissResult={dismissCombatResult}
-        onAllocateStat={(stat, amount) => allocate(stat as keyof Player["stats"], amount)}
-        onForfeitDaily={forfeitDaily}
-        onRebirth={handleRebirth}
-        onReset={resetGame}
-        onSave={saveGame}
-        onLoad={loadGame}
-        onToggleAuto={() => setAutoDungeon(a => !a)}
-        onTrain={(type) => {
-          if (type === "work") doWork();
-          else doTraining(type as "physical" | "mental" | "meditation");
-        }}
-        onBuyItem={(itemId) => {
-          if (itemId === "potion") buyPotion();
-          else buyUpgrade(itemId as "weapon" | "armor" | "accessory");
-        }}
-        onEquipItem={equipItem}
-        onUnequipItem={(slot: string) => unequipItem(slot as keyof Equipment)}
-        onUseRune={useRune}
-        onSetSoundEnabled={setSoundEnabled}
-        onSetMusicEnabled={setMusicEnabled}
-        onSetVolume={setVolume}
-        spiritBindingState={spiritBindingState}
-        levelUpState={levelUpState}
-        rebirthModalOpen={rebirthModalOpen}
-        onSetRebirthModalOpen={setRebirthModalOpen}
-        prestigeUpgrades={prestigeUpgrades}
-        modalOverlay={
-          <>
-            {/* Spirit Binding Sequence Modal */}
-            {spiritBindingState.isActive && (
-              <div className="fixed inset-0 bg-black/80 flex items-center justify-center z-50">
-                <div className="relative w-full h-full flex items-center justify-center">
-                  <div className="absolute inset-0">
-                    <div className="absolute top-1/4 left-1/4 w-2 h-2 bg-purple-400 rounded-full animate-pulse opacity-60"></div>
-                    <div className="absolute top-1/3 right-1/3 w-1 h-1 bg-blue-400 rounded-full animate-pulse opacity-40"></div>
-                    <div className="absolute bottom-1/4 left-1/3 w-1.5 h-1.5 bg-green-400 rounded-full animate-pulse opacity-50"></div>
-                    <div className="absolute bottom-1/3 right-1/4 w-1 h-1 bg-yellow-400 rounded-full animate-pulse opacity-30"></div>
-                    <div className="absolute top-1/2 left-1/2 w-3 h-3 bg-red-400 rounded-full animate-pulse opacity-70"></div>
-                    <div
-                      className={`absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 w-64 h-64 border-2 border-purple-500/30 rounded-full animate-shadow-ripple ${
-                        spiritBindingState.phase === "extracting" ? "opacity-100" : "opacity-0"
-                      }`}
-                    ></div>
-                    <div
-                      className={`absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 w-96 h-96 border border-purple-400/20 rounded-full animate-pulse ${
-                        spiritBindingState.phase === "extracting" ? "opacity-100" : "opacity-0"
-                      }`}
-                    ></div>
-                  </div>
-                  <div className="relative z-10 text-center max-w-2xl mx-4">
-                    <div
-                      className={`mb-8 p-8 rounded-lg border-2 transition-all duration-500 ${
-                        spiritBindingState.phase === "preparing"
-                          ? "bg-blue-900/30 border-blue-500/50"
-                          : spiritBindingState.phase === "extracting"
-                          ? "bg-purple-900/30 border-purple-500/50"
-                          : spiritBindingState.phase === "success"
-                          ? "bg-green-900/30 border-green-500/50"
-                          : spiritBindingState.phase === "failure"
-                          ? "bg-red-900/30 border-red-500/50"
-                          : "bg-zinc-900/30 border-zinc-500/50"
-                      }`}
-                    >
-                      <div
-                        className={`w-24 h-24 mx-auto mb-6 rounded-full flex items-center justify-center transition-all duration-500 ${
-                          spiritBindingState.phase === "preparing"
-                            ? "bg-blue-600 animate-shadow-pulse"
-                            : spiritBindingState.phase === "extracting"
-                            ? "bg-purple-600 animate-shadow-spin animate-shadow-glow"
-                            : spiritBindingState.phase === "success"
-                            ? "bg-green-600 animate-shadow-bounce"
-                            : spiritBindingState.phase === "failure"
-                            ? "bg-red-600 animate-shadow-pulse"
-                            : "bg-zinc-600"
-                        }`}
-                      >
-                        <i
-                          className={`text-3xl text-white ${
-                            spiritBindingState.phase === "preparing"
-                              ? "fas fa-magic"
-                              : spiritBindingState.phase === "extracting"
-                              ? "fas fa-ghost"
-                              : spiritBindingState.phase === "success"
-                              ? "fas fa-check"
-                              : spiritBindingState.phase === "failure"
-                              ? "fas fa-times"
-                              : "fas fa-question"
-                          }`}
-                        ></i>
-                      </div>
-                      {(() => {
-                        const text = getExtractionSequenceText();
-                        return (
-                          <>
-                            <h2
-                              className={`text-3xl font-bold mb-4 transition-all duration-500 ${
-                                spiritBindingState.phase === "preparing"
-                                  ? "text-blue-300"
-                                  : spiritBindingState.phase === "extracting"
-                                  ? "text-purple-300"
-                                  : spiritBindingState.phase === "success"
-                                  ? "text-green-300"
-                                  : spiritBindingState.phase === "failure"
-                                  ? "text-red-300"
-                                  : "text-zinc-300"
-                              }`}
-                            >
-                              {text.title}
-                            </h2>
-                            <p className="text-xl text-zinc-200 mb-3">{text.subtitle}</p>
-                            <p className="text-zinc-400 mb-6">{text.description}</p>
-                            {spiritBindingState.phase === "extracting" && (
-                              <div className="w-full bg-zinc-700 rounded-full h-4 mb-4 overflow-hidden">
-                                <div
-                                  className="bg-gradient-to-r from-purple-500 to-purple-400 h-4 rounded-full transition-all duration-300 ease-out"
-                                  style={{ width: `${spiritBindingState.progress}%` }}
-                                ></div>
-                              </div>
-                            )}
-                            <div className="text-sm text-zinc-500">
-                              Target: {spiritBindingState.bossName} ({spiritBindingState.bossRank}-Rank)
-                            </div>
-                          </>
-                        );
-                      })()}
-                    </div>
-                    {spiritBindingState.phase === "extracting" && (
-                      <div className="text-center">
-                        <div className="text-purple-400 text-sm animate-pulse">
-                          <i className="fas fa-magic mr-2"></i>
-                          Channeling magical energy...
-                        </div>
-                      </div>
-                    )}
-                    {spiritBindingState.phase === "success" && (
-                      <div className="text-center">
-                        <div className="text-green-400 text-lg font-bold animate-bounce">
-                          🎉 Spirit Binding Complete! 🎉
-                        </div>
-                      </div>
-                    )}
-                    {spiritBindingState.phase === "failure" && (
-                      <div className="text-center">
-                        <div className="text-red-400 text-lg font-bold animate-pulse">
-                          💀 Extraction Failed 💀
-                        </div>
-                      </div>
-                    )}
-                  </div>
-                </div>
-              </div>
-            )}
- 
-            {/* Level-Up Celebration Modal */}
-            {levelUpState.isActive && (
-              <div className="fixed inset-0 bg-black/80 flex items-center justify-center z-50">
-                <div className="relative w-full h-full flex items-center justify-center">
-                  <div className="absolute inset-0">
-                    <div className="absolute top-1/4 left-1/4 w-3 h-3 bg-yellow-400 rounded-full animate-bounce opacity-80"></div>
-                    <div
-                      className="absolute top-1/3 right-1/3 w-2 h-2 bg-orange-400 rounded-full animate-bounce opacity-60"
-                      style={{ animationDelay: "0.2s" }}
-                    ></div>
-                    <div
-                      className="absolute bottom-1/4 left-1/3 w-2.5 h-2.5 bg-red-400 rounded-full animate-bounce opacity-70"
-                      style={{ animationDelay: "0.4s" }}
-                    ></div>
-                    <div
-                      className="absolute bottom-1/3 right-1/4 w-2 h-2 bg-pink-400 rounded-full animate-bounce opacity-50"
-                      style={{ animationDelay: "0.6s" }}
-                    ></div>
-                    <div
-                      className="absolute top-1/2 left-1/2 w-4 h-4 bg-purple-400 rounded-full animate-bounce opacity-90"
-                      style={{ animationDelay: "0.8s" }}
-                    ></div>
-                    <div className="absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 w-80 h-80 border-4 border-yellow-500/40 rounded-full animate-pulse"></div>
-                    <div
-                      className="absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 w-96 h-96 border-2 border-orange-400/30 rounded-full animate-pulse"
-                      style={{ animationDelay: "0.5s" }}
-                    ></div>
-                  </div>
-                  <div className="relative z-10 text-center max-w-2xl mx-4">
-                    <div className="mb-8 p-8 rounded-lg border-2 bg-gradient-to-br from-yellow-900/40 to-orange-900/40 border-yellow-500/60">
-                      <div className="w-32 h-32 mx-auto mb-6 rounded-full flex items-center justify-center bg-gradient-to-br from-yellow-400 to-orange-500 animate-pulse shadow-2xl">
-                        <i className="fas fa-star text-6xl text-white animate-spin"></i>
-                      </div>
-                      <h2 className="text-5xl font-bold mb-4 text-yellow-300 animate-celebration-bounce">
-                        LEVEL UP!
-                      </h2>
-                      <div className="text-3xl font-bold text-orange-300 mb-4">
-                        Level {levelUpState.newLevel}
-                      </div>
-                      <div className="text-xl text-yellow-200 mb-6">
-                        +{levelUpState.statPointsGained} Stat Points Available!
-                      </div>
-                      {levelUpState.showStatAllocation && (
-                        <div className="mt-8 p-6 bg-zinc-800/50 rounded-lg border border-yellow-500/30">
-                          <h3 className="text-xl font-bold text-yellow-300 mb-4">
-                            Allocate Your Stat Points
-                          </h3>
-                          <div className="grid grid-cols-2 md:grid-cols-5 gap-3 mb-6">
-                            {Object.entries(player.stats).map(([stat, value]) => (
-                              <div key={stat} className="text-center">
-                                <div className="text-sm text-zinc-400 mb-1">{stat}</div>
-                                <div className="text-lg font-bold text-white mb-2">{value as number}</div>
-                                <button
-                                  onClick={() =>
-                                    allocateStatWithFeedback(stat as keyof Player["stats"])
-                                  }
-                                  disabled={player.points <= 0}
-                                  className="w-8 h-8 bg-yellow-600 hover:bg-yellow-500 disabled:bg-zinc-600 disabled:cursor-not-allowed text-white rounded-full transition-colors font-bold"
-                                >
-                                  +
-                                </button>
-                              </div>
-                            ))}
-                          </div>
-                          <div className="text-center">
-                            <div className="text-sm text-zinc-400 mb-2">
-                              Points Remaining:{" "}
-                              <span className="text-yellow-400 font-bold">{player.points}</span>
-                            </div>
-                            <button
-                              onClick={completeLevelUp}
-                              className="bg-green-600 hover:bg-green-500 text-white px-6 py-3 rounded-lg font-bold transition-colors"
-                            >
-                              Continue Adventure
-                            </button>
-                          </div>
-                        </div>
-                      )}
-                      {!levelUpState.showStatAllocation && (
-                        <div className="text-center">
-                          <div className="text-yellow-200 text-lg animate-pulse">
-                            Preparing stat allocation...
-                          </div>
-                        </div>
-                      )}
-                    </div>
-                  </div>
-                </div>
-              </div>
-            )}
- 
-            {/* Story Event Modal — milestones & first clears */}
-            {storyEvent && (
-              <div
-                className="fixed inset-0 bg-black/90 flex items-center justify-center z-50 cursor-pointer"
-                onClick={() => setStoryEvent(null)}
-              >
-                <div className="relative w-full h-full flex items-center justify-center overflow-hidden">
-                  {/* Atmospheric particles */}
-                  <div className="absolute inset-0 pointer-events-none">
-                    <div className="absolute top-1/4 left-1/5 w-1 h-1 bg-violet-400 rounded-full animate-pulse opacity-40" />
-                    <div className="absolute top-1/3 right-1/4 w-1.5 h-1.5 bg-blue-400 rounded-full animate-pulse opacity-30" style={{ animationDelay: "0.3s" }} />
-                    <div className="absolute bottom-1/3 left-1/3 w-1 h-1 bg-purple-400 rounded-full animate-pulse opacity-50" style={{ animationDelay: "0.6s" }} />
-                    <div className="absolute bottom-1/4 right-1/3 w-2 h-2 bg-violet-300 rounded-full animate-pulse opacity-20" style={{ animationDelay: "0.9s" }} />
-                  </div>
-                  {/* Content */}
-                  <div className="relative z-10 text-center max-w-lg mx-6 animate-fade-in">
-                    <div className="mb-3 text-xs uppercase tracking-[0.3em] text-violet-400/70 font-semibold">
-                      Story Event
-                    </div>
-                    <div className="w-16 h-0.5 bg-gradient-to-r from-transparent via-violet-500 to-transparent mx-auto mb-6" />
-                    <h2 className="text-3xl sm:text-4xl font-bold mb-6 text-violet-200 leading-tight">
-                      {storyEvent.title}
-                    </h2>
-                    <p className="text-lg text-zinc-300 leading-relaxed mb-8 font-light">
-                      {storyEvent.message}
-                    </p>
-                    <div className="w-16 h-0.5 bg-gradient-to-r from-transparent via-violet-500 to-transparent mx-auto mb-6" />
-                    <div className="text-sm text-zinc-500 animate-pulse">
-                      Tap to continue
-                    </div>
-                  </div>
-                </div>
-              </div>
-            )}
- 
-            {/* Boss Intro Sequence — shown before combat starts */}
-            {bossIntro && (
-              <div
-                className="fixed inset-0 bg-black/90 flex items-center justify-center z-50 cursor-pointer"
-                onClick={skipBossIntro}
-              >
-                <div className="relative w-full h-full flex items-center justify-center overflow-hidden">
-                  {/* Dramatic radial glow */}
-                  <div className="absolute inset-0 pointer-events-none">
-                    <div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-64 h-64 rounded-full bg-red-900/20 blur-3xl animate-pulse" />
-                  </div>
-                  {/* Content */}
-                  <div className="relative z-10 text-center max-w-md mx-6">
-                    <div className="mb-2 text-xs uppercase tracking-[0.3em] text-red-400/70 font-semibold">
-                      {bossIntro.gate.name}
-                    </div>
-                    <div className="w-12 h-0.5 bg-gradient-to-r from-transparent via-red-500 to-transparent mx-auto mb-5" />
-                    {/* Boss art */}
-                    {(() => {
-                      const BossComp = BOSS_COMPONENTS[bossIntro.gate.rank as BossRank];
-                      return BossComp ? (
-                        <BossComp className="w-24 h-24 mx-auto mb-4 drop-shadow-[0_0_15px_rgba(239,68,68,0.4)]" />
-                      ) : (
-                        <div className="w-24 h-24 mx-auto mb-4 bg-zinc-800 rounded-full" />
-                      );
-                    })()}
-                    <h2 className="text-2xl sm:text-3xl font-bold mb-1 text-red-200">
-                      {bossIntro.boss.name}
-                    </h2>
-                    <div className="text-sm text-zinc-500 mb-5">
-                      {bossIntro.gate.rank}-Rank Boss
-                    </div>
-                    {bossIntro.dialogue && (
-                      <p className="text-lg text-zinc-300 italic leading-relaxed mb-6">
-                        {bossIntro.dialogue}
-                      </p>
-                    )}
-                    <div className="text-sm text-zinc-600 animate-pulse">
-                      Tap to skip
-                    </div>
-                  </div>
-                </div>
-              </div>
-            )}
- 
-            {/* Rebirth Modal */}
-            {rebirthModalOpen && (
-              <Dialog open={rebirthModalOpen} onOpenChange={setRebirthModalOpen}>
-                <DialogContent>
-                  <DialogHeader>
-                    <DialogTitle>⚡ Rebirth</DialogTitle>
-                    <DialogDescription>
-                      Reset your progress to gain permanent bonuses!
-                    </DialogDescription>
-                  </DialogHeader>
-                  <div className="space-y-4 py-4">
-                    <div className="bg-red-900/20 border border-red-500/30 p-3 rounded-lg">
-                      <p className="text-red-400 font-bold">⚠️ This will reset:</p>
-                      <ul className="text-red-300 text-sm mt-2 space-y-1">
-                        <li>• All gold (₲)</li>
-                        <li>• All keys</li>
-                        <li>• All gates cleared</li>
-                        <li>• Fatigue</li>
-                      </ul>
-                    </div>
-                    <div className="bg-green-900/20 border border-green-500/30 p-3 rounded-lg">
-                      <p className="text-green-400 font-bold">✅ You will keep:</p>
-                      <ul className="text-green-300 text-sm mt-2 space-y-1">
-                        <li>• Your level ({player.level})</li>
-                        <li>• All allocated stats</li>
-                        <li>• Your Spirit Legion</li>
-                      </ul>
-                    </div>
-                    <div className="bg-purple-900/20 border border-purple-500/30 p-3 rounded-lg text-center">
-                      <p className="text-purple-400 font-bold">🎁 You will gain:</p>
-                      <p className="text-2xl font-bold text-purple-300">
-                        +{Math.floor(player.level * 10 * (1 + player.rebirths * 0.5))} Prestige Points
-                      </p>
-                      <p className="text-purple-400">+{(player.rebirths + 1) * 15}% Power Bonus</p>
-                    </div>
-                  </div>
-                  <DialogFooter>
-                    <button
-                      onClick={() => setRebirthModalOpen(false)}
-                      className="px-4 py-2 bg-zinc-700 text-white rounded hover:bg-zinc-600"
-                    >
-                      Cancel
-                    </button>
-                    <button
-                      onClick={handleRebirth}
-                      className="px-4 py-2 bg-purple-600 text-white rounded hover:bg-purple-500 font-bold"
-                    >
-                      Confirm Rebirth
-                    </button>
-                  </DialogFooter>
-                </DialogContent>
-              </Dialog>
-            )}
-          </>
-        }
-      />
-    );
-  }
- 
-  return (
-    <div className="min-h-screen game-gradient font-game text-zinc-100 p-4">
-      <div className="max-w-7xl mx-auto">
-        {/* Header */}
-        <header className="mb-6">
-          <Card>
-            <div className="flex flex-col lg:flex-row lg:items-center lg:justify-between space-y-4 lg:space-y-0">
-              {/* Game Title and Time */}
-              <div className="flex flex-col sm:flex-row sm:items-center space-y-2 sm:space-y-0 sm:space-x-4">
-                <div>
-                  <h1 className="text-2xl sm:text-3xl font-bold font-display tracking-wide bg-gradient-to-r from-violet-400 via-purple-300 to-violet-400 bg-clip-text text-transparent drop-shadow-sm">
-                    Hunter's Path
-                  </h1>
-                  <p className="text-zinc-500 text-xs font-medium tracking-widest uppercase">
-                    {formatGameTime(gameTime)}
-                  </p>
-                </div>
- 
-                {/* Resources - Stack on small screens */}
-                <div className="flex flex-wrap items-center gap-2">
-                  <div className="flex items-center space-x-2 bg-zinc-800 px-3 py-2 rounded-lg">
-                    <i className="fas fa-coins text-yellow-400"></i>
-                    <span className="font-bold">{fmt(gold)}</span>
-                    <span className="text-zinc-400 text-sm">₲</span>
-                  </div>
-                  <div className="flex items-center space-x-2 bg-zinc-800 px-3 py-2 rounded-lg">
-                    <i className="fas fa-key text-violet-400"></i>
-                    <span className="font-bold">{player.keys}</span>
-                    <span className="text-zinc-400 text-sm">Keys</span>
-                  </div>
-                  {player.prestigePoints > 0 && (
-                    <div className="flex items-center space-x-2 bg-purple-900/50 px-3 py-2 rounded-lg">
-                      <i className="fas fa-star text-purple-400"></i>
-                      <span className="font-bold text-purple-300">{player.prestigePoints.toLocaleString()}</span>
-                      <span className="text-purple-400 text-sm">PP</span>
-                    </div>
-                  )}
-                </div>
-              </div>
- 
-              {/* Controls - Responsive Layout */}
-              <div className="flex flex-col sm:flex-row items-start sm:items-center space-y-2 sm:space-y-0 sm:space-x-2">
-                {/* Primary Actions */}
-                <div className="flex items-center space-x-2">
-                  <Btn
-                    onClick={() => setShowStats(!showStats)}
-                    theme="default"
-                    sm
-                  >
-                    <i className="fas fa-chart-bar mr-1"></i>
-                    Stats
-                  </Btn>
-                  <Btn onClick={resetGame} theme="danger" sm>
-                    <i className="fas fa-trash mr-1"></i>
-                    Reset
-                  </Btn>
-                  {player.level >= 50 && (
-                    <Btn
-                      onClick={() => setRebirthModalOpen(true)}
-                      theme="purple"
-                      sm
-                    >
-                      <i className="fas fa-bolt mr-1"></i>
-                      Rebirth
-                      {player.rebirths > 0 && (
-                        <span className="ml-1 bg-purple-800 px-1.5 py-0.5 rounded text-xs">
-                          +{player.rebirths * 15}%
-                        </span>
-                      )}
-                    </Btn>
-                  )}
-                  <button
-                    onClick={() => setAutoDungeon(prev => !prev)}
-                    disabled={player.fatigue > 80 && !autoDungeon}
-                    className={`flex items-center space-x-1 px-3 py-2 rounded text-sm font-bold transition-colors ${
-                      autoDungeon
-                        ? 'bg-green-600 hover:bg-green-500 text-white'
-                        : 'bg-zinc-700 hover:bg-zinc-600 text-zinc-200'
-                    }`}
-                    title={player.fatigue > 80 ? "Too fatigued for auto-dungeon (fatigue > 80)" : autoDungeon ? "Auto-dungeon: ON (click to stop)" : "Auto-dungeon: OFF (click to start)"}
-                  >
-                    <i className={`fas ${autoDungeon ? 'fa-stop-circle' : 'fa-play-circle'} mr-1`}></i>
-                    {autoDungeon ? 'Auto: ON' : 'Auto'}
-                  </button>
-                  {process.env.NODE_ENV === "development" && (
-                    <Btn
-                      onClick={() => setShowDebugPanel(!showDebugPanel)}
-                      theme="default"
-                      sm
-                    >
-                      <i className="fas fa-bug mr-1"></i>
-                      Debug
-                    </Btn>
-                  )}
-                </div>
- 
-                {/* Audio Controls */}
-                <div className="flex items-center space-x-2 bg-zinc-800 px-3 py-1 rounded-lg">
-                  <button
-                    onClick={toggleSound}
-                    className={`text-sm ${
-                      soundEnabled ? "text-green-400" : "text-red-400"
-                    }`}
-                    title={soundEnabled ? "Sound On" : "Sound Off"}
-                  >
-                    <i
-                      className={`fas ${
-                        soundEnabled ? "fa-volume-up" : "fa-volume-mute"
-                      }`}
-                    ></i>
-                  </button>
-                  <button
-                    onClick={toggleMusic}
-                    className={`text-sm ${
-                      musicEnabled ? "text-blue-400" : "text-red-400"
-                    }`}
-                    title={musicEnabled ? "Music On" : "Music Off"}
-                  >
-                    <i
-                      className={`fas ${
-                        musicEnabled ? "fa-music" : "fa-volume-xmark"
-                      }`}
-                    ></i>
-                  </button>
-                  <input
-                    type="range"
-                    min="0"
-                    max="1"
-                    step="0.1"
-                    value={volume}
-                    onChange={(e) => updateVolume(parseFloat(e.target.value))}
-                    className="w-12 sm:w-16 h-1 bg-zinc-600 rounded-lg appearance-none cursor-pointer"
-                    title={`Volume: ${Math.round(volume * 100)}%`}
-                  />
-                </div>
- 
-                {/* Mobile Menu Toggle */}
-                <button
-                  onClick={() => setShowMobileMenu(!showMobileMenu)}
-                  className="lg:hidden bg-zinc-800 p-2 rounded-lg text-zinc-400 hover:text-zinc-300"
-                  title="Toggle Mobile Menu"
-                >
-                  <i
-                    className={`fas ${showMobileMenu ? "fa-times" : "fa-bars"}`}
-                  ></i>
-                </button>
-              </div>
-            </div>
-          </Card>
-        </header>
- 
-        {/* Mobile Menu Overlay */}
-        {showMobileMenu && (
-          <div
-            className="fixed inset-0 bg-black/50 z-40 lg:hidden"
-            onClick={() => setShowMobileMenu(false)}
-          >
-            <div
-              className="absolute right-4 top-20 bg-zinc-900 border border-zinc-700 rounded-lg p-4 w-80 max-h-[80vh] overflow-y-auto"
-              onClick={(e) => e.stopPropagation()}
-            >
-              <div className="flex items-center justify-between mb-4">
-                <h3 className="text-lg font-bold text-zinc-100">
-                  Quick Actions
-                </h3>
-                <button
-                  onClick={() => setShowMobileMenu(false)}
-                  className="text-zinc-400 hover:text-zinc-300"
-                >
-                  <i className="fas fa-times"></i>
-                </button>
-              </div>
- 
-              <div className="space-y-3">
-                <Btn
-                  onClick={rest}
-                  disabled={inRun}
-                  className="w-full justify-start"
-                >
-                  <i className="fas fa-bed mr-2"></i>
-                  Rest & Recover
-                </Btn>
-                <Btn
-                  onClick={useKey}
-                  disabled={player.keys <= 0 || inRun}
-                  className="w-full justify-start"
-                >
-                  <i className="fas fa-key mr-2"></i>
-                  Use Key ({player.keys})
-                </Btn>
-                <Btn
-                  onClick={saveGame}
-                  disabled={inRun}
-                  className="w-full justify-start"
-                >
-                  <i className="fas fa-save mr-2"></i>
-                  Save Game
-                </Btn>
-                <Btn
-                  onClick={loadGame}
-                  disabled={inRun}
-                  className="w-full justify-start"
-                >
-                  <i className="fas fa-upload mr-2"></i>
-                  Load Game
-                </Btn>
-              </div>
-            </div>
-          </div>
-        )}
- 
-        <div className="grid grid-cols-1 lg:grid-cols-4 gap-6">
-          {/* Left: Player & Actions */}
-          <section className="lg:col-span-1 space-y-6">
-            <Card>
-              <div className="flex items-center space-x-4 mb-6">
-                <PlayerAvatar className="w-16 h-16 rounded-full" />
-                <div>
-                  <h2 className="text-xl font-bold text-zinc-100">Hunter</h2>
-                  <div className="flex items-center space-x-2">
-                    <span className="text-violet-400 font-bold">
-                      Level {player.level}
-                    </span>
-                    <span className="text-zinc-400">•</span>
-                    <span className="text-zinc-400">Power: {fmt(pPower)}</span>
-                  </div>
-                </div>
-              </div>
- 
-              <Bar
-                label="HP"
-                value={player.hp}
-                max={player.maxHp}
-                color="progress-hp"
-              />
-              <Bar
-                label="MP"
-                value={player.mp}
-                max={player.maxMp}
-                color="progress-mp"
-              />
-              <Bar
-                label="EXP"
-                value={player.exp}
-                max={player.expNext}
-                color="progress-exp"
-              />
- 
-              {player.fatigue > 0 && (
-                <div className="bg-orange-900/30 border border-orange-500/30 rounded-lg p-3 mt-4">
-                  <div className="flex items-center space-x-2 mb-2">
-                    <i className="fas fa-exclamation-triangle text-orange-400"></i>
-                    <span className="text-sm text-orange-200">
-                      Fatigue: {Math.round(player.fatigue)}%
-                    </span>
-                  </div>
-                  <BarMini
-                    value={player.fatigue}
-                    max={100}
-                    color="progress-fatigue"
-                  />
-                </div>
-              )}
- 
-              <div className="flex gap-2 mt-6 flex-wrap">
-                <Btn onClick={rest} disabled={inRun}>
-                  <i className="fas fa-bed mr-2"></i>
-                  Rest & Recover
-                </Btn>
-                <Btn onClick={useKey} disabled={player.keys <= 0 || inRun}>
-                  <i className="fas fa-key mr-2"></i>
-                  Use Key ({player.keys})
-                </Btn>
-                <Btn onClick={refreshGates} disabled={gold < 90 || inRun}>
-                  <i className="fas fa-sync-alt mr-2"></i>
-                  Refresh Gates (90¢)
-                </Btn>
-                <Btn onClick={saveGame} disabled={inRun}>
-                  <i className="fas fa-save mr-2"></i>
-                  Save Game
-                </Btn>
-                <Btn onClick={loadGame} disabled={inRun}>
-                  <i className="fas fa-upload mr-2"></i>
-                  Load Game
-                </Btn>
-                {daily.active && !daily.completed && (
-                  <Btn onClick={forfeitDaily} theme="danger">
-                    <i className="fas fa-times mr-2"></i>
-                    Forfeit Daily
-                  </Btn>
-                )}
-              </div>
-            </Card>
- 
-            {/* Training Activities */}
-            <Card>
-              <Accordion type="single" collapsible className="w-full">
-                <AccordionItem value="training">
-                  <AccordionTrigger className="text-lg font-bold text-violet-300 hover:no-underline">
-                    <i className="fas fa-dumbbell mr-2"></i>
-                    Training Activities
-                  </AccordionTrigger>
-                  <AccordionContent>
-                    <div className="space-y-3 max-h-80 overflow-y-auto">
-                      <div className="grid grid-cols-1 gap-2">
-                        <Btn
-                          onClick={() => doTraining("physical")}
-                          disabled={inRun}
-                          className="justify-start text-left"
-                        >
-                          <i className="fas fa-fist-raised mr-2 text-red-400"></i>
-                          Physical Training
-                          <span className="ml-auto text-xs text-zinc-400">
-                            8-15 EXP
-                          </span>
-                        </Btn>
-                        <Btn
-                          onClick={() => doTraining("mental")}
-                          disabled={inRun}
-                          className="justify-start text-left"
-                        >
-                          <i className="fas fa-brain mr-2 text-blue-400"></i>
-                          Mental Training
-                          <span className="ml-auto text-xs text-zinc-400">
-                            6-12 EXP
-                          </span>
-                        </Btn>
-                        <Btn
-                          onClick={() => doTraining("meditation")}
-                          disabled={inRun}
-                          className="justify-start text-left"
-                        >
-                          <i className="fas fa-leaf mr-2 text-green-400"></i>
-                          Meditation
-                          <span className="ml-auto text-xs text-zinc-400">
-                            4-8 EXP, -Fatigue
-                          </span>
-                        </Btn>
-                        <Btn
-                          onClick={doWork}
-                          disabled={inRun}
-                          className="justify-start text-left"
-                        >
-                          <i className="fas fa-hammer mr-2 text-yellow-400"></i>
-                          Work Job
-                          <span className="ml-auto text-xs text-zinc-400">
-                            15-35₲, 3-8 EXP
-                          </span>
-                        </Btn>
-                      </div>
-                      <p className="text-xs text-zinc-500 mt-2">
-                        Train to gain experience when stuck, or work for extra
-                        gold. Most activities increase fatigue.
-                      </p>
-                    </div>
-                  </AccordionContent>
-                </AccordionItem>
-              </Accordion>
-            </Card>
- 
-            {/* Prestige Shop */}
-            {(player.rebirths > 0 || player.prestigePoints > 0) && (
-              <Card>
-                <Accordion type="single" collapsible className="w-full">
-                  <AccordionItem value="prestige-shop">
-                    <AccordionTrigger className="text-lg font-bold text-purple-300 hover:no-underline">
-                      <i className="fas fa-star mr-2"></i>
-                      Prestige Shop
-                      <span className="ml-2 text-sm font-normal text-purple-400">({player.prestigePoints} PP available)</span>
-                    </AccordionTrigger>
-                    <AccordionContent>
-                      <div className="space-y-2">
-                        {PRESTIGE_UPGRADES.map(upgrade => {
-                          const level = prestigeUpgrades[upgrade.id] || 0;
-                          const cost = level < upgrade.maxLevel ? upgrade.costPer * (level + 1) : 0;
-                          const maxed = level >= upgrade.maxLevel;
-                          const canAfford = player.prestigePoints >= cost;
-                          return (
-                            <div key={upgrade.id} className="bg-purple-900/20 border border-purple-500/30 p-3 rounded-lg flex items-center justify-between gap-2">
-                              <div className="flex-1 min-w-0">
-                                <p className="font-bold text-purple-200 text-sm">
-                                  {upgrade.name}
-                                  <span className="ml-2 text-xs text-purple-400">Lv {level}/{upgrade.maxLevel}</span>
-                                </p>
-                                <p className="text-xs text-purple-300">{upgrade.description}</p>
-                              </div>
-                              <button
-                                disabled={maxed || !canAfford}
-                                onClick={() => buyPrestigeUpgrade(upgrade.id)}
-                                className={`flex-shrink-0 px-3 py-1 rounded text-sm font-bold transition-colors ${
-                                  maxed
-                                    ? 'bg-zinc-600 text-zinc-400 cursor-not-allowed'
-                                    : canAfford
-                                    ? 'bg-purple-600 hover:bg-purple-500 text-white'
-                                    : 'bg-zinc-700 text-zinc-500 cursor-not-allowed'
-                                }`}
-                              >
-                                {maxed ? 'MAX' : `${cost} PP`}
-                              </button>
-                            </div>
-                          );
-                        })}
-                      </div>
-                    </AccordionContent>
-                  </AccordionItem>
-                </Accordion>
-              </Card>
-            )}
- 
-            {/* Shop */}
-            <Card>
-              <Accordion type="single" collapsible className="w-full">
-                <AccordionItem value="shop">
-                  <AccordionTrigger className="text-lg font-bold text-yellow-300 hover:no-underline">
-                    <i className="fas fa-shopping-cart mr-2"></i>
-                    Hunter Shop
-                  </AccordionTrigger>
-                  <AccordionContent>
-                    <div className="space-y-3 max-h-80 overflow-y-auto">
-                      <div className="grid grid-cols-1 gap-2">
-                        <Btn
-                          onClick={buyPotion}
-                          disabled={gold < 25}
-                          className="justify-between text-left"
-                        >
-                          <div className="flex items-center">
-                            <i className="fas fa-flask mr-2 text-green-400"></i>
-                            Health Potion
-                          </div>
-                          <span className="text-yellow-400">25₲</span>
-                        </Btn>
-                        <Btn
-                          onClick={() => buyUpgrade("weapon")}
-                          disabled={gold < 100 + player.level * 25}
-                          className="justify-between text-left"
-                        >
-                          <div className="flex items-center">
-                            <i className="fas fa-hand-fist mr-2 text-red-400"></i>
-                            Weapon Upgrade (+STR)
-                          </div>
-                          <span className="text-yellow-400">
-                            {100 + player.level * 25}₲
-                          </span>
-                        </Btn>
-                        <Btn
-                          onClick={() => buyUpgrade("armor")}
-                          disabled={gold < 80 + player.level * 20}
-                          className="justify-between text-left"
-                        >
-                          <div className="flex items-center">
-                            <i className="fas fa-shield-alt mr-2 text-orange-400"></i>
-                            Armor Upgrade (+VIT)
-                          </div>
-                          <span className="text-yellow-400">
-                            {80 + player.level * 20}₲
-                          </span>
-                        </Btn>
-                        <Btn
-                          onClick={() => buyUpgrade("accessory")}
-                          disabled={gold < 120 + player.level * 30}
-                          className="justify-between text-left"
-                        >
-                          <div className="flex items-center">
-                            <i className="fas fa-ring mr-2 text-purple-400"></i>
-                            Lucky Charm (+LUCK)
-                          </div>
-                          <span className="text-yellow-400">
-                            {120 + player.level * 30}₲
-                          </span>
-                        </Btn>
-                      </div>
-                      <p className="text-xs text-zinc-500 mt-2">
-                        Equipment prices scale with your level. Upgrades
-                        permanently increase stats.
-                      </p>
-                    </div>
-                  </AccordionContent>
-                </AccordionItem>
-              </Accordion>
-            </Card>
- 
-            <Card>
-              <Accordion type="single" collapsible className="w-full">
-                <AccordionItem value="stats">
-                  <AccordionTrigger className="text-lg font-bold text-zinc-100 hover:no-underline">
-                    <div className="flex items-center justify-between w-full mr-4">
-                      <span>Stats</span>
-                      {player.points > 0 && (
-                        <div className="bg-violet-600 text-white px-3 py-1 rounded-full text-sm font-bold">
-                          {player.points} Points
-                        </div>
-                      )}
-                    </div>
-                  </AccordionTrigger>
-                  <AccordionContent>
-                    <div className="max-h-96 overflow-y-auto">
-                      <div className="mb-4 p-3 bg-blue-900/20 border border-blue-500/30 rounded-lg">
-                        <h4 className="text-sm font-bold text-blue-300 mb-2">
-                          <i className="fas fa-info-circle mr-1"></i>
-                          Stat Effects
-                        </h4>
-                        <div className="text-xs text-blue-200 space-y-1">
-                          <div>
-                            <span className="text-red-400 font-bold">STR:</span>{" "}
-                            Primary damage (+3 power each)
-                          </div>
-                          <div>
-                            <span className="text-green-400 font-bold">
-                              AGI:
-                            </span>{" "}
-                            Speed & damage (+2 power each)
-                          </div>
-                          <div>
-                            <span className="text-blue-400 font-bold">
-                              INT:
-                            </span>{" "}
-                            Magic damage & spirit binding (+1.5 power each)
-                          </div>
-                          <div>
-                            <span className="text-orange-400 font-bold">
-                              VIT:
-                            </span>{" "}
-                            Health & defense (+0.5 power each)
-                          </div>
-                          <div>
-                            <span className="text-yellow-400 font-bold">
-                              LUCK:
-                            </span>{" "}
-                            Critical hits & item drops
-                          </div>
-                        </div>
-                      </div>
- 
-                      <div className="space-y-3">
-                        {Object.entries(player.stats).map(([k, v]) => (
-                          <div
-                            key={k}
-                            className="flex items-center justify-between bg-zinc-800/50 rounded-lg p-3"
-                          >
-                            <div className="flex items-center space-x-3">
-                              <div
-                                className={`w-8 h-8 ${
-                                  STAT_COLORS[k as keyof typeof STAT_COLORS]
-                                } rounded-full flex items-center justify-center text-white text-sm font-bold`}
-                              >
-                                <i
-                                  className={
-                                    STAT_ICONS[k as keyof typeof STAT_ICONS]
-                                  }
-                                ></i>
-                              </div>
-                              <div>
-                                <div className="font-bold text-zinc-100">
-                                  {k}
-                                </div>
-                                <div className="text-sm text-zinc-400">
-                                  {k === "STR" && "Strength"}
-                                  {k === "AGI" && "Agility"}
-                                  {k === "INT" && "Intelligence"}
-                                  {k === "VIT" && "Vitality"}
-                                  {k === "LUCK" && "Luck"}
-                                </div>
-                              </div>
-                            </div>
-                            <div className="flex items-center space-x-2">
-                              <span className="font-bold text-xl">{v}</span>
-                              <button
-                                className="w-8 h-8 bg-violet-600 hover:bg-violet-500 text-white rounded-full transition-colors disabled:opacity-40"
-                                onClick={() =>
-                                  allocateStatWithFeedback(
-                                    k as keyof Player["stats"]
-                                  )
-                                }
-                                disabled={player.points <= 0}
-                              >
-                                <i className="fas fa-plus text-xs"></i>
-                              </button>
-                            </div>
-                          </div>
-                        ))}
-                      </div>
-                    </div>
-                  </AccordionContent>
-                </AccordionItem>
-              </Accordion>
-            </Card>
- 
-            {/* Stat Progression Chart */}
-            <StatProgressionChart />
- 
-            <Card>
-              <Accordion type="single" collapsible className="w-full">
-                <AccordionItem value="spirit-legion">
-                  <AccordionTrigger className="text-lg font-bold text-zinc-100 hover:no-underline">
-                    <div className="flex items-center space-x-2">
-                      <i className="fas fa-users text-purple-400"></i>
-                      <span>Spirit Legion</span>
-                      {player.spirits.length > 0 && (
-                        <span className="bg-purple-600 text-white px-2 py-1 rounded-full text-xs font-bold">
-                          {player.spirits.length}
-                        </span>
-                      )}
-                    </div>
-                  </AccordionTrigger>
-                  <AccordionContent>
-                    <div className="max-h-96 overflow-y-auto">
-                      {player.spirits.length === 0 && (
-                        <div className="opacity-70 text-sm text-center py-4">
-                          No spirits recruited
-                        </div>
-                      )}
- 
-                      <div className="space-y-3 mb-4">
-                        {player.spirits.map((s) => (
-                          <div
-                            key={s.id}
-                            className={`bg-zinc-800/30 border ${getRarityBorder(
-                              s.rarity
-                            )} rounded-lg p-3`}
-                          >
-                            <div className="flex items-center justify-between mb-2">
-                              <div className="flex items-center space-x-3">
-                                <div
-                                  className={`w-8 h-8 bg-gradient-to-br ${getRarityColor(
-                                    s.rarity
-                                  )
-                                    .replace("text-", "from-")
-                                    .replace(
-                                      "-400",
-                                      "-600"
-                                    )} to-purple-800 rounded-full flex items-center justify-center`}
-                                >
-                                  <i className="fas fa-ghost text-white text-xs"></i>
-                                </div>
-                                <div>
-                                  <div
-                                    className={`font-bold ${getRarityColor(
-                                      s.rarity
-                                    )}`}
-                                  >
-                                    {s.name}
-                                  </div>
-                                  <div className="text-xs text-zinc-400 capitalize">
-                                    {s.rarity} {s.type} • Level {s.level}
-                                  </div>
-                                </div>
-                              </div>
-                              <div className="text-right">
-                                <div className="font-bold text-purple-400">
-                                  +{s.power}
-                                </div>
-                                <div className="text-xs text-zinc-500">
-                                  Power
-                                </div>
-                              </div>
-                            </div>
- 
-                            <div className="text-xs text-zinc-400 mb-2">
-                              {s.description}
-                            </div>
- 
-                            <div className="space-y-1">
-                              <div className="text-xs font-semibold text-zinc-300 mb-1">
-                                Abilities:
-                              </div>
-                              {(s.abilities || []).map((ability) => (
-                                <div
-                                  key={ability.id}
-                                  className="flex items-center space-x-2"
-                                >
-                                  <span
-                                    className={`text-xs px-2 py-1 rounded ${
-                                      ability.type === "passive"
-                                        ? "bg-blue-600/20 text-blue-400"
-                                        : "bg-green-600/20 text-green-400"
-                                    }`}
-                                  >
-                                    {ability.type}
-                                  </span>
-                                  <span className="text-xs text-zinc-300 font-medium">
-                                    {ability.name}
-                                  </span>
-                                </div>
-                              ))}
-                            </div>
- 
-                            <div className="mt-2 pt-2 border-t border-zinc-700">
-                              <div className="flex items-center justify-between text-xs">
-                                <span className="text-zinc-400">
-                                  EXP: {s.exp}/{s.expToNext}
-                                </span>
-                                <div className="w-20 bg-zinc-700 rounded-full h-1.5">
-                                  <div
-                                    className="bg-purple-500 h-1.5 rounded-full transition-all duration-300"
-                                    style={{
-                                      width: `${(s.exp / s.expToNext) * 100}%`,
-                                    }}
-                                  ></div>
-                                </div>
-                              </div>
-                            </div>
-                          </div>
-                        ))}
-                      </div>
- 
-                      {player.spirits.length > 0 && (
-                        <div className="bg-purple-900/30 border border-purple-500/30 rounded-lg p-3">
-                          <div className="flex items-center justify-between text-sm">
-                            <span className="text-purple-300">
-                              Total Army Power:
-                            </span>
-                            <span className="font-bold text-purple-400">
-                              +{player.spirits.reduce((a, s) => a + s.power, 0)}
-                            </span>
-                          </div>
-                          <div className="flex items-center justify-between text-sm mt-1">
-                            <span className="text-purple-300">
-                              MP Upkeep/tick:
-                            </span>
-                            <span className="font-bold text-blue-400">
-                              -{spiritUpkeep(player)} MP
-                            </span>
-                          </div>
-                        </div>
-                      )}
-                    </div>
-                  </AccordionContent>
-                </AccordionItem>
-              </Accordion>
-            </Card>
-          </section>
- 
-          {/* Middle: Gates & Combat */}
-          <section className="lg:col-span-2 space-y-6">
-            <Card>
-              <h3 className="text-xl font-bold mb-4 text-zinc-100">
-                Combat Zone
-              </h3>
- 
-              {!inRun && (
-                <div className="text-sm opacity-80 mb-6 text-center py-8">
-                  Enter a Gate to begin combat. Allocate stats and complete
-                  Daily Quests first for best odds.
-                </div>
-              )}
- 
-              {(inRun && running) || combatResult ? (
-                <div
-                  className={`border rounded-lg p-6 mb-6 relative overflow-hidden transition-all duration-500 ${
-                    visualEffects.screenShake ? "animate-screen-shake" : ""
-                  } ${
-                    visualEffects.damageFlash ? "animate-damage-flash" : ""
-                  } ${visualEffects.healFlash ? "animate-heal-flash" : ""} ${
-                    running
-                      ? `gate-environment-${running.gate.rank}`
-                      : "bg-gradient-to-r from-red-900/30 to-purple-900/30 border-red-500/30"
-                  }`}
-                >
-                  {/* Animated Background Particles */}
-                  <div className="absolute inset-0 pointer-events-none">
-                    <div className="combat-particle absolute top-4 left-4 w-2 h-2 bg-purple-400 rounded-full animate-floating-particle opacity-60"></div>
-                    <div className="combat-particle absolute top-8 right-8 w-1 h-1 bg-red-400 rounded-full animate-floating-particle opacity-40"></div>
-                    <div className="combat-particle absolute bottom-6 left-12 w-1.5 h-1.5 bg-blue-400 rounded-full animate-floating-particle opacity-50"></div>
-                    <div className="combat-particle absolute bottom-12 right-4 w-1 h-1 bg-green-400 rounded-full animate-floating-particle opacity-30"></div>
- 
-                    {/* Environment-specific particles — 6 per rank for depth */}
-                    {running && (
-                      <>
-                        <div className={`environment-particle environment-particle-${running.gate.rank} absolute top-[10%] left-[15%] w-10 h-10 rounded-full`} style={{ animationDelay: "0s" }}></div>
-                        <div className={`environment-particle environment-particle-${running.gate.rank} absolute top-[60%] right-[10%] w-7 h-7 rounded-full`} style={{ animationDelay: "1s" }}></div>
-                        <div className={`environment-particle environment-particle-${running.gate.rank} absolute bottom-[15%] left-[40%] w-5 h-5 rounded-full`} style={{ animationDelay: "2s" }}></div>
-                        <div className={`environment-particle environment-particle-${running.gate.rank} absolute top-[40%] right-[30%] w-8 h-8 rounded-full`} style={{ animationDelay: "0.5s" }}></div>
-                        <div className={`environment-particle environment-particle-${running.gate.rank} absolute bottom-[30%] left-[10%] w-6 h-6 rounded-full`} style={{ animationDelay: "1.5s" }}></div>
-                        <div className={`environment-particle environment-particle-${running.gate.rank} absolute top-[75%] right-[50%] w-4 h-4 rounded-full`} style={{ animationDelay: "3s" }}></div>
-                      </>
-                    )}
-                  </div>
- 
-                  {/* Gate Header with Enhanced Styling */}
-                  <div className="text-center mb-6 relative z-10">
-                    <h4 className="text-xl font-bold text-red-300 mb-2 animate-pulse">
-                      {running?.gate.name || combatResult?.gate.name}
-                    </h4>
- 
-                    {/* Environment Description */}
-                    {running && (
-                      <div className="mb-4 p-3 bg-zinc-800/50 rounded-lg border border-zinc-600/30">
-                        <p className="text-sm text-zinc-300 italic">
-                          {
-                            MONSTER_DATA[
-                              running.gate.rank as keyof typeof MONSTER_DATA
-                            ]?.environment
-                          }
-                        </p>
-                        <p className="text-xs text-zinc-400 mt-1">
-                          {
-                            MONSTER_DATA[
-                              running.gate.rank as keyof typeof MONSTER_DATA
-                            ]?.sound
-                          }
-                        </p>
-                      </div>
-                    )}
- 
-                    <div className="flex items-center justify-center space-x-4 text-sm text-zinc-400">
-                      <div className="flex items-center space-x-2 bg-red-900/50 px-3 py-1 rounded-full border border-red-500/30">
-                        <i className="fas fa-skull text-red-400 animate-pulse"></i>
-                        <span>
-                          Rank {running?.gate.rank || combatResult?.gate.rank}
-                        </span>
-                      </div>
-                      <div className="flex items-center space-x-2 bg-blue-900/50 px-3 py-1 rounded-full border border-blue-500/30">
-                        <i className="fas fa-clock text-blue-400"></i>
-                        <span>{running?.tick || "Complete"}</span>
-                      </div>
-                    </div>
-                  </div>
- 
-                  {/* Particle Effects Layer */}
-                  <ParticleLayer bursts={bursts} onBurstComplete={removeBurst} />
- 
-                  {/* Combat Arena with Enhanced Visuals */}
-                  <div className="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-6 relative z-10">
-                    {/* Hunter Side with Glow Effects */}
-                    <motion.div
-                      className="bg-zinc-800/50 border border-purple-500/30 rounded-lg p-4 relative group hover:border-purple-400/50 transition-colors duration-300"
-                      initial={{ opacity: 0, x: -30 }}
-                      animate={{ opacity: 1, x: 0 }}
-                      transition={{ duration: 0.4, ease: "easeOut" }}
-                    >
-                      <div className="absolute inset-0 bg-gradient-to-r from-purple-500/10 to-transparent rounded-lg opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div>
- 
-                      {/* Floating damage numbers on player side */}
-                      <AnimatePresence>
-                        {damageNumbers.filter(d => d.side === "player").map((d) => (
-                          <DamageNumber key={d.id} id={d.id} amount={d.amount} type={d.type} />
-                        ))}
-                      </AnimatePresence>
- 
-                      <div className="text-center mb-4 relative z-10">
-                        <PlayerAvatar className="w-16 h-16 rounded-full mx-auto mb-2 shadow-lg shadow-purple-500/30" />
-                        <h5 className="font-bold text-purple-300 font-display">Hunter</h5>
-                        <p className="text-xs text-zinc-400">
-                          Level {player.level}
-                        </p>
-                      </div>
- 
-                      <div className="space-y-3 relative z-10">
-                        <CombatBar value={player.hp} max={player.maxHp} color="text-green-400" label="HP" />
-                        <CombatBar value={player.mp} max={player.maxMp} color="text-blue-400" label="MP" />
-                      </div>
-                    </motion.div>
- 
-                    {/* Enemy Side with Threatening Effects */}
-                    <motion.div
-                      className="bg-zinc-800/50 border border-red-500/30 rounded-lg p-4 relative group hover:border-red-400/50 transition-colors duration-300"
-                      initial={{ opacity: 0, x: 30 }}
-                      animate={{ opacity: 1, x: 0 }}
-                      transition={{ duration: 0.4, ease: "easeOut", delay: 0.1 }}
-                    >
-                      <div className="absolute inset-0 bg-gradient-to-r from-red-500/10 to-transparent rounded-lg opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div>
- 
-                      {/* Floating damage numbers on enemy side */}
-                      <AnimatePresence>
-                        {damageNumbers.filter(d => d.side === "enemy").map((d) => (
-                          <DamageNumber key={d.id} id={d.id} amount={d.amount} type={d.type} />
-                        ))}
-                      </AnimatePresence>
- 
-                      <div className="text-center mb-4 relative z-10">
-                        <motion.div
-                          className={`w-16 h-16 bg-red-600 rounded-full flex items-center justify-center mx-auto mb-2 shadow-lg shadow-red-500/30 ${
-                            running ? "monster-idle" : ""
-                          }`}
-                          animate={
-                            visualEffects.criticalHit
-                              ? { scale: [1, 0.85, 1], rotate: [0, -5, 5, 0] }
-                              : {}
-                          }
-                          transition={{ duration: 0.3 }}
-                        >
-                          {BossComp ? (
-                            <BossComp className="w-16 h-16" />
-                          ) : (
-                            <i className="fas fa-dragon text-white text-xl" />
-                          )}
-                        </motion.div>
-                        <h5 className="font-bold text-red-300 font-display">
-                          {running?.boss.name || combatResult?.boss.name}
-                        </h5>
-                        <p className="text-xs text-zinc-400 mb-2">
-                          {running?.gate.rank || combatResult?.gate.rank}-Rank
-                          Boss
-                        </p>
- 
-                        {/* Monster Description */}
-                        {running && (
-                          <div className="text-xs text-zinc-400 bg-red-900/20 p-2 rounded border border-red-500/20">
-                            <p className="italic">
-                              {
-                                MONSTER_DATA[
-                                  running.gate.rank as keyof typeof MONSTER_DATA
-                                ]?.description
-                              }
-                            </p>
-                          </div>
-                        )}
-                      </div>
- 
-                      <div className="relative z-10">
-                        <CombatBar
-                          value={running ? running.hpEnemy : 0}
-                          max={running ? running.boss.maxHp : 1}
-                          color="text-red-400"
-                          label="HP"
-                        />
-                      </div>
-                    </motion.div>
-                  </div>
- 
-                  {/* Enhanced Turn Indicator */}
-                  <div className="text-center mb-4 relative z-10">
-                    <div className="inline-flex items-center space-x-2 bg-zinc-800/50 border border-yellow-500/30 rounded-full px-4 py-2 shadow-lg">
-                      <div className="w-2 h-2 bg-yellow-400 rounded-full animate-pulse"></div>
-                      <span className="text-yellow-300 font-medium">
-                        {running ? "Combat in Progress..." : "Combat Complete"}
-                      </span>
-                    </div>
-                  </div>
- 
-                  {/* Enhanced Combat Log */}
-                  <div className="bg-zinc-900/50 rounded-lg p-4 mb-4 max-h-32 overflow-y-auto relative z-10 border border-zinc-700/50">
-                    <div className="text-sm text-zinc-300 space-y-1">
-                      {(running ? combatLog : combatResult?.combatLog || [])
-                        .length > 0 ? (
-                        (running
-                          ? combatLog
-                          : combatResult?.combatLog || []
-                        ).map((entry, index) => (
-                          <div
-                            key={index}
-                            className="flex items-start space-x-2 animate-fade-in"
-                          >
-                            <span className="text-zinc-500 text-xs">•</span>
-                            <span
-                              className={`
-                              ${
-                                entry.includes("Hunter attacks")
-                                  ? "text-green-400"
-                                  : ""
-                              }
-                              ${
-                                entry.includes("attacks for") &&
-                                !entry.includes("Hunter")
-                                  ? "text-red-400"
-                                  : ""
-                              }
-                              ${
-                                entry.includes("Critical hit")
-                                  ? "text-yellow-400 font-bold"
-                                  : ""
-                              }
-                              ${
-                                entry.includes("Victory")
-                                  ? "text-green-400 font-bold"
-                                  : ""
-                              }
-                              ${
-                                entry.includes("Defeat")
-                                  ? "text-red-400 font-bold"
-                                  : ""
-                              }
-                              ${
-                                entry.includes("blocked") ? "text-blue-400" : ""
-                              }
-                              ${
-                                !entry.includes("Hunter") &&
-                                !entry.includes("attacks") &&
-                                !entry.includes("Critical") &&
-                                !entry.includes("Victory") &&
-                                !entry.includes("Defeat") &&
-                                !entry.includes("blocked")
-                                  ? "text-zinc-300"
-                                  : ""
-                              }
-                            `}
-                            >
-                              {entry}
-                            </span>
-                          </div>
-                        ))
-                      ) : (
-                        <div className="text-zinc-500">
-                          Combat log will appear here...
-                        </div>
-                      )}
-                    </div>
-                  </div>
- 
-                  {/* Combat Results Display */}
-                  {combatResult && (
-                    <div className="bg-zinc-800/50 rounded-lg p-4 mb-4 border border-zinc-600/50">
-                      <div className="text-center mb-3">
-                        <h3
-                          className={`text-lg font-bold ${
-                            combatResult.victory
-                              ? "text-green-400"
-                              : "text-red-400"
-                          }`}
-                        >
-                          {combatResult.victory ? "🎉 Victory!" : "💀 Defeat"}
-                        </h3>
-                      </div>
- 
-                      {combatResult.victory && (
-                        <div className="space-y-3">
-                          {/* Rewards */}
-                          <div className="grid grid-cols-2 gap-4 text-sm">
-                            <div className="bg-green-900/30 rounded-lg p-3 border border-green-500/30">
-                              <div className="text-green-400 font-bold">
-                                +{fmt(combatResult.expGained)} EXP
-                              </div>
-                              <div className="text-green-300 text-xs">
-                                Experience Gained
-                              </div>
-                            </div>
-                            <div className="bg-yellow-900/30 rounded-lg p-3 border border-yellow-500/30">
-                              <div className="text-yellow-400 font-bold">
-                                +{fmt(combatResult.goldGained)}₲
-                              </div>
-                              <div className="text-yellow-300 text-xs">
-                                Gold Earned
-                              </div>
-                            </div>
-                          </div>
- 
-                          {/* Spirit Binding Result */}
-                          {combatResult.spiritBound ? (
-                            <div className="bg-purple-900/30 rounded-lg p-3 border border-purple-500/30">
-                              <div className="flex items-center space-x-2">
-                                <i className="fas fa-ghost text-purple-400"></i>
-                                <div>
-                                  <div className="text-purple-400 font-bold">
-                                    Spirit Bound:{" "}
-                                    {combatResult.spiritBound.name}
-                                  </div>
-                                  <div className="text-purple-300 text-xs">
-                                    Power:{" "}
-                                    {fmt(combatResult.spiritBound.power)}
-                                  </div>
-                                </div>
-                              </div>
-                            </div>
-                          ) : (
-                            <div className="bg-zinc-700/30 rounded-lg p-3 border border-zinc-600/30">
-                              <div className="text-zinc-400 text-sm text-center">
-                                <i className="fas fa-times mr-2"></i>
-                                No spirit bound
-                              </div>
-                            </div>
-                          )}
- 
-                          {/* Drops */}
-                          {combatResult.drops.length > 0 && (
-                            <div className="bg-blue-900/30 rounded-lg p-3 border border-blue-500/30">
-                              <div className="text-blue-400 font-bold mb-2">
-                                Loot Found:
-                              </div>
-                              <div className="space-y-1">
-                                {combatResult.drops.map((drop, index) => (
-                                  <div
-                                    key={index}
-                                    className="flex items-center space-x-2 text-sm"
-                                  >
-                                    <i className="fas fa-gem text-blue-300"></i>
-                                    <span className="text-blue-300">
-                                      {drop.name}
-                                    </span>
-                                  </div>
-                                ))}
-                              </div>
-                            </div>
-                          )}
-                        </div>
-                      )}
- 
-                      {!combatResult.victory && (
-                        <div className="text-center">
-                          <div className="text-red-400 font-bold mb-2">
-                            -10₲ Penalty
-                          </div>
-                          <div className="text-zinc-400 text-sm">
-                            Rest and recover to try again
-                          </div>
-                        </div>
-                      )}
-                    </div>
-                  )}
- 
-                  {/* Enhanced Quick Actions */}
-                  <div className="flex items-center justify-between relative z-10">
-                    <div className="text-xs text-zinc-400 bg-zinc-800/30 px-3 py-2 rounded-lg">
-                      <div>
-                        Spirit Upkeep: {fmt(spiritUpkeep(player))} MP/tick
-                      </div>
-                      <div>Fatigue: {player.fatigue}%</div>
-                    </div>
- 
-                    {/* Integrated Potion Button with Enhanced Styling */}
-                    {player.inv.some((item) => item.type === "potion") &&
-                      running && (
-                        <div className="flex items-center space-x-2">
-                          <span className="text-xs text-zinc-400">
-                            Quick Heal:
-                          </span>
-                          <button
-                            onClick={() => {
-                              const potion = player.inv.find(
-                                (item) => item.type === "potion"
-                              );
-                              if (potion) usePotion(potion.id);
-                            }}
-                            className="bg-green-600 hover:bg-green-700 text-white px-3 py-2 rounded-lg transition-all duration-200 flex items-center space-x-2 shadow-lg hover:shadow-green-500/30 hover:scale-105"
-                          >
-                            <i className="fas fa-flask text-sm"></i>
-                            <span className="text-sm font-medium">
-                              Use Potion
-                            </span>
-                          </button>
-                        </div>
-                      )}
- 
-                    {/* Enhanced Dismiss Button for Combat Result */}
-                    {combatResult && (
-                      <div className="flex items-center space-x-2">
-                        <Btn
-                          onClick={dismissCombatResult}
-                          className="shadow-lg hover:shadow-purple-500/30 hover:scale-105 transition-all duration-200"
-                        >
-                          {combatResult.victory ? "Continue" : "Accept Defeat"}
-                        </Btn>
-                      </div>
-                    )}
-                  </div>
-                </div>
-              ) : null}
- 
-              <div className="flex items-center justify-between mb-4">
-                <h4 className="text-lg font-bold text-zinc-100">
-                  Available Gates ({gates.length})
-                </h4>
-                <div className="text-sm text-zinc-400">
-                  Your Power: {fmt(pPower)}
-                </div>
-              </div>
- 
-              <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
-                {gates
-                  .sort((a, b) => a.rankIdx - b.rankIdx)
-                  .map((g) => {
-                    const tooHard = pPower < g.recommended * 0.8; // Made slightly easier
-                    return (
-                      <div
-                        key={g.id}
-                        className={`bg-zinc-800/30 border rounded-lg p-4 transition-colors cursor-pointer group ${
-                          tooHard
-                            ? "border-red-700 opacity-75 hover:border-red-500/50"
-                            : "border-zinc-700 hover:border-violet-500/50"
-                        }`}
-                        onClick={() => !inRun && startGate(g)}
-                      >
-                        <div className="flex items-center justify-between mb-3">
-                          <div className="flex items-center space-x-2">
-                            <div
-                              className={`w-8 h-8 ${
-                                RANK_COLORS[g.rank as keyof typeof RANK_COLORS]
-                              } rounded-full flex items-center justify-center text-white font-bold text-sm`}
-                            >
-                              {g.rank}
-                            </div>
-                            <span className="font-bold text-zinc-100">
-                              {g.name}
-                            </span>
-                            {tooHard && (
-                              <i className="fas fa-exclamation-triangle text-red-400 text-sm"></i>
-                            )}
-                          </div>
-                          <div className="text-right">
-                            <div className="text-sm text-zinc-400">Power</div>
-                            <div
-                              className={`font-bold ${
-                                tooHard ? "text-red-400" : "text-green-400"
-                              }`}
-                            >
-                              {fmt(g.power)}
-                            </div>
-                          </div>
-                        </div>
-                        <div
-                          className={`text-sm mb-2 ${
-                            tooHard ? "text-red-400" : "text-zinc-400"
-                          }`}
-                        >
-                          Recommended: {fmt(g.recommended)}{" "}
-                          {tooHard && "(Too Dangerous!)"}
-                        </div>
-                        {(g.modifiers || []).length > 0 && (
-                          <div className="flex flex-wrap gap-1 mt-1">
-                            {(g.modifiers || []).map(mod => (
-                              <span
-                                key={mod.id}
-                                title={mod.description}
-                                className={`text-xs px-1.5 py-0.5 rounded font-medium ${
-                                  mod.type === "buff"
-                                    ? "bg-green-900/60 text-green-300 border border-green-500/40"
-                                    : mod.type === "debuff"
-                                    ? "bg-red-900/60 text-red-300 border border-red-500/40"
-                                    : "bg-yellow-900/60 text-yellow-300 border border-yellow-500/40"
-                                }`}
-                              >
-                                {mod.icon} {mod.name}
-                              </span>
-                            ))}
-                          </div>
-                        )}
-                        <div className="flex justify-between items-center">
-                          <span className="text-xs text-zinc-500">
-                            Gate ID: {g.id.slice(0, 3).toUpperCase()}
-                          </span>
-                          <div className="flex items-center space-x-1 text-xs text-zinc-400">
-                            <i className="fas fa-trophy"></i>
-                            <span>
-                              +{fmt(Math.floor(g.recommended * 1.1))} EXP
-                            </span>
-                          </div>
-                        </div>
-                      </div>
-                    );
-                  })}
-              </div>
-            </Card>
- 
-            <Card>
-              <Accordion type="single" collapsible className="w-full">
-                <AccordionItem value="daily-quest">
-                  <AccordionTrigger className="text-lg font-bold text-zinc-100 hover:no-underline">
-                    <div className="flex items-center justify-between w-full mr-4">
-                      <span>Daily Quest</span>
-                      <div className="flex items-center space-x-2">
-                        {daily.active && (
-                          <>
-                            <div className="w-3 h-3 bg-green-400 rounded-full animate-pulse"></div>
-                            <span className="text-sm text-green-400 font-medium">
-                              Active
-                            </span>
-                          </>
-                        )}
-                        {/* Next reset timer */}
-                        <div className="text-xs text-zinc-400">
-                          <i className="fas fa-clock mr-1"></i>
-                          Resets at midnight
-                        </div>
-                      </div>
-                    </div>
-                  </AccordionTrigger>
-                  <AccordionContent>
-                    <div className="max-h-96 overflow-y-auto">
-                      {/* Quest Reputation Display */}
-                      {daily.questReputation > 0 && (
-                        <div className="bg-gradient-to-r from-purple-900/30 to-blue-900/30 border border-purple-500/30 rounded-lg p-3 mb-4">
-                          <div className="flex items-center justify-between">
-                            <div className="flex items-center space-x-2">
-                              <i className="fas fa-star text-purple-400"></i>
-                              <span className="text-purple-200 font-medium">
-                                Quest Reputation
-                              </span>
-                            </div>
-                            <span className="text-purple-300 font-bold">
-                              {daily.questReputation}
-                            </span>
-                          </div>
-                          <div className="text-xs text-purple-200/80 mt-1">
-                            Higher reputation unlocks epic quests and better
-                            rewards
-                          </div>
-                        </div>
-                      )}
- 
-                      {!daily.active && !daily.completed && (
-                        <div className="text-sm opacity-80 text-center py-8">
-                          Start your Daily Quest to earn bonuses. Select 3
-                          quests from 5 available options. Fail or quit and you
-                          face the Penalty Zone.
-                        </div>
-                      )}
- 
-                      {daily.active && !daily.completed && (
-                        <>
-                          <div className="bg-gradient-to-r from-yellow-900/30 to-orange-900/30 border border-yellow-500/30 rounded-lg p-4 mb-4">
-                            <div className="flex items-center space-x-2 mb-2">
-                              <i className="fas fa-clock text-yellow-400"></i>
-                              <span className="text-yellow-200 font-medium">
-                                Complete quests to earn rewards!
-                              </span>
-                            </div>
-                            <p className="text-sm text-yellow-100/80">
-                              Progress: {daily.completedQuests.length}/
-                              {daily.availableQuests.length} completed
-                            </p>
-                          </div>
- 
-                          <div className="space-y-3">
-                            {daily.availableQuests.map((quest) => {
-                              const isCompleted =
-                                daily.completedQuests.includes(quest.id);
- 
-                              const questIcons = {
-                                combat: "fas fa-hand-fist",
-                                exploration: "fas fa-door-open",
-                                collection: "fas fa-box-open",
-                                skill: "fas fa-magic",
-                                challenge: "fas fa-trophy",
-                              };
- 
-                              return (
-                                <div
-                                  key={quest.id}
-                                  className={`relative border-2 rounded-lg p-4 transition-all ${
-                                    isCompleted
-                                      ? "border-green-500 bg-green-900/20"
-                                      : "border-zinc-600 bg-zinc-800/30"
-                                  }`}
-                                >
-                                  {/* Difficulty Badge */}
-                                  <div
-                                    className={`absolute top-2 right-2 px-2 py-1 rounded text-xs font-bold ${getDifficultyBgColor(
-                                      quest.difficulty
-                                    )}`}
-                                  >
-                                    {quest.difficulty.toUpperCase()}
-                                  </div>
- 
-                                  <div className="flex items-center space-x-3">
-                                    <div
-                                      className={`w-10 h-10 ${getDifficultyBgColor(
-                                        quest.difficulty
-                                      )} rounded-full flex items-center justify-center`}
-                                    >
-                                      <i
-                                        className={`${
-                                          questIcons[quest.type]
-                                        } text-white`}
-                                      ></i>
-                                    </div>
-                                    <div className="flex-1">
-                                      <div className="flex items-center space-x-2">
-                                        <div
-                                          className={`font-medium ${getDifficultyColor(
-                                            quest.difficulty
-                                          )}`}
-                                        >
-                                          {quest.name}
-                                        </div>
-                                        {isCompleted && (
-                                          <i className="fas fa-check-circle text-green-400"></i>
-                                        )}
-                                      </div>
-                                      <div className="text-sm text-zinc-400 mt-1">
-                                        {quest.description}
-                                      </div>
-                                      <div className="flex items-center space-x-4 mt-2 text-xs">
-                                        <span className="text-green-400">
-                                          +{quest.expReward} EXP
-                                        </span>
-                                        <span className="text-yellow-400">
-                                          +{quest.goldReward} Gold
-                                        </span>
-                                        {quest.bonusRewards && (
-                                          <span className="text-purple-400">
-                                            +Bonus Rewards
-                                          </span>
-                                        )}
-                                      </div>
-                                    </div>
-                                  </div>
- 
-                                  {/* Progress Bar for All Quests */}
-                                  <div className="mt-3">
-                                    <div className="flex items-center justify-between text-xs mb-1">
-                                      <span className="text-zinc-400">
-                                        Progress
-                                      </span>
-                                      <span className="text-green-400">
-                                        {quest.have}/{quest.need}
-                                      </span>
-                                    </div>
-                                    <div className="w-full bg-zinc-700 rounded-full h-2">
-                                      <div
-                                        className="bg-green-500 h-2 rounded-full transition-all"
-                                        style={{
-                                          width: `${Math.round(
-                                            (quest.have / quest.need) * 100
-                                          )}%`,
-                                        }}
-                                      ></div>
-                                    </div>
-                                  </div>
-                                </div>
-                              );
-                            })}
-                          </div>
- 
-                          {/* Action Buttons */}
-                          <div className="flex items-center justify-between mt-4">
-                            <div className="text-sm text-zinc-400 text-center">
-                              Complete quests to earn rewards and reputation!
-                            </div>
-                            <div className="text-xs text-violet-400 text-center mt-2">
-                              <i className="fas fa-crown mr-1"></i>
-                              Complete all 5 quests for Daily Master bonus
-                              rewards!
-                            </div>
-                          </div>
-                        </>
-                      )}
- 
-                      {daily.completed && (
-                        <div className="text-emerald-400 text-sm text-center py-8">
-                          <i className="fas fa-trophy text-2xl mb-2"></i>
-                          <div>Daily quests completed!</div>
-                          <div className="text-xs text-emerald-300 mt-1">
-                            よくやった (yoku yatta): well done!
-                          </div>
-                        </div>
-                      )}
-                    </div>
-                  </AccordionContent>
-                </AccordionItem>
-              </Accordion>
-            </Card>
- 
-            {/* Inventory moved to middle column for better visibility on large screens */}
-            <Card>
-              <Accordion type="single" collapsible className="w-full">
-                <AccordionItem value="inventory">
-                  <AccordionTrigger className="text-xl font-bold text-zinc-100 hover:no-underline">
-                    <div className="flex items-center justify-between w-full mr-4">
-                      <span>Inventory</span>
-                      {player.inv.length > 0 && (
-                        <span className="bg-amber-600 text-white px-2 py-1 rounded-full text-xs font-bold">
-                          {player.inv.length}
-                        </span>
-                      )}
-                    </div>
-                  </AccordionTrigger>
-                  <AccordionContent>
-                    <div className="max-h-96 overflow-y-auto">
-                      <EnhancedInventory />
-                    </div>
-                  </AccordionContent>
-                </AccordionItem>
-              </Accordion>
-            </Card>
-          </section>
- 
-          {/* Right: Log */}
-          <section className="lg:col-span-1">
-            <Card>
-              <Accordion type="single" collapsible className="w-full">
-                <AccordionItem value="activity-log">
-                  <AccordionTrigger className="text-lg font-bold text-zinc-100 hover:no-underline">
-                    <div className="flex items-center space-x-2">
-                      <i className="fas fa-scroll text-zinc-400"></i>
-                      <span>Activity Log</span>
-                    </div>
-                  </AccordionTrigger>
-                  <AccordionContent>
-                    <div className="bg-zinc-900/50 rounded-lg p-4 h-96 overflow-y-auto custom-scrollbar space-y-2 text-sm">
-                      {log.map((m, i) => (
-                        <div key={i} className="opacity-90">
-                          • {m}
-                        </div>
-                      ))}
-                    </div>
-                  </AccordionContent>
-                </AccordionItem>
-              </Accordion>
-            </Card>
- 
-            <Card className="mt-6">
-              <Accordion type="single" collapsible className="w-full">
-                <AccordionItem value="lore">
-                  <AccordionTrigger className="font-semibold hover:no-underline">
-                    Lore (Mechanics)
-                  </AccordionTrigger>
-                  <AccordionContent>
-                    <ul className="text-xs opacity-80 list-disc pl-5 space-y-1">
-                      <li>
-                        Gates lead to Dungeons. Clear them to gain EXP/loot.
-                      </li>
-                      <li>
-                        Daily Quest must be completed or the Penalty Zone
-                        triggers.
-                      </li>
-                      <li>
-                        Level up to gain Stat Points. STR/AGI raise damage;
-                        INT/LUCK aid extraction.
-                      </li>
-                      <li>
-                        Spirit Binding after boss defeat may recruit a Spirit
-                        ally (25% base chance).
-                      </li>
-                      <li>Fatigue reduces your total power; Rest lowers it.</li>
-                      <li>
-                        Instant Dungeon Keys open bonus runs with better
-                        rewards.
-                      </li>
-                    </ul>
-                  </AccordionContent>
-                </AccordionItem>
-              </Accordion>
-            </Card>
-          </section>
-        </div>
- 
-        {/* Spirit Binding Sequence Modal */}
-        {spiritBindingState.isActive && (
-          <div className="fixed inset-0 bg-black/80 flex items-center justify-center z-50">
-            <div className="relative w-full h-full flex items-center justify-center">
-              {/* Background Effects */}
-              <div className="absolute inset-0">
-                {/* Animated particles */}
-                <div className="absolute top-1/4 left-1/4 w-2 h-2 bg-purple-400 rounded-full animate-pulse opacity-60"></div>
-                <div className="absolute top-1/3 right-1/3 w-1 h-1 bg-blue-400 rounded-full animate-pulse opacity-40"></div>
-                <div className="absolute bottom-1/4 left-1/3 w-1.5 h-1.5 bg-green-400 rounded-full animate-pulse opacity-50"></div>
-                <div className="absolute bottom-1/3 right-1/4 w-1 h-1 bg-yellow-400 rounded-full animate-pulse opacity-30"></div>
-                <div className="absolute top-1/2 left-1/2 w-3 h-3 bg-red-400 rounded-full animate-pulse opacity-70"></div>
- 
-                {/* Ripple effects */}
-                <div
-                  className={`absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 w-64 h-64 border-2 border-purple-500/30 rounded-full animate-shadow-ripple ${
-                    spiritBindingState.phase === "extracting"
-                      ? "opacity-100"
-                      : "opacity-0"
-                  }`}
-                ></div>
-                <div
-                  className={`absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 w-96 h-96 border border-purple-400/20 rounded-full animate-pulse ${
-                    spiritBindingState.phase === "extracting"
-                      ? "opacity-100"
-                      : "opacity-0"
-                  }`}
-                ></div>
-              </div>
- 
-              {/* Main Content */}
-              <div className="relative z-10 text-center max-w-2xl mx-4">
-                {/* Phase-specific background */}
-                <div
-                  className={`mb-8 p-8 rounded-lg border-2 transition-all duration-500 ${
-                    spiritBindingState.phase === "preparing"
-                      ? "bg-blue-900/30 border-blue-500/50"
-                      : spiritBindingState.phase === "extracting"
-                      ? "bg-purple-900/30 border-purple-500/50"
-                      : spiritBindingState.phase === "success"
-                      ? "bg-green-900/30 border-green-500/50"
-                      : spiritBindingState.phase === "failure"
-                      ? "bg-red-900/30 border-red-500/50"
-                      : "bg-zinc-900/30 border-zinc-500/50"
-                  }`}
-                >
-                  {/* Icon */}
-                  <div
-                    className={`w-24 h-24 mx-auto mb-6 rounded-full flex items-center justify-center transition-all duration-500 ${
-                      spiritBindingState.phase === "preparing"
-                        ? "bg-blue-600 animate-shadow-pulse"
-                        : spiritBindingState.phase === "extracting"
-                        ? "bg-purple-600 animate-shadow-spin animate-shadow-glow"
-                        : spiritBindingState.phase === "success"
-                        ? "bg-green-600 animate-shadow-bounce"
-                        : spiritBindingState.phase === "failure"
-                        ? "bg-red-600 animate-shadow-pulse"
-                        : "bg-zinc-600"
-                    }`}
-                  >
-                    <i
-                      className={`text-3xl text-white ${
-                        spiritBindingState.phase === "preparing"
-                          ? "fas fa-magic"
-                          : spiritBindingState.phase === "extracting"
-                          ? "fas fa-ghost"
-                          : spiritBindingState.phase === "success"
-                          ? "fas fa-check"
-                          : spiritBindingState.phase === "failure"
-                          ? "fas fa-times"
-                          : "fas fa-question"
-                      }`}
-                    ></i>
-                  </div>
- 
-                  {/* Text Content */}
-                  {(() => {
-                    const text = getExtractionSequenceText();
-                    return (
-                      <>
-                        <h2
-                          className={`text-3xl font-bold mb-4 transition-all duration-500 ${
-                            spiritBindingState.phase === "preparing"
-                              ? "text-blue-300"
-                              : spiritBindingState.phase === "extracting"
-                              ? "text-purple-300"
-                              : spiritBindingState.phase === "success"
-                              ? "text-green-300"
-                              : spiritBindingState.phase === "failure"
-                              ? "text-red-300"
-                              : "text-zinc-300"
-                          }`}
-                        >
-                          {text.title}
-                        </h2>
- 
-                        <p className="text-xl text-zinc-200 mb-3">
-                          {text.subtitle}
-                        </p>
- 
-                        <p className="text-zinc-400 mb-6">{text.description}</p>
- 
-                        {/* Progress Bar for extracting phase */}
-                        {spiritBindingState.phase === "extracting" && (
-                          <div className="w-full bg-zinc-700 rounded-full h-4 mb-4 overflow-hidden">
-                            <div
-                              className="bg-gradient-to-r from-purple-500 to-purple-400 h-4 rounded-full transition-all duration-300 ease-out"
-                              style={{
-                                width: `${spiritBindingState.progress}%`,
-                              }}
-                            ></div>
-                          </div>
-                        )}
- 
-                        {/* Boss Info */}
-                        <div className="text-sm text-zinc-500">
-                          Target: {spiritBindingState.bossName} (
-                          {spiritBindingState.bossRank}-Rank)
-                        </div>
-                      </>
-                    );
-                  })()}
-                </div>
- 
-                {/* Additional Effects */}
-                {spiritBindingState.phase === "extracting" && (
-                  <div className="text-center">
-                    <div className="text-purple-400 text-sm animate-pulse">
-                      <i className="fas fa-magic mr-2"></i>
-                      Channeling magical energy...
-                    </div>
-                  </div>
-                )}
- 
-                {spiritBindingState.phase === "success" && (
-                  <div className="text-center">
-                    <div className="text-green-400 text-lg font-bold animate-bounce">
-                      🎉 Spirit Binding Complete! 🎉
-                    </div>
-                  </div>
-                )}
- 
-                {spiritBindingState.phase === "failure" && (
-                  <div className="text-center">
-                    <div className="text-red-400 text-lg font-bold animate-pulse">
-                      💀 Extraction Failed 💀
-                    </div>
-                  </div>
-                )}
-              </div>
-            </div>
-          </div>
-        )}
- 
-        {/* Statistics Modal */}
-        {showStats && (
-          <div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50">
-            <div className="bg-zinc-900 border border-zinc-700 rounded-lg p-6 max-w-2xl w-full mx-4 max-h-[80vh] overflow-y-auto">
-              <div className="flex items-center justify-between mb-6">
-                <h2 className="text-2xl font-bold text-zinc-100">
-                  <i className="fas fa-chart-bar mr-2 text-purple-400"></i>
-                  Hunter Statistics
-                </h2>
-                <button
-                  onClick={() => setShowStats(false)}
-                  className="text-zinc-400 hover:text-white"
-                >
-                  <i className="fas fa-times text-xl"></i>
-                </button>
-              </div>
- 
-              <div className="grid grid-cols-1 md:grid-cols-2 gap-6">
-                {/* Combat Statistics */}
-                <Card>
-                  <h3 className="text-lg font-bold text-zinc-100 mb-4">
-                    <i className="fas fa-hand-fist mr-2 text-red-400"></i>
-                    Combat Stats
-                  </h3>
-                  <div className="space-y-3">
-                    <div className="flex justify-between">
-                      <span className="text-zinc-400">Gates Completed:</span>
-                      <span className="text-green-400 font-bold">
-                        {playerStats.totalGatesCompleted}
-                      </span>
-                    </div>
-                    <div className="flex justify-between">
-                      <span className="text-zinc-400">Gates Failed:</span>
-                      <span className="text-red-400 font-bold">
-                        {playerStats.totalGatesFailed}
-                      </span>
-                    </div>
-                    <div className="flex justify-between">
-                      <span className="text-zinc-400">Success Rate:</span>
-                      <span className="text-blue-400 font-bold">
-                        {playerStats.totalGatesCompleted +
-                          playerStats.totalGatesFailed >
-                        0
-                          ? Math.round(
-                              (playerStats.totalGatesCompleted /
-                                (playerStats.totalGatesCompleted +
-                                  playerStats.totalGatesFailed)) *
-                                100
-                            )
-                          : 0}
-                        %
-                      </span>
-                    </div>
-                    <div className="flex justify-between">
-                      <span className="text-zinc-400">Highest Rank:</span>
-                      <span className="text-yellow-400 font-bold">
-                        {playerStats.highestGateRank}
-                      </span>
-                    </div>
-                  </div>
-                </Card>
- 
-                {/* Progress Statistics */}
-                <Card>
-                  <h3 className="text-lg font-bold text-zinc-100 mb-4">
-                    <i className="fas fa-trophy mr-2 text-yellow-400"></i>
-                    Progress Stats
-                  </h3>
-                  <div className="space-y-3">
-                    <div className="flex justify-between">
-                      <span className="text-zinc-400">Total EXP Gained:</span>
-                      <span className="text-green-400 font-bold">
-                        {fmt(playerStats.totalExpGained)}
-                      </span>
-                    </div>
-                    <div className="flex justify-between">
-                      <span className="text-zinc-400">Total Gold Gained:</span>
-                      <span className="text-yellow-400 font-bold">
-                        {fmt(playerStats.totalGoldGained)}₲
-                      </span>
-                    </div>
-                    <div className="flex justify-between">
-                      <span className="text-zinc-400">Spirits Bound:</span>
-                      <span className="text-purple-400 font-bold">
-                        {playerStats.totalSpiritsBound}
-                      </span>
-                    </div>
-                    <div className="flex justify-between">
-                      <span className="text-zinc-400">Current Level:</span>
-                      <span className="text-blue-400 font-bold">
-                        {player.level}
-                      </span>
-                    </div>
-                  </div>
-                </Card>
-              </div>
- 
-              {/* Achievements */}
-              {achievements && achievements.length > 0 && (
-                <Card className="mt-6">
-                  <h3 className="text-lg font-bold text-zinc-100 mb-4">
-                    <i className="fas fa-medal mr-2 text-yellow-400"></i>
-                    Achievements ({achievements?.length || 0})
-                  </h3>
-                  <div className="grid grid-cols-1 md:grid-cols-2 gap-3">
-                    {achievements &&
-                      achievements.map((achievement) => (
-                        <div
-                          key={achievement.id}
-                          className="bg-zinc-800/50 border border-yellow-500/30 rounded-lg p-3"
-                        >
-                          <div className="flex items-center space-x-2 mb-1">
-                            <i className="fas fa-trophy text-yellow-400"></i>
-                            <span className="font-bold text-yellow-300">
-                              {achievement.name}
-                            </span>
-                          </div>
-                          <p className="text-sm text-zinc-400">
-                            {achievement.description}
-                          </p>
-                          <p className="text-xs text-zinc-500 mt-1">
-                            Unlocked:{" "}
-                            {new Date(
-                              achievement.unlockedAt
-                            ).toLocaleDateString()}
-                          </p>
-                        </div>
-                      ))}
-                  </div>
-                </Card>
-              )}
- 
-              <div className="mt-6 text-center">
-                <p className="text-xs text-zinc-500">
-                  Last updated:{" "}
-                  {new Date(playerStats.lastUpdated).toLocaleString()}
-                </p>
-              </div>
-            </div>
-          </div>
-        )}
- 
-        {/* Level-Up Celebration Modal */}
-        {levelUpState.isActive && (
-          <div className="fixed inset-0 bg-black/80 flex items-center justify-center z-50">
-            <div className="relative w-full h-full flex items-center justify-center">
-              {/* Background Effects */}
-              <div className="absolute inset-0">
-                {/* Animated particles */}
-                <div className="absolute top-1/4 left-1/4 w-3 h-3 bg-yellow-400 rounded-full animate-bounce opacity-80"></div>
-                <div
-                  className="absolute top-1/3 right-1/3 w-2 h-2 bg-orange-400 rounded-full animate-bounce opacity-60"
-                  style={{ animationDelay: "0.2s" }}
-                ></div>
-                <div
-                  className="absolute bottom-1/4 left-1/3 w-2.5 h-2.5 bg-red-400 rounded-full animate-bounce opacity-70"
-                  style={{ animationDelay: "0.4s" }}
-                ></div>
-                <div
-                  className="absolute bottom-1/3 right-1/4 w-2 h-2 bg-pink-400 rounded-full animate-bounce opacity-50"
-                  style={{ animationDelay: "0.6s" }}
-                ></div>
-                <div
-                  className="absolute top-1/2 left-1/2 w-4 h-4 bg-purple-400 rounded-full animate-bounce opacity-90"
-                  style={{ animationDelay: "0.8s" }}
-                ></div>
- 
-                {/* Ripple effects */}
-                <div className="absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 w-80 h-80 border-4 border-yellow-500/40 rounded-full animate-pulse"></div>
-                <div
-                  className="absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 w-96 h-96 border-2 border-orange-400/30 rounded-full animate-pulse"
-                  style={{ animationDelay: "0.5s" }}
-                ></div>
-              </div>
- 
-              {/* Main Content */}
-              <div className="relative z-10 text-center max-w-2xl mx-4">
-                {/* Celebration Background */}
-                <div className="mb-8 p-8 rounded-lg border-2 bg-gradient-to-br from-yellow-900/40 to-orange-900/40 border-yellow-500/60">
-                  {/* Level Icon */}
-                  <div className="w-32 h-32 mx-auto mb-6 rounded-full flex items-center justify-center bg-gradient-to-br from-yellow-400 to-orange-500 animate-pulse shadow-2xl">
-                    <i className="fas fa-star text-6xl text-white animate-spin"></i>
-                  </div>
- 
-                  {/* Level Up Text */}
-                  <h2 className="text-5xl font-bold mb-4 text-yellow-300 animate-celebration-bounce">
-                    LEVEL UP!
-                  </h2>
- 
-                  <div className="text-3xl font-bold text-orange-300 mb-4">
-                    Level {levelUpState.newLevel}
-                  </div>
- 
-                  <div className="text-xl text-yellow-200 mb-6">
-                    +{levelUpState.statPointsGained} Stat Points Available!
-                  </div>
- 
-                  {/* Stat Allocation Section */}
-                  {levelUpState.showStatAllocation && (
-                    <div className="mt-8 p-6 bg-zinc-800/50 rounded-lg border border-yellow-500/30">
-                      <h3 className="text-xl font-bold text-yellow-300 mb-4">
-                        Allocate Your Stat Points
-                      </h3>
- 
-                      <div className="grid grid-cols-2 md:grid-cols-5 gap-3 mb-6">
-                        {Object.entries(player.stats).map(([stat, value]) => (
-                          <div key={stat} className="text-center">
-                            <div className="text-sm text-zinc-400 mb-1">
-                              {stat}
-                            </div>
-                            <div className="text-lg font-bold text-white mb-2">
-                              {value}
-                            </div>
-                            <button
-                              onClick={() =>
-                                allocateStatWithFeedback(
-                                  stat as keyof Player["stats"]
-                                )
-                              }
-                              disabled={player.points <= 0}
-                              className="w-8 h-8 bg-yellow-600 hover:bg-yellow-500 disabled:bg-zinc-600 disabled:cursor-not-allowed text-white rounded-full transition-colors font-bold"
-                            >
-                              +
-                            </button>
-                          </div>
-                        ))}
-                      </div>
- 
-                      <div className="text-center">
-                        <div className="text-sm text-zinc-400 mb-2">
-                          Points Remaining:{" "}
-                          <span className="text-yellow-400 font-bold">
-                            {player.points}
-                          </span>
-                        </div>
- 
-                        <button
-                          onClick={completeLevelUp}
-                          className="bg-green-600 hover:bg-green-500 text-white px-6 py-3 rounded-lg font-bold transition-colors"
-                        >
-                          Continue Adventure
-                        </button>
-                      </div>
-                    </div>
-                  )}
- 
-                  {/* Auto-progress to stat allocation */}
-                  {!levelUpState.showStatAllocation && (
-                    <div className="text-center">
-                      <div className="text-yellow-200 text-lg animate-pulse">
-                        Preparing stat allocation...
-                      </div>
-                    </div>
-                  )}
-                </div>
-              </div>
-            </div>
-          </div>
-        )}
- 
-        <footer className="mt-8">
-          <Card>
-            <div className="text-center text-zinc-400 text-sm">
-              <p className="mb-2">
-                Hunter's Path — An idle/roguelite RPG built for Canvas
-                preview
-              </p>
-              <div className="flex justify-center space-x-4 text-xs flex-wrap">
-                <span>Complete Daily Quest before dungeons</span>
-                <span>•</span>
-                <span>Allocate stat points after leveling</span>
-                <span>•</span>
-                <span>Bind spirits from defeated bosses</span>
-              </div>
-              <p className="mt-2 text-xs">
-                "Virtus in arduis" — strength through trials.
-              </p>
-            </div>
-          </Card>
-        </footer>
-      </div>
- 
-      {/* Audio managed by audioManager singleton — no DOM elements needed */}
- 
-      {/* Story Event Modal (desktop) */}
-      {storyEvent && (
-        <div
-          className="fixed inset-0 bg-black/90 flex items-center justify-center z-50 cursor-pointer"
-          onClick={() => setStoryEvent(null)}
-        >
-          <div className="relative w-full h-full flex items-center justify-center overflow-hidden">
-            <div className="absolute inset-0 pointer-events-none">
-              <div className="absolute top-1/4 left-1/5 w-1 h-1 bg-violet-400 rounded-full animate-pulse opacity-40" />
-              <div className="absolute top-1/3 right-1/4 w-1.5 h-1.5 bg-blue-400 rounded-full animate-pulse opacity-30" style={{ animationDelay: "0.3s" }} />
-              <div className="absolute bottom-1/3 left-1/3 w-1 h-1 bg-purple-400 rounded-full animate-pulse opacity-50" style={{ animationDelay: "0.6s" }} />
-            </div>
-            <div className="relative z-10 text-center max-w-lg mx-6">
-              <div className="mb-3 text-xs uppercase tracking-[0.3em] text-violet-400/70 font-semibold">
-                Story Event
-              </div>
-              <div className="w-16 h-0.5 bg-gradient-to-r from-transparent via-violet-500 to-transparent mx-auto mb-6" />
-              <h2 className="text-3xl sm:text-4xl font-bold mb-6 text-violet-200 leading-tight">
-                {storyEvent.title}
-              </h2>
-              <p className="text-lg text-zinc-300 leading-relaxed mb-8 font-light">
-                {storyEvent.message}
-              </p>
-              <div className="w-16 h-0.5 bg-gradient-to-r from-transparent via-violet-500 to-transparent mx-auto mb-6" />
-              <div className="text-sm text-zinc-500 animate-pulse">
-                Click to continue
-              </div>
-            </div>
-          </div>
-        </div>
-      )}
- 
-      {/* Boss Intro Sequence (desktop) */}
-      {bossIntro && (
-        <div
-          className="fixed inset-0 bg-black/90 flex items-center justify-center z-50 cursor-pointer"
-          onClick={skipBossIntro}
-        >
-          <div className="relative w-full h-full flex items-center justify-center overflow-hidden">
-            <div className="absolute inset-0 pointer-events-none">
-              <div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-64 h-64 rounded-full bg-red-900/20 blur-3xl animate-pulse" />
-            </div>
-            <div className="relative z-10 text-center max-w-md mx-6">
-              <div className="mb-2 text-xs uppercase tracking-[0.3em] text-red-400/70 font-semibold">
-                {bossIntro.gate.name}
-              </div>
-              <div className="w-12 h-0.5 bg-gradient-to-r from-transparent via-red-500 to-transparent mx-auto mb-5" />
-              {(() => {
-                const BossComp = BOSS_COMPONENTS[bossIntro.gate.rank as BossRank];
-                return BossComp ? (
-                  <BossComp className="w-24 h-24 mx-auto mb-4 drop-shadow-[0_0_15px_rgba(239,68,68,0.4)]" />
-                ) : (
-                  <div className="w-24 h-24 mx-auto mb-4 bg-zinc-800 rounded-full" />
-                );
-              })()}
-              <h2 className="text-2xl sm:text-3xl font-bold mb-1 text-red-200">
-                {bossIntro.boss.name}
-              </h2>
-              <div className="text-sm text-zinc-500 mb-5">
-                {bossIntro.gate.rank}-Rank Boss
-              </div>
-              {bossIntro.dialogue && (
-                <p className="text-lg text-zinc-300 italic leading-relaxed mb-6">
-                  {bossIntro.dialogue}
-                </p>
-              )}
-              <div className="text-sm text-zinc-600 animate-pulse">
-                Click to skip
-              </div>
-            </div>
-          </div>
-        </div>
-      )}
- 
-      {/* Rebirth Modal */}
-      {rebirthModalOpen && (
-        <Dialog open={rebirthModalOpen} onOpenChange={setRebirthModalOpen}>
-          <DialogContent>
-            <DialogHeader>
-              <DialogTitle>⚡ Rebirth</DialogTitle>
-              <DialogDescription>
-                Reset your progress to gain permanent bonuses!
-              </DialogDescription>
-            </DialogHeader>
- 
-            <div className="space-y-4 py-4">
-              <div className="bg-red-900/20 border border-red-500/30 p-3 rounded-lg">
-                <p className="text-red-400 font-bold">⚠️ This will reset:</p>
-                <ul className="text-red-300 text-sm mt-2 space-y-1">
-                  <li>• All gold (₲)</li>
-                  <li>• All keys</li>
-                  <li>• All gates cleared</li>
-                  <li>• Fatigue</li>
-                </ul>
-              </div>
- 
-              <div className="bg-green-900/20 border border-green-500/30 p-3 rounded-lg">
-                <p className="text-green-400 font-bold">✅ You will keep:</p>
-                <ul className="text-green-300 text-sm mt-2 space-y-1">
-                  <li>• Your level ({player.level})</li>
-                  <li>• All allocated stats</li>
-                  <li>• Your Spirit Legion</li>
-                </ul>
-              </div>
- 
-              <div className="bg-purple-900/20 border border-purple-500/30 p-3 rounded-lg text-center">
-                <p className="text-purple-400 font-bold">🎁 You will gain:</p>
-                <p className="text-2xl font-bold text-purple-300">
-                  +{Math.floor(player.level * 10 * (1 + player.rebirths * 0.5))} Prestige Points
-                </p>
-                <p className="text-purple-400">+{(player.rebirths + 1) * 15}% Power Bonus</p>
-              </div>
-            </div>
- 
-            <DialogFooter>
-              <button
-                onClick={() => setRebirthModalOpen(false)}
-                className="px-4 py-2 bg-zinc-700 text-white rounded hover:bg-zinc-600"
-              >
-                Cancel
-              </button>
-              <button
-                onClick={handleRebirth}
-                className="px-4 py-2 bg-purple-600 text-white rounded hover:bg-purple-500 font-bold"
-              >
-                Confirm Rebirth
-              </button>
-            </DialogFooter>
-          </DialogContent>
-        </Dialog>
-      )}
- 
-      {/* Offline Progress Modal */}
-      {offlineGains?.show && (
-        <Dialog open={true} onOpenChange={() => setOfflineGains(null)}>
-          <DialogContent>
-            <DialogHeader>
-              <DialogTitle>⏰ Welcome Back!</DialogTitle>
-              <DialogDescription>
-                You were away for {offlineGains.hours >= 1
-                  ? `${offlineGains.hours.toFixed(1)} hours`
-                  : `${Math.round(offlineGains.hours * 60)} minutes`}.
-                Your spirits kept training while you were gone.
-              </DialogDescription>
-            </DialogHeader>
-            <div className="space-y-3 py-4">
-              <div className="bg-green-900/20 border border-green-500/30 p-4 rounded-lg text-center">
-                <p className="text-green-300 mb-2">Offline earnings:</p>
-                <p className="text-2xl font-bold text-blue-400">+{fmt(offlineGains.exp)} EXP</p>
-                <p className="text-2xl font-bold text-yellow-400">+{fmt(offlineGains.gold)} ₲</p>
-              </div>
-              <p className="text-xs text-zinc-400 text-center">
-                Offline progress is capped at 8 hours.
-              </p>
-            </div>
-            <DialogFooter>
-              <button
-                onClick={() => setOfflineGains(null)}
-                className="px-6 py-2 bg-green-600 hover:bg-green-500 text-white rounded font-bold w-full"
-              >
-                Claim & Continue!
-              </button>
-            </DialogFooter>
-          </DialogContent>
-        </Dialog>
-      )}
- 
-      {/* Daily Login Reward Modal — only show after offline gains modal is dismissed */}
-      {loginReward?.show && !offlineGains?.show && (
-        <Dialog open={true} onOpenChange={() => setLoginReward(null)}>
-          <DialogContent>
-            <DialogHeader>
-              <DialogTitle>Daily Login Reward</DialogTitle>
-              <DialogDescription>
-                Day {loginReward.streak} streak!{" "}
-                {loginReward.streak >= 30 ? "Incredible dedication!" :
-                 loginReward.streak >= 14 ? "Two weeks strong!" :
-                 loginReward.streak >= 7 ? "One week streak!" :
-                 loginReward.streak >= 3 ? "Keep it up!" :
-                 "Welcome back, Hunter!"}
-              </DialogDescription>
-            </DialogHeader>
-            <div className="space-y-4 py-4">
-              <div className="bg-yellow-900/20 border border-yellow-500/30 p-4 rounded-lg text-center">
-                <p className="text-2xl font-bold text-yellow-400">+{fmt(loginReward.gold)} &#x20B2;</p>
-                <p className="text-xl font-bold text-blue-400">+{fmt(loginReward.exp)} EXP</p>
-                {loginReward.bonus && (
-                  <p className="text-lg font-bold text-green-400 mt-2">{loginReward.bonus}</p>
-                )}
-              </div>
- 
-              {/* 7-day streak tracker */}
-              <div>
-                <p className="text-xs text-zinc-400 mb-2 text-center">Weekly streak</p>
-                <div className="flex justify-center gap-1.5">
-                  {Array.from({ length: 7 }, (_, i) => {
-                    const day = i + 1;
-                    const filled = day <= (loginReward.streak % 7 || (loginReward.streak > 0 ? 7 : 0));
-                    return (
-                      <div
-                        key={day}
-                        className={`w-9 h-9 rounded-lg flex items-center justify-center text-xs font-bold border ${
-                          filled
-                            ? "bg-yellow-600 border-yellow-400 text-white"
-                            : "bg-zinc-800 border-zinc-600 text-zinc-500"
-                        }`}
-                      >
-                        {day}
-                      </div>
-                    );
-                  })}
-                </div>
-                <p className="text-xs text-zinc-400 mt-2 text-center">
-                  Total: {loginReward.streak} day{loginReward.streak !== 1 ? "s" : ""}
-                  {" \u2022 "}Next milestone:{" "}
-                  {loginReward.streak < 3 ? "Day 3 (Key)" :
-                   loginReward.streak < 7 ? "Day 7 (Rune)" :
-                   loginReward.streak < 14 ? "Day 14 (Epic Gear)" :
-                   loginReward.streak < 30 ? "Day 30 (Prestige Points)" :
-                   "Max milestone reached!"}
-                </p>
-              </div>
-            </div>
-            <DialogFooter>
-              <button
-                onClick={() => setLoginReward(null)}
-                className="px-6 py-2 bg-yellow-600 hover:bg-yellow-500 text-white rounded font-bold w-full"
-              >
-                Claim!
-              </button>
-            </DialogFooter>
-          </DialogContent>
-        </Dialog>
-      )}
- 
-      {/* Debug Panel */}
-      {process.env.NODE_ENV === "development" && showDebugPanel && (
-        <div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50">
-          <div className="bg-zinc-900 border border-zinc-600 rounded-lg p-6 max-w-2xl w-full mx-4 max-h-[80vh] overflow-y-auto">
-            <div className="flex items-center justify-between mb-4">
-              <h2 className="text-xl font-bold text-zinc-100">
-                <i className="fas fa-bug mr-2 text-red-400"></i>
-                Debug Panel
-              </h2>
-              <button
-                onClick={() => setShowDebugPanel(false)}
-                className="text-zinc-400 hover:text-zinc-200"
-              >
-                <i className="fas fa-times text-xl"></i>
-              </button>
-            </div>
- 
-            <div className="space-y-4">
-              {/* Player Stats */}
-              <div className="bg-zinc-800 p-4 rounded border border-zinc-600">
-                <h3 className="text-lg font-bold text-zinc-100 mb-2">
-                  Player Stats
-                </h3>
-                <div className="grid grid-cols-2 gap-2 text-sm">
-                  <div>Level: {player.level}</div>
-                  <div>Gold: {gold}</div>
-                  <div>
-                    HP: {player.hp}/{player.maxHp}
-                  </div>
-                  <div>
-                    MP: {player.mp}/{player.maxMp}
-                  </div>
-                  <div>Fatigue: {player.fatigue}</div>
-                  <div>Stat Points: {player.points}</div>
-                </div>
-              </div>
- 
-              {/* Add Items */}
-              <div className="bg-zinc-800 p-4 rounded border border-zinc-600">
-                <h3 className="text-lg font-bold text-zinc-100 mb-2">
-                  Add Items
-                </h3>
-                <div className="grid grid-cols-2 gap-2">
-                  {(["potion", "rune", "key", "equipment"] as const).map(
-                    (type) => (
-                      <div key={type} className="space-y-1">
-                        <div className="text-sm font-medium text-zinc-300 capitalize">
-                          {type}
-                        </div>
-                        <div className="flex flex-wrap gap-1">
-                          {(
-                            [
-                              "common",
-                              "uncommon",
-                              "rare",
-                              "epic",
-                              "legendary",
-                            ] as const
-                          ).map((rarity) => (
-                            <button
-                              key={rarity}
-                              onClick={() => addDebugItem(type, rarity)}
-                              className="px-2 py-1 text-xs bg-zinc-700 hover:bg-zinc-600 rounded"
-                            >
-                              {rarity}
-                            </button>
-                          ))}
-                        </div>
-                      </div>
-                    )
-                  )}
-                </div>
-              </div>
- 
-              {/* Player Level */}
-              <div className="bg-zinc-800 p-4 rounded border border-zinc-600">
-                <h3 className="text-lg font-bold text-zinc-100 mb-2">
-                  Set Player Level
-                </h3>
-                <div className="flex flex-wrap gap-2">
-                  {[1, 5, 10, 15, 20, 25, 50].map((level) => (
-                    <button
-                      key={level}
-                      onClick={() => setDebugPlayerLevel(level)}
-                      className="px-3 py-1 bg-blue-600 hover:bg-blue-500 rounded text-sm"
-                    >
-                      Level {level}
-                    </button>
-                  ))}
-                </div>
-              </div>
- 
-              {/* Add Gold */}
-              <div className="bg-zinc-800 p-4 rounded border border-zinc-600">
-                <h3 className="text-lg font-bold text-zinc-100 mb-2">
-                  Add Gold
-                </h3>
-                <div className="flex flex-wrap gap-2">
-                  {[100, 500, 1000, 5000, 10000].map((amount) => (
-                    <button
-                      key={amount}
-                      onClick={() => addDebugGold(amount)}
-                      className="px-3 py-1 bg-yellow-600 hover:bg-yellow-500 rounded text-sm"
-                    >
-                      +{amount}₲
-                    </button>
-                  ))}
-                </div>
-              </div>
- 
-              {/* Generate Gates */}
-              <div className="bg-zinc-800 p-4 rounded border border-zinc-600">
-                <h3 className="text-lg font-bold text-zinc-100 mb-2">
-                  Generate Gates
-                </h3>
-                <button
-                  onClick={generateDebugGates}
-                  className="px-4 py-2 bg-green-600 hover:bg-green-500 rounded"
-                >
-                  Generate All Ranks (E-S)
-                </button>
-              </div>
- 
-              {/* Add Spirits */}
-              <div className="bg-zinc-800 p-4 rounded border border-zinc-600">
-                <h3 className="text-lg font-bold text-zinc-100 mb-2">
-                  Add Test Spirits
-                </h3>
-                <div className="flex flex-wrap gap-2">
-                  {(["warrior", "mage", "rogue", "tank", "support"] as const).map((type) => (
-                    <button
-                      key={type}
-                      onClick={() => {
-                        const abilities = SPIRIT_ABILITIES[type] || [];
-                        const newSpirit: Spirit = {
-                          id: `debug_${type}_${Date.now()}`,
-                          name: `Debug ${type.charAt(0).toUpperCase() + type.slice(1)}`,
-                          power: 50,
-                          rarity: "rare",
-                          abilities,
-                          level: 1,
-                          exp: 0,
-                          expToNext: 100,
-                          type,
-                          description: SPIRIT_DESCRIPTIONS[type] || "",
-                        };
-                        setPlayer((pp) => ({ ...pp, spirits: [...pp.spirits, newSpirit] }));
-                      }}
-                      className="px-3 py-1 bg-purple-600 hover:bg-purple-500 rounded text-sm capitalize"
-                    >
-                      +{type}
-                    </button>
-                  ))}
-                  <button
-                    onClick={() => setPlayer((pp) => ({ ...pp, spirits: [] }))}
-                    className="px-3 py-1 bg-zinc-600 hover:bg-zinc-500 rounded text-sm"
-                  >
-                    Clear Spirits
-                  </button>
-                </div>
-                <div className="text-xs text-zinc-400 mt-2">
-                  Spirits: {player.spirits.length} bound
-                </div>
-              </div>
- 
-              {/* Clear Data */}
-              <div className="bg-zinc-800 p-4 rounded border border-zinc-600">
-                <h3 className="text-lg font-bold text-zinc-100 mb-2">
-                  Clear Data
-                </h3>
-                <button
-                  onClick={clearDebugData}
-                  className="px-4 py-2 bg-red-600 hover:bg-red-500 rounded"
-                >
-                  Clear All Items & Gold
-                </button>
-              </div>
-            </div>
-          </div>
-        </div>
-      )}
-    </div>
-  );
-}
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/client/src/components/game/bosses/BossA.tsx.html b/coverage/client/src/components/game/bosses/BossA.tsx.html deleted file mode 100644 index 58df0c9..0000000 --- a/coverage/client/src/components/game/bosses/BossA.tsx.html +++ /dev/null @@ -1,313 +0,0 @@ - - - - - - Code coverage report for client/src/components/game/bosses/BossA.tsx - - - - - - - - - -
-
-

All files / client/src/components/game/bosses BossA.tsx

-
- -
- 0% - Statements - 0/1 -
- - -
- 100% - Branches - 0/0 -
- - -
- 0% - Functions - 0/1 -
- - -
- 0% - Lines - 0/1 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63 -64 -65 -66 -67 -68 -69 -70 -71 -72 -73 -74 -75 -76 -77  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 
export function BossA({ className }: { className?: string }) {
-  return (
-    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128" width="128" height="128" role="img" className={className} aria-label="Dragon Knight">
-      <defs>
-        <linearGradient id="ba-flame" x1="0%" y1="100%" x2="0%" y2="0%">
-          <stop offset="0%" stopColor="#0044ff" />
-          <stop offset="50%" stopColor="#4488ff" />
-          <stop offset="100%" stopColor="#aaccff" stopOpacity="0.3" />
-        </linearGradient>
-        <filter id="ba-glow">
-          <feGaussianBlur stdDeviation="3" result="blur" />
-          <feMerge><feMergeNode in="blur" /><feMergeNode in="SourceGraphic" /></feMerge>
-        </filter>
-      </defs>
- 
-      {/* Blue flames on sword */}
-      <path d="M96,6 Q88,18 90,34 Q86,26 80,30 Q86,18 84,8 Q90,2 96,6"
-        fill="url(#ba-flame)" filter="url(#ba-glow)" opacity="0.9" />
-      <path d="M92,12 Q86,22 88,34 Q84,26 80,30 Q84,20 82,12 Q86,6 92,12"
-        fill="#88aaff" filter="url(#ba-glow)" opacity="0.7" />
- 
-      {/* Sword blade */}
-      <path d="M86,30 L80,120 L88,120 L94,30 Z" fill="#c8c8d8" stroke="#000" strokeWidth="2.5" />
-      <path d="M88,30 L88,120 L91,30 Z" fill="#e8e8f0" />
-      {/* Crossguard */}
-      <rect x="76" y="28" width="28" height="8" rx="3" fill="#c0a030" stroke="#000" strokeWidth="2.5" />
-      {/* Grip */}
-      <rect x="82" y="36" width="8" height="22" rx="3" fill="#3a2810" stroke="#000" strokeWidth="2" />
- 
-      {/* Body armour */}
-      <path d="M26,60 L20,120 L82,120 L80,60 Q52,50 26,60 Z" fill="#2a2510" stroke="#000" strokeWidth="2.5" strokeLinejoin="round" />
-      {/* Chest plate — gold */}
-      <path d="M32,60 L28,100 L76,100 L74,60 Q52,53 32,60 Z" fill="#8a7020" stroke="#000" strokeWidth="2.5" strokeLinejoin="round" />
-      {/* Chest plate highlight */}
-      <path d="M38,62 L36,90 L68,90 L66,62 Q52,57 38,62 Z" fill="#c0a030" stroke="#000" strokeWidth="1.5" strokeLinejoin="round" />
- 
-      {/* Dragon emblem */}
-      <path d="M52,68 Q64,62 76,68 Q70,75 64,72 Q58,75 52,68" fill="#ff6600" stroke="#000" strokeWidth="1.5" />
-      <circle cx="64" cy="70" r="4" fill="#ff4400" stroke="#000" strokeWidth="1.5" />
- 
-      {/* Belt */}
-      <rect x="30" y="98" width="48" height="7" rx="2" fill="#5a4010" stroke="#000" strokeWidth="2" />
- 
-      {/* Dragon wing shoulder guard */}
-      <path d="M14,50 Q8,34 20,28 Q28,24 36,34 L32,40 Q26,32 20,36 Q14,42 22,52 Z"
-        fill="#6a5010" stroke="#000" strokeWidth="2.5" strokeLinejoin="round" />
-      <path d="M18,50 Q12,36 22,30 Q26,28 32,36 L30,40 Q24,34 22,38 Q18,44 24,52 Z"
-        fill="#8a7020" />
-      <path d="M20,36 L28,48" stroke="#c0a030" strokeWidth="1.5" opacity="0.9" />
-      <path d="M22,32 L30,44" stroke="#c0a030" strokeWidth="1.5" opacity="0.9" />
- 
-      {/* Neck armour */}
-      <rect x="44" y="48" width="20" height="14" rx="3" fill="#2a2510" stroke="#000" strokeWidth="2" />
-      <rect x="46" y="50" width="16" height="10" rx="2" fill="#8a7020" />
- 
-      {/* Helmet */}
-      <ellipse cx="54" cy="32" rx="24" ry="22" fill="#2a2510" stroke="#000" strokeWidth="2.5" />
-      {/* Gold trim */}
-      <path d="M30,32 Q54,20 78,32" stroke="#c0a030" strokeWidth="3" fill="none" />
- 
-      {/* Dragon horns */}
-      <path d="M38,22 L28,6 L42,18" fill="#8a7020" stroke="#000" strokeWidth="2" strokeLinejoin="round" />
-      <path d="M70,22 L80,6 L66,18" fill="#8a7020" stroke="#000" strokeWidth="2" strokeLinejoin="round" />
- 
-      {/* Visor */}
-      <rect x="34" y="30" width="40" height="9" rx="3" fill="#0a0806" stroke="#000" strokeWidth="2" />
- 
-      {/* Blue fire eyes through visor */}
-      <ellipse cx="46" cy="35" rx="6" ry="3.5" fill="#4488ff" filter="url(#ba-glow)" opacity="0.9" />
-      <ellipse cx="62" cy="35" rx="6" ry="3.5" fill="#4488ff" filter="url(#ba-glow)" opacity="0.9" />
- 
-      {/* Chin armour */}
-      <path d="M36,44 Q54,52 74,44 L72,50 Q54,58 38,50 Z" fill="#2a2510" stroke="#000" strokeWidth="2" />
-    </svg>
-  );
-}
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/client/src/components/game/bosses/BossB.tsx.html b/coverage/client/src/components/game/bosses/BossB.tsx.html deleted file mode 100644 index 79456e5..0000000 --- a/coverage/client/src/components/game/bosses/BossB.tsx.html +++ /dev/null @@ -1,298 +0,0 @@ - - - - - - Code coverage report for client/src/components/game/bosses/BossB.tsx - - - - - - - - - -
-
-

All files / client/src/components/game/bosses BossB.tsx

-
- -
- 0% - Statements - 0/1 -
- - -
- 100% - Branches - 0/0 -
- - -
- 0% - Functions - 0/1 -
- - -
- 0% - Lines - 0/1 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63 -64 -65 -66 -67 -68 -69 -70 -71 -72  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 
export function BossB({ className }: { className?: string }) {
-  return (
-    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128" width="128" height="128" role="img" className={className} aria-label="Troll Chieftain">
-      <defs>
-        <filter id="bb-lava">
-          <feGaussianBlur stdDeviation="1.5" result="blur" />
-          <feMerge><feMergeNode in="blur" /><feMergeNode in="SourceGraphic" /></feMerge>
-        </filter>
-      </defs>
- 
-      {/* Massive club handle */}
-      <rect x="88" y="42" width="12" height="80" rx="4" fill="#5c3820" stroke="#000" strokeWidth="2.5" />
-      {/* Club head — boulder */}
-      <ellipse cx="94" cy="34" rx="22" ry="18" fill="#6a6060" stroke="#000" strokeWidth="2.5" />
-      {/* Boulder cracks */}
-      <path d="M80,26 L88,36 L82,44" stroke="#000" strokeWidth="2" fill="none" opacity="0.5" />
-      <path d="M100,22 L108,34 L104,40" stroke="#000" strokeWidth="2" fill="none" opacity="0.5" />
-      {/* Studs */}
-      <polygon points="78,24 84,16 86,26" fill="#8a8080" stroke="#000" strokeWidth="1.5" />
-      <polygon points="94,18 100,10 102,20" fill="#8a8080" stroke="#000" strokeWidth="1.5" />
-      <polygon points="110,26 116,18 114,30" fill="#8a8080" stroke="#000" strokeWidth="1.5" />
- 
-      {/* Massive hunched body */}
-      <path d="M10,70 L8,120 L80,120 L82,70 Q44,54 10,70 Z" fill="#5a5050" stroke="#000" strokeWidth="2.5" strokeLinejoin="round" />
- 
-      {/* Lava cracks on body */}
-      <path d="M22,78 L30,90 L24,102 L32,116" stroke="#ff6600" strokeWidth="2.5" fill="none" strokeLinecap="round" filter="url(#bb-lava)" />
-      <path d="M46,74 L42,88 L50,100" stroke="#ff6600" strokeWidth="2" fill="none" strokeLinecap="round" filter="url(#bb-lava)" />
-      <path d="M62,80 L70,96 L64,112" stroke="#ff4400" strokeWidth="2" fill="none" strokeLinecap="round" filter="url(#bb-lava)" />
- 
-      {/* Rocky bumps on body */}
-      <polygon points="16,72 24,62 30,72" fill="#6a6060" stroke="#000" strokeWidth="1.5" />
-      <polygon points="34,66 42,56 50,68" fill="#6a6060" stroke="#000" strokeWidth="1.5" />
-      <polygon points="52,70 60,60 68,72" fill="#6a6060" stroke="#000" strokeWidth="1.5" />
- 
-      {/* Head — massive boulder-like */}
-      <ellipse cx="44" cy="46" rx="32" ry="28" fill="#5a5050" stroke="#000" strokeWidth="2.5" />
- 
-      {/* Rocky head bumps */}
-      <polygon points="20,34 30,24 36,36" fill="#6a6060" stroke="#000" strokeWidth="1.5" />
-      <polygon points="46,26 54,16 60,28" fill="#6a6060" stroke="#000" strokeWidth="1.5" />
- 
-      {/* Lava crack on head */}
-      <path d="M28,32 L38,48 L32,60" stroke="#ff6600" strokeWidth="2" fill="none" strokeLinecap="round" filter="url(#bb-lava)" />
- 
-      {/* Heavy brow overhang */}
-      <path d="M14,42 Q44,34 74,42 L72,48 Q44,40 16,48 Z" fill="#3a3030" stroke="#000" strokeWidth="2" />
- 
-      {/* Beady deep-set eyes */}
-      <ellipse cx="30" cy="48" rx="8" ry="6" fill="#1a1010" stroke="#000" strokeWidth="2" />
-      <ellipse cx="58" cy="48" rx="8" ry="6" fill="#1a1010" stroke="#000" strokeWidth="2" />
-      <circle cx="30" cy="47" r="4" fill="#ff6600" filter="url(#bb-lava)" />
-      <circle cx="58" cy="47" r="4" fill="#ff6600" filter="url(#bb-lava)" />
-      <circle cx="30" cy="47" r="2" fill="#ff9900" />
-      <circle cx="58" cy="47" r="2" fill="#ff9900" />
- 
-      {/* Flat nostrils */}
-      <circle cx="40" cy="58" r="3" fill="#3a3030" stroke="#000" strokeWidth="1.5" />
-      <circle cx="48" cy="58" r="3" fill="#3a3030" stroke="#000" strokeWidth="1.5" />
- 
-      {/* Mouth with lower teeth */}
-      <path d="M18,64 Q44,72 70,64 L68,70 Q44,78 20,70 Z" fill="#1a1010" stroke="#000" strokeWidth="2" />
-      <path d="M24,66 L28,74 L33,66 L38,74 L44,66 L50,74 L56,66 L62,74 L66,66"
-        fill="#e8e0c0" stroke="#000" strokeWidth="1.5" strokeLinejoin="round" />
- 
-      {/* Tiny horns */}
-      <path d="M18,30 L12,14 L24,26" fill="#3a3030" stroke="#000" strokeWidth="2" strokeLinejoin="round" />
-      <path d="M70,30 L76,14 L64,26" fill="#3a3030" stroke="#000" strokeWidth="2" strokeLinejoin="round" />
-    </svg>
-  );
-}
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/client/src/components/game/bosses/BossC.tsx.html b/coverage/client/src/components/game/bosses/BossC.tsx.html deleted file mode 100644 index 498bda7..0000000 --- a/coverage/client/src/components/game/bosses/BossC.tsx.html +++ /dev/null @@ -1,283 +0,0 @@ - - - - - - Code coverage report for client/src/components/game/bosses/BossC.tsx - - - - - - - - - -
-
-

All files / client/src/components/game/bosses BossC.tsx

-
- -
- 0% - Statements - 0/1 -
- - -
- 100% - Branches - 0/0 -
- - -
- 0% - Functions - 0/1 -
- - -
- 0% - Lines - 0/1 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63 -64 -65 -66 -67  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 
export function BossC({ className }: { className?: string }) {
-  return (
-    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128" width="128" height="128" role="img" className={className} aria-label="Dark Elf Assassin">
-      <defs>
-        <radialGradient id="bc-purple" cx="50%" cy="50%" r="50%">
-          <stop offset="0%" stopColor="#dd44ff" />
-          <stop offset="100%" stopColor="#dd44ff" stopOpacity="0" />
-        </radialGradient>
-        <filter id="bc-glow">
-          <feGaussianBlur stdDeviation="2.5" result="blur" />
-          <feMerge><feMergeNode in="blur" /><feMergeNode in="SourceGraphic" /></feMerge>
-        </filter>
-      </defs>
- 
-      {/* Left dagger */}
-      <path d="M26,28 L46,82" stroke="#c0c0cc" strokeWidth="4" strokeLinecap="round" />
-      <path d="M22,24 L30,20 L50,78 L42,82 Z" fill="#9090a0" stroke="#000" strokeWidth="2" />
-      <rect x="17" y="27" width="16" height="6" rx="2" fill="#5a3a80" stroke="#000" strokeWidth="2"
-        transform="rotate(-42,25,30)" />
- 
-      {/* Right dagger */}
-      <path d="M102,28 L82,82" stroke="#c0c0cc" strokeWidth="4" strokeLinecap="round" />
-      <path d="M106,24 L98,20 L78,78 L86,82 Z" fill="#9090a0" stroke="#000" strokeWidth="2" />
-      <rect x="95" y="27" width="16" height="6" rx="2" fill="#5a3a80" stroke="#000" strokeWidth="2"
-        transform="rotate(42,103,30)" />
- 
-      {/* Cloak body */}
-      <path d="M36,60 L24,120 L104,120 L92,60 Q64,48 36,60 Z" fill="#1a0a30" stroke="#000" strokeWidth="2.5" strokeLinejoin="round" />
-      {/* Cloak folds */}
-      <path d="M42,65 L30,112" stroke="#2a1040" strokeWidth="2" opacity="0.9" />
-      <path d="M64,62 L60,117" stroke="#2a1040" strokeWidth="2" opacity="0.8" />
-      <path d="M86,65 L98,112" stroke="#2a1040" strokeWidth="2" opacity="0.9" />
- 
-      {/* Belt with rune clasp */}
-      <rect x="38" y="96" width="52" height="7" rx="2" fill="#3a1a50" stroke="#000" strokeWidth="2" />
-      <polygon points="64,93 70,100 64,107 58,100" fill="#9932cc" stroke="#000" strokeWidth="2" />
- 
-      {/* Neck */}
-      <rect x="56" y="50" width="16" height="12" fill="#301050" stroke="#000" strokeWidth="2" />
- 
-      {/* Hood back */}
-      <path d="M32,40 Q64,22 96,40 Q92,20 64,14 Q36,20 32,40 Z" fill="#120820" stroke="#000" strokeWidth="2.5" />
- 
-      {/* Head */}
-      <ellipse cx="64" cy="42" rx="24" ry="22" fill="#2a1050" stroke="#000" strokeWidth="2.5" />
- 
-      {/* Hood drape over forehead */}
-      <path d="M38,38 Q64,28 90,38 L92,48 Q64,38 36,48 Z" fill="#120820" stroke="#000" strokeWidth="2.5" strokeLinejoin="round" />
- 
-      {/* Face shadow */}
-      <ellipse cx="64" cy="48" rx="18" ry="14" fill="#1a0838" opacity="0.9" />
- 
-      {/* Glowing purple eyes — the visual focus */}
-      <ellipse cx="53" cy="44" rx="8" ry="5" fill="url(#bc-purple)" filter="url(#bc-glow)" />
-      <ellipse cx="75" cy="44" rx="8" ry="5" fill="url(#bc-purple)" filter="url(#bc-glow)" />
-      <ellipse cx="53" cy="44" rx="4.5" ry="3" fill="#dd44ff" />
-      <ellipse cx="75" cy="44" rx="4.5" ry="3" fill="#dd44ff" />
-      <ellipse cx="53" cy="44" rx="2" ry="1.5" fill="#fff" opacity="0.9" />
-      <ellipse cx="75" cy="44" rx="2" ry="1.5" fill="#fff" opacity="0.9" />
- 
-      {/* Pointed ears */}
-      <path d="M40,38 L30,22 L44,34" fill="#2a1050" stroke="#000" strokeWidth="2" strokeLinejoin="round" />
-      <path d="M88,38 L98,22 L84,34" fill="#2a1050" stroke="#000" strokeWidth="2" strokeLinejoin="round" />
-    </svg>
-  );
-}
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/client/src/components/game/bosses/BossD.tsx.html b/coverage/client/src/components/game/bosses/BossD.tsx.html deleted file mode 100644 index df97b3a..0000000 --- a/coverage/client/src/components/game/bosses/BossD.tsx.html +++ /dev/null @@ -1,286 +0,0 @@ - - - - - - Code coverage report for client/src/components/game/bosses/BossD.tsx - - - - - - - - - -
-
-

All files / client/src/components/game/bosses BossD.tsx

-
- -
- 0% - Statements - 0/1 -
- - -
- 100% - Branches - 0/0 -
- - -
- 0% - Functions - 0/1 -
- - -
- 0% - Lines - 0/1 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63 -64 -65 -66 -67 -68  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 
export function BossD({ className }: { className?: string }) {
-  return (
-    <svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 128 128" role="img" className={className} aria-label="Orc Berserker">
-      <defs>
-        <filter id="bd-rage">
-          <feGaussianBlur stdDeviation="2" result="blur" />
-          <feMerge><feMergeNode in="blur" /><feMergeNode in="SourceGraphic" /></feMerge>
-        </filter>
-      </defs>
- 
-      {/* Axe handle */}
-      <rect x="96" y="28" width="8" height="92" rx="3" fill="#5c3820" stroke="#000" strokeWidth="2.5" />
-      {/* Axe head - right blade */}
-      <path d="M104,26 Q122,16 120,40 Q122,62 104,52 Z" fill="#9a9aa0" stroke="#000" strokeWidth="2.5" strokeLinejoin="round" />
-      {/* Axe head - left bevel */}
-      <path d="M104,26 Q88,16 90,40 Q88,62 104,52 Z" fill="#7a7a80" stroke="#000" strokeWidth="2.5" strokeLinejoin="round" />
-      {/* Blade edge */}
-      <path d="M120,16 Q128,40 120,64" stroke="#c8c8d8" strokeWidth="3" fill="none" strokeLinecap="round" />
- 
-      {/* Body */}
-      <path d="M18,62 L14,118 L82,118 L86,62 Q50,50 18,62 Z" fill="#3a4a5a" stroke="#000" strokeWidth="2.5" strokeLinejoin="round" />
-      {/* Massive pecs */}
-      <ellipse cx="38" cy="78" rx="18" ry="16" fill="#4a5a6a" stroke="#000" strokeWidth="2" />
-      <ellipse cx="62" cy="78" rx="18" ry="16" fill="#4a5a6a" stroke="#000" strokeWidth="2" />
-      {/* Belly armor */}
-      <path d="M22,92 L26,114 L78,114 L80,92 Q50,84 22,92 Z" fill="#2a3a4a" stroke="#000" strokeWidth="2" />
- 
-      {/* Left spiked shoulder */}
-      <ellipse cx="12" cy="68" rx="16" ry="12" fill="#2a3a4a" stroke="#000" strokeWidth="2.5" />
-      <polygon points="2,60 12,50 10,64" fill="#8a8a90" stroke="#000" strokeWidth="1.5" />
-      <polygon points="12,54 14,44 18,58" fill="#8a8a90" stroke="#000" strokeWidth="1.5" />
-      <polygon points="24,60 20,50 26,64" fill="#8a8a90" stroke="#000" strokeWidth="1.5" />
- 
-      {/* Head — wide and brutish */}
-      <ellipse cx="50" cy="40" rx="30" ry="26" fill="#4a5a6a" stroke="#000" strokeWidth="2.5" />
- 
-      {/* Heavy brow ridge */}
-      <path d="M22,32 L42,38" stroke="#1a2a3a" strokeWidth="5" strokeLinecap="round" />
-      <path d="M78,32 L58,38" stroke="#1a2a3a" strokeWidth="5" strokeLinecap="round" />
- 
-      {/* Rage eyes */}
-      <ellipse cx="36" cy="40" rx="10" ry="8" fill="#aa8800" stroke="#000" strokeWidth="2" />
-      <ellipse cx="64" cy="40" rx="10" ry="8" fill="#aa8800" stroke="#000" strokeWidth="2" />
-      <circle cx="36" cy="38" r="4.5" fill="#ffcc00" filter="url(#bd-rage)" />
-      <circle cx="64" cy="38" r="4.5" fill="#ffcc00" filter="url(#bd-rage)" />
-      <circle cx="37" cy="38" r="2" fill="#000" />
-      <circle cx="65" cy="38" r="2" fill="#000" />
- 
-      {/* Flat nose */}
-      <path d="M44,48 Q50,54 56,48" stroke="#2a3a4a" strokeWidth="3" fill="none" />
- 
-      {/* Tusks */}
-      <path d="M42,58 L36,76" stroke="#e8e0c0" strokeWidth="5" strokeLinecap="round" />
-      <path d="M58,58 L64,76" stroke="#e8e0c0" strokeWidth="5" strokeLinecap="round" />
- 
-      {/* Mouth snarl */}
-      <path d="M34,60 Q50,68 66,60" fill="#1a2a1a" stroke="#000" strokeWidth="2" />
- 
-      {/* Battle scar */}
-      <path d="M24,34 L44,52" stroke="#2a3a2a" strokeWidth="3" opacity="0.6" strokeLinecap="round" />
- 
-      {/* War paint stripes */}
-      <path d="M22,38 L34,34" stroke="#cc3322" strokeWidth="2.5" opacity="0.9" strokeLinecap="round" />
-      <path d="M26,44 L36,42" stroke="#cc3322" strokeWidth="2" opacity="0.8" strokeLinecap="round" />
-    </svg>
-  );
-}
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/client/src/components/game/bosses/BossE.tsx.html b/coverage/client/src/components/game/bosses/BossE.tsx.html deleted file mode 100644 index c280ae1..0000000 --- a/coverage/client/src/components/game/bosses/BossE.tsx.html +++ /dev/null @@ -1,277 +0,0 @@ - - - - - - Code coverage report for client/src/components/game/bosses/BossE.tsx - - - - - - - - - -
-
-

All files / client/src/components/game/bosses BossE.tsx

-
- -
- 0% - Statements - 0/1 -
- - -
- 100% - Branches - 0/0 -
- - -
- 0% - Functions - 0/1 -
- - -
- 0% - Lines - 0/1 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63 -64 -65  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 
export function BossE({ className }: { className?: string }) {
-  return (
-    <svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 128 128" role="img" className={className} aria-label="Goblin Warrior">
-      <defs>
-        <filter id="be-red">
-          <feGaussianBlur stdDeviation="2.5" result="blur" />
-          <feMerge><feMergeNode in="blur" /><feMergeNode in="SourceGraphic" /></feMerge>
-        </filter>
-      </defs>
- 
-      {/* Club handle */}
-      <rect x="91" y="52" width="10" height="68" rx="4" fill="#6b4226" stroke="#000" strokeWidth="2.5" />
-      {/* Club head */}
-      <ellipse cx="96" cy="46" rx="14" ry="11" fill="#8b5226" stroke="#000" strokeWidth="2.5" />
-      {/* Club spikes */}
-      <polygon points="82,40 90,33 90,47" fill="#a0a0a8" stroke="#000" strokeWidth="1.5" />
-      <polygon points="110,40 102,33 102,47" fill="#a0a0a8" stroke="#000" strokeWidth="1.5" />
-      <polygon points="96,33 90,42 102,42" fill="#a0a0a8" stroke="#000" strokeWidth="1.5" />
- 
-      {/* Body / leather armour */}
-      <path d="M36,60 L28,118 L82,118 L88,60 Q62,50 36,60 Z" fill="#2a4a20" stroke="#000" strokeWidth="2.5" strokeLinejoin="round" />
-      {/* Chest plate */}
-      <path d="M42,62 L38,100 L78,100 L82,62 Q62,55 42,62 Z" fill="#3a5a28" stroke="#000" strokeWidth="2" />
-      {/* Belt */}
-      <rect x="34" y="98" width="46" height="7" rx="2" fill="#5a3a10" stroke="#000" strokeWidth="2" />
-      <rect x="57" y="97" width="10" height="9" rx="1" fill="#c8a020" stroke="#000" strokeWidth="2" />
- 
-      {/* Left pointed ear */}
-      <path d="M30,36 L10,18 L36,32" fill="#5a8c3f" stroke="#000" strokeWidth="2.5" strokeLinejoin="round" />
-      {/* Right pointed ear */}
-      <path d="M98,36 L118,18 L92,32" fill="#5a8c3f" stroke="#000" strokeWidth="2.5" strokeLinejoin="round" />
- 
-      {/* Head */}
-      <ellipse cx="64" cy="42" rx="32" ry="28" fill="#5a8c3f" stroke="#000" strokeWidth="2.5" />
- 
-      {/* Angry brow */}
-      <path d="M36,32 L52,38" stroke="#1a3a10" strokeWidth="4" strokeLinecap="round" />
-      <path d="M92,32 L76,38" stroke="#1a3a10" strokeWidth="4" strokeLinecap="round" />
- 
-      {/* Eyes */}
-      <ellipse cx="48" cy="42" rx="9" ry="7" fill="#cc1100" stroke="#000" strokeWidth="2" />
-      <ellipse cx="80" cy="42" rx="9" ry="7" fill="#cc1100" stroke="#000" strokeWidth="2" />
-      <circle cx="50" cy="40" r="4" fill="#ff3311" filter="url(#be-red)" />
-      <circle cx="82" cy="40" r="4" fill="#ff3311" filter="url(#be-red)" />
-      <circle cx="50" cy="40" r="2" fill="#fff" opacity="0.8" />
-      <circle cx="82" cy="40" r="2" fill="#fff" opacity="0.8" />
- 
-      {/* Snout / nostrils */}
-      <path d="M58,50 Q64,56 70,50" stroke="#3a6028" strokeWidth="3" fill="none" strokeLinecap="round" />
-      <circle cx="60" cy="52" r="2" fill="#3a6028" />
-      <circle cx="68" cy="52" r="2" fill="#3a6028" />
- 
-      {/* Wide grinning mouth */}
-      <path d="M40,60 Q64,72 88,60" fill="#1a2a10" stroke="#000" strokeWidth="2" />
-      {/* Jagged teeth */}
-      <path d="M45,60 L49,68 L54,60 L58,68 L64,60 L70,68 L74,60 L79,68 L83,60"
-        fill="#f0e8c0" stroke="#000" strokeWidth="1.5" strokeLinejoin="round" />
- 
-      {/* Warts */}
-      <circle cx="36" cy="28" r="3" fill="#4a7c35" stroke="#000" strokeWidth="1.5" />
-      <circle cx="92" cy="26" r="2.5" fill="#4a7c35" stroke="#000" strokeWidth="1.5" />
-    </svg>
-  );
-}
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/client/src/components/game/bosses/BossS.tsx.html b/coverage/client/src/components/game/bosses/BossS.tsx.html deleted file mode 100644 index 98cac90..0000000 --- a/coverage/client/src/components/game/bosses/BossS.tsx.html +++ /dev/null @@ -1,343 +0,0 @@ - - - - - - Code coverage report for client/src/components/game/bosses/BossS.tsx - - - - - - - - - -
-
-

All files / client/src/components/game/bosses BossS.tsx

-
- -
- 0% - Statements - 0/1 -
- - -
- 100% - Branches - 0/0 -
- - -
- 0% - Functions - 0/1 -
- - -
- 0% - Lines - 0/1 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63 -64 -65 -66 -67 -68 -69 -70 -71 -72 -73 -74 -75 -76 -77 -78 -79 -80 -81 -82 -83 -84 -85 -86 -87  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 
export function BossS({ className }: { className?: string }) {
-  return (
-    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128" width="128" height="128" role="img" className={className} aria-label="Void Lord">
-      <defs>
-        <radialGradient id="bs-eye" cx="50%" cy="50%" r="50%">
-          <stop offset="0%" stopColor="#ffffff" />
-          <stop offset="40%" stopColor="#cc88ff" />
-          <stop offset="100%" stopColor="#4400aa" stopOpacity="0" />
-        </radialGradient>
-        <filter id="bs-void">
-          <feGaussianBlur stdDeviation="4" result="blur" />
-          <feMerge><feMergeNode in="blur" /><feMergeNode in="SourceGraphic" /></feMerge>
-        </filter>
-        <radialGradient id="bs-aura" cx="50%" cy="60%" r="50%">
-          <stop offset="0%" stopColor="#1a0030" stopOpacity="0.8" />
-          <stop offset="100%" stopColor="#000000" stopOpacity="0" />
-        </radialGradient>
-      </defs>
- 
-      {/* Void aura */}
-      <ellipse cx="64" cy="72" rx="58" ry="56" fill="url(#bs-aura)" />
- 
-      {/* Stars */}
-      <circle cx="18" cy="18" r="1.5" fill="#fff" opacity="0.9" />
-      <circle cx="110" cy="14" r="1" fill="#cc88ff" opacity="0.8" />
-      <circle cx="12" cy="58" r="1" fill="#fff" opacity="0.7" />
-      <circle cx="118" cy="48" r="1.5" fill="#fff" opacity="0.6" />
-      <circle cx="20" cy="102" r="1" fill="#cc88ff" opacity="0.9" />
-      <circle cx="108" cy="98" r="1.5" fill="#fff" opacity="0.8" />
-      <circle cx="54" cy="8" r="1" fill="#fff" opacity="0.7" />
-      <circle cx="82" cy="12" r="1" fill="#cc88ff" opacity="0.8" />
- 
-      {/* Void tendrils */}
-      <path d="M64,82 Q28,92 8,80 Q18,100 8,116" stroke="#6600aa" strokeWidth="3" fill="none" strokeLinecap="round" opacity="0.8" />
-      <path d="M64,82 Q100,92 120,80 Q110,100 120,116" stroke="#6600aa" strokeWidth="3" fill="none" strokeLinecap="round" opacity="0.8" />
-      <path d="M50,96 Q34,106 18,120" stroke="#4400aa" strokeWidth="2.5" fill="none" strokeLinecap="round" opacity="0.7" />
-      <path d="M78,96 Q94,106 110,120" stroke="#4400aa" strokeWidth="2.5" fill="none" strokeLinecap="round" opacity="0.7" />
- 
-      {/* Floating void orbs */}
-      <circle cx="18" cy="36" r="5" fill="#6600aa" filter="url(#bs-void)" opacity="0.9" />
-      <circle cx="110" cy="36" r="5" fill="#6600aa" filter="url(#bs-void)" opacity="0.9" />
-      <circle cx="14" cy="72" r="4" fill="#4400aa" filter="url(#bs-void)" opacity="0.7" />
-      <circle cx="114" cy="72" r="4" fill="#4400aa" filter="url(#bs-void)" opacity="0.7" />
- 
-      {/* Staff */}
-      <rect x="4" y="42" width="6" height="80" rx="3" fill="#1a0028" stroke="#000" strokeWidth="2" />
-      <circle cx="7" cy="36" r="10" fill="#2a0044" stroke="#6600aa" strokeWidth="2" />
-      <circle cx="7" cy="36" r="6" fill="#4400aa" filter="url(#bs-void)" />
-      <circle cx="7" cy="36" r="3" fill="#cc88ff" />
-      <circle cx="7" cy="36" r="1" fill="#fff" />
- 
-      {/* Robe body */}
-      <path d="M32,58 L18,122 L110,122 L96,58 Q64,44 32,58 Z" fill="#080010" stroke="#1a0030" strokeWidth="2.5" strokeLinejoin="round" />
-      {/* Robe folds */}
-      <path d="M38,65 L26,116" stroke="#150025" strokeWidth="2.5" opacity="0.9" />
-      <path d="M54,60 L48,120" stroke="#150025" strokeWidth="2" opacity="0.8" />
-      <path d="M74,60 L80,120" stroke="#150025" strokeWidth="2" opacity="0.8" />
-      <path d="M90,65 L102,116" stroke="#150025" strokeWidth="2.5" opacity="0.9" />
- 
-      {/* Belt void clasp */}
-      <rect x="36" y="96" width="56" height="7" rx="2" fill="#0a0018" stroke="#4400aa" strokeWidth="1.5" />
-      <circle cx="64" cy="100" r="6" fill="#2a0044" stroke="#6600aa" strokeWidth="1.5" />
-      <circle cx="64" cy="100" r="3" fill="#cc88ff" filter="url(#bs-void)" />
- 
-      {/* Hood back */}
-      <path d="M30,42 Q64,26 98,42 Q94,22 64,16 Q34,22 30,42 Z" fill="#060008" stroke="#1a0030" strokeWidth="2.5" />
- 
-      {/* Head */}
-      <ellipse cx="64" cy="44" rx="26" ry="24" fill="#080010" stroke="#1a0030" strokeWidth="2.5" />
- 
-      {/* Hood drape */}
-      <path d="M36,40 Q64,30 92,40 L94,50 Q64,40 34,50 Z" fill="#060008" stroke="#1a0030" strokeWidth="2.5" />
- 
-      {/* Face void */}
-      <ellipse cx="64" cy="48" rx="20" ry="14" fill="#030006" opacity="0.9" />
- 
-      {/* COSMIC EYES — the visual centrepiece */}
-      <ellipse cx="50" cy="46" rx="12" ry="8" fill="url(#bs-eye)" filter="url(#bs-void)" />
-      <ellipse cx="78" cy="46" rx="12" ry="8" fill="url(#bs-eye)" filter="url(#bs-void)" />
-      <ellipse cx="50" cy="46" rx="7" ry="5" fill="#cc88ff" />
-      <ellipse cx="78" cy="46" rx="7" ry="5" fill="#cc88ff" />
-      <ellipse cx="50" cy="46" rx="3.5" ry="2.5" fill="#fff" />
-      <ellipse cx="78" cy="46" rx="3.5" ry="2.5" fill="#fff" />
-    </svg>
-  );
-}
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/client/src/components/game/bosses/PlayerAvatar.tsx.html b/coverage/client/src/components/game/bosses/PlayerAvatar.tsx.html deleted file mode 100644 index 46d918d..0000000 --- a/coverage/client/src/components/game/bosses/PlayerAvatar.tsx.html +++ /dev/null @@ -1,325 +0,0 @@ - - - - - - Code coverage report for client/src/components/game/bosses/PlayerAvatar.tsx - - - - - - - - - -
-
-

All files / client/src/components/game/bosses PlayerAvatar.tsx

-
- -
- 0% - Statements - 0/1 -
- - -
- 100% - Branches - 0/0 -
- - -
- 0% - Functions - 0/1 -
- - -
- 0% - Lines - 0/1 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63 -64 -65 -66 -67 -68 -69 -70 -71 -72 -73 -74 -75 -76 -77 -78 -79 -80 -81  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 
export function PlayerAvatar({ className }: { className?: string }) {
-  return (
-    <svg
-      xmlns="http://www.w3.org/2000/svg"
-      width="128"
-      height="128"
-      viewBox="0 0 128 128"
-      className={className}
-      role="img"
-      aria-label="Hunter"
-    >
-      <defs>
-        <radialGradient id="pa-cyan" cx="50%" cy="50%" r="50%">
-          <stop offset="0%" stopColor="#00ffcc" />
-          <stop offset="100%" stopColor="#00ffcc" stopOpacity="0" />
-        </radialGradient>
-        <filter id="pa-glow">
-          <feGaussianBlur stdDeviation="2" result="blur" />
-          <feMerge>
-            <feMergeNode in="blur" />
-            <feMergeNode in="SourceGraphic" />
-          </feMerge>
-        </filter>
-      </defs>
- 
-      {/* Cloak/Cape */}
-      <path d="M32,55 L22,120 L106,120 L96,55 Z" fill="#0f0a2a" stroke="#000" strokeWidth="2.5" strokeLinejoin="round" />
- 
-      {/* Body armor */}
-      <path d="M40,55 L34,108 L94,108 L88,55 Q64,46 40,55 Z" fill="#1a1240" stroke="#000" strokeWidth="2.5" strokeLinejoin="round" />
- 
-      {/* Chest plate */}
-      <path d="M48,58 L44,90 L84,90 L80,58 Q64,53 48,58 Z" fill="#22185a" stroke="#000" strokeWidth="2" />
- 
-      {/* Armor accent lines */}
-      <path d="M56,65 L72,65" stroke="#7c3aed" strokeWidth="1.5" opacity="0.9" />
-      <path d="M54,72 L74,72" stroke="#7c3aed" strokeWidth="1.5" opacity="0.9" />
-      <path d="M56,79 L72,79" stroke="#7c3aed" strokeWidth="1.5" opacity="0.9" />
- 
-      {/* Chest emblem */}
-      <circle cx="64" cy="73" r="6" fill="#7c3aed" stroke="#000" strokeWidth="2" />
-      <circle cx="64" cy="73" r="3" fill="#a855f7" filter="url(#pa-glow)" />
- 
-      {/* Belt */}
-      <rect x="38" y="96" width="52" height="8" rx="2" fill="#3a2810" stroke="#000" strokeWidth="2.5" />
-      <rect x="59" y="95" width="10" height="10" rx="1" fill="#c0a030" stroke="#000" strokeWidth="2" />
- 
-      {/* Left shoulder pauldron */}
-      <ellipse cx="30" cy="65" rx="16" ry="11" fill="#1a1240" stroke="#000" strokeWidth="2.5" />
-      <ellipse cx="30" cy="63" rx="11" ry="8" fill="#22185a" />
-      <path d="M18,60 Q30,54 42,60" stroke="#7c3aed" strokeWidth="1.5" fill="none" />
- 
-      {/* Right shoulder pauldron */}
-      <ellipse cx="98" cy="65" rx="16" ry="11" fill="#1a1240" stroke="#000" strokeWidth="2.5" />
-      <ellipse cx="98" cy="63" rx="11" ry="8" fill="#22185a" />
-      <path d="M86,60 Q98,54 110,60" stroke="#7c3aed" strokeWidth="1.5" fill="none" />
- 
-      {/* Neck guard */}
-      <rect x="52" y="48" width="24" height="12" rx="3" fill="#1a1240" stroke="#000" strokeWidth="2" />
- 
-      {/* Helmet */}
-      <ellipse cx="64" cy="34" rx="26" ry="24" fill="#1a1240" stroke="#000" strokeWidth="2.5" />
- 
-      {/* Helmet crest */}
-      <path d="M56,10 Q64,4 72,10 L70,20 Q64,16 58,20 Z" fill="#7c3aed" stroke="#000" strokeWidth="2" />
- 
-      {/* Visor */}
-      <rect x="42" y="30" width="44" height="10" rx="4" fill="#080614" stroke="#000" strokeWidth="2" />
- 
-      {/* Glowing cyan eyes through visor */}
-      <ellipse cx="52" cy="35" rx="6" ry="4" fill="url(#pa-cyan)" filter="url(#pa-glow)" opacity="0.9" />
-      <ellipse cx="76" cy="35" rx="6" ry="4" fill="url(#pa-cyan)" filter="url(#pa-glow)" opacity="0.9" />
-      <ellipse cx="52" cy="35" rx="3" ry="2" fill="#00ffcc" />
-      <ellipse cx="76" cy="35" rx="3" ry="2" fill="#00ffcc" />
- 
-      {/* Chin guard */}
-      <path d="M44,44 Q64,52 84,44 L82,52 Q64,60 46,52 Z" fill="#1a1240" stroke="#000" strokeWidth="2" />
-    </svg>
-  );
-}
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/client/src/components/game/bosses/index.html b/coverage/client/src/components/game/bosses/index.html deleted file mode 100644 index eac8603..0000000 --- a/coverage/client/src/components/game/bosses/index.html +++ /dev/null @@ -1,221 +0,0 @@ - - - - - - Code coverage report for client/src/components/game/bosses - - - - - - - - - -
-
-

All files client/src/components/game/bosses

-
- -
- 0% - Statements - 0/7 -
- - -
- 100% - Branches - 0/0 -
- - -
- 0% - Functions - 0/7 -
- - -
- 0% - Lines - 0/7 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FileStatementsBranchesFunctionsLines
BossA.tsx -
-
0%0/1100%0/00%0/10%0/1
BossB.tsx -
-
0%0/1100%0/00%0/10%0/1
BossC.tsx -
-
0%0/1100%0/00%0/10%0/1
BossD.tsx -
-
0%0/1100%0/00%0/10%0/1
BossE.tsx -
-
0%0/1100%0/00%0/10%0/1
BossS.tsx -
-
0%0/1100%0/00%0/10%0/1
PlayerAvatar.tsx -
-
0%0/1100%0/00%0/10%0/1
index.ts -
-
0%0/00%0/00%0/00%0/0
-
-
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/client/src/components/game/bosses/index.ts.html b/coverage/client/src/components/game/bosses/index.ts.html deleted file mode 100644 index ee7e7af..0000000 --- a/coverage/client/src/components/game/bosses/index.ts.html +++ /dev/null @@ -1,106 +0,0 @@ - - - - - - Code coverage report for client/src/components/game/bosses/index.ts - - - - - - - - - -
-
-

All files / client/src/components/game/bosses index.ts

-
- -
- 0% - Statements - 0/0 -
- - -
- 0% - Branches - 0/0 -
- - -
- 0% - Functions - 0/0 -
- - -
- 0% - Lines - 0/0 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8  -  -  -  -  -  -  - 
export { PlayerAvatar } from "./PlayerAvatar";
-export { BossE } from "./BossE";
-export { BossD } from "./BossD";
-export { BossC } from "./BossC";
-export { BossB } from "./BossB";
-export { BossA } from "./BossA";
-export { BossS } from "./BossS";
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/client/src/components/game/index.html b/coverage/client/src/components/game/index.html deleted file mode 100644 index 607bb92..0000000 --- a/coverage/client/src/components/game/index.html +++ /dev/null @@ -1,116 +0,0 @@ - - - - - - Code coverage report for client/src/components/game - - - - - - - - - -
-
-

All files client/src/components/game

-
- -
- 0% - Statements - 0/1359 -
- - -
- 0% - Branches - 0/1056 -
- - -
- 0% - Functions - 0/361 -
- - -
- 0% - Lines - 0/1199 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FileStatementsBranchesFunctionsLines
HuntersPath.tsx -
-
0%0/13590%0/10560%0/3610%0/1199
-
-
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/client/src/components/game/mobile/BottomTabBar.tsx.html b/coverage/client/src/components/game/mobile/BottomTabBar.tsx.html deleted file mode 100644 index 4b8d8cb..0000000 --- a/coverage/client/src/components/game/mobile/BottomTabBar.tsx.html +++ /dev/null @@ -1,226 +0,0 @@ - - - - - - Code coverage report for client/src/components/game/mobile/BottomTabBar.tsx - - - - - - - - - -
-
-

All files / client/src/components/game/mobile BottomTabBar.tsx

-
- -
- 0% - Statements - 0/6 -
- - -
- 0% - Branches - 0/14 -
- - -
- 0% - Functions - 0/3 -
- - -
- 0% - Lines - 0/6 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 
import { Sword, BarChart2, Ghost, ScrollText } from "lucide-react";
- 
-export type MobileTab = "combat" | "manage" | "spirits" | "log";
- 
-interface Props {
-  activeTab: MobileTab;
-  onTabChange: (tab: MobileTab) => void;
-  statPointBadge: boolean;
-  dailyCompleteBadge: boolean;
-}
- 
-const TABS = [
-  { id: "combat"  as MobileTab, label: "Combat",  Icon: Sword },
-  { id: "manage"  as MobileTab, label: "Manage",  Icon: BarChart2 },
-  { id: "spirits" as MobileTab, label: "Spirits", Icon: Ghost },
-  { id: "log"     as MobileTab, label: "Log",     Icon: ScrollText },
-];
- 
-export function BottomTabBar({ activeTab, onTabChange, statPointBadge, dailyCompleteBadge }: Props) {
-  return (
-    <nav className="flex border-t border-zinc-800 bg-zinc-950 shrink-0">
-      {TABS.map(({ id, label, Icon }) => {
-        const active = id === activeTab;
-        const badge = (id === "manage" && statPointBadge) || (id === "combat" && dailyCompleteBadge);
-        return (
-          <button
-            key={id}
-            onClick={() => onTabChange(id)}
-            aria-current={active ? "page" : undefined}
-            className={`relative flex flex-1 flex-col items-center justify-center py-3 gap-0.5 text-xs font-medium transition-colors ${
-              active ? "text-violet-400" : "text-zinc-500"
-            }`}
-          >
-            <Icon size={20} />
-            <span>{label}</span>
-            {badge && (
-              <span
-                aria-label={id === "manage" ? "Stat points available" : "Daily quest complete"}
-                className={`absolute top-2 right-1/4 w-2 h-2 rounded-full ${id === "manage" ? "bg-red-500" : "bg-yellow-400"}`}
-              />
-            )}
-          </button>
-        );
-      })}
-    </nav>
-  );
-}
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/client/src/components/game/mobile/CombatTab.tsx.html b/coverage/client/src/components/game/mobile/CombatTab.tsx.html deleted file mode 100644 index 0ce3c58..0000000 --- a/coverage/client/src/components/game/mobile/CombatTab.tsx.html +++ /dev/null @@ -1,1141 +0,0 @@ - - - - - - Code coverage report for client/src/components/game/mobile/CombatTab.tsx - - - - - - - - - -
-
-

All files / client/src/components/game/mobile CombatTab.tsx

-
- -
- 0% - Statements - 0/23 -
- - -
- 0% - Branches - 0/82 -
- - -
- 0% - Functions - 0/12 -
- - -
- 0% - Lines - 0/22 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63 -64 -65 -66 -67 -68 -69 -70 -71 -72 -73 -74 -75 -76 -77 -78 -79 -80 -81 -82 -83 -84 -85 -86 -87 -88 -89 -90 -91 -92 -93 -94 -95 -96 -97 -98 -99 -100 -101 -102 -103 -104 -105 -106 -107 -108 -109 -110 -111 -112 -113 -114 -115 -116 -117 -118 -119 -120 -121 -122 -123 -124 -125 -126 -127 -128 -129 -130 -131 -132 -133 -134 -135 -136 -137 -138 -139 -140 -141 -142 -143 -144 -145 -146 -147 -148 -149 -150 -151 -152 -153 -154 -155 -156 -157 -158 -159 -160 -161 -162 -163 -164 -165 -166 -167 -168 -169 -170 -171 -172 -173 -174 -175 -176 -177 -178 -179 -180 -181 -182 -183 -184 -185 -186 -187 -188 -189 -190 -191 -192 -193 -194 -195 -196 -197 -198 -199 -200 -201 -202 -203 -204 -205 -206 -207 -208 -209 -210 -211 -212 -213 -214 -215 -216 -217 -218 -219 -220 -221 -222 -223 -224 -225 -226 -227 -228 -229 -230 -231 -232 -233 -234 -235 -236 -237 -238 -239 -240 -241 -242 -243 -244 -245 -246 -247 -248 -249 -250 -251 -252 -253 -254 -255 -256 -257 -258 -259 -260 -261 -262 -263 -264 -265 -266 -267 -268 -269 -270 -271 -272 -273 -274 -275 -276 -277 -278 -279 -280 -281 -282 -283 -284 -285 -286 -287 -288 -289 -290 -291 -292 -293 -294 -295 -296 -297 -298 -299 -300 -301 -302 -303 -304 -305 -306 -307 -308 -309 -310 -311 -312 -313 -314 -315 -316 -317 -318 -319 -320 -321 -322 -323 -324 -325 -326 -327 -328 -329 -330 -331 -332 -333 -334 -335 -336 -337 -338 -339 -340 -341 -342 -343 -344 -345 -346 -347 -348 -349 -350 -351 -352 -353  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 
import React from "react";
-import { PlayerAvatar, BossE, BossD, BossC, BossB, BossA, BossS } from "../bosses";
-import { RANK_COLORS } from "../HuntersPath";
- 
-const BOSS_COMPONENTS: Record<string, React.ComponentType<{ className?: string }>> = {
-  E: BossE, D: BossD, C: BossC, B: BossB, A: BossA, S: BossS,
-};
- 
- 
-interface CombatTabProps {
-  player: any;
-  playerPower: number;
-  gates: any[];
-  running: any;
-  combatResult: any;
-  combatLog: string[];
-  autoDungeon: boolean;
-  onToggleAuto: () => void;
-  onStartGate: (gate: any) => void;
-  onRest: () => void;
-  onUseKey: () => void;
-  onRefreshGates: () => void;
-  onUsePotion: (itemId: string) => void;
-  onDismissResult: () => void;
-}
- 
-function HpBar({ current, max, color }: { current: number; max: number; color: string }) {
-  const pct = max > 0 ? Math.max(0, Math.min(100, (current / max) * 100)) : 0;
-  return (
-    <div className="w-full h-2 bg-zinc-800 rounded-full overflow-hidden">
-      <div
-        className={`h-full rounded-full transition-all duration-300 ${color}`}
-        style={{ width: `${pct}%` }}
-      />
-    </div>
-  );
-}
- 
-export function CombatTab({
-  player, playerPower, gates, running, combatResult, combatLog,
-  autoDungeon, onToggleAuto, onStartGate, onRest, onUseKey,
-  onRefreshGates, onUsePotion, onDismissResult,
-}: CombatTabProps) {
-  const inRun = Boolean(running);
-  const potions = (player.inv ?? []).filter((i: any) => i.type === "potion" || i.id?.includes("potion"));
- 
-  return (
-    <div className="flex flex-col min-h-full">
-      {/* Player strip */}
-      <div className="bg-zinc-900 border-b border-zinc-800 px-3 py-2 shrink-0">
-        <div className="flex items-center gap-2 mb-1">
-          <PlayerAvatar className="w-10 h-10 rounded-full shrink-0" />
-          <div className="flex-1 min-w-0">
-            <div className="flex items-center justify-between">
-              <span className="text-sm font-semibold text-zinc-100">Hunter  Lv{player.level}</span>
-              <span className="text-xs text-zinc-400">PWR {Math.floor(playerPower)}</span>
-            </div>
-            <div className="flex gap-1 mt-1">
-              <div className="flex-1">
-                <HpBar current={player.hp} max={player.maxHp} color="bg-red-500" />
-                <div className="text-[10px] text-zinc-500 mt-0.5">{player.hp}/{player.maxHp}</div>
-              </div>
-              <div className="flex-1">
-                <HpBar current={player.mp} max={player.maxMp} color="bg-blue-500" />
-                <div className="text-[10px] text-zinc-500 mt-0.5">{player.mp}/{player.maxMp}</div>
-              </div>
-            </div>
-          </div>
-        </div>
-        {(player.fatigue ?? 0) > 5 && (
-          <div className="text-xs text-amber-400 mt-0.5">Fatigue {Math.round(player.fatigue)}%</div>
-        )}
-      </div>
- 
-      {/* Main area */}
-      <div className="flex-1">
-        {inRun ? (
-          <ActiveCombat
-            running={running}
-            player={player}
-            combatLog={combatLog}
-          />
-        ) : combatResult ? (
-          <CombatResultScreen
-            combatResult={combatResult}
-            onDismissResult={onDismissResult}
-          />
-        ) : (
-          <GateList gates={gates} playerPower={playerPower} onStartGate={onStartGate} />
-        )}
-      </div>
- 
-      {/* Action strip */}
-      <div className="shrink-0 border-t border-zinc-800 bg-zinc-900 px-2 py-2">
-        <div className="flex gap-1.5">
-          <button
-            onClick={onToggleAuto}
-            className={`flex-1 rounded-lg py-2.5 text-xs font-semibold transition-colors ${
-              autoDungeon ? "bg-violet-600 text-white" : "bg-zinc-800 text-zinc-400"
-            }`}
-          >
-            Auto {autoDungeon ? "ON" : "OFF"}
-          </button>
-          <button
-            onClick={onRest}
-            disabled={inRun}
-            className="flex-1 rounded-lg py-2.5 text-xs font-semibold bg-zinc-800 text-zinc-300 disabled:opacity-40"
-          >
-            Rest
-          </button>
-          <button
-            onClick={onUseKey}
-            disabled={(player.keys ?? 0) <= 0 || inRun}
-            className="flex-1 rounded-lg py-2.5 text-xs font-semibold bg-zinc-800 text-zinc-300 disabled:opacity-40"
-          >
-            Key ({player.keys ?? 0})
-          </button>
-          <button
-            onClick={onRefreshGates}
-            disabled={inRun}
-            className="flex-1 rounded-lg py-2.5 text-xs font-semibold bg-zinc-800 text-zinc-300 disabled:opacity-40"
-          >
-            Refresh
-          </button>
-          {potions.length > 0 && (
-            <button
-              onClick={() => onUsePotion(potions[0].id)}
-              className="flex-1 rounded-lg py-2.5 text-xs font-semibold bg-emerald-900 text-emerald-300"
-            >
-              Potion ({potions.length})
-            </button>
-          )}
-        </div>
-      </div>
-    </div>
-  );
-}
- 
-function GateList({
-  gates,
-  playerPower,
-  onStartGate,
-}: {
-  gates: any[];
-  playerPower: number;
-  onStartGate: (g: any) => void;
-}) {
-  return (
-    <div className="p-3 space-y-2">
-      <div className="flex items-center justify-between mb-1">
-        <span className="text-sm font-semibold text-zinc-300">Gates ({gates.length})</span>
-        <span className="text-xs text-zinc-500">Your PWR {Math.floor(playerPower)}</span>
-      </div>
-      {gates.map((gate) => {
-        // recommended is the difficulty baseline; power is the boss's actual power
-        const rec = gate.recommended ?? gate.power;
-        const danger = playerPower < rec * 0.8;
-        const rankBg = RANK_COLORS[gate.rank as keyof typeof RANK_COLORS] ?? "bg-zinc-600";
-        // EXP is computed dynamically on completion; show an estimate from recommended
-        const estExp = Math.floor(rec * 1.1 + 25);
-        return (
-          <button
-            key={gate.id}
-            onClick={() => onStartGate(gate)}
-            className="w-full text-left rounded-xl bg-zinc-900 border border-zinc-800 active:border-violet-600 p-3"
-          >
-            <div className="flex items-center justify-between mb-1">
-              <div className="flex items-center gap-2">
-                <span
-                  className={`${rankBg} text-white text-xs font-bold w-6 h-6 rounded flex items-center justify-center`}
-                >
-                  {gate.rank}
-                </span>
-                <span className="text-sm text-zinc-200">{gate.name ?? `${gate.rank}-Rank Gate`}</span>
-                {gate.modifiers?.length > 0 && (
-                  <span className="text-xs text-zinc-500">
-                    {gate.modifiers.length} mod{gate.modifiers.length !== 1 ? "s" : ""}
-                  </span>
-                )}
-              </div>
-              <span className={`text-xs font-bold ${danger ? "text-red-400" : "text-emerald-400"}`}>
-                PWR {Math.round(gate.power)}
-              </span>
-            </div>
-            <div className="flex justify-between text-xs text-zinc-500">
-              <span>{gate.rank}-Rank</span>
-              <span className="text-violet-400">~{estExp} EXP</span>
-            </div>
-            {danger && <div className="text-xs text-red-400 mt-1">Too Dangerous!</div>}
-          </button>
-        );
-      })}
-    </div>
-  );
-}
- 
-function CombatResultScreen({
-  combatResult,
-  onDismissResult,
-}: {
-  combatResult: any;
-  onDismissResult: () => void;
-}) {
-  return (
-    <div className="p-3 flex items-center justify-center min-h-[60vh]">
-      <div
-        className={`rounded-xl p-5 border w-full max-w-sm ${
-          combatResult.victory
-            ? "bg-emerald-900/30 border-emerald-700"
-            : "bg-red-900/30 border-red-800"
-        }`}
-      >
-        <div className="text-2xl font-bold text-center mb-1">
-          {combatResult.victory ? "Victory!" : "Defeated"}
-        </div>
-        <div className="text-xs text-zinc-500 text-center mb-4">
-          {combatResult.gate?.name ?? "Gate"} — {combatResult.boss?.name ?? "Boss"}
-        </div>
- 
-        {combatResult.victory ? (
-          <div className="space-y-2 mb-4">
-            {/* EXP + Gold */}
-            <div className="grid grid-cols-2 gap-2">
-              <div className="bg-green-900/40 rounded-lg px-3 py-2.5 text-center">
-                <div className="text-green-400 font-bold text-sm">+{combatResult.expGained ?? 0}</div>
-                <div className="text-green-300/60 text-xs">EXP</div>
-              </div>
-              <div className="bg-yellow-900/40 rounded-lg px-3 py-2.5 text-center">
-                <div className="text-yellow-400 font-bold text-sm">+{combatResult.goldGained ?? 0}₲</div>
-                <div className="text-yellow-300/60 text-xs">Gold</div>
-              </div>
-            </div>
- 
-            {/* Spirit Bound */}
-            {combatResult.spiritBound && (
-              <div className="bg-purple-900/40 rounded-lg px-3 py-2.5 flex items-center gap-2">
-                <span className="text-purple-400 text-lg">👻</span>
-                <div>
-                  <div className="text-purple-300 text-sm font-semibold">{combatResult.spiritBound.name}</div>
-                  <div className="text-purple-400/60 text-xs">Spirit Bound · PWR {Math.floor(combatResult.spiritBound.power)}</div>
-                </div>
-              </div>
-            )}
- 
-            {/* Drops */}
-            {(combatResult.drops ?? []).length > 0 && (
-              <div className="bg-blue-900/40 rounded-lg px-3 py-2.5">
-                <div className="text-blue-400 text-xs font-semibold mb-1">Loot</div>
-                {combatResult.drops.map((drop: any, i: number) => (
-                  <div key={i} className="text-blue-300 text-sm flex items-center gap-1.5">
-                    <span className="text-xs">💎</span>
-                    {drop.name}
-                    {drop.stats && (
-                      <span className="text-blue-400/60 text-xs ml-auto">
-                        {Object.entries(drop.stats).map(([k, v]) => `+${v} ${k}`).join(", ")}
-                      </span>
-                    )}
-                  </div>
-                ))}
-              </div>
-            )}
-          </div>
-        ) : (
-          <div className="text-center mb-4">
-            <div className="text-red-400 font-bold text-sm mb-1">-10₲ Penalty</div>
-            <div className="text-zinc-500 text-xs">Rest and try again</div>
-          </div>
-        )}
- 
-        <button
-          onClick={onDismissResult}
-          className={`w-full rounded-lg py-3 font-semibold ${
-            combatResult.victory
-              ? "bg-violet-600 hover:bg-violet-500 text-white"
-              : "bg-zinc-800 hover:bg-zinc-700 text-zinc-300"
-          }`}
-        >
-          {combatResult.victory ? "Continue" : "Accept Defeat"}
-        </button>
-      </div>
-    </div>
-  );
-}
- 
-function ActiveCombat({
-  running,
-  player,
-  combatLog,
-}: {
-  running: any;
-  player: any;
-  combatLog: string[];
-}) {
-  const BossComp = running ? BOSS_COMPONENTS[running.gate?.rank] : null;
-  // RunningState uses hpEnemy for current boss HP; boss.maxHp for the ceiling
-  const bossHp = running?.hpEnemy ?? 0;
-  const bossMaxHp = running?.boss?.maxHp ?? 1;
- 
-  return (
-    <div className="p-3 space-y-3">
-      {/* VS layout */}
-      <div className="grid grid-cols-2 gap-2">
-        <div className="bg-zinc-900 rounded-xl p-3 text-center border border-zinc-800">
-          <PlayerAvatar className="w-14 h-14 mx-auto mb-1" />
-          <div className="text-xs font-semibold text-violet-300 mb-1">Hunter</div>
-          <HpBar current={player.hp} max={player.maxHp} color="bg-red-500" />
-          <div className="text-xs text-zinc-500 mt-0.5">
-            {player.hp}/{player.maxHp}
-          </div>
-          <HpBar current={player.mp} max={player.maxMp} color="bg-blue-500" />
-        </div>
-        <div className="bg-zinc-900 rounded-xl p-3 text-center border border-zinc-800">
-          {BossComp ? (
-            <BossComp className="w-14 h-14 mx-auto mb-1" />
-          ) : (
-            <div className="w-14 h-14 mx-auto mb-1 bg-zinc-800 rounded-full" />
-          )}
-          <div className="text-xs font-semibold text-red-400 mb-1">
-            {running?.boss?.name ?? "Boss"}
-          </div>
-          <div className="text-[10px] text-zinc-500">
-            {running?.gate?.rank}-Rank Boss
-          </div>
-          <HpBar current={bossHp} max={bossMaxHp} color="bg-orange-500" />
-          <div className="text-xs text-zinc-500 mt-0.5">
-            {bossHp}/{bossMaxHp}
-          </div>
-        </div>
-      </div>
- 
-      {/* Gate info */}
-      <div className="text-xs text-zinc-500 text-center">
-        {running?.gate?.name ?? `${running?.gate?.rank}-Rank Gate`}
-        {running?.tick != null && <span className="ml-2">Tick {running.tick}</span>}
-      </div>
- 
-      {/* Combat log */}
-      <div className="bg-zinc-950 rounded-xl p-2 h-40 overflow-y-auto text-xs space-y-0.5 border border-zinc-800">
-        {combatLog.length === 0 ? (
-          <div className="text-zinc-600 text-center pt-6">Combat in progress...</div>
-        ) : (
-          combatLog.slice(-30).map((entry: string, i: number) => (
-            <div key={i} className="text-zinc-400 leading-relaxed">
-              {entry}
-            </div>
-          ))
-        )}
-      </div>
- 
-    </div>
-  );
-}
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/client/src/components/game/mobile/LogTab.tsx.html b/coverage/client/src/components/game/mobile/LogTab.tsx.html deleted file mode 100644 index 7445f63..0000000 --- a/coverage/client/src/components/game/mobile/LogTab.tsx.html +++ /dev/null @@ -1,625 +0,0 @@ - - - - - - Code coverage report for client/src/components/game/mobile/LogTab.tsx - - - - - - - - - -
-
-

All files / client/src/components/game/mobile LogTab.tsx

-
- -
- 0% - Statements - 0/14 -
- - -
- 0% - Branches - 0/55 -
- - -
- 0% - Functions - 0/7 -
- - -
- 0% - Lines - 0/13 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63 -64 -65 -66 -67 -68 -69 -70 -71 -72 -73 -74 -75 -76 -77 -78 -79 -80 -81 -82 -83 -84 -85 -86 -87 -88 -89 -90 -91 -92 -93 -94 -95 -96 -97 -98 -99 -100 -101 -102 -103 -104 -105 -106 -107 -108 -109 -110 -111 -112 -113 -114 -115 -116 -117 -118 -119 -120 -121 -122 -123 -124 -125 -126 -127 -128 -129 -130 -131 -132 -133 -134 -135 -136 -137 -138 -139 -140 -141 -142 -143 -144 -145 -146 -147 -148 -149 -150 -151 -152 -153 -154 -155 -156 -157 -158 -159 -160 -161 -162 -163 -164 -165 -166 -167 -168 -169 -170 -171 -172 -173 -174 -175 -176 -177 -178 -179 -180 -181  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 
const MOBILE_LORE = [
-  { level: 1,  title: "What Are Gates?",            text: "Dimensional rifts that appeared across the world without warning. Inside lie monsters, treasure, and mysteries. Hunters are those brave enough to enter." },
-  { level: 5,  title: "The Hunter's Guild",          text: "Formed to organize Hunters and manage gate clearance. They rank both Hunters and gates from E (weakest) to S (catastrophic). Guild support keeps cities safe." },
-  { level: 10, title: "Spirit Binding",              text: "Some Hunters develop the ability to bind the essence of defeated bosses, creating spirit allies that fight alongside them. The mechanism is poorly understood." },
-  { level: 15, title: "The Fatigue Problem",         text: "Prolonged exposure to gate energy causes fatigue — a dulling of the senses that weakens even the strongest Hunters. Rest is not optional; it is survival." },
-  { level: 20, title: "Gate Ranks Explained",        text: "E-Rank gates are manageable. D through C require real skill. B-Rank gates have leveled entire city blocks when left unchecked. A and S-Rank gates are existential threats." },
-  { level: 30, title: "The Origin of Gates",         text: "No one knows why gates appeared. Some theories suggest a weakening barrier between dimensions. Others point to an ancient experiment gone wrong. The truth remains buried." },
-  { level: 40, title: "Rebirth",                    text: "A handful of Hunters have discovered a way to shed their accumulated power and start anew — emerging stronger each time. They call it Rebirth. The cost is everything you've built." },
-  { level: 50, title: "Beyond S-Rank",               text: "Rumors persist of gates beyond S-Rank — tears in reality so vast they could swallow nations. If they exist, only a reborn Hunter could hope to survive them." },
-];
- 
-const DIFFICULTY_STYLE: Record<string, string> = {
-  easy:   "bg-green-900/50 text-green-400 border-green-800",
-  medium: "bg-yellow-900/50 text-yellow-400 border-yellow-800",
-  hard:   "bg-red-900/50 text-red-400 border-red-800",
-  epic:   "bg-purple-900/50 text-purple-400 border-purple-800",
-};
- 
-interface LogTabProps {
-  daily: any;
-  log: string[];
-  player: any;
-  onForfeitDaily: () => void;
-}
- 
-export function LogTab({ daily, log, player, onForfeitDaily }: LogTabProps) {
-  const quests: any[] = daily?.availableQuests ?? [];
-  const completedIds: string[] = daily?.completedQuests ?? [];
-  const completedCount = quests.filter((q) => completedIds.includes(q.id)).length;
-  const allDone = daily?.completed === true;
- 
-  return (
-    <div className="p-3 space-y-3 pb-4">
-      {/* Daily Quest section */}
-      <div className="bg-zinc-900 rounded-xl border border-zinc-800 overflow-hidden">
-        <div className="flex items-center justify-between px-4 py-3 border-b border-zinc-800">
-          <div className="flex items-center gap-2">
-            <span className="text-sm font-semibold text-zinc-200">Daily Quest</span>
-            <span
-              className={`text-xs px-2 py-0.5 rounded-full font-medium ${
-                allDone
-                  ? "bg-emerald-900/60 text-emerald-400"
-                  : "bg-violet-900/60 text-violet-400"
-              }`}
-            >
-              {allDone ? "Complete ✓" : "Active"}
-            </span>
-          </div>
-          <button
-            onClick={onForfeitDaily}
-            className="text-xs text-zinc-600 active:text-red-400 py-1 px-2"
-          >
-            Forfeit
-          </button>
-        </div>
- 
-        {/* Overall progress bar */}
-        {daily?.active && !allDone && quests.length > 0 && (
-          <div className="px-4 pt-3 pb-1">
-            <div className="flex justify-between text-xs text-zinc-500 mb-1">
-              <span>
-                {completedCount}/{quests.length} completed
-              </span>
-              {(daily?.questReputation ?? 0) > 0 && (
-                <span className="text-amber-400">Rep: {daily.questReputation}</span>
-              )}
-            </div>
-            <div className="w-full h-1.5 bg-zinc-800 rounded-full overflow-hidden">
-              <div
-                className="h-full bg-violet-600 rounded-full"
-                style={{
-                  width: `${
-                    quests.length > 0 ? (completedCount / quests.length) * 100 : 0
-                  }%`,
-                }}
-              />
-            </div>
-          </div>
-        )}
- 
-        {/* Individual quest cards */}
-        {quests.map((quest: any) => {
-          const done = completedIds.includes(quest.id);
-          return (
-            <div
-              key={quest.id}
-              className={`px-4 py-3 border-t border-zinc-800 ${done ? "opacity-60" : ""}`}
-            >
-              <div className="flex items-center gap-2 mb-1">
-                <span
-                  className={`text-xs px-1.5 py-0.5 rounded border ${
-                    DIFFICULTY_STYLE[quest.difficulty] ?? ""
-                  }`}
-                >
-                  {quest.difficulty}
-                </span>
-                <span className="text-sm text-zinc-200 flex-1 truncate">{quest.name}</span>
-                {done && <span className="text-emerald-400 shrink-0">✓</span>}
-              </div>
-              <div className="text-xs text-zinc-500 mb-1.5">{quest.description}</div>
-              <div className="w-full h-1 bg-zinc-800 rounded-full overflow-hidden mb-1">
-                <div
-                  className="h-full bg-violet-500 rounded-full"
-                  style={{
-                    width: `${
-                      (quest.need ?? 0) > 0
-                        ? Math.min(100, ((quest.have ?? 0) / quest.need) * 100)
-                        : 0
-                    }%`,
-                  }}
-                />
-              </div>
-              <div className="flex justify-between text-xs text-zinc-600">
-                <span>
-                  {quest.have ?? 0}/{quest.need ?? 0}
-                </span>
-                <span className="text-violet-400">
-                  {(quest.expReward ?? 0) > 0 ? `+${quest.expReward} EXP` : ""}
-                  {(quest.goldReward ?? 0) > 0 ? ` +${quest.goldReward}₲` : ""}
-                </span>
-              </div>
-            </div>
-          );
-        })}
- 
-        {allDone && (
-          <div className="px-4 py-3 text-center text-emerald-400 text-sm font-semibold border-t border-zinc-800">
-            All quests complete! Rewards claimed.
-          </div>
-        )}
- 
-        {!daily?.active && quests.length === 0 && (
-          <div className="px-4 py-3 text-xs text-zinc-600 text-center">
-            No active daily quest. One will appear at the next reset.
-          </div>
-        )}
-      </div>
- 
-      {/* Activity log */}
-      <div className="bg-zinc-900 rounded-xl border border-zinc-800 p-3">
-        <div className="text-sm font-semibold text-zinc-300 mb-2">Activity Log</div>
-        <div className="space-y-0.5 max-h-52 overflow-y-auto">
-          {log.length === 0 ? (
-            <div className="text-xs text-zinc-600">No activity yet.</div>
-          ) : (
-            [...log]
-              .reverse()
-              .slice(0, 60)
-              .map((entry, i) => (
-                <div key={i} className="text-xs text-zinc-500 leading-relaxed">
-                  {entry}
-                </div>
-              ))
-          )}
-        </div>
-      </div>
- 
-      {/* Lore & Story */}
-      <details className="bg-zinc-900 rounded-xl border border-zinc-800">
-        <summary className="px-4 py-3 text-sm font-semibold text-zinc-400 cursor-pointer select-none list-none flex justify-between">
-          <span>Lore &amp; Story</span>
-          <span className="text-zinc-600 text-xs">tap to expand</span>
-        </summary>
-        <div className="px-4 pb-4 pt-1 space-y-3 border-t border-zinc-800">
-          {MOBILE_LORE.filter(e => (player.level ?? 1) >= e.level).map((entry, i) => (
-            <div key={i}>
-              <div className="text-xs font-semibold text-violet-400 mb-0.5">{entry.title}</div>
-              <div className="text-xs text-zinc-500 leading-relaxed">{entry.text}</div>
-            </div>
-          ))}
-          {MOBILE_LORE.some(e => (player.level ?? 1) < e.level) && (
-            <div className="text-xs text-zinc-600 italic text-center pt-1">
-              More lore unlocks as you level up...
-            </div>
-          )}
-        </div>
-      </details>
-    </div>
-  );
-}
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/client/src/components/game/mobile/ManageTab.tsx.html b/coverage/client/src/components/game/mobile/ManageTab.tsx.html deleted file mode 100644 index 9b58e19..0000000 --- a/coverage/client/src/components/game/mobile/ManageTab.tsx.html +++ /dev/null @@ -1,1012 +0,0 @@ - - - - - - Code coverage report for client/src/components/game/mobile/ManageTab.tsx - - - - - - - - - -
-
-

All files / client/src/components/game/mobile ManageTab.tsx

-
- -
- 0% - Statements - 0/29 -
- - -
- 0% - Branches - 0/70 -
- - -
- 0% - Functions - 0/21 -
- - -
- 0% - Lines - 0/28 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63 -64 -65 -66 -67 -68 -69 -70 -71 -72 -73 -74 -75 -76 -77 -78 -79 -80 -81 -82 -83 -84 -85 -86 -87 -88 -89 -90 -91 -92 -93 -94 -95 -96 -97 -98 -99 -100 -101 -102 -103 -104 -105 -106 -107 -108 -109 -110 -111 -112 -113 -114 -115 -116 -117 -118 -119 -120 -121 -122 -123 -124 -125 -126 -127 -128 -129 -130 -131 -132 -133 -134 -135 -136 -137 -138 -139 -140 -141 -142 -143 -144 -145 -146 -147 -148 -149 -150 -151 -152 -153 -154 -155 -156 -157 -158 -159 -160 -161 -162 -163 -164 -165 -166 -167 -168 -169 -170 -171 -172 -173 -174 -175 -176 -177 -178 -179 -180 -181 -182 -183 -184 -185 -186 -187 -188 -189 -190 -191 -192 -193 -194 -195 -196 -197 -198 -199 -200 -201 -202 -203 -204 -205 -206 -207 -208 -209 -210 -211 -212 -213 -214 -215 -216 -217 -218 -219 -220 -221 -222 -223 -224 -225 -226 -227 -228 -229 -230 -231 -232 -233 -234 -235 -236 -237 -238 -239 -240 -241 -242 -243 -244 -245 -246 -247 -248 -249 -250 -251 -252 -253 -254 -255 -256 -257 -258 -259 -260 -261 -262 -263 -264 -265 -266 -267 -268 -269 -270 -271 -272 -273 -274 -275 -276 -277 -278 -279 -280 -281 -282 -283 -284 -285 -286 -287 -288 -289 -290 -291 -292 -293 -294 -295 -296 -297 -298 -299 -300 -301 -302 -303 -304 -305 -306 -307 -308 -309 -310  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 
import { useState } from "react";
- 
-const STATS = ["STR", "AGI", "INT", "VIT", "LUCK"] as const;
- 
-interface ManageTabProps {
-  player: any;
-  gold: number;
-  prestigeUpgrades: Record<string, number>;
-  soundEnabled: boolean;
-  musicEnabled: boolean;
-  volume: number;
-  onAllocateStat: (stat: string, amount?: number) => void;
-  onTrain: (type: string) => void;
-  onBuyItem: (itemId: string) => void;
-  onEquipItem: (itemId: string) => void;
-  onUnequipItem: (slot: string) => void;
-  onUseRune: (itemId: string) => void;
-  onSave: () => void;
-  onLoad: () => void;
-  onRebirth: () => void;
-  onReset: () => void;
-  onSetSoundEnabled: (v: boolean) => void;
-  onSetMusicEnabled: (v: boolean) => void;
-  onSetVolume: (v: number) => void;
-}
- 
-function Accordion({ title, badge, defaultOpen = false, children }: {
-  title: string;
-  badge?: React.ReactNode;
-  defaultOpen?: boolean;
-  children: React.ReactNode;
-}) {
-  const [open, setOpen] = useState(defaultOpen);
-  return (
-    <div className="border border-zinc-800 rounded-xl overflow-hidden">
-      <button
-        onClick={() => setOpen(o => !o)}
-        className="w-full flex items-center justify-between px-4 py-3.5 bg-zinc-900 text-sm font-semibold text-zinc-200"
-      >
-        <span className="flex items-center gap-2">{title}{badge}</span>
-        <span className="text-zinc-500 text-xs">{open ? "▲" : "▼"}</span>
-      </button>
-      {open && <div className="bg-zinc-950 p-4">{children}</div>}
-    </div>
-  );
-}
- 
-const RARITY_COLOR: Record<string, string> = {
-  common: "text-zinc-400",
-  uncommon: "text-green-400",
-  rare: "text-blue-400",
-  epic: "text-purple-400",
-  legendary: "text-yellow-400",
-};
- 
-const SLOT_LABEL: Record<string, string> = {
-  weapon: "Weapon",
-  armor: "Armor",
-  accessory: "Accessory",
-};
- 
-export function ManageTab({
-  player, gold, prestigeUpgrades,
-  soundEnabled, musicEnabled, volume,
-  onAllocateStat, onTrain, onBuyItem,
-  onEquipItem, onUnequipItem, onUseRune,
-  onSave, onLoad, onRebirth, onReset,
-  onSetSoundEnabled, onSetMusicEnabled, onSetVolume,
-}: ManageTabProps) {
-  const hasPoints = (player.points ?? 0) > 0;
-  const level = player.level ?? 1;
- 
-  // Match real game cost formulas from HuntersPath.tsx
-  const shopItems = [
-    { id: "potion",    label: "Health Potion",   effect: "Restore HP in combat",   cost: 25 },
-    { id: "weapon",    label: "Weapon Upgrade",  effect: "+STR",                    cost: 100 + level * 25 },
-    { id: "armor",     label: "Armor Upgrade",   effect: "+VIT",                    cost: 80 + level * 20 },
-    { id: "accessory", label: "Accessory Upgrade", effect: "+LUCK",                 cost: 120 + level * 30 },
-  ];
- 
-  return (
-    <div className="p-3 space-y-2 pb-4">
-      {/* Stat points banner */}
-      {hasPoints && (
-        <div className="bg-violet-900/40 border border-violet-700 rounded-xl px-4 py-2.5 text-sm text-violet-300 font-semibold">
-          ● {player.points} stat point{player.points !== 1 ? "s" : ""} available — allocate below
-        </div>
-      )}
- 
-      {/* Stats */}
-      <Accordion
-        title="Stats"
-        defaultOpen={hasPoints}
-        badge={hasPoints ? <span className="w-2 h-2 rounded-full bg-red-500 inline-block" /> : undefined}
-      >
-        <div className="grid grid-cols-2 gap-2">
-          {STATS.map(stat => (
-            <div key={stat} className="flex items-center justify-between bg-zinc-900 rounded-lg px-3 py-2.5">
-              <div>
-                <div className="text-xs text-zinc-500 uppercase tracking-wide">{stat}</div>
-                <div className="text-lg font-bold text-zinc-100">
-                  {player.stats?.[stat] ?? 0}
-                </div>
-              </div>
-              <div className="flex gap-1">
-                {[1, 5, 10].map(n => (
-                  <button
-                    key={n}
-                    onClick={() => onAllocateStat(stat, n)}
-                    disabled={!hasPoints}
-                    className={`${n === 1 ? "w-9" : "w-10"} h-9 rounded-lg bg-violet-600 text-white text-xs font-bold disabled:bg-zinc-800 disabled:text-zinc-600 flex items-center justify-center active:bg-violet-500`}
-                    aria-label={`Allocate ${n} point${n > 1 ? "s" : ""} to ${stat}`}
-                  >
-                    +{n}
-                  </button>
-                ))}
-              </div>
-            </div>
-          ))}
-        </div>
-        <div className="mt-2 text-xs text-zinc-600 text-center">
-          {player.points ?? 0} point{(player.points ?? 0) !== 1 ? "s" : ""} remaining
-        </div>
-      </Accordion>
- 
-      {/* Equipment */}
-      <Accordion title="Equipment">
-        <div className="space-y-2">
-          {(["weapon", "armor", "accessory"] as const).map((slot) => {
-            const item = player.equipment?.[slot];
-            return (
-              <div key={slot} className="flex items-center justify-between bg-zinc-900 rounded-lg px-3 py-2.5">
-                <div className="min-w-0">
-                  <div className="text-xs text-zinc-500 uppercase tracking-wide">{SLOT_LABEL[slot]}</div>
-                  {item ? (
-                    <div className={`text-sm font-medium ${RARITY_COLOR[item.rarity] ?? "text-zinc-300"}`}>
-                      {item.name}
-                      {item.stats && (
-                        <span className="text-xs text-zinc-500 ml-1">
-                          ({Object.entries(item.stats).map(([k, v]) => `+${v} ${k}`).join(", ")})
-                        </span>
-                      )}
-                    </div>
-                  ) : (
-                    <div className="text-sm text-zinc-600 italic">Empty</div>
-                  )}
-                </div>
-                {item && (
-                  <button
-                    onClick={() => onUnequipItem(slot)}
-                    className="shrink-0 ml-2 px-2.5 py-1.5 rounded-lg bg-zinc-800 text-xs text-zinc-400 active:bg-zinc-700"
-                  >
-                    Unequip
-                  </button>
-                )}
-              </div>
-            );
-          })}
-        </div>
-      </Accordion>
- 
-      {/* Inventory */}
-      {(player.inv ?? []).length > 0 && (
-        <Accordion title={`Inventory (${player.inv.length})`}>
-          <div className="space-y-1.5">
-            {(player.inv ?? []).map((item: any) => (
-              <div key={item.id} className="flex items-center justify-between bg-zinc-900 rounded-lg px-3 py-2.5">
-                <div className="min-w-0 flex-1">
-                  <div className={`text-sm font-medium ${RARITY_COLOR[item.rarity] ?? "text-zinc-300"}`}>
-                    {item.name}
-                  </div>
-                  <div className="text-xs text-zinc-500">
-                    {item.type}
-                    {item.stats && (
-                      <span className="ml-1">
-                        ({Object.entries(item.stats).map(([k, v]) => `+${v} ${k}`).join(", ")})
-                      </span>
-                    )}
-                  </div>
-                </div>
-                {item.type === "equipment" && item.equipmentSlot && (
-                  <button
-                    onClick={() => onEquipItem(item.id)}
-                    className="shrink-0 ml-2 px-3 py-1.5 rounded-lg bg-violet-600 text-xs text-white font-semibold active:bg-violet-500"
-                  >
-                    Equip
-                  </button>
-                )}
-                {item.type === "rune" && (
-                  <button
-                    onClick={() => onUseRune(item.id)}
-                    className="shrink-0 ml-2 px-3 py-1.5 rounded-lg bg-emerald-700 text-xs text-white font-semibold active:bg-emerald-600"
-                  >
-                    Use
-                  </button>
-                )}
-              </div>
-            ))}
-          </div>
-        </Accordion>
-      )}
- 
-      {/* Training */}
-      <Accordion title="Training">
-        <div className="space-y-2">
-          {[
-            { id: "physical",   label: "Physical Training", reward: "+8–15 EXP",             color: "text-green-400" },
-            { id: "mental",     label: "Mental Training",   reward: "+6–12 EXP",             color: "text-blue-400" },
-            { id: "meditation", label: "Meditation",        reward: "–Fatigue · +4–8 EXP",  color: "text-purple-400" },
-            { id: "work",       label: "Work Job",          reward: "+15–35₲ · +3–8 EXP",   color: "text-yellow-400" },
-          ].map(({ id, label, reward, color }) => (
-            <button
-              key={id}
-              onClick={() => onTrain(id)}
-              className="w-full flex items-center justify-between bg-zinc-900 rounded-lg px-4 py-3 active:bg-zinc-800 text-left"
-            >
-              <span className="text-sm text-zinc-200">{label}</span>
-              <span className={`text-xs ${color}`}>{reward}</span>
-            </button>
-          ))}
-        </div>
-      </Accordion>
- 
-      {/* Hunter Shop */}
-      <Accordion title="Hunter Shop">
-        <div className="space-y-2">
-          {shopItems.map(({ id, label, effect, cost }) => (
-            <button
-              key={id}
-              onClick={() => onBuyItem(id)}
-              disabled={gold < cost}
-              className="w-full flex items-center justify-between bg-zinc-900 rounded-lg px-4 py-3 disabled:opacity-40 active:bg-zinc-800 text-left"
-            >
-              <div>
-                <div className="text-sm text-zinc-200">{label}</div>
-                <div className="text-xs text-zinc-500">{effect}</div>
-              </div>
-              <span className={`text-sm font-bold ${gold >= cost ? "text-yellow-400" : "text-zinc-600"}`}>
-                {cost}₲
-              </span>
-            </button>
-          ))}
-        </div>
-      </Accordion>
- 
-      {/* Prestige Shop — only after first rebirth */}
-      {(player.rebirths ?? 0) > 0 && (
-        <Accordion title={`Prestige Shop  ⚡${player.prestigePoints ?? 0} PP`}>
-          <div className="text-xs text-zinc-500 text-center py-2">
-            Prestige upgrades available here. Check desktop view for full details.
-          </div>
-        </Accordion>
-      )}
- 
-      {/* Settings */}
-      <Accordion title="Settings">
-        <div className="space-y-2">
-          {/* Audio */}
-          <div className="flex gap-2">
-            <button
-              onClick={() => onSetSoundEnabled(!soundEnabled)}
-              className={`flex-1 rounded-lg py-2.5 text-sm font-medium ${soundEnabled ? "bg-violet-700 text-white" : "bg-zinc-800 text-zinc-500"}`}
-            >
-              Sound {soundEnabled ? "ON" : "OFF"}
-            </button>
-            <button
-              onClick={() => onSetMusicEnabled(!musicEnabled)}
-              className={`flex-1 rounded-lg py-2.5 text-sm font-medium ${musicEnabled ? "bg-violet-700 text-white" : "bg-zinc-800 text-zinc-500"}`}
-            >
-              Music {musicEnabled ? "ON" : "OFF"}
-            </button>
-          </div>
-          <input
-            type="range" min="0" max="1" step="0.05"
-            value={volume}
-            onChange={e => onSetVolume(Number(e.target.value))}
-            className="w-full accent-violet-500"
-            aria-label="Volume"
-          />
-          {/* Save / Load */}
-          <div className="flex gap-2">
-            <button onClick={onSave} className="flex-1 bg-zinc-800 rounded-lg py-2.5 text-sm text-zinc-200 active:bg-zinc-700">
-              Save Game
-            </button>
-            <button onClick={onLoad} className="flex-1 bg-zinc-800 rounded-lg py-2.5 text-sm text-zinc-200 active:bg-zinc-700">
-              Load Game
-            </button>
-          </div>
-          {/* Rebirth */}
-          {(player.level ?? 0) >= 50 && (
-            <button
-              onClick={onRebirth}
-              className="w-full bg-amber-900/50 border border-amber-700 rounded-lg py-3 text-sm text-amber-300 font-semibold active:bg-amber-900"
-            >
-              ⚡ Rebirth  (Level {player.level})
-            </button>
-          )}
-          {/* Reset */}
-          <button
-            onClick={onReset}
-            className="w-full bg-zinc-900 border border-red-900/60 rounded-lg py-2.5 text-sm text-red-500 active:border-red-700"
-          >
-            Reset Game
-          </button>
-        </div>
-      </Accordion>
-    </div>
-  );
-}
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/client/src/components/game/mobile/MobileLayout.tsx.html b/coverage/client/src/components/game/mobile/MobileLayout.tsx.html deleted file mode 100644 index 76e4537..0000000 --- a/coverage/client/src/components/game/mobile/MobileLayout.tsx.html +++ /dev/null @@ -1,529 +0,0 @@ - - - - - - Code coverage report for client/src/components/game/mobile/MobileLayout.tsx - - - - - - - - - -
-
-

All files / client/src/components/game/mobile MobileLayout.tsx

-
- -
- 0% - Statements - 0/8 -
- - -
- 0% - Branches - 0/20 -
- - -
- 0% - Functions - 0/2 -
- - -
- 0% - Lines - 0/7 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63 -64 -65 -66 -67 -68 -69 -70 -71 -72 -73 -74 -75 -76 -77 -78 -79 -80 -81 -82 -83 -84 -85 -86 -87 -88 -89 -90 -91 -92 -93 -94 -95 -96 -97 -98 -99 -100 -101 -102 -103 -104 -105 -106 -107 -108 -109 -110 -111 -112 -113 -114 -115 -116 -117 -118 -119 -120 -121 -122 -123 -124 -125 -126 -127 -128 -129 -130 -131 -132 -133 -134 -135 -136 -137 -138 -139 -140 -141 -142 -143 -144 -145 -146 -147 -148 -149  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 
import React, { useEffect, useState } from "react";
-import { BottomTabBar, MobileTab } from "./BottomTabBar";
-import { CombatTab } from "./CombatTab";
-import { ManageTab } from "./ManageTab";
-import { SpiritsTab } from "./SpiritsTab";
-import { LogTab } from "./LogTab";
- 
-// Full props interface — using loose types here so we can build incrementally
-// will be tightened in a later task
-export interface MobileLayoutProps {
-  player: any;
-  playerPower: number;
-  gates: any[];
-  gold: number;
-  daily: any;
-  log: string[];
-  running: any;
-  combatResult: any;
-  combatLog: string[];
-  autoDungeon: boolean;
-  soundEnabled: boolean;
-  musicEnabled: boolean;
-  volume: number;
-  // handlers
-  onStartGate: (gate: any) => void;
-  onRest: () => void;
-  onUseKey: () => void;
-  onRefreshGates: () => void;
-  onUsePotion: (itemId: string) => void;
-  onDismissResult: () => void;
-  onAllocateStat: (stat: string, amount?: number) => void;
-  onForfeitDaily: () => void;
-  onRebirth: () => void;
-  onReset: () => void;
-  onSave: () => void;
-  onLoad: () => void;
-  onToggleAuto: () => void;
-  onTrain: (type: string) => void;
-  onBuyItem: (itemId: string) => void;
-  onEquipItem: (itemId: string) => void;
-  onUnequipItem: (slot: string) => void;
-  onUseRune: (itemId: string) => void;
-  onSetSoundEnabled: (v: boolean) => void;
-  onSetMusicEnabled: (v: boolean) => void;
-  onSetVolume: (v: number) => void;
-  // modal state
-  spiritBindingState: any;
-  levelUpState: any;
-  rebirthModalOpen: boolean;
-  onSetRebirthModalOpen: (v: boolean) => void;
-  // extra
-  prestigeUpgrades: Record<string, number>;
-  // modal overlays
-  modalOverlay?: React.ReactNode;
-}
- 
-export function MobileLayout(props: MobileLayoutProps) {
-  const [activeTab, setActiveTab] = useState<MobileTab>("combat");
- 
-  const isRunning = Boolean(props.running);
-  // Auto-switch to Combat when a run starts
-  useEffect(() => {
-    if (isRunning) setActiveTab("combat");
-  }, [isRunning]);
- 
-  const statPointBadge = (props.player?.points ?? 0) > 0;
-  const dailyCompleteBadge = props.daily?.completed === true;
- 
-  return (
-    <div className="flex flex-col h-[100dvh] bg-zinc-950 text-zinc-100 overflow-hidden">
-      {/* Slim header */}
-      <header className="flex items-center justify-between px-4 py-2 bg-zinc-900 border-b border-zinc-800 shrink-0">
-        <span className="text-sm font-bold text-violet-400">Hunter's Path</span>
-        <div className="flex items-center gap-3 text-xs text-zinc-300">
-          <span>₲{props.gold ?? 0}</span>
-          <span>🔑{props.player?.keys ?? 0}</span>
-          {(props.player?.prestigePoints ?? 0) > 0 && (
-            <span className="text-amber-400">⚡{props.player.prestigePoints}</span>
-          )}
-        </div>
-      </header>
- 
-      {/* Tab content */}
-      <main className="flex-1 overflow-y-auto overflow-x-hidden">
-        {activeTab === "combat" && (
-          <CombatTab
-            player={props.player}
-            playerPower={props.playerPower}
-            gates={props.gates}
-            running={props.running}
-            combatResult={props.combatResult}
-            combatLog={props.combatLog}
-            autoDungeon={props.autoDungeon}
-            onToggleAuto={props.onToggleAuto}
-            onStartGate={props.onStartGate}
-            onRest={props.onRest}
-            onUseKey={props.onUseKey}
-            onRefreshGates={props.onRefreshGates}
-            onUsePotion={props.onUsePotion}
-            onDismissResult={props.onDismissResult}
-          />
-        )}
-        {activeTab === "manage" && (
-          <ManageTab
-            player={props.player}
-            gold={props.gold}
-            prestigeUpgrades={props.prestigeUpgrades}
-            soundEnabled={props.soundEnabled}
-            musicEnabled={props.musicEnabled}
-            volume={props.volume}
-            onAllocateStat={props.onAllocateStat}
-            onTrain={props.onTrain}
-            onBuyItem={props.onBuyItem}
-            onEquipItem={props.onEquipItem}
-            onUnequipItem={props.onUnequipItem}
-            onUseRune={props.onUseRune}
-            onSave={props.onSave}
-            onLoad={props.onLoad}
-            onRebirth={props.onRebirth}
-            onReset={props.onReset}
-            onSetSoundEnabled={props.onSetSoundEnabled}
-            onSetMusicEnabled={props.onSetMusicEnabled}
-            onSetVolume={props.onSetVolume}
-          />
-        )}
-        {activeTab === "spirits" && <SpiritsTab player={props.player} />}
-        {activeTab === "log" && (
-          <LogTab
-            daily={props.daily}
-            log={props.log}
-            player={props.player}
-            onForfeitDaily={props.onForfeitDaily}
-          />
-        )}
-      </main>
- 
-      <BottomTabBar
-        activeTab={activeTab}
-        onTabChange={setActiveTab}
-        statPointBadge={statPointBadge}
-        dailyCompleteBadge={dailyCompleteBadge}
-      />
- 
-      {/* Modal overlays — rendered on top of the mobile layout */}
-      {props.modalOverlay}
-    </div>
-  );
-}
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/client/src/components/game/mobile/SpiritsTab.tsx.html b/coverage/client/src/components/game/mobile/SpiritsTab.tsx.html deleted file mode 100644 index daf0e15..0000000 --- a/coverage/client/src/components/game/mobile/SpiritsTab.tsx.html +++ /dev/null @@ -1,385 +0,0 @@ - - - - - - Code coverage report for client/src/components/game/mobile/SpiritsTab.tsx - - - - - - - - - -
-
-

All files / client/src/components/game/mobile SpiritsTab.tsx

-
- -
- 0% - Statements - 0/12 -
- - -
- 0% - Branches - 0/30 -
- - -
- 0% - Functions - 0/5 -
- - -
- 0% - Lines - 0/11 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63 -64 -65 -66 -67 -68 -69 -70 -71 -72 -73 -74 -75 -76 -77 -78 -79 -80 -81 -82 -83 -84 -85 -86 -87 -88 -89 -90 -91 -92 -93 -94 -95 -96 -97 -98 -99 -100 -101  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 
const RARITY_BORDER: Record<string, string> = {
-  common:    "border-l-zinc-500",
-  uncommon:  "border-l-green-500",
-  rare:      "border-l-blue-500",
-  epic:      "border-l-purple-500",
-  legendary: "border-l-yellow-400",
-};
- 
-const RARITY_LABEL: Record<string, string> = {
-  common:    "★",
-  uncommon:  "★★",
-  rare:      "★★★",
-  epic:      "★★★★",
-  legendary: "★★★★★",
-};
- 
-export function SpiritsTab({ player }: { player: any }) {
-  const spirits = player.spirits ?? [];
-  const totalPower = spirits.reduce((a: number, s: any) => a + (s.power ?? 0), 0);
-  const mpUpkeep = Math.floor(
-    spirits.length +
-    spirits.reduce((a: number, s: any) => a + (s.power ?? 0) * 0.02, 0)
-  );
- 
-  if (spirits.length === 0) {
-    return (
-      <div className="flex flex-col items-center justify-center h-64 text-zinc-500 px-6 text-center gap-3 pt-12">
-        <div className="text-5xl">👻</div>
-        <div className="text-sm font-semibold text-zinc-400">No spirits yet</div>
-        <div className="text-xs">Defeat bosses in gates to bind their spirits to your army.</div>
-      </div>
-    );
-  }
- 
-  return (
-    <div className="p-3">
-      {/* Summary bar */}
-      <div className="flex justify-between text-sm mb-3 bg-zinc-900 rounded-xl px-4 py-3 border border-zinc-800">
-        <span className="text-zinc-400">
-          Army PWR <span className="text-violet-300 font-bold ml-1">{totalPower}</span>
-        </span>
-        <span className="text-zinc-400">
-          MP Upkeep <span className="text-blue-300 font-bold ml-1">{mpUpkeep}/tick</span>
-        </span>
-      </div>
- 
-      {/* Spirit cards */}
-      <div className="space-y-2">
-        {spirits.map((spirit: any) => (
-          <div
-            key={spirit.id}
-            className={`bg-zinc-900 border-l-4 ${RARITY_BORDER[spirit.rarity] ?? "border-l-zinc-500"} rounded-xl p-3 border border-zinc-800`}
-          >
-            <div className="flex items-start justify-between mb-2">
-              <div>
-                <span className="text-sm font-semibold text-zinc-100">{spirit.name}</span>
-                <span className="ml-2 text-xs text-zinc-500">{spirit.type}</span>
-              </div>
-              <div className="text-right shrink-0">
-                <div className="text-xs text-zinc-500">
-                  {RARITY_LABEL[spirit.rarity] ?? "★"} {spirit.rarity}
-                </div>
-                <div className="text-xs text-violet-400 font-semibold">PWR {spirit.power ?? 0}</div>
-              </div>
-            </div>
- 
-            {/* Level + EXP bar */}
-            <div className="flex items-center gap-2 mb-2">
-              <span className="text-xs bg-zinc-800 rounded px-1.5 py-0.5 text-zinc-400">
-                Lv {spirit.level ?? 1}
-              </span>
-              <div className="flex-1 h-1.5 bg-zinc-800 rounded-full overflow-hidden">
-                <div
-                  className="h-full bg-violet-600 rounded-full"
-                  style={{
-                    width: `${
-                      (spirit.expToNext ?? 0) > 0
-                        ? Math.min(100, ((spirit.exp ?? 0) / spirit.expToNext) * 100)
-                        : 0
-                    }%`,
-                  }}
-                />
-              </div>
-              <span className="text-xs text-zinc-600">
-                {spirit.exp ?? 0}/{spirit.expToNext ?? 100}
-              </span>
-            </div>
- 
-            {/* Abilities */}
-            {(spirit.abilities ?? []).map((ab: any, i: number) => (
-              <div key={ab.id ?? i} className="text-xs text-zinc-500">
-                <span className="text-zinc-300 font-medium">{ab.name}:</span> {ab.description}
-              </div>
-            ))}
-          </div>
-        ))}
-      </div>
-    </div>
-  );
-}
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/client/src/components/game/mobile/index.html b/coverage/client/src/components/game/mobile/index.html deleted file mode 100644 index 4e191a8..0000000 --- a/coverage/client/src/components/game/mobile/index.html +++ /dev/null @@ -1,191 +0,0 @@ - - - - - - Code coverage report for client/src/components/game/mobile - - - - - - - - - -
-
-

All files client/src/components/game/mobile

-
- -
- 0% - Statements - 0/92 -
- - -
- 0% - Branches - 0/271 -
- - -
- 0% - Functions - 0/50 -
- - -
- 0% - Lines - 0/87 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FileStatementsBranchesFunctionsLines
BottomTabBar.tsx -
-
0%0/60%0/140%0/30%0/6
CombatTab.tsx -
-
0%0/230%0/820%0/120%0/22
LogTab.tsx -
-
0%0/140%0/550%0/70%0/13
ManageTab.tsx -
-
0%0/290%0/700%0/210%0/28
MobileLayout.tsx -
-
0%0/80%0/200%0/20%0/7
SpiritsTab.tsx -
-
0%0/120%0/300%0/50%0/11
-
-
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/client/src/components/game/sections/ActivityLog.tsx.html b/coverage/client/src/components/game/sections/ActivityLog.tsx.html deleted file mode 100644 index 7584111..0000000 --- a/coverage/client/src/components/game/sections/ActivityLog.tsx.html +++ /dev/null @@ -1,190 +0,0 @@ - - - - - - Code coverage report for client/src/components/game/sections/ActivityLog.tsx - - - - - - - - - -
-
-

All files / client/src/components/game/sections ActivityLog.tsx

-
- -
- 100% - Statements - 2/2 -
- - -
- 100% - Branches - 0/0 -
- - -
- 100% - Functions - 2/2 -
- - -
- 100% - Lines - 2/2 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36  -  -  -  -  -  -  -  -  -  -  -  -  -3x -  -  -  -  -  -  -  -  -  -  -  -4x -  -  -  -  -  -  -  -  -  - 
import React from "react";
-import {
-  Accordion,
-  AccordionContent,
-  AccordionItem,
-  AccordionTrigger,
-} from "@/components/ui/accordion";
- 
-interface ActivityLogProps {
-  log: string[];
-}
- 
-export function ActivityLog({ log }: ActivityLogProps) {
-  return (
-    <Accordion type="single" collapsible className="w-full">
-      <AccordionItem value="activity-log">
-        <AccordionTrigger className="text-lg font-bold text-zinc-100 hover:no-underline">
-          <div className="flex items-center space-x-2">
-            <i className="fas fa-scroll text-zinc-400"></i>
-            <span>Activity Log</span>
-          </div>
-        </AccordionTrigger>
-        <AccordionContent>
-          <div className="bg-zinc-900/50 rounded-lg p-4 h-96 overflow-y-auto custom-scrollbar space-y-2 text-sm">
-            {log.map((m, i) => (
-              <div key={i} className="opacity-90">
-                • {m}
-              </div>
-            ))}
-          </div>
-        </AccordionContent>
-      </AccordionItem>
-    </Accordion>
-  );
-}
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/client/src/components/game/sections/DailyQuest.tsx.html b/coverage/client/src/components/game/sections/DailyQuest.tsx.html deleted file mode 100644 index f456e61..0000000 --- a/coverage/client/src/components/game/sections/DailyQuest.tsx.html +++ /dev/null @@ -1,796 +0,0 @@ - - - - - - Code coverage report for client/src/components/game/sections/DailyQuest.tsx - - - - - - - - - -
-
-

All files / client/src/components/game/sections DailyQuest.tsx

-
- -
- 100% - Statements - 4/4 -
- - -
- 83.33% - Branches - 15/18 -
- - -
- 100% - Functions - 2/2 -
- - -
- 100% - Lines - 4/4 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63 -64 -65 -66 -67 -68 -69 -70 -71 -72 -73 -74 -75 -76 -77 -78 -79 -80 -81 -82 -83 -84 -85 -86 -87 -88 -89 -90 -91 -92 -93 -94 -95 -96 -97 -98 -99 -100 -101 -102 -103 -104 -105 -106 -107 -108 -109 -110 -111 -112 -113 -114 -115 -116 -117 -118 -119 -120 -121 -122 -123 -124 -125 -126 -127 -128 -129 -130 -131 -132 -133 -134 -135 -136 -137 -138 -139 -140 -141 -142 -143 -144 -145 -146 -147 -148 -149 -150 -151 -152 -153 -154 -155 -156 -157 -158 -159 -160 -161 -162 -163 -164 -165 -166 -167 -168 -169 -170 -171 -172 -173 -174 -175 -176 -177 -178 -179 -180 -181 -182 -183 -184 -185 -186 -187 -188 -189 -190 -191 -192 -193 -194 -195 -196 -197 -198 -199 -200 -201 -202 -203 -204 -205 -206 -207 -208 -209 -210 -211 -212 -213 -214 -215 -216 -217 -218 -219 -220 -221 -222 -223 -224 -225 -226 -227 -228 -229 -230 -231 -232 -233 -234 -235 -236 -237 -238  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -8x -  -  -  -  -  -  -  -8x -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -12x -  -  -  -12x -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 
import React from "react";
-import {
-  Accordion,
-  AccordionContent,
-  AccordionItem,
-  AccordionTrigger,
-} from "@/components/ui/accordion";
- 
-interface Quest {
-  id: string;
-  name: string;
-  description: string;
-  difficulty: string;
-  type: string;
-  expReward: number;
-  goldReward: number;
-  bonusRewards?: boolean;
-  have: number;
-  need: number;
-}
- 
-interface Daily {
-  active: boolean;
-  completed: boolean;
-  questReputation: number;
-  completedQuests: string[];
-  availableQuests: Quest[];
-}
- 
-interface DailyQuestProps {
-  daily: Daily;
-  getDifficultyBgColor: (difficulty: string) => string;
-  getDifficultyColor: (difficulty: string) => string;
-}
- 
-export function DailyQuest({
-  daily,
-  getDifficultyBgColor,
-  getDifficultyColor,
-}: DailyQuestProps) {
-  const questIcons = {
-    combat: "fas fa-hand-fist",
-    exploration: "fas fa-door-open",
-    collection: "fas fa-box-open",
-    skill: "fas fa-magic",
-    challenge: "fas fa-trophy",
-  };
- 
-  return (
-    <Accordion type="single" collapsible className="w-full">
-      <AccordionItem value="daily-quest">
-        <AccordionTrigger className="text-lg font-bold text-zinc-100 hover:no-underline">
-          <div className="flex items-center justify-between w-full mr-4">
-            <span>Daily Quest</span>
-            <div className="flex items-center space-x-2">
-              {daily.active && (
-                <>
-                  <div className="w-3 h-3 bg-green-400 rounded-full animate-pulse"></div>
-                  <span className="text-sm text-green-400 font-medium">
-                    Active
-                  </span>
-                </>
-              )}
-              {/* Next reset timer */}
-              <div className="text-xs text-zinc-400">
-                <i className="fas fa-clock mr-1"></i>
-                Resets at midnight
-              </div>
-            </div>
-          </div>
-        </AccordionTrigger>
-        <AccordionContent>
-          <div className="max-h-96 overflow-y-auto">
-            {/* Quest Reputation Display */}
-            {daily.questReputation > 0 && (
-              <div className="bg-gradient-to-r from-purple-900/30 to-blue-900/30 border border-purple-500/30 rounded-lg p-3 mb-4">
-                <div className="flex items-center justify-between">
-                  <div className="flex items-center space-x-2">
-                    <i className="fas fa-star text-purple-400"></i>
-                    <span className="text-purple-200 font-medium">
-                      Quest Reputation
-                    </span>
-                  </div>
-                  <span className="text-purple-300 font-bold">
-                    {daily.questReputation}
-                  </span>
-                </div>
-                <div className="text-xs text-purple-200/80 mt-1">
-                  Higher reputation unlocks epic quests and better rewards
-                </div>
-              </div>
-            )}
- 
-            {!daily.active && !daily.completed && (
-              <div className="text-sm opacity-80 text-center py-8">
-                Start your Daily Quest to earn bonuses. Select 3 quests from 5
-                available options. Fail or quit and you face the Penalty Zone.
-              </div>
-            )}
- 
-            {daily.active && !daily.completed && (
-              <>
-                <div className="bg-gradient-to-r from-yellow-900/30 to-orange-900/30 border border-yellow-500/30 rounded-lg p-4 mb-4">
-                  <div className="flex items-center space-x-2 mb-2">
-                    <i className="fas fa-clock text-yellow-400"></i>
-                    <span className="text-yellow-200 font-medium">
-                      Complete quests to earn rewards!
-                    </span>
-                  </div>
-                  <p className="text-sm text-yellow-100/80">
-                    Progress: {daily.completedQuests.length}/
-                    {daily.availableQuests.length} completed
-                  </p>
-                </div>
- 
-                <div className="space-y-3">
-                  {daily.availableQuests.map((quest) => {
-                    const isCompleted = daily.completedQuests.includes(
-                      quest.id
-                    );
- 
-                    return (
-                      <div
-                        key={quest.id}
-                        className={`relative border-2 rounded-lg p-4 transition-all ${
-                          isCompleted
-                            ? "border-green-500 bg-green-900/20"
-                            : "border-zinc-600 bg-zinc-800/30"
-                        }`}
-                      >
-                        {/* Difficulty Badge */}
-                        <div
-                          className={`absolute top-2 right-2 px-2 py-1 rounded text-xs font-bold ${getDifficultyBgColor(
-                            quest.difficulty
-                          )}`}
-                        >
-                          {quest.difficulty.toUpperCase()}
-                        </div>
- 
-                        <div className="flex items-center space-x-3">
-                          <div
-                            className={`w-10 h-10 ${getDifficultyBgColor(
-                              quest.difficulty
-                            )} rounded-full flex items-center justify-center`}
-                          >
-                            <i
-                              className={`${
-                                questIcons[
-                                  quest.type as keyof typeof questIcons
-                                ]
-                              } text-white`}
-                            ></i>
-                          </div>
-                          <div className="flex-1">
-                            <div className="flex items-center space-x-2">
-                              <div
-                                className={`font-medium ${getDifficultyColor(
-                                  quest.difficulty
-                                )}`}
-                              >
-                                {quest.name}
-                              </div>
-                              {isCompleted && (
-                                <i className="fas fa-check-circle text-green-400"></i>
-                              )}
-                            </div>
-                            <div className="text-sm text-zinc-400 mt-1">
-                              {quest.description}
-                            </div>
-                            <div className="flex items-center space-x-4 mt-2 text-xs">
-                              <span className="text-green-400">
-                                +{quest.expReward} EXP
-                              </span>
-                              <span className="text-yellow-400">
-                                +{quest.goldReward} Gold
-                              </span>
-                              {quest.bonusRewards && (
-                                <span className="text-purple-400">
-                                  +Bonus Rewards
-                                </span>
-                              )}
-                            </div>
-                          </div>
-                        </div>
- 
-                        {/* Progress Bar for All Quests */}
-                        <div className="mt-3">
-                          <div className="flex items-center justify-between text-xs mb-1">
-                            <span className="text-zinc-400">Progress</span>
-                            <span className="text-green-400">
-                              {quest.have}/{quest.need}
-                            </span>
-                          </div>
-                          <div className="w-full bg-zinc-700 rounded-full h-2">
-                            <div
-                              className="bg-green-500 h-2 rounded-full transition-all"
-                              style={{
-                                width: `${Math.round(
-                                  (quest.have / quest.need) * 100
-                                )}%`,
-                              }}
-                            ></div>
-                          </div>
-                        </div>
-                      </div>
-                    );
-                  })}
-                </div>
- 
-                {/* Action Buttons */}
-                <div className="flex items-center justify-between mt-4">
-                  <div className="text-sm text-zinc-400 text-center">
-                    Complete quests to earn rewards and reputation!
-                  </div>
-                  <div className="text-xs text-violet-400 text-center mt-2">
-                    <i className="fas fa-crown mr-1"></i>
-                    Complete all 5 quests for Daily Master bonus rewards!
-                  </div>
-                </div>
-              </>
-            )}
- 
-            {daily.completed && (
-              <div className="text-emerald-400 text-sm text-center py-8">
-                <i className="fas fa-trophy text-2xl mb-2"></i>
-                <div>Daily quests completed!</div>
-                <div className="text-xs text-emerald-300 mt-1">
-                  よくやった (yoku yatta): well done!
-                </div>
-              </div>
-            )}
-          </div>
-        </AccordionContent>
-      </AccordionItem>
-    </Accordion>
-  );
-}
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/client/src/components/game/sections/HunterShop.tsx.html b/coverage/client/src/components/game/sections/HunterShop.tsx.html deleted file mode 100644 index e6ca0ee..0000000 --- a/coverage/client/src/components/game/sections/HunterShop.tsx.html +++ /dev/null @@ -1,361 +0,0 @@ - - - - - - Code coverage report for client/src/components/game/sections/HunterShop.tsx - - - - - - - - - -
-
-

All files / client/src/components/game/sections HunterShop.tsx

-
- -
- 0% - Statements - 0/4 -
- - -
- 100% - Branches - 0/0 -
- - -
- 0% - Functions - 0/4 -
- - -
- 0% - Lines - 0/4 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63 -64 -65 -66 -67 -68 -69 -70 -71 -72 -73 -74 -75 -76 -77 -78 -79 -80 -81 -82 -83 -84 -85 -86 -87 -88 -89 -90 -91 -92 -93  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 
import React from "react";
-import {
-  Accordion,
-  AccordionContent,
-  AccordionItem,
-  AccordionTrigger,
-} from "@/components/ui/accordion";
- 
-interface HunterShopProps {
-  gold: number;
-  playerLevel: number;
-  buyPotion: () => void;
-  buyUpgrade: (type: "weapon" | "armor" | "accessory") => void;
-}
- 
-export function HunterShop({
-  gold,
-  playerLevel,
-  buyPotion,
-  buyUpgrade,
-}: HunterShopProps) {
-  return (
-    <Accordion type="single" collapsible className="w-full">
-      <AccordionItem value="shop">
-        <AccordionTrigger className="text-lg font-bold text-yellow-300 hover:no-underline">
-          <i className="fas fa-shopping-cart mr-2"></i>
-          Hunter Shop
-        </AccordionTrigger>
-        <AccordionContent>
-          <div className="space-y-3 max-h-80 overflow-y-auto">
-            <div className="grid grid-cols-1 gap-2">
-              <button
-                onClick={buyPotion}
-                disabled={gold < 25}
-                className="flex items-center justify-between text-left w-full px-4 py-2 bg-zinc-700 hover:bg-zinc-600 disabled:opacity-50 disabled:cursor-not-allowed rounded-lg transition-colors"
-              >
-                <div className="flex items-center">
-                  <i className="fas fa-flask mr-2 text-green-400"></i>
-                  Health Potion
-                </div>
-                <span className="text-yellow-400">25₲</span>
-              </button>
-              <button
-                onClick={() => buyUpgrade("weapon")}
-                disabled={gold < 100 + playerLevel * 25}
-                className="flex items-center justify-between text-left w-full px-4 py-2 bg-zinc-700 hover:bg-zinc-600 disabled:opacity-50 disabled:cursor-not-allowed rounded-lg transition-colors"
-              >
-                <div className="flex items-center">
-                  <i className="fas fa-hand-fist mr-2 text-red-400"></i>
-                  Weapon Upgrade (+STR)
-                </div>
-                <span className="text-yellow-400">
-                  {100 + playerLevel * 25}₲
-                </span>
-              </button>
-              <button
-                onClick={() => buyUpgrade("armor")}
-                disabled={gold < 80 + playerLevel * 20}
-                className="flex items-center justify-between text-left w-full px-4 py-2 bg-zinc-700 hover:bg-zinc-600 disabled:opacity-50 disabled:cursor-not-allowed rounded-lg transition-colors"
-              >
-                <div className="flex items-center">
-                  <i className="fas fa-shield-alt mr-2 text-orange-400"></i>
-                  Armor Upgrade (+VIT)
-                </div>
-                <span className="text-yellow-400">
-                  {80 + playerLevel * 20}₲
-                </span>
-              </button>
-              <button
-                onClick={() => buyUpgrade("accessory")}
-                disabled={gold < 120 + playerLevel * 30}
-                className="flex items-center justify-between text-left w-full px-4 py-2 bg-zinc-700 hover:bg-zinc-600 disabled:opacity-50 disabled:cursor-not-allowed rounded-lg transition-colors"
-              >
-                <div className="flex items-center">
-                  <i className="fas fa-ring mr-2 text-purple-400"></i>
-                  Lucky Charm (+LUCK)
-                </div>
-                <span className="text-yellow-400">
-                  {120 + playerLevel * 30}₲
-                </span>
-              </button>
-            </div>
-            <p className="text-xs text-zinc-500 mt-2">
-              Equipment prices scale with your level. Upgrades permanently
-              increase stats.
-            </p>
-          </div>
-        </AccordionContent>
-      </AccordionItem>
-    </Accordion>
-  );
-}
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/client/src/components/game/sections/Inventory.tsx.html b/coverage/client/src/components/game/sections/Inventory.tsx.html deleted file mode 100644 index 29be62e..0000000 --- a/coverage/client/src/components/game/sections/Inventory.tsx.html +++ /dev/null @@ -1,235 +0,0 @@ - - - - - - Code coverage report for client/src/components/game/sections/Inventory.tsx - - - - - - - - - -
-
-

All files / client/src/components/game/sections Inventory.tsx

-
- -
- 0% - Statements - 0/1 -
- - -
- 0% - Branches - 0/2 -
- - -
- 0% - Functions - 0/1 -
- - -
- 0% - Lines - 0/1 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 
import React from "react";
-import {
-  Accordion,
-  AccordionContent,
-  AccordionItem,
-  AccordionTrigger,
-} from "@/components/ui/accordion";
- 
-interface Item {
-  id: string;
-  name: string;
-  type: string;
-  rarity: string;
-  quality: number;
-  description: string;
-  stats?: Record<string, number>;
-}
- 
-interface Player {
-  inv: Item[];
-}
- 
-interface InventoryProps {
-  player: Player;
-  EnhancedInventory: React.ComponentType;
-}
- 
-export function Inventory({ player, EnhancedInventory }: InventoryProps) {
-  return (
-    <Accordion type="single" collapsible className="w-full">
-      <AccordionItem value="inventory">
-        <AccordionTrigger className="text-xl font-bold text-zinc-100 hover:no-underline">
-          <div className="flex items-center justify-between w-full mr-4">
-            <span>Inventory</span>
-            {player.inv.length > 0 && (
-              <span className="bg-amber-600 text-white px-2 py-1 rounded-full text-xs font-bold">
-                {player.inv.length}
-              </span>
-            )}
-          </div>
-        </AccordionTrigger>
-        <AccordionContent>
-          <div className="max-h-96 overflow-y-auto">
-            <EnhancedInventory />
-          </div>
-        </AccordionContent>
-      </AccordionItem>
-    </Accordion>
-  );
-}
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/client/src/components/game/sections/Lore.tsx.html b/coverage/client/src/components/game/sections/Lore.tsx.html deleted file mode 100644 index e9cbd2d..0000000 --- a/coverage/client/src/components/game/sections/Lore.tsx.html +++ /dev/null @@ -1,190 +0,0 @@ - - - - - - Code coverage report for client/src/components/game/sections/Lore.tsx - - - - - - - - - -
-
-

All files / client/src/components/game/sections Lore.tsx

-
- -
- 0% - Statements - 0/1 -
- - -
- 100% - Branches - 0/0 -
- - -
- 0% - Functions - 0/1 -
- - -
- 0% - Lines - 0/1 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 
import React from "react";
-import {
-  Accordion,
-  AccordionContent,
-  AccordionItem,
-  AccordionTrigger,
-} from "@/components/ui/accordion";
- 
-export function Lore() {
-  return (
-    <Accordion type="single" collapsible className="w-full">
-      <AccordionItem value="lore">
-        <AccordionTrigger className="font-semibold hover:no-underline">
-          Lore (Mechanics)
-        </AccordionTrigger>
-        <AccordionContent>
-          <ul className="text-xs opacity-80 list-disc pl-5 space-y-1">
-            <li>Gates lead to Dungeons. Clear them to gain EXP/loot.</li>
-            <li>Daily Quest must be completed or the Penalty Zone triggers.</li>
-            <li>
-              Level up to gain Stat Points. STR/AGI raise damage; INT/LUCK aid
-              extraction.
-            </li>
-            <li>
-              Spirit Binding after boss defeat may recruit a bound spirit (25%
-              base chance).
-            </li>
-            <li>Fatigue reduces your total power; Rest lowers it.</li>
-            <li>Instant Dungeon Keys open bonus runs with better rewards.</li>
-          </ul>
-        </AccordionContent>
-      </AccordionItem>
-    </Accordion>
-  );
-}
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/client/src/components/game/sections/RebirthModal.tsx.html b/coverage/client/src/components/game/sections/RebirthModal.tsx.html deleted file mode 100644 index 78f9b3c..0000000 --- a/coverage/client/src/components/game/sections/RebirthModal.tsx.html +++ /dev/null @@ -1,292 +0,0 @@ - - - - - - Code coverage report for client/src/components/game/sections/RebirthModal.tsx - - - - - - - - - -
-
-

All files / client/src/components/game/sections RebirthModal.tsx

-
- -
- 0% - Statements - 0/4 -
- - -
- 100% - Branches - 0/0 -
- - -
- 0% - Functions - 0/2 -
- - -
- 0% - Lines - 0/4 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63 -64 -65 -66 -67 -68 -69 -70  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter } from "@/components/ui/dialog";
- 
-interface RebirthModalProps {
-  open: boolean;
-  onOpenChange: (open: boolean) => void;
-  onConfirm: () => void;
-  playerLevel: number;
-  rebirthCount: number;
-}
- 
-export function RebirthModal({ open, onOpenChange, onConfirm, playerLevel, rebirthCount }: RebirthModalProps) {
-  const earnedPoints = Math.floor(playerLevel * 10 * (1 + rebirthCount * 0.5));
-  const newBonus = (rebirthCount + 1) * 15;
- 
-  return (
-    <Dialog open={open} onOpenChange={onOpenChange}>
-      <DialogContent>
-        <DialogHeader>
-          <DialogTitle>⚡ Rebirth</DialogTitle>
-          <DialogDescription>
-            Reset your progress to gain permanent bonuses!
-          </DialogDescription>
-        </DialogHeader>
- 
-        <div className="space-y-4 py-4">
-          <div className="bg-red-900/20 border border-red-500/30 p-3 rounded-lg">
-            <p className="text-red-400 font-bold">⚠️ This will reset:</p>
-            <ul className="text-red-300 text-sm mt-2 space-y-1">
-              <li>• All gold (₲)</li>
-              <li>• All keys</li>
-              <li>• All gates cleared</li>
-              <li>• Fatigue</li>
-            </ul>
-          </div>
- 
-          <div className="bg-green-900/20 border border-green-500/30 p-3 rounded-lg">
-            <p className="text-green-400 font-bold">✅ You will keep:</p>
-            <ul className="text-green-300 text-sm mt-2 space-y-1">
-              <li>• Your level ({playerLevel})</li>
-              <li>• All allocated stats</li>
-              <li>• Your Spirit Legion</li>
-            </ul>
-          </div>
- 
-          <div className="bg-purple-900/20 border border-purple-500/30 p-3 rounded-lg text-center">
-            <p className="text-purple-400 font-bold">🎁 You will gain:</p>
-            <p className="text-2xl font-bold text-purple-300">+{earnedPoints} Prestige Points</p>
-            <p className="text-purple-400">+{newBonus}% Power Bonus</p>
-          </div>
-        </div>
- 
-        <DialogFooter>
-          <button
-            onClick={() => onOpenChange(false)}
-            className="px-4 py-2 bg-zinc-700 text-white rounded hover:bg-zinc-600"
-          >
-            Cancel
-          </button>
-          <button
-            onClick={onConfirm}
-            className="px-4 py-2 bg-purple-600 text-white rounded hover:bg-purple-500 font-bold"
-          >
-            Confirm Rebirth
-          </button>
-        </DialogFooter>
-      </DialogContent>
-    </Dialog>
-  );
-}
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/client/src/components/game/sections/SpiritLegion.tsx.html b/coverage/client/src/components/game/sections/SpiritLegion.tsx.html deleted file mode 100644 index c62d241..0000000 --- a/coverage/client/src/components/game/sections/SpiritLegion.tsx.html +++ /dev/null @@ -1,604 +0,0 @@ - - - - - - Code coverage report for client/src/components/game/sections/SpiritLegion.tsx - - - - - - - - - -
-
-

All files / client/src/components/game/sections SpiritLegion.tsx

-
- -
- 0% - Statements - 0/4 -
- - -
- 0% - Branches - 0/10 -
- - -
- 0% - Functions - 0/4 -
- - -
- 0% - Lines - 0/4 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63 -64 -65 -66 -67 -68 -69 -70 -71 -72 -73 -74 -75 -76 -77 -78 -79 -80 -81 -82 -83 -84 -85 -86 -87 -88 -89 -90 -91 -92 -93 -94 -95 -96 -97 -98 -99 -100 -101 -102 -103 -104 -105 -106 -107 -108 -109 -110 -111 -112 -113 -114 -115 -116 -117 -118 -119 -120 -121 -122 -123 -124 -125 -126 -127 -128 -129 -130 -131 -132 -133 -134 -135 -136 -137 -138 -139 -140 -141 -142 -143 -144 -145 -146 -147 -148 -149 -150 -151 -152 -153 -154 -155 -156 -157 -158 -159 -160 -161 -162 -163 -164 -165 -166 -167 -168 -169 -170 -171 -172 -173 -174  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 
import React from "react";
-import {
-  Accordion,
-  AccordionContent,
-  AccordionItem,
-  AccordionTrigger,
-} from "@/components/ui/accordion";
- 
-interface Spirit {
-  id: string;
-  name: string;
-  rarity: string;
-  type: string;
-  level: number;
-  power: number;
-  description: string;
-  abilities?: Array<{
-    id: string;
-    name: string;
-    type: string;
-  }>;
-  exp: number;
-  expToNext: number;
-}
- 
-interface Player {
-  spirits: Spirit[];
-}
- 
-interface SpiritLegionProps {
-  player: Player;
-  getRarityBorder: (rarity: string) => string;
-  getRarityColor: (rarity: string) => string;
-  spiritUpkeep: (player: Player) => number;
-}
- 
-export function SpiritLegion({
-  player,
-  getRarityBorder,
-  getRarityColor,
-  spiritUpkeep,
-}: SpiritLegionProps) {
-  return (
-    <Accordion type="single" collapsible className="w-full">
-      <AccordionItem value="spirit-legion">
-        <AccordionTrigger className="text-lg font-bold text-zinc-100 hover:no-underline">
-          <div className="flex items-center space-x-2">
-            <i className="fas fa-users text-purple-400"></i>
-            <span>Spirit Legion</span>
-            {player.spirits.length > 0 && (
-              <span className="bg-purple-600 text-white px-2 py-1 rounded-full text-xs font-bold">
-                {player.spirits.length}
-              </span>
-            )}
-          </div>
-        </AccordionTrigger>
-        <AccordionContent>
-          <div className="max-h-96 overflow-y-auto">
-            {player.spirits.length === 0 && (
-              <div className="opacity-70 text-sm text-center py-4">
-                No spirits bound
-              </div>
-            )}
- 
-            <div className="space-y-3 mb-4">
-              {player.spirits.map((s: Spirit) => (
-                <div
-                  key={s.id}
-                  className={`bg-zinc-800/30 border ${getRarityBorder(
-                    s.rarity
-                  )} rounded-lg p-3`}
-                >
-                  <div className="flex items-center justify-between mb-2">
-                    <div className="flex items-center space-x-3">
-                      <div
-                        className={`w-8 h-8 bg-gradient-to-br ${getRarityColor(
-                          s.rarity
-                        )
-                          .replace("text-", "from-")
-                          .replace(
-                            "-400",
-                            "-600"
-                          )} to-purple-800 rounded-full flex items-center justify-center`}
-                      >
-                        <i className="fas fa-ghost text-white text-xs"></i>
-                      </div>
-                      <div>
-                        <div
-                          className={`font-bold ${getRarityColor(s.rarity)}`}
-                        >
-                          {s.name}
-                        </div>
-                        <div className="text-xs text-zinc-400 capitalize">
-                          {s.rarity} {s.type} • Level {s.level}
-                        </div>
-                      </div>
-                    </div>
-                    <div className="text-right">
-                      <div className="font-bold text-purple-400">
-                        +{s.power}
-                      </div>
-                      <div className="text-xs text-zinc-500">Power</div>
-                    </div>
-                  </div>
- 
-                  <div className="text-xs text-zinc-400 mb-2">
-                    {s.description}
-                  </div>
- 
-                  <div className="space-y-1">
-                    <div className="text-xs font-semibold text-zinc-300 mb-1">
-                      Abilities:
-                    </div>
-                    {(s.abilities || []).map((ability: { id: string; name: string; type: string }) => (
-                      <div
-                        key={ability.id}
-                        className="flex items-center space-x-2"
-                      >
-                        <span
-                          className={`text-xs px-2 py-1 rounded ${
-                            ability.type === "passive"
-                              ? "bg-blue-600/20 text-blue-400"
-                              : "bg-green-600/20 text-green-400"
-                          }`}
-                        >
-                          {ability.type}
-                        </span>
-                        <span className="text-xs text-zinc-300 font-medium">
-                          {ability.name}
-                        </span>
-                      </div>
-                    ))}
-                  </div>
- 
-                  <div className="mt-2 pt-2 border-t border-zinc-700">
-                    <div className="flex items-center justify-between text-xs">
-                      <span className="text-zinc-400">
-                        EXP: {s.exp}/{s.expToNext}
-                      </span>
-                      <div className="w-20 bg-zinc-700 rounded-full h-1.5">
-                        <div
-                          className="bg-purple-500 h-1.5 rounded-full transition-all duration-300"
-                          style={{ width: `${(s.exp / s.expToNext) * 100}%` }}
-                        ></div>
-                      </div>
-                    </div>
-                  </div>
-                </div>
-              ))}
-            </div>
- 
-            {player.spirits.length > 0 && (
-              <div className="bg-purple-900/30 border border-purple-500/30 rounded-lg p-3">
-                <div className="flex items-center justify-between text-sm">
-                  <span className="text-purple-300">Total Legion Power:</span>
-                  <span className="font-bold text-purple-400">
-                    +{player.spirits.reduce((a: number, s: Spirit) => a + s.power, 0)}
-                  </span>
-                </div>
-                <div className="flex items-center justify-between text-sm mt-1">
-                  <span className="text-purple-300">MP Upkeep/tick:</span>
-                  <span className="font-bold text-blue-400">
-                    -{spiritUpkeep(player)} MP
-                  </span>
-                </div>
-              </div>
-            )}
-          </div>
-        </AccordionContent>
-      </AccordionItem>
-    </Accordion>
-  );
-}
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/client/src/components/game/sections/Stats.tsx.html b/coverage/client/src/components/game/sections/Stats.tsx.html deleted file mode 100644 index d21a356..0000000 --- a/coverage/client/src/components/game/sections/Stats.tsx.html +++ /dev/null @@ -1,484 +0,0 @@ - - - - - - Code coverage report for client/src/components/game/sections/Stats.tsx - - - - - - - - - -
-
-

All files / client/src/components/game/sections Stats.tsx

-
- -
- 100% - Statements - 5/5 -
- - -
- 100% - Branches - 12/12 -
- - -
- 100% - Functions - 3/3 -
- - -
- 100% - Lines - 5/5 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63 -64 -65 -66 -67 -68 -69 -70 -71 -72 -73 -74 -75 -76 -77 -78 -79 -80 -81 -82 -83 -84 -85 -86 -87 -88 -89 -90 -91 -92 -93 -94 -95 -96 -97 -98 -99 -100 -101 -102 -103 -104 -105 -106 -107 -108 -109 -110 -111 -112 -113 -114 -115 -116 -117 -118 -119 -120 -121 -122 -123 -124 -125 -126 -127 -128 -129 -130 -131 -132 -133 -134  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -1x -  -  -  -  -  -  -  -1x -  -  -  -  -  -  -  -  -8x -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -40x -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -1x -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 
import React from "react";
-import {
-  Accordion,
-  AccordionContent,
-  AccordionItem,
-  AccordionTrigger,
-} from "@/components/ui/accordion";
- 
-interface Player {
-  stats: {
-    STR: number;
-    AGI: number;
-    INT: number;
-    VIT: number;
-    LUCK: number;
-  };
-  points: number;
-}
- 
-interface StatsProps {
-  player: Player;
-  allocateStatWithFeedback: (stat: keyof Player["stats"]) => void;
-}
- 
-const STAT_ICONS = {
-  STR: "fas fa-fist-raised",
-  AGI: "fas fa-running",
-  INT: "fas fa-brain",
-  VIT: "fas fa-heart",
-  LUCK: "fas fa-dice",
-};
- 
-const STAT_COLORS = {
-  STR: "bg-red-600",
-  AGI: "bg-green-600",
-  INT: "bg-blue-600",
-  VIT: "bg-orange-600",
-  LUCK: "bg-yellow-600",
-};
- 
-export function Stats({ player, allocateStatWithFeedback }: StatsProps) {
-  return (
-    <Accordion type="single" collapsible className="w-full">
-      <AccordionItem value="stats">
-        <AccordionTrigger className="text-lg font-bold text-zinc-100 hover:no-underline">
-          <div className="flex items-center justify-between w-full mr-4">
-            <span>Stats</span>
-            {player.points > 0 && (
-              <div className="bg-violet-600 text-white px-3 py-1 rounded-full text-sm font-bold">
-                {player.points} Points
-              </div>
-            )}
-          </div>
-        </AccordionTrigger>
-        <AccordionContent>
-          <div className="max-h-96 overflow-y-auto">
-            <div className="mb-4 p-3 bg-blue-900/20 border border-blue-500/30 rounded-lg">
-              <h4 className="text-sm font-bold text-blue-300 mb-2">
-                <i className="fas fa-info-circle mr-1"></i>
-                Stat Effects
-              </h4>
-              <div className="text-xs text-blue-200 space-y-1">
-                <div>
-                  <span className="text-red-400 font-bold">STR:</span> Primary
-                  damage (+3 power each)
-                </div>
-                <div>
-                  <span className="text-green-400 font-bold">AGI:</span> Speed &
-                  damage (+2 power each)
-                </div>
-                <div>
-                  <span className="text-blue-400 font-bold">INT:</span> Magic
-                  damage & spirit binding (+1.5 power each)
-                </div>
-                <div>
-                  <span className="text-orange-400 font-bold">VIT:</span> Health
-                  & defense (+0.5 power each)
-                </div>
-                <div>
-                  <span className="text-yellow-400 font-bold">LUCK:</span>{" "}
-                  Critical hits & item drops
-                </div>
-              </div>
-            </div>
- 
-            <div className="space-y-3">
-              {Object.entries(player.stats).map(([k, v]) => (
-                <div
-                  key={k}
-                  className="flex items-center justify-between bg-zinc-800/50 rounded-lg p-3"
-                >
-                  <div className="flex items-center space-x-3">
-                    <div
-                      className={`w-8 h-8 ${
-                        STAT_COLORS[k as keyof typeof STAT_COLORS]
-                      } rounded-full flex items-center justify-center text-white text-sm font-bold`}
-                    >
-                      <i
-                        className={STAT_ICONS[k as keyof typeof STAT_ICONS]}
-                      ></i>
-                    </div>
-                    <div>
-                      <div className="font-bold text-zinc-100">{k}</div>
-                      <div className="text-sm text-zinc-400">
-                        {k === "STR" && "Strength"}
-                        {k === "AGI" && "Agility"}
-                        {k === "INT" && "Intelligence"}
-                        {k === "VIT" && "Vitality"}
-                        {k === "LUCK" && "Luck"}
-                      </div>
-                    </div>
-                  </div>
-                  <div className="flex items-center space-x-2">
-                    <span className="font-bold text-xl">{v}</span>
-                    <button
-                      className="w-8 h-8 bg-violet-600 hover:bg-violet-500 text-white rounded-full transition-colors disabled:opacity-40"
-                      onClick={() =>
-                        allocateStatWithFeedback(k as keyof Player["stats"])
-                      }
-                      disabled={player.points <= 0}
-                    >
-                      <i className="fas fa-plus text-xs"></i>
-                    </button>
-                  </div>
-                </div>
-              ))}
-            </div>
-          </div>
-        </AccordionContent>
-      </AccordionItem>
-    </Accordion>
-  );
-}
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/client/src/components/game/sections/TrainingActivities.tsx.html b/coverage/client/src/components/game/sections/TrainingActivities.tsx.html deleted file mode 100644 index 6508f04..0000000 --- a/coverage/client/src/components/game/sections/TrainingActivities.tsx.html +++ /dev/null @@ -1,325 +0,0 @@ - - - - - - Code coverage report for client/src/components/game/sections/TrainingActivities.tsx - - - - - - - - - -
-
-

All files / client/src/components/game/sections TrainingActivities.tsx

-
- -
- 0% - Statements - 0/4 -
- - -
- 100% - Branches - 0/0 -
- - -
- 0% - Functions - 0/4 -
- - -
- 0% - Lines - 0/4 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63 -64 -65 -66 -67 -68 -69 -70 -71 -72 -73 -74 -75 -76 -77 -78 -79 -80 -81  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 
import React from "react";
-import {
-  Accordion,
-  AccordionContent,
-  AccordionItem,
-  AccordionTrigger,
-} from "@/components/ui/accordion";
- 
-interface TrainingActivitiesProps {
-  inRun: boolean;
-  doTraining: (type: "physical" | "mental" | "meditation") => void;
-  doWork: () => void;
-}
- 
-export function TrainingActivities({
-  inRun,
-  doTraining,
-  doWork,
-}: TrainingActivitiesProps) {
-  return (
-    <Accordion type="single" collapsible className="w-full">
-      <AccordionItem value="training">
-        <AccordionTrigger className="text-lg font-bold text-violet-300 hover:no-underline">
-          <i className="fas fa-dumbbell mr-2"></i>
-          Training Activities
-        </AccordionTrigger>
-        <AccordionContent>
-          <div className="space-y-3 max-h-80 overflow-y-auto">
-            <div className="grid grid-cols-1 gap-2">
-              <button
-                onClick={() => doTraining("physical")}
-                disabled={inRun}
-                className="flex items-center justify-start text-left w-full px-4 py-2 bg-zinc-700 hover:bg-zinc-600 disabled:opacity-50 disabled:cursor-not-allowed rounded-lg transition-colors"
-              >
-                <i className="fas fa-fist-raised mr-2 text-red-400"></i>
-                Physical Training
-                <span className="ml-auto text-xs text-zinc-400">8-15 EXP</span>
-              </button>
-              <button
-                onClick={() => doTraining("mental")}
-                disabled={inRun}
-                className="flex items-center justify-start text-left w-full px-4 py-2 bg-zinc-700 hover:bg-zinc-600 disabled:opacity-50 disabled:cursor-not-allowed rounded-lg transition-colors"
-              >
-                <i className="fas fa-brain mr-2 text-blue-400"></i>
-                Mental Training
-                <span className="ml-auto text-xs text-zinc-400">6-12 EXP</span>
-              </button>
-              <button
-                onClick={() => doTraining("meditation")}
-                disabled={inRun}
-                className="flex items-center justify-start text-left w-full px-4 py-2 bg-zinc-700 hover:bg-zinc-600 disabled:opacity-50 disabled:cursor-not-allowed rounded-lg transition-colors"
-              >
-                <i className="fas fa-leaf mr-2 text-green-400"></i>
-                Meditation
-                <span className="ml-auto text-xs text-zinc-400">
-                  4-8 EXP, -Fatigue
-                </span>
-              </button>
-              <button
-                onClick={doWork}
-                disabled={inRun}
-                className="flex items-center justify-start text-left w-full px-4 py-2 bg-zinc-700 hover:bg-zinc-600 disabled:opacity-50 disabled:cursor-not-allowed rounded-lg transition-colors"
-              >
-                <i className="fas fa-hammer mr-2 text-yellow-400"></i>
-                Work Job
-                <span className="ml-auto text-xs text-zinc-400">
-                  15-35₲, 3-8 EXP
-                </span>
-              </button>
-            </div>
-            <p className="text-xs text-zinc-500 mt-2">
-              Train to gain experience when stuck, or work for extra gold. Most
-              activities increase fatigue.
-            </p>
-          </div>
-        </AccordionContent>
-      </AccordionItem>
-    </Accordion>
-  );
-}
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/client/src/components/game/sections/index.html b/coverage/client/src/components/game/sections/index.html deleted file mode 100644 index ffdb5db..0000000 --- a/coverage/client/src/components/game/sections/index.html +++ /dev/null @@ -1,251 +0,0 @@ - - - - - - Code coverage report for client/src/components/game/sections - - - - - - - - - -
-
-

All files client/src/components/game/sections

-
- -
- 37.93% - Statements - 11/29 -
- - -
- 64.28% - Branches - 27/42 -
- - -
- 30.43% - Functions - 7/23 -
- - -
- 37.93% - Lines - 11/29 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FileStatementsBranchesFunctionsLines
ActivityLog.tsx -
-
100%2/2100%0/0100%2/2100%2/2
DailyQuest.tsx -
-
100%4/483.33%15/18100%2/2100%4/4
HunterShop.tsx -
-
0%0/4100%0/00%0/40%0/4
Inventory.tsx -
-
0%0/10%0/20%0/10%0/1
Lore.tsx -
-
0%0/1100%0/00%0/10%0/1
RebirthModal.tsx -
-
0%0/4100%0/00%0/20%0/4
SpiritLegion.tsx -
-
0%0/40%0/100%0/40%0/4
Stats.tsx -
-
100%5/5100%12/12100%3/3100%5/5
TrainingActivities.tsx -
-
0%0/4100%0/00%0/40%0/4
index.ts -
-
0%0/00%0/00%0/00%0/0
-
-
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/client/src/components/game/sections/index.ts.html b/coverage/client/src/components/game/sections/index.ts.html deleted file mode 100644 index df03f33..0000000 --- a/coverage/client/src/components/game/sections/index.ts.html +++ /dev/null @@ -1,112 +0,0 @@ - - - - - - Code coverage report for client/src/components/game/sections/index.ts - - - - - - - - - -
-
-

All files / client/src/components/game/sections index.ts

-
- -
- 0% - Statements - 0/0 -
- - -
- 0% - Branches - 0/0 -
- - -
- 0% - Functions - 0/0 -
- - -
- 0% - Lines - 0/0 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10  -  -  -  -  -  -  -  -  - 
export { TrainingActivities } from "./TrainingActivities";
-export { HunterShop } from "./HunterShop";
-export { Stats } from "./Stats";
-export { SpiritLegion } from "./SpiritLegion";
-export { DailyQuest } from "./DailyQuest";
-export { Inventory } from "./Inventory";
-export { ActivityLog } from "./ActivityLog";
-export { Lore } from "./Lore";
-export { RebirthModal } from "./RebirthModal";
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/client/src/components/index.html b/coverage/client/src/components/index.html deleted file mode 100644 index ef77a98..0000000 --- a/coverage/client/src/components/index.html +++ /dev/null @@ -1,131 +0,0 @@ - - - - - - Code coverage report for client/src/components - - - - - - - - - -
-
-

All files client/src/components

-
- -
- 19.35% - Statements - 6/31 -
- - -
- 25% - Branches - 3/12 -
- - -
- 27.27% - Functions - 3/11 -
- - -
- 19.35% - Lines - 6/31 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FileStatementsBranchesFunctionsLines
ErrorBoundary.tsx -
-
85.71%6/775%3/475%3/485.71%6/7
PWAInstallPrompt.tsx -
-
0%0/240%0/80%0/70%0/24
-
-
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/client/src/lib/game/gameLogic.ts.html b/coverage/client/src/lib/game/gameLogic.ts.html deleted file mode 100644 index 1cf24ce..0000000 --- a/coverage/client/src/lib/game/gameLogic.ts.html +++ /dev/null @@ -1,223 +0,0 @@ - - - - - - Code coverage report for client/src/lib/game/gameLogic.ts - - - - - - - - - -
-
-

All files / client/src/lib/game gameLogic.ts

-
- -
- 100% - Statements - 18/18 -
- - -
- 100% - Branches - 7/7 -
- - -
- 100% - Functions - 7/7 -
- - -
- 100% - Lines - 16/16 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47  -  -  -  -  -  -  -  -  -  -  -  -4x -  -  -  -  -  -  -  -  -12x -12x -12x -12x -12x -12x -12x -  -  -  -4x -7x -  -  -  -6x -6x -6x -6x -  -  -  -4x -4x -  - 
import { clamp, rand } from "@/lib/game/gameUtils";
- 
-export interface LogicPlayer {
-  stats: { STR: number; AGI: number; INT: number; VIT: number; LUCK: number };
-  spirits?: Array<{ power: number }>;
-  fatigue: number;
-  rebirths?: number;
-}
- 
-export interface LogicGate { recommended: number; }
- 
-export function createInitialPlayer() {
-  return {
-    level: 1, exp: 0, expNext: 100, hp: 100, mp: 50, maxHp: 100, maxMp: 50,
-    fatigue: 0, points: 5,
-    stats: { STR: 5, AGI: 5, INT: 5, VIT: 5, LUCK: 5 },
-    spirits: [], inv: [], keys: 0, equipment: {}, rebirths: 0, prestigePoints: 0,
-  };
-}
- 
-export function playerPower(player: LogicPlayer, spiritPowerBoostLevel = 0) {
-  const { STR, AGI, INT, VIT } = player.stats;
-  const base = STR * 3 + AGI * 2 + INT * 1.5 + VIT * 0.5;
-  const spiritPowerMult = 1 + spiritPowerBoostLevel * 0.02;
-  const spiritBonus = (player.spirits ?? []).reduce((a, s) => a + s.power, 0) * spiritPowerMult;
-  const fatiguePenalty = 1 - Math.min(0.4, player.fatigue / 250);
-  const rebirthMultiplier = 1 + (player.rebirths ?? 0) * 0.15;
-  return Math.max(1, (base + spiritBonus) * fatiguePenalty * rebirthMultiplier);
-}
- 
-export function spiritUpkeep(player: Pick<LogicPlayer, "spirits">) {
-  const spirits = player.spirits ?? [];
-  return Math.floor(spirits.length + spirits.reduce((a, s) => a + s.power * 0.02, 0));
-}
- 
-export function calcExtractionChance(player: Pick<LogicPlayer, "stats">, bossRankIdx: number) {
-  const { INT, LUCK } = player.stats;
-  const base = 0.25 + INT * 0.008 + LUCK * 0.01;
-  const rankPenalty = 0.03 * bossRankIdx;
-  return clamp(base - rankPenalty, 0.08, 0.85);
-}
- 
-export function gainExpGoldFromGate(gate: LogicGate) {
-  const base = gate.recommended;
-  return { exp: Math.floor(base * 1.1 + rand(10, 40)), gold: Math.floor(base * 0.8 + rand(5, 25)) };
-}
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/client/src/lib/game/gameUtils.ts.html b/coverage/client/src/lib/game/gameUtils.ts.html deleted file mode 100644 index 79be282..0000000 --- a/coverage/client/src/lib/game/gameUtils.ts.html +++ /dev/null @@ -1,100 +0,0 @@ - - - - - - Code coverage report for client/src/lib/game/gameUtils.ts - - - - - - - - - -
-
-

All files / client/src/lib/game gameUtils.ts

-
- -
- 100% - Statements - 10/10 -
- - -
- 100% - Branches - 0/0 -
- - -
- 100% - Functions - 5/5 -
- - -
- 100% - Lines - 5/5 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -616x -3655x -793x -8x -53x - 
export const clamp = (n: number, a: number, b: number) => Math.max(a, Math.min(b, n));
-export const rand = (min: number, max: number) => Math.floor(Math.random() * (max - min + 1)) + min;
-export const uid = () => Math.random().toString(36).slice(2, 9);
-export const fmt = (n: number) => new Intl.NumberFormat().format(Math.floor(n));
-export const pick = <T,>(arr: T[]): T => arr[Math.floor(Math.random() * arr.length)];
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/client/src/lib/game/gateSystem.ts.html b/coverage/client/src/lib/game/gateSystem.ts.html deleted file mode 100644 index b2eaba9..0000000 --- a/coverage/client/src/lib/game/gateSystem.ts.html +++ /dev/null @@ -1,250 +0,0 @@ - - - - - - Code coverage report for client/src/lib/game/gateSystem.ts - - - - - - - - - -
-
-

All files / client/src/lib/game gateSystem.ts

-
- -
- 94.84% - Statements - 92/97 -
- - -
- 84.09% - Branches - 37/44 -
- - -
- 77.27% - Functions - 17/22 -
- - -
- 100% - Lines - 28/28 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56  -  -1x -1x -  -  -  -  -  -1x -1x -1x -1x -1x -1x -1x -  -1x -  -  -  -1x -  -  -  -  -  -  -  -  -1944x -  -702x -702x -  -  -4880x -610x -5751x -  -  -507x -133x -46x -  -  -106x -106x -106x -106x -94x -74x -47x -37x -  - 
import { rand, uid } from "@/lib/game/gameUtils";
- 
-export const RANKS = ["E", "D", "C", "B", "A", "S"] as const;
-export const RANK_COLORS = { E: "bg-green-600", D: "bg-blue-600", C: "bg-purple-600", B: "bg-red-600", A: "bg-orange-600", S: "bg-yellow-600" };
-export interface Boss { name: string; maxHp: number; hp: number; atk: number; def: number; }
-export interface DungeonModifier { id: string; name: string; description: string; icon: string; type: "buff" | "debuff" | "neutral"; applyToRewards: (expMult: number, goldMult: number) => { expMult: number; goldMult: number }; applyToCombat: (playerDmgMult: number, bossDmgMult: number) => { playerDmgMult: number; bossDmgMult: number }; }
-export interface Gate { id: string; name: string; rank: string; rankIdx: number; recommended: number; power: number; boss: Boss; modifiers: DungeonModifier[]; }
-export interface Item { id: string; name: string; type: string; rarity: "common" | "uncommon" | "rare" | "epic" | "legendary"; quality: number; description?: string; stats?: Record<string, number>; equipmentSlot?: "weapon" | "armor" | "accessory" | null; sellValue?: number; }
- 
-export const DUNGEON_MODIFIERS: DungeonModifier[] = [
-  { id: "double_exp", name: "Double EXP", description: "2× EXP reward from this gate", icon: "📚", type: "buff", applyToRewards: (e, g) => ({ expMult: e * 2, goldMult: g }), applyToCombat: (p, b) => ({ playerDmgMult: p, bossDmgMult: b }) },
-  { id: "treasure_vault", name: "Treasure Vault", description: "2× gold reward", icon: "💰", type: "buff", applyToRewards: (e, g) => ({ expMult: e, goldMult: g * 2 }), applyToCombat: (p, b) => ({ playerDmgMult: p, bossDmgMult: b }) },
-  { id: "empowered_boss", name: "Empowered Boss", description: "Boss deals 40% more damage", icon: "💀", type: "debuff", applyToRewards: (e, g) => ({ expMult: e, goldMult: g }), applyToCombat: (p, b) => ({ playerDmgMult: p, bossDmgMult: b * 1.4 }) },
-  { id: "cursed_ground", name: "Cursed Ground", description: "You deal 25% less damage", icon: "☠️", type: "debuff", applyToRewards: (e, g) => ({ expMult: e, goldMult: g }), applyToCombat: (p, b) => ({ playerDmgMult: p * 0.75, bossDmgMult: b }) },
-  { id: "heroic", name: "Heroic", description: "Boss is stronger, but rewards are doubled", icon: "⚔️", type: "neutral", applyToRewards: (e, g) => ({ expMult: e * 2, goldMult: g * 2 }), applyToCombat: (p, b) => ({ playerDmgMult: p, bossDmgMult: b * 1.5 }) },
-  { id: "weakened_boss", name: "Weakened Boss", description: "Boss deals 30% less damage", icon: "🤕", type: "buff", applyToRewards: (e, g) => ({ expMult: e, goldMult: g }), applyToCombat: (p, b) => ({ playerDmgMult: p, bossDmgMult: b * 0.7 }) },
-];
-const MONSTER_DATA = {
-  E: { name: "Goblin Warrior" }, D: { name: "Orc Berserker" }, C: { name: "Dark Elf Assassin" },
-  B: { name: "Troll Chieftain" }, A: { name: "Dragon Knight" }, S: { name: "Void Lord" },
-} as const;
-const GATE_NAMES: Record<string, string[]> = {
-  E: ["Goblin Burrow", "Mushroom Grotto", "Rat Warren", "Slime Pit", "Mossy Tunnel", "Abandoned Mine", "Shallow Cave", "Dusty Cellar"],
-  D: ["Orc Stronghold", "Cursed Mines", "Swamp Depths", "Iron Crypt", "Bandit Hideout", "Troll Bridge", "Dark Hollow", "Bone Quarry"],
-  C: ["Shadow Forest", "Moonlit Ruins", "Phantom Keep", "Crimson Marsh", "Spider Nest", "Haunted Chapel", "Witch's Glade", "Twilight Gorge"],
-  B: ["Troll Citadel", "Thunder Peak", "Frozen Fortress", "Magma Cavern", "War Bastion", "Storm Spire", "Obsidian Vault", "Siege Grounds"],
-  A: ["Dragon's Lair", "Inferno Sanctum", "Sky Fortress", "Ashen Throne", "Blazing Halls", "Wyrm's Den", "Phoenix Roost", "Flame Citadel"],
-  S: ["Void Nexus", "Abyssal Gate", "Reality Fracture", "Chaos Rift", "World's Edge", "Dimensional Tear", "Oblivion Core", "Shattered Plane"],
-};
- 
-export function gatePowerForRank(rankIdx: number) { return Math.round(Math.pow(1.7, rankIdx) * 30 + rankIdx * 20); }
-export function makeBoss(rankIdx: number): Boss {
-  const base = gatePowerForRank(rankIdx); const rank = RANKS[rankIdx]; const hp = Math.floor(base * 8 + rand(-25, 25));
-  return { name: MONSTER_DATA[rank].name, maxHp: hp, hp, atk: Math.floor(base * 0.8 + rand(-5, 5)), def: Math.floor(base * 0.3 + rand(-3, 3)) };
-}
-export function makeGate(rankIdx: number, usedNames?: Set<string>): Gate {
-  const rank = RANKS[rankIdx]; const namePool = GATE_NAMES[rank] ?? GATE_NAMES.E; const unused = namePool.filter((n) => !usedNames?.has(n)); const source = unused.length ? unused : namePool;
-  const modifierCount = Math.random() < 0.25 + rankIdx * 0.08 ? (Math.random() < 0.35 ? 2 : 1) : 0;
-  return { id: uid(), name: source[Math.floor(Math.random() * source.length)], rank, rankIdx, recommended: gatePowerForRank(rankIdx), power: Math.round(Math.max(10, gatePowerForRank(rankIdx) + rand(-20, 20))), boss: makeBoss(rankIdx), modifiers: [...DUNGEON_MODIFIERS].sort(() => Math.random() - 0.5).slice(0, modifierCount) };
-}
-export function generateGatePool(playerLevel: number): Gate[] {
-  const gates: Gate[] = []; const used = new Set<string>(); const add = (rankIdx: number) => { const gate = makeGate(rankIdx, used); used.add(gate.name); gates.push(gate); };
-  for (let i = 0; i < rand(2, 4); i++) add(0); if (playerLevel >= 3) for (let i = 0; i < rand(2, 4); i++) add(1); if (playerLevel >= 6) for (let i = 0; i < rand(2, 4); i++) add(2); if (playerLevel >= 10) for (let i = 0; i < rand(2, 4); i++) add(3); if (playerLevel >= 15) for (let i = 0; i < rand(2, 4); i++) add(4); if (playerLevel >= 18) for (let i = 0; i < rand(1, 2); i++) add(5); if (playerLevel >= 25) { for (let i = 0; i < rand(1, 2); i++) add(4); for (let i = 0; i < rand(1, 2); i++) add(5); }
-  return gates;
-}
-export function rollDrop(gate: Gate): Item | null {
-  const rarityRoll = (rankIdx: number) => { const r = Math.random(); return rankIdx >= 4 && r < 0.05 ? "legendary" : rankIdx >= 3 && r < 0.15 ? "epic" : rankIdx >= 2 && r < 0.35 ? "rare" : rankIdx >= 1 && r < 0.65 ? "uncommon" : "common"; };
-  const qualityFor = (rarity: string) => Math.max(1, Math.min(100, ({ common: 30, uncommon: 50, rare: 70, epic: 85, legendary: 95 } as Record<string, number>)[rarity] + rand(-10, 10)));
-  const r = Math.random();
-  if (r < 0.08) { const rarity = rarityRoll(gate.rankIdx); const quality = qualityFor(rarity); return { id: uid(), name: "Instant Dungeon Key", type: "key", rarity, quality, description: "Opens a special dungeon with enhanced rewards", sellValue: Math.floor(quality * 2) }; }
-  if (r < 0.28) { const statType = ["STR", "AGI", "INT", "VIT", "LUCK"][rand(0, 4)]; const rarity = rarityRoll(gate.rankIdx); const quality = qualityFor(rarity); const statBonus = Math.max(1, Math.floor((quality / 100) * (gate.rankIdx + 1) * 2)); return { id: uid(), name: `${gate.rank}-grade ${statType} Rune`, type: "rune", rarity, quality, description: `Temporarily boosts ${statType} by ${statBonus}`, stats: { [statType]: statBonus }, sellValue: Math.floor(quality * 1.5) }; }
-  if (r < 0.55) { const rarity = rarityRoll(gate.rankIdx); const quality = qualityFor(rarity); const healAmount = Math.floor((quality / 100) * 50 + 25 + gate.rankIdx * 15); return { id: uid(), name: `${gate.rank}-grade Potion`, type: "potion", rarity, quality, description: `Restores ${healAmount} HP`, stats: { HP: healAmount }, sellValue: Math.floor(quality * 1.2) }; }
-  if (r < 0.65) { const rarity = rarityRoll(gate.rankIdx); const quality = qualityFor(rarity); const slot = ["weapon", "armor", "accessory"][rand(0, 2)] as "weapon" | "armor" | "accessory"; const statMap = { weapon: "STR", armor: "VIT", accessory: "LUCK" } as const; const itemName = { weapon: `${gate.rank}-Rank Blade`, armor: `${gate.rank}-Rank Armor`, accessory: `${gate.rank}-Rank Charm` }[slot]; const statBonus = Math.max(1, Math.floor((quality / 100) * (gate.rankIdx + 1) * 3)); return { id: uid(), name: itemName, type: "equipment", rarity, quality, description: `Provides ${statBonus} ${statMap[slot]}`, stats: { [statMap[slot]]: statBonus }, equipmentSlot: slot, sellValue: Math.floor(quality * 3) }; }
-  return null;
-}
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/client/src/lib/game/index.html b/coverage/client/src/lib/game/index.html deleted file mode 100644 index 8c33d3d..0000000 --- a/coverage/client/src/lib/game/index.html +++ /dev/null @@ -1,176 +0,0 @@ - - - - - - Code coverage report for client/src/lib/game - - - - - - - - - -
-
-

All files client/src/lib/game

-
- -
- 97.09% - Statements - 167/172 -
- - -
- 88% - Branches - 88/100 -
- - -
- 88.88% - Functions - 40/45 -
- - -
- 100% - Lines - 79/79 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FileStatementsBranchesFunctionsLines
gameLogic.ts -
-
100%18/18100%7/7100%7/7100%16/16
gameUtils.ts -
-
100%10/10100%0/0100%5/5100%5/5
gateSystem.ts -
-
94.84%92/9784.09%37/4477.27%17/22100%28/28
questSystem.ts -
-
100%30/3090.47%19/21100%7/7100%15/15
spiritSystem.ts -
-
100%17/1789.28%25/28100%4/4100%15/15
-
-
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/client/src/lib/game/questSystem.ts.html b/coverage/client/src/lib/game/questSystem.ts.html deleted file mode 100644 index cb1ece4..0000000 --- a/coverage/client/src/lib/game/questSystem.ts.html +++ /dev/null @@ -1,175 +0,0 @@ - - - - - - Code coverage report for client/src/lib/game/questSystem.ts - - - - - - - - - -
-
-

All files / client/src/lib/game questSystem.ts

-
- -
- 100% - Statements - 30/30 -
- - -
- 90.47% - Branches - 19/21 -
- - -
- 100% - Functions - 7/7 -
- - -
- 100% - Lines - 15/15 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31  -  -  -  -  -5x -2x -2x -5x -5x -  -  -12x -12x -  -  -  -  -  -  -12x -12x -12x -12x -300x -60x -60x -  -60x -  - 
import { uid } from "@/lib/game/gameUtils";
- 
-export interface DailyTask { id: string; name: string; description: string; type: "combat" | "exploration" | "collection" | "skill" | "challenge"; difficulty: "easy" | "medium" | "hard" | "epic"; need: number; have: number; expReward: number; goldReward: number; bonusRewards?: { items?: Array<{ id: string; name: string; type: string; rarity: "common" | "uncommon" | "rare" | "epic" | "legendary"; quality: number; description?: string; sellValue?: number }>; statPoints?: number } }
-export interface GameTime { day: number; currentDate: string; lastReset: string; }
- 
-export function getCurrentGameDate() { const now = new Date(); return `${String(now.getMonth() + 1).padStart(2, "0")}/${String(now.getDate()).padStart(2, "0")}`; }
-export function initialGameTime(): GameTime { const currentDate = getCurrentGameDate(); return { day: 1, currentDate, lastReset: currentDate }; }
-export function formatGameTime(gameTime: GameTime) { return `Day ${gameTime.day} - ${gameTime.currentDate}`; }
-export function getDifficultyColor(difficulty: string) { return ({ easy: "text-green-400", medium: "text-yellow-400", hard: "text-orange-400", epic: "text-purple-400" } as Record<string, string>)[difficulty] ?? "text-gray-400"; }
-export function getDifficultyBgColor(difficulty: string) { return ({ easy: "bg-green-600", medium: "bg-yellow-600", hard: "bg-orange-600", epic: "bg-purple-600" } as Record<string, string>)[difficulty] ?? "bg-gray-600"; }
- 
-export function generateDailyQuests(playerLevel: number, questReputation = 0): DailyTask[] {
-  const quests: DailyTask[] = []; const difficulties: DailyTask["difficulty"][] = ["easy"]; if (playerLevel >= 5) difficulties.push("medium"); if (playerLevel >= 10) difficulties.push("hard"); if (playerLevel >= 15 && questReputation >= 50) difficulties.push("epic");
-  const defs = [
-    { type: "combat" as const, name: "Monster Hunter", description: "Defeat monsters in gates", scale: 3, epic: 5 },
-    { type: "exploration" as const, name: "Gate Explorer", description: "Enter gates of different ranks", scale: 5, epic: 4 },
-    { type: "collection" as const, name: "Item Collector", description: "Gather items from gates", scale: 4, epic: 4 },
-    { type: "skill" as const, name: "Resource Manager", description: "Use potions and runes effectively", scale: 6, epic: 4 },
-    { type: "challenge" as const, name: "Perfect Hunter", description: "Complete gates without taking damage", scale: 8, epic: 4 },
-  ];
-  const mult: Record<DailyTask["difficulty"], number> = { easy: 1, medium: 2, hard: 3, epic: 4 };
-  const rewardMult: Record<DailyTask["difficulty"], number> = { easy: 0.8, medium: 1.2, hard: 1.8, epic: 2.5 };
-  const used = new Set<string>();
-  for (let i = 0; i < 5; i++) {
-    const available = defs.filter((d) => !used.has(d.type)); const quest = (available.length ? available : defs)[Math.floor(Math.random() * (available.length ? available.length : defs.length))]; used.add(quest.type);
-    const difficulty = difficulties[Math.floor(Math.random() * difficulties.length)]; const base = Math.max(1, Math.floor(playerLevel / quest.scale)); const need = difficulty === "epic" ? base * quest.epic : base * mult[difficulty];
-    quests.push({ id: `${quest.type}_${difficulty}_${i}`, name: `${quest.name} (${difficulty.charAt(0).toUpperCase() + difficulty.slice(1)})`, description: `${quest.description} - ${need} times`, type: quest.type, difficulty, need, have: 0, expReward: Math.floor(playerLevel * 10 * rewardMult[difficulty]), goldReward: Math.floor(playerLevel * 5 * rewardMult[difficulty]), bonusRewards: difficulty === "epic" ? { items: [{ id: uid(), name: "Epic Quest Reward", type: "potion", rarity: "rare", quality: 80, description: "Special reward for completing an epic quest", sellValue: 100 }], statPoints: 1 } : undefined });
-  }
-  return quests;
-}
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/client/src/lib/game/spiritSystem.ts.html b/coverage/client/src/lib/game/spiritSystem.ts.html deleted file mode 100644 index 6841a52..0000000 --- a/coverage/client/src/lib/game/spiritSystem.ts.html +++ /dev/null @@ -1,208 +0,0 @@ - - - - - - Code coverage report for client/src/lib/game/spiritSystem.ts - - - - - - - - - -
-
-

All files / client/src/lib/game spiritSystem.ts

-
- -
- 100% - Statements - 17/17 -
- - -
- 89.28% - Branches - 25/28 -
- - -
- 100% - Functions - 4/4 -
- - -
- 100% - Lines - 15/15 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42  -  -  -  -  -  -  -1x -1x -  -  -  -  -  -  -1x -  -  -  -  -  -  -1x -1x -  -  -1011x -1011x -507x -505x -  -  -  -7x -7x -7x -7x -  -  -10x -7x - 
import { rand, uid } from "@/lib/game/gameUtils";
- 
-export type SpiritRarity = "common" | "uncommon" | "rare" | "epic" | "legendary";
-export type SpiritType = "warrior" | "mage" | "rogue" | "tank" | "support";
-export interface SpiritAbility { id: string; name: string; description: string; type: "passive" | "active"; effect: string; cooldown?: number; }
-export interface Spirit { id: string; name: string; power: number; rarity: SpiritRarity; abilities: SpiritAbility[]; level: number; exp: number; expToNext: number; type: SpiritType; description: string; }
- 
-export const SPIRIT_TYPES: SpiritType[] = ["warrior", "mage", "rogue", "tank", "support"];
-export const SPIRIT_ABILITIES: Record<SpiritType, SpiritAbility[]> = {
-  warrior: [{ id: "berserker_rage", name: "Berserker Rage", description: "Increases damage by 25% when below 50% HP", type: "passive", effect: "damage_boost" }, { id: "cleave", name: "Cleave", description: "Attacks all enemies in range", type: "active", effect: "aoe_attack", cooldown: 3 }],
-  mage: [{ id: "arcane_mastery", name: "Arcane Mastery", description: "Spells have 15% chance to cast twice", type: "passive", effect: "double_cast" }, { id: "mana_shield", name: "Mana Shield", description: "Absorbs damage using MP instead of HP", type: "active", effect: "damage_absorption", cooldown: 5 }],
-  rogue: [{ id: "shadow_step", name: "Shadow Step", description: "Every 3rd attack is enhanced (+10% damage)", type: "passive", effect: "damage_boost" }, { id: "poison_blade", name: "Poison Blade", description: "Attacks poison enemies for 3 turns", type: "passive", effect: "poison_damage" }],
-  tank: [{ id: "fortress", name: "Fortress", description: "Reduces all damage taken by 30%", type: "passive", effect: "damage_reduction" }, { id: "ethereal_shield", name: "Ethereal Shield", description: "15% chance to block boss attacks entirely", type: "passive", effect: "block_chance" }, { id: "taunt", name: "Taunt", description: "Forces enemies to attack this spirit", type: "active", effect: "force_aggro", cooldown: 2 }],
-  support: [{ id: "healing_aura", name: "Healing Aura", description: "Heals all allies for 10% of max HP each turn", type: "passive", effect: "heal_aura" }, { id: "vitality_aura", name: "Vitality Aura", description: "Restores 2 HP per combat tick", type: "passive", effect: "hp_regen" }, { id: "blessing", name: "Blessing", description: "Increases all ally stats by 20% for 3 turns", type: "active", effect: "stat_boost", cooldown: 6 }],
-};
-export const SPIRIT_DESCRIPTIONS: Record<SpiritType, string> = {
-  warrior: "A fierce combatant specializing in melee damage and aggressive tactics.",
-  mage: "A master of arcane arts, wielding powerful spells and magical abilities.",
-  rogue: "A stealthy assassin with high critical hit chance and poison attacks.",
-  tank: "A stalwart defender who protects allies and absorbs enemy attacks.",
-  support: "A benevolent ally who heals and enhances the capabilities of the team.",
-};
-const rarityMultipliers: Record<SpiritRarity, number> = { common: 1, uncommon: 1.2, rare: 1.5, epic: 2, legendary: 3 };
-const spiritNames = ["Umbra", "Noctis", "Tenebris", "Kage", "Silens", "Vorago", "Ater", "Nox", "Moria", "Caecus"];
- 
-export function getRarityFromBossRank(bossRankIdx: number): SpiritRarity {
-  const roll = Math.random();
-  if (bossRankIdx >= 4) return roll < 0.05 ? "legendary" : roll < 0.15 ? "epic" : roll < 0.35 ? "rare" : roll < 0.65 ? "uncommon" : "common";
-  if (bossRankIdx >= 2) return roll < 0.02 ? "epic" : roll < 0.08 ? "rare" : roll < 0.25 ? "uncommon" : "common";
-  return roll < 0.01 ? "rare" : roll < 0.1 ? "uncommon" : "common";
-}
- 
-export function createSpirit(gatePower: number, bossRankIdx: number): Spirit {
-  const type = SPIRIT_TYPES[rand(0, SPIRIT_TYPES.length - 1)];
-  const rarity = getRarityFromBossRank(bossRankIdx);
-  const abilities = SPIRIT_ABILITIES[type].slice(0, Math.min(rarity === "common" ? 1 : rarity === "epic" ? 3 : rarity === "legendary" ? 4 : 2, SPIRIT_ABILITIES[type].length));
-  return { id: uid(), name: `${spiritNames[rand(0, spiritNames.length - 1)]}-${rand(1, 999)}`, power: Math.floor(gatePower * 0.8 * rarityMultipliers[rarity]), rarity, abilities, level: 1, exp: 0, expToNext: 100, type, description: SPIRIT_DESCRIPTIONS[type] };
-}
- 
-export function getRarityColor(rarity: SpiritRarity) { return ({ common: "text-gray-400", uncommon: "text-green-400", rare: "text-blue-400", epic: "text-purple-400", legendary: "text-yellow-400" })[rarity]; }
-export function getRarityBorder(rarity: SpiritRarity) { return ({ common: "border-gray-500", uncommon: "border-green-500", rare: "border-blue-500", epic: "border-purple-500", legendary: "border-yellow-500" })[rarity]; }
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/favicon.png b/coverage/favicon.png deleted file mode 100644 index c1525b8..0000000 Binary files a/coverage/favicon.png and /dev/null differ diff --git a/coverage/index.html b/coverage/index.html deleted file mode 100644 index e374674..0000000 --- a/coverage/index.html +++ /dev/null @@ -1,221 +0,0 @@ - - - - - - Code coverage report for All files - - - - - - - - - -
-
-

All files

-
- -
- 11.44% - Statements - 204/1782 -
- - -
- 7.86% - Branches - 118/1501 -
- - -
- 10.59% - Functions - 55/519 -
- - -
- 7.61% - Lines - 116/1524 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FileStatementsBranchesFunctionsLines
client/src/components -
-
19.35%6/3125%3/1227.27%3/1119.35%6/31
client/src/components/game -
-
0%0/13590%0/10560%0/3610%0/1199
client/src/components/game/bosses -
-
0%0/7100%0/00%0/70%0/7
client/src/components/game/mobile -
-
0%0/920%0/2710%0/500%0/87
client/src/components/game/sections -
-
37.93%11/2964.28%27/4230.43%7/2337.93%11/29
client/src/lib/game -
-
97.09%167/17288%88/10088.88%40/45100%79/79
server -
-
12.82%10/780%0/2027.77%5/1812.82%10/78
shared -
-
71.42%10/14100%0/00%0/471.42%10/14
-
-
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/prettify.css b/coverage/prettify.css deleted file mode 100644 index b317a7c..0000000 --- a/coverage/prettify.css +++ /dev/null @@ -1 +0,0 @@ -.pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee} diff --git a/coverage/prettify.js b/coverage/prettify.js deleted file mode 100644 index b322523..0000000 --- a/coverage/prettify.js +++ /dev/null @@ -1,2 +0,0 @@ -/* eslint-disable */ -window.PR_SHOULD_USE_CONTINUATION=true;(function(){var h=["break,continue,do,else,for,if,return,while"];var u=[h,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"];var p=[u,"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"];var l=[p,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"];var x=[p,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"];var R=[x,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"];var r="all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes";var w=[p,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"];var s="caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END";var I=[h,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"];var f=[h,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"];var H=[h,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"];var A=[l,R,w,s+I,f,H];var e=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/;var C="str";var z="kwd";var j="com";var O="typ";var G="lit";var L="pun";var F="pln";var m="tag";var E="dec";var J="src";var P="atn";var n="atv";var N="nocode";var M="(?:^^\\.?|[+-]|\\!|\\!=|\\!==|\\#|\\%|\\%=|&|&&|&&=|&=|\\(|\\*|\\*=|\\+=|\\,|\\-=|\\->|\\/|\\/=|:|::|\\;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|\\?|\\@|\\[|\\^|\\^=|\\^\\^|\\^\\^=|\\{|\\||\\|=|\\|\\||\\|\\|=|\\~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*";function k(Z){var ad=0;var S=false;var ac=false;for(var V=0,U=Z.length;V122)){if(!(al<65||ag>90)){af.push([Math.max(65,ag)|32,Math.min(al,90)|32])}if(!(al<97||ag>122)){af.push([Math.max(97,ag)&~32,Math.min(al,122)&~32])}}}}af.sort(function(av,au){return(av[0]-au[0])||(au[1]-av[1])});var ai=[];var ap=[NaN,NaN];for(var ar=0;arat[0]){if(at[1]+1>at[0]){an.push("-")}an.push(T(at[1]))}}an.push("]");return an.join("")}function W(al){var aj=al.source.match(new RegExp("(?:\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]|\\\\u[A-Fa-f0-9]{4}|\\\\x[A-Fa-f0-9]{2}|\\\\[0-9]+|\\\\[^ux0-9]|\\(\\?[:!=]|[\\(\\)\\^]|[^\\x5B\\x5C\\(\\)\\^]+)","g"));var ah=aj.length;var an=[];for(var ak=0,am=0;ak=2&&ai==="["){aj[ak]=X(ag)}else{if(ai!=="\\"){aj[ak]=ag.replace(/[a-zA-Z]/g,function(ao){var ap=ao.charCodeAt(0);return"["+String.fromCharCode(ap&~32,ap|32)+"]"})}}}}return aj.join("")}var aa=[];for(var V=0,U=Z.length;V=0;){S[ac.charAt(ae)]=Y}}var af=Y[1];var aa=""+af;if(!ag.hasOwnProperty(aa)){ah.push(af);ag[aa]=null}}ah.push(/[\0-\uffff]/);V=k(ah)})();var X=T.length;var W=function(ah){var Z=ah.sourceCode,Y=ah.basePos;var ad=[Y,F];var af=0;var an=Z.match(V)||[];var aj={};for(var ae=0,aq=an.length;ae=5&&"lang-"===ap.substring(0,5);if(am&&!(ai&&typeof ai[1]==="string")){am=false;ap=J}if(!am){aj[ag]=ap}}var ab=af;af+=ag.length;if(!am){ad.push(Y+ab,ap)}else{var al=ai[1];var ak=ag.indexOf(al);var ac=ak+al.length;if(ai[2]){ac=ag.length-ai[2].length;ak=ac-al.length}var ar=ap.substring(5);B(Y+ab,ag.substring(0,ak),W,ad);B(Y+ab+ak,al,q(ar,al),ad);B(Y+ab+ac,ag.substring(ac),W,ad)}}ah.decorations=ad};return W}function i(T){var W=[],S=[];if(T.tripleQuotedStrings){W.push([C,/^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/,null,"'\""])}else{if(T.multiLineStrings){W.push([C,/^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,null,"'\"`"])}else{W.push([C,/^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,null,"\"'"])}}if(T.verbatimStrings){S.push([C,/^@\"(?:[^\"]|\"\")*(?:\"|$)/,null])}var Y=T.hashComments;if(Y){if(T.cStyleComments){if(Y>1){W.push([j,/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,null,"#"])}else{W.push([j,/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\r\n]*)/,null,"#"])}S.push([C,/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,null])}else{W.push([j,/^#[^\r\n]*/,null,"#"])}}if(T.cStyleComments){S.push([j,/^\/\/[^\r\n]*/,null]);S.push([j,/^\/\*[\s\S]*?(?:\*\/|$)/,null])}if(T.regexLiterals){var X=("/(?=[^/*])(?:[^/\\x5B\\x5C]|\\x5C[\\s\\S]|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+/");S.push(["lang-regex",new RegExp("^"+M+"("+X+")")])}var V=T.types;if(V){S.push([O,V])}var U=(""+T.keywords).replace(/^ | $/g,"");if(U.length){S.push([z,new RegExp("^(?:"+U.replace(/[\s,]+/g,"|")+")\\b"),null])}W.push([F,/^\s+/,null," \r\n\t\xA0"]);S.push([G,/^@[a-z_$][a-z_$@0-9]*/i,null],[O,/^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\w+_t\b)/,null],[F,/^[a-z_$][a-z_$@0-9]*/i,null],[G,new RegExp("^(?:0x[a-f0-9]+|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)(?:e[+\\-]?\\d+)?)[a-z]*","i"),null,"0123456789"],[F,/^\\[\s\S]?/,null],[L,/^.[^\s\w\.$@\'\"\`\/\#\\]*/,null]);return g(W,S)}var K=i({keywords:A,hashComments:true,cStyleComments:true,multiLineStrings:true,regexLiterals:true});function Q(V,ag){var U=/(?:^|\s)nocode(?:\s|$)/;var ab=/\r\n?|\n/;var ac=V.ownerDocument;var S;if(V.currentStyle){S=V.currentStyle.whiteSpace}else{if(window.getComputedStyle){S=ac.defaultView.getComputedStyle(V,null).getPropertyValue("white-space")}}var Z=S&&"pre"===S.substring(0,3);var af=ac.createElement("LI");while(V.firstChild){af.appendChild(V.firstChild)}var W=[af];function ae(al){switch(al.nodeType){case 1:if(U.test(al.className)){break}if("BR"===al.nodeName){ad(al);if(al.parentNode){al.parentNode.removeChild(al)}}else{for(var an=al.firstChild;an;an=an.nextSibling){ae(an)}}break;case 3:case 4:if(Z){var am=al.nodeValue;var aj=am.match(ab);if(aj){var ai=am.substring(0,aj.index);al.nodeValue=ai;var ah=am.substring(aj.index+aj[0].length);if(ah){var ak=al.parentNode;ak.insertBefore(ac.createTextNode(ah),al.nextSibling)}ad(al);if(!ai){al.parentNode.removeChild(al)}}}break}}function ad(ak){while(!ak.nextSibling){ak=ak.parentNode;if(!ak){return}}function ai(al,ar){var aq=ar?al.cloneNode(false):al;var ao=al.parentNode;if(ao){var ap=ai(ao,1);var an=al.nextSibling;ap.appendChild(aq);for(var am=an;am;am=an){an=am.nextSibling;ap.appendChild(am)}}return aq}var ah=ai(ak.nextSibling,0);for(var aj;(aj=ah.parentNode)&&aj.nodeType===1;){ah=aj}W.push(ah)}for(var Y=0;Y=S){ah+=2}if(V>=ap){Z+=2}}}var t={};function c(U,V){for(var S=V.length;--S>=0;){var T=V[S];if(!t.hasOwnProperty(T)){t[T]=U}else{if(window.console){console.warn("cannot override language handler %s",T)}}}}function q(T,S){if(!(T&&t.hasOwnProperty(T))){T=/^\s*]*(?:>|$)/],[j,/^<\!--[\s\S]*?(?:-\->|$)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],[L,/^(?:<[%?]|[%?]>)/],["lang-",/^]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-js",/^]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),["default-markup","htm","html","mxml","xhtml","xml","xsl"]);c(g([[F,/^[\s]+/,null," \t\r\n"],[n,/^(?:\"[^\"]*\"?|\'[^\']*\'?)/,null,"\"'"]],[[m,/^^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i],[P,/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^>\'\"\s]*(?:[^>\'\"\s\/]|\/(?=\s)))/],[L,/^[=<>\/]+/],["lang-js",/^on\w+\s*=\s*\"([^\"]+)\"/i],["lang-js",/^on\w+\s*=\s*\'([^\']+)\'/i],["lang-js",/^on\w+\s*=\s*([^\"\'>\s]+)/i],["lang-css",/^style\s*=\s*\"([^\"]+)\"/i],["lang-css",/^style\s*=\s*\'([^\']+)\'/i],["lang-css",/^style\s*=\s*([^\"\'>\s]+)/i]]),["in.tag"]);c(g([],[[n,/^[\s\S]+/]]),["uq.val"]);c(i({keywords:l,hashComments:true,cStyleComments:true,types:e}),["c","cc","cpp","cxx","cyc","m"]);c(i({keywords:"null,true,false"}),["json"]);c(i({keywords:R,hashComments:true,cStyleComments:true,verbatimStrings:true,types:e}),["cs"]);c(i({keywords:x,cStyleComments:true}),["java"]);c(i({keywords:H,hashComments:true,multiLineStrings:true}),["bsh","csh","sh"]);c(i({keywords:I,hashComments:true,multiLineStrings:true,tripleQuotedStrings:true}),["cv","py"]);c(i({keywords:s,hashComments:true,multiLineStrings:true,regexLiterals:true}),["perl","pl","pm"]);c(i({keywords:f,hashComments:true,multiLineStrings:true,regexLiterals:true}),["rb"]);c(i({keywords:w,cStyleComments:true,regexLiterals:true}),["js"]);c(i({keywords:r,hashComments:3,cStyleComments:true,multilineStrings:true,tripleQuotedStrings:true,regexLiterals:true}),["coffee"]);c(g([],[[C,/^[\s\S]+/]]),["regex"]);function d(V){var U=V.langExtension;try{var S=a(V.sourceNode);var T=S.sourceCode;V.sourceCode=T;V.spans=S.spans;V.basePos=0;q(U,T)(V);D(V)}catch(W){if("console" in window){console.log(W&&W.stack?W.stack:W)}}}function y(W,V,U){var S=document.createElement("PRE");S.innerHTML=W;if(U){Q(S,U)}var T={langExtension:V,numberLines:U,sourceNode:S};d(T);return S.innerHTML}function b(ad){function Y(af){return document.getElementsByTagName(af)}var ac=[Y("pre"),Y("code"),Y("xmp")];var T=[];for(var aa=0;aa=0){var ah=ai.match(ab);var am;if(!ah&&(am=o(aj))&&"CODE"===am.tagName){ah=am.className.match(ab)}if(ah){ah=ah[1]}var al=false;for(var ak=aj.parentNode;ak;ak=ak.parentNode){if((ak.tagName==="pre"||ak.tagName==="code"||ak.tagName==="xmp")&&ak.className&&ak.className.indexOf("prettyprint")>=0){al=true;break}}if(!al){var af=aj.className.match(/\blinenums\b(?::(\d+))?/);af=af?af[1]&&af[1].length?+af[1]:true:false;if(af){Q(aj,af)}S={langExtension:ah,sourceNode:aj,numberLines:af};d(S)}}}if(X]*(?:>|$)/],[PR.PR_COMMENT,/^<\!--[\s\S]*?(?:-\->|$)/],[PR.PR_PUNCTUATION,/^(?:<[%?]|[%?]>)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],["lang-",/^]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-handlebars",/^]*type\s*=\s*['"]?text\/x-handlebars-template['"]?\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-js",/^]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i],[PR.PR_DECLARATION,/^{{[#^>/]?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{&?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{{>?\s*[\w.][^}]*}}}/],[PR.PR_COMMENT,/^{{![^}]*}}/]]),["handlebars","hbs"]);PR.registerLangHandler(PR.createSimpleLexer([[PR.PR_PLAIN,/^[ \t\r\n\f]+/,null," \t\r\n\f"]],[[PR.PR_STRING,/^\"(?:[^\n\r\f\\\"]|\\(?:\r\n?|\n|\f)|\\[\s\S])*\"/,null],[PR.PR_STRING,/^\'(?:[^\n\r\f\\\']|\\(?:\r\n?|\n|\f)|\\[\s\S])*\'/,null],["lang-css-str",/^url\(([^\)\"\']*)\)/i],[PR.PR_KEYWORD,/^(?:url|rgb|\!important|@import|@page|@media|@charset|inherit)(?=[^\-\w]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|(?:\\[0-9a-f]+ ?))(?:[_a-z0-9\-]|\\(?:\\[0-9a-f]+ ?))*)\s*:/i],[PR.PR_COMMENT,/^\/\*[^*]*\*+(?:[^\/*][^*]*\*+)*\//],[PR.PR_COMMENT,/^(?:)/],[PR.PR_LITERAL,/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],[PR.PR_LITERAL,/^#(?:[0-9a-f]{3}){1,2}/i],[PR.PR_PLAIN,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i],[PR.PR_PUNCTUATION,/^[^\s\w\'\"]+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_KEYWORD,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_STRING,/^[^\)\"\']+/]]),["css-str"]); diff --git a/coverage/server/db.ts.html b/coverage/server/db.ts.html deleted file mode 100644 index 66ebdf5..0000000 --- a/coverage/server/db.ts.html +++ /dev/null @@ -1,130 +0,0 @@ - - - - - - Code coverage report for server/db.ts - - - - - - - - - -
-
-

All files / server db.ts

-
- -
- 0% - Statements - 0/5 -
- - -
- 0% - Branches - 0/2 -
- - -
- 100% - Functions - 0/0 -
- - -
- 0% - Lines - 0/5 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 
import { Pool, neonConfig } from '@neondatabase/serverless';
-import { drizzle } from 'drizzle-orm/neon-serverless';
-import ws from "ws";
-import * as schema from "@shared/schema";
- 
-neonConfig.webSocketConstructor = ws;
- 
-if (!process.env.DATABASE_URL) {
-  throw new Error(
-    "DATABASE_URL must be set. Did you forget to provision a database?",
-  );
-}
- 
-export const pool = new Pool({ connectionString: process.env.DATABASE_URL });
-export const db = drizzle({ client: pool, schema });
- -
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/server/index.html b/coverage/server/index.html deleted file mode 100644 index 605aaf7..0000000 --- a/coverage/server/index.html +++ /dev/null @@ -1,176 +0,0 @@ - - - - - - Code coverage report for server - - - - - - - - - -
-
-

All files server

-
- -
- 12.82% - Statements - 10/78 -
- - -
- 0% - Branches - 0/20 -
- - -
- 27.77% - Functions - 5/18 -
- - -
- 12.82% - Lines - 10/78 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FileStatementsBranchesFunctionsLines
db.ts -
-
0%0/50%0/2100%0/00%0/5
index.ts -
-
0%0/340%0/150%0/60%0/34
routes.ts -
-
0%0/3100%0/00%0/10%0/3
storage.ts -
-
100%10/10100%0/0100%5/5100%10/10
vite.ts -
-
0%0/260%0/30%0/60%0/26
-
-
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/server/index.ts.html b/coverage/server/index.ts.html deleted file mode 100644 index 21decfa..0000000 --- a/coverage/server/index.ts.html +++ /dev/null @@ -1,298 +0,0 @@ - - - - - - Code coverage report for server/index.ts - - - - - - - - - -
-
-

All files / server index.ts

-
- -
- 0% - Statements - 0/34 -
- - -
- 0% - Branches - 0/15 -
- - -
- 0% - Functions - 0/6 -
- - -
- 0% - Lines - 0/34 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63 -64 -65 -66 -67 -68 -69 -70 -71 -72  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 
import express, { type Request, Response, NextFunction } from "express";
-import { registerRoutes } from "./routes";
-import { setupVite, serveStatic, log } from "./vite";
- 
-const app = express();
-app.use(express.json());
-app.use(express.urlencoded({ extended: false }));
- 
-app.use((req, res, next) => {
-  const start = Date.now();
-  const path = req.path;
-  let capturedJsonResponse: Record<string, any> | undefined = undefined;
- 
-  const originalResJson = res.json;
-  res.json = function (bodyJson, ...args) {
-    capturedJsonResponse = bodyJson;
-    return originalResJson.apply(res, [bodyJson, ...args]);
-  };
- 
-  res.on("finish", () => {
-    const duration = Date.now() - start;
-    if (path.startsWith("/api")) {
-      let logLine = `${req.method} ${path} ${res.statusCode} in ${duration}ms`;
-      if (capturedJsonResponse) {
-        logLine += ` :: ${JSON.stringify(capturedJsonResponse)}`;
-      }
- 
-      if (logLine.length > 80) {
-        logLine = logLine.slice(0, 79) + "…";
-      }
- 
-      log(logLine);
-    }
-  });
- 
-  next();
-});
- 
-(async () => {
-  const server = await registerRoutes(app);
- 
-  app.use((err: any, _req: Request, res: Response, _next: NextFunction) => {
-    const status = err.status || err.statusCode || 500;
-    const message = err.message || "Internal Server Error";
- 
-    res.status(status).json({ message });
-    throw err;
-  });
- 
-  // importantly only setup vite in development and after
-  // setting up all the other routes so the catch-all route
-  // doesn't interfere with the other routes
-  if (app.get("env") === "development") {
-    await setupVite(app, server);
-  } else {
-    serveStatic(app);
-  }
- 
-  // ALWAYS serve the app on the port specified in the environment variable PORT
-  // Other ports are firewalled. Default to 5000 if not specified.
-  // this serves both the API and the client.
-  // It is the only port that is not firewalled.
-  const port = parseInt(process.env.PORT || '5000', 10);
-  server.listen({
-    port,
-    host: "0.0.0.0",
-    reusePort: true,
-  }, () => {
-    log(`serving on port ${port}`);
-  });
-})();
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/server/routes.ts.html b/coverage/server/routes.ts.html deleted file mode 100644 index 226e89d..0000000 --- a/coverage/server/routes.ts.html +++ /dev/null @@ -1,130 +0,0 @@ - - - - - - Code coverage report for server/routes.ts - - - - - - - - - -
-
-

All files / server routes.ts

-
- -
- 0% - Statements - 0/3 -
- - -
- 100% - Branches - 0/0 -
- - -
- 0% - Functions - 0/1 -
- - -
- 0% - Lines - 0/3 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 
import type { Express } from "express";
-import { createServer, type Server } from "http";
-import { storage } from "./storage";
- 
-export async function registerRoutes(app: Express): Promise<Server> {
-  // put application routes here
-  // prefix all routes with /api
- 
-  // use storage to perform CRUD operations on the storage interface
-  // e.g. storage.insertUser(user) or storage.getUserByUsername(username)
- 
-  const httpServer = createServer(app);
- 
-  return httpServer;
-}
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/server/storage.ts.html b/coverage/server/storage.ts.html deleted file mode 100644 index 8b5eea0..0000000 --- a/coverage/server/storage.ts.html +++ /dev/null @@ -1,199 +0,0 @@ - - - - - - Code coverage report for server/storage.ts - - - - - - - - - -
-
-

All files / server storage.ts

-
- -
- 100% - Statements - 10/10 -
- - -
- 100% - Branches - 0/0 -
- - -
- 100% - Functions - 5/5 -
- - -
- 100% - Lines - 10/10 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39  -1x -  -  -  -  -  -  -  -  -  -  -  -  -  -  -8x -  -  -  -2x -  -  -  -3x -3x -  -  -  -  -8x -8x -8x -8x -  -  -  -1x - 
import { type User, type InsertUser } from "@shared/schema";
-import { randomUUID } from "crypto";
- 
-// modify the interface with any CRUD methods
-// you might need
- 
-export interface IStorage {
-  getUser(id: string): Promise<User | undefined>;
-  getUserByUsername(username: string): Promise<User | undefined>;
-  createUser(user: InsertUser): Promise<User>;
-}
- 
-export class MemStorage implements IStorage {
-  private users: Map<string, User>;
- 
-  constructor() {
-    this.users = new Map();
-  }
- 
-  async getUser(id: string): Promise<User | undefined> {
-    return this.users.get(id);
-  }
- 
-  async getUserByUsername(username: string): Promise<User | undefined> {
-    return Array.from(this.users.values()).find(
-      (user) => user.username === username,
-    );
-  }
- 
-  async createUser(insertUser: InsertUser): Promise<User> {
-    const id = randomUUID();
-    const user: User = { ...insertUser, id };
-    this.users.set(id, user);
-    return user;
-  }
-}
- 
-export const storage = new MemStorage();
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/server/vite.ts.html b/coverage/server/vite.ts.html deleted file mode 100644 index bff42e9..0000000 --- a/coverage/server/vite.ts.html +++ /dev/null @@ -1,349 +0,0 @@ - - - - - - Code coverage report for server/vite.ts - - - - - - - - - -
-
-

All files / server vite.ts

-
- -
- 0% - Statements - 0/26 -
- - -
- 0% - Branches - 0/3 -
- - -
- 0% - Functions - 0/6 -
- - -
- 0% - Lines - 0/26 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63 -64 -65 -66 -67 -68 -69 -70 -71 -72 -73 -74 -75 -76 -77 -78 -79 -80 -81 -82 -83 -84 -85 -86 -87 -88 -89  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 
import express, { type Express } from "express";
-import fs from "fs";
-import path from "path";
-import { fileURLToPath } from "url";
-import { createServer as createViteServer, createLogger } from "vite";
-import { type Server } from "http";
-import viteConfig from "../vite.config";
-import { nanoid } from "nanoid";
- 
-const __dirname = path.dirname(fileURLToPath(import.meta.url));
- 
-const viteLogger = createLogger();
- 
-export function log(message: string, source = "express") {
-  const formattedTime = new Date().toLocaleTimeString("en-US", {
-    hour: "numeric",
-    minute: "2-digit",
-    second: "2-digit",
-    hour12: true,
-  });
- 
-  console.log(`${formattedTime} [${source}] ${message}`);
-}
- 
-export async function setupVite(app: Express, server: Server) {
-  const serverOptions = {
-    middlewareMode: true,
-    hmr: { server },
-    allowedHosts: true as const,
-  };
- 
-  const vite = await createViteServer({
-    ...viteConfig,
-    configFile: false,
-    customLogger: {
-      ...viteLogger,
-      error: (msg, options) => {
-        viteLogger.error(msg, options);
-        process.exit(1);
-      },
-    },
-    server: serverOptions,
-    appType: "custom",
-  });
- 
-  app.use(vite.middlewares);
-  app.use("*", async (req, res, next) => {
-    const url = req.originalUrl;
- 
-    try {
-      const clientTemplate = path.resolve(
-        __dirname,
-        "..",
-        "client",
-        "index.html",
-      );
- 
-      // always reload the index.html file from disk incase it changes
-      let template = await fs.promises.readFile(clientTemplate, "utf-8");
-      template = template.replace(
-        `src="/src/main.tsx"`,
-        `src="/src/main.tsx?v=${nanoid()}"`,
-      );
-      const page = await vite.transformIndexHtml(url, template);
-      res.status(200).set({ "Content-Type": "text/html" }).end(page);
-    } catch (e) {
-      vite.ssrFixStacktrace(e as Error);
-      next(e);
-    }
-  });
-}
- 
-export function serveStatic(app: Express) {
-  const distPath = path.resolve(import.meta.dirname, "public");
- 
-  if (!fs.existsSync(distPath)) {
-    throw new Error(
-      `Could not find the build directory: ${distPath}, make sure to build the client first`,
-    );
-  }
- 
-  app.use(express.static(distPath));
- 
-  // fall through to index.html if the file doesn't exist
-  app.use("*", (_req, res) => {
-    res.sendFile(path.resolve(distPath, "index.html"));
-  });
-}
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/shared/index.html b/coverage/shared/index.html deleted file mode 100644 index 26baee0..0000000 --- a/coverage/shared/index.html +++ /dev/null @@ -1,116 +0,0 @@ - - - - - - Code coverage report for shared - - - - - - - - - -
-
-

All files shared

-
- -
- 71.42% - Statements - 10/14 -
- - -
- 100% - Branches - 0/0 -
- - -
- 0% - Functions - 0/4 -
- - -
- 71.42% - Lines - 10/14 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FileStatementsBranchesFunctionsLines
schema.ts -
-
71.42%10/14100%0/00%0/471.42%10/14
-
-
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/shared/schema.ts.html b/coverage/shared/schema.ts.html deleted file mode 100644 index b7c27ab..0000000 --- a/coverage/shared/schema.ts.html +++ /dev/null @@ -1,478 +0,0 @@ - - - - - - Code coverage report for shared/schema.ts - - - - - - - - - -
-
-

All files / shared schema.ts

-
- -
- 71.42% - Statements - 10/14 -
- - -
- 100% - Branches - 0/0 -
- - -
- 0% - Functions - 0/4 -
- - -
- 71.42% - Lines - 10/14 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63 -64 -65 -66 -67 -68 -69 -70 -71 -72 -73 -74 -75 -76 -77 -78 -79 -80 -81 -82 -83 -84 -85 -86 -87 -88 -89 -90 -91 -92 -93 -94 -95 -96 -97 -98 -99 -100 -101 -102 -103 -104 -105 -106 -107 -108 -109 -110 -111 -112 -113 -114 -115 -116 -117 -118 -119 -120 -121 -122 -123 -124 -125 -126 -127 -128 -129 -130 -131 -132  -  -  -  -  -  -  -  -  -  -  -  -  -1x -  -  -  -  -  -  -  -1x -  -  -  -  -  -  -  -  -  -  -  -  -  -  -1x -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -1x -  -  -  -  -  -  -  -  -  -  -  -  -  -  -1x -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -1x -  -  -  -  -1x -  -  -  -  -  -1x -  -  -  -  -1x -  -  -  -  -1x -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 
import { sql } from "drizzle-orm";
-import {
-  pgTable,
-  text,
-  varchar,
-  integer,
-  jsonb,
-  timestamp,
-  boolean,
-} from "drizzle-orm/pg-core";
-import { createInsertSchema } from "drizzle-zod";
-import { z } from "zod";
- 
-export const users = pgTable("users", {
-  id: varchar("id")
-    .primaryKey()
-    .default(sql`gen_random_uuid()`),
-  username: text("username").notNull().unique(),
-  password: text("password").notNull(),
-});
- 
-export const gameStates = pgTable("game_states", {
-  id: varchar("id")
-    .primaryKey()
-    .default(sql`gen_random_uuid()`),
-  userId: varchar("user_id").references(() => users.id),
-  player: jsonb("player").notNull(),
-  gates: jsonb("gates").notNull(),
-  gold: integer("gold").default(50),
-  gameTime: jsonb("game_time").notNull(),
-  daily: jsonb("daily").notNull(),
-  createdAt: timestamp("created_at").defaultNow(),
-  updatedAt: timestamp("updated_at").defaultNow(),
-});
- 
-// New tables for Phase 1: Gate History & Statistics
-export const gateRuns = pgTable("gate_runs", {
-  id: varchar("id")
-    .primaryKey()
-    .default(sql`gen_random_uuid()`),
-  userId: varchar("user_id").references(() => users.id),
-  gateId: varchar("gate_id").notNull(),
-  gateName: text("gate_name").notNull(),
-  gateRank: text("gate_rank").notNull(),
-  gateRankIdx: integer("gate_rank_idx").notNull(),
-  bossName: text("boss_name").notNull(),
-  victory: boolean("victory").notNull(),
-  duration: integer("duration").notNull(), // in ticks
-  expGained: integer("exp_gained").notNull(),
-  goldGained: integer("gold_gained").notNull(),
-  damageDealt: integer("damage_dealt").notNull(),
-  damageTaken: integer("damage_taken").notNull(),
-  playerLevel: integer("player_level").notNull(),
-  playerStats: jsonb("player_stats").notNull(),
-  drops: jsonb("drops").notNull(), // array of items
-  spiritBound: boolean("spirit_bound").default(false),
-  spiritName: text("spirit_name"),
-  combatLog: jsonb("combat_log").notNull(), // array of strings
-  createdAt: timestamp("created_at").defaultNow(),
-});
- 
-export const achievements = pgTable("achievements", {
-  id: varchar("id")
-    .primaryKey()
-    .default(sql`gen_random_uuid()`),
-  userId: varchar("user_id").references(() => users.id),
-  achievementId: text("achievement_id").notNull(),
-  name: text("name").notNull(),
-  description: text("description").notNull(),
-  category: text("category").notNull(), // "combat", "progression", "collection", "daily"
-  unlockedAt: timestamp("unlocked_at").defaultNow(),
-  progress: integer("progress").default(0),
-  maxProgress: integer("max_progress").default(1),
-  isUnlocked: boolean("is_unlocked").default(false),
-});
- 
-export const playerStats = pgTable("player_stats", {
-  id: varchar("id")
-    .primaryKey()
-    .default(sql`gen_random_uuid()`),
-  userId: varchar("user_id").references(() => users.id),
-  totalGatesCompleted: integer("total_gates_completed").default(0),
-  totalGatesFailed: integer("total_gates_failed").default(0),
-  totalExpGained: integer("total_exp_gained").default(0),
-  totalGoldGained: integer("total_gold_gained").default(0),
-  totalDamageDealt: integer("total_damage_dealt").default(0),
-  totalDamageTaken: integer("total_damage_taken").default(0),
-  totalSpiritsBound: integer("total_spirits_bound").default(0),
-  highestGateRank: text("highest_gate_rank").default("E"),
-  longestCombat: integer("longest_combat").default(0),
-  fastestVictory: integer("fastest_victory"),
-  totalPlayTime: integer("total_play_time").default(0), // in seconds
-  lastUpdated: timestamp("last_updated").defaultNow(),
-});
- 
-export const insertUserSchema = createInsertSchema(users).pick({
-  username: true,
-  password: true,
-});
- 
-export const insertGameStateSchema = createInsertSchema(gameStates).omit({
-  id: true,
-  createdAt: true,
-  updatedAt: true,
-});
- 
-export const insertGateRunSchema = createInsertSchema(gateRuns).omit({
-  id: true,
-  createdAt: true,
-});
- 
-export const insertAchievementSchema = createInsertSchema(achievements).omit({
-  id: true,
-  unlockedAt: true,
-});
- 
-export const insertPlayerStatsSchema = createInsertSchema(playerStats).omit({
-  id: true,
-  lastUpdated: true,
-});
- 
-export type InsertUser = z.infer<typeof insertUserSchema>;
-export type User = typeof users.$inferSelect;
-export type GameState = typeof gameStates.$inferSelect;
-export type InsertGameState = z.infer<typeof insertGameStateSchema>;
-export type GateRun = typeof gateRuns.$inferSelect;
-export type InsertGateRun = z.infer<typeof insertGateRunSchema>;
-export type Achievement = typeof achievements.$inferSelect;
-export type InsertAchievement = z.infer<typeof insertAchievementSchema>;
-export type PlayerStats = typeof playerStats.$inferSelect;
-export type InsertPlayerStats = z.infer<typeof insertPlayerStatsSchema>;
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/sort-arrow-sprite.png b/coverage/sort-arrow-sprite.png deleted file mode 100644 index 6ed6831..0000000 Binary files a/coverage/sort-arrow-sprite.png and /dev/null differ diff --git a/coverage/sorter.js b/coverage/sorter.js deleted file mode 100644 index 4ed70ae..0000000 --- a/coverage/sorter.js +++ /dev/null @@ -1,210 +0,0 @@ -/* eslint-disable */ -var addSorting = (function() { - 'use strict'; - var cols, - currentSort = { - index: 0, - desc: false - }; - - // returns the summary table element - function getTable() { - return document.querySelector('.coverage-summary'); - } - // returns the thead element of the summary table - function getTableHeader() { - return getTable().querySelector('thead tr'); - } - // returns the tbody element of the summary table - function getTableBody() { - return getTable().querySelector('tbody'); - } - // returns the th element for nth column - function getNthColumn(n) { - return getTableHeader().querySelectorAll('th')[n]; - } - - function onFilterInput() { - const searchValue = document.getElementById('fileSearch').value; - const rows = document.getElementsByTagName('tbody')[0].children; - - // Try to create a RegExp from the searchValue. If it fails (invalid regex), - // it will be treated as a plain text search - let searchRegex; - try { - searchRegex = new RegExp(searchValue, 'i'); // 'i' for case-insensitive - } catch (error) { - searchRegex = null; - } - - for (let i = 0; i < rows.length; i++) { - const row = rows[i]; - let isMatch = false; - - if (searchRegex) { - // If a valid regex was created, use it for matching - isMatch = searchRegex.test(row.textContent); - } else { - // Otherwise, fall back to the original plain text search - isMatch = row.textContent - .toLowerCase() - .includes(searchValue.toLowerCase()); - } - - row.style.display = isMatch ? '' : 'none'; - } - } - - // loads the search box - function addSearchBox() { - var template = document.getElementById('filterTemplate'); - var templateClone = template.content.cloneNode(true); - templateClone.getElementById('fileSearch').oninput = onFilterInput; - template.parentElement.appendChild(templateClone); - } - - // loads all columns - function loadColumns() { - var colNodes = getTableHeader().querySelectorAll('th'), - colNode, - cols = [], - col, - i; - - for (i = 0; i < colNodes.length; i += 1) { - colNode = colNodes[i]; - col = { - key: colNode.getAttribute('data-col'), - sortable: !colNode.getAttribute('data-nosort'), - type: colNode.getAttribute('data-type') || 'string' - }; - cols.push(col); - if (col.sortable) { - col.defaultDescSort = col.type === 'number'; - colNode.innerHTML = - colNode.innerHTML + ''; - } - } - return cols; - } - // attaches a data attribute to every tr element with an object - // of data values keyed by column name - function loadRowData(tableRow) { - var tableCols = tableRow.querySelectorAll('td'), - colNode, - col, - data = {}, - i, - val; - for (i = 0; i < tableCols.length; i += 1) { - colNode = tableCols[i]; - col = cols[i]; - val = colNode.getAttribute('data-value'); - if (col.type === 'number') { - val = Number(val); - } - data[col.key] = val; - } - return data; - } - // loads all row data - function loadData() { - var rows = getTableBody().querySelectorAll('tr'), - i; - - for (i = 0; i < rows.length; i += 1) { - rows[i].data = loadRowData(rows[i]); - } - } - // sorts the table using the data for the ith column - function sortByIndex(index, desc) { - var key = cols[index].key, - sorter = function(a, b) { - a = a.data[key]; - b = b.data[key]; - return a < b ? -1 : a > b ? 1 : 0; - }, - finalSorter = sorter, - tableBody = document.querySelector('.coverage-summary tbody'), - rowNodes = tableBody.querySelectorAll('tr'), - rows = [], - i; - - if (desc) { - finalSorter = function(a, b) { - return -1 * sorter(a, b); - }; - } - - for (i = 0; i < rowNodes.length; i += 1) { - rows.push(rowNodes[i]); - tableBody.removeChild(rowNodes[i]); - } - - rows.sort(finalSorter); - - for (i = 0; i < rows.length; i += 1) { - tableBody.appendChild(rows[i]); - } - } - // removes sort indicators for current column being sorted - function removeSortIndicators() { - var col = getNthColumn(currentSort.index), - cls = col.className; - - cls = cls.replace(/ sorted$/, '').replace(/ sorted-desc$/, ''); - col.className = cls; - } - // adds sort indicators for current column being sorted - function addSortIndicators() { - getNthColumn(currentSort.index).className += currentSort.desc - ? ' sorted-desc' - : ' sorted'; - } - // adds event listeners for all sorter widgets - function enableUI() { - var i, - el, - ithSorter = function ithSorter(i) { - var col = cols[i]; - - return function() { - var desc = col.defaultDescSort; - - if (currentSort.index === i) { - desc = !currentSort.desc; - } - sortByIndex(i, desc); - removeSortIndicators(); - currentSort.index = i; - currentSort.desc = desc; - addSortIndicators(); - }; - }; - for (i = 0; i < cols.length; i += 1) { - if (cols[i].sortable) { - // add the click event handler on the th so users - // dont have to click on those tiny arrows - el = getNthColumn(i).querySelector('.sorter').parentElement; - if (el.addEventListener) { - el.addEventListener('click', ithSorter(i)); - } else { - el.attachEvent('onclick', ithSorter(i)); - } - } - } - } - // adds sorting functionality to the UI - return function() { - if (!getTable()) { - return; - } - cols = loadColumns(); - loadData(); - addSearchBox(); - addSortIndicators(); - enableUI(); - }; -})(); - -window.addEventListener('load', addSorting); diff --git a/current-game-state.png b/current-game-state.png deleted file mode 100644 index c86a9f8..0000000 Binary files a/current-game-state.png and /dev/null differ diff --git a/firebase-debug.log b/firebase-debug.log deleted file mode 100644 index aa18c76..0000000 --- a/firebase-debug.log +++ /dev/null @@ -1,109 +0,0 @@ -[debug] [2026-02-12T17:46:43.282Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-02-12T17:46:43.283Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-02-12T17:46:43.284Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-02-12T17:46:43.368Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-02-12T17:46:43.369Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-02-12T17:46:43.370Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-02-12T17:46:43.370Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-02-13T15:07:52.591Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-02-13T15:07:52.592Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-02-13T15:07:52.593Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-02-13T15:07:52.694Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-02-13T15:07:52.694Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-02-13T15:07:52.695Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-02-13T15:07:52.695Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-02-13T19:50:58.423Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-02-13T19:50:58.424Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-02-13T19:50:58.425Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-02-13T19:50:58.493Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-02-13T19:50:58.494Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-02-13T19:50:58.494Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-02-13T19:50:58.495Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-02-23T14:58:31.045Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-02-23T14:58:31.046Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-02-23T14:58:31.047Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-02-23T14:58:31.126Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-02-23T14:58:31.127Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-02-23T14:58:31.127Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-02-23T14:58:31.128Z] >>> [apiv2][query] POST https://developerknowledge.googleapis.com/mcp [none] -[debug] [2026-02-23T14:58:31.128Z] >>> [apiv2][body] POST https://developerknowledge.googleapis.com/mcp {"method":"tools/list","jsonrpc":"2.0","id":1} -[debug] [2026-02-23T14:58:31.318Z] <<< [apiv2][status] POST https://developerknowledge.googleapis.com/mcp 200 -[debug] [2026-02-23T14:58:31.318Z] <<< [apiv2][body] POST https://developerknowledge.googleapis.com/mcp {"id":1,"jsonrpc":"2.0","result":{"tools":[{"annotations":{"destructiveHint":false,"idempotentHint":true,"openWorldHint":false,"readOnlyHint":true},"description":"Use this tool to find documentation about Google developer products.\nThe documents contain official APIs, code snippets, release notes, best\npractices, guides, debugging info, and more. It covers the following\nproducts and domains:\n\n* Android: developer.android.com\n* Apigee: docs.apigee.com\n* Chrome: developer.chrome.com\n* Firebase: firebase.google.com\n* Fuchsia: fuchsia.dev\n* Google AI: ai.google.dev\n* Google Cloud: docs.cloud.google.com\n* Google Developers, Ads, Search, Google Maps, Youtube: developers.google.com\n* Google Home: developers.home.google.com\n* TensorFlow: www.tensorflow.org\n* Web: web.dev\n\nThis tool returns chunks of text, names, and URLs for matching documents.\nIf the returned chunks are not detailed enough to answer the\nuser's question, use `get_document` or `batch_get_documents` with the\n`parent` from this tool's output to retrieve the full document\ncontent.","inputSchema":{"description":"Request schema for search_documents. Use the query field to search for related Google developer documentation.","properties":{"query":{"description":"Required. The raw query string provided by the user, such as \"How to create a Cloud Storage bucket?\".","type":"string"}},"required":["query"],"type":"object"},"name":"search_documents","outputSchema":{"$defs":{"DocumentChunk":{"description":"A DocumentChunk represents a piece of content from a Document in the DeveloperKnowledge corpus. To fetch the entire document content, pass the `parent` to get_document or batch_get_documents.","properties":{"content":{"description":"Output only. The content of the document chunk.","readOnly":true,"type":"string"},"id":{"description":"Output only. The ID of this chunk within the document. The chunk ID is unique within a document, but not globally unique across documents. The chunk ID is not stable and may change over time.","readOnly":true,"type":"string"},"parent":{"description":"Output only. The resource name of the document this chunk is from. Format: `documents/{uri_without_scheme}` Example: `documents/docs.cloud.google.com/storage/docs/creating-buckets`","readOnly":true,"type":"string"}},"type":"object"}},"description":"Response schema for search_documents.","properties":{"results":{"description":"The search results for the given query. Each Document in this list contains a snippet of content relevant to the search query. Use the Document.name field of each result with get_document or batch_get_documents to retrieve the full document content.","items":{"$ref":"#/$defs/DocumentChunk"},"type":"array"}},"type":"object"}},{"annotations":{"destructiveHint":false,"idempotentHint":true,"openWorldHint":false,"readOnlyHint":true},"description":"Use this tool to retrieve the full content of a single document. The\ndocument name should be obtained from the `parent` field of results from a\ncall to the `search_documents` tool. If you need to retrieve multiple\ndocuments, use `batch_get_documents` instead.","inputSchema":{"description":"Request schema for get_document.","properties":{"name":{"description":"Required. The name of the document to retrieve. Format: `documents/{uri_without_scheme}` Example: `documents/docs.cloud.google.com/storage/docs/creating-buckets`","type":"string"}},"required":["name"],"type":"object"},"name":"get_document","outputSchema":{"description":"A Document represents a piece of content from the Developer Knowledge corpus.","properties":{"content":{"description":"Output only. The content of the document in Markdown format. If this document is returned by search_documents, this field contains a snippet of text relevant to the search query. If this document is returned by get_document or batch_get_documents, this field contains the full document content.","readOnly":true,"type":"string"},"description":{"description":"Output only. A description of the document.","readOnly":true,"type":"string"},"name":{"description":"Identifier. The resource name of the document. Format: `documents/{uri_without_scheme}` Example: `documents/docs.cloud.google.com/storage/docs/creating-buckets`","type":"string","x-google-identifier":true},"uri":{"description":"Output only. The URI of the content, such as `https://cloud.google.com/storage/docs/creating-buckets`.","readOnly":true,"type":"string"}},"type":"object"}},{"annotations":{"destructiveHint":false,"idempotentHint":true,"openWorldHint":false,"readOnlyHint":true},"description":"Use this tool to retrieve the full content of up to 20 documents in a\nsingle call. The document names should be obtained from the `parent` field\nof results from a call to the `search_documents` tool. Use this tool\ninstead of calling `get_document` multiple times to fetch multiple\ndocuments.","inputSchema":{"description":"Request schema for batch_get_documents.","properties":{"names":{"description":"Required. The names of the documents to retrieve, as returned by search_documents. A maximum of 20 documents can be retrieved in a batch. The documents are returned in the same order as the `names` in the request. Format: `documents/{uri_without_scheme}` Example: `documents/docs.cloud.google.com/storage/docs/creating-buckets`","items":{"type":"string"},"type":"array"}},"required":["names"],"type":"object"},"name":"batch_get_documents","outputSchema":{"$defs":{"Document":{"description":"A Document represents a piece of content from the Developer Knowledge corpus.","properties":{"content":{"description":"Output only. The content of the document in Markdown format. If this document is returned by search_documents, this field contains a snippet of text relevant to the search query. If this document is returned by get_document or batch_get_documents, this field contains the full document content.","readOnly":true,"type":"string"},"description":{"description":"Output only. A description of the document.","readOnly":true,"type":"string"},"name":{"description":"Identifier. The resource name of the document. Format: `documents/{uri_without_scheme}` Example: `documents/docs.cloud.google.com/storage/docs/creating-buckets`","type":"string","x-google-identifier":true},"uri":{"description":"Output only. The URI of the content, such as `https://cloud.google.com/storage/docs/creating-buckets`.","readOnly":true,"type":"string"}},"type":"object"}},"description":"Response schema for batch_get_documents.","properties":{"documents":{"description":"Documents requested.","items":{"$ref":"#/$defs/Document"},"type":"array"}},"type":"object"}}]}} -[debug] [2026-02-23T14:58:31.320Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-02-23T17:46:31.346Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-02-23T17:46:31.347Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-02-23T17:46:31.349Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-02-23T17:46:31.420Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-02-23T17:46:31.421Z] >>> [apiv2][query] POST https://developerknowledge.googleapis.com/mcp [none] -[debug] [2026-02-23T17:46:31.421Z] >>> [apiv2][body] POST https://developerknowledge.googleapis.com/mcp {"method":"tools/list","jsonrpc":"2.0","id":1} -[debug] [2026-02-23T17:46:31.426Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-02-23T17:46:31.427Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-02-23T17:46:31.612Z] <<< [apiv2][status] POST https://developerknowledge.googleapis.com/mcp 200 -[debug] [2026-02-23T17:46:31.613Z] <<< [apiv2][body] POST https://developerknowledge.googleapis.com/mcp {"id":1,"jsonrpc":"2.0","result":{"tools":[{"annotations":{"destructiveHint":false,"idempotentHint":true,"openWorldHint":false,"readOnlyHint":true},"description":"Use this tool to find documentation about Google developer products.\nThe documents contain official APIs, code snippets, release notes, best\npractices, guides, debugging info, and more. It covers the following\nproducts and domains:\n\n* Android: developer.android.com\n* Apigee: docs.apigee.com\n* Chrome: developer.chrome.com\n* Firebase: firebase.google.com\n* Fuchsia: fuchsia.dev\n* Google AI: ai.google.dev\n* Google Cloud: docs.cloud.google.com\n* Google Developers, Ads, Search, Google Maps, Youtube: developers.google.com\n* Google Home: developers.home.google.com\n* TensorFlow: www.tensorflow.org\n* Web: web.dev\n\nThis tool returns chunks of text, names, and URLs for matching documents.\nIf the returned chunks are not detailed enough to answer the\nuser's question, use `get_document` or `batch_get_documents` with the\n`parent` from this tool's output to retrieve the full document\ncontent.","inputSchema":{"description":"Request schema for search_documents. Use the query field to search for related Google developer documentation.","properties":{"query":{"description":"Required. The raw query string provided by the user, such as \"How to create a Cloud Storage bucket?\".","type":"string"}},"required":["query"],"type":"object"},"name":"search_documents","outputSchema":{"$defs":{"DocumentChunk":{"description":"A DocumentChunk represents a piece of content from a Document in the DeveloperKnowledge corpus. To fetch the entire document content, pass the `parent` to get_document or batch_get_documents.","properties":{"content":{"description":"Output only. The content of the document chunk.","readOnly":true,"type":"string"},"id":{"description":"Output only. The ID of this chunk within the document. The chunk ID is unique within a document, but not globally unique across documents. The chunk ID is not stable and may change over time.","readOnly":true,"type":"string"},"parent":{"description":"Output only. The resource name of the document this chunk is from. Format: `documents/{uri_without_scheme}` Example: `documents/docs.cloud.google.com/storage/docs/creating-buckets`","readOnly":true,"type":"string"}},"type":"object"}},"description":"Response schema for search_documents.","properties":{"results":{"description":"The search results for the given query. Each Document in this list contains a snippet of content relevant to the search query. Use the Document.name field of each result with get_document or batch_get_documents to retrieve the full document content.","items":{"$ref":"#/$defs/DocumentChunk"},"type":"array"}},"type":"object"}},{"annotations":{"destructiveHint":false,"idempotentHint":true,"openWorldHint":false,"readOnlyHint":true},"description":"Use this tool to retrieve the full content of a single document. The\ndocument name should be obtained from the `parent` field of results from a\ncall to the `search_documents` tool. If you need to retrieve multiple\ndocuments, use `batch_get_documents` instead.","inputSchema":{"description":"Request schema for get_document.","properties":{"name":{"description":"Required. The name of the document to retrieve. Format: `documents/{uri_without_scheme}` Example: `documents/docs.cloud.google.com/storage/docs/creating-buckets`","type":"string"}},"required":["name"],"type":"object"},"name":"get_document","outputSchema":{"description":"A Document represents a piece of content from the Developer Knowledge corpus.","properties":{"content":{"description":"Output only. The content of the document in Markdown format. If this document is returned by search_documents, this field contains a snippet of text relevant to the search query. If this document is returned by get_document or batch_get_documents, this field contains the full document content.","readOnly":true,"type":"string"},"description":{"description":"Output only. A description of the document.","readOnly":true,"type":"string"},"name":{"description":"Identifier. The resource name of the document. Format: `documents/{uri_without_scheme}` Example: `documents/docs.cloud.google.com/storage/docs/creating-buckets`","type":"string","x-google-identifier":true},"uri":{"description":"Output only. The URI of the content, such as `https://cloud.google.com/storage/docs/creating-buckets`.","readOnly":true,"type":"string"}},"type":"object"}},{"annotations":{"destructiveHint":false,"idempotentHint":true,"openWorldHint":false,"readOnlyHint":true},"description":"Use this tool to retrieve the full content of up to 20 documents in a\nsingle call. The document names should be obtained from the `parent` field\nof results from a call to the `search_documents` tool. Use this tool\ninstead of calling `get_document` multiple times to fetch multiple\ndocuments.","inputSchema":{"description":"Request schema for batch_get_documents.","properties":{"names":{"description":"Required. The names of the documents to retrieve, as returned by search_documents. A maximum of 20 documents can be retrieved in a batch. The documents are returned in the same order as the `names` in the request. Format: `documents/{uri_without_scheme}` Example: `documents/docs.cloud.google.com/storage/docs/creating-buckets`","items":{"type":"string"},"type":"array"}},"required":["names"],"type":"object"},"name":"batch_get_documents","outputSchema":{"$defs":{"Document":{"description":"A Document represents a piece of content from the Developer Knowledge corpus.","properties":{"content":{"description":"Output only. The content of the document in Markdown format. If this document is returned by search_documents, this field contains a snippet of text relevant to the search query. If this document is returned by get_document or batch_get_documents, this field contains the full document content.","readOnly":true,"type":"string"},"description":{"description":"Output only. A description of the document.","readOnly":true,"type":"string"},"name":{"description":"Identifier. The resource name of the document. Format: `documents/{uri_without_scheme}` Example: `documents/docs.cloud.google.com/storage/docs/creating-buckets`","type":"string","x-google-identifier":true},"uri":{"description":"Output only. The URI of the content, such as `https://cloud.google.com/storage/docs/creating-buckets`.","readOnly":true,"type":"string"}},"type":"object"}},"description":"Response schema for batch_get_documents.","properties":{"documents":{"description":"Documents requested.","items":{"$ref":"#/$defs/Document"},"type":"array"}},"type":"object"}}]}} -[debug] [2026-02-23T17:46:31.614Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-02-23T18:51:57.194Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-02-23T18:51:57.195Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-02-23T18:51:57.196Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-02-23T18:51:57.266Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-02-23T18:51:57.267Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-02-23T18:51:57.267Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-02-23T18:51:57.268Z] >>> [apiv2][query] POST https://developerknowledge.googleapis.com/mcp [none] -[debug] [2026-02-23T18:51:57.268Z] >>> [apiv2][body] POST https://developerknowledge.googleapis.com/mcp {"method":"tools/list","jsonrpc":"2.0","id":1} -[debug] [2026-02-23T18:51:57.442Z] <<< [apiv2][status] POST https://developerknowledge.googleapis.com/mcp 200 -[debug] [2026-02-23T18:51:57.442Z] <<< [apiv2][body] POST https://developerknowledge.googleapis.com/mcp {"id":1,"jsonrpc":"2.0","result":{"tools":[{"annotations":{"destructiveHint":false,"idempotentHint":true,"openWorldHint":false,"readOnlyHint":true},"description":"Use this tool to find documentation about Google developer products.\nThe documents contain official APIs, code snippets, release notes, best\npractices, guides, debugging info, and more. It covers the following\nproducts and domains:\n\n* Android: developer.android.com\n* Apigee: docs.apigee.com\n* Chrome: developer.chrome.com\n* Firebase: firebase.google.com\n* Fuchsia: fuchsia.dev\n* Google AI: ai.google.dev\n* Google Cloud: docs.cloud.google.com\n* Google Developers, Ads, Search, Google Maps, Youtube: developers.google.com\n* Google Home: developers.home.google.com\n* TensorFlow: www.tensorflow.org\n* Web: web.dev\n\nThis tool returns chunks of text, names, and URLs for matching documents.\nIf the returned chunks are not detailed enough to answer the\nuser's question, use `get_document` or `batch_get_documents` with the\n`parent` from this tool's output to retrieve the full document\ncontent.","inputSchema":{"description":"Request schema for search_documents. Use the query field to search for related Google developer documentation.","properties":{"query":{"description":"Required. The raw query string provided by the user, such as \"How to create a Cloud Storage bucket?\".","type":"string"}},"required":["query"],"type":"object"},"name":"search_documents","outputSchema":{"$defs":{"DocumentChunk":{"description":"A DocumentChunk represents a piece of content from a Document in the DeveloperKnowledge corpus. To fetch the entire document content, pass the `parent` to get_document or batch_get_documents.","properties":{"content":{"description":"Output only. The content of the document chunk.","readOnly":true,"type":"string"},"id":{"description":"Output only. The ID of this chunk within the document. The chunk ID is unique within a document, but not globally unique across documents. The chunk ID is not stable and may change over time.","readOnly":true,"type":"string"},"parent":{"description":"Output only. The resource name of the document this chunk is from. Format: `documents/{uri_without_scheme}` Example: `documents/docs.cloud.google.com/storage/docs/creating-buckets`","readOnly":true,"type":"string"}},"type":"object"}},"description":"Response schema for search_documents.","properties":{"results":{"description":"The search results for the given query. Each Document in this list contains a snippet of content relevant to the search query. Use the Document.name field of each result with get_document or batch_get_documents to retrieve the full document content.","items":{"$ref":"#/$defs/DocumentChunk"},"type":"array"}},"type":"object"}},{"annotations":{"destructiveHint":false,"idempotentHint":true,"openWorldHint":false,"readOnlyHint":true},"description":"Use this tool to retrieve the full content of a single document. The\ndocument name should be obtained from the `parent` field of results from a\ncall to the `search_documents` tool. If you need to retrieve multiple\ndocuments, use `batch_get_documents` instead.","inputSchema":{"description":"Request schema for get_document.","properties":{"name":{"description":"Required. The name of the document to retrieve. Format: `documents/{uri_without_scheme}` Example: `documents/docs.cloud.google.com/storage/docs/creating-buckets`","type":"string"}},"required":["name"],"type":"object"},"name":"get_document","outputSchema":{"description":"A Document represents a piece of content from the Developer Knowledge corpus.","properties":{"content":{"description":"Output only. The content of the document in Markdown format. If this document is returned by search_documents, this field contains a snippet of text relevant to the search query. If this document is returned by get_document or batch_get_documents, this field contains the full document content.","readOnly":true,"type":"string"},"description":{"description":"Output only. A description of the document.","readOnly":true,"type":"string"},"name":{"description":"Identifier. The resource name of the document. Format: `documents/{uri_without_scheme}` Example: `documents/docs.cloud.google.com/storage/docs/creating-buckets`","type":"string","x-google-identifier":true},"uri":{"description":"Output only. The URI of the content, such as `https://cloud.google.com/storage/docs/creating-buckets`.","readOnly":true,"type":"string"}},"type":"object"}},{"annotations":{"destructiveHint":false,"idempotentHint":true,"openWorldHint":false,"readOnlyHint":true},"description":"Use this tool to retrieve the full content of up to 20 documents in a\nsingle call. The document names should be obtained from the `parent` field\nof results from a call to the `search_documents` tool. Use this tool\ninstead of calling `get_document` multiple times to fetch multiple\ndocuments.","inputSchema":{"description":"Request schema for batch_get_documents.","properties":{"names":{"description":"Required. The names of the documents to retrieve, as returned by search_documents. A maximum of 20 documents can be retrieved in a batch. The documents are returned in the same order as the `names` in the request. Format: `documents/{uri_without_scheme}` Example: `documents/docs.cloud.google.com/storage/docs/creating-buckets`","items":{"type":"string"},"type":"array"}},"required":["names"],"type":"object"},"name":"batch_get_documents","outputSchema":{"$defs":{"Document":{"description":"A Document represents a piece of content from the Developer Knowledge corpus.","properties":{"content":{"description":"Output only. The content of the document in Markdown format. If this document is returned by search_documents, this field contains a snippet of text relevant to the search query. If this document is returned by get_document or batch_get_documents, this field contains the full document content.","readOnly":true,"type":"string"},"description":{"description":"Output only. A description of the document.","readOnly":true,"type":"string"},"name":{"description":"Identifier. The resource name of the document. Format: `documents/{uri_without_scheme}` Example: `documents/docs.cloud.google.com/storage/docs/creating-buckets`","type":"string","x-google-identifier":true},"uri":{"description":"Output only. The URI of the content, such as `https://cloud.google.com/storage/docs/creating-buckets`.","readOnly":true,"type":"string"}},"type":"object"}},"description":"Response schema for batch_get_documents.","properties":{"documents":{"description":"Documents requested.","items":{"$ref":"#/$defs/Document"},"type":"array"}},"type":"object"}}]}} -[debug] [2026-02-23T18:51:57.443Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-02-23T18:53:23.697Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-02-23T18:53:23.698Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-02-23T18:53:23.699Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-02-23T18:53:23.774Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-02-23T18:53:23.775Z] >>> [apiv2][query] POST https://developerknowledge.googleapis.com/mcp [none] -[debug] [2026-02-23T18:53:23.775Z] >>> [apiv2][body] POST https://developerknowledge.googleapis.com/mcp {"method":"tools/list","jsonrpc":"2.0","id":1} -[debug] [2026-02-23T18:53:23.780Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-02-23T18:53:23.781Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-02-23T18:53:23.976Z] <<< [apiv2][status] POST https://developerknowledge.googleapis.com/mcp 200 -[debug] [2026-02-23T18:53:23.976Z] <<< [apiv2][body] POST https://developerknowledge.googleapis.com/mcp {"id":1,"jsonrpc":"2.0","result":{"tools":[{"annotations":{"destructiveHint":false,"idempotentHint":true,"openWorldHint":false,"readOnlyHint":true},"description":"Use this tool to find documentation about Google developer products.\nThe documents contain official APIs, code snippets, release notes, best\npractices, guides, debugging info, and more. It covers the following\nproducts and domains:\n\n* Android: developer.android.com\n* Apigee: docs.apigee.com\n* Chrome: developer.chrome.com\n* Firebase: firebase.google.com\n* Fuchsia: fuchsia.dev\n* Google AI: ai.google.dev\n* Google Cloud: docs.cloud.google.com\n* Google Developers, Ads, Search, Google Maps, Youtube: developers.google.com\n* Google Home: developers.home.google.com\n* TensorFlow: www.tensorflow.org\n* Web: web.dev\n\nThis tool returns chunks of text, names, and URLs for matching documents.\nIf the returned chunks are not detailed enough to answer the\nuser's question, use `get_document` or `batch_get_documents` with the\n`parent` from this tool's output to retrieve the full document\ncontent.","inputSchema":{"description":"Request schema for search_documents. Use the query field to search for related Google developer documentation.","properties":{"query":{"description":"Required. The raw query string provided by the user, such as \"How to create a Cloud Storage bucket?\".","type":"string"}},"required":["query"],"type":"object"},"name":"search_documents","outputSchema":{"$defs":{"DocumentChunk":{"description":"A DocumentChunk represents a piece of content from a Document in the DeveloperKnowledge corpus. To fetch the entire document content, pass the `parent` to get_document or batch_get_documents.","properties":{"content":{"description":"Output only. The content of the document chunk.","readOnly":true,"type":"string"},"id":{"description":"Output only. The ID of this chunk within the document. The chunk ID is unique within a document, but not globally unique across documents. The chunk ID is not stable and may change over time.","readOnly":true,"type":"string"},"parent":{"description":"Output only. The resource name of the document this chunk is from. Format: `documents/{uri_without_scheme}` Example: `documents/docs.cloud.google.com/storage/docs/creating-buckets`","readOnly":true,"type":"string"}},"type":"object"}},"description":"Response schema for search_documents.","properties":{"results":{"description":"The search results for the given query. Each Document in this list contains a snippet of content relevant to the search query. Use the Document.name field of each result with get_document or batch_get_documents to retrieve the full document content.","items":{"$ref":"#/$defs/DocumentChunk"},"type":"array"}},"type":"object"}},{"annotations":{"destructiveHint":false,"idempotentHint":true,"openWorldHint":false,"readOnlyHint":true},"description":"Use this tool to retrieve the full content of a single document. The\ndocument name should be obtained from the `parent` field of results from a\ncall to the `search_documents` tool. If you need to retrieve multiple\ndocuments, use `batch_get_documents` instead.","inputSchema":{"description":"Request schema for get_document.","properties":{"name":{"description":"Required. The name of the document to retrieve. Format: `documents/{uri_without_scheme}` Example: `documents/docs.cloud.google.com/storage/docs/creating-buckets`","type":"string"}},"required":["name"],"type":"object"},"name":"get_document","outputSchema":{"description":"A Document represents a piece of content from the Developer Knowledge corpus.","properties":{"content":{"description":"Output only. The content of the document in Markdown format. If this document is returned by search_documents, this field contains a snippet of text relevant to the search query. If this document is returned by get_document or batch_get_documents, this field contains the full document content.","readOnly":true,"type":"string"},"description":{"description":"Output only. A description of the document.","readOnly":true,"type":"string"},"name":{"description":"Identifier. The resource name of the document. Format: `documents/{uri_without_scheme}` Example: `documents/docs.cloud.google.com/storage/docs/creating-buckets`","type":"string","x-google-identifier":true},"uri":{"description":"Output only. The URI of the content, such as `https://cloud.google.com/storage/docs/creating-buckets`.","readOnly":true,"type":"string"}},"type":"object"}},{"annotations":{"destructiveHint":false,"idempotentHint":true,"openWorldHint":false,"readOnlyHint":true},"description":"Use this tool to retrieve the full content of up to 20 documents in a\nsingle call. The document names should be obtained from the `parent` field\nof results from a call to the `search_documents` tool. Use this tool\ninstead of calling `get_document` multiple times to fetch multiple\ndocuments.","inputSchema":{"description":"Request schema for batch_get_documents.","properties":{"names":{"description":"Required. The names of the documents to retrieve, as returned by search_documents. A maximum of 20 documents can be retrieved in a batch. The documents are returned in the same order as the `names` in the request. Format: `documents/{uri_without_scheme}` Example: `documents/docs.cloud.google.com/storage/docs/creating-buckets`","items":{"type":"string"},"type":"array"}},"required":["names"],"type":"object"},"name":"batch_get_documents","outputSchema":{"$defs":{"Document":{"description":"A Document represents a piece of content from the Developer Knowledge corpus.","properties":{"content":{"description":"Output only. The content of the document in Markdown format. If this document is returned by search_documents, this field contains a snippet of text relevant to the search query. If this document is returned by get_document or batch_get_documents, this field contains the full document content.","readOnly":true,"type":"string"},"description":{"description":"Output only. A description of the document.","readOnly":true,"type":"string"},"name":{"description":"Identifier. The resource name of the document. Format: `documents/{uri_without_scheme}` Example: `documents/docs.cloud.google.com/storage/docs/creating-buckets`","type":"string","x-google-identifier":true},"uri":{"description":"Output only. The URI of the content, such as `https://cloud.google.com/storage/docs/creating-buckets`.","readOnly":true,"type":"string"}},"type":"object"}},"description":"Response schema for batch_get_documents.","properties":{"documents":{"description":"Documents requested.","items":{"$ref":"#/$defs/Document"},"type":"array"}},"type":"object"}}]}} -[debug] [2026-02-23T18:53:23.977Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-02-24T21:45:23.687Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-02-24T21:45:23.688Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-02-24T21:45:23.689Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-02-24T21:45:23.779Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-02-24T21:45:23.780Z] >>> [apiv2][query] POST https://developerknowledge.googleapis.com/mcp [none] -[debug] [2026-02-24T21:45:23.780Z] >>> [apiv2][body] POST https://developerknowledge.googleapis.com/mcp {"method":"tools/list","jsonrpc":"2.0","id":1} -[debug] [2026-02-24T21:45:23.785Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-02-24T21:45:23.786Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-02-24T21:45:24.005Z] <<< [apiv2][status] POST https://developerknowledge.googleapis.com/mcp 200 -[debug] [2026-02-24T21:45:24.005Z] <<< [apiv2][body] POST https://developerknowledge.googleapis.com/mcp {"id":1,"jsonrpc":"2.0","result":{"tools":[{"annotations":{"destructiveHint":false,"idempotentHint":true,"openWorldHint":false,"readOnlyHint":true},"description":"Use this tool to find documentation about Google developer products.\nThe documents contain official APIs, code snippets, release notes, best\npractices, guides, debugging info, and more. It covers the following\nproducts and domains:\n\n* Android: developer.android.com\n* Apigee: docs.apigee.com\n* Chrome: developer.chrome.com\n* Firebase: firebase.google.com\n* Fuchsia: fuchsia.dev\n* Google AI: ai.google.dev\n* Google Cloud: docs.cloud.google.com\n* Google Developers, Ads, Search, Google Maps, Youtube: developers.google.com\n* Google Home: developers.home.google.com\n* TensorFlow: www.tensorflow.org\n* Web: web.dev\n\nThis tool returns chunks of text, names, and URLs for matching documents.\nIf the returned chunks are not detailed enough to answer the\nuser's question, use `get_document` or `batch_get_documents` with the\n`parent` from this tool's output to retrieve the full document\ncontent.","inputSchema":{"description":"Request schema for search_documents. Use the query field to search for related Google developer documentation.","properties":{"query":{"description":"Required. The raw query string provided by the user, such as \"How to create a Cloud Storage bucket?\".","type":"string"}},"required":["query"],"type":"object"},"name":"search_documents","outputSchema":{"$defs":{"DocumentChunk":{"description":"A DocumentChunk represents a piece of content from a Document in the DeveloperKnowledge corpus. To fetch the entire document content, pass the `parent` to get_document or batch_get_documents.","properties":{"content":{"description":"Output only. The content of the document chunk.","readOnly":true,"type":"string"},"id":{"description":"Output only. The ID of this chunk within the document. The chunk ID is unique within a document, but not globally unique across documents. The chunk ID is not stable and may change over time.","readOnly":true,"type":"string"},"parent":{"description":"Output only. The resource name of the document this chunk is from. Format: `documents/{uri_without_scheme}` Example: `documents/docs.cloud.google.com/storage/docs/creating-buckets`","readOnly":true,"type":"string"}},"type":"object"}},"description":"Response schema for search_documents.","properties":{"results":{"description":"The search results for the given query. Each Document in this list contains a snippet of content relevant to the search query. Use the Document.name field of each result with get_document or batch_get_documents to retrieve the full document content.","items":{"$ref":"#/$defs/DocumentChunk"},"type":"array"}},"type":"object"}},{"annotations":{"destructiveHint":false,"idempotentHint":true,"openWorldHint":false,"readOnlyHint":true},"description":"Use this tool to retrieve the full content of a single document. The\ndocument name should be obtained from the `parent` field of results from a\ncall to the `search_documents` tool. If you need to retrieve multiple\ndocuments, use `batch_get_documents` instead.","inputSchema":{"description":"Request schema for get_document.","properties":{"name":{"description":"Required. The name of the document to retrieve. Format: `documents/{uri_without_scheme}` Example: `documents/docs.cloud.google.com/storage/docs/creating-buckets`","type":"string"}},"required":["name"],"type":"object"},"name":"get_document","outputSchema":{"description":"A Document represents a piece of content from the Developer Knowledge corpus.","properties":{"content":{"description":"Output only. The content of the document in Markdown format. If this document is returned by search_documents, this field contains a snippet of text relevant to the search query. If this document is returned by get_document or batch_get_documents, this field contains the full document content.","readOnly":true,"type":"string"},"description":{"description":"Output only. A description of the document.","readOnly":true,"type":"string"},"name":{"description":"Identifier. The resource name of the document. Format: `documents/{uri_without_scheme}` Example: `documents/docs.cloud.google.com/storage/docs/creating-buckets`","type":"string","x-google-identifier":true},"uri":{"description":"Output only. The URI of the content, such as `https://cloud.google.com/storage/docs/creating-buckets`.","readOnly":true,"type":"string"}},"type":"object"}},{"annotations":{"destructiveHint":false,"idempotentHint":true,"openWorldHint":false,"readOnlyHint":true},"description":"Use this tool to retrieve the full content of up to 20 documents in a\nsingle call. The document names should be obtained from the `parent` field\nof results from a call to the `search_documents` tool. Use this tool\ninstead of calling `get_document` multiple times to fetch multiple\ndocuments.","inputSchema":{"description":"Request schema for batch_get_documents.","properties":{"names":{"description":"Required. The names of the documents to retrieve, as returned by search_documents. A maximum of 20 documents can be retrieved in a batch. The documents are returned in the same order as the `names` in the request. Format: `documents/{uri_without_scheme}` Example: `documents/docs.cloud.google.com/storage/docs/creating-buckets`","items":{"type":"string"},"type":"array"}},"required":["names"],"type":"object"},"name":"batch_get_documents","outputSchema":{"$defs":{"Document":{"description":"A Document represents a piece of content from the Developer Knowledge corpus.","properties":{"content":{"description":"Output only. The content of the document in Markdown format. If this document is returned by search_documents, this field contains a snippet of text relevant to the search query. If this document is returned by get_document or batch_get_documents, this field contains the full document content.","readOnly":true,"type":"string"},"description":{"description":"Output only. A description of the document.","readOnly":true,"type":"string"},"name":{"description":"Identifier. The resource name of the document. Format: `documents/{uri_without_scheme}` Example: `documents/docs.cloud.google.com/storage/docs/creating-buckets`","type":"string","x-google-identifier":true},"uri":{"description":"Output only. The URI of the content, such as `https://cloud.google.com/storage/docs/creating-buckets`.","readOnly":true,"type":"string"}},"type":"object"}},"description":"Response schema for batch_get_documents.","properties":{"documents":{"description":"Documents requested.","items":{"$ref":"#/$defs/Document"},"type":"array"}},"type":"object"}}]}} -[debug] [2026-02-24T21:45:24.007Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-02-25T13:00:12.736Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-02-25T13:00:12.737Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-02-25T13:00:12.738Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-02-25T13:00:12.827Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-02-25T13:00:12.828Z] >>> [apiv2][query] POST https://developerknowledge.googleapis.com/mcp [none] -[debug] [2026-02-25T13:00:12.828Z] >>> [apiv2][body] POST https://developerknowledge.googleapis.com/mcp {"method":"tools/list","jsonrpc":"2.0","id":1} -[debug] [2026-02-25T13:00:12.833Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-02-25T13:00:12.834Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-02-25T13:00:13.015Z] <<< [apiv2][status] POST https://developerknowledge.googleapis.com/mcp 200 -[debug] [2026-02-25T13:00:13.015Z] <<< [apiv2][body] POST https://developerknowledge.googleapis.com/mcp {"id":1,"jsonrpc":"2.0","result":{"tools":[{"annotations":{"destructiveHint":false,"idempotentHint":true,"openWorldHint":false,"readOnlyHint":true},"description":"Use this tool to find documentation about Google developer products.\nThe documents contain official APIs, code snippets, release notes, best\npractices, guides, debugging info, and more. It covers the following\nproducts and domains:\n\n* Android: developer.android.com\n* Apigee: docs.apigee.com\n* Chrome: developer.chrome.com\n* Firebase: firebase.google.com\n* Fuchsia: fuchsia.dev\n* Google AI: ai.google.dev\n* Google Cloud: docs.cloud.google.com\n* Google Developers, Ads, Search, Google Maps, Youtube: developers.google.com\n* Google Home: developers.home.google.com\n* TensorFlow: www.tensorflow.org\n* Web: web.dev\n\nThis tool returns chunks of text, names, and URLs for matching documents.\nIf the returned chunks are not detailed enough to answer the\nuser's question, use `get_document` or `batch_get_documents` with the\n`parent` from this tool's output to retrieve the full document\ncontent.","inputSchema":{"description":"Request schema for search_documents. Use the query field to search for related Google developer documentation.","properties":{"query":{"description":"Required. The raw query string provided by the user, such as \"How to create a Cloud Storage bucket?\".","type":"string"}},"required":["query"],"type":"object"},"name":"search_documents","outputSchema":{"$defs":{"DocumentChunk":{"description":"A DocumentChunk represents a piece of content from a Document in the DeveloperKnowledge corpus. To fetch the entire document content, pass the `parent` to get_document or batch_get_documents.","properties":{"content":{"description":"Output only. The content of the document chunk.","readOnly":true,"type":"string"},"id":{"description":"Output only. The ID of this chunk within the document. The chunk ID is unique within a document, but not globally unique across documents. The chunk ID is not stable and may change over time.","readOnly":true,"type":"string"},"parent":{"description":"Output only. The resource name of the document this chunk is from. Format: `documents/{uri_without_scheme}` Example: `documents/docs.cloud.google.com/storage/docs/creating-buckets`","readOnly":true,"type":"string"}},"type":"object"}},"description":"Response schema for search_documents.","properties":{"results":{"description":"The search results for the given query. Each Document in this list contains a snippet of content relevant to the search query. Use the Document.name field of each result with get_document or batch_get_documents to retrieve the full document content.","items":{"$ref":"#/$defs/DocumentChunk"},"type":"array"}},"type":"object"}},{"annotations":{"destructiveHint":false,"idempotentHint":true,"openWorldHint":false,"readOnlyHint":true},"description":"Use this tool to retrieve the full content of a single document. The\ndocument name should be obtained from the `parent` field of results from a\ncall to the `search_documents` tool. If you need to retrieve multiple\ndocuments, use `batch_get_documents` instead.","inputSchema":{"description":"Request schema for get_document.","properties":{"name":{"description":"Required. The name of the document to retrieve. Format: `documents/{uri_without_scheme}` Example: `documents/docs.cloud.google.com/storage/docs/creating-buckets`","type":"string"}},"required":["name"],"type":"object"},"name":"get_document","outputSchema":{"description":"A Document represents a piece of content from the Developer Knowledge corpus.","properties":{"content":{"description":"Output only. The content of the document in Markdown format. If this document is returned by search_documents, this field contains a snippet of text relevant to the search query. If this document is returned by get_document or batch_get_documents, this field contains the full document content.","readOnly":true,"type":"string"},"description":{"description":"Output only. A description of the document.","readOnly":true,"type":"string"},"name":{"description":"Identifier. The resource name of the document. Format: `documents/{uri_without_scheme}` Example: `documents/docs.cloud.google.com/storage/docs/creating-buckets`","type":"string","x-google-identifier":true},"uri":{"description":"Output only. The URI of the content, such as `https://cloud.google.com/storage/docs/creating-buckets`.","readOnly":true,"type":"string"}},"type":"object"}},{"annotations":{"destructiveHint":false,"idempotentHint":true,"openWorldHint":false,"readOnlyHint":true},"description":"Use this tool to retrieve the full content of up to 20 documents in a\nsingle call. The document names should be obtained from the `parent` field\nof results from a call to the `search_documents` tool. Use this tool\ninstead of calling `get_document` multiple times to fetch multiple\ndocuments.","inputSchema":{"description":"Request schema for batch_get_documents.","properties":{"names":{"description":"Required. The names of the documents to retrieve, as returned by search_documents. A maximum of 20 documents can be retrieved in a batch. The documents are returned in the same order as the `names` in the request. Format: `documents/{uri_without_scheme}` Example: `documents/docs.cloud.google.com/storage/docs/creating-buckets`","items":{"type":"string"},"type":"array"}},"required":["names"],"type":"object"},"name":"batch_get_documents","outputSchema":{"$defs":{"Document":{"description":"A Document represents a piece of content from the Developer Knowledge corpus.","properties":{"content":{"description":"Output only. The content of the document in Markdown format. If this document is returned by search_documents, this field contains a snippet of text relevant to the search query. If this document is returned by get_document or batch_get_documents, this field contains the full document content.","readOnly":true,"type":"string"},"description":{"description":"Output only. A description of the document.","readOnly":true,"type":"string"},"name":{"description":"Identifier. The resource name of the document. Format: `documents/{uri_without_scheme}` Example: `documents/docs.cloud.google.com/storage/docs/creating-buckets`","type":"string","x-google-identifier":true},"uri":{"description":"Output only. The URI of the content, such as `https://cloud.google.com/storage/docs/creating-buckets`.","readOnly":true,"type":"string"}},"type":"object"}},"description":"Response schema for batch_get_documents.","properties":{"documents":{"description":"Documents requested.","items":{"$ref":"#/$defs/Document"},"type":"array"}},"type":"object"}}]}} -[debug] [2026-02-25T13:00:13.016Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-02-25T13:35:08.944Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-02-25T13:35:08.946Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-02-25T13:35:08.947Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-02-25T13:35:09.147Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-02-25T13:35:09.148Z] >>> [apiv2][query] POST https://developerknowledge.googleapis.com/mcp [none] -[debug] [2026-02-25T13:35:09.148Z] >>> [apiv2][body] POST https://developerknowledge.googleapis.com/mcp {"method":"tools/list","jsonrpc":"2.0","id":1} -[debug] [2026-02-25T13:35:09.153Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-02-25T13:35:09.154Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-02-25T13:35:09.674Z] <<< [apiv2][status] POST https://developerknowledge.googleapis.com/mcp 200 -[debug] [2026-02-25T13:35:09.674Z] <<< [apiv2][body] POST https://developerknowledge.googleapis.com/mcp {"id":1,"jsonrpc":"2.0","result":{"tools":[{"annotations":{"destructiveHint":false,"idempotentHint":true,"openWorldHint":false,"readOnlyHint":true},"description":"Use this tool to find documentation about Google developer products.\nThe documents contain official APIs, code snippets, release notes, best\npractices, guides, debugging info, and more. It covers the following\nproducts and domains:\n\n* Android: developer.android.com\n* Apigee: docs.apigee.com\n* Chrome: developer.chrome.com\n* Firebase: firebase.google.com\n* Fuchsia: fuchsia.dev\n* Google AI: ai.google.dev\n* Google Cloud: docs.cloud.google.com\n* Google Developers, Ads, Search, Google Maps, Youtube: developers.google.com\n* Google Home: developers.home.google.com\n* TensorFlow: www.tensorflow.org\n* Web: web.dev\n\nThis tool returns chunks of text, names, and URLs for matching documents.\nIf the returned chunks are not detailed enough to answer the\nuser's question, use `get_document` or `batch_get_documents` with the\n`parent` from this tool's output to retrieve the full document\ncontent.","inputSchema":{"description":"Request schema for search_documents. Use the query field to search for related Google developer documentation.","properties":{"query":{"description":"Required. The raw query string provided by the user, such as \"How to create a Cloud Storage bucket?\".","type":"string"}},"required":["query"],"type":"object"},"name":"search_documents","outputSchema":{"$defs":{"DocumentChunk":{"description":"A DocumentChunk represents a piece of content from a Document in the DeveloperKnowledge corpus. To fetch the entire document content, pass the `parent` to get_document or batch_get_documents.","properties":{"content":{"description":"Output only. The content of the document chunk.","readOnly":true,"type":"string"},"id":{"description":"Output only. The ID of this chunk within the document. The chunk ID is unique within a document, but not globally unique across documents. The chunk ID is not stable and may change over time.","readOnly":true,"type":"string"},"parent":{"description":"Output only. The resource name of the document this chunk is from. Format: `documents/{uri_without_scheme}` Example: `documents/docs.cloud.google.com/storage/docs/creating-buckets`","readOnly":true,"type":"string"}},"type":"object"}},"description":"Response schema for search_documents.","properties":{"results":{"description":"The search results for the given query. Each Document in this list contains a snippet of content relevant to the search query. Use the Document.name field of each result with get_document or batch_get_documents to retrieve the full document content.","items":{"$ref":"#/$defs/DocumentChunk"},"type":"array"}},"type":"object"}},{"annotations":{"destructiveHint":false,"idempotentHint":true,"openWorldHint":false,"readOnlyHint":true},"description":"Use this tool to retrieve the full content of a single document. The\ndocument name should be obtained from the `parent` field of results from a\ncall to the `search_documents` tool. If you need to retrieve multiple\ndocuments, use `batch_get_documents` instead.","inputSchema":{"description":"Request schema for get_document.","properties":{"name":{"description":"Required. The name of the document to retrieve. Format: `documents/{uri_without_scheme}` Example: `documents/docs.cloud.google.com/storage/docs/creating-buckets`","type":"string"}},"required":["name"],"type":"object"},"name":"get_document","outputSchema":{"description":"A Document represents a piece of content from the Developer Knowledge corpus.","properties":{"content":{"description":"Output only. The content of the document in Markdown format. If this document is returned by search_documents, this field contains a snippet of text relevant to the search query. If this document is returned by get_document or batch_get_documents, this field contains the full document content.","readOnly":true,"type":"string"},"description":{"description":"Output only. A description of the document.","readOnly":true,"type":"string"},"name":{"description":"Identifier. The resource name of the document. Format: `documents/{uri_without_scheme}` Example: `documents/docs.cloud.google.com/storage/docs/creating-buckets`","type":"string","x-google-identifier":true},"uri":{"description":"Output only. The URI of the content, such as `https://cloud.google.com/storage/docs/creating-buckets`.","readOnly":true,"type":"string"}},"type":"object"}},{"annotations":{"destructiveHint":false,"idempotentHint":true,"openWorldHint":false,"readOnlyHint":true},"description":"Use this tool to retrieve the full content of up to 20 documents in a\nsingle call. The document names should be obtained from the `parent` field\nof results from a call to the `search_documents` tool. Use this tool\ninstead of calling `get_document` multiple times to fetch multiple\ndocuments.","inputSchema":{"description":"Request schema for batch_get_documents.","properties":{"names":{"description":"Required. The names of the documents to retrieve, as returned by search_documents. A maximum of 20 documents can be retrieved in a batch. The documents are returned in the same order as the `names` in the request. Format: `documents/{uri_without_scheme}` Example: `documents/docs.cloud.google.com/storage/docs/creating-buckets`","items":{"type":"string"},"type":"array"}},"required":["names"],"type":"object"},"name":"batch_get_documents","outputSchema":{"$defs":{"Document":{"description":"A Document represents a piece of content from the Developer Knowledge corpus.","properties":{"content":{"description":"Output only. The content of the document in Markdown format. If this document is returned by search_documents, this field contains a snippet of text relevant to the search query. If this document is returned by get_document or batch_get_documents, this field contains the full document content.","readOnly":true,"type":"string"},"description":{"description":"Output only. A description of the document.","readOnly":true,"type":"string"},"name":{"description":"Identifier. The resource name of the document. Format: `documents/{uri_without_scheme}` Example: `documents/docs.cloud.google.com/storage/docs/creating-buckets`","type":"string","x-google-identifier":true},"uri":{"description":"Output only. The URI of the content, such as `https://cloud.google.com/storage/docs/creating-buckets`.","readOnly":true,"type":"string"}},"type":"object"}},"description":"Response schema for batch_get_documents.","properties":{"documents":{"description":"Documents requested.","items":{"$ref":"#/$defs/Document"},"type":"array"}},"type":"object"}}]}} -[debug] [2026-02-25T13:35:09.676Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-03-14T19:58:52.712Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-03-14T19:58:52.713Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-03-14T19:58:52.714Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-03-14T19:58:52.813Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-03-14T19:58:52.814Z] >>> [apiv2][query] POST https://developerknowledge.googleapis.com/mcp [none] -[debug] [2026-03-14T19:58:52.814Z] >>> [apiv2][body] POST https://developerknowledge.googleapis.com/mcp {"method":"tools/list","jsonrpc":"2.0","id":1} -[debug] [2026-03-14T19:58:52.819Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-03-14T19:58:52.819Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] -[debug] [2026-03-14T19:58:53.038Z] <<< [apiv2][status] POST https://developerknowledge.googleapis.com/mcp 200 -[debug] [2026-03-14T19:58:53.038Z] <<< [apiv2][body] POST https://developerknowledge.googleapis.com/mcp {"id":1,"jsonrpc":"2.0","result":{"tools":[{"annotations":{"destructiveHint":false,"idempotentHint":true,"openWorldHint":false,"readOnlyHint":true},"description":"Use this tool to find documentation about Google developer products. The documents contain official APIs, code snippets, release notes, best practices, guides, debugging info, and more. It covers the following products and domains:\n\n* Android: developer.android.com\n* Apigee: docs.apigee.com\n* Chrome: developer.chrome.com\n* Firebase: firebase.google.com\n* Fuchsia: fuchsia.dev\n* Google AI: ai.google.dev\n* Google Cloud: docs.cloud.google.com\n* Google Developers, Ads, Search, Google Maps, Youtube: developers.google.com\n* Google Home: developers.home.google.com\n* TensorFlow: www.tensorflow.org\n* Web: web.dev\n\nThis tool returns chunks of text, names, and URLs for matching documents. If the returned chunks are not detailed enough to answer the user's question, use `get_documents` with the `parent` from this tool's output to retrieve the full document content.","inputSchema":{"description":"Request schema for search_documents. Use the query field to search for related Google developer documentation.","properties":{"query":{"description":"Required. The raw query string provided by the user, such as \"How to create a Cloud Storage bucket?\".","type":"string"}},"required":["query"],"type":"object"},"name":"search_documents","outputSchema":{"$defs":{"DocumentChunk":{"description":"A DocumentChunk represents a piece of content from a Document in the DeveloperKnowledge corpus. To fetch the entire document content, pass the `parent` to get_document or batch_get_documents.","properties":{"content":{"description":"Output only. The content of the document chunk.","readOnly":true,"type":"string"},"id":{"description":"Output only. The ID of this chunk within the document. The chunk ID is unique within a document, but not globally unique across documents. The chunk ID is not stable and may change over time.","readOnly":true,"type":"string"},"parent":{"description":"Output only. The resource name of the document this chunk is from. Format: `documents/{uri_without_scheme}` Example: `documents/docs.cloud.google.com/storage/docs/creating-buckets`","readOnly":true,"type":"string"}},"type":"object"}},"description":"Response schema for search_documents.","properties":{"results":{"description":"The search results for the given query. Each Document in this list contains a snippet of content relevant to the search query. Use the DocumentChunk.name field of each result with get_documents to retrieve the full document content.","items":{"$ref":"#/$defs/DocumentChunk"},"type":"array"}},"type":"object"}},{"annotations":{"destructiveHint":false,"idempotentHint":true,"openWorldHint":false,"readOnlyHint":true},"description":"Use this tool to retrieve the full content of a single document or up to 20 documents in a single call. The document names should be obtained from the `parent` field of results from a call to the `search_documents` tool. Set the `names` parameter to a list of document names.","inputSchema":{"description":"Request schema for get_documents.","properties":{"names":{"description":"Required. The names of the documents to retrieve, as returned by search_documents. A maximum of 20 documents can be retrieved in one call. The documents are returned in the same order as the `names` in the request. Format: `documents/{uri_without_scheme}` Example: `documents/docs.cloud.google.com/storage/docs/creating-buckets`","items":{"type":"string"},"type":"array"}},"required":["names"],"type":"object"},"name":"get_documents","outputSchema":{"$defs":{"Document":{"description":"A Document represents a piece of content from the Developer Knowledge corpus.","properties":{"content":{"description":"Output only. The content of the document in Markdown format.","readOnly":true,"type":"string"},"description":{"description":"Output only. A description of the document.","readOnly":true,"type":"string"},"name":{"description":"Identifier. The resource name of the document. Format: `documents/{uri_without_scheme}` Example: `documents/docs.cloud.google.com/storage/docs/creating-buckets`","type":"string","x-google-identifier":true},"uri":{"description":"Output only. The URI of the content, such as `https://cloud.google.com/storage/docs/creating-buckets`.","readOnly":true,"type":"string"}},"type":"object"}},"description":"Response schema for get_documents.","properties":{"documents":{"description":"Documents requested.","items":{"$ref":"#/$defs/Document"},"type":"array"}},"type":"object"}}]}} -[debug] [2026-03-14T19:58:53.039Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] diff --git a/first-clear-d-rank.png b/first-clear-d-rank.png deleted file mode 100644 index a232a4b..0000000 Binary files a/first-clear-d-rank.png and /dev/null differ diff --git a/game-auto-running.png b/game-auto-running.png deleted file mode 100644 index c9edeae..0000000 Binary files a/game-auto-running.png and /dev/null differ diff --git a/game-auto-start.png b/game-auto-start.png deleted file mode 100644 index e380a20..0000000 Binary files a/game-auto-start.png and /dev/null differ diff --git a/game-combat-active.png b/game-combat-active.png deleted file mode 100644 index 15d7191..0000000 Binary files a/game-combat-active.png and /dev/null differ diff --git a/game-combat-tick0.png b/game-combat-tick0.png deleted file mode 100644 index 577d58a..0000000 Binary files a/game-combat-tick0.png and /dev/null differ diff --git a/game-combat-tick1.png b/game-combat-tick1.png deleted file mode 100644 index 202587a..0000000 Binary files a/game-combat-tick1.png and /dev/null differ diff --git a/game-combat-tick2.png b/game-combat-tick2.png deleted file mode 100644 index dc08c39..0000000 Binary files a/game-combat-tick2.png and /dev/null differ diff --git a/game-combat-tick3.png b/game-combat-tick3.png deleted file mode 100644 index dc08c39..0000000 Binary files a/game-combat-tick3.png and /dev/null differ diff --git a/game-combat.png b/game-combat.png deleted file mode 100644 index 9d2c9ec..0000000 Binary files a/game-combat.png and /dev/null differ diff --git a/game-desktop-clean.png b/game-desktop-clean.png deleted file mode 100644 index da6240c..0000000 Binary files a/game-desktop-clean.png and /dev/null differ diff --git a/game-desktop.png b/game-desktop.png deleted file mode 100644 index 0b02564..0000000 Binary files a/game-desktop.png and /dev/null differ diff --git a/game-initial.png b/game-initial.png deleted file mode 100644 index 111ad90..0000000 Binary files a/game-initial.png and /dev/null differ diff --git a/game-log.png b/game-log.png deleted file mode 100644 index ddc7da2..0000000 Binary files a/game-log.png and /dev/null differ diff --git a/game-lore.png b/game-lore.png deleted file mode 100644 index f5175ed..0000000 Binary files a/game-lore.png and /dev/null differ diff --git a/game-manage.png b/game-manage.png deleted file mode 100644 index 266068f..0000000 Binary files a/game-manage.png and /dev/null differ diff --git a/game-shop.png b/game-shop.png deleted file mode 100644 index dca954d..0000000 Binary files a/game-shop.png and /dev/null differ diff --git a/game-spirits.png b/game-spirits.png deleted file mode 100644 index 936aeff..0000000 Binary files a/game-spirits.png and /dev/null differ diff --git a/game-srank-tick0.png b/game-srank-tick0.png deleted file mode 100644 index 4662c82..0000000 Binary files a/game-srank-tick0.png and /dev/null differ diff --git a/game-srank-tick1.png b/game-srank-tick1.png deleted file mode 100644 index 0c5b2c7..0000000 Binary files a/game-srank-tick1.png and /dev/null differ diff --git a/game-srank-tick2.png b/game-srank-tick2.png deleted file mode 100644 index 5f2d11d..0000000 Binary files a/game-srank-tick2.png and /dev/null differ diff --git a/game-srank-tick3.png b/game-srank-tick3.png deleted file mode 100644 index 60e537e..0000000 Binary files a/game-srank-tick3.png and /dev/null differ diff --git a/game-srank-tick4.png b/game-srank-tick4.png deleted file mode 100644 index 4829673..0000000 Binary files a/game-srank-tick4.png and /dev/null differ diff --git a/game-training.png b/game-training.png deleted file mode 100644 index 69e25e1..0000000 Binary files a/game-training.png and /dev/null differ diff --git a/generated-icon.png b/generated-icon.png deleted file mode 100644 index 5ab99b6..0000000 Binary files a/generated-icon.png and /dev/null differ diff --git a/hunterpath-test.png b/hunterpath-test.png deleted file mode 100644 index 574ff03..0000000 Binary files a/hunterpath-test.png and /dev/null differ diff --git a/sprites-test.png b/sprites-test.png deleted file mode 100644 index 7eea600..0000000 Binary files a/sprites-test.png and /dev/null differ diff --git a/test-auto-dungeon-running.png b/test-auto-dungeon-running.png deleted file mode 100644 index 399a4a9..0000000 Binary files a/test-auto-dungeon-running.png and /dev/null differ diff --git a/test-auto-dungeon.png b/test-auto-dungeon.png deleted file mode 100644 index f68ec9e..0000000 Binary files a/test-auto-dungeon.png and /dev/null differ diff --git a/test-auto-on.png b/test-auto-on.png deleted file mode 100644 index 7cd10a7..0000000 Binary files a/test-auto-on.png and /dev/null differ diff --git a/test-boss-name.png b/test-boss-name.png deleted file mode 100644 index 566c752..0000000 Binary files a/test-boss-name.png and /dev/null differ diff --git a/test-bulk-stats.png b/test-bulk-stats.png deleted file mode 100644 index d2a485a..0000000 Binary files a/test-bulk-stats.png and /dev/null differ diff --git a/test-combat-active.png b/test-combat-active.png deleted file mode 100644 index 545eb5e..0000000 Binary files a/test-combat-active.png and /dev/null differ diff --git a/test-combat-log.png b/test-combat-log.png deleted file mode 100644 index 43c2ea1..0000000 Binary files a/test-combat-log.png and /dev/null differ diff --git a/test-crash-check.png b/test-crash-check.png deleted file mode 100644 index 30ede76..0000000 Binary files a/test-crash-check.png and /dev/null differ diff --git a/test-debug-panel.png b/test-debug-panel.png deleted file mode 100644 index d8c79c7..0000000 Binary files a/test-debug-panel.png and /dev/null differ diff --git a/test-full-features.png b/test-full-features.png deleted file mode 100644 index 8a0f401..0000000 Binary files a/test-full-features.png and /dev/null differ diff --git a/test-gate-cards-2.png b/test-gate-cards-2.png deleted file mode 100644 index 87a4beb..0000000 Binary files a/test-gate-cards-2.png and /dev/null differ diff --git a/test-gate-cards.png b/test-gate-cards.png deleted file mode 100644 index 1abda1c..0000000 Binary files a/test-gate-cards.png and /dev/null differ diff --git a/test-ghpages-combat-victory.png b/test-ghpages-combat-victory.png deleted file mode 100644 index d1dcaad..0000000 Binary files a/test-ghpages-combat-victory.png and /dev/null differ diff --git a/test-ghpages-live.png b/test-ghpages-live.png deleted file mode 100644 index 6f3dd38..0000000 Binary files a/test-ghpages-live.png and /dev/null differ diff --git a/test-initial-load.png b/test-initial-load.png deleted file mode 100644 index 3780ee6..0000000 Binary files a/test-initial-load.png and /dev/null differ diff --git a/test-lore-entries.png b/test-lore-entries.png deleted file mode 100644 index 5848348..0000000 Binary files a/test-lore-entries.png and /dev/null differ diff --git a/test-post-victory-heal.png b/test-post-victory-heal.png deleted file mode 100644 index ee1f231..0000000 Binary files a/test-post-victory-heal.png and /dev/null differ diff --git a/test-rebirth-button.png b/test-rebirth-button.png deleted file mode 100644 index b46b48b..0000000 Binary files a/test-rebirth-button.png and /dev/null differ diff --git a/test-round3-arank.png b/test-round3-arank.png deleted file mode 100644 index cd224b2..0000000 Binary files a/test-round3-arank.png and /dev/null differ diff --git a/test-round3-auto-nodebug.png b/test-round3-auto-nodebug.png deleted file mode 100644 index 350684d..0000000 Binary files a/test-round3-auto-nodebug.png and /dev/null differ diff --git a/test-round3-auto-progress.png b/test-round3-auto-progress.png deleted file mode 100644 index 9347af3..0000000 Binary files a/test-round3-auto-progress.png and /dev/null differ diff --git a/test-round3-auto.png b/test-round3-auto.png deleted file mode 100644 index bf714d5..0000000 Binary files a/test-round3-auto.png and /dev/null differ diff --git a/test-round3-auto2.png b/test-round3-auto2.png deleted file mode 100644 index 4a37da2..0000000 Binary files a/test-round3-auto2.png and /dev/null differ diff --git a/test-round3-auto3.png b/test-round3-auto3.png deleted file mode 100644 index 42d2b48..0000000 Binary files a/test-round3-auto3.png and /dev/null differ diff --git a/test-round3-auto4.png b/test-round3-auto4.png deleted file mode 100644 index 4cac9bd..0000000 Binary files a/test-round3-auto4.png and /dev/null differ diff --git a/test-round3-brank-result.png b/test-round3-brank-result.png deleted file mode 100644 index 2dffbdc..0000000 Binary files a/test-round3-brank-result.png and /dev/null differ diff --git a/test-round3-combat.png b/test-round3-combat.png deleted file mode 100644 index 6796903..0000000 Binary files a/test-round3-combat.png and /dev/null differ diff --git a/test-round3-final-spirits.png b/test-round3-final-spirits.png deleted file mode 100644 index e80d330..0000000 Binary files a/test-round3-final-spirits.png and /dev/null differ diff --git a/test-round3-hptext.png b/test-round3-hptext.png deleted file mode 100644 index 4f6fcde..0000000 Binary files a/test-round3-hptext.png and /dev/null differ diff --git a/test-round3-initial.png b/test-round3-initial.png deleted file mode 100644 index 15964ff..0000000 Binary files a/test-round3-initial.png and /dev/null differ diff --git a/test-round3-spirits.png b/test-round3-spirits.png deleted file mode 100644 index e83acf4..0000000 Binary files a/test-round3-spirits.png and /dev/null differ diff --git a/test-rounded-pwr.png b/test-rounded-pwr.png deleted file mode 100644 index e165883..0000000 Binary files a/test-rounded-pwr.png and /dev/null differ diff --git a/test-thematic-gates.png b/test-thematic-gates.png deleted file mode 100644 index 27b8cb4..0000000 Binary files a/test-thematic-gates.png and /dev/null differ diff --git a/test-victory-screen-2.png b/test-victory-screen-2.png deleted file mode 100644 index 1b966d7..0000000 Binary files a/test-victory-screen-2.png and /dev/null differ diff --git a/test-victory-screen.png b/test-victory-screen.png deleted file mode 100644 index 63ad315..0000000 Binary files a/test-victory-screen.png and /dev/null differ