This is an automated email from the ASF dual-hosted git repository.

piotr pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iggy.git


The following commit(s) were added to refs/heads/master by this push:
     new 33bee3db6 fix(web): improve handling of `message_expiry` (#2888)
33bee3db6 is described below

commit 33bee3db6242dc55ac162ec9fbe1a2f0dbdccd40
Author: Piotr Ziółko <[email protected]>
AuthorDate: Sat Mar 7 21:02:34 2026 +0100

    fix(web): improve handling of `message_expiry` (#2888)
    
    The domain mapper, duration formatter, and form modals previously
    assumed message_expiry was in seconds. They now correctly handle
    microsecond values from the server, with appropriate conversions where
    needed.
    
    A new DurationInput component replaces the raw number input with text
    mode (e.g. "1h 30m"), numeric fields mode (d/h/min/s), a "Never"
    checkbox, and validation (min 1s, max 10 years)
---
 web/eslint.config.js                               |    3 +
 web/package-lock.json                              | 1016 ++++++++------------
 web/package.json                                   |   24 +-
 web/src/lib/components/DurationInput.svelte        |  243 +++++
 web/src/lib/components/Modals/AddTopicModal.svelte |   23 +-
 .../components/Modals/TopicSettingsModal.svelte    |  137 ++-
 web/src/lib/components/SegmentedControl.svelte     |   48 +
 web/src/lib/domain/Topic.ts                        |   21 +-
 web/src/lib/utils/formatters/durationFormatter.ts  |   10 +-
 9 files changed, 794 insertions(+), 731 deletions(-)

diff --git a/web/eslint.config.js b/web/eslint.config.js
index 38abaef46..de7269453 100644
--- a/web/eslint.config.js
+++ b/web/eslint.config.js
@@ -70,6 +70,9 @@ export default defineConfig(
         parser: ts.parser,
         svelteConfig
       }
+    },
+    rules: {
+      'no-useless-assignment': 'off'
     }
   }
 );
diff --git a/web/package-lock.json b/web/package-lock.json
index 13316a628..743de0569 100644
--- a/web/package-lock.json
+++ b/web/package-lock.json
@@ -8,13 +8,13 @@
       "name": "iggy-web-ui",
       "version": "0.2.1-edge.1",
       "dependencies": {
-        "@floating-ui/dom": "^1.7.5",
+        "@floating-ui/dom": "^1.7.6",
         "@tailwindcss/postcss": "^4.2.1",
-        "@types/gsap": "^3.0.0",
         "d3-interpolate": "^3.0.1",
         "date-fns": "^4.1.0",
         "gsap": "^3.14.2",
         "json-bigint": "^1.0.0",
+        "parse-duration": "^2.1.5",
         "svelte-headlessui": "^0.0.46",
         "svelte-popperjs": "^1.3.2",
         "svelte-transition": "^0.0.17",
@@ -22,26 +22,26 @@
         "uuid": "^13.0.0"
       },
       "devDependencies": {
-        "@eslint/compat": "^2.0.2",
-        "@eslint/js": "^9.39.1",
-        "@sveltejs/adapter-node": "^5.5.3",
+        "@eslint/compat": "^2.0.3",
+        "@eslint/js": "^10.0.1",
+        "@sveltejs/adapter-node": "^5.5.4",
         "@sveltejs/adapter-static": "^3.0.10",
-        "@sveltejs/kit": "^2.53.2",
+        "@sveltejs/kit": "^2.53.4",
         "@sveltejs/vite-plugin-svelte": "^6.2.4",
         "@types/d3-interpolate": "^3.0.4",
         "@types/json-bigint": "^1.0.4",
-        "@types/node": "^25.3.1",
+        "@types/node": "^25.3.5",
         "autoprefixer": "^10.4.27",
         "esbuild": "^0.27.3",
-        "eslint": "^9.39.1",
+        "eslint": "^10.0.3",
         "eslint-config-prettier": "^10.1.8",
         "eslint-plugin-svelte": "^3.15.0",
-        "globals": "^17.3.0",
+        "globals": "^17.4.0",
         "jwt-decode": "^4.0.0",
-        "postcss": "^8.5.6",
+        "postcss": "^8.5.8",
         "prettier": "^3.8.1",
-        "prettier-plugin-svelte": "^3.5.0",
-        "svelte": "^5.53.5",
+        "prettier-plugin-svelte": "^3.5.1",
+        "svelte": "^5.53.7",
         "svelte-check": "^4.4.3",
         "sveltekit-superforms": "^2.30.0",
         "tailwindcss": "^4.2.1",
@@ -85,9 +85,9 @@
       "optional": true
     },
     "node_modules/@babel/runtime": {
-      "version": "7.28.4",
-      "resolved": 
"https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz";,
-      "integrity": 
"sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==",
+      "version": "7.28.6",
+      "resolved": 
"https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.6.tgz";,
+      "integrity": 
"sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==",
       "dev": true,
       "license": "MIT",
       "optional": true,
@@ -580,13 +580,13 @@
       }
     },
     "node_modules/@eslint/compat": {
-      "version": "2.0.2",
-      "resolved": 
"https://registry.npmjs.org/@eslint/compat/-/compat-2.0.2.tgz";,
-      "integrity": 
"sha512-pR1DoD0h3HfF675QZx0xsyrsU8q70Z/plx7880NOhS02NuWLgBCOMDL787nUeQ7EWLkxv3bPQJaarjcPQb2Dwg==",
+      "version": "2.0.3",
+      "resolved": 
"https://registry.npmjs.org/@eslint/compat/-/compat-2.0.3.tgz";,
+      "integrity": 
"sha512-SjIJhGigp8hmd1YGIBwh7Ovri7Kisl42GYFjrOyHhtfYGGoLW6teYi/5p8W50KSsawUPpuLOSmsq1bD0NGQLBw==",
       "dev": true,
       "license": "Apache-2.0",
       "dependencies": {
-        "@eslint/core": "^1.1.0"
+        "@eslint/core": "^1.1.1"
       },
       "engines": {
         "node": "^20.19.0 || ^22.13.0 || >=24"
@@ -601,50 +601,37 @@
       }
     },
     "node_modules/@eslint/config-array": {
-      "version": "0.21.1",
-      "resolved": 
"https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz";,
-      "integrity": 
"sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==",
+      "version": "0.23.3",
+      "resolved": 
"https://registry.npmjs.org/@eslint/config-array/-/config-array-0.23.3.tgz";,
+      "integrity": 
"sha512-j+eEWmB6YYLwcNOdlwQ6L2OsptI/LO6lNBuLIqe5R7RetD658HLoF+Mn7LzYmAWWNNzdC6cqP+L6r8ujeYXWLw==",
       "dev": true,
       "license": "Apache-2.0",
       "dependencies": {
-        "@eslint/object-schema": "^2.1.7",
+        "@eslint/object-schema": "^3.0.3",
         "debug": "^4.3.1",
-        "minimatch": "^3.1.2"
+        "minimatch": "^10.2.4"
       },
       "engines": {
-        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+        "node": "^20.19.0 || ^22.13.0 || >=24"
       }
     },
     "node_modules/@eslint/config-helpers": {
-      "version": "0.4.2",
-      "resolved": 
"https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz";,
-      "integrity": 
"sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==",
-      "dev": true,
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@eslint/core": "^0.17.0"
-      },
-      "engines": {
-        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
-      }
-    },
-    "node_modules/@eslint/config-helpers/node_modules/@eslint/core": {
-      "version": "0.17.0",
-      "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz";,
-      "integrity": 
"sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==",
+      "version": "0.5.3",
+      "resolved": 
"https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.5.3.tgz";,
+      "integrity": 
"sha512-lzGN0onllOZCGroKJmRwY6QcEHxbjBw1gwB8SgRSqK8YbbtEXMvKynsXc3553ckIEBxsbMBU7oOZXKIPGZNeZw==",
       "dev": true,
       "license": "Apache-2.0",
       "dependencies": {
-        "@types/json-schema": "^7.0.15"
+        "@eslint/core": "^1.1.1"
       },
       "engines": {
-        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+        "node": "^20.19.0 || ^22.13.0 || >=24"
       }
     },
     "node_modules/@eslint/core": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/@eslint/core/-/core-1.1.0.tgz";,
-      "integrity": 
"sha512-/nr9K9wkr3P1EzFTdFdMoLuo1PmIxjmwvPozwoSodjNBdefGujXQUF93u1DDZpEaTuDvMsIQddsd35BwtrW9Xw==",
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/@eslint/core/-/core-1.1.1.tgz";,
+      "integrity": 
"sha512-QUPblTtE51/7/Zhfv8BDwO0qkkzQL7P/aWWbqcf4xWLEYn1oKjdO0gglQBB4GAsu7u6wjijbCmzsUTy6mnk6oQ==",
       "dev": true,
       "license": "Apache-2.0",
       "dependencies": {
@@ -654,91 +641,49 @@
         "node": "^20.19.0 || ^22.13.0 || >=24"
       }
     },
