Repository: ObsidianIRC/ObsidianIRC
Pull request #23: Home screen
Author: login: ValwareIRC
Created: 2025-05-13T13:22:20Z | Merged: 2025-05-18T14:25:08Z

This creates a homescreen where if you click on a server it'll open the "add server" modal with the details prefilled.

This needs to work by reading a json file where people can edit, so there will be a repository where people can add their own servers by making a pull request.


Diff:
diff --git a/package-lock.json b/package-lock.json
index 73d8d339..d589233f 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -30,6 +30,7 @@
         "@testing-library/jest-dom": "^6.6.3",
         "@testing-library/react": "^16.3.0",
         "@testing-library/user-event": "^14.6.1",
+        "@types/node": "^22.15.18",
         "@types/react": "^18.3.18",
         "@types/react-dom": "^18.3.5",
         "@typescript-eslint/parser": "^8.20.0",
@@ -82,9 +83,9 @@
       }
     },
     "node_modules/@asamuzakjp/css-color": {
-      "version": "3.1.3",
-      "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-3.1.3.tgz",
-      "integrity": "sha512-u25AyjuNrRFGb1O7KmWEu0ExN6iJMlUmDSlOPW/11JF8khOrIGG6oCoYpC+4mZlthNVhFUahk68lNrNI91f6Yg==",
+      "version": "3.1.7",
+      "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-3.1.7.tgz",
+      "integrity": "sha512-Ok5fYhtwdyJQmU1PpEv6Si7Y+A4cYb8yNM9oiIJC9TzXPMuN9fvdonKJqcnz9TbFqV6bQ8z0giRq0iaOpGZV2g==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
@@ -103,24 +104,24 @@
       "license": "ISC"
     },
     "node_modules/@babel/code-frame": {
-      "version": "7.26.2",
-      "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz",
-      "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==",
+      "version": "7.27.1",
+      "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz",
+      "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
-        "@babel/helper-validator-identifier": "^7.25.9",
+        "@babel/helper-validator-identifier": "^7.27.1",
         "js-tokens": "^4.0.0",
-        "picocolors": "^1.0.0"
+        "picocolors": "^1.1.1"
       },
       "engines": {
         "node": ">=6.9.0"
       }
     },
     "node_modules/@babel/compat-data": {
-      "version": "7.26.8",
-      "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.8.tgz",
-      "integrity": "sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==",
+      "version": "7.27.2",
+      "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.27.2.tgz",
+      "integrity": "sha512-TUtMJYRPyUb/9aU8f3K0mjmjf6M9N5Woshn2CS6nqJSeJtTtQcpLUXjGt9vbF8ZGff0El99sWkLgzwW3VXnxZQ==",
       "dev": true,
       "license": "MIT",
       "engines": {
@@ -128,22 +129,22 @@
       }
     },
     "node_modules/@babel/core": {
-      "version": "7.26.10",
-      "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.10.tgz",
-      "integrity": "sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==",
+      "version": "7.27.1",
+      "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.27.1.tgz",
+      "integrity": "sha512-IaaGWsQqfsQWVLqMn9OB92MNN7zukfVA4s7KKAI0KfrrDsZ0yhi5uV4baBuLuN7n3vsZpwP8asPPcVwApxvjBQ==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
         "@ampproject/remapping": "^2.2.0",
-        "@babel/code-frame": "^7.26.2",
-        "@babel/generator": "^7.26.10",
-        "@babel/helper-compilation-targets": "^7.26.5",
-        "@babel/helper-module-transforms": "^7.26.0",
-        "@babel/helpers": "^7.26.10",
-        "@babel/parser": "^7.26.10",
-        "@babel/template": "^7.26.9",
-        "@babel/traverse": "^7.26.10",
-        "@babel/types": "^7.26.10",
+        "@babel/code-frame": "^7.27.1",
+        "@babel/generator": "^7.27.1",
+        "@babel/helper-compilation-targets": "^7.27.1",
+        "@babel/helper-module-transforms": "^7.27.1",
+        "@babel/helpers": "^7.27.1",
+        "@babel/parser": "^7.27.1",
+        "@babel/template": "^7.27.1",
+        "@babel/traverse": "^7.27.1",
+        "@babel/types": "^7.27.1",
         "convert-source-map": "^2.0.0",
         "debug": "^4.1.0",
         "gensync": "^1.0.0-beta.2",
@@ -169,14 +170,14 @@
       }
     },
     "node_modules/@babel/generator": {
-      "version": "7.27.0",
-      "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.0.tgz",
-      "integrity": "sha512-VybsKvpiN1gU1sdMZIp7FcqphVVKEwcuj02x73uvcHE0PTihx1nlBcowYWhDwjpoAXRv43+gDzyggGnn1XZhVw==",
+      "version": "7.27.1",
+      "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.1.tgz",
+      "integrity": "sha512-UnJfnIpc/+JO0/+KRVQNGU+y5taA5vCbwN8+azkX6beii/ZF+enZJSOKo11ZSzGJjlNfJHfQtmQT8H+9TXPG2w==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
-        "@babel/parser": "^7.27.0",
-        "@babel/types": "^7.27.0",
+        "@babel/parser": "^7.27.1",
+        "@babel/types": "^7.27.1",
         "@jridgewell/gen-mapping": "^0.3.5",
         "@jridgewell/trace-mapping": "^0.3.25",
         "jsesc": "^3.0.2"
@@ -186,14 +187,14 @@
       }
     },
     "node_modules/@babel/helper-compilation-targets": {
-      "version": "7.27.0",
-      "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.0.tgz",
-      "integrity": "sha512-LVk7fbXml0H2xH34dFzKQ7TDZ2G4/rVTOrq9V+icbbadjbVxxeFeDsNHv2SrZeWoA+6ZiTyWYWtScEIW07EAcA==",
+      "version": "7.27.2",
+      "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz",
+      "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
-        "@babel/compat-data": "^7.26.8",
-        "@babel/helper-validator-option": "^7.25.9",
+        "@babel/compat-data": "^7.27.2",
+        "@babel/helper-validator-option": "^7.27.1",
         "browserslist": "^4.24.0",
         "lru-cache": "^5.1.1",
         "semver": "^6.3.1"
@@ -213,29 +214,29 @@
       }
     },
     "node_modules/@babel/helper-module-imports": {
-      "version": "7.25.9",
-      "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz",
-      "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==",
+      "version": "7.27.1",
+      "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz",
+      "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
-        "@babel/traverse": "^7.25.9",
-        "@babel/types": "^7.25.9"
+        "@babel/traverse": "^7.27.1",
+        "@babel/types": "^7.27.1"
       },
       "engines": {
         "node": ">=6.9.0"
       }
     },
     "node_modules/@babel/helper-module-transforms": {
-      "version": "7.26.0",
-      "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz",
-      "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==",
+      "version": "7.27.1",
+      "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.27.1.tgz",
+      "integrity": "sha512-9yHn519/8KvTU5BjTVEEeIM3w9/2yXNKoD82JifINImhpKkARMJKPP59kLo+BafpdN5zgNeIcS4jsGDmd3l58g==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
-        "@babel/helper-module-imports": "^7.25.9",
-        "@babel/helper-validator-identifier": "^7.25.9",
-        "@babel/traverse": "^7.25.9"
+        "@babel/helper-module-imports": "^7.27.1",
+        "@babel/helper-validator-identifier": "^7.27.1",
+        "@babel/traverse": "^7.27.1"
       },
       "engines": {
         "node": ">=6.9.0"
@@ -245,9 +246,9 @@
       }
     },
     "node_modules/@babel/helper-plugin-utils": {
-      "version": "7.26.5",
-      "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz",
-      "integrity": "sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==",
+      "version": "7.27.1",
+      "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz",
+      "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==",
       "dev": true,
       "license": "MIT",
       "engines": {
@@ -255,9 +256,9 @@
       }
     },
     "node_modules/@babel/helper-string-parser": {
-      "version": "7.25.9",
-      "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz",
-      "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==",
+      "version": "7.27.1",
+      "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
+      "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
       "dev": true,
       "license": "MIT",
       "engines": {
@@ -265,9 +266,9 @@
       }
     },
     "node_modules/@babel/helper-validator-identifier": {
-      "version": "7.25.9",
-      "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz",
-      "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==",
+      "version": "7.27.1",
+      "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz",
+      "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==",
       "dev": true,
       "license": "MIT",
       "engines": {
@@ -275,9 +276,9 @@
       }
     },
     "node_modules/@babel/helper-validator-option": {
-      "version": "7.25.9",
-      "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz",
-      "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==",
+      "version": "7.27.1",
+      "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz",
+      "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==",
       "dev": true,
       "license": "MIT",
       "engines": {
@@ -285,27 +286,27 @@
       }
     },
     "node_modules/@babel/helpers": {
-      "version": "7.27.0",
-      "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.0.tgz",
-      "integrity": "sha512-U5eyP/CTFPuNE3qk+WZMxFkp/4zUzdceQlfzf7DdGdhp+Fezd7HD+i8Y24ZuTMKX3wQBld449jijbGq6OdGNQg==",
+      "version": "7.27.1",
+      "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.1.tgz",
+      "integrity": "sha512-FCvFTm0sWV8Fxhpp2McP5/W53GPllQ9QeQ7SiqGWjMf/LVG07lFa5+pgK05IRhVwtvafT22KF+ZSnM9I545CvQ==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
-        "@babel/template": "^7.27.0",
-        "@babel/types": "^7.27.0"
+        "@babel/template": "^7.27.1",
+        "@babel/types": "^7.27.1"
       },
       "engines": {
         "node": ">=6.9.0"
       }
     },
     "node_modules/@babel/parser": {
-      "version": "7.27.0",
-      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.0.tgz",
-      "integrity": "sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg==",
+      "version": "7.27.2",
+      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.2.tgz",
+      "integrity": "sha512-QYLs8299NA7WM/bZAdp+CviYYkVoYXlDW2rzliy3chxd1PQjej7JORuMJDJXJUb9g0TT+B99EwaVLKmX+sPXWw==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
-        "@babel/types": "^7.27.0"
+        "@babel/types": "^7.27.1"
       },
       "bin": {
         "parser": "bin/babel-parser.js"
@@ -315,13 +316,13 @@
       }
     },
     "node_modules/@babel/plugin-transform-react-jsx-self": {
-      "version": "7.25.9",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.25.9.tgz",
-      "integrity": "sha512-y8quW6p0WHkEhmErnfe58r7x0A70uKphQm8Sp8cV7tjNQwK56sNVK0M73LK3WuYmsuyrftut4xAkjjgU0twaMg==",
+      "version": "7.27.1",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz",
+      "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
-        "@babel/helper-plugin-utils": "^7.25.9"
+        "@babel/helper-plugin-utils": "^7.27.1"
       },
       "engines": {
         "node": ">=6.9.0"
@@ -331,13 +332,13 @@
       }
     },
     "node_modules/@babel/plugin-transform-react-jsx-source": {
-      "version": "7.25.9",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.25.9.tgz",
-      "integrity": "sha512-+iqjT8xmXhhYv4/uiYd8FNQsraMFZIfxVSqxxVSZP0WbbSAWvBXAul0m/zu+7Vv4O/3WtApy9pmaTMiumEZgfg==",
+      "version": "7.27.1",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz",
+      "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
-        "@babel/helper-plugin-utils": "^7.25.9"
+        "@babel/helper-plugin-utils": "^7.27.1"
       },
       "engines": {
         "node": ">=6.9.0"
@@ -347,45 +348,42 @@
       }
     },
     "node_modules/@babel/runtime": {
-      "version": "7.27.0",
-      "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.0.tgz",
-      "integrity": "sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw==",
+      "version": "7.27.1",
+      "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.1.tgz",
+      "integrity": "sha512-1x3D2xEk2fRo3PAhwQwu5UubzgiVWSXTBfWpVd2Mx2AzRqJuDJCsgaDVZ7HB5iGzDW1Hl1sWN2mFyKjmR9uAog==",
       "dev": true,
       "license": "MIT",
-      "dependencies": {
-        "regenerator-runtime": "^0.14.0"
-      },
       "engines": {
         "node": ">=6.9.0"
       }
     },
     "node_modules/@babel/template": {
-      "version": "7.27.0",
-      "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.0.tgz",
-      "integrity": "sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA==",
+      "version": "7.27.2",
+      "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz",
+      "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
-        "@babel/code-frame": "^7.26.2",
-        "@babel/parser": "^7.27.0",
-        "@babel/types": "^7.27.0"
+        "@babel/code-frame": "^7.27.1",
+        "@babel/parser": "^7.27.2",
+        "@babel/types": "^7.27.1"
       },
       "engines": {
         "node": ">=6.9.0"
       }
     },
     "node_modules/@babel/traverse": {
-      "version": "7.27.0",
-      "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.0.tgz",
-      "integrity": "sha512-19lYZFzYVQkkHkl4Cy4WrAVcqBkgvV2YM2TU3xG6DIwO7O3ecbDPfW3yM3bjAGcqcQHi+CCtjMR3dIEHxsd6bA==",
+      "version": "7.27.1",
+      "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.1.tgz",
+      "integrity": "sha512-ZCYtZciz1IWJB4U61UPu4KEaqyfj+r5T1Q5mqPo+IBpcG9kHv30Z0aD8LXPgC1trYa6rK0orRyAhqUgk4MjmEg==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
-        "@babel/code-frame": "^7.26.2",
-        "@babel/generator": "^7.27.0",
-        "@babel/parser": "^7.27.0",
-        "@babel/template": "^7.27.0",
-        "@babel/types": "^7.27.0",
+        "@babel/code-frame": "^7.27.1",
+        "@babel/generator": "^7.27.1",
+        "@babel/parser": "^7.27.1",
+        "@babel/template": "^7.27.1",
+        "@babel/types": "^7.27.1",
         "debug": "^4.3.1",
         "globals": "^11.1.0"
       },
