diff --git a/frontend/fic/package-lock.json b/frontend/fic/package-lock.json
index a8e1b7cc..b25b327c 100644
--- a/frontend/fic/package-lock.json
+++ b/frontend/fic/package-lock.json
@@ -15,6 +15,7 @@
         "hash-wasm": "^4.9.0",
         "seedrandom": "^3.0.5",
         "svelte-bricks": "^0.2.1",
+        "vite": "^5.0.0",
         "wordcloud": "^1.2.2"
       },
       "devDependencies": {
@@ -24,7 +25,7 @@
         "@sveltestrap/sveltestrap": "^7.0.0",
         "eslint": "^9.0.0",
         "eslint-config-prettier": "^10.0.0",
-        "eslint-plugin-svelte": "^2.35.1",
+        "eslint-plugin-svelte": "^3.0.0",
         "prettier": "^3.0.0",
         "prettier-plugin-svelte": "^3.1.2",
         "sass": "^1.51.0",
@@ -1854,9 +1855,9 @@
       }
     },
     "node_modules/eslint-compat-utils": {
-      "version": "0.5.1",
-      "resolved": "https://registry.npmjs.org/eslint-compat-utils/-/eslint-compat-utils-0.5.1.tgz",
-      "integrity": "sha512-3z3vFexKIEnjHE3zCMRo6fn/e44U7T1khUjg+Hp0ZQMCigh28rALD0nPFBcGZuiLC5rLZa2ubQHDRln09JfU2Q==",
+      "version": "0.6.4",
+      "resolved": "https://registry.npmjs.org/eslint-compat-utils/-/eslint-compat-utils-0.6.4.tgz",
+      "integrity": "sha512-/u+GQt8NMfXO8w17QendT4gvO5acfxQsAKirAt0LVxDnr2N8YLCVbregaNc/Yhp7NM128DwCaRvr8PLDfeNkQw==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
@@ -1883,32 +1884,31 @@
       }
     },
     "node_modules/eslint-plugin-svelte": {
-      "version": "2.46.1",
-      "resolved": "https://registry.npmjs.org/eslint-plugin-svelte/-/eslint-plugin-svelte-2.46.1.tgz",
-      "integrity": "sha512-7xYr2o4NID/f9OEYMqxsEQsCsj4KaMy4q5sANaKkAb6/QeCjYFxRmDm2S3YC3A3pl1kyPZ/syOx/i7LcWYSbIw==",
+      "version": "3.3.3",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-svelte/-/eslint-plugin-svelte-3.3.3.tgz",
+      "integrity": "sha512-imzGqIgWbfsb/CR14d3k3M8MiVNGet+l9mjPhvo1Rm0Nxi0rNn4/eELqyR8FWlgKBMlGkOp2kshRJm0xpxNfHQ==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
-        "@eslint-community/eslint-utils": "^4.4.0",
-        "@jridgewell/sourcemap-codec": "^1.4.15",
-        "eslint-compat-utils": "^0.5.1",
+        "@eslint-community/eslint-utils": "^4.4.1",
+        "@jridgewell/sourcemap-codec": "^1.5.0",
+        "eslint-compat-utils": "^0.6.4",
         "esutils": "^2.0.3",
         "known-css-properties": "^0.35.0",
-        "postcss": "^8.4.38",
+        "postcss": "^8.4.49",
         "postcss-load-config": "^3.1.4",
-        "postcss-safe-parser": "^6.0.0",
-        "postcss-selector-parser": "^6.1.0",
-        "semver": "^7.6.2",
-        "svelte-eslint-parser": "^0.43.0"
+        "postcss-safe-parser": "^7.0.0",
+        "semver": "^7.6.3",
+        "svelte-eslint-parser": "^1.0.1"
       },
       "engines": {
-        "node": "^14.17.0 || >=16.0.0"
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
       },
       "funding": {
         "url": "https://github.com/sponsors/ota-meshi"
       },
       "peerDependencies": {
-        "eslint": "^7.0.0 || ^8.0.0-0 || ^9.0.0-0",
+        "eslint": "^8.57.1 || ^9.0.0",
         "svelte": "^3.37.0 || ^4.0.0 || ^5.0.0"
       },
       "peerDependenciesMeta": {
@@ -2675,20 +2675,30 @@
       }
     },
     "node_modules/postcss-safe-parser": {
-      "version": "6.0.0",
-      "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-6.0.0.tgz",
-      "integrity": "sha512-FARHN8pwH+WiS2OPCxJI8FuRJpTVnn6ZNFiqAM2aeW2LwTHWWmWgIyKC6cUo0L8aeKiF/14MNvnpls6R2PBeMQ==",
+      "version": "7.0.1",
+      "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-7.0.1.tgz",
+      "integrity": "sha512-0AioNCJZ2DPYz5ABT6bddIqlhgwhpHZ/l65YAYo0BCIn0xiDpsnTHz0gnoTGk0OXZW0JRs+cDwL8u/teRdz+8A==",
       "dev": true,
+      "funding": [
+        {
+          "type": "opencollective",
+          "url": "https://opencollective.com/postcss/"
+        },
+        {
+          "type": "tidelift",
+          "url": "https://tidelift.com/funding/github/npm/postcss-safe-parser"
+        },
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/ai"
+        }
+      ],
       "license": "MIT",
       "engines": {
-        "node": ">=12.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/postcss/"
+        "node": ">=18.0"
       },
       "peerDependencies": {
-        "postcss": "^8.3.3"
+        "postcss": "^8.4.31"
       }
     },
     "node_modules/postcss-scss": {
@@ -2719,9 +2729,9 @@
       }
     },
     "node_modules/postcss-selector-parser": {
-      "version": "6.1.2",
-      "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz",
-      "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==",
+      "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==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
@@ -3051,20 +3061,21 @@
       }
     },
     "node_modules/svelte-eslint-parser": {
-      "version": "0.43.0",
-      "resolved": "https://registry.npmjs.org/svelte-eslint-parser/-/svelte-eslint-parser-0.43.0.tgz",
-      "integrity": "sha512-GpU52uPKKcVnh8tKN5P4UZpJ/fUDndmq7wfsvoVXsyP+aY0anol7Yqo01fyrlaWGMFfm4av5DyrjlaXdLRJvGA==",
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/svelte-eslint-parser/-/svelte-eslint-parser-1.1.1.tgz",
+      "integrity": "sha512-QLVGPIMDettl30qRHXU2VrPvVJKG8GsGstye7n8rFbEiu3gEARksuQg9Xu4GzubNxhGNM8stfBZkhyMbBQmjFA==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
-        "eslint-scope": "^7.2.2",
-        "eslint-visitor-keys": "^3.4.3",
-        "espree": "^9.6.1",
-        "postcss": "^8.4.39",
-        "postcss-scss": "^4.0.9"
+        "eslint-scope": "^8.2.0",
+        "eslint-visitor-keys": "^4.0.0",
+        "espree": "^10.0.0",
+        "postcss": "^8.4.49",
+        "postcss-scss": "^4.0.9",
+        "postcss-selector-parser": "^7.0.0"
       },
       "engines": {
-        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
       },
       "funding": {
         "url": "https://github.com/sponsors/ota-meshi"
@@ -3078,54 +3089,6 @@
         }
       }
     },