-    "node_modules/@eslint/eslintrc": {
-      "version": "3.3.1",
-      "resolved": 
"https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz";,
-      "integrity": 
"sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==",
-      "dev": true,
-      "license": "MIT",
-      "dependencies": {
-        "ajv": "^6.12.4",
-        "debug": "^4.3.2",
-        "espree": "^10.0.1",
-        "globals": "^14.0.0",
-        "ignore": "^5.2.0",
-        "import-fresh": "^3.2.1",
-        "js-yaml": "^4.1.0",
-        "minimatch": "^3.1.2",
-        "strip-json-comments": "^3.1.1"
-      },
-      "engines": {
-        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
-      },
-      "funding": {
-        "url": "https://opencollective.com/eslint";
-      }
-    },
-    "node_modules/@eslint/eslintrc/node_modules/globals": {
-      "version": "14.0.0",
-      "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz";,
-      "integrity": 
"sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==",
-      "dev": true,
-      "license": "MIT",
-      "engines": {
-        "node": ">=18"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus";
-      }
-    },
     "node_modules/@eslint/js": {
-      "version": "9.39.1",
-      "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.1.tgz";,
-      "integrity": 
"sha512-S26Stp4zCy88tH94QbBv3XCuzRQiZ9yXofEILmglYTh/Ug/a9/umqvgFtYBAo3Lp0nsI/5/qH1CCrbdK3AP1Tw==",
+      "version": "10.0.1",
+      "resolved": "https://registry.npmjs.org/@eslint/js/-/js-10.0.1.tgz";,
+      "integrity": 
"sha512-zeR9k5pd4gxjZ0abRoIaxdc7I3nDktoXZk2qOv9gCNWx3mVwEn32VRhyLaRsDiJjTs0xq/T8mfPtyuXu7GWBcA==",
       "dev": true,
       "license": "MIT",
       "engines": {
-        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+        "node": "^20.19.0 || ^22.13.0 || >=24"
       },
       "funding": {
         "url": "https://eslint.org/donate";
+      },
+      "peerDependencies": {
+        "eslint": "^10.0.0"
+      },
+      "peerDependenciesMeta": {
+        "eslint": {
+          "optional": true
+        }
       }
     },
     "node_modules/@eslint/object-schema": {
-      "version": "2.1.7",
-      "resolved": 
"https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz";,
-      "integrity": 
"sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==",
+      "version": "3.0.3",
+      "resolved": 
"https://registry.npmjs.org/@eslint/object-schema/-/object-schema-3.0.3.tgz";,
+      "integrity": 
"sha512-iM869Pugn9Nsxbh/YHRqYiqd23AmIbxJOcpUMOuWCVNdoQJ5ZtwL6h3t0bcZzJUlC3Dq9jCFCESBZnX0GTv7iQ==",
       "dev": true,
       "license": "Apache-2.0",
       "engines": {
-        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+        "node": "^20.19.0 || ^22.13.0 || >=24"
       }
     },
     "node_modules/@eslint/plugin-kit": {
-      "version": "0.4.1",
-      "resolved": 
"https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz";,
-      "integrity": 
"sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==",
+      "version": "0.6.1",
+      "resolved": 
"https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.6.1.tgz";,
+      "integrity": 
"sha512-iH1B076HoAshH1mLpHMgwdGeTs0CYwL0SPMkGuSebZrwBp16v415e9NZXg2jtrqPVQjf6IANe2Vtlr5KswtcZQ==",
       "dev": true,
       "license": "Apache-2.0",
       "dependencies": {
-        "@eslint/core": "^0.17.0",
+        "@eslint/core": "^1.1.1",
         "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.17.0",
-      "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz";,
-      "integrity": 
"sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==",
-      "dev": true,
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@types/json-schema": "^7.0.15"
-      },
-      "engines": {
-        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+        "node": "^20.19.0 || ^22.13.0 || >=24"
       }
     },
     "node_modules/@exodus/schemasafe": {
@@ -750,28 +695,28 @@
       "optional": true
     },
     "node_modules/@floating-ui/core": {
-      "version": "1.7.4",
-      "resolved": 
"https://registry.npmjs.org/@floating-ui/core/-/core-1.7.4.tgz";,
-      "integrity": 
"sha512-C3HlIdsBxszvm5McXlB8PeOEWfBhcGBTZGkGlWc2U0KFY5IwG5OQEuQ8rq52DZmcHDlPLd+YFBK+cZcytwIFWg==",
+      "version": "1.7.5",
+      "resolved": 
"https://registry.npmjs.org/@floating-ui/core/-/core-1.7.5.tgz";,
+      "integrity": 
"sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==",
       "license": "MIT",
       "dependencies": {
-        "@floating-ui/utils": "^0.2.10"
+        "@floating-ui/utils": "^0.2.11"
       }
     },
     "node_modules/@floating-ui/dom": {
-      "version": "1.7.5",
-      "resolved": 
"https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.5.tgz";,
-      "integrity": 
"sha512-N0bD2kIPInNHUHehXhMke1rBGs1dwqvC9O9KYMyyjK7iXt7GAhnro7UlcuYcGdS/yYOlq0MAVgrow8IbWJwyqg==",
+      "version": "1.7.6",
+      "resolved": 
"https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.6.tgz";,
+      "integrity": 
"sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==",
       "license": "MIT",
       "dependencies": {
-        "@floating-ui/core": "^1.7.4",
-        "@floating-ui/utils": "^0.2.10"
+        "@floating-ui/core": "^1.7.5",
+        "@floating-ui/utils": "^0.2.11"
       }
     },
     "node_modules/@floating-ui/utils": {
-      "version": "0.2.10",
-      "resolved": 
"https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.10.tgz";,
-      "integrity": 
"sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==",
+      "version": "0.2.11",
+      "resolved": 
"https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.11.tgz";,
+      "integrity": 
"sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==",
       "license": "MIT"
     },
     "node_modules/@hapi/hoek": {
@@ -917,9 +862,9 @@
       "optional": true
     },
     "node_modules/@rollup/plugin-commonjs": {
-      "version": "29.0.0",
-      "resolved": 
"https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-29.0.0.tgz";,
-      "integrity": 
"sha512-U2YHaxR2cU/yAiwKJtJRhnyLk7cifnQw0zUpISsocBDoHDJn+HTV74ABqnwr5bEgWUwFZC9oFL6wLe21lHu5eQ==",
+      "version": "29.0.2",
+      "resolved": 
"https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-29.0.2.tgz";,
+      "integrity": 
"sha512-S/ggWH1LU7jTyi9DxZOKyxpVd4hF/OZ0JrEbeLjXk/DFXwRny0tjD2c992zOUYQobLrVkRVMDdmHP16HKP7GRg==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
@@ -1013,9 +958,9 @@
       }
     },
     "node_modules/@rollup/rollup-android-arm-eabi": {
-      "version": "4.53.2",
-      "resolved": 
"https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.53.2.tgz";,
-      "integrity": 
"sha512-yDPzwsgiFO26RJA4nZo8I+xqzh7sJTZIWQOxn+/XOdPE31lAvLIYCKqjV+lNH/vxE2L2iH3plKxDCRK6i+CwhA==",
+      "version": "4.59.0",
+      "resolved": 
"https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.59.0.tgz";,
+      "integrity": 
"sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==",
       "cpu": [
         "arm"
       ],
@@ -1027,9 +972,9 @@
       ]
     },
     "node_modules/@rollup/rollup-android-arm64": {
-      "version": "4.53.2",
-      "resolved": 
"https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.53.2.tgz";,
-      "integrity": 
"sha512-k8FontTxIE7b0/OGKeSN5B6j25EuppBcWM33Z19JoVT7UTXFSo3D9CdU39wGTeb29NO3XxpMNauh09B+Ibw+9g==",
+      "version": "4.59.0",
+      "resolved": 
"https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.59.0.tgz";,
+      "integrity": 
"sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==",
       "cpu": [
         "arm64"
       ],
@@ -1041,9 +986,9 @@
       ]
     },
     "node_modules/@rollup/rollup-darwin-arm64": {
-      "version": "4.53.2",
-      "resolved": 
"https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.53.2.tgz";,
-      "integrity": 
"sha512-A6s4gJpomNBtJ2yioj8bflM2oogDwzUiMl2yNJ2v9E7++sHrSrsQ29fOfn5DM/iCzpWcebNYEdXpaK4tr2RhfQ==",
+      "version": "4.59.0",
+      "resolved": 
"https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.59.0.tgz";,
+      "integrity": 
"sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==",
       "cpu": [
         "arm64"
       ],
@@ -1055,9 +1000,9 @@
       ]
     },
     "node_modules/@rollup/rollup-darwin-x64": {
-      "version": "4.53.2",
-      "resolved": 
"https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.53.2.tgz";,
-      "integrity": 
"sha512-e6XqVmXlHrBlG56obu9gDRPW3O3hLxpwHpLsBJvuI8qqnsrtSZ9ERoWUXtPOkY8c78WghyPHZdmPhHLWNdAGEw==",
+      "version": "4.59.0",
+      "resolved": 
"https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.59.0.tgz";,
+      "integrity": 
"sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==",
       "cpu": [
         "x64"
       ],
@@ -1069,9 +1014,9 @@
       ]
     },
     "node_modules/@rollup/rollup-freebsd-arm64": {
-      "version": "4.53.2",
-      "resolved": 
"https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.53.2.tgz";,
-      "integrity": 
"sha512-v0E9lJW8VsrwPux5Qe5CwmH/CF/2mQs6xU1MF3nmUxmZUCHazCjLgYvToOk+YuuUqLQBio1qkkREhxhc656ViA==",
+      "version": "4.59.0",
+      "resolved": 
"https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.59.0.tgz";,
+      "integrity": 
"sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==",
       "cpu": [
         "arm64"
       ],
@@ -1083,9 +1028,9 @@
       ]
     },
     "node_modules/@rollup/rollup-freebsd-x64": {
-      "version": "4.53.2",
-      "resolved": 
"https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.53.2.tgz";,
-      "integrity": 
"sha512-ClAmAPx3ZCHtp6ysl4XEhWU69GUB1D+s7G9YjHGhIGCSrsg00nEGRRZHmINYxkdoJehde8VIsDC5t9C0gb6yqA==",
+      "version": "4.59.0",
+      "resolved": 
"https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.59.0.tgz";,
+      "integrity": 
"sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==",
       "cpu": [
         "x64"
       ],
@@ -1097,9 +1042,9 @@
       ]
     },
     "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
-      "version": "4.53.2",
-      "resolved": 
"https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.53.2.tgz";,
-      "integrity": 
"sha512-EPlb95nUsz6Dd9Qy13fI5kUPXNSljaG9FiJ4YUGU1O/Q77i5DYFW5KR8g1OzTcdZUqQQ1KdDqsTohdFVwCwjqg==",
+      "version": "4.59.0",
+      "resolved": 
"https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.59.0.tgz";,
+      "integrity": 
"sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==",
       "cpu": [
         "arm"
       ],
@@ -1111,9 +1056,9 @@
       ]
     },
     "node_modules/@rollup/rollup-linux-arm-musleabihf": {
-      "version": "4.53.2",
-      "resolved": 
"https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.53.2.tgz";,
-      "integrity": 
"sha512-BOmnVW+khAUX+YZvNfa0tGTEMVVEerOxN0pDk2E6N6DsEIa2Ctj48FOMfNDdrwinocKaC7YXUZ1pHlKpnkja/Q==",
+      "version": "4.59.0",
+      "resolved": 
"https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.59.0.tgz";,
+      "integrity": 
"sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==",
       "cpu": [
         "arm"
       ],
@@ -1125,9 +1070,9 @@
       ]
     },
     "node_modules/@rollup/rollup-linux-arm64-gnu": {
-      "version": "4.53.2",
-      "resolved": 
"https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.53.2.tgz";,
-      "integrity": 
"sha512-Xt2byDZ+6OVNuREgBXr4+CZDJtrVso5woFtpKdGPhpTPHcNG7D8YXeQzpNbFRxzTVqJf7kvPMCub/pcGUWgBjA==",
+      "version": "4.59.0",
+      "resolved": 
"https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.59.0.tgz";,
+      "integrity": 
"sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==",
       "cpu": [
         "arm64"
       ],
@@ -1139,9 +1084,9 @@
       ]
     },
     "node_modules/@rollup/rollup-linux-arm64-musl": {
-      "version": "4.53.2",
-      "resolved": 
"https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.53.2.tgz";,
-      "integrity": 
"sha512-+LdZSldy/I9N8+klim/Y1HsKbJ3BbInHav5qE9Iy77dtHC/pibw1SR/fXlWyAk0ThnpRKoODwnAuSjqxFRDHUQ==",
+      "version": "4.59.0",
+      "resolved": 
"https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.59.0.tgz";,
+      "integrity": 
"sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==",
       "cpu": [
         "arm64"
       ],
@@ -1153,9 +1098,23 @@
       ]
     },
     "node_modules/@rollup/rollup-linux-loong64-gnu": {
-      "version": "4.53.2",
-      "resolved": 
"https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.53.2.tgz";,
-      "integrity": 
"sha512-8ms8sjmyc1jWJS6WdNSA23rEfdjWB30LH8Wqj0Cqvv7qSHnvw6kgMMXRdop6hkmGPlyYBdRPkjJnj3KCUHV/uQ==",
+      "version": "4.59.0",
+      "resolved": 
"https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.59.0.tgz";,
+      "integrity": 
"sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==",
+      "cpu": [
+        "loong64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-loong64-musl": {
+      "version": "4.59.0",
+      "resolved": 
"https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.59.0.tgz";,
+      "integrity": 
"sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==",
       "cpu": [
         "loong64"
       ],
@@ -1167,9 +1126,23 @@
       ]
     },
     "node_modules/@rollup/rollup-linux-ppc64-gnu": {
-      "version": "4.53.2",
-      "resolved": 
"https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.53.2.tgz";,
-      "integrity": 
"sha512-3HRQLUQbpBDMmzoxPJYd3W6vrVHOo2cVW8RUo87Xz0JPJcBLBr5kZ1pGcQAhdZgX9VV7NbGNipah1omKKe23/g==",
+      "version": "4.59.0",
+      "resolved": 
"https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.59.0.tgz";,
+      "integrity": 
"sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==",
+      "cpu": [
+        "ppc64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-ppc64-musl": {
+      "version": "4.59.0",
+      "resolved": 
"https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.59.0.tgz";,
+      "integrity": 
"sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==",
       "cpu": [
         "ppc64"
       ],
@@ -1181,9 +1154,9 @@
       ]
     },
     "node_modules/@rollup/rollup-linux-riscv64-gnu": {
-      "version": "4.53.2",
-      "resolved": 
"https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.53.2.tgz";,
-      "integrity": 
"sha512-fMjKi+ojnmIvhk34gZP94vjogXNNUKMEYs+EDaB/5TG/wUkoeua7p7VCHnE6T2Tx+iaghAqQX8teQzcvrYpaQA==",
+      "version": "4.59.0",
+      "resolved": 
"https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.59.0.tgz";,
+      "integrity": 
"sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==",
       "cpu": [
         "riscv64"
       ],
@@ -1195,9 +1168,9 @@
       ]
     },
     "node_modules/@rollup/rollup-linux-riscv64-musl": {
-      "version": "4.53.2",
-      "resolved": 
"https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.53.2.tgz";,
-      "integrity": 
"sha512-XuGFGU+VwUUV5kLvoAdi0Wz5Xbh2SrjIxCtZj6Wq8MDp4bflb/+ThZsVxokM7n0pcbkEr2h5/pzqzDYI7cCgLQ==",
+      "version": "4.59.0",
+      "resolved": 
"https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.59.0.tgz";,
+      "integrity": 
"sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==",
       "cpu": [
         "riscv64"
       ],
@@ -1209,9 +1182,9 @@
       ]
     },
     "node_modules/@rollup/rollup-linux-s390x-gnu": {
-      "version": "4.53.2",
-      "resolved": 
"https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.53.2.tgz";,
-      "integrity": 
"sha512-w6yjZF0P+NGzWR3AXWX9zc0DNEGdtvykB03uhonSHMRa+oWA6novflo2WaJr6JZakG2ucsyb+rvhrKac6NIy+w==",
+      "version": "4.59.0",
+      "resolved": 
"https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.59.0.tgz";,
+      "integrity": 
"sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==",
       "cpu": [
         "s390x"
       ],
@@ -1223,9 +1196,9 @@
       ]
     },
     "node_modules/@rollup/rollup-linux-x64-gnu": {
-      "version": "4.53.2",
-      "resolved": 
"https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.53.2.tgz";,
-      "integrity": 
"sha512-yo8d6tdfdeBArzC7T/PnHd7OypfI9cbuZzPnzLJIyKYFhAQ8SvlkKtKBMbXDxe1h03Rcr7u++nFS7tqXz87Gtw==",
+      "version": "4.59.0",
+      "resolved": 
"https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.59.0.tgz";,
+      "integrity": 
"sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==",
       "cpu": [
         "x64"
       ],
@@ -1237,9 +1210,9 @@
       ]
     },
     "node_modules/@rollup/rollup-linux-x64-musl": {
-      "version": "4.53.2",
-      "resolved": 
"https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.53.2.tgz";,
-      "integrity": 
"sha512-ah59c1YkCxKExPP8O9PwOvs+XRLKwh/mV+3YdKqQ5AMQ0r4M4ZDuOrpWkUaqO7fzAHdINzV9tEVu8vNw48z0lA==",
+      "version": "4.59.0",
+      "resolved": 
"https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.59.0.tgz";,
+      "integrity": 
"sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==",
       "cpu": [
         "x64"
       ],
@@ -1250,10 +1223,24 @@
         "linux"
       ]
     },