@@ -404,14 +402,14 @@
       }
     },
     "node_modules/@babel/types": {
-      "version": "7.27.0",
-      "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.0.tgz",
-      "integrity": "sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==",
+      "version": "7.27.1",
+      "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.1.tgz",
+      "integrity": "sha512-+EzkxvLNfiUeKMgy/3luqfsCWFRXLb7U6wNQTk60tovuckwB15B191tJWvpp4HjiQWdJkCxO3Wbvc6jlk3Xb2Q==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
-        "@babel/helper-string-parser": "^7.25.9",
-        "@babel/helper-validator-identifier": "^7.25.9"
+        "@babel/helper-string-parser": "^7.27.1",
+        "@babel/helper-validator-identifier": "^7.27.1"
       },
       "engines": {
         "node": ">=6.9.0"
@@ -697,9 +695,9 @@
       }
     },
     "node_modules/@esbuild/aix-ppc64": {
-      "version": "0.25.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.2.tgz",
-      "integrity": "sha512-wCIboOL2yXZym2cgm6mlA742s9QeJ8DjGVaL39dLN4rRwrOgOyYSnOaFPhKZGLb2ngj4EyfAFjsNJwPXZvseag==",
+      "version": "0.25.4",
+      "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.4.tgz",
+      "integrity": "sha512-1VCICWypeQKhVbE9oW/sJaAmjLxhVqacdkvPLEjwlttjfwENRSClS8EjBz0KzRyFSCPDIkuXW34Je/vk7zdB7Q==",
       "cpu": [
         "ppc64"
       ],
@@ -714,9 +712,9 @@
       }
     },
     "node_modules/@esbuild/android-arm": {
-      "version": "0.25.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.2.tgz",
-      "integrity": "sha512-NQhH7jFstVY5x8CKbcfa166GoV0EFkaPkCKBQkdPJFvo5u+nGXLEH/ooniLb3QI8Fk58YAx7nsPLozUWfCBOJA==",
+      "version": "0.25.4",
+      "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.4.tgz",
+      "integrity": "sha512-QNdQEps7DfFwE3hXiU4BZeOV68HHzYwGd0Nthhd3uCkkEKK7/R6MTgM0P7H7FAs5pU/DIWsviMmEGxEoxIZ+ZQ==",
       "cpu": [
         "arm"
       ],
@@ -731,9 +729,9 @@
       }
     },
     "node_modules/@esbuild/android-arm64": {
-      "version": "0.25.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.2.tgz",
-      "integrity": "sha512-5ZAX5xOmTligeBaeNEPnPaeEuah53Id2tX4c2CVP3JaROTH+j4fnfHCkr1PjXMd78hMst+TlkfKcW/DlTq0i4w==",
+      "version": "0.25.4",
+      "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.4.tgz",
+      "integrity": "sha512-bBy69pgfhMGtCnwpC/x5QhfxAz/cBgQ9enbtwjf6V9lnPI/hMyT9iWpR1arm0l3kttTr4L0KSLpKmLp/ilKS9A==",
       "cpu": [
         "arm64"
       ],
@@ -748,9 +746,9 @@
       }
     },
     "node_modules/@esbuild/android-x64": {
-      "version": "0.25.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.2.tgz",
-      "integrity": "sha512-Ffcx+nnma8Sge4jzddPHCZVRvIfQ0kMsUsCMcJRHkGJ1cDmhe4SsrYIjLUKn1xpHZybmOqCWwB0zQvsjdEHtkg==",
+      "version": "0.25.4",
+      "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.4.tgz",
+      "integrity": "sha512-TVhdVtQIFuVpIIR282btcGC2oGQoSfZfmBdTip2anCaVYcqWlZXGcdcKIUklfX2wj0JklNYgz39OBqh2cqXvcQ==",
       "cpu": [
         "x64"
       ],
@@ -765,9 +763,9 @@
       }
     },
     "node_modules/@esbuild/darwin-arm64": {
-      "version": "0.25.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.2.tgz",
-      "integrity": "sha512-MpM6LUVTXAzOvN4KbjzU/q5smzryuoNjlriAIx+06RpecwCkL9JpenNzpKd2YMzLJFOdPqBpuub6eVRP5IgiSA==",
+      "version": "0.25.4",
+      "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.4.tgz",
+      "integrity": "sha512-Y1giCfM4nlHDWEfSckMzeWNdQS31BQGs9/rouw6Ub91tkK79aIMTH3q9xHvzH8d0wDru5Ci0kWB8b3up/nl16g==",
       "cpu": [
         "arm64"
       ],
@@ -782,9 +780,9 @@
       }
     },
     "node_modules/@esbuild/darwin-x64": {
-      "version": "0.25.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.2.tgz",
-      "integrity": "sha512-5eRPrTX7wFyuWe8FqEFPG2cU0+butQQVNcT4sVipqjLYQjjh8a8+vUTfgBKM88ObB85ahsnTwF7PSIt6PG+QkA==",
+      "version": "0.25.4",
+      "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.4.tgz",
+      "integrity": "sha512-CJsry8ZGM5VFVeyUYB3cdKpd/H69PYez4eJh1W/t38vzutdjEjtP7hB6eLKBoOdxcAlCtEYHzQ/PJ/oU9I4u0A==",
       "cpu": [
         "x64"
       ],
@@ -799,9 +797,9 @@
       }
     },
     "node_modules/@esbuild/freebsd-arm64": {
-      "version": "0.25.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.2.tgz",
-      "integrity": "sha512-mLwm4vXKiQ2UTSX4+ImyiPdiHjiZhIaE9QvC7sw0tZ6HoNMjYAqQpGyui5VRIi5sGd+uWq940gdCbY3VLvsO1w==",
+      "version": "0.25.4",
+      "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.4.tgz",
+      "integrity": "sha512-yYq+39NlTRzU2XmoPW4l5Ifpl9fqSk0nAJYM/V/WUGPEFfek1epLHJIkTQM6bBs1swApjO5nWgvr843g6TjxuQ==",
       "cpu": [
         "arm64"
       ],
@@ -816,9 +814,9 @@
       }
     },
     "node_modules/@esbuild/freebsd-x64": {
-      "version": "0.25.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.2.tgz",
-      "integrity": "sha512-6qyyn6TjayJSwGpm8J9QYYGQcRgc90nmfdUb0O7pp1s4lTY+9D0H9O02v5JqGApUyiHOtkz6+1hZNvNtEhbwRQ==",
+      "version": "0.25.4",
+      "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.4.tgz",
+      "integrity": "sha512-0FgvOJ6UUMflsHSPLzdfDnnBBVoCDtBTVyn/MrWloUNvq/5SFmh13l3dvgRPkDihRxb77Y17MbqbCAa2strMQQ==",
       "cpu": [
         "x64"
       ],
@@ -833,9 +831,9 @@
       }
     },
     "node_modules/@esbuild/linux-arm": {
-      "version": "0.25.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.2.tgz",
-      "integrity": "sha512-UHBRgJcmjJv5oeQF8EpTRZs/1knq6loLxTsjc3nxO9eXAPDLcWW55flrMVc97qFPbmZP31ta1AZVUKQzKTzb0g==",
+      "version": "0.25.4",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.4.tgz",
+      "integrity": "sha512-kro4c0P85GMfFYqW4TWOpvmF8rFShbWGnrLqlzp4X1TNWjRY3JMYUfDCtOxPKOIY8B0WC8HN51hGP4I4hz4AaQ==",
       "cpu": [
         "arm"
       ],
@@ -850,9 +848,9 @@
       }
     },
     "node_modules/@esbuild/linux-arm64": {
-      "version": "0.25.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.2.tgz",
-      "integrity": "sha512-gq/sjLsOyMT19I8obBISvhoYiZIAaGF8JpeXu1u8yPv8BE5HlWYobmlsfijFIZ9hIVGYkbdFhEqC0NvM4kNO0g==",
+      "version": "0.25.4",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.4.tgz",
+      "integrity": "sha512-+89UsQTfXdmjIvZS6nUnOOLoXnkUTB9hR5QAeLrQdzOSWZvNSAXAtcRDHWtqAUtAmv7ZM1WPOOeSxDzzzMogiQ==",
       "cpu": [
         "arm64"
       ],
@@ -867,9 +865,9 @@
       }
     },
     "node_modules/@esbuild/linux-ia32": {
-      "version": "0.25.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.2.tgz",
-      "integrity": "sha512-bBYCv9obgW2cBP+2ZWfjYTU+f5cxRoGGQ5SeDbYdFCAZpYWrfjjfYwvUpP8MlKbP0nwZ5gyOU/0aUzZ5HWPuvQ==",
+      "version": "0.25.4",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.4.tgz",
+      "integrity": "sha512-yTEjoapy8UP3rv8dB0ip3AfMpRbyhSN3+hY8mo/i4QXFeDxmiYbEKp3ZRjBKcOP862Ua4b1PDfwlvbuwY7hIGQ==",
       "cpu": [
         "ia32"
       ],
@@ -884,9 +882,9 @@
       }
     },
     "node_modules/@esbuild/linux-loong64": {
-      "version": "0.25.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.2.tgz",
-      "integrity": "sha512-SHNGiKtvnU2dBlM5D8CXRFdd+6etgZ9dXfaPCeJtz+37PIUlixvlIhI23L5khKXs3DIzAn9V8v+qb1TRKrgT5w==",
+      "version": "0.25.4",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.4.tgz",
+      "integrity": "sha512-NeqqYkrcGzFwi6CGRGNMOjWGGSYOpqwCjS9fvaUlX5s3zwOtn1qwg1s2iE2svBe4Q/YOG1q6875lcAoQK/F4VA==",
       "cpu": [
         "loong64"
       ],
@@ -901,9 +899,9 @@
       }
     },
     "node_modules/@esbuild/linux-mips64el": {
-      "version": "0.25.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.2.tgz",
-      "integrity": "sha512-hDDRlzE6rPeoj+5fsADqdUZl1OzqDYow4TB4Y/3PlKBD0ph1e6uPHzIQcv2Z65u2K0kpeByIyAjCmjn1hJgG0Q==",
+      "version": "0.25.4",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.4.tgz",
+      "integrity": "sha512-IcvTlF9dtLrfL/M8WgNI/qJYBENP3ekgsHbYUIzEzq5XJzzVEV/fXY9WFPfEEXmu3ck2qJP8LG/p3Q8f7Zc2Xg==",
       "cpu": [
         "mips64el"
       ],
@@ -918,9 +916,9 @@
       }
     },
     "node_modules/@esbuild/linux-ppc64": {
-      "version": "0.25.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.2.tgz",
-      "integrity": "sha512-tsHu2RRSWzipmUi9UBDEzc0nLc4HtpZEI5Ba+Omms5456x5WaNuiG3u7xh5AO6sipnJ9r4cRWQB2tUjPyIkc6g==",
+      "version": "0.25.4",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.4.tgz",
+      "integrity": "sha512-HOy0aLTJTVtoTeGZh4HSXaO6M95qu4k5lJcH4gxv56iaycfz1S8GO/5Jh6X4Y1YiI0h7cRyLi+HixMR+88swag==",
       "cpu": [
         "ppc64"
       ],
@@ -935,9 +933,9 @@
       }
     },
     "node_modules/@esbuild/linux-riscv64": {
-      "version": "0.25.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.2.tgz",
-      "integrity": "sha512-k4LtpgV7NJQOml/10uPU0s4SAXGnowi5qBSjaLWMojNCUICNu7TshqHLAEbkBdAszL5TabfvQ48kK84hyFzjnw==",
+      "version": "0.25.4",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.4.tgz",
+      "integrity": "sha512-i8JUDAufpz9jOzo4yIShCTcXzS07vEgWzyX3NH2G7LEFVgrLEhjwL3ajFE4fZI3I4ZgiM7JH3GQ7ReObROvSUA==",
       "cpu": [
         "riscv64"
       ],
@@ -952,9 +950,9 @@
       }
     },
     "node_modules/@esbuild/linux-s390x": {
-      "version": "0.25.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.2.tgz",
-      "integrity": "sha512-GRa4IshOdvKY7M/rDpRR3gkiTNp34M0eLTaC1a08gNrh4u488aPhuZOCpkF6+2wl3zAN7L7XIpOFBhnaE3/Q8Q==",
+      "version": "0.25.4",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.4.tgz",
+      "integrity": "sha512-jFnu+6UbLlzIjPQpWCNh5QtrcNfMLjgIavnwPQAfoGx4q17ocOU9MsQ2QVvFxwQoWpZT8DvTLooTvmOQXkO51g==",
       "cpu": [
         "s390x"
       ],
@@ -969,9 +967,9 @@
       }
     },
     "node_modules/@esbuild/linux-x64": {
-      "version": "0.25.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.2.tgz",
-      "integrity": "sha512-QInHERlqpTTZ4FRB0fROQWXcYRD64lAoiegezDunLpalZMjcUcld3YzZmVJ2H/Cp0wJRZ8Xtjtj0cEHhYc/uUg==",
+      "version": "0.25.4",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.4.tgz",
+      "integrity": "sha512-6e0cvXwzOnVWJHq+mskP8DNSrKBr1bULBvnFLpc1KY+d+irZSgZ02TGse5FsafKS5jg2e4pbvK6TPXaF/A6+CA==",
       "cpu": [
         "x64"
       ],
@@ -986,9 +984,9 @@
       }
     },
     "node_modules/@esbuild/netbsd-arm64": {
-      "version": "0.25.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.2.tgz",
-      "integrity": "sha512-talAIBoY5M8vHc6EeI2WW9d/CkiO9MQJ0IOWX8hrLhxGbro/vBXJvaQXefW2cP0z0nQVTdQ/eNyGFV1GSKrxfw==",
+      "version": "0.25.4",
+      "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.4.tgz",
+      "integrity": "sha512-vUnkBYxZW4hL/ie91hSqaSNjulOnYXE1VSLusnvHg2u3jewJBz3YzB9+oCw8DABeVqZGg94t9tyZFoHma8gWZQ==",
       "cpu": [
         "arm64"
       ],
@@ -1003,9 +1001,9 @@
       }
     },
     "node_modules/@esbuild/netbsd-x64": {
-      "version": "0.25.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.2.tgz",
-      "integrity": "sha512-voZT9Z+tpOxrvfKFyfDYPc4DO4rk06qamv1a/fkuzHpiVBMOhpjK+vBmWM8J1eiB3OLSMFYNaOaBNLXGChf5tg==",
+      "version": "0.25.4",
+      "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.4.tgz",
+      "integrity": "sha512-XAg8pIQn5CzhOB8odIcAm42QsOfa98SBeKUdo4xa8OvX8LbMZqEtgeWE9P/Wxt7MlG2QqvjGths+nq48TrUiKw==",
       "cpu": [
         "x64"
       ],
@@ -1020,9 +1018,9 @@
       }
     },
     "node_modules/@esbuild/openbsd-arm64": {
-      "version": "0.25.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.2.tgz",
-      "integrity": "sha512-dcXYOC6NXOqcykeDlwId9kB6OkPUxOEqU+rkrYVqJbK2hagWOMrsTGsMr8+rW02M+d5Op5NNlgMmjzecaRf7Tg==",
+      "version": "0.25.4",
+      "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.4.tgz",
+      "integrity": "sha512-Ct2WcFEANlFDtp1nVAXSNBPDxyU+j7+tId//iHXU2f/lN5AmO4zLyhDcpR5Cz1r08mVxzt3Jpyt4PmXQ1O6+7A==",
       "cpu": [
         "arm64"
       ],
@@ -1037,9 +1035,9 @@
       }
     },
     "node_modules/@esbuild/openbsd-x64": {
-      "version": "0.25.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.2.tgz",
-      "integrity": "sha512-t/TkWwahkH0Tsgoq1Ju7QfgGhArkGLkF1uYz8nQS/PPFlXbP5YgRpqQR3ARRiC2iXoLTWFxc6DJMSK10dVXluw==",
+      "version": "0.25.4",
+      "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.4.tgz",
+      "integrity": "sha512-xAGGhyOQ9Otm1Xu8NT1ifGLnA6M3sJxZ6ixylb+vIUVzvvd6GOALpwQrYrtlPouMqd/vSbgehz6HaVk4+7Afhw==",
       "cpu": [
         "x64"
       ],
@@ -1054,9 +1052,9 @@
       }
     },
     "node_modules/@esbuild/sunos-x64": {
-      "version": "0.25.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.2.tgz",
-      "integrity": "sha512-cfZH1co2+imVdWCjd+D1gf9NjkchVhhdpgb1q5y6Hcv9TP6Zi9ZG/beI3ig8TvwT9lH9dlxLq5MQBBgwuj4xvA==",
+      "version": "0.25.4",
+      "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.4.tgz",
+      "integrity": "sha512-Mw+tzy4pp6wZEK0+Lwr76pWLjrtjmJyUB23tHKqEDP74R3q95luY/bXqXZeYl4NYlvwOqoRKlInQialgCKy67Q==",
       "cpu": [
         "x64"
       ],
@@ -1071,9 +1069,9 @@
       }
     },
     "node_modules/@esbuild/win32-arm64": {
-      "version": "0.25.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.2.tgz",
-      "integrity": "sha512-7Loyjh+D/Nx/sOTzV8vfbB3GJuHdOQyrOryFdZvPHLf42Tk9ivBU5Aedi7iyX+x6rbn2Mh68T4qq1SDqJBQO5Q==",
+      "version": "0.25.4",
+      "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.4.tgz",
+      "integrity": "sha512-AVUP428VQTSddguz9dO9ngb+E5aScyg7nOeJDrF1HPYu555gmza3bDGMPhmVXL8svDSoqPCsCPjb265yG/kLKQ==",
       "cpu": [
         "arm64"
       ],
@@ -1088,9 +1086,9 @@
       }
     },
     "node_modules/@esbuild/win32-ia32": {
-      "version": "0.25.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.2.tgz",
-      "integrity": "sha512-WRJgsz9un0nqZJ4MfhabxaD9Ft8KioqU3JMinOTvobbX6MOSUigSBlogP8QB3uxpJDsFS6yN+3FDBdqE5lg9kg==",
+      "version": "0.25.4",
+      "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.4.tgz",
+      "integrity": "sha512-i1sW+1i+oWvQzSgfRcxxG2k4I9n3O9NRqy8U+uugaT2Dy7kLO9Y7wI72haOahxceMX8hZAzgGou1FhndRldxRg==",
       "cpu": [
         "ia32"
       ],
@@ -1105,9 +1103,9 @@
       }
     },
     "node_modules/@esbuild/win32-x64": {
-      "version": "0.25.2",
-      "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.2.tgz",
-      "integrity": "sha512-kM3HKb16VIXZyIeVrM1ygYmZBKybX8N4p754bw390wGO3Tf2j4L2/WYL+4suWujpgf6GBYs3jv7TyUivdd05JA==",
+      "version": "0.25.4",
+      "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.4.tgz",
+      "integrity": "sha512-nOT2vZNw6hJ+z43oP1SPea/G/6AbN6X+bGNhNuq8NtRHy4wsMhw765IKLNmnjek7GvjWBYQ8Q5VBoYTFg9y1UQ==",
       "cpu": [
         "x64"
       ],
@@ -1122,9 +1120,9 @@
       }
     },
     "node_modules/@eslint-community/eslint-utils": {
-      "version": "4.6.1",
-      "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.6.1.tgz",
-      "integrity": "sha512-KTsJMmobmbrFLe3LDh0PC2FXpcSYJt/MLjlkh/9LEnmKYLSYmT/0EW9JWANjeoemiuZrmogti0tW5Ch+qNUYDw==",
+      "version": "4.7.0",
+      "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz",
+      "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
@@ -1140,6 +1138,19 @@
         "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
       }
     },
+    "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": {
+      "version": "3.4.3",
+      "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+      "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
+      "dev": true,
+      "license": "Apache-2.0",
+      "engines": {
+        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+      },
+      "funding": {
+        "url": "https://opencollective.com/eslint"
+      }
+    },
     "node_modules/@eslint-community/regexpp": {
       "version": "4.12.1",
       "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz",
@@ -1193,9 +1204,9 @@
       }
     },
     "node_modules/@eslint/config-helpers": {
-      "version": "0.2.1",
-      "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.2.1.tgz",
-      "integrity": "sha512-RI17tsD2frtDu/3dmI7QRrD4bedNKPM08ziRYaC5AhkGrzIAJelm9kJU1TznK+apx6V+cqRz8tfpEeG3oIyjxw==",
+      "version": "0.2.2",
+      "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.2.2.tgz",
+      "integrity": "sha512-+GPzk8PlG0sPpzdU5ZvIRMPidzAnZDl/s9L+y13iodqvb8leL53bTannOrQ/Im7UkpsmFU5Ily5U60LWixnmLg==",
       "dev": true,
       "license": "Apache-2.0",
       "peer": true,
@@ -1204,9 +1215,9 @@
       }
     },
     "node_modules/@eslint/core": {
-      "version": "0.12.0",
-      "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.12.0.tgz",
-      "integrity": "sha512-cmrR6pytBuSMTaBweKoGMwu3EiHiEC+DoyupPmlZ0HxBJBtIxwe+j/E4XPIKNx+Q74c8lXKPwYawBf5glsTkHg==",
+      "version": "0.14.0",
+      "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.14.0.tgz",
+      "integrity": "sha512-qIbV0/JZr7iSDjqAc60IqbLdsj9GDt16xQtWD+B78d/HAlvysGdZZ6rpJHGAc2T0FQx1X6thsSPdnoiGKdNtdg==",
       "dev": true,
       "license": "Apache-2.0",
       "peer": true,
@@ -1283,14 +1294,17 @@
       }
     },
     "node_modules/@eslint/js": {
-      "version": "9.24.0",
-      "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.24.0.tgz",
-      "integrity": "sha512-uIY/y3z0uvOGX8cp1C2fiC4+ZmBhp6yZWkojtHL1YEMnRt1Y63HB9TM17proGEmeG7HeUY+UP36F0aknKYTpYA==",
+      "version": "9.27.0",
+      "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.27.0.tgz",
+      "integrity": "sha512-G5JD9Tu5HJEu4z2Uo4aHY2sLV64B7CDMXxFzqzjl3NKd6RVzSXNoE80jk7Y0lJkTTkjiIhBAqmlYwjuBY3tvpA==",
       "dev": true,
       "license": "MIT",
       "peer": true,
       "engines": {
         "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+      },
+      "funding": {
+        "url": "https://eslint.org/donate"
       }
     },
     "node_modules/@eslint/object-schema": {
@@ -1305,34 +1319,20 @@
       }
     },
     "node_modules/@eslint/plugin-kit": {
-      "version": "0.2.8",
-      "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.8.tgz",
-      "integrity": "sha512-ZAoA40rNMPwSm+AeHpCq8STiNAwzWLJuP8Xv4CHIc9wv/PSuExjMrmjfYNj682vW0OOiZ1HKxzvjQr9XZIisQA==",
+      "version": "0.3.1",
+      "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.1.tgz",
+      "integrity": "sha512-0J+zgWxHN+xXONWIyPWKFMgVuJoZuGiIFu8yxk7RJjxkzpGmyja5wRFqZIVtjDVOQpV+Rw0iOAjYPE2eQyjr0w==",
       "dev": true,
       "license": "Apache-2.0",
       "peer": true,
       "dependencies": {
-        "@eslint/core": "^0.13.0",
+        "@eslint/core": "^0.14.0",
         "levn": "^0.4.1"
       },
       "engines": {
         "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
       }
     },
-    "node_modules/@eslint/plugin-kit/node_modules/@eslint/core": {
-      "version": "0.13.0",
-      "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.13.0.tgz",
-      "integrity": "sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw==",
-      "dev": true,
-      "license": "Apache-2.0",
-      "peer": true,
-      "dependencies": {
-        "@types/json-schema": "^7.0.15"
-      },
-      "engines": {
-        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
-      }
-    },
     "node_modules/@heroicons/react": {
       "version": "2.2.0",
       "resolved": "https://registry.npmjs.org/@heroicons/react/-/react-2.2.0.tgz",
@@ -1399,9 +1399,9 @@
       }
     },
     "node_modules/@humanwhocodes/retry": {
-      "version": "0.4.2",
-      "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.2.tgz",
-      "integrity": "sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ==",
+      "version": "0.4.3",
+      "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz",
+      "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==",
       "dev": true,
       "license": "Apache-2.0",
       "peer": true,
@@ -1531,9 +1531,9 @@
       "license": "MIT"
     },
     "node_modules/@rollup/rollup-android-arm-eabi": {
-      "version": "4.40.0",
-      "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.40.0.tgz",
-      "integrity": "sha512-+Fbls/diZ0RDerhE8kyC6hjADCXA1K4yVNlH0EYfd2XjyH0UGgzaQ8MlT0pCXAThfxv3QUAczHaL+qSv1E4/Cg==",
+      "version": "4.40.2",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.40.2.tgz",
+      "integrity": "sha512-JkdNEq+DFxZfUwxvB58tHMHBHVgX23ew41g1OQinthJ+ryhdRk67O31S7sYw8u2lTjHUPFxwar07BBt1KHp/hg==",
       "cpu": [
         "arm"
       ],
@@ -1545,9 +1545,9 @@
       ]
     },
     "node_modules/@rollup/rollup-android-arm64": {
-      "version": "4.40.0",
-      "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.40.0.tgz",
-      "integrity": "sha512-PPA6aEEsTPRz+/4xxAmaoWDqh67N7wFbgFUJGMnanCFs0TV99M0M8QhhaSCks+n6EbQoFvLQgYOGXxlMGQe/6w==",
+      "version": "4.40.2",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.40.2.tgz",
+      "integrity": "sha512-13unNoZ8NzUmnndhPTkWPWbX3vtHodYmy+I9kuLxN+F+l+x3LdVF7UCu8TWVMt1POHLh6oDHhnOA04n8oJZhBw==",
       "cpu": [
         "arm64"
       ],
@@ -1559,9 +1559,9 @@
       ]
     },
     "node_modules/@rollup/rollup-darwin-arm64": {
-      "version": "4.40.0",
-      "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.40.0.tgz",
-      "integrity": "sha512-GwYOcOakYHdfnjjKwqpTGgn5a6cUX7+Ra2HeNj/GdXvO2VJOOXCiYYlRFU4CubFM67EhbmzLOmACKEfvp3J1kQ==",
+      "version": "4.40.2",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.40.2.tgz",
+      "integrity": "sha512-Gzf1Hn2Aoe8VZzevHostPX23U7N5+4D36WJNHK88NZHCJr7aVMG4fadqkIf72eqVPGjGc0HJHNuUaUcxiR+N/w==",
       "cpu": [
         "arm64"
       ],
@@ -1573,9 +1573,9 @@
       ]
     },
     "node_modules/@rollup/rollup-darwin-x64": {
-      "version": "4.40.0",
-      "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.40.0.tgz",
-      "integrity": "sha512-CoLEGJ+2eheqD9KBSxmma6ld01czS52Iw0e2qMZNpPDlf7Z9mj8xmMemxEucinev4LgHalDPczMyxzbq+Q+EtA==",
+      "version": "4.40.2",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.40.2.tgz",
+      "integrity": "sha512-47N4hxa01a4x6XnJoskMKTS8XZ0CZMd8YTbINbi+w03A2w4j1RTlnGHOz/P0+Bg1LaVL6ufZyNprSg+fW5nYQQ==",
       "cpu": [
         "x64"
       ],
@@ -1587,9 +1587,9 @@
       ]
     },
     "node_modules/@rollup/rollup-freebsd-arm64": {
-      "version": "4.40.0",
-      "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.40.0.tgz",
-      "integrity": "sha512-r7yGiS4HN/kibvESzmrOB/PxKMhPTlz+FcGvoUIKYoTyGd5toHp48g1uZy1o1xQvybwwpqpe010JrcGG2s5nkg==",
+      "version": "4.40.2",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.40.2.tgz",
+      "integrity": "sha512-8t6aL4MD+rXSHHZUR1z19+9OFJ2rl1wGKvckN47XFRVO+QL/dUSpKA2SLRo4vMg7ELA8pzGpC+W9OEd1Z/ZqoQ==",
       "cpu": [
         "arm64"
       ],
@@ -1601,9 +1601,9 @@
       ]
     },
     "node_modules/@rollup/rollup-freebsd-x64": {
-      "version": "4.40.0",
-      "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.40.0.tgz",
-      "integrity": "sha512-mVDxzlf0oLzV3oZOr0SMJ0lSDd3xC4CmnWJ8Val8isp9jRGl5Dq//LLDSPFrasS7pSm6m5xAcKaw3sHXhBjoRw==",
+      "version": "4.40.2",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.40.2.tgz",
+      "integrity": "sha512-C+AyHBzfpsOEYRFjztcYUFsH4S7UsE9cDtHCtma5BK8+ydOZYgMmWg1d/4KBytQspJCld8ZIujFMAdKG1xyr4Q==",
       "cpu": [
         "x64"
       ],
@@ -1615,9 +1615,9 @@
       ]
     },
     "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
