diff --git a/.env.example b/.env.example index 02af3a50d..cd78fae27 100644 --- a/.env.example +++ b/.env.example @@ -4,11 +4,19 @@ # Values below are PUBLIC (they're shipped to the browser by Astro's # `envField`, and live behind rate limiting / allow-lists on the vendor side). -# Kapa Custom Frontend integration ID for the "Ask AI" button in the header. -# If unset, the Ask AI button is hidden and the site still runs normally. -# Get yours at: https://app.kapa.ai/admin +# Kapa Website Widget integration ID for the "Ask AI" button in the sidebar. +# If unset, docs falls back to the shared widget integration ID used in preview/prod. +# Get yours at: https://app.kapa.ai/admin (Integrations → Widget → Copy integration ID). +# The same value is passed to the widget as `data-website-id`. +# PUBLIC_KAPA_INTEGRATION_ID=f31c5644-dd65-4f49-9762-bf580062afa8 PUBLIC_KAPA_INTEGRATION_ID= +# Optional Kapa project ID used to build internal conversation links in +# "Create ticket" email drafts: +# https://app.kapa.ai//conversations/ +# You can find this in the Kapa dashboard URL while viewing the project. +PUBLIC_KAPA_PROJECT_ID= + # RudderStack analytics — required for docs_404 event tracking and page analytics. # Without these, no analytics events are sent and the weekly 404 monitor will # report zero data. Set both in the Vercel project environment (all environments). @@ -21,3 +29,12 @@ PUBLIC_KAPA_INTEGRATION_ID= # directive in vercel.json (a mismatch silently blocks all events in the browser). PUBLIC_RUDDERSTACK_WRITE_KEY= PUBLIC_RUDDERSTACK_DATA_PLANE_URL= + +# Server-side handoff forwarding endpoint used by /api/support-handoff. +# This should point at the DevX service endpoint that creates Front +# conversations from docs chat handoff requests. +SUPPORT_HANDOFF_ENDPOINT_URL= + +# Optional shared secret sent as an authorization bearer token when +# forwarding to SUPPORT_HANDOFF_ENDPOINT_URL. +SUPPORT_HANDOFF_SHARED_SECRET= diff --git a/astro.config.mjs b/astro.config.mjs index 12462c7b4..cfad50019 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -28,6 +28,11 @@ export default defineConfig({ access: 'public', optional: true, }), + PUBLIC_KAPA_PROJECT_ID: envField.string({ + context: 'client', + access: 'public', + optional: true, + }), PUBLIC_RUDDERSTACK_WRITE_KEY: envField.string({ context: 'client', access: 'public', @@ -43,6 +48,16 @@ export default defineConfig({ access: 'public', optional: true, }), + SUPPORT_HANDOFF_ENDPOINT_URL: envField.string({ + context: 'server', + access: 'secret', + optional: true, + }), + SUPPORT_HANDOFF_SHARED_SECRET: envField.string({ + context: 'server', + access: 'secret', + optional: true, + }), }, }, integrations: [ @@ -61,15 +76,24 @@ export default defineConfig({ baseUrl: 'https://github.com/warpdotdev/docs/edit/main/', }, lastUpdated: true, - // Soft-wrap long lines by default. Expressive Code defaults to - // `overflow-x: auto` for `
`, which combined with macOS's
-			// auto-hidden scrollbars made wide lines silently truncate.
-			// `wrap: true` adds the `.wrap` class so EC's `white-space: pre-wrap`
-			// kicks in; leading indents are preserved via its `span.indent` rule.
+			// Keep long lines unwrapped so code blocks use horizontal scrolling.
+			// This aligns docs behavior with the side chat renderer and preserves
+			// exact line shape for commands and snippets.
 			expressiveCode: {
 				defaultProps: {
-					wrap: true,
+					wrap: false,
 				},
+				// IMPORTANT: Expressive Code's Vite plugin rewrites Shiki's bundled
+				// theme registry (shiki/dist/themes.mjs) and strips every theme not
+				// listed as a *string* in its `themes` config. Starlight passes its
+				// themes as objects, so the registry is emptied for the entire Vite
+				// module graph — including the Kapa side-chat island, whose runtime
+				// createHighlighter(['github-light', 'github-dark']) then throws
+				// "theme is not included in this bundle" and falls back to plaintext.
+				// Keeping the registry intact restores chat code block highlighting.
+				// Only the requested themes are ever fetched at runtime (lazy chunks),
+				// so this does not bloat the pages served to visitors.
+				removeUnusedThemes: false,
 				// Map languages Shiki doesn't bundle to a safe fallback. PromQL
 				// blocks live in platform/self-hosting/monitoring.mdx;
 				// without this alias every build emits noisy "language could not be
diff --git a/package-lock.json b/package-lock.json
index fc8163d9c..ff6515873 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -274,6 +274,9 @@
       "cpu": [
         "arm64"
       ],
+      "libc": [
+        "glibc"
+      ],
       "license": "MIT",
       "optional": true,
       "os": [
@@ -290,6 +293,9 @@
       "cpu": [
         "arm64"
       ],
+      "libc": [
+        "musl"
+      ],
       "license": "MIT",
       "optional": true,
       "os": [
@@ -306,6 +312,9 @@
       "cpu": [
         "x64"
       ],
+      "libc": [
+        "glibc"
+      ],
       "license": "MIT",
       "optional": true,
       "os": [
@@ -322,6 +331,9 @@
       "cpu": [
         "x64"
       ],
+      "libc": [
+        "musl"
+      ],
       "license": "MIT",
       "optional": true,
       "os": [
@@ -392,14 +404,14 @@
       }
     },
     "node_modules/@astrojs/internal-helpers": {
-      "version": "0.10.2",
-      "resolved": "https://registry.npmjs.org/@astrojs/internal-helpers/-/internal-helpers-0.10.2.tgz",
-      "integrity": "sha512-yt7fMgPYqSM4Tmr+taTW6Per+hjJ8Pk6lA1PAcDyqzOt8HzJ6Kje5WzCxA2Sd+9wsUW7uhkLeoTMK0cXPwH9rQ==",
+      "version": "0.10.0",
+      "resolved": "https://registry.npmjs.org/@astrojs/internal-helpers/-/internal-helpers-0.10.0.tgz",
+      "integrity": "sha512-Ry2R3VPeIN4uPCSA4xQc+e+vsJXkalKpEbDc07hV+a/o5Bs2N/s/uDcPJH/05L19DKh9tAy7e6JM3YZ6Cxfezw==",
       "license": "MIT",
       "dependencies": {
         "@types/hast": "^3.0.4",
         "@types/mdast": "^4.0.4",
-        "js-yaml": "^4.3.0",
+        "js-yaml": "^4.1.1",
         "picomatch": "^4.0.4",
         "retext-smartypants": "^6.2.0",
         "shiki": "^4.0.2",
@@ -481,121 +493,6 @@
         "vfile": "^6.0.3"
       }
     },
-    "node_modules/@astrojs/markdown-remark/node_modules/@astrojs/internal-helpers": {
-      "version": "0.10.0",
-      "resolved": "https://registry.npmjs.org/@astrojs/internal-helpers/-/internal-helpers-0.10.0.tgz",
-      "integrity": "sha512-Ry2R3VPeIN4uPCSA4xQc+e+vsJXkalKpEbDc07hV+a/o5Bs2N/s/uDcPJH/05L19DKh9tAy7e6JM3YZ6Cxfezw==",
-      "license": "MIT",
-      "dependencies": {
-        "@types/hast": "^3.0.4",
-        "@types/mdast": "^4.0.4",
-        "js-yaml": "^4.1.1",
-        "picomatch": "^4.0.4",
-        "retext-smartypants": "^6.2.0",
-        "shiki": "^4.0.2",
-        "smol-toml": "^1.6.0",
-        "unified": "^11.0.5"
-      }
-    },
-    "node_modules/@astrojs/markdown-remark/node_modules/@shikijs/core": {
-      "version": "4.3.0",
-      "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-4.3.0.tgz",
-      "integrity": "sha512-EooU3i9F6IAE8kEu+AnGf9DFZWkQBZ+hJn3tLVbsH+61mtQiva5biai66fAA6nvFPXkLgvrh7BrR7YcJU83xQQ==",
-      "license": "MIT",
-      "dependencies": {
-        "@shikijs/primitive": "4.3.0",
-        "@shikijs/types": "4.3.0",
-        "@shikijs/vscode-textmate": "^10.0.2",
-        "@types/hast": "^3.0.4",
-        "hast-util-to-html": "^9.0.5"
-      },
-      "engines": {
-        "node": ">=20"
-      }
-    },
-    "node_modules/@astrojs/markdown-remark/node_modules/@shikijs/engine-javascript": {
-      "version": "4.3.0",
-      "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-4.3.0.tgz",
-      "integrity": "sha512-hTv/KiFf2tpiqlACPiztGGurEARWIutB8YUhcrA1pUC7VzzwKO+g5crUocrLztrZ5ro5Z4hbXg7bYclETn3gSQ==",
-      "license": "MIT",
-      "dependencies": {
-        "@shikijs/types": "4.3.0",
-        "@shikijs/vscode-textmate": "^10.0.2",
-        "oniguruma-to-es": "^4.3.6"
-      },
-      "engines": {
-        "node": ">=20"
-      }
-    },
-    "node_modules/@astrojs/markdown-remark/node_modules/@shikijs/engine-oniguruma": {
-      "version": "4.3.0",
-      "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-4.3.0.tgz",
-      "integrity": "sha512-1vMdN3gHfnKfLYwecUI2ITJI4RhHt96xEaJumVn7Heb0IlJ8WQMIH0Voak+2j22BpSNKdnOfB/pCTPnPm2gq7A==",
-      "license": "MIT",
-      "dependencies": {
-        "@shikijs/types": "4.3.0",
-        "@shikijs/vscode-textmate": "^10.0.2"
-      },
-      "engines": {
-        "node": ">=20"
-      }
-    },
-    "node_modules/@astrojs/markdown-remark/node_modules/@shikijs/langs": {
-      "version": "4.3.0",
-      "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-4.3.0.tgz",
-      "integrity": "sha512-rnlqFbBRSys9bT4gl/5rw9RnS0W/I84ZldXPkO7cvlEMoV85TyF/aU01N7/NbSR776RNLjrJKjfFUXJR6wN1Cg==",
-      "license": "MIT",
-      "dependencies": {
-        "@shikijs/types": "4.3.0"
-      },
-      "engines": {
-        "node": ">=20"
-      }
-    },
-    "node_modules/@astrojs/markdown-remark/node_modules/@shikijs/themes": {
-      "version": "4.3.0",
-      "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-4.3.0.tgz",
-      "integrity": "sha512-Avgt05YiT+Y3prjIc9lmQxhJzHBcCfR6cjiFW4OyaMBbt2A6trX5rfjUzx+Vj/mE9qpArYjatnqo9XPjQNW/AQ==",
-      "license": "MIT",
-      "dependencies": {
-        "@shikijs/types": "4.3.0"
-      },
-      "engines": {
-        "node": ">=20"
-      }
-    },
-    "node_modules/@astrojs/markdown-remark/node_modules/@shikijs/types": {
-      "version": "4.3.0",
-      "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-4.3.0.tgz",
-      "integrity": "sha512-oc8b9U2SYvofKZk8e/737nIX0qwf6eV2vHFATeObAu7r+mUVpLs8Re0BmVkIjAWAYgkmG/CzLNo7rzuBzRu/wQ==",
-      "license": "MIT",
-      "dependencies": {
-        "@shikijs/vscode-textmate": "^10.0.2",
-        "@types/hast": "^3.0.4"
-      },
-      "engines": {
-        "node": ">=20"
-      }
-    },
-    "node_modules/@astrojs/markdown-remark/node_modules/shiki": {
-      "version": "4.3.0",
-      "resolved": "https://registry.npmjs.org/shiki/-/shiki-4.3.0.tgz",
-      "integrity": "sha512-NKKjWzR6LIGL3sXBrWDw9sDS9cxx42/DkysaNqJEeOWE8Kix5gpak0bc00OfDVEO4oyXSyz8+aRaqKoBD1yo7A==",
-      "license": "MIT",
-      "dependencies": {
-        "@shikijs/core": "4.3.0",
-        "@shikijs/engine-javascript": "4.3.0",
-        "@shikijs/engine-oniguruma": "4.3.0",
-        "@shikijs/langs": "4.3.0",
-        "@shikijs/themes": "4.3.0",
-        "@shikijs/types": "4.3.0",
-        "@shikijs/vscode-textmate": "^10.0.2",
-        "@types/hast": "^3.0.4"
-      },
-      "engines": {
-        "node": ">=20"
-      }
-    },
     "node_modules/@astrojs/markdown-satteri": {
       "version": "0.3.4",
       "resolved": "https://registry.npmjs.org/@astrojs/markdown-satteri/-/markdown-satteri-0.3.4.tgz",
@@ -709,6 +606,22 @@
         "react-dom": "^17.0.2 || ^18.0.0 || ^19.0.0"
       }
     },
+    "node_modules/@astrojs/react/node_modules/@astrojs/internal-helpers": {
+      "version": "0.10.2",
+      "resolved": "https://registry.npmjs.org/@astrojs/internal-helpers/-/internal-helpers-0.10.2.tgz",
+      "integrity": "sha512-yt7fMgPYqSM4Tmr+taTW6Per+hjJ8Pk6lA1PAcDyqzOt8HzJ6Kje5WzCxA2Sd+9wsUW7uhkLeoTMK0cXPwH9rQ==",
+      "license": "MIT",
+      "dependencies": {
+        "@types/hast": "^3.0.4",
+        "@types/mdast": "^4.0.4",
+        "js-yaml": "^4.3.0",
+        "picomatch": "^4.0.4",
+        "retext-smartypants": "^6.2.0",
+        "shiki": "^4.0.2",
+        "smol-toml": "^1.6.0",
+        "unified": "^11.0.5"
+      }
+    },
     "node_modules/@astrojs/rss": {
       "version": "4.0.19",
       "resolved": "https://registry.npmjs.org/@astrojs/rss/-/rss-4.0.19.tgz",
@@ -888,9 +801,9 @@
       }
     },
     "node_modules/@babel/code-frame/node_modules/@babel/helper-validator-identifier": {
-      "version": "8.0.2",
-      "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-8.0.2.tgz",
-      "integrity": "sha512-9Fr9QeyCAyi1BR1jKZ6uYQ24EIhQUx5ReHfQU7drOE+TPOb+w11/dsqLkMOT2U29OdCT71XajrOT8xDc1C7orA==",
+      "version": "8.0.4",
+      "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-8.0.4.tgz",
+      "integrity": "sha512-4wFaiLd0bVo4cIoTXI3zKI038NIWE/cr3jvBjejOVYVxV/m8Ltav1USiGzG1fmS5J2RhgEOgXNNK46cRPnRsrg==",
       "license": "MIT",
       "engines": {
         "node": "^22.18.0 || >=24.11.0"
@@ -946,21 +859,21 @@
       }
     },
     "node_modules/@babel/core/node_modules/@babel/helper-validator-identifier": {
-      "version": "8.0.2",
-      "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-8.0.2.tgz",
-      "integrity": "sha512-9Fr9QeyCAyi1BR1jKZ6uYQ24EIhQUx5ReHfQU7drOE+TPOb+w11/dsqLkMOT2U29OdCT71XajrOT8xDc1C7orA==",
+      "version": "8.0.4",
+      "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-8.0.4.tgz",
+      "integrity": "sha512-4wFaiLd0bVo4cIoTXI3zKI038NIWE/cr3jvBjejOVYVxV/m8Ltav1USiGzG1fmS5J2RhgEOgXNNK46cRPnRsrg==",
       "license": "MIT",
       "engines": {
         "node": "^22.18.0 || >=24.11.0"
       }
     },
     "node_modules/@babel/core/node_modules/@babel/parser": {
-      "version": "8.0.0",
-      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-8.0.0.tgz",
-      "integrity": "sha512-aLxAE+imI9bCcyaPrUDjBv3uSkWieifjLe0kuFOZF0zli0L6GCsTmsePnTr55adbIAgYz2zhN1vnFimCBUYcRQ==",
+      "version": "8.0.4",
+      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-8.0.4.tgz",
+      "integrity": "sha512-srpptsAkEbbNIC/q8nT7o+m6CQe8CJUTV/t7MYc9NnWlgYVtHOb7JH6SorxMhN0kuRJjVqXbKClG6xSbPtzz+g==",
       "license": "MIT",
       "dependencies": {
-        "@babel/types": "^8.0.0"
+        "@babel/types": "^8.0.4"
       },
       "bin": {
         "parser": "bin/babel-parser.js"
@@ -970,13 +883,13 @@
       }
     },
     "node_modules/@babel/core/node_modules/@babel/types": {
-      "version": "8.0.0",
-      "resolved": "https://registry.npmjs.org/@babel/types/-/types-8.0.0.tgz",
-      "integrity": "sha512-K8ponJDxBwDHigkeFqaqT5wLGl4bTlwMafR8k7b5CPxr6Ww+UG9ls8Yx6Tcpboxu97eeGVEEyKcHmEyOwN1vSw==",
+      "version": "8.0.4",
+      "resolved": "https://registry.npmjs.org/@babel/types/-/types-8.0.4.tgz",
+      "integrity": "sha512-eY+Yn3dCqTGmyiq2QRU66lA5FL8lqqqvecHt0fF3uHONIa7ToYsaCiWV8lOKqAs0Rb2SjixiKFROngnulPtt2g==",
       "license": "MIT",
       "dependencies": {
         "@babel/helper-string-parser": "^8.0.0",
-        "@babel/helper-validator-identifier": "^8.0.0"
+        "@babel/helper-validator-identifier": "^8.0.4"
       },
       "engines": {
         "node": "^22.18.0 || >=24.11.0"
@@ -1009,21 +922,21 @@
       }
     },
     "node_modules/@babel/generator/node_modules/@babel/helper-validator-identifier": {
-      "version": "8.0.2",
-      "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-8.0.2.tgz",
-      "integrity": "sha512-9Fr9QeyCAyi1BR1jKZ6uYQ24EIhQUx5ReHfQU7drOE+TPOb+w11/dsqLkMOT2U29OdCT71XajrOT8xDc1C7orA==",
+      "version": "8.0.4",
+      "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-8.0.4.tgz",
+      "integrity": "sha512-4wFaiLd0bVo4cIoTXI3zKI038NIWE/cr3jvBjejOVYVxV/m8Ltav1USiGzG1fmS5J2RhgEOgXNNK46cRPnRsrg==",
       "license": "MIT",
       "engines": {
         "node": "^22.18.0 || >=24.11.0"
       }
     },
     "node_modules/@babel/generator/node_modules/@babel/parser": {
-      "version": "8.0.0",
-      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-8.0.0.tgz",
-      "integrity": "sha512-aLxAE+imI9bCcyaPrUDjBv3uSkWieifjLe0kuFOZF0zli0L6GCsTmsePnTr55adbIAgYz2zhN1vnFimCBUYcRQ==",
+      "version": "8.0.4",
+      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-8.0.4.tgz",
+      "integrity": "sha512-srpptsAkEbbNIC/q8nT7o+m6CQe8CJUTV/t7MYc9NnWlgYVtHOb7JH6SorxMhN0kuRJjVqXbKClG6xSbPtzz+g==",
       "license": "MIT",
       "dependencies": {
-        "@babel/types": "^8.0.0"
+        "@babel/types": "^8.0.4"
       },
       "bin": {
         "parser": "bin/babel-parser.js"
@@ -1033,13 +946,13 @@
       }
     },
     "node_modules/@babel/generator/node_modules/@babel/types": {
-      "version": "8.0.0",
-      "resolved": "https://registry.npmjs.org/@babel/types/-/types-8.0.0.tgz",
-      "integrity": "sha512-K8ponJDxBwDHigkeFqaqT5wLGl4bTlwMafR8k7b5CPxr6Ww+UG9ls8Yx6Tcpboxu97eeGVEEyKcHmEyOwN1vSw==",
+      "version": "8.0.4",
+      "resolved": "https://registry.npmjs.org/@babel/types/-/types-8.0.4.tgz",
+      "integrity": "sha512-eY+Yn3dCqTGmyiq2QRU66lA5FL8lqqqvecHt0fF3uHONIa7ToYsaCiWV8lOKqAs0Rb2SjixiKFROngnulPtt2g==",
       "license": "MIT",
       "dependencies": {
         "@babel/helper-string-parser": "^8.0.0",
-        "@babel/helper-validator-identifier": "^8.0.0"
+        "@babel/helper-validator-identifier": "^8.0.4"
       },
       "engines": {
         "node": "^22.18.0 || >=24.11.0"
@@ -1071,9 +984,9 @@
       }
     },
     "node_modules/@babel/helper-plugin-utils": {
-      "version": "7.28.6",
-      "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz",
-      "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==",
+      "version": "7.29.7",
+      "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.29.7.tgz",
+      "integrity": "sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==",
       "license": "MIT",
       "engines": {
         "node": ">=6.9.0"
@@ -1129,22 +1042,22 @@
       }
     },
     "node_modules/@babel/helpers/node_modules/@babel/helper-validator-identifier": {
-      "version": "8.0.2",
-      "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-8.0.2.tgz",
-      "integrity": "sha512-9Fr9QeyCAyi1BR1jKZ6uYQ24EIhQUx5ReHfQU7drOE+TPOb+w11/dsqLkMOT2U29OdCT71XajrOT8xDc1C7orA==",
+      "version": "8.0.4",
+      "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-8.0.4.tgz",
+      "integrity": "sha512-4wFaiLd0bVo4cIoTXI3zKI038NIWE/cr3jvBjejOVYVxV/m8Ltav1USiGzG1fmS5J2RhgEOgXNNK46cRPnRsrg==",
       "license": "MIT",
       "engines": {
         "node": "^22.18.0 || >=24.11.0"
       }
     },
     "node_modules/@babel/helpers/node_modules/@babel/types": {
-      "version": "8.0.0",
-      "resolved": "https://registry.npmjs.org/@babel/types/-/types-8.0.0.tgz",
-      "integrity": "sha512-K8ponJDxBwDHigkeFqaqT5wLGl4bTlwMafR8k7b5CPxr6Ww+UG9ls8Yx6Tcpboxu97eeGVEEyKcHmEyOwN1vSw==",
+      "version": "8.0.4",
+      "resolved": "https://registry.npmjs.org/@babel/types/-/types-8.0.4.tgz",
+      "integrity": "sha512-eY+Yn3dCqTGmyiq2QRU66lA5FL8lqqqvecHt0fF3uHONIa7ToYsaCiWV8lOKqAs0Rb2SjixiKFROngnulPtt2g==",
       "license": "MIT",
       "dependencies": {
         "@babel/helper-string-parser": "^8.0.0",
-        "@babel/helper-validator-identifier": "^8.0.0"
+        "@babel/helper-validator-identifier": "^8.0.4"
       },
       "engines": {
         "node": "^22.18.0 || >=24.11.0"
@@ -1166,12 +1079,12 @@
       }
     },
     "node_modules/@babel/plugin-transform-react-jsx-self": {
-      "version": "7.27.1",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz",
-      "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==",
+      "version": "7.29.7",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.29.7.tgz",
+      "integrity": "sha512-TL0hMc9xzy86VD31nUiwzd5otRAcyEPcsegCxolO0PvcXuH1v0kECe/UIznYFihpkvU5wg/jk4v0TTEFfm53fw==",
       "license": "MIT",
       "dependencies": {
-        "@babel/helper-plugin-utils": "^7.27.1"
+        "@babel/helper-plugin-utils": "^7.29.7"
       },
       "engines": {
         "node": ">=6.9.0"
@@ -1181,12 +1094,12 @@
       }
     },
     "node_modules/@babel/plugin-transform-react-jsx-source": {
-      "version": "7.27.1",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz",
-      "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==",
+      "version": "7.29.7",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.29.7.tgz",
+      "integrity": "sha512-06IyK09H3wi4cGbhDBwp5gUGo0IKtnYa8tyTiephirPCK6fbobVGiXMMI5zLQ4aKEYP3wZ3ArU44o+8KMrSG/Q==",
       "license": "MIT",
       "dependencies": {
-        "@babel/helper-plugin-utils": "^7.27.1"
+        "@babel/helper-plugin-utils": "^7.29.7"
       },
       "engines": {
         "node": ">=6.9.0"
@@ -1196,9 +1109,9 @@
       }
     },
     "node_modules/@babel/runtime": {
-      "version": "7.28.6",
-      "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.6.tgz",
-      "integrity": "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==",
+      "version": "7.29.7",
+      "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.7.tgz",
+      "integrity": "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==",
       "license": "MIT",
       "engines": {
         "node": ">=6.9.0"
@@ -1228,21 +1141,21 @@
       }
     },
     "node_modules/@babel/template/node_modules/@babel/helper-validator-identifier": {
-      "version": "8.0.2",
-      "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-8.0.2.tgz",
-      "integrity": "sha512-9Fr9QeyCAyi1BR1jKZ6uYQ24EIhQUx5ReHfQU7drOE+TPOb+w11/dsqLkMOT2U29OdCT71XajrOT8xDc1C7orA==",
+      "version": "8.0.4",
+      "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-8.0.4.tgz",
+      "integrity": "sha512-4wFaiLd0bVo4cIoTXI3zKI038NIWE/cr3jvBjejOVYVxV/m8Ltav1USiGzG1fmS5J2RhgEOgXNNK46cRPnRsrg==",
       "license": "MIT",
       "engines": {
         "node": "^22.18.0 || >=24.11.0"
       }
     },
     "node_modules/@babel/template/node_modules/@babel/parser": {
-      "version": "8.0.0",
-      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-8.0.0.tgz",
-      "integrity": "sha512-aLxAE+imI9bCcyaPrUDjBv3uSkWieifjLe0kuFOZF0zli0L6GCsTmsePnTr55adbIAgYz2zhN1vnFimCBUYcRQ==",
+      "version": "8.0.4",
+      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-8.0.4.tgz",
+      "integrity": "sha512-srpptsAkEbbNIC/q8nT7o+m6CQe8CJUTV/t7MYc9NnWlgYVtHOb7JH6SorxMhN0kuRJjVqXbKClG6xSbPtzz+g==",
       "license": "MIT",
       "dependencies": {
-        "@babel/types": "^8.0.0"
+        "@babel/types": "^8.0.4"
       },
       "bin": {
         "parser": "bin/babel-parser.js"
@@ -1252,30 +1165,30 @@
       }
     },
     "node_modules/@babel/template/node_modules/@babel/types": {
-      "version": "8.0.0",
-      "resolved": "https://registry.npmjs.org/@babel/types/-/types-8.0.0.tgz",
-      "integrity": "sha512-K8ponJDxBwDHigkeFqaqT5wLGl4bTlwMafR8k7b5CPxr6Ww+UG9ls8Yx6Tcpboxu97eeGVEEyKcHmEyOwN1vSw==",
+      "version": "8.0.4",
+      "resolved": "https://registry.npmjs.org/@babel/types/-/types-8.0.4.tgz",
+      "integrity": "sha512-eY+Yn3dCqTGmyiq2QRU66lA5FL8lqqqvecHt0fF3uHONIa7ToYsaCiWV8lOKqAs0Rb2SjixiKFROngnulPtt2g==",
       "license": "MIT",
       "dependencies": {
         "@babel/helper-string-parser": "^8.0.0",
-        "@babel/helper-validator-identifier": "^8.0.0"
+        "@babel/helper-validator-identifier": "^8.0.4"
       },
       "engines": {
         "node": "^22.18.0 || >=24.11.0"
       }
     },
     "node_modules/@babel/traverse": {
-      "version": "8.0.0",
-      "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-8.0.0.tgz",
-      "integrity": "sha512-bxTj/W2VclGE6CctlfQOpxg8MPDzXArRqkOBePw8EHfebcjF7fETWSS3BriEECo+UiU/Yblq+xUtSImFu7cTbw==",
+      "version": "8.0.4",
+      "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-8.0.4.tgz",
+      "integrity": "sha512-bZnmqzGG8UZneG1lLxBoWIH0G6Gr1D846Yu4/3XnY6FhCndMR49u26nTY08u/dAxWmLWF9vGQOuC+84FfIUoeg==",
       "license": "MIT",
       "dependencies": {
         "@babel/code-frame": "^8.0.0",
         "@babel/generator": "^8.0.0",
         "@babel/helper-globals": "^8.0.0",
-        "@babel/parser": "^8.0.0",
+        "@babel/parser": "^8.0.4",
         "@babel/template": "^8.0.0",
-        "@babel/types": "^8.0.0",
+        "@babel/types": "^8.0.4",
         "obug": "^2.1.1"
       },
       "engines": {
@@ -1292,21 +1205,21 @@
       }
     },
     "node_modules/@babel/traverse/node_modules/@babel/helper-validator-identifier": {
-      "version": "8.0.2",
-      "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-8.0.2.tgz",
-      "integrity": "sha512-9Fr9QeyCAyi1BR1jKZ6uYQ24EIhQUx5ReHfQU7drOE+TPOb+w11/dsqLkMOT2U29OdCT71XajrOT8xDc1C7orA==",
+      "version": "8.0.4",
+      "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-8.0.4.tgz",
+      "integrity": "sha512-4wFaiLd0bVo4cIoTXI3zKI038NIWE/cr3jvBjejOVYVxV/m8Ltav1USiGzG1fmS5J2RhgEOgXNNK46cRPnRsrg==",
       "license": "MIT",
       "engines": {
         "node": "^22.18.0 || >=24.11.0"
       }
     },
     "node_modules/@babel/traverse/node_modules/@babel/parser": {
-      "version": "8.0.0",
-      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-8.0.0.tgz",
-      "integrity": "sha512-aLxAE+imI9bCcyaPrUDjBv3uSkWieifjLe0kuFOZF0zli0L6GCsTmsePnTr55adbIAgYz2zhN1vnFimCBUYcRQ==",
+      "version": "8.0.4",
+      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-8.0.4.tgz",
+      "integrity": "sha512-srpptsAkEbbNIC/q8nT7o+m6CQe8CJUTV/t7MYc9NnWlgYVtHOb7JH6SorxMhN0kuRJjVqXbKClG6xSbPtzz+g==",
       "license": "MIT",
       "dependencies": {
-        "@babel/types": "^8.0.0"
+        "@babel/types": "^8.0.4"
       },
       "bin": {
         "parser": "bin/babel-parser.js"
@@ -1316,13 +1229,13 @@
       }
     },
     "node_modules/@babel/traverse/node_modules/@babel/types": {
-      "version": "8.0.0",
-      "resolved": "https://registry.npmjs.org/@babel/types/-/types-8.0.0.tgz",
-      "integrity": "sha512-K8ponJDxBwDHigkeFqaqT5wLGl4bTlwMafR8k7b5CPxr6Ww+UG9ls8Yx6Tcpboxu97eeGVEEyKcHmEyOwN1vSw==",
+      "version": "8.0.4",
+      "resolved": "https://registry.npmjs.org/@babel/types/-/types-8.0.4.tgz",
+      "integrity": "sha512-eY+Yn3dCqTGmyiq2QRU66lA5FL8lqqqvecHt0fF3uHONIa7ToYsaCiWV8lOKqAs0Rb2SjixiKFROngnulPtt2g==",
       "license": "MIT",
       "dependencies": {
         "@babel/helper-string-parser": "^8.0.0",
-        "@babel/helper-validator-identifier": "^8.0.0"
+        "@babel/helper-validator-identifier": "^8.0.4"
       },
       "engines": {
         "node": "^22.18.0 || >=24.11.0"
@@ -1374,6 +1287,9 @@
       "cpu": [
         "arm64"
       ],
+      "libc": [
+        "glibc"
+      ],
       "license": "MIT",
       "optional": true,
       "os": [
@@ -1387,6 +1303,9 @@
       "cpu": [
         "arm64"
       ],
+      "libc": [
+        "musl"
+      ],
       "license": "MIT",
       "optional": true,
       "os": [
@@ -1400,6 +1319,9 @@
       "cpu": [
         "x64"
       ],
+      "libc": [
+        "glibc"
+      ],
       "license": "MIT",
       "optional": true,
       "os": [
@@ -1413,6 +1335,9 @@
       "cpu": [
         "x64"
       ],
+      "libc": [
+        "musl"
+      ],
       "license": "MIT",
       "optional": true,
       "os": [
@@ -1577,25 +1502,14 @@
       "license": "MIT"
     },
     "node_modules/@emnapi/core": {
-      "version": "1.11.3",
-      "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.11.3.tgz",
-      "integrity": "sha512-zLpS5asjEb7lq8jYLq37N6XKaE41DIexlY1rF/z4/tIl3wo13Sqm28fRyfIsKZD+NZ8mM5RoKkpW/rBcuoSZSg==",
-      "license": "MIT",
-      "optional": true,
-      "peer": true,
-      "dependencies": {
-        "@emnapi/wasi-threads": "1.2.3",
-        "tslib": "^2.4.0"
-      }
-    },
-    "node_modules/@emnapi/core/node_modules/@emnapi/wasi-threads": {
-      "version": "1.2.3",
-      "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.3.tgz",
-      "integrity": "sha512-ELEBe8PsLvvJ6QMr0zLt8ffvOHW/dc1m3CEzNMg7aJUv3bMaoDtw2TXyDAwkYBuroxxuHEwhRTLJSe5sya547g==",
+      "version": "1.11.2",
+      "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.11.2.tgz",
+      "integrity": "sha512-TC8MkTuZUtcTSiFeuC0ksCh9QIJ5+F21MvZ4Wn4ORfYaFJ/0dsiudv5tVkejgwZlwQ39jL9WWDe2lz8x0WglOA==",
       "license": "MIT",
       "optional": true,
       "peer": true,
       "dependencies": {
+        "@emnapi/wasi-threads": "1.2.2",
         "tslib": "^2.4.0"
       }
     },
@@ -2081,9 +1995,9 @@
       }
     },
     "node_modules/@fingerprintjs/fingerprintjs-pro": {
-      "version": "3.12.8",
-      "resolved": "https://registry.npmjs.org/@fingerprintjs/fingerprintjs-pro/-/fingerprintjs-pro-3.12.8.tgz",
-      "integrity": "sha512-6BEMtAkfvMTnTLpHaS6q+lW11msE9vFzHheE95SD/+X21QKGVsMGlel7lBG2ClGHHdqpFNO+nNKvuIl/xdPgng==",
+      "version": "3.12.13",
+      "resolved": "https://registry.npmjs.org/@fingerprintjs/fingerprintjs-pro/-/fingerprintjs-pro-3.12.13.tgz",
+      "integrity": "sha512-l9G1jn6d9wpIG8bMW7TsrHjPwm26B4T6OB42PlLNQ9QrblbuGWvVEFb+gqdCzzPcP6J+zfCoXQ3xMPlp88SgXg==",
       "license": "SEE LICENSE IN LICENSE"
     },
     "node_modules/@fingerprintjs/fingerprintjs-pro-react": {
@@ -2108,31 +2022,31 @@
       }
     },
     "node_modules/@floating-ui/core": {
-      "version": "1.7.5",
-      "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.5.tgz",
-      "integrity": "sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==",
+      "version": "1.8.0",
+      "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.8.0.tgz",
+      "integrity": "sha512-0CIZ5itps/8x7BG8dEIhs53BvCUH2PCoogtakwRTut+Arm58sJooJ0AuZhLw2HJYIR5cMLNPBSS728sPho2khQ==",
       "license": "MIT",
       "dependencies": {
-        "@floating-ui/utils": "^0.2.11"
+        "@floating-ui/utils": "^0.2.12"
       }
     },
     "node_modules/@floating-ui/dom": {
-      "version": "1.7.6",
-      "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.6.tgz",
-      "integrity": "sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==",
+      "version": "1.8.0",
+      "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.8.0.tgz",
+      "integrity": "sha512-yXSrzeHZBTZadLOlfyhCkJHNeLJnHRnRInwdZ40L7ZiaAtrBwoYlsDrX3v5zB1Utk7CLfzcOVnVVWoXEky7Ceg==",
       "license": "MIT",
       "dependencies": {
-        "@floating-ui/core": "^1.7.5",
-        "@floating-ui/utils": "^0.2.11"
+        "@floating-ui/core": "^1.8.0",
+        "@floating-ui/utils": "^0.2.12"
       }
     },
     "node_modules/@floating-ui/react-dom": {
-      "version": "2.1.8",
-      "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.8.tgz",
-      "integrity": "sha512-cC52bHwM/n/CxS87FH0yWdngEZrjdtLW/qVruo68qg+prK7ZQ4YGdut2GyDVpoGeAYe/h899rVeOVm6Oi40k2A==",
+      "version": "2.1.9",
+      "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.9.tgz",
+      "integrity": "sha512-JDjEFGCpImxDCA7JJKviA0M9+RtmJdj0m/NVU5IMgBK+AmZouAQQ7/+2GLH0GXXY0YMw9oXPB8hKdbPYg5QLYg==",
       "license": "MIT",
       "dependencies": {
-        "@floating-ui/dom": "^1.7.6"
+        "@floating-ui/dom": "^1.8.0"
       },
       "peerDependencies": {
         "react": ">=16.8.0",
@@ -2140,15 +2054,15 @@
       }
     },
     "node_modules/@floating-ui/utils": {
-      "version": "0.2.11",
-      "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.11.tgz",
-      "integrity": "sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==",
+      "version": "0.2.12",
+      "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.12.tgz",
+      "integrity": "sha512-HpCo8tmWzLVad5s2d19EhAz5zqrrQ6s69qd6moPMQvkOuSwDT1YgRfWSVuc4ennqrgv3OHppiOGMQ7oC13yIww==",
       "license": "MIT"
     },
     "node_modules/@hcaptcha/loader": {
-      "version": "2.3.0",
-      "resolved": "https://registry.npmjs.org/@hcaptcha/loader/-/loader-2.3.0.tgz",
-      "integrity": "sha512-i4lnNxKBe+COf3R1nFZEWaZoHIoJjvDgWqvcNrdZq8ehoSNMN6KVZ56dcQ02qKie2h3+BkbkwlJA9DOIuLlK/g==",
+      "version": "2.4.2",
+      "resolved": "https://registry.npmjs.org/@hcaptcha/loader/-/loader-2.4.2.tgz",
+      "integrity": "sha512-+Pf0Vin6iJlJj5u/mq6XMgbJT1mi/Sg5LWHxxqO4YHt2YvdZgecp5V2sbC6vRaNPJUqQGk2HOu1K/i12mqs5vw==",
       "license": "MIT"
     },
     "node_modules/@hcaptcha/react-hcaptcha": {
@@ -2276,6 +2190,9 @@
       "cpu": [
         "arm"
       ],
+      "libc": [
+        "glibc"
+      ],
       "license": "LGPL-3.0-or-later",
       "optional": true,
       "os": [
@@ -2292,6 +2209,9 @@
       "cpu": [
         "arm64"
       ],
+      "libc": [
+        "glibc"
+      ],
       "license": "LGPL-3.0-or-later",
       "optional": true,
       "os": [
@@ -2308,6 +2228,9 @@
       "cpu": [
         "ppc64"
       ],
+      "libc": [
+        "glibc"
+      ],
       "license": "LGPL-3.0-or-later",
       "optional": true,
       "os": [
@@ -2324,6 +2247,9 @@
       "cpu": [
         "riscv64"
       ],
+      "libc": [
+        "glibc"
+      ],
       "license": "LGPL-3.0-or-later",
       "optional": true,
       "os": [
@@ -2340,6 +2266,9 @@
       "cpu": [
         "s390x"
       ],
+      "libc": [
+        "glibc"
+      ],
       "license": "LGPL-3.0-or-later",
       "optional": true,
       "os": [
@@ -2356,6 +2285,9 @@
       "cpu": [
         "x64"
       ],
+      "libc": [
+        "glibc"
+      ],
       "license": "LGPL-3.0-or-later",
       "optional": true,
       "os": [
@@ -2372,6 +2304,9 @@
       "cpu": [
         "arm64"
       ],
+      "libc": [
+        "musl"
+      ],
       "license": "LGPL-3.0-or-later",
       "optional": true,
       "os": [
@@ -2388,6 +2323,9 @@
       "cpu": [
         "x64"
       ],
+      "libc": [
+        "musl"
+      ],
       "license": "LGPL-3.0-or-later",
       "optional": true,
       "os": [
@@ -2404,6 +2342,9 @@
       "cpu": [
         "arm"
       ],
+      "libc": [
+        "glibc"
+      ],
       "license": "Apache-2.0",
       "optional": true,
       "os": [
@@ -2426,6 +2367,9 @@
       "cpu": [
         "arm64"
       ],
+      "libc": [
+        "glibc"
+      ],
       "license": "Apache-2.0",
       "optional": true,
       "os": [
@@ -2448,6 +2392,9 @@
       "cpu": [
         "ppc64"
       ],
+      "libc": [
+        "glibc"
+      ],
       "license": "Apache-2.0",
       "optional": true,
       "os": [
@@ -2470,6 +2417,9 @@
       "cpu": [
         "riscv64"
       ],
+      "libc": [
+        "glibc"
+      ],
       "license": "Apache-2.0",
       "optional": true,
       "os": [
@@ -2492,6 +2442,9 @@
       "cpu": [
         "s390x"
       ],
+      "libc": [
+        "glibc"
+      ],
       "license": "Apache-2.0",
       "optional": true,
       "os": [
@@ -2514,6 +2467,9 @@
       "cpu": [
         "x64"
       ],
+      "libc": [
+        "glibc"
+      ],
       "license": "Apache-2.0",
       "optional": true,
       "os": [
@@ -2536,6 +2492,9 @@
       "cpu": [
         "arm64"
       ],
+      "libc": [
+        "musl"
+      ],
       "license": "Apache-2.0",
       "optional": true,
       "os": [
@@ -2558,6 +2517,9 @@
       "cpu": [
         "x64"
       ],
+      "libc": [
+        "musl"
+      ],
       "license": "Apache-2.0",
       "optional": true,
       "os": [
@@ -2713,14 +2675,14 @@
       }
     },
     "node_modules/@kapaai/react-sdk": {
-      "version": "0.9.2",
-      "resolved": "https://registry.npmjs.org/@kapaai/react-sdk/-/react-sdk-0.9.2.tgz",
-      "integrity": "sha512-PeqgKL6d0yIkkmPn+1O8TBjH7KGx5HNiH7fhGl0FEV2MfJZBzWNvAOdOm/34VLdpb2Nawe3H1gSURdJ0DG6z7Q==",
+      "version": "0.9.10",
+      "resolved": "https://registry.npmjs.org/@kapaai/react-sdk/-/react-sdk-0.9.10.tgz",
+      "integrity": "sha512-osQyFgBJmhNM207MpB0aZbjs2kjNHjEJbNc5YEReJuyFE72Iydn9CoZGxox2GYRgMIlQ7wljHCzgQqkvR8lXqA==",
       "license": "MIT",
       "dependencies": {
         "@fingerprintjs/fingerprintjs-pro-react": "^2.7.0",
+        "@fingerprintjs/fingerprintjs-pro-spa": "^1.3.0",
         "@hcaptcha/react-hcaptcha": "^1.12.0",
-        "@tanstack/react-query": "^5.74.3",
         "js-cookie": "^3.0.5",
         "tldts": "^7.0.7"
       },
@@ -2794,21 +2756,24 @@
       "license": "BSD-2-Clause"
     },
     "node_modules/@napi-rs/wasm-runtime": {
-      "version": "1.1.6",
-      "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.6.tgz",
-      "integrity": "sha512-ZLv/JdUfkvOy9eCnnBaGfiO+XimbjebAeO+MRQqD/B+FR1tnRN0tpKSJHRbE8sFfS6aqsXZ67TQjfwfsxULVbg==",
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.2.1.tgz",
+      "integrity": "sha512-KjZdi8Q1wh89gsVmghvbrMgWl6ZWmRmHV6wjB7/g4Zf0dyO+hH3neZUtuDNPO00qq5YE5RITVWvrIZKRaAmzGQ==",
       "license": "MIT",
       "optional": true,
       "dependencies": {
         "@tybys/wasm-util": "^0.10.3"
       },
+      "engines": {
+        "node": "^20.19.0 || ^22.13.0 || >=23.5.0"
+      },
       "funding": {
         "type": "github",
         "url": "https://github.com/sponsors/Brooooooklyn"
       },
       "peerDependencies": {
-        "@emnapi/core": "^1.7.1",
-        "@emnapi/runtime": "^1.7.1"
+        "@emnapi/core": "^1.7.1 || ^2.0.0-alpha.3",
+        "@emnapi/runtime": "^1.7.1 || ^2.0.0-alpha.3"
       }
     },
     "node_modules/@nodable/entities": {
@@ -2830,9 +2795,9 @@
       "license": "MIT"
     },
     "node_modules/@oxc-project/types": {
-      "version": "0.139.0",
-      "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.139.0.tgz",
-      "integrity": "sha512-r9gHphtCs+1M7J0pw6Sn/hh/Wpa/iQrOOkrNAlVLF/gHq+/CJmHIWKKUUhdWjcD6CIa8idarspCsASiXCXvFUw==",
+      "version": "0.142.0",
+      "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.142.0.tgz",
+      "integrity": "sha512-7W+2q5AKQVU36fkaryontrHn3YDt1RyUYXatw9i5H8ocYe2sPKSFB6eS8WNPeRKiN1qAWWZUPm7gwFzJGrccqQ==",
       "license": "MIT",
       "funding": {
         "url": "https://github.com/sponsors/Boshen"
@@ -2936,18 +2901,18 @@
       ]
     },
     "node_modules/@radix-ui/primitive": {
-      "version": "1.1.3",
-      "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.3.tgz",
-      "integrity": "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==",
+      "version": "1.1.7",
+      "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.7.tgz",
+      "integrity": "sha512-rqWnm76nYT8HoNNqEjpgJ7Pw/DrBj5iBTrmEPo6HTX5+VJyBNOqTdv4g89G63HuR5g0AaENoAcH7Is5fF2kZ8Q==",
       "license": "MIT"
     },
     "node_modules/@radix-ui/react-arrow": {
-      "version": "1.1.7",
-      "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.7.tgz",
-      "integrity": "sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==",
+      "version": "1.1.15",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.15.tgz",
+      "integrity": "sha512-v4zggRcjadnI+ClKDuijlQEW4tw3NoaeHc/PwpKnLoLLKNUG4InLegkstooLcRIUWCs+8L22dGURCVuFfOKfnA==",
       "license": "MIT",
       "dependencies": {
-        "@radix-ui/react-primitive": "2.1.3"
+        "@radix-ui/react-primitive": "2.1.10"
       },
       "peerDependencies": {
         "@types/react": "*",
@@ -2965,9 +2930,9 @@
       }
     },
     "node_modules/@radix-ui/react-compose-refs": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz",
-      "integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==",
+      "version": "1.1.5",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.5.tgz",
+      "integrity": "sha512-+48PbAAbq3didjJxa+OaWY2ZwgAKsNiRGyeHKszblZMQ+kcpd9pAaT11cMkGEie0vsOi3QdeTE6d5Fe3Gn61kA==",
       "license": "MIT",
       "peerDependencies": {
         "@types/react": "*",
@@ -2980,9 +2945,9 @@
       }
     },
     "node_modules/@radix-ui/react-context": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz",
-      "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==",
+      "version": "1.2.2",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.2.2.tgz",
+      "integrity": "sha512-RHCUGwKHDr0hDGg4X7ma4JG4/+12qxw8rkh5QKdDldlCvtja6nUx1Ef/8HVrJze81lEsgLQlqjzjGNHantgnQA==",
       "license": "MIT",
       "peerDependencies": {
         "@types/react": "*",
@@ -2995,16 +2960,16 @@
       }
     },
     "node_modules/@radix-ui/react-dismissable-layer": {
-      "version": "1.1.11",
-      "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.11.tgz",
-      "integrity": "sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg==",
+      "version": "1.1.19",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.19.tgz",
+      "integrity": "sha512-8g4pfOL9HoKKLWGiypT+dphVqjFfmcXO5GBnhsG6zI+lxAx/8feQpr+1LSN8Re3hiZ+XkLNS4O9ztK11/LzQ6w==",
       "license": "MIT",
       "dependencies": {
-        "@radix-ui/primitive": "1.1.3",
-        "@radix-ui/react-compose-refs": "1.1.2",
-        "@radix-ui/react-primitive": "2.1.3",
-        "@radix-ui/react-use-callback-ref": "1.1.1",
-        "@radix-ui/react-use-escape-keydown": "1.1.1"
+        "@radix-ui/primitive": "1.1.7",
+        "@radix-ui/react-compose-refs": "1.1.5",
+        "@radix-ui/react-primitive": "2.1.10",
+        "@radix-ui/react-use-callback-ref": "1.1.4",
+        "@radix-ui/react-use-effect-event": "0.0.5"
       },
       "peerDependencies": {
         "@types/react": "*",
@@ -3022,9 +2987,9 @@
       }
     },
     "node_modules/@radix-ui/react-focus-guards": {
-      "version": "1.1.3",
-      "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.3.tgz",
-      "integrity": "sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw==",
+      "version": "1.1.6",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.6.tgz",
+      "integrity": "sha512-RNOJjfZMTyBM6xYmV3IVGXkPjIhcBAuv48POevAXwrGJhkWZ9p1rFoIS1JFooPuT193AZmRsCPhpoVJxx6OPoQ==",
       "license": "MIT",
       "peerDependencies": {
         "@types/react": "*",
@@ -3037,14 +3002,14 @@
       }
     },
     "node_modules/@radix-ui/react-focus-scope": {
-      "version": "1.1.7",
-      "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.7.tgz",
-      "integrity": "sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==",
+      "version": "1.1.16",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.16.tgz",
+      "integrity": "sha512-wmRZ2WWLvmt6KHy2rNPOdPUjwq5xOHY02+m+udwJTn0aNIox/rkskAvJTyTLGhPK6KgrUjlJUJpgmx/+wFiFIQ==",
       "license": "MIT",
       "dependencies": {
-        "@radix-ui/react-compose-refs": "1.1.2",
-        "@radix-ui/react-primitive": "2.1.3",
-        "@radix-ui/react-use-callback-ref": "1.1.1"
+        "@radix-ui/react-compose-refs": "1.1.5",
+        "@radix-ui/react-primitive": "2.1.10",
+        "@radix-ui/react-use-callback-ref": "1.1.4"
       },
       "peerDependencies": {
         "@types/react": "*",
@@ -3062,12 +3027,12 @@
       }
     },
     "node_modules/@radix-ui/react-id": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.1.tgz",
-      "integrity": "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==",
+      "version": "1.1.4",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.4.tgz",
+      "integrity": "sha512-TMQp2llA+RYn7JcjnrMnz7wN4pcVttPZnRZo52PLQsoLVKzNlVwUeHmfePgTgRluXFvlD3GD5g5MOVVTJCO0qA==",
       "license": "MIT",
       "dependencies": {
-        "@radix-ui/react-use-layout-effect": "1.1.1"
+        "@radix-ui/react-use-layout-effect": "1.1.4"
       },
       "peerDependencies": {
         "@types/react": "*",
@@ -3080,26 +3045,26 @@
       }
     },
     "node_modules/@radix-ui/react-popover": {
-      "version": "1.1.15",
-      "resolved": "https://registry.npmjs.org/@radix-ui/react-popover/-/react-popover-1.1.15.tgz",
-      "integrity": "sha512-kr0X2+6Yy/vJzLYJUPCZEc8SfQcf+1COFoAqauJm74umQhta9M7lNJHP7QQS3vkvcGLQUbWpMzwrXYwrYztHKA==",
-      "license": "MIT",
-      "dependencies": {
-        "@radix-ui/primitive": "1.1.3",
-        "@radix-ui/react-compose-refs": "1.1.2",
-        "@radix-ui/react-context": "1.1.2",
-        "@radix-ui/react-dismissable-layer": "1.1.11",
-        "@radix-ui/react-focus-guards": "1.1.3",
-        "@radix-ui/react-focus-scope": "1.1.7",
-        "@radix-ui/react-id": "1.1.1",
-        "@radix-ui/react-popper": "1.2.8",
-        "@radix-ui/react-portal": "1.1.9",
-        "@radix-ui/react-presence": "1.1.5",
-        "@radix-ui/react-primitive": "2.1.3",
-        "@radix-ui/react-slot": "1.2.3",
-        "@radix-ui/react-use-controllable-state": "1.2.2",
+      "version": "1.1.23",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-popover/-/react-popover-1.1.23.tgz",
+      "integrity": "sha512-mw58MrBlyHWFisTOYignD0vf/3gdcgAR+9of1s9G/38CbFiUwH1nCDkc0AUM9IrXFgN5Ue8n45j9WCgyM1sbiQ==",
+      "license": "MIT",
+      "dependencies": {
+        "@radix-ui/primitive": "1.1.7",
+        "@radix-ui/react-compose-refs": "1.1.5",
+        "@radix-ui/react-context": "1.2.2",
+        "@radix-ui/react-dismissable-layer": "1.1.19",
+        "@radix-ui/react-focus-guards": "1.1.6",
+        "@radix-ui/react-focus-scope": "1.1.16",
+        "@radix-ui/react-id": "1.1.4",
+        "@radix-ui/react-popper": "1.3.7",
+        "@radix-ui/react-portal": "1.1.17",
+        "@radix-ui/react-presence": "1.1.10",
+        "@radix-ui/react-primitive": "2.1.10",
+        "@radix-ui/react-slot": "1.3.3",
+        "@radix-ui/react-use-controllable-state": "1.2.6",
         "aria-hidden": "^1.2.4",
-        "react-remove-scroll": "^2.6.3"
+        "react-remove-scroll": "^2.7.2"
       },
       "peerDependencies": {
         "@types/react": "*",
@@ -3117,21 +3082,21 @@
       }
     },
     "node_modules/@radix-ui/react-popper": {
-      "version": "1.2.8",
-      "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.8.tgz",
-      "integrity": "sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw==",
+      "version": "1.3.7",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.3.7.tgz",
+      "integrity": "sha512-UsJrrd7w4wuKKTdvd/DNERVlwSlUcyXzjhyDwBk+3aPOsCjOY6ZSbxuw8E6lZTjjfP8Cpd0J8VVkrYUWyGYXyg==",
       "license": "MIT",
       "dependencies": {
         "@floating-ui/react-dom": "^2.0.0",
-        "@radix-ui/react-arrow": "1.1.7",
-        "@radix-ui/react-compose-refs": "1.1.2",
-        "@radix-ui/react-context": "1.1.2",
-        "@radix-ui/react-primitive": "2.1.3",
-        "@radix-ui/react-use-callback-ref": "1.1.1",
-        "@radix-ui/react-use-layout-effect": "1.1.1",
-        "@radix-ui/react-use-rect": "1.1.1",
-        "@radix-ui/react-use-size": "1.1.1",
-        "@radix-ui/rect": "1.1.1"
+        "@radix-ui/react-arrow": "1.1.15",
+        "@radix-ui/react-compose-refs": "1.1.5",
+        "@radix-ui/react-context": "1.2.2",
+        "@radix-ui/react-primitive": "2.1.10",
+        "@radix-ui/react-use-callback-ref": "1.1.4",
+        "@radix-ui/react-use-layout-effect": "1.1.4",
+        "@radix-ui/react-use-rect": "1.1.4",
+        "@radix-ui/react-use-size": "1.1.4",
+        "@radix-ui/rect": "1.1.3"
       },
       "peerDependencies": {
         "@types/react": "*",
@@ -3149,13 +3114,13 @@
       }
     },
     "node_modules/@radix-ui/react-portal": {
-      "version": "1.1.9",
-      "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.9.tgz",
-      "integrity": "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==",
+      "version": "1.1.17",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.17.tgz",
+      "integrity": "sha512-vKQLcWypUnwZVvfV7UkGahH2g6ySe8M8R+zYBwPrv5byZ9QAW6cQVvNKo7GgmD+p8aYb6D9JBuvy8/WhOno2wQ==",
       "license": "MIT",
       "dependencies": {
-        "@radix-ui/react-primitive": "2.1.3",
-        "@radix-ui/react-use-layout-effect": "1.1.1"
+        "@radix-ui/react-primitive": "2.1.10",
+        "@radix-ui/react-use-layout-effect": "1.1.4"
       },
       "peerDependencies": {
         "@types/react": "*",
@@ -3173,13 +3138,12 @@
       }
     },
     "node_modules/@radix-ui/react-presence": {
-      "version": "1.1.5",
-      "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.5.tgz",
-      "integrity": "sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==",
+      "version": "1.1.10",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.10.tgz",
+      "integrity": "sha512-3wyzCQ6+ubRA+D4uv9m95JYLXxmOHp05qjrkjeA7uKHHtjpPggQzc6DAb0URl7j67oR0K2foO4ip27TiX037Bw==",
       "license": "MIT",
       "dependencies": {
-        "@radix-ui/react-compose-refs": "1.1.2",
-        "@radix-ui/react-use-layout-effect": "1.1.1"
+        "@radix-ui/react-use-layout-effect": "1.1.4"
       },
       "peerDependencies": {
         "@types/react": "*",
@@ -3197,12 +3161,12 @@
       }
     },
     "node_modules/@radix-ui/react-primitive": {
-      "version": "2.1.3",
-      "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz",
-      "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==",
+      "version": "2.1.10",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.10.tgz",
+      "integrity": "sha512-MucOnzh6hR5mid6VpkbglRAMYMjKLqRnGBbjXkzjK52fuQDd1qbkx78a5P40mkcnVXJdEVxm26E9OPAiUq7nBg==",
       "license": "MIT",
       "dependencies": {
-        "@radix-ui/react-slot": "1.2.3"
+        "@radix-ui/react-slot": "1.3.3"
       },
       "peerDependencies": {
         "@types/react": "*",
@@ -3220,12 +3184,12 @@
       }
     },
     "node_modules/@radix-ui/react-slot": {
-      "version": "1.2.3",
-      "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
-      "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
+      "version": "1.3.3",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.3.3.tgz",
+      "integrity": "sha512-qx7oqnYbxnK9kYI9m317qmFmEgo6ywqWvbTogdj7cL9p3/yx4M48p7Rnw5z3H890cL/ow/EeWJsuTykeZVXP5Q==",
       "license": "MIT",
       "dependencies": {
-        "@radix-ui/react-compose-refs": "1.1.2"
+        "@radix-ui/react-compose-refs": "1.1.5"
       },
       "peerDependencies": {
         "@types/react": "*",
@@ -3238,9 +3202,9 @@
       }
     },
     "node_modules/@radix-ui/react-use-callback-ref": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz",
-      "integrity": "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==",
+      "version": "1.1.4",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.4.tgz",
+      "integrity": "sha512-R6OUY2e2fA6Yn6s+VSx5KBV6Nx8LQEhu+cz7LCej18rQ1HLyg9PSC9jP/ZNx0o6FAIK9c0F1kHylzSxKsdlkrQ==",
       "license": "MIT",
       "peerDependencies": {
         "@types/react": "*",
@@ -3253,13 +3217,14 @@
       }
     },
     "node_modules/@radix-ui/react-use-controllable-state": {
-      "version": "1.2.2",
-      "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz",
-      "integrity": "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==",
+      "version": "1.2.6",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.6.tgz",
+      "integrity": "sha512-uEQJGT97ZA/TgP/Hydw47lHu+/vQj6z/0jA+WeTbK1o9Rx45GImjpD0tc3W5ad3D6XTSR6e1yEO0FvGq6WQfVQ==",
       "license": "MIT",
       "dependencies": {
-        "@radix-ui/react-use-effect-event": "0.0.2",
-        "@radix-ui/react-use-layout-effect": "1.1.1"
+        "@radix-ui/primitive": "1.1.7",
+        "@radix-ui/react-use-effect-event": "0.0.5",
+        "@radix-ui/react-use-layout-effect": "1.1.4"
       },
       "peerDependencies": {
         "@types/react": "*",
@@ -3272,30 +3237,12 @@
       }
     },
     "node_modules/@radix-ui/react-use-effect-event": {
-      "version": "0.0.2",
-      "resolved": "https://registry.npmjs.org/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.2.tgz",
-      "integrity": "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==",
+      "version": "0.0.5",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.5.tgz",
+      "integrity": "sha512-7cshFL8HGS/7HEiHH+9kL9HBwp2sa9yX18Knwek6KYWmXwM7pegMgta2AXMQKI+rq3JnfSj9x8wYqFMTdG1Jgg==",
       "license": "MIT",
       "dependencies": {
-        "@radix-ui/react-use-layout-effect": "1.1.1"
-      },
-      "peerDependencies": {
-        "@types/react": "*",
-        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
-      },
-      "peerDependenciesMeta": {
-        "@types/react": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/@radix-ui/react-use-escape-keydown": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.1.tgz",
-      "integrity": "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==",
-      "license": "MIT",
-      "dependencies": {
-        "@radix-ui/react-use-callback-ref": "1.1.1"
+        "@radix-ui/react-use-layout-effect": "1.1.4"
       },
       "peerDependencies": {
         "@types/react": "*",
@@ -3308,9 +3255,9 @@
       }
     },
     "node_modules/@radix-ui/react-use-layout-effect": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz",
-      "integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==",
+      "version": "1.1.4",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.4.tgz",
+      "integrity": "sha512-K20DkRkUwDnxEYMBPcg3Y6voLkEy5p5QQmszZgLngKKiC7dzBR/aEuK3w1qlx2JWDUNH6FluahYdgR3BP+QbYw==",
       "license": "MIT",
       "peerDependencies": {
         "@types/react": "*",
@@ -3323,12 +3270,12 @@
       }
     },
     "node_modules/@radix-ui/react-use-rect": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.1.tgz",
-      "integrity": "sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==",
+      "version": "1.1.4",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.4.tgz",
+      "integrity": "sha512-cSOCh6JlkmfjLyNcLiu2nB4v+nm+dkZ+Q5KHWk/soo4U7ZLiEQFKHK9/YmtBHjfCEaU43IBKQOc4/uJmCaiCTQ==",
       "license": "MIT",
       "dependencies": {
-        "@radix-ui/rect": "1.1.1"
+        "@radix-ui/rect": "1.1.3"
       },
       "peerDependencies": {
         "@types/react": "*",
@@ -3341,12 +3288,12 @@
       }
     },
     "node_modules/@radix-ui/react-use-size": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.1.tgz",
-      "integrity": "sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==",
+      "version": "1.1.4",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.4.tgz",
+      "integrity": "sha512-D3anSY15EJoxrihpsXI6SMrmmonnQtR2ni7arO+Lfdg3O95b9hNXxONk8jA5C8ANdF/h5HMAxejgs8PWJ6rlhw==",
       "license": "MIT",
       "dependencies": {
-        "@radix-ui/react-use-layout-effect": "1.1.1"
+        "@radix-ui/react-use-layout-effect": "1.1.4"
       },
       "peerDependencies": {
         "@types/react": "*",
@@ -3359,15 +3306,15 @@
       }
     },
     "node_modules/@radix-ui/rect": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.1.tgz",
-      "integrity": "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==",
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.3.tgz",
+      "integrity": "sha512-JtyZR+mqgBibTo8xea3B6ZRmzZiM/YeVBtUkas6zMuXjAlfIFIW2FgqeM9eLyvEaYX66vr6DJMK+4U6LV0KhNw==",
       "license": "MIT"
     },
     "node_modules/@rolldown/binding-android-arm64": {
-      "version": "1.1.5",
-      "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.1.5.tgz",
-      "integrity": "sha512-lZg8fqIv2v7FF237bwMgzGZEJvGL79/s5knJ/i6FmsGF4XXlzccZ4jb+TrFIxtSSxFtIpdsgrPZeMk1I9AFcyQ==",
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.1.tgz",
+      "integrity": "sha512-02hOeOSryYxVrOIphmLAsqnCJWxwlzFk+pEt/N/i6OgT3lShHO7xGCU5cpgchRDHboAEbSjzgGh+O/u1GswQmA==",
       "cpu": [
         "arm64"
       ],
@@ -3381,9 +3328,9 @@
       }
     },
     "node_modules/@rolldown/binding-darwin-arm64": {
-      "version": "1.1.5",
-      "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.1.5.tgz",
-      "integrity": "sha512-51Bnx9pNiMRKSUNtBfySkNJ9vMU9Hh3I1ozDd6gyPPYzaXCfnptUcEZxXGYFn+ul2dtcMUiqGR1Yai2K10uoTw==",
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.1.tgz",
+      "integrity": "sha512-fMsTOnN0OjFm3CyppWPitKnc8UlliVARUULW6cfU6AIqjdtgmSFWSk9vecHzZduv/yMWIHDlRhM1e8Iff9uAfA==",
       "cpu": [
         "arm64"
       ],
@@ -3397,9 +3344,9 @@
       }
     },
     "node_modules/@rolldown/binding-darwin-x64": {
-      "version": "1.1.5",
-      "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.1.5.tgz",
-      "integrity": "sha512-Tm+gbfC0aHu1tBA/JvKQh32S0K6YgCHkiAF4/W6xX0K0RmNuc94VeK419dJoE65R5aRxmo+noZQSWrAMF6yb6g==",
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.1.tgz",
+      "integrity": "sha512-1wjKdz/XLGKHaTNHjQveQ/B23TKx4ItAqm1JbyVuvNPc4Ze0Fb48s49TAd/2zcplPl8okE/UbTgmlVfwT7eFeQ==",
       "cpu": [
         "x64"
       ],
@@ -3413,9 +3360,9 @@
       }
     },
     "node_modules/@rolldown/binding-freebsd-x64": {
-      "version": "1.1.5",
-      "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.1.5.tgz",
-      "integrity": "sha512-JMzDKCCXq93YccG5gz3hvOs1oXRKAf0XYpfOS88e+wZrC8Iugj6j68867vrYZkvpDDpKn/KoKORThmchMpF6TA==",
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.1.tgz",
+      "integrity": "sha512-Fa0jHR07E7YBN4vOEsbVf2briYNsuOowfLJaXULZM0ldMlaCaj2LJgLMbMe4iacRyZmvR8efFhgR9wKuGclQUg==",
       "cpu": [
         "x64"
       ],
@@ -3429,9 +3376,9 @@
       }
     },
     "node_modules/@rolldown/binding-linux-arm-gnueabihf": {
-      "version": "1.1.5",
-      "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.1.5.tgz",
-      "integrity": "sha512-uML21j2K5TfPGutKxub+M+nLjZIrWjXQ5Grx4lCe/nimTj9B4L63zHpjXLl4y0L3mcm2htEQIb06oCG/szerNw==",
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.1.tgz",
+      "integrity": "sha512-pzkgu1SSHGgRRyRZ4fbmSgmajbVt+epaLP99NDjFft69v/ypfTi6swBMiVdh2EkQ0OSnHE1lZDM7DRGkyAzUpA==",
       "cpu": [
         "arm"
       ],
@@ -3445,12 +3392,15 @@
       }
     },
     "node_modules/@rolldown/binding-linux-arm64-gnu": {
-      "version": "1.1.5",
-      "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.1.5.tgz",
-      "integrity": "sha512-navSiuTMogvnQoZoM/v+l3ZWo50/NTwSHSzheABx/RCnmUPaKwq9qSo4Br2OYRs21+Fz8uFqITZM3H4opOB0/Q==",
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.1.tgz",
+      "integrity": "sha512-QI5SEDY8cbiYWHx0VO4vIc3UlS6a32vXHjU8Qy/17adEmZIPuByJg13UEvo9c/UCiUkdcVWY83C+b+JrwnNyUg==",
       "cpu": [
         "arm64"
       ],
+      "libc": [
+        "glibc"
+      ],
       "license": "MIT",
       "optional": true,
       "os": [
@@ -3461,12 +3411,15 @@
       }
     },
     "node_modules/@rolldown/binding-linux-arm64-musl": {
-      "version": "1.1.5",
-      "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.1.5.tgz",
-      "integrity": "sha512-lAryqH7IteztmCXQXk0etKj4wBQ7Gx5S6LjKhsgp9zb8I5bsuvU/2llH1hDQcjsFeqIsovMVN339/8pUDDBXxA==",
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.1.tgz",
+      "integrity": "sha512-Sm41FyCeXqmYcERoYOCbGIL5hNfd8w9LQ7Y61Bev48HkcjaJqV/iiVOaiDxjVTRMS+QKrZmD8cfPt4uMVnvM+A==",
       "cpu": [
         "arm64"
       ],
+      "libc": [
+        "musl"
+      ],
       "license": "MIT",
       "optional": true,
       "os": [
@@ -3477,12 +3430,15 @@
       }
     },
     "node_modules/@rolldown/binding-linux-ppc64-gnu": {
-      "version": "1.1.5",
-      "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.1.5.tgz",
-      "integrity": "sha512-fsK/sNBnxzBlL4O1JNrZakVQxPspqpED5dLtNsZS9oOKmtSpdNIzxH2kkol5HYTWJN47sE20ztMJPxfZ89qGOg==",
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.1.tgz",
+      "integrity": "sha512-2x+WhXTGl9yJYPbltW/BSEPTVz9OIWQyER4N+gJEDWkkn904eRcBzELqh/Hf7K0w/ubGbKNMv0ZC+94QK/IFEg==",
       "cpu": [
         "ppc64"
       ],
+      "libc": [
+        "glibc"
+      ],
       "license": "MIT",
       "optional": true,
       "os": [
@@ -3493,12 +3449,15 @@
       }
     },
     "node_modules/@rolldown/binding-linux-s390x-gnu": {
-      "version": "1.1.5",
-      "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.1.5.tgz",
-      "integrity": "sha512-gLYb4BIadlfTOYT5gO503n8zQjXflgzpD0FcyKh0Mzx3rqCZKnHoJWV9xe1KXUJ5lx2JfcSHr/mhzS0PC/McAA==",
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.1.tgz",
+      "integrity": "sha512-eEjmQpuRQayHPWWnywaWHkFT3ToPbP3RYy42VVd/B9aBGDA+Ol25EIWHxKQST3IiWJjikCWUF7KtbfqwZrzVwQ==",
       "cpu": [
         "s390x"
       ],
+      "libc": [
+        "glibc"
+      ],
       "license": "MIT",
       "optional": true,
       "os": [
@@ -3509,12 +3468,15 @@
       }
     },
     "node_modules/@rolldown/binding-linux-x64-gnu": {
-      "version": "1.1.5",
-      "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.1.5.tgz",
-      "integrity": "sha512-FjcpEKUyJygHgs1o50VYNvkt5+7Le/VEdYt0AkRpkL33MnyQfwr8l5mXwMmfmTbyMPr5vJLC+8/Gd9gXnwU1QQ==",
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.1.tgz",
+      "integrity": "sha512-/Orga1fZYkLc/56jBICcHrKchl8Z2UKdDSr3LG9ToWO1lQ6a4Livk9Xz+9WN91zsz5QR3XQz2NNoSDEvP6qadw==",
       "cpu": [
         "x64"
       ],
+      "libc": [
+        "glibc"
+      ],
       "license": "MIT",
       "optional": true,
       "os": [
@@ -3525,12 +3487,15 @@
       }
     },
     "node_modules/@rolldown/binding-linux-x64-musl": {
-      "version": "1.1.5",
-      "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.1.5.tgz",
-      "integrity": "sha512-Me+PfPI2TMeOQk0gYWfLQZtTktrmzbr8cDboqX83XKc7UrgAi55gF+2dUkWdxd19n55Essp2yeca+O9N5rBxHg==",
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.1.tgz",
+      "integrity": "sha512-xxBJRL+0q0Kce7orznGWLuylHDY65vuARXZRpX+hPdv+DqK2c3NlCsVA98tlWzWNEE7yPqA/1NQ5nnCrj49Y5A==",
       "cpu": [
         "x64"
       ],
+      "libc": [
+        "musl"
+      ],
       "license": "MIT",
       "optional": true,
       "os": [
@@ -3541,9 +3506,9 @@
       }
     },
     "node_modules/@rolldown/binding-openharmony-arm64": {
-      "version": "1.1.5",
-      "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.1.5.tgz",
-      "integrity": "sha512-yc5WrLzXks6zCQfn9Oxr8pORKyl/pF+QjHmW/Qx3qu0oyrrNC+y2JLTU1E2rcWYAmzlnqngWXHQjy51VzW70Vw==",
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.1.tgz",
+      "integrity": "sha512-M6AdXIXw3s+/8XpKMzdGDEXGS1S7kwUsy+rcTIUIOx5Ge4nXKCtAFHFV9YKkXvGcC5WMoTjAteLzlsQROVI0Yw==",
       "cpu": [
         "arm64"
       ],
@@ -3557,38 +3522,55 @@
       }
     },
     "node_modules/@rolldown/binding-wasm32-wasi": {
-      "version": "1.1.5",
-      "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.1.5.tgz",
-      "integrity": "sha512-VbQGPX2b4r48TAMIM2cjgluIM1HYutm4pcTEJsle7iEP7sB1dFqtPLBVbdLAZCxy1txCcPxf4QFf4v8uvltPqA==",
-      "cpu": [
-        "wasm32"
-      ],
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.2.1.tgz",
+      "integrity": "sha512-/TX0SoRGojHzSAHpfVBbavRVSazg5U3h3Y3VXfcc0cdugq6kxdqw8LPGFiPr+/7gE/60zRcsOY2Vi9b9eT0jww==",
       "license": "MIT",
       "optional": true,
       "dependencies": {
-        "@emnapi/core": "1.11.1",
-        "@emnapi/runtime": "1.11.1",
-        "@napi-rs/wasm-runtime": "^1.1.6"
+        "@emnapi/core": "2.0.0-alpha.3",
+        "@emnapi/runtime": "2.0.0-alpha.3",
+        "@napi-rs/wasm-runtime": "^1.2.0"
       },
       "engines": {
-        "node": "^20.19.0 || >=22.12.0"
+        "node": "^20.19.0 || ^22.13.0 || >=23.5.0"
       }
     },
     "node_modules/@rolldown/binding-wasm32-wasi/node_modules/@emnapi/core": {
-      "version": "1.11.1",
-      "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.11.1.tgz",
-      "integrity": "sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ==",
+      "version": "2.0.0-alpha.3",
+      "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-2.0.0-alpha.3.tgz",
+      "integrity": "sha512-AZypUeJ/yByuxyS7BlSNRDOMLMlROYtjYdIAuBmJssVz1UJDSeYxLrdizhXCFYhedC5bqd/ASy8EuNXbVVXp9g==",
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "@emnapi/wasi-threads": "2.0.1",
+        "tslib": "^2.4.0"
+      }
+    },
+    "node_modules/@rolldown/binding-wasm32-wasi/node_modules/@emnapi/runtime": {
+      "version": "2.0.0-alpha.3",
+      "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-2.0.0-alpha.3.tgz",
+      "integrity": "sha512-hFPAhMUjJD9BSyCANEISPOogeXC9Zo9ZQl7L6vKnaVsMkCtzznaW/naYypeyl0Gv5rYfWYsZbpixTMpjDJzQeA==",
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "tslib": "^2.4.0"
+      }
+    },
+    "node_modules/@rolldown/binding-wasm32-wasi/node_modules/@emnapi/wasi-threads": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-2.0.1.tgz",
+      "integrity": "sha512-9DsSk+o5NBX0CCJT8s0EROGSGxjR/tKu6aBTaVyq+SjAEQH4XcdcRxPBRzsBLizTTJ49MJjF+jgu3qnO9GLQcQ==",
       "license": "MIT",
       "optional": true,
       "dependencies": {
-        "@emnapi/wasi-threads": "1.2.2",
         "tslib": "^2.4.0"
       }
     },
     "node_modules/@rolldown/binding-win32-arm64-msvc": {
-      "version": "1.1.5",
-      "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.1.5.tgz",
-      "integrity": "sha512-gHv82k63z4qpV5+Q1y/12KrK0ltWBukVDI8nZcbT7Tt/ZlOIVwppazneq0F93oDxTo3IgAMEDIoQh3E2n6mVsw==",
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.1.tgz",
+      "integrity": "sha512-EvRrivJieyHG+AO9lleZWgq+g0+S7oV2C51yuqlcyU/R9net+sI4Pj0F+lUoP2bEr6TWX3SqFaaS0SzfLxSzkw==",
       "cpu": [
         "arm64"
       ],
@@ -3602,9 +3584,9 @@
       }
     },
     "node_modules/@rolldown/binding-win32-x64-msvc": {
-      "version": "1.1.5",
-      "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.1.5.tgz",
-      "integrity": "sha512-tTZuDBPw85tEN5PQi1pnEBzDy0Z49HtScLAbD5t6hyeU92A95pRWaSMw1GZZi/RwgSgUIl0xrSlXIT/9QzvYSA==",
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.1.tgz",
+      "integrity": "sha512-Z4eCmn5QJ/5+azF9knpLWKfVd9aidn0mAe9TpJgvBLId9Ax3t0+JVxBmT25Bv7NBbVW1TZyKjQjQReouMeH5UQ==",
       "cpu": [
         "x64"
       ],
@@ -3720,33 +3702,6 @@
         "node": ">=20"
       }
     },
-    "node_modules/@shikijs/primitive": {
-      "version": "4.3.0",
-      "resolved": "https://registry.npmjs.org/@shikijs/primitive/-/primitive-4.3.0.tgz",
-      "integrity": "sha512-CPkz64PTa5diRW1ggzMZH9VM/du4RNChYgVtgqrFcgruvIybmCvySv8GkiHSczUHXYuuR8TdKEwFx+UnZMpgdg==",
-      "license": "MIT",
-      "dependencies": {
-        "@shikijs/types": "4.3.0",
-        "@shikijs/vscode-textmate": "^10.0.2",
-        "@types/hast": "^3.0.4"
-      },
-      "engines": {
-        "node": ">=20"
-      }
-    },
-    "node_modules/@shikijs/primitive/node_modules/@shikijs/types": {
-      "version": "4.3.0",
-      "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-4.3.0.tgz",
-      "integrity": "sha512-oc8b9U2SYvofKZk8e/737nIX0qwf6eV2vHFATeObAu7r+mUVpLs8Re0BmVkIjAWAYgkmG/CzLNo7rzuBzRu/wQ==",
-      "license": "MIT",
-      "dependencies": {
-        "@shikijs/vscode-textmate": "^10.0.2",
-        "@types/hast": "^3.0.4"
-      },
-      "engines": {
-        "node": ">=20"
-      }
-    },
     "node_modules/@shikijs/themes": {
       "version": "4.3.1",
       "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-4.3.1.tgz",
@@ -3778,32 +3733,6 @@
       "integrity": "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==",
       "license": "MIT"
     },
-    "node_modules/@tanstack/query-core": {
-      "version": "5.90.20",
-      "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.90.20.tgz",
-      "integrity": "sha512-OMD2HLpNouXEfZJWcKeVKUgQ5n+n3A2JFmBaScpNDUqSrQSjiveC7dKMe53uJUg1nDG16ttFPz2xfilz6i2uVg==",
-      "license": "MIT",
-      "funding": {
-        "type": "github",
-        "url": "https://github.com/sponsors/tannerlinsley"
-      }
-    },
-    "node_modules/@tanstack/react-query": {
-      "version": "5.90.21",
-      "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.90.21.tgz",
-      "integrity": "sha512-0Lu6y5t+tvlTJMTO7oh5NSpJfpg/5D41LlThfepTixPYkJ0sE2Jj0m0f6yYqujBwIXlId87e234+MxG3D3g7kg==",
-      "license": "MIT",
-      "dependencies": {
-        "@tanstack/query-core": "5.90.20"
-      },
-      "funding": {
-        "type": "github",
-        "url": "https://github.com/sponsors/tannerlinsley"
-      },
-      "peerDependencies": {
-        "react": "^18 || ^19"
-      }
-    },
     "node_modules/@tybys/wasm-util": {
       "version": "0.10.3",
       "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.3.tgz",
@@ -3961,9 +3890,9 @@
       }
     },
     "node_modules/@types/react": {
-      "version": "19.2.15",
-      "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.15.tgz",
-      "integrity": "sha512-eRwcGNHve+E8qtEQSSRl6urh+rFop4v8gm6O8rGv25CodbvFdLjA1vVQ1KkiFE0w0UPOnb8tDiFKL5lp0rtY5Q==",
+      "version": "19.2.18",
+      "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.18.tgz",
+      "integrity": "sha512-AnzbBERsrLKtk2XSfTbYRLjQPdy116Sty4q+T+Bp3IC4l6jNBvreVPAHmpq9qhXQM7CXZPjLVmGMw9sy+hxQ3w==",
       "license": "MIT",
       "peer": true,
       "dependencies": {
@@ -3971,9 +3900,9 @@
       }
     },
     "node_modules/@types/react-dom": {
-      "version": "19.2.3",
-      "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz",
-      "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==",
+      "version": "19.2.4",
+      "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.4.tgz",
+      "integrity": "sha512-Bsc+QHgp+P/F02XDzNCY9jnZNCUuLki36KT7VKrTXXLdHf+vHMNZnW1rVu5DNW/rCK+fya3DATySbLM4yhtKUw==",
       "license": "MIT",
       "peer": true,
       "peerDependencies": {
@@ -4642,9 +4571,9 @@
       }
     },
     "node_modules/baseline-browser-mapping": {
-      "version": "2.10.40",
-      "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.40.tgz",
-      "integrity": "sha512-BSSLZ9/Cjjv7Gtj5B68ZzXcXUg8iOf3fme+FCuh8rC/Go+Kmh8cox7M3A8dolou16s64QjLPOSdngh7GxXvkSw==",
+      "version": "2.11.12",
+      "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.12.tgz",
+      "integrity": "sha512-r7WnVImvVCeFpf2DOXfy41aPWzeNg3H/A2X4dKmy1QL0MSyyk/e7z8ihJ3N6Nn2PsdhkVlqnEfnUE4a05P2aTA==",
       "license": "Apache-2.0",
       "bin": {
         "baseline-browser-mapping": "dist/cli.cjs"
@@ -4718,9 +4647,9 @@
       }
     },
     "node_modules/browserslist": {
-      "version": "4.28.4",
-      "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.4.tgz",
-      "integrity": "sha512-MTc8i/x9jBQd1iMw2CFGS+rwMa07eYjLR0CCTLDACl9xhxy+nIs3KeML/biicXtk9JrZ6dnnTatmc7ErPXIxqw==",
+      "version": "4.28.7",
+      "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.7.tgz",
+      "integrity": "sha512-JxV13hNrFxqjOc8alRbq9dK1MM79NEXYpma2B2J4wAtpWS5zIEIKqWPGCl7N4o7Uc7B7itylh7SuDujATRyyTw==",
       "funding": [
         {
           "type": "opencollective",
@@ -4737,10 +4666,10 @@
       ],
       "license": "MIT",
       "dependencies": {
-        "baseline-browser-mapping": "^2.10.38",
-        "caniuse-lite": "^1.0.30001799",
-        "electron-to-chromium": "^1.5.376",
-        "node-releases": "^2.0.48",
+        "baseline-browser-mapping": "^2.10.44",
+        "caniuse-lite": "^1.0.30001806",
+        "electron-to-chromium": "^1.5.393",
+        "node-releases": "^2.0.51",
         "update-browserslist-db": "^1.2.3"
       },
       "bin": {
@@ -4801,9 +4730,9 @@
       }
     },
     "node_modules/caniuse-lite": {
-      "version": "1.0.30001799",
-      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001799.tgz",
-      "integrity": "sha512-hG1bReV+OUU+MOqK4t/ZWI0tZOyz3rqS9XuhOUz1cIcbwBKjOyJEJuw9ER5JuNyqxNk8u/JUVbGibBOL1yrjFw==",
+      "version": "1.0.30001806",
+      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001806.tgz",
+      "integrity": "sha512-72Cuvd95zbSYPKq6Fhg8eDJRlzgWDf7/mtoZv6Qe/DYNCEBdNxoA3+rZAU2ZhGCpZlns3EssFavaZomckT5Uuw==",
       "funding": [
         {
           "type": "opencollective",
@@ -5426,9 +5355,9 @@
       }
     },
     "node_modules/electron-to-chromium": {
-      "version": "1.5.379",
-      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.379.tgz",
-      "integrity": "sha512-v/qV5aV5EUA2pGilzUCq5/eyOloZAqDZBu9UMBIzgPpLlprjSR6zswsWBTv0KpqxLGUAZEwhO95ZCt7srymNVA==",
+      "version": "1.5.399",
+      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.399.tgz",
+      "integrity": "sha512-lEcqhErbHjXRvd41rnWLpzbyU/IXfIYo7QwaFWmxGeLiLyY2TBCdHnWY88vB+p3ubnihRypDm66panXl7TylLA==",
       "license": "ISC"
     },
     "node_modules/emmet": {
@@ -5731,9 +5660,9 @@
       "optional": true
     },
     "node_modules/fast-uri": {
-      "version": "3.1.5",
-      "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.5.tgz",
-      "integrity": "sha512-gHwA1O9LDIcKunMKhObS/HimwtehO1nPUECKAu5TpKgaO19fcWEl4bliWe1jWxVFvIXztJjjQ4L8XQ1EU9f7Jw==",
+      "version": "3.1.4",
+      "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.4.tgz",
+      "integrity": "sha512-8JnbkQ4juDyvYs4mgFGQqg4yCYtFDtUtmp2QIQq11ZZe5CFQ5wcqm1rqDgAh/QdMySuBnPzMUiJUNZG5N/AiQw==",
       "dev": true,
       "funding": [
         {
@@ -6692,13 +6621,10 @@
       }
     },
     "node_modules/js-cookie": {
-      "version": "3.0.7",
-      "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.7.tgz",
-      "integrity": "sha512-z/wZZgDrkNV1eA0ULjM/F9/50Ya8fbzgKneSpoPsXSGd0KnpdtHfOZWK+GcwLk+EZbS4F9RBhU+K2RgzuDaItw==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=20"
-      }
+      "version": "3.0.8",
+      "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.8.tgz",
+      "integrity": "sha512-yeJd4aNAdYZQjaon2bpD/Gb0B/omw7HQOsynXXcOiWVCacbBcPlgn8S/d1X6blFSaHao7ozqtW7NZW19xpCtIw==",
+      "license": "MIT"
     },
     "node_modules/js-tokens": {
       "version": "10.0.0",
@@ -6987,6 +6913,9 @@
       "cpu": [
         "arm64"
       ],
+      "libc": [
+        "glibc"
+      ],
       "license": "MPL-2.0",
       "optional": true,
       "os": [
@@ -7007,6 +6936,9 @@
       "cpu": [
         "arm64"
       ],
+      "libc": [
+        "musl"
+      ],
       "license": "MPL-2.0",
       "optional": true,
       "os": [
@@ -7027,6 +6959,9 @@
       "cpu": [
         "x64"
       ],
+      "libc": [
+        "glibc"
+      ],
       "license": "MPL-2.0",
       "optional": true,
       "os": [
@@ -7047,6 +6982,9 @@
       "cpu": [
         "x64"
       ],
+      "libc": [
+        "musl"
+      ],
       "license": "MPL-2.0",
       "optional": true,
       "os": [
@@ -8422,9 +8360,9 @@
       "license": "MIT"
     },
     "node_modules/node-releases": {
-      "version": "2.0.50",
-      "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.50.tgz",
-      "integrity": "sha512-J6l92tKHX6w8Jy5nO1Vuc01NoIiRGi/d6qBKVxh+IQ8Cr3b6HbVNfKiF8ZpFKufTwpwxMmce2W3iQZ861ZRyTg==",
+      "version": "2.0.51",
+      "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.51.tgz",
+      "integrity": "sha512-wRNIrw4DmVLKQlbgOMdkMx27Wrpzes2hh5Jtbi2bjPd+4wJstWIqP5A+lscnqbm0xxmT5Bpg8Lec5ItEBwx6BQ==",
       "license": "MIT",
       "engines": {
         "node": ">=18"
@@ -8814,9 +8752,9 @@
       }
     },
     "node_modules/postcss": {
-      "version": "8.5.23",
-      "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.23.tgz",
-      "integrity": "sha512-g50586zr4bZmwFiTlflMu8E0bDTb5I5gertgwAKmsdUlTQIhZtunzUlD1WSzwcVWPoAVpsrA6vlfCD7oXvRwgg==",
+      "version": "8.5.25",
+      "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.25.tgz",
+      "integrity": "sha512-DTPx3RWSSnWyzLxQnlH0rJP+EW5ekl16ZU4/psbIhA0e53kJfdgaN5vKM+xP7yJtXVu+nfdVFmlgFDEKAe4Pyw==",
       "funding": [
         {
           "type": "opencollective",
@@ -8940,30 +8878,30 @@
       "license": "MIT"
     },
     "node_modules/react": {
-      "version": "19.2.4",
-      "resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz",
-      "integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==",
+      "version": "19.2.8",
+      "resolved": "https://registry.npmjs.org/react/-/react-19.2.8.tgz",
+      "integrity": "sha512-PWaYA1L/q9u2u7xYQi+Y3L3Yfnie7XyLeaJICV1MGD6LprsBxcAqGjYyr0eY3p+QdsA+x/Irkt4Qif8D63+Sbw==",
       "license": "MIT",
       "engines": {
         "node": ">=0.10.0"
       }
     },
     "node_modules/react-dom": {
-      "version": "19.2.4",
-      "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.4.tgz",
-      "integrity": "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==",
+      "version": "19.2.8",
+      "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.8.tgz",
+      "integrity": "sha512-rVprimfGBG3DR+Tq0IQG2DT5PxKth1WIGDmj5yPmlzr4YBe7uyE+Du4oVqTDXZSHGGGXRtTJEGSSePyQCMBglQ==",
       "license": "MIT",
       "dependencies": {
         "scheduler": "^0.27.0"
       },
       "peerDependencies": {
-        "react": "^19.2.4"
+        "react": "^19.2.8"
       }
     },
     "node_modules/react-icons": {
-      "version": "5.6.0",
-      "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.6.0.tgz",
-      "integrity": "sha512-RH93p5ki6LfOiIt0UtDyNg/cee+HLVR6cHHtW3wALfo+eOHTp8RnU2kRkI6E+H19zMIs03DyxUG/GfZMOGvmiA==",
+      "version": "5.7.0",
+      "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.7.0.tgz",
+      "integrity": "sha512-LBLy340Rzqy6+/yVhZKT3B/QpP1BZaesGqasf09HPOBzRarcDIFH0WwXlXQfE7q7ipxK4MSiC5DIBWURCny6fw==",
       "license": "MIT",
       "peerDependencies": {
         "react": "*"
@@ -9526,12 +9464,12 @@
       }
     },
     "node_modules/rolldown": {
-      "version": "1.1.5",
-      "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.1.5.tgz",
-      "integrity": "sha512-t9z29cJjXf/vxQ8dyhCSpt6H6aSwHTk8cT5I3iy6SMXuFpk5mB6PL6XfC8PCwrPTx93udwKUm9HRteAlTGBLiA==",
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.2.1.tgz",
+      "integrity": "sha512-4FKJhg8d3OiyQOA6Q1Q0hoFFpW9/OoX+VsHzpECsdsIZoOArrAK90gl59YK/Z+gnDel45bgJZK03ozH/9bCqEw==",
       "license": "MIT",
       "dependencies": {
-        "@oxc-project/types": "=0.139.0",
+        "@oxc-project/types": "=0.142.0",
         "@rolldown/pluginutils": "^1.0.0"
       },
       "bin": {
@@ -9541,21 +9479,21 @@
         "node": "^20.19.0 || >=22.12.0"
       },
       "optionalDependencies": {
-        "@rolldown/binding-android-arm64": "1.1.5",
-        "@rolldown/binding-darwin-arm64": "1.1.5",
-        "@rolldown/binding-darwin-x64": "1.1.5",
-        "@rolldown/binding-freebsd-x64": "1.1.5",
-        "@rolldown/binding-linux-arm-gnueabihf": "1.1.5",
-        "@rolldown/binding-linux-arm64-gnu": "1.1.5",
-        "@rolldown/binding-linux-arm64-musl": "1.1.5",
-        "@rolldown/binding-linux-ppc64-gnu": "1.1.5",
-        "@rolldown/binding-linux-s390x-gnu": "1.1.5",
-        "@rolldown/binding-linux-x64-gnu": "1.1.5",
-        "@rolldown/binding-linux-x64-musl": "1.1.5",
-        "@rolldown/binding-openharmony-arm64": "1.1.5",
-        "@rolldown/binding-wasm32-wasi": "1.1.5",
-        "@rolldown/binding-win32-arm64-msvc": "1.1.5",
-        "@rolldown/binding-win32-x64-msvc": "1.1.5"
+        "@rolldown/binding-android-arm64": "1.2.1",
+        "@rolldown/binding-darwin-arm64": "1.2.1",
+        "@rolldown/binding-darwin-x64": "1.2.1",
+        "@rolldown/binding-freebsd-x64": "1.2.1",
+        "@rolldown/binding-linux-arm-gnueabihf": "1.2.1",
+        "@rolldown/binding-linux-arm64-gnu": "1.2.1",
+        "@rolldown/binding-linux-arm64-musl": "1.2.1",
+        "@rolldown/binding-linux-ppc64-gnu": "1.2.1",
+        "@rolldown/binding-linux-s390x-gnu": "1.2.1",
+        "@rolldown/binding-linux-x64-gnu": "1.2.1",
+        "@rolldown/binding-linux-x64-musl": "1.2.1",
+        "@rolldown/binding-openharmony-arm64": "1.2.1",
+        "@rolldown/binding-wasm32-wasi": "1.2.1",
+        "@rolldown/binding-win32-arm64-msvc": "1.2.1",
+        "@rolldown/binding-win32-x64-msvc": "1.2.1"
       }
     },
     "node_modules/satteri": {
@@ -9962,21 +9900,21 @@
       }
     },
     "node_modules/tldts": {
-      "version": "7.0.25",
-      "resolved": "https://registry.npmjs.org/tldts/-/tldts-7.0.25.tgz",
-      "integrity": "sha512-keinCnPbwXEUG3ilrWQZU+CqcTTzHq9m2HhoUP2l7Xmi8l1LuijAXLpAJ5zRW+ifKTNscs4NdCkfkDCBYm352w==",
+      "version": "7.4.10",
+      "resolved": "https://registry.npmjs.org/tldts/-/tldts-7.4.10.tgz",
+      "integrity": "sha512-GgouD1B+sWwvkaEq8vXC15DjQitxbvs12oIXELpconwm+Tg3zfcEv4jgzq3vtKverDXsg3VI8aRgNL2Nra0Iog==",
       "license": "MIT",
       "dependencies": {
-        "tldts-core": "^7.0.25"
+        "tldts-core": "^7.4.10"
       },
       "bin": {
         "tldts": "bin/cli.js"
       }
     },
     "node_modules/tldts-core": {
-      "version": "7.0.25",
-      "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.0.25.tgz",
-      "integrity": "sha512-ZjCZK0rppSBu7rjHYDYsEaMOIbbT+nWF57hKkv4IUmZWBNrBWBOjIElc0mKRgLM8bm7x/BBlof6t2gi/Oq/Asw==",
+      "version": "7.4.10",
+      "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.4.10.tgz",
+      "integrity": "sha512-KnQjp53ZekKgm/r3l+u8kJGGzYgrWdP8+Mql7a4vijh2WE0IrZWspQj/TpTxDho/YxO+AnOZnIjQcCD+q6iJsw==",
       "license": "MIT"
     },
     "node_modules/tmp": {
@@ -10550,15 +10488,15 @@
       }
     },
     "node_modules/vite": {
-      "version": "8.1.5",
-      "resolved": "https://registry.npmjs.org/vite/-/vite-8.1.5.tgz",
-      "integrity": "sha512-7ULLwsCdYx/nRyrpiEwvqb5TFHrMVZyBt+rg/OAXT7rgj/z+DtTDyKFeLAdDkubDVDKD8jOsndmy7m55XcfUsw==",
+      "version": "8.2.0",
+      "resolved": "https://registry.npmjs.org/vite/-/vite-8.2.0.tgz",
+      "integrity": "sha512-pn+CFpM0lwDeKwmOq1ZaBK/9sjorZcgqxki6MbY/jPEVd9vichIlmlD4HmQ5wdP5EgqQCFRaACBxMC7uEGc6lQ==",
       "license": "MIT",
       "dependencies": {
-        "lightningcss": "^1.32.0",
+        "lightningcss": "^1.33.0",
         "picomatch": "^4.0.5",
-        "postcss": "^8.5.17",
-        "rolldown": "~1.1.5",
+        "postcss": "^8.5.23",
+        "rolldown": "~1.2.0",
         "tinyglobby": "^0.2.17"
       },
       "bin": {
@@ -10575,7 +10513,7 @@
       },
       "peerDependencies": {
         "@types/node": "^20.19.0 || >=22.12.0",
-        "@vitejs/devtools": "^0.3.0",
+        "@vitejs/devtools": "^0.4.0",
         "esbuild": "^0.27.0 || ^0.28.0",
         "jiti": ">=1.21.0",
         "less": "^4.0.0",
diff --git a/src/components/CustomSidebar.astro b/src/components/CustomSidebar.astro
index 6ab218ca8..954f822f7 100644
--- a/src/components/CustomSidebar.astro
+++ b/src/components/CustomSidebar.astro
@@ -77,9 +77,9 @@ import KapaLauncher from './KapaLauncher.astro';
 			'api': 'API',
 		};
 
-		// Detect Apple platforms once so the Ask AI kbd reads ⌘+I on Macs and
-		// Ctrl+I elsewhere. Mirrors KapaChatLauncher.tsx which binds the same
-		// shortcut via keymatch's `CmdOrCtrl+I`.
+// Detect Apple platforms once so the Ask AI kbd reads ⌘+I on Macs and
+		// Ctrl+I elsewhere. Mirrors KapaLauncher.astro which binds the same
+		// shortcut for opening the Kapa Website Widget.
 		var isMac = /(Mac|iPhone|iPod|iPad)/i.test(navigator.platform || '');
 		var modKey = isMac ? '\u2318' : 'Ctrl';
 
@@ -143,9 +143,9 @@ import KapaLauncher from './KapaLauncher.astro';
 				+ ''
 				+ 'Ask AI'
 				+ '';
-			askAi.addEventListener('click', function () {
-				// openPanel() in KapaChatLauncher reads the live search input and
-				// closes the search dialog itself, so we just route the click.
+askAi.addEventListener('click', function () {
+				// KapaLauncher reads the live search input and closes the search
+				// dialog itself, then opens the widget with that query prefilled.
 				var kapaBtn = document.querySelector('.warp-kapa-button');
 				if (kapaBtn) kapaBtn.click();
 			});
diff --git a/src/components/KapaChatLauncher.css b/src/components/KapaChatLauncher.css
index 3aca6dc6c..d810c5b08 100644
--- a/src/components/KapaChatLauncher.css
+++ b/src/components/KapaChatLauncher.css
@@ -200,6 +200,126 @@
 	padding: 0.1rem 0.3rem;
 }
 
+.sl-kapa-codeblock {
+	position: relative;
+	margin: 0.85rem 0;
+	max-width: 100%;
+}
+
+/* Chat-only copy control. Deliberately avoids EC's `.copy` class so EC CSS
+   (`button::after` mask) and EC JS never attach a second icon/handler. Visual
+   tokens match docs frosted-glass copy buttons in warp-components.css §2. */
+.sl-kapa-codeblock__copy-wrap {
+	position: absolute;
+	inset-block-start: 0.5rem;
+	inset-inline-end: 0.5rem;
+	z-index: 2;
+	display: flex;
+	align-items: center;
+	gap: 0.25rem;
+	pointer-events: none;
+}
+
+.sl-kapa-codeblock__copy {
+	pointer-events: auto;
+	position: relative;
+	box-sizing: border-box;
+	width: 2rem;
+	height: 2rem;
+	margin: 0;
+	padding: 0;
+	border-radius: var(--sl-radius-sm);
+	border: 1px solid rgba(255, 255, 255, 0.1);
+	background: rgba(255, 255, 255, 0.08);
+	backdrop-filter: blur(8px);
+	cursor: pointer;
+	opacity: 0.4;
+	transition:
+		opacity 0.15s ease,
+		background-color 0.15s ease,
+		border-color 0.15s ease;
+}
+
+.sl-kapa-codeblock:hover .sl-kapa-codeblock__copy,
+.sl-kapa-codeblock:focus-within .sl-kapa-codeblock__copy {
+	opacity: 0.75;
+}
+
+.sl-kapa-codeblock__copy:hover,
+.sl-kapa-codeblock__copy:focus-visible {
+	opacity: 1;
+	background: rgba(255, 255, 255, 0.16);
+	border-color: rgba(255, 255, 255, 0.18);
+}
+
+.sl-kapa-codeblock__copy:focus-visible {
+	outline: 2px solid var(--sl-color-accent-high);
+	outline-offset: 2px;
+}
+
+.sl-kapa-codeblock__copy-icon {
+	position: absolute;
+	inset: 0.475rem;
+	background-color: var(--sl-color-white, #f9f8f6);
+	-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.75'%3E%3Cpath d='M3 19a2 2 0 0 1-1-2V2a2 2 0 0 1 1-1h13a2 2 0 0 1 2 1'/%3E%3Crect x='6' y='5' width='16' height='18' rx='1.5' ry='1.5'/%3E%3C/svg%3E");
+	mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.75'%3E%3Cpath d='M3 19a2 2 0 0 1-1-2V2a2 2 0 0 1 1-1h13a2 2 0 0 1 2 1'/%3E%3Crect x='6' y='5' width='16' height='18' rx='1.5' ry='1.5'/%3E%3C/svg%3E");
+	-webkit-mask-repeat: no-repeat;
+	mask-repeat: no-repeat;
+	-webkit-mask-position: center;
+	mask-position: center;
+	-webkit-mask-size: contain;
+	mask-size: contain;
+}
+
+.sl-kapa-codeblock__copy-feedback {
+	pointer-events: none;
+	user-select: none;
+	font-size: var(--sl-text-2xs);
+	line-height: 1.2;
+	padding: 0.2rem 0.4rem;
+	border-radius: var(--sl-radius-sm);
+	background: color-mix(in srgb, var(--sl-color-accent) 85%, black);
+	color: var(--sl-color-white);
+	white-space: nowrap;
+}
+
+:root[data-theme='light'] .sl-kapa-codeblock__copy {
+	background: rgba(0, 0, 0, 0.04);
+	border: 1px solid rgba(0, 0, 0, 0.08);
+	opacity: 0.6;
+}
+
+:root[data-theme='light'] .sl-kapa-codeblock__copy:hover,
+:root[data-theme='light'] .sl-kapa-codeblock__copy:focus-visible {
+	background: rgba(0, 0, 0, 0.08);
+	border-color: rgba(0, 0, 0, 0.12);
+	opacity: 1;
+}
+
+:root[data-theme='light'] .sl-kapa-codeblock__copy-icon {
+	background-color: var(--sl-color-white, #0a0d12);
+}
+
+.sl-kapa-codeblock pre {
+	margin: 0;
+	padding: var(--ec-codePadBlk) var(--ec-codePadInl);
+	overflow-x: auto;
+	overflow-y: hidden;
+	white-space: pre;
+}
+
+.sl-kapa-codeblock code {
+	font-family: var(--__sl-font-mono, 'JetBrains Mono', 'SFMono-Regular', monospace);
+	display: block;
+	min-width: max-content;
+}
+
+/* Shiki separates `.line` spans with literal newline characters, which
+   `white-space: pre` (set on the pre above) already renders as line
+   breaks. The spans must stay inline — giving them `display: block`
+   would add a second break per line and double-space the code. */
+
+
 .sl-kapa-thinking {
 	display: flex;
 	align-items: center;
@@ -249,18 +369,73 @@
 
 .sl-kapa-feedback {
 	display: flex;
+	flex-wrap: wrap;
+	align-items: center;
 	gap: 0.5rem;
 	margin-top: 0.875rem;
 }
+.sl-kapa-feedback__handoff {
+	display: inline-flex;
+	align-items: center;
+	justify-content: center;
+	height: 2.25rem;
+	padding: 0 0.75rem;
+	border: 1px solid var(--sl-color-gray-5);
+	border-radius: var(--sl-radius-sm);
+	background: var(--sl-color-black);
+	color: var(--sl-color-gray-1);
+	font: inherit;
+	font-size: var(--sl-text-xs);
+	font-weight: 500;
+	cursor: pointer;
+	transition:
+		border-color 0.15s ease,
+		background-color 0.15s ease,
+		color 0.15s ease;
+}
+
+.sl-kapa-feedback__handoff:hover {
+	border-color: var(--warp-control-border-hover);
+	background: var(--warp-control-bg-hover);
+	color: var(--sl-color-white);
+}
+
+.sl-kapa-feedback__handoff:focus-visible {
+	outline: 2px solid var(--sl-color-accent-high);
+	outline-offset: 2px;
+}
+.sl-kapa-feedback__handoff--submit {
+	background: var(--sl-color-text-accent);
+	border-color: var(--sl-color-text-accent);
+	color: var(--sl-color-black);
+}
+
+.sl-kapa-feedback__handoff--submit:hover:not(:disabled) {
+	border-color: color-mix(in srgb, var(--sl-color-text-accent), var(--sl-color-white) 18%);
+	background: color-mix(in srgb, var(--sl-color-text-accent), var(--sl-color-white) 8%);
+	color: var(--sl-color-black);
+}
+
+.sl-kapa-feedback__handoff--ghost {
+	background: transparent;
+}
 
 .sl-kapa-error {
-	border: 1px solid color-mix(in srgb, #ef4444, var(--sl-color-black) 35%);
-	background: rgb(127 29 29 / 0.2);
-	color: #fecaca;
+	border: 1px solid rgb(248 113 113 / 0.8);
+	background: rgb(254 226 226 / 0.9);
+	color: #991b1b;
 	border-radius: var(--sl-radius-lg);
 	padding: 0.875rem 1rem;
 }
 
+@media (prefers-color-scheme: dark) {
+	.sl-kapa-error {
+		border: 1px solid color-mix(in srgb, #ef4444, var(--sl-color-black) 35%);
+		background: rgb(127 29 29 / 0.2);
+		color: #fecaca;
+	}
+}
+
 .sl-kapa-panel__footer {
 	position: relative;
 	padding: 1rem;
@@ -337,6 +512,228 @@
 	opacity: 0.5;
 	cursor: not-allowed;
 }
+.sl-kapa-handoff-inline {
+	margin-top: 0.75rem;
+	padding-top: 0.75rem;
+	border-top: 1px solid var(--sl-color-gray-5);
+	display: flex;
+	flex-direction: column;
+	gap: 0.5rem;
+}
+
+.sl-kapa-handoff-inline label {
+	font-size: var(--sl-text-xs);
+	font-weight: 600;
+	color: var(--sl-color-gray-2);
+}
+
+.sl-kapa-handoff-inline__row {
+	display: grid;
+	grid-template-columns: minmax(0, 1fr) auto auto;
+	gap: 0.5rem;
+}
+
+.sl-kapa-handoff-inline input {
+	width: 100%;
+	min-width: 0;
+	height: 2.25rem;
+	border: 1px solid var(--sl-color-gray-5);
+	border-radius: var(--sl-radius-sm);
+	background: var(--sl-color-black);
+	color: var(--sl-color-white);
+	padding: 0 0.625rem;
+	font: inherit;
+	font-size: var(--sl-text-sm);
+}
+
+.sl-kapa-handoff-inline input::placeholder {
+	color: var(--sl-color-gray-3);
+}
+
+.sl-kapa-handoff-inline input:focus-visible {
+	outline: 2px solid var(--sl-color-accent-high);
+	outline-offset: 2px;
+}
+
+.sl-kapa-handoff-inline__status {
+	margin: 0;
+	font-size: var(--sl-text-xs);
+	line-height: 1.4;
+}
+
+.sl-kapa-handoff-inline__status--success {
+	color: #14532d;
+	background: rgb(220 252 231 / 0.9);
+	border: 1px solid rgb(74 222 128 / 0.7);
+	padding: 0.375rem 0.5rem;
+	border-radius: var(--sl-radius-sm);
+}
+
+.sl-kapa-handoff-inline__status--error {
+	color: #b91c1c;
+	background: rgb(254 226 226 / 0.9);
+	border: 1px solid rgb(248 113 113 / 0.8);
+	padding: 0.375rem 0.5rem;
+	border-radius: var(--sl-radius-sm);
+}
+
+.sl-kapa-handoff-inline__status a {
+	color: inherit;
+	text-decoration: underline;
+}
+
+@media (prefers-color-scheme: dark) {
+	.sl-kapa-handoff-inline__status--success {
+		color: #86efac;
+		background: rgb(20 83 45 / 0.35);
+		border-color: rgb(74 222 128 / 0.45);
+	}
+	.sl-kapa-handoff-inline__status--error {
+		color: #fecaca;
+		background: rgb(127 29 29 / 0.3);
+		border-color: rgb(248 113 113 / 0.5);
+	}
+}
+
+.sl-kapa-handoff {
+	margin-top: 0.75rem;
+	display: flex;
+	flex-direction: column;
+	gap: 0.625rem;
+}
+
+.sl-kapa-handoff__toggle {
+	display: inline-flex;
+	align-items: center;
+	justify-content: center;
+	gap: 0.5rem;
+	width: 100%;
+	height: 2.5rem;
+	padding: 0 0.875rem;
+	border: 1px solid var(--sl-color-gray-5);
+	border-radius: var(--sl-radius-sm);
+	background: var(--sl-color-black);
+	color: var(--sl-color-gray-1);
+	font: inherit;
+	font-size: var(--sl-text-sm);
+	font-weight: 500;
+	cursor: pointer;
+	transition:
+		border-color 0.15s ease,
+		background-color 0.15s ease,
+		color 0.15s ease;
+}
+
+.sl-kapa-handoff__toggle svg {
+	width: 0.95rem;
+	height: 0.95rem;
+	flex: none;
+}
+
+.sl-kapa-handoff__toggle:hover {
+	border-color: var(--warp-control-border-hover);
+	background: var(--warp-control-bg-hover);
+	color: var(--sl-color-white);
+}
+
+.sl-kapa-handoff__toggle:focus-visible {
+	outline: 2px solid var(--sl-color-accent-high);
+	outline-offset: 2px;
+}
+
+.sl-kapa-handoff__form {
+	display: flex;
+	flex-direction: column;
+	gap: 0.5rem;
+	padding: 0.75rem;
+	border: 1px solid var(--sl-color-gray-5);
+	border-radius: var(--sl-radius-lg);
+	background: color-mix(in srgb, var(--sl-color-black), var(--sl-color-gray-6) 28%);
+}
+
+.sl-kapa-handoff__form label {
+	display: flex;
+	flex-direction: column;
+	gap: 0.25rem;
+}
+
+.sl-kapa-handoff__form label span {
+	font-size: var(--sl-text-2xs);
+	color: var(--sl-color-gray-3);
+}
+
+.sl-kapa-handoff__form input,
+.sl-kapa-handoff__form textarea {
+	width: 100%;
+	border: 1px solid var(--sl-color-gray-5);
+	border-radius: var(--sl-radius-sm);
+	background: var(--sl-color-black);
+	color: var(--sl-color-white);
+	padding: 0.5rem 0.625rem;
+	font: inherit;
+	font-size: var(--sl-text-sm);
+}
+
+.sl-kapa-handoff__form textarea {
+	resize: vertical;
+	min-height: 4rem;
+}
+
+.sl-kapa-handoff__form input::placeholder,
+.sl-kapa-handoff__form textarea::placeholder {
+	color: var(--sl-color-gray-3);
+}
+
+.sl-kapa-handoff__form input:focus-visible,
+.sl-kapa-handoff__form textarea:focus-visible {
+	outline: 2px solid var(--sl-color-accent-high);
+	outline-offset: 2px;
+}
+
+.sl-kapa-handoff__submit {
+	margin-top: 0.25rem;
+	height: 2.5rem;
+	border: 1px solid var(--sl-color-text-accent);
+	border-radius: var(--sl-radius-sm);
+	background: var(--sl-color-text-accent);
+	color: var(--sl-color-black);
+	font: inherit;
+	font-size: var(--sl-text-sm);
+	font-weight: 600;
+	cursor: pointer;
+	transition:
+		border-color 0.15s ease,
+		background-color 0.15s ease;
+}
+
+.sl-kapa-handoff__submit:hover:not(:disabled) {
+	border-color: color-mix(in srgb, var(--sl-color-text-accent), var(--sl-color-white) 18%);
+	background: color-mix(in srgb, var(--sl-color-text-accent), var(--sl-color-white) 8%);
+}
+
+.sl-kapa-handoff__submit:focus-visible {
+	outline: 2px solid var(--sl-color-accent-high);
+	outline-offset: 2px;
+}
+
+.sl-kapa-handoff__submit:disabled {
+	opacity: 0.55;
+	cursor: not-allowed;
+}
+
+.sl-kapa-handoff__status {
+	margin: 0;
+	font-size: var(--sl-text-xs);
+	line-height: 1.4;
+}
+
+.sl-kapa-handoff__status--success {
+	color: #86efac;
+}
+
+.sl-kapa-handoff__status--error {
+	color: #fecaca;
+}
 
 /* Hide the reCAPTCHA badge */
 .grecaptcha-badge {
diff --git a/src/components/KapaChatLauncher.mount.tsx b/src/components/KapaChatLauncher.mount.tsx
deleted file mode 100644
index e69de29bb..000000000
diff --git a/src/components/KapaChatLauncher.tsx b/src/components/KapaChatLauncher.tsx
index d4e1bcb9b..dcc0b2e55 100644
--- a/src/components/KapaChatLauncher.tsx
+++ b/src/components/KapaChatLauncher.tsx
@@ -1,8 +1,8 @@
-import type { FormEvent, MouseEvent } from 'react';
+import type { FormEvent, MouseEvent, ReactElement, ReactNode } from 'react';
 import * as Popover from '@radix-ui/react-popover';
-import { useEffect, useMemo, useRef, useState } from 'react';
-import { KapaProvider, useChat } from '@kapaai/react-sdk';
-import { PUBLIC_KAPA_INTEGRATION_ID } from 'astro:env/client';
+import { isValidElement, useEffect, useMemo, useRef, useState } from 'react';
+import { CaptchaAction, KapaProvider, useCaptcha, useChat } from '@kapaai/react-sdk';
+import { PUBLIC_KAPA_INTEGRATION_ID, PUBLIC_KAPA_PROJECT_ID } from 'astro:env/client';
 import { isMac, keymatch } from 'keymatch';
 import ReactMarkdown from 'react-markdown';
 import {
@@ -18,10 +18,395 @@ import {
 import './KapaChatLauncher.css';
 
 const integrationId = PUBLIC_KAPA_INTEGRATION_ID;
+const projectId = PUBLIC_KAPA_PROJECT_ID?.trim() || '';
 const title = 'Ask Warp';
 const welcomeMessage = 'What do you want to know about Warp?';
+const uncertaintyThreshold = 0.15;
+const conversationLengthThreshold = 3;
+const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
 
 type FeedbackReaction = 'upvote' | 'downvote';
+type GenericRecord = Record;
+type HandoffApiSuccess = {
+	message?: string;
+};
+
+function isObject(value: unknown): value is GenericRecord {
+	return typeof value === 'object' && value !== null;
+}
+
+function readNumberField(record: GenericRecord, key: string) {
+	const value = record[key];
+	if (typeof value === 'number' && Number.isFinite(value)) return value;
+	if (typeof value === 'string') {
+		const parsed = Number(value);
+		if (Number.isFinite(parsed)) return parsed;
+	}
+	return null;
+}
+
+function readBooleanField(record: GenericRecord, key: string) {
+	const value = record[key];
+	if (typeof value === 'boolean') return value;
+	if (typeof value === 'string') {
+		const normalized = value.trim().toLowerCase();
+		if (normalized === 'true') return true;
+		if (normalized === 'false') return false;
+	}
+	return null;
+}
+
+function getUncertaintyScore(metadata: unknown) {
+	if (!isObject(metadata)) return null;
+	return (
+		readNumberField(metadata, 'uncertainty') ??
+		readNumberField(metadata, 'uncertainty_score') ??
+		readNumberField(metadata, 'uncertaintyScore')
+	);
+}
+
+function isAnswerUncertain(metadata: unknown) {
+	if (!isObject(metadata)) return false;
+	const flag =
+		readBooleanField(metadata, 'is_uncertain') ??
+		readBooleanField(metadata, 'isUncertain');
+	if (flag === true) return true;
+	const score = getUncertaintyScore(metadata);
+	return score !== null ? score >= uncertaintyThreshold : false;
+}
+
+function isValidEmailAddress(value: string) {
+	return emailPattern.test(value.trim());
+}
+function getChatErrorMessage(error: unknown) {
+	const message = typeof error === 'string' ? error : String(error ?? '');
+	const normalized = message.toLowerCase();
+	const looksLikeBlockedNetworkError =
+		normalized.includes('network error while fetching answer') ||
+		normalized.includes('failed to fetch') ||
+		normalized.includes('err_blocked_by_client');
+	if (looksLikeBlockedNetworkError) {
+		return "Couldn't reach the chat service. If you use an ad blocker or privacy extension, allow kapa.ai and proxy.kapa.ai, then try again.";
+	}
+	return message;
+}
+
+const CHAT_LANGUAGE_ALIASES: Record = {
+	shell: 'bash',
+	zsh: 'bash',
+	pwsh: 'powershell',
+	plaintext: 'text',
+};
+
+function normalizeChatLanguage(language: string): string {
+	return CHAT_LANGUAGE_ALIASES[language.toLowerCase()] ?? language.toLowerCase();
+}
+
+function inferLanguageFromCode(codeText: string, fallbackLanguage: string): string {
+	if (fallbackLanguage !== 'text') return fallbackLanguage;
+	const sample = codeText.trim();
+	if (!sample) return fallbackLanguage;
+	const commandLikePattern =
+		/^(sudo|apt|apt-get|dnf|yum|zypper|pacman|curl|wget|git|npm|pnpm|yarn|cargo|python|node|brew|sh|bash)\b/m;
+	if (commandLikePattern.test(sample)) return 'bash';
+	return fallbackLanguage;
+}
+
+function escapeHtml(value: string): string {
+	return value.replace(/&/g, '&').replace(//g, '>');
+}
+
+async function copyTextToClipboard(text: string): Promise {
+	try {
+		if (navigator.clipboard?.writeText) {
+			await navigator.clipboard.writeText(text);
+			return true;
+		}
+	} catch {
+		// Fall through to execCommand fallback.
+	}
+	try {
+		const pre = document.createElement('pre');
+		Object.assign(pre.style, {
+			opacity: '0',
+			pointerEvents: 'none',
+			position: 'absolute',
+			overflow: 'hidden',
+			left: '0',
+			top: '0',
+			width: '20px',
+			height: '20px',
+			webkitUserSelect: 'auto',
+			userSelect: 'all',
+		});
+		pre.setAttribute('aria-hidden', 'true');
+		pre.textContent = text;
+		document.body.appendChild(pre);
+		const range = document.createRange();
+		range.selectNode(pre);
+		const selection = window.getSelection();
+		if (!selection) {
+			document.body.removeChild(pre);
+			return false;
+		}
+		selection.removeAllRanges();
+		selection.addRange(range);
+		const ok = document.execCommand('copy');
+		selection.removeAllRanges();
+		document.body.removeChild(pre);
+		return ok;
+	} catch {
+		return false;
+	}
+}
+
+type MarkdownCodeProps = { className?: string; children?: ReactNode };
+
+// react-markdown v9+ no longer passes an `inline` flag to the `code`
+// component. The reliable way to tell fenced blocks apart from inline
+// code is nesting: fenced blocks are always rendered as 
, so
+// we intercept `pre` (block) and leave bare `code` (inline) untouched.
+function extractCodeElement(children: ReactNode): ReactElement | null {
+	const items = Array.isArray(children) ? children : [children];
+	for (const item of items) {
+		if (isValidElement(item)) return item;
+	}
+	return null;
+}
+
+function markdownChildrenToText(children: ReactNode): string {
+	return (Array.isArray(children) ? children.join('') : String(children ?? '')).replace(/\n$/, '');
+}
+
+const highlightCache = new Map();
+const highlightInFlight = new Map>();
+let highlightRequestQueue: Promise = Promise.resolve();
+type ShikiModule = typeof import('shiki');
+type ShikiHighlighter = Awaited>;
+let shikiHighlighterPromise: Promise | null = null;
+const SHIKI_LANGUAGES = new Set([
+	'bash',
+	'powershell',
+	'json',
+	'javascript',
+	'typescript',
+	'tsx',
+	'jsx',
+	'python',
+	'go',
+	'rust',
+	'yaml',
+	'markdown',
+	'html',
+	'css',
+	'text',
+]);
+
+async function getShikiHighlighter(): Promise {
+	if (!shikiHighlighterPromise) {
+		shikiHighlighterPromise = import('shiki/bundle/full').then(({ createHighlighter }) =>
+			createHighlighter({
+				themes: ['github-light', 'github-dark'],
+				langs: [...SHIKI_LANGUAGES],
+			})
+		);
+	}
+	return shikiHighlighterPromise;
+}
+
+async function requestHighlightedPre({
+	code,
+	language,
+	theme,
+}: {
+	code: string;
+	language: string;
+	theme: 'dark' | 'light';
+}): Promise {
+	const cacheKey = `${theme}:${language}:${code}`;
+	if (highlightCache.has(cacheKey)) {
+		return highlightCache.get(cacheKey) ?? null;
+	}
+	const existing = highlightInFlight.get(cacheKey);
+	if (existing) return existing;
+
+	const requestPromise = new Promise((resolve, reject) => {
+		const run = async () => {
+			try {
+				const highlighter = await getShikiHighlighter();
+				const shikiLanguage = SHIKI_LANGUAGES.has(language) ? language : 'text';
+				const html = highlighter.codeToHtml(code, {
+					lang: shikiLanguage,
+					theme: theme === 'light' ? 'github-light' : 'github-dark',
+				});
+				const preMatch = html.match(/]*>[\s\S]*?<\/pre>/i);
+				const preHtml = preMatch?.[0] ?? null;
+				highlightCache.set(cacheKey, preHtml);
+				resolve(preHtml);
+			} catch (error) {
+				reject(error);
+			}
+		};
+
+		highlightRequestQueue = highlightRequestQueue
+			.then(run)
+			.catch(() => run())
+			.then(() => undefined, () => undefined);
+	});
+
+	highlightInFlight.set(cacheKey, requestPromise);
+	requestPromise.then(
+		() => {
+			highlightInFlight.delete(cacheKey);
+		},
+		() => {
+			highlightInFlight.delete(cacheKey);
+		}
+	);
+	return requestPromise;
+}
+
+function ChatCodeBlock({
+	className,
+	codeText,
+	deferHighlight,
+}: {
+	className?: string;
+	codeText: string;
+	deferHighlight?: boolean;
+}) {
+	const language = className?.replace('language-', '') ?? 'text';
+	const normalizedLanguage = inferLanguageFromCode(
+		codeText,
+		normalizeChatLanguage(language)
+	);
+	const isTerminalLanguage = ['bash', 'sh', 'shell', 'zsh', 'powershell'].includes(normalizedLanguage);
+	const [highlighted, setHighlighted] = useState<{ key: string; preHtml: string } | null>(null);
+	const [isDarkTheme, setIsDarkTheme] = useState(true);
+	const [isCopied, setIsCopied] = useState(false);
+	const copiedResetRef = useRef(null);
+
+	useEffect(() => {
+		const root = document.documentElement;
+		const updateTheme = () => {
+			const explicitTheme = root.dataset.theme;
+			if (explicitTheme === 'light') {
+				setIsDarkTheme(false);
+				return;
+			}
+			if (explicitTheme === 'dark') {
+				setIsDarkTheme(true);
+				return;
+			}
+			setIsDarkTheme(window.matchMedia('(prefers-color-scheme: dark)').matches);
+		};
+
+		updateTheme();
+		const observer = new MutationObserver(updateTheme);
+		observer.observe(root, { attributes: true, attributeFilter: ['data-theme'] });
+		return () => observer.disconnect();
+	}, []);
+
+	useEffect(() => {
+		return () => {
+			if (copiedResetRef.current !== null) {
+				window.clearTimeout(copiedResetRef.current);
+			}
+		};
+	}, []);
+
+	const theme = isDarkTheme ? 'dark' : 'light';
+	const highlightKey = `${theme}:${normalizedLanguage}:${codeText}`;
+
+	useEffect(() => {
+		// While the answer is still streaming, the code text changes on every
+		// token. Requesting a highlight per token causes the block to churn
+		// between plaintext and highlighted DOM (visible flicker), so wait
+		// until streaming settles and highlight the final text once.
+		if (deferHighlight) return;
+		const controller = new AbortController();
+		(async (): Promise => {
+			try {
+				const preHtml = await requestHighlightedPre({
+					code: codeText,
+					language: normalizedLanguage,
+					theme,
+				});
+				if (!controller.signal.aborted && preHtml) {
+					setHighlighted({ key: `${theme}:${normalizedLanguage}:${codeText}`, preHtml });
+				}
+			} catch (error) {
+				if (!controller.signal.aborted) {
+					console.warn('[kapa-chat] code highlighting failed; using plaintext fallback', error);
+				}
+			}
+		})();
+
+		return () => {
+			controller.abort();
+		};
+	}, [codeText, deferHighlight, theme, normalizedLanguage]);
+
+	// Only use highlighted HTML that matches the *current* code text and
+	// theme; otherwise render the plaintext fallback. This prevents stale
+	// highlighted content from flashing while new text is streaming in.
+	const highlightedPreHtml = highlighted?.key === highlightKey ? highlighted.preHtml : null;
+
+	const onCopy = async () => {
+		const ok = await copyTextToClipboard(codeText);
+		if (!ok) return;
+		setIsCopied(true);
+		if (copiedResetRef.current !== null) {
+			window.clearTimeout(copiedResetRef.current);
+		}
+		copiedResetRef.current = window.setTimeout(() => {
+			setIsCopied(false);
+			copiedResetRef.current = null;
+		}, 1500);
+	};
+
+	return (
+		
+
+
+ + {isTerminalLanguage ? Terminal window : null} +
+ {highlightedPreHtml ? ( +
+ ) : ( +
+						
+					
+ )} + {/* Dedicated chat copy control — intentionally NOT EC's `.copy` + class. Reusing EC markup stacked EC's CSS mask icon on top of + any residual SVG and produced a double clipboard. One button, + one icon (CSS mask), one click handler. */} +
+ + {isCopied ? 'Copied!' : ''} + + {isCopied ? Copied! : null} + +
+
+
+ ); +} function ChatSurface({ title, welcomeMessage, autoOpen = false, onNewConversation }: { title: string; @@ -33,6 +418,13 @@ function ChatSurface({ title, welcomeMessage, autoOpen = false, onNewConversatio const [query, setQuery] = useState(''); const [hasStartedConversation, setHasStartedConversation] = useState(false); const [isAppleDevice, setIsAppleDevice] = useState(false); + const [storedThreadId, setStoredThreadId] = useState(null); + const [downvotedAnswerIds, setDownvotedAnswerIds] = useState>({}); + const [handoffEmailInput, setHandoffEmailInput] = useState(''); + const [handoffQaId, setHandoffQaId] = useState(null); + const [handoffErrorMessage, setHandoffErrorMessage] = useState(null); + const [handoffSuccessMessage, setHandoffSuccessMessage] = useState(null); + const [isSubmittingHandoff, setIsSubmittingHandoff] = useState(false); const messagesRef = useRef(null); const dialogRef = useRef(null); const triggerRef = useRef(null); @@ -45,16 +437,55 @@ function ChatSurface({ title, welcomeMessage, autoOpen = false, onNewConversatio isGeneratingAnswer, isPreparingAnswer, submitQuery, + threadId, } = useChat(); + const { executeCaptcha } = useCaptcha(); + useEffect(() => { setIsAppleDevice(isMac()); }, []); + useEffect(() => { + const savedThreadId = localStorage.getItem('warp_docs_kapa_thread_id'); + if (savedThreadId) { + setStoredThreadId(savedThreadId); + } + }, []); + + useEffect(() => { + if (!threadId) return; + setStoredThreadId(threadId); + localStorage.setItem('warp_docs_kapa_thread_id', threadId); + }, [threadId]); + useEffect(() => { if (!isOpen || !messagesRef.current) return; messagesRef.current.scrollTop = messagesRef.current.scrollHeight; }, [conversation.length, isOpen]); + useEffect(() => { + if (!isOpen || !messagesRef.current) return; + if (!isGeneratingAnswer && !isPreparingAnswer) return; + messagesRef.current.scrollTop = messagesRef.current.scrollHeight; + }, [conversation, isGeneratingAnswer, isOpen, isPreparingAnswer]); + + useEffect(() => { + if (!handoffQaId || !isOpen) return; + const frame = window.requestAnimationFrame(() => { + const inlineForm = document.getElementById(`sl-kapa-handoff-inline-${handoffQaId}`); + if (!inlineForm) return; + inlineForm.scrollIntoView({ + behavior: 'smooth', + block: 'nearest', + }); + const emailInput = inlineForm.querySelector('input[type="email"]'); + emailInput?.focus(); + }); + return () => { + window.cancelAnimationFrame(frame); + }; + }, [handoffQaId, isOpen, conversation.length]); + useEffect(() => { const dialog = dialogRef.current; if (!dialog) return; @@ -107,6 +538,7 @@ function ChatSurface({ title, welcomeMessage, autoOpen = false, onNewConversatio const submit = () => { const value = query.trim(); if (!value || isBusy) return; + closeHandoffForm(); submitQuery(value); setHasStartedConversation(true); setQuery(''); @@ -119,6 +551,116 @@ function ChatSurface({ title, welcomeMessage, autoOpen = false, onNewConversatio const feedback = (questionAnswerId: string, reaction: FeedbackReaction) => { addFeedback(questionAnswerId, reaction); + if (reaction === 'downvote') { + setDownvotedAnswerIds((current) => ({ ...current, [questionAnswerId]: true })); + } + }; + + const isDownvoted = (qaId: string | null | undefined, reaction: string | null | undefined) => { + if (!qaId) return false; + return reaction === 'downvote' || downvotedAnswerIds[qaId] === true; + }; + + const shouldShowHandoffForAnswer = (qa: { + id?: string | null; + answer?: string | null; + metadata?: unknown; + reaction?: string | null; + }) => { + if (!qa.answer?.trim()) return false; + const conversationLengthTriggered = conversation.length >= conversationLengthThreshold; + const downvoteTriggered = isDownvoted(qa.id ?? null, qa.reaction ?? null); + const uncertaintyTriggered = isAnswerUncertain(qa.metadata); + return conversationLengthTriggered || downvoteTriggered || uncertaintyTriggered; + }; + + const buildConversationTranscript = () => { + if (!conversation.length) return 'No conversation history yet.'; + return conversation + .map((qa, index) => { + const sources = qa.sources?.length + ? `\nSources:\n${qa.sources.map((source) => `- ${source.title}: ${source.source_url}`).join('\n')}` + : ''; + return `Q${index + 1}: ${qa.question}\nA${index + 1}: ${qa.answer || '(no answer generated yet)'}${sources}`; + }) + .join('\n\n'); + }; + + const buildConversationLink = (currentThreadId: string | null) => { + if (!projectId || !currentThreadId) return null; + return `https://app.kapa.ai/${projectId}/conversations/${currentThreadId}`; + }; + + const openHandoffForm = (qaId: string) => { + setHandoffQaId(qaId); + setHandoffErrorMessage(null); + setHandoffSuccessMessage(null); + }; + + const closeHandoffForm = () => { + setHandoffQaId(null); + setHandoffErrorMessage(null); + setHandoffSuccessMessage(null); + }; + + const submitSupportHandoff = async (qa: { id?: string | null; question?: string }) => { + const userEmail = handoffEmailInput.trim().toLowerCase(); + if (!isValidEmailAddress(userEmail)) { + setHandoffErrorMessage('Enter a valid email address to continue.'); + return; + } + const localStorageThreadId = localStorage.getItem('warp_docs_kapa_thread_id'); + const activeThreadId = threadId || storedThreadId || localStorageThreadId; + if (!activeThreadId) { + setHandoffErrorMessage('Missing Kapa thread context; please send another message and try again.'); + return; + } + + const question = qa.question?.trim(); + if (!question) { + setHandoffErrorMessage('Missing question context for handoff.'); + return; + } + + const conversationLink = buildConversationLink(activeThreadId); + const captcha = await executeCaptcha(CaptchaAction.FeedbackSubmit); + if (!captcha?.token || !captcha?.key) { + setHandoffErrorMessage('Captcha verification failed. Please try again.'); + return; + } + + setIsSubmittingHandoff(true); + setHandoffErrorMessage(null); + setHandoffSuccessMessage(null); + try { + const response = await fetch('/api/support-handoff', { + method: 'POST', + headers: { + 'content-type': 'application/json', + }, + body: JSON.stringify({ + user_email: userEmail, + question, + page_url: window.location.href, + conversation_transcript: buildConversationTranscript(), + kapa_project_id: projectId || null, + kapa_thread_id: activeThreadId, + kapa_conversation_url: conversationLink || null, + captcha_token: captcha.token, + captcha_header: captcha.key, + }), + }); + const payload: HandoffApiSuccess & { message?: string } = await response.json().catch(() => ({})); + if (!response.ok) { + setHandoffErrorMessage(payload.message || 'Could not create support ticket. Please try again.'); + return; + } + setHandoffSuccessMessage(payload.message || 'Support ticket created successfully.'); + } catch { + setHandoffErrorMessage('Could not reach support handoff service. Please try again.'); + } finally { + setIsSubmittingHandoff(false); + } }; const openPanel = () => { @@ -137,9 +679,10 @@ function ChatSurface({ title, welcomeMessage, autoOpen = false, onNewConversatio // Legacy fallback: earlier callers stashed the query on window before // triggering us. Kept as a belt-and-braces guard in case any path // still uses it. - if (!pendingQuery && (window as any).__warpAskAiQuery) { - pendingQuery = (window as any).__warpAskAiQuery; - delete (window as any).__warpAskAiQuery; + const windowWithAskQuery = window as Window & { __warpAskAiQuery?: string }; + if (!pendingQuery && windowWithAskQuery.__warpAskAiQuery) { + pendingQuery = windowWithAskQuery.__warpAskAiQuery; + delete windowWithAskQuery.__warpAskAiQuery; } setIsOpen(true); @@ -236,7 +779,38 @@ function ChatSurface({ title, welcomeMessage, autoOpen = false, onNewConversatio
{qa.question}
{qa.answer ? ( - {qa.answer} + ; inline code + // arrives as a bare . react-markdown v9+ removed the + // `inline` prop, so nesting is the only reliable signal. + pre({ children }) { + const codeElement = extractCodeElement(children); + if (!codeElement) { + return
{children}
; + } + const codeClassName = + typeof codeElement.props.className === 'string' + ? codeElement.props.className + : undefined; + const codeText = markdownChildrenToText(codeElement.props.children); + const isStreamingAnswer = + isBusy && conversation[conversation.length - 1]?.id === qa.id; + return ( + + ); + }, + code({ className, children }) { + return {children}; + }, + }} + > + {qa.answer} +
) : (
+ ) : null} + {handoffQaId === qa.id && !isBusy && shouldShowHandoffForAnswer(qa) ? ( +
+ +
{ + event.preventDefault(); + void submitSupportHandoff(qa); + }} + > + setHandoffEmailInput(event.target.value)} + required + /> + + +
+ {handoffErrorMessage ? ( +

+ {handoffErrorMessage} +

+ ) : null} + {handoffSuccessMessage ? ( +

+ {handoffSuccessMessage} +

+ ) : null}
) : null}
))} - {error ?
{error}
: null} + {error ?
{getChatErrorMessage(error)}
: null}