+    "node_modules/@rollup/rollup-openbsd-x64": {
+      "version": "4.59.0",
+      "resolved": 
"https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.59.0.tgz";,
+      "integrity": 
"sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "openbsd"
+      ]
+    },
     "node_modules/@rollup/rollup-openharmony-arm64": {
-      "version": "4.53.2",
-      "resolved": 
"https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.53.2.tgz";,
-      "integrity": 
"sha512-4VEd19Wmhr+Zy7hbUsFZ6YXEiP48hE//KPLCSVNY5RMGX2/7HZ+QkN55a3atM1C/BZCGIgqN+xrVgtdak2S9+A==",
+      "version": "4.59.0",
+      "resolved": 
"https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.59.0.tgz";,
+      "integrity": 
"sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==",
       "cpu": [
         "arm64"
       ],
@@ -1265,9 +1252,9 @@
       ]
     },
     "node_modules/@rollup/rollup-win32-arm64-msvc": {
-      "version": "4.53.2",
-      "resolved": 
"https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.53.2.tgz";,
-      "integrity": 
"sha512-IlbHFYc/pQCgew/d5fslcy1KEaYVCJ44G8pajugd8VoOEI8ODhtb/j8XMhLpwHCMB3yk2J07ctup10gpw2nyMA==",
+      "version": "4.59.0",
+      "resolved": 
"https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.59.0.tgz";,
+      "integrity": 
"sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==",
       "cpu": [
         "arm64"
       ],
@@ -1279,9 +1266,9 @@
       ]
     },
     "node_modules/@rollup/rollup-win32-ia32-msvc": {
-      "version": "4.53.2",
-      "resolved": 
"https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.53.2.tgz";,
-      "integrity": 
"sha512-lNlPEGgdUfSzdCWU176ku/dQRnA7W+Gp8d+cWv73jYrb8uT7HTVVxq62DUYxjbaByuf1Yk0RIIAbDzp+CnOTFg==",
+      "version": "4.59.0",
+      "resolved": 
"https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.59.0.tgz";,
+      "integrity": 
"sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==",
       "cpu": [
         "ia32"
       ],
@@ -1293,9 +1280,9 @@
       ]
     },
     "node_modules/@rollup/rollup-win32-x64-gnu": {
-      "version": "4.53.2",
-      "resolved": 
"https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.53.2.tgz";,
-      "integrity": 
"sha512-S6YojNVrHybQis2lYov1sd+uj7K0Q05NxHcGktuMMdIQ2VixGwAfbJ23NnlvvVV1bdpR2m5MsNBViHJKcA4ADw==",
+      "version": "4.59.0",
+      "resolved": 
"https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.59.0.tgz";,
+      "integrity": 
"sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==",
       "cpu": [
         "x64"
       ],
@@ -1307,9 +1294,9 @@
       ]
     },
     "node_modules/@rollup/rollup-win32-x64-msvc": {
-      "version": "4.53.2",
-      "resolved": 
"https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.53.2.tgz";,
-      "integrity": 
"sha512-k+/Rkcyx//P6fetPoLMb8pBeqJBNGx81uuf7iljX9++yNBVRDQgD04L+SVXmXmh5ZP4/WOp4mWF0kmi06PW2tA==",
+      "version": "4.59.0",
+      "resolved": 
"https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.59.0.tgz";,
+      "integrity": 
"sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==",
       "cpu": [
         "x64"
       ],
@@ -1348,32 +1335,32 @@
       "optional": true
     },
     "node_modules/@standard-schema/spec": {
-      "version": "1.0.0",
-      "resolved": 
"https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz";,
-      "integrity": 
"sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==",
+      "version": "1.1.0",
+      "resolved": 
"https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz";,
+      "integrity": 
"sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==",
       "dev": true,
       "license": "MIT"
     },
     "node_modules/@sveltejs/acorn-typescript": {
-      "version": "1.0.6",
-      "resolved": 
"https://registry.npmjs.org/@sveltejs/acorn-typescript/-/acorn-typescript-1.0.6.tgz";,
-      "integrity": 
"sha512-4awhxtMh4cx9blePWl10HRHj8Iivtqj+2QdDCSMDzxG+XKa9+VCNupQuCuvzEhYPzZSrX+0gC+0lHA/0fFKKQQ==",
+      "version": "1.0.9",
+      "resolved": 
"https://registry.npmjs.org/@sveltejs/acorn-typescript/-/acorn-typescript-1.0.9.tgz";,
+      "integrity": 
"sha512-lVJX6qEgs/4DOcRTpo56tmKzVPtoWAaVbL4hfO7t7NVwl9AAXzQR6cihesW1BmNMPl+bK6dreu2sOKBP2Q9CIA==",
       "license": "MIT",
       "peerDependencies": {
         "acorn": "^8.9.0"
       }
     },
     "node_modules/@sveltejs/adapter-node": {
-      "version": "5.5.3",
-      "resolved": 
"https://registry.npmjs.org/@sveltejs/adapter-node/-/adapter-node-5.5.3.tgz";,
-      "integrity": 
"sha512-yeWbKXBL9vqDb/7R8ebvRHeuBHN4cRYYBSquNJSMQtS6rIYkXxsVSveaMTUaLvHYQsb1zNa+nH2iLTOMawBohA==",
+      "version": "5.5.4",
+      "resolved": 
"https://registry.npmjs.org/@sveltejs/adapter-node/-/adapter-node-5.5.4.tgz";,
+      "integrity": 
"sha512-45X92CXW+2J8ZUzPv3eLlKWEzINKiiGeFWTjyER4ZN4sGgNoaoeSkCY/QYNxHpPXy71QPsctwccBo9jJs0ySPQ==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
         "@rollup/plugin-commonjs": "^29.0.0",
         "@rollup/plugin-json": "^6.1.0",
         "@rollup/plugin-node-resolve": "^16.0.0",
-        "rollup": "^4.9.5"
+        "rollup": "^4.59.0"
       },
       "peerDependencies": {
         "@sveltejs/kit": "^2.4.0"
@@ -1390,9 +1377,9 @@
       }
     },
     "node_modules/@sveltejs/kit": {
-      "version": "2.53.2",
-      "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.53.2.tgz";,
-      "integrity": 
"sha512-M+MqAvFve12T1HWws/2npP/s3hFtyjw3GB/OXW/8a1jZBk48qnvPJrtgE+VOMc3RnjUMxc4mv/vQ73nvj2uNMg==",
+      "version": "2.53.4",
+      "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.53.4.tgz";,
+      "integrity": 
"sha512-iAIPEahFgDJJyvz8g0jP08KvqnM6JvdW8YfsygZ+pMeMvyM2zssWMltcsotETvjSZ82G3VlitgDtBIvpQSZrTA==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
@@ -1453,13 +1440,13 @@
       }
     },
     "node_modules/@sveltejs/vite-plugin-svelte-inspector": {
-      "version": "5.0.1",
-      "resolved": 
"https://registry.npmjs.org/@sveltejs/vite-plugin-svelte-inspector/-/vite-plugin-svelte-inspector-5.0.1.tgz";,
-      "integrity": 
"sha512-ubWshlMk4bc8mkwWbg6vNvCeT7lGQojE3ijDh3QTR6Zr/R+GXxsGbyH4PExEPpiFmqPhYiVSVmHBjUcVc1JIrA==",
+      "version": "5.0.2",
+      "resolved": 
"https://registry.npmjs.org/@sveltejs/vite-plugin-svelte-inspector/-/vite-plugin-svelte-inspector-5.0.2.tgz";,
+      "integrity": 
"sha512-TZzRTcEtZffICSAoZGkPSl6Etsj2torOVrx6Uw0KpXxrec9Gg6jFWQ60Q3+LmNGfZSxHRCZL7vXVZIWmuV50Ig==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
-        "debug": "^4.4.1"
+        "obug": "^2.1.0"
       },
       "engines": {
         "node": "^20.19 || ^22.12 || >=24"
@@ -1750,22 +1737,19 @@
         "@types/d3-color": "*"
       }
     },
+    "node_modules/@types/esrecurse": {
+      "version": "4.3.1",
+      "resolved": 
"https://registry.npmjs.org/@types/esrecurse/-/esrecurse-4.3.1.tgz";,
+      "integrity": 
"sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==",
+      "dev": true,
+      "license": "MIT"
+    },
     "node_modules/@types/estree": {
       "version": "1.0.8",
       "resolved": 
"https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz";,
       "integrity": 
"sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
       "license": "MIT"
     },
-    "node_modules/@types/gsap": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/@types/gsap/-/gsap-3.0.0.tgz";,
-      "integrity": 
"sha512-BbWLi4WRHGze4C8NV7U7yRevuBFiPkPZZyGa0rryanvh/9HPUFXTNBXsGQxJZJq7Ix7j4RXMYodP3s+OsqCErg==",
-      "deprecated": "This is a stub types definition. gsap provides its own 
type definitions, so you do not need this installed.",
-      "license": "MIT",
-      "dependencies": {
-        "gsap": "*"
-      }
-    },
     "node_modules/@types/json-bigint": {
       "version": "1.0.4",
       "resolved": 
"https://registry.npmjs.org/@types/json-bigint/-/json-bigint-1.0.4.tgz";,
@@ -1781,9 +1765,9 @@
       "license": "MIT"
     },
     "node_modules/@types/node": {
-      "version": "25.3.1",
-      "resolved": "https://registry.npmjs.org/@types/node/-/node-25.3.1.tgz";,
-      "integrity": 
"sha512-hj9YIJimBCipHVfHKRMnvmHg+wfhKc0o4mTtXh9pKBjC8TLJzz0nzGmLi5UJsYAUgSvXFHgb0V2oY10DUFtImw==",
+      "version": "25.3.5",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-25.3.5.tgz";,
+      "integrity": 
"sha512-oX8xrhvpiyRCQkG1MFchB09f+cXftgIXb3a7UUa4Y3wpmZPw5tyZGTLWhlESOLq1Rq6oDlc8npVU2/9xiCuXMA==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
@@ -2034,45 +2018,6 @@
         "typescript": ">=4.8.4 <6.0.0"
       }
     },