-      "version": "4.40.0",
-      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.40.0.tgz",
-      "integrity": "sha512-y/qUMOpJxBMy8xCXD++jeu8t7kzjlOCkoxxajL58G62PJGBZVl/Gwpm7JK9+YvlB701rcQTzjUZ1JgUoPTnoQA==",
+      "version": "4.40.2",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.40.2.tgz",
+      "integrity": "sha512-de6TFZYIvJwRNjmW3+gaXiZ2DaWL5D5yGmSYzkdzjBDS3W+B9JQ48oZEsmMvemqjtAFzE16DIBLqd6IQQRuG9Q==",
       "cpu": [
         "arm"
       ],
@@ -1629,9 +1629,9 @@
       ]
     },
     "node_modules/@rollup/rollup-linux-arm-musleabihf": {
-      "version": "4.40.0",
-      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.40.0.tgz",
-      "integrity": "sha512-GoCsPibtVdJFPv/BOIvBKO/XmwZLwaNWdyD8TKlXuqp0veo2sHE+A/vpMQ5iSArRUz/uaoj4h5S6Pn0+PdhRjg==",
+      "version": "4.40.2",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.40.2.tgz",
+      "integrity": "sha512-urjaEZubdIkacKc930hUDOfQPysezKla/O9qV+O89enqsqUmQm8Xj8O/vh0gHg4LYfv7Y7UsE3QjzLQzDYN1qg==",
       "cpu": [
         "arm"
       ],
@@ -1643,9 +1643,9 @@
       ]
     },
     "node_modules/@rollup/rollup-linux-arm64-gnu": {
-      "version": "4.40.0",
-      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.40.0.tgz",
-      "integrity": "sha512-L5ZLphTjjAD9leJzSLI7rr8fNqJMlGDKlazW2tX4IUF9P7R5TMQPElpH82Q7eNIDQnQlAyiNVfRPfP2vM5Avvg==",
+      "version": "4.40.2",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.40.2.tgz",
+      "integrity": "sha512-KlE8IC0HFOC33taNt1zR8qNlBYHj31qGT1UqWqtvR/+NuCVhfufAq9fxO8BMFC22Wu0rxOwGVWxtCMvZVLmhQg==",
       "cpu": [
         "arm64"
       ],
@@ -1657,9 +1657,9 @@
       ]
     },
     "node_modules/@rollup/rollup-linux-arm64-musl": {
-      "version": "4.40.0",
-      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.40.0.tgz",
-      "integrity": "sha512-ATZvCRGCDtv1Y4gpDIXsS+wfFeFuLwVxyUBSLawjgXK2tRE6fnsQEkE4csQQYWlBlsFztRzCnBvWVfcae/1qxQ==",
+      "version": "4.40.2",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.40.2.tgz",
+      "integrity": "sha512-j8CgxvfM0kbnhu4XgjnCWJQyyBOeBI1Zq91Z850aUddUmPeQvuAy6OiMdPS46gNFgy8gN1xkYyLgwLYZG3rBOg==",
       "cpu": [
         "arm64"
       ],
@@ -1671,9 +1671,9 @@
       ]
     },
     "node_modules/@rollup/rollup-linux-loongarch64-gnu": {
-      "version": "4.40.0",
-      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.40.0.tgz",
-      "integrity": "sha512-wG9e2XtIhd++QugU5MD9i7OnpaVb08ji3P1y/hNbxrQ3sYEelKJOq1UJ5dXczeo6Hj2rfDEL5GdtkMSVLa/AOg==",
+      "version": "4.40.2",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.40.2.tgz",
+      "integrity": "sha512-Ybc/1qUampKuRF4tQXc7G7QY9YRyeVSykfK36Y5Qc5dmrIxwFhrOzqaVTNoZygqZ1ZieSWTibfFhQ5qK8jpWxw==",
       "cpu": [
         "loong64"
       ],
@@ -1685,9 +1685,9 @@
       ]
     },
     "node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
-      "version": "4.40.0",
-      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.40.0.tgz",
-      "integrity": "sha512-vgXfWmj0f3jAUvC7TZSU/m/cOE558ILWDzS7jBhiCAFpY2WEBn5jqgbqvmzlMjtp8KlLcBlXVD2mkTSEQE6Ixw==",
+      "version": "4.40.2",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.40.2.tgz",
+      "integrity": "sha512-3FCIrnrt03CCsZqSYAOW/k9n625pjpuMzVfeI+ZBUSDT3MVIFDSPfSUgIl9FqUftxcUXInvFah79hE1c9abD+Q==",
       "cpu": [
         "ppc64"
       ],
@@ -1699,9 +1699,9 @@
       ]
     },
     "node_modules/@rollup/rollup-linux-riscv64-gnu": {
-      "version": "4.40.0",
-      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.40.0.tgz",
-      "integrity": "sha512-uJkYTugqtPZBS3Z136arevt/FsKTF/J9dEMTX/cwR7lsAW4bShzI2R0pJVw+hcBTWF4dxVckYh72Hk3/hWNKvA==",
+      "version": "4.40.2",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.40.2.tgz",
+      "integrity": "sha512-QNU7BFHEvHMp2ESSY3SozIkBPaPBDTsfVNGx3Xhv+TdvWXFGOSH2NJvhD1zKAT6AyuuErJgbdvaJhYVhVqrWTg==",
       "cpu": [
         "riscv64"
       ],
@@ -1713,9 +1713,9 @@
       ]
     },
     "node_modules/@rollup/rollup-linux-riscv64-musl": {
-      "version": "4.40.0",
-      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.40.0.tgz",
-      "integrity": "sha512-rKmSj6EXQRnhSkE22+WvrqOqRtk733x3p5sWpZilhmjnkHkpeCgWsFFo0dGnUGeA+OZjRl3+VYq+HyCOEuwcxQ==",
+      "version": "4.40.2",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.40.2.tgz",
+      "integrity": "sha512-5W6vNYkhgfh7URiXTO1E9a0cy4fSgfE4+Hl5agb/U1sa0kjOLMLC1wObxwKxecE17j0URxuTrYZZME4/VH57Hg==",
       "cpu": [
         "riscv64"
       ],
@@ -1727,9 +1727,9 @@
       ]
     },
     "node_modules/@rollup/rollup-linux-s390x-gnu": {
-      "version": "4.40.0",
-      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.40.0.tgz",
-      "integrity": "sha512-SpnYlAfKPOoVsQqmTFJ0usx0z84bzGOS9anAC0AZ3rdSo3snecihbhFTlJZ8XMwzqAcodjFU4+/SM311dqE5Sw==",
+      "version": "4.40.2",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.40.2.tgz",
+      "integrity": "sha512-B7LKIz+0+p348JoAL4X/YxGx9zOx3sR+o6Hj15Y3aaApNfAshK8+mWZEf759DXfRLeL2vg5LYJBB7DdcleYCoQ==",
       "cpu": [
         "s390x"
       ],
@@ -1741,9 +1741,9 @@
       ]
     },
     "node_modules/@rollup/rollup-linux-x64-gnu": {
-      "version": "4.40.0",
-      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.40.0.tgz",
-      "integrity": "sha512-RcDGMtqF9EFN8i2RYN2W+64CdHruJ5rPqrlYw+cgM3uOVPSsnAQps7cpjXe9be/yDp8UC7VLoCoKC8J3Kn2FkQ==",
+      "version": "4.40.2",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.40.2.tgz",
+      "integrity": "sha512-lG7Xa+BmBNwpjmVUbmyKxdQJ3Q6whHjMjzQplOs5Z+Gj7mxPtWakGHqzMqNER68G67kmCX9qX57aRsW5V0VOng==",
       "cpu": [
         "x64"
       ],
@@ -1755,9 +1755,9 @@
       ]
     },
     "node_modules/@rollup/rollup-linux-x64-musl": {
-      "version": "4.40.0",
-      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.40.0.tgz",
-      "integrity": "sha512-HZvjpiUmSNx5zFgwtQAV1GaGazT2RWvqeDi0hV+AtC8unqqDSsaFjPxfsO6qPtKRRg25SisACWnJ37Yio8ttaw==",
+      "version": "4.40.2",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.40.2.tgz",
+      "integrity": "sha512-tD46wKHd+KJvsmije4bUskNuvWKFcTOIM9tZ/RrmIvcXnbi0YK/cKS9FzFtAm7Oxi2EhV5N2OpfFB348vSQRXA==",
       "cpu": [
         "x64"
       ],
@@ -1769,9 +1769,9 @@
       ]
     },
     "node_modules/@rollup/rollup-win32-arm64-msvc": {
-      "version": "4.40.0",
-      "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.40.0.tgz",
-      "integrity": "sha512-UtZQQI5k/b8d7d3i9AZmA/t+Q4tk3hOC0tMOMSq2GlMYOfxbesxG4mJSeDp0EHs30N9bsfwUvs3zF4v/RzOeTQ==",
+      "version": "4.40.2",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.40.2.tgz",
+      "integrity": "sha512-Bjv/HG8RRWLNkXwQQemdsWw4Mg+IJ29LK+bJPW2SCzPKOUaMmPEppQlu/Fqk1d7+DX3V7JbFdbkh/NMmurT6Pg==",
       "cpu": [
         "arm64"
       ],
@@ -1783,9 +1783,9 @@
       ]
     },
     "node_modules/@rollup/rollup-win32-ia32-msvc": {
-      "version": "4.40.0",
-      "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.40.0.tgz",
-      "integrity": "sha512-+m03kvI2f5syIqHXCZLPVYplP8pQch9JHyXKZ3AGMKlg8dCyr2PKHjwRLiW53LTrN/Nc3EqHOKxUxzoSPdKddA==",
+      "version": "4.40.2",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.40.2.tgz",
+      "integrity": "sha512-dt1llVSGEsGKvzeIO76HToiYPNPYPkmjhMHhP00T9S4rDern8P2ZWvWAQUEJ+R1UdMWJ/42i/QqJ2WV765GZcA==",
       "cpu": [
         "ia32"
       ],
@@ -1797,9 +1797,9 @@
       ]
     },
     "node_modules/@rollup/rollup-win32-x64-msvc": {
-      "version": "4.40.0",
-      "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.40.0.tgz",
-      "integrity": "sha512-lpPE1cLfP5oPzVjKMx10pgBmKELQnFJXHgvtHCtuJWOv8MxqdEIMNtgHgBFf7Ea2/7EuVwa9fodWUfXAlXZLZQ==",
+      "version": "4.40.2",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.40.2.tgz",
+      "integrity": "sha512-bwspbWB04XJpeElvsp+DCylKfF4trJDa2Y9Go8O6A7YLX2LIKGcNK/CYImJN6ZP4DcuOHB4Utl3iCbnR62DudA==",
       "cpu": [
         "x64"
       ],
@@ -2254,13 +2254,11 @@
       "peer": true
     },
     "node_modules/@types/node": {
-      "version": "22.14.1",
-      "resolved": "https://registry.npmjs.org/@types/node/-/node-22.14.1.tgz",
-      "integrity": "sha512-u0HuPQwe/dHrItgHHpmw3N2fYCR6x4ivMNbPHRkBVP4CvN+kiRrKHWk3i8tXiO/joPwXLMYvF9TTF0eqgHIuOw==",
+      "version": "22.15.18",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.18.tgz",
+      "integrity": "sha512-v1DKRfUdyW+jJhZNEI1PYy29S2YRxMV5AOO/x/SjKmW0acCIOqmbj6Haf9eHAhsPmrhlHSxEhv/1WszcLWV4cg==",
       "dev": true,
       "license": "MIT",
-      "optional": true,
-      "peer": true,
       "dependencies": {
         "undici-types": "~6.21.0"
       }
@@ -2273,9 +2271,9 @@
       "license": "MIT"
     },
     "node_modules/@types/react": {
-      "version": "18.3.20",
-      "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.20.tgz",
-      "integrity": "sha512-IPaCZN7PShZK/3t6Q87pfTkRm6oLTd4vztyoj+cbHUF1g3FfVb2tFIL79uCRKEfv16AhqDMBywP2VW3KIZUvcg==",
+      "version": "18.3.21",
+      "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.21.tgz",
+      "integrity": "sha512-gXLBtmlcRJeT09/sI4PxVwyrku6SaNUj/6cMubjE6T6XdY1fDmBL7r0nX0jbSZPU/Xr0KuwLLZh6aOYY5d91Xw==",
       "devOptional": true,
       "license": "MIT",
       "dependencies": {
@@ -2284,9 +2282,9 @@
       }
     },
     "node_modules/@types/react-dom": {
-      "version": "18.3.6",
-      "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.6.tgz",
-      "integrity": "sha512-nf22//wEbKXusP6E9pfOCDwFdHAX4u172eaJI4YkDRQEZiorm6KfYnSC2SWLDMVWUOWPERmJnN0ujeAfTBLvrw==",
+      "version": "18.3.7",
+      "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz",
+      "integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==",
       "dev": true,
       "license": "MIT",
       "peerDependencies": {
@@ -2300,21 +2298,21 @@
       "license": "MIT"
     },
     "node_modules/@typescript-eslint/eslint-plugin": {
-      "version": "8.30.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.30.1.tgz",
-      "integrity": "sha512-v+VWphxMjn+1t48/jO4t950D6KR8JaJuNXzi33Ve6P8sEmPr5k6CEXjdGwT6+LodVnEa91EQCtwjWNUCPweo+Q==",
+      "version": "8.32.1",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.32.1.tgz",
+      "integrity": "sha512-6u6Plg9nP/J1GRpe/vcjjabo6Uc5YQPAMxsgQyGC/I0RuukiG1wIe3+Vtg3IrSCVJDmqK3j8adrtzXSENRtFgg==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
         "@eslint-community/regexpp": "^4.10.0",
-        "@typescript-eslint/scope-manager": "8.30.1",
-        "@typescript-eslint/type-utils": "8.30.1",
-        "@typescript-eslint/utils": "8.30.1",
-        "@typescript-eslint/visitor-keys": "8.30.1",
+        "@typescript-eslint/scope-manager": "8.32.1",
+        "@typescript-eslint/type-utils": "8.32.1",
+        "@typescript-eslint/utils": "8.32.1",
+        "@typescript-eslint/visitor-keys": "8.32.1",
         "graphemer": "^1.4.0",
-        "ignore": "^5.3.1",
+        "ignore": "^7.0.0",
         "natural-compare": "^1.4.0",
-        "ts-api-utils": "^2.0.1"
+        "ts-api-utils": "^2.1.0"
       },
       "engines": {
         "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -2329,17 +2327,27 @@
         "typescript": ">=4.8.4 <5.9.0"
       }
     },
+    "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": {
+      "version": "7.0.4",
+      "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.4.tgz",
+      "integrity": "sha512-gJzzk+PQNznz8ysRrC0aOkBNVRBDtE1n53IqyqEf3PXrYwomFs5q4pGMizBMJF+ykh03insJ27hB8gSrD2Hn8A==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 4"
+      }
+    },
     "node_modules/@typescript-eslint/parser": {
-      "version": "8.30.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.30.1.tgz",
-      "integrity": "sha512-H+vqmWwT5xoNrXqWs/fesmssOW70gxFlgcMlYcBaWNPIEWDgLa4W9nkSPmhuOgLnXq9QYgkZ31fhDyLhleCsAg==",
+      "version": "8.32.1",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.32.1.tgz",
+      "integrity": "sha512-LKMrmwCPoLhM45Z00O1ulb6jwyVr2kr3XJp+G+tSEZcbauNnScewcQwtJqXDhXeYPDEjZ8C1SjXm015CirEmGg==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
-        "@typescript-eslint/scope-manager": "8.30.1",
-        "@typescript-eslint/types": "8.30.1",
-        "@typescript-eslint/typescript-estree": "8.30.1",
-        "@typescript-eslint/visitor-keys": "8.30.1",
+        "@typescript-eslint/scope-manager": "8.32.1",
+        "@typescript-eslint/types": "8.32.1",
+        "@typescript-eslint/typescript-estree": "8.32.1",
+        "@typescript-eslint/visitor-keys": "8.32.1",
         "debug": "^4.3.4"
       },
       "engines": {
@@ -2355,14 +2363,14 @@
       }
     },
     "node_modules/@typescript-eslint/scope-manager": {
-      "version": "8.30.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.30.1.tgz",
-      "integrity": "sha512-+C0B6ChFXZkuaNDl73FJxRYT0G7ufVPOSQkqkpM/U198wUwUFOtgo1k/QzFh1KjpBitaK7R1tgjVz6o9HmsRPg==",
+      "version": "8.32.1",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.32.1.tgz",
+      "integrity": "sha512-7IsIaIDeZn7kffk7qXC3o6Z4UblZJKV3UBpkvRNpr5NSyLji7tvTcvmnMNYuYLyh26mN8W723xpo3i4MlD33vA==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
-        "@typescript-eslint/types": "8.30.1",
-        "@typescript-eslint/visitor-keys": "8.30.1"
+        "@typescript-eslint/types": "8.32.1",
+        "@typescript-eslint/visitor-keys": "8.32.1"
       },
       "engines": {
         "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -2373,16 +2381,16 @@
       }
     },
     "node_modules/@typescript-eslint/type-utils": {
-      "version": "8.30.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.30.1.tgz",
-      "integrity": "sha512-64uBF76bfQiJyHgZISC7vcNz3adqQKIccVoKubyQcOnNcdJBvYOILV1v22Qhsw3tw3VQu5ll8ND6hycgAR5fEA==",
+      "version": "8.32.1",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.32.1.tgz",
+      "integrity": "sha512-mv9YpQGA8iIsl5KyUPi+FGLm7+bA4fgXaeRcFKRDRwDMu4iwrSHeDPipwueNXhdIIZltwCJv+NkxftECbIZWfA==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
-        "@typescript-eslint/typescript-estree": "8.30.1",
-        "@typescript-eslint/utils": "8.30.1",
+        "@typescript-eslint/typescript-estree": "8.32.1",
+        "@typescript-eslint/utils": "8.32.1",
         "debug": "^4.3.4",
-        "ts-api-utils": "^2.0.1"
+        "ts-api-utils": "^2.1.0"
       },
       "engines": {
         "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -2397,9 +2405,9 @@
       }
     },
     "node_modules/@typescript-eslint/types": {
-      "version": "8.30.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.30.1.tgz",
-      "integrity": "sha512-81KawPfkuulyWo5QdyG/LOKbspyyiW+p4vpn4bYO7DM/hZImlVnFwrpCTnmNMOt8CvLRr5ojI9nU1Ekpw4RcEw==",
+      "version": "8.32.1",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.32.1.tgz",
+      "integrity": "sha512-YmybwXUJcgGqgAp6bEsgpPXEg6dcCyPyCSr0CAAueacR/CCBi25G3V8gGQ2kRzQRBNol7VQknxMs9HvVa9Rvfg==",
       "dev": true,
       "license": "MIT",
       "engines": {
@@ -2411,20 +2419,20 @@
       }
     },
     "node_modules/@typescript-eslint/typescript-estree": {
-      "version": "8.30.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.30.1.tgz",
-      "integrity": "sha512-kQQnxymiUy9tTb1F2uep9W6aBiYODgq5EMSk6Nxh4Z+BDUoYUSa029ISs5zTzKBFnexQEh71KqwjKnRz58lusQ==",
+      "version": "8.32.1",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.32.1.tgz",
+      "integrity": "sha512-Y3AP9EIfYwBb4kWGb+simvPaqQoT5oJuzzj9m0i6FCY6SPvlomY2Ei4UEMm7+FXtlNJbor80ximyslzaQF6xhg==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
-        "@typescript-eslint/types": "8.30.1",
-        "@typescript-eslint/visitor-keys": "8.30.1",
+        "@typescript-eslint/types": "8.32.1",
+        "@typescript-eslint/visitor-keys": "8.32.1",
         "debug": "^4.3.4",
         "fast-glob": "^3.3.2",
         "is-glob": "^4.0.3",
         "minimatch": "^9.0.4",
         "semver": "^7.6.0",
-        "ts-api-utils": "^2.0.1"
+        "ts-api-utils": "^2.1.0"
       },
       "engines": {
         "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -2438,16 +2446,16 @@
       }
     },
     "node_modules/@typescript-eslint/utils": {
-      "version": "8.30.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.30.1.tgz",
-      "integrity": "sha512-T/8q4R9En2tcEsWPQgB5BQ0XJVOtfARcUvOa8yJP3fh9M/mXraLxZrkCfGb6ChrO/V3W+Xbd04RacUEqk1CFEQ==",
+      "version": "8.32.1",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.32.1.tgz",
+      "integrity": "sha512-DsSFNIgLSrc89gpq1LJB7Hm1YpuhK086DRDJSNrewcGvYloWW1vZLHBTIvarKZDcAORIy/uWNx8Gad+4oMpkSA==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
-        "@eslint-community/eslint-utils": "^4.4.0",
-        "@typescript-eslint/scope-manager": "8.30.1",
-        "@typescript-eslint/types": "8.30.1",
-        "@typescript-eslint/typescript-estree": "8.30.1"
+        "@eslint-community/eslint-utils": "^4.7.0",
+        "@typescript-eslint/scope-manager": "8.32.1",
+        "@typescript-eslint/types": "8.32.1",
+        "@typescript-eslint/typescript-estree": "8.32.1"
       },
       "engines": {
         "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -2462,13 +2470,13 @@
       }
     },
     "node_modules/@typescript-eslint/visitor-keys": {
-      "version": "8.30.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.30.1.tgz",
-      "integrity": "sha512-aEhgas7aJ6vZnNFC7K4/vMGDGyOiqWcYZPpIWrTKuTAlsvDNKy2GFDqh9smL+iq069ZvR0YzEeq0B8NJlLzjFA==",
+      "version": "8.32.1",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.32.1.tgz",
+      "integrity": "sha512-ar0tjQfObzhSaW3C3QNmTc5ofj0hDoNQ5XWrCy6zDyabdr0TWhCkClp+rywGNj/odAFBVzzJrK4tEq5M4Hmu4w==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
-        "@typescript-eslint/types": "8.30.1",
+        "@typescript-eslint/types": "8.32.1",
         "eslint-visitor-keys": "^4.2.0"
       },
       "engines": {
@@ -2479,23 +2487,10 @@
         "url": "https://opencollective.com/typescript-eslint"
       }
     },