-    "node_modules/svelte-eslint-parser/node_modules/eslint-scope": {
-      "version": "7.2.2",
-      "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz",
-      "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==",
-      "dev": true,
-      "license": "BSD-2-Clause",
-      "dependencies": {
-        "esrecurse": "^4.3.0",
-        "estraverse": "^5.2.0"
-      },
-      "engines": {
-        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
-      },
-      "funding": {
-        "url": "https://opencollective.com/eslint"
-      }
-    },
-    "node_modules/svelte-eslint-parser/node_modules/eslint-visitor-keys": {
-      "version": "3.4.3",
-      "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
-      "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
-      "dev": true,
-      "license": "Apache-2.0",
-      "engines": {
-        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
-      },
-      "funding": {
-        "url": "https://opencollective.com/eslint"
-      }
-    },
-    "node_modules/svelte-eslint-parser/node_modules/espree": {
-      "version": "9.6.1",
-      "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz",
-      "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==",
-      "dev": true,
-      "license": "BSD-2-Clause",
-      "dependencies": {
-        "acorn": "^8.9.0",
-        "acorn-jsx": "^5.3.2",
-        "eslint-visitor-keys": "^3.4.1"
-      },
-      "engines": {
-        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
-      },
-      "funding": {
-        "url": "https://opencollective.com/eslint"
-      }
-    },
     "node_modules/svelte-hmr": {
       "version": "0.16.0",
       "resolved": "https://registry.npmjs.org/svelte-hmr/-/svelte-hmr-0.16.0.tgz",
diff --git a/frontend/fic/package.json b/frontend/fic/package.json
index 2daf9418..8a4515e6 100644
--- a/frontend/fic/package.json
+++ b/frontend/fic/package.json
@@ -15,7 +15,7 @@
     "@sveltestrap/sveltestrap": "^7.0.0",
     "eslint": "^9.0.0",
     "eslint-config-prettier": "^10.0.0",
-    "eslint-plugin-svelte": "^2.35.1",
+    "eslint-plugin-svelte": "^3.0.0",
     "prettier": "^3.0.0",
     "prettier-plugin-svelte": "^3.1.2",
     "sass": "^1.51.0",
diff --git a/qa/ui/package-lock.json b/qa/ui/package-lock.json
index 6f026eca..37033911 100644
--- a/qa/ui/package-lock.json
+++ b/qa/ui/package-lock.json
@@ -18,7 +18,7 @@
         "@sveltejs/vite-plugin-svelte": "^3.0.0",
         "eslint": "^9.0.0",
         "eslint-config-prettier": "^10.0.0",
-        "eslint-plugin-svelte": "^2.35.1",
+        "eslint-plugin-svelte": "^3.0.0",
         "prettier": "^3.0.0",
         "prettier-plugin-svelte": "^3.1.2",
         "svelte": "^4.0.0",
@@ -1485,9 +1485,9 @@
       }
     },
     "node_modules/eslint-compat-utils": {
-      "version": "0.5.1",
-      "resolved": "https://registry.npmjs.org/eslint-compat-utils/-/eslint-compat-utils-0.5.1.tgz",
-      "integrity": "sha512-3z3vFexKIEnjHE3zCMRo6fn/e44U7T1khUjg+Hp0ZQMCigh28rALD0nPFBcGZuiLC5rLZa2ubQHDRln09JfU2Q==",
+      "version": "0.6.4",
+      "resolved": "https://registry.npmjs.org/eslint-compat-utils/-/eslint-compat-utils-0.6.4.tgz",
+      "integrity": "sha512-/u+GQt8NMfXO8w17QendT4gvO5acfxQsAKirAt0LVxDnr2N8YLCVbregaNc/Yhp7NM128DwCaRvr8PLDfeNkQw==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
@@ -1514,32 +1514,31 @@
       }
     },
     "node_modules/eslint-plugin-svelte": {
-      "version": "2.46.1",
-      "resolved": "https://registry.npmjs.org/eslint-plugin-svelte/-/eslint-plugin-svelte-2.46.1.tgz",
-      "integrity": "sha512-7xYr2o4NID/f9OEYMqxsEQsCsj4KaMy4q5sANaKkAb6/QeCjYFxRmDm2S3YC3A3pl1kyPZ/syOx/i7LcWYSbIw==",
+      "version": "3.3.3",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-svelte/-/eslint-plugin-svelte-3.3.3.tgz",
+      "integrity": "sha512-imzGqIgWbfsb/CR14d3k3M8MiVNGet+l9mjPhvo1Rm0Nxi0rNn4/eELqyR8FWlgKBMlGkOp2kshRJm0xpxNfHQ==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
-        "@eslint-community/eslint-utils": "^4.4.0",
-        "@jridgewell/sourcemap-codec": "^1.4.15",
-        "eslint-compat-utils": "^0.5.1",
+        "@eslint-community/eslint-utils": "^4.4.1",
+        "@jridgewell/sourcemap-codec": "^1.5.0",
+        "eslint-compat-utils": "^0.6.4",
         "esutils": "^2.0.3",
         "known-css-properties": "^0.35.0",
-        "postcss": "^8.4.38",
+        "postcss": "^8.4.49",
         "postcss-load-config": "^3.1.4",
-        "postcss-safe-parser": "^6.0.0",
-        "postcss-selector-parser": "^6.1.0",
-        "semver": "^7.6.2",
-        "svelte-eslint-parser": "^0.43.0"
+        "postcss-safe-parser": "^7.0.0",
+        "semver": "^7.6.3",
+        "svelte-eslint-parser": "^1.0.1"
       },
       "engines": {
-        "node": "^14.17.0 || >=16.0.0"
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
       },
       "funding": {
         "url": "https://github.com/sponsors/ota-meshi"
       },
       "peerDependencies": {
-        "eslint": "^7.0.0 || ^8.0.0-0 || ^9.0.0-0",
+        "eslint": "^8.57.1 || ^9.0.0",
         "svelte": "^3.37.0 || ^4.0.0 || ^5.0.0"
       },
       "peerDependenciesMeta": {
@@ -2224,20 +2223,30 @@
       }
     },
     "node_modules/postcss-safe-parser": {
-      "version": "6.0.0",
-      "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-6.0.0.tgz",
-      "integrity": "sha512-FARHN8pwH+WiS2OPCxJI8FuRJpTVnn6ZNFiqAM2aeW2LwTHWWmWgIyKC6cUo0L8aeKiF/14MNvnpls6R2PBeMQ==",
+      "version": "7.0.1",
+      "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-7.0.1.tgz",
+      "integrity": "sha512-0AioNCJZ2DPYz5ABT6bddIqlhgwhpHZ/l65YAYo0BCIn0xiDpsnTHz0gnoTGk0OXZW0JRs+cDwL8u/teRdz+8A==",
       "dev": true,
+      "funding": [
+        {
+          "type": "opencollective",
+          "url": "https://opencollective.com/postcss/"
+        },
+        {
+          "type": "tidelift",
+          "url": "https://tidelift.com/funding/github/npm/postcss-safe-parser"
+        },
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/ai"
+        }
+      ],
       "license": "MIT",
       "engines": {
-        "node": ">=12.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/postcss/"
+        "node": ">=18.0"
       },
       "peerDependencies": {
-        "postcss": "^8.3.3"
+        "postcss": "^8.4.31"
       }
     },
     "node_modules/postcss-scss": {
@@ -2268,9 +2277,9 @@
       }
     },
     "node_modules/postcss-selector-parser": {
-      "version": "6.1.2",
-      "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz",
-      "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==",
+      "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==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
@@ -2509,20 +2518,21 @@
       }
     },
     "node_modules/svelte-eslint-parser": {
-      "version": "0.43.0",
-      "resolved": "https://registry.npmjs.org/svelte-eslint-parser/-/svelte-eslint-parser-0.43.0.tgz",
-      "integrity": "sha512-GpU52uPKKcVnh8tKN5P4UZpJ/fUDndmq7wfsvoVXsyP+aY0anol7Yqo01fyrlaWGMFfm4av5DyrjlaXdLRJvGA==",
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/svelte-eslint-parser/-/svelte-eslint-parser-1.1.1.tgz",
+      "integrity": "sha512-QLVGPIMDettl30qRHXU2VrPvVJKG8GsGstye7n8rFbEiu3gEARksuQg9Xu4GzubNxhGNM8stfBZkhyMbBQmjFA==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
-        "eslint-scope": "^7.2.2",
-        "eslint-visitor-keys": "^3.4.3",
-        "espree": "^9.6.1",
-        "postcss": "^8.4.39",
-        "postcss-scss": "^4.0.9"
+        "eslint-scope": "^8.2.0",
+        "eslint-visitor-keys": "^4.0.0",
+        "espree": "^10.0.0",
+        "postcss": "^8.4.49",
+        "postcss-scss": "^4.0.9",
+        "postcss-selector-parser": "^7.0.0"
       },
       "engines": {
-        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
       },
       "funding": {
         "url": "https://github.com/sponsors/ota-meshi"
@@ -2536,54 +2546,6 @@
         }
       }
     },