-    
"node_modules/@typescript-eslint/typescript-estree/node_modules/balanced-match":
 {
-      "version": "4.0.4",
-      "resolved": 
"https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz";,
-      "integrity": 
"sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==",
-      "dev": true,
-      "license": "MIT",
-      "engines": {
-        "node": "18 || 20 || >=22"
-      }
-    },
-    
"node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion":
 {
-      "version": "5.0.3",
-      "resolved": 
"https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.3.tgz";,
-      "integrity": 
"sha512-fy6KJm2RawA5RcHkLa1z/ScpBeA762UF9KmZQxwIbDtRJrgLzM10depAiEQ+CXYcoiqW1/m96OAAoke2nE9EeA==",
-      "dev": true,
-      "license": "MIT",
-      "dependencies": {
-        "balanced-match": "^4.0.2"
-      },
-      "engines": {
-        "node": "18 || 20 || >=22"
-      }
-    },
-    
"node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": {
-      "version": "10.2.4",
-      "resolved": 
"https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz";,
-      "integrity": 
"sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==",
-      "dev": true,
-      "license": "BlueOak-1.0.0",
-      "dependencies": {
-        "brace-expansion": "^5.0.2"
-      },
-      "engines": {
-        "node": "18 || 20 || >=22"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/isaacs";
-      }
-    },
     "node_modules/@typescript-eslint/utils": {
       "version": "8.56.1",
       "resolved": 
"https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.56.1.tgz";,
@@ -2115,19 +2060,6 @@
         "url": "https://opencollective.com/typescript-eslint";
       }
     },
-    
"node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys":
 {
-      "version": "5.0.1",
-      "resolved": 
"https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz";,
-      "integrity": 
"sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==",
-      "dev": true,
-      "license": "Apache-2.0",
-      "engines": {
-        "node": "^20.19.0 || ^22.13.0 || >=24"
-      },
-      "funding": {
-        "url": "https://opencollective.com/eslint";
-      }
-    },
     "node_modules/@valibot/to-json-schema": {
       "version": "1.5.0",
       "resolved": 
"https://registry.npmjs.org/@valibot/to-json-schema/-/to-json-schema-1.5.0.tgz";,
@@ -2172,9 +2104,9 @@
       }
     },
     "node_modules/acorn": {
-      "version": "8.15.0",
-      "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz";,
-      "integrity": 
"sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
+      "version": "8.16.0",
+      "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz";,
+      "integrity": 
"sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==",
       "license": "MIT",
       "bin": {
         "acorn": "bin/acorn"
@@ -2194,9 +2126,9 @@
       }
     },
     "node_modules/ajv": {
-      "version": "6.12.6",
-      "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz";,
-      "integrity": 
"sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+      "version": "6.14.0",
+      "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz";,
+      "integrity": 
"sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
@@ -2210,29 +2142,6 @@
         "url": "https://github.com/sponsors/epoberezkin";
       }
     },
-    "node_modules/ansi-styles": {
-      "version": "4.3.0",
-      "resolved": 
"https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz";,
-      "integrity": 
"sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
-      "dev": true,
-      "license": "MIT",
-      "dependencies": {
-        "color-convert": "^2.0.1"
-      },
-      "engines": {
-        "node": ">=8"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/ansi-styles?sponsor=1";
-      }
-    },
-    "node_modules/argparse": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz";,
-      "integrity": 
"sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
-      "dev": true,
-      "license": "Python-2.0"
-    },
     "node_modules/aria-query": {
       "version": "5.3.1",
       "resolved": 
"https://registry.npmjs.org/aria-query/-/aria-query-5.3.1.tgz";,
@@ -2254,9 +2163,9 @@
       }
     },
     "node_modules/arktype": {
-      "version": "2.1.29",
-      "resolved": "https://registry.npmjs.org/arktype/-/arktype-2.1.29.tgz";,
-      "integrity": 
"sha512-jyfKk4xIOzvYNayqnD8ZJQqOwcrTOUbIU4293yrzAjA3O1dWh61j71ArMQ6tS/u4pD7vabSPe7nG3RCyoXW6RQ==",
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/arktype/-/arktype-2.2.0.tgz";,
+      "integrity": 
"sha512-t54MZ7ti5BhOEvzEkgKnWvqj+UbDfWig+DHr5I34xatymPusKLS0lQpNJd8M6DzmIto2QGszHfNKoFIT8tMCZQ==",
       "dev": true,
       "license": "MIT",
       "optional": true,
@@ -2313,11 +2222,14 @@
       }
     },
     "node_modules/balanced-match": {
-      "version": "1.0.2",
-      "resolved": 
"https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz";,
-      "integrity": 
"sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+      "version": "4.0.4",
+      "resolved": 
"https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz";,
+      "integrity": 
"sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==",
       "dev": true,
-      "license": "MIT"
+      "license": "MIT",
+      "engines": {
+        "node": "18 || 20 || >=22"
+      }
     },
     "node_modules/baseline-browser-mapping": {
       "version": "2.10.0",
@@ -2342,14 +2254,16 @@
       }
     },
     "node_modules/brace-expansion": {
-      "version": "1.1.12",
-      "resolved": 
"https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz";,
-      "integrity": 
"sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
+      "version": "5.0.4",
+      "resolved": 
"https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.4.tgz";,
+      "integrity": 
"sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
-        "balanced-match": "^1.0.0",
-        "concat-map": "0.0.1"
+        "balanced-match": "^4.0.2"
+      },
+      "engines": {
+        "node": "18 || 20 || >=22"
       }
     },
     "node_modules/browserslist": {
@@ -2386,16 +2300,6 @@
         "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
       }
     },
-    "node_modules/callsites": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz";,
-      "integrity": 
"sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
-      "dev": true,
-      "license": "MIT",
-      "engines": {
-        "node": ">=6"
-      }
-    },
     "node_modules/camelcase": {
       "version": "8.0.0",
       "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-8.0.0.tgz";,
@@ -2411,9 +2315,9 @@
       }
     },
     "node_modules/caniuse-lite": {
-      "version": "1.0.30001774",
-      "resolved": 
"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001774.tgz";,
-      "integrity": 
"sha512-DDdwPGz99nmIEv216hKSgLD+D4ikHQHjBC/seF98N9CPqRX4M5mSxT9eTV6oyisnJcuzxtZy4n17yKKQYmYQOA==",
+      "version": "1.0.30001777",
+      "resolved": 
"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001777.tgz";,
+      "integrity": 
"sha512-tmN+fJxroPndC74efCdp12j+0rk0RHwV5Jwa1zWaFVyw2ZxAuPeG8ZgWC3Wz7uSjT3qMRQ5XHZ4COgQmsCMJAQ==",
       "dev": true,
       "funding": [
         {
@@ -2431,23 +2335,6 @@
       ],
       "license": "CC-BY-4.0"
     },
-    "node_modules/chalk": {
-      "version": "4.1.2",
-      "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz";,
-      "integrity": 
"sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
-      "dev": true,
-      "license": "MIT",
-      "dependencies": {
-        "ansi-styles": "^4.1.0",
-        "supports-color": "^7.1.0"
-      },
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/chalk?sponsor=1";
-      }
-    },
     "node_modules/chokidar": {
       "version": "4.0.3",
       "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz";,
@@ -2465,16 +2352,16 @@
       }
     },
     "node_modules/class-validator": {
-      "version": "0.14.3",
-      "resolved": 
"https://registry.npmjs.org/class-validator/-/class-validator-0.14.3.tgz";,
-      "integrity": 
"sha512-rXXekcjofVN1LTOSw+u4u9WXVEUvNBVjORW154q/IdmYWy1nMbOU9aNtZB0t8m+FJQ9q91jlr2f9CwwUFdFMRA==",
+      "version": "0.14.4",
+      "resolved": 
"https://registry.npmjs.org/class-validator/-/class-validator-0.14.4.tgz";,
+      "integrity": 
"sha512-AwNusCCam51q703dW82x95tOqQp6oC9HNUl724KxJJOfnKscI8dOloXFgyez7LbTTKWuRBA37FScqVbJEoq8Yw==",
       "dev": true,
       "license": "MIT",
       "optional": true,
       "dependencies": {
         "@types/validator": "^13.15.3",
         "libphonenumber-js": "^1.11.1",
-        "validator": "^13.15.20"
+        "validator": "^13.15.22"
       }
     },
     "node_modules/clsx": {
@@ -2486,26 +2373,6 @@
         "node": ">=6"
       }
     },
-    "node_modules/color-convert": {
-      "version": "2.0.1",
-      "resolved": 
"https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz";,
-      "integrity": 
"sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
-      "dev": true,
-      "license": "MIT",
-      "dependencies": {
-        "color-name": "~1.1.4"
-      },
-      "engines": {
-        "node": ">=7.0.0"
-      }
-    },
-    "node_modules/color-name": {
-      "version": "1.1.4",
-      "resolved": 
"https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz";,
-      "integrity": 
"sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
-      "dev": true,
-      "license": "MIT"
-    },
     "node_modules/commondir": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz";,
@@ -2513,13 +2380,6 @@
       "dev": true,
       "license": "MIT"
     },
-    "node_modules/concat-map": {
-      "version": "0.0.1",
-      "resolved": 
"https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz";,
-      "integrity": 
"sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
-      "dev": true,
-      "license": "MIT"
-    },
     "node_modules/cookie": {
       "version": "0.7.2",
       "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz";,
@@ -2656,9 +2516,9 @@
       "optional": true
     },
     "node_modules/effect": {
-      "version": "3.19.12",
-      "resolved": "https://registry.npmjs.org/effect/-/effect-3.19.12.tgz";,
-      "integrity": 
"sha512-7F9RGTrCTC3D7nh9Zw+3VlJWwZgo5k33KA+476BAaD0rKIXKZsY/jQ+ipyhR/Avo239Fi6GqAVFs1mqM1IJ7yg==",
+      "version": "3.19.19",
+      "resolved": "https://registry.npmjs.org/effect/-/effect-3.19.19.tgz";,
+      "integrity": 
"sha512-Yc8U/SVXo2dHnaP7zNBlAo83h/nzSJpi7vph6Hzyl4ulgMBIgPmz3UzOjb9sBgpFE00gC0iETR244sfXDNLHRg==",
       "dev": true,
       "license": "MIT",
       "optional": true,
@@ -2668,16 +2528,16 @@
       }
     },
     "node_modules/electron-to-chromium": {
-      "version": "1.5.302",
-      "resolved": 
"https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.302.tgz";,
-      "integrity": 
"sha512-sM6HAN2LyK82IyPBpznDRqlTQAtuSaO+ShzFiWTvoMJLHyZ+Y39r8VMfHzwbU8MVBzQ4Wdn85+wlZl2TLGIlwg==",
+      "version": "1.5.307",
+      "resolved": 
"https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.307.tgz";,
+      "integrity": 
"sha512-5z3uFKBWjiNR44nFcYdkcXjKMbg5KXNdciu7mhTPo9tB7NbqSNP2sSnGR+fqknZSCwKkBN+oxiiajWs4dT6ORg==",
       "dev": true,
       "license": "ISC"
     },
     "node_modules/enhanced-resolve": {
-      "version": "5.19.0",
-      "resolved": 
"https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.19.0.tgz";,
-      "integrity": 
"sha512-phv3E1Xl4tQOShqSte26C7Fl84EwUdZsyOuSSk9qtAGyyQs2s3jJzComh+Abf4g187lUUAvH+H26omrqia2aGg==",
+      "version": "5.20.0",
+      "resolved": 
"https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.20.0.tgz";,
+      "integrity": 
"sha512-/ce7+jQ1PQ6rVXwe+jKEg5hW5ciicHwIQUagZkp6IufBoY3YDgdTTY1azVs0qoRgVmvsNB+rbjLJxDAeHHtwsQ==",
       "license": "MIT",
       "dependencies": {
         "graceful-fs": "^4.2.4",
@@ -2753,33 +2613,30 @@
       }
     },
     "node_modules/eslint": {
-      "version": "9.39.1",
-      "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.1.tgz";,
-      "integrity": 
"sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==",
+      "version": "10.0.3",
+      "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.0.3.tgz";,
+      "integrity": 
"sha512-COV33RzXZkqhG9P2rZCFl9ZmJ7WL+gQSCRzE7RhkbclbQPtLAWReL7ysA0Sh4c8Im2U9ynybdR56PV0XcKvqaQ==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
         "@eslint-community/eslint-utils": "^4.8.0",
-        "@eslint-community/regexpp": "^4.12.1",
-        "@eslint/config-array": "^0.21.1",
-        "@eslint/config-helpers": "^0.4.2",
-        "@eslint/core": "^0.17.0",
-        "@eslint/eslintrc": "^3.3.1",
-        "@eslint/js": "9.39.1",
-        "@eslint/plugin-kit": "^0.4.1",
+        "@eslint-community/regexpp": "^4.12.2",
+        "@eslint/config-array": "^0.23.3",
+        "@eslint/config-helpers": "^0.5.2",
+        "@eslint/core": "^1.1.1",
+        "@eslint/plugin-kit": "^0.6.1",
         "@humanfs/node": "^0.16.6",
         "@humanwhocodes/module-importer": "^1.0.1",
         "@humanwhocodes/retry": "^0.4.2",
         "@types/estree": "^1.0.6",
-        "ajv": "^6.12.4",
-        "chalk": "^4.0.0",
+        "ajv": "^6.14.0",
         "cross-spawn": "^7.0.6",
         "debug": "^4.3.2",
         "escape-string-regexp": "^4.0.0",
-        "eslint-scope": "^8.4.0",
-        "eslint-visitor-keys": "^4.2.1",
-        "espree": "^10.4.0",
-        "esquery": "^1.5.0",
+        "eslint-scope": "^9.1.2",
+        "eslint-visitor-keys": "^5.0.1",
+        "espree": "^11.1.1",
+        "esquery": "^1.7.0",
         "esutils": "^2.0.2",
         "fast-deep-equal": "^3.1.3",
         "file-entry-cache": "^8.0.0",
@@ -2789,8 +2646,7 @@
         "imurmurhash": "^0.1.4",
         "is-glob": "^4.0.0",
         "json-stable-stringify-without-jsonify": "^1.0.1",
-        "lodash.merge": "^4.6.2",
-        "minimatch": "^3.1.2",
+        "minimatch": "^10.2.4",
         "natural-compare": "^1.4.0",
         "optionator": "^0.9.3"
       },