-    "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": {
-      "version": "4.2.0",
-      "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz",
-      "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==",
-      "dev": true,
-      "license": "Apache-2.0",
-      "engines": {
-        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
-      },
-      "funding": {
-        "url": "https://opencollective.com/eslint"
-      }
-    },
     "node_modules/@vitejs/plugin-react": {
-      "version": "4.4.0",
-      "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.4.0.tgz",
-      "integrity": "sha512-x/EztcTKVj+TDeANY1WjNeYsvZjZdfWRMP/KXi5Yn8BoTzpa13ZltaQqKfvWYbX8CE10GOHHdC5v86jY9x8i/g==",
+      "version": "4.4.1",
+      "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.4.1.tgz",
+      "integrity": "sha512-IpEm5ZmeXAP/osiBXVVP5KjFMzbWOonMs0NaQQl+xYnUAcq4oHUBsF2+p4MgKWG4YMmFYJU8A6sxRPuowllm6w==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
@@ -2512,54 +2507,16 @@
         "vite": "^4.2.0 || ^5.0.0 || ^6.0.0"
       }
     },
-    "node_modules/@vitest/browser": {
-      "version": "3.1.2",
-      "resolved": "https://registry.npmjs.org/@vitest/browser/-/browser-3.1.2.tgz",
-      "integrity": "sha512-dwL6hQg3NSDP3Z4xzIZL0xHq/AkQAPQ4StFpWVlY2zbRJtK3Y2YqdFZ7YmZjszTETN1BDQZRn/QOrcP+c8ATgg==",
-      "dev": true,
-      "license": "MIT",
-      "optional": true,
-      "peer": true,
-      "dependencies": {
-        "@testing-library/dom": "^10.4.0",
-        "@testing-library/user-event": "^14.6.1",
-        "@vitest/mocker": "3.1.2",
-        "@vitest/utils": "3.1.2",
-        "magic-string": "^0.30.17",
-        "sirv": "^3.0.1",
-        "tinyrainbow": "^2.0.0",
-        "ws": "^8.18.1"
-      },
-      "funding": {
-        "url": "https://opencollective.com/vitest"
-      },
-      "peerDependencies": {
-        "playwright": "*",
-        "vitest": "3.1.2",
-        "webdriverio": "^7.0.0 || ^8.0.0 || ^9.0.0"
-      },
-      "peerDependenciesMeta": {
-        "playwright": {
-          "optional": true
-        },
-        "safaridriver": {
-          "optional": true
-        },
-        "webdriverio": {
-          "optional": true
-        }
-      }
-    },
     "node_modules/@vitest/expect": {
-      "version": "3.1.2",
-      "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.1.2.tgz",
-      "integrity": "sha512-O8hJgr+zREopCAqWl3uCVaOdqJwZ9qaDwUP7vy3Xigad0phZe9APxKhPcDNqYYi0rX5oMvwJMSCAXY2afqeTSA==",
+      "version": "3.1.3",
+      "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.1.3.tgz",
+      "integrity": "sha512-7FTQQuuLKmN1Ig/h+h/GO+44Q1IlglPlR2es4ab7Yvfx+Uk5xsv+Ykk+MEt/M2Yn/xGmzaLKxGw2lgy2bwuYqg==",
       "dev": true,
       "license": "MIT",
       "peer": true,
       "dependencies": {
-        "@vitest/spy": "3.1.2",
-        "@vitest/utils": "3.1.2",
+        "@vitest/spy": "3.1.3",
+        "@vitest/utils": "3.1.3",
         "chai": "^5.2.0",
         "tinyrainbow": "^2.0.0"
       },
@@ -2568,14 +2525,14 @@
       }
     },
     "node_modules/@vitest/mocker": {
-      "version": "3.1.2",
-      "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.1.2.tgz",
-      "integrity": "sha512-kOtd6K2lc7SQ0mBqYv/wdGedlqPdM/B38paPY+OwJ1XiNi44w3Fpog82UfOibmHaV9Wod18A09I9SCKLyDMqgw==",
+      "version": "3.1.3",
+      "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.1.3.tgz",
+      "integrity": "sha512-PJbLjonJK82uCWHjzgBJZuR7zmAOrSvKk1QBxrennDIgtH4uK0TB1PvYmc0XBCigxxtiAVPfWtAdy4lpz8SQGQ==",
       "dev": true,
       "license": "MIT",
       "peer": true,
       "dependencies": {
-        "@vitest/spy": "3.1.2",
+        "@vitest/spy": "3.1.3",
         "estree-walker": "^3.0.3",
         "magic-string": "^0.30.17"
       },
@@ -2596,9 +2553,9 @@
       }
     },
     "node_modules/@vitest/pretty-format": {
-      "version": "3.1.2",
-      "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.1.2.tgz",
-      "integrity": "sha512-R0xAiHuWeDjTSB3kQ3OQpT8Rx3yhdOAIm/JM4axXxnG7Q/fS8XUwggv/A4xzbQA+drYRjzkMnpYnOGAc4oeq8w==",
+      "version": "3.1.3",
+      "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.1.3.tgz",
+      "integrity": "sha512-i6FDiBeJUGLDKADw2Gb01UtUNb12yyXAqC/mmRWuYl+m/U9GS7s8us5ONmGkGpUUo7/iAYzI2ePVfOZTYvUifA==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
@@ -2609,14 +2566,14 @@
       }
     },
     "node_modules/@vitest/runner": {
-      "version": "3.1.2",
-      "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.1.2.tgz",
-      "integrity": "sha512-bhLib9l4xb4sUMPXnThbnhX2Yi8OutBMA8Yahxa7yavQsFDtwY/jrUZwpKp2XH9DhRFJIeytlyGpXCqZ65nR+g==",
+      "version": "3.1.3",
+      "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.1.3.tgz",
+      "integrity": "sha512-Tae+ogtlNfFei5DggOsSUvkIaSuVywujMj6HzR97AHK6XK8i3BuVyIifWAm/sE3a15lF5RH9yQIrbXYuo0IFyA==",
       "dev": true,
       "license": "MIT",
       "peer": true,
       "dependencies": {
-        "@vitest/utils": "3.1.2",
+        "@vitest/utils": "3.1.3",
         "pathe": "^2.0.3"
       },
       "funding": {
@@ -2624,14 +2581,14 @@
       }
     },
     "node_modules/@vitest/snapshot": {
-      "version": "3.1.2",
-      "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.1.2.tgz",
-      "integrity": "sha512-Q1qkpazSF/p4ApZg1vfZSQ5Yw6OCQxVMVrLjslbLFA1hMDrT2uxtqMaw8Tc/jy5DLka1sNs1Y7rBcftMiaSH/Q==",
+      "version": "3.1.3",
+      "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.1.3.tgz",
+      "integrity": "sha512-XVa5OPNTYUsyqG9skuUkFzAeFnEzDp8hQu7kZ0N25B1+6KjGm4hWLtURyBbsIAOekfWQ7Wuz/N/XXzgYO3deWQ==",
       "dev": true,
       "license": "MIT",
       "peer": true,
       "dependencies": {
-        "@vitest/pretty-format": "3.1.2",
+        "@vitest/pretty-format": "3.1.3",
         "magic-string": "^0.30.17",
         "pathe": "^2.0.3"
       },
@@ -2640,9 +2597,9 @@
       }
     },
     "node_modules/@vitest/spy": {
-      "version": "3.1.2",
-      "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.1.2.tgz",
-      "integrity": "sha512-OEc5fSXMws6sHVe4kOFyDSj/+4MSwst0ib4un0DlcYgQvRuYQ0+M2HyqGaauUMnjq87tmUaMNDxKQx7wNfVqPA==",
+      "version": "3.1.3",
+      "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.1.3.tgz",
+      "integrity": "sha512-x6w+ctOEmEXdWaa6TO4ilb7l9DxPR5bwEb6hILKuxfU1NqWT2mpJD9NJN7t3OTfxmVlOMrvtoFJGdgyzZ605lQ==",
       "dev": true,
       "license": "MIT",
       "peer": true,
@@ -2654,13 +2611,13 @@
       }
     },
     "node_modules/@vitest/ui": {
-      "version": "3.1.2",
-      "resolved": "https://registry.npmjs.org/@vitest/ui/-/ui-3.1.2.tgz",
-      "integrity": "sha512-+YPgKiLpFEyBVJNHDkRcSDcLrrnr20lyU4HQoI9Jtq1MdvoX8usql9h38mQw82MBU1Zo5BPC6sw+sXZ6NS18CQ==",
+      "version": "3.1.3",
+      "resolved": "https://registry.npmjs.org/@vitest/ui/-/ui-3.1.3.tgz",
+      "integrity": "sha512-IipSzX+8DptUdXN/GWq3hq5z18MwnpphYdOMm0WndkRGYELzfq7NDP8dMpZT7JGW1uXFrIGxOW2D0Xi++ulByg==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
-        "@vitest/utils": "3.1.2",
+        "@vitest/utils": "3.1.3",
         "fflate": "^0.8.2",
         "flatted": "^3.3.3",
         "pathe": "^2.0.3",
@@ -2672,17 +2629,17 @@
         "url": "https://opencollective.com/vitest"
       },
       "peerDependencies": {
-        "vitest": "3.1.2"
+        "vitest": "3.1.3"
       }
     },
     "node_modules/@vitest/utils": {
-      "version": "3.1.2",
-      "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.1.2.tgz",
-      "integrity": "sha512-5GGd0ytZ7BH3H6JTj9Kw7Prn1Nbg0wZVrIvou+UWxm54d+WoXXgAgjFJ8wn3LdagWLFSEfpPeyYrByZaGEZHLg==",
+      "version": "3.1.3",
+      "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.1.3.tgz",
+      "integrity": "sha512-2Ltrpht4OmHO9+c/nmHtF09HWiyWdworqnHIwjfvDyWjuwKbdkcS9AnhsDn+8E2RM4x++foD1/tNuLPVvWG1Rg==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
-        "@vitest/pretty-format": "3.1.2",
+        "@vitest/pretty-format": "3.1.3",
         "loupe": "^3.1.3",
         "tinyrainbow": "^2.0.0"
       },
@@ -2744,15 +2701,12 @@
       }
     },
     "node_modules/ansi-regex": {
-      "version": "6.1.0",
-      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
-      "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+      "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
       "license": "MIT",
       "engines": {
-        "node": ">=12"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+        "node": ">=8"
       }
     },
     "node_modules/ansi-styles": {
@@ -2917,9 +2871,9 @@
       }
     },
     "node_modules/browserslist": {
-      "version": "4.24.4",
-      "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz",
-      "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==",
+      "version": "4.24.5",
+      "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.5.tgz",
+      "integrity": "sha512-FDToo4Wo82hIdgc1CQ+NQD0hEhmpPjrZ3hiUgwgOG6IuTdlpr8jdjyG24P6cNP1yJpTLzS5OcGgSw0xmDU1/Tw==",
       "dev": true,
       "funding": [
         {
@@ -2937,10 +2891,10 @@
       ],
       "license": "MIT",
       "dependencies": {
-        "caniuse-lite": "^1.0.30001688",
-        "electron-to-chromium": "^1.5.73",
+        "caniuse-lite": "^1.0.30001716",
+        "electron-to-chromium": "^1.5.149",
         "node-releases": "^2.0.19",
-        "update-browserslist-db": "^1.1.1"
+        "update-browserslist-db": "^1.1.3"
       },
       "bin": {
         "browserslist": "cli.js"
@@ -2981,9 +2935,9 @@
       }
     },
     "node_modules/caniuse-lite": {
-      "version": "1.0.30001714",
-      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001714.tgz",
-      "integrity": "sha512-mtgapdwDLSSBnCI3JokHM7oEQBLxiJKVRtg10AxM1AyeiKcM96f0Mkbqeq+1AbiCtvMcHRulAAEMu693JrSWqg==",
+      "version": "1.0.30001718",
+      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001718.tgz",
+      "integrity": "sha512-AflseV1ahcSunK53NfEs9gFWgOEmzr0f+kaMFA4xiLZlr9Hzt7HxcSpIFcnNCUkz6R6dWKa54rUz3HUmI3nVcw==",
       "dev": true,
       "funding": [
         {
@@ -3205,9 +3159,9 @@
       "license": "MIT"
     },
     "node_modules/daisyui": {
-      "version": "5.0.27",
-      "resolved": "https://registry.npmjs.org/daisyui/-/daisyui-5.0.27.tgz",
-      "integrity": "sha512-XrpqgfpGaZJvTPg9pS9Rq6xbYpmMnR0a7AKqyVPZceJzjAs5HH3rfkRkiuGin0+KC2Adnu+WLHU7UDxAtCMyAw==",
+      "version": "5.0.35",
+      "resolved": "https://registry.npmjs.org/daisyui/-/daisyui-5.0.35.tgz",
+      "integrity": "sha512-AWi11n/x5++mps55jcwrBf0Lmip1euWY0FYcH/05SFGmoqrU7S7/aIUWaiaeqlJ5EcmEZ/7zEY73aOxMv6hcIg==",
       "license": "MIT",
       "funding": {
         "url": "https://github.com/saadeghi/daisyui?sponsor=1"
@@ -3228,9 +3182,9 @@
       }
     },
     "node_modules/debug": {
-      "version": "4.4.0",
-      "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
-      "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
+      "version": "4.4.1",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
+      "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
@@ -3320,9 +3274,9 @@
       "license": "MIT"
     },
     "node_modules/electron-to-chromium": {
-      "version": "1.5.138",
-      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.138.tgz",
-      "integrity": "sha512-FWlQc52z1dXqm+9cCJ2uyFgJkESd+16j6dBEjsgDNuHjBpuIzL8/lRc0uvh1k8RNI6waGo6tcy2DvwkTBJOLDg==",
+      "version": "1.5.155",
+      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.155.tgz",
+      "integrity": "sha512-ps5KcGGmwL8VaeJlvlDlu4fORQpv3+GIcF5I3f9tUKUlJ/wsysh6HU8P5L1XWRYeXfA0oJd4PyM8ds8zTFf6Ng==",
       "dev": true,
       "license": "ISC"
     },
@@ -3339,9 +3293,9 @@
       "license": "MIT"
     },
     "node_modules/entities": {
-      "version": "4.5.0",
-      "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
-      "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.0.tgz",
+      "integrity": "sha512-aKstq2TDOndCn4diEyp9Uq/Flu2i1GlLkc6XIDQSDMuaFE3OPW5OphLCyQ5SpSJZTb4reN+kTcYru5yIfXoRPw==",
       "dev": true,
       "license": "BSD-2-Clause",
       "engines": {
@@ -3352,17 +3306,17 @@
       }
     },
     "node_modules/es-module-lexer": {
-      "version": "1.6.0",
-      "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.6.0.tgz",
-      "integrity": "sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==",
+      "version": "1.7.0",
+      "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz",
+      "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==",
       "dev": true,
       "license": "MIT",
       "peer": true
     },
     "node_modules/esbuild": {
-      "version": "0.25.2",
-      "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.2.tgz",
-      "integrity": "sha512-16854zccKPnC+toMywC+uKNeYSv+/eXkevRAfwRD/G9Cleq66m8XFIrigkbvauLLlCfDL45Q2cWegSg53gGBnQ==",
+      "version": "0.25.4",
+      "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.4.tgz",
+      "integrity": "sha512-8pgjLUcUjcgDg+2Q4NYXnPbo/vncAY4UmyaCm0jZevERqCHZIaWwdJHkf8XQtu4AxSKCdvrUbT0XUr1IdZzI8Q==",
       "dev": true,
       "hasInstallScript": true,
       "license": "MIT",
@@ -3373,31 +3327,31 @@
         "node": ">=18"
       },
       "optionalDependencies": {
-        "@esbuild/aix-ppc64": "0.25.2",
-        "@esbuild/android-arm": "0.25.2",
-        "@esbuild/android-arm64": "0.25.2",
-        "@esbuild/android-x64": "0.25.2",
-        "@esbuild/darwin-arm64": "0.25.2",
-        "@esbuild/darwin-x64": "0.25.2",
-        "@esbuild/freebsd-arm64": "0.25.2",
-        "@esbuild/freebsd-x64": "0.25.2",
-        "@esbuild/linux-arm": "0.25.2",
-        "@esbuild/linux-arm64": "0.25.2",
-        "@esbuild/linux-ia32": "0.25.2",
-        "@esbuild/linux-loong64": "0.25.2",
-        "@esbuild/linux-mips64el": "0.25.2",
-        "@esbuild/linux-ppc64": "0.25.2",
-        "@esbuild/linux-riscv64": "0.25.2",
-        "@esbuild/linux-s390x": "0.25.2",
-        "@esbuild/linux-x64": "0.25.2",
-        "@esbuild/netbsd-arm64": "0.25.2",
-        "@esbuild/netbsd-x64": "0.25.2",
-        "@esbuild/openbsd-arm64": "0.25.2",
-        "@esbuild/openbsd-x64": "0.25.2",
-        "@esbuild/sunos-x64": "0.25.2",
-        "@esbuild/win32-arm64": "0.25.2",
-        "@esbuild/win32-ia32": "0.25.2",
-        "@esbuild/win32-x64": "0.25.2"
+        "@esbuild/aix-ppc64": "0.25.4",
+        "@esbuild/android-arm": "0.25.4",
+        "@esbuild/android-arm64": "0.25.4",
+        "@esbuild/android-x64": "0.25.4",
+        "@esbuild/darwin-arm64": "0.25.4",
+        "@esbuild/darwin-x64": "0.25.4",
+        "@esbuild/freebsd-arm64": "0.25.4",
+        "@esbuild/freebsd-x64": "0.25.4",
+        "@esbuild/linux-arm": "0.25.4",
+        "@esbuild/linux-arm64": "0.25.4",
+        "@esbuild/linux-ia32": "0.25.4",
+        "@esbuild/linux-loong64": "0.25.4",
+        "@esbuild/linux-mips64el": "0.25.4",
+        "@esbuild/linux-ppc64": "0.25.4",
+        "@esbuild/linux-riscv64": "0.25.4",
+        "@esbuild/linux-s390x": "0.25.4",
+        "@esbuild/linux-x64": "0.25.4",
+        "@esbuild/netbsd-arm64": "0.25.4",
+        "@esbuild/netbsd-x64": "0.25.4",
+        "@esbuild/openbsd-arm64": "0.25.4",
+        "@esbuild/openbsd-x64": "0.25.4",
+        "@esbuild/sunos-x64": "0.25.4",
+        "@esbuild/win32-arm64": "0.25.4",
+        "@esbuild/win32-ia32": "0.25.4",
+        "@esbuild/win32-x64": "0.25.4"
       }
     },
     "node_modules/escalade": {
@@ -3425,9 +3379,9 @@
       }
     },
     "node_modules/eslint": {
-      "version": "9.24.0",
-      "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.24.0.tgz",
-      "integrity": "sha512-eh/jxIEJyZrvbWRe4XuVclLPDYSYYYgLy5zXGGxD6j8zjSAxFEzI2fL/8xNq6O2yKqVt+eF2YhV+hxjV6UKXwQ==",
+      "version": "9.27.0",
+      "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.27.0.tgz",
+      "integrity": "sha512-ixRawFQuMB9DZ7fjU3iGGganFDp3+45bPOdaRurcFHSXO1e/sYwUX/FtQZpLZJR6SjMoJH8hR2pPEAfDyCoU2Q==",
       "dev": true,
       "license": "MIT",
       "peer": true,
@@ -3435,11 +3389,11 @@
         "@eslint-community/eslint-utils": "^4.2.0",
         "@eslint-community/regexpp": "^4.12.1",
         "@eslint/config-array": "^0.20.0",
-        "@eslint/config-helpers": "^0.2.0",
-        "@eslint/core": "^0.12.0",
+        "@eslint/config-helpers": "^0.2.1",
+        "@eslint/core": "^0.14.0",
         "@eslint/eslintrc": "^3.3.1",
-        "@eslint/js": "9.24.0",
-        "@eslint/plugin-kit": "^0.2.7",
+        "@eslint/js": "9.27.0",
+        "@eslint/plugin-kit": "^0.3.1",
         "@humanfs/node": "^0.16.6",
         "@humanwhocodes/module-importer": "^1.0.1",
         "@humanwhocodes/retry": "^0.4.2",
@@ -3505,13 +3459,13 @@
       }
     },
     "node_modules/eslint-visitor-keys": {
-      "version": "3.4.3",
-      "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
-      "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz",
+      "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==",
       "dev": true,
       "license": "Apache-2.0",
       "engines": {
-        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
       },
       "funding": {
         "url": "https://opencollective.com/eslint"
@@ -3529,20 +3483,6 @@
         "concat-map": "0.0.1"
       }
     },
