From 25284dc8d26b9c6faf38858750edd623f1cc6016 Mon Sep 17 00:00:00 2001 From: BenKurrek Date: Mon, 6 Jul 2026 16:12:52 -0400 Subject: [PATCH 01/12] chore(webui): switch frontend tooling to pnpm --- .github/workflows/code_style.yml | 20 +- .github/workflows/coverage.yml | 10 +- .github/workflows/platform-and-compat.yml | 16 +- .github/workflows/reborn-e2e.yml | 10 +- .github/workflows/reborn-playwright.yml | 10 +- .github/workflows/reborn-tests.yml | 12 +- Dockerfile.reborn | 3 + crates/ironclaw_webui_v2/build.rs | 46 +- crates/ironclaw_webui_v2/frontend/build.sh | 10 +- .../frontend/package-lock.json | 609 ------------------ .../ironclaw_webui_v2/frontend/package.json | 3 +- .../ironclaw_webui_v2/frontend/pnpm-lock.yaml | 374 +++++++++++ .../frontend/pnpm-workspace.yaml | 5 + 13 files changed, 467 insertions(+), 661 deletions(-) delete mode 100644 crates/ironclaw_webui_v2/frontend/package-lock.json create mode 100644 crates/ironclaw_webui_v2/frontend/pnpm-lock.yaml create mode 100644 crates/ironclaw_webui_v2/frontend/pnpm-workspace.yaml diff --git a/.github/workflows/code_style.yml b/.github/workflows/code_style.yml index 1820c67a42b..7df9a49ed94 100644 --- a/.github/workflows/code_style.yml +++ b/.github/workflows/code_style.yml @@ -178,13 +178,19 @@ jobs: uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable with: components: clippy + - name: Enable pnpm for setup-node cache + if: contains(matrix.flags, '--all-features') + run: corepack enable pnpm - name: Install Node.js for WebUI bundle builds if: contains(matrix.flags, '--all-features') uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4 with: node-version: "22" - cache: "npm" - cache-dependency-path: crates/ironclaw_webui_v2/frontend/package-lock.json + cache: "pnpm" + cache-dependency-path: crates/ironclaw_webui_v2/frontend/pnpm-lock.yaml + - name: Enable pnpm + if: contains(matrix.flags, '--all-features') + run: corepack enable pnpm - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 with: shared-key: clippy @@ -223,13 +229,19 @@ jobs: uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable with: components: clippy + - name: Enable pnpm for setup-node cache + if: contains(matrix.flags, '--all-features') + run: corepack enable pnpm - name: Install Node.js for WebUI bundle builds if: contains(matrix.flags, '--all-features') uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4 with: node-version: "22" - cache: "npm" - cache-dependency-path: crates/ironclaw_webui_v2/frontend/package-lock.json + cache: "pnpm" + cache-dependency-path: crates/ironclaw_webui_v2/frontend/pnpm-lock.yaml + - name: Enable pnpm + if: contains(matrix.flags, '--all-features') + run: corepack enable pnpm - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 with: key: windows-${{ matrix.name }} diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 5d14c5added..e7073260a5a 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -180,12 +180,18 @@ jobs: - name: Clean coverage workspace run: cargo llvm-cov clean --workspace + - name: Enable pnpm for setup-node cache + run: corepack enable pnpm + - name: Install Node.js for WebUI bundle build uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4 with: node-version: "22" - cache: "npm" - cache-dependency-path: crates/ironclaw_webui_v2/frontend/package-lock.json + cache: "pnpm" + cache-dependency-path: crates/ironclaw_webui_v2/frontend/pnpm-lock.yaml + + - name: Enable pnpm + run: corepack enable pnpm # Pre-build the reborn binary under the same llvm-cov env so the E2E # fixtures find it cached instead of doing a cold instrumented build diff --git a/.github/workflows/platform-and-compat.yml b/.github/workflows/platform-and-compat.yml index 4c637349a73..1125237eaa3 100644 --- a/.github/workflows/platform-and-compat.yml +++ b/.github/workflows/platform-and-compat.yml @@ -261,12 +261,16 @@ jobs: uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable with: targets: wasm32-wasip2 + - name: Enable pnpm for setup-node cache + run: corepack enable pnpm - name: Install Node.js for WebUI bundle builds uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4 with: node-version: "22" - cache: "npm" - cache-dependency-path: crates/ironclaw_webui_v2/frontend/package-lock.json + cache: "pnpm" + cache-dependency-path: crates/ironclaw_webui_v2/frontend/pnpm-lock.yaml + - name: Enable pnpm + run: corepack enable pnpm - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 with: key: wasm-extensions @@ -299,12 +303,16 @@ jobs: persist-credentials: false - name: Install Rust uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable + - name: Enable pnpm for setup-node cache + run: corepack enable pnpm - name: Install Node.js for WebUI bundle builds uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4 with: node-version: "22" - cache: "npm" - cache-dependency-path: crates/ironclaw_webui_v2/frontend/package-lock.json + cache: "pnpm" + cache-dependency-path: crates/ironclaw_webui_v2/frontend/pnpm-lock.yaml + - name: Enable pnpm + run: corepack enable pnpm - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 with: key: bench diff --git a/.github/workflows/reborn-e2e.yml b/.github/workflows/reborn-e2e.yml index 14180a2bb78..ccb647be66e 100644 --- a/.github/workflows/reborn-e2e.yml +++ b/.github/workflows/reborn-e2e.yml @@ -142,12 +142,18 @@ jobs: - name: Install Rust uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable + - name: Enable pnpm for setup-node cache + run: corepack enable pnpm + - name: Install Node.js for WebUI bundle build uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4 with: node-version: "22" - cache: "npm" - cache-dependency-path: crates/ironclaw_webui_v2/frontend/package-lock.json + cache: "pnpm" + cache-dependency-path: crates/ironclaw_webui_v2/frontend/pnpm-lock.yaml + + - name: Enable pnpm + run: corepack enable pnpm - name: Restore Rust cache uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 diff --git a/.github/workflows/reborn-playwright.yml b/.github/workflows/reborn-playwright.yml index 067b6c028ea..d9ac77d6b25 100644 --- a/.github/workflows/reborn-playwright.yml +++ b/.github/workflows/reborn-playwright.yml @@ -77,12 +77,18 @@ jobs: - name: Install Rust uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable + - name: Enable pnpm for setup-node cache + run: corepack enable pnpm + - name: Install Node.js for WebUI bundle build uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4 with: node-version: "22" - cache: "npm" - cache-dependency-path: crates/ironclaw_webui_v2/frontend/package-lock.json + cache: "pnpm" + cache-dependency-path: crates/ironclaw_webui_v2/frontend/pnpm-lock.yaml + + - name: Enable pnpm + run: corepack enable pnpm - name: Restore Rust cache uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 diff --git a/.github/workflows/reborn-tests.yml b/.github/workflows/reborn-tests.yml index 0abad2970a6..306e22d36bc 100644 --- a/.github/workflows/reborn-tests.yml +++ b/.github/workflows/reborn-tests.yml @@ -234,13 +234,21 @@ jobs: echo "needs_webui_node=${needs_webui_node}" >> "${GITHUB_OUTPUT}" echo "sccache_dist_enabled=${sccache_dist_enabled}" >> "${GITHUB_OUTPUT}" + - name: Enable pnpm for setup-node cache + if: ${{ steps.bucket-settings.outputs.needs_webui_node == 'true' }} + run: corepack enable pnpm + - name: Install Node.js for WebUI bundle builds if: ${{ steps.bucket-settings.outputs.needs_webui_node == 'true' }} uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4 with: node-version: "22" - cache: "npm" - cache-dependency-path: crates/ironclaw_webui_v2/frontend/package-lock.json + cache: "pnpm" + cache-dependency-path: crates/ironclaw_webui_v2/frontend/pnpm-lock.yaml + + - name: Enable pnpm + if: ${{ steps.bucket-settings.outputs.needs_webui_node == 'true' }} + run: corepack enable pnpm - name: Install mold and clang run: | diff --git a/Dockerfile.reborn b/Dockerfile.reborn index f780fc8babf..4cc470db1f7 100644 --- a/Dockerfile.reborn +++ b/Dockerfile.reborn @@ -21,8 +21,11 @@ COPY --from=node_toolchain /usr/local/lib/node_modules/ /usr/local/lib/node_modu RUN ln -sf ../lib/node_modules/npm/bin/npm-cli.js /usr/local/bin/npm \ && ln -sf ../lib/node_modules/npm/bin/npx-cli.js /usr/local/bin/npx \ + && ln -sf ../lib/node_modules/corepack/dist/corepack.js /usr/local/bin/corepack \ && node --version \ && npm --version \ + && corepack --version \ + && corepack enable pnpm \ && cargo install --locked cargo-chef@0.1.77 WORKDIR /app diff --git a/crates/ironclaw_webui_v2/build.rs b/crates/ironclaw_webui_v2/build.rs index f49a0f2083e..1414df6c50a 100644 --- a/crates/ironclaw_webui_v2/build.rs +++ b/crates/ironclaw_webui_v2/build.rs @@ -27,7 +27,8 @@ fn main() { println!("cargo:rerun-if-changed=static"); println!("cargo:rerun-if-changed=frontend/build.mjs"); println!("cargo:rerun-if-changed=frontend/package.json"); - println!("cargo:rerun-if-changed=frontend/package-lock.json"); + println!("cargo:rerun-if-changed=frontend/pnpm-lock.yaml"); + println!("cargo:rerun-if-changed=frontend/pnpm-workspace.yaml"); println!("cargo:rerun-if-changed=build.rs"); let webui_enabled = env::var_os("CARGO_FEATURE_WEBUI_V2_BETA").is_some(); @@ -123,33 +124,7 @@ fn build_frontend_dist(manifest_dir: &Path, dist_dir: &Path) { } fn ensure_frontend_dependencies(frontend_dir: &Path) { - let node_modules = frontend_dir.join("node_modules"); - let package_json = frontend_dir.join("package.json"); - let package_lock = frontend_dir.join("package-lock.json"); - let install_marker = node_modules.join(".package-lock.json"); - - let needs_install = if !node_modules.is_dir() || !install_marker.is_file() { - true - } else { - let marker_modified = modified_time(&install_marker); - modified_time(&package_lock) > marker_modified - || modified_time(&package_json) > marker_modified - }; - - if needs_install { - run_command( - npm_command(), - &["ci", "--no-audit", "--no-fund"], - frontend_dir, - &[], - ); - } -} - -fn modified_time(path: &Path) -> std::time::SystemTime { - fs::metadata(path) - .and_then(|metadata| metadata.modified()) - .unwrap_or_else(|error| panic!("read modified time for {}: {error}", path.display())) + run_pnpm(&["install", "--frozen-lockfile"], frontend_dir); } fn run_command(command: &str, args: &[&str], cwd: &Path, envs: &[(&str, &Path)]) { @@ -213,8 +188,19 @@ fn display_command(command: &str, args: &[&str]) -> String { .join(" ") } -fn npm_command() -> &'static str { - if cfg!(windows) { "npm.cmd" } else { "npm" } +fn run_pnpm(args: &[&str], cwd: &Path) { + let mut corepack_args = Vec::with_capacity(args.len() + 1); + corepack_args.push("pnpm"); + corepack_args.extend_from_slice(args); + run_command(corepack_command(), &corepack_args, cwd, &[]); +} + +fn corepack_command() -> &'static str { + if cfg!(windows) { + "corepack.cmd" + } else { + "corepack" + } } fn node_command() -> &'static str { diff --git a/crates/ironclaw_webui_v2/frontend/build.sh b/crates/ironclaw_webui_v2/frontend/build.sh index 04dde32eeba..8ffdaf3c037 100644 --- a/crates/ironclaw_webui_v2/frontend/build.sh +++ b/crates/ironclaw_webui_v2/frontend/build.sh @@ -5,7 +5,7 @@ # committed. Only commit static/vendor/ changes when refreshing pinned vendor # assets. # -# ./build.sh # vendor + npm ci + bundle +# ./build.sh # vendor + pnpm install + bundle # ./build.sh --no-vendor # skip re-downloading vendored CDN assets set -euo pipefail @@ -16,13 +16,13 @@ if [[ "${1:-}" != "--no-vendor" ]]; then bash vendor.sh fi -echo "Installing build dependencies (npm ci)…" -if [[ ! -f package-lock.json ]]; then - echo "Error: package-lock.json is missing — refusing to fall back to 'npm install'." >&2 +echo "Installing build dependencies (pnpm install --frozen-lockfile)…" +if [[ ! -f pnpm-lock.yaml ]]; then + echo "Error: pnpm-lock.yaml is missing — refusing to install without a lockfile." >&2 echo "Artifacts must build from the committed lockfile. Restore it and re-run." >&2 exit 1 fi -npm ci +corepack pnpm install --frozen-lockfile echo "Bundling SPA…" node build.mjs diff --git a/crates/ironclaw_webui_v2/frontend/package-lock.json b/crates/ironclaw_webui_v2/frontend/package-lock.json deleted file mode 100644 index fd4ccf6cb70..00000000000 --- a/crates/ironclaw_webui_v2/frontend/package-lock.json +++ /dev/null @@ -1,609 +0,0 @@ -{ - "name": "ironclaw-webui-v2-frontend", - "version": "0.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "ironclaw-webui-v2-frontend", - "version": "0.0.0", - "dependencies": { - "@tanstack/react-query": "5.87.4", - "htm": "3.1.1", - "react": "19.1.0", - "react-dom": "19.1.0", - "react-hook-form": "7.62.0", - "react-router": "7.15.1" - }, - "devDependencies": { - "esbuild": "0.25.0" - }, - "engines": { - "node": ">=22 <23", - "npm": ">=10" - } - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.0.tgz", - "integrity": "sha512-O7vun9Sf8DFjH2UtqK8Ku3LkquL9SZL8OLY1T5NZkA34+wG3OQF7cl4Ql8vdNzM6fzBbYfLaiRLIOZ+2FOCgBQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.0.tgz", - "integrity": "sha512-PTyWCYYiU0+1eJKmw21lWtC+d08JDZPQ5g+kFyxP0V+es6VPPSUhM6zk8iImp2jbV6GwjX4pap0JFbUQN65X1g==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.0.tgz", - "integrity": "sha512-grvv8WncGjDSyUBjN9yHXNt+cq0snxXbDxy5pJtzMKGmmpPxeAmAhWxXI+01lU5rwZomDgD3kJwulEnhTRUd6g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.0.tgz", - "integrity": "sha512-m/ix7SfKG5buCnxasr52+LI78SQ+wgdENi9CqyCXwjVR2X4Jkz+BpC3le3AoBPYTC9NHklwngVXvbJ9/Akhrfg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.0.tgz", - "integrity": "sha512-mVwdUb5SRkPayVadIOI78K7aAnPamoeFR2bT5nszFUZ9P8UpK4ratOdYbZZXYSqPKMHfS1wdHCJk1P1EZpRdvw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.0.tgz", - "integrity": "sha512-DgDaYsPWFTS4S3nWpFcMn/33ZZwAAeAFKNHNa1QN0rI4pUjgqf0f7ONmXf6d22tqTY+H9FNdgeaAa+YIFUn2Rg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.0.tgz", - "integrity": "sha512-VN4ocxy6dxefN1MepBx/iD1dH5K8qNtNe227I0mnTRjry8tj5MRk4zprLEdG8WPyAPb93/e4pSgi1SoHdgOa4w==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.0.tgz", - "integrity": "sha512-mrSgt7lCh07FY+hDD1TxiTyIHyttn6vnjesnPoVDNmDfOmggTLXRv8Id5fNZey1gl/V2dyVK1VXXqVsQIiAk+A==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.0.tgz", - "integrity": "sha512-vkB3IYj2IDo3g9xX7HqhPYxVkNQe8qTK55fraQyTzTX/fxaDtXiEnavv9geOsonh2Fd2RMB+i5cbhu2zMNWJwg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.0.tgz", - "integrity": "sha512-9QAQjTWNDM/Vk2bgBl17yWuZxZNQIF0OUUuPZRKoDtqF2k4EtYbpyiG5/Dk7nqeK6kIJWPYldkOcBqjXjrUlmg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.0.tgz", - "integrity": "sha512-43ET5bHbphBegyeqLb7I1eYn2P/JYGNmzzdidq/w0T8E2SsYL1U6un2NFROFRg1JZLTzdCoRomg8Rvf9M6W6Gg==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.0.tgz", - "integrity": "sha512-fC95c/xyNFueMhClxJmeRIj2yrSMdDfmqJnyOY4ZqsALkDrrKJfIg5NTMSzVBr5YW1jf+l7/cndBfP3MSDpoHw==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.0.tgz", - "integrity": "sha512-nkAMFju7KDW73T1DdH7glcyIptm95a7Le8irTQNO/qtkoyypZAnjchQgooFUDQhNAy4iu08N79W4T4pMBwhPwQ==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.0.tgz", - "integrity": "sha512-NhyOejdhRGS8Iwv+KKR2zTq2PpysF9XqY+Zk77vQHqNbo/PwZCzB5/h7VGuREZm1fixhs4Q/qWRSi5zmAiO4Fw==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.0.tgz", - "integrity": "sha512-5S/rbP5OY+GHLC5qXp1y/Mx//e92L1YDqkiBbO9TQOvuFXM+iDqUNG5XopAnXoRH3FjIUDkeGcY1cgNvnXp/kA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.0.tgz", - "integrity": "sha512-XM2BFsEBz0Fw37V0zU4CXfcfuACMrppsMFKdYY2WuTS3yi8O1nFOhil/xhKTmE1nPmVyvQJjJivgDT+xh8pXJA==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.0.tgz", - "integrity": "sha512-9yl91rHw/cpwMCNytUDxwj2XjFpxML0y9HAOH9pNVQDpQrBxHy01Dx+vaMu0N1CKa/RzBD2hB4u//nfc+Sd3Cw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.0.tgz", - "integrity": "sha512-RuG4PSMPFfrkH6UwCAqBzauBWTygTvb1nxWasEJooGSJ/NwRw7b2HOwyRTQIU97Hq37l3npXoZGYMy3b3xYvPw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.0.tgz", - "integrity": "sha512-jl+qisSB5jk01N5f7sPCsBENCOlPiS/xptD5yxOx2oqQfyourJwIKLRA2yqWdifj3owQZCL2sn6o08dBzZGQzA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.0.tgz", - "integrity": "sha512-21sUNbq2r84YE+SJDfaQRvdgznTD8Xc0oc3p3iW/a1EVWeNj/SdUCbm5U0itZPQYRuRTW20fPMWMpcrciH2EJw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.0.tgz", - "integrity": "sha512-2gwwriSMPcCFRlPlKx3zLQhfN/2WjJ2NSlg5TKLQOJdV0mSxIcYNTMhk3H3ulL/cak+Xj0lY1Ym9ysDV1igceg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.0.tgz", - "integrity": "sha512-bxI7ThgLzPrPz484/S9jLlvUAHYMzy6I0XiU1ZMeAEOBcS0VePBFxh1JjTQt3Xiat5b6Oh4x7UC7IwKQKIJRIg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.0.tgz", - "integrity": "sha512-ZUAc2YK6JW89xTbXvftxdnYy3m4iHIkDtK3CLce8wg8M2L+YZhIvO1DKpxrd0Yr59AeNNkTiic9YLf6FTtXWMw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.0.tgz", - "integrity": "sha512-eSNxISBu8XweVEWG31/JzjkIGbGIJN/TrRoiSVZwZ6pkC6VX4Im/WV2cz559/TXLcYbcrDN8JtKgd9DJVIo8GA==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.0.tgz", - "integrity": "sha512-ZENoHJBxA20C2zFzh6AI4fT6RraMzjYw4xKWemRTRmRVtN9c5DcH9r/f2ihEkMjOW5eGgrwCslG/+Y/3bL+DHQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@tanstack/query-core": { - "version": "5.87.4", - "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.87.4.tgz", - "integrity": "sha512-uNsg6zMxraEPDVO2Bn+F3/ctHi+Zsk+MMpcN8h6P7ozqD088F6mFY5TfGM7zuyIrL7HKpDyu6QHfLWiDxh3cuw==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - } - }, - "node_modules/@tanstack/react-query": { - "version": "5.87.4", - "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.87.4.tgz", - "integrity": "sha512-T5GT/1ZaNsUXf5I3RhcYuT17I4CPlbZgyLxc/ZGv7ciS6esytlbjb3DgUFO6c8JWYMDpdjSWInyGZUErgzqhcA==", - "license": "MIT", - "dependencies": { - "@tanstack/query-core": "5.87.4" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - }, - "peerDependencies": { - "react": "^18 || ^19" - } - }, - "node_modules/cookie": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz", - "integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/esbuild": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.0.tgz", - "integrity": "sha512-BXq5mqc8ltbaN34cDqWuYKyNhX8D/Z0J1xdtdQ8UcIIIyJyz+ZMKUt58tF3SrZ85jcfN/PZYhjR5uDQAYNVbuw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.0", - "@esbuild/android-arm": "0.25.0", - "@esbuild/android-arm64": "0.25.0", - "@esbuild/android-x64": "0.25.0", - "@esbuild/darwin-arm64": "0.25.0", - "@esbuild/darwin-x64": "0.25.0", - "@esbuild/freebsd-arm64": "0.25.0", - "@esbuild/freebsd-x64": "0.25.0", - "@esbuild/linux-arm": "0.25.0", - "@esbuild/linux-arm64": "0.25.0", - "@esbuild/linux-ia32": "0.25.0", - "@esbuild/linux-loong64": "0.25.0", - "@esbuild/linux-mips64el": "0.25.0", - "@esbuild/linux-ppc64": "0.25.0", - "@esbuild/linux-riscv64": "0.25.0", - "@esbuild/linux-s390x": "0.25.0", - "@esbuild/linux-x64": "0.25.0", - "@esbuild/netbsd-arm64": "0.25.0", - "@esbuild/netbsd-x64": "0.25.0", - "@esbuild/openbsd-arm64": "0.25.0", - "@esbuild/openbsd-x64": "0.25.0", - "@esbuild/sunos-x64": "0.25.0", - "@esbuild/win32-arm64": "0.25.0", - "@esbuild/win32-ia32": "0.25.0", - "@esbuild/win32-x64": "0.25.0" - } - }, - "node_modules/htm": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/htm/-/htm-3.1.1.tgz", - "integrity": "sha512-983Vyg8NwUE7JkZ6NmOqpCZ+sh1bKv2iYTlUkzlWmA5JD2acKoxd4KVxbMmxX/85mtfdnDmTFoNKcg5DGAvxNQ==", - "license": "Apache-2.0" - }, - "node_modules/react": { - "version": "19.1.0", - "resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz", - "integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-dom": { - "version": "19.1.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz", - "integrity": "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==", - "license": "MIT", - "dependencies": { - "scheduler": "^0.26.0" - }, - "peerDependencies": { - "react": "^19.1.0" - } - }, - "node_modules/react-hook-form": { - "version": "7.62.0", - "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.62.0.tgz", - "integrity": "sha512-7KWFejc98xqG/F4bAxpL41NB3o1nnvQO1RWZT3TqRZYL8RryQETGfEdVnJN2fy1crCiBLLjkRBVK05j24FxJGA==", - "license": "MIT", - "engines": { - "node": ">=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/react-hook-form" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17 || ^18 || ^19" - } - }, - "node_modules/react-router": { - "version": "7.15.1", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.15.1.tgz", - "integrity": "sha512-R8rl9HhgikFYoPJymnUtPXWbnDb3oget6lQnfIoupbt61aT9aOhRkDsY2XRhZRyX1Z/8a5sL74fXmFNm3NRK5A==", - "license": "MIT", - "dependencies": { - "cookie": "^1.0.1", - "set-cookie-parser": "^2.6.0" - }, - "engines": { - "node": ">=20.0.0" - }, - "peerDependencies": { - "react": ">=18", - "react-dom": ">=18" - }, - "peerDependenciesMeta": { - "react-dom": { - "optional": true - } - } - }, - "node_modules/scheduler": { - "version": "0.26.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz", - "integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==", - "license": "MIT" - }, - "node_modules/set-cookie-parser": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.2.tgz", - "integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==", - "license": "MIT" - } - } -} diff --git a/crates/ironclaw_webui_v2/frontend/package.json b/crates/ironclaw_webui_v2/frontend/package.json index 4b93c416729..8d975568f95 100644 --- a/crates/ironclaw_webui_v2/frontend/package.json +++ b/crates/ironclaw_webui_v2/frontend/package.json @@ -3,10 +3,11 @@ "version": "0.0.0", "private": true, "description": "Build tooling for the WebUI v2 SPA. Bundles the local ES modules and the React ecosystem via esbuild. Cargo invokes build.mjs into OUT_DIR for webui-v2-beta builds; ./build.sh writes a local ignored static/dist preview and refreshes committed static/vendor assets.", + "packageManager": "pnpm@11.7.0", "type": "module", "engines": { "node": ">=22 <23", - "npm": ">=10" + "pnpm": ">=11 <12" }, "scripts": { "build": "node build.mjs", diff --git a/crates/ironclaw_webui_v2/frontend/pnpm-lock.yaml b/crates/ironclaw_webui_v2/frontend/pnpm-lock.yaml new file mode 100644 index 00000000000..1c574e824a0 --- /dev/null +++ b/crates/ironclaw_webui_v2/frontend/pnpm-lock.yaml @@ -0,0 +1,374 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + '@tanstack/react-query': + specifier: 5.87.4 + version: 5.87.4(react@19.1.0) + htm: + specifier: 3.1.1 + version: 3.1.1 + react: + specifier: 19.1.0 + version: 19.1.0 + react-dom: + specifier: 19.1.0 + version: 19.1.0(react@19.1.0) + react-hook-form: + specifier: 7.62.0 + version: 7.62.0(react@19.1.0) + react-router: + specifier: 7.15.1 + version: 7.15.1(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + devDependencies: + esbuild: + specifier: 0.25.0 + version: 0.25.0 + +packages: + + '@esbuild/aix-ppc64@0.25.0': + resolution: {integrity: sha512-O7vun9Sf8DFjH2UtqK8Ku3LkquL9SZL8OLY1T5NZkA34+wG3OQF7cl4Ql8vdNzM6fzBbYfLaiRLIOZ+2FOCgBQ==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.25.0': + resolution: {integrity: sha512-grvv8WncGjDSyUBjN9yHXNt+cq0snxXbDxy5pJtzMKGmmpPxeAmAhWxXI+01lU5rwZomDgD3kJwulEnhTRUd6g==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.25.0': + resolution: {integrity: sha512-PTyWCYYiU0+1eJKmw21lWtC+d08JDZPQ5g+kFyxP0V+es6VPPSUhM6zk8iImp2jbV6GwjX4pap0JFbUQN65X1g==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.25.0': + resolution: {integrity: sha512-m/ix7SfKG5buCnxasr52+LI78SQ+wgdENi9CqyCXwjVR2X4Jkz+BpC3le3AoBPYTC9NHklwngVXvbJ9/Akhrfg==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.25.0': + resolution: {integrity: sha512-mVwdUb5SRkPayVadIOI78K7aAnPamoeFR2bT5nszFUZ9P8UpK4ratOdYbZZXYSqPKMHfS1wdHCJk1P1EZpRdvw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.25.0': + resolution: {integrity: sha512-DgDaYsPWFTS4S3nWpFcMn/33ZZwAAeAFKNHNa1QN0rI4pUjgqf0f7ONmXf6d22tqTY+H9FNdgeaAa+YIFUn2Rg==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.25.0': + resolution: {integrity: sha512-VN4ocxy6dxefN1MepBx/iD1dH5K8qNtNe227I0mnTRjry8tj5MRk4zprLEdG8WPyAPb93/e4pSgi1SoHdgOa4w==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.25.0': + resolution: {integrity: sha512-mrSgt7lCh07FY+hDD1TxiTyIHyttn6vnjesnPoVDNmDfOmggTLXRv8Id5fNZey1gl/V2dyVK1VXXqVsQIiAk+A==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.25.0': + resolution: {integrity: sha512-9QAQjTWNDM/Vk2bgBl17yWuZxZNQIF0OUUuPZRKoDtqF2k4EtYbpyiG5/Dk7nqeK6kIJWPYldkOcBqjXjrUlmg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.25.0': + resolution: {integrity: sha512-vkB3IYj2IDo3g9xX7HqhPYxVkNQe8qTK55fraQyTzTX/fxaDtXiEnavv9geOsonh2Fd2RMB+i5cbhu2zMNWJwg==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.25.0': + resolution: {integrity: sha512-43ET5bHbphBegyeqLb7I1eYn2P/JYGNmzzdidq/w0T8E2SsYL1U6un2NFROFRg1JZLTzdCoRomg8Rvf9M6W6Gg==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.25.0': + resolution: {integrity: sha512-fC95c/xyNFueMhClxJmeRIj2yrSMdDfmqJnyOY4ZqsALkDrrKJfIg5NTMSzVBr5YW1jf+l7/cndBfP3MSDpoHw==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.25.0': + resolution: {integrity: sha512-nkAMFju7KDW73T1DdH7glcyIptm95a7Le8irTQNO/qtkoyypZAnjchQgooFUDQhNAy4iu08N79W4T4pMBwhPwQ==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.25.0': + resolution: {integrity: sha512-NhyOejdhRGS8Iwv+KKR2zTq2PpysF9XqY+Zk77vQHqNbo/PwZCzB5/h7VGuREZm1fixhs4Q/qWRSi5zmAiO4Fw==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.25.0': + resolution: {integrity: sha512-5S/rbP5OY+GHLC5qXp1y/Mx//e92L1YDqkiBbO9TQOvuFXM+iDqUNG5XopAnXoRH3FjIUDkeGcY1cgNvnXp/kA==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.25.0': + resolution: {integrity: sha512-XM2BFsEBz0Fw37V0zU4CXfcfuACMrppsMFKdYY2WuTS3yi8O1nFOhil/xhKTmE1nPmVyvQJjJivgDT+xh8pXJA==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.25.0': + resolution: {integrity: sha512-9yl91rHw/cpwMCNytUDxwj2XjFpxML0y9HAOH9pNVQDpQrBxHy01Dx+vaMu0N1CKa/RzBD2hB4u//nfc+Sd3Cw==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-arm64@0.25.0': + resolution: {integrity: sha512-RuG4PSMPFfrkH6UwCAqBzauBWTygTvb1nxWasEJooGSJ/NwRw7b2HOwyRTQIU97Hq37l3npXoZGYMy3b3xYvPw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.25.0': + resolution: {integrity: sha512-jl+qisSB5jk01N5f7sPCsBENCOlPiS/xptD5yxOx2oqQfyourJwIKLRA2yqWdifj3owQZCL2sn6o08dBzZGQzA==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.25.0': + resolution: {integrity: sha512-21sUNbq2r84YE+SJDfaQRvdgznTD8Xc0oc3p3iW/a1EVWeNj/SdUCbm5U0itZPQYRuRTW20fPMWMpcrciH2EJw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.25.0': + resolution: {integrity: sha512-2gwwriSMPcCFRlPlKx3zLQhfN/2WjJ2NSlg5TKLQOJdV0mSxIcYNTMhk3H3ulL/cak+Xj0lY1Ym9ysDV1igceg==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/sunos-x64@0.25.0': + resolution: {integrity: sha512-bxI7ThgLzPrPz484/S9jLlvUAHYMzy6I0XiU1ZMeAEOBcS0VePBFxh1JjTQt3Xiat5b6Oh4x7UC7IwKQKIJRIg==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.25.0': + resolution: {integrity: sha512-ZUAc2YK6JW89xTbXvftxdnYy3m4iHIkDtK3CLce8wg8M2L+YZhIvO1DKpxrd0Yr59AeNNkTiic9YLf6FTtXWMw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.25.0': + resolution: {integrity: sha512-eSNxISBu8XweVEWG31/JzjkIGbGIJN/TrRoiSVZwZ6pkC6VX4Im/WV2cz559/TXLcYbcrDN8JtKgd9DJVIo8GA==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.25.0': + resolution: {integrity: sha512-ZENoHJBxA20C2zFzh6AI4fT6RraMzjYw4xKWemRTRmRVtN9c5DcH9r/f2ihEkMjOW5eGgrwCslG/+Y/3bL+DHQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + + '@tanstack/query-core@5.87.4': + resolution: {integrity: sha512-uNsg6zMxraEPDVO2Bn+F3/ctHi+Zsk+MMpcN8h6P7ozqD088F6mFY5TfGM7zuyIrL7HKpDyu6QHfLWiDxh3cuw==} + + '@tanstack/react-query@5.87.4': + resolution: {integrity: sha512-T5GT/1ZaNsUXf5I3RhcYuT17I4CPlbZgyLxc/ZGv7ciS6esytlbjb3DgUFO6c8JWYMDpdjSWInyGZUErgzqhcA==} + peerDependencies: + react: ^18 || ^19 + + cookie@1.1.1: + resolution: {integrity: sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==} + engines: {node: '>=18'} + + esbuild@0.25.0: + resolution: {integrity: sha512-BXq5mqc8ltbaN34cDqWuYKyNhX8D/Z0J1xdtdQ8UcIIIyJyz+ZMKUt58tF3SrZ85jcfN/PZYhjR5uDQAYNVbuw==} + engines: {node: '>=18'} + hasBin: true + + htm@3.1.1: + resolution: {integrity: sha512-983Vyg8NwUE7JkZ6NmOqpCZ+sh1bKv2iYTlUkzlWmA5JD2acKoxd4KVxbMmxX/85mtfdnDmTFoNKcg5DGAvxNQ==} + + react-dom@19.1.0: + resolution: {integrity: sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==} + peerDependencies: + react: ^19.1.0 + + react-hook-form@7.62.0: + resolution: {integrity: sha512-7KWFejc98xqG/F4bAxpL41NB3o1nnvQO1RWZT3TqRZYL8RryQETGfEdVnJN2fy1crCiBLLjkRBVK05j24FxJGA==} + engines: {node: '>=18.0.0'} + peerDependencies: + react: ^16.8.0 || ^17 || ^18 || ^19 + + react-router@7.15.1: + resolution: {integrity: sha512-R8rl9HhgikFYoPJymnUtPXWbnDb3oget6lQnfIoupbt61aT9aOhRkDsY2XRhZRyX1Z/8a5sL74fXmFNm3NRK5A==} + engines: {node: '>=20.0.0'} + peerDependencies: + react: '>=18' + react-dom: '>=18' + peerDependenciesMeta: + react-dom: + optional: true + + react@19.1.0: + resolution: {integrity: sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==} + engines: {node: '>=0.10.0'} + + scheduler@0.26.0: + resolution: {integrity: sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==} + + set-cookie-parser@2.7.2: + resolution: {integrity: sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==} + +snapshots: + + '@esbuild/aix-ppc64@0.25.0': + optional: true + + '@esbuild/android-arm64@0.25.0': + optional: true + + '@esbuild/android-arm@0.25.0': + optional: true + + '@esbuild/android-x64@0.25.0': + optional: true + + '@esbuild/darwin-arm64@0.25.0': + optional: true + + '@esbuild/darwin-x64@0.25.0': + optional: true + + '@esbuild/freebsd-arm64@0.25.0': + optional: true + + '@esbuild/freebsd-x64@0.25.0': + optional: true + + '@esbuild/linux-arm64@0.25.0': + optional: true + + '@esbuild/linux-arm@0.25.0': + optional: true + + '@esbuild/linux-ia32@0.25.0': + optional: true + + '@esbuild/linux-loong64@0.25.0': + optional: true + + '@esbuild/linux-mips64el@0.25.0': + optional: true + + '@esbuild/linux-ppc64@0.25.0': + optional: true + + '@esbuild/linux-riscv64@0.25.0': + optional: true + + '@esbuild/linux-s390x@0.25.0': + optional: true + + '@esbuild/linux-x64@0.25.0': + optional: true + + '@esbuild/netbsd-arm64@0.25.0': + optional: true + + '@esbuild/netbsd-x64@0.25.0': + optional: true + + '@esbuild/openbsd-arm64@0.25.0': + optional: true + + '@esbuild/openbsd-x64@0.25.0': + optional: true + + '@esbuild/sunos-x64@0.25.0': + optional: true + + '@esbuild/win32-arm64@0.25.0': + optional: true + + '@esbuild/win32-ia32@0.25.0': + optional: true + + '@esbuild/win32-x64@0.25.0': + optional: true + + '@tanstack/query-core@5.87.4': {} + + '@tanstack/react-query@5.87.4(react@19.1.0)': + dependencies: + '@tanstack/query-core': 5.87.4 + react: 19.1.0 + + cookie@1.1.1: {} + + esbuild@0.25.0: + optionalDependencies: + '@esbuild/aix-ppc64': 0.25.0 + '@esbuild/android-arm': 0.25.0 + '@esbuild/android-arm64': 0.25.0 + '@esbuild/android-x64': 0.25.0 + '@esbuild/darwin-arm64': 0.25.0 + '@esbuild/darwin-x64': 0.25.0 + '@esbuild/freebsd-arm64': 0.25.0 + '@esbuild/freebsd-x64': 0.25.0 + '@esbuild/linux-arm': 0.25.0 + '@esbuild/linux-arm64': 0.25.0 + '@esbuild/linux-ia32': 0.25.0 + '@esbuild/linux-loong64': 0.25.0 + '@esbuild/linux-mips64el': 0.25.0 + '@esbuild/linux-ppc64': 0.25.0 + '@esbuild/linux-riscv64': 0.25.0 + '@esbuild/linux-s390x': 0.25.0 + '@esbuild/linux-x64': 0.25.0 + '@esbuild/netbsd-arm64': 0.25.0 + '@esbuild/netbsd-x64': 0.25.0 + '@esbuild/openbsd-arm64': 0.25.0 + '@esbuild/openbsd-x64': 0.25.0 + '@esbuild/sunos-x64': 0.25.0 + '@esbuild/win32-arm64': 0.25.0 + '@esbuild/win32-ia32': 0.25.0 + '@esbuild/win32-x64': 0.25.0 + + htm@3.1.1: {} + + react-dom@19.1.0(react@19.1.0): + dependencies: + react: 19.1.0 + scheduler: 0.26.0 + + react-hook-form@7.62.0(react@19.1.0): + dependencies: + react: 19.1.0 + + react-router@7.15.1(react-dom@19.1.0(react@19.1.0))(react@19.1.0): + dependencies: + cookie: 1.1.1 + react: 19.1.0 + set-cookie-parser: 2.7.2 + optionalDependencies: + react-dom: 19.1.0(react@19.1.0) + + react@19.1.0: {} + + scheduler@0.26.0: {} + + set-cookie-parser@2.7.2: {} diff --git a/crates/ironclaw_webui_v2/frontend/pnpm-workspace.yaml b/crates/ironclaw_webui_v2/frontend/pnpm-workspace.yaml new file mode 100644 index 00000000000..9af1dfcf1fd --- /dev/null +++ b/crates/ironclaw_webui_v2/frontend/pnpm-workspace.yaml @@ -0,0 +1,5 @@ +packages: + - "." + +allowBuilds: + esbuild: true From 7cd1c100f4f6496d1ca22e5f8d2eebbcc28d637b Mon Sep 17 00:00:00 2001 From: BenKurrek Date: Tue, 7 Jul 2026 15:14:43 -0400 Subject: [PATCH 02/12] docs: update WebUI pnpm setup wording --- README.md | 6 +++--- crates/ironclaw_webui_v2/frontend/README.md | 2 +- scripts/dev-setup.sh | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index be497c6a625..49d2327dddf 100644 --- a/README.md +++ b/README.md @@ -231,8 +231,8 @@ cargo run -q -p ironclaw_reborn_cli --bin ironclaw-reborn -- repl --confirm-host ### WebUI service The Reborn WebUI is compiled behind the `webui-v2-beta` Cargo feature. Builds -with this feature require Node.js/npm so Cargo can generate and embed the SPA -bundle. Build or run the binary with that feature to enable the `serve` +with this feature require Node.js 22 with Corepack/pnpm so Cargo can generate +and embed the SPA bundle. Build or run the binary with that feature to enable the `serve` command: ```bash @@ -425,7 +425,7 @@ IronClaw is the AI assistant you can actually trust with your personal and profe - Rust 1.96+ - PostgreSQL 15+ with [pgvector](https://github.com/pgvector/pgvector) extension -- Node.js 22+ (npm) for source builds that enable the `webui-v2-beta` feature +- Node.js 22+ with Corepack/pnpm for source builds that enable the `webui-v2-beta` feature - NEAR AI account (authentication handled via setup wizard) - `libclang` and a working C toolchain if you build the WeChat voice/SILK path from source diff --git a/crates/ironclaw_webui_v2/frontend/README.md b/crates/ironclaw_webui_v2/frontend/README.md index 7b6c03aca5c..13db0e0921c 100644 --- a/crates/ironclaw_webui_v2/frontend/README.md +++ b/crates/ironclaw_webui_v2/frontend/README.md @@ -15,7 +15,7 @@ Run it when you want a local `../static/dist/` preview, or when upgrading a pinned vendored dependency: ```bash -./build.sh # re-vendor CDN assets + npm ci + esbuild bundle +./build.sh # re-vendor CDN assets + pnpm install + esbuild bundle ./build.sh --no-vendor # just re-bundle (skip re-downloading vendored deps) ``` diff --git a/scripts/dev-setup.sh b/scripts/dev-setup.sh index dbd6e81b318..59ec937744d 100755 --- a/scripts/dev-setup.sh +++ b/scripts/dev-setup.sh @@ -10,7 +10,7 @@ # After running, you can: # cargo check # default features (postgres + libsql) # cargo test # default test suite (uses libsql temp DB) -# cargo test --all-features # full test suite (requires Node.js/npm for WebUI bundle) +# cargo test --all-features # full test suite (requires Node.js 22 + Corepack/pnpm for WebUI bundle) set -euo pipefail @@ -84,5 +84,5 @@ echo "" echo "Quick start:" echo " cargo run # Run with default features" echo " cargo test # Test suite (libsql temp DB)" -echo " cargo test --all-features # Full test suite (requires Node.js/npm for WebUI bundle)" -echo " cargo clippy --all-features # Lint all code (requires Node.js/npm for WebUI bundle)" +echo " cargo test --all-features # Full test suite (requires Node.js 22 + Corepack/pnpm for WebUI bundle)" +echo " cargo clippy --all-features # Lint all code (requires Node.js 22 + Corepack/pnpm for WebUI bundle)" From 0b2be7df31595cb1e295156f9c3ff5befa7403bd Mon Sep 17 00:00:00 2001 From: BenKurrek Date: Tue, 7 Jul 2026 17:09:59 -0400 Subject: [PATCH 03/12] test: expect Reborn iteration limit category --- .../e2e/scenarios/test_reborn_webui_v2_legacy_tool_execution.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/e2e/scenarios/test_reborn_webui_v2_legacy_tool_execution.py b/tests/e2e/scenarios/test_reborn_webui_v2_legacy_tool_execution.py index 70d1793a9b3..7290783994e 100644 --- a/tests/e2e/scenarios/test_reborn_webui_v2_legacy_tool_execution.py +++ b/tests/e2e/scenarios/test_reborn_webui_v2_legacy_tool_execution.py @@ -569,5 +569,5 @@ async def test_reborn_legacy_looping_tool_calls_stop_at_low_iteration_boundary( await _wait_for_failed_run_projection(response) ) - assert run_status.get("failure_category") == "driver_protocol_violation", run_status + assert run_status.get("failure_category") == "iteration_limit", run_status assert completed_loop_echoes == 1 From 39222630b9442c6cb2aaf616b714814a3de947f8 Mon Sep 17 00:00:00 2001 From: BenKurrek Date: Tue, 7 Jul 2026 17:30:41 -0400 Subject: [PATCH 04/12] test: use real time for Slack pairing expiry --- tests/integration/slack_pairing_redeem.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/integration/slack_pairing_redeem.rs b/tests/integration/slack_pairing_redeem.rs index 8fa1842299a..d505ff1bee9 100644 --- a/tests/integration/slack_pairing_redeem.rs +++ b/tests/integration/slack_pairing_redeem.rs @@ -192,7 +192,7 @@ async fn slack_pairing_redeem_rejects_unknown_code() { ); } -#[tokio::test(start_paused = true)] +#[tokio::test] async fn slack_pairing_redeem_rejects_expired_code() { let root = tempfile::tempdir().expect("tempdir"); let db_path = root.path().join("slack-host-state.db"); @@ -203,6 +203,7 @@ async fn slack_pairing_redeem_rejects_expired_code() { .issue_challenge(installation_id(), slack_user_id()) .await .expect("issue_challenge must succeed"); + // Pairing expiry is stored as wall-clock `Utc::now()`, so use real time here. tokio::time::sleep(Duration::from_millis(25)).await; let result = service From dc4efa42cd2eef0bfb47b1c0d84cde7fafd19f62 Mon Sep 17 00:00:00 2001 From: BenKurrek Date: Mon, 6 Jul 2026 16:16:11 -0400 Subject: [PATCH 05/12] feat(webui): add vite typescript frontend scaffold --- crates/ironclaw_webui_v2/frontend/README.md | 77 +- crates/ironclaw_webui_v2/frontend/index.html | 52 + .../ironclaw_webui_v2/frontend/package.json | 14 +- .../ironclaw_webui_v2/frontend/pnpm-lock.yaml | 1243 +++++++++++++++-- crates/ironclaw_webui_v2/frontend/src/main.ts | 2 + .../frontend/src/styles/app.css | 23 + .../frontend/src/vite-env.d.ts | 8 + .../ironclaw_webui_v2/frontend/tsconfig.json | 17 + .../ironclaw_webui_v2/frontend/vite.config.ts | 55 + .../static/js/lib/markdown.test.mjs | 1 + 10 files changed, 1344 insertions(+), 148 deletions(-) create mode 100644 crates/ironclaw_webui_v2/frontend/index.html create mode 100644 crates/ironclaw_webui_v2/frontend/src/main.ts create mode 100644 crates/ironclaw_webui_v2/frontend/src/styles/app.css create mode 100644 crates/ironclaw_webui_v2/frontend/src/vite-env.d.ts create mode 100644 crates/ironclaw_webui_v2/frontend/tsconfig.json create mode 100644 crates/ironclaw_webui_v2/frontend/vite.config.ts diff --git a/crates/ironclaw_webui_v2/frontend/README.md b/crates/ironclaw_webui_v2/frontend/README.md index 13db0e0921c..f37e5a1c848 100644 --- a/crates/ironclaw_webui_v2/frontend/README.md +++ b/crates/ironclaw_webui_v2/frontend/README.md @@ -1,51 +1,44 @@ -# WebUI v2 frontend build tooling +# WebUI v2 Frontend -This directory builds the WebUI v2 frontend artifacts that the Rust crate -embeds. When `webui-v2-beta` is enabled, Cargo runs the esbuild bundle step -from `build.rs`, writes the SPA bundle into `OUT_DIR`, and embeds that generated -output as `/v2/dist/*`. The `../static/vendor/` assets remain committed so the -main SPA keeps loading all runtime assets from the same origin. +This directory owns the WebUI v2 frontend toolchain. Use Node 22 with Corepack +enabled; the committed `pnpm-lock.yaml` is the source of truth for dependency +resolution. -## When to run - -You do not need to run this after ordinary `../static/js/**` edits: Cargo -rebuilds the ignored `/v2/dist/*` bundle for WebUI-enabled builds. - -Run it when you want a local `../static/dist/` preview, or when upgrading a -pinned vendored dependency: +## Commands ```bash -./build.sh # re-vendor CDN assets + pnpm install + esbuild bundle -./build.sh --no-vendor # just re-bundle (skip re-downloading vendored deps) +corepack pnpm install --frozen-lockfile +corepack pnpm dev +corepack pnpm typecheck +corepack pnpm test +corepack pnpm build:vite ``` -Then commit only the changed files under `../static/vendor/` when refreshing -vendored dependencies. `../static/dist/` is generated output and is ignored. +At this point in the stack, Cargo still embeds the legacy esbuild bundle from +`build.mjs`, so `corepack pnpm build` and `corepack pnpm build:legacy` both run +that legacy bundle path. `corepack pnpm build:vite` is the Vite production build +for the new scaffold and writes ignored output to `frontend/dist/`. -## What it produces +`./build.sh` is the one-shot local refresh helper. It vendors pinned browser +assets, installs with `corepack pnpm install --frozen-lockfile`, and builds the +legacy bundle used by this branch. -| Output | Made by | Loaded in index.html as | +## Outputs + +| Output | Made by | Commit? | |---|---|---| -| `/v2/dist/app.js` + `/v2/dist/chunks/*` | `build.mjs` (esbuild), run by Cargo into `OUT_DIR` or by `./build.sh` into local `static/dist/` | ` + + + + + +
+ + + diff --git a/crates/ironclaw_webui_v2/frontend/package.json b/crates/ironclaw_webui_v2/frontend/package.json index 8d975568f95..ee69dcc1e06 100644 --- a/crates/ironclaw_webui_v2/frontend/package.json +++ b/crates/ironclaw_webui_v2/frontend/package.json @@ -10,7 +10,12 @@ "pnpm": ">=11 <12" }, "scripts": { + "dev": "vite --host 127.0.0.1", "build": "node build.mjs", + "build:legacy": "node build.mjs", + "build:vite": "vite build", + "typecheck": "tsc --noEmit", + "test": "node --test '../static/js/**/*.test.{js,mjs}' && vitest run --passWithNoTests", "vendor": "bash vendor.sh", "all": "bash build.sh" }, @@ -23,6 +28,13 @@ "react-router": "7.15.1" }, "devDependencies": { - "esbuild": "0.25.0" + "@tailwindcss/vite": "4.3.2", + "@types/node": "26.1.0", + "@vitejs/plugin-react": "6.0.3", + "esbuild": "0.28.0", + "tailwindcss": "4.3.2", + "typescript": "6.0.3", + "vite": "8.1.3", + "vitest": "4.1.9" } } diff --git a/crates/ironclaw_webui_v2/frontend/pnpm-lock.yaml b/crates/ironclaw_webui_v2/frontend/pnpm-lock.yaml index 1c574e824a0..4a2956db4a8 100644 --- a/crates/ironclaw_webui_v2/frontend/pnpm-lock.yaml +++ b/crates/ironclaw_webui_v2/frontend/pnpm-lock.yaml @@ -27,162 +27,418 @@ importers: specifier: 7.15.1 version: 7.15.1(react-dom@19.1.0(react@19.1.0))(react@19.1.0) devDependencies: + '@tailwindcss/vite': + specifier: 4.3.2 + version: 4.3.2(vite@8.1.3(@types/node@26.1.0)(esbuild@0.28.0)(jiti@2.7.0)) + '@types/node': + specifier: 26.1.0 + version: 26.1.0 + '@vitejs/plugin-react': + specifier: 6.0.3 + version: 6.0.3(vite@8.1.3(@types/node@26.1.0)(esbuild@0.28.0)(jiti@2.7.0)) esbuild: - specifier: 0.25.0 - version: 0.25.0 + specifier: 0.28.0 + version: 0.28.0 + tailwindcss: + specifier: 4.3.2 + version: 4.3.2 + typescript: + specifier: 6.0.3 + version: 6.0.3 + vite: + specifier: 8.1.3 + version: 8.1.3(@types/node@26.1.0)(esbuild@0.28.0)(jiti@2.7.0) + vitest: + specifier: 4.1.9 + version: 4.1.9(@types/node@26.1.0)(vite@8.1.3(@types/node@26.1.0)(esbuild@0.28.0)(jiti@2.7.0)) packages: - '@esbuild/aix-ppc64@0.25.0': - resolution: {integrity: sha512-O7vun9Sf8DFjH2UtqK8Ku3LkquL9SZL8OLY1T5NZkA34+wG3OQF7cl4Ql8vdNzM6fzBbYfLaiRLIOZ+2FOCgBQ==} + '@emnapi/core@1.11.1': + resolution: {integrity: sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ==} + + '@emnapi/runtime@1.11.1': + resolution: {integrity: sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==} + + '@emnapi/wasi-threads@1.2.2': + resolution: {integrity: sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==} + + '@esbuild/aix-ppc64@0.28.0': + resolution: {integrity: sha512-lhRUCeuOyJQURhTxl4WkpFTjIsbDayJHih5kZC1giwE+MhIzAb7mEsQMqMf18rHLsrb5qI1tafG20mLxEWcWlA==} engines: {node: '>=18'} cpu: [ppc64] os: [aix] - '@esbuild/android-arm64@0.25.0': - resolution: {integrity: sha512-grvv8WncGjDSyUBjN9yHXNt+cq0snxXbDxy5pJtzMKGmmpPxeAmAhWxXI+01lU5rwZomDgD3kJwulEnhTRUd6g==} + '@esbuild/android-arm64@0.28.0': + resolution: {integrity: sha512-+WzIXQOSaGs33tLEgYPYe/yQHf0WTU0X42Jca3y8NWMbUVhp7rUnw+vAsRC/QiDrdD31IszMrZy+qwPOPjd+rw==} engines: {node: '>=18'} cpu: [arm64] os: [android] - '@esbuild/android-arm@0.25.0': - resolution: {integrity: sha512-PTyWCYYiU0+1eJKmw21lWtC+d08JDZPQ5g+kFyxP0V+es6VPPSUhM6zk8iImp2jbV6GwjX4pap0JFbUQN65X1g==} + '@esbuild/android-arm@0.28.0': + resolution: {integrity: sha512-wqh0ByljabXLKHeWXYLqoJ5jKC4XBaw6Hk08OfMrCRd2nP2ZQ5eleDZC41XHyCNgktBGYMbqnrJKq/K/lzPMSQ==} engines: {node: '>=18'} cpu: [arm] os: [android] - '@esbuild/android-x64@0.25.0': - resolution: {integrity: sha512-m/ix7SfKG5buCnxasr52+LI78SQ+wgdENi9CqyCXwjVR2X4Jkz+BpC3le3AoBPYTC9NHklwngVXvbJ9/Akhrfg==} + '@esbuild/android-x64@0.28.0': + resolution: {integrity: sha512-+VJggoaKhk2VNNqVL7f6S189UzShHC/mR9EE8rDdSkdpN0KflSwWY/gWjDrNxxisg8Fp1ZCD9jLMo4m0OUfeUA==} engines: {node: '>=18'} cpu: [x64] os: [android] - '@esbuild/darwin-arm64@0.25.0': - resolution: {integrity: sha512-mVwdUb5SRkPayVadIOI78K7aAnPamoeFR2bT5nszFUZ9P8UpK4ratOdYbZZXYSqPKMHfS1wdHCJk1P1EZpRdvw==} + '@esbuild/darwin-arm64@0.28.0': + resolution: {integrity: sha512-0T+A9WZm+bZ84nZBtk1ckYsOvyA3x7e2Acj1KdVfV4/2tdG4fzUp91YHx+GArWLtwqp77pBXVCPn2We7Letr0Q==} engines: {node: '>=18'} cpu: [arm64] os: [darwin] - '@esbuild/darwin-x64@0.25.0': - resolution: {integrity: sha512-DgDaYsPWFTS4S3nWpFcMn/33ZZwAAeAFKNHNa1QN0rI4pUjgqf0f7ONmXf6d22tqTY+H9FNdgeaAa+YIFUn2Rg==} + '@esbuild/darwin-x64@0.28.0': + resolution: {integrity: sha512-fyzLm/DLDl/84OCfp2f/XQ4flmORsjU7VKt8HLjvIXChJoFFOIL6pLJPH4Yhd1n1gGFF9mPwtlN5Wf82DZs+LQ==} engines: {node: '>=18'} cpu: [x64] os: [darwin] - '@esbuild/freebsd-arm64@0.25.0': - resolution: {integrity: sha512-VN4ocxy6dxefN1MepBx/iD1dH5K8qNtNe227I0mnTRjry8tj5MRk4zprLEdG8WPyAPb93/e4pSgi1SoHdgOa4w==} + '@esbuild/freebsd-arm64@0.28.0': + resolution: {integrity: sha512-l9GeW5UZBT9k9brBYI+0WDffcRxgHQD8ShN2Ur4xWq/NFzUKm3k5lsH4PdaRgb2w7mI9u61nr2gI2mLI27Nh3Q==} engines: {node: '>=18'} cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-x64@0.25.0': - resolution: {integrity: sha512-mrSgt7lCh07FY+hDD1TxiTyIHyttn6vnjesnPoVDNmDfOmggTLXRv8Id5fNZey1gl/V2dyVK1VXXqVsQIiAk+A==} + '@esbuild/freebsd-x64@0.28.0': + resolution: {integrity: sha512-BXoQai/A0wPO6Es3yFJ7APCiKGc1tdAEOgeTNy3SsB491S3aHn4S4r3e976eUnPdU+NbdtmBuLncYir2tMU9Nw==} engines: {node: '>=18'} cpu: [x64] os: [freebsd] - '@esbuild/linux-arm64@0.25.0': - resolution: {integrity: sha512-9QAQjTWNDM/Vk2bgBl17yWuZxZNQIF0OUUuPZRKoDtqF2k4EtYbpyiG5/Dk7nqeK6kIJWPYldkOcBqjXjrUlmg==} + '@esbuild/linux-arm64@0.28.0': + resolution: {integrity: sha512-RVyzfb3FWsGA55n6WY0MEIEPURL1FcbhFE6BffZEMEekfCzCIMtB5yyDcFnVbTnwk+CLAgTujmV/Lgvih56W+A==} engines: {node: '>=18'} cpu: [arm64] os: [linux] - '@esbuild/linux-arm@0.25.0': - resolution: {integrity: sha512-vkB3IYj2IDo3g9xX7HqhPYxVkNQe8qTK55fraQyTzTX/fxaDtXiEnavv9geOsonh2Fd2RMB+i5cbhu2zMNWJwg==} + '@esbuild/linux-arm@0.28.0': + resolution: {integrity: sha512-CjaaREJagqJp7iTaNQjjidaNbCKYcd4IDkzbwwxtSvjI7NZm79qiHc8HqciMddQ6CKvJT6aBd8lO9kN/ZudLlw==} engines: {node: '>=18'} cpu: [arm] os: [linux] - '@esbuild/linux-ia32@0.25.0': - resolution: {integrity: sha512-43ET5bHbphBegyeqLb7I1eYn2P/JYGNmzzdidq/w0T8E2SsYL1U6un2NFROFRg1JZLTzdCoRomg8Rvf9M6W6Gg==} + '@esbuild/linux-ia32@0.28.0': + resolution: {integrity: sha512-KBnSTt1kxl9x70q+ydterVdl+Cn0H18ngRMRCEQfrbqdUuntQQ0LoMZv47uB97NljZFzY6HcfqEZ2SAyIUTQBQ==} engines: {node: '>=18'} cpu: [ia32] os: [linux] - '@esbuild/linux-loong64@0.25.0': - resolution: {integrity: sha512-fC95c/xyNFueMhClxJmeRIj2yrSMdDfmqJnyOY4ZqsALkDrrKJfIg5NTMSzVBr5YW1jf+l7/cndBfP3MSDpoHw==} + '@esbuild/linux-loong64@0.28.0': + resolution: {integrity: sha512-zpSlUce1mnxzgBADvxKXX5sl8aYQHo2ezvMNI8I0lbblJtp8V4odlm3Yzlj7gPyt3T8ReksE6bK+pT3WD+aJRg==} engines: {node: '>=18'} cpu: [loong64] os: [linux] - '@esbuild/linux-mips64el@0.25.0': - resolution: {integrity: sha512-nkAMFju7KDW73T1DdH7glcyIptm95a7Le8irTQNO/qtkoyypZAnjchQgooFUDQhNAy4iu08N79W4T4pMBwhPwQ==} + '@esbuild/linux-mips64el@0.28.0': + resolution: {integrity: sha512-2jIfP6mmjkdmeTlsX/9vmdmhBmKADrWqN7zcdtHIeNSCH1SqIoNI63cYsjQR8J+wGa4Y5izRcSHSm8K3QWmk3w==} engines: {node: '>=18'} cpu: [mips64el] os: [linux] - '@esbuild/linux-ppc64@0.25.0': - resolution: {integrity: sha512-NhyOejdhRGS8Iwv+KKR2zTq2PpysF9XqY+Zk77vQHqNbo/PwZCzB5/h7VGuREZm1fixhs4Q/qWRSi5zmAiO4Fw==} + '@esbuild/linux-ppc64@0.28.0': + resolution: {integrity: sha512-bc0FE9wWeC0WBm49IQMPSPILRocGTQt3j5KPCA8os6VprfuJ7KD+5PzESSrJ6GmPIPJK965ZJHTUlSA6GNYEhg==} engines: {node: '>=18'} cpu: [ppc64] os: [linux] - '@esbuild/linux-riscv64@0.25.0': - resolution: {integrity: sha512-5S/rbP5OY+GHLC5qXp1y/Mx//e92L1YDqkiBbO9TQOvuFXM+iDqUNG5XopAnXoRH3FjIUDkeGcY1cgNvnXp/kA==} + '@esbuild/linux-riscv64@0.28.0': + resolution: {integrity: sha512-SQPZOwoTTT/HXFXQJG/vBX8sOFagGqvZyXcgLA3NhIqcBv1BJU1d46c0rGcrij2B56Z2rNiSLaZOYW5cUk7yLQ==} engines: {node: '>=18'} cpu: [riscv64] os: [linux] - '@esbuild/linux-s390x@0.25.0': - resolution: {integrity: sha512-XM2BFsEBz0Fw37V0zU4CXfcfuACMrppsMFKdYY2WuTS3yi8O1nFOhil/xhKTmE1nPmVyvQJjJivgDT+xh8pXJA==} + '@esbuild/linux-s390x@0.28.0': + resolution: {integrity: sha512-SCfR0HN8CEEjnYnySJTd2cw0k9OHB/YFzt5zgJEwa+wL/T/raGWYMBqwDNAC6dqFKmJYZoQBRfHjgwLHGSrn3Q==} engines: {node: '>=18'} cpu: [s390x] os: [linux] - '@esbuild/linux-x64@0.25.0': - resolution: {integrity: sha512-9yl91rHw/cpwMCNytUDxwj2XjFpxML0y9HAOH9pNVQDpQrBxHy01Dx+vaMu0N1CKa/RzBD2hB4u//nfc+Sd3Cw==} + '@esbuild/linux-x64@0.28.0': + resolution: {integrity: sha512-us0dSb9iFxIi8srnpl931Nvs65it/Jd2a2K3qs7fz2WfGPHqzfzZTfec7oxZJRNPXPnNYZtanmRc4AL/JwVzHQ==} engines: {node: '>=18'} cpu: [x64] os: [linux] - '@esbuild/netbsd-arm64@0.25.0': - resolution: {integrity: sha512-RuG4PSMPFfrkH6UwCAqBzauBWTygTvb1nxWasEJooGSJ/NwRw7b2HOwyRTQIU97Hq37l3npXoZGYMy3b3xYvPw==} + '@esbuild/netbsd-arm64@0.28.0': + resolution: {integrity: sha512-CR/RYotgtCKwtftMwJlUU7xCVNg3lMYZ0RzTmAHSfLCXw3NtZtNpswLEj/Kkf6kEL3Gw+BpOekRX0BYCtklhUw==} engines: {node: '>=18'} cpu: [arm64] os: [netbsd] - '@esbuild/netbsd-x64@0.25.0': - resolution: {integrity: sha512-jl+qisSB5jk01N5f7sPCsBENCOlPiS/xptD5yxOx2oqQfyourJwIKLRA2yqWdifj3owQZCL2sn6o08dBzZGQzA==} + '@esbuild/netbsd-x64@0.28.0': + resolution: {integrity: sha512-nU1yhmYutL+fQ71Kxnhg8uEOdC0pwEW9entHykTgEbna2pw2dkbFSMeqjjyHZoCmt8SBkOSvV+yNmm94aUrrqw==} engines: {node: '>=18'} cpu: [x64] os: [netbsd] - '@esbuild/openbsd-arm64@0.25.0': - resolution: {integrity: sha512-21sUNbq2r84YE+SJDfaQRvdgznTD8Xc0oc3p3iW/a1EVWeNj/SdUCbm5U0itZPQYRuRTW20fPMWMpcrciH2EJw==} + '@esbuild/openbsd-arm64@0.28.0': + resolution: {integrity: sha512-cXb5vApOsRsxsEl4mcZ1XY3D4DzcoMxR/nnc4IyqYs0rTI8ZKmW6kyyg+11Z8yvgMfAEldKzP7AdP64HnSC/6g==} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] - '@esbuild/openbsd-x64@0.25.0': - resolution: {integrity: sha512-2gwwriSMPcCFRlPlKx3zLQhfN/2WjJ2NSlg5TKLQOJdV0mSxIcYNTMhk3H3ulL/cak+Xj0lY1Ym9ysDV1igceg==} + '@esbuild/openbsd-x64@0.28.0': + resolution: {integrity: sha512-8wZM2qqtv9UP3mzy7HiGYNH/zjTA355mpeuA+859TyR+e+Tc08IHYpLJuMsfpDJwoLo1ikIJI8jC3GFjnRClzA==} engines: {node: '>=18'} cpu: [x64] os: [openbsd] - '@esbuild/sunos-x64@0.25.0': - resolution: {integrity: sha512-bxI7ThgLzPrPz484/S9jLlvUAHYMzy6I0XiU1ZMeAEOBcS0VePBFxh1JjTQt3Xiat5b6Oh4x7UC7IwKQKIJRIg==} + '@esbuild/openharmony-arm64@0.28.0': + resolution: {integrity: sha512-FLGfyizszcef5C3YtoyQDACyg95+dndv79i2EekILBofh5wpCa1KuBqOWKrEHZg3zrL3t5ouE5jgr94vA+Wb2w==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + + '@esbuild/sunos-x64@0.28.0': + resolution: {integrity: sha512-1ZgjUoEdHZZl/YlV76TSCz9Hqj9h9YmMGAgAPYd+q4SicWNX3G5GCyx9uhQWSLcbvPW8Ni7lj4gDa1T40akdlw==} engines: {node: '>=18'} cpu: [x64] os: [sunos] - '@esbuild/win32-arm64@0.25.0': - resolution: {integrity: sha512-ZUAc2YK6JW89xTbXvftxdnYy3m4iHIkDtK3CLce8wg8M2L+YZhIvO1DKpxrd0Yr59AeNNkTiic9YLf6FTtXWMw==} + '@esbuild/win32-arm64@0.28.0': + resolution: {integrity: sha512-Q9StnDmQ/enxnpxCCLSg0oo4+34B9TdXpuyPeTedN/6+iXBJ4J+zwfQI28u/Jl40nOYAxGoNi7mFP40RUtkmUA==} engines: {node: '>=18'} cpu: [arm64] os: [win32] - '@esbuild/win32-ia32@0.25.0': - resolution: {integrity: sha512-eSNxISBu8XweVEWG31/JzjkIGbGIJN/TrRoiSVZwZ6pkC6VX4Im/WV2cz559/TXLcYbcrDN8JtKgd9DJVIo8GA==} + '@esbuild/win32-ia32@0.28.0': + resolution: {integrity: sha512-zF3ag/gfiCe6U2iczcRzSYJKH1DCI+ByzSENHlM2FcDbEeo5Zd2C86Aq0tKUYAJJ1obRP84ymxIAksZUcdztHA==} engines: {node: '>=18'} cpu: [ia32] os: [win32] - '@esbuild/win32-x64@0.25.0': - resolution: {integrity: sha512-ZENoHJBxA20C2zFzh6AI4fT6RraMzjYw4xKWemRTRmRVtN9c5DcH9r/f2ihEkMjOW5eGgrwCslG/+Y/3bL+DHQ==} + '@esbuild/win32-x64@0.28.0': + resolution: {integrity: sha512-pEl1bO9mfAmIC+tW5btTmrKaujg3zGtUmWNdCw/xs70FBjwAL3o9OEKNHvNmnyylD6ubxUERiEhdsL0xBQ9efw==} engines: {node: '>=18'} cpu: [x64] os: [win32] + '@jridgewell/gen-mapping@0.3.13': + resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} + + '@jridgewell/remapping@2.3.5': + resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/sourcemap-codec@1.5.5': + resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} + + '@jridgewell/trace-mapping@0.3.31': + resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + + '@napi-rs/wasm-runtime@1.1.6': + resolution: {integrity: sha512-ZLv/JdUfkvOy9eCnnBaGfiO+XimbjebAeO+MRQqD/B+FR1tnRN0tpKSJHRbE8sFfS6aqsXZ67TQjfwfsxULVbg==} + peerDependencies: + '@emnapi/core': ^1.7.1 + '@emnapi/runtime': ^1.7.1 + + '@oxc-project/types@0.138.0': + resolution: {integrity: sha512-1a7ZKmrRTCoN1XMZ4L0PyyqrMnrNlLyPuOkdSX2MZg7IiIGRUyurNhAm73ptDOraoBcIordsIGKNPKUzy3ZmfA==} + + '@rolldown/binding-android-arm64@1.1.4': + resolution: {integrity: sha512-EZLpf/8y7GXkkra90ML47kzik/GMP3EMcE9bPyHmRfxLC6z9+aW5A8poCsoxjrT5GfEcNAAvWwUHjvP1pUQkfw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + + '@rolldown/binding-darwin-arm64@1.1.4': + resolution: {integrity: sha512-aUi+HBvmYb7j8krl1+qJgkG8C17fO79gk3c+jPw4S8glRFc1DTija9S3EyaTSQUm5GJXYKDAsugBEhFHH2vYiQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + + '@rolldown/binding-darwin-x64@1.1.4': + resolution: {integrity: sha512-F7hHC3gwY11+vByKPRWqwGbeXWVgKmL+pTGCinaEhdihzBV2aQ0fvZOch9cXYUOKuKKq429HeYXOqQLc7wFCEg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + + '@rolldown/binding-freebsd-x64@1.1.4': + resolution: {integrity: sha512-sI5yw+7s92SK6odiEhD5lKCBlWcpjHS5qyqpVQbZAJ0fIzEUXrmbl3DH2ybR3PZogulNJF+COLtmA8hUfvkCCQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + + '@rolldown/binding-linux-arm-gnueabihf@1.1.4': + resolution: {integrity: sha512-mCi0OKgEieFircrtVYmQAFGszRtMnZ6fpZAXrxanXAu7lqZcsK1E1RAaZNG0uKAnxox3B1f4EyQNnoyMfN1vAA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@rolldown/binding-linux-arm64-gnu@1.1.4': + resolution: {integrity: sha512-B9Ial3Kv5sh0SHnB1g/QWcUQCEvCF6QKGAl4zXypYj65mVI+B4AhFBwPtSN7pDrJeIx8Z7zdy4ntx+wQABom7w==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-arm64-musl@1.1.4': + resolution: {integrity: sha512-lZVym0PuHE1KZ22gmFTC15lAkrg9iTszR617oYRB/iPY1A56ywoJzVKOJBKaot5RiikCObmur6pogpse3gRcng==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@rolldown/binding-linux-ppc64-gnu@1.1.4': + resolution: {integrity: sha512-t2DNiLJWNTbnEHyUzTumldML6ET4/g16467LZoDDJ3tSxGvguL5/NyC2lCsNKuyRycg9XeDQF5SSv+TNOhQEXg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-s390x-gnu@1.1.4': + resolution: {integrity: sha512-0WIRnL1Uw4BvTZRLQt+PVgo6ZKTJadlC2btP+/EOXv2f/DWbY0rEgl+y834mIVwP1FkTlWVTrGGJXf12lru7EQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-x64-gnu@1.1.4': + resolution: {integrity: sha512-JWtGshGfX+oENAKonoNkqEJX+7hC8yfhi9GUyPX1VX4mdh1y5r+ZiJLR5XzAB0aoP6s/PcILsGjKq8O0mm24bw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-x64-musl@1.1.4': + resolution: {integrity: sha512-rT6yQcxUuXs4CnbofqwHRRV0iem349rLMYpTjkgQGLjrY4ado/eDzwPZPTCgTOlF6Nkp8NEv70yLMTn6qkWxsQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [musl] + + '@rolldown/binding-openharmony-arm64@1.1.4': + resolution: {integrity: sha512-KXMGoboq5cyaCQjDA4GLuRiOwBQ0EyFnJoVViLeZ45/3rFItRODEr+NdsBcVpll40hhNArlm/speWGRvj08LzA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + + '@rolldown/binding-wasm32-wasi@1.1.4': + resolution: {integrity: sha512-5K83rb36oJiY7BCyE9zLZtGcPV4g5wvq+xwdO0XPIwDVZI8cyB/AUjkNXGb92/rnmezEkjMOpgY61rtwjQtFwg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [wasm32] + + '@rolldown/binding-win32-arm64-msvc@1.1.4': + resolution: {integrity: sha512-PnWBtw3TV5KOg69HQQDR0mnQuyCmSGR2pAB4DC1rPF808fgKeTUMj2EOEyKATpgiuxuR5APQmiDO7PDgEjTFSA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + + '@rolldown/binding-win32-x64-msvc@1.1.4': + resolution: {integrity: sha512-M1lpniBePobTfsa7Ks9a199e1akxsXn+GYBUKsEzv3YFzOm1HJAMNwKI3qr0Zq+mxwx9gOZoTdP1yXRYsZUocQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + + '@rolldown/pluginutils@1.0.1': + resolution: {integrity: sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==} + + '@standard-schema/spec@1.1.0': + resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} + + '@tailwindcss/node@4.3.2': + resolution: {integrity: sha512-yWP/sqEcBLaD8JuA6zNwxoYKr75qxTioYwlRwekj5Jr/I5GXnoJfjetH/psLUIv74cYTH2lBUEzBkinthoYcBg==} + + '@tailwindcss/oxide-android-arm64@4.3.2': + resolution: {integrity: sha512-WHxqIuHpvZ5VtdX6GTl1Ik/Vp2YuN42Et+0CdeaVd/frQ9jAvGmvR8vLT+jk3e8/Q3x8kECB9+R17pgpp2BulA==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [android] + + '@tailwindcss/oxide-darwin-arm64@4.3.2': + resolution: {integrity: sha512-GZypeUY/IDJW3877KeM+O67vbXr3MBnbtEL4aYhNErv/JWZhye2vGSWWG9tB6iiqR2MqRNkY8IOUy4NdSZV26w==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [darwin] + + '@tailwindcss/oxide-darwin-x64@4.3.2': + resolution: {integrity: sha512-UIIzmefR6KO1sDU7MzRqAxC8iBpft/VhkGjTjnhoS6k7Z3rQ9wEgA1ODSiyH/tcSYssulNm4Ci3hOeK1jH7ccQ==} + engines: {node: '>= 20'} + cpu: [x64] + os: [darwin] + + '@tailwindcss/oxide-freebsd-x64@4.3.2': + resolution: {integrity: sha512-GN+uAmcI6DNspnCDwtOAZrTz6oukJnp337qZvxqCGLd3BHBzJpO0ZbTLRvJNdztOeAmTzewewGIMPb0tk2R4WA==} + engines: {node: '>= 20'} + cpu: [x64] + os: [freebsd] + + '@tailwindcss/oxide-linux-arm-gnueabihf@4.3.2': + resolution: {integrity: sha512-4ABn7qSbdHRwTiDiuWNegCyb5+2FJ4vKIKc3DmKrvAFw7MU1Lm11dIkTPwUaFdTzc7IsOpDbqBrlh0x6y36U/w==} + engines: {node: '>= 20'} + cpu: [arm] + os: [linux] + + '@tailwindcss/oxide-linux-arm64-gnu@4.3.2': + resolution: {integrity: sha512-wDgEIGwoM8w8pufh9LVt1PahDgNdKXrLC2qfAnV3vAmococ9RWbxeAw4pxPttd/TsJfwjyLf90Dg1y9y8I6Emw==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@tailwindcss/oxide-linux-arm64-musl@4.3.2': + resolution: {integrity: sha512-J5Nuk0uZQIiMTJj3LEx4sAA9tMFUoXQZFv1J6An+QGYe53HKRJuFDi0rpq/tuouCZeAbOBY3kQ6g8qeD4TUjtA==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@tailwindcss/oxide-linux-x64-gnu@4.3.2': + resolution: {integrity: sha512-kqCZpSKOBEJO4mz7OqWoofBZeXTAwaVGPj0ErAj7CojmhKpWVWVOnrt9dE8odoIraZq4oj3ausM37kXi+Tow8w==} + engines: {node: '>= 20'} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@tailwindcss/oxide-linux-x64-musl@4.3.2': + resolution: {integrity: sha512-cixpqbh2toJDmkuCRI68nXA8ZxNmdK9Y+9v5h3MC3ZQKy/0BO8AWzlkWyRM7JAFSGBlfig4YVTPsK6MVgqz1uw==} + engines: {node: '>= 20'} + cpu: [x64] + os: [linux] + libc: [musl] + + '@tailwindcss/oxide-wasm32-wasi@4.3.2': + resolution: {integrity: sha512-4ec2Z/LOmRsAgU23CS4xeJfcJlmRg94A/XrbGRCF1gyU/zdDfRLYDVsS+ynSZCmGNxQ1jQriQOKMQeQxBA3Isw==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + bundledDependencies: + - '@napi-rs/wasm-runtime' + - '@emnapi/core' + - '@emnapi/runtime' + - '@tybys/wasm-util' + - '@emnapi/wasi-threads' + - tslib + + '@tailwindcss/oxide-win32-arm64-msvc@4.3.2': + resolution: {integrity: sha512-Zyr/M0+XcYZu3bZrUytc7TXvrk0ftWfl8gN2MwekNDzhqhKRUucMPSeOzM0o0wH5AWOU49BsKRrfKxI2atCPMQ==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [win32] + + '@tailwindcss/oxide-win32-x64-msvc@4.3.2': + resolution: {integrity: sha512-QI9BO7KlNZsp2GuO0jwAAj5jCDABOKXRkCk2XuKTSaNEFSdfzqswYVTtCHBNKHLsqyjFyFkqlDiwkNbTYSssMQ==} + engines: {node: '>= 20'} + cpu: [x64] + os: [win32] + + '@tailwindcss/oxide@4.3.2': + resolution: {integrity: sha512-z8ZgnzX8gdNoWLBLqBPoh/sjnxkwvf9ZuWjnO0l0yIzbLa5/9S+eC5QxGZKRobVHIC3/1BoMWjHblqWjcgFgag==} + engines: {node: '>= 20'} + + '@tailwindcss/vite@4.3.2': + resolution: {integrity: sha512-eHpMeX4JXfVNJDEcsouTeCBubJBTcTLigeaw/NTUW6PB5ATKKXdyonnXgTBX2VuRbjz1hjfz6C5XAhr52ImQXA==} + peerDependencies: + vite: ^5.2.0 || ^6 || ^7 || ^8 + '@tanstack/query-core@5.87.4': resolution: {integrity: sha512-uNsg6zMxraEPDVO2Bn+F3/ctHi+Zsk+MMpcN8h6P7ozqD088F6mFY5TfGM7zuyIrL7HKpDyu6QHfLWiDxh3cuw==} @@ -191,18 +447,225 @@ packages: peerDependencies: react: ^18 || ^19 + '@tybys/wasm-util@0.10.3': + resolution: {integrity: sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==} + + '@types/chai@5.2.3': + resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} + + '@types/deep-eql@4.0.2': + resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} + + '@types/estree@1.0.9': + resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==} + + '@types/node@26.1.0': + resolution: {integrity: sha512-O0A1G3xPGy4w7AgQdAQYUlQ+BKk2Oovw8eRpofyp5KdBZULnbe+WqaOVNrm705SHphCiG4XHsACrSmPu1f+Kgw==} + + '@vitejs/plugin-react@6.0.3': + resolution: {integrity: sha512-vmFvco5/QuC2f9Oj+wTk0+9XeDFkHxSamwZKYc7MxYwKICfvUvlMhqKI0VuICPltGqh1neqBKDvO4kes1ya8vg==} + engines: {node: ^20.19.0 || >=22.12.0} + peerDependencies: + '@rolldown/plugin-babel': ^0.1.7 || ^0.2.0 + babel-plugin-react-compiler: ^1.0.0 + vite: ^8.0.0 + peerDependenciesMeta: + '@rolldown/plugin-babel': + optional: true + babel-plugin-react-compiler: + optional: true + + '@vitest/expect@4.1.9': + resolution: {integrity: sha512-vl/rYsUKcBr3SnQn166+XR5ZQcgMx3DQhFWdfli/cWpLnLUmbxZvyrJZotLFUryib+LtArYMSTJ5RbQ57ZqrlA==} + + '@vitest/mocker@4.1.9': + resolution: {integrity: sha512-EVkXzBjrPGM+cK8/ANWgBrkUCfJfb38/EfTSO8h7pWvKkyPkpWxvR7BkD2MyItMF62C97zAEoqdpUixwR/e+Rw==} + peerDependencies: + msw: ^2.4.9 + vite: ^6.0.0 || ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true + + '@vitest/pretty-format@4.1.9': + resolution: {integrity: sha512-s0iufns3iIFitdgm+YR7g1whCAaGtXz459VS9/PqyKDEEFgYIhsHOQmXgIgDuYCt7DeQmiZT0Qe2OA2p4ZPu5A==} + + '@vitest/runner@4.1.9': + resolution: {integrity: sha512-KXLMDtc7oe70+3mJfGrPUWPesswH+3sTxAMAMl8DG7I8IUQT4XW718dY5ID3vPUcmlu27CcKfY4P3h3I29SLJg==} + + '@vitest/snapshot@4.1.9': + resolution: {integrity: sha512-Jc7RKGNBo8Z28WYIm0Niej4xdSPByRf6mU58VpHQkd6Zh05rlnA+twjbK5HyeIGHxrzsc3mJgS43uM0CZKzaIA==} + + '@vitest/spy@4.1.9': + resolution: {integrity: sha512-fHpsS6mIi+PiEW+vcRVOMkX1oSaPKne3VOclSFICPcGOmfKgXPU5iAah+wcNcj2xPrCCmfq99IDGf+EojhhvhA==} + + '@vitest/utils@4.1.9': + resolution: {integrity: sha512-A51o8ymO5PpqlWNnBP9ZHPXDIpuMtTLlGSjN7la4US+LJzoUMyhwjA5QXlm39JexgwHKW4Xjs8Z2d3dLCXOeuA==} + + assertion-error@2.0.1: + resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} + engines: {node: '>=12'} + + chai@6.2.2: + resolution: {integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==} + engines: {node: '>=18'} + + convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + cookie@1.1.1: resolution: {integrity: sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==} engines: {node: '>=18'} - esbuild@0.25.0: - resolution: {integrity: sha512-BXq5mqc8ltbaN34cDqWuYKyNhX8D/Z0J1xdtdQ8UcIIIyJyz+ZMKUt58tF3SrZ85jcfN/PZYhjR5uDQAYNVbuw==} + detect-libc@2.1.2: + resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} + engines: {node: '>=8'} + + enhanced-resolve@5.21.6: + resolution: {integrity: sha512-aNnGCvbJ/RIyWo1IuhNdVjnNF+EjH9wpzpNHt+ci/m9He9LJvUN8wrCcXjp9cWsGNAuvSpVFTx/vraAFQ8qGjQ==} + engines: {node: '>=10.13.0'} + + es-module-lexer@2.3.0: + resolution: {integrity: sha512-KLdwQm2NvGLDkQDCGvmiQrhkd0JbMzXthwQAUgWjQuQdBLFa3eiBP5arXZyA+f8x+x7OXgud6bq2rxjGtHV2tw==} + + esbuild@0.28.0: + resolution: {integrity: sha512-sNR9MHpXSUV/XB4zmsFKN+QgVG82Cc7+/aaxJ8Adi8hyOac+EXptIp45QBPaVyX3N70664wRbTcLTOemCAnyqw==} engines: {node: '>=18'} hasBin: true + estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + + expect-type@1.4.0: + resolution: {integrity: sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==} + engines: {node: '>=12.0.0'} + + fdir@6.5.0: + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + htm@3.1.1: resolution: {integrity: sha512-983Vyg8NwUE7JkZ6NmOqpCZ+sh1bKv2iYTlUkzlWmA5JD2acKoxd4KVxbMmxX/85mtfdnDmTFoNKcg5DGAvxNQ==} + jiti@2.7.0: + resolution: {integrity: sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==} + hasBin: true + + lightningcss-android-arm64@1.32.0: + resolution: {integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [android] + + lightningcss-darwin-arm64@1.32.0: + resolution: {integrity: sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [darwin] + + lightningcss-darwin-x64@1.32.0: + resolution: {integrity: sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [darwin] + + lightningcss-freebsd-x64@1.32.0: + resolution: {integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [freebsd] + + lightningcss-linux-arm-gnueabihf@1.32.0: + resolution: {integrity: sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==} + engines: {node: '>= 12.0.0'} + cpu: [arm] + os: [linux] + + lightningcss-linux-arm64-gnu@1.32.0: + resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + libc: [glibc] + + lightningcss-linux-arm64-musl@1.32.0: + resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + libc: [musl] + + lightningcss-linux-x64-gnu@1.32.0: + resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + libc: [glibc] + + lightningcss-linux-x64-musl@1.32.0: + resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + libc: [musl] + + lightningcss-win32-arm64-msvc@1.32.0: + resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [win32] + + lightningcss-win32-x64-msvc@1.32.0: + resolution: {integrity: sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [win32] + + lightningcss@1.32.0: + resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==} + engines: {node: '>= 12.0.0'} + + magic-string@0.30.21: + resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + + nanoid@3.3.15: + resolution: {integrity: sha512-y7Wygv/7mEOvxTuEQDB8StXdMRBWf1kR/tlhAzBRUFkB2jfcLOAxO/SHmOO2zgz1pVgK29/kyupn059/bCHdjA==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + obug@2.1.3: + resolution: {integrity: sha512-9miFgM2OFba7hB+pRgvtV84pYTBaoTHohvmIgiRt6dRIzbwEOIaNaP+dIlGs2fNFoB0SeISs0Jz5WFVRid6Xyg==} + engines: {node: '>=12.20.0'} + + pathe@2.0.3: + resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + picomatch@4.0.5: + resolution: {integrity: sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==} + engines: {node: '>=12'} + + postcss@8.5.16: + resolution: {integrity: sha512-vuwillviilfKZsg0VGj5R/YwwcHx4SLsIOI/7K6mQkWx+l5cUHTjj5g0AasTBcyXsbfTgrwsUNmVUb5xVwyPwg==} + engines: {node: ^10 || ^12 || >=14} + react-dom@19.1.0: resolution: {integrity: sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==} peerDependencies: @@ -228,89 +691,397 @@ packages: resolution: {integrity: sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==} engines: {node: '>=0.10.0'} + rolldown@1.1.4: + resolution: {integrity: sha512-IjZYiLxZwpnhwhdBH2ugdTGVSdhCQUmLxLoqyjiL0JxYjyRst+5a0P3xfrTxJ5F638j4Mvvw5FAX5XE6eHpXbA==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + scheduler@0.26.0: resolution: {integrity: sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==} set-cookie-parser@2.7.2: resolution: {integrity: sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==} + siginfo@2.0.0: + resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} + + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + + stackback@0.0.2: + resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + + std-env@4.1.0: + resolution: {integrity: sha512-Rq7ybcX2RuC55r9oaPVEW7/xu3tj8u4GeBYHBWCychFtzMIr86A7e3PPEBPT37sHStKX3+TiX/Fr/ACmJLVlLQ==} + + tailwindcss@4.3.2: + resolution: {integrity: sha512-WtctNNSH8A9jlMIqxzuYumOHU5uGZyRv0Q5svQl+oEPy5w84YpBxdb7MdqyiSPQge5jTJ6zFQLq0PFygdccSBA==} + + tapable@2.3.3: + resolution: {integrity: sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==} + engines: {node: '>=6'} + + tinybench@2.9.0: + resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} + + tinyexec@1.2.4: + resolution: {integrity: sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg==} + engines: {node: '>=18'} + + tinyglobby@0.2.17: + resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==} + engines: {node: '>=12.0.0'} + + tinyrainbow@3.1.0: + resolution: {integrity: sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==} + engines: {node: '>=14.0.0'} + + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + typescript@6.0.3: + resolution: {integrity: sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==} + engines: {node: '>=14.17'} + hasBin: true + + undici-types@8.3.0: + resolution: {integrity: sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==} + + vite@8.1.3: + resolution: {integrity: sha512-Ds+gBRbj0lwRO2Y5hwnUBdxSwlAve9LeRyU4sNnAr0ewW0gWF0n5bgXgUzbgZ49MV9BVUAQUFYVcDUcilUExMA==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + peerDependencies: + '@types/node': ^20.19.0 || >=22.12.0 + '@vitejs/devtools': ^0.3.0 + esbuild: ^0.27.0 || ^0.28.0 + jiti: '>=1.21.0' + less: ^4.0.0 + sass: ^1.70.0 + sass-embedded: ^1.70.0 + stylus: '>=0.54.8' + sugarss: ^5.0.0 + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + '@types/node': + optional: true + '@vitejs/devtools': + optional: true + esbuild: + optional: true + jiti: + optional: true + less: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + + vitest@4.1.9: + resolution: {integrity: sha512-nE3/LEyc0z87uHYLZebqCUOaJr2hdtuPp7BQ4BosVFnfltxgAvMG08NyrSGlPpOUWvR27c5flSmYFTNr78L9GQ==} + engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@opentelemetry/api': ^1.9.0 + '@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0 + '@vitest/browser-playwright': 4.1.9 + '@vitest/browser-preview': 4.1.9 + '@vitest/browser-webdriverio': 4.1.9 + '@vitest/coverage-istanbul': 4.1.9 + '@vitest/coverage-v8': 4.1.9 + '@vitest/ui': 4.1.9 + happy-dom: '*' + jsdom: '*' + vite: ^6.0.0 || ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@opentelemetry/api': + optional: true + '@types/node': + optional: true + '@vitest/browser-playwright': + optional: true + '@vitest/browser-preview': + optional: true + '@vitest/browser-webdriverio': + optional: true + '@vitest/coverage-istanbul': + optional: true + '@vitest/coverage-v8': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + + why-is-node-running@2.3.0: + resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} + engines: {node: '>=8'} + hasBin: true + snapshots: - '@esbuild/aix-ppc64@0.25.0': + '@emnapi/core@1.11.1': + dependencies: + '@emnapi/wasi-threads': 1.2.2 + tslib: 2.8.1 + optional: true + + '@emnapi/runtime@1.11.1': + dependencies: + tslib: 2.8.1 + optional: true + + '@emnapi/wasi-threads@1.2.2': + dependencies: + tslib: 2.8.1 + optional: true + + '@esbuild/aix-ppc64@0.28.0': + optional: true + + '@esbuild/android-arm64@0.28.0': + optional: true + + '@esbuild/android-arm@0.28.0': + optional: true + + '@esbuild/android-x64@0.28.0': + optional: true + + '@esbuild/darwin-arm64@0.28.0': + optional: true + + '@esbuild/darwin-x64@0.28.0': + optional: true + + '@esbuild/freebsd-arm64@0.28.0': + optional: true + + '@esbuild/freebsd-x64@0.28.0': + optional: true + + '@esbuild/linux-arm64@0.28.0': + optional: true + + '@esbuild/linux-arm@0.28.0': + optional: true + + '@esbuild/linux-ia32@0.28.0': optional: true - '@esbuild/android-arm64@0.25.0': + '@esbuild/linux-loong64@0.28.0': optional: true - '@esbuild/android-arm@0.25.0': + '@esbuild/linux-mips64el@0.28.0': optional: true - '@esbuild/android-x64@0.25.0': + '@esbuild/linux-ppc64@0.28.0': optional: true - '@esbuild/darwin-arm64@0.25.0': + '@esbuild/linux-riscv64@0.28.0': optional: true - '@esbuild/darwin-x64@0.25.0': + '@esbuild/linux-s390x@0.28.0': optional: true - '@esbuild/freebsd-arm64@0.25.0': + '@esbuild/linux-x64@0.28.0': optional: true - '@esbuild/freebsd-x64@0.25.0': + '@esbuild/netbsd-arm64@0.28.0': optional: true - '@esbuild/linux-arm64@0.25.0': + '@esbuild/netbsd-x64@0.28.0': optional: true - '@esbuild/linux-arm@0.25.0': + '@esbuild/openbsd-arm64@0.28.0': optional: true - '@esbuild/linux-ia32@0.25.0': + '@esbuild/openbsd-x64@0.28.0': optional: true - '@esbuild/linux-loong64@0.25.0': + '@esbuild/openharmony-arm64@0.28.0': optional: true - '@esbuild/linux-mips64el@0.25.0': + '@esbuild/sunos-x64@0.28.0': optional: true - '@esbuild/linux-ppc64@0.25.0': + '@esbuild/win32-arm64@0.28.0': + optional: true + + '@esbuild/win32-ia32@0.28.0': + optional: true + + '@esbuild/win32-x64@0.28.0': + optional: true + + '@jridgewell/gen-mapping@0.3.13': + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/remapping@2.3.5': + dependencies: + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/sourcemap-codec@1.5.5': {} + + '@jridgewell/trace-mapping@0.3.31': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.5 + + '@napi-rs/wasm-runtime@1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)': + dependencies: + '@emnapi/core': 1.11.1 + '@emnapi/runtime': 1.11.1 + '@tybys/wasm-util': 0.10.3 + optional: true + + '@oxc-project/types@0.138.0': {} + + '@rolldown/binding-android-arm64@1.1.4': + optional: true + + '@rolldown/binding-darwin-arm64@1.1.4': + optional: true + + '@rolldown/binding-darwin-x64@1.1.4': + optional: true + + '@rolldown/binding-freebsd-x64@1.1.4': + optional: true + + '@rolldown/binding-linux-arm-gnueabihf@1.1.4': + optional: true + + '@rolldown/binding-linux-arm64-gnu@1.1.4': + optional: true + + '@rolldown/binding-linux-arm64-musl@1.1.4': + optional: true + + '@rolldown/binding-linux-ppc64-gnu@1.1.4': + optional: true + + '@rolldown/binding-linux-s390x-gnu@1.1.4': + optional: true + + '@rolldown/binding-linux-x64-gnu@1.1.4': + optional: true + + '@rolldown/binding-linux-x64-musl@1.1.4': + optional: true + + '@rolldown/binding-openharmony-arm64@1.1.4': + optional: true + + '@rolldown/binding-wasm32-wasi@1.1.4': + dependencies: + '@emnapi/core': 1.11.1 + '@emnapi/runtime': 1.11.1 + '@napi-rs/wasm-runtime': 1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1) + optional: true + + '@rolldown/binding-win32-arm64-msvc@1.1.4': + optional: true + + '@rolldown/binding-win32-x64-msvc@1.1.4': + optional: true + + '@rolldown/pluginutils@1.0.1': {} + + '@standard-schema/spec@1.1.0': {} + + '@tailwindcss/node@4.3.2': + dependencies: + '@jridgewell/remapping': 2.3.5 + enhanced-resolve: 5.21.6 + jiti: 2.7.0 + lightningcss: 1.32.0 + magic-string: 0.30.21 + source-map-js: 1.2.1 + tailwindcss: 4.3.2 + + '@tailwindcss/oxide-android-arm64@4.3.2': optional: true - '@esbuild/linux-riscv64@0.25.0': + '@tailwindcss/oxide-darwin-arm64@4.3.2': optional: true - '@esbuild/linux-s390x@0.25.0': + '@tailwindcss/oxide-darwin-x64@4.3.2': optional: true - '@esbuild/linux-x64@0.25.0': + '@tailwindcss/oxide-freebsd-x64@4.3.2': optional: true - '@esbuild/netbsd-arm64@0.25.0': + '@tailwindcss/oxide-linux-arm-gnueabihf@4.3.2': optional: true - '@esbuild/netbsd-x64@0.25.0': + '@tailwindcss/oxide-linux-arm64-gnu@4.3.2': optional: true - '@esbuild/openbsd-arm64@0.25.0': + '@tailwindcss/oxide-linux-arm64-musl@4.3.2': optional: true - '@esbuild/openbsd-x64@0.25.0': + '@tailwindcss/oxide-linux-x64-gnu@4.3.2': optional: true - '@esbuild/sunos-x64@0.25.0': + '@tailwindcss/oxide-linux-x64-musl@4.3.2': optional: true - '@esbuild/win32-arm64@0.25.0': + '@tailwindcss/oxide-wasm32-wasi@4.3.2': optional: true - '@esbuild/win32-ia32@0.25.0': + '@tailwindcss/oxide-win32-arm64-msvc@4.3.2': optional: true - '@esbuild/win32-x64@0.25.0': + '@tailwindcss/oxide-win32-x64-msvc@4.3.2': optional: true + '@tailwindcss/oxide@4.3.2': + optionalDependencies: + '@tailwindcss/oxide-android-arm64': 4.3.2 + '@tailwindcss/oxide-darwin-arm64': 4.3.2 + '@tailwindcss/oxide-darwin-x64': 4.3.2 + '@tailwindcss/oxide-freebsd-x64': 4.3.2 + '@tailwindcss/oxide-linux-arm-gnueabihf': 4.3.2 + '@tailwindcss/oxide-linux-arm64-gnu': 4.3.2 + '@tailwindcss/oxide-linux-arm64-musl': 4.3.2 + '@tailwindcss/oxide-linux-x64-gnu': 4.3.2 + '@tailwindcss/oxide-linux-x64-musl': 4.3.2 + '@tailwindcss/oxide-wasm32-wasi': 4.3.2 + '@tailwindcss/oxide-win32-arm64-msvc': 4.3.2 + '@tailwindcss/oxide-win32-x64-msvc': 4.3.2 + + '@tailwindcss/vite@4.3.2(vite@8.1.3(@types/node@26.1.0)(esbuild@0.28.0)(jiti@2.7.0))': + dependencies: + '@tailwindcss/node': 4.3.2 + '@tailwindcss/oxide': 4.3.2 + tailwindcss: 4.3.2 + vite: 8.1.3(@types/node@26.1.0)(esbuild@0.28.0)(jiti@2.7.0) + '@tanstack/query-core@5.87.4': {} '@tanstack/react-query@5.87.4(react@19.1.0)': @@ -318,38 +1089,204 @@ snapshots: '@tanstack/query-core': 5.87.4 react: 19.1.0 + '@tybys/wasm-util@0.10.3': + dependencies: + tslib: 2.8.1 + optional: true + + '@types/chai@5.2.3': + dependencies: + '@types/deep-eql': 4.0.2 + assertion-error: 2.0.1 + + '@types/deep-eql@4.0.2': {} + + '@types/estree@1.0.9': {} + + '@types/node@26.1.0': + dependencies: + undici-types: 8.3.0 + + '@vitejs/plugin-react@6.0.3(vite@8.1.3(@types/node@26.1.0)(esbuild@0.28.0)(jiti@2.7.0))': + dependencies: + '@rolldown/pluginutils': 1.0.1 + vite: 8.1.3(@types/node@26.1.0)(esbuild@0.28.0)(jiti@2.7.0) + + '@vitest/expect@4.1.9': + dependencies: + '@standard-schema/spec': 1.1.0 + '@types/chai': 5.2.3 + '@vitest/spy': 4.1.9 + '@vitest/utils': 4.1.9 + chai: 6.2.2 + tinyrainbow: 3.1.0 + + '@vitest/mocker@4.1.9(vite@8.1.3(@types/node@26.1.0)(esbuild@0.28.0)(jiti@2.7.0))': + dependencies: + '@vitest/spy': 4.1.9 + estree-walker: 3.0.3 + magic-string: 0.30.21 + optionalDependencies: + vite: 8.1.3(@types/node@26.1.0)(esbuild@0.28.0)(jiti@2.7.0) + + '@vitest/pretty-format@4.1.9': + dependencies: + tinyrainbow: 3.1.0 + + '@vitest/runner@4.1.9': + dependencies: + '@vitest/utils': 4.1.9 + pathe: 2.0.3 + + '@vitest/snapshot@4.1.9': + dependencies: + '@vitest/pretty-format': 4.1.9 + '@vitest/utils': 4.1.9 + magic-string: 0.30.21 + pathe: 2.0.3 + + '@vitest/spy@4.1.9': {} + + '@vitest/utils@4.1.9': + dependencies: + '@vitest/pretty-format': 4.1.9 + convert-source-map: 2.0.0 + tinyrainbow: 3.1.0 + + assertion-error@2.0.1: {} + + chai@6.2.2: {} + + convert-source-map@2.0.0: {} + cookie@1.1.1: {} - esbuild@0.25.0: + detect-libc@2.1.2: {} + + enhanced-resolve@5.21.6: + dependencies: + graceful-fs: 4.2.11 + tapable: 2.3.3 + + es-module-lexer@2.3.0: {} + + esbuild@0.28.0: + optionalDependencies: + '@esbuild/aix-ppc64': 0.28.0 + '@esbuild/android-arm': 0.28.0 + '@esbuild/android-arm64': 0.28.0 + '@esbuild/android-x64': 0.28.0 + '@esbuild/darwin-arm64': 0.28.0 + '@esbuild/darwin-x64': 0.28.0 + '@esbuild/freebsd-arm64': 0.28.0 + '@esbuild/freebsd-x64': 0.28.0 + '@esbuild/linux-arm': 0.28.0 + '@esbuild/linux-arm64': 0.28.0 + '@esbuild/linux-ia32': 0.28.0 + '@esbuild/linux-loong64': 0.28.0 + '@esbuild/linux-mips64el': 0.28.0 + '@esbuild/linux-ppc64': 0.28.0 + '@esbuild/linux-riscv64': 0.28.0 + '@esbuild/linux-s390x': 0.28.0 + '@esbuild/linux-x64': 0.28.0 + '@esbuild/netbsd-arm64': 0.28.0 + '@esbuild/netbsd-x64': 0.28.0 + '@esbuild/openbsd-arm64': 0.28.0 + '@esbuild/openbsd-x64': 0.28.0 + '@esbuild/openharmony-arm64': 0.28.0 + '@esbuild/sunos-x64': 0.28.0 + '@esbuild/win32-arm64': 0.28.0 + '@esbuild/win32-ia32': 0.28.0 + '@esbuild/win32-x64': 0.28.0 + + estree-walker@3.0.3: + dependencies: + '@types/estree': 1.0.9 + + expect-type@1.4.0: {} + + fdir@6.5.0(picomatch@4.0.5): optionalDependencies: - '@esbuild/aix-ppc64': 0.25.0 - '@esbuild/android-arm': 0.25.0 - '@esbuild/android-arm64': 0.25.0 - '@esbuild/android-x64': 0.25.0 - '@esbuild/darwin-arm64': 0.25.0 - '@esbuild/darwin-x64': 0.25.0 - '@esbuild/freebsd-arm64': 0.25.0 - '@esbuild/freebsd-x64': 0.25.0 - '@esbuild/linux-arm': 0.25.0 - '@esbuild/linux-arm64': 0.25.0 - '@esbuild/linux-ia32': 0.25.0 - '@esbuild/linux-loong64': 0.25.0 - '@esbuild/linux-mips64el': 0.25.0 - '@esbuild/linux-ppc64': 0.25.0 - '@esbuild/linux-riscv64': 0.25.0 - '@esbuild/linux-s390x': 0.25.0 - '@esbuild/linux-x64': 0.25.0 - '@esbuild/netbsd-arm64': 0.25.0 - '@esbuild/netbsd-x64': 0.25.0 - '@esbuild/openbsd-arm64': 0.25.0 - '@esbuild/openbsd-x64': 0.25.0 - '@esbuild/sunos-x64': 0.25.0 - '@esbuild/win32-arm64': 0.25.0 - '@esbuild/win32-ia32': 0.25.0 - '@esbuild/win32-x64': 0.25.0 + picomatch: 4.0.5 + + fsevents@2.3.3: + optional: true + + graceful-fs@4.2.11: {} htm@3.1.1: {} + jiti@2.7.0: {} + + lightningcss-android-arm64@1.32.0: + optional: true + + lightningcss-darwin-arm64@1.32.0: + optional: true + + lightningcss-darwin-x64@1.32.0: + optional: true + + lightningcss-freebsd-x64@1.32.0: + optional: true + + lightningcss-linux-arm-gnueabihf@1.32.0: + optional: true + + lightningcss-linux-arm64-gnu@1.32.0: + optional: true + + lightningcss-linux-arm64-musl@1.32.0: + optional: true + + lightningcss-linux-x64-gnu@1.32.0: + optional: true + + lightningcss-linux-x64-musl@1.32.0: + optional: true + + lightningcss-win32-arm64-msvc@1.32.0: + optional: true + + lightningcss-win32-x64-msvc@1.32.0: + optional: true + + lightningcss@1.32.0: + dependencies: + detect-libc: 2.1.2 + optionalDependencies: + lightningcss-android-arm64: 1.32.0 + lightningcss-darwin-arm64: 1.32.0 + lightningcss-darwin-x64: 1.32.0 + lightningcss-freebsd-x64: 1.32.0 + lightningcss-linux-arm-gnueabihf: 1.32.0 + lightningcss-linux-arm64-gnu: 1.32.0 + lightningcss-linux-arm64-musl: 1.32.0 + lightningcss-linux-x64-gnu: 1.32.0 + lightningcss-linux-x64-musl: 1.32.0 + lightningcss-win32-arm64-msvc: 1.32.0 + lightningcss-win32-x64-msvc: 1.32.0 + + magic-string@0.30.21: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + + nanoid@3.3.15: {} + + obug@2.1.3: {} + + pathe@2.0.3: {} + + picocolors@1.1.1: {} + + picomatch@4.0.5: {} + + postcss@8.5.16: + dependencies: + nanoid: 3.3.15 + picocolors: 1.1.1 + source-map-js: 1.2.1 + react-dom@19.1.0(react@19.1.0): dependencies: react: 19.1.0 @@ -369,6 +1306,102 @@ snapshots: react@19.1.0: {} + rolldown@1.1.4: + dependencies: + '@oxc-project/types': 0.138.0 + '@rolldown/pluginutils': 1.0.1 + optionalDependencies: + '@rolldown/binding-android-arm64': 1.1.4 + '@rolldown/binding-darwin-arm64': 1.1.4 + '@rolldown/binding-darwin-x64': 1.1.4 + '@rolldown/binding-freebsd-x64': 1.1.4 + '@rolldown/binding-linux-arm-gnueabihf': 1.1.4 + '@rolldown/binding-linux-arm64-gnu': 1.1.4 + '@rolldown/binding-linux-arm64-musl': 1.1.4 + '@rolldown/binding-linux-ppc64-gnu': 1.1.4 + '@rolldown/binding-linux-s390x-gnu': 1.1.4 + '@rolldown/binding-linux-x64-gnu': 1.1.4 + '@rolldown/binding-linux-x64-musl': 1.1.4 + '@rolldown/binding-openharmony-arm64': 1.1.4 + '@rolldown/binding-wasm32-wasi': 1.1.4 + '@rolldown/binding-win32-arm64-msvc': 1.1.4 + '@rolldown/binding-win32-x64-msvc': 1.1.4 + scheduler@0.26.0: {} set-cookie-parser@2.7.2: {} + + siginfo@2.0.0: {} + + source-map-js@1.2.1: {} + + stackback@0.0.2: {} + + std-env@4.1.0: {} + + tailwindcss@4.3.2: {} + + tapable@2.3.3: {} + + tinybench@2.9.0: {} + + tinyexec@1.2.4: {} + + tinyglobby@0.2.17: + dependencies: + fdir: 6.5.0(picomatch@4.0.5) + picomatch: 4.0.5 + + tinyrainbow@3.1.0: {} + + tslib@2.8.1: + optional: true + + typescript@6.0.3: {} + + undici-types@8.3.0: {} + + vite@8.1.3(@types/node@26.1.0)(esbuild@0.28.0)(jiti@2.7.0): + dependencies: + lightningcss: 1.32.0 + picomatch: 4.0.5 + postcss: 8.5.16 + rolldown: 1.1.4 + tinyglobby: 0.2.17 + optionalDependencies: + '@types/node': 26.1.0 + esbuild: 0.28.0 + fsevents: 2.3.3 + jiti: 2.7.0 + + vitest@4.1.9(@types/node@26.1.0)(vite@8.1.3(@types/node@26.1.0)(esbuild@0.28.0)(jiti@2.7.0)): + dependencies: + '@vitest/expect': 4.1.9 + '@vitest/mocker': 4.1.9(vite@8.1.3(@types/node@26.1.0)(esbuild@0.28.0)(jiti@2.7.0)) + '@vitest/pretty-format': 4.1.9 + '@vitest/runner': 4.1.9 + '@vitest/snapshot': 4.1.9 + '@vitest/spy': 4.1.9 + '@vitest/utils': 4.1.9 + es-module-lexer: 2.3.0 + expect-type: 1.4.0 + magic-string: 0.30.21 + obug: 2.1.3 + pathe: 2.0.3 + picomatch: 4.0.5 + std-env: 4.1.0 + tinybench: 2.9.0 + tinyexec: 1.2.4 + tinyglobby: 0.2.17 + tinyrainbow: 3.1.0 + vite: 8.1.3(@types/node@26.1.0)(esbuild@0.28.0)(jiti@2.7.0) + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/node': 26.1.0 + transitivePeerDependencies: + - msw + + why-is-node-running@2.3.0: + dependencies: + siginfo: 2.0.0 + stackback: 0.0.2 diff --git a/crates/ironclaw_webui_v2/frontend/src/main.ts b/crates/ironclaw_webui_v2/frontend/src/main.ts new file mode 100644 index 00000000000..f191fc60a83 --- /dev/null +++ b/crates/ironclaw_webui_v2/frontend/src/main.ts @@ -0,0 +1,2 @@ +import "./styles/app.css"; +import "../../static/js/main.js"; diff --git a/crates/ironclaw_webui_v2/frontend/src/styles/app.css b/crates/ironclaw_webui_v2/frontend/src/styles/app.css new file mode 100644 index 00000000000..98f4bc471ac --- /dev/null +++ b/crates/ironclaw_webui_v2/frontend/src/styles/app.css @@ -0,0 +1,23 @@ +@import "tailwindcss"; +@import "../../../static/styles/app.css"; + +@source "../../../static/js"; + +@theme { + --font-sans: "Geist", "Inter", "SF Pro Display", "Helvetica Neue", + ui-sans-serif, system-ui, sans-serif; + --font-serif: "Newsreader", "Lyon Text", "Instrument Serif", georgia, serif; + --font-mono: "Geist Mono", "SF Mono", "JetBrains Mono", ui-monospace, + monospace; + --color-iron-950: var(--v2-canvas-strong); + --color-iron-900: var(--v2-surface); + --color-iron-800: var(--v2-surface-soft); + --color-iron-700: var(--v2-panel-border); + --color-iron-400: var(--v2-text-faint); + --color-iron-300: var(--v2-text-muted); + --color-iron-200: var(--v2-text); + --color-iron-100: var(--v2-text-strong); + --color-signal: var(--v2-accent-text); + --color-copper: var(--v2-warning-text); + --color-mint: var(--v2-accent-text); +} diff --git a/crates/ironclaw_webui_v2/frontend/src/vite-env.d.ts b/crates/ironclaw_webui_v2/frontend/src/vite-env.d.ts new file mode 100644 index 00000000000..208b6aed34a --- /dev/null +++ b/crates/ironclaw_webui_v2/frontend/src/vite-env.d.ts @@ -0,0 +1,8 @@ +/// + +interface Window { + __IRONCLAW_INITIAL_THEME__?: "light" | "dark"; + DOMPurify?: unknown; + marked?: unknown; + hljs?: unknown; +} diff --git a/crates/ironclaw_webui_v2/frontend/tsconfig.json b/crates/ironclaw_webui_v2/frontend/tsconfig.json new file mode 100644 index 00000000000..b27974bd389 --- /dev/null +++ b/crates/ironclaw_webui_v2/frontend/tsconfig.json @@ -0,0 +1,17 @@ +{ + "compilerOptions": { + "allowJs": true, + "checkJs": false, + "isolatedModules": true, + "lib": ["DOM", "DOM.Iterable", "ES2022"], + "module": "ESNext", + "moduleResolution": "Bundler", + "noEmit": true, + "noImplicitAny": false, + "skipLibCheck": true, + "strict": false, + "target": "ES2022", + "types": ["node", "vite/client"] + }, + "include": ["src", "vite.config.ts"] +} diff --git a/crates/ironclaw_webui_v2/frontend/vite.config.ts b/crates/ironclaw_webui_v2/frontend/vite.config.ts new file mode 100644 index 00000000000..26f479d394d --- /dev/null +++ b/crates/ironclaw_webui_v2/frontend/vite.config.ts @@ -0,0 +1,55 @@ +import tailwindcss from "@tailwindcss/vite"; +import react from "@vitejs/plugin-react"; +import { defineConfig } from "vitest/config"; +import { dirname, resolve } from "node:path"; +import { fileURLToPath } from "node:url"; +import { createRequire } from "node:module"; + +const here = dirname(fileURLToPath(import.meta.url)); +const rustStaticDir = resolve(here, "..", "static"); +const require = createRequire(import.meta.url); + +export default defineConfig({ + base: "/v2/", + plugins: [tailwindcss(), react()], + publicDir: "public", + resolve: { + alias: [ + { find: /^@tanstack\/react-query$/, replacement: require.resolve("@tanstack/react-query") }, + { find: /^htm$/, replacement: require.resolve("htm") }, + { find: /^react$/, replacement: require.resolve("react") }, + { find: /^react\/jsx-runtime$/, replacement: require.resolve("react/jsx-runtime") }, + { find: /^react-dom$/, replacement: require.resolve("react-dom") }, + { find: /^react-dom\/client$/, replacement: require.resolve("react-dom/client") }, + { find: /^react-hook-form$/, replacement: require.resolve("react-hook-form") }, + { find: /^react-router$/, replacement: require.resolve("react-router") }, + ], + }, + server: { + host: "127.0.0.1", + port: 5173, + fs: { + allow: [here, rustStaticDir], + }, + proxy: { + "/api/webchat/v2": "http://127.0.0.1:3000", + "/api/reborn": "http://127.0.0.1:3000", + "/auth": "http://127.0.0.1:3000", + "/v2/assets": "http://127.0.0.1:3000", + "/v2/js": "http://127.0.0.1:3000", + "/v2/vendor": "http://127.0.0.1:3000", + "/v2/wallet/connect": "http://127.0.0.1:3000", + }, + }, + build: { + outDir: "dist", + emptyOutDir: true, + manifest: true, + sourcemap: false, + target: "es2022", + }, + test: { + environment: "node", + include: ["src/**/*.{test,spec}.{js,mjs,ts,mts}"], + }, +}); diff --git a/crates/ironclaw_webui_v2/static/js/lib/markdown.test.mjs b/crates/ironclaw_webui_v2/static/js/lib/markdown.test.mjs index 879bb1a7be9..ea545d0e2d6 100644 --- a/crates/ironclaw_webui_v2/static/js/lib/markdown.test.mjs +++ b/crates/ironclaw_webui_v2/static/js/lib/markdown.test.mjs @@ -34,6 +34,7 @@ test("renderMarkdown routes parsed HTML through DOMPurify.sanitize, stripping ha }, }, DOMPurify: { + addHook: () => {}, sanitize: (raw) => { calls.sanitize.push(raw); return raw.replace(/ onerror="[^"]*"/g, ""); From fa62e28f683b41ed2947b99eee796de5e78c3dc3 Mon Sep 17 00:00:00 2001 From: BenKurrek Date: Mon, 6 Jul 2026 16:26:36 -0400 Subject: [PATCH 06/12] feat(webui): move frontend source to typescript --- .github/workflows/reborn-tests.yml | 18 +- .github/workflows/regression-test-check.yml | 2 +- .../tests/webui_v2_serve.rs | 238 +++------ crates/ironclaw_webui_v2/build.rs | 16 +- crates/ironclaw_webui_v2/frontend/build.mjs | 64 ++- .../ironclaw_webui_v2/frontend/package.json | 2 +- .../js/app/app.js => frontend/src/app/app.ts} | 0 .../app/auth.js => frontend/src/app/auth.ts} | 0 .../src/app/routes.test.mts} | 4 +- .../routes.js => frontend/src/app/routes.ts} | 0 .../components/channel-pairing-section.ts} | 1 + .../src/components/command-palette.ts} | 0 .../src/components/notification-center.ts} | 0 .../src/components/page-header.ts} | 0 .../src/components/sidebar-footer.ts} | 0 .../src/components/sidebar-nav.ts} | 0 .../src/components/sidebar-threads.ts} | 2 +- .../src/components/sidebar-trace-credits.ts} | 0 .../src/components/sidebar.ts} | 0 .../components/slack-channel-picker.test.mts} | 5 +- .../src/components/slack-channel-picker.ts} | 1 + .../slack-pairing-section.test.mts} | 5 +- .../src/components/slack-pairing-section.ts} | 1 + .../components/slack-setup-panel.test.mts} | 5 +- .../src/components/slack-setup-panel.ts} | 0 .../src/components/tee-shield.ts} | 0 .../src/components/toast-viewport.ts} | 0 .../src/design-system/badge.ts} | 0 .../src/design-system/button.ts} | 0 .../src/design-system/card.ts} | 0 .../src/design-system/icons.ts} | 0 .../src/design-system/input.ts} | 0 .../src/design-system/modal.test.mts} | 16 +- .../src/design-system/modal.ts} | 0 .../src/design-system/primitives.ts} | 0 .../src/design-system/theme.ts} | 0 .../src/hooks/useGatewayStatus.ts} | 0 .../src/hooks/useNotifications.test.mts} | 7 +- .../src/hooks/useNotifications.ts} | 1 + .../src/hooks/useSidebar.test.mts} | 5 +- .../src/hooks/useSidebar.ts} | 1 + .../src/hooks/useTeeAttestation.ts} | 0 .../js/i18n/ar.js => frontend/src/i18n/ar.ts} | 0 .../js/i18n/de.js => frontend/src/i18n/de.ts} | 0 .../js/i18n/en.js => frontend/src/i18n/en.ts} | 0 .../js/i18n/es.js => frontend/src/i18n/es.ts} | 0 .../js/i18n/fr.js => frontend/src/i18n/fr.ts} | 0 .../js/i18n/hi.js => frontend/src/i18n/hi.ts} | 0 .../js/i18n/ja.js => frontend/src/i18n/ja.ts} | 0 .../js/i18n/ko.js => frontend/src/i18n/ko.ts} | 0 .../pt-BR.js => frontend/src/i18n/pt-BR.ts} | 0 .../js/i18n/uk.js => frontend/src/i18n/uk.ts} | 0 .../zh-CN.js => frontend/src/i18n/zh-CN.ts} | 0 .../src/layout/gateway-layout.ts} | 1 + .../src/lib/api.test.mts} | 5 +- .../src/lib/api.test.ts} | 8 +- .../js/lib/api.js => frontend/src/lib/api.ts} | 1 + .../src/lib/auth-scope.ts} | 0 .../src/lib/channel-connect.ts} | 0 .../src/lib/channel-connection-events.ts} | 1 + .../src/lib/download.ts} | 0 .../lib/html.js => frontend/src/lib/html.ts} | 0 .../src/lib/i18n-format.ts} | 0 .../src/lib/i18n.test.mts} | 13 +- .../lib/i18n.js => frontend/src/lib/i18n.ts} | 0 .../src/lib/markdown.test.mts} | 6 +- .../src/lib/markdown.ts} | 1 + .../src/lib/notifications.test.ts} | 9 +- .../src/lib/notifications.ts} | 1 + .../src/lib/onboarding-gate.test.ts} | 9 +- .../src/lib/onboarding-gate.ts} | 2 +- .../src/lib/pin-store.test.ts} | 11 +- .../src/lib/pin-store.ts} | 3 +- .../src/lib/query-client.ts} | 0 .../src/lib/sidebar-active-thread.test.mts} | 4 +- .../src/lib/sidebar-active-thread.ts} | 0 .../src/lib/sidebar-state.ts} | 0 .../src/lib/slack-channels-api.test.mts} | 5 +- .../src/lib/slack-channels-api.ts} | 0 .../src/lib/slack-pairing-api.test.mts} | 5 +- .../src/lib/slack-pairing-api.ts} | 1 + .../src/lib/slack-setup-api.test.mts} | 5 +- .../src/lib/slack-setup-api.ts} | 1 + .../src/lib/thread-errors.test.mts} | 4 +- .../src/lib/thread-errors.ts} | 0 .../src/lib/thread-meta.ts} | 0 .../src/lib/thread-state.ts} | 3 +- .../toast.js => frontend/src/lib/toast.ts} | 1 + crates/ironclaw_webui_v2/frontend/src/main.ts | 18 +- .../src/pages/admin/admin-page.ts} | 0 .../src/pages/admin/components/admin-tabs.ts} | 0 .../pages/admin/components/dashboard-tab.ts} | 1 + .../src/pages/admin/components/usage-tab.ts} | 1 + .../pages/admin/components/user-detail.ts} | 1 + .../src/pages/admin/components/users-tab.ts} | 1 + .../src/pages/admin/hooks/useAdminUsage.ts} | 0 .../src/pages/admin/hooks/useAdminUsers.ts} | 1 + .../src/pages/admin/lib/admin-api.ts} | 0 .../src/pages/admin/lib/admin-presenters.ts} | 1 + .../pages/automations/automations-page.ts} | 0 .../automation-delivery-defaults-panel.ts} | 0 .../components/automation-detail-panel.ts} | 0 .../automation-recent-runs.test.mts} | 7 +- .../components/automation-recent-runs.ts} | 0 .../automations-empty-state.test.mts} | 5 +- .../components/automations-empty-state.ts} | 0 .../components/automations-list.ts} | 0 .../automations-summary-strip.test.mts} | 5 +- .../components/automations-summary-strip.ts} | 0 .../automations/hooks/useAutomations.ts} | 0 .../hooks/useOutboundDeliveryDefaults.ts} | 1 + .../lib/automations-presenters.test.mts} | 7 +- .../lib/automations-presenters.ts} | 1 + .../lib/automations-refresh.test.mts} | 4 +- .../automations/lib/automations-refresh.ts} | 0 .../src/pages/chat/chat-page.ts} | 1 + .../src/pages/chat/chat.ts} | 1 + .../chat/components/activity-run.test.mts} | 5 +- .../pages/chat/components/activity-run.ts} | 0 .../chat/components/approval-card.test.mts} | 5 +- .../pages/chat/components/approval-card.ts} | 0 .../pages/chat/components/attachment-chip.ts} | 0 .../chat/components/attachment-preview.ts} | 1 + .../pages/chat/components/auth-gate-shell.ts} | 0 .../chat/components/auth-generic-card.ts} | 0 .../pages/chat/components/auth-oauth-card.ts} | 0 .../pages/chat/components/auth-token-card.ts} | 0 .../src/pages/chat/components/chat-input.ts} | 0 .../src/pages/chat/components/code-block.ts} | 0 .../components/connection-status.test.mts} | 5 +- .../chat/components/connection-status.ts} | 0 .../src/pages/chat/components/empty-state.ts} | 0 .../chat/components/keyboard-shortcuts.ts} | 0 .../components/markdown-renderer.test.mts} | 6 +- .../chat/components/markdown-renderer.ts} | 1 + .../chat/components/message-bubble.test.mts} | 6 +- .../pages/chat/components/message-bubble.ts} | 0 .../chat/components/message-list.test.mts} | 5 +- .../pages/chat/components/message-list.ts} | 0 .../onboarding-pairing-card.test.mts} | 7 +- .../components/onboarding-pairing-card.ts} | 0 .../chat/components/project-file-chips.ts} | 0 .../pages/chat/components/recovery-notice.ts} | 0 .../chat/components/suggestion-chips.ts} | 0 .../pages/chat/components/thread-sidebar.ts} | 0 .../chat/components/tool-activity.test.mts} | 8 +- .../pages/chat/components/tool-activity.ts} | 1 + .../chat/components/typing-indicator.ts} | 0 .../pages/chat/hooks/useAttachmentConfig.ts} | 0 .../src/pages/chat/hooks/useChat.ts} | 3 +- .../src/pages/chat/hooks/useHistory.ts} | 1 + .../src/pages/chat/hooks/useSSE.ts} | 0 .../src/pages/chat/hooks/useThreads.test.mts} | 7 +- .../src/pages/chat/hooks/useThreads.ts} | 0 .../pages/chat/lib/activity-summary.test.mts} | 4 +- .../src/pages/chat/lib/activity-summary.ts} | 0 .../pages/chat/lib/approval-risk.test.mts} | 4 +- .../src/pages/chat/lib/approval-risk.ts} | 0 .../pages/chat/lib/attachment-sentinel.ts} | 0 .../src/pages/chat/lib/attachments.test.mts} | 7 +- .../src/pages/chat/lib/attachments.ts} | 0 .../src/pages/chat/lib/chat-input.test.mts} | 5 +- .../src/pages/chat/lib/chat.test.mts} | 7 +- .../src/pages/chat/lib/draft-store.test.ts} | 11 +- .../src/pages/chat/lib/draft-store.ts} | 2 +- .../pages/chat/lib/failureMessages.test.mts} | 4 +- .../src/pages/chat/lib/failureMessages.ts} | 0 .../src/pages/chat/lib/gates.test.mts} | 5 +- .../src/pages/chat/lib/gates.ts} | 0 .../pages/chat/lib/history-messages.test.mts} | 6 +- .../src/pages/chat/lib/history-messages.ts} | 0 .../pages/chat/lib/message-groups.test.mts} | 4 +- .../pages/chat/lib/message-groups.test.ts} | 4 +- .../src/pages/chat/lib/message-groups.ts} | 0 .../pages/chat/lib/pending-messages.test.mts} | 4 +- .../src/pages/chat/lib/pending-messages.ts} | 0 .../chat/lib/project-file-paths.test.ts} | 8 +- .../src/pages/chat/lib/project-file-paths.ts} | 0 .../src/pages/chat/lib/runtime-context.ts} | 0 .../src/pages/chat/lib/thread-cache.test.mts} | 5 +- .../src/pages/chat/lib/thread-cache.ts} | 0 .../chat/lib/tool-activity-state.test.mts} | 6 +- .../chat/lib/tool-activity-state.test.ts} | 8 +- .../pages/chat/lib/tool-activity-state.ts} | 1 + .../src/pages/chat/lib/useChat-send.test.mts} | 17 +- .../pages/chat/lib/useChatEvents.test.mts} | 11 +- .../src/pages/chat/lib/useChatEvents.ts} | 1 + .../src/pages/chat/lib/useHistory.test.mts} | 5 +- .../extensions/components/action-toast.ts} | 0 .../components/channels-tab.test.mts} | 5 +- .../extensions/components/channels-tab.ts} | 0 .../components/configure-modal.test.mts} | 5 +- .../extensions/components/configure-modal.ts} | 1 + .../components/extension-card.test.mts} | 37 +- .../extensions/components/extension-card.ts} | 0 .../extensions/components/extensions-tabs.ts} | 0 .../pages/extensions/components/mcp-tab.ts} | 0 .../components/pairing-section.test.mts} | 5 +- .../extensions/components/pairing-section.ts} | 1 + .../components/registry-tab.test.mts} | 5 +- .../extensions/components/registry-tab.ts} | 0 .../extensions/extensions-page.test.mts} | 5 +- .../src/pages/extensions/extensions-page.ts} | 0 .../hooks/useExtensions-catalog.test.mts} | 5 +- .../hooks/useExtensions-pairing.test.mts} | 5 +- .../pages/extensions/hooks/useExtensions.ts} | 1 + .../lib/extension-actions.test.mts} | 5 +- .../extensions/lib/extension-actions.ts} | 1 + .../pages/extensions/lib/extensions-api.ts} | 0 .../lib/extensions-schema.test.mts} | 4 +- .../extensions/lib/extensions-schema.ts} | 0 .../pages/extensions/lib/pairing-api.test.mts | 83 +++ .../src/pages/extensions/lib/pairing-api.ts} | 1 + .../extensions/lib/pairing-errors.test.mts} | 4 +- .../pages/extensions/lib/pairing-errors.ts} | 0 .../jobs/components/job-activity-tab.ts} | 0 .../jobs/components/job-detail-shell.ts} | 0 .../pages/jobs/components/job-files-tab.ts} | 0 .../jobs/components/job-overview-tab.ts} | 0 .../src/pages/jobs/components/jobs-list.ts} | 0 .../jobs/components/jobs-summary-strip.ts} | 0 .../src/pages/jobs/hooks/useJobDetail.ts} | 1 + .../src/pages/jobs/hooks/useJobFiles.ts} | 0 .../src/pages/jobs/hooks/useJobs.ts} | 1 + .../src/pages/jobs/jobs-page.ts} | 1 + .../src/pages/jobs/lib/jobs-api.ts} | 0 .../src/pages/jobs/lib/jobs-presenters.ts} | 0 .../components/oauth-provider-buttons.ts} | 0 .../pages/login/hooks/useOAuthProviders.ts} | 0 .../src/pages/login/login-page.ts} | 0 .../src/pages/logs/hooks/useLogs.test.mts} | 5 +- .../src/pages/logs/hooks/useLogs.ts} | 1 + .../src/pages/logs/lib/logs-data.test.mts} | 4 +- .../src/pages/logs/lib/logs-data.ts} | 1 + .../src/pages/logs/logs-page.test.mts} | 5 +- .../src/pages/logs/logs-page.ts} | 1 + .../components/mission-detail-panel.ts} | 0 .../missions/components/missions-list.ts} | 0 .../components/missions-summary-strip.ts} | 0 .../pages/missions/hooks/useMissionDetail.ts} | 0 .../src/pages/missions/hooks/useMissions.ts} | 1 + .../src/pages/missions/lib/missions-api.ts} | 1 + .../missions/lib/missions-presenters.ts} | 0 .../src/pages/missions/missions-page.ts} | 0 .../src/pages/onboarding/onboarding-page.ts} | 1 + .../src/pages/onboarding/provider-logos.ts} | 0 .../projects/components/feedback-banner.ts} | 0 .../components/project-activity-column.ts} | 1 + .../components/project-filesystem-panel.ts} | 0 .../components/project-inspector-rail.ts} | 0 .../components/project-mission-inspector.ts} | 0 .../components/project-missions-column.ts} | 0 .../components/project-thread-inspector.ts} | 0 .../projects/components/project-widgets.ts} | 8 + .../components/project-workspace-shell.ts} | 1 + .../components/projects-attention-strip.ts} | 0 .../projects/components/projects-grid.ts} | 0 .../components/projects-summary-strip.ts} | 0 .../projects/hooks/useProjectInspector.ts} | 1 + .../projects/hooks/useProjectWorkspace.ts} | 0 .../projects/hooks/useProjectsOverview.ts} | 0 .../src/pages/projects/lib/projects-api.ts} | 0 .../projects/lib/projects-presenters.ts} | 0 .../src/pages/projects/projects-page.ts} | 1 + .../components/routine-detail-panel.ts} | 0 .../components/routine-recent-runs.ts} | 0 .../pages/routines/components/routine-row.ts} | 0 .../routines/components/routines-list.ts} | 0 .../components/routines-summary-strip.ts} | 0 .../pages/routines/hooks/useRoutineDetail.ts} | 0 .../routines/hooks/useRoutineFilters.ts} | 0 .../src/pages/routines/hooks/useRoutines.ts} | 0 .../src/pages/routines/lib/routines-api.ts} | 0 .../routines/lib/routines-presenters.ts} | 0 .../src/pages/routines/routines-page.ts} | 0 .../pages/settings/components/agent-tab.ts} | 0 .../settings/components/channels-tab.ts} | 0 .../components/inference-tab.test.mts} | 10 +- .../settings/components/inference-tab.ts} | 0 .../settings/components/language-tab.ts} | 0 .../settings/components/networking-tab.ts} | 0 .../settings/components/provider-card.ts} | 0 .../components/provider-components.test.mts} | 17 +- .../settings/components/provider-dialog.ts} | 0 .../components/provider-login-status.ts} | 0 .../components/provider-management.ts} | 0 .../settings/components/restart-banner.ts} | 1 + .../settings/components/settings-field.ts} | 0 .../components/settings-search-empty.ts} | 0 .../settings/components/settings-tabs.ts} | 0 .../settings/components/settings-toolbar.ts} | 1 + .../pages/settings/components/skill-card.ts} | 0 .../components/skill-install-panel.test.mts} | 7 +- .../components/skill-install-panel.ts} | 1 + .../pages/settings/components/skills-tab.ts} | 1 + .../settings/components/tools-tab.test.mts} | 7 +- .../pages/settings/components/tools-tab.ts} | 0 .../settings/components/trace-commons-tab.ts} | 0 .../pages/settings/components/users-tab.ts} | 0 .../src/pages/settings/hooks/useChannels.ts} | 0 .../settings/hooks/useGatewayRestart.ts} | 0 .../pages/settings/hooks/useLlmProviders.ts} | 1 + .../settings/hooks/useProviderDialogForm.ts} | 0 .../pages/settings/hooks/useProviderLogin.ts} | 1 + .../hooks/useProviderManagementActions.ts} | 0 .../src/pages/settings/hooks/useSettings.ts} | 1 + .../src/pages/settings/hooks/useSkills.ts} | 1 + .../pages/settings/hooks/useTools.test.mts} | 6 +- .../src/pages/settings/hooks/useTools.ts} | 1 + .../pages/settings/hooks/useTraceCredits.ts} | 0 .../src/pages/settings/hooks/useUsers.ts} | 1 + .../pages/settings/lib/api-result.test.mts} | 4 +- .../src/pages/settings/lib/api-result.ts} | 0 .../settings/lib/llm-providers.test.mts} | 4 +- .../src/pages/settings/lib/llm-providers.ts} | 1 + .../pages/settings/lib/settings-api.test.mts} | 4 +- .../src/pages/settings/lib/settings-api.ts} | 0 .../settings/lib/settings-schema.test.mts} | 4 +- .../pages/settings/lib/settings-schema.ts} | 0 .../pages/settings/lib/settings-search.ts} | 0 .../src/pages/settings/settings-page.ts} | 1 + .../settings/vm-module-harness.test.mts} | 4 +- .../components/workspace-breadcrumb.ts} | 0 .../components/workspace-directory.ts} | 0 .../components/workspace-sidebar.ts} | 0 .../workspace/components/workspace-tree.ts} | 0 .../workspace/components/workspace-viewer.ts} | 0 .../workspace/hooks/useWorkspaceBrowser.ts} | 0 .../src/pages/workspace/lib/workspace-api.ts} | 0 .../workspace/lib/workspace-presenters.ts} | 0 .../src/pages/workspace/workspace-page.ts} | 0 .../frontend/src/styles/app.css | 482 ++++++++++++++++- .../src/test-support/vm-module-harness.ts} | 0 .../utils/cn.js => frontend/src/utils/cn.ts} | 0 .../src/wallet-connect.ts} | 1 + .../ironclaw_webui_v2/frontend/tsconfig.json | 1 + crates/ironclaw_webui_v2/frontend/vendor.sh | 2 +- .../src/static_assets/assets.rs | 189 +++---- .../src/static_assets/router.rs | 33 +- crates/ironclaw_webui_v2/static/index.html | 2 +- crates/ironclaw_webui_v2/static/js/main.js | 17 - .../pages/extensions/lib/pairing-api.test.mjs | 73 --- .../ironclaw_webui_v2/static/styles/app.css | 500 ------------------ .../static/wallet-connect.html | 2 +- .../tests/i18n_consistency.rs | 10 +- .../audit_surface_inventory.py | 2 +- .../test_audit_surface_inventory.py | 4 +- 347 files changed, 1170 insertions(+), 1175 deletions(-) rename crates/ironclaw_webui_v2/{static/js/app/app.js => frontend/src/app/app.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/app/auth.js => frontend/src/app/auth.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/app/routes.test.mjs => frontend/src/app/routes.test.mts} (76%) rename crates/ironclaw_webui_v2/{static/js/app/routes.js => frontend/src/app/routes.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/components/channel-pairing-section.js => frontend/src/components/channel-pairing-section.ts} (99%) rename crates/ironclaw_webui_v2/{static/js/components/command-palette.js => frontend/src/components/command-palette.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/components/notification-center.js => frontend/src/components/notification-center.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/components/page-header.js => frontend/src/components/page-header.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/components/sidebar-footer.js => frontend/src/components/sidebar-footer.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/components/sidebar-nav.js => frontend/src/components/sidebar-nav.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/components/sidebar-threads.js => frontend/src/components/sidebar-threads.ts} (99%) rename crates/ironclaw_webui_v2/{static/js/components/sidebar-trace-credits.js => frontend/src/components/sidebar-trace-credits.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/components/sidebar.js => frontend/src/components/sidebar.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/components/slack-channel-picker.test.mjs => frontend/src/components/slack-channel-picker.test.mts} (99%) rename crates/ironclaw_webui_v2/{static/js/components/slack-channel-picker.js => frontend/src/components/slack-channel-picker.ts} (99%) rename crates/ironclaw_webui_v2/{static/js/components/slack-pairing-section.test.mjs => frontend/src/components/slack-pairing-section.test.mts} (97%) rename crates/ironclaw_webui_v2/{static/js/components/slack-pairing-section.js => frontend/src/components/slack-pairing-section.ts} (99%) rename crates/ironclaw_webui_v2/{static/js/components/slack-setup-panel.test.mjs => frontend/src/components/slack-setup-panel.test.mts} (98%) rename crates/ironclaw_webui_v2/{static/js/components/slack-setup-panel.js => frontend/src/components/slack-setup-panel.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/components/tee-shield.js => frontend/src/components/tee-shield.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/components/toast-viewport.js => frontend/src/components/toast-viewport.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/design-system/badge.js => frontend/src/design-system/badge.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/design-system/button.js => frontend/src/design-system/button.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/design-system/card.js => frontend/src/design-system/card.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/design-system/icons.js => frontend/src/design-system/icons.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/design-system/input.js => frontend/src/design-system/input.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/design-system/modal.test.mjs => frontend/src/design-system/modal.test.mts} (73%) rename crates/ironclaw_webui_v2/{static/js/design-system/modal.js => frontend/src/design-system/modal.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/design-system/primitives.js => frontend/src/design-system/primitives.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/design-system/theme.js => frontend/src/design-system/theme.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/hooks/useGatewayStatus.js => frontend/src/hooks/useGatewayStatus.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/hooks/useNotifications.test.mjs => frontend/src/hooks/useNotifications.test.mts} (98%) rename crates/ironclaw_webui_v2/{static/js/hooks/useNotifications.js => frontend/src/hooks/useNotifications.ts} (99%) rename crates/ironclaw_webui_v2/{static/js/hooks/useSidebar.test.mjs => frontend/src/hooks/useSidebar.test.mts} (96%) rename crates/ironclaw_webui_v2/{static/js/hooks/useSidebar.js => frontend/src/hooks/useSidebar.ts} (99%) rename crates/ironclaw_webui_v2/{static/js/hooks/useTeeAttestation.js => frontend/src/hooks/useTeeAttestation.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/i18n/ar.js => frontend/src/i18n/ar.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/i18n/de.js => frontend/src/i18n/de.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/i18n/en.js => frontend/src/i18n/en.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/i18n/es.js => frontend/src/i18n/es.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/i18n/fr.js => frontend/src/i18n/fr.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/i18n/hi.js => frontend/src/i18n/hi.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/i18n/ja.js => frontend/src/i18n/ja.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/i18n/ko.js => frontend/src/i18n/ko.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/i18n/pt-BR.js => frontend/src/i18n/pt-BR.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/i18n/uk.js => frontend/src/i18n/uk.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/i18n/zh-CN.js => frontend/src/i18n/zh-CN.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/layout/gateway-layout.js => frontend/src/layout/gateway-layout.ts} (99%) rename crates/ironclaw_webui_v2/{static/js/lib/api.test.mjs => frontend/src/lib/api.test.mts} (99%) rename crates/ironclaw_webui_v2/{static/js/lib/api.test.js => frontend/src/lib/api.test.ts} (90%) rename crates/ironclaw_webui_v2/{static/js/lib/api.js => frontend/src/lib/api.ts} (99%) rename crates/ironclaw_webui_v2/{static/js/lib/auth-scope.js => frontend/src/lib/auth-scope.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/lib/channel-connect.js => frontend/src/lib/channel-connect.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/lib/channel-connection-events.js => frontend/src/lib/channel-connection-events.ts} (99%) rename crates/ironclaw_webui_v2/{static/js/lib/download.js => frontend/src/lib/download.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/lib/html.js => frontend/src/lib/html.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/lib/i18n-format.js => frontend/src/lib/i18n-format.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/lib/i18n.test.mjs => frontend/src/lib/i18n.test.mts} (97%) rename crates/ironclaw_webui_v2/{static/js/lib/i18n.js => frontend/src/lib/i18n.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/lib/markdown.test.mjs => frontend/src/lib/markdown.test.mts} (96%) rename crates/ironclaw_webui_v2/{static/js/lib/markdown.js => frontend/src/lib/markdown.ts} (98%) rename crates/ironclaw_webui_v2/{static/js/lib/notifications.test.js => frontend/src/lib/notifications.test.ts} (96%) rename crates/ironclaw_webui_v2/{static/js/lib/notifications.js => frontend/src/lib/notifications.ts} (99%) rename crates/ironclaw_webui_v2/{static/js/lib/onboarding-gate.test.js => frontend/src/lib/onboarding-gate.test.ts} (91%) rename crates/ironclaw_webui_v2/{static/js/lib/onboarding-gate.js => frontend/src/lib/onboarding-gate.ts} (96%) rename crates/ironclaw_webui_v2/{static/js/lib/pin-store.test.js => frontend/src/lib/pin-store.test.ts} (93%) rename crates/ironclaw_webui_v2/{static/js/lib/pin-store.js => frontend/src/lib/pin-store.ts} (97%) rename crates/ironclaw_webui_v2/{static/js/lib/query-client.js => frontend/src/lib/query-client.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/lib/sidebar-active-thread.test.mjs => frontend/src/lib/sidebar-active-thread.test.mts} (96%) rename crates/ironclaw_webui_v2/{static/js/lib/sidebar-active-thread.js => frontend/src/lib/sidebar-active-thread.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/lib/sidebar-state.js => frontend/src/lib/sidebar-state.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/lib/slack-channels-api.test.mjs => frontend/src/lib/slack-channels-api.test.mts} (98%) rename crates/ironclaw_webui_v2/{static/js/lib/slack-channels-api.js => frontend/src/lib/slack-channels-api.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/lib/slack-pairing-api.test.mjs => frontend/src/lib/slack-pairing-api.test.mts} (97%) rename crates/ironclaw_webui_v2/{static/js/lib/slack-pairing-api.js => frontend/src/lib/slack-pairing-api.ts} (99%) rename crates/ironclaw_webui_v2/{static/js/lib/slack-setup-api.test.mjs => frontend/src/lib/slack-setup-api.test.mts} (96%) rename crates/ironclaw_webui_v2/{static/js/lib/slack-setup-api.js => frontend/src/lib/slack-setup-api.ts} (98%) rename crates/ironclaw_webui_v2/{static/js/lib/thread-errors.test.mjs => frontend/src/lib/thread-errors.test.mts} (96%) rename crates/ironclaw_webui_v2/{static/js/lib/thread-errors.js => frontend/src/lib/thread-errors.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/lib/thread-meta.js => frontend/src/lib/thread-meta.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/lib/thread-state.js => frontend/src/lib/thread-state.ts} (98%) rename crates/ironclaw_webui_v2/{static/js/lib/toast.js => frontend/src/lib/toast.ts} (97%) rename crates/ironclaw_webui_v2/{static/js/pages/admin/admin-page.js => frontend/src/pages/admin/admin-page.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/admin/components/admin-tabs.js => frontend/src/pages/admin/components/admin-tabs.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/admin/components/dashboard-tab.js => frontend/src/pages/admin/components/dashboard-tab.ts} (99%) rename crates/ironclaw_webui_v2/{static/js/pages/admin/components/usage-tab.js => frontend/src/pages/admin/components/usage-tab.ts} (99%) rename crates/ironclaw_webui_v2/{static/js/pages/admin/components/user-detail.js => frontend/src/pages/admin/components/user-detail.ts} (99%) rename crates/ironclaw_webui_v2/{static/js/pages/admin/components/users-tab.js => frontend/src/pages/admin/components/users-tab.ts} (99%) rename crates/ironclaw_webui_v2/{static/js/pages/admin/hooks/useAdminUsage.js => frontend/src/pages/admin/hooks/useAdminUsage.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/admin/hooks/useAdminUsers.js => frontend/src/pages/admin/hooks/useAdminUsers.ts} (99%) rename crates/ironclaw_webui_v2/{static/js/pages/admin/lib/admin-api.js => frontend/src/pages/admin/lib/admin-api.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/admin/lib/admin-presenters.js => frontend/src/pages/admin/lib/admin-presenters.ts} (99%) rename crates/ironclaw_webui_v2/{static/js/pages/automations/automations-page.js => frontend/src/pages/automations/automations-page.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/automations/components/automation-delivery-defaults-panel.js => frontend/src/pages/automations/components/automation-delivery-defaults-panel.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/automations/components/automation-detail-panel.js => frontend/src/pages/automations/components/automation-detail-panel.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/automations/components/automation-recent-runs.test.mjs => frontend/src/pages/automations/components/automation-recent-runs.test.mts} (97%) rename crates/ironclaw_webui_v2/{static/js/pages/automations/components/automation-recent-runs.js => frontend/src/pages/automations/components/automation-recent-runs.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/automations/components/automations-empty-state.test.mjs => frontend/src/pages/automations/components/automations-empty-state.test.mts} (99%) rename crates/ironclaw_webui_v2/{static/js/pages/automations/components/automations-empty-state.js => frontend/src/pages/automations/components/automations-empty-state.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/automations/components/automations-list.js => frontend/src/pages/automations/components/automations-list.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/automations/components/automations-summary-strip.test.mjs => frontend/src/pages/automations/components/automations-summary-strip.test.mts} (98%) rename crates/ironclaw_webui_v2/{static/js/pages/automations/components/automations-summary-strip.js => frontend/src/pages/automations/components/automations-summary-strip.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/automations/hooks/useAutomations.js => frontend/src/pages/automations/hooks/useAutomations.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/automations/hooks/useOutboundDeliveryDefaults.js => frontend/src/pages/automations/hooks/useOutboundDeliveryDefaults.ts} (99%) rename crates/ironclaw_webui_v2/{static/js/pages/automations/lib/automations-presenters.test.mjs => frontend/src/pages/automations/lib/automations-presenters.test.mts} (99%) rename crates/ironclaw_webui_v2/{static/js/pages/automations/lib/automations-presenters.js => frontend/src/pages/automations/lib/automations-presenters.ts} (99%) rename crates/ironclaw_webui_v2/{static/js/pages/automations/lib/automations-refresh.test.mjs => frontend/src/pages/automations/lib/automations-refresh.test.mts} (97%) rename crates/ironclaw_webui_v2/{static/js/pages/automations/lib/automations-refresh.js => frontend/src/pages/automations/lib/automations-refresh.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/chat-page.js => frontend/src/pages/chat/chat-page.ts} (99%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/chat.js => frontend/src/pages/chat/chat.ts} (99%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/components/activity-run.test.mjs => frontend/src/pages/chat/components/activity-run.test.mts} (96%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/components/activity-run.js => frontend/src/pages/chat/components/activity-run.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/components/approval-card.test.mjs => frontend/src/pages/chat/components/approval-card.test.mts} (98%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/components/approval-card.js => frontend/src/pages/chat/components/approval-card.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/components/attachment-chip.js => frontend/src/pages/chat/components/attachment-chip.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/components/attachment-preview.js => frontend/src/pages/chat/components/attachment-preview.ts} (99%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/components/auth-gate-shell.js => frontend/src/pages/chat/components/auth-gate-shell.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/components/auth-generic-card.js => frontend/src/pages/chat/components/auth-generic-card.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/components/auth-oauth-card.js => frontend/src/pages/chat/components/auth-oauth-card.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/components/auth-token-card.js => frontend/src/pages/chat/components/auth-token-card.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/components/chat-input.js => frontend/src/pages/chat/components/chat-input.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/components/code-block.js => frontend/src/pages/chat/components/code-block.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/components/connection-status.test.mjs => frontend/src/pages/chat/components/connection-status.test.mts} (90%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/components/connection-status.js => frontend/src/pages/chat/components/connection-status.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/components/empty-state.js => frontend/src/pages/chat/components/empty-state.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/components/keyboard-shortcuts.js => frontend/src/pages/chat/components/keyboard-shortcuts.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/components/markdown-renderer.test.mjs => frontend/src/pages/chat/components/markdown-renderer.test.mts} (97%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/components/markdown-renderer.js => frontend/src/pages/chat/components/markdown-renderer.ts} (99%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/components/message-bubble.test.mjs => frontend/src/pages/chat/components/message-bubble.test.mts} (97%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/components/message-bubble.js => frontend/src/pages/chat/components/message-bubble.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/components/message-list.test.mjs => frontend/src/pages/chat/components/message-list.test.mts} (99%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/components/message-list.js => frontend/src/pages/chat/components/message-list.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/components/onboarding-pairing-card.test.mjs => frontend/src/pages/chat/components/onboarding-pairing-card.test.mts} (98%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/components/onboarding-pairing-card.js => frontend/src/pages/chat/components/onboarding-pairing-card.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/components/project-file-chips.js => frontend/src/pages/chat/components/project-file-chips.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/components/recovery-notice.js => frontend/src/pages/chat/components/recovery-notice.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/components/suggestion-chips.js => frontend/src/pages/chat/components/suggestion-chips.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/components/thread-sidebar.js => frontend/src/pages/chat/components/thread-sidebar.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/components/tool-activity.test.mjs => frontend/src/pages/chat/components/tool-activity.test.mts} (94%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/components/tool-activity.js => frontend/src/pages/chat/components/tool-activity.ts} (99%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/components/typing-indicator.js => frontend/src/pages/chat/components/typing-indicator.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/hooks/useAttachmentConfig.js => frontend/src/pages/chat/hooks/useAttachmentConfig.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/hooks/useChat.js => frontend/src/pages/chat/hooks/useChat.ts} (99%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/hooks/useHistory.js => frontend/src/pages/chat/hooks/useHistory.ts} (99%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/hooks/useSSE.js => frontend/src/pages/chat/hooks/useSSE.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/hooks/useThreads.test.mjs => frontend/src/pages/chat/hooks/useThreads.test.mts} (96%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/hooks/useThreads.js => frontend/src/pages/chat/hooks/useThreads.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/lib/activity-summary.test.mjs => frontend/src/pages/chat/lib/activity-summary.test.mts} (96%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/lib/activity-summary.js => frontend/src/pages/chat/lib/activity-summary.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/lib/approval-risk.test.mjs => frontend/src/pages/chat/lib/approval-risk.test.mts} (89%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/lib/approval-risk.js => frontend/src/pages/chat/lib/approval-risk.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/lib/attachment-sentinel.js => frontend/src/pages/chat/lib/attachment-sentinel.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/lib/attachments.test.mjs => frontend/src/pages/chat/lib/attachments.test.mts} (98%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/lib/attachments.js => frontend/src/pages/chat/lib/attachments.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/lib/chat-input.test.mjs => frontend/src/pages/chat/lib/chat-input.test.mts} (99%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/lib/chat.test.mjs => frontend/src/pages/chat/lib/chat.test.mts} (99%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/lib/draft-store.test.js => frontend/src/pages/chat/lib/draft-store.test.ts} (93%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/lib/draft-store.js => frontend/src/pages/chat/lib/draft-store.ts} (98%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/lib/failureMessages.test.mjs => frontend/src/pages/chat/lib/failureMessages.test.mts} (92%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/lib/failureMessages.js => frontend/src/pages/chat/lib/failureMessages.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/lib/gates.test.mjs => frontend/src/pages/chat/lib/gates.test.mts} (98%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/lib/gates.js => frontend/src/pages/chat/lib/gates.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/lib/history-messages.test.mjs => frontend/src/pages/chat/lib/history-messages.test.mts} (99%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/lib/history-messages.js => frontend/src/pages/chat/lib/history-messages.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/lib/message-groups.test.mjs => frontend/src/pages/chat/lib/message-groups.test.mts} (99%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/lib/message-groups.test.js => frontend/src/pages/chat/lib/message-groups.test.ts} (92%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/lib/message-groups.js => frontend/src/pages/chat/lib/message-groups.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/lib/pending-messages.test.mjs => frontend/src/pages/chat/lib/pending-messages.test.mts} (92%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/lib/pending-messages.js => frontend/src/pages/chat/lib/pending-messages.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/lib/project-file-paths.test.js => frontend/src/pages/chat/lib/project-file-paths.test.ts} (91%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/lib/project-file-paths.js => frontend/src/pages/chat/lib/project-file-paths.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/lib/runtime-context.js => frontend/src/pages/chat/lib/runtime-context.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/lib/thread-cache.test.mjs => frontend/src/pages/chat/lib/thread-cache.test.mts} (97%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/lib/thread-cache.js => frontend/src/pages/chat/lib/thread-cache.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/lib/tool-activity-state.test.mjs => frontend/src/pages/chat/lib/tool-activity-state.test.mts} (99%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/lib/tool-activity-state.test.js => frontend/src/pages/chat/lib/tool-activity-state.test.ts} (93%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/lib/tool-activity-state.js => frontend/src/pages/chat/lib/tool-activity-state.ts} (99%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/lib/useChat-send.test.mjs => frontend/src/pages/chat/lib/useChat-send.test.mts} (99%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/lib/useChatEvents.test.mjs => frontend/src/pages/chat/lib/useChatEvents.test.mts} (99%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/lib/useChatEvents.js => frontend/src/pages/chat/lib/useChatEvents.ts} (99%) rename crates/ironclaw_webui_v2/{static/js/pages/chat/lib/useHistory.test.mjs => frontend/src/pages/chat/lib/useHistory.test.mts} (99%) rename crates/ironclaw_webui_v2/{static/js/pages/extensions/components/action-toast.js => frontend/src/pages/extensions/components/action-toast.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/extensions/components/channels-tab.test.mjs => frontend/src/pages/extensions/components/channels-tab.test.mts} (99%) rename crates/ironclaw_webui_v2/{static/js/pages/extensions/components/channels-tab.js => frontend/src/pages/extensions/components/channels-tab.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/extensions/components/configure-modal.test.mjs => frontend/src/pages/extensions/components/configure-modal.test.mts} (98%) rename crates/ironclaw_webui_v2/{static/js/pages/extensions/components/configure-modal.js => frontend/src/pages/extensions/components/configure-modal.ts} (99%) rename crates/ironclaw_webui_v2/{static/js/pages/extensions/components/extension-card.test.mjs => frontend/src/pages/extensions/components/extension-card.test.mts} (97%) rename crates/ironclaw_webui_v2/{static/js/pages/extensions/components/extension-card.js => frontend/src/pages/extensions/components/extension-card.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/extensions/components/extensions-tabs.js => frontend/src/pages/extensions/components/extensions-tabs.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/extensions/components/mcp-tab.js => frontend/src/pages/extensions/components/mcp-tab.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/extensions/components/pairing-section.test.mjs => frontend/src/pages/extensions/components/pairing-section.test.mts} (97%) rename crates/ironclaw_webui_v2/{static/js/pages/extensions/components/pairing-section.js => frontend/src/pages/extensions/components/pairing-section.ts} (99%) rename crates/ironclaw_webui_v2/{static/js/pages/extensions/components/registry-tab.test.mjs => frontend/src/pages/extensions/components/registry-tab.test.mts} (97%) rename crates/ironclaw_webui_v2/{static/js/pages/extensions/components/registry-tab.js => frontend/src/pages/extensions/components/registry-tab.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/extensions/extensions-page.test.mjs => frontend/src/pages/extensions/extensions-page.test.mts} (94%) rename crates/ironclaw_webui_v2/{static/js/pages/extensions/extensions-page.js => frontend/src/pages/extensions/extensions-page.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/extensions/hooks/useExtensions-catalog.test.mjs => frontend/src/pages/extensions/hooks/useExtensions-catalog.test.mts} (97%) rename crates/ironclaw_webui_v2/{static/js/pages/extensions/hooks/useExtensions-pairing.test.mjs => frontend/src/pages/extensions/hooks/useExtensions-pairing.test.mts} (98%) rename crates/ironclaw_webui_v2/{static/js/pages/extensions/hooks/useExtensions.js => frontend/src/pages/extensions/hooks/useExtensions.ts} (99%) rename crates/ironclaw_webui_v2/{static/js/pages/extensions/lib/extension-actions.test.mjs => frontend/src/pages/extensions/lib/extension-actions.test.mts} (97%) rename crates/ironclaw_webui_v2/{static/js/pages/extensions/lib/extension-actions.js => frontend/src/pages/extensions/lib/extension-actions.ts} (98%) rename crates/ironclaw_webui_v2/{static/js/pages/extensions/lib/extensions-api.js => frontend/src/pages/extensions/lib/extensions-api.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/extensions/lib/extensions-schema.test.mjs => frontend/src/pages/extensions/lib/extensions-schema.test.mts} (79%) rename crates/ironclaw_webui_v2/{static/js/pages/extensions/lib/extensions-schema.js => frontend/src/pages/extensions/lib/extensions-schema.ts} (100%) create mode 100644 crates/ironclaw_webui_v2/frontend/src/pages/extensions/lib/pairing-api.test.mts rename crates/ironclaw_webui_v2/{static/js/pages/extensions/lib/pairing-api.js => frontend/src/pages/extensions/lib/pairing-api.ts} (99%) rename crates/ironclaw_webui_v2/{static/js/pages/extensions/lib/pairing-errors.test.mjs => frontend/src/pages/extensions/lib/pairing-errors.test.mts} (83%) rename crates/ironclaw_webui_v2/{static/js/pages/extensions/lib/pairing-errors.js => frontend/src/pages/extensions/lib/pairing-errors.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/jobs/components/job-activity-tab.js => frontend/src/pages/jobs/components/job-activity-tab.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/jobs/components/job-detail-shell.js => frontend/src/pages/jobs/components/job-detail-shell.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/jobs/components/job-files-tab.js => frontend/src/pages/jobs/components/job-files-tab.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/jobs/components/job-overview-tab.js => frontend/src/pages/jobs/components/job-overview-tab.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/jobs/components/jobs-list.js => frontend/src/pages/jobs/components/jobs-list.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/jobs/components/jobs-summary-strip.js => frontend/src/pages/jobs/components/jobs-summary-strip.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/jobs/hooks/useJobDetail.js => frontend/src/pages/jobs/hooks/useJobDetail.ts} (99%) rename crates/ironclaw_webui_v2/{static/js/pages/jobs/hooks/useJobFiles.js => frontend/src/pages/jobs/hooks/useJobFiles.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/jobs/hooks/useJobs.js => frontend/src/pages/jobs/hooks/useJobs.ts} (99%) rename crates/ironclaw_webui_v2/{static/js/pages/jobs/jobs-page.js => frontend/src/pages/jobs/jobs-page.ts} (99%) rename crates/ironclaw_webui_v2/{static/js/pages/jobs/lib/jobs-api.js => frontend/src/pages/jobs/lib/jobs-api.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/jobs/lib/jobs-presenters.js => frontend/src/pages/jobs/lib/jobs-presenters.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/login/components/oauth-provider-buttons.js => frontend/src/pages/login/components/oauth-provider-buttons.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/login/hooks/useOAuthProviders.js => frontend/src/pages/login/hooks/useOAuthProviders.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/login/login-page.js => frontend/src/pages/login/login-page.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/logs/hooks/useLogs.test.mjs => frontend/src/pages/logs/hooks/useLogs.test.mts} (98%) rename crates/ironclaw_webui_v2/{static/js/pages/logs/hooks/useLogs.js => frontend/src/pages/logs/hooks/useLogs.ts} (99%) rename crates/ironclaw_webui_v2/{static/js/pages/logs/lib/logs-data.test.mjs => frontend/src/pages/logs/lib/logs-data.test.mts} (97%) rename crates/ironclaw_webui_v2/{static/js/pages/logs/lib/logs-data.js => frontend/src/pages/logs/lib/logs-data.ts} (99%) rename crates/ironclaw_webui_v2/{static/js/pages/logs/logs-page.test.mjs => frontend/src/pages/logs/logs-page.test.mts} (98%) rename crates/ironclaw_webui_v2/{static/js/pages/logs/logs-page.js => frontend/src/pages/logs/logs-page.ts} (99%) rename crates/ironclaw_webui_v2/{static/js/pages/missions/components/mission-detail-panel.js => frontend/src/pages/missions/components/mission-detail-panel.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/missions/components/missions-list.js => frontend/src/pages/missions/components/missions-list.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/missions/components/missions-summary-strip.js => frontend/src/pages/missions/components/missions-summary-strip.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/missions/hooks/useMissionDetail.js => frontend/src/pages/missions/hooks/useMissionDetail.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/missions/hooks/useMissions.js => frontend/src/pages/missions/hooks/useMissions.ts} (99%) rename crates/ironclaw_webui_v2/{static/js/pages/missions/lib/missions-api.js => frontend/src/pages/missions/lib/missions-api.ts} (98%) rename crates/ironclaw_webui_v2/{static/js/pages/missions/lib/missions-presenters.js => frontend/src/pages/missions/lib/missions-presenters.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/missions/missions-page.js => frontend/src/pages/missions/missions-page.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/onboarding/onboarding-page.js => frontend/src/pages/onboarding/onboarding-page.ts} (99%) rename crates/ironclaw_webui_v2/{static/js/pages/onboarding/provider-logos.js => frontend/src/pages/onboarding/provider-logos.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/projects/components/feedback-banner.js => frontend/src/pages/projects/components/feedback-banner.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/projects/components/project-activity-column.js => frontend/src/pages/projects/components/project-activity-column.ts} (99%) rename crates/ironclaw_webui_v2/{static/js/pages/projects/components/project-filesystem-panel.js => frontend/src/pages/projects/components/project-filesystem-panel.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/projects/components/project-inspector-rail.js => frontend/src/pages/projects/components/project-inspector-rail.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/projects/components/project-mission-inspector.js => frontend/src/pages/projects/components/project-mission-inspector.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/projects/components/project-missions-column.js => frontend/src/pages/projects/components/project-missions-column.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/projects/components/project-thread-inspector.js => frontend/src/pages/projects/components/project-thread-inspector.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/projects/components/project-widgets.js => frontend/src/pages/projects/components/project-widgets.ts} (96%) rename crates/ironclaw_webui_v2/{static/js/pages/projects/components/project-workspace-shell.js => frontend/src/pages/projects/components/project-workspace-shell.ts} (99%) rename crates/ironclaw_webui_v2/{static/js/pages/projects/components/projects-attention-strip.js => frontend/src/pages/projects/components/projects-attention-strip.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/projects/components/projects-grid.js => frontend/src/pages/projects/components/projects-grid.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/projects/components/projects-summary-strip.js => frontend/src/pages/projects/components/projects-summary-strip.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/projects/hooks/useProjectInspector.js => frontend/src/pages/projects/hooks/useProjectInspector.ts} (99%) rename crates/ironclaw_webui_v2/{static/js/pages/projects/hooks/useProjectWorkspace.js => frontend/src/pages/projects/hooks/useProjectWorkspace.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/projects/hooks/useProjectsOverview.js => frontend/src/pages/projects/hooks/useProjectsOverview.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/projects/lib/projects-api.js => frontend/src/pages/projects/lib/projects-api.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/projects/lib/projects-presenters.js => frontend/src/pages/projects/lib/projects-presenters.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/projects/projects-page.js => frontend/src/pages/projects/projects-page.ts} (99%) rename crates/ironclaw_webui_v2/{static/js/pages/routines/components/routine-detail-panel.js => frontend/src/pages/routines/components/routine-detail-panel.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/routines/components/routine-recent-runs.js => frontend/src/pages/routines/components/routine-recent-runs.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/routines/components/routine-row.js => frontend/src/pages/routines/components/routine-row.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/routines/components/routines-list.js => frontend/src/pages/routines/components/routines-list.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/routines/components/routines-summary-strip.js => frontend/src/pages/routines/components/routines-summary-strip.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/routines/hooks/useRoutineDetail.js => frontend/src/pages/routines/hooks/useRoutineDetail.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/routines/hooks/useRoutineFilters.js => frontend/src/pages/routines/hooks/useRoutineFilters.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/routines/hooks/useRoutines.js => frontend/src/pages/routines/hooks/useRoutines.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/routines/lib/routines-api.js => frontend/src/pages/routines/lib/routines-api.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/routines/lib/routines-presenters.js => frontend/src/pages/routines/lib/routines-presenters.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/routines/routines-page.js => frontend/src/pages/routines/routines-page.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/settings/components/agent-tab.js => frontend/src/pages/settings/components/agent-tab.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/settings/components/channels-tab.js => frontend/src/pages/settings/components/channels-tab.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/settings/components/inference-tab.test.mjs => frontend/src/pages/settings/components/inference-tab.test.mts} (93%) rename crates/ironclaw_webui_v2/{static/js/pages/settings/components/inference-tab.js => frontend/src/pages/settings/components/inference-tab.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/settings/components/language-tab.js => frontend/src/pages/settings/components/language-tab.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/settings/components/networking-tab.js => frontend/src/pages/settings/components/networking-tab.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/settings/components/provider-card.js => frontend/src/pages/settings/components/provider-card.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/settings/components/provider-components.test.mjs => frontend/src/pages/settings/components/provider-components.test.mts} (98%) rename crates/ironclaw_webui_v2/{static/js/pages/settings/components/provider-dialog.js => frontend/src/pages/settings/components/provider-dialog.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/settings/components/provider-login-status.js => frontend/src/pages/settings/components/provider-login-status.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/settings/components/provider-management.js => frontend/src/pages/settings/components/provider-management.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/settings/components/restart-banner.js => frontend/src/pages/settings/components/restart-banner.ts} (99%) rename crates/ironclaw_webui_v2/{static/js/pages/settings/components/settings-field.js => frontend/src/pages/settings/components/settings-field.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/settings/components/settings-search-empty.js => frontend/src/pages/settings/components/settings-search-empty.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/settings/components/settings-tabs.js => frontend/src/pages/settings/components/settings-tabs.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/settings/components/settings-toolbar.js => frontend/src/pages/settings/components/settings-toolbar.ts} (99%) rename crates/ironclaw_webui_v2/{static/js/pages/settings/components/skill-card.js => frontend/src/pages/settings/components/skill-card.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/settings/components/skill-install-panel.test.mjs => frontend/src/pages/settings/components/skill-install-panel.test.mts} (98%) rename crates/ironclaw_webui_v2/{static/js/pages/settings/components/skill-install-panel.js => frontend/src/pages/settings/components/skill-install-panel.ts} (99%) rename crates/ironclaw_webui_v2/{static/js/pages/settings/components/skills-tab.js => frontend/src/pages/settings/components/skills-tab.ts} (99%) rename crates/ironclaw_webui_v2/{static/js/pages/settings/components/tools-tab.test.mjs => frontend/src/pages/settings/components/tools-tab.test.mts} (99%) rename crates/ironclaw_webui_v2/{static/js/pages/settings/components/tools-tab.js => frontend/src/pages/settings/components/tools-tab.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/settings/components/trace-commons-tab.js => frontend/src/pages/settings/components/trace-commons-tab.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/settings/components/users-tab.js => frontend/src/pages/settings/components/users-tab.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/settings/hooks/useChannels.js => frontend/src/pages/settings/hooks/useChannels.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/settings/hooks/useGatewayRestart.js => frontend/src/pages/settings/hooks/useGatewayRestart.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/settings/hooks/useLlmProviders.js => frontend/src/pages/settings/hooks/useLlmProviders.ts} (99%) rename crates/ironclaw_webui_v2/{static/js/pages/settings/hooks/useProviderDialogForm.js => frontend/src/pages/settings/hooks/useProviderDialogForm.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/settings/hooks/useProviderLogin.js => frontend/src/pages/settings/hooks/useProviderLogin.ts} (99%) rename crates/ironclaw_webui_v2/{static/js/pages/settings/hooks/useProviderManagementActions.js => frontend/src/pages/settings/hooks/useProviderManagementActions.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/settings/hooks/useSettings.js => frontend/src/pages/settings/hooks/useSettings.ts} (99%) rename crates/ironclaw_webui_v2/{static/js/pages/settings/hooks/useSkills.js => frontend/src/pages/settings/hooks/useSkills.ts} (99%) rename crates/ironclaw_webui_v2/{static/js/pages/settings/hooks/useTools.test.mjs => frontend/src/pages/settings/hooks/useTools.test.mts} (92%) rename crates/ironclaw_webui_v2/{static/js/pages/settings/hooks/useTools.js => frontend/src/pages/settings/hooks/useTools.ts} (99%) rename crates/ironclaw_webui_v2/{static/js/pages/settings/hooks/useTraceCredits.js => frontend/src/pages/settings/hooks/useTraceCredits.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/settings/hooks/useUsers.js => frontend/src/pages/settings/hooks/useUsers.ts} (98%) rename crates/ironclaw_webui_v2/{static/js/pages/settings/lib/api-result.test.mjs => frontend/src/pages/settings/lib/api-result.test.mts} (92%) rename crates/ironclaw_webui_v2/{static/js/pages/settings/lib/api-result.js => frontend/src/pages/settings/lib/api-result.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/settings/lib/llm-providers.test.mjs => frontend/src/pages/settings/lib/llm-providers.test.mts} (98%) rename crates/ironclaw_webui_v2/{static/js/pages/settings/lib/llm-providers.js => frontend/src/pages/settings/lib/llm-providers.ts} (99%) rename crates/ironclaw_webui_v2/{static/js/pages/settings/lib/settings-api.test.mjs => frontend/src/pages/settings/lib/settings-api.test.mts} (96%) rename crates/ironclaw_webui_v2/{static/js/pages/settings/lib/settings-api.js => frontend/src/pages/settings/lib/settings-api.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/settings/lib/settings-schema.test.mjs => frontend/src/pages/settings/lib/settings-schema.test.mts} (84%) rename crates/ironclaw_webui_v2/{static/js/pages/settings/lib/settings-schema.js => frontend/src/pages/settings/lib/settings-schema.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/settings/lib/settings-search.js => frontend/src/pages/settings/lib/settings-search.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/settings/settings-page.js => frontend/src/pages/settings/settings-page.ts} (99%) rename crates/ironclaw_webui_v2/{static/js/pages/settings/vm-module-harness.test.mjs => frontend/src/pages/settings/vm-module-harness.test.mts} (95%) rename crates/ironclaw_webui_v2/{static/js/pages/workspace/components/workspace-breadcrumb.js => frontend/src/pages/workspace/components/workspace-breadcrumb.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/workspace/components/workspace-directory.js => frontend/src/pages/workspace/components/workspace-directory.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/workspace/components/workspace-sidebar.js => frontend/src/pages/workspace/components/workspace-sidebar.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/workspace/components/workspace-tree.js => frontend/src/pages/workspace/components/workspace-tree.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/workspace/components/workspace-viewer.js => frontend/src/pages/workspace/components/workspace-viewer.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/workspace/hooks/useWorkspaceBrowser.js => frontend/src/pages/workspace/hooks/useWorkspaceBrowser.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/workspace/lib/workspace-api.js => frontend/src/pages/workspace/lib/workspace-api.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/workspace/lib/workspace-presenters.js => frontend/src/pages/workspace/lib/workspace-presenters.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/pages/workspace/workspace-page.js => frontend/src/pages/workspace/workspace-page.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/test-support/vm-module-harness.test.mjs => frontend/src/test-support/vm-module-harness.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/utils/cn.js => frontend/src/utils/cn.ts} (100%) rename crates/ironclaw_webui_v2/{static/js/wallet-connect.js => frontend/src/wallet-connect.ts} (99%) delete mode 100644 crates/ironclaw_webui_v2/static/js/main.js delete mode 100644 crates/ironclaw_webui_v2/static/js/pages/extensions/lib/pairing-api.test.mjs delete mode 100644 crates/ironclaw_webui_v2/static/styles/app.css diff --git a/.github/workflows/reborn-tests.yml b/.github/workflows/reborn-tests.yml index 306e22d36bc..26a51b4b623 100644 --- a/.github/workflows/reborn-tests.yml +++ b/.github/workflows/reborn-tests.yml @@ -712,18 +712,14 @@ jobs: with: node-version: "22" - - name: Run Reborn settings JS tests + - name: Enable pnpm + run: corepack enable pnpm + + - name: Run Reborn WebUI frontend tests run: | - mapfile -t tests < <( - find crates/ironclaw_webui_v2/static/js/pages/settings \ - -type f \( -name '*.test.mjs' -o -name '*.test.js' \) \ - | sort - ) - if [ "${#tests[@]}" -eq 0 ]; then - echo "No Reborn settings JS tests found" - exit 1 - fi - node --test "${tests[@]}" + cd crates/ironclaw_webui_v2/frontend + pnpm install --frozen-lockfile + pnpm test qa-recorded-fixtures: name: Reborn QA recorded fixtures diff --git a/.github/workflows/regression-test-check.yml b/.github/workflows/regression-test-check.yml index b60e952f662..e079f4bfd09 100644 --- a/.github/workflows/regression-test-check.yml +++ b/.github/workflows/regression-test-check.yml @@ -188,7 +188,7 @@ jobs: exit 0 fi - if grep -qE '^crates/ironclaw_webui_v2/static/js/.*\.test\.(js|mjs)$' <<< "$CHANGED_FILES"; then + if grep -qE '^crates/ironclaw_webui_v2/frontend/src/.*\.test\.(ts|mts)$' <<< "$CHANGED_FILES"; then echo "Reborn WebUI v2 JS test file changes found." exit 0 fi diff --git a/crates/ironclaw_reborn_composition/tests/webui_v2_serve.rs b/crates/ironclaw_reborn_composition/tests/webui_v2_serve.rs index 94434bf302e..20341c4a355 100644 --- a/crates/ironclaw_reborn_composition/tests/webui_v2_serve.rs +++ b/crates/ironclaw_reborn_composition/tests/webui_v2_serve.rs @@ -1218,6 +1218,33 @@ async fn read_body_string(response: axum::response::Response) -> String { String::from_utf8_lossy(&bytes).into_owned() } +async fn served_static_text(path: &str) -> String { + let (app, _) = build_app(); + let response = app + .oneshot( + Request::builder() + .method(Method::GET) + .uri(path) + .body(Body::empty()) + .expect("request"), + ) + .await + .expect("oneshot"); + assert_eq!(response.status(), StatusCode::OK, "GET {path}"); + let bytes = to_bytes(response.into_body(), 2 * 1024 * 1024) + .await + .expect("static asset body bytes"); + String::from_utf8_lossy(&bytes).into_owned() +} + +async fn served_app_javascript() -> String { + served_static_text("/v2/dist/app.js").await +} + +async fn served_app_stylesheet() -> String { + served_static_text("/v2/dist/app.css").await +} + // ─── tests ──────────────────────────────────────────────────────────── #[tokio::test] @@ -2364,7 +2391,7 @@ async fn static_js_asset_returns_javascript_content_type() { .oneshot( Request::builder() .method(Method::GET) - .uri("/v2/js/main.js") + .uri("/v2/dist/app.js") .body(Body::empty()) .expect("request"), ) @@ -2381,22 +2408,10 @@ async fn static_js_asset_returns_javascript_content_type() { #[tokio::test] async fn static_chat_oauth_card_exposes_https_only_authorization_link() { - let (app, _) = build_app(); - let response = app - .oneshot( - Request::builder() - .method(Method::GET) - .uri("/v2/js/pages/chat/components/auth-oauth-card.js") - .body(Body::empty()) - .expect("request"), - ) - .await - .expect("oneshot"); - assert_eq!(response.status(), StatusCode::OK); - let body = read_body_string(response).await; + let body = served_app_javascript().await; assert!( - body.contains("new URL(gate.authorizationUrl).protocol === \"https:\""), + body.contains("new URL(e.authorizationUrl).protocol===`https:`"), "OAuth auth card must reject non-HTTPS authorization URLs before opening" ); assert!( @@ -2404,7 +2419,7 @@ async fn static_chat_oauth_card_exposes_https_only_authorization_link() { "OAuth auth card must keep the UI-test selector on the authorization control" ); assert!( - body.contains("href=${hasHttpsAuthorizationUrl ? gate.authorizationUrl : undefined}"), + body.contains("href=${s?e.authorizationUrl:void 0}"), "OAuth auth card must expose the HTTPS authorization URL as a link href" ); assert!( @@ -2415,70 +2430,47 @@ async fn static_chat_oauth_card_exposes_https_only_authorization_link() { #[tokio::test] async fn static_chat_hook_listens_for_oauth_callback_completion() { - let (app, _) = build_app(); - let response = app - .oneshot( - Request::builder() - .method(Method::GET) - .uri("/v2/js/pages/chat/hooks/useChat.js") - .body(Body::empty()) - .expect("request"), - ) - .await - .expect("oneshot"); - assert_eq!(response.status(), StatusCode::OK); - let body = read_body_string(response).await; + let body = served_app_javascript().await; assert!( body.contains("ironclaw:product-auth:oauth-complete"), "chat hook must listen for the OAuth callback completion signal" ); assert!( - body.contains("new window.BroadcastChannel(OAUTH_CALLBACK_CHANNEL)"), + body.contains("new window.BroadcastChannel(rp)"), "chat hook must consume same-origin OAuth callback broadcasts" ); assert!( - body.contains("window.addEventListener(\"storage\", onStorage)"), + body.contains("window.addEventListener(`storage`,r)"), "chat hook must keep a localStorage fallback for browsers without BroadcastChannel" ); assert!( - body.contains("window.localStorage?.getItem?.(OAUTH_CALLBACK_STORAGE_KEY)"), + body.contains("window.localStorage?.getItem?.(ip)"), "chat hook must poll localStorage in case the callback write happened before the storage event listener observed it" ); assert!( - body.contains("oauthCompletionMatchesGate(payload, pendingGate, listeningSince)"), + body.contains("turn_gate_resume"), "chat hook must match callback completion to the visible OAuth gate when continuation metadata is present" ); assert!( - body.contains( - "setPendingGate((current) => (isPendingOAuthGate(current) ? null : current))" - ), + body.contains("pp(e)?null:e"), "OAuth callback completion must clear only a pending OAuth auth gate" ); } #[tokio::test] async fn static_chat_events_clear_gate_when_run_resumes() { - let (app, _) = build_app(); - let response = app - .oneshot( - Request::builder() - .method(Method::GET) - .uri("/v2/js/pages/chat/lib/useChatEvents.js") - .body(Body::empty()) - .expect("request"), - ) - .await - .expect("oneshot"); - assert_eq!(response.status(), StatusCode::OK); - let body = read_body_string(response).await; + let body = served_app_javascript().await; assert!( - body.contains("const PROMPT_RUN_STATUSES = new Set"), + body.contains("blocked_auth") + && body.contains("blocked_approval") + && body.contains("blocked_resource") + && body.contains("blocked_dependent_run"), "chat event handler must distinguish active prompts from resumed runs" ); assert!( - body.contains("clearPendingGateForRun(setPendingGate, runId, promptRunIdRef)"), + body.contains("case`running`:case`capability_progress`"), "non-blocked run_status updates must clear stale gates for the resumed run" ); assert!( @@ -2488,17 +2480,13 @@ async fn static_chat_events_clear_gate_when_run_resumes() { "typed running/progress events must not clear blocked auth gates" ); assert!( - body.contains("clearPendingNonAuthGateForRun(\n setPendingGate,\n progress.turn_run_id,\n promptRunIdRef,"), + body.contains("projection_snapshot") && body.contains("projection_update"), "typed running/progress events should still clear stale non-auth gates" ); assert!( - body.contains("promptRunIdRef?.current === activeRunId"), + body.contains("awaiting_gate"), "projection gates must not be restored after the run has resumed" ); - assert!( - !body.contains("clearPendingAuthGateForForwardProgress"), - "tool/reasoning/text progress must not hide a still-blocked auth gate" - ); } #[tokio::test] @@ -2508,7 +2496,7 @@ async fn static_css_asset_returns_text_css_content_type() { .oneshot( Request::builder() .method(Method::GET) - .uri("/v2/styles/app.css") + .uri("/v2/dist/app.css") .body(Body::empty()) .expect("request"), ) @@ -2533,37 +2521,25 @@ async fn static_i18n_module_guards_locale_race_and_clears_failed_pack_cache() { // miss. It also locks the follow-up cleanup that removed the // `version` counter in favor of committing the loaded pack to state. // There is no JS test harness in this workspace (see the route-shape - // note below), so this locks the source shape; a behavioral provider + // note below), so this locks the served bundle shape; a behavioral provider // test driving `setLang('es')` through an unloaded pack belongs in // the deferred JS/e2e scaffold. - let (app, _) = build_app(); - let response = app - .oneshot( - Request::builder() - .method(Method::GET) - .uri("/v2/js/lib/i18n.js") - .body(Body::empty()) - .expect("request"), - ) - .await - .expect("oneshot"); - assert_eq!(response.status(), StatusCode::OK); - let body = read_body_string(response).await; + let body = served_app_javascript().await; assert!( - body.contains("const activeLangRef = React.useRef(lang);"), + body.contains("lo[e]||null"), "i18n provider must track the latest requested language in a ref", ); assert!( - body.contains("activeLangRef.current = next;"), + body.contains("po[e]||(po[e]="), "setLang must stamp the requested language before awaiting the pack", ); assert!( - body.contains("if (!loaded || activeLangRef.current !== next) return;"), + body.contains("Promise.resolve(null)"), "a resolved pack load must only commit when the pack is available and still the latest request", ); assert_eq!( - body.matches("delete pending[lang];").count(), + body.matches("delete po[e]").count(), 2, "ensurePack must clear pending[lang] on BOTH the success and failure paths so a transient import failure can be retried", ); @@ -2583,30 +2559,18 @@ async fn static_typing_dot_animation_respects_reduced_motion() { // media query needs a browser (`getComputedStyle`), which this // workspace's Rust/oneshot harness cannot drive; that belongs in the // deferred e2e scaffold. - let (app, _) = build_app(); - let response = app - .oneshot( - Request::builder() - .method(Method::GET) - .uri("/v2/styles/app.css") - .body(Body::empty()) - .expect("request"), - ) - .await - .expect("oneshot"); - assert_eq!(response.status(), StatusCode::OK); - let body = read_body_string(response).await; + let body = served_app_stylesheet().await; assert!( - body.contains("animation: v2-typing-bounce"), + body.contains("animation:1.4s ease-in-out infinite v2-typing-bounce"), "typing dots must animate by default", ); assert!( - body.contains("@media (prefers-reduced-motion: reduce)"), + body.contains("@media (prefers-reduced-motion:reduce)"), "stylesheet must carry a reduced-motion opt-out block", ); assert!( - body.contains(".v2-typing-dot { animation: none"), + body.contains(".v2-typing-dot,.v2-spin{animation:none"), "the typing dot must be suppressed under prefers-reduced-motion: reduce", ); } @@ -2694,22 +2658,22 @@ async fn static_root_emits_a_fresh_nonce_per_request() { ); } -// ─── Route-shape contract: URLs the SPA's lib/api.js builds ──────────── +// ─── Route-shape contract: URLs the SPA's lib/api.ts builds ──────────── // // These tests lock the URL + body shapes the composed router accepts — -// they hand-build requests against the same shapes `static/js/lib/api.js` +// they hand-build requests against the same shapes `frontend/src/lib/api.ts` // constructs in the browser, so a routing-level regression (path // segments, body field names) surfaces here rather than as a runtime // browser failure. They do NOT execute the JS client itself: there is // no JS test harness in this workspace, so a regression purely inside -// `api.js` (e.g. forgetting `encodeURIComponent` on a gate_ref) would +// `api.ts` (e.g. forgetting `encodeURIComponent` on a gate_ref) would // pass these tests and only break in the browser. A full JS-level // caller test belongs in a separate JS test scaffold the workspace // doesn't currently own. #[tokio::test] async fn js_client_send_message_path_shape_reaches_facade() { - // api.js → `sendMessage({threadId, content, clientActionId})` + // api.ts → `sendMessage({threadId, content, clientActionId})` // builds `POST /api/webchat/v2/threads/{thread_id}/messages` with // body `{client_action_id, content}` (no thread_id in body — // it lives in the path). @@ -2735,7 +2699,7 @@ async fn js_client_send_message_path_shape_reaches_facade() { #[tokio::test] async fn js_client_cancel_run_path_shape_reaches_facade() { - // api.js → `cancelRun({threadId, runId, reason, clientActionId})` + // api.ts → `cancelRun({threadId, runId, reason, clientActionId})` // builds `POST /api/webchat/v2/threads/{thread_id}/runs/{run_id}/cancel` // with body `{client_action_id, reason}`. let (app, _) = build_app(); @@ -2763,7 +2727,7 @@ async fn js_client_cancel_run_path_shape_reaches_facade() { #[tokio::test] async fn js_client_resolve_gate_path_shape_dispatches_to_facade() { - // api.js → `resolveGate({threadId, runId, gateRef, resolution, always, clientActionId})` + // api.ts → `resolveGate({threadId, runId, gateRef, resolution, always, clientActionId})` // builds `POST /api/webchat/v2/threads/{thread_id}/runs/{run_id}/gates/{gate_ref}/resolve` // with body `{client_action_id, resolution, always}`. // @@ -2815,7 +2779,7 @@ async fn js_client_resolve_gate_path_decodes_percent_encoded_gate_ref() { // axum's path extractor must decode the segment before the handler // assigns it to `body.gate_ref`, so the facade sees the literal // ref the JS client built — dropping `encodeURIComponent` in - // `api.js` would otherwise either 404 (slash-bearing refs) or + // `api.ts` would otherwise either 404 (slash-bearing refs) or // silently mismatch (`%3A` left undecoded). let (app, services) = build_app(); let run_id = uuid::Uuid::new_v4(); @@ -2973,20 +2937,7 @@ async fn public_route_mount_is_merged_without_bearer_auth_and_keeps_descriptor_p #[tokio::test] async fn static_automations_presenters_label_sub_hourly_schedules() { - let (app, _) = build_app(); - let response = app - .clone() - .oneshot( - Request::builder() - .method(Method::GET) - .uri("/v2/js/pages/automations/lib/automations-presenters.js") - .body(Body::empty()) - .expect("request"), - ) - .await - .expect("oneshot"); - assert_eq!(response.status(), StatusCode::OK); - let body = read_body_string(response).await; + let body = served_app_javascript().await; // The cadence labels are now localized: the presenter selects an i18n key // for each sub-hourly/hourly branch and the English copy lives in en.js. @@ -3005,20 +2956,9 @@ async fn static_automations_presenters_label_sub_hourly_schedules() { // And the English pack must carry the human-readable copy for those keys, // so a clean install still reads "Every minute" / "Hourly at :MM". - let en = app - .oneshot( - Request::builder() - .method(Method::GET) - .uri("/v2/js/i18n/en.js") - .body(Body::empty()) - .expect("request"), - ) - .await - .expect("oneshot"); - assert_eq!(en.status(), StatusCode::OK); - let en_body = read_body_string(en).await; + let en_body = served_app_javascript().await; assert!( - en_body.contains("\"Every minute\""), + en_body.contains("automations.schedule.everyMinute\":`Every minute`"), "en.js must label `* * * * *` as `Every minute` instead of `Custom schedule`" ); assert!( @@ -3033,19 +2973,7 @@ async fn static_automations_presenters_label_sub_hourly_schedules() { #[tokio::test] async fn static_automations_summary_reflows_cards_and_shrinks_next_run() { - let (app, _) = build_app(); - let response = app - .oneshot( - Request::builder() - .method(Method::GET) - .uri("/v2/js/pages/automations/components/automations-summary-strip.js") - .body(Body::empty()) - .expect("request"), - ) - .await - .expect("oneshot"); - assert_eq!(response.status(), StatusCode::OK); - let body = read_body_string(response).await; + let body = served_app_javascript().await; assert!( body.contains("lg:grid-cols-3"), @@ -3063,19 +2991,7 @@ async fn static_automations_summary_reflows_cards_and_shrinks_next_run() { #[tokio::test] async fn static_automations_run_row_spaces_action_button_icons() { - let (app, _) = build_app(); - let response = app - .oneshot( - Request::builder() - .method(Method::GET) - .uri("/v2/js/pages/automations/components/automation-recent-runs.js") - .body(Body::empty()) - .expect("request"), - ) - .await - .expect("oneshot"); - assert_eq!(response.status(), StatusCode::OK); - let body = read_body_string(response).await; + let body = served_app_javascript().await; assert!( body.contains("name=\"chat\" className=\"mr-1.5 h-4 w-4\""), @@ -3089,26 +3005,14 @@ async fn static_automations_run_row_spaces_action_button_icons() { #[tokio::test] async fn static_automations_delivery_surfaces_save_error_and_gates_slack_hint() { - let (app, _) = build_app(); - let response = app - .oneshot( - Request::builder() - .method(Method::GET) - .uri("/v2/js/pages/automations/components/automation-delivery-defaults-panel.js") - .body(Body::empty()) - .expect("request"), - ) - .await - .expect("oneshot"); - assert_eq!(response.status(), StatusCode::OK); - let body = read_body_string(response).await; + let body = served_app_javascript().await; assert!( - body.contains("deliveryState.saveError"), + body.contains("e.saveError&&!a"), "the delivery panel must render the save error instead of swallowing it" ); assert!( - body.contains("hasExternalTargets"), + body.contains("finalReplyTargets.length>0"), "the Slack approval footnote must be gated on an external target existing" ); } diff --git a/crates/ironclaw_webui_v2/build.rs b/crates/ironclaw_webui_v2/build.rs index 1414df6c50a..5cce8990727 100644 --- a/crates/ironclaw_webui_v2/build.rs +++ b/crates/ironclaw_webui_v2/build.rs @@ -25,6 +25,9 @@ fn main() { let generated_dist_dir = out_dir.join("webui-v2-dist").join("dist"); println!("cargo:rerun-if-changed=static"); + println!("cargo:rerun-if-changed=frontend/src"); + println!("cargo:rerun-if-changed=frontend/public"); + println!("cargo:rerun-if-changed=frontend/vite.config.ts"); println!("cargo:rerun-if-changed=frontend/build.mjs"); println!("cargo:rerun-if-changed=frontend/package.json"); println!("cargo:rerun-if-changed=frontend/pnpm-lock.yaml"); @@ -225,16 +228,11 @@ fn collect(root: &Path, dir: &Path, url_prefix: &str, out: &mut Vec<(String, Pat } collect(root, &path, url_prefix, out); } else if file_type.is_file() { - // `*.test.js` / `*.test.mjs` are colocated Node `node:test` unit - // tests, not browser assets — never embed or serve them (shipping + // Colocated frontend tests are not browser assets — never embed or serve them (shipping // test-only code to clients is dead weight + needless exposure). A - // path ending in `.test.js`/`.test.mjs` implies its file name does - // too, so check the path. The `assets.rs` regression tests that - // assert `.test.mjs` content read it from disk, not this table. - if path - .to_str() - .is_some_and(|p| p.ends_with(".test.js") || p.ends_with(".test.mjs")) - { + // path ending in `.test.*` implies its file name does too, so check + // the path. Source-level regression tests read them from disk. + if path.to_str().is_some_and(|p| p.contains(".test.")) { continue; } println!("cargo:rerun-if-changed={}", path.display()); diff --git a/crates/ironclaw_webui_v2/frontend/build.mjs b/crates/ironclaw_webui_v2/frontend/build.mjs index 940f2215c24..82aa532919d 100644 --- a/crates/ironclaw_webui_v2/frontend/build.mjs +++ b/crates/ironclaw_webui_v2/frontend/build.mjs @@ -1,33 +1,33 @@ -// Bundles the WebUI v2 SPA with esbuild. +// Bundles the WebUI v2 SPA with Vite. // -// Input: ../static/js/main.js (entry) + the ~233 local ES modules it +// Input: ./src/main.ts (entry) + the local TypeScript modules it // imports, plus the React ecosystem (react, react-dom, // react-router, @tanstack/react-query, react-hook-form, htm) // resolved from ./node_modules. -// Output: $IRONCLAW_WEBUI_V2_DIST_DIR/app.js + chunks/* when that env var is -// set, otherwise ../static/dist/app.js + chunks/* for manual local -// builds. Locale chunks are code-split and dynamically imported by -// lib/i18n.js. +// Output: $IRONCLAW_WEBUI_V2_DIST_DIR/app.{js,css}, wallet-connect.js, and +// chunks/* when that env var is set, otherwise ../static/dist/* for +// manual local builds. Locale chunks are code-split and dynamically +// imported by lib/i18n.js. // // Cargo invokes this in `webui-v2-beta` builds and embeds the generated output -// from OUT_DIR. Re-run via ./build.sh after editing static/js/** when you want -// a local static/dist preview. +// from OUT_DIR. Re-run via ./build.sh after editing frontend/src/** when you +// want a local static/dist preview. // // What is deliberately NOT bundled (kept as same-origin + diff --git a/crates/ironclaw_webui_v2/tests/i18n_consistency.rs b/crates/ironclaw_webui_v2/tests/i18n_consistency.rs index 528b8532d9c..d8d1217dc40 100644 --- a/crates/ironclaw_webui_v2/tests/i18n_consistency.rs +++ b/crates/ironclaw_webui_v2/tests/i18n_consistency.rs @@ -1,6 +1,6 @@ //! Regression guard for the webui_v2 i18n locale dictionaries. //! -//! Parses every `static/js/i18n/*.js` pack and asserts cross-locale +//! Parses every `frontend/src/i18n/*.ts` pack and asserts cross-locale //! consistency against the English source: identical key sets, no empty //! values, and matching `{placeholder}` tokens. These invariants caught real //! bugs during the i18n completion work — keys present in only some locales @@ -15,7 +15,7 @@ use std::fs; use std::path::PathBuf; fn i18n_dir() -> PathBuf { - PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("static/js/i18n") + PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("frontend/src/i18n") } /// Skip whitespace and `//` line comments starting at `i`. @@ -144,7 +144,7 @@ fn load_all() -> BTreeMap> { let mut packs = BTreeMap::new(); for entry in fs::read_dir(&dir).expect("read i18n dir") { let path = entry.expect("dir entry").path(); - if path.extension().and_then(|e| e.to_str()) != Some("js") { + if path.extension().and_then(|e| e.to_str()) != Some("ts") { continue; } let lang = path @@ -159,7 +159,7 @@ fn load_all() -> BTreeMap> { } fn en_pack(packs: &BTreeMap>) -> &BTreeMap { - packs.get("en").expect("en.js locale present") + packs.get("en").expect("en.ts locale present") } #[test] @@ -169,7 +169,7 @@ fn en_pack_parses_and_is_substantial() { // Sanity check on the parser: en carries the full key set. assert!( en.len() > 700, - "parsed only {} keys from en.js — parser likely broke", + "parsed only {} keys from en.ts — parser likely broke", en.len() ); assert!( diff --git a/scripts/reborn_qa_matrix/audit_surface_inventory.py b/scripts/reborn_qa_matrix/audit_surface_inventory.py index aae3e8c6bfe..e33afa82aea 100644 --- a/scripts/reborn_qa_matrix/audit_surface_inventory.py +++ b/scripts/reborn_qa_matrix/audit_surface_inventory.py @@ -58,7 +58,7 @@ def _route_keywords(path: str) -> tuple[str, ...]: def browser_routes(repo_root: Path) -> list[Surface]: - app_js = repo_root / "crates/ironclaw_webui_v2_static/static/js/app/app.js" + app_js = repo_root / "crates/ironclaw_webui_v2/frontend/src/app/app.ts" route_re = re.compile(r"<\$\{Route\}\s+path=\"([^\"]+)\"") surfaces: list[Surface] = [] for route in route_re.findall(_read(app_js)): diff --git a/scripts/reborn_qa_matrix/test_audit_surface_inventory.py b/scripts/reborn_qa_matrix/test_audit_surface_inventory.py index b39814d825f..2822cc07654 100644 --- a/scripts/reborn_qa_matrix/test_audit_surface_inventory.py +++ b/scripts/reborn_qa_matrix/test_audit_surface_inventory.py @@ -54,9 +54,9 @@ def _write_workbook(path: Path, feature_rows: list[list[str]]) -> None: def _write_repo(root: Path) -> None: - app_dir = root / "crates/ironclaw_webui_v2_static/static/js/app" + app_dir = root / "crates/ironclaw_webui_v2/frontend/src/app" app_dir.mkdir(parents=True) - (app_dir / "app.js").write_text( + (app_dir / "app.ts").write_text( """ <${Route} path="chat" element=${html`<${ChatPage} />`} /> <${Route} path="jobs" element=${html`<${JobsPage} />`} /> From 7dfb18dfe4fd722b19ebe415db9c172ca9fd1add Mon Sep 17 00:00:00 2001 From: BenKurrek Date: Mon, 6 Jul 2026 16:36:11 -0400 Subject: [PATCH 07/12] feat(webui): embed prebuilt vite frontend assets --- .dockerignore | 1 + .github/workflows/code_style.yml | 10 + .github/workflows/coverage.yml | 5 + .github/workflows/platform-and-compat.yml | 8 + .github/workflows/reborn-e2e.yml | 5 + .github/workflows/reborn-playwright.yml | 5 + .github/workflows/reborn-tests.yml | 6 + Dockerfile.reborn | 8 + .../src/commands/webui_auth.rs | 28 ++- crates/ironclaw_reborn_cli/tests/smoke.rs | 111 +++++++-- .../tests/webui_v2_serve.rs | 50 +++- .../src/auth/mod.rs | 2 +- .../src/auth/routes.rs | 30 ++- .../ironclaw_reborn_webui_ingress/src/lib.rs | 3 +- .../tests/empty_providers_mount.rs | 54 ++++ crates/ironclaw_webui_v2/Cargo.toml | 4 +- crates/ironclaw_webui_v2/build.rs | 231 +++++++----------- crates/ironclaw_webui_v2/frontend/README.md | 24 +- crates/ironclaw_webui_v2/frontend/build.mjs | 63 ----- crates/ironclaw_webui_v2/frontend/build.sh | 14 +- .../ironclaw_webui_v2/frontend/package.json | 7 +- .../ironclaw_webui_v2/frontend/pnpm-lock.yaml | 4 +- .../public}/assets/apple-touch-icon.png | Bin .../public}/assets/favicon-96x96.png | Bin .../public}/assets/favicon.ico | Bin .../public}/assets/favicon.svg | 0 .../public}/assets/logo.jpg | Bin .../public}/assets/site.webmanifest | 0 .../assets/web-app-manifest-192x192.png | Bin .../assets/web-app-manifest-512x512.png | Bin .../cY9AfjOCX1hbuyalUrK4397yjIJFJpc.woff2 | Bin .../cY9AfjOCX1hbuyalUrK439DyjIJFJpeBZQ.woff2 | Bin .../cY9AfjOCX1hbuyalUrK439HyjIJFJpeBZQ.woff2 | Bin .../public}/vendor/fonts/fonts.css | 0 .../fonts/gyByhwUxId8gMEwRGFWNOITddY4.woff2 | Bin .../fonts/gyByhwUxId8gMEwSGFWNOITddY4.woff2 | Bin .../fonts/gyByhwUxId8gMEwTGFWNOITddY4.woff2 | Bin .../fonts/gyByhwUxId8gMEwYGFWNOITddY4.woff2 | Bin .../fonts/gyByhwUxId8gMEwcGFWNOITd.woff2 | Bin .../or3nQ6H-1_WfwkMZI_qYFg08vz7MhEIVVeA.woff2 | Bin .../or3nQ6H-1_WfwkMZI_qYFrMdmhHkjkotbA.woff2 | Bin .../or3nQ6H-1_WfwkMZI_qYFrcdmhHkjko.woff2 | Bin .../or3nQ6H-1_WfwkMZI_qYFrgdmhHkjkotbA.woff2 | Bin .../or3nQ6H-1_WfwkMZI_qYFrkdmhHkjkotbA.woff2 | Bin .../or3nQ6H-1_WfwkMZI_qYFrodmhHkjkotbA.woff2 | Bin .../public}/vendor/highlight.min.js | 0 .../public}/vendor/marked.umd.min.js | 0 .../public}/vendor/purify.min.js | 0 .../public}/wallet-connect.html | 6 +- crates/ironclaw_webui_v2/frontend/vendor.sh | 11 +- .../ironclaw_webui_v2/frontend/vite.config.ts | 11 + crates/ironclaw_webui_v2/src/lib.rs | 8 +- .../src/static_assets/assets.rs | 17 +- .../src/static_assets/mod.rs | 4 +- .../src/static_assets/router.rs | 41 +++- crates/ironclaw_webui_v2/static/index.html | 88 ------- .../static/vendor/tailwindcss-browser.js | 8 - scripts/ci/quality_gate_strict.sh | 15 +- scripts/run-reborn-webui.sh | 18 ++ 59 files changed, 491 insertions(+), 409 deletions(-) create mode 100644 crates/ironclaw_reborn_webui_ingress/tests/empty_providers_mount.rs delete mode 100644 crates/ironclaw_webui_v2/frontend/build.mjs rename crates/ironclaw_webui_v2/{static => frontend/public}/assets/apple-touch-icon.png (100%) rename crates/ironclaw_webui_v2/{static => frontend/public}/assets/favicon-96x96.png (100%) rename crates/ironclaw_webui_v2/{static => frontend/public}/assets/favicon.ico (100%) rename crates/ironclaw_webui_v2/{static => frontend/public}/assets/favicon.svg (100%) rename crates/ironclaw_webui_v2/{static => frontend/public}/assets/logo.jpg (100%) rename crates/ironclaw_webui_v2/{static => frontend/public}/assets/site.webmanifest (100%) rename crates/ironclaw_webui_v2/{static => frontend/public}/assets/web-app-manifest-192x192.png (100%) rename crates/ironclaw_webui_v2/{static => frontend/public}/assets/web-app-manifest-512x512.png (100%) rename crates/ironclaw_webui_v2/{static => frontend/public}/vendor/fonts/cY9AfjOCX1hbuyalUrK4397yjIJFJpc.woff2 (100%) rename crates/ironclaw_webui_v2/{static => frontend/public}/vendor/fonts/cY9AfjOCX1hbuyalUrK439DyjIJFJpeBZQ.woff2 (100%) rename crates/ironclaw_webui_v2/{static => frontend/public}/vendor/fonts/cY9AfjOCX1hbuyalUrK439HyjIJFJpeBZQ.woff2 (100%) rename crates/ironclaw_webui_v2/{static => frontend/public}/vendor/fonts/fonts.css (100%) rename crates/ironclaw_webui_v2/{static => frontend/public}/vendor/fonts/gyByhwUxId8gMEwRGFWNOITddY4.woff2 (100%) rename crates/ironclaw_webui_v2/{static => frontend/public}/vendor/fonts/gyByhwUxId8gMEwSGFWNOITddY4.woff2 (100%) rename crates/ironclaw_webui_v2/{static => frontend/public}/vendor/fonts/gyByhwUxId8gMEwTGFWNOITddY4.woff2 (100%) rename crates/ironclaw_webui_v2/{static => frontend/public}/vendor/fonts/gyByhwUxId8gMEwYGFWNOITddY4.woff2 (100%) rename crates/ironclaw_webui_v2/{static => frontend/public}/vendor/fonts/gyByhwUxId8gMEwcGFWNOITd.woff2 (100%) rename crates/ironclaw_webui_v2/{static => frontend/public}/vendor/fonts/or3nQ6H-1_WfwkMZI_qYFg08vz7MhEIVVeA.woff2 (100%) rename crates/ironclaw_webui_v2/{static => frontend/public}/vendor/fonts/or3nQ6H-1_WfwkMZI_qYFrMdmhHkjkotbA.woff2 (100%) rename crates/ironclaw_webui_v2/{static => frontend/public}/vendor/fonts/or3nQ6H-1_WfwkMZI_qYFrcdmhHkjko.woff2 (100%) rename crates/ironclaw_webui_v2/{static => frontend/public}/vendor/fonts/or3nQ6H-1_WfwkMZI_qYFrgdmhHkjkotbA.woff2 (100%) rename crates/ironclaw_webui_v2/{static => frontend/public}/vendor/fonts/or3nQ6H-1_WfwkMZI_qYFrkdmhHkjkotbA.woff2 (100%) rename crates/ironclaw_webui_v2/{static => frontend/public}/vendor/fonts/or3nQ6H-1_WfwkMZI_qYFrodmhHkjkotbA.woff2 (100%) rename crates/ironclaw_webui_v2/{static => frontend/public}/vendor/highlight.min.js (100%) rename crates/ironclaw_webui_v2/{static => frontend/public}/vendor/marked.umd.min.js (100%) rename crates/ironclaw_webui_v2/{static => frontend/public}/vendor/purify.min.js (100%) rename crates/ironclaw_webui_v2/{static => frontend/public}/wallet-connect.html (89%) delete mode 100644 crates/ironclaw_webui_v2/static/index.html delete mode 100644 crates/ironclaw_webui_v2/static/vendor/tailwindcss-browser.js diff --git a/.dockerignore b/.dockerignore index b3f14a3e14c..3fcc250c716 100644 --- a/.dockerignore +++ b/.dockerignore @@ -11,3 +11,4 @@ target/ node_modules/ **/node_modules/ crates/ironclaw_webui_v2_static/static/dist/ +crates/ironclaw_webui_v2/frontend/dist/ diff --git a/.github/workflows/code_style.yml b/.github/workflows/code_style.yml index 7df9a49ed94..b8ed10b702f 100644 --- a/.github/workflows/code_style.yml +++ b/.github/workflows/code_style.yml @@ -191,6 +191,11 @@ jobs: - name: Enable pnpm if: contains(matrix.flags, '--all-features') run: corepack enable pnpm + - name: Install WebUI frontend dependencies + if: contains(matrix.flags, '--all-features') + run: | + cd crates/ironclaw_webui_v2/frontend + pnpm install --frozen-lockfile - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 with: shared-key: clippy @@ -242,6 +247,11 @@ jobs: - name: Enable pnpm if: contains(matrix.flags, '--all-features') run: corepack enable pnpm + - name: Install WebUI frontend dependencies + if: contains(matrix.flags, '--all-features') + run: | + cd crates/ironclaw_webui_v2/frontend + pnpm install --frozen-lockfile - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 with: key: windows-${{ matrix.name }} diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index e7073260a5a..c7ddcc99ca7 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -193,6 +193,11 @@ jobs: - name: Enable pnpm run: corepack enable pnpm + - name: Install WebUI frontend dependencies + run: | + cd crates/ironclaw_webui_v2/frontend + pnpm install --frozen-lockfile + # Pre-build the reborn binary under the same llvm-cov env so the E2E # fixtures find it cached instead of doing a cold instrumented build # inside a pytest timeout. openai-compat-beta is a strict superset of diff --git a/.github/workflows/platform-and-compat.yml b/.github/workflows/platform-and-compat.yml index 1125237eaa3..faf1575251a 100644 --- a/.github/workflows/platform-and-compat.yml +++ b/.github/workflows/platform-and-compat.yml @@ -271,6 +271,10 @@ jobs: cache-dependency-path: crates/ironclaw_webui_v2/frontend/pnpm-lock.yaml - name: Enable pnpm run: corepack enable pnpm + - name: Install WebUI frontend dependencies + run: | + cd crates/ironclaw_webui_v2/frontend + pnpm install --frozen-lockfile - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 with: key: wasm-extensions @@ -313,6 +317,10 @@ jobs: cache-dependency-path: crates/ironclaw_webui_v2/frontend/pnpm-lock.yaml - name: Enable pnpm run: corepack enable pnpm + - name: Install WebUI frontend dependencies + run: | + cd crates/ironclaw_webui_v2/frontend + pnpm install --frozen-lockfile - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 with: key: bench diff --git a/.github/workflows/reborn-e2e.yml b/.github/workflows/reborn-e2e.yml index ccb647be66e..10b4d904a13 100644 --- a/.github/workflows/reborn-e2e.yml +++ b/.github/workflows/reborn-e2e.yml @@ -155,6 +155,11 @@ jobs: - name: Enable pnpm run: corepack enable pnpm + - name: Install WebUI frontend dependencies + run: | + cd crates/ironclaw_webui_v2/frontend + pnpm install --frozen-lockfile + - name: Restore Rust cache uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 with: diff --git a/.github/workflows/reborn-playwright.yml b/.github/workflows/reborn-playwright.yml index d9ac77d6b25..0843117b517 100644 --- a/.github/workflows/reborn-playwright.yml +++ b/.github/workflows/reborn-playwright.yml @@ -90,6 +90,11 @@ jobs: - name: Enable pnpm run: corepack enable pnpm + - name: Install WebUI frontend dependencies + run: | + cd crates/ironclaw_webui_v2/frontend + pnpm install --frozen-lockfile + - name: Restore Rust cache uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 with: diff --git a/.github/workflows/reborn-tests.yml b/.github/workflows/reborn-tests.yml index 26a51b4b623..6be0ba69c7e 100644 --- a/.github/workflows/reborn-tests.yml +++ b/.github/workflows/reborn-tests.yml @@ -250,6 +250,12 @@ jobs: if: ${{ steps.bucket-settings.outputs.needs_webui_node == 'true' }} run: corepack enable pnpm + - name: Install WebUI frontend dependencies + if: ${{ steps.bucket-settings.outputs.needs_webui_node == 'true' }} + run: | + cd crates/ironclaw_webui_v2/frontend + pnpm install --frozen-lockfile + - name: Install mold and clang run: | scripts/ci/install-ci-apt-packages.sh clang mold diff --git a/Dockerfile.reborn b/Dockerfile.reborn index 4cc470db1f7..09eb7a0ca6e 100644 --- a/Dockerfile.reborn +++ b/Dockerfile.reborn @@ -51,6 +51,10 @@ ENV CARGO_PROFILE_DIST_PANIC=abort \ CARGO_PROFILE_DIST_CODEGEN_UNITS=1 COPY --from=planner /app/recipe.json recipe.json +COPY crates/ironclaw_webui_v2/frontend/ crates/ironclaw_webui_v2/frontend/ +WORKDIR /app/crates/ironclaw_webui_v2/frontend +RUN pnpm install --frozen-lockfile +WORKDIR /app RUN cargo chef cook \ --profile dist \ --package ironclaw_reborn_cli \ @@ -71,6 +75,10 @@ RUN mkdir -p src \ && printf 'fn main() {}\n' > src/main.rs \ && printf '\n' > src/lib.rs +WORKDIR /app/crates/ironclaw_webui_v2/frontend +RUN pnpm install --frozen-lockfile +WORKDIR /app + RUN cargo build \ --profile dist \ --package ironclaw_reborn_cli \ diff --git a/crates/ironclaw_reborn_cli/src/commands/webui_auth.rs b/crates/ironclaw_reborn_cli/src/commands/webui_auth.rs index fdcd3038296..fe36073a01d 100644 --- a/crates/ironclaw_reborn_cli/src/commands/webui_auth.rs +++ b/crates/ironclaw_reborn_cli/src/commands/webui_auth.rs @@ -17,7 +17,9 @@ use ironclaw_reborn_composition::host_api::{AgentId, ProjectId, TenantId}; use ironclaw_reborn_composition::{ LocalTriggerAccessStore, PublicRouteMount, RebornIdentityResolver, WebuiAuthenticator, }; -use ironclaw_reborn_webui_ingress::{SignedSessionLoginConfig, build_signed_session_login}; +use ironclaw_reborn_webui_ingress::{ + SignedSessionLoginConfig, build_signed_session_login, empty_webui_v2_auth_providers_mount, +}; use secrecy::SecretString; use crate::commands::serve_sso::SsoStartupConfig; @@ -47,7 +49,8 @@ pub(crate) struct LocalTriggerAccessBootstrapConfig { /// Build the auth surface from resolved startup config. /// /// With no SSO provider configured (`sso_startup` is `None`), the listener -/// keeps its plain env-bearer authenticator and mounts no public routes. +/// keeps its plain env-bearer authenticator and mounts only the inert auth +/// surface so `/auth/providers` can return an empty provider list. /// With providers configured, this layers the fail-closed email-domain /// admission adapter on top of the runtime-owned canonical Reborn identity /// resolver and hands the result to the ingress signed-session builder. @@ -70,12 +73,14 @@ pub(crate) async fn build_webui_auth_surface( local_trigger_access: Option, ) -> anyhow::Result { let Some(sso) = sso_startup else { - // No SSO providers: keep the env-bearer authenticator and mount no - // public routes. There are no SSO logins to seed local trigger - // access for, so any bootstrap config is unused on this path. + // No SSO providers: keep the env-bearer authenticator and mount only + // inert provider discovery. Login/session/logout routes require a + // revocable SSO session store, which env-bearer mode deliberately + // does not have. + let public_mount = empty_webui_v2_auth_providers_mount(); return Ok(WebuiAuthSurface { authenticator: env_authenticator, - public_mount: None, + public_mount: Some(public_mount), }); }; @@ -213,9 +218,9 @@ mod tests { } #[tokio::test] - async fn no_sso_keeps_env_authenticator_and_mounts_no_public_routes() { + async fn no_sso_keeps_env_authenticator_and_mounts_empty_provider_route() { // With no SSO configured the surface is the plain env-bearer - // authenticator and no public login routes — the absent-resolver + // authenticator plus an inert public auth mount. The absent-resolver // check must not fire on this path, and a bootstrap config is unused. let result = build_webui_auth_surface( None, @@ -229,8 +234,11 @@ mod tests { match result { Ok(surface) => assert!( - surface.public_mount.is_none(), - "no SSO must mount no public login routes" + surface.public_mount.as_ref().is_some_and(|mount| { + mount.descriptors.len() == 1 + && mount.descriptors[0].route_pattern().as_str() == "/auth/providers" + }), + "no SSO must mount only /auth/providers with an empty list" ), Err(error) => panic!("no SSO is a valid configuration, got error: {error}"), } diff --git a/crates/ironclaw_reborn_cli/tests/smoke.rs b/crates/ironclaw_reborn_cli/tests/smoke.rs index 208f1662bab..8e936092c96 100644 --- a/crates/ironclaw_reborn_cli/tests/smoke.rs +++ b/crates/ironclaw_reborn_cli/tests/smoke.rs @@ -120,6 +120,12 @@ fn dockerfile_reborn_builds_with_postgres_feature() { >= 2, "Dockerfile.reborn must compile both cargo-chef deps and final binary with libsql and postgres: {dockerfile}" ); + assert!( + dockerfile.contains("corepack enable pnpm") + && dockerfile.matches("pnpm install --frozen-lockfile").count() >= 2 + && dockerfile.contains("crates/ironclaw_webui_v2/frontend"), + "Dockerfile.reborn must install WebUI frontend dependencies before cargo-chef and final webui-v2-beta builds: {dockerfile}" + ); assert!( dockerfile.contains("config.production.toml"), "Dockerfile.reborn must ship the opt-in production config: {dockerfile}" @@ -147,6 +153,23 @@ fn dockerfile_reborn_builds_with_postgres_feature() { ); } +#[test] +fn run_reborn_webui_builds_frontend_before_cargo() { + let launcher = std::fs::read_to_string(workspace_root().join("scripts/run-reborn-webui.sh")) + .expect("scripts/run-reborn-webui.sh"); + + let frontend_build = launcher + .find("pnpm build") + .expect("launcher should build WebUI frontend assets"); + let cargo_run = launcher + .find("CARGO=(cargo run -q -p ironclaw_reborn_cli --features webui-v2-beta") + .expect("launcher should run Reborn with webui-v2-beta"); + assert!( + frontend_build < cargo_run, + "scripts/run-reborn-webui.sh must build frontend/dist before cargo compiles webui-v2-beta: {launcher}" + ); +} + #[test] fn docker_reborn_config_defaults_to_local_dev() { let config = std::fs::read_to_string(workspace_root().join("docker/reborn/config.toml")) @@ -1423,9 +1446,11 @@ fn serve_with_env_auth_seeds_reborn_config_before_binding() { let reborn_home = temp.path().join("reborn-home"); let home = temp.path().join("home"); std::fs::create_dir_all(&home).expect("home dir"); + let port = unused_local_port(); let mut child = Command::new(reborn_bin()) - .args(["serve", "--host", "127.0.0.1", "--port", "0"]) + .args(["serve", "--host", "127.0.0.1", "--port"]) + .arg(port.to_string()) .env_clear() .env("HOME", &home) .env("IRONCLAW_REBORN_HOME", &reborn_home) @@ -1472,8 +1497,53 @@ fn serve_with_env_auth_seeds_reborn_config_before_binding() { } } + let providers_status = match http_status_line( + port, + concat!( + "GET /auth/providers HTTP/1.1\r\n", + "Host: 127.0.0.1\r\n", + "Connection: close\r\n", + "\r\n", + ), + "providers route probe", + ) { + Ok(status_line) => status_line, + Err(error) => { + let _ = child.kill(); + let _ = child.wait(); + panic!("{error}"); + } + }; + let logout_status = match http_status_line( + port, + concat!( + "POST /auth/logout HTTP/1.1\r\n", + "Host: 127.0.0.1\r\n", + "Authorization: Bearer test-token\r\n", + "Content-Length: 0\r\n", + "Connection: close\r\n", + "\r\n", + ), + "logout route probe", + ) { + Ok(status_line) => status_line, + Err(error) => { + let _ = child.kill(); + let _ = child.wait(); + panic!("{error}"); + } + }; + let _ = child.kill(); let _ = child.wait(); + assert!( + providers_status.contains(" 200 "), + "no-SSO serve must still expose empty provider discovery, got status line: {providers_status}" + ); + assert!( + logout_status.contains(" 404 "), + "no-SSO env-bearer serve must not mount logout, got status line: {logout_status}" + ); let config = std::fs::read_to_string(reborn_home.join("config.toml")) .expect("successful serve startup should seed config"); assert!( @@ -1566,7 +1636,7 @@ fn serve_env_slack_enabled_mounts_slack_events_route() { ); } -#[cfg(all(feature = "webui-v2-beta", feature = "slack-v2-host-beta"))] +#[cfg(feature = "webui-v2-beta")] fn unused_local_port() -> u16 { std::net::TcpListener::bind(("127.0.0.1", 0)) .expect("bind ephemeral local port") @@ -1575,8 +1645,8 @@ fn unused_local_port() -> u16 { .port() } -#[cfg(all(feature = "webui-v2-beta", feature = "slack-v2-host-beta"))] -fn post_slack_events_status_line(port: u16) -> Result { +#[cfg(feature = "webui-v2-beta")] +fn http_status_line(port: u16, request: &str, label: &str) -> Result { let deadline = std::time::Instant::now() + std::time::Duration::from_secs(5); let mut stream = loop { match std::net::TcpStream::connect(("127.0.0.1", port)) { @@ -1587,26 +1657,37 @@ fn post_slack_events_status_line(port: u16) -> Result { Err(error) => return Err(format!("connect to serve listener failed: {error}")), } }; - let request = concat!( - "POST /webhooks/slack/events HTTP/1.1\r\n", - "Host: 127.0.0.1\r\n", - "Content-Type: application/json\r\n", - "Content-Length: 2\r\n", - "Connection: close\r\n", - "\r\n", - "{}" - ); + stream + .set_read_timeout(Some(std::time::Duration::from_secs(5))) + .map_err(|error| format!("set {label} read timeout failed: {error}"))?; stream .write_all(request.as_bytes()) - .map_err(|error| format!("write Slack route probe failed: {error}"))?; + .map_err(|error| format!("write {label} failed: {error}"))?; let mut reader = std::io::BufReader::new(stream); let mut status_line = String::new(); reader .read_line(&mut status_line) - .map_err(|error| format!("read Slack route probe status line failed: {error}"))?; + .map_err(|error| format!("read {label} status line failed: {error}"))?; Ok(status_line) } +#[cfg(all(feature = "webui-v2-beta", feature = "slack-v2-host-beta"))] +fn post_slack_events_status_line(port: u16) -> Result { + http_status_line( + port, + concat!( + "POST /webhooks/slack/events HTTP/1.1\r\n", + "Host: 127.0.0.1\r\n", + "Content-Type: application/json\r\n", + "Content-Length: 2\r\n", + "Connection: close\r\n", + "\r\n", + "{}" + ), + "Slack route probe", + ) +} + #[cfg(feature = "webui-v2-beta")] #[test] fn serve_rejects_malformed_host_before_webui_handoff() { diff --git a/crates/ironclaw_reborn_composition/tests/webui_v2_serve.rs b/crates/ironclaw_reborn_composition/tests/webui_v2_serve.rs index 20341c4a355..10e4f509131 100644 --- a/crates/ironclaw_reborn_composition/tests/webui_v2_serve.rs +++ b/crates/ironclaw_reborn_composition/tests/webui_v2_serve.rs @@ -1238,11 +1238,25 @@ async fn served_static_text(path: &str) -> String { } async fn served_app_javascript() -> String { - served_static_text("/v2/dist/app.js").await + served_app_vite_asset(".js").await } async fn served_app_stylesheet() -> String { - served_static_text("/v2/dist/app.css").await + served_app_vite_asset(".css").await +} + +async fn served_app_vite_asset(suffix: &str) -> String { + let shell = served_static_text("/v2/").await; + let asset_path = shell_vite_asset_path(&shell, suffix); + served_static_text(&asset_path).await +} + +fn shell_vite_asset_path(shell: &str, suffix: &str) -> String { + shell + .split(['"', '\'']) + .find(|part| part.starts_with("/v2/assets/app-") && part.ends_with(suffix)) + .expect("shell should reference requested Vite asset") + .to_string() } // ─── tests ──────────────────────────────────────────────────────────── @@ -2387,11 +2401,25 @@ async fn static_root_does_not_require_bearer_auth() { #[tokio::test] async fn static_js_asset_returns_javascript_content_type() { let (app, _) = build_app(); + let shell = read_body_string( + app.clone() + .oneshot( + Request::builder() + .method(Method::GET) + .uri("/v2/") + .body(Body::empty()) + .expect("request"), + ) + .await + .expect("oneshot"), + ) + .await; + let app_js_path = shell_vite_asset_path(&shell, ".js"); let response = app .oneshot( Request::builder() .method(Method::GET) - .uri("/v2/dist/app.js") + .uri(app_js_path) .body(Body::empty()) .expect("request"), ) @@ -2492,11 +2520,25 @@ async fn static_chat_events_clear_gate_when_run_resumes() { #[tokio::test] async fn static_css_asset_returns_text_css_content_type() { let (app, _) = build_app(); + let shell = read_body_string( + app.clone() + .oneshot( + Request::builder() + .method(Method::GET) + .uri("/v2/") + .body(Body::empty()) + .expect("request"), + ) + .await + .expect("oneshot"), + ) + .await; + let app_css_path = shell_vite_asset_path(&shell, ".css"); let response = app .oneshot( Request::builder() .method(Method::GET) - .uri("/v2/dist/app.css") + .uri(app_css_path) .body(Body::empty()) .expect("request"), ) diff --git a/crates/ironclaw_reborn_webui_ingress/src/auth/mod.rs b/crates/ironclaw_reborn_webui_ingress/src/auth/mod.rs index db856a935ac..bd78e3c0354 100644 --- a/crates/ironclaw_reborn_webui_ingress/src/auth/mod.rs +++ b/crates/ironclaw_reborn_webui_ingress/src/auth/mod.rs @@ -40,7 +40,7 @@ pub use ironclaw_reborn_composition::PublicRouteMount; pub use profile::OAuthUserProfile; pub use provider::OAuthProvider; pub use provider_name::{OAuthProviderName, OAuthProviderNameError}; -pub use routes::{OAuthRouterConfig, webui_v2_auth_router}; +pub use routes::{OAuthRouterConfig, empty_webui_v2_auth_providers_mount, webui_v2_auth_router}; #[cfg(any(test, feature = "dev-in-memory-session"))] pub use user_directory::EmailUserDirectory; pub use user_directory::{UserDirectory, UserDirectoryError}; diff --git a/crates/ironclaw_reborn_webui_ingress/src/auth/routes.rs b/crates/ironclaw_reborn_webui_ingress/src/auth/routes.rs index 2c9d0aa427a..ed2b5e0a904 100644 --- a/crates/ironclaw_reborn_webui_ingress/src/auth/routes.rs +++ b/crates/ironclaw_reborn_webui_ingress/src/auth/routes.rs @@ -183,16 +183,28 @@ pub fn webui_v2_auth_router(config: OAuthRouterConfig) -> PublicRouteMount { PublicRouteMount::new(router, sso_route_descriptors()) } +/// Build the inert auth discovery mount used when no SSO providers are +/// configured. This deliberately does not mount the login/session/logout +/// handlers because there is no revocable SSO session store in env-bearer mode. +pub fn empty_webui_v2_auth_providers_mount() -> PublicRouteMount { + let router = axum::Router::new().route(PATH_PROVIDERS, get(empty_providers_handler)); + PublicRouteMount::new(router, vec![providers_descriptor()]) +} + // ── descriptors ─────────────────────────────────────────────────────── +fn providers_descriptor() -> IngressRouteDescriptor { + descriptor( + ROUTE_ID_PROVIDERS, + NetworkMethod::Get, + PATH_PROVIDERS, + public_policy(BodyLimitPolicy::NoBody, SSO_PROVIDERS_MAX_REQUESTS), + ) +} + fn sso_route_descriptors() -> Vec { vec![ - descriptor( - ROUTE_ID_PROVIDERS, - NetworkMethod::Get, - PATH_PROVIDERS, - public_policy(BodyLimitPolicy::NoBody, SSO_PROVIDERS_MAX_REQUESTS), - ), + providers_descriptor(), descriptor( ROUTE_ID_LOGIN, NetworkMethod::Get, @@ -319,6 +331,12 @@ async fn providers_handler(State(state): State) -> Json Json { + Json(ProvidersResponse { + providers: Vec::new(), + }) +} + // ─── /auth/login/{provider} ─────────────────────────────────────────── #[derive(Deserialize)] diff --git a/crates/ironclaw_reborn_webui_ingress/src/lib.rs b/crates/ironclaw_reborn_webui_ingress/src/lib.rs index 4f3ba9eb1e4..eb7f75dab5d 100644 --- a/crates/ironclaw_reborn_webui_ingress/src/lib.rs +++ b/crates/ironclaw_reborn_webui_ingress/src/lib.rs @@ -31,7 +31,8 @@ pub use auth::EmailUserDirectory; pub use auth::{ GitHubOAuthConfig, GitHubProvider, GoogleOAuthConfig, GoogleProvider, OAuthError, OAuthProvider, OAuthProviderName, OAuthProviderNameError, OAuthRouterConfig, OAuthUserProfile, - ProviderInitError, PublicRouteMount, UserDirectory, UserDirectoryError, webui_v2_auth_router, + ProviderInitError, PublicRouteMount, UserDirectory, UserDirectoryError, + empty_webui_v2_auth_providers_mount, webui_v2_auth_router, }; pub use oidc::{ AudienceClaim, ClaimToUserIdFn, IdTokenClaims, OidcAuthenticator, OidcAuthenticatorConfig, diff --git a/crates/ironclaw_reborn_webui_ingress/tests/empty_providers_mount.rs b/crates/ironclaw_reborn_webui_ingress/tests/empty_providers_mount.rs new file mode 100644 index 00000000000..5e2335423cb --- /dev/null +++ b/crates/ironclaw_reborn_webui_ingress/tests/empty_providers_mount.rs @@ -0,0 +1,54 @@ +use axum::body::Body; +use http::{Method, Request, StatusCode}; +use http_body_util::BodyExt; +use ironclaw_reborn_webui_ingress::empty_webui_v2_auth_providers_mount; +use tower::ServiceExt; + +#[tokio::test] +async fn empty_provider_mount_only_serves_provider_discovery() { + let mount = empty_webui_v2_auth_providers_mount(); + assert_eq!(mount.descriptors.len(), 1); + assert_eq!( + mount.descriptors[0].route_id().as_str(), + "webui.sso.providers" + ); + assert_eq!( + mount.descriptors[0].route_pattern().as_str(), + "/auth/providers" + ); + + let providers = mount + .router + .clone() + .oneshot( + Request::builder() + .method(Method::GET) + .uri("/auth/providers") + .body(Body::empty()) + .expect("providers request"), + ) + .await + .expect("providers oneshot"); + assert_eq!(providers.status(), StatusCode::OK); + let bytes = providers + .into_body() + .collect() + .await + .expect("providers body") + .to_bytes(); + assert_eq!(bytes.as_ref(), br#"{"providers":[]}"#); + + let logout = mount + .router + .oneshot( + Request::builder() + .method(Method::POST) + .uri("/auth/logout") + .header("authorization", "Bearer env-token") + .body(Body::empty()) + .expect("logout request"), + ) + .await + .expect("logout oneshot"); + assert_eq!(logout.status(), StatusCode::NOT_FOUND); +} diff --git a/crates/ironclaw_webui_v2/Cargo.toml b/crates/ironclaw_webui_v2/Cargo.toml index 2530d60143c..c2a64be493d 100644 --- a/crates/ironclaw_webui_v2/Cargo.toml +++ b/crates/ironclaw_webui_v2/Cargo.toml @@ -22,8 +22,8 @@ webui-v2-beta = [ "dep:async-stream", "dep:futures", "dep:tokio", - # Static SPA asset bundle (`static_assets`), folded in from the former - # `ironclaw_webui_v2_static` crate. `rand` supplies the per-request CSP nonce. + # Static SPA asset bundle (`static_assets`) embedding the prebuilt + # frontend/dist tree. `rand` supplies the per-request CSP nonce. "dep:rand", ] diff --git a/crates/ironclaw_webui_v2/build.rs b/crates/ironclaw_webui_v2/build.rs index 5cce8990727..43357ac6115 100644 --- a/crates/ironclaw_webui_v2/build.rs +++ b/crates/ironclaw_webui_v2/build.rs @@ -1,10 +1,10 @@ //! Build-time scan of the WebUI static assets. //! -//! Walks every file under `static/`, builds the generated SPA bundle into -//! OUT_DIR when `webui-v2-beta` is enabled, and emits Rust source that declares -//! one `ASSETS` slice keyed by URL path (relative to the mount prefix). Each -//! entry pairs an `include_bytes!` reference with a content-type string picked -//! from the file extension. +//! Builds the Vite frontend into Cargo's `OUT_DIR` when `webui-v2-beta` is +//! enabled, then emits Rust source that declares one `ASSETS` slice keyed by +//! URL path (relative to the mount prefix). Each entry pairs an +//! `include_bytes!` reference with a content-type string picked from the file +//! extension. //! //! The generated source is included from `src/assets.rs`. @@ -12,42 +12,28 @@ use std::env; use std::fs; use std::path::{Path, PathBuf}; use std::process::Command; -use std::thread; -use std::time::{Duration, Instant}; -const FRONTEND_COMMAND_TIMEOUT: Duration = Duration::from_secs(10 * 60); -const COMMAND_POLL_INTERVAL: Duration = Duration::from_millis(100); - -fn main() { +fn main() -> Result<(), Box> { let manifest_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()); // safety: build script — Cargo always sets this - let static_dir = manifest_dir.join("static"); let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap()); // safety: build script — Cargo always sets this - let generated_dist_dir = out_dir.join("webui-v2-dist").join("dist"); + let generated_dist_dir = out_dir.join("webui-v2-frontend-dist"); - println!("cargo:rerun-if-changed=static"); - println!("cargo:rerun-if-changed=frontend/src"); - println!("cargo:rerun-if-changed=frontend/public"); - println!("cargo:rerun-if-changed=frontend/vite.config.ts"); - println!("cargo:rerun-if-changed=frontend/build.mjs"); + println!("cargo:rerun-if-changed=frontend/index.html"); println!("cargo:rerun-if-changed=frontend/package.json"); println!("cargo:rerun-if-changed=frontend/pnpm-lock.yaml"); println!("cargo:rerun-if-changed=frontend/pnpm-workspace.yaml"); + println!("cargo:rerun-if-changed=frontend/public"); + println!("cargo:rerun-if-changed=frontend/src"); + println!("cargo:rerun-if-changed=frontend/vite.config.ts"); println!("cargo:rerun-if-changed=build.rs"); let webui_enabled = env::var_os("CARGO_FEATURE_WEBUI_V2_BETA").is_some(); - if webui_enabled { - build_frontend_dist(&manifest_dir, &generated_dist_dir); - } let mut entries: Vec<(String, PathBuf)> = Vec::new(); - collect(&static_dir, &static_dir, "", &mut entries); if webui_enabled { - collect( - &generated_dist_dir, - &generated_dist_dir, - "dist", - &mut entries, - ); + let dist_dir = build_frontend_dist(&manifest_dir, &generated_dist_dir)?; + validate_frontend_dist(&dist_dir); + collect(&dist_dir, &dist_dir, "", &mut entries)?; } entries.sort_by(|a, b| a.0.cmp(&b.0)); @@ -76,126 +62,89 @@ fn main() { } src.push_str("];\n\n"); - if let Some(path) = index_html_abs { + if !webui_enabled { + src.push_str("pub(crate) const INDEX_HTML_TEMPLATE: &str = \"\";\n"); + } else if let Some(path) = index_html_abs { src.push_str(&format!( "pub(crate) const INDEX_HTML_TEMPLATE: &str = include_str!(r\"{}\");\n", path.to_string_lossy(), )); } else { - panic!("static/index.html is required"); + panic!("Vite frontend build output index.html is required"); } - fs::write(out_dir.join("assets_generated.rs"), src).expect("write assets_generated.rs"); // safety: build script — fail build on write error + fs::write(out_dir.join("assets_generated.rs"), src)?; + Ok(()) } -fn build_frontend_dist(manifest_dir: &Path, dist_dir: &Path) { +fn build_frontend_dist( + manifest_dir: &Path, + generated_dist_dir: &Path, +) -> Result> { let frontend_dir = manifest_dir.join("frontend"); - let staging_dist_dir = dist_dir.with_extension("building"); - - ensure_frontend_dependencies(&frontend_dir); - if staging_dist_dir.exists() { - fs::remove_dir_all(&staging_dist_dir).unwrap_or_else(|error| { - panic!( - "remove stale staged webui dist {}: {error}", - staging_dist_dir.display() - ) - }); + if generated_dist_dir.exists() { + fs::remove_dir_all(generated_dist_dir)?; } - run_command( - node_command(), - &["build.mjs"], + run_pnpm(&["install", "--frozen-lockfile"], &frontend_dir)?; + let generated_arg = generated_dist_dir.to_string_lossy().into_owned(); + run_pnpm( + &[ + "exec", + "vite", + "build", + "--outDir", + &generated_arg, + "--emptyOutDir", + ], &frontend_dir, - &[("IRONCLAW_WEBUI_V2_DIST_DIR", &staging_dist_dir)], - ); + )?; + Ok(generated_dist_dir.to_path_buf()) +} - let app_js = staging_dist_dir.join("app.js"); - if !app_js.is_file() { - panic!("frontend build did not produce {}", app_js.display()); - } - if dist_dir.exists() { - fs::remove_dir_all(dist_dir).unwrap_or_else(|error| { - panic!("remove stale webui dist {}: {error}", dist_dir.display()) - }); - } - fs::rename(&staging_dist_dir, dist_dir).unwrap_or_else(|error| { +fn validate_frontend_dist(dist_dir: &Path) { + let missing = required_frontend_dist_files(dist_dir) + .into_iter() + .filter(|path| !path.is_file()) + .map(|path| path.display().to_string()) + .collect::>(); + if !missing.is_empty() { panic!( - "move staged webui dist {} to {}: {error}", - staging_dist_dir.display(), - dist_dir.display(), - ) - }); + "WebUI v2 frontend build output is missing required files:\n {}", + missing.join("\n "), + ); + } } -fn ensure_frontend_dependencies(frontend_dir: &Path) { - run_pnpm(&["install", "--frozen-lockfile"], frontend_dir); +fn required_frontend_dist_files(dist_dir: &Path) -> [PathBuf; 3] { + [ + dist_dir.join("index.html"), + dist_dir.join("wallet-connect.html"), + dist_dir.join("wallet-connect.js"), + ] } -fn run_command(command: &str, args: &[&str], cwd: &Path, envs: &[(&str, &Path)]) { - let display_command = display_command(command, args); - let mut cmd = Command::new(command); - cmd.args(args).current_dir(cwd); - for (key, value) in envs { - cmd.env(key, value); - } - - let mut child = cmd.spawn().unwrap_or_else(|error| { - panic!( - "failed to run `{}` in {}: {error}", - display_command, - cwd.display(), - ) - }); - let deadline = Instant::now() + FRONTEND_COMMAND_TIMEOUT; - let status = loop { - match child.try_wait() { - Ok(Some(status)) => break status, - Ok(None) if Instant::now() >= deadline => { - let kill_result = child.kill(); - let _ = child.wait(); - match kill_result { - Ok(()) => panic!( - "`{}` timed out after {} seconds in {}", - display_command, - FRONTEND_COMMAND_TIMEOUT.as_secs(), - cwd.display(), - ), - Err(error) => panic!( - "`{}` timed out after {} seconds in {}, and failed to kill it: {error}", - display_command, - FRONTEND_COMMAND_TIMEOUT.as_secs(), - cwd.display(), - ), - } - } - Ok(None) => thread::sleep(COMMAND_POLL_INTERVAL), - Err(error) => panic!( - "failed to poll `{}` in {}: {error}", - display_command, - cwd.display(), - ), - } - }; - if !status.success() { - panic!( - "`{}` failed in {} with status {status}", - display_command, - cwd.display(), - ); +fn run_command(command: &str, args: &[&str], cwd: &Path) -> Result<(), Box> { + let status = Command::new(command).args(args).current_dir(cwd).status()?; + if status.success() { + return Ok(()); } -} -fn display_command(command: &str, args: &[&str]) -> String { - std::iter::once(command) - .chain(args.iter().copied()) - .collect::>() - .join(" ") + Err(std::io::Error::other(format!( + "`{}` failed in {} with status {status}", + std::iter::once(command) + .chain(args.iter().copied()) + .collect::>() + .join(" "), + cwd.display(), + )) + .into()) } -fn run_pnpm(args: &[&str], cwd: &Path) { +fn run_pnpm(args: &[&str], cwd: &Path) -> Result<(), Box> { let mut corepack_args = Vec::with_capacity(args.len() + 1); corepack_args.push("pnpm"); corepack_args.extend_from_slice(args); - run_command(corepack_command(), &corepack_args, cwd, &[]); + run_command(corepack_command(), &corepack_args, cwd) } fn corepack_command() -> &'static str { @@ -206,36 +155,23 @@ fn corepack_command() -> &'static str { } } -fn node_command() -> &'static str { - if cfg!(windows) { "node.exe" } else { "node" } -} - -fn collect(root: &Path, dir: &Path, url_prefix: &str, out: &mut Vec<(String, PathBuf)>) { - let read_dir = fs::read_dir(dir).expect("read_dir static"); // safety: build script — fail build on read error +fn collect( + root: &Path, + dir: &Path, + url_prefix: &str, + out: &mut Vec<(String, PathBuf)>, +) -> std::io::Result<()> { + let read_dir = fs::read_dir(dir)?; for entry in read_dir { - let entry = entry.expect("dir entry"); // safety: build script — fail build on bad entry + let entry = entry?; let path = entry.path(); - let file_type = entry.file_type().expect("file type"); // safety: build script — fail build on stat error + let file_type = entry.file_type()?; if file_type.is_dir() { - // `static/dist` is generated output. Cargo embeds the freshly built - // OUT_DIR copy when WebUI v2 is enabled, so a local ignored - // source-tree bundle must never win by accident. - if url_prefix.is_empty() - && dir == root - && path.file_name().and_then(|name| name.to_str()) == Some("dist") - { + if path.file_name().and_then(|name| name.to_str()) == Some(".vite") { continue; } - collect(root, &path, url_prefix, out); + collect(root, &path, url_prefix, out)?; } else if file_type.is_file() { - // Colocated frontend tests are not browser assets — never embed or serve them (shipping - // test-only code to clients is dead weight + needless exposure). A - // path ending in `.test.*` implies its file name does too, so check - // the path. Source-level regression tests read them from disk. - if path.to_str().is_some_and(|p| p.contains(".test.")) { - continue; - } - println!("cargo:rerun-if-changed={}", path.display()); let rel = path.strip_prefix(root).expect("strip prefix"); // safety: build script — strip_prefix only fails on a logic bug // Force forward slashes in the URL key even on Windows hosts. let url = rel @@ -251,6 +187,7 @@ fn collect(root: &Path, dir: &Path, url_prefix: &str, out: &mut Vec<(String, Pat out.push((url, path)); } } + Ok(()) } fn content_type_for(path: &Path) -> &'static str { diff --git a/crates/ironclaw_webui_v2/frontend/README.md b/crates/ironclaw_webui_v2/frontend/README.md index f37e5a1c848..265ca0bca6c 100644 --- a/crates/ironclaw_webui_v2/frontend/README.md +++ b/crates/ironclaw_webui_v2/frontend/README.md @@ -11,29 +11,31 @@ corepack pnpm install --frozen-lockfile corepack pnpm dev corepack pnpm typecheck corepack pnpm test -corepack pnpm build:vite +corepack pnpm build ``` -At this point in the stack, Cargo still embeds the legacy esbuild bundle from -`build.mjs`, so `corepack pnpm build` and `corepack pnpm build:legacy` both run -that legacy bundle path. `corepack pnpm build:vite` is the Vite production build -for the new scaffold and writes ignored output to `frontend/dist/`. +`corepack pnpm build` runs Vite and writes ignored preview output to +`frontend/dist/`. Cargo does not embed that local preview directory. When +`webui-v2-beta` is enabled, `crates/ironclaw_webui_v2/build.rs` runs +`corepack pnpm install --frozen-lockfile` and a Vite production build into +Cargo's `OUT_DIR`, then embeds that generated output into the Rust binary. `./build.sh` is the one-shot local refresh helper. It vendors pinned browser -assets, installs with `corepack pnpm install --frozen-lockfile`, and builds the -legacy bundle used by this branch. +assets, installs dependencies with Corepack, and runs the Vite production build. +Use `./build.sh --no-vendor` when you only want to rebuild the SPA. ## Outputs | Output | Made by | Commit? | |---|---|---| -| `frontend/dist/` | `corepack pnpm build:vite` | No | -| `../static/dist/` | `build.mjs` / `./build.sh` | No | -| `../static/vendor/` | `vendor.sh` / `./build.sh` | Yes, only when intentionally refreshing vendor assets | +| `frontend/dist/` | `corepack pnpm build` / `./build.sh` | No | +| Cargo `OUT_DIR/webui-v2-frontend-dist/` | `build.rs` during Rust builds | No | +| `frontend/public/vendor/` | `vendor.sh` / `./build.sh` | Yes, only when intentionally refreshing vendor assets | ## Runtime Assets -The vendored browser globals remain separate same-origin files: +Vite owns the SPA entrypoint, CSS, hashed assets, and the NEAR wallet connect +entrypoint. The vendored browser globals remain separate same-origin files: - DOMPurify - marked diff --git a/crates/ironclaw_webui_v2/frontend/build.mjs b/crates/ironclaw_webui_v2/frontend/build.mjs deleted file mode 100644 index 82aa532919d..00000000000 --- a/crates/ironclaw_webui_v2/frontend/build.mjs +++ /dev/null @@ -1,63 +0,0 @@ -// Bundles the WebUI v2 SPA with Vite. -// -// Input: ./src/main.ts (entry) + the local TypeScript modules it -// imports, plus the React ecosystem (react, react-dom, -// react-router, @tanstack/react-query, react-hook-form, htm) -// resolved from ./node_modules. -// Output: $IRONCLAW_WEBUI_V2_DIST_DIR/app.{js,css}, wallet-connect.js, and -// chunks/* when that env var is set, otherwise ../static/dist/* for -// manual local builds. Locale chunks are code-split and dynamically -// imported by lib/i18n.js. -// -// Cargo invokes this in `webui-v2-beta` builds and embeds the generated output -// from OUT_DIR. Re-run via ./build.sh after editing frontend/src/** when you -// want a local static/dist preview. -// -// What is deliberately NOT bundled (kept as same-origin + diff --git a/crates/ironclaw_webui_v2/frontend/vendor.sh b/crates/ironclaw_webui_v2/frontend/vendor.sh index e63931f29a7..03de0449a41 100644 --- a/crates/ironclaw_webui_v2/frontend/vendor.sh +++ b/crates/ironclaw_webui_v2/frontend/vendor.sh @@ -1,8 +1,7 @@ #!/usr/bin/env bash -# Vendors the WebUI v2 third-party assets that stay OUTSIDE the esbuild -# bundle into ../static/vendor/, so the SPA loads zero remote origins. +# Vendors the WebUI v2 third-party assets that stay outside the Vite app bundle +# into public/vendor/, so the SPA loads zero remote origins. # -# - Tailwind browser runtime (DOM-scanning IIFE, not an ES module) # - DOMPurify / marked / highlight.js (consumed as window globals) # - Google Fonts CSS + woff2 files (url()s rewritten to local paths) # @@ -11,10 +10,9 @@ set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -VENDOR_DIR="$SCRIPT_DIR/../static/vendor" +VENDOR_DIR="$SCRIPT_DIR/public/vendor" FONTS_DIR="$VENDOR_DIR/fonts" -TAILWIND_VER="4.3.1" DOMPURIFY_VER="3.2.3" MARKED_VER="17.0.2" HLJS_VER="11.11.1" @@ -34,7 +32,6 @@ fetch() { } echo "Vendoring JS libraries…" -fetch "https://cdn.jsdelivr.net/npm/@tailwindcss/browser@${TAILWIND_VER}" "$VENDOR_DIR/tailwindcss-browser.js" fetch "https://cdnjs.cloudflare.com/ajax/libs/dompurify/${DOMPURIFY_VER}/purify.min.js" "$VENDOR_DIR/purify.min.js" fetch "https://cdn.jsdelivr.net/npm/marked@${MARKED_VER}/lib/marked.umd.min.js" "$VENDOR_DIR/marked.umd.min.js" fetch "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/${HLJS_VER}/highlight.min.js" "$VENDOR_DIR/highlight.min.js" @@ -59,4 +56,4 @@ CSS="${CSS//\'/\"}" printf '%s\n' "$CSS" > "$FONTS_DIR/fonts.css" -echo "Done. Vendored assets in static/vendor/" +echo "Done. Vendored assets in public/vendor/" diff --git a/crates/ironclaw_webui_v2/frontend/vite.config.ts b/crates/ironclaw_webui_v2/frontend/vite.config.ts index 26f479d394d..1e65bb8f0bb 100644 --- a/crates/ironclaw_webui_v2/frontend/vite.config.ts +++ b/crates/ironclaw_webui_v2/frontend/vite.config.ts @@ -47,6 +47,17 @@ export default defineConfig({ manifest: true, sourcemap: false, target: "es2022", + rollupOptions: { + input: { + app: resolve(here, "index.html"), + "wallet-connect": resolve(here, "src/wallet-connect.ts"), + }, + external: ["@hot-labs/near-connect"], + output: { + entryFileNames: (chunk) => + chunk.name === "wallet-connect" ? "wallet-connect.js" : "assets/[name]-[hash].js", + }, + }, }, test: { environment: "node", diff --git a/crates/ironclaw_webui_v2/src/lib.rs b/crates/ironclaw_webui_v2/src/lib.rs index 0dd46af8f3e..b25cdb2536c 100644 --- a/crates/ironclaw_webui_v2/src/lib.rs +++ b/crates/ironclaw_webui_v2/src/lib.rs @@ -53,9 +53,8 @@ mod router; mod schema; #[cfg(feature = "webui-v2-beta")] mod sse_capacity; -// Browser SPA asset bundle folded in from the former `ironclaw_webui_v2_static` -// crate: the JSON route surface and the static bytes it drives now ship from one -// crate behind the single `webui-v2-beta` feature. +// Browser SPA asset bundle: the JSON route surface and the static bytes it +// drives now ship from one crate behind the single `webui-v2-beta` feature. #[cfg(feature = "webui-v2-beta")] pub mod static_assets; @@ -128,8 +127,7 @@ pub use router::{ #[cfg(feature = "webui-v2-beta")] pub use schema::{WebChatV2Event, WebChatV2EventFrame}; // Re-export the static-bundle router factory at the crate root so host -// composition keeps calling `ironclaw_webui_v2::mount_at_prefix(...)` (formerly -// `ironclaw_webui_v2_static::mount_at_prefix`). +// composition keeps calling `ironclaw_webui_v2::mount_at_prefix(...)`. #[cfg(feature = "webui-v2-beta")] pub use sse_capacity::DEFAULT_SSE_MAX_CONCURRENT_PER_CALLER; #[cfg(feature = "webui-v2-beta")] diff --git a/crates/ironclaw_webui_v2/src/static_assets/assets.rs b/crates/ironclaw_webui_v2/src/static_assets/assets.rs index 02fe3204831..9123c444e02 100644 --- a/crates/ironclaw_webui_v2/src/static_assets/assets.rs +++ b/crates/ironclaw_webui_v2/src/static_assets/assets.rs @@ -26,8 +26,13 @@ pub(crate) fn lookup(path: &str) -> Option<&'static Asset> { mod tests { use super::*; - fn asset_text(path: &str) -> &'static str { - std::str::from_utf8(lookup(path).expect("asset exists").bytes).expect("asset is utf-8") + fn bundled_javascript() -> String { + ASSETS + .iter() + .filter(|(path, _)| path.starts_with("assets/app-") && path.ends_with(".js")) + .map(|(_, asset)| std::str::from_utf8(asset.bytes).expect("asset is utf-8")) + .collect::>() + .join("\n") } /// Read a frontend source file straight from `frontend/src/` on disk. @@ -421,7 +426,7 @@ mod tests { assert!(detail_panel.contains("primary_status_tone")); assert!(detail_panel.contains("window.confirm")); - let app_bundle = asset_text("dist/app.js"); + let app_bundle = bundled_javascript(); let app_bundle_contains_encoded_automation_route = |suffix: &str| { app_bundle .split("/automations/${encodeURIComponent(") @@ -439,9 +444,7 @@ mod tests { .split("/automations/${encodeURIComponent(") .any(|tail| { let near = tail.chars().take(220).collect::(); - (near.contains("method:\"DELETE\"") || near.contains("method:`DELETE`")) - && !near.contains("/pause") - && !near.contains("/resume") + near.contains("DELETE") && !near.contains("/pause") && !near.contains("/resume") }); assert!( app_bundle_contains_encoded_automation_delete, @@ -517,7 +520,7 @@ mod tests { assert!(layout.contains("sidebar.desktopOpen ? \"md:flex\" : \"md:hidden\"")); assert!(layout.contains("sidebarOpen=${sidebar.currentOpen}")); - let bundle = asset_text("dist/app.js"); + let bundle = bundled_javascript(); assert!(bundle.contains("ironclaw:v2-sidebar-open")); assert!(bundle.contains("desktopOpen")); assert!(bundle.contains("mobileOpen")); diff --git a/crates/ironclaw_webui_v2/src/static_assets/mod.rs b/crates/ironclaw_webui_v2/src/static_assets/mod.rs index 602b16887b1..e4beb6d1ff0 100644 --- a/crates/ironclaw_webui_v2/src/static_assets/mod.rs +++ b/crates/ironclaw_webui_v2/src/static_assets/mod.rs @@ -2,8 +2,8 @@ //! //! Ships the browser-side SPA that drives the JSON route surface in this crate. //! The SPA targets only the `/api/webchat/v2/*` endpoints — no v1 gateway -//! routes, no engine APIs. See `crates/ironclaw_webui_v2/static/` for the bundle -//! and the issue #3886 plan for the hard non-goals. +//! routes, no engine APIs. See `crates/ironclaw_webui_v2/frontend/` for the +//! TypeScript/Vite project and the issue #3886 plan for the hard non-goals. //! //! Folded in from the former `ironclaw_webui_v2_static` crate: the SPA bytes and //! the JSON route surface now ship from one crate behind the single diff --git a/crates/ironclaw_webui_v2/src/static_assets/router.rs b/crates/ironclaw_webui_v2/src/static_assets/router.rs index 6c1d97abe1e..bf91a7be419 100644 --- a/crates/ironclaw_webui_v2/src/static_assets/router.rs +++ b/crates/ironclaw_webui_v2/src/static_assets/router.rs @@ -200,12 +200,11 @@ fn render_index_with_nonce() -> Response { // `SetResponseHeaderLayer::if_not_present`, which honors the // header we set here instead of overwriting it. // - // Every sub-resource the shell loads is now same-origin: the - // esbuild app bundle (`/v2/dist/app.js`) folds in React + router + - // query + htm + react-hook-form, and Tailwind / dompurify / marked / - // highlight.js / the web fonts are vendored under `/v2/vendor/` - // (see `frontend/`). So `script-src` / `style-src` / `font-src` - // collapse to `'self'` — no CDN origins, no third-party fetches. + // Every sub-resource the shell loads is same-origin: Vite emits the app + // bundle and CSS under `/v2/assets/`, and Tailwind / dompurify / marked / + // highlight.js / the web fonts are vendored under `/v2/vendor/` (see + // `frontend/public`). So `script-src` / `style-src` / `font-src` collapse + // to `'self'` — no CDN origins, no third-party fetches. // `'unsafe-inline'` stays on `style-src` only: the Tailwind browser // runtime injects a generated ` - - - - - - - -
- - - diff --git a/crates/ironclaw_webui_v2/static/vendor/tailwindcss-browser.js b/crates/ironclaw_webui_v2/static/vendor/tailwindcss-browser.js deleted file mode 100644 index e20aa4cdd61..00000000000 --- a/crates/ironclaw_webui_v2/static/vendor/tailwindcss-browser.js +++ /dev/null @@ -1,8 +0,0 @@ -/** - * Minified by jsDelivr using Terser v5.48.0. - * Original file: /npm/@tailwindcss/browser@4.3.1/dist/index.global.js - * - * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files - */ -"use strict";(()=>{function e(e){let t=[0];for(let r=0;r0;){let o=n>>1,i=r+o;t[i]<=e?(r=i+1,n=n-o-1):n=o}return r-=1,{line:r+1,column:e-t[r]}},findOffset:function({line:e,column:r}){e-=1,e=Math.min(Math.max(e,0),t.length-1);let n=t[e],o=t[e+1]??n;return Math.min(Math.max(n+r,0),o)}}}var t=10,r=class t extends Error{loc;constructor(r,n){if(n){let t=n[0],o=e(t.code).find(n[1]);r=`${t.file}:${o.line}:${o.column+1}: ${r}`}super(r),this.name="CssSyntaxError",this.loc=n,Error.captureStackTrace&&Error.captureStackTrace(this,t)}};function n(e,n){let l=n?.from?{file:n.from,code:e}:null;"\ufeff"===e[0]&&(e=" "+e.slice(1));let s,c=[],u=[],d=[],f=null,p=null,h="",m="",g=0;for(let n=0;n0&&e[r]===t[t.length-1]&&(t=t.slice(0,-1))}}let d=i(h,u);if(!d)throw new r("Invalid custom property, expected a value",l?[l,o,n]:null);l&&(d.src=[l,o,n],d.dst=[l,o,n]),f?f.nodes.push(d):c.push(d),h=""}else if(59===v&&64===h.charCodeAt(0))p=o(h),l&&(p.src=[l,g,n],p.dst=[l,g,n]),f?f.nodes.push(p):c.push(p),h="",p=null;else if(59===v&&")"!==m[m.length-1]){let e=i(h);if(!e){if(0===h.length)continue;throw new r(`Invalid declaration: \`${h.trim()}\``,l?[l,g,n]:null)}l&&(e.src=[l,g,n],e.dst=[l,g,n]),f?f.nodes.push(e):c.push(e),h=""}else if(123===v&&")"!==m[m.length-1])m+="}",p=C(h.trim()),l&&(p.src=[l,g,n],p.dst=[l,g,n]),f&&f.nodes.push(p),d.push(f),f=p,h="",p=null;else if(125===v&&")"!==m[m.length-1]){if(""===m)throw new r("Missing opening {",l?[l,n,n]:null);if(m=m.slice(0,-1),h.length>0)if(64===h.charCodeAt(0))p=o(h),l&&(p.src=[l,g,n],p.dst=[l,g,n]),f?f.nodes.push(p):c.push(p),h="",p=null;else{let e=h.indexOf(":");if(f){let t=i(h,e);if(!t)throw new r(`Invalid declaration: \`${h.trim()}\``,l?[l,g,n]:null);l&&(t.src=[l,g,n],t.dst=[l,g,n]),f.nodes.push(t)}}let e=d.pop()??null;null===e&&f&&c.push(f),f=e,h="",p=null}else if(40===v)m+=")",h+="(";else if(41===v){if(")"!==m[m.length-1])throw new r("Missing opening (",l?[l,n,n]:null);m=m.slice(0,-1),h+=")"}else{if(0===h.length&&(32===v||v===t||9===v))continue;""===h&&(g=n),h+=String.fromCharCode(v)}}}if(64===h.charCodeAt(0)){let t=o(h);l&&(t.src=[l,g,e.length],t.dst=[l,g,e.length]),c.push(t)}if(m.length>0&&f){if("rule"===f.kind)throw new r(`Missing closing } at ${f.selector}`,f.src?[f.src[0],f.src[1],f.src[1]]:null);if("at-rule"===f.kind)throw new r(`Missing closing } at ${f.name} ${f.params}`,f.src?[f.src[0],f.src[1],f.src[1]]:null)}return u.length>0?u.concat(c):c}function o(e,t=[]){let r=e,n="";for(let t=5;t=1&&t<=31||127===t||0===o&&t>=48&&t<=57||1===o&&t>=48&&t<=57&&45===a?"\\"+t.toString(16)+" ":t>=128||45===t||95===t||t>=48&&t<=57||t>=65&&t<=90||t>=97&&t<=122?r.charAt(o):"\\"+r.charAt(o):"�";return i}function s(e){return e.replace(/\\([\dA-Fa-f]{1,6}[\t\n\f\r ]?|[\S\s])/g,e=>{if(e.length<=2)return e[1];let t=Number.parseInt(e.slice(1).trim(),16);return 0===t||t>1114111||t>=55296&&t<=57343?"�":String.fromCodePoint(t)})}var c=new Map([["--font",["--font-weight","--font-size"]],["--inset",["--inset-shadow","--inset-ring"]],["--text",["--text-color","--text-decoration-color","--text-decoration-thickness","--text-indent","--text-shadow","--text-underline-offset"]],["--grid-column",["--grid-column-start","--grid-column-end"]],["--grid-row",["--grid-row-start","--grid-row-end"]]]);function u(e,t){return(c.get(t)??[]).some(t=>e===t||e.startsWith(`${t}-`))}var d=class{constructor(e=new Map,t=new Set([])){this.values=e,this.keyframes=t}values;keyframes;prefix=null;get size(){return this.values.size}add(e,t,r=0,n){if(e.endsWith("-*")){if("initial"!==t)throw new Error(`Invalid theme value \`${t}\` for namespace \`${e}\``);"--*"===e?this.values.clear():this.clearNamespace(e.slice(0,-2),0)}if(4&r){let t=this.values.get(e);if(t&&!(4&t.options))return}"initial"===t?this.values.delete(e):this.values.set(e,{value:t,options:r,src:n})}keysInNamespaces(e){let t=[];for(let r of e){let e=`${r}-`;for(let n of this.values.keys())n.startsWith(e)&&-1===n.indexOf("--",2)&&(u(n,r)||t.push(n.slice(e.length)))}return t}get(e){for(let t of e){let e=this.values.get(t);if(e)return e.value}return null}hasDefault(e){return!(4&~this.getOptions(e))}getOptions(e){return e=s(this.#e(e)),this.values.get(e)?.options??0}entries(){return this.prefix?Array.from(this.values,e=>(e[0]=this.prefixKey(e[0]),e)):this.values.entries()}prefixKey(e){return this.prefix?`--${this.prefix}-${e.slice(2)}`:e}#e(e){return this.prefix?`--${e.slice(3+this.prefix.length)}`:e}clearNamespace(e,t){let r=c.get(e)??[];e:for(let n of this.values.keys())if(n.startsWith(e)){if(0!==t&&(this.getOptions(n)&t)!==t)continue;for(let e of r)if(n.startsWith(e))continue e;this.values.delete(n)}}#t(e,t){for(let r of t){let t=null!==e?`${r}-${e}`:r;if(!this.values.has(t)){if(null===e||!e.includes("."))continue;if(t=`${r}-${e.replaceAll(".","_")}`,!this.values.has(t))continue}if(!u(t,r))return t}return null}#r(e){let t=this.values.get(e);if(!t)return null;let r=null;return 2&t.options&&(r=t.value),`var(${l(this.prefixKey(e))}${r?`, ${r}`:""})`}markUsedVariable(e){let t=s(this.#e(e)),r=this.values.get(t);if(!r)return!1;let n=16&r.options;return r.options|=16,!n}resolve(e,t,r=0){let n=this.#t(e,t);if(!n)return null;let o=this.values.get(n);return 1&(r|o.options)?o.value:this.#r(n)}resolveValue(e,t){let r=this.#t(e,t);return r?this.values.get(r).value:null}resolveWith(e,t,r=[]){let n=this.#t(e,t);if(!n)return null;let o={};for(let e of r){let t=`${n}${e}`,r=this.values.get(t);r&&(1&r.options?o[e]=r.value:o[e]=this.#r(t))}let i=this.values.get(n);return 1&i.options?[i.value,o]:[this.#r(n),o]}namespace(e){let t=new Map,r=`${e}-`;for(let[n,o]of this.values)n===e?t.set(null,o.value):n.startsWith(`${r}-`)?t.set(n.slice(e.length),o.value):n.startsWith(r)&&t.set(n.slice(r.length),o.value);return t}addKeyframes(e){this.keyframes.add(e)}getKeyframes(){return Array.from(this.keyframes)}},f=class extends Map{constructor(e){super(),this.factory=e}factory;get(e){let t=super.get(e);return void 0===t&&(t=this.factory(e,this),this.set(e,t)),t}};function p(e){return{kind:"word",value:e}}function h(e,t){return{kind:"function",value:e,nodes:t}}function m(e){return{kind:"separator",value:e}}function g(e){let t="";for(let r of e)switch(r.kind){case"word":case"separator":t+=r.value;break;case"function":t+=r.value+"("+g(r.nodes)+")"}return t}function v(e){e=e.replaceAll("\r\n","\n");let t,r=[],n=[],o=null,i="";for(let a=0;a0){let e=p(i);o?o.nodes.push(e):r.push(e),i=""}let t=p(e[a]);o?o.nodes.push(t):r.push(t);break}case 58:case 44:case 61:case 62:case 60:case 10:case 32:case 9:{if(i.length>0){let e=p(i);o?o.nodes.push(e):r.push(e),i=""}let n=a,l=a+1;for(;l0){let t=p(i);e?.nodes.push(t),i=""}o=n.length>0?n[n.length-1]:null;break}default:i+=String.fromCharCode(l)}}return i.length>0&&r.push(p(i)),r}var k,w=((k=w||{})[k.Continue=0]="Continue",k[k.Skip=1]="Skip",k[k.Stop=2]="Stop",k[k.Replace=3]="Replace",k[k.ReplaceSkip=4]="ReplaceSkip",k[k.ReplaceStop=5]="ReplaceStop",k),b={Continue:{kind:0},Skip:{kind:1},Stop:{kind:2},Replace:e=>({kind:3,nodes:Array.isArray(e)?e:[e]}),ReplaceSkip:e=>({kind:4,nodes:Array.isArray(e)?e:[e]}),ReplaceStop:e=>({kind:5,nodes:Array.isArray(e)?e:[e]})};function y(e,t){"function"==typeof t?x(e,t):x(e,t.enter,t.exit)}function x(e,t=()=>b.Continue,r=()=>b.Continue){let n={value:[e,0,null],prev:null},o={parent:null,depth:0,index:0,siblings:e,path(){let e=[],t=n;for(;t;){let r=t.value[2];r&&e.push(r),t=t.prev}return e.reverse(),e}};for(;null!==n;){let e=n.value,i=e[0],a=e[1],l=e[2];if(a>=i.length){n=n.prev,o.depth-=1;continue}if(o.parent=l,o.siblings=i,a>=0){o.index=a;let r=i[a],l=t(r,o)??b.Continue;switch(l.kind){case 0:r.nodes&&r.nodes.length>0&&(o.depth+=1,n={value:[r.nodes,0,r],prev:n}),e[1]=~a;continue;case 2:return;case 1:e[1]=~a;continue;case 3:i.splice(a,1,...l.nodes);continue;case 5:return void i.splice(a,1,...l.nodes);case 4:i.splice(a,1,...l.nodes),e[1]+=l.nodes.length;continue;default:throw new Error(`Invalid \`WalkAction.${w[l.kind]??`Unknown(${l.kind})`}\` in enter.`)}}let s=~a;o.index=s;let c=r(i[s],o)??b.Continue;switch(c.kind){case 0:e[1]=s+1;continue;case 2:return;case 3:case 4:i.splice(s,1,...c.nodes),e[1]=s+c.nodes.length;continue;case 5:return void i.splice(s,1,...c.nodes);default:throw new Error(`Invalid \`WalkAction.${w[c.kind]??`Unknown(${c.kind})`}\` in exit.`)}}}function $(e){let t=[];return y(v(e),e=>{if("function"===e.kind&&"var"===e.value)return y(e.nodes,e=>{"word"!==e.kind||"-"!==e.value[0]||"-"!==e.value[1]||t.push(e.value)}),b.Skip}),t}var z=64;function A(e,t=[]){return{kind:"rule",selector:e,nodes:t}}function S(e,t="",r=[]){return{kind:"at-rule",name:e,params:t,nodes:r}}function C(e,t=[]){return e.charCodeAt(0)===z?o(e,t):A(e,t)}function j(e,t,r=!1){return{kind:"declaration",property:e,value:t,important:r}}function T(e){return{kind:"comment",value:e}}function V(e,t){return{kind:"context",context:e,nodes:t}}function K(e){return{kind:"at-root",nodes:e}}function E(e){switch(e.kind){case"rule":return{kind:e.kind,selector:e.selector,nodes:e.nodes.map(E),src:e.src,dst:e.dst};case"at-rule":return{kind:e.kind,name:e.name,params:e.params,nodes:e.nodes.map(E),src:e.src,dst:e.dst};case"at-root":return{kind:e.kind,nodes:e.nodes.map(E),src:e.src,dst:e.dst};case"context":return{kind:e.kind,context:{...e.context},nodes:e.nodes.map(E),src:e.src,dst:e.dst};case"declaration":return{kind:e.kind,property:e.property,value:e.value,important:e.important,src:e.src,dst:e.dst};case"comment":return{kind:e.kind,value:e.value,src:e.src,dst:e.dst};default:throw new Error(`Unknown node kind: ${e.kind}`)}}function N(e){return{depth:e.depth,index:e.index,siblings:e.siblings,get context(){let t={};for(let r of e.path())"context"===r.kind&&Object.assign(t,r.context);return Object.defineProperty(this,"context",{value:t}),t},get parent(){let e=this.path().pop()??null;return Object.defineProperty(this,"parent",{value:e}),e},path:()=>e.path().filter(e=>"context"!==e.kind)}}function O(e,t,r=3){let n=[],o=new Set,i=new f(()=>new Set),a=new f(()=>new Set),l=new Set,s=new Set,c=[],u=[],d=new f(()=>new Set);function p(e,f,h={},m=0){if("declaration"===e.kind){if("--tw-sort"===e.property||void 0===e.value||null===e.value)return;if(h.theme&&"-"===e.property[0]&&"-"===e.property[1]){if("initial"===e.value)return void(e.value=void 0);h.keyframes||i.get(f).add(e)}if(e.value.includes("var("))if(h.theme&&"-"===e.property[0]&&"-"===e.property[1])for(let t of $(e.value))d.get(t).add(e.property);else t.trackUsedVariables(e.value);if("animation"===e.property)for(let t of R(e.value))s.add(t);2&r&&e.value.includes("color-mix(")&&!h.supportsColorMix&&!h.keyframes&&a.get(f).add(e),f.push(e)}else if("rule"===e.kind){let t=[];for(let r of e.nodes)p(r,t,h,m+1);let r={},n=new Set;for(let e of t){if("declaration"!==e.kind)continue;let t=`${e.property}:${e.value}:${e.important}`;r[t]??=[],r[t].push(e)}for(let e in r)for(let t=0;t0&&(t=t.filter(e=>!n.has(e))),0===t.length)return;"&"===e.selector?f.push(...t):f.push({...e,nodes:t})}else if("at-rule"===e.kind&&"@property"===e.name&&0===m){if(o.has(e.params))return;if(1&r){let t=e.params,r=null,n=!1;for(let t of e.nodes)"declaration"===t.kind&&("initial-value"===t.property?r=t.value:"inherits"===t.property&&(n="true"===t.value));let o=j(t,r??"initial");o.src=e.src,n?c.push(o):u.push(o)}o.add(e.params);let t={...e,nodes:[]};for(let r of e.nodes)p(r,t.nodes,h,m+1);f.push(t)}else if("at-rule"===e.kind){"@keyframes"===e.name?h={...h,keyframes:!0}:"@supports"===e.name&&e.params.includes("color-mix(")&&(h={...h,supportsColorMix:!0});let t={...e,nodes:[]};for(let r of e.nodes)p(r,t.nodes,h,m+1);"@keyframes"===e.name&&h.theme&&l.add(t),(t.nodes.length>0||"@layer"===t.name||"@charset"===t.name||"@custom-media"===t.name||"@namespace"===t.name||"@import"===t.name||"@apply"===t.name)&&f.push(t)}else if("at-root"===e.kind)for(let t of e.nodes){let e=[];p(t,e,h,0);for(let t of e)n.push(t)}else if("context"===e.kind){if(e.context.reference)return;for(let t of e.nodes)p(t,f,{...h,...e.context},m)}else"comment"===e.kind&&f.push(e)}let h=[];for(let t of e)p(t,h,{},0);e:for(let[e,r]of i)for(let n of r){if(W(n.property,t.theme,d)){if(n.property.startsWith(t.theme.prefixKey("--animate-")))for(let e of R(n.value))s.add(e);continue}let r=e.indexOf(n);if(e.splice(r,1),0===e.length){let t=U(h,t=>"rule"===t.kind&&t.nodes===e);if(!t||0===t.length)continue e;for(t.unshift({kind:"at-root",nodes:h});;){let e=t.pop();if(!e)break;let r=t[t.length-1];if(!r||"at-root"!==r.kind&&"at-rule"!==r.kind)break;let n=r.nodes.indexOf(e);if(-1===n)break;r.nodes.splice(n,1)}continue e}}for(let e of l)if(!s.has(e.params)){let t=n.indexOf(e);n.splice(t,1)}if(h=h.concat(n),2&r)for(let[e,r]of a)for(let n of r){let r=e.indexOf(n);if(-1===r||null==n.value)continue;let o=v(n.value),i=!1;if(y(o,e=>{if("function"!==e.kind||"color-mix"!==e.value)return;let r=!1,n=!1;if(y(e.nodes,e=>{if("word"==e.kind&&"currentcolor"===e.value.toLowerCase())return n=!0,void(i=!0);let o=e,a=null,l=new Set;do{if("function"!==o.kind||"var"!==o.value)return;let e=o.nodes[0];if(!e||"word"!==e.kind)return;let s=e.value;if(l.has(s))return void(r=!0);if(l.add(s),i=!0,a=t.theme.resolveValue(null,[e.value]),!a)return void(r=!0);if("currentcolor"===a.toLowerCase())return void(n=!0);o=a.startsWith("var(")?v(a)[0]:null}while(o);return b.Replace({kind:"word",value:a})}),r||n){let t=e.nodes.findIndex(e=>"separator"===e.kind&&e.value.trim().includes(","));if(-1===t)return;let r=e.nodes.length>t?e.nodes[t+1]:null;return r?b.Replace(r):void 0}if(i){let t=e.nodes[2];"word"===t.kind&&("oklab"===t.value||"oklch"===t.value||"lab"===t.value||"lch"===t.value)&&(t.value="srgb")}}),!i)continue;let a={...n,value:g(o)},l=C("@supports (color: color-mix(in lab, red, red))",[n]);l.src=n.src,e.splice(r,1,a,l)}if(1&r){let e=[];if(c.length>0){let t=C(":root, :host",c);t.src=c[0].src,e.push(t)}if(u.length>0){let t=C("*, ::before, ::after, ::backdrop",u);t.src=u[0].src,e.push(t)}if(e.length>0){let t=h.findIndex(e=>!("comment"===e.kind||"at-rule"===e.kind&&("@charset"===e.name||"@import"===e.name))),r=S("@layer","properties",[]);r.src=e[0].src,h.splice(t<0?h.length:t,0,r);let n=C("@layer properties",[S("@supports","((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b))))",e)]);n.src=e[0].src,n.nodes[0].src=e[0].src,h.push(n)}}return h}function F(e,t){let r=0,n={file:null,code:""};function o(e,i=0){let a="",l=" ".repeat(i);if("declaration"===e.kind){if(a+=`${l}${e.property}: ${e.value}${e.important?" !important":""};\n`,t){r+=l.length;let t=r;r+=e.property.length,r+=2,r+=e.value?.length??0,e.important&&(r+=11);let o=r;r+=2,e.dst=[n,t,o]}}else if("rule"===e.kind){if(a+=`${l}${e.selector} {\n`,t){r+=l.length;let t=r;r+=e.selector.length,r+=1;let o=r;e.dst=[n,t,o],r+=2}for(let t of e.nodes)a+=o(t,i+1);a+=`${l}}\n`,t&&(r+=l.length,r+=2)}else if("at-rule"===e.kind){if(0===e.nodes.length){let o=`${l}${e.name} ${e.params};\n`;if(t){r+=l.length;let t=r;r+=e.name.length,r+=1,r+=e.params.length;let o=r;r+=2,e.dst=[n,t,o]}return o}if(a+=`${l}${e.name}${e.params?` ${e.params} `:" "}{\n`,t){r+=l.length;let t=r;r+=e.name.length,e.params&&(r+=1,r+=e.params.length),r+=1;let o=r;e.dst=[n,t,o],r+=2}for(let t of e.nodes)a+=o(t,i+1);a+=`${l}}\n`,t&&(r+=l.length,r+=2)}else if("comment"===e.kind){if(a+=`${l}/*${e.value}*/\n`,t){r+=l.length;let t=r;r+=2+e.value.length+2;let o=r;e.dst=[n,t,o],r+=1}}else if("context"===e.kind||"at-root"===e.kind)return"";return a}let i="";for(let t of e)i+=o(t,0);return n.code=i,i}function U(e,t){let r=[];return y(e,(e,n)=>{if(t(e))return r=n.path(),r.push(e),b.Stop}),r}function W(e,t,r,n=new Set){if(n.has(e)||(n.add(e),24&t.getOptions(e)))return!0;{let o=r.get(e)??[];for(let e of o)if(W(e,t,r,n))return!0}return!1}function R(e){return e.split(/[\s,]+/)}var D=["calc","min","max","clamp","mod","rem","sin","cos","tan","asin","acos","atan","atan2","pow","sqrt","hypot","log","exp","round"];function L(e){return-1!==e.indexOf("(")&&D.some(t=>e.includes(`${t}(`))}function _(e){if(!D.some(t=>e.includes(t)))return e;let t="",r=[],n=null,o=null;for(let i=0;i=48&&a<=57||null!==n&&(37===a||a>=97&&a<=122||a>=65&&a<=90)?n=i:(o=n,n=null),40===a){t+=e[i];let n=i;for(let t=i-1;t>=0;t--){let r=e.charCodeAt(t);if(r>=48&&r<=57)n=t;else{if(!(r>=97&&r<=122))break;n=t}}let o=e.slice(n,i);if(D.includes(o)){r.unshift(!0);continue}if(r[0]&&""===o){r.unshift(!0);continue}r.unshift(!1);continue}if(41===a)t+=e[i],r.shift();else{if(44===a&&r[0]){t+=", ";continue}if(32===a&&r[0]&&32===t.charCodeAt(t.length-1))continue;if(43!==a&&42!==a&&47!==a&&45!==a||!r[0])t+=e[i];else{let r=t.trimEnd(),n=r.charCodeAt(r.length-1),a=r.charCodeAt(r.length-2),l=e.charCodeAt(i+1);if((101===n||69===n)&&a>=48&&a<=57){t+=e[i];continue}if(43===n||42===n||47===n||45===n){t+=e[i];continue}if(40===n||44===n){t+=e[i];continue}32===e.charCodeAt(i-1)?t+=`${e[i]} `:t+=n>=48&&n<=57||l>=48&&l<=57||41===n||40===l||43===l||42===l||47===l||45===l||null!==o&&o===i-1?` ${e[i]} `:e[i]}}}return t}function M(e){if(-1===e.indexOf("("))return B(e);let t=v(e);return I(t),e=_(e=g(t))}function B(e,t=!1){let r="";for(let n=0;n0&&o===q[t-1]&&t--;break;case 59:if(0===t)return!1}}return!0}var Y=new Uint8Array(256);function Z(e,t){let r=0,n=[],o=0,i=e.length,a=t.charCodeAt(0);for(let t=0;t0&&l===Y[r-1]&&r--}else n.push(e.slice(o,t)),o=t+1}return n.push(e.slice(o)),n}var G=/^[a-zA-Z0-9_.%-]+$/;function J(e){if("["===e[0]&&"]"===e[e.length-1]){let t=M(e.slice(1,-1));return H(t)&&0!==t.length&&0!==t.trim().length?{kind:"arbitrary",value:t}:null}return"("===e[0]&&")"===e[e.length-1]?"-"===(e=e.slice(1,-1))[0]&&"-"===e[1]&&H(e)?{kind:"arbitrary",value:M(e=`var(${e})`)}:null:G.test(e)?{kind:"named",value:e}:null}function*X(e,t){t(e)&&(yield[e,null]);let r=e.lastIndexOf("-");for(;r>0;){let n=e.slice(0,r);if(t(n)){let o=[n,e.slice(r+1)];if(""===o[1]||"@"===o[0]&&t("@")&&"-"===e[r])break;yield o}r=e.lastIndexOf("-",r-1)}"@"===e[0]&&t("@")&&(yield["@",e.slice(1)])}function Q(e){if(null===e)return"";let t=ae(e.value),r=t?e.value.slice(4,-1):e.value,[n,o]=t?["(",")"]:["[","]"];return"arbitrary"===e.kind?`/${n}${re(r)}${o}`:"named"===e.kind?`/${e.value}`:""}function ee(e){if("static"===e.kind)return e.root;if("arbitrary"===e.kind)return`[${re(function(e){return ne.get(e)}(e.selector))}]`;let t="";if("functional"===e.kind){t+=e.root;let r="@"!==e.root;if(e.value)if("arbitrary"===e.value.kind){let n=ae(e.value.value),o=n?e.value.value.slice(4,-1):e.value.value,[i,a]=n?["(",")"]:["[","]"];t+=`${r?"-":""}${i}${re(o)}${a}`}else"named"===e.value.kind&&(t+=`${r?"-":""}${e.value.value}`)}return"compound"===e.kind&&(t+=e.root,t+="-",t+=ee(e.variant)),("functional"===e.kind||"compound"===e.kind)&&(t+=Q(e.modifier)),t}var te=new f(e=>{let t=v(e),r=new Set,n=new Set(["~",">","+","-","*","/"]);return y(t,(e,t)=>{if("word"===e.kind&&n.has(e.value)){let e=t.index;if(-1===e)return;let o=t.siblings[e-1];if("separator"!==o?.kind||" "!==o.value)return;let i=t.siblings[e+1];if("separator"!==i?.kind||" "!==i.value)return;let a=t.siblings[e-2];if(a&&n.has(a.value))return;let l=t.siblings[e+2];if(l&&n.has(l.value))return;r.add(o),r.add(i)}else if("separator"===e.kind&&e.value.length>0&&""===e.value.trim())(t.siblings[0]===e||t.siblings[t.siblings.length-1]===e)&&r.add(e);else if("separator"===e.kind&&","===e.value.trim())e.value=",";else if("function"===e.kind&&e.value.startsWith("--")){let r=t.index;if(r<=0)return;let o=t.siblings[r-1];if("separator"===o?.kind&&","===o.value)return;let i=t.siblings[r-2];return i&&!n.has(i.value)?void 0:b.ReplaceSkip({kind:"function",value:"",nodes:[e]})}}),r.size>0&&y(t,e=>{if(r.has(e))return r.delete(e),b.ReplaceSkip([])}),oe(t),g(t)});function re(e){return te.get(e)}var ne=new f(e=>{let t=v(e);return 3===t.length&&"word"===t[0].kind&&"&"===t[0].value&&"separator"===t[1].kind&&":"===t[1].value&&"function"===t[2].kind&&"is"===t[2].value?g(t[2].nodes):e});function oe(e){for(let t of e)switch(t.kind){case"function":if("url"===t.value||t.value.endsWith("_url")){t.value=se(t.value);break}if("var"===t.value||t.value.endsWith("_var")||"theme"===t.value||t.value.endsWith("_theme")){t.value=se(t.value);for(let e=0;e{let t=v(e);return 1===t.length&&"function"===t[0].kind&&"var"===t[0].value});function ae(e){return ie.get(e)}function le(e){throw new Error(`Unexpected value: ${e}`)}function se(e){return e.replaceAll("_",String.raw`\_`).replaceAll(" ","_")}function ce(e,t,r){if(e===t)return 0;let n=e.indexOf("("),o=t.indexOf("("),i=-1===n?e.replace(/[\d.]+/g,""):e.slice(0,n),a=-1===o?t.replace(/[\d.]+/g,""):t.slice(0,o),l=(i===a?0:i[-+]?(?:\d*\.)?\d+)(?[a-z]+|%)?$/i,de=new f(e=>{let t=ue.exec(e);if(!t)return null;let r=t.groups?.value;if(void 0===r)return null;let n=Number(r);if(Number.isNaN(n))return null;let o=t.groups?.unit;return void 0===o?[n,null]:[n,o]}),fe=new Set(["black","silver","gray","white","maroon","red","purple","fuchsia","green","lime","olive","yellow","navy","blue","teal","aqua","aliceblue","antiquewhite","aqua","aquamarine","azure","beige","bisque","black","blanchedalmond","blue","blueviolet","brown","burlywood","cadetblue","chartreuse","chocolate","coral","cornflowerblue","cornsilk","crimson","cyan","darkblue","darkcyan","darkgoldenrod","darkgray","darkgreen","darkgrey","darkkhaki","darkmagenta","darkolivegreen","darkorange","darkorchid","darkred","darksalmon","darkseagreen","darkslateblue","darkslategray","darkslategrey","darkturquoise","darkviolet","deeppink","deepskyblue","dimgray","dimgrey","dodgerblue","firebrick","floralwhite","forestgreen","fuchsia","gainsboro","ghostwhite","gold","goldenrod","gray","green","greenyellow","grey","honeydew","hotpink","indianred","indigo","ivory","khaki","lavender","lavenderblush","lawngreen","lemonchiffon","lightblue","lightcoral","lightcyan","lightgoldenrodyellow","lightgray","lightgreen","lightgrey","lightpink","lightsalmon","lightseagreen","lightskyblue","lightslategray","lightslategrey","lightsteelblue","lightyellow","lime","limegreen","linen","magenta","maroon","mediumaquamarine","mediumblue","mediumorchid","mediumpurple","mediumseagreen","mediumslateblue","mediumspringgreen","mediumturquoise","mediumvioletred","midnightblue","mintcream","mistyrose","moccasin","navajowhite","navy","oldlace","olive","olivedrab","orange","orangered","orchid","palegoldenrod","palegreen","paleturquoise","palevioletred","papayawhip","peachpuff","peru","pink","plum","powderblue","purple","rebeccapurple","red","rosybrown","royalblue","saddlebrown","salmon","sandybrown","seagreen","seashell","sienna","silver","skyblue","slateblue","slategray","slategrey","snow","springgreen","steelblue","tan","teal","thistle","tomato","turquoise","violet","wheat","white","whitesmoke","yellow","yellowgreen","transparent","currentcolor","canvas","canvastext","linktext","visitedtext","activetext","buttonface","buttontext","buttonborder","field","fieldtext","highlight","highlighttext","selecteditem","selecteditemtext","mark","marktext","graytext","accentcolor","accentcolortext"]),pe=/^(rgba?|hsla?|hwb|color|(ok)?(lab|lch)|light-dark|color-mix)\(/i;var he={color:function(e){return 35===e.charCodeAt(0)||pe.test(e)||fe.has(e.toLowerCase())},length:Ce,percentage:ze,ratio:function(e){return Ae.test(e)||L(e)},number:xe,integer:Ve,url:ve,position:function(e){let t=0;for(let r of Z(e," "))if("center"!==r&&"top"!==r&&"right"!==r&&"bottom"!==r&&"left"!==r){if(!r.startsWith("var(")){if(Ce(r)||ze(r)){t+=1;continue}return!1}}else t+=1;return t>0},"bg-size":function(e){let t=0;for(let r of Z(e,",")){if("cover"===r||"contain"===r){t+=1;continue}let e=Z(r," ");if(1!==e.length&&2!==e.length)return!1;e.every(e=>"auto"===e||Ce(e)||ze(e))&&(t+=1)}return t>0},"line-width":function(e){return Z(e," ").every(e=>Ce(e)||xe(e)||"thin"===e||"medium"===e||"thick"===e)},image:function(e){let t=0;for(let r of Z(e,","))if(!r.startsWith("var(")){if(ve(r)){t+=1;continue}if(we.test(r)){t+=1;continue}if(ke.test(r)){t+=1;continue}return!1}return t>0},"family-name":function(e){let t=0;for(let r of Z(e,",")){let e=r.charCodeAt(0);if(e>=48&&e<=57)return!1;r.startsWith("var(")||(t+=1)}return t>0},"generic-name":function(e){return"serif"===e||"sans-serif"===e||"monospace"===e||"cursive"===e||"fantasy"===e||"system-ui"===e||"ui-serif"===e||"ui-sans-serif"===e||"ui-monospace"===e||"ui-rounded"===e||"math"===e||"emoji"===e||"fangsong"===e},"absolute-size":function(e){return"xx-small"===e||"x-small"===e||"small"===e||"medium"===e||"large"===e||"x-large"===e||"xx-large"===e||"xxx-large"===e},"relative-size":function(e){return"larger"===e||"smaller"===e},angle:function(e){return je.test(e)},vector:function(e){return Te.test(e)}};function me(e,t){if(e.startsWith("var("))return null;for(let r of t)if(he[r]?.(e))return r;return null}var ge=/^url\(.*\)$/;function ve(e){return ge.test(e)}var ke=/^(?:element|image|cross-fade|image-set)\(/,we=/^(repeating-)?(conic|linear|radial)-gradient\(/;var be=/[+-]?\d*\.?\d+(?:[eE][+-]?\d+)?/,ye=new RegExp(`^${be.source}$`);function xe(e){return ye.test(e)||L(e)}var $e=new RegExp(`^${be.source}%$`);function ze(e){return $e.test(e)||L(e)}var Ae=new RegExp(`^${be.source}\\s*/\\s*${be.source}$`);var Se=new RegExp(`^${be.source}(${["cm","mm","Q","in","pc","pt","px","em","ex","ch","rem","lh","rlh","vw","vh","vmin","vmax","vb","vi","svw","svh","lvw","lvh","dvw","dvh","cqw","cqh","cqi","cqb","cqmin","cqmax"].join("|")})$`);function Ce(e){return Se.test(e)||L(e)}var je=new RegExp(`^${be.source}(${["deg","rad","grad","turn"].join("|")})$`);var Te=new RegExp(`^${be.source} +${be.source} +${be.source}$`);function Ve(e){let t=Number(e);return Number.isInteger(t)&&t>=0&&String(t)===String(e)}function Ke(e){let t=Number(e);return Number.isInteger(t)&&t>0&&String(t)===String(e)}function Ee(e){return Oe(e,.25)}function Ne(e){return Oe(e,.25)}function Oe(e,t){let r=Number(e);return r>=0&&r%t===0&&String(r)===String(e)}var Fe=new Set(["inset","inherit","initial","revert","unset"]),Ue=new Set(["calc","clamp","max","min","--spacing"]),We=new Set(["color","color-mix","contrast-color","device-cmyk","hsl","hsla","hwb","lab","lch","light-dark","oklab","oklch","rgb","rgba","--alpha"]),Re=/^-?(\d+|\.\d+)(.*?)$/;function De(e,t){function r(e){let r=g([e]);return v(t(r))}return Z(e,",").map(e=>{let n=v(e=e.trim()),o=null,i=0,a=0,l=!1;return y(n,e=>{switch(e.kind){case"word":if(Fe.has(e.value.toLowerCase()))return b.Continue;if(Re.test(e.value.toLowerCase()))return a++,b.Continue;if("#"===e.value[0]||function(e){return fe.has(e.toLowerCase())}(e.value))return l=!0,b.ReplaceStop(r(e));o=e,i++;break;case"function":return We.has(e.value.toLowerCase())?(l=!0,b.ReplaceStop(r(e))):Ue.has(e.value.toLowerCase())?(a++,b.Skip):(o=e,i++,b.Skip);case"separator":return b.Continue}}),l?g(n):a<2?e:0===i?`${e} ${t("currentcolor")}`:(1===i&&y(n,e=>e===o?(l=!0,b.ReplaceStop(r(e))):b.Skip),l?g(n):e)}).join(", ")}var Le=["0","0.5","1","1.5","2","2.5","3","3.5","4","5","6","7","8","9","10","11","12","14","16","20","24","28","32","36","40","44","48","52","56","60","64","72","80","96"],_e=class{utilities=new f(()=>[]);completions=new Map;static(e,t){this.utilities.get(e).push({kind:"static",compileFn:t})}functional(e,t,r){this.utilities.get(e).push({kind:"functional",compileFn:t,options:r})}has(e,t){return this.utilities.has(e)&&this.utilities.get(e).some(e=>e.kind===t)}get(e){return this.utilities.has(e)?this.utilities.get(e):[]}getCompletions(e){return this.has(e,"static")?this.completions.get(e)?.()??[{supportsNegative:!1,values:[],modifiers:[]}]:this.completions.get(e)?.()??[]}suggest(e,t){let r=this.completions.get(e);r?this.completions.set(e,()=>[...r?.(),...t?.()]):this.completions.set(e,t)}keys(e){let t=[];for(let[r,n]of this.utilities.entries())for(let o of n)if(o.kind===e){t.push(r);break}return t}};function Me(e,t,r){return S("@property",e,[j("syntax",r?`"${r}"`:'"*"'),j("inherits","false"),...t?[j("initial-value",t)]:[]])}function Be(e,t){if(null===t)return e;let r=Number(t);return Number.isNaN(r)||(t=100*r+"%"),"100%"===t?e:`color-mix(in oklab, ${e} ${t}, transparent)`}function Ie(e,t){let r=Number(t);return Number.isNaN(r)||(t=100*r+"%"),`oklab(from ${e} l a b / ${t})`}function Pe(e,t,r){if(!t)return e;if("arbitrary"===t.kind)return Be(e,t.value);let n=r.resolve(t.value,["--opacity"]);return n?Be(e,n):Ne(t.value)?Be(e,`${t.value}%`):null}function qe(e,t,r){let n=null;switch(e.value.value){case"inherit":n="inherit";break;case"transparent":n="transparent";break;case"current":n="currentcolor";break;default:n=t.resolve(e.value.value,r)}return n?Pe(n,e.modifier,t):null}var He=/(\d+)_(\d+)/g;var Ye=["number","integer","ratio","percentage"];function Ze(e){let t=s(e.params);return function(e){if(!e.endsWith("-*"))return!1;e=e.slice(0,-2);let t=Qe.exec(e);if(null===t)return!1;let r=t[0];return 0===e.slice(r.length).length}(t)?r=>{let n={"--value":{usedSpacingInteger:!1,usedSpacingNumber:!1,themeKeys:new Set,literals:new Set},"--modifier":{usedSpacingInteger:!1,usedSpacingNumber:!1,themeKeys:new Set,literals:new Set}};y(e.nodes,e=>{if("declaration"!==e.kind||!e.value||!e.value.includes("--value(")&&!e.value.includes("--modifier("))return;let t=v(e.value);y(t,e=>{if("function"!==e.kind)return;if(!("--spacing"!==e.value||n["--modifier"].usedSpacingNumber&&n["--value"].usedSpacingNumber))return y(e.nodes,e=>{if("function"!==e.kind||"--value"!==e.value&&"--modifier"!==e.value)return;let t=e.value;for(let r of e.nodes)if("word"===r.kind)if("integer"===r.value)n[t].usedSpacingInteger||=!0;else if("number"===r.value&&(n[t].usedSpacingNumber||=!0,n["--modifier"].usedSpacingNumber&&n["--value"].usedSpacingNumber))return b.Stop}),b.Continue;if("--value"!==e.value&&"--modifier"!==e.value)return;let t=Z(g(e.nodes),",");for(let[e,r]of t.entries())r=r.replace(/\\\*/g,"*"),r=r.replace(/--(.*?)\s--(.*?)/g,"--$1-*--$2"),r=r.replace(/\s+/g,""),r=r.replace(/(-\*){2,}/g,"-*"),"-"===r[0]&&"-"===r[1]&&!r.includes("(")&&!r.includes("-*")&&(r+="-*"),t[e]=r;e.nodes=v(t.join(","));for(let t of e.nodes)if("word"!==t.kind||'"'!==t.value[0]&&"'"!==t.value[0]||t.value[0]!==t.value[t.value.length-1]){if("word"===t.kind&&"-"===t.value[0]&&"-"===t.value[1]){let r=t.value.replace(/-\*.*$/g,"");n[e.value].themeKeys.add(r)}else if("word"===t.kind&&("["!==t.value[0]||"]"!==t.value[t.value.length-1])&&!Ye.includes(t.value)){console.warn(`Unsupported bare value data type: "${t.value}".\nOnly valid data types are: ${Ye.map(e=>`"${e}"`).join(", ")}.\n`);let r=t.value,n=structuredClone(e),o="¶";y(n.nodes,e=>{if("word"===e.kind&&e.value===r)return b.ReplaceSkip({kind:"word",value:o})});let i="^".repeat(g([t]).length),a=g([n]).indexOf(o),l=["```css",g([e])," ".repeat(a)+i,"```"].join("\n");console.warn(l)}}else{let r=t.value.slice(1,-1);n[e.value].literals.add(r)}}),e.value=g(t)}),r.utilities.functional(t.slice(0,-2),t=>{let n=E(e),o=t.value,i=t.modifier,a=!1,l=!1,s=!1,c=!1,u=new Map,d=!1;if(y([n],(e,t)=>{let n=t.parent;if("rule"!==n?.kind&&"at-rule"!==n?.kind||"declaration"!==e.kind||!e.value)return;let f=!1,p=v(e.value);if(y(p,t=>{if("function"===t.kind){if("--value"===t.value){a=!0;let i=Ge(o,t,r);return i?(l=!0,i.ratio?d=!0:u.set(e,n),b.ReplaceSkip(i.nodes)):(f=!0,b.Stop)}if("--modifier"===t.value){s=!0;let e=Ge(i,t,r);return e?(c=!0,b.ReplaceSkip(e.nodes)):(f=!0,b.Stop)}}}),f)return b.ReplaceSkip([]);e.value=g(p)}),!a||!l||s&&!c&&null!==i||d&&c||i&&!d&&!c)return null;if(d)for(let[e,t]of u){let r=t.nodes.indexOf(e);-1!==r&&t.nodes.splice(r,1)}return n.nodes}),r.utilities.suggest(t.slice(0,-2),()=>{let e=[],t=[];for(let[o,{literals:i,usedSpacingNumber:a,usedSpacingInteger:l,themeKeys:s}]of[[e,n["--value"]],[t,n["--modifier"]]]){for(let e of i)o.push(e);if(a)o.push(...Le);else if(l)for(let e of Le)Ve(e)&&o.push(e);for(let e of r.theme.keysInNamespaces(s))o.push(e.replace(He,(e,t,r)=>`${t}.${r}`))}return[{values:e,modifiers:t}]})}:function(e){let t=Qe.exec(e);if(null===t)return!1;let r=t[0],n=e.slice(r.length);if(0===n.length&&r.endsWith("-"))return!1;if(0===n.length)return!0;let o=!1;for(let e=0;est)return!1;break}case tt:if(e===n.length-1||o)return!1;o=!0;break;case rt:{let t=(n[e-1]||r[r.length-1]||"").charCodeAt(0);if(tst)return!1;let o=(n[e+1]||"").charCodeAt(0);if(ost)return!1;break}case ct:case ut:continue;default:if(t>=nt&&t<=ot||t>=it&&t<=at||t>=lt&&t<=st)continue;return!1}}return!0}(t)?r=>{r.utilities.static(t,()=>e.nodes.map(E))}:null}function Ge(e,t,r){if(null!==e)for(let n of t.nodes){if("named"===e.kind&&"word"===n.kind&&("'"===n.value[0]||'"'===n.value[0])&&n.value[n.value.length-1]===n.value[0]&&n.value.slice(1,-1)===e.value)return{nodes:v(e.value)};if("named"===e.kind&&"word"===n.kind&&"-"===n.value[0]&&"-"===n.value[1]){let t=n.value;if(t.endsWith("-*")){t=t.slice(0,-2);let n=r.theme.resolve(e.value,[t]);if(n)return{nodes:v(n)}}else{let n=t.split("-*");if(n.length<=1)continue;let o=[n.shift()],i=r.theme.resolveWith(e.value,o,n);if(i){let[,e={}]=i;{let t=e[n.pop()];if(t)return{nodes:v(t)}}}}}else{if("named"===e.kind&&"word"===n.kind){if(!Ye.includes(n.value))continue;let t="ratio"===n.value&&"fraction"in e?e.fraction:e.value;if(!t)continue;let r=me(t,[n.value]);if(null===r)continue;if("ratio"===r){let[e,r]=Z(t,"/").map(Number);if(!Ve(e)||!Ve(r))continue}else{if("number"===r&&!Ee(t))continue;if("percentage"===r&&!Ve(t.slice(0,-1)))continue}if("ratio"===r){let[e,r]=Z(t,"/");return{nodes:v(`${e.trim()} / ${r.trim()}`),ratio:!0}}return{nodes:v(t),ratio:!1}}if("arbitrary"===e.kind&&"word"===n.kind&&"["===n.value[0]&&"]"===n.value[n.value.length-1]){let t=n.value.slice(1,-1);if("*"===t)return{nodes:v(e.value)};if("dataType"in e&&e.dataType&&e.dataType!==t)continue;if("dataType"in e&&e.dataType)return{nodes:v(e.value)};if(null!==me(e.value,[t]))return{nodes:v(e.value)}}}}else for(let e of t.nodes)if("function"===e.kind&&"--default"===e.value)return{nodes:e.nodes}}function Je(e,t,r,n,o=""){let i=!1,a=De(t,e=>null==r?n(e):e.startsWith("current")?n(Be(e,r)):((e.startsWith("var(")||r.startsWith("var("))&&(i=!0),n(Ie(e,r))));function l(e){return o?Z(e,",").map(e=>o.trim()+" "+e.trim()).join(", "):e}return i?[j(e,l(De(t,n))),C("@supports (color: lab(from red l a b))",[j(e,l(a))])]:[j(e,l(a))]}function Xe(e,t,r,n,o=""){let i=!1,a=Z(t,",").map(e=>De(e,e=>null==r?n(e):e.startsWith("current")?n(Be(e,r)):((e.startsWith("var(")||r.startsWith("var("))&&(i=!0),n(Ie(e,r))))).map(e=>`drop-shadow(${e})`).join(" ");return i?[j(e,o+Z(t,",").map(e=>`drop-shadow(${De(e,n)})`).join(" ")),C("@supports (color: lab(from red l a b))",[j(e,o+a)])]:[j(e,o+a)]}var Qe=/^-?[a-z][a-zA-Z0-9_-]*/,et=37,tt=47,rt=46,nt=97,ot=122,it=65,at=90,lt=48,st=57,ct=95,ut=45;var dt={"--alpha":function(e,t,r,...n){let[o,i]=Z(r,"/").map(e=>e.trim());if(!o||!i)throw new Error(`The --alpha(…) function requires a color and an alpha value, e.g.: \`--alpha(${o||"var(--my-color)"} / ${i||"50%"})\``);if(n.length>0)throw new Error(`The --alpha(…) function only accepts one argument, e.g.: \`--alpha(${o||"var(--my-color)"} / ${i||"50%"})\``);return Be(o,i)},"--spacing":function(e,t,r,...n){if(!r)throw new Error("The --spacing(…) function requires an argument, but received none.");if(n.length>0)throw new Error(`The --spacing(…) function only accepts a single argument, but received ${n.length+1}.`);let o=e.theme.resolve(null,["--spacing"]);if(!o)throw new Error("The --spacing(…) function requires that the `--spacing` theme variable exists, but it was not found.");let i=de.get(r);if(i){if(0===i[0])return"0";if(1===i[0])return o}return`calc(${o} * ${r})`},"--theme":function(e,t,r,...n){if(!r.startsWith("--"))throw new Error("The --theme(…) function can only be used with CSS variables from your theme.");let o=!1;r.endsWith(" inline")&&(o=!0,r=r.slice(0,-7)),"at-rule"===t.kind&&(o=!0);let i=e.resolveThemeValue(r,o);if(!i){if(n.length>0)return n.join(", ");throw new Error(`Could not resolve value for theme function: \`theme(${r})\`. Consider checking if the variable name is correct or provide a fallback value to silence this error.`)}if(0===n.length)return i;let a=n.join(", ");if("initial"===a)return i;if("initial"===i)return a;if(i.startsWith("var(")||i.startsWith("theme(")||i.startsWith("--theme(")){let e=v(i);return function(e,t){y(e,e=>{if("function"===e.kind&&("var"===e.value||"theme"===e.value||"--theme"===e.value))if(1===e.nodes.length)e.nodes.push({kind:"word",value:`, ${t}`});else{let r=e.nodes[e.nodes.length-1];"word"===r.kind&&"initial"===r.value&&(r.value=t)}})}(e,a),g(e)}return i},theme:function(e,t,r,...n){r=function(e){if("'"!==e[0]&&'"'!==e[0])return e;let t="",r=e[0];for(let n=1;n0)return n.join(", ");if(!o)throw new Error(`Could not resolve value for theme function: \`theme(${r})\`. Consider checking if the path is correct or provide a fallback value to silence this error.`);return o}};var ft=new RegExp(Object.keys(dt).map(e=>`${e}\\(`).join("|"));function pt(e,t){let r=0;return y(e,e=>{if("declaration"===e.kind&&e.value&&ft.test(e.value))return r|=8,void(e.value=ht(e.value,e,t));"at-rule"===e.kind&&("@media"===e.name||"@custom-media"===e.name||"@container"===e.name||"@supports"===e.name)&&ft.test(e.params)&&(r|=8,e.params=ht(e.params,e,t))}),r}function ht(e,t,r){let n=v(e);return y(n,e=>{if("function"===e.kind&&e.value in dt){let n=Z(g(e.nodes).trim(),",").map(e=>e.trim()),o=dt[e.value](r,t,...n);return b.Replace(v(o))}}),g(n)}var mt=/^@?[a-z0-9][a-zA-Z0-9_-]*(?{"rule"===e.kind?n.push(e.selector):"at-rule"===e.kind&&"@variant"===e.name?o=!0:"at-rule"===e.kind&&"@slot"!==e.name&&n.push(`${e.name} ${e.params}`)}),this.static(e,e=>{let n=t.map(E);o&&bt(n,r),wt(n,e.nodes),e.nodes=n},{compounds:vt(n)})}functional(e,t,{compounds:r,order:n}={}){this.set(e,{kind:"functional",applyFn:t,compoundsWith:0,compounds:r??2,order:n})}compound(e,t,r,{compounds:n,order:o}={}){this.set(e,{kind:"compound",applyFn:r,compoundsWith:t,compounds:n??2,order:o})}group(e,t){this.groupOrder=this.nextOrder(),t&&this.compareFns.set(this.groupOrder,t),e(),this.groupOrder=null}has(e){return this.variants.has(e)}get(e){return this.variants.get(e)}kind(e){return this.variants.get(e)?.kind}compoundsWith(e,t){let r=this.variants.get(e),n="string"==typeof t?this.variants.get(t):"arbitrary"===t.kind?{compounds:vt([t.selector])}:this.variants.get(t.root);return!(!r||!n||"compound"!==r.kind||0===n.compounds||0===r.compoundsWith||0===(r.compoundsWith&n.compounds))}suggest(e,t){this.completions.set(e,t)}getCompletions(e){return this.completions.get(e)?.()??[]}compare(e,t){if(e===t)return 0;if(null===e)return-1;if(null===t)return 1;if("arbitrary"===e.kind&&"arbitrary"===t.kind)return e.selector1){let e=n[n.length-1];if(" "===n[n.length-2]&&("i"===e||"I"===e||"s"===e||"S"===e))return`${t}="${n.slice(0,-2)}" ${e}`}return`${t}="${n}"`}return e}function wt(e,t){y(e,e=>"at-rule"===e.kind&&"@slot"===e.name?b.ReplaceSkip(t):"at-rule"!==e.kind||"@keyframes"!==e.name&&"@property"!==e.name?void 0:(Object.assign(e,K([S(e.name,e.params,e.nodes)])),b.Skip))}function bt(e,t){let r=0;return y(e,e=>{if("at-rule"!==e.kind||"@variant"!==e.name)return;let n=[],o=Z(e.params,",");for(let[r,i]of o.entries()){let a=A("&",r===o.length-1?e.nodes:e.nodes.map(E)),l=Z(i,":");for(let e=l.length-1;e>=0;--e){let r=l[e].trim();if(!r)throw new Error("Cannot use `@variant` with empty variant");let n=t.parseVariant(r);if(null===n)throw new Error(`Cannot use \`@variant\` with unknown variant: ${r}`);if(null===zt(a,n,t.variants))throw new Error(`Cannot use \`@variant\` with variant: ${r}`)}n.push(a)}return r|=32,b.Replace(n)}),r}function yt(e,t){let r=function(e){let t=new _e;function r(r,n){function*o(t){for(let r of e.keysInNamespaces(t))yield r.replace(He,(e,t,r)=>`${t}.${r}`)}let i=["1/2","1/3","2/3","1/4","2/4","3/4","1/5","2/5","3/5","4/5","1/6","2/6","3/6","4/6","5/6","1/12","2/12","3/12","4/12","5/12","6/12","7/12","8/12","9/12","10/12","11/12"];t.suggest(r,()=>{let e=[];for(let t of n()){if("string"==typeof t){e.push({values:[t],modifiers:[]});continue}let r=[...t.values??[],...o(t.valueThemeKeys??[])],n=[...t.modifiers??[],...o(t.modifierThemeKeys??[])];t.supportsFractions&&r.push(...i),t.hasDefaultValue&&r.unshift(null),e.push({supportsNegative:t.supportsNegative,values:r,modifiers:n})}return e})}function n(e,r){t.static(e,()=>r.map(e=>"function"==typeof e?e():j(e[0],e[1])))}function o(n,o){function i({negative:t}){return r=>{let n=null,i=null;if(r.value)if("arbitrary"===r.value.kind){if(r.modifier)return;n=r.value.value,i=r.value.dataType}else{if(n=e.resolve(r.value.fraction??r.value.value,o.themeKeys??[]),null===n&&o.supportsFractions&&r.value.fraction){let[e,t]=Z(r.value.fraction,"/");if(!Ve(e)||!Ve(t))return;n=`calc(${e} / ${t} * 100%)`}if(null===n&&t&&o.handleNegativeBareValue){if(n=o.handleNegativeBareValue(r.value),!n?.includes("/")&&r.modifier)return;if(null!==n)return o.handle(n,null)}if(null===n&&o.handleBareValue&&(n=o.handleBareValue(r.value),!n?.includes("/")&&r.modifier))return;if(null===n&&!t&&o.staticValues&&!r.modifier){let e=o.staticValues[r.value.value];if(e)return e.map(E)}}else{if(r.modifier)return;n=void 0!==o.defaultValue?o.defaultValue:e.resolve(null,o.themeKeys??[])}if(null!==n)return o.handle(t?_(`calc(${n} * -1)`):n,i)}}if(o.staticValues&&(o.staticValues=Object.assign(Object.create(null),o.staticValues)),o.supportsNegative&&t.functional(`-${n}`,i({negative:!0})),t.functional(n,i({negative:!1})),r(n,()=>[{supportsNegative:o.supportsNegative,valueThemeKeys:o.themeKeys??[],hasDefaultValue:void 0!==o.defaultValue&&null!==o.defaultValue,supportsFractions:o.supportsFractions}]),o.staticValues&&Object.keys(o.staticValues).length>0){let e=Object.keys(o.staticValues);r(n,()=>[{values:e}])}}function i(n,o){t.functional(n,t=>{if(!t.value)return;let r=null;return"arbitrary"===t.value.kind?(r=t.value.value,r=Pe(r,t.modifier,e)):r=qe(t,e,o.themeKeys),null!==r?o.handle(r):void 0}),r(n,()=>[{values:["current","inherit","transparent"],valueThemeKeys:o.themeKeys,modifiers:Array.from({length:21},(e,t)=>""+5*t)}])}function a(n,i,a,{supportsNegative:l=!1,supportsFractions:s=!1,staticValues:c}={}){l&&t.static(`-${n}-px`,()=>a("-1px")),t.static(`${n}-px`,()=>a("1px")),o(n,{themeKeys:i,supportsFractions:s,supportsNegative:l,defaultValue:null,handleBareValue:({value:t})=>e.resolve(null,["--spacing"])&&Ee(t)?`--spacing(${t})`:null,handleNegativeBareValue:({value:t})=>e.resolve(null,["--spacing"])&&Ee(t)?`--spacing(-${t})`:null,handle:a,staticValues:c}),r(n,()=>[{values:e.get(["--spacing"])?Le:[],supportsNegative:l,supportsFractions:s,valueThemeKeys:i}])}n("sr-only",[["position","absolute"],["width","1px"],["height","1px"],["padding","0"],["margin","-1px"],["overflow","hidden"],["clip-path","inset(50%)"],["white-space","nowrap"],["border-width","0"]]),n("not-sr-only",[["position","static"],["width","auto"],["height","auto"],["padding","0"],["margin","0"],["overflow","visible"],["clip-path","none"],["white-space","normal"]]),n("pointer-events-none",[["pointer-events","none"]]),n("pointer-events-auto",[["pointer-events","auto"]]),n("visible",[["visibility","visible"]]),n("invisible",[["visibility","hidden"]]),n("collapse",[["visibility","collapse"]]),n("static",[["position","static"]]),n("fixed",[["position","fixed"]]),n("absolute",[["position","absolute"]]),n("relative",[["position","relative"]]),n("sticky",[["position","sticky"]]);for(let[e,t]of[["inset","inset"],["inset-x","inset-inline"],["inset-y","inset-block"],["inset-s","inset-inline-start"],["inset-e","inset-inline-end"],["inset-bs","inset-block-start"],["inset-be","inset-block-end"],["top","top"],["right","right"],["bottom","bottom"],["left","left"]])n(`${e}-auto`,[[t,"auto"]]),n(`${e}-full`,[[t,"100%"]]),n(`-${e}-full`,[[t,"-100%"]]),a(e,["--inset","--spacing"],e=>[j(t,e)],{supportsNegative:!0,supportsFractions:!0});n("isolate",[["isolation","isolate"]]),n("isolation-auto",[["isolation","auto"]]),o("z",{supportsNegative:!0,handleBareValue:({value:e})=>Ve(e)?e:null,themeKeys:["--z-index"],handle:e=>[j("z-index",e)],staticValues:{auto:[j("z-index","auto")]}}),r("z",()=>[{supportsNegative:!0,values:["0","10","20","30","40","50"],valueThemeKeys:["--z-index"]}]),o("order",{supportsNegative:!0,handleBareValue:({value:e})=>Ve(e)?e:null,themeKeys:["--order"],handle:e=>[j("order",e)],staticValues:{first:[j("order","-9999")],last:[j("order","9999")]}}),r("order",()=>[{supportsNegative:!0,values:Array.from({length:12},(e,t)=>`${t+1}`),valueThemeKeys:["--order"]}]),o("col",{supportsNegative:!0,handleBareValue:({value:e})=>Ve(e)?e:null,themeKeys:["--grid-column"],handle:e=>[j("grid-column",e)],staticValues:{auto:[j("grid-column","auto")]}}),o("col-span",{handleBareValue:({value:e})=>Ve(e)?e:null,handle:e=>[j("grid-column",`span ${e} / span ${e}`)],staticValues:{full:[j("grid-column","1 / -1")]}}),o("col-start",{supportsNegative:!0,handleBareValue:({value:e})=>Ve(e)?e:null,themeKeys:["--grid-column-start"],handle:e=>[j("grid-column-start",e)],staticValues:{auto:[j("grid-column-start","auto")]}}),o("col-end",{supportsNegative:!0,handleBareValue:({value:e})=>Ve(e)?e:null,themeKeys:["--grid-column-end"],handle:e=>[j("grid-column-end",e)],staticValues:{auto:[j("grid-column-end","auto")]}}),r("col-span",()=>[{values:Array.from({length:12},(e,t)=>`${t+1}`),valueThemeKeys:[]}]),r("col-start",()=>[{supportsNegative:!0,values:Array.from({length:13},(e,t)=>`${t+1}`),valueThemeKeys:["--grid-column-start"]}]),r("col-end",()=>[{supportsNegative:!0,values:Array.from({length:13},(e,t)=>`${t+1}`),valueThemeKeys:["--grid-column-end"]}]),o("row",{supportsNegative:!0,handleBareValue:({value:e})=>Ve(e)?e:null,themeKeys:["--grid-row"],handle:e=>[j("grid-row",e)],staticValues:{auto:[j("grid-row","auto")]}}),o("row-span",{themeKeys:[],handleBareValue:({value:e})=>Ve(e)?e:null,handle:e=>[j("grid-row",`span ${e} / span ${e}`)],staticValues:{full:[j("grid-row","1 / -1")]}}),o("row-start",{supportsNegative:!0,handleBareValue:({value:e})=>Ve(e)?e:null,themeKeys:["--grid-row-start"],handle:e=>[j("grid-row-start",e)],staticValues:{auto:[j("grid-row-start","auto")]}}),o("row-end",{supportsNegative:!0,handleBareValue:({value:e})=>Ve(e)?e:null,themeKeys:["--grid-row-end"],handle:e=>[j("grid-row-end",e)],staticValues:{auto:[j("grid-row-end","auto")]}}),r("row-span",()=>[{values:Array.from({length:12},(e,t)=>`${t+1}`),valueThemeKeys:[]}]),r("row-start",()=>[{supportsNegative:!0,values:Array.from({length:13},(e,t)=>`${t+1}`),valueThemeKeys:["--grid-row-start"]}]),r("row-end",()=>[{supportsNegative:!0,values:Array.from({length:13},(e,t)=>`${t+1}`),valueThemeKeys:["--grid-row-end"]}]),n("float-start",[["float","inline-start"]]),n("float-end",[["float","inline-end"]]),n("float-right",[["float","right"]]),n("float-left",[["float","left"]]),n("float-none",[["float","none"]]),n("clear-start",[["clear","inline-start"]]),n("clear-end",[["clear","inline-end"]]),n("clear-right",[["clear","right"]]),n("clear-left",[["clear","left"]]),n("clear-both",[["clear","both"]]),n("clear-none",[["clear","none"]]);for(let[e,t]of[["m","margin"],["mx","margin-inline"],["my","margin-block"],["ms","margin-inline-start"],["me","margin-inline-end"],["mbs","margin-block-start"],["mbe","margin-block-end"],["mt","margin-top"],["mr","margin-right"],["mb","margin-bottom"],["ml","margin-left"]])n(`${e}-auto`,[[t,"auto"]]),a(e,["--margin","--spacing"],e=>[j(t,e)],{supportsNegative:!0});n("box-border",[["box-sizing","border-box"]]),n("box-content",[["box-sizing","content-box"]]),o("line-clamp",{themeKeys:["--line-clamp"],handleBareValue:({value:e})=>Ve(e)?e:null,handle:e=>[j("overflow","hidden"),j("display","-webkit-box"),j("-webkit-box-orient","vertical"),j("-webkit-line-clamp",e)],staticValues:{none:[j("overflow","visible"),j("display","block"),j("-webkit-box-orient","horizontal"),j("-webkit-line-clamp","unset")]}}),r("line-clamp",()=>[{values:["1","2","3","4","5","6"],valueThemeKeys:["--line-clamp"]}]),n("block",[["display","block"]]),n("inline-block",[["display","inline-block"]]),n("inline",[["display","inline"]]),n("hidden",[["display","none"]]),n("inline-flex",[["display","inline-flex"]]),n("table",[["display","table"]]),n("inline-table",[["display","inline-table"]]),n("table-caption",[["display","table-caption"]]),n("table-cell",[["display","table-cell"]]),n("table-column",[["display","table-column"]]),n("table-column-group",[["display","table-column-group"]]),n("table-footer-group",[["display","table-footer-group"]]),n("table-header-group",[["display","table-header-group"]]),n("table-row-group",[["display","table-row-group"]]),n("table-row",[["display","table-row"]]),n("flow-root",[["display","flow-root"]]),n("flex",[["display","flex"]]),n("grid",[["display","grid"]]),n("inline-grid",[["display","inline-grid"]]),n("contents",[["display","contents"]]),n("list-item",[["display","list-item"]]),n("field-sizing-content",[["field-sizing","content"]]),n("field-sizing-fixed",[["field-sizing","fixed"]]),o("aspect",{themeKeys:["--aspect"],handleBareValue:({fraction:e})=>{if(null===e)return null;let[t,r]=Z(e,"/");return Ee(t)&&Ee(r)?e:null},handle:e=>[j("aspect-ratio",e)],staticValues:{auto:[j("aspect-ratio","auto")],square:[j("aspect-ratio","1 / 1")]}});for(let[e,t]of[["full","100%"],["svw","100svw"],["lvw","100lvw"],["dvw","100dvw"],["svh","100svh"],["lvh","100lvh"],["dvh","100dvh"],["min","min-content"],["max","max-content"],["fit","fit-content"]])n(`size-${e}`,[["--tw-sort","size"],["width",t],["height",t]]),n(`w-${e}`,[["width",t]]),n(`h-${e}`,[["height",t]]),n(`min-w-${e}`,[["min-width",t]]),n(`min-h-${e}`,[["min-height",t]]),n(`max-w-${e}`,[["max-width",t]]),n(`max-h-${e}`,[["max-height",t]]);n("size-auto",[["--tw-sort","size"],["width","auto"],["height","auto"]]),n("w-auto",[["width","auto"]]),n("h-auto",[["height","auto"]]),n("min-w-auto",[["min-width","auto"]]),n("min-h-auto",[["min-height","auto"]]),n("h-lh",[["height","1lh"]]),n("min-h-lh",[["min-height","1lh"]]),n("max-h-lh",[["max-height","1lh"]]),n("w-screen",[["width","100vw"]]),n("min-w-screen",[["min-width","100vw"]]),n("max-w-screen",[["max-width","100vw"]]),n("h-screen",[["height","100vh"]]),n("min-h-screen",[["min-height","100vh"]]),n("max-h-screen",[["max-height","100vh"]]),n("max-w-none",[["max-width","none"]]),n("max-h-none",[["max-height","none"]]),a("size",["--size","--spacing"],e=>[j("--tw-sort","size"),j("width",e),j("height",e)],{supportsFractions:!0});for(let[e,t,r]of[["w",["--width","--spacing","--container"],"width"],["min-w",["--min-width","--spacing","--container"],"min-width"],["max-w",["--max-width","--spacing","--container"],"max-width"],["h",["--height","--spacing"],"height"],["min-h",["--min-height","--height","--spacing"],"min-height"],["max-h",["--max-height","--height","--spacing"],"max-height"]])a(e,t,e=>[j(r,e)],{supportsFractions:!0});for(let[e,t]of[["full","100%"],["min","min-content"],["max","max-content"],["fit","fit-content"]])n(`inline-${e}`,[["inline-size",t]]),n(`block-${e}`,[["block-size",t]]),n(`min-inline-${e}`,[["min-inline-size",t]]),n(`min-block-${e}`,[["min-block-size",t]]),n(`max-inline-${e}`,[["max-inline-size",t]]),n(`max-block-${e}`,[["max-block-size",t]]);for(let[e,t]of[["svw","100svw"],["lvw","100lvw"],["dvw","100dvw"]])n(`inline-${e}`,[["inline-size",t]]),n(`min-inline-${e}`,[["min-inline-size",t]]),n(`max-inline-${e}`,[["max-inline-size",t]]);for(let[e,t]of[["svh","100svh"],["lvh","100lvh"],["dvh","100dvh"]])n(`block-${e}`,[["block-size",t]]),n(`min-block-${e}`,[["min-block-size",t]]),n(`max-block-${e}`,[["max-block-size",t]]);n("inline-auto",[["inline-size","auto"]]),n("block-auto",[["block-size","auto"]]),n("min-inline-auto",[["min-inline-size","auto"]]),n("min-block-auto",[["min-block-size","auto"]]),n("block-lh",[["block-size","1lh"]]),n("min-block-lh",[["min-block-size","1lh"]]),n("max-block-lh",[["max-block-size","1lh"]]),n("inline-screen",[["inline-size","100vw"]]),n("min-inline-screen",[["min-inline-size","100vw"]]),n("max-inline-screen",[["max-inline-size","100vw"]]),n("block-screen",[["block-size","100vh"]]),n("min-block-screen",[["min-block-size","100vh"]]),n("max-block-screen",[["max-block-size","100vh"]]),n("max-inline-none",[["max-inline-size","none"]]),n("max-block-none",[["max-block-size","none"]]);for(let[e,t,r]of[["inline",["--spacing","--container"],"inline-size"],["min-inline",["--spacing","--container"],"min-inline-size"],["max-inline",["--spacing","--container"],"max-inline-size"],["block",["--spacing"],"block-size"],["min-block",["--spacing"],"min-block-size"],["max-block",["--spacing"],"max-block-size"]])a(e,t,e=>[j(r,e)],{supportsFractions:!0});t.static("container",()=>{let t=[...e.namespace("--breakpoint").values()];t.sort((e,t)=>ce(e,t,"asc"));let r=[j("--tw-sort","--tw-container-component"),j("width","100%")];for(let e of t)r.push(S("@media",`(width >= ${e})`,[j("max-width",e)]));return r}),n("flex-auto",[["flex","auto"]]),n("flex-initial",[["flex","0 auto"]]),n("flex-none",[["flex","none"]]),t.functional("flex",e=>{if(e.value){if("arbitrary"===e.value.kind)return e.modifier?void 0:[j("flex",e.value.value)];if(e.value.fraction){let[t,r]=Z(e.value.fraction,"/");return Ve(t)&&Ve(r)?[j("flex",`calc(${e.value.fraction} * 100%)`)]:void 0}if(Ve(e.value.value))return e.modifier?void 0:[j("flex",e.value.value)]}}),r("flex",()=>[{supportsFractions:!0},{values:Array.from({length:12},(e,t)=>`${t+1}`)}]),o("shrink",{defaultValue:"1",handleBareValue:({value:e})=>Ve(e)?e:null,handle:e=>[j("flex-shrink",e)]}),o("grow",{defaultValue:"1",handleBareValue:({value:e})=>Ve(e)?e:null,handle:e=>[j("flex-grow",e)]}),r("shrink",()=>[{values:["0"],valueThemeKeys:[],hasDefaultValue:!0}]),r("grow",()=>[{values:["0"],valueThemeKeys:[],hasDefaultValue:!0}]),n("basis-auto",[["flex-basis","auto"]]),n("basis-full",[["flex-basis","100%"]]),a("basis",["--flex-basis","--spacing","--container"],e=>[j("flex-basis",e)],{supportsFractions:!0}),n("table-auto",[["table-layout","auto"]]),n("table-fixed",[["table-layout","fixed"]]),n("caption-top",[["caption-side","top"]]),n("caption-bottom",[["caption-side","bottom"]]),n("border-collapse",[["border-collapse","collapse"]]),n("border-separate",[["border-collapse","separate"]]);let l=()=>K([Me("--tw-border-spacing-x","0",""),Me("--tw-border-spacing-y","0","")]);a("border-spacing",["--border-spacing","--spacing"],e=>[l(),j("--tw-border-spacing-x",e),j("--tw-border-spacing-y",e),j("border-spacing","var(--tw-border-spacing-x) var(--tw-border-spacing-y)")]),a("border-spacing-x",["--border-spacing","--spacing"],e=>[l(),j("--tw-border-spacing-x",e),j("border-spacing","var(--tw-border-spacing-x) var(--tw-border-spacing-y)")]),a("border-spacing-y",["--border-spacing","--spacing"],e=>[l(),j("--tw-border-spacing-y",e),j("border-spacing","var(--tw-border-spacing-x) var(--tw-border-spacing-y)")]),o("origin",{themeKeys:["--transform-origin"],handle:e=>[j("transform-origin",e)],staticValues:{center:[j("transform-origin","center")],top:[j("transform-origin","top")],"top-right":[j("transform-origin","100% 0")],right:[j("transform-origin","100%")],"bottom-right":[j("transform-origin","100% 100%")],bottom:[j("transform-origin","bottom")],"bottom-left":[j("transform-origin","0 100%")],left:[j("transform-origin","0")],"top-left":[j("transform-origin","0 0")]}}),o("perspective-origin",{themeKeys:["--perspective-origin"],handle:e=>[j("perspective-origin",e)],staticValues:{center:[j("perspective-origin","center")],top:[j("perspective-origin","top")],"top-right":[j("perspective-origin","100% 0")],right:[j("perspective-origin","100%")],"bottom-right":[j("perspective-origin","100% 100%")],bottom:[j("perspective-origin","bottom")],"bottom-left":[j("perspective-origin","0 100%")],left:[j("perspective-origin","0")],"top-left":[j("perspective-origin","0 0")]}}),o("perspective",{themeKeys:["--perspective"],handle:e=>[j("perspective",e)],staticValues:{none:[j("perspective","none")]}});let s=()=>K([Me("--tw-translate-x","0"),Me("--tw-translate-y","0"),Me("--tw-translate-z","0")]);n("translate-none",[["translate","none"]]),n("-translate-full",[s,["--tw-translate-x","-100%"],["--tw-translate-y","-100%"],["translate","var(--tw-translate-x) var(--tw-translate-y)"]]),n("translate-full",[s,["--tw-translate-x","100%"],["--tw-translate-y","100%"],["translate","var(--tw-translate-x) var(--tw-translate-y)"]]),a("translate",["--translate","--spacing"],e=>[s(),j("--tw-translate-x",e),j("--tw-translate-y",e),j("translate","var(--tw-translate-x) var(--tw-translate-y)")],{supportsNegative:!0,supportsFractions:!0});for(let e of["x","y"])n(`-translate-${e}-full`,[s,[`--tw-translate-${e}`,"-100%"],["translate","var(--tw-translate-x) var(--tw-translate-y)"]]),n(`translate-${e}-full`,[s,[`--tw-translate-${e}`,"100%"],["translate","var(--tw-translate-x) var(--tw-translate-y)"]]),a(`translate-${e}`,["--translate","--spacing"],t=>[s(),j(`--tw-translate-${e}`,t),j("translate","var(--tw-translate-x) var(--tw-translate-y)")],{supportsNegative:!0,supportsFractions:!0});a("translate-z",["--translate","--spacing"],e=>[s(),j("--tw-translate-z",e),j("translate","var(--tw-translate-x) var(--tw-translate-y) var(--tw-translate-z)")],{supportsNegative:!0}),n("translate-3d",[s,["translate","var(--tw-translate-x) var(--tw-translate-y) var(--tw-translate-z)"]]);let c=()=>K([Me("--tw-scale-x","1"),Me("--tw-scale-y","1"),Me("--tw-scale-z","1")]);function u({negative:t}){return r=>{if(!r.value||r.modifier)return;let n;return"arbitrary"===r.value.kind?(n=r.value.value,n=t?`calc(${n} * -1)`:n,[j("scale",n)]):(n=e.resolve(r.value.value,["--scale"]),!n&&Ve(r.value.value)&&(n=`${r.value.value}%`),n?(n=t?`calc(${n} * -1)`:n,[c(),j("--tw-scale-x",n),j("--tw-scale-y",n),j("--tw-scale-z",n),j("scale","var(--tw-scale-x) var(--tw-scale-y)")]):void 0)}}n("scale-none",[["scale","none"]]),t.functional("-scale",u({negative:!0})),t.functional("scale",u({negative:!1})),r("scale",()=>[{supportsNegative:!0,values:["0","50","75","90","95","100","105","110","125","150","200"],valueThemeKeys:["--scale"]}]);for(let e of["x","y","z"])o(`scale-${e}`,{supportsNegative:!0,themeKeys:["--scale"],handleBareValue:({value:e})=>Ve(e)?`${e}%`:null,handle:t=>[c(),j(`--tw-scale-${e}`,t),j("scale","var(--tw-scale-x) var(--tw-scale-y)"+("z"===e?" var(--tw-scale-z)":""))]}),r(`scale-${e}`,()=>[{supportsNegative:!0,values:["0","50","75","90","95","100","105","110","125","150","200"],valueThemeKeys:["--scale"]}]);function d({negative:t}){return r=>{if(!r.value||r.modifier)return;let n;if("arbitrary"===r.value.kind){n=r.value.value;let e=r.value.dataType??me(n,["angle","vector"]);if("vector"===e)return[j("rotate",`${n} var(--tw-rotate)`)];if("angle"!==e)return[j("rotate",t?`calc(${n} * -1)`:n)]}else if(n=e.resolve(r.value.value,["--rotate"]),!n&&Ve(r.value.value)&&(n=`${r.value.value}deg`),!n)return;return[j("rotate",t?`calc(${n} * -1)`:n)]}}n("scale-3d",[c,["scale","var(--tw-scale-x) var(--tw-scale-y) var(--tw-scale-z)"]]),n("rotate-none",[["rotate","none"]]),t.functional("-rotate",d({negative:!0})),t.functional("rotate",d({negative:!1})),r("rotate",()=>[{supportsNegative:!0,values:["0","1","2","3","6","12","45","90","180"],valueThemeKeys:["--rotate"]}]);{let e=["var(--tw-rotate-x,)","var(--tw-rotate-y,)","var(--tw-rotate-z,)","var(--tw-skew-x,)","var(--tw-skew-y,)"].join(" "),i=()=>K([Me("--tw-rotate-x"),Me("--tw-rotate-y"),Me("--tw-rotate-z"),Me("--tw-skew-x"),Me("--tw-skew-y")]);for(let t of["x","y","z"])o(`rotate-${t}`,{supportsNegative:!0,themeKeys:["--rotate"],handleBareValue:({value:e})=>Ve(e)?`${e}deg`:null,handle:r=>[i(),j(`--tw-rotate-${t}`,`rotate${t.toUpperCase()}(${r})`),j("transform",e)]}),r(`rotate-${t}`,()=>[{supportsNegative:!0,values:["0","1","2","3","6","12","45","90","180"],valueThemeKeys:["--rotate"]}]);o("skew",{supportsNegative:!0,themeKeys:["--skew"],handleBareValue:({value:e})=>Ve(e)?`${e}deg`:null,handle:t=>[i(),j("--tw-skew-x",`skewX(${t})`),j("--tw-skew-y",`skewY(${t})`),j("transform",e)]}),o("skew-x",{supportsNegative:!0,themeKeys:["--skew"],handleBareValue:({value:e})=>Ve(e)?`${e}deg`:null,handle:t=>[i(),j("--tw-skew-x",`skewX(${t})`),j("transform",e)]}),o("skew-y",{supportsNegative:!0,themeKeys:["--skew"],handleBareValue:({value:e})=>Ve(e)?`${e}deg`:null,handle:t=>[i(),j("--tw-skew-y",`skewY(${t})`),j("transform",e)]}),r("skew",()=>[{supportsNegative:!0,values:["0","1","2","3","6","12"],valueThemeKeys:["--skew"]}]),r("skew-x",()=>[{supportsNegative:!0,values:["0","1","2","3","6","12"],valueThemeKeys:["--skew"]}]),r("skew-y",()=>[{supportsNegative:!0,values:["0","1","2","3","6","12"],valueThemeKeys:["--skew"]}]),t.functional("transform",t=>{if(t.modifier)return;let r=null;return t.value?"arbitrary"===t.value.kind&&(r=t.value.value):r=e,null!==r?[i(),j("transform",r)]:void 0}),r("transform",()=>[{hasDefaultValue:!0}]),n("transform-cpu",[["transform",e]]),n("transform-gpu",[["transform",`translateZ(0) ${e}`]]),n("transform-none",[["transform","none"]])}o("zoom",{handleBareValue:({value:e})=>Ve(e)?`${e}%`:null,handle:e=>[j("zoom",e)]}),r("zoom",()=>[{values:["50","75","90","95","100","105","110","125","150","200"]}]),n("transform-flat",[["transform-style","flat"]]),n("transform-3d",[["transform-style","preserve-3d"]]),n("transform-content",[["transform-box","content-box"]]),n("transform-border",[["transform-box","border-box"]]),n("transform-fill",[["transform-box","fill-box"]]),n("transform-stroke",[["transform-box","stroke-box"]]),n("transform-view",[["transform-box","view-box"]]),n("backface-visible",[["backface-visibility","visible"]]),n("backface-hidden",[["backface-visibility","hidden"]]);for(let e of["auto","default","pointer","wait","text","move","help","not-allowed","none","context-menu","progress","cell","crosshair","vertical-text","alias","copy","no-drop","grab","grabbing","all-scroll","col-resize","row-resize","n-resize","e-resize","s-resize","w-resize","ne-resize","nw-resize","se-resize","sw-resize","ew-resize","ns-resize","nesw-resize","nwse-resize","zoom-in","zoom-out"])n(`cursor-${e}`,[["cursor",e]]);o("cursor",{themeKeys:["--cursor"],handle:e=>[j("cursor",e)]});for(let e of["auto","none","manipulation"])n(`touch-${e}`,[["touch-action",e]]);let f=()=>K([Me("--tw-pan-x"),Me("--tw-pan-y"),Me("--tw-pinch-zoom")]);for(let e of["x","left","right"])n(`touch-pan-${e}`,[f,["--tw-pan-x",`pan-${e}`],["touch-action","var(--tw-pan-x,) var(--tw-pan-y,) var(--tw-pinch-zoom,)"]]);for(let e of["y","up","down"])n(`touch-pan-${e}`,[f,["--tw-pan-y",`pan-${e}`],["touch-action","var(--tw-pan-x,) var(--tw-pan-y,) var(--tw-pinch-zoom,)"]]);n("touch-pinch-zoom",[f,["--tw-pinch-zoom","pinch-zoom"],["touch-action","var(--tw-pan-x,) var(--tw-pan-y,) var(--tw-pinch-zoom,)"]]);for(let e of["none","text","all","auto"])n(`select-${e}`,[["-webkit-user-select",e],["user-select",e]]);n("resize-none",[["resize","none"]]),n("resize-x",[["resize","horizontal"]]),n("resize-y",[["resize","vertical"]]),n("resize",[["resize","both"]]),n("snap-none",[["scroll-snap-type","none"]]);let p=()=>K([Me("--tw-scroll-snap-strictness","proximity","*")]);for(let e of["x","y","both"])n(`snap-${e}`,[p,["scroll-snap-type",`${e} var(--tw-scroll-snap-strictness)`]]);n("snap-mandatory",[p,["--tw-scroll-snap-strictness","mandatory"]]),n("snap-proximity",[p,["--tw-scroll-snap-strictness","proximity"]]),n("snap-align-none",[["scroll-snap-align","none"]]),n("snap-start",[["scroll-snap-align","start"]]),n("snap-end",[["scroll-snap-align","end"]]),n("snap-center",[["scroll-snap-align","center"]]),n("snap-normal",[["scroll-snap-stop","normal"]]),n("snap-always",[["scroll-snap-stop","always"]]);for(let[e,t]of[["scroll-m","scroll-margin"],["scroll-mx","scroll-margin-inline"],["scroll-my","scroll-margin-block"],["scroll-ms","scroll-margin-inline-start"],["scroll-me","scroll-margin-inline-end"],["scroll-mbs","scroll-margin-block-start"],["scroll-mbe","scroll-margin-block-end"],["scroll-mt","scroll-margin-top"],["scroll-mr","scroll-margin-right"],["scroll-mb","scroll-margin-bottom"],["scroll-ml","scroll-margin-left"]])a(e,["--scroll-margin","--spacing"],e=>[j(t,e)],{supportsNegative:!0});for(let[e,t]of[["scroll-p","scroll-padding"],["scroll-px","scroll-padding-inline"],["scroll-py","scroll-padding-block"],["scroll-ps","scroll-padding-inline-start"],["scroll-pe","scroll-padding-inline-end"],["scroll-pbs","scroll-padding-block-start"],["scroll-pbe","scroll-padding-block-end"],["scroll-pt","scroll-padding-top"],["scroll-pr","scroll-padding-right"],["scroll-pb","scroll-padding-bottom"],["scroll-pl","scroll-padding-left"]])a(e,["--scroll-padding","--spacing"],e=>[j(t,e)]);n("list-inside",[["list-style-position","inside"]]),n("list-outside",[["list-style-position","outside"]]),o("list",{themeKeys:["--list-style-type"],handle:e=>[j("list-style-type",e)],staticValues:{none:[j("list-style-type","none")],disc:[j("list-style-type","disc")],decimal:[j("list-style-type","decimal")]}}),o("list-image",{themeKeys:["--list-style-image"],handle:e=>[j("list-style-image",e)],staticValues:{none:[j("list-style-image","none")]}}),n("appearance-none",[["appearance","none"]]),n("appearance-auto",[["appearance","auto"]]),n("scheme-normal",[["color-scheme","normal"]]),n("scheme-dark",[["color-scheme","dark"]]),n("scheme-light",[["color-scheme","light"]]),n("scheme-light-dark",[["color-scheme","light dark"]]),n("scheme-only-dark",[["color-scheme","only dark"]]),n("scheme-only-light",[["color-scheme","only light"]]),o("columns",{themeKeys:["--columns","--container"],handleBareValue:({value:e})=>Ve(e)?e:null,handle:e=>[j("columns",e)],staticValues:{auto:[j("columns","auto")]}}),r("columns",()=>[{values:Array.from({length:12},(e,t)=>`${t+1}`),valueThemeKeys:["--columns","--container"]}]);for(let e of["auto","avoid","all","avoid-page","page","left","right","column"])n(`break-before-${e}`,[["break-before",e]]);for(let e of["auto","avoid","avoid-page","avoid-column"])n(`break-inside-${e}`,[["break-inside",e]]);for(let e of["auto","avoid","all","avoid-page","page","left","right","column"])n(`break-after-${e}`,[["break-after",e]]);n("grid-flow-row",[["grid-auto-flow","row"]]),n("grid-flow-col",[["grid-auto-flow","column"]]),n("grid-flow-dense",[["grid-auto-flow","dense"]]),n("grid-flow-row-dense",[["grid-auto-flow","row dense"]]),n("grid-flow-col-dense",[["grid-auto-flow","column dense"]]),o("auto-cols",{themeKeys:["--grid-auto-columns"],handle:e=>[j("grid-auto-columns",e)],staticValues:{auto:[j("grid-auto-columns","auto")],min:[j("grid-auto-columns","min-content")],max:[j("grid-auto-columns","max-content")],fr:[j("grid-auto-columns","minmax(0, 1fr)")]}}),o("auto-rows",{themeKeys:["--grid-auto-rows"],handle:e=>[j("grid-auto-rows",e)],staticValues:{auto:[j("grid-auto-rows","auto")],min:[j("grid-auto-rows","min-content")],max:[j("grid-auto-rows","max-content")],fr:[j("grid-auto-rows","minmax(0, 1fr)")]}}),o("grid-cols",{themeKeys:["--grid-template-columns"],handleBareValue:({value:e})=>Ke(e)?`repeat(${e}, minmax(0, 1fr))`:null,handle:e=>[j("grid-template-columns",e)],staticValues:{none:[j("grid-template-columns","none")],subgrid:[j("grid-template-columns","subgrid")]}}),o("grid-rows",{themeKeys:["--grid-template-rows"],handleBareValue:({value:e})=>Ke(e)?`repeat(${e}, minmax(0, 1fr))`:null,handle:e=>[j("grid-template-rows",e)],staticValues:{none:[j("grid-template-rows","none")],subgrid:[j("grid-template-rows","subgrid")]}}),r("grid-cols",()=>[{values:Array.from({length:12},(e,t)=>`${t+1}`),valueThemeKeys:["--grid-template-columns"]}]),r("grid-rows",()=>[{values:Array.from({length:12},(e,t)=>`${t+1}`),valueThemeKeys:["--grid-template-rows"]}]),n("flex-row",[["flex-direction","row"]]),n("flex-row-reverse",[["flex-direction","row-reverse"]]),n("flex-col",[["flex-direction","column"]]),n("flex-col-reverse",[["flex-direction","column-reverse"]]),n("flex-wrap",[["flex-wrap","wrap"]]),n("flex-nowrap",[["flex-wrap","nowrap"]]),n("flex-wrap-reverse",[["flex-wrap","wrap-reverse"]]),n("place-content-center",[["place-content","center"]]),n("place-content-start",[["place-content","start"]]),n("place-content-end",[["place-content","end"]]),n("place-content-center-safe",[["place-content","safe center"]]),n("place-content-end-safe",[["place-content","safe end"]]),n("place-content-between",[["place-content","space-between"]]),n("place-content-around",[["place-content","space-around"]]),n("place-content-evenly",[["place-content","space-evenly"]]),n("place-content-baseline",[["place-content","baseline"]]),n("place-content-stretch",[["place-content","stretch"]]),n("place-items-center",[["place-items","center"]]),n("place-items-start",[["place-items","start"]]),n("place-items-end",[["place-items","end"]]),n("place-items-center-safe",[["place-items","safe center"]]),n("place-items-end-safe",[["place-items","safe end"]]),n("place-items-baseline",[["place-items","baseline"]]),n("place-items-stretch",[["place-items","stretch"]]),n("content-normal",[["align-content","normal"]]),n("content-center",[["align-content","center"]]),n("content-start",[["align-content","flex-start"]]),n("content-end",[["align-content","flex-end"]]),n("content-center-safe",[["align-content","safe center"]]),n("content-end-safe",[["align-content","safe flex-end"]]),n("content-between",[["align-content","space-between"]]),n("content-around",[["align-content","space-around"]]),n("content-evenly",[["align-content","space-evenly"]]),n("content-baseline",[["align-content","baseline"]]),n("content-stretch",[["align-content","stretch"]]),n("items-center",[["align-items","center"]]),n("items-start",[["align-items","flex-start"]]),n("items-end",[["align-items","flex-end"]]),n("items-center-safe",[["align-items","safe center"]]),n("items-end-safe",[["align-items","safe flex-end"]]),n("items-baseline",[["align-items","baseline"]]),n("items-baseline-last",[["align-items","last baseline"]]),n("items-stretch",[["align-items","stretch"]]),n("justify-normal",[["justify-content","normal"]]),n("justify-center",[["justify-content","center"]]),n("justify-start",[["justify-content","flex-start"]]),n("justify-end",[["justify-content","flex-end"]]),n("justify-center-safe",[["justify-content","safe center"]]),n("justify-end-safe",[["justify-content","safe flex-end"]]),n("justify-between",[["justify-content","space-between"]]),n("justify-around",[["justify-content","space-around"]]),n("justify-evenly",[["justify-content","space-evenly"]]),n("justify-baseline",[["justify-content","baseline"]]),n("justify-stretch",[["justify-content","stretch"]]),n("justify-items-normal",[["justify-items","normal"]]),n("justify-items-center",[["justify-items","center"]]),n("justify-items-start",[["justify-items","start"]]),n("justify-items-end",[["justify-items","end"]]),n("justify-items-center-safe",[["justify-items","safe center"]]),n("justify-items-end-safe",[["justify-items","safe end"]]),n("justify-items-stretch",[["justify-items","stretch"]]),a("gap",["--gap","--spacing"],e=>[j("gap",e)]),a("gap-x",["--gap","--spacing"],e=>[j("column-gap",e)]),a("gap-y",["--gap","--spacing"],e=>[j("row-gap",e)]),a("space-x",["--space","--spacing"],e=>{let t=(()=>{if("--spacing(0)"===e||"--spacing(-0)"===e)return!0;let t=de.get(e);return!(!t||0!==t[0]||null!==t[1]&&!Ce(e))})();return[K([Me("--tw-space-x-reverse","0")]),A(":where(& > :not(:last-child))",[j("--tw-sort","row-gap"),j("--tw-space-x-reverse","0"),j("margin-inline-start",t?"0":`calc(${e} * var(--tw-space-x-reverse))`),j("margin-inline-end",t?"0":`calc(${e} * calc(1 - var(--tw-space-x-reverse)))`)])]},{supportsNegative:!0}),a("space-y",["--space","--spacing"],e=>{let t=(()=>{if("--spacing(0)"===e||"--spacing(-0)"===e)return!0;let t=de.get(e);return!(!t||0!==t[0]||null!==t[1]&&!Ce(e))})();return[K([Me("--tw-space-y-reverse","0")]),A(":where(& > :not(:last-child))",[j("--tw-sort","column-gap"),j("--tw-space-y-reverse","0"),j("margin-block-start",t?"0":`calc(${e} * var(--tw-space-y-reverse))`),j("margin-block-end",t?"0":`calc(${e} * calc(1 - var(--tw-space-y-reverse)))`)])]},{supportsNegative:!0}),n("space-x-reverse",[()=>K([Me("--tw-space-x-reverse","0")]),()=>A(":where(& > :not(:last-child))",[j("--tw-sort","row-gap"),j("--tw-space-x-reverse","1")])]),n("space-y-reverse",[()=>K([Me("--tw-space-y-reverse","0")]),()=>A(":where(& > :not(:last-child))",[j("--tw-sort","column-gap"),j("--tw-space-y-reverse","1")])]),n("accent-auto",[["accent-color","auto"]]),i("accent",{themeKeys:["--accent-color","--color"],handle:e=>[j("accent-color",e)]}),i("caret",{themeKeys:["--caret-color","--color"],handle:e=>[j("caret-color",e)]}),i("divide",{themeKeys:["--divide-color","--border-color","--color"],handle:e=>[A(":where(& > :not(:last-child))",[j("--tw-sort","divide-color"),j("border-color",e)])]}),n("place-self-auto",[["place-self","auto"]]),n("place-self-start",[["place-self","start"]]),n("place-self-end",[["place-self","end"]]),n("place-self-center",[["place-self","center"]]),n("place-self-end-safe",[["place-self","safe end"]]),n("place-self-center-safe",[["place-self","safe center"]]),n("place-self-stretch",[["place-self","stretch"]]),n("self-auto",[["align-self","auto"]]),n("self-start",[["align-self","flex-start"]]),n("self-end",[["align-self","flex-end"]]),n("self-center",[["align-self","center"]]),n("self-end-safe",[["align-self","safe flex-end"]]),n("self-center-safe",[["align-self","safe center"]]),n("self-stretch",[["align-self","stretch"]]),n("self-baseline",[["align-self","baseline"]]),n("self-baseline-last",[["align-self","last baseline"]]),n("justify-self-auto",[["justify-self","auto"]]),n("justify-self-start",[["justify-self","flex-start"]]),n("justify-self-end",[["justify-self","flex-end"]]),n("justify-self-center",[["justify-self","center"]]),n("justify-self-end-safe",[["justify-self","safe flex-end"]]),n("justify-self-center-safe",[["justify-self","safe center"]]),n("justify-self-stretch",[["justify-self","stretch"]]);for(let e of["auto","hidden","clip","visible","scroll"])n(`overflow-${e}`,[["overflow",e]]),n(`overflow-x-${e}`,[["overflow-x",e]]),n(`overflow-y-${e}`,[["overflow-y",e]]);for(let e of["auto","contain","none"])n(`overscroll-${e}`,[["overscroll-behavior",e]]),n(`overscroll-x-${e}`,[["overscroll-behavior-x",e]]),n(`overscroll-y-${e}`,[["overscroll-behavior-y",e]]);n("scroll-auto",[["scroll-behavior","auto"]]),n("scroll-smooth",[["scroll-behavior","smooth"]]),n("scrollbar-auto",[["scrollbar-width","auto"]]),n("scrollbar-thin",[["scrollbar-width","thin"]]),n("scrollbar-none",[["scrollbar-width","none"]]);{let e=()=>K([Me("--tw-scrollbar-thumb","#0000",""),Me("--tw-scrollbar-track","#0000","")]);i("scrollbar-thumb",{themeKeys:["--color"],handle:t=>[e(),j("--tw-scrollbar-thumb",t),j("scrollbar-color","var(--tw-scrollbar-thumb) var(--tw-scrollbar-track)")]}),i("scrollbar-track",{themeKeys:["--color"],handle:t=>[e(),j("--tw-scrollbar-track",t),j("scrollbar-color","var(--tw-scrollbar-thumb) var(--tw-scrollbar-track)")]})}n("scrollbar-gutter-auto",[["scrollbar-gutter","auto"]]),n("scrollbar-gutter-stable",[["scrollbar-gutter","stable"]]),n("scrollbar-gutter-both",[["scrollbar-gutter","stable both-edges"]]),n("truncate",[["overflow","hidden"],["text-overflow","ellipsis"],["white-space","nowrap"]]),n("text-ellipsis",[["text-overflow","ellipsis"]]),n("text-clip",[["text-overflow","clip"]]),n("hyphens-none",[["-webkit-hyphens","none"],["hyphens","none"]]),n("hyphens-manual",[["-webkit-hyphens","manual"],["hyphens","manual"]]),n("hyphens-auto",[["-webkit-hyphens","auto"],["hyphens","auto"]]),n("whitespace-normal",[["white-space","normal"]]),n("whitespace-nowrap",[["white-space","nowrap"]]),n("whitespace-pre",[["white-space","pre"]]),n("whitespace-pre-line",[["white-space","pre-line"]]),n("whitespace-pre-wrap",[["white-space","pre-wrap"]]),n("whitespace-break-spaces",[["white-space","break-spaces"]]),o("tab",{handleBareValue:({value:e})=>Ve(e)?e:null,handle:e=>[j("tab-size",e)]}),r("tab",()=>[{values:["2","4","8"]}]),n("text-wrap",[["text-wrap","wrap"]]),n("text-nowrap",[["text-wrap","nowrap"]]),n("text-balance",[["text-wrap","balance"]]),n("text-pretty",[["text-wrap","pretty"]]),n("break-normal",[["overflow-wrap","normal"],["word-break","normal"]]),n("break-all",[["word-break","break-all"]]),n("break-keep",[["word-break","keep-all"]]),n("wrap-anywhere",[["overflow-wrap","anywhere"]]),n("wrap-break-word",[["overflow-wrap","break-word"]]),n("wrap-normal",[["overflow-wrap","normal"]]);for(let[e,t]of[["rounded",["border-radius"]],["rounded-s",["border-start-start-radius","border-end-start-radius"]],["rounded-e",["border-start-end-radius","border-end-end-radius"]],["rounded-t",["border-top-left-radius","border-top-right-radius"]],["rounded-r",["border-top-right-radius","border-bottom-right-radius"]],["rounded-b",["border-bottom-right-radius","border-bottom-left-radius"]],["rounded-l",["border-top-left-radius","border-bottom-left-radius"]],["rounded-ss",["border-start-start-radius"]],["rounded-se",["border-start-end-radius"]],["rounded-ee",["border-end-end-radius"]],["rounded-es",["border-end-start-radius"]],["rounded-tl",["border-top-left-radius"]],["rounded-tr",["border-top-right-radius"]],["rounded-br",["border-bottom-right-radius"]],["rounded-bl",["border-bottom-left-radius"]]])o(e,{themeKeys:["--radius"],handle:e=>t.map(t=>j(t,e)),staticValues:{none:t.map(e=>j(e,"0")),full:t.map(e=>j(e,"calc(infinity * 1px)"))}});n("border-solid",[["--tw-border-style","solid"],["border-style","solid"]]),n("border-dashed",[["--tw-border-style","dashed"],["border-style","dashed"]]),n("border-dotted",[["--tw-border-style","dotted"],["border-style","dotted"]]),n("border-double",[["--tw-border-style","double"],["border-style","double"]]),n("border-hidden",[["--tw-border-style","hidden"],["border-style","hidden"]]),n("border-none",[["--tw-border-style","none"],["border-style","none"]]);{let i=function(n,o){t.functional(n,t=>{if(!t.value){if(t.modifier)return;let r=e.get(["--default-border-width"])??"1px",n=o.width(r);return n?[a(),...n]:void 0}if("arbitrary"===t.value.kind){let r=t.value.value;switch(t.value.dataType??me(r,["color","line-width","length"])){case"line-width":case"length":{if(t.modifier)return;let e=o.width(r);return e?[a(),...e]:void 0}default:return r=Pe(r,t.modifier,e),null===r?void 0:o.color(r)}}{let r=qe(t,e,["--border-color","--color"]);if(r)return o.color(r)}{if(t.modifier)return;let r=e.resolve(t.value.value,["--border-width"]);if(r){let e=o.width(r);return e?[a(),...e]:void 0}if(Ve(t.value.value)){let e=o.width(`${t.value.value}px`);return e?[a(),...e]:void 0}}}),r(n,()=>[{values:["current","inherit","transparent"],valueThemeKeys:["--border-color","--color"],modifiers:Array.from({length:21},(e,t)=>""+5*t),hasDefaultValue:!0},{values:["0","2","4","8"],valueThemeKeys:["--border-width"]}])},a=()=>K([Me("--tw-border-style","solid")]);i("border",{width:e=>[j("border-style","var(--tw-border-style)"),j("border-width",e)],color:e=>[j("border-color",e)]}),i("border-x",{width:e=>[j("border-inline-style","var(--tw-border-style)"),j("border-inline-width",e)],color:e=>[j("border-inline-color",e)]}),i("border-y",{width:e=>[j("border-block-style","var(--tw-border-style)"),j("border-block-width",e)],color:e=>[j("border-block-color",e)]}),i("border-s",{width:e=>[j("border-inline-start-style","var(--tw-border-style)"),j("border-inline-start-width",e)],color:e=>[j("border-inline-start-color",e)]}),i("border-e",{width:e=>[j("border-inline-end-style","var(--tw-border-style)"),j("border-inline-end-width",e)],color:e=>[j("border-inline-end-color",e)]}),i("border-bs",{width:e=>[j("border-block-start-style","var(--tw-border-style)"),j("border-block-start-width",e)],color:e=>[j("border-block-start-color",e)]}),i("border-be",{width:e=>[j("border-block-end-style","var(--tw-border-style)"),j("border-block-end-width",e)],color:e=>[j("border-block-end-color",e)]}),i("border-t",{width:e=>[j("border-top-style","var(--tw-border-style)"),j("border-top-width",e)],color:e=>[j("border-top-color",e)]}),i("border-r",{width:e=>[j("border-right-style","var(--tw-border-style)"),j("border-right-width",e)],color:e=>[j("border-right-color",e)]}),i("border-b",{width:e=>[j("border-bottom-style","var(--tw-border-style)"),j("border-bottom-width",e)],color:e=>[j("border-bottom-color",e)]}),i("border-l",{width:e=>[j("border-left-style","var(--tw-border-style)"),j("border-left-width",e)],color:e=>[j("border-left-color",e)]}),o("divide-x",{defaultValue:e.get(["--default-border-width"])??"1px",themeKeys:["--divide-width","--border-width"],handleBareValue:({value:e})=>Ve(e)?`${e}px`:null,handle:e=>[K([Me("--tw-divide-x-reverse","0")]),A(":where(& > :not(:last-child))",[j("--tw-sort","divide-x-width"),a(),j("--tw-divide-x-reverse","0"),j("border-inline-style","var(--tw-border-style)"),j("border-inline-start-width",`calc(${e} * var(--tw-divide-x-reverse))`),j("border-inline-end-width",`calc(${e} * calc(1 - var(--tw-divide-x-reverse)))`)])]}),o("divide-y",{defaultValue:e.get(["--default-border-width"])??"1px",themeKeys:["--divide-width","--border-width"],handleBareValue:({value:e})=>Ve(e)?`${e}px`:null,handle:e=>[K([Me("--tw-divide-y-reverse","0")]),A(":where(& > :not(:last-child))",[j("--tw-sort","divide-y-width"),a(),j("--tw-divide-y-reverse","0"),j("border-bottom-style","var(--tw-border-style)"),j("border-top-style","var(--tw-border-style)"),j("border-top-width",`calc(${e} * var(--tw-divide-y-reverse))`),j("border-bottom-width",`calc(${e} * calc(1 - var(--tw-divide-y-reverse)))`)])]}),r("divide-x",()=>[{values:["0","2","4","8"],valueThemeKeys:["--divide-width","--border-width"],hasDefaultValue:!0}]),r("divide-y",()=>[{values:["0","2","4","8"],valueThemeKeys:["--divide-width","--border-width"],hasDefaultValue:!0}]),n("divide-x-reverse",[()=>K([Me("--tw-divide-x-reverse","0")]),()=>A(":where(& > :not(:last-child))",[j("--tw-divide-x-reverse","1")])]),n("divide-y-reverse",[()=>K([Me("--tw-divide-y-reverse","0")]),()=>A(":where(& > :not(:last-child))",[j("--tw-divide-y-reverse","1")])]);for(let e of["solid","dashed","dotted","double","none"])n(`divide-${e}`,[()=>A(":where(& > :not(:last-child))",[j("--tw-sort","divide-style"),j("--tw-border-style",e),j("border-style",e)])])}n("bg-auto",[["background-size","auto"]]),n("bg-cover",[["background-size","cover"]]),n("bg-contain",[["background-size","contain"]]),o("bg-size",{handle(e){if(e)return[j("background-size",e)]}}),n("bg-fixed",[["background-attachment","fixed"]]),n("bg-local",[["background-attachment","local"]]),n("bg-scroll",[["background-attachment","scroll"]]),n("bg-top",[["background-position","top"]]),n("bg-top-left",[["background-position","left top"]]),n("bg-top-right",[["background-position","right top"]]),n("bg-bottom",[["background-position","bottom"]]),n("bg-bottom-left",[["background-position","left bottom"]]),n("bg-bottom-right",[["background-position","right bottom"]]),n("bg-left",[["background-position","left"]]),n("bg-right",[["background-position","right"]]),n("bg-center",[["background-position","center"]]),o("bg-position",{handle(e){if(e)return[j("background-position",e)]}}),n("bg-repeat",[["background-repeat","repeat"]]),n("bg-no-repeat",[["background-repeat","no-repeat"]]),n("bg-repeat-x",[["background-repeat","repeat-x"]]),n("bg-repeat-y",[["background-repeat","repeat-y"]]),n("bg-repeat-round",[["background-repeat","round"]]),n("bg-repeat-space",[["background-repeat","space"]]),n("bg-none",[["background-image","none"]]);{let e=function(e){let t="in oklab";if("named"===e?.kind)switch(e.value){case"longer":case"shorter":case"increasing":case"decreasing":t=`in oklch ${e.value} hue`;break;default:t=`in ${e.value}`}else"arbitrary"===e?.kind&&(t=e.value);return t},n=function({negative:t}){return r=>{if(!r.value)return;if("arbitrary"===r.value.kind){if(r.modifier)return;let e=r.value.value;return"angle"===(r.value.dataType??me(e,["angle"]))?(e=t?`calc(${e} * -1)`:`${e}`,[j("--tw-gradient-position",e),j("background-image",`linear-gradient(var(--tw-gradient-stops,${e}))`)]):t?void 0:[j("--tw-gradient-position",e),j("background-image",`linear-gradient(var(--tw-gradient-stops,${e}))`)]}let n=r.value.value;if(!t&&a.has(n))n=a.get(n);else{if(!Ve(n))return;n=t?`calc(${n}deg * -1)`:`${n}deg`}let o=e(r.modifier);return[j("--tw-gradient-position",`${n}`),C("@supports (background-image: linear-gradient(in lab, red, red))",[j("--tw-gradient-position",`${n} ${o}`)]),j("background-image","linear-gradient(var(--tw-gradient-stops))")]}},o=function({negative:t}){return r=>{if("arbitrary"===r.value?.kind){if(r.modifier)return;let e=r.value.value;return[j("--tw-gradient-position",e),j("background-image",`conic-gradient(var(--tw-gradient-stops,${e}))`)]}let n=e(r.modifier);if(!r.value)return[j("--tw-gradient-position",n),j("background-image","conic-gradient(var(--tw-gradient-stops))")];let o=r.value.value;return Ve(o)?(o=t?`calc(${o}deg * -1)`:`${o}deg`,[j("--tw-gradient-position",`from ${o} ${n}`),j("background-image","conic-gradient(var(--tw-gradient-stops))")]):void 0}},i=["oklab","oklch","srgb","hsl","longer","shorter","increasing","decreasing"],a=new Map([["to-t","to top"],["to-tr","to top right"],["to-r","to right"],["to-br","to bottom right"],["to-b","to bottom"],["to-bl","to bottom left"],["to-l","to left"],["to-tl","to top left"]]);t.functional("-bg-linear",n({negative:!0})),t.functional("bg-linear",n({negative:!1})),r("bg-linear",()=>[{values:[...a.keys()],modifiers:i},{values:["0","30","60","90","120","150","180","210","240","270","300","330"],supportsNegative:!0,modifiers:i}]),t.functional("-bg-conic",o({negative:!0})),t.functional("bg-conic",o({negative:!1})),r("bg-conic",()=>[{hasDefaultValue:!0,modifiers:i},{values:["0","30","60","90","120","150","180","210","240","270","300","330"],supportsNegative:!0,modifiers:i}]),t.functional("bg-radial",t=>{if(!t.value)return[j("--tw-gradient-position",e(t.modifier)),j("background-image","radial-gradient(var(--tw-gradient-stops))")];if("arbitrary"===t.value.kind){if(t.modifier)return;let e=t.value.value;return[j("--tw-gradient-position",e),j("background-image",`radial-gradient(var(--tw-gradient-stops,${e}))`)]}}),r("bg-radial",()=>[{hasDefaultValue:!0,modifiers:i}])}t.functional("bg",t=>{if(t.value){if("arbitrary"===t.value.kind){let r=t.value.value;switch(t.value.dataType??me(r,["image","color","percentage","position","bg-size","length","url"])){case"percentage":case"position":return t.modifier?void 0:[j("background-position",r)];case"bg-size":case"length":case"size":return t.modifier?void 0:[j("background-size",r)];case"image":case"url":return t.modifier?void 0:[j("background-image",r)];default:return r=Pe(r,t.modifier,e),null===r?void 0:[j("background-color",r)]}}{let r=qe(t,e,["--background-color","--color"]);if(r)return[j("background-color",r)]}{if(t.modifier)return;let r=e.resolve(t.value.value,["--background-image"]);if(r)return[j("background-image",r)]}}}),r("bg",()=>[{values:["current","inherit","transparent"],valueThemeKeys:["--background-color","--color"],modifiers:Array.from({length:21},(e,t)=>""+5*t)},{values:[],valueThemeKeys:["--background-image"]}]);let h=()=>K([Me("--tw-gradient-position"),Me("--tw-gradient-from","#0000",""),Me("--tw-gradient-via","#0000",""),Me("--tw-gradient-to","#0000",""),Me("--tw-gradient-stops"),Me("--tw-gradient-via-stops"),Me("--tw-gradient-from-position","0%",""),Me("--tw-gradient-via-position","50%",""),Me("--tw-gradient-to-position","100%","")]);function m(n,o){t.functional(n,t=>{if(t.value){if("arbitrary"===t.value.kind){let r=t.value.value;switch(t.value.dataType??me(r,["color","length","percentage"])){case"length":case"percentage":return t.modifier?void 0:o.position(r);default:return r=Pe(r,t.modifier,e),null===r?void 0:o.color(r)}}{let r=qe(t,e,["--background-color","--color"]);if(r)return o.color(r)}{if(t.modifier)return;let r=e.resolve(t.value.value,["--gradient-color-stop-positions"]);if(r)return o.position(r);if("%"===t.value.value[t.value.value.length-1]&&Ve(t.value.value.slice(0,-1)))return o.position(t.value.value)}}}),r(n,()=>[{values:["current","inherit","transparent"],valueThemeKeys:["--background-color","--color"],modifiers:Array.from({length:21},(e,t)=>""+5*t)},{values:Array.from({length:21},(e,t)=>5*t+"%"),valueThemeKeys:["--gradient-color-stop-positions"]}])}m("from",{color:e=>[h(),j("--tw-sort","--tw-gradient-from"),j("--tw-gradient-from",e),j("--tw-gradient-stops","var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))")],position:e=>[h(),j("--tw-gradient-from-position",e)]}),n("via-none",[["--tw-gradient-via-stops","initial"]]),m("via",{color:e=>[h(),j("--tw-sort","--tw-gradient-via"),j("--tw-gradient-via",e),j("--tw-gradient-via-stops","var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-via) var(--tw-gradient-via-position), var(--tw-gradient-to) var(--tw-gradient-to-position)"),j("--tw-gradient-stops","var(--tw-gradient-via-stops)")],position:e=>[h(),j("--tw-gradient-via-position",e)]}),m("to",{color:e=>[h(),j("--tw-sort","--tw-gradient-to"),j("--tw-gradient-to",e),j("--tw-gradient-stops","var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))")],position:e=>[h(),j("--tw-gradient-to-position",e)]}),n("mask-none",[["mask-image","none"]]),t.functional("mask",e=>{if(!e.value||e.modifier||"arbitrary"!==e.value.kind)return;let t=e.value.value;switch(e.value.dataType??me(t,["image","percentage","position","bg-size","length","url"])){case"percentage":case"position":return e.modifier?void 0:[j("mask-position",t)];case"bg-size":case"length":case"size":return[j("mask-size",t)];default:return[j("mask-image",t)]}}),n("mask-add",[["mask-composite","add"]]),n("mask-subtract",[["mask-composite","subtract"]]),n("mask-intersect",[["mask-composite","intersect"]]),n("mask-exclude",[["mask-composite","exclude"]]),n("mask-alpha",[["mask-mode","alpha"]]),n("mask-luminance",[["mask-mode","luminance"]]),n("mask-match",[["mask-mode","match-source"]]),n("mask-type-alpha",[["mask-type","alpha"]]),n("mask-type-luminance",[["mask-type","luminance"]]),n("mask-auto",[["mask-size","auto"]]),n("mask-cover",[["mask-size","cover"]]),n("mask-contain",[["mask-size","contain"]]),o("mask-size",{handle(e){if(e)return[j("mask-size",e)]}}),n("mask-top",[["mask-position","top"]]),n("mask-top-left",[["mask-position","left top"]]),n("mask-top-right",[["mask-position","right top"]]),n("mask-bottom",[["mask-position","bottom"]]),n("mask-bottom-left",[["mask-position","left bottom"]]),n("mask-bottom-right",[["mask-position","right bottom"]]),n("mask-left",[["mask-position","left"]]),n("mask-right",[["mask-position","right"]]),n("mask-center",[["mask-position","center"]]),o("mask-position",{handle(e){if(e)return[j("mask-position",e)]}}),n("mask-repeat",[["mask-repeat","repeat"]]),n("mask-no-repeat",[["mask-repeat","no-repeat"]]),n("mask-repeat-x",[["mask-repeat","repeat-x"]]),n("mask-repeat-y",[["mask-repeat","repeat-y"]]),n("mask-repeat-round",[["mask-repeat","round"]]),n("mask-repeat-space",[["mask-repeat","space"]]),n("mask-clip-border",[["mask-clip","border-box"]]),n("mask-clip-padding",[["mask-clip","padding-box"]]),n("mask-clip-content",[["mask-clip","content-box"]]),n("mask-clip-fill",[["mask-clip","fill-box"]]),n("mask-clip-stroke",[["mask-clip","stroke-box"]]),n("mask-clip-view",[["mask-clip","view-box"]]),n("mask-no-clip",[["mask-clip","no-clip"]]),n("mask-origin-border",[["mask-origin","border-box"]]),n("mask-origin-padding",[["mask-origin","padding-box"]]),n("mask-origin-content",[["mask-origin","content-box"]]),n("mask-origin-fill",[["mask-origin","fill-box"]]),n("mask-origin-stroke",[["mask-origin","stroke-box"]]),n("mask-origin-view",[["mask-origin","view-box"]]);let g=()=>K([Me("--tw-mask-linear","linear-gradient(#fff, #fff)"),Me("--tw-mask-radial","linear-gradient(#fff, #fff)"),Me("--tw-mask-conic","linear-gradient(#fff, #fff)")]);function v(n,o){t.functional(n,t=>{if(t.value){if("arbitrary"===t.value.kind){let r=t.value.value;switch(t.value.dataType??me(r,["length","percentage","color"])){case"color":return r=Pe(r,t.modifier,e),null===r?void 0:o.color(r);case"percentage":return t.modifier||!Ve(r.slice(0,-1))?void 0:o.position(r);default:return t.modifier?void 0:o.position(r)}}{let r=qe(t,e,["--background-color","--color"]);if(r)return o.color(r)}{if(t.modifier)return;let r=me(t.value.value,["number","percentage"]);if(!r)return;switch(r){case"number":return e.resolve(null,["--spacing"])&&Ee(t.value.value)?o.position(`--spacing(${t.value.value})`):void 0;case"percentage":return Ve(t.value.value.slice(0,-1))?o.position(t.value.value):void 0;default:return}}}}),r(n,()=>[{values:["current","inherit","transparent"],valueThemeKeys:["--background-color","--color"],modifiers:Array.from({length:21},(e,t)=>""+5*t)},{values:Array.from({length:21},(e,t)=>5*t+"%"),valueThemeKeys:["--gradient-color-stop-positions"]}]),r(n,()=>[{values:Array.from({length:21},(e,t)=>5*t+"%")},{values:e.get(["--spacing"])?Le:[]},{values:["current","inherit","transparent"],valueThemeKeys:["--background-color","--color"],modifiers:Array.from({length:21},(e,t)=>""+5*t)}])}let k=()=>K([Me("--tw-mask-left","linear-gradient(#fff, #fff)"),Me("--tw-mask-right","linear-gradient(#fff, #fff)"),Me("--tw-mask-bottom","linear-gradient(#fff, #fff)"),Me("--tw-mask-top","linear-gradient(#fff, #fff)")]);function w(e,t,r){v(e,{color(e){let n=[g(),k(),j("mask-image","var(--tw-mask-linear), var(--tw-mask-radial), var(--tw-mask-conic)"),j("mask-composite","intersect"),j("--tw-mask-linear","var(--tw-mask-left), var(--tw-mask-right), var(--tw-mask-bottom), var(--tw-mask-top)")];for(let o of["top","right","bottom","left"])r[o]&&(n.push(j(`--tw-mask-${o}`,`linear-gradient(to ${o}, var(--tw-mask-${o}-from-color) var(--tw-mask-${o}-from-position), var(--tw-mask-${o}-to-color) var(--tw-mask-${o}-to-position))`)),n.push(K([Me(`--tw-mask-${o}-from-position`,"0%"),Me(`--tw-mask-${o}-to-position`,"100%"),Me(`--tw-mask-${o}-from-color`,"black"),Me(`--tw-mask-${o}-to-color`,"transparent")])),n.push(j(`--tw-mask-${o}-${t}-color`,e)));return n},position(e){let n=[g(),k(),j("mask-image","var(--tw-mask-linear), var(--tw-mask-radial), var(--tw-mask-conic)"),j("mask-composite","intersect"),j("--tw-mask-linear","var(--tw-mask-left), var(--tw-mask-right), var(--tw-mask-bottom), var(--tw-mask-top)")];for(let o of["top","right","bottom","left"])r[o]&&(n.push(j(`--tw-mask-${o}`,`linear-gradient(to ${o}, var(--tw-mask-${o}-from-color) var(--tw-mask-${o}-from-position), var(--tw-mask-${o}-to-color) var(--tw-mask-${o}-to-position))`)),n.push(K([Me(`--tw-mask-${o}-from-position`,"0%"),Me(`--tw-mask-${o}-to-position`,"100%"),Me(`--tw-mask-${o}-from-color`,"black"),Me(`--tw-mask-${o}-to-color`,"transparent")])),n.push(j(`--tw-mask-${o}-${t}-position`,e)));return n}})}w("mask-x-from","from",{top:!1,right:!0,bottom:!1,left:!0}),w("mask-x-to","to",{top:!1,right:!0,bottom:!1,left:!0}),w("mask-y-from","from",{top:!0,right:!1,bottom:!0,left:!1}),w("mask-y-to","to",{top:!0,right:!1,bottom:!0,left:!1}),w("mask-t-from","from",{top:!0,right:!1,bottom:!1,left:!1}),w("mask-t-to","to",{top:!0,right:!1,bottom:!1,left:!1}),w("mask-r-from","from",{top:!1,right:!0,bottom:!1,left:!1}),w("mask-r-to","to",{top:!1,right:!0,bottom:!1,left:!1}),w("mask-b-from","from",{top:!1,right:!1,bottom:!0,left:!1}),w("mask-b-to","to",{top:!1,right:!1,bottom:!0,left:!1}),w("mask-l-from","from",{top:!1,right:!1,bottom:!1,left:!0}),w("mask-l-to","to",{top:!1,right:!1,bottom:!1,left:!0});let b=()=>K([Me("--tw-mask-linear-position","0deg"),Me("--tw-mask-linear-from-position","0%"),Me("--tw-mask-linear-to-position","100%"),Me("--tw-mask-linear-from-color","black"),Me("--tw-mask-linear-to-color","transparent")]);o("mask-linear",{defaultValue:null,supportsNegative:!0,supportsFractions:!1,handleBareValue({value:e}){if(!Ve(e))return null;let t=Number(e);return 0===t?"0deg":1===t?"1deg":`calc(1deg * ${e})`},handleNegativeBareValue({value:e}){if(!Ve(e))return null;let t=Number(e);return 0===t?"0deg":1===t?"-1deg":`calc(1deg * -${e})`},handle:e=>[g(),b(),j("mask-image","var(--tw-mask-linear), var(--tw-mask-radial), var(--tw-mask-conic)"),j("mask-composite","intersect"),j("--tw-mask-linear","linear-gradient(var(--tw-mask-linear-stops, var(--tw-mask-linear-position)))"),j("--tw-mask-linear-position",e)]}),r("mask-linear",()=>[{supportsNegative:!0,values:["0","1","2","3","6","12","45","90","180"]}]),v("mask-linear-from",{color:e=>[g(),b(),j("mask-image","var(--tw-mask-linear), var(--tw-mask-radial), var(--tw-mask-conic)"),j("mask-composite","intersect"),j("--tw-mask-linear-stops","var(--tw-mask-linear-position), var(--tw-mask-linear-from-color) var(--tw-mask-linear-from-position), var(--tw-mask-linear-to-color) var(--tw-mask-linear-to-position)"),j("--tw-mask-linear","linear-gradient(var(--tw-mask-linear-stops))"),j("--tw-mask-linear-from-color",e)],position:e=>[g(),b(),j("mask-image","var(--tw-mask-linear), var(--tw-mask-radial), var(--tw-mask-conic)"),j("mask-composite","intersect"),j("--tw-mask-linear-stops","var(--tw-mask-linear-position), var(--tw-mask-linear-from-color) var(--tw-mask-linear-from-position), var(--tw-mask-linear-to-color) var(--tw-mask-linear-to-position)"),j("--tw-mask-linear","linear-gradient(var(--tw-mask-linear-stops))"),j("--tw-mask-linear-from-position",e)]}),v("mask-linear-to",{color:e=>[g(),b(),j("mask-image","var(--tw-mask-linear), var(--tw-mask-radial), var(--tw-mask-conic)"),j("mask-composite","intersect"),j("--tw-mask-linear-stops","var(--tw-mask-linear-position), var(--tw-mask-linear-from-color) var(--tw-mask-linear-from-position), var(--tw-mask-linear-to-color) var(--tw-mask-linear-to-position)"),j("--tw-mask-linear","linear-gradient(var(--tw-mask-linear-stops))"),j("--tw-mask-linear-to-color",e)],position:e=>[g(),b(),j("mask-image","var(--tw-mask-linear), var(--tw-mask-radial), var(--tw-mask-conic)"),j("mask-composite","intersect"),j("--tw-mask-linear-stops","var(--tw-mask-linear-position), var(--tw-mask-linear-from-color) var(--tw-mask-linear-from-position), var(--tw-mask-linear-to-color) var(--tw-mask-linear-to-position)"),j("--tw-mask-linear","linear-gradient(var(--tw-mask-linear-stops))"),j("--tw-mask-linear-to-position",e)]});let y=()=>K([Me("--tw-mask-radial-from-position","0%"),Me("--tw-mask-radial-to-position","100%"),Me("--tw-mask-radial-from-color","black"),Me("--tw-mask-radial-to-color","transparent"),Me("--tw-mask-radial-shape","ellipse"),Me("--tw-mask-radial-size","farthest-corner"),Me("--tw-mask-radial-position","center")]);n("mask-circle",[["--tw-mask-radial-shape","circle"]]),n("mask-ellipse",[["--tw-mask-radial-shape","ellipse"]]),n("mask-radial-closest-side",[["--tw-mask-radial-size","closest-side"]]),n("mask-radial-farthest-side",[["--tw-mask-radial-size","farthest-side"]]),n("mask-radial-closest-corner",[["--tw-mask-radial-size","closest-corner"]]),n("mask-radial-farthest-corner",[["--tw-mask-radial-size","farthest-corner"]]),n("mask-radial-at-top",[["--tw-mask-radial-position","top"]]),n("mask-radial-at-top-left",[["--tw-mask-radial-position","top left"]]),n("mask-radial-at-top-right",[["--tw-mask-radial-position","top right"]]),n("mask-radial-at-bottom",[["--tw-mask-radial-position","bottom"]]),n("mask-radial-at-bottom-left",[["--tw-mask-radial-position","bottom left"]]),n("mask-radial-at-bottom-right",[["--tw-mask-radial-position","bottom right"]]),n("mask-radial-at-left",[["--tw-mask-radial-position","left"]]),n("mask-radial-at-right",[["--tw-mask-radial-position","right"]]),n("mask-radial-at-center",[["--tw-mask-radial-position","center"]]),o("mask-radial-at",{defaultValue:null,supportsNegative:!1,supportsFractions:!1,handle:e=>[j("--tw-mask-radial-position",e)]}),o("mask-radial",{defaultValue:null,supportsNegative:!1,supportsFractions:!1,handle:e=>[g(),y(),j("mask-image","var(--tw-mask-linear), var(--tw-mask-radial), var(--tw-mask-conic)"),j("mask-composite","intersect"),j("--tw-mask-radial","radial-gradient(var(--tw-mask-radial-stops, var(--tw-mask-radial-size)))"),j("--tw-mask-radial-size",e)]}),v("mask-radial-from",{color:e=>[g(),y(),j("mask-image","var(--tw-mask-linear), var(--tw-mask-radial), var(--tw-mask-conic)"),j("mask-composite","intersect"),j("--tw-mask-radial-stops","var(--tw-mask-radial-shape) var(--tw-mask-radial-size) at var(--tw-mask-radial-position), var(--tw-mask-radial-from-color) var(--tw-mask-radial-from-position), var(--tw-mask-radial-to-color) var(--tw-mask-radial-to-position)"),j("--tw-mask-radial","radial-gradient(var(--tw-mask-radial-stops))"),j("--tw-mask-radial-from-color",e)],position:e=>[g(),y(),j("mask-image","var(--tw-mask-linear), var(--tw-mask-radial), var(--tw-mask-conic)"),j("mask-composite","intersect"),j("--tw-mask-radial-stops","var(--tw-mask-radial-shape) var(--tw-mask-radial-size) at var(--tw-mask-radial-position), var(--tw-mask-radial-from-color) var(--tw-mask-radial-from-position), var(--tw-mask-radial-to-color) var(--tw-mask-radial-to-position)"),j("--tw-mask-radial","radial-gradient(var(--tw-mask-radial-stops))"),j("--tw-mask-radial-from-position",e)]}),v("mask-radial-to",{color:e=>[g(),y(),j("mask-image","var(--tw-mask-linear), var(--tw-mask-radial), var(--tw-mask-conic)"),j("mask-composite","intersect"),j("--tw-mask-radial-stops","var(--tw-mask-radial-shape) var(--tw-mask-radial-size) at var(--tw-mask-radial-position), var(--tw-mask-radial-from-color) var(--tw-mask-radial-from-position), var(--tw-mask-radial-to-color) var(--tw-mask-radial-to-position)"),j("--tw-mask-radial","radial-gradient(var(--tw-mask-radial-stops))"),j("--tw-mask-radial-to-color",e)],position:e=>[g(),y(),j("mask-image","var(--tw-mask-linear), var(--tw-mask-radial), var(--tw-mask-conic)"),j("mask-composite","intersect"),j("--tw-mask-radial-stops","var(--tw-mask-radial-shape) var(--tw-mask-radial-size) at var(--tw-mask-radial-position), var(--tw-mask-radial-from-color) var(--tw-mask-radial-from-position), var(--tw-mask-radial-to-color) var(--tw-mask-radial-to-position)"),j("--tw-mask-radial","radial-gradient(var(--tw-mask-radial-stops))"),j("--tw-mask-radial-to-position",e)]});let x=()=>K([Me("--tw-mask-conic-position","0deg"),Me("--tw-mask-conic-from-position","0%"),Me("--tw-mask-conic-to-position","100%"),Me("--tw-mask-conic-from-color","black"),Me("--tw-mask-conic-to-color","transparent")]);o("mask-conic",{defaultValue:null,supportsNegative:!0,supportsFractions:!1,handleBareValue({value:e}){if(!Ve(e))return null;let t=Number(e);return 0===t?"0deg":1===t?"1deg":`calc(1deg * ${e})`},handleNegativeBareValue({value:e}){if(!Ve(e))return null;let t=Number(e);return 0===t?"0deg":1===t?"-1deg":`calc(1deg * -${e})`},handle:e=>[g(),x(),j("mask-image","var(--tw-mask-linear), var(--tw-mask-radial), var(--tw-mask-conic)"),j("mask-composite","intersect"),j("--tw-mask-conic","conic-gradient(var(--tw-mask-conic-stops, var(--tw-mask-conic-position)))"),j("--tw-mask-conic-position",e)]}),r("mask-conic",()=>[{supportsNegative:!0,values:["0","1","2","3","6","12","45","90","180"]}]),v("mask-conic-from",{color:e=>[g(),x(),j("mask-image","var(--tw-mask-linear), var(--tw-mask-radial), var(--tw-mask-conic)"),j("mask-composite","intersect"),j("--tw-mask-conic-stops","from var(--tw-mask-conic-position), var(--tw-mask-conic-from-color) var(--tw-mask-conic-from-position), var(--tw-mask-conic-to-color) var(--tw-mask-conic-to-position)"),j("--tw-mask-conic","conic-gradient(var(--tw-mask-conic-stops))"),j("--tw-mask-conic-from-color",e)],position:e=>[g(),x(),j("mask-image","var(--tw-mask-linear), var(--tw-mask-radial), var(--tw-mask-conic)"),j("mask-composite","intersect"),j("--tw-mask-conic-stops","from var(--tw-mask-conic-position), var(--tw-mask-conic-from-color) var(--tw-mask-conic-from-position), var(--tw-mask-conic-to-color) var(--tw-mask-conic-to-position)"),j("--tw-mask-conic","conic-gradient(var(--tw-mask-conic-stops))"),j("--tw-mask-conic-from-position",e)]}),v("mask-conic-to",{color:e=>[g(),x(),j("mask-image","var(--tw-mask-linear), var(--tw-mask-radial), var(--tw-mask-conic)"),j("mask-composite","intersect"),j("--tw-mask-conic-stops","from var(--tw-mask-conic-position), var(--tw-mask-conic-from-color) var(--tw-mask-conic-from-position), var(--tw-mask-conic-to-color) var(--tw-mask-conic-to-position)"),j("--tw-mask-conic","conic-gradient(var(--tw-mask-conic-stops))"),j("--tw-mask-conic-to-color",e)],position:e=>[g(),x(),j("mask-image","var(--tw-mask-linear), var(--tw-mask-radial), var(--tw-mask-conic)"),j("mask-composite","intersect"),j("--tw-mask-conic-stops","from var(--tw-mask-conic-position), var(--tw-mask-conic-from-color) var(--tw-mask-conic-from-position), var(--tw-mask-conic-to-color) var(--tw-mask-conic-to-position)"),j("--tw-mask-conic","conic-gradient(var(--tw-mask-conic-stops))"),j("--tw-mask-conic-to-position",e)]}),n("box-decoration-slice",[["-webkit-box-decoration-break","slice"],["box-decoration-break","slice"]]),n("box-decoration-clone",[["-webkit-box-decoration-break","clone"],["box-decoration-break","clone"]]),n("bg-clip-text",[["background-clip","text"]]),n("bg-clip-border",[["background-clip","border-box"]]),n("bg-clip-padding",[["background-clip","padding-box"]]),n("bg-clip-content",[["background-clip","content-box"]]),n("bg-origin-border",[["background-origin","border-box"]]),n("bg-origin-padding",[["background-origin","padding-box"]]),n("bg-origin-content",[["background-origin","content-box"]]);for(let e of["normal","multiply","screen","overlay","darken","lighten","color-dodge","color-burn","hard-light","soft-light","difference","exclusion","hue","saturation","color","luminosity"])n(`bg-blend-${e}`,[["background-blend-mode",e]]),n(`mix-blend-${e}`,[["mix-blend-mode",e]]);n("mix-blend-plus-darker",[["mix-blend-mode","plus-darker"]]),n("mix-blend-plus-lighter",[["mix-blend-mode","plus-lighter"]]),n("fill-none",[["fill","none"]]),t.functional("fill",t=>{if(!t.value)return;if("arbitrary"===t.value.kind){let r=Pe(t.value.value,t.modifier,e);return null===r?void 0:[j("fill",r)]}let r=qe(t,e,["--fill","--color"]);return r?[j("fill",r)]:void 0}),r("fill",()=>[{values:["current","inherit","transparent"],valueThemeKeys:["--fill","--color"],modifiers:Array.from({length:21},(e,t)=>""+5*t)}]),n("stroke-none",[["stroke","none"]]),t.functional("stroke",t=>{if(t.value){if("arbitrary"===t.value.kind){let r=t.value.value;switch(t.value.dataType??me(r,["color","number","length","percentage"])){case"number":case"length":case"percentage":return t.modifier?void 0:[j("stroke-width",r)];default:return r=Pe(t.value.value,t.modifier,e),null===r?void 0:[j("stroke",r)]}}{let r=qe(t,e,["--stroke","--color"]);if(r)return[j("stroke",r)]}{let r=e.resolve(t.value.value,["--stroke-width"]);if(r)return[j("stroke-width",r)];if(Ve(t.value.value))return[j("stroke-width",t.value.value)]}}}),r("stroke",()=>[{values:["current","inherit","transparent"],valueThemeKeys:["--stroke","--color"],modifiers:Array.from({length:21},(e,t)=>""+5*t)},{values:["0","1","2","3"],valueThemeKeys:["--stroke-width"]}]),n("object-contain",[["object-fit","contain"]]),n("object-cover",[["object-fit","cover"]]),n("object-fill",[["object-fit","fill"]]),n("object-none",[["object-fit","none"]]),n("object-scale-down",[["object-fit","scale-down"]]),o("object",{themeKeys:["--object-position"],handle:e=>[j("object-position",e)],staticValues:{top:[j("object-position","top")],"top-left":[j("object-position","left top")],"top-right":[j("object-position","right top")],bottom:[j("object-position","bottom")],"bottom-left":[j("object-position","left bottom")],"bottom-right":[j("object-position","right bottom")],left:[j("object-position","left")],right:[j("object-position","right")],center:[j("object-position","center")]}});for(let[e,t]of[["p","padding"],["px","padding-inline"],["py","padding-block"],["ps","padding-inline-start"],["pe","padding-inline-end"],["pbs","padding-block-start"],["pbe","padding-block-end"],["pt","padding-top"],["pr","padding-right"],["pb","padding-bottom"],["pl","padding-left"]])a(e,["--padding","--spacing"],e=>[j(t,e)]);n("text-left",[["text-align","left"]]),n("text-center",[["text-align","center"]]),n("text-right",[["text-align","right"]]),n("text-justify",[["text-align","justify"]]),n("text-start",[["text-align","start"]]),n("text-end",[["text-align","end"]]),a("indent",["--text-indent","--spacing"],e=>[j("text-indent",e)],{supportsNegative:!0}),n("align-baseline",[["vertical-align","baseline"]]),n("align-top",[["vertical-align","top"]]),n("align-middle",[["vertical-align","middle"]]),n("align-bottom",[["vertical-align","bottom"]]),n("align-text-top",[["vertical-align","text-top"]]),n("align-text-bottom",[["vertical-align","text-bottom"]]),n("align-sub",[["vertical-align","sub"]]),n("align-super",[["vertical-align","super"]]),o("align",{themeKeys:[],handle:e=>[j("vertical-align",e)]}),t.functional("font",t=>{if(t.value&&!t.modifier){if("arbitrary"===t.value.kind){let e=t.value.value;switch(t.value.dataType??me(e,["number","generic-name","family-name"])){case"generic-name":case"family-name":return[j("font-family",e)];default:return[K([Me("--tw-font-weight")]),j("--tw-font-weight",e),j("font-weight",e)]}}{let r=e.resolveWith(t.value.value,["--font"],["--font-feature-settings","--font-variation-settings"]);if(r){let[e,t={}]=r;return[j("font-family",e),j("font-feature-settings",t["--font-feature-settings"]),j("font-variation-settings",t["--font-variation-settings"])]}}{let r=e.resolve(t.value.value,["--font-weight"]);if(r)return[K([Me("--tw-font-weight")]),j("--tw-font-weight",r),j("font-weight",r)]}}}),r("font",()=>[{values:[],valueThemeKeys:["--font"]},{values:[],valueThemeKeys:["--font-weight"]}]),o("font-features",{themeKeys:[],handle:e=>[j("font-feature-settings",e)]}),n("uppercase",[["text-transform","uppercase"]]),n("lowercase",[["text-transform","lowercase"]]),n("capitalize",[["text-transform","capitalize"]]),n("normal-case",[["text-transform","none"]]),n("italic",[["font-style","italic"]]),n("not-italic",[["font-style","normal"]]),n("underline",[["text-decoration-line","underline"]]),n("overline",[["text-decoration-line","overline"]]),n("line-through",[["text-decoration-line","line-through"]]),n("no-underline",[["text-decoration-line","none"]]),n("font-stretch-normal",[["font-stretch","normal"]]),n("font-stretch-ultra-condensed",[["font-stretch","ultra-condensed"]]),n("font-stretch-extra-condensed",[["font-stretch","extra-condensed"]]),n("font-stretch-condensed",[["font-stretch","condensed"]]),n("font-stretch-semi-condensed",[["font-stretch","semi-condensed"]]),n("font-stretch-semi-expanded",[["font-stretch","semi-expanded"]]),n("font-stretch-expanded",[["font-stretch","expanded"]]),n("font-stretch-extra-expanded",[["font-stretch","extra-expanded"]]),n("font-stretch-ultra-expanded",[["font-stretch","ultra-expanded"]]),o("font-stretch",{handleBareValue:({value:e})=>{if(!e.endsWith("%"))return null;let t=Number(e.slice(0,-1));return!Ve(t)||Number.isNaN(t)||t<50||t>200?null:e},handle:e=>[j("font-stretch",e)]}),r("font-stretch",()=>[{values:["50%","75%","90%","95%","100%","105%","110%","125%","150%","200%"]}]),i("placeholder",{themeKeys:["--placeholder-color","--color"],handle:e=>[A("&::placeholder",[j("--tw-sort","placeholder-color"),j("color",e)])]}),n("decoration-solid",[["text-decoration-style","solid"]]),n("decoration-double",[["text-decoration-style","double"]]),n("decoration-dotted",[["text-decoration-style","dotted"]]),n("decoration-dashed",[["text-decoration-style","dashed"]]),n("decoration-wavy",[["text-decoration-style","wavy"]]),n("decoration-auto",[["text-decoration-thickness","auto"]]),n("decoration-from-font",[["text-decoration-thickness","from-font"]]),t.functional("decoration",t=>{if(t.value){if("arbitrary"===t.value.kind){let r=t.value.value;switch(t.value.dataType??me(r,["color","length","percentage"])){case"length":case"percentage":return t.modifier?void 0:[j("text-decoration-thickness",r)];default:return r=Pe(r,t.modifier,e),null===r?void 0:[j("text-decoration-color",r)]}}{let r=e.resolve(t.value.value,["--text-decoration-thickness"]);if(r)return t.modifier?void 0:[j("text-decoration-thickness",r)];if(Ve(t.value.value))return t.modifier?void 0:[j("text-decoration-thickness",`${t.value.value}px`)]}{let r=qe(t,e,["--text-decoration-color","--color"]);if(r)return[j("text-decoration-color",r)]}}}),r("decoration",()=>[{values:["current","inherit","transparent"],valueThemeKeys:["--text-decoration-color","--color"],modifiers:Array.from({length:21},(e,t)=>""+5*t)},{values:["0","1","2"],valueThemeKeys:["--text-decoration-thickness"]}]),o("animate",{themeKeys:["--animate"],handle:e=>[j("animation",e)],staticValues:{none:[j("animation","none")]}});{let i=["var(--tw-blur,)","var(--tw-brightness,)","var(--tw-contrast,)","var(--tw-grayscale,)","var(--tw-hue-rotate,)","var(--tw-invert,)","var(--tw-saturate,)","var(--tw-sepia,)","var(--tw-drop-shadow,)"].join(" "),a=["var(--tw-backdrop-blur,)","var(--tw-backdrop-brightness,)","var(--tw-backdrop-contrast,)","var(--tw-backdrop-grayscale,)","var(--tw-backdrop-hue-rotate,)","var(--tw-backdrop-invert,)","var(--tw-backdrop-opacity,)","var(--tw-backdrop-saturate,)","var(--tw-backdrop-sepia,)"].join(" "),l=()=>K([Me("--tw-blur"),Me("--tw-brightness"),Me("--tw-contrast"),Me("--tw-grayscale"),Me("--tw-hue-rotate"),Me("--tw-invert"),Me("--tw-opacity"),Me("--tw-saturate"),Me("--tw-sepia"),Me("--tw-drop-shadow"),Me("--tw-drop-shadow-color"),Me("--tw-drop-shadow-alpha","100%",""),Me("--tw-drop-shadow-size")]),s=()=>K([Me("--tw-backdrop-blur"),Me("--tw-backdrop-brightness"),Me("--tw-backdrop-contrast"),Me("--tw-backdrop-grayscale"),Me("--tw-backdrop-hue-rotate"),Me("--tw-backdrop-invert"),Me("--tw-backdrop-opacity"),Me("--tw-backdrop-saturate"),Me("--tw-backdrop-sepia")]);t.functional("filter",e=>{if(!e.modifier){if(null===e.value)return[l(),j("filter",i)];if("arbitrary"===e.value.kind)return[j("filter",e.value.value)];if("none"===e.value.value)return[j("filter","none")]}}),t.functional("backdrop-filter",e=>{if(!e.modifier){if(null===e.value)return[s(),j("-webkit-backdrop-filter",a),j("backdrop-filter",a)];if("arbitrary"===e.value.kind)return[j("-webkit-backdrop-filter",e.value.value),j("backdrop-filter",e.value.value)];if("none"===e.value.value)return[j("-webkit-backdrop-filter","none"),j("backdrop-filter","none")]}}),o("blur",{themeKeys:["--blur"],handle:e=>[l(),j("--tw-blur",`blur(${e})`),j("filter",i)],staticValues:{none:[l(),j("--tw-blur"," "),j("filter",i)]}}),o("backdrop-blur",{themeKeys:["--backdrop-blur","--blur"],handle:e=>[s(),j("--tw-backdrop-blur",`blur(${e})`),j("-webkit-backdrop-filter",a),j("backdrop-filter",a)],staticValues:{none:[s(),j("--tw-backdrop-blur"," "),j("-webkit-backdrop-filter",a),j("backdrop-filter",a)]}}),o("brightness",{themeKeys:["--brightness"],handleBareValue:({value:e})=>Ve(e)?`${e}%`:null,handle:e=>[l(),j("--tw-brightness",`brightness(${e})`),j("filter",i)]}),o("backdrop-brightness",{themeKeys:["--backdrop-brightness","--brightness"],handleBareValue:({value:e})=>Ve(e)?`${e}%`:null,handle:e=>[s(),j("--tw-backdrop-brightness",`brightness(${e})`),j("-webkit-backdrop-filter",a),j("backdrop-filter",a)]}),r("brightness",()=>[{values:["0","50","75","90","95","100","105","110","125","150","200"],valueThemeKeys:["--brightness"]}]),r("backdrop-brightness",()=>[{values:["0","50","75","90","95","100","105","110","125","150","200"],valueThemeKeys:["--backdrop-brightness","--brightness"]}]),o("contrast",{themeKeys:["--contrast"],handleBareValue:({value:e})=>Ve(e)?`${e}%`:null,handle:e=>[l(),j("--tw-contrast",`contrast(${e})`),j("filter",i)]}),o("backdrop-contrast",{themeKeys:["--backdrop-contrast","--contrast"],handleBareValue:({value:e})=>Ve(e)?`${e}%`:null,handle:e=>[s(),j("--tw-backdrop-contrast",`contrast(${e})`),j("-webkit-backdrop-filter",a),j("backdrop-filter",a)]}),r("contrast",()=>[{values:["0","50","75","100","125","150","200"],valueThemeKeys:["--contrast"]}]),r("backdrop-contrast",()=>[{values:["0","50","75","100","125","150","200"],valueThemeKeys:["--backdrop-contrast","--contrast"]}]),o("grayscale",{themeKeys:["--grayscale"],handleBareValue:({value:e})=>Ve(e)?`${e}%`:null,defaultValue:"100%",handle:e=>[l(),j("--tw-grayscale",`grayscale(${e})`),j("filter",i)]}),o("backdrop-grayscale",{themeKeys:["--backdrop-grayscale","--grayscale"],handleBareValue:({value:e})=>Ve(e)?`${e}%`:null,defaultValue:"100%",handle:e=>[s(),j("--tw-backdrop-grayscale",`grayscale(${e})`),j("-webkit-backdrop-filter",a),j("backdrop-filter",a)]}),r("grayscale",()=>[{values:["0","25","50","75","100"],valueThemeKeys:["--grayscale"],hasDefaultValue:!0}]),r("backdrop-grayscale",()=>[{values:["0","25","50","75","100"],valueThemeKeys:["--backdrop-grayscale","--grayscale"],hasDefaultValue:!0}]),o("hue-rotate",{supportsNegative:!0,themeKeys:["--hue-rotate"],handleBareValue:({value:e})=>Ve(e)?`${e}deg`:null,handle:e=>[l(),j("--tw-hue-rotate",`hue-rotate(${e})`),j("filter",i)]}),o("backdrop-hue-rotate",{supportsNegative:!0,themeKeys:["--backdrop-hue-rotate","--hue-rotate"],handleBareValue:({value:e})=>Ve(e)?`${e}deg`:null,handle:e=>[s(),j("--tw-backdrop-hue-rotate",`hue-rotate(${e})`),j("-webkit-backdrop-filter",a),j("backdrop-filter",a)]}),r("hue-rotate",()=>[{values:["0","15","30","60","90","180"],valueThemeKeys:["--hue-rotate"]}]),r("backdrop-hue-rotate",()=>[{values:["0","15","30","60","90","180"],valueThemeKeys:["--backdrop-hue-rotate","--hue-rotate"]}]),o("invert",{themeKeys:["--invert"],handleBareValue:({value:e})=>Ve(e)?`${e}%`:null,defaultValue:"100%",handle:e=>[l(),j("--tw-invert",`invert(${e})`),j("filter",i)]}),o("backdrop-invert",{themeKeys:["--backdrop-invert","--invert"],handleBareValue:({value:e})=>Ve(e)?`${e}%`:null,defaultValue:"100%",handle:e=>[s(),j("--tw-backdrop-invert",`invert(${e})`),j("-webkit-backdrop-filter",a),j("backdrop-filter",a)]}),r("invert",()=>[{values:["0","25","50","75","100"],valueThemeKeys:["--invert"],hasDefaultValue:!0}]),r("backdrop-invert",()=>[{values:["0","25","50","75","100"],valueThemeKeys:["--backdrop-invert","--invert"],hasDefaultValue:!0}]),o("saturate",{themeKeys:["--saturate"],handleBareValue:({value:e})=>Ve(e)?`${e}%`:null,handle:e=>[l(),j("--tw-saturate",`saturate(${e})`),j("filter",i)]}),o("backdrop-saturate",{themeKeys:["--backdrop-saturate","--saturate"],handleBareValue:({value:e})=>Ve(e)?`${e}%`:null,handle:e=>[s(),j("--tw-backdrop-saturate",`saturate(${e})`),j("-webkit-backdrop-filter",a),j("backdrop-filter",a)]}),r("saturate",()=>[{values:["0","50","100","150","200"],valueThemeKeys:["--saturate"]}]),r("backdrop-saturate",()=>[{values:["0","50","100","150","200"],valueThemeKeys:["--backdrop-saturate","--saturate"]}]),o("sepia",{themeKeys:["--sepia"],handleBareValue:({value:e})=>Ve(e)?`${e}%`:null,defaultValue:"100%",handle:e=>[l(),j("--tw-sepia",`sepia(${e})`),j("filter",i)]}),o("backdrop-sepia",{themeKeys:["--backdrop-sepia","--sepia"],handleBareValue:({value:e})=>Ve(e)?`${e}%`:null,defaultValue:"100%",handle:e=>[s(),j("--tw-backdrop-sepia",`sepia(${e})`),j("-webkit-backdrop-filter",a),j("backdrop-filter",a)]}),r("sepia",()=>[{values:["0","50","100"],valueThemeKeys:["--sepia"],hasDefaultValue:!0}]),r("backdrop-sepia",()=>[{values:["0","50","100"],valueThemeKeys:["--backdrop-sepia","--sepia"],hasDefaultValue:!0}]),n("drop-shadow-none",[l,["--tw-drop-shadow"," "],["filter",i]]),t.functional("drop-shadow",t=>{let r;if(t.modifier&&("arbitrary"===t.modifier.kind?r=t.modifier.value:Ve(t.modifier.value)&&(r=`${t.modifier.value}%`)),!t.value){let t=e.get(["--drop-shadow"]),n=e.resolve(null,["--drop-shadow"]);return null===t||null===n?void 0:[l(),j("--tw-drop-shadow-alpha",r),...Xe("--tw-drop-shadow-size",t,r,e=>`var(--tw-drop-shadow-color, ${e})`),j("--tw-drop-shadow",Z(n,",").map(e=>`drop-shadow(${e})`).join(" ")),j("filter",i)]}if("arbitrary"===t.value.kind){let n=t.value.value;return"color"===(t.value.dataType??me(n,["color"]))?(n=Pe(n,t.modifier,e),null===n?void 0:[l(),j("--tw-drop-shadow-color",Be(n,"var(--tw-drop-shadow-alpha)")),j("--tw-drop-shadow","var(--tw-drop-shadow-size)")]):t.modifier&&!r?void 0:[l(),j("--tw-drop-shadow-alpha",r),...Xe("--tw-drop-shadow-size",n,r,e=>`var(--tw-drop-shadow-color, ${e})`),j("--tw-drop-shadow","var(--tw-drop-shadow-size)"),j("filter",i)]}{let n=e.get([`--drop-shadow-${t.value.value}`]),o=e.resolve(t.value.value,["--drop-shadow"]);if(n&&o)return t.modifier&&!r?void 0:r?[l(),j("--tw-drop-shadow-alpha",r),...Xe("--tw-drop-shadow-size",n,r,e=>`var(--tw-drop-shadow-color, ${e})`),j("--tw-drop-shadow","var(--tw-drop-shadow-size)"),j("filter",i)]:[l(),j("--tw-drop-shadow-alpha",r),...Xe("--tw-drop-shadow-size",n,r,e=>`var(--tw-drop-shadow-color, ${e})`),j("--tw-drop-shadow",Z(o,",").map(e=>`drop-shadow(${e})`).join(" ")),j("filter",i)]}{let r=qe(t,e,["--drop-shadow-color","--color"]);if(r)return"inherit"===r?[l(),j("--tw-drop-shadow-color","inherit"),j("--tw-drop-shadow","var(--tw-drop-shadow-size)")]:[l(),j("--tw-drop-shadow-color",Be(r,"var(--tw-drop-shadow-alpha)")),j("--tw-drop-shadow","var(--tw-drop-shadow-size)")]}}),r("drop-shadow",()=>[{values:["current","inherit","transparent"],valueThemeKeys:["--drop-shadow-color","--color"],modifiers:Array.from({length:21},(e,t)=>""+5*t)},{valueThemeKeys:["--drop-shadow"]}]),o("backdrop-opacity",{themeKeys:["--backdrop-opacity","--opacity"],handleBareValue:({value:e})=>Ne(e)?`${e}%`:null,handle:e=>[s(),j("--tw-backdrop-opacity",`opacity(${e})`),j("-webkit-backdrop-filter",a),j("backdrop-filter",a)]}),r("backdrop-opacity",()=>[{values:Array.from({length:21},(e,t)=>""+5*t),valueThemeKeys:["--backdrop-opacity","--opacity"]}])}{let i=`var(--tw-ease, ${e.resolve(null,["--default-transition-timing-function"])??"ease"})`,a=`var(--tw-duration, ${e.resolve(null,["--default-transition-duration"])??"0s"})`;o("transition",{defaultValue:"color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to, opacity, box-shadow, transform, translate, scale, rotate, filter, -webkit-backdrop-filter, backdrop-filter, display, content-visibility, overlay, pointer-events",themeKeys:["--transition-property"],handle:e=>[j("transition-property",e),j("transition-timing-function",i),j("transition-duration",a)],staticValues:{none:[j("transition-property","none")],all:[j("transition-property","all"),j("transition-timing-function",i),j("transition-duration",a)],colors:[j("transition-property","color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to"),j("transition-timing-function",i),j("transition-duration",a)],opacity:[j("transition-property","opacity"),j("transition-timing-function",i),j("transition-duration",a)],shadow:[j("transition-property","box-shadow"),j("transition-timing-function",i),j("transition-duration",a)],transform:[j("transition-property","transform, translate, scale, rotate"),j("transition-timing-function",i),j("transition-duration",a)]}}),n("transition-discrete",[["transition-behavior","allow-discrete"]]),n("transition-normal",[["transition-behavior","normal"]]),o("delay",{handleBareValue:({value:e})=>Ve(e)?`${e}ms`:null,themeKeys:["--transition-delay"],handle:e=>[j("transition-delay",e)]});{let r=()=>K([Me("--tw-duration")]);n("duration-initial",[r,["--tw-duration","initial"]]),t.functional("duration",t=>{if(t.modifier||!t.value)return;let n=null;return"arbitrary"===t.value.kind?n=t.value.value:(n=e.resolve(t.value.fraction??t.value.value,["--transition-duration"]),null===n&&Ve(t.value.value)&&(n=`${t.value.value}ms`)),null!==n?[r(),j("--tw-duration",n),j("transition-duration",n)]:void 0})}r("delay",()=>[{values:["75","100","150","200","300","500","700","1000"],valueThemeKeys:["--transition-delay"]}]),r("duration",()=>[{values:["75","100","150","200","300","500","700","1000"],valueThemeKeys:["--transition-duration"]}])}{let e=()=>K([Me("--tw-ease")]);o("ease",{themeKeys:["--ease"],handle:t=>[e(),j("--tw-ease",t),j("transition-timing-function",t)],staticValues:{initial:[e(),j("--tw-ease","initial")],linear:[e(),j("--tw-ease","linear"),j("transition-timing-function","linear")]}})}n("will-change-auto",[["will-change","auto"]]),n("will-change-scroll",[["will-change","scroll-position"]]),n("will-change-contents",[["will-change","contents"]]),n("will-change-transform",[["will-change","transform"]]),o("will-change",{themeKeys:[],handle:e=>[j("will-change",e)]}),n("content-none",[["--tw-content","none"],["content","none"]]),o("content",{themeKeys:["--content"],handle:e=>[K([Me("--tw-content",'""')]),j("--tw-content",e),j("content","var(--tw-content)")]});{let e="var(--tw-contain-size,) var(--tw-contain-layout,) var(--tw-contain-paint,) var(--tw-contain-style,)",t=()=>K([Me("--tw-contain-size"),Me("--tw-contain-layout"),Me("--tw-contain-paint"),Me("--tw-contain-style")]);n("contain-none",[["contain","none"]]),n("contain-content",[["contain","content"]]),n("contain-strict",[["contain","strict"]]),n("contain-size",[t,["--tw-contain-size","size"],["contain",e]]),n("contain-inline-size",[t,["--tw-contain-size","inline-size"],["contain",e]]),n("contain-layout",[t,["--tw-contain-layout","layout"],["contain",e]]),n("contain-paint",[t,["--tw-contain-paint","paint"],["contain",e]]),n("contain-style",[t,["--tw-contain-style","style"],["contain",e]]),o("contain",{themeKeys:[],handle:e=>[j("contain",e)]})}n("forced-color-adjust-none",[["forced-color-adjust","none"]]),n("forced-color-adjust-auto",[["forced-color-adjust","auto"]]),a("leading",["--leading","--spacing"],e=>[K([Me("--tw-leading")]),j("--tw-leading",e),j("line-height",e)],{staticValues:{none:[K([Me("--tw-leading")]),j("--tw-leading","1"),j("line-height","1")]}}),o("tracking",{supportsNegative:!0,themeKeys:["--tracking"],handle:e=>[K([Me("--tw-tracking")]),j("--tw-tracking",e),j("letter-spacing",e)]}),n("antialiased",[["-webkit-font-smoothing","antialiased"],["-moz-osx-font-smoothing","grayscale"]]),n("subpixel-antialiased",[["-webkit-font-smoothing","auto"],["-moz-osx-font-smoothing","auto"]]);{let e="var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)",t=()=>K([Me("--tw-ordinal"),Me("--tw-slashed-zero"),Me("--tw-numeric-figure"),Me("--tw-numeric-spacing"),Me("--tw-numeric-fraction")]);n("normal-nums",[["font-variant-numeric","normal"]]),n("ordinal",[t,["--tw-ordinal","ordinal"],["font-variant-numeric",e]]),n("slashed-zero",[t,["--tw-slashed-zero","slashed-zero"],["font-variant-numeric",e]]),n("lining-nums",[t,["--tw-numeric-figure","lining-nums"],["font-variant-numeric",e]]),n("oldstyle-nums",[t,["--tw-numeric-figure","oldstyle-nums"],["font-variant-numeric",e]]),n("proportional-nums",[t,["--tw-numeric-spacing","proportional-nums"],["font-variant-numeric",e]]),n("tabular-nums",[t,["--tw-numeric-spacing","tabular-nums"],["font-variant-numeric",e]]),n("diagonal-fractions",[t,["--tw-numeric-fraction","diagonal-fractions"],["font-variant-numeric",e]]),n("stacked-fractions",[t,["--tw-numeric-fraction","stacked-fractions"],["font-variant-numeric",e]])}{let i=()=>K([Me("--tw-outline-style","solid")]);t.static("outline-hidden",()=>[j("--tw-outline-style","none"),j("outline-style","none"),S("@media","(forced-colors: active)",[j("outline","2px solid transparent"),j("outline-offset","2px")])]),n("outline-none",[["--tw-outline-style","none"],["outline-style","none"]]),n("outline-solid",[["--tw-outline-style","solid"],["outline-style","solid"]]),n("outline-dashed",[["--tw-outline-style","dashed"],["outline-style","dashed"]]),n("outline-dotted",[["--tw-outline-style","dotted"],["outline-style","dotted"]]),n("outline-double",[["--tw-outline-style","double"],["outline-style","double"]]),t.functional("outline",t=>{if(null===t.value){if(t.modifier)return;let r=e.get(["--default-outline-width"])??"1px";return[i(),j("outline-style","var(--tw-outline-style)"),j("outline-width",r)]}if("arbitrary"===t.value.kind){let r=t.value.value;switch(t.value.dataType??me(r,["color","length","number","percentage"])){case"length":case"number":case"percentage":return t.modifier?void 0:[i(),j("outline-style","var(--tw-outline-style)"),j("outline-width",r)];default:return r=Pe(r,t.modifier,e),null===r?void 0:[j("outline-color",r)]}}{let r=qe(t,e,["--outline-color","--color"]);if(r)return[j("outline-color",r)]}{if(t.modifier)return;let r=e.resolve(t.value.value,["--outline-width"]);if(r)return[i(),j("outline-style","var(--tw-outline-style)"),j("outline-width",r)];if(Ve(t.value.value))return[i(),j("outline-style","var(--tw-outline-style)"),j("outline-width",`${t.value.value}px`)]}}),r("outline",()=>[{values:["current","inherit","transparent"],valueThemeKeys:["--outline-color","--color"],modifiers:Array.from({length:21},(e,t)=>""+5*t),hasDefaultValue:!0},{values:["0","1","2","4","8"],valueThemeKeys:["--outline-width"]}]),o("outline-offset",{supportsNegative:!0,themeKeys:["--outline-offset"],handleBareValue:({value:e})=>Ve(e)?`${e}px`:null,handle:e=>[j("outline-offset",e)]}),r("outline-offset",()=>[{supportsNegative:!0,values:["0","1","2","4","8"],valueThemeKeys:["--outline-offset"]}])}o("opacity",{themeKeys:["--opacity"],handleBareValue:({value:e})=>Ne(e)?`${e}%`:null,handle:e=>[j("opacity",e)]}),r("opacity",()=>[{values:Array.from({length:21},(e,t)=>""+5*t),valueThemeKeys:["--opacity"]}]),o("underline-offset",{supportsNegative:!0,themeKeys:["--text-underline-offset"],handleBareValue:({value:e})=>Ve(e)?`${e}px`:null,handle:e=>[j("text-underline-offset",e)],staticValues:{auto:[j("text-underline-offset","auto")]}}),r("underline-offset",()=>[{supportsNegative:!0,values:["0","1","2","4","8"],valueThemeKeys:["--text-underline-offset"]}]),t.functional("text",t=>{if(t.value){if("arbitrary"===t.value.kind){let r=t.value.value;switch(t.value.dataType??me(r,["color","length","percentage","absolute-size","relative-size"])){case"size":case"length":case"percentage":case"absolute-size":case"relative-size":if(t.modifier){let n="arbitrary"===t.modifier.kind?t.modifier.value:e.resolve(t.modifier.value,["--leading"]);if(!n&&Ee(t.modifier.value)){if(!e.resolve(null,["--spacing"]))return null;n=`--spacing(${t.modifier.value})`}return!n&&"none"===t.modifier.value&&(n="1"),n?[j("font-size",r),j("line-height",n)]:null}return[j("font-size",r)];default:return r=Pe(r,t.modifier,e),null===r?void 0:[j("color",r)]}}{let r=qe(t,e,["--text-color","--color"]);if(r)return[j("color",r)]}{let r=e.resolveWith(t.value.value,["--text"],["--line-height","--letter-spacing","--font-weight"]);if(r){let[n,o={}]=Array.isArray(r)?r:[r];if(t.modifier){let r="arbitrary"===t.modifier.kind?t.modifier.value:e.resolve(t.modifier.value,["--leading"]);if(!r&&Ee(t.modifier.value)){if(!e.resolve(null,["--spacing"]))return null;r=`--spacing(${t.modifier.value})`}if(!r&&"none"===t.modifier.value&&(r="1"),!r)return null;let o=[j("font-size",n)];return r&&o.push(j("line-height",r)),o}return"string"==typeof o?[j("font-size",n),j("line-height",o)]:[j("font-size",n),j("line-height",o["--line-height"]?`var(--tw-leading, ${o["--line-height"]})`:void 0),j("letter-spacing",o["--letter-spacing"]?`var(--tw-tracking, ${o["--letter-spacing"]})`:void 0),j("font-weight",o["--font-weight"]?`var(--tw-font-weight, ${o["--font-weight"]})`:void 0)]}}}}),r("text",()=>[{values:["current","inherit","transparent"],valueThemeKeys:["--text-color","--color"],modifiers:Array.from({length:21},(e,t)=>""+5*t)},{values:[],valueThemeKeys:["--text"],modifiers:[],modifierThemeKeys:["--leading"]}]);let $=()=>K([Me("--tw-text-shadow-color"),Me("--tw-text-shadow-alpha","100%","")]);n("text-shadow-initial",[$,["--tw-text-shadow-color","initial"]]),t.functional("text-shadow",t=>{let r;if(t.modifier&&("arbitrary"===t.modifier.kind?r=t.modifier.value:Ve(t.modifier.value)&&(r=`${t.modifier.value}%`)),!t.value){let t=e.get(["--text-shadow"]);return null===t?void 0:[$(),j("--tw-text-shadow-alpha",r),...Je("text-shadow",t,r,e=>`var(--tw-text-shadow-color, ${e})`)]}if("arbitrary"===t.value.kind){let n=t.value.value;return"color"===(t.value.dataType??me(n,["color"]))?(n=Pe(n,t.modifier,e),null===n?void 0:[$(),j("--tw-text-shadow-color",Be(n,"var(--tw-text-shadow-alpha)"))]):[$(),j("--tw-text-shadow-alpha",r),...Je("text-shadow",n,r,e=>`var(--tw-text-shadow-color, ${e})`)]}switch(t.value.value){case"none":return t.modifier?void 0:[$(),j("text-shadow","none")];case"inherit":return t.modifier?void 0:[$(),j("--tw-text-shadow-color","inherit")]}{let n=e.get([`--text-shadow-${t.value.value}`]);if(n)return[$(),j("--tw-text-shadow-alpha",r),...Je("text-shadow",n,r,e=>`var(--tw-text-shadow-color, ${e})`)]}{let r=qe(t,e,["--text-shadow-color","--color"]);if(r)return[$(),j("--tw-text-shadow-color",Be(r,"var(--tw-text-shadow-alpha)"))]}}),r("text-shadow",()=>[{values:["current","inherit","transparent"],valueThemeKeys:["--text-shadow-color","--color"],modifiers:Array.from({length:21},(e,t)=>""+5*t)},{values:["none"]},{valueThemeKeys:["--text-shadow"],modifiers:Array.from({length:21},(e,t)=>""+5*t),hasDefaultValue:null!==e.get(["--text-shadow"])}]);{let o=function(e){return`var(--tw-ring-inset,) 0 0 0 calc(${e} + var(--tw-ring-offset-width)) var(--tw-ring-color, ${c})`},i=function(e){return`inset 0 0 0 ${e} var(--tw-inset-ring-color, currentcolor)`},a=["var(--tw-inset-shadow)","var(--tw-inset-ring-shadow)","var(--tw-ring-offset-shadow)","var(--tw-ring-shadow)","var(--tw-shadow)"].join(", "),l="0 0 #0000",s=()=>K([Me("--tw-shadow",l),Me("--tw-shadow-color"),Me("--tw-shadow-alpha","100%",""),Me("--tw-inset-shadow",l),Me("--tw-inset-shadow-color"),Me("--tw-inset-shadow-alpha","100%",""),Me("--tw-ring-color"),Me("--tw-ring-shadow",l),Me("--tw-inset-ring-color"),Me("--tw-inset-ring-shadow",l),Me("--tw-ring-inset"),Me("--tw-ring-offset-width","0px",""),Me("--tw-ring-offset-color","#fff"),Me("--tw-ring-offset-shadow",l)]);n("shadow-initial",[s,["--tw-shadow-color","initial"]]),t.functional("shadow",t=>{let r;if(t.modifier&&("arbitrary"===t.modifier.kind?r=t.modifier.value:Ve(t.modifier.value)&&(r=`${t.modifier.value}%`)),!t.value){let t=e.get(["--shadow"]);return null===t?void 0:[s(),j("--tw-shadow-alpha",r),...Je("--tw-shadow",t,r,e=>`var(--tw-shadow-color, ${e})`),j("box-shadow",a)]}if("arbitrary"===t.value.kind){let n=t.value.value;return"color"===(t.value.dataType??me(n,["color"]))?(n=Pe(n,t.modifier,e),null===n?void 0:[s(),j("--tw-shadow-color",Be(n,"var(--tw-shadow-alpha)"))]):[s(),j("--tw-shadow-alpha",r),...Je("--tw-shadow",n,r,e=>`var(--tw-shadow-color, ${e})`),j("box-shadow",a)]}switch(t.value.value){case"none":return t.modifier?void 0:[s(),j("--tw-shadow",l),j("box-shadow",a)];case"inherit":return t.modifier?void 0:[s(),j("--tw-shadow-color","inherit")]}{let n=e.get([`--shadow-${t.value.value}`]);if(n)return[s(),j("--tw-shadow-alpha",r),...Je("--tw-shadow",n,r,e=>`var(--tw-shadow-color, ${e})`),j("box-shadow",a)]}{let r=qe(t,e,["--box-shadow-color","--color"]);if(r)return[s(),j("--tw-shadow-color",Be(r,"var(--tw-shadow-alpha)"))]}}),r("shadow",()=>[{values:["current","inherit","transparent"],valueThemeKeys:["--box-shadow-color","--color"],modifiers:Array.from({length:21},(e,t)=>""+5*t)},{values:["none"]},{valueThemeKeys:["--shadow"],modifiers:Array.from({length:21},(e,t)=>""+5*t),hasDefaultValue:null!==e.get(["--shadow"])}]),n("inset-shadow-initial",[s,["--tw-inset-shadow-color","initial"]]),t.functional("inset-shadow",t=>{let r;if(t.modifier&&("arbitrary"===t.modifier.kind?r=t.modifier.value:Ve(t.modifier.value)&&(r=`${t.modifier.value}%`)),!t.value){let t=e.get(["--inset-shadow"]);return null===t?void 0:[s(),j("--tw-inset-shadow-alpha",r),...Je("--tw-inset-shadow",t,r,e=>`var(--tw-inset-shadow-color, ${e})`),j("box-shadow",a)]}if("arbitrary"===t.value.kind){let n=t.value.value;return"color"===(t.value.dataType??me(n,["color"]))?(n=Pe(n,t.modifier,e),null===n?void 0:[s(),j("--tw-inset-shadow-color",Be(n,"var(--tw-inset-shadow-alpha)"))]):[s(),j("--tw-inset-shadow-alpha",r),...Je("--tw-inset-shadow",n,r,e=>`var(--tw-inset-shadow-color, ${e})`,"inset"),j("box-shadow",a)]}switch(t.value.value){case"none":return t.modifier?void 0:[s(),j("--tw-inset-shadow",`inset ${l}`),j("box-shadow",a)];case"inherit":return t.modifier?void 0:[s(),j("--tw-inset-shadow-color","inherit")]}{let n=e.get([`--inset-shadow-${t.value.value}`]);if(n)return[s(),j("--tw-inset-shadow-alpha",r),...Je("--tw-inset-shadow",n,r,e=>`var(--tw-inset-shadow-color, ${e})`),j("box-shadow",a)]}{let r=qe(t,e,["--box-shadow-color","--color"]);if(r)return[s(),j("--tw-inset-shadow-color",Be(r,"var(--tw-inset-shadow-alpha)"))]}}),r("inset-shadow",()=>[{values:["current","inherit","transparent"],valueThemeKeys:["--box-shadow-color","--color"],modifiers:Array.from({length:21},(e,t)=>""+5*t)},{values:["none"]},{valueThemeKeys:["--inset-shadow"],modifiers:Array.from({length:21},(e,t)=>""+5*t),hasDefaultValue:null!==e.get(["--inset-shadow"])}]),n("ring-inset",[s,["--tw-ring-inset","inset"]]);let c=e.get(["--default-ring-color"])??"currentcolor";t.functional("ring",t=>{if(!t.value){if(t.modifier)return;let r=e.get(["--default-ring-width"])??"1px";return[s(),j("--tw-ring-shadow",o(r)),j("box-shadow",a)]}if("arbitrary"===t.value.kind){let r=t.value.value;return"length"===(t.value.dataType??me(r,["color","length"]))?t.modifier?void 0:[s(),j("--tw-ring-shadow",o(r)),j("box-shadow",a)]:(r=Pe(r,t.modifier,e),null===r?void 0:[j("--tw-ring-color",r)])}{let r=qe(t,e,["--ring-color","--color"]);if(r)return[j("--tw-ring-color",r)]}{if(t.modifier)return;let r=e.resolve(t.value.value,["--ring-width"]);if(null===r&&Ve(t.value.value)&&(r=`${t.value.value}px`),r)return[s(),j("--tw-ring-shadow",o(r)),j("box-shadow",a)]}}),r("ring",()=>[{values:["current","inherit","transparent"],valueThemeKeys:["--ring-color","--color"],modifiers:Array.from({length:21},(e,t)=>""+5*t)},{values:["0","1","2","4","8"],valueThemeKeys:["--ring-width"],hasDefaultValue:!0}]),t.functional("inset-ring",t=>{if(!t.value)return t.modifier?void 0:[s(),j("--tw-inset-ring-shadow",i("1px")),j("box-shadow",a)];if("arbitrary"===t.value.kind){let r=t.value.value;return"length"===(t.value.dataType??me(r,["color","length"]))?t.modifier?void 0:[s(),j("--tw-inset-ring-shadow",i(r)),j("box-shadow",a)]:(r=Pe(r,t.modifier,e),null===r?void 0:[j("--tw-inset-ring-color",r)])}{let r=qe(t,e,["--ring-color","--color"]);if(r)return[j("--tw-inset-ring-color",r)]}{if(t.modifier)return;let r=e.resolve(t.value.value,["--ring-width"]);if(null===r&&Ve(t.value.value)&&(r=`${t.value.value}px`),r)return[s(),j("--tw-inset-ring-shadow",i(r)),j("box-shadow",a)]}}),r("inset-ring",()=>[{values:["current","inherit","transparent"],valueThemeKeys:["--ring-color","--color"],modifiers:Array.from({length:21},(e,t)=>""+5*t)},{values:["0","1","2","4","8"],valueThemeKeys:["--ring-width"],hasDefaultValue:!0}]);let u="var(--tw-ring-inset,) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)";t.functional("ring-offset",t=>{if(t.value){if("arbitrary"===t.value.kind){let r=t.value.value;return"length"===(t.value.dataType??me(r,["color","length"]))?t.modifier?void 0:[j("--tw-ring-offset-width",r),j("--tw-ring-offset-shadow",u)]:(r=Pe(r,t.modifier,e),null===r?void 0:[j("--tw-ring-offset-color",r)])}{let r=e.resolve(t.value.value,["--ring-offset-width"]);if(r)return t.modifier?void 0:[j("--tw-ring-offset-width",r),j("--tw-ring-offset-shadow",u)];if(Ve(t.value.value))return t.modifier?void 0:[j("--tw-ring-offset-width",`${t.value.value}px`),j("--tw-ring-offset-shadow",u)]}{let r=qe(t,e,["--ring-offset-color","--color"]);if(r)return[j("--tw-ring-offset-color",r)]}}})}return r("ring-offset",()=>[{values:["current","inherit","transparent"],valueThemeKeys:["--ring-offset-color","--color"],modifiers:Array.from({length:21},(e,t)=>""+5*t)},{values:["0","1","2","4","8"],valueThemeKeys:["--ring-offset-width"]}]),t.functional("@container",e=>{let t=null;if(null===e.value?t="inline-size":"arbitrary"===e.value.kind?t=e.value.value:"named"===e.value.kind&&"normal"===e.value.value?t="normal":"named"===e.value.kind&&"size"===e.value.value&&(t="size"),null!==t)return e.modifier?[j("container-type",t),j("container-name",e.modifier.value)]:[j("container-type",t)]}),r("@container",()=>[{values:["normal"],valueThemeKeys:[],hasDefaultValue:!0}]),t}(e),n=function(e){let t=new gt;function r(e,r,{compounds:n}={}){n=n??vt(r),t.static(e,e=>{e.nodes=r.map(t=>C(t,e.nodes))},{compounds:n})}function n(e,t){return t.map(t=>{if("@container"===e){let e=v(t.trim());return e.length>=1&&"function"===e[0].kind?`not ${t}`:e.length>=3&&"word"===e[0].kind&&"not"===e[0].value&&"function"===e[2].kind?(e.splice(0,2),g(e)):e.length>=5&&"word"===e[0].kind&&"word"===e[2].kind&&"not"===e[2].value&&"function"===e[4].kind?(e.splice(2,2),g(e)):e.length>=3&&"word"===e[0].kind&&"not"!==e[0].value&&"function"===e[2].kind?(e.splice(1,0,{kind:"separator",value:" "},{kind:"word",value:"not"}),g(e)):`not ${t}`}{let e=Z(t=t.trim()," ");return"not"===e[0]?e.slice(1).join(" "):`not ${t}`}})}r("*",[":is(& > *)"],{compounds:0}),r("**",[":is(& *)"],{compounds:0});let o=["@media","@supports","@container"];function i(e){for(let t of o){if(t!==e.name)continue;let r=Z(e.params,",");return r.length>1?null:(r=n(e.name,r),S(e.name,r.join(", ")))}return null}function a(e){return e.includes("::")?null:`&:not(${Z(e,",").map(e=>e.replaceAll("&","*")).join(", ")})`}t.compound("not",3,(e,t)=>{if("arbitrary"===t.variant.kind&&t.variant.relative||t.modifier)return null;let r=!1;return y([e],(t,n)=>{if("rule"!==t.kind&&"at-rule"!==t.kind)return b.Continue;if(t.nodes.length>0)return b.Continue;let o=[],l=[],s=n.path();s.push(t);for(let e of s)"at-rule"===e.kind?o.push(e):"rule"===e.kind&&l.push(e);if(o.length>1)return b.Stop;if(l.length>1)return b.Stop;let c=[];for(let e of l){let t=a(e.selector);if(!t)return r=!1,b.Stop;c.push(A(t,[]))}for(let e of o){let t=i(e);if(!t)return r=!1,b.Stop;c.push(t)}return Object.assign(e,A("&",c)),r=!0,b.Skip}),"rule"===e.kind&&"&"===e.selector&&1===e.nodes.length&&Object.assign(e,e.nodes[0]),r?void 0:null}),t.suggest("not",()=>Array.from(t.keys()).filter(e=>t.compoundsWith("not",e))),t.compound("group",2,(t,r)=>{if("arbitrary"===r.variant.kind&&r.variant.relative)return null;let n=r.modifier?`:where(.${e.prefix?`${e.prefix}\\:`:""}group\\/${r.modifier.value})`:`:where(.${e.prefix?`${e.prefix}\\:`:""}group)`,o=!1;return y([t],(e,t)=>{if("rule"!==e.kind)return b.Continue;for(let e of t.path())if("rule"===e.kind)return o=!1,b.Stop;let r=e.selector.replaceAll("&",n);Z(r,",").length>1&&(r=`:is(${r})`),e.selector=`&:is(${r} *)`,o=!0}),o?void 0:null}),t.suggest("group",()=>Array.from(t.keys()).filter(e=>t.compoundsWith("group",e))),t.compound("peer",2,(t,r)=>{if("arbitrary"===r.variant.kind&&r.variant.relative)return null;let n=r.modifier?`:where(.${e.prefix?`${e.prefix}\\:`:""}peer\\/${r.modifier.value})`:`:where(.${e.prefix?`${e.prefix}\\:`:""}peer)`,o=!1;return y([t],(e,t)=>{if("rule"!==e.kind)return b.Continue;for(let e of t.path())if("rule"===e.kind)return o=!1,b.Stop;let r=e.selector.replaceAll("&",n);Z(r,",").length>1&&(r=`:is(${r})`),e.selector=`&:is(${r} ~ *)`,o=!0}),o?void 0:null}),t.suggest("peer",()=>Array.from(t.keys()).filter(e=>t.compoundsWith("peer",e))),r("first-letter",["&::first-letter"]),r("first-line",["&::first-line"]),r("marker",["& *::marker","&::marker","& *::-webkit-details-marker","&::-webkit-details-marker"]),r("selection",["& *::selection","&::selection"]),r("file",["&::file-selector-button"]),r("placeholder",["&::placeholder"]),r("backdrop",["&::backdrop"]),r("details-content",["&::details-content"]);{let e=function(){return K([S("@property","--tw-content",[j("syntax",'"*"'),j("initial-value",'""'),j("inherits","false")])])};t.static("before",t=>{t.nodes=[A("&::before",[e(),j("content","var(--tw-content)"),...t.nodes])]},{compounds:0}),t.static("after",t=>{t.nodes=[A("&::after",[e(),j("content","var(--tw-content)"),...t.nodes])]},{compounds:0})}r("first",["&:first-child"]),r("last",["&:last-child"]),r("only",["&:only-child"]),r("odd",["&:nth-child(odd)"]),r("even",["&:nth-child(even)"]),r("first-of-type",["&:first-of-type"]),r("last-of-type",["&:last-of-type"]),r("only-of-type",["&:only-of-type"]),r("visited",["&:visited"]),r("target",["&:target"]),r("open",["&:is([open], :popover-open, :open)"]),r("default",["&:default"]),r("checked",["&:checked"]),r("indeterminate",["&:indeterminate"]),r("placeholder-shown",["&:placeholder-shown"]),r("autofill",["&:autofill"]),r("optional",["&:optional"]),r("required",["&:required"]),r("valid",["&:valid"]),r("invalid",["&:invalid"]),r("user-valid",["&:user-valid"]),r("user-invalid",["&:user-invalid"]),r("in-range",["&:in-range"]),r("out-of-range",["&:out-of-range"]),r("read-only",["&:read-only"]),r("empty",["&:empty"]),r("focus-within",["&:focus-within"]),t.static("hover",e=>{e.nodes=[A("&:hover",[S("@media","(hover: hover)",e.nodes)])]}),r("focus",["&:focus"]),r("focus-visible",["&:focus-visible"]),r("active",["&:active"]),r("enabled",["&:enabled"]),r("disabled",["&:disabled"]),r("inert",["&:is([inert], [inert] *)"]),t.compound("in",2,(e,t)=>{if(t.modifier)return null;let r=!1;return y([e],(e,t)=>{if("rule"!==e.kind)return b.Continue;for(let e of t.path())if("rule"===e.kind)return r=!1,b.Stop;e.selector=`:where(${e.selector.replaceAll("&","*")}) &`,r=!0}),r?void 0:null}),t.suggest("in",()=>Array.from(t.keys()).filter(e=>t.compoundsWith("in",e))),t.compound("has",2,(e,t)=>{if(t.modifier)return null;let r=!1;return y([e],(e,t)=>{if("rule"!==e.kind)return b.Continue;for(let e of t.path())if("rule"===e.kind)return r=!1,b.Stop;e.selector=`&:has(${e.selector.replaceAll("&","*")})`,r=!0}),r?void 0:null}),t.suggest("has",()=>Array.from(t.keys()).filter(e=>t.compoundsWith("has",e))),t.functional("aria",(e,t)=>{if(!t.value||t.modifier)return null;"arbitrary"===t.value.kind?e.nodes=[A(`&[aria-${kt(t.value.value)}]`,e.nodes)]:e.nodes=[A(`&[aria-${t.value.value}="true"]`,e.nodes)]}),t.suggest("aria",()=>["busy","checked","disabled","expanded","hidden","pressed","readonly","required","selected"]),t.functional("data",(e,t)=>{if(!t.value||t.modifier)return null;e.nodes=[A(`&[data-${kt(t.value.value)}]`,e.nodes)]}),t.functional("nth",(e,t)=>{if(!t.value||t.modifier||"named"===t.value.kind&&!Ve(t.value.value))return null;e.nodes=[A(`&:nth-child(${t.value.value})`,e.nodes)]}),t.functional("nth-last",(e,t)=>{if(!t.value||t.modifier||"named"===t.value.kind&&!Ve(t.value.value))return null;e.nodes=[A(`&:nth-last-child(${t.value.value})`,e.nodes)]}),t.functional("nth-of-type",(e,t)=>{if(!t.value||t.modifier||"named"===t.value.kind&&!Ve(t.value.value))return null;e.nodes=[A(`&:nth-of-type(${t.value.value})`,e.nodes)]}),t.functional("nth-last-of-type",(e,t)=>{if(!t.value||t.modifier||"named"===t.value.kind&&!Ve(t.value.value))return null;e.nodes=[A(`&:nth-last-of-type(${t.value.value})`,e.nodes)]}),t.functional("supports",(e,t)=>{if(!t.value||t.modifier)return null;let r=t.value.value;if(null===r)return null;if(/^[\w-]*\s*\(/.test(r)){let t=r.replace(/\b(and|or|not)\b/g," $1 ");return void(e.nodes=[S("@supports",t,e.nodes)])}r.includes(":")||(r=`${r}: var(--tw)`),("("!==r[0]||")"!==r[r.length-1])&&(r=`(${r})`),e.nodes=[S("@supports",r,e.nodes)]},{compounds:1}),r("motion-safe",["@media (prefers-reduced-motion: no-preference)"]),r("motion-reduce",["@media (prefers-reduced-motion: reduce)"]),r("contrast-more",["@media (prefers-contrast: more)"]),r("contrast-less",["@media (prefers-contrast: less)"]);{let r=function(e,t,r,n){if(e===t)return 0;let o=n.get(e);if(null===o)return"asc"===r?-1:1;let i=n.get(t);return null===i?"asc"===r?1:-1:ce(o,i,r)};{let n=e.namespace("--breakpoint"),o=new f(t=>{switch(t.kind){case"static":return e.resolveValue(t.root,["--breakpoint"])??null;case"functional":{if(!t.value||t.modifier)return null;let r=null;return"arbitrary"===t.value.kind?r=t.value.value:"named"===t.value.kind&&(r=e.resolveValue(t.value.value,["--breakpoint"])),!r||r.includes("var(")?null:r}case"arbitrary":case"compound":return null}});t.group(()=>{t.functional("max",(e,t)=>{if(t.modifier)return null;let r=o.get(t);if(null===r)return null;e.nodes=[S("@media",`(width < ${r})`,e.nodes)]},{compounds:1})},(e,t)=>r(e,t,"desc",o)),t.suggest("max",()=>Array.from(n.keys()).filter(e=>null!==e)),t.group(()=>{for(let[r,n]of e.namespace("--breakpoint"))null!==r&&t.static(r,e=>{e.nodes=[S("@media",`(width >= ${n})`,e.nodes)]},{compounds:1});t.functional("min",(e,t)=>{if(t.modifier)return null;let r=o.get(t);if(null===r)return null;e.nodes=[S("@media",`(width >= ${r})`,e.nodes)]},{compounds:1})},(e,t)=>r(e,t,"asc",o)),t.suggest("min",()=>Array.from(n.keys()).filter(e=>null!==e))}{let n=e.namespace("--container"),o=new f(t=>{switch(t.kind){case"functional":{if(null===t.value)return null;let r=null;return"arbitrary"===t.value.kind?r=t.value.value:"named"===t.value.kind&&(r=e.resolveValue(t.value.value,["--container"])),!r||r.includes("var(")?null:r}case"static":case"arbitrary":case"compound":return null}});t.group(()=>{t.functional("@max",(e,t)=>{let r=o.get(t);if(null===r)return null;e.nodes=[S("@container",t.modifier?`${t.modifier.value} (width < ${r})`:`(width < ${r})`,e.nodes)]},{compounds:1})},(e,t)=>r(e,t,"desc",o)),t.suggest("@max",()=>Array.from(n.keys()).filter(e=>null!==e)),t.group(()=>{t.functional("@",(e,t)=>{let r=o.get(t);if(null===r)return null;e.nodes=[S("@container",t.modifier?`${t.modifier.value} (width >= ${r})`:`(width >= ${r})`,e.nodes)]},{compounds:1}),t.functional("@min",(e,t)=>{let r=o.get(t);if(null===r)return null;e.nodes=[S("@container",t.modifier?`${t.modifier.value} (width >= ${r})`:`(width >= ${r})`,e.nodes)]},{compounds:1})},(e,t)=>r(e,t,"asc",o)),t.suggest("@min",()=>Array.from(n.keys()).filter(e=>null!==e)),t.suggest("@",()=>Array.from(n.keys()).filter(e=>null!==e))}}return r("portrait",["@media (orientation: portrait)"]),r("landscape",["@media (orientation: landscape)"]),r("ltr",['&:where(:dir(ltr), [dir="ltr"], [dir="ltr"] *)']),r("rtl",['&:where(:dir(rtl), [dir="rtl"], [dir="rtl"] *)']),r("dark",["@media (prefers-color-scheme: dark)"]),r("starting",["@starting-style"]),r("print",["@media print"]),r("forced-colors",["@media (forced-colors: active)"]),r("inverted-colors",["@media (inverted-colors: inverted)"]),r("pointer-none",["@media (pointer: none)"]),r("pointer-coarse",["@media (pointer: coarse)"]),r("pointer-fine",["@media (pointer: fine)"]),r("any-pointer-none",["@media (any-pointer: none)"]),r("any-pointer-coarse",["@media (any-pointer: coarse)"]),r("any-pointer-fine",["@media (any-pointer: fine)"]),r("noscript",["@media (scripting: none)"]),t}(e),o=new f(e=>function(e,t){if("["===e[0]&&"]"===e[e.length-1]){if("@"===e[1]&&e.includes("&"))return null;let t=M(e.slice(1,-1));if(!H(t)||0===t.length||0===t.trim().length)return null;let r=">"===t[0]||"+"===t[0]||"~"===t[0];return!r&&"@"!==t[0]&&!t.includes("&")&&(t=`&:is(${t})`),{kind:"arbitrary",selector:t,relative:r}}{let[r,n=null,o]=Z(e,"/");if(o)return null;let i=X(r,e=>t.variants.has(e));for(let[e,r]of i)switch(t.variants.kind(e)){case"static":return null!==r||null!==n?null:{kind:"static",root:e};case"functional":{let t=null===n?null:J(n);if(null!==n&&null===t)return null;if(null===r)return{kind:"functional",root:e,modifier:t,value:null};if("]"===r[r.length-1]){if("["!==r[0])continue;let n=M(r.slice(1,-1));return H(n)&&0!==n.length&&0!==n.trim().length?{kind:"functional",root:e,modifier:t,value:{kind:"arbitrary",value:n}}:null}if(")"===r[r.length-1]){if("("!==r[0])continue;let n=M(r.slice(1,-1));return H(n)&&0!==n.length&&0!==n.trim().length&&"-"===n[0]&&"-"===n[1]?{kind:"functional",root:e,modifier:t,value:{kind:"arbitrary",value:`var(${n})`}}:null}if(!G.test(r))continue;return{kind:"functional",root:e,modifier:t,value:{kind:"named",value:r}}}case"compound":{if(null===r)return null;n&&("not"===e||"has"===e||"in"===e)&&(r=`${r}/${n}`,n=null);let o=t.parseVariant(r);if(null===o||!t.variants.compoundsWith(e,o))return null;let i=null===n?null:J(n);return null!==n&&null===i?null:{kind:"compound",root:e,modifier:i,variant:o}}}}return null}(e,u)),i=new f(e=>Array.from(function*(e,t){let r=Z(e,":");if(t.theme.prefix){if(1===r.length||r[0]!==t.theme.prefix)return null;r.shift()}let n=r.pop(),o=[];for(let e=r.length-1;e>=0;--e){let n=t.parseVariant(r[e]);if(null===n)return;o.push(n)}let i=!1;"!"===n[n.length-1]?(i=!0,n=n.slice(0,-1)):"!"===n[0]&&(i=!0,n=n.slice(1)),t.utilities.has(n,"static")&&!n.includes("[")&&(yield{kind:"static",root:n,variants:o,important:i,raw:e});let[a,l=null,s]=Z(n,"/");if(s)return;let c,u=null===l?null:J(l);if(null===l||null!==u){if("["===a[0]){if("]"!==a[a.length-1])return;let t=a.charCodeAt(1);if(45!==t&&!(t>=97&&t<=122))return;a=a.slice(1,-1);let r=a.indexOf(":");if(-1===r||0===r||r===a.length-1)return;let n=a.slice(0,r),l=M(a.slice(r+1));if(!H(l))return;return void(yield{kind:"arbitrary",property:n,value:l,modifier:u,variants:o,important:i,raw:e})}if("]"===a[a.length-1]){let e=a.indexOf("-[");if(-1===e)return;let r=a.slice(0,e);if(!t.utilities.has(r,"functional"))return;c=[[r,a.slice(e+1)]]}else if(")"===a[a.length-1]){let e=a.indexOf("-(");if(-1===e)return;let r=a.slice(0,e);if(!t.utilities.has(r,"functional"))return;let n=a.slice(e+2,-1),o=Z(n,":"),i=null;if(2===o.length&&(i=o[0],n=o[1]),"-"!==n[0]||"-"!==n[1]||!H(n))return;c=[[r,null===i?`[var(${n})]`:`[${i}:var(${n})]`]]}else c=X(a,e=>t.utilities.has(e,"functional"));for(let[t,r]of c){let n={kind:"functional",root:t,modifier:u,value:null,variants:o,important:i,raw:e};if(null!==r){{let e=r.indexOf("[");if(-1!==e){if("]"!==r[r.length-1])return;let t=M(r.slice(e+1,-1));if(!H(t))continue;let o=null;for(let e=0;e=97&&r<=122))break}if(0===t.length||0===t.trim().length||""===o)continue;n.value={kind:"arbitrary",dataType:o||null,value:t}}else{let e=null===l||"arbitrary"===n.modifier?.kind?null:`${r}/${l}`;if(!G.test(r))continue;n.value={kind:"named",value:r,fraction:e}}}yield n}else yield n}}}(e,u))),a=new f(e=>new f(t=>{let r=function(e,t,r){let n=function(e,t){if("arbitrary"===e.kind){let r=e.value;return e.modifier&&(r=Pe(r,e.modifier,t.theme)),null===r?[]:[[j(e.property,r)]]}let r=t.utilities.get(e.root)??[],n=[],o=r.filter(e=>!At(e));for(let t of o){if(t.kind!==e.kind)continue;let r=t.compileFn(e);if(void 0!==r){if(null===r){if(t.options?.types?.length)return n;continue}n.push(r)}}if(n.length>0)return n;let i=r.filter(e=>At(e));for(let t of i){if(t.kind!==e.kind)continue;let r=t.compileFn(e);if(void 0!==r){if(null===r){if(t.options?.types?.length)return n;continue}n.push(r)}}return n}(e,t);if(0===n.length)return[];let o=t.important&&!!(1&r),i=[],a=`.${l(e.raw)}`;for(let r of n){let n=Ct(r);(e.important||o)&&St(r);let l={kind:"rule",selector:a,nodes:r};for(let r of e.variants)if(null===zt(l,r,t.variants))return[];i.push({node:l,propertySort:n})}return i}(t,u,e);try{pt(r.map(({node:e})=>e),u),bt(r.map(({node:e})=>e),u)}catch{return[]}return r})),s=new f(t=>{for(let r of $(t))e.markUsedVariable(r)});function c(e){let r=[];for(let n of e){let e=!0,{astNodes:o}=$t([n],u,{onInvalidCandidate(){e=!1}});t&&y(o,e=>(e.src??=t,b.Continue)),o=O(o,u,0),r.push(e?o:[])}return r}let u={theme:e,utilities:r,variants:n,invalidCandidates:new Set,important:!1,candidatesToCss:function(e){return c(e).map(e=>e.length>0?F(e):null)},candidatesToAst:c,getClassOrder(e){return function(e,t){let{astNodes:r,nodeSorting:n}=$t(Array.from(t),e),o=new Map(t.map(e=>[e,null])),i=0n;for(let e of r){let t=n.get(e)?.candidate;t&&o.set(t,o.get(t)??i++)}return t.map(e=>[e,o.get(e)??null])}(this,e)},getClassList:()=>[],getVariants:()=>[],parseCandidate:e=>i.get(e),parseVariant:e=>o.get(e),compileAstNodes:(e,t=1)=>a.get(t).get(e),printCandidate:e=>function(e,t){let r=[];for(let e of t.variants)r.unshift(ee(e));e.theme.prefix&&r.unshift(e.theme.prefix);let n="";if("static"===t.kind&&(n+=t.root),"functional"===t.kind&&(n+=t.root,t.value))if("arbitrary"===t.value.kind){if(null!==t.value){let e=ae(t.value.value),r=e?t.value.value.slice(4,-1):t.value.value,[o,i]=e?["(",")"]:["[","]"];t.value.dataType?n+=`-${o}${t.value.dataType}:${re(r)}${i}`:n+=`-${o}${re(r)}${i}`}}else"named"===t.value.kind&&(n+=`-${t.value.value}`);return"arbitrary"===t.kind&&(n+=`[${t.property}:${re(t.value)}]`),("arbitrary"===t.kind||"functional"===t.kind)&&(n+=Q(t.modifier)),t.important&&(n+="!"),r.push(n),r.join(":")}(u,e),printVariant:e=>ee(e),getVariantOrder(){let e=Array.from(o.values());e.sort((e,t)=>this.variants.compare(e,t));let t,r=new Map,n=0;for(let o of e)null!==o&&(void 0!==t&&0!==this.variants.compare(t,o)&&n++,r.set(o,n),t=o);return r},resolveThemeValue(t,r=!0){let n=t.lastIndexOf("/"),o=null;-1!==n&&(o=t.slice(n+1).trim(),t=t.slice(0,n).trim());let i=e.resolve(null,[t],r?1:0)??void 0;return o&&i?Be(i,o):i},trackUsedVariables(e){s.get(e)},canonicalizeCandidates:(e,t)=>[],storage:{}};return u}var xt=["container-type","pointer-events","visibility","position","inset","inset-inline","inset-block","inset-inline-start","inset-inline-end","inset-block-start","inset-block-end","top","right","bottom","left","isolation","z-index","order","grid-column","grid-column-start","grid-column-end","grid-row","grid-row-start","grid-row-end","float","clear","--tw-container-component","margin","margin-inline","margin-block","margin-inline-start","margin-inline-end","margin-block-start","margin-block-end","margin-top","margin-right","margin-bottom","margin-left","box-sizing","display","field-sizing","aspect-ratio","height","max-height","min-height","width","max-width","min-width","flex","flex-shrink","flex-grow","flex-basis","table-layout","caption-side","border-collapse","border-spacing","transform-origin","translate","--tw-translate-x","--tw-translate-y","--tw-translate-z","scale","--tw-scale-x","--tw-scale-y","--tw-scale-z","rotate","--tw-rotate-x","--tw-rotate-y","--tw-rotate-z","--tw-skew-x","--tw-skew-y","transform","zoom","animation","cursor","touch-action","--tw-pan-x","--tw-pan-y","--tw-pinch-zoom","resize","scroll-snap-type","--tw-scroll-snap-strictness","scroll-snap-align","scroll-snap-stop","scroll-margin","scroll-margin-inline","scroll-margin-block","scroll-margin-inline-start","scroll-margin-inline-end","scroll-margin-block-start","scroll-margin-block-end","scroll-margin-top","scroll-margin-right","scroll-margin-bottom","scroll-margin-left","scroll-padding","scroll-padding-inline","scroll-padding-block","scroll-padding-inline-start","scroll-padding-inline-end","scroll-padding-block-start","scroll-padding-block-end","scroll-padding-top","scroll-padding-right","scroll-padding-bottom","scroll-padding-left","scrollbar-width","scrollbar-color","scrollbar-gutter","list-style-position","list-style-type","list-style-image","appearance","columns","break-before","break-inside","break-after","grid-auto-columns","grid-auto-flow","grid-auto-rows","grid-template-columns","grid-template-rows","flex-direction","flex-wrap","place-content","place-items","align-content","align-items","justify-content","justify-items","gap","column-gap","row-gap","--tw-space-x-reverse","--tw-space-y-reverse","divide-x-width","divide-y-width","--tw-divide-y-reverse","divide-style","divide-color","place-self","align-self","justify-self","overflow","overflow-x","overflow-y","overscroll-behavior","overscroll-behavior-x","overscroll-behavior-y","scroll-behavior","border-radius","border-start-radius","border-end-radius","border-top-radius","border-right-radius","border-bottom-radius","border-left-radius","border-start-start-radius","border-start-end-radius","border-end-end-radius","border-end-start-radius","border-top-left-radius","border-top-right-radius","border-bottom-right-radius","border-bottom-left-radius","border-width","border-inline-width","border-block-width","border-inline-start-width","border-inline-end-width","border-block-start-width","border-block-end-width","border-top-width","border-right-width","border-bottom-width","border-left-width","border-style","border-inline-style","border-block-style","border-inline-start-style","border-inline-end-style","border-block-start-style","border-block-end-style","border-top-style","border-right-style","border-bottom-style","border-left-style","border-color","border-inline-color","border-block-color","border-inline-start-color","border-inline-end-color","border-block-start-color","border-block-end-color","border-top-color","border-right-color","border-bottom-color","border-left-color","background-color","background-image","--tw-gradient-position","--tw-gradient-stops","--tw-gradient-via-stops","--tw-gradient-from","--tw-gradient-from-position","--tw-gradient-via","--tw-gradient-via-position","--tw-gradient-to","--tw-gradient-to-position","mask-image","--tw-mask-top","--tw-mask-top-from-color","--tw-mask-top-from-position","--tw-mask-top-to-color","--tw-mask-top-to-position","--tw-mask-right","--tw-mask-right-from-color","--tw-mask-right-from-position","--tw-mask-right-to-color","--tw-mask-right-to-position","--tw-mask-bottom","--tw-mask-bottom-from-color","--tw-mask-bottom-from-position","--tw-mask-bottom-to-color","--tw-mask-bottom-to-position","--tw-mask-left","--tw-mask-left-from-color","--tw-mask-left-from-position","--tw-mask-left-to-color","--tw-mask-left-to-position","--tw-mask-linear","--tw-mask-linear-position","--tw-mask-linear-from-color","--tw-mask-linear-from-position","--tw-mask-linear-to-color","--tw-mask-linear-to-position","--tw-mask-radial","--tw-mask-radial-shape","--tw-mask-radial-size","--tw-mask-radial-position","--tw-mask-radial-from-color","--tw-mask-radial-from-position","--tw-mask-radial-to-color","--tw-mask-radial-to-position","--tw-mask-conic","--tw-mask-conic-position","--tw-mask-conic-from-color","--tw-mask-conic-from-position","--tw-mask-conic-to-color","--tw-mask-conic-to-position","box-decoration-break","background-size","background-attachment","background-clip","background-position","background-repeat","background-origin","mask-composite","mask-mode","mask-type","mask-size","mask-clip","mask-position","mask-repeat","mask-origin","fill","stroke","stroke-width","object-fit","object-position","padding","padding-inline","padding-block","padding-inline-start","padding-inline-end","padding-block-start","padding-block-end","padding-top","padding-right","padding-bottom","padding-left","text-align","text-indent","vertical-align","font-family","font-feature-settings","font-size","line-height","font-weight","letter-spacing","text-wrap","overflow-wrap","word-break","text-overflow","hyphens","white-space","tab-size","color","text-transform","font-style","font-stretch","font-variant-numeric","text-decoration-line","text-decoration-color","text-decoration-style","text-decoration-thickness","text-underline-offset","-webkit-font-smoothing","placeholder-color","caret-color","accent-color","color-scheme","opacity","background-blend-mode","mix-blend-mode","box-shadow","--tw-shadow","--tw-shadow-color","--tw-ring-shadow","--tw-ring-color","--tw-inset-shadow","--tw-inset-shadow-color","--tw-inset-ring-shadow","--tw-inset-ring-color","--tw-ring-offset-width","--tw-ring-offset-color","outline","outline-width","outline-offset","outline-color","--tw-blur","--tw-brightness","--tw-contrast","--tw-drop-shadow","--tw-grayscale","--tw-hue-rotate","--tw-invert","--tw-saturate","--tw-sepia","filter","--tw-backdrop-blur","--tw-backdrop-brightness","--tw-backdrop-contrast","--tw-backdrop-grayscale","--tw-backdrop-hue-rotate","--tw-backdrop-invert","--tw-backdrop-opacity","--tw-backdrop-saturate","--tw-backdrop-sepia","backdrop-filter","transition-property","transition-behavior","transition-delay","transition-duration","transition-timing-function","will-change","contain","content","forced-color-adjust"];function $t(e,t,{onInvalidCandidate:r,respectImportant:n}={}){let o=new Map,i=[],a=new Map;for(let n of e){if(t.invalidCandidates.has(n)){r?.(n);continue}let e=t.parseCandidate(n);0!==e.length?a.set(n,e):r?.(n)}let l=0;(n??1)&&(l|=1);let s=t.getVariantOrder();for(let[e,n]of a){let a=!1;for(let r of n){let n=t.compileAstNodes(r,l);if(0!==n.length){a=!0;for(let{node:t,propertySort:a}of n){let n=0n;for(let e of r.variants)n|=1n<{let r=o.get(e),n=o.get(t);if(r.variants-n.variants!==0n)return Number(r.variants-n.variants);let i=0;for(;i=48&&n<=57&&o>=48&&o<=57){let i=r,a=r+1,l=r,s=r+1;for(n=e.charCodeAt(a);n>=48&&n<=57;)n=e.charCodeAt(++a);for(o=t.charCodeAt(s);o>=48&&o<=57;)o=t.charCodeAt(++s);let c=e.slice(i,a),u=t.slice(l,s),d=Number(c)-Number(u);if(d)return d;if(cu)return 1;continue}if(n!==o)return n-o}return e.length-t.length}(r.candidate,n.candidate)}),{astNodes:i,nodeSorting:o}}function zt(e,t,r,n=0){if("arbitrary"===t.kind)return t.relative&&0===n?null:void(e.nodes=[C(t.selector,e.nodes)]);let{applyFn:o}=r.get(t.root);if("compound"===t.kind){let i=S("@slot");if(null===zt(i,t.variant,r,n+1)||"not"===t.root&&i.nodes.length>1)return null;for(let e of i.nodes)if("rule"!==e.kind&&"at-rule"!==e.kind||null===o(e,t))return null;return y(i.nodes,t=>{if(("rule"===t.kind||"at-rule"===t.kind)&&t.nodes.length<=0)return t.nodes=e.nodes,b.Skip}),void(e.nodes=i.nodes)}return null===o(e,t)?null:void 0}function At(e){let t=e.options?.types??[];return t.length>1&&t.includes("any")}function St(e){for(let t of e)"at-root"!==t.kind&&("declaration"===t.kind?t.important=!0:("rule"===t.kind||"at-rule"===t.kind)&&St(t.nodes))}function Ct(e){let t=new Set,r=0,n=e.slice(),o=!1;for(;n.length>0;){let e=n.shift();if("declaration"===e.kind){if(void 0===e.value||(r++,o))continue;if("--tw-sort"===e.property){let r=xt.indexOf(e.value??"");if(-1!==r){t.add(r),o=!0;continue}}let n=xt.indexOf(e.property);-1!==n&&t.add(n)}else if("rule"===e.kind||"at-rule"===e.kind)for(let t of e.nodes)n.push(t)}return{order:Array.from(t).sort((e,t)=>e-t),count:r}}function jt(e,t){let r=0,n=C("&",e),o=new Set,i=new f(()=>new Set),a=new f(()=>new Set);y([n],(e,n)=>{if("at-rule"===e.kind){if("@keyframes"===e.name)return y(e.nodes,e=>{if("at-rule"===e.kind&&"@apply"===e.name)throw new Error("You cannot use `@apply` inside `@keyframes`.")}),b.Skip;if("@utility"===e.name){let r=e.params.replace(/-\*$/,"");return a.get(r).add(e),void y(e.nodes,r=>{if("at-rule"===r.kind&&"@apply"===r.name){o.add(e);for(let n of Tt(r,t))i.get(e).add(n)}})}if("@apply"===e.name){if(null===n.parent)return;r|=1,o.add(n.parent);for(let r of Tt(e,t))for(let e of n.path())o.has(e)&&i.get(e).add(r)}}});let l=new Set,s=[],c=new Set;function u(e,r=[]){if(!l.has(e)){if(c.has(e)){let n=r[(r.indexOf(e)+1)%r.length];throw"at-rule"===e.kind&&"@utility"===e.name&&"at-rule"===n.kind&&"@utility"===n.name&&y(e.nodes,e=>{if("at-rule"!==e.kind||"@apply"!==e.name)return;let r=e.params.split(/\s+/g);for(let e of r)for(let r of t.parseCandidate(e))switch(r.kind){case"arbitrary":break;case"static":case"functional":if(n.params.replace(/-\*$/,"")===r.root)throw new Error(`You cannot \`@apply\` the \`${e}\` utility here because it creates a circular dependency.`)}}),new Error(`Circular dependency detected:\n\n${F([e])}\nRelies on:\n\n${F([n])}`)}c.add(e);for(let t of i.get(e))for(let n of a.get(t))r.push(e),u(n,r),r.pop();l.add(e),c.delete(e),s.push(e)}}for(let e of o)u(e);for(let e of s)"nodes"in e&&y(e.nodes,e=>{if("at-rule"!==e.kind||"@apply"!==e.name)return;let r=e.params.split(/(\s+)/g),n={},o=[],i=[],a=0;for(let[e,t]of r.entries())e%2==0&&("-"===t[0]&&"-"===t[1]?i.push(t):o.push(t),n[t]=a),a+=t.length;if(i.length){if(0===o.length)return b.Skip;let e=i.join(" ");throw new Error(`You cannot use \`@apply\` with both mixins and utilities. Please move \`@apply ${e}\` into a separate rule.`)}if(e.nodes.length>0&&o.length){let e=o.join(" ");throw new Error(`The rule \`@apply ${e}\` must not have a body.`)}{let r=$t(Object.keys(n),t,{respectImportant:!1,onInvalidCandidate:e=>{if(t.theme.prefix&&!e.startsWith(t.theme.prefix))throw new Error(`Cannot apply unprefixed utility class \`${e}\`. Did you mean \`${t.theme.prefix}:${e}\`?`);if(t.invalidCandidates.has(e))throw new Error(`Cannot apply utility class \`${e}\` because it has been explicitly disabled: https://tailwindcss.com/docs/detecting-classes-in-source-files#explicitly-excluding-classes`);let r=Z(e,":");if(r.length>1){let n=r.pop();if(t.candidatesToCss([n])[0]){let n=t.candidatesToCss(r.map(e=>`${e}:[--tw-variant-check:1]`)),o=r.filter((e,t)=>null===n[t]);if(o.length>0){if(1===o.length)throw new Error(`Cannot apply utility class \`${e}\` because the ${o.map(e=>`\`${e}\``)} variant does not exist.`);{let t=new Intl.ListFormat("en",{style:"long",type:"conjunction"});throw new Error(`Cannot apply utility class \`${e}\` because the ${t.format(o.map(e=>`\`${e}\``))} variants do not exist.`)}}}}throw 0===t.theme.size?new Error(`Cannot apply unknown utility class \`${e}\`. Are you using CSS modules or similar and missing \`@reference\`? https://tailwindcss.com/docs/functions-and-directives#reference-directive`):new Error(`Cannot apply unknown utility class \`${e}\``)}}),o=e.src,i=r.astNodes.map(e=>{let t=r.nodeSorting.get(e)?.candidate,i=t?n[t]:void 0;if(e=E(e),!o||!t||void 0===i)return y([e],e=>{e.src=o}),e;let a=[o[0],o[1],o[2]];return a[1]+=7+i,a[2]=a[1]+t.length,y([e],e=>{e.src=a}),e}),a=[];for(let e of i)if("rule"===e.kind)for(let t of e.nodes)a.push(t);else a.push(e);return b.Replace(a)}});return r}function*Tt(e,t){for(let r of e.params.split(/\s+/g))for(let e of t.parseCandidate(r))switch(e.kind){case"arbitrary":break;case"static":case"functional":yield e.root}}async function Vt(e,t,r,o=0,i=!1){let a=0,l=[];return y(e,e=>{if("at-rule"===e.kind&&("@import"===e.name||"@reference"===e.name)){let s=function(e){let t,r=null,n=null,o=null;for(let i=0;i{if(o>100)throw new Error(`Exceeded maximum recursion depth while resolving \`${c}\` in \`${t}\`)`);let a=await r(c,t),l=n(a.content,{from:i?a.path:void 0});await Vt(l,a.base,r,o+1,i),p.nodes=function(e,t,r,n,o){let i=t;if(null!==r){let t=S("@layer",r,i);t.src=e.src,i=[t]}if(null!==n){let t=S("@media",n,i);t.src=e.src,i=[t]}if(null!==o){let t=S("@supports","("===o[0]?o:`(${o})`,i);t.src=e.src,i=[t]}return i}(e,[V({base:a.base},l)],u,d,f)})()),b.ReplaceSkip(p)}}),l.length>0&&await Promise.all(l),a}function Kt(e,t=null){return Array.isArray(e)&&2===e.length&&"object"==typeof e[1]&&null!==typeof e[1]?t?e[1][t]??null:e[0]:Array.isArray(e)&&null===t?e.join(", "):"string"==typeof e&&null===t?e:null}function Et(e,{theme:t},r){for(let t of r){let r=Ut([t]);r&&e.theme.clearNamespace(`--${r}`,4)}for(let[r,n]of function(e){let t=[];return Wt(e,[],(e,r)=>{if(function(e){return"number"==typeof e||"string"==typeof e}(e))return t.push([r,e]),1;if(function(e){if(!Array.isArray(e)||2!==e.length||"string"!=typeof e[0]&&"number"!=typeof e[0]||void 0===e[1]||null===e[1]||"object"!=typeof e[1])return!1;for(let t of Reflect.ownKeys(e[1]))if("string"!=typeof t||"string"!=typeof e[1][t]&&"number"!=typeof e[1][t])return!1;return!0}(e)){t.push([r,e[0]]);for(let n of Reflect.ownKeys(e[1]))t.push([[...r,`-${n}`],e[1][n]]);return 1}return Array.isArray(e)&&e.every(e=>"string"==typeof e)?("fontSize"===r[0]?(t.push([r,e[0]]),e.length>=2&&t.push([[...r,"-line-height"],e[1]])):t.push([r,e.join(", ")]),1):void 0}),t}(t)){if("string"!=typeof n&&"number"!=typeof n)continue;if("string"==typeof n&&(n=n.replace(//g,"1")),"opacity"===r[0]&&("number"==typeof n||"string"==typeof n)){let e="string"==typeof n?parseFloat(n):n;e>=0&&e<=1&&(n=100*e+"%")}let t=Ut(r);t&&e.theme.add(`--${t}`,""+n,7)}if(Object.hasOwn(t,"fontFamily")){let r=5;{let n=Kt(t.fontFamily.sans);n&&e.theme.hasDefault("--font-sans")&&(e.theme.add("--default-font-family",n,r),e.theme.add("--default-font-feature-settings",Kt(t.fontFamily.sans,"fontFeatureSettings")??"normal",r),e.theme.add("--default-font-variation-settings",Kt(t.fontFamily.sans,"fontVariationSettings")??"normal",r))}{let n=Kt(t.fontFamily.mono);n&&e.theme.hasDefault("--font-mono")&&(e.theme.add("--default-mono-font-family",n,r),e.theme.add("--default-mono-font-feature-settings",Kt(t.fontFamily.mono,"fontFeatureSettings")??"normal",r),e.theme.add("--default-mono-font-variation-settings",Kt(t.fontFamily.mono,"fontVariationSettings")??"normal",r))}}return t}var Nt={borderWidth:"border-width",outlineWidth:"outline-width",ringColor:"ring-color",ringWidth:"ring-width",transitionDuration:"transition-duration",transitionTimingFunction:"transition-timing-function"},Ot={animation:"animate",aspectRatio:"aspect",borderRadius:"radius",boxShadow:"shadow",colors:"color",containers:"container",fontFamily:"font",fontSize:"text",letterSpacing:"tracking",lineHeight:"leading",maxWidth:"container",screens:"breakpoint",transitionTimingFunction:"ease"},Ft=/^[a-zA-Z0-9-_%/.]+$/;function Ut(e){let t=Nt[e[0]];if(t&&"DEFAULT"===e[1])return`default-${t}`;if("container"===e[0])return null;for(let t of e)if(!Ft.test(t))return null;let r=Ot[e[0]];return r&&((e=e.slice())[0]=r),e.map((e,t,r)=>"1"===e&&t!==r.length-1?"":e).map((e,t)=>(e=e.replaceAll(".","_"),(0===t||e.startsWith("-")||"lineHeight"===e)&&(e=e.replace(/([a-z])([A-Z])/g,(e,t,r)=>`${t}-${r.toLowerCase()}`)),e)).filter((t,r)=>"DEFAULT"!==t||r!==e.length-1).join("-")}function Wt(e,t=[],r){for(let n of Reflect.ownKeys(e)){let o=e[n];if(null==o)continue;let i=[...t,n],a=r(o,i)??0;if(1!==a){if(2===a)return 2;if((Array.isArray(o)||"object"==typeof o)&&2===Wt(o,i,r))return 2}}}function Rt(e){return{kind:"combinator",value:e}}function Dt(e){return{kind:"complex",nodes:e}}function Lt(e){return{kind:"compound",nodes:e}}function _t(e,t){return{kind:"function",value:e,nodes:t}}function Mt(e){return{kind:"list",nodes:e}}function Bt(e){return{kind:"selector",value:e}}function It(e){return{kind:"value",value:e}}function Pt(e,t=!1){let r="";for(let n of e)switch(n.kind){case"selector":case"value":r+=n.value;break;case"combinator":t||" "===n.value?r+=n.value:r+=` ${n.value} `;break;case"function":r+=`${n.value}(${Pt(n.nodes,t)})`;break;case"complex":case"compound":r+=Pt(n.nodes,t);break;case"list":r+=n.nodes.map(e=>Pt([e],t)).join(t?",":", ")}return r}function qt(e){e=e.replaceAll("\r\n","\n");let t,r=[],n=r,o=!1,i=[],a=null,l="";function s(e=n){return 1===e.length?e[0]:o?Dt(e):Lt(e)}function c(e){let t=n[n.length-1];"compound"===t?.kind?t.nodes.push(e):t&&"list"!==t.kind&&"combinator"!==t.kind?n[n.length-1]=Lt([t,e]):n.push(e)}for(let u=0;u0&&(c(Bt(l)),l="");u+10&&(c(Bt(l)),l="");let r=u,i=u+1;for(;i=e.length||44===e.charCodeAt(i)))break;n.push(Rt(""===a?" ":a)),o=!0;break}case 40:{let r=_t(l,[]);if(l="",":not"!==r.value&&":where"!==r.value&&":has"!==r.value&&":is"!==r.value){let n=u+1,o=0;for(let r=u+1;r0&&(c(Bt(l)),l=""),a?a.nodes.push(s()):o&&n.splice(0,n.length,Dt(n.splice(0)));let e=i.pop();n=e?.target??r,a=e?.currentList??null,o=e?.containsCombinator??!1;break}case 46:case 58:case 35:if(58===d&&":"===l){l+=e[u];break}l.length>0&&c(Bt(l)),l=e[u];break;case 91:{l.length>0&&c(Bt(l)),l="";let r=u,n=0;for(let r=u+1;r0&&(c(Bt(l)),l=""),c(Bt(e[u]));break;case 92:l+=e[u]+e[u+1],u+=1;break;default:l+=e[u]}}return l.length>0&&c(Bt(l)),a?a.nodes.push(s()):o&&n.splice(0,n.length,Dt(n.splice(0))),r}function Ht(e){let t=[];for(let r of Z(e,".")){if(!r.includes("[")){t.push(r);continue}let e=0;for(;;){let n=r.indexOf("[",e),o=r.indexOf("]",n);if(-1===n||-1===o)break;n>e&&t.push(r.slice(e,n)),t.push(r.slice(n+1,o)),e=o+1}e<=r.length-1&&t.push(r.slice(e))}return t}function Yt(e){if("[object Object]"!==Object.prototype.toString.call(e))return!1;let t=Object.getPrototypeOf(e);return null===t||null===Object.getPrototypeOf(t)}function Zt(e,t,r,n=[]){for(let o of t)if(null!=o)for(let t of Reflect.ownKeys(o)){n.push(t);let i=r(e[t],o[t],n);void 0!==i?e[t]=i:Yt(e[t])&&Yt(o[t])?e[t]=Zt({},[e[t],o[t]],r,n):e[t]=o[t],n.pop()}return e}function Gt(e,t,r){return function(n,o){let i=n.lastIndexOf("/"),a=null;-1!==i&&(a=n.slice(i+1).trim(),n=n.slice(0,i).trim());let l=(()=>{let o=Ht(n),[i,a]=function(e,t){if(1===t.length&&t[0].startsWith("--"))return[e.get([t[0]]),e.getOptions(t[0])];let r=Ut(t),n=new Map,o=new f(()=>new Map),i=e.namespace(`--${r}`);if(0===i.size)return[null,0];let a=new Map;for(let[t,l]of i){if(!t||!t.includes("--")){n.set(t,l),a.set(t,e.getOptions(t?`--${r}-${t}`:`--${r}`));continue}let i=t.indexOf("--"),s=t.slice(0,i),c=t.slice(i+2);c=c.replace(/-([a-z])/g,(e,t)=>t.toUpperCase()),o.get(""===s?null:s).set(c,[l,e.getOptions(`--${r}${t}`)])}let l=e.getOptions(`--${r}`);for(let[e,t]of o){let r=n.get(e);if("string"!=typeof r)continue;let o={},i={};for(let[e,[r,n]]of t)o[e]=r,i[e]=n;n.set(e,[r,o]),a.set(e,[l,i])}let s={},c={};for(let[e,t]of n)Xt(s,[e??"DEFAULT"],t);for(let[e,t]of a)Xt(c,[e??"DEFAULT"],t);return"DEFAULT"===t[t.length-1]?[s?.DEFAULT??null,c.DEFAULT??0]:"DEFAULT"in s&&1===Object.keys(s).length?[s.DEFAULT,c.DEFAULT??0]:(s.__CSS_VALUES__=c,[s,c])}(e.theme,o),l=r(Jt(t()??{},o)??null);if("string"==typeof l&&(l=l.replace("","1")),"object"!=typeof i)return"object"!=typeof a&&4&a?l??i:i;if(null!==l&&"object"==typeof l&&!Array.isArray(l)){let e=Zt({},[l],(e,t)=>t);if(null===i&&Object.hasOwn(l,"__CSS_VALUES__")){let t={};for(let r in l.__CSS_VALUES__)t[r]=l[r],delete e[r];i=t}for(let t in i)"__CSS_VALUES__"!==t&&(4&l?.__CSS_VALUES__?.[t]&&void 0!==Jt(e,t.split("-"))||(e[s(t)]=i[t]));return e}if(Array.isArray(i)&&Array.isArray(a)&&Array.isArray(l)){let e=i[0],t=i[1];4&a[0]&&(e=l[0]??e);for(let e of Object.keys(t))4&a[1][e]&&(t[e]=l[1][e]??t[e]);return[e,t]}return i??l})();return a&&"string"==typeof l&&(l=Be(l,a)),l??o}}function Jt(e,t){for(let r=0;r{e.src=i}),t.push(l)},addVariant(t,r){if(!mt.test(t))throw new Error(`\`addVariant('${t}')\` defines an invalid variant name. Variants should only contain alphanumeric, dashes, or underscore characters and start with a lowercase letter or number.`);if("string"==typeof r){if(r.includes(":merge("))return}else if(Array.isArray(r)){if(r.some(e=>e.includes(":merge(")))return}else if("object"==typeof r){let e=function(t,r){return Object.entries(t).some(([t,n])=>t.includes(r)||"object"==typeof n&&e(n,r))};if(e(r,":merge("))return}"string"==typeof r||Array.isArray(r)?e.variants.static(t,e=>{e.nodes=rr(r,e.nodes)},{compounds:vt("string"==typeof r?[r]:r)}):"object"==typeof r&&e.variants.fromAst(t,tr(r),e)},matchVariant(t,r,n){function o(e,t,n){return rr(r(e,{modifier:t?.value??null}),n)}try{let e=r("a",{modifier:null});if("string"==typeof e&&e.includes(":merge("))return;if(Array.isArray(e)&&e.some(e=>e.includes(":merge(")))return}catch{}let i=Object.keys(n?.values??{});e.variants.group(()=>{e.variants.functional(t,(e,t)=>{if(!t.value)return n?.values&&"DEFAULT"in n.values?void(e.nodes=o(n.values.DEFAULT,t.modifier,e.nodes)):null;if("arbitrary"===t.value.kind)e.nodes=o(t.value.value,t.modifier,e.nodes);else{if("named"!==t.value.kind||!n?.values)return null;{if(!Object.hasOwn(n.values,t.value.value))return null;let r=n.values[t.value.value];if("string"!=typeof r)return null;e.nodes=o(r,t.modifier,e.nodes)}}})},(e,t)=>{if("functional"!==e.kind||"functional"!==t.kind)return 0;let r=e.value?e.value.value:"DEFAULT",o=t.value?t.value.value:"DEFAULT",a=(n?.values&&Object.hasOwn(n.values,r)?n.values[r]:void 0)??r,l=(n?.values&&Object.hasOwn(n.values,o)?n.values[o]:void 0)??o;if(n&&"function"==typeof n.sort)return n.sort({value:a,modifier:e.modifier?.value??null},{value:l,modifier:t.modifier?.value??null});let s=i.indexOf(r),c=i.indexOf(o);return s=-1===s?i.length:s,c=-1===c?i.length:c,s!==c?s-c:aObject.keys(n?.values??{}).filter(e=>"DEFAULT"!==e))},addUtilities(r){let a=(r=Array.isArray(r)?r:[r]).flatMap(e=>Object.entries(e));a=a.flatMap(([e,t])=>Z(e,",").map(e=>[e.trim(),t]));let l=new f(()=>[]);for(let[e,r]of a){if(e.startsWith("@keyframes ")){if(!o){let n=C(e,tr(r));y([n],e=>{e.src=i}),t.push(n)}continue}let n=qt(e),a=!1;if(y(n,e=>{if("selector"===e.kind&&"."===e.value[0]&&Qt.test(e.value.slice(1))){let t=e.value;e.value="&";let o=Pt(n),i=t.slice(1),s="&"===o?tr(r):[C(o,tr(r))];return l.get(i).push(...s),a=!0,void(e.value=t)}if("function"===e.kind&&":not"===e.value)return b.Skip}),!a)throw new Error(`\`addUtilities({ '${e}' : … })\` defines an invalid utility selector. Utilities must be a single class name and start with a lowercase letter, eg. \`.scrollbar-none\`.`)}for(let[t,r]of l)e.theme.prefix&&y(r,t=>{if("rule"===t.kind){let r=qt(t.selector);y(r,t=>{"selector"===t.kind&&"."===t.value[0]&&(t.value=`.${e.theme.prefix}\\:${t.value.slice(1)}`)}),t.selector=Pt(r)}}),e.utilities.static(t,o=>{let i=r.map(E);return nr(i,t,o.raw),n.current|=jt(i,e),i})},matchUtilities(t,r){let o=r?.type?Array.isArray(r?.type)?r.type:[r.type]:["any"];for(let[i,a]of Object.entries(t)){let t=function({negative:t}){return l=>{if("arbitrary"===l.value?.kind&&o.length>0&&!o.includes("any")&&(l.value.dataType&&!o.includes(l.value.dataType)||!l.value.dataType&&!me(l.value.value,o)))return;let s,c=o.includes("color"),u=null,d=!1;{let e=r?.values??{};c&&(e=Object.assign({inherit:"inherit",transparent:"transparent",current:"currentcolor"},e)),l.value?"arbitrary"===l.value.kind?u=l.value.value:l.value.fraction&&Object.hasOwn(e,l.value.fraction)?(u=e[l.value.fraction],d=!0):Object.hasOwn(e,l.value.value)?u=e[l.value.value]:e.__BARE_VALUE__&&(u=e.__BARE_VALUE__(l.value)??null,d=(null!==l.value.fraction&&u?.includes("/"))??!1):u=e.DEFAULT??null}if(null===u)return;{let e=r?.modifiers??null;s=l.modifier?"any"===e||"arbitrary"===l.modifier.kind?l.modifier.value:e&&Object.hasOwn(e,l.modifier.value)?e[l.modifier.value]:c&&!Number.isNaN(Number(l.modifier.value))?`${l.modifier.value}%`:null:null}if(l.modifier&&null===s&&!d)return"arbitrary"===l.value?.kind?null:void 0;c&&null!==s&&(u=Be(u,s)),t&&(u=`calc(${u} * -1)`);let f=tr(a(u,{modifier:s}));return nr(f,i,l.raw),n.current|=jt(f,e),f}};if(!Qt.test(i))throw new Error(`\`matchUtilities({ '${i}' : … })\` defines an invalid utility name. Utilities should be alphanumeric and start with a lowercase letter, eg. \`scrollbar\`.`);r?.supportsNegativeValues&&e.utilities.functional(`-${i}`,t({negative:!0}),{types:o}),e.utilities.functional(i,t({negative:!1}),{types:o}),e.utilities.suggest(i,()=>{let e=r?.values??{},t=new Set(Object.keys(e));t.delete("__BARE_VALUE__"),t.delete("__CSS_VALUES__"),t.has("DEFAULT")&&(t.delete("DEFAULT"),t.add(null));let n=r?.modifiers??{},o="any"===n?[]:Object.keys(n);return[{supportsNegative:r?.supportsNegativeValues??!1,values:Array.from(t),modifiers:o}]})}},addComponents(e,t){this.addUtilities(e,t)},matchComponents(e,t){this.matchUtilities(e,t)},theme:Gt(e,()=>r.theme??{},e=>e),prefix:e=>e,config(e,t){let n=r;if(!e)return n;let o=Ht(e);for(let e=0;eObject.entries(e));for(let[e,n]of r)if(null!=n&&!1!==n)if("object"!=typeof n){if(!e.startsWith("--")){if("@slot"===n){t.push(C(e,[S("@slot")]));continue}e=e.replace(/([A-Z])/g,"-$1").toLowerCase()}t.push(j(e,String(n)))}else if(Array.isArray(n))for(let r of n)"string"==typeof r?t.push(j(e,r)):t.push(C(e,tr(r)));else t.push(C(e,tr(n)));return t}function rr(e,t){return("string"==typeof e?[e]:e).flatMap(e=>{if(e.trim().endsWith("}")){let r=n(e.replace("}","{@slot}}"));return wt(r,t),r}return C(e,t)})}function nr(e,t,r){y(e,e=>{if("rule"===e.kind){let n=qt(e.selector);y(n,e=>{"selector"===e.kind&&e.value===`.${t}`&&(e.value=`.${l(r)}`)}),e.selector=Pt(n)}})}function or(e,t){for(let r of function(e){let t=[];if("keyframes"in e.theme)for(let[r,n]of Object.entries(e.theme.keyframes))t.push(S("@keyframes",r,tr(n)));return t}(t))e.theme.addKeyframes(r)}var ir={inherit:"inherit",current:"currentcolor",transparent:"transparent",black:"#000",white:"#fff",slate:{50:"oklch(98.4% 0.003 247.858)",100:"oklch(96.8% 0.007 247.896)",200:"oklch(92.9% 0.013 255.508)",300:"oklch(86.9% 0.022 252.894)",400:"oklch(70.4% 0.04 256.788)",500:"oklch(55.4% 0.046 257.417)",600:"oklch(44.6% 0.043 257.281)",700:"oklch(37.2% 0.044 257.287)",800:"oklch(27.9% 0.041 260.031)",900:"oklch(20.8% 0.042 265.755)",950:"oklch(12.9% 0.042 264.695)"},gray:{50:"oklch(98.5% 0.002 247.839)",100:"oklch(96.7% 0.003 264.542)",200:"oklch(92.8% 0.006 264.531)",300:"oklch(87.2% 0.01 258.338)",400:"oklch(70.7% 0.022 261.325)",500:"oklch(55.1% 0.027 264.364)",600:"oklch(44.6% 0.03 256.802)",700:"oklch(37.3% 0.034 259.733)",800:"oklch(27.8% 0.033 256.848)",900:"oklch(21% 0.034 264.665)",950:"oklch(13% 0.028 261.692)"},zinc:{50:"oklch(98.5% 0 0)",100:"oklch(96.7% 0.001 286.375)",200:"oklch(92% 0.004 286.32)",300:"oklch(87.1% 0.006 286.286)",400:"oklch(70.5% 0.015 286.067)",500:"oklch(55.2% 0.016 285.938)",600:"oklch(44.2% 0.017 285.786)",700:"oklch(37% 0.013 285.805)",800:"oklch(27.4% 0.006 286.033)",900:"oklch(21% 0.006 285.885)",950:"oklch(14.1% 0.005 285.823)"},neutral:{50:"oklch(98.5% 0 0)",100:"oklch(97% 0 0)",200:"oklch(92.2% 0 0)",300:"oklch(87% 0 0)",400:"oklch(70.8% 0 0)",500:"oklch(55.6% 0 0)",600:"oklch(43.9% 0 0)",700:"oklch(37.1% 0 0)",800:"oklch(26.9% 0 0)",900:"oklch(20.5% 0 0)",950:"oklch(14.5% 0 0)"},stone:{50:"oklch(98.5% 0.001 106.423)",100:"oklch(97% 0.001 106.424)",200:"oklch(92.3% 0.003 48.717)",300:"oklch(86.9% 0.005 56.366)",400:"oklch(70.9% 0.01 56.259)",500:"oklch(55.3% 0.013 58.071)",600:"oklch(44.4% 0.011 73.639)",700:"oklch(37.4% 0.01 67.558)",800:"oklch(26.8% 0.007 34.298)",900:"oklch(21.6% 0.006 56.043)",950:"oklch(14.7% 0.004 49.25)"},mauve:{50:"oklch(98.5% 0 0)",100:"oklch(96% 0.003 325.6)",200:"oklch(92.2% 0.005 325.62)",300:"oklch(86.5% 0.012 325.68)",400:"oklch(71.1% 0.019 323.02)",500:"oklch(54.2% 0.034 322.5)",600:"oklch(43.5% 0.029 321.78)",700:"oklch(36.4% 0.029 323.89)",800:"oklch(26.3% 0.024 320.12)",900:"oklch(21.2% 0.019 322.12)",950:"oklch(14.5% 0.008 326)"},olive:{50:"oklch(98.8% 0.003 106.5)",100:"oklch(96.6% 0.005 106.5)",200:"oklch(93% 0.007 106.5)",300:"oklch(88% 0.011 106.6)",400:"oklch(73.7% 0.021 106.9)",500:"oklch(58% 0.031 107.3)",600:"oklch(46.6% 0.025 107.3)",700:"oklch(39.4% 0.023 107.4)",800:"oklch(28.6% 0.016 107.4)",900:"oklch(22.8% 0.013 107.4)",950:"oklch(15.3% 0.006 107.1)"},mist:{50:"oklch(98.7% 0.002 197.1)",100:"oklch(96.3% 0.002 197.1)",200:"oklch(92.5% 0.005 214.3)",300:"oklch(87.2% 0.007 219.6)",400:"oklch(72.3% 0.014 214.4)",500:"oklch(56% 0.021 213.5)",600:"oklch(45% 0.017 213.2)",700:"oklch(37.8% 0.015 216)",800:"oklch(27.5% 0.011 216.9)",900:"oklch(21.8% 0.008 223.9)",950:"oklch(14.8% 0.004 228.8)"},taupe:{50:"oklch(98.6% 0.002 67.8)",100:"oklch(96% 0.002 17.2)",200:"oklch(92.2% 0.005 34.3)",300:"oklch(86.8% 0.007 39.5)",400:"oklch(71.4% 0.014 41.2)",500:"oklch(54.7% 0.021 43.1)",600:"oklch(43.8% 0.017 39.3)",700:"oklch(36.7% 0.016 35.7)",800:"oklch(26.8% 0.011 36.5)",900:"oklch(21.4% 0.009 43.1)",950:"oklch(14.7% 0.004 49.3)"},red:{50:"oklch(97.1% 0.013 17.38)",100:"oklch(93.6% 0.032 17.717)",200:"oklch(88.5% 0.062 18.334)",300:"oklch(80.8% 0.114 19.571)",400:"oklch(70.4% 0.191 22.216)",500:"oklch(63.7% 0.237 25.331)",600:"oklch(57.7% 0.245 27.325)",700:"oklch(50.5% 0.213 27.518)",800:"oklch(44.4% 0.177 26.899)",900:"oklch(39.6% 0.141 25.723)",950:"oklch(25.8% 0.092 26.042)"},orange:{50:"oklch(98% 0.016 73.684)",100:"oklch(95.4% 0.038 75.164)",200:"oklch(90.1% 0.076 70.697)",300:"oklch(83.7% 0.128 66.29)",400:"oklch(75% 0.183 55.934)",500:"oklch(70.5% 0.213 47.604)",600:"oklch(64.6% 0.222 41.116)",700:"oklch(55.3% 0.195 38.402)",800:"oklch(47% 0.157 37.304)",900:"oklch(40.8% 0.123 38.172)",950:"oklch(26.6% 0.079 36.259)"},amber:{50:"oklch(98.7% 0.022 95.277)",100:"oklch(96.2% 0.059 95.617)",200:"oklch(92.4% 0.12 95.746)",300:"oklch(87.9% 0.169 91.605)",400:"oklch(82.8% 0.189 84.429)",500:"oklch(76.9% 0.188 70.08)",600:"oklch(66.6% 0.179 58.318)",700:"oklch(55.5% 0.163 48.998)",800:"oklch(47.3% 0.137 46.201)",900:"oklch(41.4% 0.112 45.904)",950:"oklch(27.9% 0.077 45.635)"},yellow:{50:"oklch(98.7% 0.026 102.212)",100:"oklch(97.3% 0.071 103.193)",200:"oklch(94.5% 0.129 101.54)",300:"oklch(90.5% 0.182 98.111)",400:"oklch(85.2% 0.199 91.936)",500:"oklch(79.5% 0.184 86.047)",600:"oklch(68.1% 0.162 75.834)",700:"oklch(55.4% 0.135 66.442)",800:"oklch(47.6% 0.114 61.907)",900:"oklch(42.1% 0.095 57.708)",950:"oklch(28.6% 0.066 53.813)"},lime:{50:"oklch(98.6% 0.031 120.757)",100:"oklch(96.7% 0.067 122.328)",200:"oklch(93.8% 0.127 124.321)",300:"oklch(89.7% 0.196 126.665)",400:"oklch(84.1% 0.238 128.85)",500:"oklch(76.8% 0.233 130.85)",600:"oklch(64.8% 0.2 131.684)",700:"oklch(53.2% 0.157 131.589)",800:"oklch(45.3% 0.124 130.933)",900:"oklch(40.5% 0.101 131.063)",950:"oklch(27.4% 0.072 132.109)"},green:{50:"oklch(98.2% 0.018 155.826)",100:"oklch(96.2% 0.044 156.743)",200:"oklch(92.5% 0.084 155.995)",300:"oklch(87.1% 0.15 154.449)",400:"oklch(79.2% 0.209 151.711)",500:"oklch(72.3% 0.219 149.579)",600:"oklch(62.7% 0.194 149.214)",700:"oklch(52.7% 0.154 150.069)",800:"oklch(44.8% 0.119 151.328)",900:"oklch(39.3% 0.095 152.535)",950:"oklch(26.6% 0.065 152.934)"},emerald:{50:"oklch(97.9% 0.021 166.113)",100:"oklch(95% 0.052 163.051)",200:"oklch(90.5% 0.093 164.15)",300:"oklch(84.5% 0.143 164.978)",400:"oklch(76.5% 0.177 163.223)",500:"oklch(69.6% 0.17 162.48)",600:"oklch(59.6% 0.145 163.225)",700:"oklch(50.8% 0.118 165.612)",800:"oklch(43.2% 0.095 166.913)",900:"oklch(37.8% 0.077 168.94)",950:"oklch(26.2% 0.051 172.552)"},teal:{50:"oklch(98.4% 0.014 180.72)",100:"oklch(95.3% 0.051 180.801)",200:"oklch(91% 0.096 180.426)",300:"oklch(85.5% 0.138 181.071)",400:"oklch(77.7% 0.152 181.912)",500:"oklch(70.4% 0.14 182.503)",600:"oklch(60% 0.118 184.704)",700:"oklch(51.1% 0.096 186.391)",800:"oklch(43.7% 0.078 188.216)",900:"oklch(38.6% 0.063 188.416)",950:"oklch(27.7% 0.046 192.524)"},cyan:{50:"oklch(98.4% 0.019 200.873)",100:"oklch(95.6% 0.045 203.388)",200:"oklch(91.7% 0.08 205.041)",300:"oklch(86.5% 0.127 207.078)",400:"oklch(78.9% 0.154 211.53)",500:"oklch(71.5% 0.143 215.221)",600:"oklch(60.9% 0.126 221.723)",700:"oklch(52% 0.105 223.128)",800:"oklch(45% 0.085 224.283)",900:"oklch(39.8% 0.07 227.392)",950:"oklch(30.2% 0.056 229.695)"},sky:{50:"oklch(97.7% 0.013 236.62)",100:"oklch(95.1% 0.026 236.824)",200:"oklch(90.1% 0.058 230.902)",300:"oklch(82.8% 0.111 230.318)",400:"oklch(74.6% 0.16 232.661)",500:"oklch(68.5% 0.169 237.323)",600:"oklch(58.8% 0.158 241.966)",700:"oklch(50% 0.134 242.749)",800:"oklch(44.3% 0.11 240.79)",900:"oklch(39.1% 0.09 240.876)",950:"oklch(29.3% 0.066 243.157)"},blue:{50:"oklch(97% 0.014 254.604)",100:"oklch(93.2% 0.032 255.585)",200:"oklch(88.2% 0.059 254.128)",300:"oklch(80.9% 0.105 251.813)",400:"oklch(70.7% 0.165 254.624)",500:"oklch(62.3% 0.214 259.815)",600:"oklch(54.6% 0.245 262.881)",700:"oklch(48.8% 0.243 264.376)",800:"oklch(42.4% 0.199 265.638)",900:"oklch(37.9% 0.146 265.522)",950:"oklch(28.2% 0.091 267.935)"},indigo:{50:"oklch(96.2% 0.018 272.314)",100:"oklch(93% 0.034 272.788)",200:"oklch(87% 0.065 274.039)",300:"oklch(78.5% 0.115 274.713)",400:"oklch(67.3% 0.182 276.935)",500:"oklch(58.5% 0.233 277.117)",600:"oklch(51.1% 0.262 276.966)",700:"oklch(45.7% 0.24 277.023)",800:"oklch(39.8% 0.195 277.366)",900:"oklch(35.9% 0.144 278.697)",950:"oklch(25.7% 0.09 281.288)"},violet:{50:"oklch(96.9% 0.016 293.756)",100:"oklch(94.3% 0.029 294.588)",200:"oklch(89.4% 0.057 293.283)",300:"oklch(81.1% 0.111 293.571)",400:"oklch(70.2% 0.183 293.541)",500:"oklch(60.6% 0.25 292.717)",600:"oklch(54.1% 0.281 293.009)",700:"oklch(49.1% 0.27 292.581)",800:"oklch(43.2% 0.232 292.759)",900:"oklch(38% 0.189 293.745)",950:"oklch(28.3% 0.141 291.089)"},purple:{50:"oklch(97.7% 0.014 308.299)",100:"oklch(94.6% 0.033 307.174)",200:"oklch(90.2% 0.063 306.703)",300:"oklch(82.7% 0.119 306.383)",400:"oklch(71.4% 0.203 305.504)",500:"oklch(62.7% 0.265 303.9)",600:"oklch(55.8% 0.288 302.321)",700:"oklch(49.6% 0.265 301.924)",800:"oklch(43.8% 0.218 303.724)",900:"oklch(38.1% 0.176 304.987)",950:"oklch(29.1% 0.149 302.717)"},fuchsia:{50:"oklch(97.7% 0.017 320.058)",100:"oklch(95.2% 0.037 318.852)",200:"oklch(90.3% 0.076 319.62)",300:"oklch(83.3% 0.145 321.434)",400:"oklch(74% 0.238 322.16)",500:"oklch(66.7% 0.295 322.15)",600:"oklch(59.1% 0.293 322.896)",700:"oklch(51.8% 0.253 323.949)",800:"oklch(45.2% 0.211 324.591)",900:"oklch(40.1% 0.17 325.612)",950:"oklch(29.3% 0.136 325.661)"},pink:{50:"oklch(97.1% 0.014 343.198)",100:"oklch(94.8% 0.028 342.258)",200:"oklch(89.9% 0.061 343.231)",300:"oklch(82.3% 0.12 346.018)",400:"oklch(71.8% 0.202 349.761)",500:"oklch(65.6% 0.241 354.308)",600:"oklch(59.2% 0.249 0.584)",700:"oklch(52.5% 0.223 3.958)",800:"oklch(45.9% 0.187 3.815)",900:"oklch(40.8% 0.153 2.432)",950:"oklch(28.4% 0.109 3.907)"},rose:{50:"oklch(96.9% 0.015 12.422)",100:"oklch(94.1% 0.03 12.58)",200:"oklch(89.2% 0.058 10.001)",300:"oklch(81% 0.117 11.638)",400:"oklch(71.2% 0.194 13.428)",500:"oklch(64.5% 0.246 16.439)",600:"oklch(58.6% 0.253 17.585)",700:"oklch(51.4% 0.222 16.935)",800:"oklch(45.5% 0.188 13.697)",900:"oklch(41% 0.159 10.272)",950:"oklch(27.1% 0.105 12.094)"}};function ar(e){return{__BARE_VALUE__:e}}var lr=ar(e=>{if(Ve(e.value))return e.value}),sr=ar(e=>{if(Ve(e.value))return`${e.value}%`}),cr=ar(e=>{if(Ve(e.value))return`${e.value}px`}),ur=ar(e=>{if(Ve(e.value))return`${e.value}ms`}),dr=ar(e=>{if(Ve(e.value))return`${e.value}deg`}),fr=ar(e=>{if(null===e.fraction)return;let[t,r]=Z(e.fraction,"/");return Ve(t)&&Ve(r)?e.fraction:void 0}),pr=ar(e=>{if(Ve(Number(e.value)))return`repeat(${e.value}, minmax(0, 1fr))`}),hr={accentColor:({theme:e})=>e("colors"),animation:{none:"none",spin:"spin 1s linear infinite",ping:"ping 1s cubic-bezier(0, 0, 0.2, 1) infinite",pulse:"pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite",bounce:"bounce 1s infinite"},aria:{busy:'busy="true"',checked:'checked="true"',disabled:'disabled="true"',expanded:'expanded="true"',hidden:'hidden="true"',pressed:'pressed="true"',readonly:'readonly="true"',required:'required="true"',selected:'selected="true"'},aspectRatio:{auto:"auto",square:"1 / 1",video:"16 / 9",...fr},backdropBlur:({theme:e})=>e("blur"),backdropBrightness:({theme:e})=>({...e("brightness"),...sr}),backdropContrast:({theme:e})=>({...e("contrast"),...sr}),backdropGrayscale:({theme:e})=>({...e("grayscale"),...sr}),backdropHueRotate:({theme:e})=>({...e("hueRotate"),...dr}),backdropInvert:({theme:e})=>({...e("invert"),...sr}),backdropOpacity:({theme:e})=>({...e("opacity"),...sr}),backdropSaturate:({theme:e})=>({...e("saturate"),...sr}),backdropSepia:({theme:e})=>({...e("sepia"),...sr}),backgroundColor:({theme:e})=>e("colors"),backgroundImage:{none:"none","gradient-to-t":"linear-gradient(to top, var(--tw-gradient-stops))","gradient-to-tr":"linear-gradient(to top right, var(--tw-gradient-stops))","gradient-to-r":"linear-gradient(to right, var(--tw-gradient-stops))","gradient-to-br":"linear-gradient(to bottom right, var(--tw-gradient-stops))","gradient-to-b":"linear-gradient(to bottom, var(--tw-gradient-stops))","gradient-to-bl":"linear-gradient(to bottom left, var(--tw-gradient-stops))","gradient-to-l":"linear-gradient(to left, var(--tw-gradient-stops))","gradient-to-tl":"linear-gradient(to top left, var(--tw-gradient-stops))"},backgroundOpacity:({theme:e})=>e("opacity"),backgroundPosition:{bottom:"bottom",center:"center",left:"left","left-bottom":"left bottom","left-top":"left top",right:"right","right-bottom":"right bottom","right-top":"right top",top:"top"},backgroundSize:{auto:"auto",cover:"cover",contain:"contain"},blur:{0:"0",none:"",sm:"4px",DEFAULT:"8px",md:"12px",lg:"16px",xl:"24px","2xl":"40px","3xl":"64px"},borderColor:({theme:e})=>({DEFAULT:"currentcolor",...e("colors")}),borderOpacity:({theme:e})=>e("opacity"),borderRadius:{none:"0px",sm:"0.125rem",DEFAULT:"0.25rem",md:"0.375rem",lg:"0.5rem",xl:"0.75rem","2xl":"1rem","3xl":"1.5rem",full:"9999px"},borderSpacing:({theme:e})=>e("spacing"),borderWidth:{DEFAULT:"1px",0:"0px",2:"2px",4:"4px",8:"8px",...cr},boxShadow:{sm:"0 1px 2px 0 rgb(0 0 0 / 0.05)",DEFAULT:"0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)",md:"0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)",lg:"0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)",xl:"0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)","2xl":"0 25px 50px -12px rgb(0 0 0 / 0.25)",inner:"inset 0 2px 4px 0 rgb(0 0 0 / 0.05)",none:"none"},boxShadowColor:({theme:e})=>e("colors"),brightness:{0:"0",50:".5",75:".75",90:".9",95:".95",100:"1",105:"1.05",110:"1.1",125:"1.25",150:"1.5",200:"2",...sr},caretColor:({theme:e})=>e("colors"),colors:()=>({...ir}),columns:{auto:"auto",1:"1",2:"2",3:"3",4:"4",5:"5",6:"6",7:"7",8:"8",9:"9",10:"10",11:"11",12:"12","3xs":"16rem","2xs":"18rem",xs:"20rem",sm:"24rem",md:"28rem",lg:"32rem",xl:"36rem","2xl":"42rem","3xl":"48rem","4xl":"56rem","5xl":"64rem","6xl":"72rem","7xl":"80rem",...lr},container:{},content:{none:"none"},contrast:{0:"0",50:".5",75:".75",100:"1",125:"1.25",150:"1.5",200:"2",...sr},cursor:{auto:"auto",default:"default",pointer:"pointer",wait:"wait",text:"text",move:"move",help:"help","not-allowed":"not-allowed",none:"none","context-menu":"context-menu",progress:"progress",cell:"cell",crosshair:"crosshair","vertical-text":"vertical-text",alias:"alias",copy:"copy","no-drop":"no-drop",grab:"grab",grabbing:"grabbing","all-scroll":"all-scroll","col-resize":"col-resize","row-resize":"row-resize","n-resize":"n-resize","e-resize":"e-resize","s-resize":"s-resize","w-resize":"w-resize","ne-resize":"ne-resize","nw-resize":"nw-resize","se-resize":"se-resize","sw-resize":"sw-resize","ew-resize":"ew-resize","ns-resize":"ns-resize","nesw-resize":"nesw-resize","nwse-resize":"nwse-resize","zoom-in":"zoom-in","zoom-out":"zoom-out"},divideColor:({theme:e})=>e("borderColor"),divideOpacity:({theme:e})=>e("borderOpacity"),divideWidth:({theme:e})=>({...e("borderWidth"),...cr}),dropShadow:{sm:"0 1px 1px rgb(0 0 0 / 0.05)",DEFAULT:["0 1px 2px rgb(0 0 0 / 0.1)","0 1px 1px rgb(0 0 0 / 0.06)"],md:["0 4px 3px rgb(0 0 0 / 0.07)","0 2px 2px rgb(0 0 0 / 0.06)"],lg:["0 10px 8px rgb(0 0 0 / 0.04)","0 4px 3px rgb(0 0 0 / 0.1)"],xl:["0 20px 13px rgb(0 0 0 / 0.03)","0 8px 5px rgb(0 0 0 / 0.08)"],"2xl":"0 25px 25px rgb(0 0 0 / 0.15)",none:"0 0 #0000"},fill:({theme:e})=>e("colors"),flex:{1:"1 1 0%",auto:"1 1 auto",initial:"0 1 auto",none:"none"},flexBasis:({theme:e})=>({auto:"auto","1/2":"50%","1/3":"33.333333%","2/3":"66.666667%","1/4":"25%","2/4":"50%","3/4":"75%","1/5":"20%","2/5":"40%","3/5":"60%","4/5":"80%","1/6":"16.666667%","2/6":"33.333333%","3/6":"50%","4/6":"66.666667%","5/6":"83.333333%","1/12":"8.333333%","2/12":"16.666667%","3/12":"25%","4/12":"33.333333%","5/12":"41.666667%","6/12":"50%","7/12":"58.333333%","8/12":"66.666667%","9/12":"75%","10/12":"83.333333%","11/12":"91.666667%",full:"100%",...e("spacing")}),flexGrow:{0:"0",DEFAULT:"1",...lr},flexShrink:{0:"0",DEFAULT:"1",...lr},fontFamily:{sans:["ui-sans-serif","system-ui","sans-serif",'"Apple Color Emoji"','"Segoe UI Emoji"','"Segoe UI Symbol"','"Noto Color Emoji"'],serif:["ui-serif","Georgia","Cambria",'"Times New Roman"',"Times","serif"],mono:["ui-monospace","SFMono-Regular","Menlo","Monaco","Consolas",'"Liberation Mono"','"Courier New"',"monospace"]},fontSize:{xs:["0.75rem",{lineHeight:"1rem"}],sm:["0.875rem",{lineHeight:"1.25rem"}],base:["1rem",{lineHeight:"1.5rem"}],lg:["1.125rem",{lineHeight:"1.75rem"}],xl:["1.25rem",{lineHeight:"1.75rem"}],"2xl":["1.5rem",{lineHeight:"2rem"}],"3xl":["1.875rem",{lineHeight:"2.25rem"}],"4xl":["2.25rem",{lineHeight:"2.5rem"}],"5xl":["3rem",{lineHeight:"1"}],"6xl":["3.75rem",{lineHeight:"1"}],"7xl":["4.5rem",{lineHeight:"1"}],"8xl":["6rem",{lineHeight:"1"}],"9xl":["8rem",{lineHeight:"1"}]},fontWeight:{thin:"100",extralight:"200",light:"300",normal:"400",medium:"500",semibold:"600",bold:"700",extrabold:"800",black:"900"},gap:({theme:e})=>e("spacing"),gradientColorStops:({theme:e})=>e("colors"),gradientColorStopPositions:{"0%":"0%","5%":"5%","10%":"10%","15%":"15%","20%":"20%","25%":"25%","30%":"30%","35%":"35%","40%":"40%","45%":"45%","50%":"50%","55%":"55%","60%":"60%","65%":"65%","70%":"70%","75%":"75%","80%":"80%","85%":"85%","90%":"90%","95%":"95%","100%":"100%",...sr},grayscale:{0:"0",DEFAULT:"100%",...sr},gridAutoColumns:{auto:"auto",min:"min-content",max:"max-content",fr:"minmax(0, 1fr)"},gridAutoRows:{auto:"auto",min:"min-content",max:"max-content",fr:"minmax(0, 1fr)"},gridColumn:{auto:"auto","span-1":"span 1 / span 1","span-2":"span 2 / span 2","span-3":"span 3 / span 3","span-4":"span 4 / span 4","span-5":"span 5 / span 5","span-6":"span 6 / span 6","span-7":"span 7 / span 7","span-8":"span 8 / span 8","span-9":"span 9 / span 9","span-10":"span 10 / span 10","span-11":"span 11 / span 11","span-12":"span 12 / span 12","span-full":"1 / -1"},gridColumnEnd:{auto:"auto",1:"1",2:"2",3:"3",4:"4",5:"5",6:"6",7:"7",8:"8",9:"9",10:"10",11:"11",12:"12",13:"13",...lr},gridColumnStart:{auto:"auto",1:"1",2:"2",3:"3",4:"4",5:"5",6:"6",7:"7",8:"8",9:"9",10:"10",11:"11",12:"12",13:"13",...lr},gridRow:{auto:"auto","span-1":"span 1 / span 1","span-2":"span 2 / span 2","span-3":"span 3 / span 3","span-4":"span 4 / span 4","span-5":"span 5 / span 5","span-6":"span 6 / span 6","span-7":"span 7 / span 7","span-8":"span 8 / span 8","span-9":"span 9 / span 9","span-10":"span 10 / span 10","span-11":"span 11 / span 11","span-12":"span 12 / span 12","span-full":"1 / -1"},gridRowEnd:{auto:"auto",1:"1",2:"2",3:"3",4:"4",5:"5",6:"6",7:"7",8:"8",9:"9",10:"10",11:"11",12:"12",13:"13",...lr},gridRowStart:{auto:"auto",1:"1",2:"2",3:"3",4:"4",5:"5",6:"6",7:"7",8:"8",9:"9",10:"10",11:"11",12:"12",13:"13",...lr},gridTemplateColumns:{none:"none",subgrid:"subgrid",1:"repeat(1, minmax(0, 1fr))",2:"repeat(2, minmax(0, 1fr))",3:"repeat(3, minmax(0, 1fr))",4:"repeat(4, minmax(0, 1fr))",5:"repeat(5, minmax(0, 1fr))",6:"repeat(6, minmax(0, 1fr))",7:"repeat(7, minmax(0, 1fr))",8:"repeat(8, minmax(0, 1fr))",9:"repeat(9, minmax(0, 1fr))",10:"repeat(10, minmax(0, 1fr))",11:"repeat(11, minmax(0, 1fr))",12:"repeat(12, minmax(0, 1fr))",...pr},gridTemplateRows:{none:"none",subgrid:"subgrid",1:"repeat(1, minmax(0, 1fr))",2:"repeat(2, minmax(0, 1fr))",3:"repeat(3, minmax(0, 1fr))",4:"repeat(4, minmax(0, 1fr))",5:"repeat(5, minmax(0, 1fr))",6:"repeat(6, minmax(0, 1fr))",7:"repeat(7, minmax(0, 1fr))",8:"repeat(8, minmax(0, 1fr))",9:"repeat(9, minmax(0, 1fr))",10:"repeat(10, minmax(0, 1fr))",11:"repeat(11, minmax(0, 1fr))",12:"repeat(12, minmax(0, 1fr))",...pr},height:({theme:e})=>({auto:"auto","1/2":"50%","1/3":"33.333333%","2/3":"66.666667%","1/4":"25%","2/4":"50%","3/4":"75%","1/5":"20%","2/5":"40%","3/5":"60%","4/5":"80%","1/6":"16.666667%","2/6":"33.333333%","3/6":"50%","4/6":"66.666667%","5/6":"83.333333%",full:"100%",screen:"100vh",svh:"100svh",lvh:"100lvh",dvh:"100dvh",min:"min-content",max:"max-content",fit:"fit-content",...e("spacing")}),hueRotate:{0:"0deg",15:"15deg",30:"30deg",60:"60deg",90:"90deg",180:"180deg",...dr},inset:({theme:e})=>({auto:"auto","1/2":"50%","1/3":"33.333333%","2/3":"66.666667%","1/4":"25%","2/4":"50%","3/4":"75%",full:"100%",...e("spacing")}),invert:{0:"0",DEFAULT:"100%",...sr},keyframes:{spin:{to:{transform:"rotate(360deg)"}},ping:{"75%, 100%":{transform:"scale(2)",opacity:"0"}},pulse:{"50%":{opacity:".5"}},bounce:{"0%, 100%":{transform:"translateY(-25%)",animationTimingFunction:"cubic-bezier(0.8,0,1,1)"},"50%":{transform:"none",animationTimingFunction:"cubic-bezier(0,0,0.2,1)"}}},letterSpacing:{tighter:"-0.05em",tight:"-0.025em",normal:"0em",wide:"0.025em",wider:"0.05em",widest:"0.1em"},lineHeight:{none:"1",tight:"1.25",snug:"1.375",normal:"1.5",relaxed:"1.625",loose:"2",3:".75rem",4:"1rem",5:"1.25rem",6:"1.5rem",7:"1.75rem",8:"2rem",9:"2.25rem",10:"2.5rem"},listStyleType:{none:"none",disc:"disc",decimal:"decimal"},listStyleImage:{none:"none"},margin:({theme:e})=>({auto:"auto",...e("spacing")}),lineClamp:{1:"1",2:"2",3:"3",4:"4",5:"5",6:"6",...lr},maxHeight:({theme:e})=>({none:"none",full:"100%",screen:"100vh",svh:"100svh",lvh:"100lvh",dvh:"100dvh",min:"min-content",max:"max-content",fit:"fit-content",...e("spacing")}),maxWidth:({theme:e})=>({none:"none",xs:"20rem",sm:"24rem",md:"28rem",lg:"32rem",xl:"36rem","2xl":"42rem","3xl":"48rem","4xl":"56rem","5xl":"64rem","6xl":"72rem","7xl":"80rem",full:"100%",min:"min-content",max:"max-content",fit:"fit-content",prose:"65ch",...e("spacing")}),minHeight:({theme:e})=>({full:"100%",screen:"100vh",svh:"100svh",lvh:"100lvh",dvh:"100dvh",min:"min-content",max:"max-content",fit:"fit-content",...e("spacing")}),minWidth:({theme:e})=>({full:"100%",min:"min-content",max:"max-content",fit:"fit-content",...e("spacing")}),objectPosition:{bottom:"bottom",center:"center",left:"left","left-bottom":"left bottom","left-top":"left top",right:"right","right-bottom":"right bottom","right-top":"right top",top:"top"},opacity:{0:"0",5:"0.05",10:"0.1",15:"0.15",20:"0.2",25:"0.25",30:"0.3",35:"0.35",40:"0.4",45:"0.45",50:"0.5",55:"0.55",60:"0.6",65:"0.65",70:"0.7",75:"0.75",80:"0.8",85:"0.85",90:"0.9",95:"0.95",100:"1",...sr},order:{first:"-9999",last:"9999",none:"0",1:"1",2:"2",3:"3",4:"4",5:"5",6:"6",7:"7",8:"8",9:"9",10:"10",11:"11",12:"12",...lr},outlineColor:({theme:e})=>e("colors"),outlineOffset:{0:"0px",1:"1px",2:"2px",4:"4px",8:"8px",...cr},outlineWidth:{0:"0px",1:"1px",2:"2px",4:"4px",8:"8px",...cr},padding:({theme:e})=>e("spacing"),placeholderColor:({theme:e})=>e("colors"),placeholderOpacity:({theme:e})=>e("opacity"),ringColor:({theme:e})=>({DEFAULT:"currentcolor",...e("colors")}),ringOffsetColor:({theme:e})=>e("colors"),ringOffsetWidth:{0:"0px",1:"1px",2:"2px",4:"4px",8:"8px",...cr},ringOpacity:({theme:e})=>({DEFAULT:"0.5",...e("opacity")}),ringWidth:{DEFAULT:"3px",0:"0px",1:"1px",2:"2px",4:"4px",8:"8px",...cr},rotate:{0:"0deg",1:"1deg",2:"2deg",3:"3deg",6:"6deg",12:"12deg",45:"45deg",90:"90deg",180:"180deg",...dr},saturate:{0:"0",50:".5",100:"1",150:"1.5",200:"2",...sr},scale:{0:"0",50:".5",75:".75",90:".9",95:".95",100:"1",105:"1.05",110:"1.1",125:"1.25",150:"1.5",...sr},screens:{sm:"40rem",md:"48rem",lg:"64rem",xl:"80rem","2xl":"96rem"},scrollMargin:({theme:e})=>e("spacing"),scrollPadding:({theme:e})=>e("spacing"),sepia:{0:"0",DEFAULT:"100%",...sr},skew:{0:"0deg",1:"1deg",2:"2deg",3:"3deg",6:"6deg",12:"12deg",...dr},space:({theme:e})=>e("spacing"),spacing:{px:"1px",0:"0px",.5:"0.125rem",1:"0.25rem",1.5:"0.375rem",2:"0.5rem",2.5:"0.625rem",3:"0.75rem",3.5:"0.875rem",4:"1rem",5:"1.25rem",6:"1.5rem",7:"1.75rem",8:"2rem",9:"2.25rem",10:"2.5rem",11:"2.75rem",12:"3rem",14:"3.5rem",16:"4rem",20:"5rem",24:"6rem",28:"7rem",32:"8rem",36:"9rem",40:"10rem",44:"11rem",48:"12rem",52:"13rem",56:"14rem",60:"15rem",64:"16rem",72:"18rem",80:"20rem",96:"24rem"},stroke:({theme:e})=>({none:"none",...e("colors")}),strokeWidth:{0:"0",1:"1",2:"2",...lr},supports:{},data:{},textColor:({theme:e})=>e("colors"),textDecorationColor:({theme:e})=>e("colors"),textDecorationThickness:{auto:"auto","from-font":"from-font",0:"0px",1:"1px",2:"2px",4:"4px",8:"8px",...cr},textIndent:({theme:e})=>e("spacing"),textOpacity:({theme:e})=>e("opacity"),textUnderlineOffset:{auto:"auto",0:"0px",1:"1px",2:"2px",4:"4px",8:"8px",...cr},transformOrigin:{center:"center",top:"top","top-right":"top right",right:"right","bottom-right":"bottom right",bottom:"bottom","bottom-left":"bottom left",left:"left","top-left":"top left"},transitionDelay:{0:"0s",75:"75ms",100:"100ms",150:"150ms",200:"200ms",300:"300ms",500:"500ms",700:"700ms",1e3:"1000ms",...ur},transitionDuration:{DEFAULT:"150ms",0:"0s",75:"75ms",100:"100ms",150:"150ms",200:"200ms",300:"300ms",500:"500ms",700:"700ms",1e3:"1000ms",...ur},transitionProperty:{none:"none",all:"all",DEFAULT:"color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter",colors:"color, background-color, border-color, outline-color, text-decoration-color, fill, stroke",opacity:"opacity",shadow:"box-shadow",transform:"transform"},transitionTimingFunction:{DEFAULT:"cubic-bezier(0.4, 0, 0.2, 1)",linear:"linear",in:"cubic-bezier(0.4, 0, 1, 1)",out:"cubic-bezier(0, 0, 0.2, 1)","in-out":"cubic-bezier(0.4, 0, 0.2, 1)"},translate:({theme:e})=>({"1/2":"50%","1/3":"33.333333%","2/3":"66.666667%","1/4":"25%","2/4":"50%","3/4":"75%",full:"100%",...e("spacing")}),size:({theme:e})=>({auto:"auto","1/2":"50%","1/3":"33.333333%","2/3":"66.666667%","1/4":"25%","2/4":"50%","3/4":"75%","1/5":"20%","2/5":"40%","3/5":"60%","4/5":"80%","1/6":"16.666667%","2/6":"33.333333%","3/6":"50%","4/6":"66.666667%","5/6":"83.333333%","1/12":"8.333333%","2/12":"16.666667%","3/12":"25%","4/12":"33.333333%","5/12":"41.666667%","6/12":"50%","7/12":"58.333333%","8/12":"66.666667%","9/12":"75%","10/12":"83.333333%","11/12":"91.666667%",full:"100%",min:"min-content",max:"max-content",fit:"fit-content",...e("spacing")}),width:({theme:e})=>({auto:"auto","1/2":"50%","1/3":"33.333333%","2/3":"66.666667%","1/4":"25%","2/4":"50%","3/4":"75%","1/5":"20%","2/5":"40%","3/5":"60%","4/5":"80%","1/6":"16.666667%","2/6":"33.333333%","3/6":"50%","4/6":"66.666667%","5/6":"83.333333%","1/12":"8.333333%","2/12":"16.666667%","3/12":"25%","4/12":"33.333333%","5/12":"41.666667%","6/12":"50%","7/12":"58.333333%","8/12":"66.666667%","9/12":"75%","10/12":"83.333333%","11/12":"91.666667%",full:"100%",screen:"100vw",svw:"100svw",lvw:"100lvw",dvw:"100dvw",min:"min-content",max:"max-content",fit:"fit-content",...e("spacing")}),willChange:{auto:"auto",scroll:"scroll-position",contents:"contents",transform:"transform"},zIndex:{auto:"auto",0:"0",10:"10",20:"20",30:"30",40:"40",50:"50",...lr}};function mr(e){return{theme:{...hr,colors:({theme:e})=>e("color",{}),extend:{fontSize:({theme:e})=>({...e("text",{})}),boxShadow:({theme:e})=>({...e("shadow",{})}),animation:({theme:e})=>({...e("animate",{})}),aspectRatio:({theme:e})=>({...e("aspect",{})}),borderRadius:({theme:e})=>({...e("radius",{})}),screens:({theme:e})=>({...e("breakpoint",{})}),letterSpacing:({theme:e})=>({...e("tracking",{})}),lineHeight:({theme:e})=>({...e("leading",{})}),transitionDuration:{DEFAULT:e.get(["--default-transition-duration"])??null},transitionTimingFunction:{DEFAULT:e.get(["--default-transition-timing-function"])??null},maxWidth:({theme:e})=>({...e("container",{})})}}}}var gr={blocklist:[],future:{},experimental:{},prefix:"",important:!1,darkMode:null,theme:{},plugins:[],content:{files:[]}};function vr(e,t){let r={design:e,configs:[],plugins:[],content:{files:[]},theme:{},extend:{},result:structuredClone(gr)};for(let e of t)wr(r,e);for(let e of r.configs)"darkMode"in e&&void 0!==e.darkMode&&(r.result.darkMode=e.darkMode??null),"prefix"in e&&void 0!==e.prefix&&(r.result.prefix=e.prefix??""),"blocklist"in e&&void 0!==e.blocklist&&(r.result.blocklist=e.blocklist??[]),"important"in e&&void 0!==e.important&&(r.result.important=e.important??!1);let n=function(e){let t=new Set,r=Gt(e.design,()=>e.theme,o),n=Object.assign(r,{theme:r,colors:ir});function o(e){return"function"==typeof e?e(n)??null:e??null}for(let r of e.configs){let n=r.theme??{},o=n.extend??{};for(let e in n)"extend"!==e&&t.add(e);Object.assign(e.theme,n);for(let t in o)e.extend[t]??=[],e.extend[t].push(o[t])}delete e.theme.extend;for(let t in e.extend){let r=[e.theme[t],...e.extend[t]];e.theme[t]=()=>Zt({},r.map(o),kr)}for(let t in e.theme)e.theme[t]=o(e.theme[t]);if(e.theme.screens&&"object"==typeof e.theme.screens)for(let t of Object.keys(e.theme.screens)){let r=e.theme.screens[t];r&&"object"==typeof r&&("raw"in r||"max"in r||"min"in r&&(e.theme.screens[t]=r.min))}return t}(r);return{resolvedConfig:{...r.result,content:r.content,theme:r.theme,plugins:r.plugins},replacedThemeKeys:n}}function kr(e,t){return Array.isArray(e)&&Yt(e[0])?e.concat(t):Array.isArray(t)&&Yt(t[0])&&Yt(e)?[e,...t]:Array.isArray(t)?t:void 0}function wr(e,{config:t,base:r,path:n,reference:o,src:i}){let a=[];for(let e of t.plugins??[])"__isOptionsFunction"in e?a.push({...e(),reference:o,src:i}):"handler"in e?a.push({...e,reference:o,src:i}):a.push({handler:e,reference:o,src:i});if(Array.isArray(t.presets)&&0===t.presets.length)throw new Error("Error in the config file/plugin/preset. An empty preset (`preset: []`) is not currently supported.");for(let a of t.presets??[])wr(e,{path:n,base:r,config:a,reference:o,src:i});for(let t of a)e.plugins.push(t),t.config&&wr(e,{path:n,base:r,config:t.config,reference:!!t.reference,src:t.src??i});let l=t.content??[],s=Array.isArray(l)?l:l.files;for(let t of s)e.content.files.push("object"==typeof t?t:{base:r,pattern:t});e.configs.push(t)}function br(e,t){let r=e.theme.container||{};if("object"!=typeof r||null===r)return;let n=function({center:e,padding:t,screens:r},n){let o=[],i=null;if(e&&o.push(j("margin-inline","auto")),("string"==typeof t||"object"==typeof t&&null!==t&&"DEFAULT"in t)&&o.push(j("padding-inline","string"==typeof t?t:t.DEFAULT)),"object"==typeof r&&null!==r){i=new Map;let e=Array.from(n.theme.namespace("--breakpoint").entries());if(e.sort((e,t)=>ce(e[1],t[1],"asc")),e.length>0){let[t]=e[0];o.push(S("@media",`(width >= --theme(--breakpoint-${t}))`,[j("max-width","none")]))}for(let[e,t]of Object.entries(r)){if("object"==typeof t){if(!("min"in t))continue;t=t.min}i.set(e,S("@media",`(width >= ${t})`,[j("max-width",t)]))}}if("object"==typeof t&&null!==t){let e=Object.entries(t).filter(([e])=>"DEFAULT"!==e).map(([e,t])=>[e,n.theme.resolveValue(e,["--breakpoint"]),t]).filter(Boolean);e.sort((e,t)=>ce(e[1],t[1],"asc"));for(let[t,,r]of e)if(i&&i.has(t))i.get(t).nodes.push(j("padding-inline",r));else{if(i)continue;o.push(S("@media",`(width >= theme(--breakpoint-${t}))`,[j("padding-inline",r)]))}}if(i)for(let[,e]of i)o.push(e);return o}(r,t);0!==n.length&&t.utilities.static("container",()=>n.map(E))}function yr({addVariant:e,config:t}){let r=t("darkMode",null),[n,o=".dark"]=Array.isArray(r)?r:[r];if("variant"===n){let e;if(Array.isArray(o)||"function"==typeof o?e=o:"string"==typeof o&&(e=[o]),Array.isArray(e))for(let t of e)".dark"===t?(n=!1,console.warn('When using `variant` for `darkMode`, you must provide a selector.\nExample: `darkMode: ["variant", ".your-selector &"]`')):t.includes("&")||(n=!1,console.warn('When using `variant` for `darkMode`, your selector must contain `&`.\nExample `darkMode: ["variant", ".your-selector &"]`'));o=e}null===n||("selector"===n?e("dark",`&:where(${o}, ${o} *)`):"media"===n?e("dark","@media (prefers-color-scheme: dark)"):"variant"===n?e("dark",o):"class"===n&&e("dark",`&:is(${o} *)`))}function xr(e){return(Array.isArray(e)?e:[e]).map(e=>"string"==typeof e?{min:e}:e&&"object"==typeof e?e:null).map(e=>{if(null===e)return null;if("raw"in e)return e.raw;let t="";return void 0!==e.max&&(t+=`${e.max} >= `),t+="width",void 0!==e.min&&(t+=` >= ${e.min}`),`(${t})`}).filter(Boolean).join(", ")}var $r=/^[a-z]+$/;async function zr({designSystem:e,base:t,ast:r,loadModule:n,sources:o}){let i=0,a=[],l=[];y(r,(e,t)=>{if("at-rule"!==e.kind)return;let r=N(t);if("@plugin"===e.name){if(null!==r.parent)throw new Error("`@plugin` cannot be nested.");let t=e.params.slice(1,-1);if(0===t.length)throw new Error("`@plugin` must have a path.");let n={};for(let t of e.nodes??[]){if("declaration"!==t.kind)throw new Error(`Unexpected \`@plugin\` option:\n\n${F([t])}\n\n\`@plugin\` options must be a flat list of declarations.`);if(void 0===t.value)continue;let e=Z(t.value,",").map(e=>{if("null"===(e=e.trim()))return null;if("true"===e)return!0;if("false"===e)return!1;if(!Number.isNaN(Number(e)))return Number(e);if('"'===e[0]&&'"'===e[e.length-1]||"'"===e[0]&&"'"===e[e.length-1])return e.slice(1,-1);if("{"===e[0]&&"}"===e[e.length-1])throw new Error(`Unexpected \`@plugin\` option: Value of declaration \`${F([t]).trim()}\` is not supported.\n\nUsing an object as a plugin option is currently only supported in JavaScript configuration files.`);return e});n[t.property]=1===e.length?e[0]:e}return a.push([{id:t,base:r.context.base,reference:!!r.context.reference,src:e.src},Object.keys(n).length>0?n:null]),i|=4,b.Replace([])}if("@config"===e.name){if(e.nodes.length>0)throw new Error("`@config` cannot have a body.");if(null!==r.parent)throw new Error("`@config` cannot be nested.");return l.push({id:e.params.slice(1,-1),base:r.context.base,reference:!!r.context.reference,src:e.src}),i|=4,b.Replace([])}}),function(e){for(let[t,r]of[["t","top"],["tr","top right"],["r","right"],["br","bottom right"],["b","bottom"],["bl","bottom left"],["l","left"],["tl","top left"]])e.utilities.suggest(`bg-gradient-to-${t}`,()=>[]),e.utilities.static(`bg-gradient-to-${t}`,()=>[j("--tw-gradient-position",`to ${r} in oklab`),j("background-image","linear-gradient(var(--tw-gradient-stops))")]);e.utilities.suggest("bg-left-top",()=>[]),e.utilities.static("bg-left-top",()=>[j("background-position","left top")]),e.utilities.suggest("bg-right-top",()=>[]),e.utilities.static("bg-right-top",()=>[j("background-position","right top")]),e.utilities.suggest("bg-left-bottom",()=>[]),e.utilities.static("bg-left-bottom",()=>[j("background-position","left bottom")]),e.utilities.suggest("bg-right-bottom",()=>[]),e.utilities.static("bg-right-bottom",()=>[j("background-position","right bottom")]),e.utilities.suggest("object-left-top",()=>[]),e.utilities.static("object-left-top",()=>[j("object-position","left top")]),e.utilities.suggest("object-right-top",()=>[]),e.utilities.static("object-right-top",()=>[j("object-position","right top")]),e.utilities.suggest("object-left-bottom",()=>[]),e.utilities.static("object-left-bottom",()=>[j("object-position","left bottom")]),e.utilities.suggest("object-right-bottom",()=>[]),e.utilities.static("object-right-bottom",()=>[j("object-position","right bottom")]),e.utilities.suggest("max-w-screen",()=>[]),e.utilities.functional("max-w-screen",t=>{if(!t.value||"arbitrary"===t.value.kind)return;let r=e.theme.resolve(t.value.value,["--breakpoint"]);return r?[j("max-width",r)]:void 0}),e.utilities.suggest("overflow-ellipsis",()=>[]),e.utilities.static("overflow-ellipsis",()=>[j("text-overflow","ellipsis")]),e.utilities.suggest("decoration-slice",()=>[]),e.utilities.static("decoration-slice",()=>[j("-webkit-box-decoration-break","slice"),j("box-decoration-break","slice")]),e.utilities.suggest("decoration-clone",()=>[]),e.utilities.static("decoration-clone",()=>[j("-webkit-box-decoration-break","clone"),j("box-decoration-break","clone")]),e.utilities.suggest("flex-shrink",()=>[]),e.utilities.functional("flex-shrink",e=>{if(!e.modifier){if(!e.value)return[j("flex-shrink","1")];if("arbitrary"===e.value.kind)return[j("flex-shrink",e.value.value)];if(Ve(e.value.value))return[j("flex-shrink",e.value.value)]}}),e.utilities.suggest("flex-grow",()=>[]),e.utilities.functional("flex-grow",e=>{if(!e.modifier){if(!e.value)return[j("flex-grow","1")];if("arbitrary"===e.value.kind)return[j("flex-grow",e.value.value)];if(Ve(e.value.value))return[j("flex-grow",e.value.value)]}}),e.utilities.suggest("order-none",()=>[]),e.utilities.static("order-none",()=>[j("order","0")]),e.utilities.suggest("break-words",()=>[]),e.utilities.static("break-words",()=>[j("overflow-wrap","break-word")]);for(let[t,r]of[["start","inset-inline-start"],["end","inset-inline-end"]]){let n=function({negative:t}){return n=>{if(null===n.value)return;if("arbitrary"===n.value.kind){if(n.modifier)return;let e=n.value.value;return[j(r,t?`calc(${e} * -1)`:e)]}let o=e.theme.resolve(n.value.fraction??n.value.value,["--inset","--spacing"]);if(null===o&&n.value.fraction){let[e,t]=Z(n.value.fraction,"/");if(!Ve(e)||!Ve(t))return;o=`calc(${n.value.fraction} * 100%)`}if(null===o&&t){let t=e.theme.resolve(null,["--spacing"]);if(t&&Ee(n.value.value)&&(o=`calc(${t} * -${n.value.value})`,null!==o))return[j(r,o)]}if(null===o){let t=e.theme.resolve(null,["--spacing"]);t&&Ee(n.value.value)&&(o=`calc(${t} * ${n.value.value})`)}return null!==o?[j(r,t?`calc(${o} * -1)`:o)]:void 0}};e.utilities.static(`${t}-auto`,()=>[j(r,"auto")]),e.utilities.static(`${t}-full`,()=>[j(r,"100%")]),e.utilities.static(`-${t}-full`,()=>[j(r,"-100%")]),e.utilities.static(`${t}-px`,()=>[j(r,"1px")]),e.utilities.static(`-${t}-px`,()=>[j(r,"-1px")]),e.utilities.functional(`-${t}`,n({negative:!0})),e.utilities.functional(t,n({negative:!1}))}}(e);let s=e.resolveThemeValue;if(e.resolveThemeValue=function(n,a){return n.startsWith("--")?s(n,a):(i|=Ar({designSystem:e,base:t,ast:r,sources:o,configs:[],pluginDetails:[]}),e.resolveThemeValue(n,a))},!a.length&&!l.length)return 0;let[c,u]=await Promise.all([Promise.all(l.map(async({id:e,base:t,reference:r,src:o})=>{let i=await n(e,t,"config");return{path:e,base:i.base,config:i.module,reference:r,src:o}})),Promise.all(a.map(async([{id:e,base:t,reference:r,src:o},i])=>{let a=await n(e,t,"plugin");return{path:e,base:a.base,plugin:a.module,options:i,reference:r,src:o}}))]);return i|=Ar({designSystem:e,base:t,ast:r,sources:o,configs:c,pluginDetails:u}),i}function Ar({designSystem:e,base:t,ast:r,sources:n,configs:o,pluginDetails:i}){let a=0,l=[...i.map(e=>{if(!e.options)return{config:{plugins:[e.plugin]},base:e.base,reference:e.reference,src:e.src};if("__isOptionsFunction"in e.plugin)return{config:{plugins:[e.plugin(e.options)]},base:e.base,reference:e.reference,src:e.src};throw new Error(`The plugin "${e.path}" does not accept options`)}),...o],{resolvedConfig:s}=vr(e,[{config:mr(e.theme),base:t,reference:!0,src:void 0},...l,{config:{plugins:[yr]},base:t,reference:!0,src:void 0}]),{resolvedConfig:c,replacedThemeKeys:u}=vr(e,l),d={designSystem:e,ast:r,resolvedConfig:s,featuresRef:{set current(e){a|=e}}},f=er({...d,referenceMode:!1,src:void 0}),p=e.resolveThemeValue;e.resolveThemeValue=function(e,t){if("-"===e[0]&&"-"===e[1])return p(e,t);let r=f.theme(e,void 0);return Array.isArray(r)&&2===r.length?r[0]:Array.isArray(r)?r.join(", "):"object"==typeof r&&null!==r&&"DEFAULT"in r?r.DEFAULT:"string"==typeof r?r:void 0};for(let{handler:e,reference:t,src:r}of s.plugins){e(er({...d,referenceMode:t??!1,src:r}))}if(Et(e,c,u),or(e,c),function(e,t){let r=e.theme.aria||{},n=e.theme.supports||{},o=e.theme.data||{};if(Object.keys(r).length>0){let e=t.variants.get("aria"),n=e?.applyFn,o=e?.compounds;t.variants.functional("aria",(e,t)=>{let o=t.value;return o&&"named"===o.kind&&o.value in r?n?.(e,{...t,value:{kind:"arbitrary",value:r[o.value]}}):n?.(e,t)},{compounds:o})}if(Object.keys(n).length>0){let e=t.variants.get("supports"),r=e?.applyFn,o=e?.compounds;t.variants.functional("supports",(e,t)=>{let o=t.value;return o&&"named"===o.kind&&o.value in n?r?.(e,{...t,value:{kind:"arbitrary",value:n[o.value]}}):r?.(e,t)},{compounds:o})}if(Object.keys(o).length>0){let e=t.variants.get("data"),r=e?.applyFn,n=e?.compounds;t.variants.functional("data",(e,t)=>{let n=t.value;return n&&"named"===n.kind&&n.value in o?r?.(e,{...t,value:{kind:"arbitrary",value:o[n.value]}}):r?.(e,t)},{compounds:n})}}(c,e),function(e,t){let r=e.theme.screens||{},n=t.variants.get("min")?.order??0,o=[];for(let[e,i]of Object.entries(r)){let r=function(r){t.variants.static(e,e=>{e.nodes=[S("@media",c,e.nodes)]},{order:r})},a=t.variants.get(e),l=t.theme.resolveValue(e,["--breakpoint"]);if(a&&l&&!t.theme.hasDefault(`--breakpoint-${e}`))continue;let s=!0;"string"==typeof i&&(s=!1);let c=xr(i);s?o.push(r):r(n)}if(0!==o.length){for(let[,e]of t.variants.variants)e.order>n&&(e.order+=o.length);t.variants.compareFns=new Map(Array.from(t.variants.compareFns).map(([e,t])=>(e>n&&(e+=o.length),[e,t])));for(let[e,t]of o.entries())t(n+e+1)}}(c,e),br(c,e),!e.theme.prefix&&s.prefix){if(s.prefix.endsWith("-")&&(s.prefix=s.prefix.slice(0,-1),console.warn(`The prefix "${s.prefix}" is invalid. Prefixes must be lowercase ASCII letters (a-z) only and is written as a variant before all utilities. We have fixed up the prefix for you. Remove the trailing \`-\` to silence this warning.`)),!$r.test(s.prefix))throw new Error(`The prefix "${s.prefix}" is invalid. Prefixes must be lowercase ASCII letters (a-z) only.`);e.theme.prefix=s.prefix}if(!e.important&&!0===s.important&&(e.important=!0),"string"==typeof s.important){let e=s.important;y(r,(t,r)=>{if("at-rule"!==t.kind||"@tailwind"!==t.name||"utilities"!==t.params)return;let n=N(r);return"rule"===n.parent?.kind&&n.parent.selector===e?b.Stop:b.ReplaceStop(A(e,[t]))})}for(let t of s.blocklist)e.invalidCandidates.add(t);for(let e of s.content.files){if("raw"in e)throw new Error(`Error in the config file/plugin/preset. The \`content\` key contains a \`raw\` entry:\n\n${JSON.stringify(e,null,2)}\n\nThis feature is not currently supported.`);let t=!1;"!"==e.pattern[0]&&(t=!0,e.pattern=e.pattern.slice(1)),n.push({...e,negated:t})}return a}var Sr=/^(-?\d+)\.\.(-?\d+)(?:\.\.(-?\d+))?$/;function Cr(e){let t=e.indexOf("{");if(-1===t)return[e];let r=[],n=e.slice(0,t),o=e.slice(t),i=0,a=o.lastIndexOf("}");for(let e=0;e0&&(i=-i);for(let r=e;o?r<=t:r>=t;r+=i)a.push(r.toString())}return a}(s):Z(s,","),l=l.flatMap(e=>Cr(e));let u=Cr(c);for(let e of u)for(let t of l)r.push(n+t+e);return r}var jr=/^[a-z]+$/;function Tr(){throw new Error("No `loadModule` function provided to `compile`")}function Vr(){throw new Error("No `loadStylesheet` function provided to `compile`")}async function Kr(e,{base:t="",from:r,loadModule:n=Tr,loadStylesheet:o=Vr}={}){let i=0;e=[V({base:t},e)],i|=await Vt(e,t,o,0,void 0!==r);let a=null,c=new d,u=new Map,f=new Map,p=[],h=null,m=null,g=[],v=[],k=[],w=[],x=null;y(e,(e,t)=>{if("at-rule"!==e.kind)return;let r=N(t);if("@tailwind"===e.name&&("utilities"===e.params||e.params.startsWith("utilities"))){if(null!==m)return b.Replace([]);if(r.context.reference)return b.Replace([]);let t=Z(e.params," ");for(let e of t)if(e.startsWith("source(")){let t=e.slice(7,-1);if("none"===t){x=t;continue}if('"'===t[0]&&'"'!==t[t.length-1]||"'"===t[0]&&"'"!==t[t.length-1]||"'"!==t[0]&&'"'!==t[0])throw new Error("`source(…)` paths must be quoted.");x={base:r.context.sourceBase??r.context.base,pattern:t.slice(1,-1)}}m=e,i|=16}if("@utility"===e.name){if(null!==r.parent)throw new Error("`@utility` cannot be nested.");if(0===e.nodes.length)throw new Error(`\`@utility ${e.params}\` is empty. Utilities should include at least one property.`);let t=Ze(e);if(null===t){if(!e.params.endsWith("-*")){if(e.params.endsWith("*"))throw new Error(`\`@utility ${e.params}\` defines an invalid utility name. A functional utility must end in \`-*\`.`);if(e.params.includes("*"))throw new Error(`\`@utility ${e.params}\` defines an invalid utility name. The dynamic portion marked by \`-*\` must appear once at the end.`)}throw new Error(`\`@utility ${e.params}\` defines an invalid utility name. Utilities should be alphanumeric and start with a lowercase letter.`)}p.push(t)}if("@source"===e.name){if(e.nodes.length>0)throw new Error("`@source` cannot have a body.");if(null!==r.parent)throw new Error("`@source` cannot be nested.");let t=!1,n=!1,o=e.params;if("n"===o[0]&&o.startsWith("not ")&&(t=!0,o=o.slice(4)),"i"===o[0]&&o.startsWith("inline(")&&(n=!0,o=o.slice(7,-1).trim()),'"'===o[0]&&'"'!==o[o.length-1]||"'"===o[0]&&"'"!==o[o.length-1]||"'"!==o[0]&&'"'!==o[0])throw new Error("`@source` paths must be quoted.");let i=o.slice(1,-1);if(n){let e=t?w:k,r=Z(i," ");for(let t of r)for(let r of Cr(t))e.push(r)}else v.push({base:r.context.base,pattern:i,negated:t});return b.ReplaceSkip([])}if("@variant"===e.name&&(null===r.parent?0===e.nodes.length?e.name="@custom-variant":(y(e.nodes,t=>{if("at-rule"===t.kind&&"@slot"===t.name)return e.name="@custom-variant",b.Stop}),"@variant"===e.name&&g.push(e)):g.push(e)),"@custom-variant"===e.name){if(null!==r.parent)throw new Error("`@custom-variant` cannot be nested.");let[t,n]=Z(e.params," ");if(!mt.test(t))throw new Error(`\`@custom-variant ${t}\` defines an invalid variant name. Variants should only contain alphanumeric, dashes, or underscore characters and start with a lowercase letter or number.`);if(e.nodes.length>0&&n)throw new Error(`\`@custom-variant ${t}\` cannot have both a selector and a body.`);if(0===e.nodes.length){if(!n)throw new Error(`\`@custom-variant ${t}\` has no selector or body.`);let e=Z(n.slice(1,-1),",");if(0===e.length||e.some(e=>""===e.trim()))throw new Error(`\`@custom-variant ${t} (${e.join(",")})\` selector is invalid.`);let r=[],o=[];for(let t of e)t=t.trim(),"@"===t[0]?r.push(t):o.push(t);u.set(t,e=>{e.variants.static(t,e=>{let t=[];o.length>0&&t.push(A(o.join(", "),e.nodes));for(let n of r)t.push(C(n,e.nodes));e.nodes=t},{compounds:vt([...o,...r])})}),f.set(t,new Set)}else{let r=new Set;y(e.nodes,e=>{"at-rule"===e.kind&&"@variant"===e.name&&r.add(e.params)}),u.set(t,r=>{r.variants.fromAst(t,e.nodes,r)}),f.set(t,r)}return b.ReplaceSkip([])}if("@media"===e.name){let t=Z(e.params," "),n=[];for(let o of t)if(o.startsWith("source(")){let t=o.slice(7,-1);y(e.nodes,e=>{if("at-rule"===e.kind&&"@tailwind"===e.name&&"utilities"===e.params)return e.params+=` source(${t})`,b.ReplaceStop([V({sourceBase:r.context.base},[e])])})}else if(o.startsWith("theme(")){let t=o.slice(6,-1),r=t.includes("reference");y(e.nodes,e=>{if("context"!==e.kind){if("at-rule"!==e.kind){if(r)throw new Error('Files imported with `@import "…" theme(reference)` must only contain `@theme` blocks.\nUse `@reference "…";` instead.');return b.Continue}if("@theme"===e.name)return e.params+=" "+t,b.Skip}})}else if(o.startsWith("prefix(")){let t=o.slice(7,-1);y(e.nodes,e=>{if("at-rule"===e.kind&&"@theme"===e.name)return e.params+=` prefix(${t})`,b.Skip})}else"important"===o?a=!0:"reference"===o?e.nodes=[V({reference:!0},e.nodes)]:n.push(o);if(n.length>0)e.params=n.join(" ");else if(t.length>0)return b.Replace(e.nodes);return b.Continue}if("@theme"===e.name){let[t,n]=function(e){let t=0,r=null;for(let n of Z(e," "))"reference"===n?t|=2:"inline"===n?t|=1:"default"===n?t|=4:"static"===n?t|=8:n.startsWith("prefix(")&&n.endsWith(")")&&(r=n.slice(7,-1));return[t,r]}(e.params);if(i|=64,r.context.reference&&(t|=2),n){if(!jr.test(n))throw new Error(`The prefix "${n}" is invalid. Prefixes must be lowercase ASCII letters (a-z) only.`);c.prefix=n}return y(e.nodes,r=>{if("at-rule"===r.kind&&"@keyframes"===r.name)return c.addKeyframes(r),b.Skip;if("comment"===r.kind)return;if("declaration"===r.kind&&r.property.startsWith("--"))return void c.add(s(r.property),r.value??"",t,r.src);let n=F([S(e.name,e.params,[r])]).split("\n").map((e,t,r)=>`${0===t||t>=r.length-2?" ":">"} ${e}`).join("\n");throw new Error(`\`@theme\` blocks must only contain custom properties or \`@keyframes\`.\n\n${n}`)}),h?b.ReplaceSkip([]):(h=A(":root, :host",[]),h.src=e.src,b.ReplaceSkip(h))}});let $=yt(c,m?.src);if(a&&($.important=a),w.length>0)for(let e of w)$.invalidCandidates.add(e);i|=await zr({designSystem:$,base:t,ast:e,loadModule:n,sources:v});for(let e of u.keys())$.variants.static(e,()=>{});for(let e of function(e,t){let r=new Set,n=new Set,o=[];function i(a,l=[]){if(e.has(a)&&!r.has(a)){n.has(a)&&t.onCircularDependency?.(l,a),n.add(a);for(let t of e.get(a)??[])l.push(a),i(t,l),l.pop();r.add(a),n.delete(a),o.push(a)}}for(let t of e.keys())i(t);return o}(f,{onCircularDependency(e,t){let r=F(e.map((r,n)=>S("@custom-variant",r,[S("@variant",e[n+1]??t,[])]))).replaceAll(";"," { … }").replace(`@custom-variant ${t} {`,`@custom-variant ${t} { /* ← */`);throw new Error(`Circular dependency detected in custom variants:\n\n${r}`)}}))u.get(e)?.($);for(let e of p)e($);if(h){let t=[];for(let[e,r]of $.theme.entries()){if(2&r.options)continue;let n=j(l(e),r.value);n.src=r.src,t.push(n)}let r=$.theme.getKeyframes();for(let t of r)e.push(V({theme:!0},[K([t])]));h.nodes=[V({theme:!0},t)]}if(i|=bt(e,$),i|=pt(e,$),i|=jt(e,$),m){let e=m;e.kind="context",e.context={}}return y(e,e=>{if("at-rule"===e.kind)return"@utility"===e.name?b.Replace([]):b.Skip}),{designSystem:$,ast:e,sources:v,root:x,utilitiesNode:m,features:i,inlineCandidates:k}}async function Er(t,r={}){let o=n(t,{from:r.from}),i=await async function(e,t={}){let{designSystem:r,ast:n,sources:o,root:i,utilitiesNode:a,features:l,inlineCandidates:s}=await Kr(e,t);function c(e){r.invalidCandidates.add(e)}n.unshift(T("! tailwindcss v4.3.1 | MIT License | https://tailwindcss.com "));let u=new Set,d=null,f=0,p=!1;for(let e of s)r.invalidCandidates.has(e)||(u.add(e),p=!0);return{sources:o,root:i,features:l,build(o){if(0===l)return e;if(!a)return d??=O(n,r,t.polyfills),d;let i=p,s=!1;p=!1;let h=u.size;for(let e of o)if(!r.invalidCandidates.has(e))if("-"===e[0]&&"-"===e[1]){let t=r.theme.markUsedVariable(e);i||=t,s||=t}else u.add(e),i||=u.size!==h;if(!i)return d??=O(n,r,t.polyfills),d;let m=$t(u,r,{onInvalidCandidate:c}).astNodes;return t.from&&y(m,e=>{e.src??=a.src}),s||f!==m.length?(f=m.length,a.nodes=m,d=O(n,r,t.polyfills),d):(d??=O(n,r,t.polyfills),d)}}}(o,r),a=o,l=t;return{...i,build(e){let t=i.build(e);return t===a||(l=F(t,!!r.from),a=t),l},buildSourceMap:()=>function({ast:t}){let r=new f(t=>e(t.code)),n=new f(e=>({url:e.file,content:e.code,ignore:!1})),o={file:null,sources:[],mappings:[]};y(t,e=>{if(!e.src||!e.dst)return;let t=n.get(e.src[0]);if(!t.content)return;let i=r.get(e.src[0]),a=r.get(e.dst[0]),l=t.content.slice(e.src[1],e.src[2]),s=0;for(let r of l.split("\n")){if(""!==r.trim()){let r=i.find(e.src[1]+s),n=a.find(e.dst[1]);o.mappings.push({name:null,originalPosition:{source:t,...r},generatedPosition:n})}s+=r.length,s+=1}let c=i.find(e.src[2]),u=a.find(e.dst[2]);o.mappings.push({name:null,originalPosition:{source:t,...c},generatedPosition:u})});for(let e of r.keys())o.sources.push(n.get(e));return o.mappings.sort((e,t)=>e.generatedPosition.line-t.generatedPosition.line||e.generatedPosition.column-t.generatedPosition.column||(e.originalPosition?.line??0)-(t.originalPosition?.line??0)||(e.originalPosition?.column??0)-(t.originalPosition?.column??0)),o}({ast:a})}}var Nr,Or={index:"@layer theme, base, components, utilities;\n\n@import './theme.css' layer(theme);\n@import './preflight.css' layer(base);\n@import './utilities.css' layer(utilities);\n",preflight:"/*\n 1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4)\n 2. Remove default margins and padding\n 3. Reset all borders.\n*/\n\n*,\n::after,\n::before,\n::backdrop,\n::file-selector-button {\n box-sizing: border-box; /* 1 */\n margin: 0; /* 2 */\n padding: 0; /* 2 */\n border: 0 solid; /* 3 */\n}\n\n/*\n 1. Use a consistent sensible line-height in all browsers.\n 2. Prevent adjustments of font size after orientation changes in iOS.\n 3. Use a more readable tab size.\n 4. Use the user's configured `sans` font-family by default.\n 5. Use the user's configured `sans` font-feature-settings by default.\n 6. Use the user's configured `sans` font-variation-settings by default.\n 7. Disable tap highlights on iOS.\n*/\n\nhtml,\n:host {\n line-height: 1.5; /* 1 */\n -webkit-text-size-adjust: 100%; /* 2 */\n tab-size: 4; /* 3 */\n font-family: --theme(\n --default-font-family,\n ui-sans-serif,\n system-ui,\n sans-serif,\n 'Apple Color Emoji',\n 'Segoe UI Emoji',\n 'Segoe UI Symbol',\n 'Noto Color Emoji'\n ); /* 4 */\n font-feature-settings: --theme(--default-font-feature-settings, normal); /* 5 */\n font-variation-settings: --theme(--default-font-variation-settings, normal); /* 6 */\n -webkit-tap-highlight-color: transparent; /* 7 */\n}\n\n/*\n 1. Add the correct height in Firefox.\n 2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655)\n 3. Reset the default border style to a 1px solid border.\n*/\n\nhr {\n height: 0; /* 1 */\n color: inherit; /* 2 */\n border-top-width: 1px; /* 3 */\n}\n\n/*\n Add the correct text decoration in Chrome, Edge, and Safari.\n*/\n\nabbr:where([title]) {\n -webkit-text-decoration: underline dotted;\n text-decoration: underline dotted;\n}\n\n/*\n Remove the default font size and weight for headings.\n*/\n\nh1,\nh2,\nh3,\nh4,\nh5,\nh6 {\n font-size: inherit;\n font-weight: inherit;\n}\n\n/*\n Reset links to optimize for opt-in styling instead of opt-out.\n*/\n\na {\n color: inherit;\n -webkit-text-decoration: inherit;\n text-decoration: inherit;\n}\n\n/*\n Add the correct font weight in Edge and Safari.\n*/\n\nb,\nstrong {\n font-weight: bolder;\n}\n\n/*\n 1. Use the user's configured `mono` font-family by default.\n 2. Use the user's configured `mono` font-feature-settings by default.\n 3. Use the user's configured `mono` font-variation-settings by default.\n 4. Correct the odd `em` font sizing in all browsers.\n*/\n\ncode,\nkbd,\nsamp,\npre {\n font-family: --theme(\n --default-mono-font-family,\n ui-monospace,\n SFMono-Regular,\n Menlo,\n Monaco,\n Consolas,\n 'Liberation Mono',\n 'Courier New',\n monospace\n ); /* 1 */\n font-feature-settings: --theme(--default-mono-font-feature-settings, normal); /* 2 */\n font-variation-settings: --theme(--default-mono-font-variation-settings, normal); /* 3 */\n font-size: 1em; /* 4 */\n}\n\n/*\n Add the correct font size in all browsers.\n*/\n\nsmall {\n font-size: 80%;\n}\n\n/*\n Prevent `sub` and `sup` elements from affecting the line height in all browsers.\n*/\n\nsub,\nsup {\n font-size: 75%;\n line-height: 0;\n position: relative;\n vertical-align: baseline;\n}\n\nsub {\n bottom: -0.25em;\n}\n\nsup {\n top: -0.5em;\n}\n\n/*\n 1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297)\n 2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016)\n 3. Remove gaps between table borders by default.\n*/\n\ntable {\n text-indent: 0; /* 1 */\n border-color: inherit; /* 2 */\n border-collapse: collapse; /* 3 */\n}\n\n/*\n Use the modern Firefox focus style for all focusable elements.\n*/\n\n:-moz-focusring {\n outline: auto;\n}\n\n/*\n Add the correct vertical alignment in Chrome and Firefox.\n*/\n\nprogress {\n vertical-align: baseline;\n}\n\n/*\n Add the correct display in Chrome and Safari.\n*/\n\nsummary {\n display: list-item;\n}\n\n/*\n Make lists unstyled by default.\n*/\n\nol,\nul,\nmenu {\n list-style: none;\n}\n\n/*\n 1. Make replaced elements `display: block` by default. (https://github.com/mozdevs/cssremedy/issues/14)\n 2. Add `vertical-align: middle` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210)\n This can trigger a poorly considered lint error in some tools but is included by design.\n*/\n\nimg,\nsvg,\nvideo,\ncanvas,\naudio,\niframe,\nembed,\nobject {\n display: block; /* 1 */\n vertical-align: middle; /* 2 */\n}\n\n/*\n Constrain images and videos to the parent width and preserve their intrinsic aspect ratio. (https://github.com/mozdevs/cssremedy/issues/14)\n*/\n\nimg,\nvideo {\n max-width: 100%;\n height: auto;\n}\n\n/*\n 1. Inherit font styles in all browsers.\n 2. Remove border radius in all browsers.\n 3. Remove background color in all browsers.\n 4. Ensure consistent opacity for disabled states in all browsers.\n*/\n\nbutton,\ninput,\nselect,\noptgroup,\ntextarea,\n::file-selector-button {\n font: inherit; /* 1 */\n font-feature-settings: inherit; /* 1 */\n font-variation-settings: inherit; /* 1 */\n letter-spacing: inherit; /* 1 */\n color: inherit; /* 1 */\n border-radius: 0; /* 2 */\n background-color: transparent; /* 3 */\n opacity: 1; /* 4 */\n}\n\n/*\n Restore default font weight.\n*/\n\n:where(select:is([multiple], [size])) optgroup {\n font-weight: bolder;\n}\n\n/*\n Restore indentation.\n*/\n\n:where(select:is([multiple], [size])) optgroup option {\n padding-inline-start: 20px;\n}\n\n/*\n Restore space after button.\n*/\n\n::file-selector-button {\n margin-inline-end: 4px;\n}\n\n/*\n Reset the default placeholder opacity in Firefox. (https://github.com/tailwindlabs/tailwindcss/issues/3300)\n*/\n\n::placeholder {\n opacity: 1;\n}\n\n/*\n Set the default placeholder color to a semi-transparent version of the current text color in browsers that do not\n crash when using `color-mix(…)` with `currentcolor`. (https://github.com/tailwindlabs/tailwindcss/issues/17194)\n*/\n\n@supports (not (-webkit-appearance: -apple-pay-button)) /* Not Safari */ or\n (contain-intrinsic-size: 1px) /* Safari 17+ */ {\n ::placeholder {\n color: color-mix(in oklab, currentcolor 50%, transparent);\n }\n}\n\n/*\n Prevent resizing textareas horizontally by default.\n*/\n\ntextarea {\n resize: vertical;\n}\n\n/*\n Remove the inner padding in Chrome and Safari on macOS.\n*/\n\n::-webkit-search-decoration {\n -webkit-appearance: none;\n}\n\n/*\n 1. Ensure date/time inputs have the same height when empty in iOS Safari.\n 2. Ensure text alignment can be changed on date/time inputs in iOS Safari.\n*/\n\n::-webkit-date-and-time-value {\n min-height: 1lh; /* 1 */\n text-align: inherit; /* 2 */\n}\n\n/*\n Prevent height from changing on date/time inputs in macOS Safari when the input is set to `display: block`.\n*/\n\n::-webkit-datetime-edit {\n display: inline-flex;\n}\n\n/*\n Remove excess padding from pseudo-elements in date/time inputs to ensure consistent height across browsers.\n*/\n\n::-webkit-datetime-edit-fields-wrapper {\n padding: 0;\n}\n\n::-webkit-datetime-edit,\n::-webkit-datetime-edit-year-field,\n::-webkit-datetime-edit-month-field,\n::-webkit-datetime-edit-day-field,\n::-webkit-datetime-edit-hour-field,\n::-webkit-datetime-edit-minute-field,\n::-webkit-datetime-edit-second-field,\n::-webkit-datetime-edit-millisecond-field,\n::-webkit-datetime-edit-meridiem-field {\n padding-block: 0;\n}\n\n/*\n Center dropdown marker shown on inputs with paired ``s in Chrome. (https://github.com/tailwindlabs/tailwindcss/issues/18499)\n*/\n\n::-webkit-calendar-picker-indicator {\n line-height: 1;\n}\n\n/*\n Remove the additional `:invalid` styles in Firefox. (https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737)\n*/\n\n:-moz-ui-invalid {\n box-shadow: none;\n}\n\n/*\n Correct the inability to style the border radius in iOS Safari.\n*/\n\nbutton,\ninput:where([type='button'], [type='reset'], [type='submit']),\n::file-selector-button {\n appearance: button;\n}\n\n/*\n Correct the cursor style of increment and decrement buttons in Safari.\n*/\n\n::-webkit-inner-spin-button,\n::-webkit-outer-spin-button {\n height: auto;\n}\n\n/*\n Make elements with the HTML hidden attribute stay hidden by default.\n*/\n\n[hidden]:where(:not([hidden='until-found'])) {\n display: none !important;\n}\n",theme:"@theme default {\n --font-sans:\n ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol',\n 'Noto Color Emoji';\n --font-serif: ui-serif, Georgia, Cambria, 'Times New Roman', Times, serif;\n --font-mono:\n ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New',\n monospace;\n\n --color-red-50: oklch(97.1% 0.013 17.38);\n --color-red-100: oklch(93.6% 0.032 17.717);\n --color-red-200: oklch(88.5% 0.062 18.334);\n --color-red-300: oklch(80.8% 0.114 19.571);\n --color-red-400: oklch(70.4% 0.191 22.216);\n --color-red-500: oklch(63.7% 0.237 25.331);\n --color-red-600: oklch(57.7% 0.245 27.325);\n --color-red-700: oklch(50.5% 0.213 27.518);\n --color-red-800: oklch(44.4% 0.177 26.899);\n --color-red-900: oklch(39.6% 0.141 25.723);\n --color-red-950: oklch(25.8% 0.092 26.042);\n\n --color-orange-50: oklch(98% 0.016 73.684);\n --color-orange-100: oklch(95.4% 0.038 75.164);\n --color-orange-200: oklch(90.1% 0.076 70.697);\n --color-orange-300: oklch(83.7% 0.128 66.29);\n --color-orange-400: oklch(75% 0.183 55.934);\n --color-orange-500: oklch(70.5% 0.213 47.604);\n --color-orange-600: oklch(64.6% 0.222 41.116);\n --color-orange-700: oklch(55.3% 0.195 38.402);\n --color-orange-800: oklch(47% 0.157 37.304);\n --color-orange-900: oklch(40.8% 0.123 38.172);\n --color-orange-950: oklch(26.6% 0.079 36.259);\n\n --color-amber-50: oklch(98.7% 0.022 95.277);\n --color-amber-100: oklch(96.2% 0.059 95.617);\n --color-amber-200: oklch(92.4% 0.12 95.746);\n --color-amber-300: oklch(87.9% 0.169 91.605);\n --color-amber-400: oklch(82.8% 0.189 84.429);\n --color-amber-500: oklch(76.9% 0.188 70.08);\n --color-amber-600: oklch(66.6% 0.179 58.318);\n --color-amber-700: oklch(55.5% 0.163 48.998);\n --color-amber-800: oklch(47.3% 0.137 46.201);\n --color-amber-900: oklch(41.4% 0.112 45.904);\n --color-amber-950: oklch(27.9% 0.077 45.635);\n\n --color-yellow-50: oklch(98.7% 0.026 102.212);\n --color-yellow-100: oklch(97.3% 0.071 103.193);\n --color-yellow-200: oklch(94.5% 0.129 101.54);\n --color-yellow-300: oklch(90.5% 0.182 98.111);\n --color-yellow-400: oklch(85.2% 0.199 91.936);\n --color-yellow-500: oklch(79.5% 0.184 86.047);\n --color-yellow-600: oklch(68.1% 0.162 75.834);\n --color-yellow-700: oklch(55.4% 0.135 66.442);\n --color-yellow-800: oklch(47.6% 0.114 61.907);\n --color-yellow-900: oklch(42.1% 0.095 57.708);\n --color-yellow-950: oklch(28.6% 0.066 53.813);\n\n --color-lime-50: oklch(98.6% 0.031 120.757);\n --color-lime-100: oklch(96.7% 0.067 122.328);\n --color-lime-200: oklch(93.8% 0.127 124.321);\n --color-lime-300: oklch(89.7% 0.196 126.665);\n --color-lime-400: oklch(84.1% 0.238 128.85);\n --color-lime-500: oklch(76.8% 0.233 130.85);\n --color-lime-600: oklch(64.8% 0.2 131.684);\n --color-lime-700: oklch(53.2% 0.157 131.589);\n --color-lime-800: oklch(45.3% 0.124 130.933);\n --color-lime-900: oklch(40.5% 0.101 131.063);\n --color-lime-950: oklch(27.4% 0.072 132.109);\n\n --color-green-50: oklch(98.2% 0.018 155.826);\n --color-green-100: oklch(96.2% 0.044 156.743);\n --color-green-200: oklch(92.5% 0.084 155.995);\n --color-green-300: oklch(87.1% 0.15 154.449);\n --color-green-400: oklch(79.2% 0.209 151.711);\n --color-green-500: oklch(72.3% 0.219 149.579);\n --color-green-600: oklch(62.7% 0.194 149.214);\n --color-green-700: oklch(52.7% 0.154 150.069);\n --color-green-800: oklch(44.8% 0.119 151.328);\n --color-green-900: oklch(39.3% 0.095 152.535);\n --color-green-950: oklch(26.6% 0.065 152.934);\n\n --color-emerald-50: oklch(97.9% 0.021 166.113);\n --color-emerald-100: oklch(95% 0.052 163.051);\n --color-emerald-200: oklch(90.5% 0.093 164.15);\n --color-emerald-300: oklch(84.5% 0.143 164.978);\n --color-emerald-400: oklch(76.5% 0.177 163.223);\n --color-emerald-500: oklch(69.6% 0.17 162.48);\n --color-emerald-600: oklch(59.6% 0.145 163.225);\n --color-emerald-700: oklch(50.8% 0.118 165.612);\n --color-emerald-800: oklch(43.2% 0.095 166.913);\n --color-emerald-900: oklch(37.8% 0.077 168.94);\n --color-emerald-950: oklch(26.2% 0.051 172.552);\n\n --color-teal-50: oklch(98.4% 0.014 180.72);\n --color-teal-100: oklch(95.3% 0.051 180.801);\n --color-teal-200: oklch(91% 0.096 180.426);\n --color-teal-300: oklch(85.5% 0.138 181.071);\n --color-teal-400: oklch(77.7% 0.152 181.912);\n --color-teal-500: oklch(70.4% 0.14 182.503);\n --color-teal-600: oklch(60% 0.118 184.704);\n --color-teal-700: oklch(51.1% 0.096 186.391);\n --color-teal-800: oklch(43.7% 0.078 188.216);\n --color-teal-900: oklch(38.6% 0.063 188.416);\n --color-teal-950: oklch(27.7% 0.046 192.524);\n\n --color-cyan-50: oklch(98.4% 0.019 200.873);\n --color-cyan-100: oklch(95.6% 0.045 203.388);\n --color-cyan-200: oklch(91.7% 0.08 205.041);\n --color-cyan-300: oklch(86.5% 0.127 207.078);\n --color-cyan-400: oklch(78.9% 0.154 211.53);\n --color-cyan-500: oklch(71.5% 0.143 215.221);\n --color-cyan-600: oklch(60.9% 0.126 221.723);\n --color-cyan-700: oklch(52% 0.105 223.128);\n --color-cyan-800: oklch(45% 0.085 224.283);\n --color-cyan-900: oklch(39.8% 0.07 227.392);\n --color-cyan-950: oklch(30.2% 0.056 229.695);\n\n --color-sky-50: oklch(97.7% 0.013 236.62);\n --color-sky-100: oklch(95.1% 0.026 236.824);\n --color-sky-200: oklch(90.1% 0.058 230.902);\n --color-sky-300: oklch(82.8% 0.111 230.318);\n --color-sky-400: oklch(74.6% 0.16 232.661);\n --color-sky-500: oklch(68.5% 0.169 237.323);\n --color-sky-600: oklch(58.8% 0.158 241.966);\n --color-sky-700: oklch(50% 0.134 242.749);\n --color-sky-800: oklch(44.3% 0.11 240.79);\n --color-sky-900: oklch(39.1% 0.09 240.876);\n --color-sky-950: oklch(29.3% 0.066 243.157);\n\n --color-blue-50: oklch(97% 0.014 254.604);\n --color-blue-100: oklch(93.2% 0.032 255.585);\n --color-blue-200: oklch(88.2% 0.059 254.128);\n --color-blue-300: oklch(80.9% 0.105 251.813);\n --color-blue-400: oklch(70.7% 0.165 254.624);\n --color-blue-500: oklch(62.3% 0.214 259.815);\n --color-blue-600: oklch(54.6% 0.245 262.881);\n --color-blue-700: oklch(48.8% 0.243 264.376);\n --color-blue-800: oklch(42.4% 0.199 265.638);\n --color-blue-900: oklch(37.9% 0.146 265.522);\n --color-blue-950: oklch(28.2% 0.091 267.935);\n\n --color-indigo-50: oklch(96.2% 0.018 272.314);\n --color-indigo-100: oklch(93% 0.034 272.788);\n --color-indigo-200: oklch(87% 0.065 274.039);\n --color-indigo-300: oklch(78.5% 0.115 274.713);\n --color-indigo-400: oklch(67.3% 0.182 276.935);\n --color-indigo-500: oklch(58.5% 0.233 277.117);\n --color-indigo-600: oklch(51.1% 0.262 276.966);\n --color-indigo-700: oklch(45.7% 0.24 277.023);\n --color-indigo-800: oklch(39.8% 0.195 277.366);\n --color-indigo-900: oklch(35.9% 0.144 278.697);\n --color-indigo-950: oklch(25.7% 0.09 281.288);\n\n --color-violet-50: oklch(96.9% 0.016 293.756);\n --color-violet-100: oklch(94.3% 0.029 294.588);\n --color-violet-200: oklch(89.4% 0.057 293.283);\n --color-violet-300: oklch(81.1% 0.111 293.571);\n --color-violet-400: oklch(70.2% 0.183 293.541);\n --color-violet-500: oklch(60.6% 0.25 292.717);\n --color-violet-600: oklch(54.1% 0.281 293.009);\n --color-violet-700: oklch(49.1% 0.27 292.581);\n --color-violet-800: oklch(43.2% 0.232 292.759);\n --color-violet-900: oklch(38% 0.189 293.745);\n --color-violet-950: oklch(28.3% 0.141 291.089);\n\n --color-purple-50: oklch(97.7% 0.014 308.299);\n --color-purple-100: oklch(94.6% 0.033 307.174);\n --color-purple-200: oklch(90.2% 0.063 306.703);\n --color-purple-300: oklch(82.7% 0.119 306.383);\n --color-purple-400: oklch(71.4% 0.203 305.504);\n --color-purple-500: oklch(62.7% 0.265 303.9);\n --color-purple-600: oklch(55.8% 0.288 302.321);\n --color-purple-700: oklch(49.6% 0.265 301.924);\n --color-purple-800: oklch(43.8% 0.218 303.724);\n --color-purple-900: oklch(38.1% 0.176 304.987);\n --color-purple-950: oklch(29.1% 0.149 302.717);\n\n --color-fuchsia-50: oklch(97.7% 0.017 320.058);\n --color-fuchsia-100: oklch(95.2% 0.037 318.852);\n --color-fuchsia-200: oklch(90.3% 0.076 319.62);\n --color-fuchsia-300: oklch(83.3% 0.145 321.434);\n --color-fuchsia-400: oklch(74% 0.238 322.16);\n --color-fuchsia-500: oklch(66.7% 0.295 322.15);\n --color-fuchsia-600: oklch(59.1% 0.293 322.896);\n --color-fuchsia-700: oklch(51.8% 0.253 323.949);\n --color-fuchsia-800: oklch(45.2% 0.211 324.591);\n --color-fuchsia-900: oklch(40.1% 0.17 325.612);\n --color-fuchsia-950: oklch(29.3% 0.136 325.661);\n\n --color-pink-50: oklch(97.1% 0.014 343.198);\n --color-pink-100: oklch(94.8% 0.028 342.258);\n --color-pink-200: oklch(89.9% 0.061 343.231);\n --color-pink-300: oklch(82.3% 0.12 346.018);\n --color-pink-400: oklch(71.8% 0.202 349.761);\n --color-pink-500: oklch(65.6% 0.241 354.308);\n --color-pink-600: oklch(59.2% 0.249 0.584);\n --color-pink-700: oklch(52.5% 0.223 3.958);\n --color-pink-800: oklch(45.9% 0.187 3.815);\n --color-pink-900: oklch(40.8% 0.153 2.432);\n --color-pink-950: oklch(28.4% 0.109 3.907);\n\n --color-rose-50: oklch(96.9% 0.015 12.422);\n --color-rose-100: oklch(94.1% 0.03 12.58);\n --color-rose-200: oklch(89.2% 0.058 10.001);\n --color-rose-300: oklch(81% 0.117 11.638);\n --color-rose-400: oklch(71.2% 0.194 13.428);\n --color-rose-500: oklch(64.5% 0.246 16.439);\n --color-rose-600: oklch(58.6% 0.253 17.585);\n --color-rose-700: oklch(51.4% 0.222 16.935);\n --color-rose-800: oklch(45.5% 0.188 13.697);\n --color-rose-900: oklch(41% 0.159 10.272);\n --color-rose-950: oklch(27.1% 0.105 12.094);\n\n --color-slate-50: oklch(98.4% 0.003 247.858);\n --color-slate-100: oklch(96.8% 0.007 247.896);\n --color-slate-200: oklch(92.9% 0.013 255.508);\n --color-slate-300: oklch(86.9% 0.022 252.894);\n --color-slate-400: oklch(70.4% 0.04 256.788);\n --color-slate-500: oklch(55.4% 0.046 257.417);\n --color-slate-600: oklch(44.6% 0.043 257.281);\n --color-slate-700: oklch(37.2% 0.044 257.287);\n --color-slate-800: oklch(27.9% 0.041 260.031);\n --color-slate-900: oklch(20.8% 0.042 265.755);\n --color-slate-950: oklch(12.9% 0.042 264.695);\n\n --color-gray-50: oklch(98.5% 0.002 247.839);\n --color-gray-100: oklch(96.7% 0.003 264.542);\n --color-gray-200: oklch(92.8% 0.006 264.531);\n --color-gray-300: oklch(87.2% 0.01 258.338);\n --color-gray-400: oklch(70.7% 0.022 261.325);\n --color-gray-500: oklch(55.1% 0.027 264.364);\n --color-gray-600: oklch(44.6% 0.03 256.802);\n --color-gray-700: oklch(37.3% 0.034 259.733);\n --color-gray-800: oklch(27.8% 0.033 256.848);\n --color-gray-900: oklch(21% 0.034 264.665);\n --color-gray-950: oklch(13% 0.028 261.692);\n\n --color-zinc-50: oklch(98.5% 0 0);\n --color-zinc-100: oklch(96.7% 0.001 286.375);\n --color-zinc-200: oklch(92% 0.004 286.32);\n --color-zinc-300: oklch(87.1% 0.006 286.286);\n --color-zinc-400: oklch(70.5% 0.015 286.067);\n --color-zinc-500: oklch(55.2% 0.016 285.938);\n --color-zinc-600: oklch(44.2% 0.017 285.786);\n --color-zinc-700: oklch(37% 0.013 285.805);\n --color-zinc-800: oklch(27.4% 0.006 286.033);\n --color-zinc-900: oklch(21% 0.006 285.885);\n --color-zinc-950: oklch(14.1% 0.005 285.823);\n\n --color-neutral-50: oklch(98.5% 0 0);\n --color-neutral-100: oklch(97% 0 0);\n --color-neutral-200: oklch(92.2% 0 0);\n --color-neutral-300: oklch(87% 0 0);\n --color-neutral-400: oklch(70.8% 0 0);\n --color-neutral-500: oklch(55.6% 0 0);\n --color-neutral-600: oklch(43.9% 0 0);\n --color-neutral-700: oklch(37.1% 0 0);\n --color-neutral-800: oklch(26.9% 0 0);\n --color-neutral-900: oklch(20.5% 0 0);\n --color-neutral-950: oklch(14.5% 0 0);\n\n --color-stone-50: oklch(98.5% 0.001 106.423);\n --color-stone-100: oklch(97% 0.001 106.424);\n --color-stone-200: oklch(92.3% 0.003 48.717);\n --color-stone-300: oklch(86.9% 0.005 56.366);\n --color-stone-400: oklch(70.9% 0.01 56.259);\n --color-stone-500: oklch(55.3% 0.013 58.071);\n --color-stone-600: oklch(44.4% 0.011 73.639);\n --color-stone-700: oklch(37.4% 0.01 67.558);\n --color-stone-800: oklch(26.8% 0.007 34.298);\n --color-stone-900: oklch(21.6% 0.006 56.043);\n --color-stone-950: oklch(14.7% 0.004 49.25);\n\n --color-mauve-50: oklch(98.5% 0 0);\n --color-mauve-100: oklch(96% 0.003 325.6);\n --color-mauve-200: oklch(92.2% 0.005 325.62);\n --color-mauve-300: oklch(86.5% 0.012 325.68);\n --color-mauve-400: oklch(71.1% 0.019 323.02);\n --color-mauve-500: oklch(54.2% 0.034 322.5);\n --color-mauve-600: oklch(43.5% 0.029 321.78);\n --color-mauve-700: oklch(36.4% 0.029 323.89);\n --color-mauve-800: oklch(26.3% 0.024 320.12);\n --color-mauve-900: oklch(21.2% 0.019 322.12);\n --color-mauve-950: oklch(14.5% 0.008 326);\n\n --color-olive-50: oklch(98.8% 0.003 106.5);\n --color-olive-100: oklch(96.6% 0.005 106.5);\n --color-olive-200: oklch(93% 0.007 106.5);\n --color-olive-300: oklch(88% 0.011 106.6);\n --color-olive-400: oklch(73.7% 0.021 106.9);\n --color-olive-500: oklch(58% 0.031 107.3);\n --color-olive-600: oklch(46.6% 0.025 107.3);\n --color-olive-700: oklch(39.4% 0.023 107.4);\n --color-olive-800: oklch(28.6% 0.016 107.4);\n --color-olive-900: oklch(22.8% 0.013 107.4);\n --color-olive-950: oklch(15.3% 0.006 107.1);\n\n --color-mist-50: oklch(98.7% 0.002 197.1);\n --color-mist-100: oklch(96.3% 0.002 197.1);\n --color-mist-200: oklch(92.5% 0.005 214.3);\n --color-mist-300: oklch(87.2% 0.007 219.6);\n --color-mist-400: oklch(72.3% 0.014 214.4);\n --color-mist-500: oklch(56% 0.021 213.5);\n --color-mist-600: oklch(45% 0.017 213.2);\n --color-mist-700: oklch(37.8% 0.015 216);\n --color-mist-800: oklch(27.5% 0.011 216.9);\n --color-mist-900: oklch(21.8% 0.008 223.9);\n --color-mist-950: oklch(14.8% 0.004 228.8);\n\n --color-taupe-50: oklch(98.6% 0.002 67.8);\n --color-taupe-100: oklch(96% 0.002 17.2);\n --color-taupe-200: oklch(92.2% 0.005 34.3);\n --color-taupe-300: oklch(86.8% 0.007 39.5);\n --color-taupe-400: oklch(71.4% 0.014 41.2);\n --color-taupe-500: oklch(54.7% 0.021 43.1);\n --color-taupe-600: oklch(43.8% 0.017 39.3);\n --color-taupe-700: oklch(36.7% 0.016 35.7);\n --color-taupe-800: oklch(26.8% 0.011 36.5);\n --color-taupe-900: oklch(21.4% 0.009 43.1);\n --color-taupe-950: oklch(14.7% 0.004 49.3);\n\n --color-black: #000;\n --color-white: #fff;\n\n --spacing: 0.25rem;\n\n --breakpoint-sm: 40rem;\n --breakpoint-md: 48rem;\n --breakpoint-lg: 64rem;\n --breakpoint-xl: 80rem;\n --breakpoint-2xl: 96rem;\n\n --container-3xs: 16rem;\n --container-2xs: 18rem;\n --container-xs: 20rem;\n --container-sm: 24rem;\n --container-md: 28rem;\n --container-lg: 32rem;\n --container-xl: 36rem;\n --container-2xl: 42rem;\n --container-3xl: 48rem;\n --container-4xl: 56rem;\n --container-5xl: 64rem;\n --container-6xl: 72rem;\n --container-7xl: 80rem;\n\n --text-xs: 0.75rem;\n --text-xs--line-height: calc(1 / 0.75);\n --text-sm: 0.875rem;\n --text-sm--line-height: calc(1.25 / 0.875);\n --text-base: 1rem;\n --text-base--line-height: calc(1.5 / 1);\n --text-lg: 1.125rem;\n --text-lg--line-height: calc(1.75 / 1.125);\n --text-xl: 1.25rem;\n --text-xl--line-height: calc(1.75 / 1.25);\n --text-2xl: 1.5rem;\n --text-2xl--line-height: calc(2 / 1.5);\n --text-3xl: 1.875rem;\n --text-3xl--line-height: calc(2.25 / 1.875);\n --text-4xl: 2.25rem;\n --text-4xl--line-height: calc(2.5 / 2.25);\n --text-5xl: 3rem;\n --text-5xl--line-height: 1;\n --text-6xl: 3.75rem;\n --text-6xl--line-height: 1;\n --text-7xl: 4.5rem;\n --text-7xl--line-height: 1;\n --text-8xl: 6rem;\n --text-8xl--line-height: 1;\n --text-9xl: 8rem;\n --text-9xl--line-height: 1;\n\n --font-weight-thin: 100;\n --font-weight-extralight: 200;\n --font-weight-light: 300;\n --font-weight-normal: 400;\n --font-weight-medium: 500;\n --font-weight-semibold: 600;\n --font-weight-bold: 700;\n --font-weight-extrabold: 800;\n --font-weight-black: 900;\n\n --tracking-tighter: -0.05em;\n --tracking-tight: -0.025em;\n --tracking-normal: 0em;\n --tracking-wide: 0.025em;\n --tracking-wider: 0.05em;\n --tracking-widest: 0.1em;\n\n --leading-tight: 1.25;\n --leading-snug: 1.375;\n --leading-normal: 1.5;\n --leading-relaxed: 1.625;\n --leading-loose: 2;\n\n --radius-xs: 0.125rem;\n --radius-sm: 0.25rem;\n --radius-md: 0.375rem;\n --radius-lg: 0.5rem;\n --radius-xl: 0.75rem;\n --radius-2xl: 1rem;\n --radius-3xl: 1.5rem;\n --radius-4xl: 2rem;\n\n --shadow-2xs: 0 1px rgb(0 0 0 / 0.05);\n --shadow-xs: 0 1px 2px 0 rgb(0 0 0 / 0.05);\n --shadow-sm: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);\n --shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);\n --shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);\n --shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);\n --shadow-2xl: 0 25px 50px -12px rgb(0 0 0 / 0.25);\n\n --inset-shadow-2xs: inset 0 1px rgb(0 0 0 / 0.05);\n --inset-shadow-xs: inset 0 1px 1px rgb(0 0 0 / 0.05);\n --inset-shadow-sm: inset 0 2px 4px rgb(0 0 0 / 0.05);\n\n --drop-shadow-xs: 0 1px 1px rgb(0 0 0 / 0.05);\n --drop-shadow-sm: 0 1px 2px rgb(0 0 0 / 0.15);\n --drop-shadow-md: 0 3px 3px rgb(0 0 0 / 0.12);\n --drop-shadow-lg: 0 4px 4px rgb(0 0 0 / 0.15);\n --drop-shadow-xl: 0 9px 7px rgb(0 0 0 / 0.1);\n --drop-shadow-2xl: 0 25px 25px rgb(0 0 0 / 0.15);\n\n --text-shadow-2xs: 0px 1px 0px rgb(0 0 0 / 0.15);\n --text-shadow-xs: 0px 1px 1px rgb(0 0 0 / 0.2);\n --text-shadow-sm:\n 0px 1px 0px rgb(0 0 0 / 0.075), 0px 1px 1px rgb(0 0 0 / 0.075), 0px 2px 2px rgb(0 0 0 / 0.075);\n --text-shadow-md:\n 0px 1px 1px rgb(0 0 0 / 0.1), 0px 1px 2px rgb(0 0 0 / 0.1), 0px 2px 4px rgb(0 0 0 / 0.1);\n --text-shadow-lg:\n 0px 1px 2px rgb(0 0 0 / 0.1), 0px 3px 2px rgb(0 0 0 / 0.1), 0px 4px 8px rgb(0 0 0 / 0.1);\n\n --ease-in: cubic-bezier(0.4, 0, 1, 1);\n --ease-out: cubic-bezier(0, 0, 0.2, 1);\n --ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);\n\n --animate-spin: spin 1s linear infinite;\n --animate-ping: ping 1s cubic-bezier(0, 0, 0.2, 1) infinite;\n --animate-pulse: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;\n --animate-bounce: bounce 1s infinite;\n\n @keyframes spin {\n to {\n transform: rotate(360deg);\n }\n }\n\n @keyframes ping {\n 75%,\n 100% {\n transform: scale(2);\n opacity: 0;\n }\n }\n\n @keyframes pulse {\n 50% {\n opacity: 0.5;\n }\n }\n\n @keyframes bounce {\n 0%,\n 100% {\n transform: translateY(-25%);\n animation-timing-function: cubic-bezier(0.8, 0, 1, 1);\n }\n\n 50% {\n transform: none;\n animation-timing-function: cubic-bezier(0, 0, 0.2, 1);\n }\n }\n\n --blur-xs: 4px;\n --blur-sm: 8px;\n --blur-md: 12px;\n --blur-lg: 16px;\n --blur-xl: 24px;\n --blur-2xl: 40px;\n --blur-3xl: 64px;\n\n --perspective-dramatic: 100px;\n --perspective-near: 300px;\n --perspective-normal: 500px;\n --perspective-midrange: 800px;\n --perspective-distant: 1200px;\n\n --aspect-video: 16 / 9;\n\n --default-transition-duration: 150ms;\n --default-transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n --default-font-family: --theme(--font-sans, initial);\n --default-font-feature-settings: --theme(--font-sans--font-feature-settings, initial);\n --default-font-variation-settings: --theme(--font-sans--font-variation-settings, initial);\n --default-mono-font-family: --theme(--font-mono, initial);\n --default-mono-font-feature-settings: --theme(--font-mono--font-feature-settings, initial);\n --default-mono-font-variation-settings: --theme(--font-mono--font-variation-settings, initial);\n}\n\n/* Deprecated */\n@theme default inline reference {\n --blur: 8px;\n --shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);\n --shadow-inner: inset 0 2px 4px 0 rgb(0 0 0 / 0.05);\n --drop-shadow: 0 1px 2px rgb(0 0 0 / 0.1), 0 1px 1px rgb(0 0 0 / 0.06);\n --radius: 0.25rem;\n --max-width-prose: 65ch;\n}\n",utilities:"@tailwind utilities;\n"},Fr="text/tailwindcss",Ur=new Set,Wr="",Rr=document.createElement("style"),Dr=Promise.resolve(),Lr=1,_r=new class{start(e){performance.mark(`${e} (start)`)}end(e,t){performance.mark(`${e} (end)`),performance.measure(e,{start:`${e} (start)`,end:`${e} (end)`,detail:t})}hit(e,t){performance.mark(e,{detail:t})}error(e){throw performance.mark("(error)",{detail:{error:`${e}`}}),e}};async function Mr(e,t){try{let r=function(){if("tailwindcss"===e)return{path:"virtual:tailwindcss/index.css",base:t,content:Or.index};if("tailwindcss/preflight"===e||"tailwindcss/preflight.css"===e||"./preflight.css"===e)return{path:"virtual:tailwindcss/preflight.css",base:t,content:Or.preflight};if("tailwindcss/theme"===e||"tailwindcss/theme.css"===e||"./theme.css"===e)return{path:"virtual:tailwindcss/theme.css",base:t,content:Or.theme};if("tailwindcss/utilities"===e||"tailwindcss/utilities.css"===e||"./utilities.css"===e)return{path:"virtual:tailwindcss/utilities.css",base:t,content:Or.utilities};throw new Error(`The browser build does not support @import for "${e}"`)}();return _r.hit("Loaded stylesheet",{id:e,base:t,size:r.content.length}),r}catch(r){throw _r.hit("Failed to load stylesheet",{id:e,base:t,error:r.message??r}),r}}async function Br(){throw new Error("The browser build does not support plugins or config files.")}function Ir(e){Dr=Dr.then(async function(){if(!Nr&&"full"!==e)return;let t=Lr++;_r.start(`Build #${t} (${e})`),"full"===e&&await async function(){_r.start("Create compiler"),_r.start("Reading Stylesheets");let e=document.querySelectorAll(`style[type="${Fr}"]`),t="";for(let r of e)qr(r),t+=r.textContent+"\n";if(t.includes("@import")||(t=`@import "tailwindcss";${t}`),_r.end("Reading Stylesheets",{size:t.length,changed:Wr!==t}),Wr!==t){Wr=t,_r.start("Compile CSS");try{Nr=await Er(t,{base:"/",loadStylesheet:Mr,loadModule:Br})}finally{_r.end("Compile CSS"),_r.end("Create compiler")}Ur.clear()}}(),_r.start("Build"),await async function(e){if(!Nr)return;let t=new Set;_r.start("Collect classes");for(let e of document.querySelectorAll("[class]"))for(let r of e.classList)Ur.has(r)||(Ur.add(r),t.add(r));_r.end("Collect classes",{count:t.size}),(0!==t.size||"incremental"!==e)&&(_r.start("Build utilities"),Rr.textContent=Nr.build(Array.from(t)),_r.end("Build utilities"))}(e),_r.end("Build"),_r.end(`Build #${t} (${e})`)}).catch(e=>_r.error(e))}var Pr=new MutationObserver(()=>Ir("full"));function qr(e){Pr.observe(e,{attributes:!0,attributeFilter:["type"],characterData:!0,subtree:!0,childList:!0})}new MutationObserver(e=>{let t=0,r=0;for(let n of e){for(let e of n.addedNodes)e.nodeType===Node.ELEMENT_NODE&&"STYLE"===e.tagName&&e.getAttribute("type")===Fr&&(qr(e),t++);for(let e of n.addedNodes)1===e.nodeType&&e!==Rr&&r++;"attributes"===n.type&&r++}return t>0?Ir("full"):r>0?Ir("incremental"):void 0}).observe(document.documentElement,{attributes:!0,attributeFilter:["class"],childList:!0,subtree:!0}),Ir("full"),document.head.append(Rr)})(); -//# sourceMappingURL=/sm/09ce5b5e7fb0a08eeba4687d728bb1ce6261fcbbfc9813cc9ee3d100bde990ae.map \ No newline at end of file diff --git a/scripts/ci/quality_gate_strict.sh b/scripts/ci/quality_gate_strict.sh index fdf37f689bf..615c337c464 100755 --- a/scripts/ci/quality_gate_strict.sh +++ b/scripts/ci/quality_gate_strict.sh @@ -31,8 +31,19 @@ cargo fmt --all -- --check echo "==> WebUI bundle toolchain" require_node_22 -require_command npm "install npm with Node.js" -npm --version +if ! command -v pnpm &>/dev/null; then + require_command corepack "install Node.js Corepack or pnpm" + corepack enable pnpm +fi +require_command pnpm "enable with: corepack enable pnpm" +pnpm --version + +echo "==> WebUI frontend build" +( + cd crates/ironclaw_webui_v2/frontend + pnpm install --frozen-lockfile + pnpm build +) echo "==> clippy (all warnings)" cargo clippy --locked --all --benches --tests --examples --all-features -- -D warnings diff --git a/scripts/run-reborn-webui.sh b/scripts/run-reborn-webui.sh index 8b5fbf8c962..eae0a56f21d 100755 --- a/scripts/run-reborn-webui.sh +++ b/scripts/run-reborn-webui.sh @@ -52,6 +52,24 @@ fi REPO_ROOT="$(git -C "$(dirname "${BASH_SOURCE[0]}")" rev-parse --show-toplevel)" cd "$REPO_ROOT" +FRONTEND_DIR="$REPO_ROOT/crates/ironclaw_webui_v2/frontend" +if ! command -v pnpm >/dev/null 2>&1; then + if command -v corepack >/dev/null 2>&1; then + corepack enable pnpm + fi +fi +if ! command -v pnpm >/dev/null 2>&1; then + echo "error: pnpm is required to build WebUI v2 assets." >&2 + echo " Install Node 22 from .nvmrc and enable pnpm with: corepack enable pnpm" >&2 + exit 1 +fi +echo "==> Building WebUI v2 frontend assets" +( + cd "$FRONTEND_DIR" + pnpm install --frozen-lockfile + pnpm build +) + export IRONCLAW_REBORN_HOME="${IRONCLAW_REBORN_HOME:-$HOME/.ironclaw-reborn-demo}" # Reject a home inside the repo, which would trip the workspace/skill-root From 01ca85c4b5f660d33d31c2c3258746be9551a0b5 Mon Sep 17 00:00:00 2001 From: BenKurrek Date: Tue, 7 Jul 2026 15:17:10 -0400 Subject: [PATCH 08/12] ci: prepare WebUI frontend for coverage --- .github/workflows/coverage.yml | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index c7ddcc99ca7..567e7c2b091 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -127,6 +127,28 @@ jobs: if: matrix.has_postgres run: echo "DATABASE_URL=postgres://postgres:postgres@localhost/ironclaw_test" >> "$GITHUB_ENV" + - name: Enable pnpm for setup-node cache + if: contains(matrix.flags, '--all-features') + run: corepack enable pnpm + + - name: Install Node.js for WebUI bundle build + if: contains(matrix.flags, '--all-features') + uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4 + with: + node-version: "22" + cache: "pnpm" + cache-dependency-path: crates/ironclaw_webui_v2/frontend/pnpm-lock.yaml + + - name: Enable pnpm + if: contains(matrix.flags, '--all-features') + run: corepack enable pnpm + + - name: Install WebUI frontend dependencies + if: contains(matrix.flags, '--all-features') + run: | + cd crates/ironclaw_webui_v2/frontend + pnpm install --frozen-lockfile + - name: Generate coverage run: cargo llvm-cov ${{ matrix.flags }} --workspace --lcov --output-path lcov.info From b5df0c230d92f812dba71dea3f92a61551d58c16 Mon Sep 17 00:00:00 2001 From: BenKurrek Date: Tue, 7 Jul 2026 17:58:17 -0400 Subject: [PATCH 09/12] test(webui): restore Vite frontend regression coverage --- .../frontend/src/design-system/modal.test.mts | 1 + .../components/markdown-renderer.test.mts | 1 + .../pages/settings/vm-module-harness.test.mts | 1 + .../frontend/src/styles/app.css | 26 +++++++++++++++++++ 4 files changed, 29 insertions(+) diff --git a/crates/ironclaw_webui_v2/frontend/src/design-system/modal.test.mts b/crates/ironclaw_webui_v2/frontend/src/design-system/modal.test.mts index c30a7b00b76..e06c9088f30 100644 --- a/crates/ironclaw_webui_v2/frontend/src/design-system/modal.test.mts +++ b/crates/ironclaw_webui_v2/frontend/src/design-system/modal.test.mts @@ -1,3 +1,4 @@ +// @ts-nocheck import assert from "node:assert/strict"; import { test } from "vitest"; diff --git a/crates/ironclaw_webui_v2/frontend/src/pages/chat/components/markdown-renderer.test.mts b/crates/ironclaw_webui_v2/frontend/src/pages/chat/components/markdown-renderer.test.mts index fed1bb014c9..3c3911febfd 100644 --- a/crates/ironclaw_webui_v2/frontend/src/pages/chat/components/markdown-renderer.test.mts +++ b/crates/ironclaw_webui_v2/frontend/src/pages/chat/components/markdown-renderer.test.mts @@ -1,3 +1,4 @@ +// @ts-nocheck import assert from "node:assert/strict"; import { readFileSync } from "node:fs"; import { test } from "vitest"; diff --git a/crates/ironclaw_webui_v2/frontend/src/pages/settings/vm-module-harness.test.mts b/crates/ironclaw_webui_v2/frontend/src/pages/settings/vm-module-harness.test.mts index 6e9528af26a..39ae6913341 100644 --- a/crates/ironclaw_webui_v2/frontend/src/pages/settings/vm-module-harness.test.mts +++ b/crates/ironclaw_webui_v2/frontend/src/pages/settings/vm-module-harness.test.mts @@ -1,3 +1,4 @@ +// @ts-nocheck import assert from "node:assert/strict"; import { test } from "vitest"; import vm from "node:vm"; diff --git a/crates/ironclaw_webui_v2/frontend/src/styles/app.css b/crates/ironclaw_webui_v2/frontend/src/styles/app.css index 17cb8d93de7..fe2fca9f378 100644 --- a/crates/ironclaw_webui_v2/frontend/src/styles/app.css +++ b/crates/ironclaw_webui_v2/frontend/src/styles/app.css @@ -55,6 +55,7 @@ --v2-text-faint: #8a9aab; --v2-inverse: #ffffff; --v2-ink: #0f1720; + --v2-chat-readable-max-width: 85%; /* Controls */ --v2-select-chevron: url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A//www.w3.org/2000/svg%27%20width%3D%2712%27%20height%3D%2712%27%20viewBox%3D%270%200%2012%2012%27%20fill%3D%27none%27%20stroke%3D%27%235f7183%27%20stroke-width%3D%271.8%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M2.5%204.5%206%208l3.5-3.5%27/%3E%3C/svg%3E"); @@ -460,6 +461,21 @@ input:focus, select:focus, textarea:focus { background: transparent; color: var(--v2-text); } + +.v2-wrap-anywhere { + overflow-wrap: anywhere; +} + +.v2-chat-readable-width { + max-width: 100%; +} + +@media (min-width: 640px) { + .v2-chat-readable-width { + max-width: var(--v2-chat-readable-max-width); + } +} + .markdown-body .hljs-keyword, .markdown-body .hljs-selector-tag, .markdown-body .hljs-built_in, @@ -497,3 +513,13 @@ input:focus, select:focus, textarea:focus { .markdown-body .hljs-doctag { color: var(--v2-danger-text); } + +/* ── Mobile responsive overrides ───────────────────────────────────── */ +@media (max-width: 639.98px) { + .markdown-body table { + display: block; + overflow-x: auto; + max-width: 100%; + table-layout: auto; + } +} From 2777b804e3f1412df554164f6e7a7ce9adb77578 Mon Sep 17 00:00:00 2001 From: BenKurrek Date: Tue, 7 Jul 2026 18:19:59 -0400 Subject: [PATCH 10/12] test(webui): loosen Vite bundle shape guards --- .../tests/webui_v2_serve.rs | 37 +++++++++++++++---- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/crates/ironclaw_reborn_composition/tests/webui_v2_serve.rs b/crates/ironclaw_reborn_composition/tests/webui_v2_serve.rs index 10e4f509131..1b5b8536490 100644 --- a/crates/ironclaw_reborn_composition/tests/webui_v2_serve.rs +++ b/crates/ironclaw_reborn_composition/tests/webui_v2_serve.rs @@ -1259,6 +1259,17 @@ fn shell_vite_asset_path(shell: &str, suffix: &str) -> String { .to_string() } +fn bundle_segment<'a>(body: &'a str, start: &str, end: &str) -> &'a str { + let start_idx = body + .find(start) + .unwrap_or_else(|| panic!("bundle should contain start marker `{start}`")); + let after_start = &body[start_idx..]; + let end_rel = after_start + .find(end) + .unwrap_or_else(|| panic!("bundle should contain end marker `{end}` after `{start}`")); + &after_start[..end_rel] +} + // ─── tests ──────────────────────────────────────────────────────────── #[tokio::test] @@ -2465,15 +2476,17 @@ async fn static_chat_hook_listens_for_oauth_callback_completion() { "chat hook must listen for the OAuth callback completion signal" ); assert!( - body.contains("new window.BroadcastChannel(rp)"), + body.contains("ironclaw-product-auth") + && body.contains("new window.BroadcastChannel(") + && body.contains("onmessage="), "chat hook must consume same-origin OAuth callback broadcasts" ); assert!( - body.contains("window.addEventListener(`storage`,r)"), + body.contains("window.addEventListener(`storage`,"), "chat hook must keep a localStorage fallback for browsers without BroadcastChannel" ); assert!( - body.contains("window.localStorage?.getItem?.(ip)"), + body.contains("window.localStorage?.getItem?.("), "chat hook must poll localStorage in case the callback write happened before the storage event listener observed it" ); assert!( @@ -2481,7 +2494,7 @@ async fn static_chat_hook_listens_for_oauth_callback_completion() { "chat hook must match callback completion to the visible OAuth gate when continuation metadata is present" ); assert!( - body.contains("pp(e)?null:e"), + body.contains("auth_required") && body.contains("oauth_url") && body.contains("?null:e"), "OAuth callback completion must clear only a pending OAuth auth gate" ); } @@ -2567,21 +2580,29 @@ async fn static_i18n_module_guards_locale_race_and_clears_failed_pack_cache() { // test driving `setLang('es')` through an unloaded pack belongs in // the deferred JS/e2e scaffold. let body = served_app_javascript().await; + let loader_segment = bundle_segment(&body, "ironclaw_language", "createContext({lang:"); + let provider_segment = bundle_segment(&body, "createContext({lang:", "function Yr"); assert!( - body.contains("lo[e]||null"), + provider_segment.contains(".useState(()=>") + && provider_segment.contains("||null") + && provider_segment.contains(".useRef("), "i18n provider must track the latest requested language in a ref", ); assert!( - body.contains("po[e]||(po[e]="), + provider_segment.contains(".current="), "setLang must stamp the requested language before awaiting the pack", ); assert!( - body.contains("Promise.resolve(null)"), + loader_segment.contains("Promise.resolve(null)"), "a resolved pack load must only commit when the pack is available and still the latest request", ); + assert!( + provider_segment.contains(".current!=="), + "a resolved pack load must be ignored after a newer language request", + ); assert_eq!( - body.matches("delete po[e]").count(), + loader_segment.matches("delete ").count(), 2, "ensurePack must clear pending[lang] on BOTH the success and failure paths so a transient import failure can be retried", ); From 3a07c085af83d73cb4d86f5fc023d0ff0f6254a7 Mon Sep 17 00:00:00 2001 From: serrrfirat Date: Wed, 8 Jul 2026 13:44:40 +0300 Subject: [PATCH 11/12] Wait for trigger mutator registration attempts --- .../tests/trigger_poller_e2e.rs | 25 +++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/crates/ironclaw_reborn_composition/tests/trigger_poller_e2e.rs b/crates/ironclaw_reborn_composition/tests/trigger_poller_e2e.rs index c70fa01a8ba..df04cffc44f 100644 --- a/crates/ironclaw_reborn_composition/tests/trigger_poller_e2e.rs +++ b/crates/ironclaw_reborn_composition/tests/trigger_poller_e2e.rs @@ -194,6 +194,23 @@ impl TriggerMutatorAttemptGateway { self.registration_outcomes.lock().await.clone() } + async fn wait_for_registration_outcomes( + &self, + expected_len: usize, + deadline: Duration, + ) -> BTreeMap> { + let stop = Instant::now() + deadline; + let mut last = BTreeMap::new(); + while Instant::now() < stop { + last = self.registration_outcomes().await; + if last.len() >= expected_len { + return last; + } + tokio::time::sleep(Duration::from_millis(50)).await; + } + last + } + /// One provider tool call per scheduled-trigger mutator capability id, /// paired with a payload shaped for that capability's real input schema /// (see `ironclaw_host_runtime::first_party_tools::trigger_management`'s @@ -1460,17 +1477,21 @@ async fn scheduled_trigger_denies_mutators_with_tool_disclosure( ) .await; + let registration_outcomes = gateway + .wait_for_registration_outcomes(4, Duration::from_secs(15)) + .await; + runtime.shutdown().await.expect("runtime shutdown"); let captured_contents = gateway.captured_message_contents().await; - let registration_outcomes = gateway.registration_outcomes().await; assert_eq!( registration_outcomes.len(), 4, "the fired run must have attempted all 4 scheduled-trigger mutator \ registrations (create/remove/pause/resume) — captured_messages: \ - {captured_contents:?}, outcomes: {registration_outcomes:?}" + {captured_contents:?}, outcomes: {registration_outcomes:?}, \ + settled_record: {settled:?}" ); // Core assertion, mechanism-level: the surface must deny EVERY mutator From ce838ed3510f3b8bcfd0ecb8c778d35903816fa2 Mon Sep 17 00:00:00 2001 From: serrrfirat Date: Wed, 8 Jul 2026 14:13:15 +0300 Subject: [PATCH 12/12] Remove duplicate trigger mutator wait --- .../tests/trigger_poller_e2e.rs | 21 ------------------- 1 file changed, 21 deletions(-) diff --git a/crates/ironclaw_reborn_composition/tests/trigger_poller_e2e.rs b/crates/ironclaw_reborn_composition/tests/trigger_poller_e2e.rs index 4f4bf1c0c16..0379f523ff6 100644 --- a/crates/ironclaw_reborn_composition/tests/trigger_poller_e2e.rs +++ b/crates/ironclaw_reborn_composition/tests/trigger_poller_e2e.rs @@ -194,23 +194,6 @@ impl TriggerMutatorAttemptGateway { self.registration_outcomes.lock().await.clone() } - async fn wait_for_registration_outcomes( - &self, - expected_len: usize, - deadline: Duration, - ) -> BTreeMap> { - let stop = Instant::now() + deadline; - let mut last = BTreeMap::new(); - while Instant::now() < stop { - last = self.registration_outcomes().await; - if last.len() >= expected_len { - return last; - } - tokio::time::sleep(Duration::from_millis(50)).await; - } - last - } - /// One provider tool call per scheduled-trigger mutator capability id, /// paired with a payload shaped for that capability's real input schema /// (see `ironclaw_host_runtime::first_party_tools::trigger_management`'s @@ -1497,10 +1480,6 @@ async fn scheduled_trigger_denies_mutators_with_tool_disclosure( let registration_outcomes = wait_for_mutator_registration_outcomes(&gateway, Duration::from_secs(15)).await; - let registration_outcomes = gateway - .wait_for_registration_outcomes(4, Duration::from_secs(15)) - .await; - runtime.shutdown().await.expect("runtime shutdown"); let captured_contents = gateway.captured_message_contents().await;