@@ -2798,7 +2654,7 @@
         "eslint": "bin/eslint.js"
       },
       "engines": {
-        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+        "node": "^20.19.0 || ^22.13.0 || >=24"
       },
       "funding": {
         "url": "https://eslint.org/donate";
@@ -2876,48 +2732,37 @@
       }
     },
     "node_modules/eslint-scope": {
-      "version": "8.4.0",
-      "resolved": 
"https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz";,
-      "integrity": 
"sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==",
+      "version": "9.1.2",
+      "resolved": 
"https://registry.npmjs.org/eslint-scope/-/eslint-scope-9.1.2.tgz";,
+      "integrity": 
"sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ==",
       "dev": true,
       "license": "BSD-2-Clause",
       "dependencies": {
+        "@types/esrecurse": "^4.3.1",
+        "@types/estree": "^1.0.8",
         "esrecurse": "^4.3.0",
         "estraverse": "^5.2.0"
       },
       "engines": {
-        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+        "node": "^20.19.0 || ^22.13.0 || >=24"
       },
       "funding": {
         "url": "https://opencollective.com/eslint";
       }
     },
     "node_modules/eslint-visitor-keys": {
-      "version": "4.2.1",
-      "resolved": 
"https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz";,
-      "integrity": 
"sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
+      "version": "5.0.1",
+      "resolved": 
"https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz";,
+      "integrity": 
"sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==",
       "dev": true,
       "license": "Apache-2.0",
       "engines": {
-        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+        "node": "^20.19.0 || ^22.13.0 || >=24"
       },
       "funding": {
         "url": "https://opencollective.com/eslint";
       }
     },
-    "node_modules/eslint/node_modules/@eslint/core": {
-      "version": "0.17.0",
-      "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz";,
-      "integrity": 
"sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==",
-      "dev": true,
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@types/json-schema": "^7.0.15"
-      },
-      "engines": {
-        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
-      }
-    },
     "node_modules/esm-env": {
       "version": "1.2.2",
       "resolved": "https://registry.npmjs.org/esm-env/-/esm-env-1.2.2.tgz";,
@@ -2925,27 +2770,27 @@
       "license": "MIT"
     },
     "node_modules/espree": {
-      "version": "10.4.0",
-      "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz";,
-      "integrity": 
"sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==",
+      "version": "11.2.0",
+      "resolved": "https://registry.npmjs.org/espree/-/espree-11.2.0.tgz";,
+      "integrity": 
"sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw==",
       "dev": true,
       "license": "BSD-2-Clause",
       "dependencies": {
-        "acorn": "^8.15.0",
+        "acorn": "^8.16.0",
         "acorn-jsx": "^5.3.2",
-        "eslint-visitor-keys": "^4.2.1"
+        "eslint-visitor-keys": "^5.0.1"
       },
       "engines": {
-        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+        "node": "^20.19.0 || ^22.13.0 || >=24"
       },
       "funding": {
         "url": "https://opencollective.com/eslint";
       }
     },
     "node_modules/esquery": {
-      "version": "1.6.0",
-      "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz";,
-      "integrity": 
"sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==",
+      "version": "1.7.0",
+      "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz";,
+      "integrity": 
"sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==",
       "dev": true,
       "license": "BSD-3-Clause",
       "dependencies": {
@@ -3112,9 +2957,9 @@
       }
     },
     "node_modules/flatted": {
-      "version": "3.3.3",
-      "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz";,
-      "integrity": 
"sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==",
+      "version": "3.3.4",
+      "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.4.tgz";,
+      "integrity": 
"sha512-3+mMldrTAPdta5kjX2G2J7iX4zxtnwpdA8Tr2ZSjkyPSanvbZAcy6flmtnXbEybHrDcU9641lxrMfFuUxVz9vA==",
       "dev": true,
       "license": "ISC"
     },
@@ -3171,9 +3016,9 @@
       }
     },
     "node_modules/globals": {
-      "version": "17.3.0",
-      "resolved": "https://registry.npmjs.org/globals/-/globals-17.3.0.tgz";,
-      "integrity": 
"sha512-yMqGUQVVCkD4tqjOJf3TnrvaaHDMYp4VlUSObbkIiuCPe/ofdMBFIAcBbCSRFWOnos6qRiTVStDwqPLUclaxIw==",
+      "version": "17.4.0",
+      "resolved": "https://registry.npmjs.org/globals/-/globals-17.4.0.tgz";,
+      "integrity": 
"sha512-hjrNztw/VajQwOLsMNT1cbJiH2muO3OROCHnbehc8eY5JyD2gqz4AcMHPqgaOR59DjgUjYAYLeH699g/eWi2jw==",
       "dev": true,
       "license": "MIT",
       "engines": {
@@ -3195,16 +3040,6 @@
       "integrity": 
"sha512-P8/mMxVLU7o4+55+1TCnQrPmgjPKnwkzkXOK1asnR9Jg2lna4tEY5qBJjMmAaOBDDZWtlRjBXjLa0w53G/uBLA==",
       "license": "Standard 'no charge' license: 
https://gsap.com/standard-license.";
     },
-    "node_modules/has-flag": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz";,
-      "integrity": 
"sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
-      "dev": true,
-      "license": "MIT",
-      "engines": {
-        "node": ">=8"
-      }
-    },
     "node_modules/hasown": {
       "version": "2.0.2",
       "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz";,
@@ -3228,23 +3063,6 @@
         "node": ">= 4"
       }
     },
-    "node_modules/import-fresh": {
-      "version": "3.3.1",
-      "resolved": 
"https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz";,
-      "integrity": 
"sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==",
-      "dev": true,
-      "license": "MIT",
-      "dependencies": {
-        "parent-module": "^1.0.0",
-        "resolve-from": "^4.0.0"
-      },
-      "engines": {
-        "node": ">=6"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus";
-      }
-    },
     "node_modules/imurmurhash": {
       "version": "0.1.4",
       "resolved": 
"https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz";,
@@ -3342,19 +3160,6 @@
         "@sideway/pinpoint": "^2.0.0"
       }
     },
-    "node_modules/js-yaml": {
-      "version": "4.1.1",
-      "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz";,
-      "integrity": 
"sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
-      "dev": true,
-      "license": "MIT",
-      "dependencies": {
-        "argparse": "^2.0.1"
-      },
-      "bin": {
-        "js-yaml": "bin/js-yaml.js"
-      }
-    },
     "node_modules/json-bigint": {
       "version": "1.0.0",
       "resolved": 
"https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz";,
@@ -3452,9 +3257,9 @@
       }
     },
     "node_modules/libphonenumber-js": {
-      "version": "1.12.31",
-      "resolved": 
"https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.12.31.tgz";,
-      "integrity": 
"sha512-Z3IhgVgrqO1S5xPYM3K5XwbkDasU67/Vys4heW+lfSBALcUZjeIIzI8zCLifY+OCzSq+fpDdywMDa7z+4srJPQ==",
+      "version": "1.12.38",
+      "resolved": 
"https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.12.38.tgz";,
+      "integrity": 
"sha512-vwzxmasAy9hZigxtqTbFEwp8ZdZ975TiqVDwj5bKx5sR+zi5ucUQy9mbVTkKM9GzqdLdxux/hTw2nmN5J7POMA==",
       "dev": true,
       "license": "MIT",
       "optional": true
@@ -3740,13 +3545,6 @@
         "url": "https://github.com/sponsors/sindresorhus";
       }
     },
-    "node_modules/lodash.merge": {
-      "version": "4.6.2",
-      "resolved": 
"https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz";,
-      "integrity": 
"sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
-      "dev": true,
-      "license": "MIT"
-    },
     "node_modules/magic-string": {
       "version": "0.30.21",
       "resolved": 
"https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz";,
@@ -3764,16 +3562,19 @@
       "license": "ISC"
     },
     "node_modules/minimatch": {
-      "version": "3.1.2",
-      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz";,
-      "integrity": 
"sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+      "version": "10.2.4",
+      "resolved": 
"https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz";,
+      "integrity": 
"sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==",
       "dev": true,
-      "license": "ISC",
+      "license": "BlueOak-1.0.0",
       "dependencies": {
-        "brace-expansion": "^1.1.7"
+        "brace-expansion": "^5.0.2"
       },
       "engines": {
-        "node": "*"
+        "node": "18 || 20 || >=22"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/isaacs";
       }
     },
     "node_modules/mri": {
@@ -3829,16 +3630,16 @@
       "license": "MIT"
     },
     "node_modules/node-releases": {
-      "version": "2.0.27",
-      "resolved": 
"https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz";,
-      "integrity": 
"sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==",
+      "version": "2.0.36",
+      "resolved": 
"https://registry.npmjs.org/node-releases/-/node-releases-2.0.36.tgz";,
+      "integrity": 
"sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA==",
       "dev": true,
       "license": "MIT"
     },
     "node_modules/normalize-url": {
-      "version": "8.1.0",
-      "resolved": 
"https://registry.npmjs.org/normalize-url/-/normalize-url-8.1.0.tgz";,
-      "integrity": 
"sha512-X06Mfd/5aKsRHc0O0J5CUedwnPmnDtLF2+nq+KN9KSDlJHkPuh0JUviWjEWMe0SW/9TDdSLVPuk7L5gGTIA1/w==",
+      "version": "8.1.1",
+      "resolved": 
"https://registry.npmjs.org/normalize-url/-/normalize-url-8.1.1.tgz";,
+      "integrity": 
"sha512-JYc0DPlpGWB40kH5g07gGTrYuMqV653k3uBKY6uITPWds3M0ov3GaWGp9lbE3Bzngx8+XkfzgvASb9vk9JDFXQ==",
       "dev": true,
       "license": "MIT",
       "optional": true,
@@ -3910,18 +3711,11 @@
         "url": "https://github.com/sponsors/sindresorhus";
       }
     },