-    "node_modules/eslint/node_modules/eslint-visitor-keys": {
-      "version": "4.2.0",
-      "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz",
-      "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==",
-      "dev": true,
-      "license": "Apache-2.0",
-      "peer": true,
-      "engines": {
-        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
-      },
-      "funding": {
-        "url": "https://opencollective.com/eslint"
-      }
-    },
     "node_modules/eslint/node_modules/minimatch": {
       "version": "3.1.2",
       "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
@@ -3576,20 +3516,6 @@
         "url": "https://opencollective.com/eslint"
       }
     },
-    "node_modules/espree/node_modules/eslint-visitor-keys": {
-      "version": "4.2.0",
-      "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz",
-      "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==",
-      "dev": true,
-      "license": "Apache-2.0",
-      "peer": true,
-      "engines": {
-        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
-      },
-      "funding": {
-        "url": "https://opencollective.com/eslint"
-      }
-    },
     "node_modules/esquery": {
       "version": "1.6.0",
       "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz",
@@ -4377,9 +4303,9 @@
       }
     },
     "node_modules/lefthook": {
-      "version": "1.11.10",
-      "resolved": "https://registry.npmjs.org/lefthook/-/lefthook-1.11.10.tgz",
-      "integrity": "sha512-nuiRqBADcRiU6dzwf2H1zBCsdcWGEOsxY8hqoXw5nkEuoTEYN1Bwi2vskHXjIzJ62iCOCo4FZhcHBAzT9gwL5g==",
+      "version": "1.11.13",
+      "resolved": "https://registry.npmjs.org/lefthook/-/lefthook-1.11.13.tgz",
+      "integrity": "sha512-SDTk3D4nW1XRpR9u9fdYQ/qj1xeZVIwZmIFdJUnyq+w9ZLdCCvIrOmtD8SFiJowSevISjQDC+f9nqyFXUxc0SQ==",
       "dev": true,
       "hasInstallScript": true,
       "license": "MIT",
@@ -4387,22 +4313,22 @@
         "lefthook": "bin/index.js"
       },
       "optionalDependencies": {
-        "lefthook-darwin-arm64": "1.11.10",
-        "lefthook-darwin-x64": "1.11.10",
-        "lefthook-freebsd-arm64": "1.11.10",
-        "lefthook-freebsd-x64": "1.11.10",
-        "lefthook-linux-arm64": "1.11.10",
-        "lefthook-linux-x64": "1.11.10",
-        "lefthook-openbsd-arm64": "1.11.10",
-        "lefthook-openbsd-x64": "1.11.10",
-        "lefthook-windows-arm64": "1.11.10",
-        "lefthook-windows-x64": "1.11.10"
+        "lefthook-darwin-arm64": "1.11.13",
+        "lefthook-darwin-x64": "1.11.13",
+        "lefthook-freebsd-arm64": "1.11.13",
+        "lefthook-freebsd-x64": "1.11.13",
+        "lefthook-linux-arm64": "1.11.13",
+        "lefthook-linux-x64": "1.11.13",
+        "lefthook-openbsd-arm64": "1.11.13",
+        "lefthook-openbsd-x64": "1.11.13",
+        "lefthook-windows-arm64": "1.11.13",
+        "lefthook-windows-x64": "1.11.13"
       }
     },
     "node_modules/lefthook-darwin-arm64": {
-      "version": "1.11.10",
-      "resolved": "https://registry.npmjs.org/lefthook-darwin-arm64/-/lefthook-darwin-arm64-1.11.10.tgz",
-      "integrity": "sha512-Rufl8BRP77GRFtgNwW95/FHPD0VDfu5bRyzASPcyVrFczJiBK1glAHRdYrErBDNqJhEEjkyv9+EkCZS/MnDKPQ==",
+      "version": "1.11.13",
+      "resolved": "https://registry.npmjs.org/lefthook-darwin-arm64/-/lefthook-darwin-arm64-1.11.13.tgz",
+      "integrity": "sha512-gHwHofXupCtzNLN+8esdWfFTnAEkmBxE/WKA0EwxPPJXdZYa1GUsiG5ipq/CdG/0j8ekYyM9Hzyrrk5BqJ42xw==",
       "cpu": [
         "arm64"
       ],
@@ -4414,9 +4340,9 @@
       ]
     },
     "node_modules/lefthook-darwin-x64": {
-      "version": "1.11.10",
-      "resolved": "https://registry.npmjs.org/lefthook-darwin-x64/-/lefthook-darwin-x64-1.11.10.tgz",
-      "integrity": "sha512-3ReMyC103S+RozcYQlej9RVa1tKr9t8/PGqXbCiWcPAgA9To3GywPk8533qzTs7Nz9fYDiqJMYyQoXovX0Q4SA==",
+      "version": "1.11.13",
+      "resolved": "https://registry.npmjs.org/lefthook-darwin-x64/-/lefthook-darwin-x64-1.11.13.tgz",
+      "integrity": "sha512-zYxkWNUirmTidhskY9J9AwxvdMi3YKH+TqZ3AQ1EOqkOwPBWJQW5PbnzsXDrd3YnrtZScYm/tE/moXJpEPPIpQ==",
       "cpu": [
         "x64"
       ],
@@ -4428,9 +4354,9 @@
       ]
     },
     "node_modules/lefthook-freebsd-arm64": {
-      "version": "1.11.10",
-      "resolved": "https://registry.npmjs.org/lefthook-freebsd-arm64/-/lefthook-freebsd-arm64-1.11.10.tgz",
-      "integrity": "sha512-UQOdQuvoVEe0HnoVX4Uz8beegndBDKE6Igo5flV3OkrBuO1Cz7dGbTQwzsYg6gBLYUOa8Ecb3Xur80oviQqwnA==",
+      "version": "1.11.13",
+      "resolved": "https://registry.npmjs.org/lefthook-freebsd-arm64/-/lefthook-freebsd-arm64-1.11.13.tgz",
+      "integrity": "sha512-gJzWnllcMcivusmPorEkXPpEciKotlBHn7QxWwYaSjss/U3YdZu+NTjDO30b3qeiVlyq4RAZ4BPKJODXxHHwUA==",
       "cpu": [
         "arm64"
       ],
@@ -4442,9 +4368,9 @@
       ]
     },
     "node_modules/lefthook-freebsd-x64": {
-      "version": "1.11.10",
-      "resolved": "https://registry.npmjs.org/lefthook-freebsd-x64/-/lefthook-freebsd-x64-1.11.10.tgz",
-      "integrity": "sha512-IkoywmTzw9dKDtN34HJ8AZkbY3CGu1XpAVU08pIIvlhv0y7PlLGHYTdmx90SC1d4FhTlTMyiANgXyIaAnXjucw==",
+      "version": "1.11.13",
+      "resolved": "https://registry.npmjs.org/lefthook-freebsd-x64/-/lefthook-freebsd-x64-1.11.13.tgz",
+      "integrity": "sha512-689XdchgtDvZQWFFx1szUvm/mqrq/v6laki0odq5FAfcSgUeLu3w+z6UicBS5l55eFJuQTDNKARFqrKJ04e+Vw==",
       "cpu": [
         "x64"
       ],
@@ -4456,9 +4382,9 @@
       ]
     },
     "node_modules/lefthook-linux-arm64": {
-      "version": "1.11.10",
-      "resolved": "https://registry.npmjs.org/lefthook-linux-arm64/-/lefthook-linux-arm64-1.11.10.tgz",
-      "integrity": "sha512-l/lH4FSljNSIetcptPKLI5sTBpjS6dJZ4gk9oXoGM0ftvb22AlLcZI4l6NFCC1oLVWM0CbhkbStDGTI5txsVaA==",
+      "version": "1.11.13",
+      "resolved": "https://registry.npmjs.org/lefthook-linux-arm64/-/lefthook-linux-arm64-1.11.13.tgz",
+      "integrity": "sha512-ujCLbaZg5S/Ao8KZAcNSb+Y3gl898ZEM0YKyiZmZo22dFFpm/5gcV46pF3xaqIw5IpH+3YYDTKDU+qTetmARyQ==",
       "cpu": [
         "arm64"
       ],
@@ -4470,9 +4396,9 @@
       ]
     },
     "node_modules/lefthook-linux-x64": {
-      "version": "1.11.10",
-      "resolved": "https://registry.npmjs.org/lefthook-linux-x64/-/lefthook-linux-x64-1.11.10.tgz",
-      "integrity": "sha512-yAIIP711p7t0Z9zLfPtdSx1d7pSgtnuVC5B9PANud3I0JOs82aCzmqpc9Q/zp+imWXdI2PpZlFyKx8GLrDW5BQ==",
+      "version": "1.11.13",
+      "resolved": "https://registry.npmjs.org/lefthook-linux-x64/-/lefthook-linux-x64-1.11.13.tgz",
+      "integrity": "sha512-O5WdodeBtFOXQlvPcckqp4W/yqVM9DbVQBkvOxwSJlmsxO4sGYK1TqdxH9ihLB85B2kPPssZj9ze36/oizzhVQ==",
       "cpu": [
         "x64"
       ],
@@ -4484,9 +4410,9 @@
       ]
     },
     "node_modules/lefthook-openbsd-arm64": {
-      "version": "1.11.10",
-      "resolved": "https://registry.npmjs.org/lefthook-openbsd-arm64/-/lefthook-openbsd-arm64-1.11.10.tgz",
-      "integrity": "sha512-OAqg9BLsTaeioCJduzZrRLupA2dhTOwHOX0GkO4HTSrOD85JuEPqr5RbYoJ7zuzTQcJEXTJYzaeATM2QHjp/aQ==",
+      "version": "1.11.13",
+      "resolved": "https://registry.npmjs.org/lefthook-openbsd-arm64/-/lefthook-openbsd-arm64-1.11.13.tgz",
+      "integrity": "sha512-SyBpciUfvY/lUDbZu7L6MtL/SVG2+yMTckBgb4PdJQhJlisY0IsyOYdlTw2icPPrY7JnwdsFv8UW0EJOB76W4g==",
       "cpu": [
         "arm64"
       ],
@@ -4498,9 +4424,9 @@
       ]
     },
     "node_modules/lefthook-openbsd-x64": {
-      "version": "1.11.10",
-      "resolved": "https://registry.npmjs.org/lefthook-openbsd-x64/-/lefthook-openbsd-x64-1.11.10.tgz",
-      "integrity": "sha512-EiUU3mFvqcUdnj3gt0V0gRpQQp0b70cLDSA0LgZyFMM4UimeMbA7OgNYl72RKJgrHcTPHrQc4Vj7Mowbhb/X5w==",
+      "version": "1.11.13",
+      "resolved": "https://registry.npmjs.org/lefthook-openbsd-x64/-/lefthook-openbsd-x64-1.11.13.tgz",
+      "integrity": "sha512-6+/0j6O2dzo9cjTWUKfL2J6hRR7Krna/ssqnW8cWh8QHZKO9WJn34epto9qgjeHwSysou8byI7Mwv5zOGthLCQ==",
       "cpu": [
         "x64"
       ],
@@ -4512,9 +4438,9 @@
       ]
     },
     "node_modules/lefthook-windows-arm64": {
-      "version": "1.11.10",
-      "resolved": "https://registry.npmjs.org/lefthook-windows-arm64/-/lefthook-windows-arm64-1.11.10.tgz",
-      "integrity": "sha512-clKfI95dCpzxJ1zVgcuYWlSl2oNbtAALoMGqYrzJsoy+CAi+vIs54sqJoGOE60+zrVbdk65z8hriCoYNr98SgA==",
+      "version": "1.11.13",
+      "resolved": "https://registry.npmjs.org/lefthook-windows-arm64/-/lefthook-windows-arm64-1.11.13.tgz",
+      "integrity": "sha512-w5TwZ8bsZ17uOMtYGc5oEb4tCHjNTSeSXRy6H9Yic8E7IsPZtZLkaZGnIIwgXFuhhrcCdc6FuTvKt2tyV7EW2g==",
       "cpu": [
         "arm64"
       ],
@@ -4526,9 +4452,9 @@
       ]
     },
     "node_modules/lefthook-windows-x64": {
-      "version": "1.11.10",
-      "resolved": "https://registry.npmjs.org/lefthook-windows-x64/-/lefthook-windows-x64-1.11.10.tgz",
-      "integrity": "sha512-zpf/0sG50xsGnwVG/a2giUbmaM/g0uIRqxN5qBbmwKCf0P4PPD2r1xiFZNDb520+tUTC1lWe0RWVoSSwZbBQRA==",
+      "version": "1.11.13",
+      "resolved": "https://registry.npmjs.org/lefthook-windows-x64/-/lefthook-windows-x64-1.11.13.tgz",
+      "integrity": "sha512-7lvwnIs8CNOXKU4y3i1Pbqna+QegIORkSD2VCuHBNpIJ8H84NpjoG3tKU91IM/aI1a2eUvCk+dw+1rfMRz7Ytg==",
       "cpu": [
         "x64"
       ],
@@ -4922,13 +4848,13 @@
       }
     },
     "node_modules/parse5": {
-      "version": "7.2.1",
-      "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.2.1.tgz",
-      "integrity": "sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ==",
+      "version": "7.3.0",
+      "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz",
+      "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
-        "entities": "^4.5.0"
+        "entities": "^6.0.0"
       },
       "funding": {
         "url": "https://github.com/inikulin/parse5?sponsor=1"
@@ -5372,17 +5298,6 @@
         "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
       }
     },
-    "node_modules/pretty-format/node_modules/ansi-regex": {
-      "version": "5.0.1",
-      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
-      "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
-      "dev": true,
-      "license": "MIT",
-      "peer": true,
-      "engines": {
-        "node": ">=8"
-      }
-    },
     "node_modules/pretty-format/node_modules/ansi-styles": {
       "version": "5.2.0",
       "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
@@ -5480,14 +5395,13 @@
       }
     },
     "node_modules/react-router": {
-      "version": "7.5.2",
-      "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.5.2.tgz",
-      "integrity": "sha512-9Rw8r199klMnlGZ8VAsV/I8WrIF6IyJ90JQUdboupx1cdkgYqwnrYjH+I/nY/7cA1X5zia4mDJqH36npP7sxGQ==",
+      "version": "7.6.0",
+      "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.6.0.tgz",
+      "integrity": "sha512-GGufuHIVCJDbnIAXP3P9Sxzq3UUsddG3rrI3ut1q6m0FI6vxVBF3JoPQ38+W/blslLH4a5Yutp8drkEpXoddGQ==",
       "license": "MIT",
       "dependencies": {
         "cookie": "^1.0.1",
-        "set-cookie-parser": "^2.6.0",
-        "turbo-stream": "2.4.0"
+        "set-cookie-parser": "^2.6.0"
       },
       "engines": {
         "node": ">=20.0.0"
@@ -5503,12 +5417,12 @@
       }
     },
     "node_modules/react-router-dom": {
-      "version": "7.5.2",
-      "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.5.2.tgz",
-      "integrity": "sha512-yk1XW8Fj7gK7flpYBXF3yzd2NbX6P7Kxjvs2b5nu1M04rb5pg/Zc4fGdBNTeT4eDYL2bvzWNyKaIMJX/RKHTTg==",
+      "version": "7.6.0",
+      "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.6.0.tgz",
+      "integrity": "sha512-DYgm6RDEuKdopSyGOWZGtDfSm7Aofb8CCzgkliTjtu/eDuB0gcsv6qdFhhi8HdtmA+KHkt5MfZ5K2PdzjugYsA==",
       "license": "MIT",
       "dependencies": {
-        "react-router": "7.5.2"
+        "react-router": "7.6.0"
       },
       "engines": {
         "node": ">=20.0.0"
@@ -5553,13 +5467,6 @@
         "node": ">=8"
       }
     },
-    "node_modules/regenerator-runtime": {
-      "version": "0.14.1",
-      "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
-      "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==",
-      "dev": true,
-      "license": "MIT"
-    },
     "node_modules/resolve": {
       "version": "1.22.10",
       "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz",
@@ -5602,9 +5509,9 @@
       }
     },
     "node_modules/rollup": {
-      "version": "4.40.0",
-      "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.40.0.tgz",
-      "integrity": "sha512-Noe455xmA96nnqH5piFtLobsGbCij7Tu+tb3c1vYjNbTkfzGqXqQXG3wJaYXkRZuQ0vEYN4bhwg7QnIrqB5B+w==",
+      "version": "4.40.2",
+      "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.40.2.tgz",
+      "integrity": "sha512-tfUOg6DTP4rhQ3VjOO6B4wyrJnGOX85requAXvqYTHsOgb2TFJdZ3aWpT8W2kPoypSGP7dZUyzxJ9ee4buM5Fg==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
@@ -5618,26 +5525,26 @@
         "npm": ">=8.0.0"
       },
       "optionalDependencies": {
-        "@rollup/rollup-android-arm-eabi": "4.40.0",
-        "@rollup/rollup-android-arm64": "4.40.0",
-        "@rollup/rollup-darwin-arm64": "4.40.0",
-        "@rollup/rollup-darwin-x64": "4.40.0",
-        "@rollup/rollup-freebsd-arm64": "4.40.0",
-        "@rollup/rollup-freebsd-x64": "4.40.0",
-        "@rollup/rollup-linux-arm-gnueabihf": "4.40.0",
-        "@rollup/rollup-linux-arm-musleabihf": "4.40.0",
-        "@rollup/rollup-linux-arm64-gnu": "4.40.0",
-        "@rollup/rollup-linux-arm64-musl": "4.40.0",
-        "@rollup/rollup-linux-loongarch64-gnu": "4.40.0",
-        "@rollup/rollup-linux-powerpc64le-gnu": "4.40.0",
-        "@rollup/rollup-linux-riscv64-gnu": "4.40.0",
-        "@rollup/rollup-linux-riscv64-musl": "4.40.0",
-        "@rollup/rollup-linux-s390x-gnu": "4.40.0",
-        "@rollup/rollup-linux-x64-gnu": "4.40.0",
-        "@rollup/rollup-linux-x64-musl": "4.40.0",
-        "@rollup/rollup-win32-arm64-msvc": "4.40.0",
-        "@rollup/rollup-win32-ia32-msvc": "4.40.0",
-        "@rollup/rollup-win32-x64-msvc": "4.40.0",
+        "@rollup/rollup-android-arm-eabi": "4.40.2",
+        "@rollup/rollup-android-arm64": "4.40.2",
+        "@rollup/rollup-darwin-arm64": "4.40.2",
+        "@rollup/rollup-darwin-x64": "4.40.2",
+        "@rollup/rollup-freebsd-arm64": "4.40.2",
+        "@rollup/rollup-freebsd-x64": "4.40.2",
+        "@rollup/rollup-linux-arm-gnueabihf": "4.40.2",
+        "@rollup/rollup-linux-arm-musleabihf": "4.40.2",
+        "@rollup/rollup-linux-arm64-gnu": "4.40.2",
+        "@rollup/rollup-linux-arm64-musl": "4.40.2",
+        "@rollup/rollup-linux-loongarch64-gnu": "4.40.2",
+        "@rollup/rollup-linux-powerpc64le-gnu": "4.40.2",
+        "@rollup/rollup-linux-riscv64-gnu": "4.40.2",
+        "@rollup/rollup-linux-riscv64-musl": "4.40.2",
+        "@rollup/rollup-linux-s390x-gnu": "4.40.2",
+        "@rollup/rollup-linux-x64-gnu": "4.40.2",
+        "@rollup/rollup-linux-x64-musl": "4.40.2",
+        "@rollup/rollup-win32-arm64-msvc": "4.40.2",
+        "@rollup/rollup-win32-ia32-msvc": "4.40.2",
+        "@rollup/rollup-win32-x64-msvc": "4.40.2",
         "fsevents": "~2.3.2"
       }
     },