-    "node_modules/svelte-eslint-parser/node_modules/eslint-scope": {
-      "version": "7.2.2",
-      "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz",
-      "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==",
-      "dev": true,
-      "license": "BSD-2-Clause",
-      "dependencies": {
-        "esrecurse": "^4.3.0",
-        "estraverse": "^5.2.0"
-      },
-      "engines": {
-        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
-      },
-      "funding": {
-        "url": "https://opencollective.com/eslint"
-      }
-    },
-    "node_modules/svelte-eslint-parser/node_modules/eslint-visitor-keys": {
-      "version": "3.4.3",
-      "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
-      "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
-      "dev": true,
-      "license": "Apache-2.0",
-      "engines": {
-        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
-      },
-      "funding": {
-        "url": "https://opencollective.com/eslint"
-      }
-    },
-    "node_modules/svelte-eslint-parser/node_modules/espree": {
-      "version": "9.6.1",
-      "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz",
-      "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==",
-      "dev": true,
-      "license": "BSD-2-Clause",
-      "dependencies": {
-        "acorn": "^8.9.0",
-        "acorn-jsx": "^5.3.2",
-        "eslint-visitor-keys": "^3.4.1"
-      },
-      "engines": {
-        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
-      },
-      "funding": {
-        "url": "https://opencollective.com/eslint"
-      }
-    },
     "node_modules/svelte-hmr": {
       "version": "0.16.0",
       "resolved": "https://registry.npmjs.org/svelte-hmr/-/svelte-hmr-0.16.0.tgz",
diff --git a/qa/ui/package.json b/qa/ui/package.json
index d65c226b..8023a3d3 100644
--- a/qa/ui/package.json
+++ b/qa/ui/package.json
@@ -15,7 +15,7 @@
     "@sveltejs/vite-plugin-svelte": "^3.0.0",
     "eslint": "^9.0.0",
     "eslint-config-prettier": "^10.0.0",
-    "eslint-plugin-svelte": "^2.35.1",
+    "eslint-plugin-svelte": "^3.0.0",
     "prettier": "^3.0.0",
     "prettier-plugin-svelte": "^3.1.2",
     "svelte": "^4.0.0",