-    "node_modules/parent-module": {
-      "version": "1.0.1",
-      "resolved": 
"https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz";,
-      "integrity": 
"sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
-      "dev": true,
-      "license": "MIT",
-      "dependencies": {
-        "callsites": "^3.0.0"
-      },
-      "engines": {
-        "node": ">=6"
-      }
+    "node_modules/parse-duration": {
+      "version": "2.1.5",
+      "resolved": 
"https://registry.npmjs.org/parse-duration/-/parse-duration-2.1.5.tgz";,
+      "integrity": 
"sha512-/IX1KRw6zHDOOJrgIz++gvFASbFl7nc8GEXaLdD7d1t1x/GnrK6hh5Fgk8G3RLpkIEi4tsGj9pupGLWNg0EiJA==",
+      "license": "MIT"
     },
     "node_modules/path-exists": {
       "version": "4.0.0",
@@ -3970,9 +3764,9 @@
       }
     },
     "node_modules/postcss": {
-      "version": "8.5.6",
-      "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz";,
-      "integrity": 
"sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==",
+      "version": "8.5.8",
+      "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.8.tgz";,
+      "integrity": 
"sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==",
       "funding": [
         {
           "type": "opencollective",
@@ -4092,9 +3886,9 @@
       }
     },
     "node_modules/postcss-selector-parser": {
-      "version": "7.1.0",
-      "resolved": 
"https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz";,
-      "integrity": 
"sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==",
+      "version": "7.1.1",
+      "resolved": 
"https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz";,
+      "integrity": 
"sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
@@ -4139,9 +3933,9 @@
       }
     },
     "node_modules/prettier-plugin-svelte": {
-      "version": "3.5.0",
-      "resolved": 
"https://registry.npmjs.org/prettier-plugin-svelte/-/prettier-plugin-svelte-3.5.0.tgz";,
-      "integrity": 
"sha512-2lLO/7EupnjO/95t+XZesXs8Bf3nYLIDfCo270h5QWbj/vjLqmrQ1LiRk9LPggxSDsnVYfehamZNf+rgQYApZg==",
+      "version": "3.5.1",
+      "resolved": 
"https://registry.npmjs.org/prettier-plugin-svelte/-/prettier-plugin-svelte-3.5.1.tgz";,
+      "integrity": 
"sha512-65+fr5+cgIKWKiqM1Doum4uX6bY8iFCdztvvp2RcF+AJoieaw9kJOFMNcJo/bkmKYsxFaM9OsVZK/gWauG/5mg==",
       "dev": true,
       "license": "MIT",
       "peerDependencies": {
@@ -4220,20 +4014,10 @@
         "url": "https://github.com/sponsors/ljharb";
       }
     },
-    "node_modules/resolve-from": {
-      "version": "4.0.0",
-      "resolved": 
"https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz";,
-      "integrity": 
"sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
-      "dev": true,
-      "license": "MIT",
-      "engines": {
-        "node": ">=4"
-      }
-    },
     "node_modules/rollup": {
-      "version": "4.53.2",
-      "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.53.2.tgz";,
-      "integrity": 
"sha512-MHngMYwGJVi6Fmnk6ISmnk7JAHRNF0UkuucA0CUW3N3a4KnONPEZz+vUanQP/ZC/iY1Qkf3bwPWzyY84wEks1g==",
+      "version": "4.59.0",
+      "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.59.0.tgz";,
+      "integrity": 
"sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
@@ -4247,28 +4031,31 @@
         "npm": ">=8.0.0"
       },
       "optionalDependencies": {
-        "@rollup/rollup-android-arm-eabi": "4.53.2",
-        "@rollup/rollup-android-arm64": "4.53.2",
-        "@rollup/rollup-darwin-arm64": "4.53.2",
-        "@rollup/rollup-darwin-x64": "4.53.2",
-        "@rollup/rollup-freebsd-arm64": "4.53.2",
-        "@rollup/rollup-freebsd-x64": "4.53.2",
-        "@rollup/rollup-linux-arm-gnueabihf": "4.53.2",
-        "@rollup/rollup-linux-arm-musleabihf": "4.53.2",
-        "@rollup/rollup-linux-arm64-gnu": "4.53.2",
-        "@rollup/rollup-linux-arm64-musl": "4.53.2",
-        "@rollup/rollup-linux-loong64-gnu": "4.53.2",
-        "@rollup/rollup-linux-ppc64-gnu": "4.53.2",
-        "@rollup/rollup-linux-riscv64-gnu": "4.53.2",
-        "@rollup/rollup-linux-riscv64-musl": "4.53.2",
-        "@rollup/rollup-linux-s390x-gnu": "4.53.2",
-        "@rollup/rollup-linux-x64-gnu": "4.53.2",
-        "@rollup/rollup-linux-x64-musl": "4.53.2",
-        "@rollup/rollup-openharmony-arm64": "4.53.2",
-        "@rollup/rollup-win32-arm64-msvc": "4.53.2",
-        "@rollup/rollup-win32-ia32-msvc": "4.53.2",
-        "@rollup/rollup-win32-x64-gnu": "4.53.2",
-        "@rollup/rollup-win32-x64-msvc": "4.53.2",
+        "@rollup/rollup-android-arm-eabi": "4.59.0",
+        "@rollup/rollup-android-arm64": "4.59.0",
+        "@rollup/rollup-darwin-arm64": "4.59.0",
+        "@rollup/rollup-darwin-x64": "4.59.0",
+        "@rollup/rollup-freebsd-arm64": "4.59.0",
+        "@rollup/rollup-freebsd-x64": "4.59.0",
+        "@rollup/rollup-linux-arm-gnueabihf": "4.59.0",
+        "@rollup/rollup-linux-arm-musleabihf": "4.59.0",
+        "@rollup/rollup-linux-arm64-gnu": "4.59.0",
+        "@rollup/rollup-linux-arm64-musl": "4.59.0",
+        "@rollup/rollup-linux-loong64-gnu": "4.59.0",
+        "@rollup/rollup-linux-loong64-musl": "4.59.0",
+        "@rollup/rollup-linux-ppc64-gnu": "4.59.0",
+        "@rollup/rollup-linux-ppc64-musl": "4.59.0",
+        "@rollup/rollup-linux-riscv64-gnu": "4.59.0",
+        "@rollup/rollup-linux-riscv64-musl": "4.59.0",
+        "@rollup/rollup-linux-s390x-gnu": "4.59.0",
+        "@rollup/rollup-linux-x64-gnu": "4.59.0",
+        "@rollup/rollup-linux-x64-musl": "4.59.0",
+        "@rollup/rollup-openbsd-x64": "4.59.0",
+        "@rollup/rollup-openharmony-arm64": "4.59.0",
+        "@rollup/rollup-win32-arm64-msvc": "4.59.0",
+        "@rollup/rollup-win32-ia32-msvc": "4.59.0",
+        "@rollup/rollup-win32-x64-gnu": "4.59.0",
+        "@rollup/rollup-win32-x64-msvc": "4.59.0",
         "fsevents": "~2.3.2"
       }
     },
@@ -4286,9 +4073,9 @@
       }
     },
     "node_modules/semver": {
-      "version": "7.7.3",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz";,
-      "integrity": 
"sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==",
+      "version": "7.7.4",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz";,
+      "integrity": 
"sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==",
       "dev": true,
       "license": "ISC",
       "bin": {
@@ -4352,19 +4139,6 @@
         "node": ">=0.10.0"
       }
     },
-    "node_modules/strip-json-comments": {
-      "version": "3.1.1",
-      "resolved": 
"https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz";,
-      "integrity": 
"sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
-      "dev": true,
-      "license": "MIT",
-      "engines": {
-        "node": ">=8"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus";
-      }
-    },
     "node_modules/superstruct": {
       "version": "2.0.2",
       "resolved": 
"https://registry.npmjs.org/superstruct/-/superstruct-2.0.2.tgz";,
@@ -4376,19 +4150,6 @@
         "node": ">=14.0.0"
       }
     },
-    "node_modules/supports-color": {
-      "version": "7.2.0",
-      "resolved": 
"https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz";,
-      "integrity": 
"sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
-      "dev": true,
-      "license": "MIT",
-      "dependencies": {
-        "has-flag": "^4.0.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
     "node_modules/supports-preserve-symlinks-flag": {
       "version": "1.0.0",
       "resolved": 
"https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz";,
@@ -4403,9 +4164,9 @@
       }
     },
     "node_modules/svelte": {
-      "version": "5.53.5",
-      "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.53.5.tgz";,
-      "integrity": 
"sha512-YkqERnF05g8KLdDZwZrF8/i1eSbj6Eoat8Jjr2IfruZz9StLuBqo8sfCSzjosNKd+ZrQ8DkKZDjpO5y3ht1Pow==",
+      "version": "5.53.7",
+      "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.53.7.tgz";,
+      "integrity": 
"sha512-uxck1KI7JWtlfP3H6HOWi/94soAl23jsGJkBzN2BAWcQng0+lTrRNhxActFqORgnO9BHVd1hKJhG+ljRuIUWfQ==",
       "license": "MIT",
       "dependencies": {
         "@jridgewell/remapping": "^2.3.4",
@@ -4454,9 +4215,9 @@
       }
     },
     "node_modules/svelte-eslint-parser": {
-      "version": "1.4.0",
-      "resolved": 
"https://registry.npmjs.org/svelte-eslint-parser/-/svelte-eslint-parser-1.4.0.tgz";,
-      "integrity": 
"sha512-fjPzOfipR5S7gQ/JvI9r2H8y9gMGXO3JtmrylHLLyahEMquXI0lrebcjT+9/hNgDej0H7abTyox5HpHmW1PSWA==",
+      "version": "1.6.0",
+      "resolved": 
"https://registry.npmjs.org/svelte-eslint-parser/-/svelte-eslint-parser-1.6.0.tgz";,
+      "integrity": 
"sha512-qoB1ehychT6OxEtQAqc/guSqLS20SlA53Uijl7x375s8nlUT0lb9ol/gzraEEatQwsyPTJo87s2CmKL9Xab+Uw==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
@@ -4465,11 +4226,12 @@
         "espree": "^10.0.0",
         "postcss": "^8.4.49",
         "postcss-scss": "^4.0.9",
-        "postcss-selector-parser": "^7.0.0"
+        "postcss-selector-parser": "^7.0.0",
+        "semver": "^7.7.2"
       },
       "engines": {
         "node": "^18.18.0 || ^20.9.0 || >=21.1.0",
-        "pnpm": "10.18.3"
+        "pnpm": "10.30.3"
       },
       "funding": {
         "url": "https://github.com/sponsors/ota-meshi";
@@ -4483,6 +4245,54 @@
         }
       }
     },