@@ -5701,9 +5608,9 @@
       }
     },
     "node_modules/semver": {
-      "version": "7.7.1",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz",
-      "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==",
+      "version": "7.7.2",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
+      "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==",
       "dev": true,
       "license": "ISC",
       "bin": {
@@ -5841,15 +5748,6 @@
         "node": ">=8"
       }
     },
-    "node_modules/string-width-cjs/node_modules/ansi-regex": {
-      "version": "5.0.1",
-      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
-      "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=8"
-      }
-    },
     "node_modules/string-width-cjs/node_modules/emoji-regex": {
       "version": "8.0.0",
       "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
@@ -5896,13 +5794,16 @@
         "node": ">=8"
       }
     },
-    "node_modules/strip-ansi-cjs/node_modules/ansi-regex": {
-      "version": "5.0.1",
-      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
-      "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+    "node_modules/strip-ansi/node_modules/ansi-regex": {
+      "version": "6.1.0",
+      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
+      "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
       "license": "MIT",
       "engines": {
-        "node": ">=8"
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/ansi-regex?sponsor=1"
       }
     },
     "node_modules/strip-indent": {
@@ -6284,12 +6185,6 @@
       "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==",
       "license": "Apache-2.0"
     },
-    "node_modules/turbo-stream": {
-      "version": "2.4.0",
-      "resolved": "https://registry.npmjs.org/turbo-stream/-/turbo-stream-2.4.0.tgz",
-      "integrity": "sha512-FHncC10WpBd2eOmGwpmQsWLDoK4cqsA/UT/GqNoaKOQnT8uzhtCbg3EoUDMvqpOSAI0S26mr0rkjzbOO6S3v1g==",
-      "license": "ISC"
-    },
     "node_modules/type-check": {
       "version": "0.4.0",
       "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
@@ -6319,15 +6214,15 @@
       }
     },
     "node_modules/typescript-eslint": {
-      "version": "8.30.1",
-      "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.30.1.tgz",
-      "integrity": "sha512-D7lC0kcehVH7Mb26MRQi64LMyRJsj3dToJxM1+JVTl53DQSV5/7oUGWQLcKl1C1KnoVHxMMU2FNQMffr7F3Row==",
+      "version": "8.32.1",
+      "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.32.1.tgz",
+      "integrity": "sha512-D7el+eaDHAmXvrZBy1zpzSNIRqnCOrkwTgZxTu3MUqRWk8k0q9m9Ho4+vPf7iHtgUfrK/o8IZaEApsxPlHTFCg==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
-        "@typescript-eslint/eslint-plugin": "8.30.1",
-        "@typescript-eslint/parser": "8.30.1",
-        "@typescript-eslint/utils": "8.30.1"
+        "@typescript-eslint/eslint-plugin": "8.32.1",
+        "@typescript-eslint/parser": "8.32.1",
+        "@typescript-eslint/utils": "8.32.1"
       },
       "engines": {
         "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -6346,9 +6241,7 @@
       "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
       "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
       "dev": true,
-      "license": "MIT",
-      "optional": true,
-      "peer": true
+      "license": "MIT"
     },
     "node_modules/universalify": {
       "version": "2.0.1",
@@ -6421,9 +6314,9 @@
       }
     },
     "node_modules/vite": {
-      "version": "6.3.4",
-      "resolved": "https://registry.npmjs.org/vite/-/vite-6.3.4.tgz",
-      "integrity": "sha512-BiReIiMS2fyFqbqNT/Qqt4CVITDU9M9vE+DKcVAsB+ZV0wvTKd+3hMbkpxz1b+NmEDMegpVbisKiAZOnvO92Sw==",
+      "version": "6.3.5",
+      "resolved": "https://registry.npmjs.org/vite/-/vite-6.3.5.tgz",
+      "integrity": "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
@@ -6496,16 +6389,16 @@
       }
     },
     "node_modules/vite-node": {
-      "version": "3.1.2",
-      "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.1.2.tgz",
-      "integrity": "sha512-/8iMryv46J3aK13iUXsei5G/A3CUlW4665THCPS+K8xAaqrVWiGB4RfXMQXCLjpK9P2eK//BczrVkn5JLAk6DA==",
+      "version": "3.1.3",
+      "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.1.3.tgz",
+      "integrity": "sha512-uHV4plJ2IxCl4u1up1FQRrqclylKAogbtBfOTwcuJ28xFi+89PZ57BRh+naIRvH70HPwxy5QHYzg1OrEaC7AbA==",
       "dev": true,
       "license": "MIT",
       "peer": true,
       "dependencies": {
         "cac": "^6.7.14",
         "debug": "^4.4.0",
-        "es-module-lexer": "^1.6.0",
+        "es-module-lexer": "^1.7.0",
         "pathe": "^2.0.3",
         "vite": "^5.0.0 || ^6.0.0"
       },
@@ -6548,20 +6441,20 @@
       }
     },
     "node_modules/vitest": {
-      "version": "3.1.2",
-      "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.1.2.tgz",
-      "integrity": "sha512-WaxpJe092ID1C0mr+LH9MmNrhfzi8I65EX/NRU/Ld016KqQNRgxSOlGNP1hHN+a/F8L15Mh8klwaF77zR3GeDQ==",
+      "version": "3.1.3",
+      "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.1.3.tgz",
+      "integrity": "sha512-188iM4hAHQ0km23TN/adso1q5hhwKqUpv+Sd6p5sOuh6FhQnRNW3IsiIpvxqahtBabsJ2SLZgmGSpcYK4wQYJw==",
       "dev": true,
       "license": "MIT",
       "peer": true,
       "dependencies": {
-        "@vitest/expect": "3.1.2",
-        "@vitest/mocker": "3.1.2",
-        "@vitest/pretty-format": "^3.1.2",
-        "@vitest/runner": "3.1.2",
-        "@vitest/snapshot": "3.1.2",
-        "@vitest/spy": "3.1.2",
-        "@vitest/utils": "3.1.2",
+        "@vitest/expect": "3.1.3",
+        "@vitest/mocker": "3.1.3",
+        "@vitest/pretty-format": "^3.1.3",
+        "@vitest/runner": "3.1.3",
+        "@vitest/snapshot": "3.1.3",
+        "@vitest/spy": "3.1.3",
+        "@vitest/utils": "3.1.3",
         "chai": "^5.2.0",
         "debug": "^4.4.0",
         "expect-type": "^1.2.1",
@@ -6574,7 +6467,7 @@
         "tinypool": "^1.0.2",
         "tinyrainbow": "^2.0.0",
         "vite": "^5.0.0 || ^6.0.0",
-        "vite-node": "3.1.2",
+        "vite-node": "3.1.3",
         "why-is-node-running": "^2.3.0"
       },
       "bin": {
@@ -6590,8 +6483,8 @@
         "@edge-runtime/vm": "*",
         "@types/debug": "^4.1.12",
         "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0",
-        "@vitest/browser": "3.1.2",
-        "@vitest/ui": "3.1.2",
+        "@vitest/browser": "3.1.3",
+        "@vitest/ui": "3.1.3",
         "happy-dom": "*",
         "jsdom": "*"
       },
@@ -6758,15 +6651,6 @@
         "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
       }
     },