+    "node_modules/svelte-eslint-parser/node_modules/eslint-scope": {
+      "version": "8.4.0",
+      "resolved": 
"https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz";,
+      "integrity": 
"sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==",
+      "dev": true,
+      "license": "BSD-2-Clause",
+      "dependencies": {
+        "esrecurse": "^4.3.0",
+        "estraverse": "^5.2.0"
+      },
+      "engines": {
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+      },
+      "funding": {
+        "url": "https://opencollective.com/eslint";
+      }
+    },
+    "node_modules/svelte-eslint-parser/node_modules/eslint-visitor-keys": {
+      "version": "4.2.1",
+      "resolved": 
"https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz";,
+      "integrity": 
"sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
+      "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/svelte-eslint-parser/node_modules/espree": {
+      "version": "10.4.0",
+      "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz";,
+      "integrity": 
"sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==",
+      "dev": true,
+      "license": "BSD-2-Clause",
+      "dependencies": {
+        "acorn": "^8.15.0",
+        "acorn-jsx": "^5.3.2",
+        "eslint-visitor-keys": "^4.2.1"
+      },
+      "engines": {
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+      },
+      "funding": {
+        "url": "https://opencollective.com/eslint";
+      }
+    },
     "node_modules/svelte-headlessui": {
       "version": "0.0.46",
       "resolved": 
"https://registry.npmjs.org/svelte-headlessui/-/svelte-headlessui-0.0.46.tgz";,
@@ -4762,9 +4572,9 @@
       }
     },
     "node_modules/typebox": {
-      "version": "1.0.62",
-      "resolved": "https://registry.npmjs.org/typebox/-/typebox-1.0.62.tgz";,
-      "integrity": 
"sha512-iWxUfvzC5tGZWFrhoPLUKQJgFif4aDVgyaBbCURFIswex8to1JsnwDtenM2GqNI1VC/vqNlHtGc0ZR5eh0vbww==",
+      "version": "1.1.6",
+      "resolved": "https://registry.npmjs.org/typebox/-/typebox-1.1.6.tgz";,
+      "integrity": 
"sha512-O2iWCF+RboQfDqr6n83eOq0dKCjVchMWklKgdwKFeR01MGTskILHYEFi9n3lQvfuua4CtvG/EJEIg3P8H9eBcw==",
       "dev": true,
       "license": "MIT",
       "optional": true
@@ -4892,9 +4702,9 @@
       }
     },
     "node_modules/validator": {
-      "version": "13.15.23",
-      "resolved": 
"https://registry.npmjs.org/validator/-/validator-13.15.23.tgz";,
-      "integrity": 
"sha512-4yoz1kEWqUjzi5zsPbAS/903QXSYp0UOtHsPpp7p9rHAw/W+dkInskAE386Fat3oKRROwO98d9ZB0G4cObgUyw==",
+      "version": "13.15.26",
+      "resolved": 
"https://registry.npmjs.org/validator/-/validator-13.15.26.tgz";,
+      "integrity": 
"sha512-spH26xU080ydGggxRyR1Yhcbgx+j3y5jbNXk/8L+iRvdIEQ4uTRH2Sgf2dokud6Q4oAtsbNvJ1Ft+9xmm6IZcA==",
       "dev": true,
       "license": "MIT",
       "optional": true,
@@ -4978,9 +4788,9 @@
       }
     },
     "node_modules/vitefu": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/vitefu/-/vitefu-1.1.1.tgz";,
-      "integrity": 
"sha512-B/Fegf3i8zh0yFbpzZ21amWzHmuNlLlmJT6n7bu5e+pCHUKQIfXSYokrqOBGEMMe9UG2sostKQF9mml/vYaWJQ==",
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/vitefu/-/vitefu-1.1.2.tgz";,
+      "integrity": 
"sha512-zpKATdUbzbsycPFBN71nS2uzBUQiVnFoOrr2rvqv34S1lcAgMKKkjWleLGeiJlZ8lwCXvtWaRn7R3ZC16SYRuw==",
       "dev": true,
       "license": "MIT",
       "workspaces": [
@@ -4989,7 +4799,7 @@
         "tests/projects/workspace/packages/*"
       ],
       "peerDependencies": {
-        "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0-beta.0"
+        "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || 
^8.0.0-beta.0"
       },
       "peerDependenciesMeta": {
         "vite": {
diff --git a/web/package.json b/web/package.json
index 2f8c89c95..76cc33d15 100644
--- a/web/package.json
+++ b/web/package.json
@@ -14,26 +14,26 @@
     "format": "prettier --write ."
   },
   "devDependencies": {
-    "@eslint/compat": "^2.0.2",
-    "@eslint/js": "^9.39.1",
-    "@sveltejs/adapter-node": "^5.5.3",
+    "@eslint/compat": "^2.0.3",
+    "@eslint/js": "^10.0.1",
+    "@sveltejs/adapter-node": "^5.5.4",
     "@sveltejs/adapter-static": "^3.0.10",
-    "@sveltejs/kit": "^2.53.2",
+    "@sveltejs/kit": "^2.53.4",
     "@sveltejs/vite-plugin-svelte": "^6.2.4",
     "@types/d3-interpolate": "^3.0.4",
     "@types/json-bigint": "^1.0.4",
-    "@types/node": "^25.3.1",
+    "@types/node": "^25.3.5",
     "autoprefixer": "^10.4.27",
     "esbuild": "^0.27.3",
-    "eslint": "^9.39.1",
+    "eslint": "^10.0.3",
     "eslint-config-prettier": "^10.1.8",
     "eslint-plugin-svelte": "^3.15.0",
-    "globals": "^17.3.0",
+    "globals": "^17.4.0",
     "jwt-decode": "^4.0.0",
-    "postcss": "^8.5.6",
+    "postcss": "^8.5.8",
     "prettier": "^3.8.1",
-    "prettier-plugin-svelte": "^3.5.0",
-    "svelte": "^5.53.5",
+    "prettier-plugin-svelte": "^3.5.1",
+    "svelte": "^5.53.7",
     "svelte-check": "^4.4.3",
     "sveltekit-superforms": "^2.30.0",
     "tailwindcss": "^4.2.1",
@@ -45,13 +45,13 @@
     "zod": "^4.3.6"
   },
   "dependencies": {
-    "@floating-ui/dom": "^1.7.5",
+    "@floating-ui/dom": "^1.7.6",
     "@tailwindcss/postcss": "^4.2.1",
-    "@types/gsap": "^3.0.0",
     "d3-interpolate": "^3.0.1",
     "date-fns": "^4.1.0",
     "gsap": "^3.14.2",
     "json-bigint": "^1.0.0",
+    "parse-duration": "^2.1.5",
     "svelte-headlessui": "^0.0.46",
     "svelte-popperjs": "^1.3.2",
     "svelte-transition": "^0.0.17",
diff --git a/web/src/lib/components/DurationInput.svelte 
b/web/src/lib/components/DurationInput.svelte
new file mode 100644
index 000000000..c9134bac0
--- /dev/null
+++ b/web/src/lib/components/DurationInput.svelte
@@ -0,0 +1,243 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+
+<script lang="ts">
+  import parseDuration from 'parse-duration';
+  import Checkbox from './Checkbox.svelte';
+  import Input from './Input.svelte';
+  import SegmentedControl from './SegmentedControl.svelte';
+  import { durationFormatter } from '$lib/utils/formatters/durationFormatter';
+
+  interface Props {
+    label?: string;
+    value: number;
+  }
+
+  let { label = 'Message expiry', value = $bindable(0) }: Props = $props();
+
+  const US_PER_DAY = 86_400 * 1_000_000;
+  const US_PER_HOUR = 3_600 * 1_000_000;
+  const US_PER_MIN = 60 * 1_000_000;
+  const US_PER_SEC = 1_000_000;
+  const MAX_US = 10 * 365 * US_PER_DAY;
+
+  function splitToSeconds(v: number) {
+    let rem = Math.floor(v / US_PER_SEC) * US_PER_SEC;
+    const d = Math.floor(rem / US_PER_DAY);
+    rem %= US_PER_DAY;
+    const h = Math.floor(rem / US_PER_HOUR);
+    rem %= US_PER_HOUR;
+    const m = Math.floor(rem / US_PER_MIN);
+    rem %= US_PER_MIN;
+    const s = Math.floor(rem / US_PER_SEC);
+    return { d, h, m, s };
+  }
+
+  const init = splitToSeconds(value);
+
+  function buildText({ d, h, m, s }: ReturnType<typeof splitToSeconds>): 
string {
+    const parts: string[] = [];
+    if (d) parts.push(`${d}d`);
+    if (h) parts.push(`${h}h`);
+    if (m) parts.push(`${m}min`);
+    if (s) parts.push(`${s}s`);
+    return parts.join(' ');
+  }
+
+  let never = $state(value === 0);
+  let mode = $state<'fields' | 'text'>('text');
+  let textInput = $state(value > 0 ? buildText(init) : '');
+  let error = $state('');
+
+  let days = $state(init.d);
+  let hours = $state(init.h);
+  let minutes = $state(init.m);
+  let seconds = $state(init.s);
+
+  let lastSetValue = value;
+
+  function setValueInternal(v: number) {
+    value = v;
+    lastSetValue = v;
+  }
+
+  $effect(() => {
+    const v = value;
+    if (v === lastSetValue) return;
+    lastSetValue = v;
+    const parts = splitToSeconds(v);
+    never = v === 0;
+    days = parts.d;
+    hours = parts.h;
+    minutes = parts.m;
+    seconds = parts.s;
+    textInput = v > 0 ? buildText(parts) : '';
+    error = '';
+  });
+
+  function updateFromFields() {
+    error = '';
+    const us =
+      days * US_PER_DAY + hours * US_PER_HOUR + minutes * US_PER_MIN + seconds 
* US_PER_SEC;
+    if (us > MAX_US) {
+      error = 'Maximum value is 10 years';
+      return;
+    }
+    setValueInternal(us);
+  }
+
+  function parseText(showError = false) {
+    error = '';
+    if (!textInput.trim()) {
+      setValueInternal(0);
+      return;
+    }
+    if (!/[a-zA-Zµ]/.test(textInput)) {
+      if (showError) error = 'Unit required. Try e.g. "1h 30m" or "45s"';
+      return;
+    }
+    const durationInUs = parseDuration(textInput, 'us');
+    if (durationInUs == null || durationInUs <= 0) {
+      if (showError) error = 'Invalid format. Try e.g. "1h 30m" or "45s"';
+      return;
+    }
+    if (durationInUs < US_PER_SEC) {
+      if (showError) error = 'Minimum value is 1 second';
+      return;
+    }
+    if (durationInUs > MAX_US) {
+      if (showError) error = 'Maximum value is 10 years';
+      return;
+    }
+    setValueInternal(durationInUs);
+    const s = splitToSeconds(value);
+    days = s.d;
+    hours = s.h;
+    minutes = s.m;
+    seconds = s.s;
+  }
+
+  function onModeChange(newMode: 'fields' | 'text') {
+    if (newMode === 'text') {
+      textInput = value > 0 ? buildText(splitToSeconds(value)) : '';
+    } else {
+      parseText();
+    }
+    error = '';
+    mode = newMode;
+  }
+
+  const preview = $derived(never ? 'never' : value > 0 ? 
durationFormatter(value) : '');
+</script>
+
+<div class="flex flex-col gap-2">
+  <span class="text-sm text-color ml-1">{label}</span>
+
+  <div class="flex items-center gap-2">
+    <Checkbox
+      bind:checked={never}
+      value="never"
+      onclick={() => {
+        if (never) {
+          mode === 'text' ? parseText() : updateFromFields();
+        } else {
+          setValueInternal(0);
+        }
+      }}
+    />
+    <span class="text-sm text-color select-none">Never</span>
+  </div>
+
+  {#if !never}
+    <div class="flex flex-col gap-2">
+      <SegmentedControl
+        options={[
+          { value: 'text', label: 'Aa Text' },
+          { value: 'fields', label: '# Fields' }
+        ]}
+        value={mode}
+        onchange={onModeChange}
+      />
+      {#if mode === 'text'}
+        <Input
+          name="duration-text"
+          type="text"
+          placeholder="e.g. &quot;1d 2h 30m&quot; or &quot;45s&quot;  (min: 
1s)"
+          bind:value={textInput}
+          oninput={() => parseText(false)}
+          onblur={() => parseText(true)}
+        />
+      {:else}
+        <div class="flex items-center gap-2 flex-wrap">
+          <div class="w-[80px]">
+            <Input
+              name="duration-days"
+              type="number"
+              label="d"
+              min={0}
+              max={3650}
+              bind:value={days}
+              oninput={updateFromFields}
+            />
+          </div>
+          <div class="w-[80px]">
+            <Input
+              name="duration-hours"
+              type="number"
+              label="h"
+              min={0}
+              max={23}
+              bind:value={hours}
+              oninput={updateFromFields}
+            />
+          </div>
+          <div class="w-[80px]">
+            <Input
+              name="duration-minutes"
+              type="number"
+              label="min"
+              min={0}
+              max={59}
+              bind:value={minutes}
+              oninput={updateFromFields}
+            />
+          </div>
+          <div class="w-[80px]">
+            <Input
+              name="duration-seconds"
+              type="number"
+              label="s"
+              min={0}
+              max={59}
+              bind:value={seconds}
+              oninput={updateFromFields}
+            />
+          </div>
+        </div>
+      {/if}
+      {#if error}
+        <span class="text-xs text-red-500">{error}</span>
+      {/if}
+    </div>
+  {/if}
+
+  {#if preview}
+    <span class="text-xs text-shade-d200 dark:text-shade-l700 
-mt-1">{preview}</span>
+  {/if}
+</div>
diff --git a/web/src/lib/components/Modals/AddTopicModal.svelte 
b/web/src/lib/components/Modals/AddTopicModal.svelte
index cfcc7741a..40c88bb23 100644
--- a/web/src/lib/components/Modals/AddTopicModal.svelte
+++ b/web/src/lib/components/Modals/AddTopicModal.svelte
@@ -28,7 +28,7 @@
   import type { CloseModalFn } from '$lib/types/utilTypes';
   import type { StreamDetails } from '$lib/domain/StreamDetails';
   import { fetchRouteApi } from '$lib/api/fetchRouteApi';
-  import { durationFormatter } from '$lib/utils/formatters/durationFormatter';
+  import DurationInput from '../DurationInput.svelte';
   import { numberSizes } from '$lib/utils/constants/numberSizes';
   import { showToast } from '../AppToasts.svelte';
   import { customInvalidateAll } from '../PeriodicInvalidator.svelte';
@@ -46,7 +46,7 @@
       .min(1, 'Name must contain at least 1 character')
       .max(255, 'Name must not exceed 255 characters'),
     partitions_count: z.number().min(0).max(numberSizes.max.u32).default(1),
-    message_expiry: z.number().min(0).max(numberSizes.max.u32).default(0),
+    message_expiry: z.number().min(0).max(Number.MAX_SAFE_INTEGER).default(0),
     compression_algorithm: z.enum(['none', 'gzip']).default('none'),
     max_topic_size: 
z.number().min(0).max(numberSizes.max.u32).default(2_000_000_000)
   });
@@ -136,24 +136,7 @@
       errorMessage={$errors.partitions_count?.[0]}
     />
 
-    <Input
-      label="Message expiry"
-      type="number"
-      name="messageExpiry"
-      bind:value={$form.message_expiry}
-      {...$constraints.message_expiry}
-      errorMessage={$errors.message_expiry?.[0]}
-    />
-
-    <span class="-mt-1 text-xs text-shade-d200 dark:text-shade-l700">
-      {#if !$form.message_expiry || $form.message_expiry > numberSizes.max.u32}
-        {#if $form.message_expiry === 0}
-          never
-        {/if}
-      {:else}
-        {durationFormatter(+$form.message_expiry)}
-      {/if}
-    </span>
+    <DurationInput label="Message expiry" bind:value={$form.message_expiry} />
 
     <Select
       label="Compression Algorithm"
diff --git a/web/src/lib/components/Modals/TopicSettingsModal.svelte 
b/web/src/lib/components/Modals/TopicSettingsModal.svelte
index 9d9208440..b6e614d8f 100644
--- a/web/src/lib/components/Modals/TopicSettingsModal.svelte
+++ b/web/src/lib/components/Modals/TopicSettingsModal.svelte
@@ -35,9 +35,8 @@
   import ModalConfirmation from '../ModalConfirmation.svelte';
   import { browser } from '$app/environment';
   import { customInvalidateAll } from '../PeriodicInvalidator.svelte';
-  import { numberSizes } from '$lib/utils/constants/numberSizes';
   import { page } from '$app/state';
-  import { durationFormatter } from '$lib/utils/formatters/durationFormatter';
+  import DurationInput from '../DurationInput.svelte';
 
   interface Props {
     topic: TopicDetails;
@@ -55,74 +54,71 @@
       .min(1, 'Name must contain at least 1 character')
       .max(255, 'Name must not exceed 255 characters')
       .default(topic.name),
-    message_expiry: 
z.number().min(0).max(numberSizes.max.u32).default(topic.messageExpiry)
+    message_expiry: 
z.number().min(0).max(Number.MAX_SAFE_INTEGER).default(topic.messageExpiry)
   });
 
-  const { form, errors, enhance, constraints, submitting, tainted } = 
superForm(
-    defaults(zod4(schema)),
-    {
-      SPA: true,
-      validators: zod4(schema),
-      invalidateAll: false,
-      taintedMessage: false,
-      async onUpdate({ form }) {
-        if (!form.valid) return;
-        if (!page.params.streamId) return;
-
-        const { data, ok } = await fetchRouteApi({
-          method: 'PUT',
-          path: `/streams/${+page.params.streamId}/topics/${topic.id}`,
-          body: {
-            name: form.data.name,
-            message_expiry: form.data.message_expiry,
-            compression_algorithm: topic.compressionAlgorithm,
-            max_topic_size: 0
-          }
-        });
+  const { form, errors, enhance, submitting, tainted } = 
superForm(defaults(zod4(schema)), {
+    SPA: true,
+    validators: zod4(schema),
+    invalidateAll: false,
+    taintedMessage: false,
+    async onUpdate({ form }) {
+      if (!form.valid) return;
+      if (!page.params.streamId) return;
+
+      const { data, ok } = await fetchRouteApi({
+        method: 'PUT',
+        path: `/streams/${+page.params.streamId}/topics/${topic.id}`,
+        body: {
+          name: form.data.name,
+          message_expiry: form.data.message_expiry,
+          compression_algorithm: topic.compressionAlgorithm,
+          max_topic_size: 0
+        }
+      });
 
-        if (!ok) {
-          // Handle API errors
-          if (data?.field && data?.reason) {
-            // Field-specific error - show in form
-            return setError(form, data.field, data.reason);
-          } else if (data?.reason) {
-            // General error with reason - show toast
-            let errorMessage = data.reason;
-            if (data.code && data.id) {
-              errorMessage += `\n${data.code} (${data.id})`;
-            } else if (data.code) {
-              errorMessage += `\n${data.code}`;
-            }
-            showToast({
-              type: 'error',
-              description: errorMessage,
-              duration: 5000
-            });
-          } else {
-            // Fallback error message
-            showToast({
-              type: 'error',
-              description: 'Operation failed',
-              duration: 5000
-            });
+      if (!ok) {
+        // Handle API errors
+        if (data?.field && data?.reason) {
+          // Field-specific error - show in form
+          return setError(form, data.field, data.reason);
+        } else if (data?.reason) {
+          // General error with reason - show toast
+          let errorMessage = data.reason;
+          if (data.code && data.id) {
+            errorMessage += `\n${data.code} (${data.id})`;
+          } else if (data.code) {
+            errorMessage += `\n${data.code}`;
           }
-          return;
+          showToast({
+            type: 'error',
+            description: errorMessage,
+            duration: 5000
+          });
+        } else {
+          // Fallback error message
+          showToast({
+            type: 'error',
+            description: 'Operation failed',
+            duration: 5000
+          });
         }
+        return;
+      }
 
-        // Success
-        if (ok) {
-          closeModal(async () => {
-            await customInvalidateAll();
-            showToast({
-              type: 'success',
-              description: `Stream ${form.data.name} has been updated.`,
-              duration: 3500
-            });
+      // Success
+      if (ok) {
+        closeModal(async () => {
+          await customInvalidateAll();
+          showToast({
+            type: 'success',
+            description: `Stream ${form.data.name} has been updated.`,
+            duration: 3500
           });
-        }
+        });
       }
     }
-  );
+  });
 
   const onConfirmationResult = async (e: any) => {
     const result = e.detail as boolean;
@@ -168,24 +164,7 @@
     <form method="POST" class="flex flex-col gap-4 flex-3 pb-5" use:enhance>
       <Input name="name" label="Name" bind:value={$form.name} 
errorMessage={$errors.name?.[0]} />
 
-      <Input
-        label="Message expiry"
-        type="number"
-        name="messageExpiry"
-        bind:value={$form.message_expiry}
-        {...$constraints.message_expiry}
-        errorMessage={$errors.message_expiry?.[0]}
-      />
-
-      <span class="-mt-1 text-xs text-shade-d200 dark:text-shade-l700">
-        {#if !$form.message_expiry || $form.message_expiry > 
numberSizes.max.u32}
-          {#if $form.message_expiry === 0}
-            never
-          {/if}
-        {:else}
-          {durationFormatter(+$form.message_expiry)}
-        {/if}
-      </span>
+      <DurationInput label="Message expiry" bind:value={$form.message_expiry} 
/>
 
       <div class="flex justify-end gap-3 w-full mt-auto">
         <Button type="button" variant="text" class="w-2/5" onclick={() => 
closeModal()}
diff --git a/web/src/lib/components/SegmentedControl.svelte 
b/web/src/lib/components/SegmentedControl.svelte
new file mode 100644
index 000000000..d6629a35e
--- /dev/null
+++ b/web/src/lib/components/SegmentedControl.svelte
@@ -0,0 +1,48 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+
+<script lang="ts" generics="T extends string">
+  interface Props {
+    options: { value: T; label: string }[];
+    value: T;
+    onchange?: (_value: T) => void;
+  }
+
+  let { options, value = $bindable(), onchange }: Props = $props();
+
+  function select(v: T) {
+    value = v;
+    onchange?.(v);
+  }
+</script>
+
+<div class="flex rounded-md ring-1 ring-gray-300 dark:ring-gray-500 
overflow-hidden w-fit">
+  {#each options as option (option.value)}
+    <button
+      type="button"
+      onclick={() => select(option.value)}
+      class="px-3 h-[32px] text-sm transition-colors text-color"
+      class:bg-gray-200={value === option.value}
+      class:dark:bg-shade-d200={value === option.value}
+      class:font-medium={value === option.value}
+    >
+      {option.label}
+    </button>
+  {/each}
+</div>
diff --git a/web/src/lib/domain/Topic.ts b/web/src/lib/domain/Topic.ts
index dfea59a40..4873c69cf 100644
--- a/web/src/lib/domain/Topic.ts
+++ b/web/src/lib/domain/Topic.ts
@@ -17,7 +17,6 @@
  * under the License.
  */
 
-import { numberSizes } from '$lib/utils/constants/numberSizes';
 import { bytesFormatter } from '$lib/utils/formatters/bytesFormatter';
 import { formatDate } from '$lib/utils/formatters/dateFormatter';
 import { durationFormatter } from '$lib/utils/formatters/durationFormatter';
@@ -37,17 +36,16 @@ export type Topic = {
 };
 
 export function topicMapper(item: any): Topic {
-  const messageExpirySeconds =
-    item.message_expiry == null || item.message_expiry >= numberSizes.max.u32
-      ? 0
-      : item.message_expiry;
+  const micros: number = item.message_expiry ?? 0;
+
+  const messageExpiry = micros === 0 || micros >= Number.MAX_SAFE_INTEGER ? 0 
: micros;
   return {
     id: item.id,
     name: item.name,
     sizeBytes: item.size,
     sizeFormatted: bytesFormatter(item.size),
-    messageExpiry: messageExpirySeconds,
-    messageExpiryFormatted: formatExpiry(messageExpirySeconds),
+    messageExpiry,
+    messageExpiryFormatted: formatExpiry(messageExpiry),
     messagesCount: item.messages_count,
     partitionsCount: item.partitions_count,
     createdAt: formatDate(item.created_at),
@@ -56,10 +54,7 @@ export function topicMapper(item: any): Topic {
   };
 }
 
-function formatExpiry(expiry: number): string {
-  if (expiry === 0 || expiry >= numberSizes.max.u32) {
-    return 'never';
-  }
-
-  return durationFormatter(expiry);
+function formatExpiry(micros: number): string {
+  if (micros === 0) return 'never';
+  return durationFormatter(micros);
 }
diff --git a/web/src/lib/utils/formatters/durationFormatter.ts 
b/web/src/lib/utils/formatters/durationFormatter.ts
index 685507fe6..445b6ea2d 100644
--- a/web/src/lib/utils/formatters/durationFormatter.ts
+++ b/web/src/lib/utils/formatters/durationFormatter.ts
@@ -17,12 +17,14 @@
  * under the License.
  */
 
-import { formatDuration, intervalToDuration, isValid } from 'date-fns';
+import { formatDuration, intervalToDuration } from 'date-fns';
 
-export const durationFormatter = (seconds: number) => {
-  if (seconds <= 0 || seconds.toString().length > 11 || !isValid(seconds)) 
return '';
+export const durationFormatter = (microseconds: number) => {
+  if (microseconds <= 0) return '';
 
-  const duration = intervalToDuration({ start: 0, end: seconds * 1000 });
+  if (microseconds < 1_000_000) return '< 1 second';
+
+  const duration = intervalToDuration({ start: 0, end: microseconds / 1000 });
 
   return formatDuration(duration, {
     format: ['years', 'months', 'days', 'hours', 'minutes', 'seconds'],

Reply via email to