-    "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": {
-      "version": "5.0.1",
-      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
-      "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=8"
-      }
-    },
     "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": {
       "version": "8.0.0",
       "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
@@ -6812,9 +6696,9 @@
       }
     },
     "node_modules/ws": {
-      "version": "8.18.1",
-      "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.1.tgz",
-      "integrity": "sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w==",
+      "version": "8.18.2",
+      "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.2.tgz",
+      "integrity": "sha512-DMricUmwGZUVr++AEAe2uiVM7UoO9MAVZMDu05UQOaUII0lp+zOzLLU4Xqh/JvTqklB1T4uELaaPBKyjE1r4fQ==",
       "dev": true,
       "license": "MIT",
       "engines": {
@@ -6858,15 +6742,15 @@
       "license": "ISC"
     },
     "node_modules/yaml": {
-      "version": "2.7.1",
-      "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.7.1.tgz",
-      "integrity": "sha512-10ULxpnOCQXxJvBgxsn9ptjq6uviG/htZKk9veJGhlqn3w/DxQ631zFF+nlQXLwmImeS5amR2dl2U8sg6U9jsQ==",
+      "version": "2.8.0",
+      "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.0.tgz",
+      "integrity": "sha512-4lLa/EcQCB0cJkyts+FpIRx5G/llPxfP6VQU5KByHEhLxY3IJCH0f0Hy1MHI8sClTvsIb8qwRJ6R/ZdlDJ/leQ==",
       "license": "ISC",
       "bin": {
         "yaml": "bin.mjs"
       },
       "engines": {
-        "node": ">= 14"
+        "node": ">= 14.6"
       }
     },
     "node_modules/yocto-queue": {
@@ -6884,9 +6768,9 @@
       }
     },
     "node_modules/zustand": {
-      "version": "5.0.3",
-      "resolved": "https://registry.npmjs.org/zustand/-/zustand-5.0.3.tgz",
-      "integrity": "sha512-14fwWQtU3pH4dE0dOpdMiWjddcH+QzKIgk1cl8epwSE7yag43k/AD/m4L6+K7DytAOr9gGBe3/EXj9g7cdostg==",
+      "version": "5.0.4",
+      "resolved": "https://registry.npmjs.org/zustand/-/zustand-5.0.4.tgz",
+      "integrity": "sha512-39VFTN5InDtMd28ZhjLyuTnlytDr9HfwO512Ai4I8ZABCoyAj4F1+sr7sD1jP/+p7k77Iko0Pb5NhgBFDCX0kQ==",
       "license": "MIT",
       "engines": {
         "node": ">=12.20.0"
diff --git a/package.json b/package.json
index 575e48fb..19a56056 100644
--- a/package.json
+++ b/package.json
@@ -45,6 +45,7 @@
     "@testing-library/jest-dom": "^6.6.3",
     "@testing-library/react": "^16.3.0",
     "@testing-library/user-event": "^14.6.1",
+    "@types/node": "^22.15.18",
     "@types/react": "^18.3.18",
     "@types/react-dom": "^18.3.5",
     "@typescript-eslint/parser": "^8.20.0",
diff --git a/src/components/layout/ChannelList.tsx b/src/components/layout/ChannelList.tsx
index d8bfc4c1..b710ab29 100644
--- a/src/components/layout/ChannelList.tsx
+++ b/src/components/layout/ChannelList.tsx
@@ -1,4 +1,4 @@
-import type React from "react";
+import type * as React from "react";
 import { useState } from "react";
 import {
   FaChevronDown,
@@ -17,7 +17,7 @@ import TouchableContextMenu from "../mobile/TouchableContextMenu";
 
 export const ChannelList: React.FC<{
   onToggle: () => void;
-}> = ({ onToggle }) => {
+}> = ({ onToggle }: { onToggle: () => void }) => {
   const {
     servers,
     ui: { selectedServerId, selectedChannelId },
@@ -87,8 +87,7 @@ export const ChannelList: React.FC<{
               `}
               onClick={() => selectChannel(null)}
             >
-              <FaHashtag />
-              <span>Welcome</span>
+              Discover
             </div>
           </div>
         )}
diff --git a/src/components/layout/ChatArea.tsx b/src/components/layout/ChatArea.tsx
index fe6d6bdc..5a373592 100644
--- a/src/components/layout/ChatArea.tsx
+++ b/src/components/layout/ChatArea.tsx
@@ -1,6 +1,6 @@
 import { UsersIcon } from "@heroicons/react/24/solid";
 import { platform } from "@tauri-apps/plugin-os";
-import type React from "react";
+import type * as React from "react";
 import { useEffect, useRef, useState } from "react";
 import {
   FaArrowDown,
@@ -8,19 +8,24 @@ import {
   FaBell,
   FaChevronLeft,
   FaChevronRight,
+  FaGift,
   FaGrinAlt,
   FaHashtag,
-  FaPenAlt,
+  FaPenAlt, // Added
   FaPlus,
   FaReply,
   FaSearch,
   FaTimes,
+  FaUserPlus, // Added
 } from "react-icons/fa";
+
 import { useMediaQuery } from "../../hooks/useMediaQuery";
 import ircClient from "../../lib/ircClient";
 import useStore from "../../store";
 import type { Message as MessageType, User } from "../../types";
+import BlankPage from "../ui/BlankPage";
 import EmojiSelector from "../ui/EmojiSelector";
+import DiscoverGrid from "../ui/HomeScreen";
 
 const EMPTY_ARRAY: User[] = [];
 let lastTypingTime = 0;
@@ -32,16 +37,16 @@ export const OptionsDropdown: React.FC<{
   if (!isOpen) return null;
 
   return (
-    <div className="absolute right-0 mt-2 w-48 bg-white rounded-md shadow-lg z-10">
+    <div className="absolute right-0 mt-2 w-48 bg-discord-dark-300 rounded-md shadow-xl z-10 border border-discord-dark-500">
       <div className="py-1">
         <button
-          className="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 w-full text-left"
+          className="block px-4 py-2 text-sm text-discord-text-muted hover:bg-discord-dark-200 hover:text-white w-full text-left transition-colors duration-150"
           onClick={onClose}
         >
           Option 1
         </button>
         <button
-          className="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 w-full text-left"
+          className="block px-4 py-2 text-sm text-discord-text-muted hover:bg-discord-dark-200 hover:text-white w-full text-left transition-colors duration-150"
           onClick={onClose}
         >
           Option 2
@@ -173,9 +178,7 @@ const MessageItem: React.FC<{
             <div className="w-8" />
           </div>
         )}
-        <div
-          className={`flex-1 ${isCurrentUser ? "text-white" : ""} text-pretty md:text-balance`}
-        >
+        <div className={`flex-1 ${isCurrentUser ? "text-white" : ""}`}>
           {showHeader && (
             <div className="flex items-center">
               <span className="font-bold text-white">
@@ -425,12 +428,14 @@ export const ChatArea: React.FC<{
               {isNarrowView ? <FaChevronLeft /> : <FaChevronRight />}
             </button>
           )}
-          <FaHashtag className="text-discord-text-muted mr-2" />
-          <h2 className="font-bold text-white mr-4">
-            {selectedChannel
-              ? selectedChannel.name.replace(/^#/, "")
-              : "welcome"}
-          </h2>
+          {selectedChannel && (
+            <>
+              <FaHashtag className="text-discord-text-muted mr-2" />
+              <h2 className="font-bold text-white mr-4">
+                {selectedChannel.name.replace(/^#/, "")}
+              </h2>
+            </>
+          )}
           {selectedChannel?.topic && (
             <>
               <div className="mx-2 text-discord-text-muted">|</div>
@@ -447,6 +452,9 @@ export const ChatArea: React.FC<{
           <button className="hover:text-discord-text-normal">
             <FaPenAlt />
           </button>
+          <button className="hover:text-discord-text-normal">
+            <FaUserPlus />
+          </button>
           <button
             className="hover:text-discord-text-normal"
             onClick={() => toggleMemberList(!isMemberListVisible)}
@@ -475,21 +483,26 @@ export const ChatArea: React.FC<{
       </div>
 
       {/* Messages area */}
-      <div
-        ref={messagesContainerRef}
-        className="flex-grow overflow-y-auto flex flex-col bg-discord-dark-200 text-discord-text-normal relative"
-      >
-        {channelMessages.map((message, index) => {
-          const previousMessage = channelMessages[index - 1];
-          const showHeader =
-            !previousMessage ||
-            previousMessage.userId !== message.userId ||
-            new Date(message.timestamp).getTime() -
-              new Date(previousMessage.timestamp).getTime() >
-              5 * 60 * 1000;
-
-          return (
-            <div key={message.id} className="text-pretty md:text-balance">
+      {selectedServer && !selectedChannel && (
+        <div className="flex-grow flex flex-col items-center justify-center bg-discord-dark-200">
+          <BlankPage /> {/* Render the blank page */}
+        </div>
+      )}
+      {selectedChannel && (
+        <div
+          ref={messagesContainerRef}
+          className="flex-grow overflow-y-auto flex flex-col bg-discord-dark-200 text-discord-text-normal relative"
+        >
+          {channelMessages.map((message, index) => {
+            const previousMessage = channelMessages[index - 1];
+            const showHeader =
+              !previousMessage ||
+              previousMessage.userId !== message.userId ||
+              new Date(message.timestamp).getTime() -
+                new Date(previousMessage.timestamp).getTime() >
+                5 * 60 * 1000;
+
+            return (
               <MessageItem
                 key={message.id}
                 message={message}
@@ -503,11 +516,12 @@ export const ChatArea: React.FC<{
                 showHeader={showHeader}
                 setReplyTo={setLocalReplyTo}
               />
-            </div>
-          );
-        })}
-        <div ref={messagesEndRef} />
-      </div>
+            );
+          })}
+          <div ref={messagesEndRef} />
+        </div>
+      )}
+      {!selectedServer && <DiscoverGrid />}
       {/* Scroll to bottom button */}
       {isScrolledUp && (
         <div className="relative bottom-10 z-50">
@@ -568,6 +582,9 @@ export const ChatArea: React.FC<{
             >
               <FaGrinAlt />
             </button>
+            <button className="px-3 text-discord-text-muted hover:text-discord-text-normal">
+              <FaGift />
+            </button>
             <button className="px-3 text-discord-text-muted hover:text-discord-text-normal">
               <FaAt />
             </button>
diff --git a/src/components/ui/AddServerModal.tsx b/src/components/ui/AddServerModal.tsx
index f757df2e..4bbf8783 100644
--- a/src/components/ui/AddServerModal.tsx
+++ b/src/components/ui/AddServerModal.tsx
@@ -1,11 +1,16 @@
 import type React from "react";
-import { useState } from "react";
+import { useEffect, useState } from "react";
 import { FaQuestionCircle, FaTimes } from "react-icons/fa";
 import useStore from "../../store";
 
 export const AddServerModal: React.FC = () => {
-  const { toggleAddServerModal, connect, isConnecting, connectionError } =
-    useStore();
+  const {
+    toggleAddServerModal,
+    connect,
+    isConnecting,
+    connectionError,
+    ui: { prefillServerDetails },
+  } = useStore();
 
   const [serverName, setServerName] = useState("");
   const [serverHost, setServerHost] = useState("");
@@ -23,6 +28,15 @@ export const AddServerModal: React.FC = () => {
 
   const [error, setError] = useState("");
 
+  useEffect(() => {
+    if (prefillServerDetails) {
+      setServerName(prefillServerDetails.name);
+      setServerHost(prefillServerDetails.host);
+      setServerPort(prefillServerDetails.port);
+      setNickname(prefillServerDetails.nickname);
+    }
+  }, [prefillServerDetails]);
+
   const handleSubmit = async (e: React.FormEvent) => {
     e.preventDefault();
     setError("");
diff --git a/src/components/ui/BlankPage.tsx b/src/components/ui/BlankPage.tsx
new file mode 100644
index 00000000..73915c2d
--- /dev/null
+++ b/src/components/ui/BlankPage.tsx
@@ -0,0 +1,22 @@
+import type * as React from "react";
+import useStore from "../../store";
+
+const BlankPage: React.FC = () => {
+  const {
+    servers,
+    ui: { selectedServerId },
+  } = useStore();
+  const server = servers.find((s) => s.id === selectedServerId);
+
+  return (
+    <div className="flex flex-col items-center justify-center h-full text-discord-text-muted">
+      <div className="text-6xl mb-4">👋</div>
+      <h2 className="text-xl font-semibold">
+        Welcome to {server?.name || "the unknown"}!
+      </h2>
+      <p className="text-sm mt-2">Select or add a channel to get started.</p>
+    </div>
+  );
+};
+
+export default BlankPage;
diff --git a/src/components/ui/HomeScreen.tsx b/src/components/ui/HomeScreen.tsx
new file mode 100644
index 00000000..8043b6cf
--- /dev/null
+++ b/src/components/ui/HomeScreen.tsx
@@ -0,0 +1,94 @@
+import { useEffect, useState } from "react";
+import { FaPlus } from "react-icons/fa";
+import useStore from "../../store";
+
+const DiscoverGrid = () => {
+  const { toggleAddServerModal, connect, isConnecting, connectionError } =
+    useStore();
+  const [query, setQuery] = useState("");
+  const [servers, setServers] = useState<
+    { name: string; description: string; server?: string; port?: string }[]
+  >([]);
+
+  useEffect(() => {
+    const fetchServers = async () => {
+      try {
+        const response = await fetch(
+          "https://raw.githubusercontent.com/ObsidianIRC/server-list/refs/heads/main/servers.json",
+        );
+        if (!response.ok) {
+          throw new Error("Failed to fetch servers");
+        }
+        const data = await response.json();
+        setServers(data);
+      } catch (error) {
+        console.error("Error fetching servers:", error);
+      }
+    };
+
+    fetchServers();
+  }, []); // Empty dependency array ensures this runs only once
+
+  const filteredServers = servers.filter(
+    (server) =>
+      server.name.toLowerCase().includes(query.toLowerCase()) ||
+      server.description.toLowerCase().includes(query.toLowerCase()),
+  );
+
+  const handleServerClick = (server: Record<string, string>) => {
+    toggleAddServerModal(true, {
+      name: server.name,
+      host: server.server || "", // Use empty string if server is undefined
+      port: server.port || "443", // Default to 443 if port is undefined
+      nickname: "", // Generate a default nickname
+    });
+  };
+
+  return (
+    <div className="h-screen flex flex-col bg-discord-dark-200 text-white">
+      <div className="m-1 rounded z-10 bg-discord-dark-300 border-b border-discord-dark-500 p-4">
+        <h1 className="rounded-lg text-2xl font-bold mb-2">
+          Discover the world of IRC with ObsidianIRC
+        </h1>
+
+        <div className="bg-discord-dark-100 rounded-lg flex items-center px-2 py-2">
+          <button className="px-2 text-discord-text-muted hover:text-discord-text-normal">
+            <a
+              href="https://github.com/ObsidianIRC/server-list"
+              target="_blank"
+              rel="noreferrer"
+            >
+              <FaPlus />
+            </a>
+          </button>
+          <input
+            placeholder="Search servers..."
+            value={query}
+            onChange={(e) => setQuery(e.target.value)}
+            className="bg-transparent border-none outline-none flex-grow text-discord-text-normal placeholder-discord-text-muted"
+          />
+        </div>
+      </div>
+      {filteredServers.length > 0 ? (
+        <div className="grid p-4 grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4">
+          {filteredServers.map((server) => (
+            <div
+              key={server.name} // Use a unique identifier as the key
+              className="bg-discord-dark-300 border border-discord-dark-500 rounded-lg p-4 shadow hover:shadow-lg transition-shadow cursor-pointer"
+              onClick={() => handleServerClick(server)} // Add click handler
+            >
+              <h2 className="text-lg font-semibold">{server.name}</h2>
+              <p className="text-sm text-discord-text-muted">
+                {server.description}
+              </p>
+            </div>
+          ))}
+        </div>
+      ) : (
+        <p className="text-discord-text-muted">No servers found.</p>
+      )}
+    </div>
+  );
+};
+
+export default DiscoverGrid;
diff --git a/src/lib/ircClient.ts b/src/lib/ircClient.ts
index a5952c89..ed7ab63c 100644
--- a/src/lib/ircClient.ts
+++ b/src/lib/ircClient.ts
@@ -55,7 +55,7 @@ export interface EventMap {
   NAMES: { serverId: string; channelName: string; users: User[] };
   "CAP LS": { serverId: string; cliCaps: string };
   "CAP ACK": { serverId: string; cliCaps: string };
-  ISUPPORT: { serverId: string; capabilities: string[] };
+  ISUPPORT: { serverId: string; key: string; value: string };
   CAP_ACKNOWLEDGED: { serverId: string; key: string; capabilities: string };
   CAP_END: { serverId: string };
   AUTHENTICATE: { serverId: string; param: string };
@@ -147,7 +147,7 @@ export class IRCClient {
   disconnect(serverId: string): void {
     const socket = this.sockets.get(serverId);
     if (socket) {
-      socket.send("QUIT :Client disconnecting");
+      socket.send("QUIT :ObsidianIRC - Bringing IRC into the future");
       socket.close();
       this.sockets.delete(serverId);
     }
@@ -423,10 +423,22 @@ export class IRCClient {
         if (subcommand === "LS") this.onCapLs(serverId, caps);
         else if (subcommand === "ACK")
           this.triggerEvent("CAP ACK", { serverId, cliCaps: caps });
-      } else if (line.split(" ")[1] === "005") {
-        console.log("005 detected");
-        const capabilities = parseIsupport(line);
-        this.triggerEvent("ISUPPORT", { serverId, capabilities });
+      } else if (command === "005") {
+        const capabilities = parseIsupport(parv.join(" "));
+        console.log("ISUPPORT capabilities:", capabilities);
+        for (const [key, value] of Object.entries(capabilities)) {
+          if (key === "NETWORK") {
+            const server = this.servers.get(serverId);
+            if (server) {
+              server.name = value;
+              this.servers.set(serverId, server);
+            }
+            console.log(
+              `Network name set to: ${this.servers.get(serverId)?.name}`,
+            );
+          }
+          this.triggerEvent("ISUPPORT", { serverId, key, value });
+        }
       } else if (command === "AUTHENTICATE") {
         const param = parv.join(" ");
         this.triggerEvent("AUTHENTICATE", { serverId, param });
diff --git a/src/lib/ircUtils.ts b/src/lib/ircUtils.ts
index 208ff91f..cced5369 100644
--- a/src/lib/ircUtils.ts
+++ b/src/lib/ircUtils.ts
@@ -41,16 +41,18 @@ export function parseMessageTags(tags: string): Record<string, string> {
   return parsedTags;
 }
 
-export function parseIsupport(line: string): string[] {
-  // Match and remove the prefix up to and including the nick
-  const prefixMatch = line.match(/^:[^\s]+ 005 [^\s]+ /);
-  if (!prefixMatch) return [];
-
-  const remaining = line.slice(prefixMatch[0].length);
-  const trailingIndex = remaining.indexOf(" :");
-
-  const tokenString =
-    trailingIndex !== -1 ? remaining.slice(0, trailingIndex) : remaining;
+export function parseIsupport(tokens: string): Record<string, string> {
+  const tokenMap: Record<string, string> = {};
+  const tokenPairs = tokens.split(" ");
+
+  for (const token of tokenPairs) {
+    const [key, value] = token.split("=");
+    if (value) {
+      tokenMap[key] = value;
+    } else {
+      tokenMap[key] = ""; // empty string fallback
+    }
+  }
 
-  return tokenString.trim().split(/\s+/);
+  return tokenMap;
 }
diff --git a/src/protocol/index.ts b/src/protocol/index.ts
index 8b0498a3..2d15796c 100644
--- a/src/protocol/index.ts
+++ b/src/protocol/index.ts
@@ -1,6 +1,12 @@
+import type { StoreApi } from "zustand";
+import type { UseBoundStore } from "zustand";
 import type { IRCClient } from "../lib/ircClient";
+import type { AppState } from "../store/";
 import { registerISupportHandler } from "./isupport";
 
-export function registerAllProtocolHandlers(ircClient: IRCClient) {
-  registerISupportHandler(ircClient);
+export function registerAllProtocolHandlers(
+  ircClient: IRCClient,
+  useStore: UseBoundStore<StoreApi<AppState>>,
+) {
+  registerISupportHandler(ircClient, useStore);
 }
diff --git a/src/protocol/isupport.ts b/src/protocol/isupport.ts
index 651210c8..326b388f 100644
--- a/src/protocol/isupport.ts
+++ b/src/protocol/isupport.ts
@@ -1,26 +1,51 @@
 import type { IRCClient } from "../lib/ircClient";
-import useStore from "../store";
-import type { ISupportEvent } from "../types/";
+import type AppState from "../store/";
+import type { Server } from "../types/";
 
-export function registerISupportHandler(ircClient: IRCClient) {
-  ircClient.on("ISUPPORT", ({ serverId, capabilities }: ISupportEvent) => {
-    const paramsArray = capabilities;
-    console.log(capabilities);
+export function registerISupportHandler(
+  ircClient: IRCClient,
+  useStore: typeof AppState,
+) {
+  ircClient.on("ISUPPORT", ({ serverId, key, value }) => {
+    if (key === "FAVICON") {
+      const favicon = value;
+      useStore.setState((state) => {
+        const updatedServers = state.servers.map((server: Server) => {
+          if (server.id === serverId) {
+            return { ...server, icon: favicon };
+          }
+          return server;
+        });
+        return { servers: updatedServers };
+      });
+      return;
+    }
+
+    if (key === "NETWORK") {
+      useStore.setState((state) => {
+        const updatedServers = state.servers.map((server: Server) => {
+          if (server.id === serverId) {
+            return { ...server, name: value };
+          }
+          return server;
+        });
+        return { servers: updatedServers };
+      });
+      return;
+    }
 
-    for (let i = 0; i < paramsArray.length; i++) {
-      /* Favicon checking */
-      if (paramsArray[i].startsWith("FAVICON=")) {
-        const favicon = paramsArray[i].substring(8);
-        useStore.setState((state) => {
-          const updatedServers = state.servers.map((server) => {
-            if (server.id === serverId) {
-              return { ...server, icon: favicon };
-            }
-            return server;
-          });
-          return { servers: updatedServers };
+    if (key === "PREFIX") {
+      const prefix = value;
+      useStore.setState((state) => {
+        const updatedServers = state.servers.map((server: Server) => {
+          if (server.id === serverId) {
+            return { ...server, prefix };
+          }
+          return server;
         });
-      }
+        return { servers: updatedServers };
+      });
+      return;
     }
   });
 }
diff --git a/src/store/index.ts b/src/store/index.ts
index 35de7609..45145956 100644
--- a/src/store/index.ts
+++ b/src/store/index.ts
@@ -1,8 +1,8 @@
 import { v4 as uuidv4 } from "uuid";
 import { create } from "zustand";
 import ircClient from "../lib/ircClient";
+import { registerAllProtocolHandlers } from "../protocol";
 import type { Channel, Message, Server, ServerConfig, User } from "../types";
-import type { ISupportEvent } from "../types/";
 
 const LOCAL_STORAGE_SERVERS_KEY = "savedServers";
 
@@ -32,7 +32,7 @@ function saveServersToLocalStorage(servers: ServerConfig[]) {
 interface UIState {
   selectedServerId: string | null;
   selectedChannelId: string | null;
-  isAddServerModalOpen: boolean;
+  isAddServerModalOpen: boolean | undefined;
   isSettingsModalOpen: boolean;
   isUserProfileModalOpen: boolean;
   isDarkMode: boolean;
@@ -48,16 +48,23 @@ interface UIState {
     type: "server" | "channel" | "user" | "message";
     itemId: string | null;
   };
+  prefillServerDetails: {
+    name: string;
+    host: string;
+    port: string;
+    nickname: string;
+  } | null;
 }
 
 interface GlobalSettings {
   enableNotifications: boolean;
 }
 
-interface AppState {
+export interface AppState {
   servers: Server[];
   currentUser: User | null;
   isConnecting: boolean;
+  selectedServerId: string | null;
   connectionError: string | null;
   messages: Record<string, Message[]>;
   typingUsers: Record<string, User[]>;
@@ -85,7 +92,15 @@ interface AppState {
   connectToSavedServers: () => void; // New action to load servers from localStorage
   deleteServer: (serverId: string) => void; // New action to delete a server
   // UI actions
-  toggleAddServerModal: (isOpen?: boolean) => void;
+  toggleAddServerModal: (
+    isOpen?: boolean,
+    prefillDetails?: {
+      name: string;
+      host: string;
+      port: string;
+      nickname: string;
+    } | null,
+  ) => void;
   toggleSettingsModal: (isOpen?: boolean) => void;
   toggleUserProfileModal: (isOpen?: boolean) => void;
   toggleDarkMode: () => void;
@@ -111,6 +126,7 @@ const useStore = create<AppState>((set, get) => ({
   connectionError: null,
   messages: {},
   typingUsers: {},
+  selectedServerId: null,
 
   // UI state
   ui: {
@@ -132,6 +148,7 @@ const useStore = create<AppState>((set, get) => ({
       type: "server",
       itemId: null,
     },
+    prefillServerDetails: null,
   },
   globalSettings: {
     enableNotifications: false,
@@ -502,12 +519,12 @@ const useStore = create<AppState>((set, get) => ({
   },
 
   // UI actions
-  toggleAddServerModal: (isOpen) => {
+  toggleAddServerModal: (isOpen, prefillDetails = null) => {
     set((state) => ({
       ui: {
         ...state.ui,
-        isAddServerModalOpen:
-          isOpen !== undefined ? isOpen : !state.ui.isAddServerModalOpen,
+        isAddServerModalOpen: isOpen,
+        prefillServerDetails: prefillDetails,
       },
     }));
   },
@@ -630,6 +647,9 @@ const useStore = create<AppState>((set, get) => ({
   },
 }));
 
+// Initialize protocol handlers
+registerAllProtocolHandlers(ircClient, useStore);
+
 // Set up event listeners for IRC client events
 //
 // TODO: We should have actual events here, The commended ones are never fired and seems to be causing a bug with the state management
@@ -1062,27 +1082,6 @@ ircClient.on("TAGMSG", (response) => {
   }
 });
 
-ircClient.on("ISUPPORT", ({ serverId, capabilities }: ISupportEvent) => {
-  const paramsArray = capabilities;
-  console.log(capabilities);
-
-  for (let i = 0; i < paramsArray.length; i++) {
-    /* Favicon checking */
-    if (paramsArray[i].startsWith("FAVICON=")) {
-      const favicon = paramsArray[i].substring(8);
-      useStore.setState((state) => {
-        const updatedServers = state.servers.map((server) => {
-          if (server.id === serverId) {
-            return { ...server, icon: favicon };
-          }
-          return server;
-        });
-        return { servers: updatedServers };
-      });
-    }
-  }
-});
-
 // Load saved servers on store initialization
 useStore.getState().connectToSavedServers();
 
diff --git a/tsconfig.tsbuildinfo b/tsconfig.tsbuildinfo
index e994cb45..9fd0b8f4 100644
--- a/tsconfig.tsbuildinfo
+++ b/tsconfig.tsbuildinfo
@@ -1 +1 @@
-{"root":["./src/app.tsx","./src/main.tsx","./src/vite-env.d.ts","./src/components/layout/applayout.tsx","./src/components/layout/channellist.tsx","./src/components/layout/chatarea.tsx","./src/components/layout/memberlist.tsx","./src/components/layout/resizablesidebar.tsx","./src/components/layout/serverlist.tsx","./src/components/mobile/touchablecontextmenu.tsx","./src/components/ui/addservermodal.tsx","./src/components/ui/emojiselector.tsx","./src/components/ui/usersettings.tsx","./src/hooks/usemediaquery.ts","./src/lib/ircclient.ts","./src/lib/ircutils.ts","./src/protocol/index.ts","./src/protocol/isupport.ts","./src/store/index.ts","./src/store/types.ts","./src/types/index.ts","./vite.config.ts"],"version":"5.6.3"}
\ No newline at end of file
+{"root":["./src/App.tsx","./src/main.tsx","./src/vite-env.d.ts","./src/components/layout/AppLayout.tsx","./src/components/layout/ChannelList.tsx","./src/components/layout/ChatArea.tsx","./src/components/layout/MemberList.tsx","./src/components/layout/ResizableSidebar.tsx","./src/components/layout/ServerList.tsx","./src/components/mobile/TouchableContextMenu.tsx","./src/components/ui/AddServerModal.tsx","./src/components/ui/BlankPage.tsx","./src/components/ui/EmojiSelector.tsx","./src/components/ui/HomeScreen.tsx","./src/components/ui/UserSettings.tsx","./src/hooks/useMediaQuery.ts","./src/lib/ircClient.ts","./src/lib/ircUtils.ts","./src/protocol/index.ts","./src/protocol/isupport.ts","./src/store/index.ts","./src/store/types.ts","./src/types/index.ts","./vite.config.ts"],"version":"5.6.3"}
\ No newline at end of file


Reviews:
user: login: copilot-pull-request-reviewer[bot]
body: ## Pull Request Overview

Adds a home/discovery screen to load servers from a JSON list, prefilling the add-server modal when a server tile is clicked, and modularizes protocol event handling.

- Introduces `HomeScreen` (DiscoverGrid) component with caching and filtering of a remote server list.
- Extends store with `prefillServerDetails` and updates `toggleAddServerModal` signature.
- Refactors ISUPPORT handler into `protocol/` modules and initializes them in the store.

### Reviewed Changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated no comments.

<details>
<summary>Show a summary per file</summary>

| File                          | Description                                                                                         |
| ----------------------------- | --------------------------------------------------------------------------------------------------- |
| tsconfig.tsbuildinfo          | Updated build cache paths to PascalCase filenames.                                                  |
| src/store/index.ts            | Added `prefillServerDetails`, expanded `toggleAddServerModal`, and initialized `registerAllProtocolHandlers`. |
| src/protocol/isupport.ts      | Refactored ISUPPORT handler to accept `useStore` as a parameter.                                    |
| src/protocol/index.ts         | Updated `registerAllProtocolHandlers` to forward `useStore`.                                        |
| src/components/ui/HomeScreen.tsx | New `DiscoverGrid` component for the home screen with server fetching, caching, and filtering.      |
| src/components/ui/AddServerModal.tsx | Populates form fields from `prefillServerDetails` via `useEffect`.                                    |
| src/components/layout/ChatArea.tsx  | Renders `DiscoverGrid` / `BlankPage` based on selection and adjusts header logic and icons.         |
| src/components/layout/ChannelList.tsx | Renames the “Welcome” tab to “Discover”.                                                           |
| package.json                  | Added `@radix-ui/react-popover` and moved type packages.                                            |
</details>



<details>
<summary>Comments suppressed due to low confidence (7)</summary>

**src/components/ui/HomeScreen.tsx:5**
* [nitpick] Component name `DiscoverGrid` does not match file name `HomeScreen.tsx`. Consider renaming the component or the file for consistency.
```
const DiscoverGrid = () => {
```
**src/store/index.ts:526**
* toggleAddServerModal now sets isAddServerModalOpen directly from isOpen, so calling it without an explicit parameter assigns undefined. Consider restoring toggle behavior by checking `isOpen !== undefined ? isOpen : !state.ui.isAddServerModalOpen`.
```
isAddServerModalOpen: isOpen,
```
**src/store/index.ts:67**
* [nitpick] AppState now includes a top-level `selectedServerId` in addition to `ui.selectedServerId`, leading to duplicate sources of truth. Consider consolidating to a single state location.
```
selectedServerId: string | null;
```
**src/protocol/isupport.ts:2**
* Importing `AppState` as a default export may be incorrect since it's exported as a named interface. Also, `useStore` should be typed as a `UseBoundStore<StoreApi<AppState>>` rather than `typeof AppState`.
```
import type AppState from "../store/";
```
**src/components/ui/HomeScreen.tsx:93**
* Using `server.name` as a React key may lead to duplicate keys if names repeat. Consider using a unique identifier like host or a generated id.
```
key={server.name} // Use a unique identifier as the key
```
**package.json:49**
* `@types/node` should be a devDependency rather than a regular dependency.
```
"@types/node": "^22.15.18",
```
**package.json:27**
* [nitpick] The `@radix-ui/react-popover` dependency isn't referenced in this PR. If it's unused, consider removing it to keep dependencies lean.
```
"@radix-ui/react-popover": "^1.1.13",
```
</details>


state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-17T19:52:32Z
user: login: matheusfillipe
body: it is ok to merge as it is IMO but left some feedback.

Another weird thing is that the server name isn't really displayed here where I think it should:
![image](https://github.com/user-attachments/assets/4984f9aa-aa08-4ac4-b55a-848f26000d52)

it is the hostname instead
Also in the tooltips.
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-17T20:09:38Z
user: login: ValwareIRC
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-18T13:26:30Z
user: login: copilot-pull-request-reviewer[bot]
body: ## Pull Request Overview

This PR adds a discovery homescreen driven by a remote JSON list, prefill logic for the add-server modal, and refactors how ISUPPORT messages are parsed and handled.

- Introduces `DiscoverGrid` to fetch and display community servers and integrates it into `ChatArea`.
- Adds `prefillServerDetails` to store/UI state and wires it through `toggleAddServerModal` and `AddServerModal`.
- Refactors ISUPPORT handling: new `parseIsupport` map output, `registerISupportHandler`, and centralized registration in `protocol/index.ts`.

### Reviewed Changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 5 comments.

<details>
<summary>Show a summary per file</summary>

| File                             | Description                                                  |
| -------------------------------- | ------------------------------------------------------------ |
| tsconfig.tsbuildinfo             | Updated root file list to match renamed/PascalCase components|
| src/store/index.ts               | Added `prefillServerDetails` state and extended `toggleAddServerModal` action |
| src/protocol/isupport.ts         | Refactored ISUPPORT handler to key/value events              |
| src/protocol/index.ts            | Registered all protocol handlers with the store              |
| src/lib/ircUtils.ts              | Changed `parseIsupport` to return a key/value map            |
| src/lib/ircClient.ts             | Updated raw 005 parsing to use new map and trigger ISUPPORT events |
| src/components/ui/HomeScreen.tsx | New `DiscoverGrid` component for server discovery            |
| src/components/ui/BlankPage.tsx  | New blank welcome page for server-only selection             |
| src/components/ui/AddServerModal.tsx | Integrated prefill data into the add-server form        |
| src/components/layout/ChatArea.tsx | Hooks up discovery/blank views and adds new UI icons      |
| src/components/layout/ChannelList.tsx | Renamed default view label and tightened prop types     |
| package.json                     | Added `@types/node` for JSON fetching support               |
</details>



<details>
<summary>Comments suppressed due to low confidence (3)</summary>

**src/components/layout/ChatArea.tsx:324**
* You’ve swapped the order of `joinChannel` and its `JOIN` event; firing the event before actually joining can lead to inconsistent state. Call `joinChannel` first, then `triggerEvent`.
```
ircClient.triggerEvent("JOIN", {
```
**src/store/index.ts:35**
* Changing `isAddServerModalOpen` to `boolean | undefined` may introduce `undefined` states; consider keeping it `boolean` and defaulting to `false` in initial state.
```
isAddServerModalOpen: boolean | undefined;
```
**src/store/index.ts:522**
* The toggle logic now always sets `isAddServerModalOpen` to `isOpen`, so calling without arguments leaves it `undefined`; restore a fallback like `isOpen !== undefined ? isOpen : !state.ui.isAddServerModalOpen`.
```
toggleAddServerModal: (isOpen, prefillDetails = null) => {
```
</details>


state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-18T13:49:49Z
user: login: ValwareIRC
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-18T14:01:50Z
user: login: ValwareIRC
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-18T14:02:44Z
user: login: ValwareIRC
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-18T14:04:38Z

Review comments:
diff_hunk: @@ -24,6 +24,7 @@
   },
   "dependencies": {
     "@heroicons/react": "^2.2.0",
+    "@radix-ui/react-popover": "^1.1.13",
path: package.json
user: login: matheusfillipe
body: If this is not used, please remove before merging:
```sh
npm remove @radix-ui/react-popover
```
created_at: 2025-05-17T19:59:54Z
author_association: CONTRIBUTOR
path: src/components/ui/BlankPage.tsx
user: login: matheusfillipe
body: NICE!
created_at: 2025-05-17T20:01:46Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,13 @@
+import type React from "react";
+
+const BlankPage: React.FC = () => {
+  return (
+    <div className="flex flex-col items-center justify-center h-full text-discord-text-muted">
+      <div className="text-6xl mb-4">👋</div>
+      <h2 className="text-xl font-semibold">Welcome to your server!</h2>
+      <p className="text-sm mt-2">Select a channel to get started.</p>
path: src/components/ui/BlankPage.tsx
user: login: matheusfillipe
body: ```suggestion
      <p className="text-sm mt-2">Select or add a channel to get started.</p>
```
created_at: 2025-05-17T20:02:22Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,13 @@
+import type React from "react";
+
+const BlankPage: React.FC = () => {
+  return (
+    <div className="flex flex-col items-center justify-center h-full text-discord-text-muted">
+      <div className="text-6xl mb-4">👋</div>
+      <h2 className="text-xl font-semibold">Welcome to your server!</h2>
path: src/components/ui/BlankPage.tsx
user: login: matheusfillipe
body: Could be a prop and display the name of the server like "Welcome to h4ks" but minor nitpick
created_at: 2025-05-17T20:03:02Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,111 @@
+import { useEffect, useState } from "react";
+import { FaPlus } from "react-icons/fa";
+import useStore from "../../store";
+
+const DiscoverGrid = () => {
+  const { toggleAddServerModal, connect, isConnecting, connectionError } =
+    useStore();
+  const [query, setQuery] = useState("");
+  const [servers, setServers] = useState<
+    { name: string; description: string; server?: string; port?: string }[]
+  >([]);
+
+  useEffect(() => {
+    const fetchServers = async () => {
+      try {
+        const cachedData = localStorage.getItem("servers");
path: src/components/ui/HomeScreen.tsx
user: login: matheusfillipe
body: I am really creeepied by caching issues, do we really need to cache this instead of feathing every open and reload? 🤔 

Makes things so much simpler to test and live updated...
created_at: 2025-05-17T20:05:20Z
author_association: CONTRIBUTOR
diff_hunk: @@ -147,7 +147,7 @@ export class IRCClient {
   disconnect(serverId: string): void {
     const socket = this.sockets.get(serverId);
     if (socket) {
-      socket.send("QUIT :Client disconnecting");
+      socket.send("QUIT :ObsidianIRC - Bringing IRC into the future");
path: src/lib/ircClient.ts
user: login: matheusfillipe
body: Is that going to be our motto? Could be also the package and repo description. We should decide one :D
created_at: 2025-05-17T20:08:11Z
author_association: CONTRIBUTOR
diff_hunk: @@ -147,7 +147,7 @@ export class IRCClient {
   disconnect(serverId: string): void {
     const socket = this.sockets.get(serverId);
     if (socket) {
-      socket.send("QUIT :Client disconnecting");
+      socket.send("QUIT :ObsidianIRC - Bringing IRC into the future");
path: src/lib/ircClient.ts
user: login: ValwareIRC
body: we should!
created_at: 2025-05-18T13:26:30Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,26 +1,51 @@
 import type { IRCClient } from "../lib/ircClient";
-import useStore from "../store";
-import type { ISupportEvent } from "../types/";
+import type AppState from "../store/";
+import type { Server } from "../types/";
 
-export function registerISupportHandler(ircClient: IRCClient) {
-  ircClient.on("ISUPPORT", ({ serverId, capabilities }: ISupportEvent) => {
-    const paramsArray = capabilities;
-    console.log(capabilities);
+export function registerISupportHandler(
path: src/protocol/isupport.ts
user: login: Copilot
body: The second parameter is typed as `typeof AppState`, but that’s an interface not a runtime store type; it should be the Zustand store type (e.g. `UseBoundStore<StoreApi<AppState>>`).
created_at: 2025-05-18T13:49:47Z
author_association: CONTRIBUTOR
diff_hunk: @@ -423,10 +423,22 @@ export class IRCClient {
         if (subcommand === "LS") this.onCapLs(serverId, caps);
         else if (subcommand === "ACK")
           this.triggerEvent("CAP ACK", { serverId, cliCaps: caps });
-      } else if (line.split(" ")[1] === "005") {
-        console.log("005 detected");
-        const capabilities = parseIsupport(line);
-        this.triggerEvent("ISUPPORT", { serverId, capabilities });
+      } else if (command === "005") {
+        const capabilities = parseIsupport(parv.join(" "));
+        console.log("ISUPPORT capabilities:", capabilities);
+        for (const [key, value] of Object.entries(capabilities)) {
+          if (key === "NETWORK") {
+            const server = this.servers.get(serverId);
+            if (server) {
+              server.name = value;
+              this.servers.set(serverId, server);
+            }
+            console.log(
+              `Network name set to: ${this.servers.get(serverId)?.name}`,
+            );
+            this.triggerEvent("ISUPPORT", { serverId, key, value });
+          }
path: src/lib/ircClient.ts
user: login: Copilot
body: Only the `NETWORK` key triggers an ISUPPORT event here, so `FAVICON` and `PREFIX` updates never fire; loop over all keys and emit for each to match your handler branches.
```suggestion
          const server = this.servers.get(serverId);
          if (key === "NETWORK" && server) {
            server.name = value;
            this.servers.set(serverId, server);
            console.log(
              `Network name set to: ${this.servers.get(serverId)?.name}`,
            );
          }
          this.triggerEvent("ISUPPORT", { serverId, key, value });
```
created_at: 2025-05-18T13:49:48Z
author_association: CONTRIBUTOR
diff_hunk: @@ -41,16 +41,18 @@ export function parseMessageTags(tags: string): Record<string, string> {
   return parsedTags;
 }
 
-export function parseIsupport(line: string): string[] {
-  // Match and remove the prefix up to and including the nick
-  const prefixMatch = line.match(/^:[^\s]+ 005 [^\s]+ /);
-  if (!prefixMatch) return [];
-
-  const remaining = line.slice(prefixMatch[0].length);
-  const trailingIndex = remaining.indexOf(" :");
-
-  const tokenString =
-    trailingIndex !== -1 ? remaining.slice(0, trailingIndex) : remaining;
+export function parseIsupport(tokens: string): Record<string, string> {
+  const tokenMap: Record<string, string> = {};
+  const tokenPairs = tokens.split(" ");
+
path: src/lib/ircUtils.ts
user: login: Copilot
body: The raw tokens string may start with a leading colon on the first key (e.g. `:FAVICON=…`), so you should strip any leading `:` before mapping keys to ensure your handler matches exactly.
```suggestion
  let tokenPairs = tokens.split(" ");

  // Strip leading colon from the first token if present
  if (tokenPairs.length > 0 && tokenPairs[0].startsWith(":")) {
    tokenPairs[0] = tokenPairs[0].substring(1);
  }
```
created_at: 2025-05-18T13:49:48Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,94 @@
+import { useEffect, useState } from "react";
+import { FaPlus } from "react-icons/fa";
+import useStore from "../../store";
+
+const DiscoverGrid = () => {
+  const { toggleAddServerModal, connect, isConnecting, connectionError } =
+    useStore();
+  const [query, setQuery] = useState("");
+  const [servers, setServers] = useState<
+    { name: string; description: string; server?: string; port?: string }[]
+  >([]);
+
+  useEffect(() => {
+    const fetchServers = async () => {
+      try {
+        const response = await fetch(
+          "https://raw.githubusercontent.com/ObsidianIRC/server-list/refs/heads/main/servers.json",
+        );
+        if (!response.ok) {
+          throw new Error("Failed to fetch servers");
+        }
+        const data = await response.json();
+        setServers(data);
+      } catch (error) {
+        console.error("Error fetching servers:", error);
+      }
+    };
+
+    fetchServers();
+  }, []); // Empty dependency array ensures this runs only once
+
+  const filteredServers = servers.filter(
+    (server) =>
+      server.name.toLowerCase().includes(query.toLowerCase()) ||
+      server.description.toLowerCase().includes(query.toLowerCase()),
+  );
+
+  const handleServerClick = (server: Record<string, string>) => {
+    toggleAddServerModal(true, {
+      name: server.name,
+      host: server.server || "", // Use empty string if server is undefined
+      port: server.port || "443", // Default to 443 if port is undefined
+      nickname: "", // Generate a default nickname
+    });
+  };
+
+  return (
+    <div className="h-screen flex flex-col bg-discord-dark-200 text-white">
+      <div className="m-1 rounded z-10 bg-discord-dark-300 border-b border-discord-dark-500 p-4">
+        <h1 className="rounded-lg text-2xl font-bold mb-2">
+          Discover the world of IRC with ObsidianIRC
+        </h1>
+
+        <div className="bg-discord-dark-100 rounded-lg flex items-center px-2 py-2">
+          <button className="px-2 text-discord-text-muted hover:text-discord-text-normal">
+            <a
+              href="https://github.com/ObsidianIRC/server-list"
+              target="_blank"
+              rel="noreferrer"
+            >
+              <FaPlus />
+            </a>
+          </button>
+          <input
+            placeholder="Search servers..."
+            value={query}
+            onChange={(e) => setQuery(e.target.value)}
+            className="bg-transparent border-none outline-none flex-grow text-discord-text-normal placeholder-discord-text-muted"
+          />
+        </div>
+      </div>
+      {filteredServers.length > 0 ? (
+        <div className="grid p-4 grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4">
+          {filteredServers.map((server) => (
+            <div
+              key={server.name} // Use a unique identifier as the key
path: src/components/ui/HomeScreen.tsx
user: login: Copilot
body: [nitpick] Using `server.name` as the React key risks collisions if names duplicate; consider using a truly unique identifier (e.g. host+port or an `id` field).
```suggestion
              key={`${server.server || ""}:${server.port || "443"}`} // Use host and port as the unique key
```
created_at: 2025-05-18T13:49:48Z
author_association: CONTRIBUTOR
diff_hunk: @@ -23,6 +28,15 @@ export const AddServerModal: React.FC = () => {
 
   const [error, setError] = useState("");
 
+  useEffect(() => {
+    if (prefillServerDetails) {
+      setServerName(prefillServerDetails.name);
+      setServerHost(prefillServerDetails.host);
+      setServerPort(prefillServerDetails.port);
+      setNickname(prefillServerDetails.nickname);
path: src/components/ui/AddServerModal.tsx
user: login: Copilot
body: The effect pre-fills the form but doesn’t clear fields when `prefillServerDetails` becomes `null`; consider resetting inputs when the modal closes or when details are cleared.
```suggestion
  useEffect(() => {
    return () => {
      setServerName("");
      setServerHost("");
      setServerPort("443");
      setNickname(`user${Math.floor(Math.random() * 1000)}`);
      setPassword("");
      setSaslAccountName("");
      setSaslPassword("");
      setSaslEnabled("");
      setShowServerPassword(false);
      setShowAccount(false);
      setRegisterAccount(false);
    };
  }, [toggleAddServerModal]);

  useEffect(() => {
    if (prefillServerDetails) {
      setServerName(prefillServerDetails.name);
      setServerHost(prefillServerDetails.host);
      setServerPort(prefillServerDetails.port);
      setNickname(prefillServerDetails.nickname);
    } else {
      setServerName("");
      setServerHost("");
      setServerPort("443");
      setNickname(`user${Math.floor(Math.random() * 1000)}`);
      setPassword("");
      setSaslAccountName("");
      setSaslPassword("");
      setSaslEnabled("");
      setShowServerPassword(false);
      setShowAccount(false);
      setRegisterAccount(false);
```
created_at: 2025-05-18T13:49:49Z
author_association: CONTRIBUTOR
diff_hunk: @@ -23,6 +28,15 @@ export const AddServerModal: React.FC = () => {
 
   const [error, setError] = useState("");
 
+  useEffect(() => {
+    if (prefillServerDetails) {
+      setServerName(prefillServerDetails.name);
+      setServerHost(prefillServerDetails.host);
+      setServerPort(prefillServerDetails.port);
+      setNickname(prefillServerDetails.nickname);
path: src/components/ui/AddServerModal.tsx
user: login: ValwareIRC
body: This is a terrible suggestion
created_at: 2025-05-18T14:01:50Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,94 @@
+import { useEffect, useState } from "react";
+import { FaPlus } from "react-icons/fa";
+import useStore from "../../store";
+
+const DiscoverGrid = () => {
+  const { toggleAddServerModal, connect, isConnecting, connectionError } =
+    useStore();
+  const [query, setQuery] = useState("");
+  const [servers, setServers] = useState<
+    { name: string; description: string; server?: string; port?: string }[]
+  >([]);
+
+  useEffect(() => {
+    const fetchServers = async () => {
+      try {
+        const response = await fetch(
+          "https://raw.githubusercontent.com/ObsidianIRC/server-list/refs/heads/main/servers.json",
+        );
+        if (!response.ok) {
+          throw new Error("Failed to fetch servers");
+        }
+        const data = await response.json();
+        setServers(data);
+      } catch (error) {
+        console.error("Error fetching servers:", error);
+      }
+    };
+
+    fetchServers();
+  }, []); // Empty dependency array ensures this runs only once
+
+  const filteredServers = servers.filter(
+    (server) =>
+      server.name.toLowerCase().includes(query.toLowerCase()) ||
+      server.description.toLowerCase().includes(query.toLowerCase()),
+  );
+
+  const handleServerClick = (server: Record<string, string>) => {
+    toggleAddServerModal(true, {
+      name: server.name,
+      host: server.server || "", // Use empty string if server is undefined
+      port: server.port || "443", // Default to 443 if port is undefined
+      nickname: "", // Generate a default nickname
+    });
+  };
+
+  return (
+    <div className="h-screen flex flex-col bg-discord-dark-200 text-white">
+      <div className="m-1 rounded z-10 bg-discord-dark-300 border-b border-discord-dark-500 p-4">
+        <h1 className="rounded-lg text-2xl font-bold mb-2">
+          Discover the world of IRC with ObsidianIRC
+        </h1>
+
+        <div className="bg-discord-dark-100 rounded-lg flex items-center px-2 py-2">
+          <button className="px-2 text-discord-text-muted hover:text-discord-text-normal">
+            <a
+              href="https://github.com/ObsidianIRC/server-list"
+              target="_blank"
+              rel="noreferrer"
+            >
+              <FaPlus />
+            </a>
+          </button>
+          <input
+            placeholder="Search servers..."
+            value={query}
+            onChange={(e) => setQuery(e.target.value)}
+            className="bg-transparent border-none outline-none flex-grow text-discord-text-normal placeholder-discord-text-muted"
+          />
+        </div>
+      </div>
+      {filteredServers.length > 0 ? (
+        <div className="grid p-4 grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4">
+          {filteredServers.map((server) => (
+            <div
+              key={server.name} // Use a unique identifier as the key
path: src/components/ui/HomeScreen.tsx
user: login: ValwareIRC
body: This is a terrible suggestion. I agree it should be unique, but this is not the way. Use the `server.id` identifier instead.
created_at: 2025-05-18T14:02:44Z
author_association: CONTRIBUTOR
diff_hunk: @@ -41,16 +41,18 @@ export function parseMessageTags(tags: string): Record<string, string> {
   return parsedTags;
 }
 
-export function parseIsupport(line: string): string[] {
-  // Match and remove the prefix up to and including the nick
-  const prefixMatch = line.match(/^:[^\s]+ 005 [^\s]+ /);
-  if (!prefixMatch) return [];
-
-  const remaining = line.slice(prefixMatch[0].length);
-  const trailingIndex = remaining.indexOf(" :");
-
-  const tokenString =
-    trailingIndex !== -1 ? remaining.slice(0, trailingIndex) : remaining;
+export function parseIsupport(tokens: string): Record<string, string> {
+  const tokenMap: Record<string, string> = {};
+  const tokenPairs = tokens.split(" ");
+
path: src/lib/ircUtils.ts
user: login: ValwareIRC
body: This is a terrible suggestion since that would break the 005 numeric's syntax requirement.
created_at: 2025-05-18T14:04:38Z
author_association: CONTRIBUTOR

PR comments:
user: login: github-actions[bot]
created_at: 2025-05-13T13:29:28Z
body: [![Pages Preview](https://img.shields.io/badge/Pages%20Preview-obsidianirc-blue?style=flat-square)](https://home-screen.obsidianirc.pages.dev)
Preview URL: https://home-screen.obsidianirc.pages.dev

Automated deployment preview for the PR in the Cloudflare Pages.
<!-- Created by actions-cool/maintain-one-comment -->
author_association: NONE
user: login: ValwareIRC
created_at: 2025-05-17T15:18:34Z
body: The home page can be improved in the future, but at least  there is something there for now and it works kinda.
author_association: CONTRIBUTOR
user: login: ValwareIRC
created_at: 2025-05-17T19:51:42Z
body: I believe this PR is ready
author_association: CONTRIBUTOR
user: login: ValwareIRC
created_at: 2025-05-18T13:47:46Z
body: Now it's ready!
author_association: CONTRIBUTOR
user: login: ValwareIRC
created_at: 2025-05-18T14:19:32Z
body: okay now it's ready no lie
author_association: CONTRIBUTOR